Skip to content

Conversation

@seung-in-Yoo
Copy link
Member

@seung-in-Yoo seung-in-Yoo commented Jul 20, 2025

#️⃣ 연관된 이슈

#58

📝 작업 내용

카카오 소셜 로그인 API 구현

  • /api/v1/users/login/kakao 엔드포인트 추가하였습니다. (POST)
  • 카카오측에서 AccessToken을 받아 사용자 정보를 조회하고 JWT 토큰 발급받는 형식으로 구현했습니다.
  • 닉네임/이메일/프로필이미지 등 3개의 회원 정보 저장을 반영하였습니다.
  • 카카오 소셜 로그인에 필요한 관련 DTO 설계를 진행했습니다.
  • 유저 엔티티의 gender 필드를 null 허용 했습니다. (카카오 소셜 로그인에서 동의항목에 성별을 받아오지 않아서 null로 들어가기때문에 해당 이유로 null 허용 했습니다. -> 동의항목에서 성별 받아오려면 앱 등록이 필요해서 현재는 null 허용으로 진행)

🖼️ 스크린샷 (선택)

client_id,redirect_uri 설정 후 들어와지는 화면

예시 url: https://kauth.kakao.com/oauth/authorize?client_id=REST_API_KEY&redirect_uri=http://localhost:8080/api/v1/users/login/kakao&response_type=code&scope=profile_nickname,account_email
카카오소셜로그인화면

카카오 디벨로퍼 -> 동의항목

카카오동의항목

카카오에서 지급한 토큰 발급 성공 (postman)

토큰발급성공(1)

지급받은 토큰으로 직접 swagger에서 테스트 진행 후 로그인 성공 (swagger)

스웨거테스트성공(1)

💬 리뷰 요구사항 (선택)

Summary by CodeRabbit

  • 신규 기능

    • 카카오 소셜 로그인을 지원하는 API 엔드포인트가 추가되었습니다.
    • 카카오 로그인 시 신규 가입 여부 및 사용자 정보를 반환합니다.
  • 버그 수정

    • 카카오 사용자 정보 응답에서 알 수 없는 JSON 필드를 무시하도록 개선되었습니다.
  • 기타

    • 사용자 성별 정보가 선택적으로 입력될 수 있도록 변경되었습니다.
    • 카카오 인증 실패 시의 에러 메시지가 추가되었습니다.
    • 사용자 장소 저장 및 조회 API에서 Authorization 헤더 파라미터가 제거되어 인증 처리가 내부 보안 컨텍스트를 통해 이루어집니다.

@seung-in-Yoo seung-in-Yoo self-assigned this Jul 20, 2025
@seung-in-Yoo seung-in-Yoo added the 💡 feature 기능 구현 및 개발 label Jul 20, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jul 20, 2025

"""

Walkthrough

카카오 소셜 로그인을 처리하는 새로운 REST 컨트롤러와 서비스가 추가되었습니다. 카카오 인증 요청 DTO와 응답 DTO를 사용하며, WebClient를 활용해 카카오 사용자 정보를 받아오고, 신규 사용자는 저장 후 JWT 토큰을 발급합니다. 관련 예외 및 DTO, 엔티티, 에러 케이스가 보완되었습니다.

Changes

파일/경로 요약 변경 내용 요약
.../controller/KakaoLoginController.java 카카오 로그인 요청을 처리하는 REST 컨트롤러 추가
.../service/auth/KakaoLoginService.java 카카오 로그인 로직, WebClient 통한 사용자 정보 조회, JWT 토큰 발급 서비스 클래스 추가
.../dto/KakaoUserInfoDto.java DTO 및 내부 클래스에 @JsonIgnoreProperties(ignoreUnknown = true) 어노테이션 추가
.../entity/User.java gender 필드 nullable 변경, profileImageUrl setter 메서드 추가
.../exception/UserErrorCase.java KAKAO_AUTH_FAILED 에러 케이스(401) 추가, FORBIDDEN 뒤 세미콜론을 콤마로 변경
.../controller/UserPlaceController.java Authorization 헤더 파라미터 제거, SecurityContextHolder 기반 인증 처리로 변경

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant KakaoLoginController
    participant KakaoLoginService
    participant KakaoAPI
    participant UserRepository
    participant JwtTokenProvider

    Client->>KakaoLoginController: POST /api/v1/users/login/kakao (accessToken)
    KakaoLoginController->>KakaoLoginService: kakaoLogin(request)
    KakaoLoginService->>KakaoAPI: GET /v2/user/me (accessToken)
    KakaoAPI-->>KakaoLoginService: KakaoUserInfoDto
    KakaoLoginService->>UserRepository: findByEmailAndLoginType(email, KAKAO)
    alt 신규 사용자
        KakaoLoginService->>UserRepository: save(new User)
    end
    KakaoLoginService->>JwtTokenProvider: createAccessToken(user)
    KakaoLoginService->>JwtTokenProvider: createRefreshToken(user)
    KakaoLoginService-->>KakaoLoginController: KakaoLoginResponseDto
    KakaoLoginController-->>Client: CommonResponse<KakaoLoginResponseDto>
Loading

Estimated code review effort

3 (90–240분)

Possibly related issues

Suggested labels

🔧 refactor

Suggested reviewers

  • KiSeungMin

Poem

🥕
카카오 바람 타고 토끼가 뛴다,
로그인 컨트롤러 새로 생겼다!
WebClient로 정보 받아
토큰 주머니에 쏙쏙 담아,
신규 유저도 반갑게 맞이해
오늘도 서버는 평화롭다네!
🐰
"""

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 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 docstrings to generate docstrings for this 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.

@seung-in-Yoo seung-in-Yoo linked an issue Jul 20, 2025 that may be closed by this pull request
7 tasks
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: 10

♻️ Duplicate comments (1)
src/main/java/com/wayble/server/user/controller/UserPlaceController.java (1)

64-67: 일관된 인증 로직이 적용되었습니다.

getUserPlaces 메서드에서도 동일한 인증 방식을 사용하여 일관성을 유지하고 있습니다. 다만 여기서도 동일한 캐스팅 안전성 문제가 있으니 위에서 제안한 방식으로 개선하시기 바랍니다.

🧹 Nitpick comments (4)
src/main/java/com/wayble/server/user/service/UserPlaceService.java (1)

75-75: 이미지 URL 조회 로직이 효율적으로 개선되었습니다.

기존의 스트림 방식에서 getMainImageUrl() 직접 호출로 변경하여 성능이 개선되었습니다. WaybleZone 엔티티의 mainImageUrl 필드 추가와 잘 연계된 변경사항입니다.

다만 mainImageUrl이 null인 경우에 대한 처리를 고려해보시기 바랍니다:

-            String imageUrl = waybleZone.getMainImageUrl();
+            String imageUrl = waybleZone.getMainImageUrl() != null ? 
+                waybleZone.getMainImageUrl() : "default_image_url";
src/main/java/com/wayble/server/user/controller/UserPlaceController.java (1)

39-39: Authorization 헤더 파라미터가 불필요합니다.

현재 코드에서는 Authorization 헤더를 파라미터로 받고 있지만 실제로는 사용하지 않습니다. Spring Security에서 자동으로 처리하므로 이 파라미터는 제거하는 것이 좋습니다.

     public CommonResponse<String> saveUserPlace(
             @PathVariable Long userId,
-            @RequestBody @Valid UserPlaceRequestDto request,
-            @RequestHeader(value = "Authorization") String authorizationHeader
+            @RequestBody @Valid UserPlaceRequestDto request
     ) {
     public CommonResponse<List<UserPlaceListResponseDto>> getUserPlaces(
-            @PathVariable Long userId,
-            @RequestHeader("Authorization") String authorizationHeader
+            @PathVariable Long userId
     ) {

Also applies to: 62-62

src/main/java/com/wayble/server/user/dto/KakaoLoginResponseDto.java (1)

12-17: 중첩 UserDto 문서화 추가

중첩된 UserDto에도 적절한 문서화가 필요합니다.

+    /**
+     * 사용자 기본 정보 DTO
+     */
    @Builder
    public record UserDto(
+            /** 사용자 ID */
            Long id,
+            /** 닉네임 */
            String nickname,
+            /** 이메일 */
            String email
    ) {}
src/main/java/com/wayble/server/user/service/auth/KakaoLoginService.java (1)

30-40: 사용자 정보 추출 로직이 적절합니다.

카카오 API 응답에서 필요한 사용자 정보를 올바르게 추출하고 있습니다. 다만, kakaoId 변수는 현재 사용되지 않고 있는 것 같습니다.

만약 향후 사용할 계획이 없다면 해당 라인을 제거하거나, 사용할 계획이 있다면 주석으로 설명을 추가해주세요.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4d3e39b and 43b16b8.

📒 Files selected for processing (11)
  • src/main/java/com/wayble/server/user/controller/KakaoLoginController.java (1 hunks)
  • src/main/java/com/wayble/server/user/controller/UserPlaceController.java (3 hunks)
  • src/main/java/com/wayble/server/user/dto/KakaoLoginRequestDto.java (1 hunks)
  • src/main/java/com/wayble/server/user/dto/KakaoLoginResponseDto.java (1 hunks)
  • src/main/java/com/wayble/server/user/dto/KakaoUserInfoDto.java (1 hunks)
  • src/main/java/com/wayble/server/user/dto/UserPlaceRequestDto.java (0 hunks)
  • src/main/java/com/wayble/server/user/entity/User.java (1 hunks)
  • src/main/java/com/wayble/server/user/exception/UserErrorCase.java (1 hunks)
  • src/main/java/com/wayble/server/user/service/UserPlaceService.java (2 hunks)
  • src/main/java/com/wayble/server/user/service/auth/KakaoLoginService.java (1 hunks)
  • src/main/java/com/wayble/server/wayblezone/entity/WaybleZone.java (1 hunks)
💤 Files with no reviewable changes (1)
  • src/main/java/com/wayble/server/user/dto/UserPlaceRequestDto.java
🧰 Additional context used
🧠 Learnings (2)
src/main/java/com/wayble/server/wayblezone/entity/WaybleZone.java (1)
Learnt from: seung-in-Yoo
PR: Wayble-Project/wayble-spring#37
File: src/main/java/com/wayble/server/user/entity/User.java:61-62
Timestamp: 2025-07-13T15:08:59.318Z
Learning: Java에서 같은 패키지 내의 클래스들은 import 구문 없이 서로를 참조할 수 있다. com.wayble.server.user.entity 패키지 내의 클래스들은 명시적인 import 없이 사용 가능하다.
src/main/java/com/wayble/server/user/dto/KakaoUserInfoDto.java (1)
Learnt from: seung-in-Yoo
PR: Wayble-Project/wayble-spring#37
File: src/main/java/com/wayble/server/user/entity/User.java:61-62
Timestamp: 2025-07-13T15:08:59.318Z
Learning: Java에서 같은 패키지 내의 클래스들은 import 구문 없이 서로를 참조할 수 있다. com.wayble.server.user.entity 패키지 내의 클래스들은 명시적인 import 없이 사용 가능하다.
🧬 Code Graph Analysis (2)
src/main/java/com/wayble/server/user/dto/KakaoLoginResponseDto.java (1)
src/main/java/com/wayble/server/common/response/CommonResponse.java (1)
  • Builder (8-42)
src/main/java/com/wayble/server/user/controller/KakaoLoginController.java (1)
src/main/java/com/wayble/server/common/config/security/jwt/JwtAuthenticationFilter.java (1)
  • RequiredArgsConstructor (13-43)
🔇 Additional comments (11)
src/main/java/com/wayble/server/wayblezone/entity/WaybleZone.java (1)

61-63: 대표 이미지 필드 추가는 성능 개선에 도움이 됩니다.

기존 방식에서 이미지 리스트를 스트림으로 조회하던 것을 직접 필드로 저장하여 성능을 개선한 좋은 변경사항입니다.

다만 이 필드가 nullable로 설정되어 있는데, 대표 이미지가 없는 경우에 대한 기본값 처리나 검증 로직을 고려해보시기 바랍니다.

src/main/java/com/wayble/server/user/service/UserPlaceService.java (3)

32-32: 메서드 시그니처 개선이 보안을 강화합니다.

userId를 별도 파라미터로 받는 것은 컨트롤러에서 인증된 사용자 ID를 직접 전달하여 보안을 강화하는 좋은 변경사항입니다.


34-34: 파라미터 활용 변경이 일관성을 개선합니다.

인증된 userId 파라미터를 직접 사용하여 사용자 조회와 중복 확인을 수행하는 것이 더 명확하고 안전합니다.

Also applies to: 42-42


32-46: 호출부 검토 완료: 메서드 시그니처가 올바르게 업데이트되었습니다.

UserPlaceController.java(36행): 컨트롤러 메서드 시그니처
UserPlaceController.java(46행): userPlaceService.saveUserPlace(userId, request) 호출

위 두 곳 모두 새 시그니처(Long userId, UserPlaceRequestDto request)에 맞춰 수정되어 있어 호환성에 문제가 없습니다.

src/main/java/com/wayble/server/user/controller/UserPlaceController.java (2)

46-46: 서비스 메서드 호출이 올바르게 업데이트되었습니다.

userId 파라미터를 별도로 전달하는 방식으로 변경된 것이 서비스 레이어의 변경사항과 일치합니다.


33-35: API 응답 문서가 적절히 업데이트되었습니다.

403 Forbidden 응답 케이스를 추가한 것이 변경된 인증 로직과 일치합니다.

src/main/java/com/wayble/server/user/exception/UserErrorCase.java (1)

17-18: 카카오 인증 실패 에러 케이스 추가 적절함

새로운 KAKAO_AUTH_FAILED 에러 케이스가 적절하게 추가되었습니다. HTTP 상태 코드 401과 에러 메시지가 카카오 인증 실패 상황에 적합합니다.

src/main/java/com/wayble/server/user/controller/KakaoLoginController.java (3)

17-19: 컨트롤러 구조가 잘 설계되었습니다.

Spring Boot의 표준 패턴을 잘 따르고 있으며, 의존성 주입과 요청 매핑이 적절히 구현되어 있습니다.


24-30: API 문서화가 잘 되어 있습니다.

OpenAPI 어노테이션을 통해 엔드포인트에 대한 명확한 설명과 응답 코드가 문서화되어 있어 좋습니다.


31-36: 전역 예외 처리기 확인 완료

src/main/java/com/wayble/server/common/exception/GlobalExceptionHandler.java에서
@ExceptionHandler(ApplicationException.class)를 통해 ApplicationException을 처리하고 있으므로,
컨트롤러 단에서 별도 예외 처리 로직을 추가할 필요가 없습니다.

src/main/java/com/wayble/server/user/service/auth/KakaoLoginService.java (1)

65-80: JWT “role” 클레임 처리 로직 확인 요청

  • JwtTokenProvider.generateToken(Long, String)에서 userType.name()"role" 클레임으로 설정하고 있습니다. UserType enum 값(DISABLED, COMPANION)과 일치합니다.
  • JwtTokenProvider에는 토큰 유효성 검사(validateToken), 사용자 ID 파싱(getUserId), 만료시간 파싱(getTokenExpiry) 메서드만 구현되어 있습니다.
    • “role” 클레임을 파싱해서 GrantedAuthority로 변환하고 Authentication 객체에 반영하는 로직이 있는지 확인해주세요.
    • 보통 JwtAuthenticationFilter 또는 SecurityConfig 내 getAuthentication 메서드에서 처리됩니다.
  • 인증/인가 전체 흐름에서 “role” 클레임이 올바르게 읽히고 권한 부여에 사용되는지 검증 부탁드립니다.

Comment on lines 41 to 44
Long tokenUserId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (!userId.equals(tokenUserId)) {
throw new ApplicationException(UserErrorCase.FORBIDDEN);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Spring Security 컨텍스트 사용이 좋은 개선입니다.

JWT 토큰을 수동으로 파싱하던 방식에서 Spring Security의 인증 컨텍스트를 사용하는 것으로 변경한 것은 표준적이고 안전한 접근법입니다.

다만 타입 캐스팅에서 ClassCastException이 발생할 수 있습니다.

안전한 캐스팅을 위해 다음과 같이 개선하는 것을 제안합니다:

-        Long tokenUserId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        if (!(authentication.getPrincipal() instanceof Long)) {
+            throw new ApplicationException(UserErrorCase.FORBIDDEN);
+        }
+        Long tokenUserId = (Long) authentication.getPrincipal();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Long tokenUserId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (!userId.equals(tokenUserId)) {
throw new ApplicationException(UserErrorCase.FORBIDDEN);
}
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication.getPrincipal() instanceof Long)) {
throw new ApplicationException(UserErrorCase.FORBIDDEN);
}
Long tokenUserId = (Long) authentication.getPrincipal();
if (!userId.equals(tokenUserId)) {
throw new ApplicationException(UserErrorCase.FORBIDDEN);
}
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/user/controller/UserPlaceController.java
around lines 41 to 44, the code casts the principal object from the Spring
Security context directly to Long, which can cause ClassCastException. To fix
this, retrieve the principal as an Object, check its type safely, and extract
the user ID accordingly, for example by checking if the principal is an instance
of a UserDetails implementation or a String, then convert or parse it to Long
before comparing with userId.

Comment on lines 3 to 5
public record KakaoLoginRequestDto(
String accessToken
) {} No newline at end of file
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

입력 검증 및 문서화 추가 필요

카카오 액세스 토큰에 대한 유효성 검사가 없어 보안상 위험할 수 있습니다.

다음과 같이 개선하세요:

package com.wayble.server.user.dto;

+import jakarta.validation.constraints.NotBlank;
+
+/**
+ * 카카오 로그인 요청 DTO
+ */
public record KakaoLoginRequestDto(
+        @NotBlank(message = "액세스 토큰은 필수입니다")
        String accessToken
) {}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public record KakaoLoginRequestDto(
String accessToken
) {}
package com.wayble.server.user.dto;
import jakarta.validation.constraints.NotBlank;
/**
* 카카오 로그인 요청 DTO
*/
public record KakaoLoginRequestDto(
@NotBlank(message = "액세스 토큰은 필수입니다")
String accessToken
) {}
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/user/dto/KakaoLoginRequestDto.java around
lines 3 to 5, the KakaoLoginRequestDto record lacks validation for the
accessToken field, which poses a security risk. Add input validation annotations
such as @NotBlank or @NotNull to ensure the accessToken is provided and not
empty. Additionally, include JavaDoc comments to document the purpose and
constraints of the accessToken field for better clarity and maintainability.

Comment on lines 5 to 11
@Builder
public record KakaoLoginResponseDto(
String accessToken,
String refreshToken,
boolean isNewUser,
UserDto user
) {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

문서화 및 보안 고려사항 추가 필요

응답 DTO에 문서화가 부족하고 민감한 토큰 정보에 대한 보안 고려사항이 필요합니다.

package com.wayble.server.user.dto;

import lombok.Builder;

+/**
+ * 카카오 로그인 응답 DTO
+ */
@Builder
public record KakaoLoginResponseDto(
+        /** JWT 액세스 토큰 */
        String accessToken,
+        /** JWT 리프레시 토큰 */
        String refreshToken,
+        /** 신규 사용자 여부 */
        boolean isNewUser,
+        /** 사용자 정보 */
        UserDto user
) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Builder
public record KakaoLoginResponseDto(
String accessToken,
String refreshToken,
boolean isNewUser,
UserDto user
) {
package com.wayble.server.user.dto;
import lombok.Builder;
/**
* 카카오 로그인 응답 DTO
*/
@Builder
public record KakaoLoginResponseDto(
/** JWT 액세스 토큰 */
String accessToken,
/** JWT 리프레시 토큰 */
String refreshToken,
/** 신규 사용자 여부 */
boolean isNewUser,
/** 사용자 정보 */
UserDto user
) {
}
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/user/dto/KakaoLoginResponseDto.java around
lines 5 to 11, the response DTO lacks proper documentation and does not address
security concerns for sensitive token fields. Add JavaDoc comments to the class
and its fields explaining their purpose. Additionally, consider marking the
accessToken and refreshToken fields to be excluded from logs or serialization
where appropriate to enhance security.

Comment on lines 6 to 10
@Getter
@Setter
public class KakaoUserInfoDto {
private Long id;
private KakaoAccount kakao_account;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

불변성과 JSON 매핑 개선 필요

DTO에서 @Setter 사용은 객체의 불변성을 해치고 예상치 못한 변경을 허용할 수 있습니다.

Jackson 어노테이션을 사용하여 불변 DTO로 개선하세요:

package com.wayble.server.user.dto;

+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
-import lombok.Setter;

@Getter
-@Setter
public class KakaoUserInfoDto {
    private Long id;
+    @JsonProperty("kakao_account")
-    private KakaoAccount kakao_account;
+    private KakaoAccount kakaoAccount;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Getter
@Setter
public class KakaoUserInfoDto {
private Long id;
private KakaoAccount kakao_account;
package com.wayble.server.user.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
@Getter
public class KakaoUserInfoDto {
private Long id;
@JsonProperty("kakao_account")
private KakaoAccount kakaoAccount;
// … any other fields or nested classes …
}
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/user/dto/KakaoUserInfoDto.java around lines 6
to 10, the use of @Setter allows modification of the DTO fields, which breaks
immutability and can lead to unexpected changes. Remove the @Setter annotation
and make the fields final. Add a constructor annotated with @JsonCreator and use
@JsonProperty on the parameters to enable proper JSON mapping while keeping the
DTO immutable.

Comment on lines 12 to 24
@Getter
@Setter
public static class KakaoAccount {
private String email;
private Profile profile;

@Getter
@Setter
public static class Profile {
private String nickname;
private String profile_image_url;
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

중첩 클래스들도 불변성 적용 필요

모든 중첩 클래스에서도 @Setter를 제거하고 Jackson 어노테이션을 추가해야 합니다.

    @Getter
-    @Setter
    public static class KakaoAccount {
        private String email;
        private Profile profile;

        @Getter
-        @Setter
        public static class Profile {
            private String nickname;
+            @JsonProperty("profile_image_url")
-            private String profile_image_url;
+            private String profileImageUrl;
        }
    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Getter
@Setter
public static class KakaoAccount {
private String email;
private Profile profile;
@Getter
@Setter
public static class Profile {
private String nickname;
private String profile_image_url;
}
}
@Getter
public static class KakaoAccount {
private String email;
private Profile profile;
@Getter
public static class Profile {
private String nickname;
@JsonProperty("profile_image_url")
private String profileImageUrl;
}
}
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/user/dto/KakaoUserInfoDto.java from lines 12
to 24, remove all @Setter annotations from the nested classes to enforce
immutability. Add appropriate Jackson annotations such as @JsonProperty to map
JSON fields to Java fields correctly without setters. This will make the nested
classes immutable and compatible with Jackson deserialization.

Comment on lines 65 to 68
// 혹시 필요할수도 있어서 추가해놓음
public void setMainImageUrl(String mainImageUrl) {
this.mainImageUrl = mainImageUrl;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

엔티티 설계 일관성을 고려해보세요.

현재 엔티티는 Lombok의 @Getter만 사용하고 있는데, 수동으로 setter를 추가하는 것은 일관성에 맞지 않습니다.

또한 주석의 톤이 비공식적입니다.

다음과 같이 개선을 제안합니다:

-    // 혹시 필요할수도 있어서 추가해놓음
-    public void setMainImageUrl(String mainImageUrl) {
-        this.mainImageUrl = mainImageUrl;
-    }
+    /**
+     * 대표 이미지 URL을 설정합니다.
+     * @param mainImageUrl 설정할 대표 이미지 URL
+     */
+    public void updateMainImageUrl(String mainImageUrl) {
+        this.mainImageUrl = mainImageUrl;
+    }

또는 엔티티의 불변성을 유지하고 생성 시에만 설정하도록 @Builder@Builder.Default 사용을 고려해보세요.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// 혹시 필요할수도 있어서 추가해놓음
public void setMainImageUrl(String mainImageUrl) {
this.mainImageUrl = mainImageUrl;
}
/**
* 대표 이미지 URL을 설정합니다.
* @param mainImageUrl 설정할 대표 이미지 URL
*/
public void updateMainImageUrl(String mainImageUrl) {
this.mainImageUrl = mainImageUrl;
}
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/wayblezone/entity/WaybleZone.java around
lines 65 to 68, the setter method for mainImageUrl is manually added while the
class uses Lombok's @Getter only, causing inconsistency. Remove the manual
setter and instead use Lombok annotations like @Setter if setters are needed, or
better, maintain immutability by setting the field via constructor or @Builder
with @Builder.Default. Also, replace the informal comment with a clear,
professional explanation or remove it if unnecessary.

Copy link
Member

@KiSeungMin KiSeungMin left a comment

Choose a reason for hiding this comment

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

오홍 저는 프론트에서 카카오 관련 정보 전부 받아서 서버에 전달하는 식으로 구현했었는데,
서버에서 처리하려면 이렇게 하는군요...! 수고 많으셨습니다!!!

이건 다른 궁금증인데 보통 웹에서 카카오 로그인 할 때는 redirection url을 반환해야 하던데 앱 쪽은 딱히 상관 없을까요??

@seung-in-Yoo
Copy link
Member Author

오홍 저는 프론트에서 카카오 관련 정보 전부 받아서 서버에 전달하는 식으로 구현했었는데, 서버에서 처리하려면 이렇게 하는군요...! 수고 많으셨습니다!!!

이건 다른 궁금증인데 보통 웹에서 카카오 로그인 할 때는 redirection url을 반환해야 하던데 앱 쪽은 딱히 상관 없을까요??

iOS/안드로이드 앱에서는 리다이렉트 URL 자체로 보여주지 않고 보통 앱에서 카카오 SDK를 사용해서 앱이 인가코드 또는 access token을 직접 받는다고 하더라구요! 그래서 서버는 프론트가 받은 access token만 전달받아서 처리하면 되는거 같아요

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: 0

♻️ Duplicate comments (1)
src/main/java/com/wayble/server/user/controller/UserPlaceController.java (1)

39-42: SecurityContext에서 Long으로 직접 캐스팅 시 ClassCastException 위험

SecurityContextHolder에서 꺼낸 principal을 바로 Long으로 캐스팅하고 있습니다.
principal 타입이 언제든지 Long이 아닐 수 있어 런타임에 ClassCastException이 발생할 수 있습니다. 이전 리뷰에서도 동일 지적이 있었으므로, 안전한 타입 체크 로직으로 교체해 주세요.

Also applies to: 61-64

🧹 Nitpick comments (1)
src/main/java/com/wayble/server/user/controller/UserPlaceController.java (1)

35-44: @AuthenticationPrincipal 활용으로 코드 단순화 가능

메서드 시그니처에 @AuthenticationPrincipal Long tokenUserId 를 추가하면 SecurityContext에서 직접 꺼내고 캐스팅할 필요가 없어집니다. 예시:

public CommonResponse<String> saveUserPlace(
        @PathVariable Long userId,
        @RequestBody @Valid UserPlaceRequestDto request,
        @AuthenticationPrincipal Long tokenUserId
) {
    if (!userId.equals(tokenUserId)) {
        throw new ApplicationException(UserErrorCase.FORBIDDEN);
    }
    ...
}

가독성과 안전성이 동시에 개선되니 검토해 보시기 바랍니다.

Also applies to: 58-66

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 30ca8fb and 939f1bc.

📒 Files selected for processing (1)
  • src/main/java/com/wayble/server/user/controller/UserPlaceController.java (2 hunks)
⏰ 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: run-docker-image-on-ec2

@KiSeungMin
Copy link
Member

오호 그렇게 처리하는군요 하나 배워갑니다...! 수고 많으셨어요!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💡 feature 기능 구현 및 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 카카오 소셜 로그인 구현

3 participants