Skip to content

feat: PortOne V2 본인인증 통합 및 프로필 관리 기능 구현#26

Merged
ekfrehd merged 1 commit intodevelopfrom
feat/portone-v2-identity-verification
Feb 9, 2026
Merged

feat: PortOne V2 본인인증 통합 및 프로필 관리 기능 구현#26
ekfrehd merged 1 commit intodevelopfrom
feat/portone-v2-identity-verification

Conversation

@ekfrehd
Copy link
Contributor

@ekfrehd ekfrehd commented Feb 9, 2026

🔍 PR 타입 선택

  • feat: 새로운 기능 추가
  • fix: 버그 수정
  • docs: 문서 수정
  • style: 코드 포맷팅, 세미콜론 누락, 코드 변경이 없는 경우
  • refactor: 코드 리팩토링
  • test: 테스트 코드 추가 또는 수정
  • chore: 빌드 업무 수정, 패키지 매니저 수정 등 기타 작업

📝 변경 사항 요약

PortOne V2 본인인증 시스템 통합 및 사용자 프로필 관리 기능 추가

주요 기능

  1. PortOne V2 API 통합

    • V1 → V2 마이그레이션 (3-key 인증 방식)
    • 본인인증 후 CI/DI 저장 및 중복 가입 방지
    • 성별, 생년월일, 나이 자동 계산 및 저장
  2. 프로필 관리 시스템

    • 프로필 조회 API (GET /api/users/profile)
    • 프로필 수정 API (PATCH /api/users/profile)
    • 알림 설정 토글 API (PATCH /api/users/notification)
  3. 여행 스타일 관리

    • 8가지 여행 스타일 자동 초기화 (계획철저, 즉흥적, 맛집탐방 등)
    • 여행 스타일 조회 API (GET /api/travel-styles)
    • 사용자별 여행 스타일 선택 및 저장
  4. 보안 강화

    • CI(Connecting Information) 기반 중복 가입 방지
    • 본인인증 완료 여부 검증
    • CORS 설정 개선 (개발 환경)

🛠 관련 이슈

close: #[이슈번호]


📋 상세 변경 내역

1️⃣ PortOne V2 통합

새로운 설정 (application.properties)

# PortOne V2 설정
portone.public.store-id=${PORTONE_STORE_ID}
portone.public.channel-key=${PORTONE_CHANNEL_KEY}
portone.api_secret=${PORTONE_API_SECRET}

새로운 파일

  • PortOneConfig.java: V2 설정 관리
  • IdentityVerificationService.java: V2 API 호출 및 인증 정보 검증
  • VerifyIdentityRequest.java / VerifyIdentityResponse.java: DTO

API 변경사항

  • Endpoint: POST /api/auth/verify-identity
  • 인증 방식: Authorization: PortOne {apiSecret}
  • 응답 구조:
    • status: "VERIFIED"
    • verifiedCustomer 객체 (name, gender, birthDate, ci, di)

2️⃣ 프로필 관리

새로운 Controller

  • ProfileController.java
    • GET /api/users/profile: 프로필 조회
    • PATCH /api/users/profile: 프로필 수정
    • PATCH /api/users/notification: 알림 설정

새로운 Service

  • ProfileService.java
    • 프로필 조회/수정 비즈니스 로직
    • 여행 스타일 검증 및 업데이트

새로운 DTO

  • ProfileResponse.java: 프로필 조회 응답
  • UpdateProfileRequest.java: 프로필 수정 요청
  • UpdateNotificationRequest.java: 알림 설정 요청

3️⃣ 여행 스타일 시스템

새로운 Entity

  • TravelStyle.java: 여행 스타일 엔티티
  • MemberTravelStyle.java: 회원-여행스타일 연관 엔티티

자동 초기화

  • DataInitializer.java: 애플리케이션 시작 시 8가지 여행 스타일 자동 생성
  • 계획철저, 즉흥적, 맛집탐방, 휴양지, 가성비, 플렉스, 아침형, 올빼미

새로운 Controller

  • TravelStyleController.java
    • GET /api/travel-styles: 전체 여행 스타일 조회

새로운 Service

  • TravelStyleService.java: 여행 스타일 CRUD 로직

4️⃣ Member Entity 확장

새로운 필드

@Column(name = "ci", unique = true, length = 88)
private String ci;  // 본인인증 CI

@Column(name = "di", length = 64)
private String di;  // 본인인증 DI

@Column(name = "is_verified", nullable = false)
private boolean isVerified = false;  // 본인인증 완료 여부

@Column(name = "verified_at")
private LocalDateTime verifiedAt;  // 본인인증 완료 시각

@Embedded
private Authorities authorities = new Authorities();  // 권한 관리

@OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true)
private List<MemberTravelStyle> travelStyles = new ArrayList<>();  // 여행 스타일

새로운 메서드

public void updateIdentityVerification(String name, String gender, String birthday, String ci, String di)
public void updateProfile(String bio, String mbti, List<Long> travelStyleIds)
public void updateNotification(boolean enabled)

5️⃣ Repository 확장

MemberRepository 추가 메서드

Optional<Member> findByEmail_Value(String email);  // 이메일 문자열로 조회
boolean existsByCi(String ci);  // CI 중복 체크

새로운 Repository

  • MemberQueryRepository / MemberQuerydslRepository: QueryDSL 기반 조회
  • TravelStyleRepository: 여행 스타일 CRUD
  • MemberTravelStyleRepository: 회원-여행스타일 관계 관리

6️⃣ 예외 처리

새로운 Exception

  • PortOneApiException.java: PortOne API 호출 실패 시
  • DuplicateUserException.java: 생성자 수정 (파라미터 없음)

7️⃣ 보안 설정

SecurityConfig 업데이트

.authorizeHttpRequests(auth -> auth
    .requestMatchers(HttpMethod.POST, "/users", "/api/users").permitAll()
    .requestMatchers(HttpMethod.GET, "/api/travel-styles").permitAll()
    .requestMatchers(HttpMethod.POST, "/api/auth/verify-identity").authenticated()
    .anyRequest().authenticated()
)

CORS 설정 개선

config.setAllowedOriginPatterns(List.of(
    "http://localhost:*",    // 모든 localhost 포트 허용
    "http://127.0.0.1:*"
));

8️⃣ 의존성 추가

build.gradle

// OkHttp (HTTP 클라이언트)
implementation 'com.squareup.okhttp3:okhttp:4.12.0'

// Gson (JSON 파싱) - 버전 충돌 해결
implementation('com.google.code.gson:gson') {
    version {
        strictly '2.11.0'
    }
}

✅ 테스트 체크리스트

  • 회원가입 정상 작동
  • 로그인 정상 작동 (JWT 토큰 발급)
  • 본인인증 API 호출 (PortOne V2)
  • 프로필 조회 API
  • 프로필 수정 API
  • 여행 스타일 조회 API
  • 여행 스타일 자동 초기화
  • CI 기반 중복 가입 방지
  • CORS preflight 요청 처리

🔄 Breaking Changes

PortOne V1 → V2 마이그레이션

변경된 설정:

  • V1: imp_code, api_key, api_secret (2-3 keys)
  • V2: store_id, channel_key, api_secret (3 keys)

변경된 API:

  • Endpoint: api.iamport.kr/certificationsapi.portone.io/identity-verifications
  • 인증 방식: Bearer {token}PortOne {secret}
  • 응답 구조: imp_uididentityVerificationId

마이그레이션 가이드:

  1. PortOne 콘솔에서 V2 Store ID, Channel Key, API Secret 발급
  2. application.properties에 V2 키 설정
  3. 프론트엔드 SDK 업데이트: cdn.portone.io/v2/browser-sdk.js

📸 스크린샷 (선택 사항)


📚 추가 문서


👥 리뷰어 참고 사항

중점 리뷰 항목

  1. 보안: CI/DI 저장 방식 및 중복 체크 로직
  2. 예외 처리: PortOne API 호출 실패 시나리오
  3. 트랜잭션: 본인인증 정보 업데이트 원자성
  4. 성능: QueryDSL 쿼리 최적화 (N+1 문제 등)
  5. CORS: 프로덕션 배포 시 허용 도메인 제한 필요

추후 개선 사항

  • 본인인증 재시도 로직 추가
  • API 응답 캐싱 (여행 스타일 조회)
  • 프로필 이미지 업로드 기능
  • 본인인증 이력 저장 (audit log)

🙏 Thanks

PortOne V2 API 통합 및 사용자 프로필 관리 시스템 구현을 완료했습니다.
리뷰 부탁드립니다! 🚀

- PortOne V2 API 통합
- 본인인증 기반 회원 정보 검증 및 CI/DI 저장
- 프로필 관리 API (조회/수정) 구현
- 여행 스타일 시스템 추가 (8가지 스타일 자동 초기화)
- 중복 가입 방지 (CI 기반)
- 테스트 환경 대응 (CI/DI 선택적 처리)
- CORS 설정 개선 (개발 환경 localhost 포트 패턴 허용)
@ekfrehd ekfrehd merged commit ecdf370 into develop Feb 9, 2026
1 check passed
@ekfrehd ekfrehd deleted the feat/portone-v2-identity-verification branch February 9, 2026 13:34
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