1. 프로젝트 개요 및 역할
사내 여러 서비스에 파편화되어 있던 인증 체계를 하나로 통합하기 위해 TypeScript와 NestJS 기반의 중앙 집중형 통합 회원 관리(SSO) 서버를 단독으로 설계하고 구축했습니다. 단순한 로그인 API 집합이 아닌, 다수의 사내 서비스 간 신뢰 모델을 보장하고 확장이 용이한 Provider 기반 인증 플랫폼을 만드는 것을 목표로 서버사이드 전반을 주도했습니다.
2. 핵심 챌린지 및 문제 해결
챌린지 1: 물리적으로 분리된 DB 환경에서의 유저 식별 설계
문제 상황
- 유저 인증 정보는 통합 SSO 서버가 관리해야 하고, 주문·예약 등 비즈니스 데이터는 개별 서비스 DB에 남아야 했습니다.
- 물리적으로 다른 DB를 사용하므로 RDBMS의 Foreign Key를 직접 연결할 수 없었습니다.
- 데이터 정합성 유지와 장애 발생 시 원인 추적이 어려워지는 문제가 예상되었습니다.
고려한 대안과 판단
| 대안 | 접근 | 기각 사유 |
|---|
| 단일 통합 DB | 모든 서비스 데이터를 SSO DB에 통합 | 서비스 간 강결합 발생, 장애 전파 범위 확대 |
| API 조회 방식 | 개별 서비스가 매 요청마다 SSO API로 유저 조회 | SSO 서버 부하 집중, 응답 지연 증가 |
| JWT Payload + Soft FK | UUID를 토큰에 담아 전달, 각 서비스 DB에 논리적 FK로 저장 | — |
UUID를 Access Token Payload에 포함시키면, 개별 서비스는 토큰 검증만으로 유저를 식별할 수 있어 SSO 서버와의 추가 통신 없이 독립성과 정합성을 동시에 확보할 수 있었습니다.
해결 과정
- 통합 SSO 서버가 로그인 시 유저에게 UUID를 발급하고 Access Token Payload에 포함하여 전달하도록 설계했습니다.
- 개별 서비스는 토큰에서 UUID를 추출해 자신의 DB에 Soft FK(논리적 외래키)로 저장하여, SSO 서버와의 물리적 DB 결합 없이 유저를 완전히 매핑할 수 있도록 구성했습니다.
- Soft FK 방식을 선택함으로써 SSO 서버 장애가 개별 서비스의 비즈니스 데이터에 영향을 주지 않는 격리 구조를 확보했습니다.
이 챌린지의 기술적 상세는 인사이트 분산 환경에서의 SSO 통합과 Soft FK 활용기 에서 깊이 있게 다루고 있습니다.
결과
- DB 간 직접 연결 없이 유저 식별 성공률 100% 달성 — 서비스별 독립 배포 및 장애 격리 가능
- SSO 서버 없이도 개별 서비스가 토큰 자체 검증으로 응답 가능하여 SSO 의존성 제거
챌린지 2: 파편화된 인증 체계 통합 및 중앙 세션 통제력 확보
문제 상황
- 서비스마다 JWT Secret Key 관리 방식이 달라 보안 수준이 불균일했습니다.
- Access Token 만료 정책이 서비스별로 상이해 세션 수명 예측이 불가능했습니다.
- 보안 사고 발생 시 특정 유저나 디바이스의 세션을 즉각 차단할 수단이 없었습니다.
고려한 대안과 판단
| 대안 | 접근 | 기각 사유 |
|---|
| 각 서비스 자체 토큰 정책 유지 | 서비스마다 독립 관리 | 보안 수준 불균일, 중앙 통제 불가 |
| Redis 기반 세션 관리 | 토큰 대신 세션 ID를 Redis에 저장 | 인프라 추가 비용, 현 규모 대비 오버엔지니어링 |
| 토큰 이중 구조 + RDBMS 저장 | Access Token은 서비스 자체 검증, Refresh Token은 SSO DB 중앙 관리 | — |
Access Token(10분) 자체 검증으로 SSO 부하를 분산하고, Refresh Token(7일)은 RDBMS에 저장하여 강제 로그아웃 시 레코드 삭제만으로 즉각 통제하는 구조가 현 인프라 조건에서 가장 실용적인 판단이었습니다.
해결 과정
- 서비스별 JWT Secret 분리, Authorization Key 발급, 허용 IP 화이트리스트 관리를 도입하여 서비스 간 인증 격벽을 설계했습니다.
- Refresh Token을 Prisma를 통해 RDBMS에 저장하고, 보안 이슈 발생 시 해당 레코드 삭제만으로 특정 디바이스나 유저를 강제 로그아웃하는 메커니즘을 구현했습니다.
- NestJS의 @UseGuards와 Custom Decorator를 활용하여 토큰 검증·Provider 권한 인가 로직을 비즈니스 레이어와 완전히 분리하고, 인증 파이프라인을 선언적으로 구성했습니다.
- 보안 정책 변경 시 Guard 단 한 곳만 수정하면 전체 서비스에 일괄 적용되는 구조로, 향후 정책 변경 비용을 최소화했습니다.
결과
- 사내 전체 서비스 토큰 만료 정책 통일 — 보안 감사 기준 충족
- 강제 로그아웃 응답: 기존 수단 없음 → DB 레코드 삭제 후 다음 Refresh 요청 시 즉각 인증 거부
3. 프로젝트 회고
- 인증 설계에서 "토큰을 어떻게 만드느냐"보다 "세션을 어떻게 통제하느냐"가 더 중요한 판단임을 체감했습니다. Refresh Token을 DB에 저장하는 결정 하나가 강제 로그아웃, 디바이스 관리, 감사 추적 등 후속 요구사항 전체를 가능하게 했습니다.
- 현 구조에서 Refresh Token 검증 시 발생하는 DB I/O는 트래픽이 증가할 경우 병목이 될 수 있습니다. Redis 캐싱 레이어 도입과 RTR(Refresh Token Rotation) 전략을 우선 적용해 보안과 성능을 함께 고도화하고 싶습니다.