목표
- 전략 패턴 적용
- 각 OAuth 제공자별로 별도의 전략 클래스 구현
- 공통 인터페이스를 통한 일관된 처리
- 보안 강화
- CSRF 방지를 위한 state 파라미터 관리 (특히 Naver)
- Apple Sign In을 위한 클라이언트 시크릿 동적 생성
- 토큰 저장소 분리 가능한 구조
- 에러 처리 개선
- 각 제공자별 특수한 에러 상황 처리
- 상세한 에러 로깅 가능
- 기능 추가
- 리프레시 토큰 처리 로직
- 사용자 프로필 정보 조회
- 토큰 만료 시간 관리
- 확장성
- 새로운 OAuth 제공자 추가가 용이한 구조
- 토큰 저장소 변경이 용이한 구조
- 타입 안전성
- 인터페이스를 통한 타입 정의
- 응답 데이터 구조화
npm install -g yarn
yarn global add @nestjs/cli
nest new iam-server
cd iam-server
yarn
yarn add @nestjs/axios axios @nestjs/jwt @nestjs/platform-express @nestjs/swagger @prisma/client prisma class-validator googleapis
5508 yarn add axios @types/axios
5509 yarn add googleapis
5523 yarn add @nestjs/config googleapis express dotenv
5532 yarn add @nestjs/config googleapis axios jsonwebtoken
5533 yarn add @nestjs/config googleapis axios jsonwebtoken\n
5534 yarn add -D @types/jsonwebtoken\n
5546 yarn add @nestjs/swagger
5547 yarn add @nestjs/config
5548 yarn add @nestjs/common @nestjs/core @nestjs/platform-express
5549 yarn add prisma --save-dev
5550 yarn add @prisma/client
5555 yarn add @nestjs/axios
5556 yarn add @nestjs/jwt
5557 yarn add class-validator
5559 yarn add class-transformer
프로젝트 소스 파일구조
src/
├── prisma/
│ ├── schema.prisma # Prisma 스키마 정의
│ └── prisma.service.ts # Prisma 서비스
│
├── config/
│ ├── configuration.ts # 환경 설정 값 정의
│ ├── env.validation.ts # 환경 변수 검증
│ └── config.module.ts # 설정 모듈
│
├── auth/
│ ├── interfaces/
│ │ ├── index.ts # 인터페이스 내보내기
│ │ ├── jwt-payload.interface.ts # JWT 페이로드 정의
│ │ ├── oauth-token.interface.ts # OAuth 토큰 응답 정의
│ │ ├── oauth-profile.interface.ts # OAuth 프로필 정의
│ │ └── provider-profiles.interface.ts # 제공자별 프로필 정의
│ │
│ ├── dto/
│ │ ├── index.ts # DTO 내보내기
│ │ ├── auth-url.dto.ts # 인증 URL 요청/응답 DTO
│ │ ├── auth-callback.dto.ts # 콜백 요청/응답 DTO
│ │ └── user-info.dto.ts # 사용자 정보 응답 DTO
│ │
│ ├── strategies/
│ │ ├── base.strategy.ts # 기본 OAuth 전략
│ │ ├── kakao.strategy.ts # 카카오 OAuth 전략
│ │ ├── naver.strategy.ts # 네이버 OAuth 전략
│ │ ├── apple.strategy.ts # 애플 OAuth 전략
│ │ └── jwt.strategy.ts # JWT 인증 전략
│ │
│ ├── guards/
│ │ ├── auth.guard.ts # 인증 가드
│ │ └── jwt-auth.guard.ts # JWT 인증 가드
│ │
│ ├── decorators/
│ │ ├── public.decorator.ts # 공개 라우트 데코레이터
│ │ └── auth.decorator.ts # 인증 관련 데코레이터
│ │
│ ├── auth.controller.ts # 인증 컨트롤러
│ ├── auth.service.ts # 인증 서비스
│ └── auth.module.ts # 인증 모듈
│
├── users/
│ ├── users.service.ts # 사용자 서비스
│ └── users.module.ts # 사용자 모듈
│
├── common/
│ ├── filters/
│ │ └── http-exception.filter.ts # 전역 예외 필터
│ │
│ └── interceptors/
│ └── logging.interceptor.ts # 로깅 인터셉터
│
├── app.module.ts # 앱 루트 모듈
└── main.ts # 앱 엔트리 포인트
설정파일 :
/
├── .env.development # 개발 환경 변수
├── .env.production # 운영 환경 변수
├── .env.test # 테스트 환경 변수
│
├── package.json # 프로젝트 의존성
├── tsconfig.json # TypeScript 설정
│
├── Dockerfile # Docker 빌드 설정
├── docker-compose.yml # Docker 컨테이너 구성
└── docker-compose.dev.yml # 개발용 Docker 구성
- prisma/
- 데이터베이스 스키마 및 클라이언트 관리
- Prisma 서비스 구현
- config/
- 환경 설정 관리
- 환경 변수 검증
- 설정 모듈화
- auth/
- OAuth 인증 관련 모든 구현
- 전략 패턴 구현
- DTO 및 인터페이스 정의
- 가드 및 데코레이터
- users/
- 사용자 관리 기능
- OAuth 사용자 처리
- common/
- 공통 기능 구현
- 예외 처리
- 로깅
각 파일의 주요 책임:
- interfaces/
- 타입 정의
- API 계약 정의
- 데이터 구조 정의
- dto/
- 요청/응답 데이터 검증
- API 문서화
- 데이터 변환
- strategies/
- OAuth 제공자별 구현
- 인증 로직 캡슐화
- 토큰 관리
- guards/
- 인증 검증
- 권한 검사
- 라우트 보호
데이터베이스
prisma/schema.prisma 설정
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// User 모델 정의
model User {
id String @id @default(uuid())
email String? @unique
name String?
picture String?
// OAuth 관련 필드
providerId String // OAuth 제공자의 유저 ID provider String // OAuth 제공자 (kakao, naver, apple)
// 메타데이터
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tokens OAuthToken[]
// 복합 유니크 제약
@@unique([providerId, provider])
@@index([email])
}
// OAuth 토큰 모델 정의
model OAuthToken {
id String @id @default(uuid())
// 토큰 정보
accessToken String @db.Text
refreshToken String? @db.Text
expiresAt DateTime
tokenType String @default("Bearer")
// 관계 필드
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
// OAuth 제공자 정보
provider String
// 메타데이터
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// 인덱스
@@index([userId, provider])
@@index([expiresAt])
}
npx prisma init
npx prisma generate
npx prisma migrate dev --name init
모듈 등록
import { Module } from '@nestjs/common';
import { PrismaService } from './prisma/prisma.service';
@Module({
providers: [PrismaService],
exports: [PrismaService],
})
export class PrismaModule {}