⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content

[volume-1] 회원가입, 내 정보 조회, 비밀번호 변경 기능 구현#47

Open
ukukdin wants to merge 2 commits intoLoopers-dev-lab:ukukdinfrom
ukukdin:main
Open

[volume-1] 회원가입, 내 정보 조회, 비밀번호 변경 기능 구현#47
ukukdin wants to merge 2 commits intoLoopers-dev-lab:ukukdinfrom
ukukdin:main

Conversation

@ukukdin
Copy link

@ukukdin ukukdin commented Feb 6, 2026

📌 Summary

  • 배경: UserController에서 X-Loopers-LoginPw 헤더가 검증 없이 선언만 되어 인증 우회 가능, 생년월일 포맷팅/비밀번호 암호화 로직이 컨트롤러에 위치하여 계층 책임 혼재
  • 목표: 비밀번호 검증 로직 추가로 보안 취약점 해결, 표현 로직과 도메인 로직을 각 계층으로 분리
  • 결과: AuthenticationService 추가로 인증 처리, UserInfoResponse.from() 팩토리 메서드로 포맷팅 분리, 전체 64개 테스트 통과

🧭 Context & Decision

문제 정의

  • 현재 동작/제약:
    • getMyInfo, updatePassword에서 loginPw 파라미터가 @NotBlank 검증만 수행
    • register에서 Password.of(), passwordEncoder.encrypt() 컨트롤러에서 직접 호출
    • UserQueryService에서 생년월일 yyyyMMdd 포맷팅 수행
  • 문제(또는 리스크):
    • 🔴 Critical: 임의의 비밀번호로 사용자 정보 조회/변경 가능 (인증 우회)
    • 컨트롤러에 도메인 로직 혼재 → 테스트 어려움, 책임 불명확
    • 포맷 변경 시 서비스 수정 필요 → 표현/도메인 계층 결합
  • 성공 기준(완료 정의):
    • 모든 인증 필요 엔드포인트에서 비밀번호 검증 수행
    • 컨트롤러는 DTO 변환과 응답 조립만 담당
    • 전체 테스트 통과

선택지와 결정

  • 고려한 대안:
    • A: 컨트롤러에서 직접 인증 로직 구현 → 코드 중복, 테스트 어려움
    • B: AuthenticationUseCase 분리 → 재사용 가능, 단일 책임
  • 최종 결정: B안 - AuthenticationUseCase 신규 생성
  • 트레이드오프: UseCase 인터페이스 증가 (허용 가능한 수준)
  • 추후 개선 여지: Spring Security 도입 시 Filter 기반 인증으로 전환 가능

🏗️ Design Overview

변경 범위

  • 영향 받는 모듈/도메인: commerce-api (interfaces, application, domain 레이어)
  • 신규 추가:
    • AuthenticationUseCase, AuthenticationService
    • UserInfoResponse.from() 팩토리 메서드
    • AuthenticationServiceTest, UserInfoResponseTest
  • 제거/대체:
    • UserController에서 PasswordEncoder 의존성 제거
    • RegisterUseCase 시그니처 변경 (primitive 타입 수신)

주요 컴포넌트 책임

  • UserController: 요청 검증, 응답 조립 (도메인 로직 없음)
  • AuthenticationService: 사용자 인증 (ID/PW 검증)
  • UserRegisterService: 회원가입 + Password 생성/암호화
  • UserInfoResponse: API 응답 포맷팅 (from() 팩토리 메서드)
sequenceDiagram
    autonumber
    title: 내 정보 조회 (Me)
    participant Client
    participant Controller as UserController
    participant Auth as AuthenticationService
    participant Query as UserQueryService
    participant DB as UserRepository

    Client->>Controller: GET /api/v1/users/me
    Note over Client,Controller: Headers: X-Loopers-Id, X-Loopers-Pw
    
    Controller->>Auth: authenticate(userId, loginPw)
    Auth->>DB: findById(userId)
    DB-->>Auth: User Entity
    
    alt 비밀번호 불일치
        Auth-->>Controller: throw InvalidPasswordException
        Controller-->>Client: 401 Unauthorized
    else 인증 성공
        Auth-->>Controller: Success
    end

    Controller->>Query: getUserInfo(userId)
    Query->>DB: findById(userId)
    DB-->>Query: User Entity
    Query-->>Controller: UserInfoResponse
    
    Note right of Controller: UserInfoResponse.from(user)<br/>LocalDate to String
    Controller-->>Client: 200 OK {"birthday": "19900515"}
Loading
sequenceDiagram
    autonumber
    title: Main Flow - 회원가입
    participant Client
    participant Controller as UserController
    participant Service as UserRegisterService
    participant DB as UserRepository

    Client->>Controller: POST /api/v1/users/register
    Note over Client,Controller: Body: loginId, name, password, birthday, email
    
    Controller->>Service: register(command)
    
    Note right of Service: Birthday.of(birthday) <br/>(VO Validation)
    
    Service->>Service: Password.of(rawPassword)
    Service->>Service: passwordEncoder.encode(password)
    
    Service->>DB: save(User Entity)
    DB-->>Service: void
    
    Service-->>Controller: void
    Controller-->>Client: 201 Created
Loading

ukukdin and others added 2 commits February 6, 2026 18:15
- GlobalExceptionHandler 추가로 예외를 HTTP 응답으로 변환
- UserApiIntegrationTest: MockMvc 기반 통합 테스트 12개
  - 회원가입 API (4개): 성공, 중복 ID, 필수 필드 누락, 잘못된 이메일
  - 내 정보 조회 API (4개): 성공, 잘못된 비밀번호, 사용자 없음, 마스킹
  - 비밀번호 변경 API (4개): 성공, 현재 비밀번호 불일치, 동일 비밀번호, 인증 실패
- UserApiE2ETest: TestRestTemplate 기반 E2E 테스트 7개
  - 회원가입 시나리오 (2개)
  - 인증 시나리오 (2개)
  - 비밀번호 변경 시나리오 (2개)
  - 전체 사용자 플로우 (1개)

총 83개 테스트 통과

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
test: 통합 테스트 및 E2E 테스트 추가
@coderabbitai
Copy link

coderabbitai bot commented Feb 6, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

Comment @coderabbitai help to get the list of available commands and usage tips.

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.

1 participant