목표

  1. 전략 패턴 적용
    • 각 OAuth 제공자별로 별도의 전략 클래스 구현
    • 공통 인터페이스를 통한 일관된 처리
  2. 보안 강화
    • CSRF 방지를 위한 state 파라미터 관리 (특히 Naver)
    • Apple Sign In을 위한 클라이언트 시크릿 동적 생성
    • 토큰 저장소 분리 가능한 구조
  3. 에러 처리 개선
    • 각 제공자별 특수한 에러 상황 처리
    • 상세한 에러 로깅 가능
  4. 기능 추가
    • 리프레시 토큰 처리 로직
    • 사용자 프로필 정보 조회
    • 토큰 만료 시간 관리
  5. 확장성
    • 새로운 OAuth 제공자 추가가 용이한 구조
    • 토큰 저장소 변경이 용이한 구조
  6. 타입 안전성
    • 인터페이스를 통한 타입 정의
    • 응답 데이터 구조화
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 구성
  1. prisma/
    • 데이터베이스 스키마 및 클라이언트 관리
    • Prisma 서비스 구현
  2. config/
    • 환경 설정 관리
    • 환경 변수 검증
    • 설정 모듈화
  3. auth/
    • OAuth 인증 관련 모든 구현
    • 전략 패턴 구현
    • DTO 및 인터페이스 정의
    • 가드 및 데코레이터
  4. users/
    • 사용자 관리 기능
    • OAuth 사용자 처리
  5. common/
    • 공통 기능 구현
    • 예외 처리
    • 로깅

각 파일의 주요 책임:

  1. interfaces/
    • 타입 정의
    • API 계약 정의
    • 데이터 구조 정의
  2. dto/
    • 요청/응답 데이터 검증
    • API 문서화
    • 데이터 변환
  3. strategies/
    • OAuth 제공자별 구현
    • 인증 로직 캡슐화
    • 토큰 관리
  4. 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 {}