# User Service 내부 시퀀스 설계서 ## 문서 정보 - **작성일**: 2025-10-22 - **작성자**: System Architect - **버전**: 1.0 - **관련 문서**: - [유저스토리](../../../userstory.md) - [외부 시퀀스](../outer/사용자인증플로우.puml) - [논리 아키텍처](../../logical/logical-architecture.md) --- ## 개요 User Service의 4가지 주요 시나리오에 대한 내부 처리 흐름을 상세히 정의합니다. ### 시나리오 목록 | 번호 | 파일명 | 유저스토리 | 주요 처리 내용 | |------|--------|-----------|---------------| | 1 | user-회원가입.puml | UFR-USER-010 | 기본 정보 검증, 사업자번호 검증(국세청 API), 트랜잭션 처리, JWT 발급 | | 2 | user-로그인.puml | UFR-USER-020 | 비밀번호 검증(bcrypt), JWT 발급, 세션 저장, 최종 로그인 시각 업데이트 | | 3 | user-프로필수정.puml | UFR-USER-030 | 기본 정보 수정, 매장 정보 수정, 비밀번호 변경, 트랜잭션 처리 | | 4 | user-로그아웃.puml | UFR-USER-040 | JWT 검증, 세션 삭제, Blacklist 추가 | --- ## 아키텍처 구조 ### Layered Architecture ``` ┌─────────────────────────────────────┐ │ API Layer (Controller) │ - HTTP 요청/응답 처리 │ │ - DTO 변환 및 검증 └─────────────────────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ Business Layer (Service) │ - 비즈니스 로직 처리 │ - UserService │ - 트랜잭션 관리 │ - AuthenticationService │ - 외부 API 연동 │ - BusinessValidator │ └─────────────────────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ Data Layer (Repository) │ - 데이터베이스 접근 │ - UserRepository │ - JPA/MyBatis │ - StoreRepository │ └─────────────────────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ External Systems │ - 국세청 API │ │ - Redis Cache │ │ - PostgreSQL DB └─────────────────────────────────────┘ ``` ### 주요 컴포넌트 #### API Layer - **UserController**: 사용자 관련 REST API 엔드포인트 - `POST /api/users/register`: 회원가입 - `POST /api/users/login`: 로그인 - `PUT /api/users/profile`: 프로필 수정 - `POST /api/users/logout`: 로그아웃 #### Business Layer - **UserService**: 사용자 정보 관리 비즈니스 로직 - **AuthenticationService**: 인증 및 세션 관리 로직 - **BusinessValidator**: 사업자번호 검증 로직 (Circuit Breaker 적용) #### Data Layer - **UserRepository**: users 테이블 CRUD - **StoreRepository**: stores 테이블 CRUD #### Utility - **PasswordEncoder**: bcrypt 해싱 (Cost Factor 10) - **JwtTokenProvider**: JWT 토큰 생성/검증 (만료 7일) --- ## 시나리오별 상세 설명 ### 1. 회원가입 (user-회원가입.puml) #### 처리 단계 1. **입력 검증**: `@Valid` 어노테이션으로 DTO 검증 2. **중복 사용자 확인**: 전화번호 기반 중복 체크 3. **사업자번호 검증**: - Redis 캐시 확인 (TTL 7일) - 캐시 MISS: 국세청 API 호출 (Circuit Breaker 적용) - 캐시 HIT: 0.1초, MISS: 5초 4. **비밀번호 해싱**: bcrypt (Cost Factor 10) 5. **사업자번호 암호화**: AES-256 6. **데이터베이스 트랜잭션**: - User INSERT - Store INSERT - COMMIT (실패 시 자동 Rollback) 7. **JWT 토큰 생성**: Claims(userId, role=OWNER, exp=7일) 8. **세션 저장**: Redis (TTL 7일) #### Resilience 패턴 - **Circuit Breaker**: 국세청 API (실패율 50% 초과 시 Open) - **Retry**: 최대 3회 (지수 백오프: 1초, 2초, 4초) - **Timeout**: 5초 - **Fallback**: 사업자번호 검증 스킵 (수동 확인 안내) #### 응답 시간 - 캐시 HIT: 1초 이내 - 캐시 MISS: 5초 이내 --- ### 2. 로그인 (user-로그인.puml) #### 처리 단계 1. **입력 검증**: 필수 필드 확인 2. **사용자 조회**: 전화번호로 사용자 검색 3. **비밀번호 검증**: bcrypt compare 4. **JWT 토큰 생성**: Claims(userId, role=OWNER, exp=7일) 5. **세션 저장**: Redis (TTL 7일) 6. **최종 로그인 시각 업데이트**: 비동기 처리 (`@Async`) #### 보안 처리 - 에러 메시지: 전화번호/비밀번호 구분 없이 동일 메시지 반환 - 비밀번호: bcrypt compare (원본 노출 안 됨) #### 성능 최적화 - 최종 로그인 시각 업데이트: 비동기 처리로 응답 시간 단축 - 응답 시간: 0.5초 목표 --- ### 3. 프로필 수정 (user-프로필수정.puml) #### 처리 단계 1. **JWT 인증**: `@AuthenticationPrincipal`로 userId 추출 2. **사용자 조회**: userId로 기존 정보 조회 3. **비밀번호 변경 처리** (선택적): - 현재 비밀번호 검증 (bcrypt compare) - 새 비밀번호 해싱 (bcrypt) 4. **기본 정보 업데이트**: 이름, 전화번호, 이메일 5. **매장 정보 업데이트**: 매장명, 업종, 주소, 영업시간 6. **데이터베이스 트랜잭션**: - User UPDATE - Store UPDATE - COMMIT (실패 시 자동 Rollback) 7. **캐시 무효화**: 프로필 캐시 삭제 (선택적) #### 보안 처리 - 비밀번호 변경: 현재 비밀번호 확인 필수 - 권한 검증: 본인만 수정 가능 #### 향후 개선사항 - 전화번호 변경: SMS/이메일 재인증 구현 - 이메일 변경: 이메일 인증 구현 --- ### 4. 로그아웃 (user-로그아웃.puml) #### 처리 단계 1. **JWT 인증**: `@AuthenticationPrincipal`로 userId 추출 2. **JWT 토큰 검증**: 서명 및 만료 시간 확인 3. **Redis 세션 삭제**: `DEL user:session:{token}` 4. **JWT Blacklist 추가** (선택적): - 만료되지 않은 토큰 강제 무효화 - Redis에 Blacklist 추가 (TTL: 남은 만료 시간) 5. **로그아웃 로그 기록**: userId, timestamp #### 보안 처리 - JWT Blacklist: 만료 전 토큰 강제 무효화 - 멱등성 보장: 중복 로그아웃 요청에 안전 #### 클라이언트 측 처리 - LocalStorage 또는 Cookie에서 JWT 토큰 삭제 - 로그인 화면으로 리다이렉트 #### 성능 최적화 - Redis 삭제 연산: O(1) 시간 복잡도 - 응답 시간: 0.1초 이내 --- ## 데이터 모델 ### User Entity ```java @Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long userId; @Column(nullable = false, length = 100) private String name; @Column(nullable = false, unique = true, length = 20) private String phoneNumber; @Column(nullable = false, unique = true, length = 255) private String email; @Column(nullable = false, length = 60) private String passwordHash; // bcrypt hash @Enumerated(EnumType.STRING) @Column(nullable = false, length = 20) private UserRole role; // OWNER, CUSTOMER @Column(name = "last_login_at") private LocalDateTime lastLoginAt; @Column(name = "created_at", nullable = false) private LocalDateTime createdAt; @Column(name = "updated_at") private LocalDateTime updatedAt; } ``` ### Store Entity ```java @Entity @Table(name = "stores") public class Store { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long storeId; @Column(name = "user_id", nullable = false) private Long userId; @Column(nullable = false, length = 200) private String storeName; @Column(length = 100) private String industry; @Column(columnDefinition = "TEXT") private String address; @Column(name = "business_number_encrypted", length = 255) private String businessNumberEncrypted; // AES-256 encrypted @Column(name = "business_hours", length = 500) private String businessHours; @Column(name = "created_at", nullable = false) private LocalDateTime createdAt; @Column(name = "updated_at") private LocalDateTime updatedAt; } ``` --- ## 캐싱 전략 ### Redis 캐시 키 구조 | 캐시 키 패턴 | 데이터 타입 | TTL | 용도 | |------------|-----------|-----|------| | `user:session:{token}` | String (JSON) | 7일 | JWT 세션 정보 (userId, role) | | `user:business:{사업자번호}` | String (JSON) | 7일 | 사업자번호 검증 결과 (valid, status) | | `jwt:blacklist:{token}` | String | 남은 만료 시간 | 로그아웃된 JWT 토큰 Blacklist | | `user:profile:{userId}` | String (JSON) | 1시간 | 사용자 프로필 정보 (선택적) | ### Cache-Aside 패턴 1. Application → Redis 확인 (Cache HIT/MISS) 2. Cache MISS → Database/External API 조회 3. Database/External API → Redis 캐싱 (TTL 설정) 4. Redis → Application 반환 --- ## 에러 처리 ### 주요 예외 클래스 | 예외 클래스 | HTTP 상태 | 발생 시점 | |-----------|---------|----------| | `DuplicateUserException` | 400 | 이미 가입된 전화번호 | | `BusinessNumberInvalidException` | 400 | 사업자번호 검증 실패 | | `AuthenticationFailedException` | 401 | 로그인 실패 (전화번호/비밀번호 불일치) | | `InvalidTokenException` | 401 | JWT 토큰 무효 | | `UserNotFoundException` | 404 | 사용자 없음 | | `InvalidPasswordException` | 400 | 현재 비밀번호 불일치 (프로필 수정) | ### 에러 응답 형식 ```json { "error": "에러 메시지", "code": "ERROR_CODE", "timestamp": "2025-10-22T10:30:00Z" } ``` --- ## 보안 고려사항 ### 1. 비밀번호 보안 - **해싱 알고리즘**: bcrypt (Cost Factor 10) - **원본 노출 방지**: 비밀번호는 해시로만 저장, 평문 로깅 금지 - **에러 메시지**: 전화번호/비밀번호 구분 없이 동일 메시지 반환 (보안 강화) ### 2. JWT 보안 - **만료 시간**: 7일 (Refresh Token 별도 구현 가능) - **서명 알고리즘**: HS256 또는 RS256 - **Blacklist 관리**: 로그아웃 시 Redis Blacklist에 추가 ### 3. 민감 정보 암호화 - **사업자번호**: AES-256 암호화 저장 - **전송 보안**: HTTPS 강제 적용 ### 4. 세션 관리 - **세션 저장**: Redis (서버 재시작에도 유지) - **세션 만료**: 7일 후 자동 삭제 (TTL) - **동시 세션**: 동일 사용자 다중 세션 허용 (필요 시 제한 가능) --- ## 성능 최적화 ### 1. 캐싱 효과 - **사업자번호 검증**: 5초 → 0.1초 (98% 개선) - **세션 조회**: Redis 사용으로 DB 부하 감소 ### 2. 비동기 처리 - **최종 로그인 시각 업데이트**: `@Async`로 비동기 처리 - **응답 시간 개선**: 0.5초 목표 달성 ### 3. 데이터베이스 최적화 - **인덱스**: `phone_number`, `email` 컬럼에 Unique Index - **Connection Pool**: HikariCP 사용 (최소 10개, 최대 50개) --- ## 테스트 전략 ### Unit Test - UserService, AuthenticationService 단위 테스트 - Mock 객체: UserRepository, Redis, 국세청 API ### Integration Test - Controller → Service → Repository 통합 테스트 - 실제 Redis 및 PostgreSQL 사용 (Testcontainers) ### E2E Test - Postman 또는 REST Assured로 전체 플로우 테스트 - 회원가입 → 로그인 → 프로필 수정 → 로그아웃 --- ## 향후 개선사항 ### Phase 2 1. **Refresh Token 구현**: Access Token 만료 시 갱신 메커니즘 2. **소셜 로그인**: 카카오, 네이버, 구글 OAuth 2.0 연동 3. **2FA (Two-Factor Authentication)**: SMS 또는 TOTP 기반 2단계 인증 4. **비밀번호 재설정**: 이메일/SMS를 통한 비밀번호 재설정 기능 ### Phase 3 1. **계정 잠금 정책**: 로그인 5회 실패 시 계정 잠금 2. **세션 관리 고도화**: 동시 세션 수 제한, 세션 활성 기록 3. **감사 로그**: 민감 작업(로그인, 비밀번호 변경) 감사 로그 저장 4. **Rate Limiting**: 로그인 API에 Rate Limiting 적용 (사용자당 5회/분) --- ## 참고 문서 - [유저스토리](../../../userstory.md) - [외부 시퀀스](../outer/사용자인증플로우.puml) - [논리 아키텍처](../../logical/logical-architecture.md) - [공통설계원칙](../../../common-principles.md) - [내부시퀀스설계가이드](../../../../claude/sequence-inner-design.md) --- **문서 버전**: 1.0 **최종 수정일**: 2025-10-22 **작성자**: System Architect **변경 사항**: User Service 내부 시퀀스 4개 시나리오 초안 작성 완료