오늘은 프레임워크에 좀 더 상세히 알아보면서 모듈로 관리하는 방법에 대해 알아보도록 하자.
DB까지 접근하기 위한 Framework의 구조는 주로 다음과 같이 구성되며
이전에 Contorller, Service, Repository에 대한 설명을 했었다.
[이전 글 참조 : https://roothyo.tistory.com/56?category=1034781]
간단히 설명하자면,
Contoller : 해당 서버로 요청이 오는 것을 처리해주는 Router 기능
Service : 유저가 요청한 데이터를 실질적으로 처리하고 Controller에게 건네주는 기능
Repository : 서버에서 DB로 직접 접근하여 데이터를 가져오는 기능
이라고 보면 된다.
그럼 그냥 Framework를 위와 같이 3개의 구조로 나누어 기능들을 그저 처리만 하면 될 것 같지만
- 잘못된 데이터 형식이 넘어온다던지
- 기존에 number로 들어와야 할 데이터가 string으로 들어온다던지
- 사용자가 해당 기능의 해킹을 시도한다던지 (Input에 DB 쿼리문을 날리는 경우 등)
등의 위험 요소를 갖고 있다.
물론, 각 프로세스에서 미리 체크하고 넘기면 처리는 가능하지만 그럼 코드가 중복될 뿐만 아니라 협업을 하게 되는경우 체크하는 방식이 달라 맡는 데이터여도 오류가 발생하는 경우가 발생하기 때문이다. 이를 해결하기 위해 디자인패턴을 적용하는 것이고, DTO, DAO, Entity를 도입하는 것이다.
그럼 DTO, DAO, Entity에 대해 알아보도록 하자.
DTO (Data Transfer Object)
: 프로세스 간에 데이터를 전달하는 객체이다. 프로세스 간 통신이 일반적으로 원격 인터페이스(예: 웹 서비스)로 재정렬하면서 이루어지게 되는데 여기에서 각 호출의 비용이 많다는 점을 동기로 하여 이용하게 된다. 각 호출의 비용이 큰 것이 클라이언트와 서버 간 왕복 시간과 관련되기 때문에 호출의 수를 줄이기 위해 여러 호출에 의해 전송되는 데이터를 축적하면서 오직 하나의 호출만으로 서비스되는 객체인 DTO를 사용하는 것이다.
DAO(Data Access Object)
: 일부 종류의 데이터베이스나 기타 퍼시스턴스 매커니즘에 추상 인터페이스를 제공하는 객체이다. 응용 프로그램의 호출들을 퍼시스턴스 계층에 매핑시킴으로써 DAO는 데이터베이스의 상세한 사항을 노출시키지 않고 특정 데이터의 일부 동작을 제공하게 된다. 이러한 분리는 단일 책임 원칙을 지원한다. 도메인 특화 객체 및 자료형(DAO의 퍼블릭 인터페이스) 관점에서 응용 프로그램이 필요로 하는 데이터 접근이 무엇인지를, 어떻게 이러한 요구사항을 특정 DBMS, 데이터 스키마 등을 만족할 수 있는지(DAO의 구현체)와 분리시킨다.
Entity
: 인간의 개념 또는 정보의 세계에서 의미있는 하나의 정보 단위이다. 사물의 본질적인 성질을 속성이라고 하며, 관련있는 속성들이 모여서 의미있는 하나의 정보 단위를 이룬 것이 바로 개체에 해당한다. 파일시스템이나 데이터베이스에서의 레코드가 개체에 해당한다. 개체들 사이의 연관성을 관계라고 하며, 개체와 관계를 나타낸 모델을 개체-관계 모델라고 한다.
위는 Wiki 백과에 적힌 정의들이다. 물론 이 것만으로는 이해가 잘 되지 않을 것이기 때문에 다시 정리하자면
Entity는 데이터베이스 시스템에서 사용되는 실질적인 스키마, 객체라고 생각하며, 각 속성으로 이루어진 테이블의 구조라고 생각하면 된다.
DAO는 데이터베이스의 상세한 사항을 노출시키지 않고, 특정 데이터의 일부 동작을 제공해주는 추상 인터페이스 객체이며, 실제 DB에 접근하는 프로세스인 레포지토리에서 사용하는 ORM(Objective Relationship Mapping)을 통작시킬때 주로 사용되는 객체라고 생각하면 될 듯 하다.
DTO는 클라이언트부터 각 프로세스 간의 데이터로 전달되는 객체로, service나 controller등 데이터의 변경이 많은 특성상 Entity나 DAO와 함께 따로 구분해주는 것이며, 레이어간의 호출이 여러번 반복되기 때문에 이를 줄이기 위해 디자인 패턴으로 Model을 따로 빼내는 것과 비슷하게 생각하면 된다.
추가적으로 VO(Value Object)가 있는데, VO도 DTO와 동일한 개념이나, DTO는 데이터를 계층간 교환하는데 의미가 있고, VO는 읽기만 가능한 read-only 속성을 가진 객체로서 데이터 그 자체에 의미를 두고 있다는 점이다.
실습으로는 DTO만 일단 적용해 보도록 하겠다.
먼저 npm install class-validator와 class-transformer를 설치해준다.
class-validator는 데코레이터를 사용하여, 데이터를 검증할 수 있도록 도와주는 라이브러리이다.
class-transformer는 class-validator의 옵션중에서 transform 옵션을 주기 위해 필요한 라이브러리로 GET 방식의 string으로 넘어오는 query들을 자동으로 type에 맞게 변환시켜주는 기능을 제공한다.
npm install class-validator class-transformer
main.ts에 다음과 같은 옵션을 입력해 validation 기능을 준다. Express의 middleware라고 보면 될 듯 하다.
- whitelist : 유효성 검사기는 유효성 검사 데코레이터를 사용하지 않는 속성의 유효성 검사(반환 된) 객체를 제거합니다.
- forbidnonWhitelisted : true로 설정하면 화이트리스트에 없는 속성 검사기를 제거하는 대신 예외가 발생합니다.
- transform : DTO 클래스에 따라 타입이 지정된 객체로 자동 변환할 수 있습니다.
[참조 : https://docs.nestjs.kr/techniques/validation]
movies 디렉토리 하위에 dto 디렉토리를 생성하고 create-movie.dto.ts 파일을 생성하고 DTO 객체를 생성하여, export 하고, class-validator를 통해 각 데이터를 검증해준다.
또, update를 하는 것에 대한 dto를 만들어 주어야 하는데, update의 경우 optional하게 create-movie.dto가 들어올 것이기 때문에, 모든 속성에 optional을 넣어도 되지만, 상속을 활용하여, 처리해 보도록 하자.
npm install @nestjs/mapped-types
먼저, @nestjs/mapped-types 라이브러리를 설치하고 update-movie.dto.ts 파일을 생성하여 다음과 같이 입력하자.
mapped-types의 경우 nest에서 create DTO를 활용해 update DTO를 손쉽게 만들기 위해 PartialType() 함수를 제공한다.
[참조 : https://docs.nestjs.kr/openapi/mapped-types]
다음과 같이 만들고, 이제 Client와 Controller, Controller와 Service 사이의 함수의 Return에 Typescript를 사용하여, 데이터 객체의 인터페이스를 선언해주자.
무사히 실행시키고 나면, 정상 작동하는 것을 볼 수 있을 것이며, 정의되지 않은 properties가 들어오는 경우 400 ERROR를 리턴하는 것을 볼 수 있다.
추가적으로 nestJS에서는 각 API별로 module을 만들어서 app.module 하위에 import 시키는 방식을 사용한다고 한다.
nest g mo
movies에 대한 모듈을 생성하고, controller와 service를 연결한다.
이 후 app.module.ts에 movie에 대한 controller와 service는 제거하고 모듈만 연결시키는 방식으로 프레임워크를 관리하면 된다.
확실히 프레임워크에 대한 구조를 배우고 나니, 이전에 Custom하게 만들었던 Framework 구조의 부족함을 많이 느낀 것 같다. 처음부터 배웠으면 좋으련만... 하지만, 오히려 필요성을 더욱 깨닫았기 때문에 다음 프로젝트에 적용하면 더욱 편리하게 관리 할 수 있지 않을까 싶다.
다음 시간에는 DB 연동을 위한 TypeORM에 대해서 알아보도록 하자
[참조 : https://nomadcoders.co/nestjs-fundamentals/lectures/1944]
'서비스개발(Web, App) > Back-End' 카테고리의 다른 글
Nest JS 프레임워크 공부하기 - TypeORM, MariaDB(mysql) 연동 (0) | 2022.01.12 |
---|---|
Nest JS 프레임워크 공부하기 (Node.js) - 2 (0) | 2022.01.03 |
Nest JS 프레임워크 공부하기 (Node.js) - 1 (0) | 2022.01.02 |
Nest JS 프레임워크 공부하기 (Node.js) - 0 (0) | 2022.01.02 |
Node.js ioredis(Redis) 외부 접속 (0) | 2021.08.19 |