RESTful API 설계 원칙과 구현
RESTful API는 확장성, 유연성, 독립성을 제공하는 웹 서비스 디자인 아키텍처입니다.
NestJS는 이러한 RESTful 원칙을 쉽게 구현할 수 있는 강력한 프레임워크를 제공합니다.
REST 아키텍처 핵심 원칙
- 클라이언트-서버 분리
- 무상태성 (Statelessness)
- 캐시 가능성 (Cacheability)
- 계층화 시스템 (Layered System)
- 코드 온 디맨드 (선택사항)
- 통일된 인터페이스
NestJS는 이러한 원칙들을 쉽게 구현할 수 있는 구조와 데코레이터를 제공합니다.
HTTP 메서드 구현
NestJS 컨트롤러에서 HTTP 메서드 구현
import { Controller, Get, Post, Put, Patch, Delete, Param, Body } from '@nestjs/common';
@Controller('users')
export class UsersController {
@Get()
findAll() {
return 'This action returns all users';
}
@Get(':id')
findOne(@Param('id') id: string) {
return `This action returns a #${id} user`;
}
@Post()
create(@Body() createUserDto: CreateUserDto) {
return 'This action adds a new user';
}
@Put(':id')
update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
return `This action updates a #${id} user`;
}
@Patch(':id')
partialUpdate(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
return `This action updates part of a #${id} user`;
}
@Delete(':id')
remove(@Param('id') id: string) {
return `This action removes a #${id} user`;
}
}
URI 설계 원칙
- 리소스를 명사로 사용
- 계층 관계를
/
로 표현 - 소문자 사용
- 언더스코어 대신 하이픈 사용
- 파일 확장자 포함하지 않기
NestJS에서 적용
@Controller('blog-posts')
export class BlogPostsController {
@Get('recent')
getRecentPosts() { ... }
@Get(':id/comments')
getPostComments(@Param('id') id: string) { ... }
}
리소스 표현과 HATEOAS
HATEOAS 구현 예시
@Get(':id')
async findOne(@Param('id') id: string) {
const user = await this.usersService.findOne(id);
return {
...user,
_links: {
self: { href: `/users/${user.id}` },
posts: { href: `/users/${user.id}/posts` },
}
};
}
상태 코드 사용
NestJS에서 상태 코드 사용
import { HttpStatus } from '@nestjs/common';
@Post()
@HttpCode(HttpStatus.CREATED)
create(@Body() createUserDto: CreateUserDto) {
return this.usersService.create(createUserDto);
}
@Get(':id')
async findOne(@Param('id') id: string) {
const user = await this.usersService.findOne(id);
if (!user) {
throw new NotFoundException(`User #${id} not found`);
}
return user;
}
쿼리 파라미터 처리
페이지네이션, 필터링, 정렬 구현
@Get()
async findAll(
@Query('page') page = 1,
@Query('limit') limit = 10,
@Query('sort') sort = 'createdAt',
@Query('order') order: 'ASC' | 'DESC' = 'DESC',
@Query('filter') filter: string
) {
const options = {
page: +page,
limit: +limit,
sort: { [sort]: order },
filter: filter ? JSON.parse(filter) : {}
};
return this.usersService.findAll(options);
}
API 버저닝
NestJS에서 API 버저닝 구현
- URI 버저닝
@Controller('v1/users')
export class UsersV1Controller { ... }
@Controller('v2/users')
export class UsersV2Controller { ... }
- 헤더 기반 버저닝
@Controller('users')
@Header('X-API-Version', '1')
export class UsersV1Controller { ... }
@Controller('users')
@Header('X-API-Version', '2')
export class UsersV2Controller { ... }
CORS 설정
NestJS에서 CORS 설정
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors({
origin: 'http://example.com',
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
credentials: true,
});
await app.listen(3000);
}
bootstrap();
Best Practices 및 성능 최적화
- 일관된 명명 규칙 사용
- 버전 관리 전략 수립
- 적절한 HTTP 메서드 및 상태 코드 사용
- 에러 처리 표준화
- 페이지네이션 구현
- 캐싱 전략 수립
- 요청 유효성 검사
- 보안 고려 (인증, 인가, 데이터 암호화)
- API 문서화 (Swagger/OpenAPI 사용)
- 성능 모니터링 및 로깅
성능 최적화 전략
- 데이터베이스 쿼리 최적화
@Get()
async findAll() {
return this.usersRepository.createQueryBuilder('user')
.leftJoinAndSelect('user.posts', 'post')
.where('user.isActive = :isActive', { isActive: true })
.take(10)
.getMany();
}
- 캐싱 구현
import { CacheInterceptor } from '@nestjs/common';
@UseInterceptors(CacheInterceptor)
@Get(':id')
async findOne(@Param('id') id: string) {
return this.usersService.findOne(id);
}
- 압축 사용
import compression from 'compression';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(compression());
await app.listen(3000);
}
- 비동기 작업의 병렬 처리
@Get('dashboard')
async getDashboard() {
const [users, posts, comments] = await Promise.all([
this.usersService.getActiveUsers(),
this.postsService.getRecentPosts(),
this.commentsService.getRecentComments()
]);
return { users, posts, comments };
}
NestJS를 사용한 RESTful API 개발은 프레임워크의 강력한 기능과 구조화된 접근 방식 덕분에 효율적이고 확장 가능한 애플리케이션을 구축할 수 있게 해줍니다.
REST 아키텍처의 핵심 원칙을 따르면서, NestJS의 데코레이터와 모듈 시스템을 활용하여 깔끔하고 유지보수가 용이한 코드를 작성할 수 있습니다.
HTTP 메서드의 적절한 사용, 명확한 URI 설계, HATEOAS 구현 등을 통해 클라이언트와 서버 간의 효과적인 통신을 구현할 수 있습니다.
또한, 상태 코드의 올바른 사용은 API의 의미론적 명확성을 높이고 클라이언트 측의 에러 처리를 용이하게 합니다.