캡스톤디자인(1)/공부

캡스톤디자인(1) NestJS 공부 3

ludvbg (이지현) 2022. 11. 4. 13:21

컴퓨터공학과 5584977 이지현
캡스톤디자인(1) TEAM 우연한 인연

 

#2.3 Movies Service part Two

 

* 한 가지 알아둬야 할 것!

- 우리가 파일을 저장하면 데이터베이스가 다 날아간다.

- 지금 사용하는 게 진짜 데이터베이스가 아니고 메모리 위의 데이터베이스라서 + 서버를 켜놓은 동안만 유효하다.

 

1. getOne 코드 개선

- 잘못된 값을 보냈을 때 적어도 에러 화면은 뜨도록 개선

 

지금 데이터베이스에 저장되지 않은 id 값인 111111을 GET 했을 때 Error가 뜨지만 에러인지 알 방법이 없다.

 

그래서 아래와 같이 getOne 코드 수정

 

그리고 아까처럼 없는 값을 GET하면 404 Error가 화면에 표시되고, 우리가 작성한 에러 메세지도 출력됨

 

 

2. deleteOne도 개선

- deleteOne에서는 this.getOne을 부르기만 하면 된다.

새로 저장해서 기존의 데이터베이스가 날아갔으므로 테스트하기 위해 데이터베이스를 새로 생성한다.

POST로 데이터베이스 생성 > GET으로 전체 데이터베이스 확인 > GET으로 movie id가 1인 데이터만 확인 > 데이터베이스에 없는 값인 아무 숫자값을 DELETE

 

데이터베이스에 없는 id를 DELETE 하려고 했을 때, 마찬가지로 404 Error가 뜨게되었다.

POST로 데이터베이스 생성
GET으로 전체 데이터베이스 확인
GET으로 movie id가 1인 데이터만 확인
데이터베이스에 없는 값인 아무 숫자값을 DELETE -> 404 Error

 

 

3. update 작성

- update 함수를 작성하고, controller에서 Patch를 수정하였다.

 

이번에는 헤더에 year을 2025년으로만 설정하고 PATCH 해주었음 (200 OK)

 

PATCH하고 실행했더니 같은 id값이 중복되어서 저장됨

이 말은 delete가 작동하지 않았다는 것이다.                                             

 

* deleteOne 코드를 잘못 작성해서 수정

 

그리고 다시 POST > GET > PATCH > GET으로 확인하니 정상적으로 작동된다.

처음에는 id가 1인 movie의 year이 2025였는데 PATCH 후 2020으로 바뀌어서 update된 것을 확인할 수 있다.

 

 

** 이제 Service는 끝!

하지만 여기서 문제는 updateData의 유효성을 검사하지 않고 있다는 것

= 누군가가 부적절한 것을 보낼 수 있다.

 

예를 들어,

내 데이터에 "hacked": "by me" 같은 부적절한 것을 아무 문제 없이 추가할 수 있다.

PATCH 정상 작동
GET했을 때 부적절한 코드가 저장된 것을 확인

 

4. updateData(movieData)의 유효성 검사

- NotFoundException과 같이 NestJS에서 기본제공하는 것을 사용할 것임

- 다음 영상에서 이어서

 

 

 

#2.4 DTOs and Validation Part One

- updateData와 movieData에 타입을 부여하기 위해서 서비스와 컨트롤러에서 DTO라는 것을 만들어야 한다.

DTO는 데이터 전송 객체(Data Transfer Object)이다.

 

1. dto 폴더 및 파일 생성

src의 movies 폴더에 dto 폴더를 생성해주고 create-movie.dto.ts 라는 이름으로 파일을 생성하였다.

create-movie.dto.ts는 기본적으로 클래스가 될 것이다.

 

 

2. CreateMovieDto 클래스 생성

CreateMovieDto class를 만들어주고 읽기 전용으로 우리가 movie에 저장할 변수들과 타입을 지정해준다.

 

그리고 controller의 @Post에서 movieData와 service의 create에서 movieData의 타입을 CreateMovieDto로 지정해주었다.

 

실행했을 때 hacked라는 정보가 아직은 그대로 저장됨

 

DTO를 쓰는 이유는 프로그래머로서 코드를 더 간결하게 만들 수 있도록 해준다.

그리고 NestJS가 들어오는 쿼리에 대해 유효성 검사를 할 수 있게 해준다.

이를 위해서 main.ts에 파이프라는 것을 만들 것이다. (파이프: 코드가 지나가는 곳)

 

 

3. 유효성 검사용 파이프 만들기

main 함수에 app.useGlobalPipes(new ValidationPipe()); 코드 추가

ValidationPipe는 유효성을 검사해주기 때문에 아주 유용한 코드이다.

 

 

그리고 진행하기 전에 몇 가지를 설치해주었다.

- npm i class-validator class-transformer

설치 후 CreateMovieDto를 위한 decorator 작성

- @IsString(), @IsNumber()

이 데코레이터는 class-validator에서 import 시켜주었다.

@IsString({ each: true })는 배열에 들어오는 각각을 검사한다는 의미

 

그리고 insomnia에서 POST로 아까와 같은 hacked 정보를 넘겨보았는데,

이번에는 400 Bad Request가 뜨면서 정보가 저장되지 않는 것을 볼 수 있다.

(title, year, genres 정보는 string/number여야 한다는 에러 메세지가 뜸)

이제 input에서도 유효성 검사를 하게 되었다.

 

 

4. ValidationPipe Option

아까 만들었던 파이프의 ValidationPipe에는 여러 옵션이 있는데, 그 중 하나가 whitelist이다.

ValidationPipe의 whitelist에 대한 설명인데, 읽어보면 true로 설정하면 아무 데코레이터도 없는 property의 object는 거를 것이라고 되어 있다. 즉, 내가 hacked by me를 보내면 이 코드는 Validator에 도달하지 않는다는 것이다.

 

 

그리고 forbidNonWhiteListed를 통해 누군가 이상한 걸 보내면 리퀘스트 자체를 막아버리도록 보안을 한 단계 업그레이드할 수 있다.

이렇게 코드를 작성하고 insomnia에서 테스트를 해 보면, 아까 없었던 "property hacked should not exist(property hacked는 존재할 수 없다)"라는 메세지도 추가되어 나온다.

 

 

그리고 ValidationPipe에 대해 한 가지 더

(+string은 string을 number로 바꿔줌) 앞에 게시물 수정))

우리가 Movie의 id를 number로 설정했는데, url에서 가져오는 값은 string이므로 service.ts에서 string으로 받은 id값을 +id를 통해 number로 바꿔주었었다. 이는 별로 좋은 방법이 아니다.

그래서 우리는 transform이라는 옵션을 사용할 것이다.

 

transform은 유저가 보낸 것을 우리가 원하는 타입으로 변환해 주는 것이다.

따라서 ValidationPipe에 transform: true를 추가해주고, 컨트롤러와 서비스에서 id 타입을 전부 number로 바꿔주었다. (string을 number로 바꿔줬던 +id도 id로 변경)

 

그리고 console.log()를 통해 movieId의 타입을 출력해보면 number라고 잘 나온다.


∴ NestJS는 타입을 받아서 넘겨줄 때 자동으로 타입도 변환해준다.