NestJS 게시판 CRUD 구현하기

7643 단어 NestJS백엔드NestJS

📌 해당 글은 따라하면서 배우는 NestJS를 참조해 작성되었습니다.

📘1. 게시물 불러오기 (Read)

Service 부분

📌 바로 데이터베이스와 연동해도 되지만, 처음부터 DB에 연결해서 하면 복잡하므로 우선 데이터를 Mock Data로 로컬 메모리에 담아 처리하겠다.

BoardsService 클래스에 private으로 선언된 boards 데이터를 만들어주고, getAllBoards()라는 boards 데이터를 return 하는 메소드를 만들어주었다.

Controller 부분

또한, BoardsController 즉 컨트롤러 부분에 @Get 데코레이터를 붙여주어서 Get Http 메소드를 사용할 것임을 선언했고, getAllBoard()메소드를 통해 boardService의 getAllBoards()메소드를 return한다.

확인하기

npm run start

로 NestJS 앱을 실행시켜주면, 우리가 main.ts에서 포트를 3000으로 지정해주었기 때문에 localhost:3000/포트에서 앱이 실행된다.

그 후 위의 사진과 같이 /boards 로 이동해주면 우리가 만들어준 데이터의 값이 잘 출력되는 것을 확인할 수 있다.

정리하자면, 클라이언트에서 요청을 보내면 먼저 컨트롤러로 요청이 가며, 컨트롤러에서 알맞은 요청 경로에 라우팅해주어 해당 핸들러로 가게 된다.

그 후 요청을 처리해주기 위해 서비스로 들어가며, 그 요청과 맞는 로직을 서비스에서 처리해준 후 컨트롤러에 리턴값을 보내준 후 컨트롤러에서 클라이언트로 결과값을 보내준다.

그래서 컨트롤러에서는 요청을 처리하고 결과값을 리턴해주는 역할을 한다.


📘2. Board Model 정의하기


📌 게시물을 보면 게시글의 이름, 게시글의 내용, 공개 / 비공개 설정과 같은 세부 요소들이 존재한다. 이렇게 게시물에 필요한 데이터가 어떤 것이 있는지 정의해주기 위해 Model을 만들어줘야 한다.

모델을 정의해주기 위해서는 Class를 이용하거나 Interface를 이용하면 된다.

Interface는 변수의 타입만을 체크해주며,
Class는 변수의 타입도 체크하고, 인스턴스 또한 생성할 수 있다.

우선 우리는 board의 구조만 정의하기 위해 Interface를 사용하겠다.

id, title, description은 모두 string이고,
board의 status는 PUBLIC / PRIVATE 두가지의 값만 들어갈 수 있으므로 enum(enumeration) 으로 정의한 BoardStatus를 따로 만들어주었다. 따라서 status에는 PUBLIC, PRIVATE 두가지의 값만 들어갈 수 있게 된다.

따라서 서비스와 컨트롤러에도 Board모델을 불러와서 타입을 정의해준다.
boards 데이터는 배열로 이루어져 있기 때문에 타입도 배열로 붙여주어야 한다.

이렇게 타입을 정의해주면 코드를 읽는 입장에서 더 쉽게 이해할 수 있으며, 원하는 타입과 다른 코드를 사용할 시 생기는 오류를 체크할 수 있다.


📘3. 게시물 생성하기 (Create)

📌 게시물에 관한 로직은 Service에서 처리한다. 그래서 Service에서 로직을 처리해준 후에 Controller에서 서비스를 불러와주려고 한다.

Service 부분

위에서 만든 Model에서 id는 유니크한 값이 되어야 한다. 그래서 우리는 uuid 라는 패키지를 사용한다.

npm install uuid --save

설치가 완료되었다면, Service에 Import 해준다.

여기서 v1은 uuid의 버전을 의미하고, 우리는 v1을 사용한다.

그 후 Service의 getAllBoards() 메소드 아래에 위와 같이 새로운 메소드를 작성해준다.

createBoard() 메소드는 title과 description을 인수로 받아 새로운 게시물을 만드는 역할을 한다.

id는 uuid를 이용해 유니크한 값을 넣어주고, title, description은 받아온 인수로, status는 위에서 만든 BoardStatus의 PUBLIC으로 설정해준다.(기본값으로)

그리고 처음에 만든 boards 배열에 새로 만든 board를 push해준다.

이 메소드는 board를 return해서 어떠한 게시물이 생성됐는지 나타낸다.

Controller 부분

우리는 Post http 메소드로 만들 게시물의 정보를 사용자로부터 받아와야 하기 때문에 @Post 데코레이터로 덮어준다.
또한, @Body 데코레이터를 이용해 받아올 데이터를 선언해줄 수 있다.
이 메소드에선 Board 하나의 정보만 다루기 때문에 타입은 Board[]가 아닌 Board로 선언해준다.

따라서 title과 description을 받아와 Service의 createBoard에 인수로 전달해준다.

확인하기

Post는 Postman 프로그램을 통해 확인한다.

localhost:3000/boards에 Post 방식으로 JSON으로 이루어진 title과 description 정보를 전달해주니, 아래에 id(uuid를 사용해 유니크한 값으로 설정되었다.), title, description, status 모두 잘 출력되는 것을 확인할 수 있다.

또한, Get으로 boards를 불러오니 방금 입력한 board 정보가 잘 출력되는 것을 확인할 수 있다.


📘4. 게시물 생성을 위한 DTO

DTO(Data Transfer Object) 란?

📌 DTO란 Data Transfer Object의 약자이며, 계층간 데이터 교환을 위한 객체이다.

DB에서 데이터를 얻어 Service나 Controller 등으로 보낼 때 사용하는 객체를 말한다.
DTO는 데이터가 네트워크를 통해 전송되는 방법을 정의하는 객체이며,
Interface나 Class를 이용해서 정의될 수 있는데, NestJS에서는 주로 Class로 정의된다.

DTO를 쓰는 이유

📌 DTO는 데이터 유효성을 체크하는데 효율적이며, 더 안정적인 코드로 만들어준다. 타입스크립트의 타입으로도 사용된다.

NestJS의 데이터 처리 흐름을 보면, Board를 위한 Property가 정말 여러군데에서 사용된다.

지금은 간단한 어플리케이션을 만들기 때문에 몇개의 Property만 불러주고 몇 군데에서만 불러 주면 되지만, 정말 많은 프로퍼티를 갖고 정말 여러 군데에서 사용하며 갑자기 한 곳에서 Property 이름을 바꿔주어야 한다면 어떨까? 그렇다면 다른 곳에 똑같이 쓰인 모든 Property의 이름을 바꿔주어야 한다.

이러면 어플리케이션의 유지보수가 매우 힘들어지기 때문에 DTO를 사용해 이러한 문제를 해결한다.

게시물 생성을 위한 DTO

우선 boards 폴더 안에 create-board.dto.ts 파일을 만들어준다.

그 후 위와같이 Class를 이용해 CreateBoardDto를 만들어준다.


그리고 Controller 와 Service부분의 메소드를 위와 같이 변경해준다.


📘5. ID로 특정 게시물 가져오기 (Read)

Service 부분

boards가 배열이기 때문에 find 메소드를 통해 board.id와 인수로 받아온 id가 같은 객체를 반환한다.

Controller 부분

:id는 id라는 변수를 사용하겠다는 뜻이다.
위에서 @Body를 사용한 것과 다르게 우리는 localhost:3000?id=~~~ 와 같은 방식으로 id를 찾을 것이기 때문에 @Param 데코레이터를 통해 id라는 변수를 받아온다.

잠깐 @Param 데코레이터 사용법을 살펴보자면, @Parma()이라고 적었을 경우엔 파라미터의 모든 값들을 불러오게 되며 타입은 string[]과 같이 배열로 선언해줘여 하며, @Parma('id')와 같이 지정했을 경우 파라미터의 특정 한 값만 가져오게 된다.


📘6. ID로 특정 게시물 지우기 (Delete)

Service 부분

deleteBoard 메소드는 다른 메소들과 달리 Board 타입이 필요없기 때문에 void 타입으로 선언해주었다. 또한, 현재 boards 배열에 인수로 받아온 id와 다른 id를 가진 board 데이터만 filter 메소드로 걸러주어서 재할당해주어 delete를 구현했다.

Controller 부분

@Delete 데코레이터를 사용했으며, 위와 마찬가지로 @Parma('id')를 통해 파라미터의 id 값을 가져온다. 또한 boardService의 deleteBoard()메소드에 인수를 전달해주는 역할을 한다.


📘7. 특정 게시물의 상태 업데이트 (Update)

Service 부분

id와 status를 인수로 받는 updateBoardStatus()메소드를 만들어준다.

getBoardById()를 이용해 id에 맞는 Board 데이터를 삽입하는 board 변수를 만들어주고,
그 board의 status를 인수로 받아온 status로 재할당해준다.

또한 board를 return해서 board의 바뀐 값을 확인할 수 있게 한다.

Controller 부분

@Patch 데코레이터로 Patch http 메소드를 사용한다. Patch는 Post와 유사하지만, 데이터의 특정 값만 바뀌게 할 수 있다.

마찬가지로 @Param을 통해 id를 가져오고, @Body를 이용해 status를 가져온다.
또한 Service의 updateBoardStatus()메소드에 id와 status를 인수로 전달해주는 역할을 한다.

좋은 웹페이지 즐겨찾기