[Hyeonu] Week9 미션#99
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 48a7b66f07
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| return Member.builder() | ||
| .email(dto.getSocialEmail()) | ||
| .name(dto.getName()) | ||
| .socialType(dto.getSocialType()) | ||
| .socialUid(dto.getSocialUid()) |
There was a problem hiding this comment.
문제는 MemberConverter.toMember(OAuthDTO)가 email/name/social만 채워서 Member를 저장한다는 점입니다. 현재 Member의 birth/address/detailAddress/phoneNumber는 nullable=false라서 소셜 신규 사용자의 첫 로그인 시 INSERT가 제약조건 위반으로 실패하고 인증 흐름이 끊깁니다. 소셜 가입 전용 플로우를 분리해 필수 프로필을 추가로 입력받거나, 소셜 모델에 맞게 엔티티/스키마 제약을 재설계해 저장 시점에 필수값이 항상 보장되도록 바꾸는 것이 좋습니다. 다음으로 엔티티 제약(nullable)과 가입 플로우 분리 개념을 학습해 보세요.
Useful? React with 👍 / 👎.
| String email = attributes.get("email").toString(); | ||
| String name = profile.get("nickname").toString(); |
There was a problem hiding this comment.
문제는 Kakao 응답에서 email과 profile.nickname을 null 검증 없이 바로 toString()으로 변환한다는 점입니다. OAuth 동의 항목이 빠지거나 응답 구조가 달라지면 여기서 NullPointerException이 발생해 로그인 요청이 500으로 끝나고, 사용자는 왜 실패했는지 알 수 없습니다. provider별 매핑 전에 attribute 존재를 확인하고, 누락 시 명시적 도메인 예외(재동의 필요 등)로 처리하면 인증 흐름을 안정적으로 유지할 수 있습니다. 다음으로 OAuth2User attribute 매핑과 null-safe 파싱을 학습해 보세요.
Useful? React with 👍 / 👎.
kjhh2605
left a comment
There was a problem hiding this comment.
[키워드 조사]
세션과 토큰의 차이, Access Token/Refresh Token, OAuth 1.0과 2.0의 차이를 핵심 키워드 중심으로 정리한 점이 좋습니다. 다음 단계에서는 OAuth 2.0을 단순히 토큰 기반 인증으로만 보지 말고 Authorization Code 흐름, client/resource owner/resource server 역할, redirect URI, scope, refresh token 저장 위치까지 함께 연결하는 것을 권장합니다. JWT는 서명, 만료 시간, 클레임 설계, 탈취 시 대응 전략을 함께 정리하면 실제 코드 이해도가 높아집니다.
[코드 리뷰]
formLogin 기반 흐름에서 JWT와 OAuth2 로그인 흐름으로 확장하려는 시도가 적절합니다. SecurityFilterChain, JwtAuthFilter, UserDetailsService, OAuth 사용자 매핑을 분리해 인증 흐름을 계층별로 나누려는 방향도 좋습니다. 다만 OAuth 회원을 기존 Member 엔티티에 저장할 때 일반 회원 필수 필드와 충돌할 수 있고, JWT Stateless 설정과 OAuth 사용자 정보 파싱의 예외 흐름이 아직 명확하지 않습니다. 회원가입/로그인/OAuth 로그인 각각의 인증 주체 식별 기준을 먼저 정리한 뒤, Entity 제약 조건과 Security 설정을 그 기준에 맞추는 것을 권장합니다.
| | 사용성 | 낮음 | 높음 | | ||
| | 현재 사용 | 거의 안 씀 | 대부분 사용 | | ||
|
|
||
| OAuth 1.0은 서명 기반으로 복잡하고, OAuth 2.0은 토큰 기반으로 단순하고 확장성이 좋다. |
There was a problem hiding this comment.
OAuth 2.0을 Access Token 기반이라고만 정리하면 핵심 흐름이 다소 단순화됩니다. Authorization Code Grant 기준으로 client, resource owner, authorization server, resource server의 역할과 redirect URI, scope가 왜 필요한지까지 함께 정리하는 것을 권장합니다.
| } | ||
|
|
||
| public static Member toMember(OAuthDTO dto) { | ||
| return Member.builder() |
There was a problem hiding this comment.
OAuth 회원을 Member로 변환할 때 일반 회원가입에서 필요한 birth, address, detailAddress, phoneNumber 값이 채워지지 않습니다. 현재 엔티티에서는 해당 컬럼이 nullable=false이므로 소셜 로그인 저장 시 DB 제약 조건과 충돌할 수 있습니다. 일반 회원과 소셜 회원의 필수 정보 정책을 먼저 나누고, 엔티티 제약 조건이나 추가 정보 입력 흐름을 그 정책에 맞추는 것을 권장합니다.
| ) | ||
| // 로그아웃 설정 | ||
| .formLogin(AbstractHttpConfigurer::disable) | ||
| .sessionManagement(AbstractHttpConfigurer::disable) |
There was a problem hiding this comment.
JWT 기반 REST API를 의도했다면 sessionManagement를 비활성화하는 것보다 sessionCreationPolicy(SessionCreationPolicy.STATELESS)로 세션을 만들지 않겠다는 정책을 명시하는 것을 권장합니다. 이렇게 하면 form login 세션 방식과 JWT stateless 방식의 차이가 코드에서 더 명확해집니다.
| // 유저 객체에서 정보 추출 | ||
| SocialType providerId; | ||
| String socialUid; | ||
| Map<String, Object> attributes = oAuthMember.getAttribute("kakao_account"); |
There was a problem hiding this comment.
kakao_account, profile, email을 바로 꺼내면 동의 항목이 빠지거나 응답 구조가 예상과 다를 때 NullPointerException이 발생할 수 있습니다. OAuth 사용자 정보는 외부 API 응답이므로 필요한 필드 존재 여부를 확인하고, 없을 때 어떤 도메인 예외로 처리할지 정리하는 것을 권장합니다.
| public record LoginReqDTO( | ||
| String email, | ||
| String password | ||
| ){} |
There was a problem hiding this comment.
email 필드의 검증 조건이 없다면, swagger에서 확인했을 때 예시 값이 'string'으로 보여 email 형식으로 로그인을 강제하고 있는지 판단하기 어렵습니다. Reqeust DTO는 항상 검증 조건을 체크해야 합니다.
🔗 연관 이슈
closes #98
🛠 작업 내용
🖼 스크린샷 (선택)
👀 리뷰 요구사항 (선택)
🤖 AI 활용
💬 나의 프롬프트
왜 스웨거에서 토큰 넣었는데 마이페이지 조회가 안되는거지?
🧠 AI 응답
스프링 OAuth방식으로 하다가 이전 이메일로 인증하는 부분을 없애서 그런거다.
✅ 내가 최종 선택한 방법 (이유)
워크북 따라하다가 수정하래서 이전꺼 삭제했던게 기억났다.
💡 나만의 Tip (선택)