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
- 인증 URL 요청 및 응답 데이터를 처리.
auth-callback.dto.ts
- 인증 콜백 요청 및 응답 데이터를 처리.
user-info.dto.ts
- 사용자 정보 응답 데이터를 정의.
index.ts
- DTO 내보내기 설정.
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
- 이 클래스는 클라이언트가 서버에 "인증 시작!"이라고 요청할 때 사용하는 정보입니다.
- 예를 들어, "나는 카카오로 로그인하고 싶어!"라고 말할 때 카카오를 골라서(
provider
) 서버에 알려줍니다. - 필요하면
state
라는 추가 정보도 보낼 수 있습니다. 이state
는 보안 때문에 사용하는 특별한 암호 같은 것입니다.
AuthUrlResponseDto
- 이 클래스는 서버가 클라이언트에게 "인증하려면 여기를 눌러!"라고 URL을 보내줄 때 사용하는 구조입니다.
- 예를 들어, 카카오 로그인 화면으로 가는 링크를 만들어서 클라이언트에게 전달합니다.
사용 예시
- 클라이언트 요청
- 클라이언트는 카카오 로그인을 요청합니다.
- 서버에
AuthUrlRequestDto
형식으로 데이터를 보냅니다
{
"provider": "kakao",
"state": "random-csrf-token"
}
- 서버응답
- 서버는 클라이언트에게 카카오 로그인 페이지로 이동할 수 있는 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"
}
- 클라이언트가
/auth/url
엔드포인트에provider=kakao&state=random-csrf-token
으로 요청합니다. - 서버는
AuthUrlRequestDto
로 요청 데이터를 검증하고, URL을 생성합니다. - 서버는
AuthUrlResponseDto
를 사용해 인증 URL을 반환합니다. - 클라이언트는 응답받은 URL로 사용자를 이동시킵니다.
``
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
이 클래스는 클라이언트가 서버로 보내는 요청의 구조입니다.
provider
:
어떤 로그인 서비스(예: 카카오, 구글 등)를 사용했는지 알려줍니다.code
:
클라이언트가 로그인 제공자로부터 받은 "인증 코드"입니다.
예를 들어, 카카오가 "이 코드로 로그인 검증해봐!"라고 주는 값이에요.state
:
보안을 위해 서버가 처음에 클라이언트에게 줬던 값입니다. CSRF공격 차단용.
2. AuthCallbackResponseDto
이 클래스는 서버가 클라이언트에게 보내는 응답의 구조입니다.
accessToken
:
클라이언트가 인증된 사용자를 대신해 서버와 통신할 때 사용하는 "열쇠"입니다.refreshToken
:
액세스 토큰이 만료되었을 때 새로운 토큰을 발급받기 위해 사용하는 "리필 열쇠"입니다.expiresIn
:
액세스 토큰이 몇 초 동안 유효한지 나타냅니다.
사용예시
- 클라이언트 요청
{
"provider": "kakao",
"code": "authorization-code",
"state": "random-csrf-token"
}
- 서버 응답 : 액서스 토큰과 리프레시 토큰을 돌려준다.
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 3600
}