[NestJS]Controller

star_moon_cloud_k·2024년 3월 27일

NestJs

목록 보기
2/5
post-thumbnail

NestJS 요청 라이프 사이클

  • 요청이 가장 먼저 Middleware - Guard - Interceptor - Pipe 등을 거치고, Controller 로 들어오며 요청 로직 처리 부분으로 연결된다.
  • 하지만 controller 이전 까지는 기능 강화 측면에서 있지만, 사실 없어도 '기능은' 동작한다.

새로운 기능 추가

╰─$ nest g resource
? What name would you like to use for this resource (plural, e.g., "users")? posts
? What transport layer do you use? REST API
? Would you like to generate CRUD entry points? No
CREATE src/posts/posts.controller.spec.ts (566 bytes)
CREATE src/posts/posts.controller.ts (210 bytes)
CREATE src/posts/posts.module.ts (248 bytes)
CREATE src/posts/posts.service.spec.ts (453 bytes)
CREATE src/posts/posts.service.ts (89 bytes)
UPDATE package.json (1984 bytes)
UPDATE src/app.module.ts (312 bytes)
✔ Packages installed successfully.

nest g resource 라는 명령어를 입력하게 되면, nestjs의 프레임워크에 맞춰서 새로운 폴더와 그 하위 디렉터리에 이름을 맞춰서 파일들을 생성해준다. (controller, service, module, spec) 또한 package.json에 정보를 추가하는 것 같다.

생성된 파일의 controller

import { Controller, Get } from '@nestjs/common';
import { PostsService } from './posts.service';
  
/**
 * author : string;
 * title : string;
 * content : string;
 * likeCount : number;
 * commentCount : number;
 */
  

interface Post {
  author: string;
  title: string;
  content: string;
  likeCount: number;
  commentCount: number;
}

//post 를 작성하게 되면, url의 path를 설정할 수 있다.
//모든 path의 prefix(접두어)를 만들 수 있다.

@Controller('posts')
export class PostsController {
  constructor(private readonly postsService: PostsService) {}

  //@Get() 데코레이터 안에도 직접 path 경로를 설정할 수 있다.

  //http://localhost:3000/post/post를 입력해야 접근 가능해다

  @Get()
  getPost(): Post {
    return {
      author: 'newjeans',
      title: '뉴진스 민지',
      content: '메이크업 고치는 민지',
      likeCount: 10000000,
      commentCount: 999999,
    };
  }
}
  • @Controller 같은 어노테이션을 nestjs에서는 데코레이터라고 하는것 같다.
    - spring 과 같이 @Controller() 안에 경로를 입력하게 되면, path 값을 지정할 수 있다.
  • 반환 값의 경우 interface를 사용하여, 어떤 값으로 반환할지 작성해주고, 데이터 형식으로 사용해야한다.

잠깐 보고가는 REST API 세트

뭐 맨날 보는거지만, 그래도 강의에 있으니 정리한번 다시 해보자.

GET

  • http://localhost:3000/posts
    - 다수의 posts를 가져온다.
    - Query 사용
  • http://localhost:3000/posts/11
    - 11이라는 ID를 갖고있는 Post를 하나 가져온다.
    - Query 사용
  • 데이터를 불러올 때는 최소한의 개수를 가져와서 전송해야한다.
    - 데이터의 길이는 돈이다.
  • 모든 데이터를 불러올 때, 모든 상세한 데이터를 가져올 필요는 없다.

POST

PATCH

  • http://localhost:3000/posts/8
    • 8이라는 ID를 갖고있는 Post를 부분 변경한다.
    • 수정할 데이터만 전송해주면 된다.
    • Body 사용

PUT

  • http://localhost:3000/posts/8
    • 8이라는 ID를 갖고있는 Post를 변경하거나 생성한다.
    • 필요한 데이터를 모두 전송해야한다.
    • PATCH와 가장 다른 중요한 포인트
    • Body 사용

DELETE

CRUD 기본 작성하기

import {
  Body,
  Controller,
  Delete,
  Get,
  NotFoundException,
  Param,
  Post,
  Put,
} from "@nestjs/common"
import { PostsService } from "./posts.service"

/**
 * author : string;
 * title : string;
 * content : string;
 * likeCount : number;
 * commentCount : number;
 */
interface Post {
  author: string
  title: string
  content: string
  likeCount: number
  commentCount: number
}

interface PostModel {
  id: number
  author: string
  title: string
  content: string
  likeCount: number
  commentCount: number
}

let posts: PostModel[] = [
  {
    id: 1,
    author: "newjeans_official",
    title: "뉴진스 민지",
    content: "메이크업 고치는 민지",
    likeCount: 1000000,
    commentCount: 999999,
  },
  {
    id: 2,
    author: "newjeans_official",
    title: "뉴진스 혜린",
    content: "노래 연습 하고 있는 혜린",
    likeCount: 1000000,
    commentCount: 999999,
  },
  {
    id: 3,
    author: "blackpink_official",
    title: "블랙핑크 리사",
    content: "랩하는 리사",
    likeCount: 1000000,
    commentCount: 999999,
  },
]

//post 를 작성하게 되면, url의 path를 설정할 수 있다.
//모든 path의 prefix(접두어)를 만들 수 있다.

@Controller("posts")
export class PostsController {
  constructor(private readonly postsService: PostsService) {}

  //@Get() 데코레이터 안에도 직접 path 경로를 설정할 수 있다.
  //http://localhost:3000/post/post를 입력해야 접근 가능해다
  //모든 포스트를 가져온다

  @Get()
  getPosts(): PostModel[] {
    return posts
  }

  //특정 아이디에 해당하는 post를 가져온다
  //@Param()안에 값을 집어넣게 되면, 특정 파라미터 id를 연결할 수 있다.

  @Get(":id")
  getPost(@Param("id") id: string) {
    const post = posts.find((post) => post.id === +id)

    if (!post) {
      throw new NotFoundException() //post가 찾으려는 Id가 없는 경우 예외처리
    }

    return post
  }

  //Post를 생성한다.
  //Post 호출시 저장된 body에서 값을 불러올 때는 @Body 데코레이터를 사용한다.

  @Post()
  postPosts(
    @Body("author") author: string,
    @Body("title") title: string,
    @Body("content") content: string
  ) {
    const post: PostModel = {
      id: posts[posts.length - 1].id + 1,
      author: author,
      title,
      content,
      likeCount: 0,
      commentCount: 0,
    }
    posts = [...posts, post]
    return posts
  }

  // id에 해당하는 데이터를 수정한다.
  //받을 body의 값을 ?를 붙여주게 되면 null 값이 될 수 있다.

  @Put(":id")
  putPost(
    @Param("id") id: string,
    @Body("author") author?: string,
    @Body("title") title?: string,
    @Body("content") content?: string
  ) {
    const post = posts.find((post) => post.id == +id)

    if (!post) {
      throw new NotFoundException()
    }

    if (author) {
      post.author = author
    }

    if (title) {
      post.title = title
    }

    if (content) {
      post.content = content
    }

    //현재 있는 게시물의 id가 같으면, 현재 수정하려고 저장한 값을 저장한다.
    posts = posts.map((prevPost) => (prevPost.id === +id ? post : prevPost))
    return posts
  }

  @Delete(":id")
  deletePost(@Param("id") id: string) {
    const post = posts.find((post) => post.id === +id)

    if (!post) {
      throw new NotFoundException() //post가 찾으려는 Id가 없는 경우 예외처리
    }

    posts = posts.filter((post) => post.id !== +id)
    return id
  }
}

  • 기본적인 구조는 spring과 유사하다.
  • @Get, @Post, @Put, @Delete와 같은 데코레이션을 사용하여 받을 Http 프로토콜을 설정해준다.

path 파라미터 값 가져오기

@Put(':id')
putPost(
	@Param('id') id: string,
	@Body('author') author?: string,
	@Body('title') title?: string,
	@Body('content') content?: string,
) 
  • @Put(':id') : path 를 결정해준다.
  • @Param('id') : 경로에서 id라는 파라미터를 값으로 가져온다.
  • @Body('author'): 전송된 데이터에서 body 값을 확인해서 특정 값을 가져온다.
    - 여기서는 'author' 값으로 저장된 값을 가져오겠다는 의미
    - 중요한 점은 변수 뒤에 '?'를 붙이게 되면 not required 같은 개념인것으로 보인다.
    - null 일 수 있으니, null 값을 체크하는 로직을 작성해준다.
const post = posts.find((post) => post.id == +id);
if (author) {
	post.author = author;
}
if (title) {
	post.title = title;
}
if (content) {
	post.content = content;
}
  • 위와 같이 작성해주면 posts(저장된 데이터)에서 해당되는 값을 변수 post로 반환한다.
  • 각 @Body 에서 받은 변수들 중 null이 아닌 값만 id로 찾아낸 게시물에서 특정 값만 변경한다.
//현재 있는 게시물의 id가 같으면, 현재 수정하려고 저장한 값을 저장한다.
posts = posts.map((prevPost) => (prevPost.id === +id ? post : prevPost));
  • posts(저장된 데이터) 에서 map() 함수를 사용하여 현재 저장된 데이터들을 탐색한다.
  • 그 중 현재 입력받은 id(@Param('id') 값으로 비교해서 prevPost(현재 저장된 데이터)와 같은 데이터를 찾아낸다.
  • true인 경우 post(변경된 데이터의 게시물)을 반환해서 저장.
  • false 인 경우 prevPost(현재 저장된 데이터)를 그대로 반환.

값이 없는지 간단히 체크

	const post = posts.find((post) => post.id === +id);
	if (!post) {

		throw new NotFoundException(); //post가 찾으려는 Id가 없는 경우 예외처리

	}

모든 내용은 강의 [코드팩토리][초급] NestJS REST API 백엔드 완전 정복 마스터 클래스를 수강하며 정리하는 내용들을 올린 글이다.

profile
자유로운 개발자

0개의 댓글