본문으로 바로가기

NestJS 유저 서비스의 인터페이스

category JavaScript/Nest 2022. 8. 22. 17:23

 유저 서비스의 인터페이스를 정의하고 컨트롤러를 구현하겠습니다.

우리의 유저 서비스는 외부에서 4가지의 요청을 받아 처리합니다.

프론트 엔드의 UI 화면을 함께 만들지 않기 때문에 프론트에서 요청이 전달된다고 가정하고 진행하겠습니다.

https://wikidocs.net/158494

각 요청에 대한 인터페이스를 다음과 같이 정의하였습니다.

기능 엔드포인트 본문 데이터 예(JSON) 쿼리 파라미터 패스 파라미터 응답
회원가입 POST /users {
  "name": "Dexter",
  "email": "dexter@example.com",
  "password": "PASSWORD"
}
    201
이메일 인증 POST /users/email-verify {
  "signupVerifyToken": "임의의 문자열"
}
    201
액세스 토큰
로그인 POST /user/login {
  "name": "Dexter",
  "email": "dexter@example.com",
  "password": "PASSWORD"
}
    201
액세스 토큰
회원 정보 조회 GET /users/:id     id: 유저 생성 시 만들어진 유저 ID.
email이 아니라 임의의 문자열
200
회원 정보

이제 위에서 정의한 인터페이스를 컨트롤러에 만들어 봅시다.

AppController와 AppService는 불필요하므로 삭제 후 컴파일 에러가 발생하는 부분을 수정해 줍니다.

그리고 UserController를 생성합니다.

$ nest g co Users

이제 src 디렉토리 내의 파일은 이렇게 구성되었습니다.

src
├── app.module.ts
├── main.ts
└── users
    └── users.controller.ts

먼저 회원가입 인터페이스를 UserController에 구현해 보겠습니다.

import { Body, Controller, Post } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';

@Controller('users')
export class UserController {
  @Post()
  async createUser(@Body() dto: CreateUserDto): Promise<void> {
    console.log(dto);
  }
}

회원가입 요청의 본문을 CreateUserDto 클래스로 받고 있습니다.

src/users/dto/create-user.dto.ts 파일을 만들고 이름, 이메일, 패스워드 데이터를 정의하는 DTO를 정의합니다.

export class CreateUserDto {
  readonly name: string;
  readonly email: string;
  readonly password: string;
}

이제 서버를 구동시키고 요청을 보내서 dto에 데이터가 제대로 전달되는지 확인합니다.

요청 헤더에는 본문이 JSON 형식임을 나타내는 Content-Type 헤더를 추가합니다.

$ curl -X POST http://localhost:3000/users -H "Content-Type: application/json" -d 
'{"name": "Dexter", "email": "dexter.haan@gmail.com"}'
{
  name: 'Dexter',
  email: 'dexter@example.com',
  password: 'PASSWORD'
}

마찬가지로 나머지 인터페이스들도 컨트롤러에 구현합니다.

 

현업에서는 이렇게 계층별로 구현하지 말고 일명 김밥썰기라고 부르는 기능별 구현 방식을 추천합니다.
임무를 진행할 때는 여러 개발자가 본인이 맡은 기능을 여러 레이어에 걸쳐 구현하는 것이 보통입니다.
또한 전체 레이어를 관통하여 구현해야 요청 처리가 전체 레이어에 걸쳐 문제 없이 동작하는 지 확인할 수 있습니다.
책에서는 컨트롤러, 서비스, 데이터베이스 등의 컴포넌트를 설명한 후 예시를 들기 떄문에 레이어별로 구현하는 방식으로 진행합니다.
import { Body, Controller, Get, Param, Post, Query } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UserLoginDto } from './dto/user-login.dto';
import { VerifyEmailDto } from './dto/verify-email.dto';
import { UserInfo } from './UserInfo';

@Controller('users')
export class UsersController {
  @Post()
  async createUser(@Body() dto: CreateUserDto): Promise<void> {
    console.log(dto);
  }

  @Post('/email-verify')
  async verifyEmail(@Query() dto: VerifyEmailDto): Promise<string> {
    console.log(dto);
    return;
  }

  @Post('/login')
  async login(@Body() dto: UserLoginDto): Promise<string> {
    console.log(dto);
    return;
  }

  @Get('/:id')
  async getUserInfo(@Param('id') userId: string): Promise<UserInfo> {
    console.log(userId);
    return;
  }
}

L15: 이메일 인증 시 URL에 포함되어 전달되는 쿼리 파라미터를 @Query 데코레이터와 함께 선언한 DTO로 받습니다.

export class VerifyEmailDto {
  signupVerifyToken: string;
}

L21: 로그인을 할 때 유저가 입력한 데이터는 본문으로 전달되도록 합니다.

export class UserLoginDto {
  email: string;
  password: string;
}

L26~27: 유저 정보 조회시 유저 아이디를 패스 파라미터 id로 받습니다. @Get 데코레이터의 인자에 있는 id와 @Param 데코레이터의 인자로 있는 id는 이름이 같아야 합니다.

 

이제 추가 구현한 요청을 보내서 콘솔에 데이터가 제대로 전달되는 지 확인합니다.

반환값은 추후 구현할 것이기 때문에 바로 return 하였습니다.

  • 이메일 인증

요청

$ curl -X POST http://localhost:3000/users/email-verify\?signupVerifyToken\=test_token

콘솔 결과

{ signupVerifyToken: 'test_token' }

 

  • 로그인

요청

$ curl -X POST http://localhost:3000/users/login -H "Content-Type: application/json" -d
'{"email": "dexter.haan@gmail.com", "password": "PASSWORD"}'

콘솔 결과

{ email: 'dexter.haan@gmail.com', password: 'PASSWORD' }

 

  • 회원 정보 조회

요청

$ curl -X GET http://localhost:3000/users/user-id

콘솔 결과

user-id

 

 

참고: NestJS로 배우는 백엔드 프로그래밍

반응형