기술과 산업/언어 및 프레임워크

NestJS 마스터 시리즈 14화. CRUD 실습 – 사용자(User) API를 완성해보자

B컷개발자 2025. 5. 15. 19:18
728x90

“백엔드 개발은 결국 CRUD에서 시작되고, 잘 만든 CRUD가 서비스의 뼈대가 된다”

 

NestJS에서 사용자(User) API를 실전 예제로 CRUD 방식으로 구축하는 방법을 설명합니다. 모듈, 컨트롤러, 서비스, DTO, Repository의 통합 개발 과정을 단계별로 소개합니다.

 


 

목표

 

다음 기능을 갖춘 User API를 완성한다.

기능라우트메서드

전체 사용자 조회 /users GET
단일 사용자 조회 /users/:id GET
사용자 생성 /users POST
사용자 수정 /users/:id PATCH
사용자 삭제 /users/:id DELETE

 


 

1. UsersModule 생성

nest generate module users
nest generate service users
nest generate controller users

모듈 구조는 다음과 같다.

src/users/
├── users.controller.ts
├── users.service.ts
├── users.module.ts
└── user.entity.ts

 


 

2. Entity 정의

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column({ unique: true })
  email: string;

  @Column()
  password: string;
}

 


 

3. DTO 정의

export class CreateUserDto {
  @IsString()
  name: string;

  @IsEmail()
  email: string;

  @IsString()
  password: string;
}

export class UpdateUserDto {
  @IsOptional()
  @IsString()
  name?: string;

  @IsOptional()
  @IsEmail()
  email?: string;

  @IsOptional()
  @IsString()
  password?: string;
}

 


 

4. UsersService 구현

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>,
  ) {}

  findAll(): Promise<User[]> {
    return this.usersRepository.find();
  }

  findOne(id: number): Promise<User> {
    return this.usersRepository.findOneBy({ id });
  }

  create(createUserDto: CreateUserDto): Promise<User> {
    const user = this.usersRepository.create(createUserDto);
    return this.usersRepository.save(user);
  }

  async update(id: number, updateUserDto: UpdateUserDto): Promise<User> {
    await this.usersRepository.update(id, updateUserDto);
    return this.findOne(id);
  }

  async remove(id: number): Promise<void> {
    await this.usersRepository.delete(id);
  }
}

 


 

5. UsersController 구현

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  findAll() {
    return this.usersService.findAll();
  }

  @Get(':id')
  findOne(@Param('id', ParseIntPipe) id: number) {
    return this.usersService.findOne(id);
  }

  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }

  @Patch(':id')
  update(
    @Param('id', ParseIntPipe) id: number,
    @Body() updateUserDto: UpdateUserDto,
  ) {
    return this.usersService.update(id, updateUserDto);
  }

  @Delete(':id')
  remove(@Param('id', ParseIntPipe) id: number) {
    return this.usersService.remove(id);
  }
}

 


 

6. API 테스트 예시

 

 

사용자 생성

POST /users
{
  "name": "Alice",
  "email": "alice@example.com",
  "password": "securepassword"
}

 

사용자 조회

GET /users
GET /users/1

 

사용자 수정

PATCH /users/1
{
  "name": "Alice Updated"
}

 

사용자 삭제

DELETE /users/1

 


 

마무리 인사이트

 

NestJS는 모듈화된 구조와 강력한 TypeORM 연동 기능을 통해

빠르고 안정적인 RESTful API 개발을 가능하게 한다.

 

  • 컨트롤러는 요청과 응답만 담당
  • 서비스는 비즈니스 로직을 담당
  • Repository는 데이터 저장소 접근을 담당

 

이 구조를 습관화하면 규모가 커져도 유지보수가 쉬운 API를 만들 수 있다.

 

“잘 만든 CRUD는 스케일링과 유지보수의 출발점이다”

 


 

다음 회차 예고

 

NestJS 마스터 시리즈 15화. 인증 시스템 구현 (1) – JWT 기반 로그인 시스템 만들기

PassportModule과 JWT 전략을 활용한 인증 로직 설계 방법을 소개합니다.

728x90