src/
│   ├── dto/
│   │   ├── index.ts              # DTO 내보내기
│   │   ├── auth-url.dto.ts       # 인증 URL 요청/응답 DTO
│   │   ├── auth-callback.dto.ts  # 콜백 요청/응답 DTO
│   │   └── user-info.dto.ts      # 사용자 정보 응답 DTO

auth-url.dto.ts

auth-callback.dto.ts

user-info.dto.ts

index.ts

auth-url.dto.ts

import { ApiProperty } from '@nestjs/swagger';  
import { Provider } from '../enums/provider.enum';  
import { IsEnum, IsOptional, IsString } from 'class-validator';  
  
export class AuthUrlRequestDto {  
  @ApiProperty({  
    description: 'OAuth 제공자',  
    enum: Provider,  
    example: Provider.KAKAO,  
  })  
  @IsEnum(Provider)  
  provider: Provider;  
  
  @ApiProperty({  
    description: 'CSRF 방지를 위한 상태값',  
    required: false,  
    example: 'random-state-string',  
  })  
  @IsOptional()  
  @IsString()  
  state?: string;  
}  
  
export class AuthUrlResponseDto {  
  @ApiProperty({  
    description: 'OAuth 인증 URL',  
    example: 'https://kauth.kakao.com/oauth/authorize?client_id=...',  
  })  
  @IsString()  
  url: string;  
}
AuthUrlRequestDto
AuthUrlResponseDto
사용 예시
  1. 클라이언트 요청
    • 클라이언트는 카카오 로그인을 요청합니다.
    • 서버에 AuthUrlRequestDto 형식으로 데이터를 보냅니다
{
  "provider": "kakao",
  "state": "random-csrf-token"
}
  1. 서버응답
    • 서버는 클라이언트에게 카카오 로그인 페이지로 이동할 수 있는 URL을 응답
{
  "url": "https://kauth.kakao.com/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&state=random-csrf-token"
}

user-info.dto.ts

import { ApiProperty } from '@nestjs/swagger';  
import {  
  IsString,  
  IsEmail,  
  IsEnum,  
  IsUrl,  
  IsOptional,  
  IsDate,  
} from 'class-validator';  
import { Provider } from '../enums/provider.enum';  
  
export class UserInfoResponseDto {  
  @ApiProperty({  
    description: '사용자 ID',  
    example: 'user-uuid',  
  })  
  @IsString()  
  id: string;  
  
  @ApiProperty({  
    description: '이메일 주소',  
    example: 'user@example.com',  
    required: false,  
  })  
  @IsOptional()  
  @IsEmail()  
  email?: string;  
  
  @ApiProperty({  
    description: '사용자 이름',  
    example: 'John Doe',  
    required: false,  
  })  
  @IsOptional()  
  @IsString()  
  name?: string;  
  
  @ApiProperty({  
    description: '프로필 이미지 URL',  
    example: 'https://example.com/profile.jpg',  
    required: false,  
  })  
  @IsOptional()  
  @IsUrl()  
  picture?: string;  
  
  @ApiProperty({  
    description: 'OAuth 제공자',  
    enum: Provider,  
    example: Provider.KAKAO,  
  })  
  @IsEnum(Provider)  
  provider: Provider;  
  
  @ApiProperty({  
    description: 'OAuth 제공자의 사용자 ID',  
    example: 'provider-user-id',  
  })  
  @IsString()  
  providerId: string;  
  
  @ApiProperty({  
    description: '이메일 인증 여부',  
    example: true,  
    required: false,  
  })  
  @IsOptional()  
  emailVerified?: boolean;  
  
  @ApiProperty({  
    description: '계정 생성일',  
    example: '2024-01-01T00:00:00Z',  
  })  
  @IsDate()  
  createdAt: Date;  
  
  @ApiProperty({  
    description: '최근 업데이트일',  
    example: '2024-01-01T00:00:00Z',  
  })  
  @IsDate()  
  updatedAt: Date;  
}
{
  "id": "user-uuid",
  "email": "user@example.com",
  "name": "John Doe",
  "picture": "https://example.com/profile.jpg",
  "provider": "kakao",
  "providerId": "provider-user-id",
  "emailVerified": true,
  "createdAt": "2024-01-01T00:00:00Z",
  "updatedAt": "2024-01-01T00:00:00Z"
}

auth-callback.dto.ts

OAuth 인증이 끝난 후 서버가 클라이언트와 데이터를 주고받을 때 사용하는 구조

import { ApiProperty } from '@nestjs/swagger';  
import { IsEnum, IsString, IsNotEmpty, IsOptional } from 'class-validator';  
import { Provider } from '../enums/provider.enum';  
  
export class AuthCallbackRequestDto {  
  @ApiProperty({  
    description: 'OAuth 제공자',  
    enum: Provider,  
    example: Provider.KAKAO,  
  })  
  @IsEnum(Provider)  
  provider: Provider;  
  
  @ApiProperty({  
    description: 'OAuth 인증 코드',  
    example: 'authorization-code',  
  })  
  @IsString()  
  @IsNotEmpty()  
  code: string;  
  
  @ApiProperty({  
    description: 'CSRF 방지를 위한 상태값',  
    required: false,  
    example: 'random-state-string',  
  })  
  @IsOptional()  
  @IsString()  
  state?: string;  
}  
  
export class AuthCallbackResponseDto {  
  @ApiProperty({  
    description: '액세스 토큰',  
    example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',  
  })  
  @IsString()  
  accessToken: string;  
  
  @ApiProperty({  
    description: '리프레시 토큰',  
    example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',  
  })  
  @IsString()  
  refreshToken: string;  
  
  @ApiProperty({  
    description: '토큰 만료 시간(초)',  
    example: 3600,  
  })  
  expiresIn: number;  
}

1. AuthCallbackRequestDto

이 클래스는 클라이언트가 서버로 보내는 요청의 구조입니다.

2. AuthCallbackResponseDto

이 클래스는 서버가 클라이언트에게 보내는 응답의 구조입니다.

사용예시

  1. 클라이언트 요청
{
  "provider": "kakao",
  "code": "authorization-code",
  "state": "random-csrf-token"
}
  1. 서버 응답 : 액서스 토큰과 리프레시 토큰을 돌려준다.
{
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expiresIn": 3600
}