Skip to content

Conversation

@sudhdkso
Copy link
Contributor

@sudhdkso sudhdkso commented Jul 15, 2025

#️⃣연관된 이슈

#140

🔀반영 브랜치

feat/#140-kakao-login -> develop

🔧변경 사항

  • 카카오 및 서비스 로그아웃 기능 추가

    • 카카오와 자체 서비스 로그아웃 기능을 구현하여 통합된 로그아웃 플로우를 완성하였습니다.
  • 로그인 플로우 리팩토링

    • 회원 생성 로직을 UserService로 이동시켜 객체지향 원칙에 맞게 책임을 분리하였습니다.
    • 서비스 레이어에서 사용자 생성과 관련된 책임을 명확히 하여 코드 가독성과 유지 보수성을 개선하였습니다.
  • JWT 토큰의 Payload에서 이메일(email) Claim을 삭제하였습니다.

    • 토큰 크기를 줄이고, 이메일을 더 이상 토큰에서 사용할 필요가 없기 때문에 제거하였습니다.

💬리뷰 요구사항(선택)

리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요
ex) 메서드 XXX의 이름을 더 잘 짓고 싶은데 혹시 좋은 명칭이 있을까요

Summary by CodeRabbit

  • 신규 기능

    • 카카오 로그아웃 기능이 추가되어, 카카오 계정 연동 사용자는 로그아웃 시 카카오 서버와 연동된 세션도 만료됩니다.
    • 게스트 및 카카오 회원 가입/로그인 로직이 개선되었습니다.
    • 카카오 관련 설정이 외부 설정 파일에 추가되어 관리가 용이해졌습니다.
  • 버그 수정

    • 쿠키 설정에 보안 옵션(secure 등)이 강화되어 적용되었습니다.
  • 리팩터링

    • 사용자 생성 및 조회 로직이 서비스 계층으로 분리되어 구조가 개선되었습니다.
    • 카카오 API 연동 설정이 별도의 구성 프로퍼티 클래스로 분리되었습니다.
    • JWT 토큰 생성 시 이메일 정보가 제외되어 토큰 구조가 간소화되었습니다.
  • 테스트

    • 카카오 로그아웃, 회원 생성, 토큰 재발급 등 신규 및 변경된 서비스 로직에 대한 단위 및 통합 테스트가 추가 및 보완되었습니다.
  • 문서화

    • 카카오 관련 응답 DTO 구조가 단순화되고 명확하게 변경되었습니다.
    • 카카오 OAuth 및 로그아웃 관련 API URI 설정이 추가되었습니다.

@sudhdkso sudhdkso self-assigned this Jul 15, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jul 15, 2025

Walkthrough

이번 변경은 카카오 OAuth 연동의 구조적 리팩토링과 로그아웃 기능 추가, 사용자 도메인 서비스 분리, DTO 및 엔티티 구조 정비, 테스트 코드 및 설정 파일 확장 등 인증/사용자 관리 전반에 걸쳐 대규모 개선을 수행합니다. 카카오 관련 설정이 외부화되고, 서비스 계층이 세분화되었으며, 로그아웃 및 토큰 발급 로직이 명확해졌습니다.

Changes

파일/그룹 변경 요약
.github/workflows/cicd.yml Docker 이미지 최신화 명령 추가 등 배포 단계 수정
src/main/resources/application.yml, src/test/resources/application.yml 카카오 API 및 쿠키 관련 설정 추가/구조 변경
src/main/java/com/dnd/moddo/global/config/KakaoProperties.java, CookieProperties.java 카카오/쿠키 설정 외부화 및 domain 필드 제거, 패키지 이동
src/main/java/com/dnd/moddo/global/config/PropertiesConfig.java JwtProperties 바인딩용 설정 클래스 삭제
src/main/java/com/dnd/moddo/domain/auth/service/KakaoClient.java, KakaoLogoutResponse.java 카카오 API URI/키 외부화, 로그아웃 API 연동 및 응답 DTO 추가
src/main/java/com/dnd/moddo/domain/auth/controller/AuthController.java, AuthService.java, RefreshTokenService.java 카카오 로그인/로그아웃 및 게스트 로그인 리팩토링, 서비스 계층 분리, 토큰 발급 방식 변경
src/main/java/com/dnd/moddo/domain/auth/dto/KakaoProfile.java, KakaoTokenResponse.java 카카오 프로필/토큰 DTO 필드 최소화 및 구조 단순화
src/main/java/com/dnd/moddo/domain/user/entity/User.java, UserRepository.java User 엔티티에 kakaoId 필드 추가, 관련 쿼리 메서드 확장
src/main/java/com/dnd/moddo/domain/user/dto/request/GuestUserSaveRequest.java, UserSaveRequest.java 게스트/카카오 사용자 저장용 DTO 신설 및 toEntity 메서드 구현
src/main/java/com/dnd/moddo/domain/user/service/CommandUserService.java, QueryUserService.java, implementation/UserCreator.java, implementation/UserReader.java 사용자 생성/조회 서비스 계층 분리 및 도입
src/main/java/com/dnd/moddo/global/jwt/service/JwtService.java, utill/JwtProvider.java JWT에서 email claim 제거, ID 추출 메서드 오버로드 추가
src/main/java/com/dnd/moddo/domain/auth/controller/AuthController.java 쿠키 도메인 제거, 로그아웃 응답 메시지 추가, 요청 파라미터 검증 강화
src/test/java/com/dnd/moddo/... 인증/사용자/카카오/토큰 관련 테스트 코드 전면 리팩토링, 신규 서비스/DTO 반영, 로그아웃 테스트 추가, 유틸/팩토리 개선
src/main/resources/config 서브모듈 커밋 참조 업데이트

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant AuthController
    participant AuthService
    participant KakaoClient
    participant CommandUserService
    participant QueryUserService
    participant JwtProvider

    Client->>AuthController: GET /api/v1/oauth/kakao/callback?code=XXX
    AuthController->>AuthService: loginOrRegisterWithKakao(code)
    AuthService->>KakaoClient: join(code)
    KakaoClient-->>AuthService: KakaoTokenResponse
    AuthService->>KakaoClient: getKakaoProfile(accessToken)
    KakaoClient-->>AuthService: KakaoProfile
    AuthService->>CommandUserService: getOrCreateUser(UserSaveRequest)
    CommandUserService->>UserReader: findByKakaoId
    alt not found
        CommandUserService->>UserCreator: createUser
        UserCreator-->>CommandUserService: User
    end
    CommandUserService-->>AuthService: User
    AuthService->>JwtProvider: generateToken(User)
    JwtProvider-->>AuthService: TokenResponse
    AuthService-->>AuthController: TokenResponse
    AuthController-->>Client: Set-Cookie(accessToken), redirect

    %% 로그아웃 시나리오
    Client->>AuthController: GET /api/v1/logout (with accessToken)
    AuthController->>JwtService: getUserId(token)
    JwtService-->>AuthController: userId
    AuthController->>AuthService: logout(userId)
    AuthService->>QueryUserService: findKakaoIdById(userId)
    QueryUserService-->>AuthService: kakaoId
    alt kakaoId exists
        AuthService->>KakaoClient: logout(kakaoId)
        KakaoClient-->>AuthService: KakaoLogoutResponse
        AuthService-->>AuthController: void
    else kakaoId null
        AuthService-->>AuthController: void
    end
    AuthController-->>Client: JSON 메시지 + 쿠키 만료
Loading

Poem

🥕
오늘은 카카오와 손잡고
로그아웃도 똑똑하게!
서비스 계층 나누고
DTO도 깔끔하게,
테스트 토끼들 춤추네
설정도 외부로 쏙쏙,
모도는 더 단단해졌지!
🐇✨

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b830b39 and db01dd3.

📒 Files selected for processing (7)
  • src/main/java/com/dnd/moddo/domain/auth/service/AuthService.java (2 hunks)
  • src/main/java/com/dnd/moddo/domain/auth/service/KakaoClient.java (4 hunks)
  • src/main/java/com/dnd/moddo/domain/user/service/QueryUserService.java (1 hunks)
  • src/test/java/com/dnd/moddo/domain/auth/controller/AuthControllerTest.java (5 hunks)
  • src/test/java/com/dnd/moddo/domain/auth/service/AuthServiceTest.java (3 hunks)
  • src/test/java/com/dnd/moddo/domain/user/service/implementation/UserReaderTest.java (1 hunks)
  • src/test/java/com/dnd/moddo/domain/user/service/queryUserServiceTest.java (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/test/java/com/dnd/moddo/domain/user/service/queryUserServiceTest.java
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/test/java/com/dnd/moddo/domain/user/service/implementation/UserReaderTest.java
  • src/test/java/com/dnd/moddo/domain/auth/controller/AuthControllerTest.java
  • src/main/java/com/dnd/moddo/domain/auth/service/KakaoClient.java
🧰 Additional context used
🧠 Learnings (1)
src/main/java/com/dnd/moddo/domain/auth/service/AuthService.java (1)
Learnt from: sudhdkso
PR: moddo-kr/moddo-backend#5
File: src/main/java/com/dnd/moddo/global/config/KakaoProperties.java:5-13
Timestamp: 2025-07-15T06:25:52.317Z
Learning: The project uses git submodules for configuration management (src/main/resources/config), where sensitive values like Kakao adminKey and clientId are managed separately from the main codebase for security purposes.
🧬 Code Graph Analysis (1)
src/test/java/com/dnd/moddo/domain/auth/service/AuthServiceTest.java (3)
src/test/java/com/dnd/moddo/domain/user/service/queryUserServiceTest.java (1)
  • ExtendWith (17-52)
src/test/java/com/dnd/moddo/domain/auth/service/KakaoClientTest.java (1)
  • ExtendWith (27-188)
src/test/java/com/dnd/moddo/domain/user/service/CommandUserServiceTest.java (1)
  • ExtendWith (21-90)
🔇 Additional comments (8)
src/main/java/com/dnd/moddo/domain/user/service/QueryUserService.java (1)

16-18: 이전 리뷰 의견이 잘 반영되었습니다.

과거 리뷰에서 제기된 Optionalnull로 변환하는 문제가 해결되었습니다. 이제 Optional<Long>을 직접 반환하여 null 안전성을 보장하고 호출하는 측에서 안전하게 처리할 수 있습니다.

src/main/java/com/dnd/moddo/domain/auth/service/AuthService.java (4)

29-30: 서비스 계층 분리가 잘 구현되었습니다.

직접적인 Repository 접근을 Service 계층 추상화로 교체한 것이 객체지향 원칙에 부합합니다. CommandUserServiceQueryUserService로 책임을 명확히 분리한 점이 좋습니다.


35-42: 게스트 로그인 로직이 깔끔하게 리팩토링되었습니다.

메소드명 변경(createGuestUserloginWithGuest)이 의도를 더 명확하게 표현하며, DTO 사용으로 데이터 전달이 체계적으로 개선되었습니다.


53-55: 카카오 프로필 검증 로직이 견고합니다.

필수 정보(email, nickname, kakaoId)의 null 체크를 통해 데이터 무결성을 보장하고, 명확한 에러 메시지로 디버깅을 용이하게 했습니다.


65-75: 로그아웃 구현이 안전하고 효율적입니다.

Optional을 활용한 조건적 처리와 카카오 응답 검증을 통해 로그아웃 실패 시나리오를 적절히 처리했습니다. 게스트 사용자의 경우 불필요한 API 호출을 방지하는 것도 좋은 설계입니다.

src/test/java/com/dnd/moddo/domain/auth/service/AuthServiceTest.java (3)

30-33: 테스트 의존성이 서비스 리팩토링에 맞게 잘 업데이트되었습니다.

UserRepository 대신 CommandUserServiceQueryUserService를 모킹하여 서비스 계층 분리를 테스트에서도 일관되게 적용했습니다.


83-121: 로그아웃 테스트 케이스가 포괄적입니다.

성공 시나리오, 게스트 사용자(카카오ID 없음) 시나리오, 그리고 ID 불일치 예외 시나리오까지 모든 주요 케이스를 다루고 있어 로그아웃 기능의 안정성을 보장합니다.


43-48: 서비스 메소드 호출 검증이 정확합니다.

commandUserService.createGuestUser() 호출과 JWT 토큰 생성을 모두 검증하여 게스트 로그인 플로우가 올바르게 동작함을 확인합니다.


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@sudhdkso sudhdkso changed the title Feat/#140 kakao login feat: 서비스 로그아웃 기능 추가 Jul 15, 2025
@github-actions
Copy link

📝 테스트 커버리지 리포트입니다!

File Coverage [86.88%] 🍏
User.java 100% 🍏
RefreshTokenService.java 100% 🍏
CommandUserService.java 100% 🍏
QueryUserService.java 100% 🍏
UserCreator.java 100% 🍏
AuthService.java 95.08% 🍏
KakaoClient.java 88.89% 🍏
UserReader.java 50%
JwtService.java 0%
Total Project Coverage 92.83% 🍏

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (17)
src/main/java/com/dnd/moddo/global/config/CookieProperties.java (1)

7-15: 설정 클래스 구조는 우수하나 개선점이 있습니다.

record 클래스와 ConfigurationProperties 사용이 적절하며, 필드 타입들도 올바르게 선택되었습니다.

다음과 같은 개선사항을 고려해보세요:

 @ConfigurationProperties(prefix = "cookie")
 public record CookieProperties(
+    /**
+     * HTTP-only 쿠키 설정 여부
+     */
+    @DefaultValue("true")
     boolean httpOnly,
+    /**
+     * HTTPS 환경에서만 쿠키 전송 여부
+     */
+    @DefaultValue("false") 
     boolean secure,
+    /**
+     * 쿠키 경로
+     */
+    @DefaultValue("/")
     String path,
+    /**
+     * SameSite 쿠키 정책
+     */
+    @DefaultValue("Lax")
     String sameSite,
+    /**
+     * 쿠키 만료 시간
+     */
+    @DefaultValue("PT24H")
     Duration maxAge
 ) {
 }

이렇게 하면 설정 파일이 없거나 일부 값이 누락되어도 안전한 기본값으로 동작할 수 있습니다.

src/test/java/com/dnd/moddo/domain/user/entity/UserTest.java (1)

30-30: 사용되지 않는 변수를 제거해주세요.

LocalDateTime time 변수가 선언되었지만 사용되지 않고 있습니다. 팩토리 메서드에서 시간을 처리하므로 이 변수는 제거할 수 있습니다.

다음과 같이 수정해주세요:

- LocalDateTime time = LocalDateTime.now();
-
src/test/java/com/dnd/moddo/domain/user/service/queryUserServiceTest.java (2)

18-18: 클래스명 네이밍 컨벤션을 수정해주세요.

Java 클래스명은 PascalCase를 사용해야 합니다. queryUserServiceTestQueryUserServiceTest로 변경해주세요.

- public class queryUserServiceTest {
+ public class QueryUserServiceTest {

30-30: Mockito 스터빙에서 구체적인 매개변수를 사용하세요.

any()를 사용하는 대신 실제 매개변수 값을 사용하는 것이 더 정확한 테스트가 됩니다.

다음과 같이 수정해보세요:

- when(userReader.findKakaoIdById(any())).thenReturn(Optional.of(kakaoId));
+ when(userReader.findKakaoIdById(userId)).thenReturn(Optional.of(kakaoId));
- when(userReader.findKakaoIdById(any())).thenReturn(Optional.empty());
+ when(userReader.findKakaoIdById(1L)).thenReturn(Optional.empty());

Also applies to: 42-42

src/test/resources/application.yml (1)

54-54: 파일 끝에 개행 문자를 추가해주세요.

YAML 파일 표준에 따라 파일 마지막에 개행 문자가 필요합니다.

-  logout-request-uri: https://kapi.kakao.com/v1/user/logout
+  logout-request-uri: https://kapi.kakao.com/v1/user/logout
+
src/test/java/com/dnd/moddo/domain/user/service/implementation/UserReaderTest.java (1)

26-40: 테스트 커버리지를 확장하여 UserReader의 모든 기능을 검증해주세요.

현재 findByKakaoId 메서드만 테스트하고 있지만, UserReader에는 findKakaoIdById 메서드도 있습니다. 또한 사용자를 찾지 못하는 경우에 대한 테스트도 추가하면 좋겠습니다.

추가 테스트 메서드 예시:

@DisplayName("존재하지 않는 kakaoId로 User를 조회하면 빈 Optional을 반환한다")
@Test
void whenFindByNonExistentKakaoId_thenReturnEmptyOptional() {
    // given
    Long nonExistentKakaoId = 999L;
    when(userRepository.findByKakaoId(nonExistentKakaoId)).thenReturn(Optional.empty());
    
    // when
    Optional<User> result = userReader.findByKakaoId(nonExistentKakaoId);
    
    // then
    assertThat(result).isEmpty();
    verify(userRepository, times(1)).findByKakaoId(nonExistentKakaoId);
}

@DisplayName("userId로 kakaoId를 조회하면 해당 kakaoId를 반환한다")
@Test
void whenFindKakaoIdById_thenReturnKakaoId() {
    // given
    Long userId = 1L;
    Long expectedKakaoId = 12345L;
    when(userRepository.findKakaoIdById(userId)).thenReturn(Optional.of(expectedKakaoId));
    
    // when
    Optional<Long> result = userReader.findKakaoIdById(userId);
    
    // then
    assertThat(result).isPresent();
    assertThat(result.get()).isEqualTo(expectedKakaoId);
    verify(userRepository, times(1)).findKakaoIdById(userId);
}
src/test/java/com/dnd/moddo/domain/user/service/CommandUserServiceTest.java (1)

75-89: 테스트 메서드명을 더 구체적으로 개선하세요.

메서드명 getOrCreateUser()는 테스트 의도를 명확히 표현하지 못합니다. 기존 유저를 반환하는 시나리오임을 명시하는 것이 좋겠습니다.

- void getOrCreateUser() {
+ void whenUserExists_thenReturnExistingUser() {
src/main/java/com/dnd/moddo/domain/user/service/CommandUserService.java (1)

30-34: getOrCreateUser 메서드의 트랜잭션 범위를 검토하세요.

현재 @Transactional이 전체 메서드에 적용되어 있지만, userReader.findByKakaoId()는 읽기 전용 작업입니다. 성능 최적화를 위해 읽기와 쓰기 작업의 트랜잭션을 분리하는 것을 고려해보세요.

+ @Transactional(readOnly = true)
  public User getOrCreateUser(UserSaveRequest request) {
-     return userReader.findByKakaoId(request.kakaoId())
-         .orElseGet(() -> createKakaoUser(request));
+     Optional<User> existingUser = userReader.findByKakaoId(request.kakaoId());
+     if (existingUser.isPresent()) {
+         return existingUser.get();
+     }
+     return createKakaoUserTransactional(request);
  }
+ 
+ @Transactional
+ private User createKakaoUserTransactional(UserSaveRequest request) {
+     return createKakaoUser(request);
+ }
src/test/java/com/dnd/moddo/global/support/UserTestFactory.java (1)

41-54: 하드코딩된 kakaoId 값을 파라미터화하는 것을 고려하세요.

현재 kakaoId1234565L로 하드코딩되어 있습니다. 테스트에서 다양한 kakaoId 값이 필요할 수 있으므로 파라미터로 받을 수 있는 오버로드 메서드를 추가하는 것이 좋겠습니다.

+ public static User createWithEmailAndKakaoId(String email, Long kakaoId) {
+     LocalDateTime time = LocalDateTime.now();
+     return User
+         .builder()
+         .name("연노른자")
+         .email(email)
+         .profile("profile.png")
+         .isMember(true)
+         .kakaoId(kakaoId)
+         .authority(USER)
+         .createdAt(time)
+         .expiredAt(time.plusDays(7))
+         .build();
+ }
src/main/java/com/dnd/moddo/global/jwt/service/JwtService.java (1)

15-30: 입력 파라미터 검증 추가를 고려하세요.

null 체크나 빈 문자열 검증을 추가하여 더 안전한 서비스를 만들 수 있습니다.

  public Long getId(HttpServletRequest request, String key) {
+     if (request == null || key == null || key.trim().isEmpty()) {
+         throw new IllegalArgumentException("Request and key must not be null or empty");
+     }
      String token = jwtUtil.resolveToken(request);
      return jwtUtil.getIdFromToken(token, key);
  }

  public Long getUserId(String token) {
+     if (token == null || token.trim().isEmpty()) {
+         throw new IllegalArgumentException("Token must not be null or empty");
+     }
      return jwtUtil.getIdFromToken(token, "userId");
  }
src/main/java/com/dnd/moddo/domain/user/entity/User.java (2)

39-39: 카카오 ID 필드에 대한 데이터베이스 제약 조건 추가 고려

카카오 ID의 유일성을 보장하기 위해 @Column(unique = true) 어노테이션 추가를 고려해보세요.

-	private Long kakaoId;
+	@Column(unique = true)
+	private Long kakaoId;

48-59: 생성자 파라미터 순서 일관성 검토

생성자의 파라미터 순서가 필드 선언 순서와 일치하지 않습니다. 가독성을 위해 일관성을 맞추는 것을 고려해보세요.

@Builder
-public User(String name, String email, String profile, Boolean isMember, Authority authority, Long kakaoId,
+public User(String name, String email, String profile, Boolean isMember, Long kakaoId, Authority authority,
	LocalDateTime createdAt, LocalDateTime expiredAt) {
	this.name = name;
	this.email = email;
	this.profile = profile;
	this.isMember = isMember;
	this.kakaoId = kakaoId;
-	this.createdAt = createdAt;
-	this.expiredAt = expiredAt;
	this.authority = authority;
+	this.createdAt = createdAt;
+	this.expiredAt = expiredAt;
}
src/main/java/com/dnd/moddo/domain/user/repository/UserRepository.java (1)

19-20: 카카오 ID 조회 쿼리 최적화 고려

현재 JPQL 쿼리는 정상 작동하지만, 인덱스 성능을 고려하여 메서드 기반 쿼리 사용을 검토해보세요.

-@Query("SELECT u.kakaoId FROM User u WHERE u.id = :userId")
-Optional<Long> findKakaoIdById(Long userId);
+Optional<Long> findKakaoIdById(Long userId);

만약 Spring Data JPA가 자동으로 생성하는 메서드로 충분하다면 @Query 어노테이션을 제거할 수 있습니다.

src/test/java/com/dnd/moddo/domain/auth/service/AuthServiceTest.java (1)

107-119: 로그아웃 실패 케이스 테스트 개선 제안

예외 메시지 검증은 좋지만, 더 구체적인 예외 타입을 사용하는 것을 고려해보세요.

-		assertThatThrownBy(() -> authService.logout(1L))
-			.isInstanceOf(RuntimeException.class)
-			.hasMessageContaining("로그아웃 실패");
+		assertThatThrownBy(() -> authService.logout(1L))
+			.isInstanceOf(KakaoLogoutException.class)
+			.hasMessageContaining("로그아웃 실패");

더 구체적인 예외 타입을 사용하면 예외 처리가 더 명확해집니다.

src/test/java/com/dnd/moddo/domain/auth/service/KakaoClientTest.java (1)

176-176: 테스트 메서드명 오타를 수정해주세요.

henCallKakaoLogoutwhenCallKakaoLogout으로 수정이 필요합니다.

-void henCallKakaoLogout_withServerError_thenThrowException() {
+void whenCallKakaoLogout_withServerError_thenThrowException() {
src/main/java/com/dnd/moddo/domain/auth/service/AuthService.java (1)

65-77: 로그아웃 로직이 적절히 구현되었습니다.

카카오 ID가 없는 경우의 처리와 ID 불일치 검증이 잘 되었습니다. 다만 75번 라인의 불필요한 공백을 제거해주세요.

-		}
-		
+		}
+
src/main/java/com/dnd/moddo/domain/auth/controller/AuthController.java (1)

67-74: 로그아웃 엔드포인트가 잘 구현되었습니다.

쿠키 만료와 카카오 로그아웃을 함께 처리하는 것이 적절합니다. 다만, accessToken 쿠키가 없는 경우를 대비해 required = false 옵션 추가를 고려해보세요.

-public ResponseEntity<?> kakaoLogout(@CookieValue(value = "accessToken") String token) {
+public ResponseEntity<?> kakaoLogout(@CookieValue(value = "accessToken", required = false) String token) {
+    if (token == null) {
+        return ResponseEntity.ok()
+            .body(Collections.singletonMap("message", "Already logged out"));
+    }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d2232e7 and b830b39.

📒 Files selected for processing (40)
  • .github/workflows/cicd.yml (1 hunks)
  • src/main/java/com/dnd/moddo/ModdoApplication.java (1 hunks)
  • src/main/java/com/dnd/moddo/domain/auth/controller/AuthController.java (4 hunks)
  • src/main/java/com/dnd/moddo/domain/auth/dto/KakaoLogoutResponse.java (1 hunks)
  • src/main/java/com/dnd/moddo/domain/auth/dto/KakaoProfile.java (1 hunks)
  • src/main/java/com/dnd/moddo/domain/auth/dto/KakaoTokenResponse.java (1 hunks)
  • src/main/java/com/dnd/moddo/domain/auth/service/AuthService.java (2 hunks)
  • src/main/java/com/dnd/moddo/domain/auth/service/KakaoClient.java (4 hunks)
  • src/main/java/com/dnd/moddo/domain/auth/service/RefreshTokenService.java (1 hunks)
  • src/main/java/com/dnd/moddo/domain/user/dto/request/GuestUserSaveRequest.java (1 hunks)
  • src/main/java/com/dnd/moddo/domain/user/dto/request/UserSaveRequest.java (1 hunks)
  • src/main/java/com/dnd/moddo/domain/user/entity/User.java (1 hunks)
  • src/main/java/com/dnd/moddo/domain/user/repository/UserRepository.java (1 hunks)
  • src/main/java/com/dnd/moddo/domain/user/service/CommandUserService.java (1 hunks)
  • src/main/java/com/dnd/moddo/domain/user/service/QueryUserService.java (1 hunks)
  • src/main/java/com/dnd/moddo/domain/user/service/implementation/UserCreator.java (1 hunks)
  • src/main/java/com/dnd/moddo/domain/user/service/implementation/UserReader.java (1 hunks)
  • src/main/java/com/dnd/moddo/global/config/CookieProperties.java (1 hunks)
  • src/main/java/com/dnd/moddo/global/config/KakaoProperties.java (1 hunks)
  • src/main/java/com/dnd/moddo/global/config/PropertiesConfig.java (0 hunks)
  • src/main/java/com/dnd/moddo/global/jwt/properties/JwtProperties.java (1 hunks)
  • src/main/java/com/dnd/moddo/global/jwt/service/JwtService.java (1 hunks)
  • src/main/java/com/dnd/moddo/global/jwt/utill/JwtProvider.java (3 hunks)
  • src/main/resources/application.yml (1 hunks)
  • src/main/resources/config (1 hunks)
  • src/test/java/com/dnd/moddo/domain/auth/controller/AuthControllerTest.java (5 hunks)
  • src/test/java/com/dnd/moddo/domain/auth/service/AuthServiceTest.java (2 hunks)
  • src/test/java/com/dnd/moddo/domain/auth/service/KakaoClientTest.java (8 hunks)
  • src/test/java/com/dnd/moddo/domain/auth/service/RefreshTokenServiceTest.java (2 hunks)
  • src/test/java/com/dnd/moddo/domain/group/controller/GroupControllerTest.java (5 hunks)
  • src/test/java/com/dnd/moddo/domain/group/service/implementation/GroupCreatorTest.java (2 hunks)
  • src/test/java/com/dnd/moddo/domain/user/entity/UserTest.java (1 hunks)
  • src/test/java/com/dnd/moddo/domain/user/service/CommandUserServiceTest.java (1 hunks)
  • src/test/java/com/dnd/moddo/domain/user/service/implementation/UserCreatorTest.java (1 hunks)
  • src/test/java/com/dnd/moddo/domain/user/service/implementation/UserReaderTest.java (1 hunks)
  • src/test/java/com/dnd/moddo/domain/user/service/queryUserServiceTest.java (1 hunks)
  • src/test/java/com/dnd/moddo/global/support/UserTestFactory.java (1 hunks)
  • src/test/java/com/dnd/moddo/global/util/ControllerTest.java (2 hunks)
  • src/test/java/com/dnd/moddo/integration/CacheIntegrationTest.java (2 hunks)
  • src/test/resources/application.yml (1 hunks)
💤 Files with no reviewable changes (1)
  • src/main/java/com/dnd/moddo/global/config/PropertiesConfig.java
🧰 Additional context used
🧬 Code Graph Analysis (10)
src/test/java/com/dnd/moddo/domain/user/entity/UserTest.java (2)
src/test/java/com/dnd/moddo/global/support/UserTestFactory.java (1)
  • UserTestFactory (10-55)
src/main/java/com/dnd/moddo/domain/user/exception/UserNotFoundException.java (1)
  • UserNotFoundException (6-12)
src/test/java/com/dnd/moddo/domain/group/service/implementation/GroupCreatorTest.java (1)
src/test/java/com/dnd/moddo/global/support/UserTestFactory.java (1)
  • UserTestFactory (10-55)
src/main/java/com/dnd/moddo/domain/user/service/implementation/UserCreator.java (2)
src/main/java/com/dnd/moddo/domain/user/service/implementation/UserReader.java (1)
  • Service (13-26)
src/main/java/com/dnd/moddo/domain/user/service/CommandUserService.java (1)
  • RequiredArgsConstructor (14-35)
src/test/java/com/dnd/moddo/domain/user/service/implementation/UserCreatorTest.java (3)
src/test/java/com/dnd/moddo/global/support/UserTestFactory.java (1)
  • UserTestFactory (10-55)
src/test/java/com/dnd/moddo/domain/user/service/implementation/UserReaderTest.java (1)
  • ExtendWith (19-41)
src/test/java/com/dnd/moddo/domain/user/service/CommandUserServiceTest.java (1)
  • ExtendWith (21-90)
src/test/java/com/dnd/moddo/domain/auth/service/RefreshTokenServiceTest.java (1)
src/test/java/com/dnd/moddo/global/support/UserTestFactory.java (1)
  • UserTestFactory (10-55)
src/test/java/com/dnd/moddo/domain/user/service/implementation/UserReaderTest.java (2)
src/test/java/com/dnd/moddo/global/support/UserTestFactory.java (1)
  • UserTestFactory (10-55)
src/test/java/com/dnd/moddo/domain/user/service/implementation/UserCreatorTest.java (1)
  • ExtendWith (17-40)
src/main/java/com/dnd/moddo/domain/user/entity/User.java (1)
src/main/java/com/dnd/moddo/domain/groupMember/entity/GroupMember.java (1)
  • NoArgsConstructor (25-82)
src/main/java/com/dnd/moddo/domain/user/service/implementation/UserReader.java (3)
src/main/java/com/dnd/moddo/domain/user/service/QueryUserService.java (1)
  • RequiredArgsConstructor (9-18)
src/main/java/com/dnd/moddo/domain/user/service/CommandUserService.java (1)
  • RequiredArgsConstructor (14-35)
src/main/java/com/dnd/moddo/domain/user/service/implementation/UserCreator.java (1)
  • RequiredArgsConstructor (11-21)
src/test/java/com/dnd/moddo/domain/auth/service/AuthServiceTest.java (3)
src/test/java/com/dnd/moddo/domain/auth/service/KakaoClientTest.java (1)
  • ExtendWith (27-188)
src/test/java/com/dnd/moddo/domain/user/service/CommandUserServiceTest.java (1)
  • ExtendWith (21-90)
src/test/java/com/dnd/moddo/domain/user/service/queryUserServiceTest.java (1)
  • ExtendWith (17-51)
src/main/java/com/dnd/moddo/domain/user/repository/UserRepository.java (1)
src/main/java/com/dnd/moddo/domain/user/exception/UserNotFoundException.java (1)
  • UserNotFoundException (6-12)
🪛 YAMLlint (1.37.1)
src/test/resources/application.yml

[error] 54-54: no new line character at the end of file

(new-line-at-end-of-file)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-test
🔇 Additional comments (65)
src/test/java/com/dnd/moddo/integration/CacheIntegrationTest.java (2)

6-6: Import 변경이 적절합니다.

@afterall로의 변경이 메서드 시그니처 변경과 일치합니다.


67-70: 테스트 격리성 이슈 없음 확인

CacheIntegrationTest 클래스에는 현재 @Test 메서드가 하나뿐이므로, 테스트 간 캐시 공유로 인한 오염 위험은 없습니다.
향후 추가 테스트가 생길 경우 다음을 고려해 주세요:

  • 각 테스트마다 고유한 캐시 키 사용
  • @AfterEach 또는 테스트 종료 시점에 캐시 클리어 로직 추가
.github/workflows/cicd.yml (1)

76-76: 앱 서비스 정의 확인 완료 – 변경사항 승인합니다.

  • .github/workflows/cicd.yml의 배포 단계에 sudo docker compose pull app 명령이 추가된 것은 최신 이미지를 확실히 사용해 배포 일관성을 높이는 적절한 개선입니다.
  • docker-compose.yml 파일에서 app 서비스 정의(image, container_name, ports, logging, restart 등)가 올바르게 확인되었습니다.

추가 검증이나 수정 없이 이 변경사항을 승인합니다.

src/main/java/com/dnd/moddo/global/config/CookieProperties.java (1)

1-1: 패키지 이동이 적절합니다.

global.config 패키지로의 이동은 설정 관련 클래스들을 일관되게 관리하기 위한 좋은 리팩토링입니다.

src/main/resources/config (1)

1-1: 서브모듈 커밋 해시 변경 확인 필요

서브모듈 포인터가 1ec2dcd…6515d7b… 로 업데이트되었습니다.

  • 실제 서브모듈 디렉터리에도 git submodule update --recursive 로 최신 소스가 반영됐는지 확인해 주세요.
  • CI/CD 파이프라인에서 서브모듈이 올바르게 체크아웃되지 않으면 빌드가 실패할 수 있습니다.

특별한 문제는 보이지 않지만, 의도된 버전 업인지 한 번 더 검증 부탁드립니다.

src/main/java/com/dnd/moddo/global/jwt/properties/JwtProperties.java (1)

3-6: 코드 포맷팅 개선이 잘 되었습니다.

임포트문 정리와 들여쓰기 표준화로 코드 가독성이 향상되었습니다. 전체적인 설정 프로퍼티 관리 표준화 작업의 일환으로 적절한 변경입니다.

Also applies to: 14-27

src/main/java/com/dnd/moddo/domain/auth/dto/KakaoLogoutResponse.java (1)

1-4: 카카오 로그아웃 응답 DTO가 잘 설계되었습니다.

레코드 클래스를 사용하여 불변성과 간결성을 보장하고, 카카오 API 응답 구조에 맞는 단순하고 명확한 설계입니다.

src/main/java/com/dnd/moddo/ModdoApplication.java (1)

6-6: 설정 프로퍼티 자동 스캔 활성화가 적절합니다.

@ConfigurationPropertiesScan 어노테이션 추가로 설정 프로퍼티 클래스들의 자동 스캔과 바인딩이 가능해져, 더 간결하고 유지보수하기 쉬운 설정 관리가 가능합니다.

Also applies to: 9-9

src/test/java/com/dnd/moddo/domain/group/service/implementation/GroupCreatorTest.java (1)

60-60: 테스트 사용자 생성 방식이 개선되었습니다.

UserTestFactory.createGuestDefault() 사용으로 테스트 코드의 일관성과 재사용성이 향상되었습니다. 수동 객체 생성보다 유지보수하기 쉬운 접근법입니다.

src/test/java/com/dnd/moddo/global/util/ControllerTest.java (1)

28-28: 테스트 인프라 확장이 적절합니다.

CookieProperties MockBean 추가로 확장된 인증 및 쿠키 처리 기능의 컨트롤러 테스트를 지원할 수 있게 되었습니다.

Also applies to: 93-94

src/main/resources/application.yml (1)

28-31: 카카오 API URI 설정이 적절히 외부화되었습니다.

하드코딩된 URI를 설정 파일로 이동한 것은 좋은 개선입니다. 향후 카카오에서 API 엔드포인트가 변경될 경우 코드 수정 없이 설정만으로 대응할 수 있습니다.

src/test/java/com/dnd/moddo/domain/user/entity/UserTest.java (2)

3-5: 정적 임포트를 통한 코드 가독성 개선이 좋습니다.

UserTestFactory와 assertion 메서드들을 정적 임포트로 처리하여 코드가 더 깔끔해졌습니다.


32-33: 팩토리 메서드 사용으로 테스트 코드 일관성이 향상되었습니다.

createGuestWithNameAndEmail 메서드를 사용하여 User 객체 생성을 일관성 있게 처리한 것이 좋습니다. 테스트 데이터 생성 로직이 중앙화되어 유지보수가 용이해집니다.

src/test/java/com/dnd/moddo/domain/group/controller/GroupControllerTest.java (2)

26-26: HttpServletRequest 임포트 추가가 적절합니다.

JwtService 메서드 시그니처 변경에 맞춰 필요한 임포트가 추가되었습니다.


39-39: Mockito 스터빙의 타입 명시로 타입 안전성이 향상되었습니다.

any()에서 any(HttpServletRequest.class)로 변경하여 메서드 매개변수 타입을 명시적으로 지정한 것이 좋습니다. 이는 테스트의 타입 안전성을 높이고 JwtService의 변경된 메서드 시그니처와 일치합니다.

Also applies to: 60-60, 81-81, 98-98

src/main/java/com/dnd/moddo/domain/user/service/QueryUserService.java (1)

9-12: 서비스 계층 분리와 의존성 주입이 적절합니다.

@Service 어노테이션과 @RequiredArgsConstructor를 통한 의존성 주입이 Spring의 모범 사례를 따르고 있습니다. 사용자 조회 로직을 별도 서비스로 분리한 것도 단일 책임 원칙에 부합합니다.

src/test/java/com/dnd/moddo/domain/user/service/queryUserServiceTest.java (1)

24-36: 테스트 커버리지와 구조가 훌륭합니다.

정상 케이스와 예외 케이스를 모두 다루고 있으며, given-when-then 패턴을 명확히 따르고 있습니다. verify()를 통한 상호작용 검증도 적절합니다.

Also applies to: 38-50

src/test/resources/application.yml (1)

48-54: 카카오 설정 구조 개선이 잘 되었습니다.

기존의 중첩된 auth 구조에서 평면적인 구조로 변경하여 가독성이 향상되었고, 로그아웃 기능을 위한 새로운 URI들이 적절히 추가되었습니다.

src/test/java/com/dnd/moddo/domain/auth/service/RefreshTokenServiceTest.java (3)

3-3: 테스트 팩토리 사용으로 코드 일관성이 향상되었습니다.

정적 임포트를 통한 UserTestFactory 사용은 테스트 코드의 가독성과 일관성을 개선합니다.


61-61: 팩토리 메서드 사용이 적절합니다.

createGuestDefault() 메서드 사용으로 테스트 데이터 생성이 표준화되었습니다.


65-65: generateAccessToken 시그니처 일관성 확인 완료

rg 검색 결과, generateAccessToken 메서드 호출은 모두 Long idString role 두 파라미터만 사용하고 있으며, 이메일 파라미터 호출은 존재하지 않습니다. 변경 사항이 전체 코드베이스에 올바르게 적용된 것으로 확인됩니다.

src/main/java/com/dnd/moddo/domain/user/dto/request/GuestUserSaveRequest.java (3)

8-8: 간결한 레코드 클래스 정의가 적절합니다.

게스트 사용자 생성에 필요한 최소한의 필드만 포함하여 명확하고 간결합니다.


9-20: 게스트 사용자 엔티티 변환 로직이 적절합니다.

게스트 사용자에 적합한 기본값들이 올바르게 설정되었습니다 (kakaoId=null, isMember=false 등).


18-18: 게스트 사용자 만료 기간을 검토해주세요.

게스트 사용자의 1개월 만료 기간이 비즈니스 요구사항에 적합한지 확인해주세요. 일반적으로 게스트 사용자는 더 짧은 기간(예: 7일)을 사용하는 경우가 많습니다.

src/test/java/com/dnd/moddo/domain/user/service/implementation/UserCreatorTest.java (2)

17-22: 테스트 클래스 구조가 잘 설계되었습니다.

Mockito 확장과 의존성 주입을 적절히 사용한 단위 테스트 구조입니다.


24-39: 단위 테스트 로직이 적절합니다.

Given-When-Then 패턴을 따르고, 모킹과 검증이 올바르게 수행되었습니다. UserTestFactory 사용도 일관성을 유지합니다.

src/main/java/com/dnd/moddo/domain/user/dto/request/UserSaveRequest.java (3)

8-12: 카카오 사용자 DTO 구조가 적절합니다.

카카오 사용자에 필요한 필드들이 명확하게 정의되었고, kakaoId 필드가 포함되어 게스트 사용자와 구분됩니다.


13-24: 카카오 사용자 엔티티 변환 로직이 올바릅니다.

isMember=truekakaoId 설정으로 카카오 사용자의 특성이 정확히 반영되었습니다.


22-22: 사용자 유형별 만료 기간 정책을 검토해주세요.

게스트 사용자와 카카오 사용자 모두 동일한 1개월 만료 기간을 가집니다. 일반적으로 가입된 사용자(카카오 사용자)는 더 긴 만료 기간을 가지거나 만료 없이 유지되는 경우가 많습니다. 비즈니스 정책에 따라 이 부분을 검토해주세요.

src/main/java/com/dnd/moddo/domain/user/service/implementation/UserCreator.java (1)

11-21: 잘 구현된 사용자 생성 서비스입니다.

단일 책임 원칙을 잘 따르고 있으며, 트랜잭션 처리와 의존성 주입이 적절히 설정되어 있습니다. CommandUserService에서 사용되는 구조도 명확하고 직관적입니다.

src/main/java/com/dnd/moddo/domain/auth/dto/KakaoTokenResponse.java (1)

5-8: DTO 변경 승인 및 호환성 검증 완료

  • 제거된 필드(token_type, refresh_token, scope, refresh_token_expires_in)는 코드베이스에서 사용되지 않음을 확인했습니다.
  • JwtConstants.REFRESH_KEY("refresh_token")는 JWT 처리용 상수로, 해당 DTO와 직접적인 연관이 없어 영향이 없습니다.

문제 없이 머지 진행 가능합니다.

src/main/java/com/dnd/moddo/domain/auth/service/RefreshTokenService.java (1)

34-34: generateAccessToken(Long id, String role) 시그니처가 JwtProvider 및 테스트에 일관되게 반영되었습니다.

하지만 아래 사항은 직접 검토해주세요:

  • 기존 토큰과의 호환성: 이메일 클레임 제거가 검증 로직에 미치는 영향
  • 보안 영향: 이메일 정보 제거로 인한 리스크
src/main/java/com/dnd/moddo/domain/user/service/implementation/UserReader.java (2)

13-17: 클래스 구조가 잘 설계되었습니다.

읽기 전용 트랜잭션 어노테이션과 단일 책임 원칙을 잘 따르고 있습니다. CQRS 패턴의 Query 부분을 담당하는 서비스로 적절합니다.


19-25: 메서드 구현이 깔끔하고 안전합니다.

Optional을 반환하여 null safety를 보장하고, repository에 적절히 위임하고 있습니다. 메서드명도 의도를 명확히 표현하고 있습니다.

src/test/java/com/dnd/moddo/domain/user/service/CommandUserServiceTest.java (2)

21-28: 테스트 설정이 적절합니다.

Mockito 확장과 의존성 주입을 올바르게 구성했습니다.


30-42: 게스트 유저 생성 테스트가 잘 구성되었습니다.

AAA 패턴을 따르고 있으며, 필요한 필드들을 모두 검증하고 있습니다.

src/main/java/com/dnd/moddo/domain/user/service/CommandUserService.java (1)

14-18: 서비스 구조가 잘 설계되었습니다.

Command와 Query를 분리한 의존성 구조가 CQRS 패턴을 잘 반영하고 있습니다.

src/test/java/com/dnd/moddo/global/support/UserTestFactory.java (1)

14-24: 빌더 패턴 적용과 UUID 사용이 좋은 개선입니다.

생성자 직접 호출에서 빌더 패턴으로 변경하여 가독성이 향상되었고, UUID를 사용한 고유 이메일 생성으로 테스트 간 충돌을 방지할 수 있습니다.

src/main/java/com/dnd/moddo/global/jwt/service/JwtService.java (2)

15-18: 범용적인 getId 메서드 추가가 좋은 리팩토링입니다.

중복 코드를 제거하고 재사용성을 높인 좋은 설계입니다.


20-26: 메서드 오버로딩이 적절하게 구현되었습니다.

HttpServletRequest에서 토큰을 추출하는 방식과 토큰 문자열을 직접 받는 방식 모두를 지원하여 유연성이 향상되었습니다.

src/main/java/com/dnd/moddo/domain/user/entity/User.java (2)

39-39: 카카오 ID 필드 추가 승인

카카오 OAuth 연동을 위한 kakaoId 필드 추가가 적절합니다.


27-29: ID 필드 위치 이동 승인

엔티티의 식별자인 id 필드를 클래스 최상단으로 이동한 것이 가독성 향상에 도움이 됩니다.

src/main/java/com/dnd/moddo/domain/user/repository/UserRepository.java (2)

17-17: 카카오 ID로 사용자 조회 메서드 추가 승인

카카오 로그인 기능을 위한 findByKakaoId 메서드 추가가 적절합니다.


22-30: 기본 메서드 포맷팅 개선 승인

기존 default 메서드들의 들여쓰기와 포맷팅이 일관성 있게 개선되었습니다.

src/test/java/com/dnd/moddo/domain/auth/controller/AuthControllerTest.java (3)

36-36: 서비스 메서드명 변경에 따른 테스트 업데이트 승인

loginWithGuest() 메서드로 변경된 것이 더 명확한 의미를 전달합니다.


85-90: 카카오 로그인 테스트 메서드 업데이트 승인

KakaoTokenResponse 생성과 loginOrRegisterWithKakao() 메서드 호출 변경이 리팩토링된 서비스와 일치합니다.


110-125: 로그아웃 테스트 로직 승인

JWT 서비스를 통한 사용자 ID 추출과 인증 서비스의 로그아웃 호출을 올바르게 테스트하고 있습니다.

src/main/java/com/dnd/moddo/global/jwt/utill/JwtProvider.java (4)

26-28: 액세스 토큰 생성에서 이메일 제거 승인

토큰에서 이메일 정보를 제거하여 토큰 크기를 최적화한 것이 좋습니다.


30-32: User 엔티티 기반 토큰 생성 메서드 추가 승인

User 엔티티에서 직접 정보를 추출하여 토큰을 생성하는 방식이 더 깔끔합니다.


47-57: JWT 클레임에서 이메일 제거 승인

JWT 페이로드에서 이메일 클레임을 제거하여 토큰을 경량화한 것이 보안과 성능 측면에서 바람직합니다.


34-41: 이메일 파라미터 제거 검증 완료
generateToken 호출 시 이메일 인자를 사용하는 부분이 전체 코드베이스에서 발견되지 않았습니다.

src/test/java/com/dnd/moddo/domain/auth/service/AuthServiceTest.java (5)

28-30: 서비스 레이어 추상화에 따른 Mock 변경 승인

직접적인 레포지토리 의존성 대신 CommandUserServiceQueryUserService를 사용하는 것이 더 나은 테스트 구조입니다.


41-46: 게스트 사용자 생성 테스트 업데이트 승인

서비스 레이어를 통한 사용자 생성 테스트가 올바르게 구현되었습니다.


49-79: 카카오 로그인 테스트 리팩토링 승인

메서드명 변경과 서비스 의존성 업데이트가 적절합니다. KakaoTokenResponse 생성도 단순화되어 좋습니다.


81-93: 카카오 로그아웃 성공 케이스 테스트 승인

카카오 ID가 일치할 때의 정상적인 로그아웃 플로우를 잘 테스트하고 있습니다.


95-105: 게스트 사용자 로그아웃 테스트 승인

카카오 ID가 null인 경우 카카오 로그아웃 호출을 하지 않는 로직을 올바르게 검증하고 있습니다.

src/main/java/com/dnd/moddo/domain/auth/dto/KakaoProfile.java (1)

1-25: DTO 구조 단순화가 적절합니다.

필요한 필드만 유지하여 코드가 깔끔해졌습니다. @JsonProperty 어노테이션을 사용한 snake_case to camelCase 매핑도 적절합니다.

src/test/java/com/dnd/moddo/domain/auth/service/KakaoClientTest.java (3)

11-12: KakaoProperties 설정 중앙화가 잘 적용되었습니다.

설정값을 하나의 configuration 클래스로 관리하는 것은 좋은 패턴입니다.

Also applies to: 24-24, 29-29, 37-38


49-50: 테스트가 설정 변경사항을 잘 반영했습니다.

모든 하드코딩된 URL과 설정값이 kakaoProperties를 통해 관리되도록 일관성 있게 변경되었습니다.

Also applies to: 55-56, 59-59, 80-81, 84-84, 106-112, 117-117, 128-128, 138-138


148-172: 로그아웃 테스트가 적절히 추가되었습니다.

성공 케이스와 실패 케이스를 모두 검증하는 것이 좋습니다.

Also applies to: 174-187

src/main/java/com/dnd/moddo/domain/auth/service/KakaoClient.java (1)

12-12: 설정 중앙화 및 코드 개선이 잘 되었습니다.

KakaoProperties를 통한 설정 관리와 MediaType 상수 사용이 코드 품질을 향상시켰습니다.

Also applies to: 15-15, 25-25, 31-31, 35-36, 42-42, 60-60

src/main/java/com/dnd/moddo/domain/auth/service/AuthService.java (2)

5-5: 서비스 계층 분리가 잘 이루어졌습니다.

CommandUserServiceQueryUserService로 명령과 조회를 분리한 것은 CQRS 패턴을 잘 적용한 사례입니다.

Also applies to: 9-10, 12-17, 29-30


35-42: 인증 메서드 리팩토링이 잘 되었습니다.

메서드명이 더 명확해졌고, 사용자 생성 책임이 적절한 서비스로 이동되었습니다.

Also applies to: 45-63

src/main/java/com/dnd/moddo/domain/auth/controller/AuthController.java (2)

3-4: 검증 및 의존성 추가가 적절합니다.

@Validated 어노테이션으로 요청 파라미터 검증을 활성화한 것이 좋습니다.

Also applies to: 8-9, 29-29, 36-36


40-40: 메서드명 변경과 파라미터 검증이 적절합니다.

서비스 계층의 메서드명 변경과 일치하며, @NotBlank 검증 추가로 안정성이 향상되었습니다.

Also applies to: 55-55, 57-57

logout-request-uri: https://kapi.kakao.com/v1/user/logout

cookie:
secure: true
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

쿠키 보안 설정 강화를 확인해주세요.

secure: true 설정이 추가되어 HTTPS에서만 쿠키가 전송되도록 보안이 강화되었습니다. 개발 환경에서 HTTP를 사용하는 경우 이 설정으로 인해 쿠키가 작동하지 않을 수 있으니 프로파일별 설정을 고려해보세요.

다음 스크립트로 개발/운영 환경별 쿠키 설정을 확인해보세요:


🏁 Script executed:

#!/bin/bash
# 개발 및 운영 환경별 설정 파일에서 쿠키 보안 설정 확인
echo "=== 개발 환경 설정 확인 ==="
fd "application-dev.yml" --exec cat {}

echo "=== 운영 환경 설정 확인 ==="
fd "application-prod.yml" --exec cat {}

Length of output: 180


프로파일별 쿠키 Secure 설정 분리 필요
현재 application.yml(34행)의

server:
  servlet:
    session:
      cookie:
        secure: true

가 글로벌로 적용되어 있어, 개발 환경(HTTP)에서 쿠키가 전송되지 않습니다. 개발/운영 환경별로 아래처럼 프로파일별 override를 추가해주세요.

• src/main/resources/application-dev.yml

server:
  servlet:
    session:
      cookie:
        secure: false

• src/main/resources/application-prod.yml

server:
  servlet:
    session:
      cookie:
        secure: true
🤖 Prompt for AI Agents
In src/main/resources/application.yml at line 34, the cookie secure setting is
globally set to true, causing issues in development environments using HTTP. To
fix this, remove or avoid setting 'secure: true' globally in application.yml and
instead create environment-specific override files: set 'secure: false' in
src/main/resources/application-dev.yml for development and 'secure: true' in
src/main/resources/application-prod.yml for production.

@github-actions
Copy link

📝 테스트 커버리지 리포트입니다!

File Coverage [86.62%] 🍏
User.java 100% 🍏
RefreshTokenService.java 100% 🍏
CommandUserService.java 100% 🍏
QueryUserService.java 100% 🍏
UserCreator.java 100% 🍏
AuthService.java 95.12% 🍏
KakaoClient.java 88.48% 🍏
UserReader.java 50%
JwtService.java 0%
Total Project Coverage 92.79% 🍏

@sudhdkso sudhdkso merged commit df33cc1 into develop Jul 15, 2025
3 checks passed
This was referenced Jul 29, 2025
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants