단위 테스트

Unit Testing 유닛 테스트 과정 Fake UsersService를 만들어서 실행할 계획이다. 정상적으로 애플리케이션을 실행하면 DI 안에 많은 종속성을 넣어야 한다. 우린 새롭게 테스트를 위한 DI를 만드는데, 내부에는 Userss Service의 모든 메서드를 실행하는 클래스를 담는다. 이로서 어떤 단위(ex. Authentication, sign in 등)을 테스트하는데 종속성 주입에서 자유로워질 수 있다. Test 설정하기 users 디렉토리에 auth.service.spec.ts 파일을 만들자 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // auth.service.spec.ts import { Test } from '@nestjs/testing'; import { AuthService } from './auth.service'; import { UsersService } from './users.service'; it('can create an instance of auth service', async () => { // 새 DI container 생성 // 하지만 AUthService를 위한 종속성을 제공하지 않았으니 실행하면 오류가 뜰것이다. constmudle = await Testing.createTestingModule({ providers:[AuthService] }).compile(); const service = module.get(AuthService); expect(service).toBeDefined(); }); 터미널에서 npm run test:watch를 입력한다. 3개가 failed라고 뜰텐데, p를 누르고 auth.service.spec 을 입력한다. 그럼 이 파일만 테스트하여 1 failed라고 뜬다. ...

2023년 10월 9일 · 5 분 · 배준수

데이터 직렬화

Custom Data Serialization 응답에서 특정 속성 제거하기 비밀번호는 보안에서 중요한 만큼 응답에서 제외하는 것이 맞다. 이 과정을 진행해보자. 어떻게 다룰지는 Nest Document를 살펴볼 것. 현재 요청-응답 Flow는 다음과 같다. 요청이 발생한다. 컨트롤러로 이동 서비스로 이동 서비스가 Repository 이용하여 Entity instance를 컨트롤러에게 반환 이 인스턴스는 JSON으로 변환된다. Document에서 권장하는 방법 서비스에서 컨트롤러로 이동하는 Entity instance에 인스턴스를 plain object로 변경하는 것에 관한 규칙 라이브러리를 추가한다. class serializer interceptor 라는 decorator를 컨트롤러에서 추가한다. 이 interceptor는 들어오는 요청이나 내보내는 응답을 가로채서 entity를 plain object로 변경해준다. 우리의 경우 나가는 응답을 가로채서 entity를 라이브러리로 추가한 규칙에 맞게 plain object로 변경해줄것 결론적으로 우리는 일단 password는 빼고 response를 보내도록 코드를 추가해줄 예정이다. ...

2023년 10월 8일 · 7 분 · 배준수

Data 처리 및 저장

User Data Users service 이제 유저서비스를 다뤄보자. users.service.ts 파일을 수정하자 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // users.service.ts import { Injectable } from '@nestjs/common'; import { Repository } from 'typeorm'; import { InjectRepository } from '@nestjs/typeorm'; import { User } from './user.entity'; @Injectable() export class UsersService { // repo : argument name // Repository<User> : User type을 다루는 Repository에 접근하여 instance를 받는다. // @InjtectRepository(User) : DI 시스템에게 우리가 User Repository가 필요하다는것을 말하는 코드 // DI 시스템은 뒤에 Repository<User>부분에서 inject할 인스턴스가 무엇인지 파악하기 위해 // type annotation 한다. generic에는 잘 작동 안하니까 앞에 decorator를 통해 더 분명히 제공한 것. constructor(@InjectRepository(User) private repo: Repository<User>) {} // create는 service 내에서 받은 정보(email과 password)로 User Entity Instance를 만든다. // save는 entity instance를 실제 Database에 저장해준다. create(email: string, password: string) { const user = this.repo.create({ email, password }); return this.repo.save(user); } } 이제 컨트롤러에 넣어보자 ...

2023년 10월 7일 · 9 분 · 배준수

Nest 아키텍처 : 모듈

종속성 주입 이해를 위한 소규모 프로젝트 소규모 프로젝트 개요 3개의 계층으로 이루어진 모듈을 만들 것이다. 최상층에는 Computer Module이 있고 내부에는 Computer Controller가 run이라는 메서드를 가진다. 이 내부에는 CPU, Disk Module이 있는데 각각 CPU Service, Disk Service를 가지고 있으며 이는 또 compute와 getData라는 메서드를 가진다. 최하층에는 Power Module이 있으며 Power Service를 가진다. 메서드는 supplyPower()이다. 생성은 당연히 최하층 Power Module이 전원을 제공하면 CPU와 Disk가 작동하고 Computer가 작동하는 형태이다. 기존과는 다른 새로운 디렉토리에서 Nest 프로젝트를 시작하자. ...

2023년 10월 7일 · 6 분 · 배준수

NestJS 프로젝트 : 기획 및 구성

중고차 판매 프로그램 중고차 판매 API 유저가 email과 Password로 가입 유저가 브랜드, 모델, 연식, 주행거리를 기반으로 예상 가격을 제공받음 유저는 중고차를 판매하고 실제 가격 기입 관리자가 기입된 가격을 검토 후 승인 API 디자인 Method and Route Body or Query String Description POST /auth/signup Body - { email, password } 새로운 유저의 회원 가입 로그인 POST /auth/signin Body - { email, password } 기존 유저의 로그인 GET /reports QS - make, model, year, mileage, longitude, latitude 자동차 가격 추정치 제공 POST /reports Body - { make, model, year, mileage, longitute, latitude, price } 판매 가격 기입 PATCH /reports Body - { approved } 유저가 제출한 가격 심사(가짜 데이터 차단) Module 디자인 Module Controllers Services Repositories Users Module Users Controller Users Service Users Repository Reports Module Reports Controller Reports Controller Reports Repository 처음부터 완벽하게 디자인 할 순 없다. 이를 기반으로 진행하면서 추가하면 된다. ...

2023년 10월 7일 · 1 분 · 배준수

TypeORM으로 데이터 처리하기

데이터베이스 ORM TypeORM SQLite Postgres MySQL MongoDB Mongoose MongoDB 아무거나 사용해도 된다. 여기서는 TypeORM과 SQLite를 사용할 것. 마지막에는 Postegres로 변경할 계획 Entity 우리는 AppModule 내부에[ 두가지 모듈(users, reports)을 만들기로 계획했었다. 이 모듈에는 각각 User Entity와 ReportEntity 파일을 만들 것이다. Entity 파일은 애플리케이션 내부에 저장하려는 한 종류의 리소스나 항목을 정의하고, 갖고 있는 모든 속성을 나열하는 리스트이다. 예를 들어 User 모듈에는 사용자가 입력한 email과 password가 있어야 하는데, User Entitiy에 나와 있어야 한다. ...

2023년 10월 7일 · 7 분 · 배준수

Nest 아키텍처 : 서비스와 레포지토리

서비스와 레포지토리 공통점과 차이점 둘 다 클래스이다. 서비스는 비즈니스 로직을 넣는 곳이다. 레포지토리는 저장과 관련된 로직을 넣는 곳이다. 서비스는 데이터를 찾거나 저장하기 위해 하나 이상의 레포지토리를 사용한다. 레포지토리는 일반적으로 TypeORM entity, Mongoose schema 등으로 끝난다. 서비스와 레포지토리에서 사용하는 메서드는 동작이 비슷하다. 서비스에서 ‘데이터를 찾아라’ 라는 메서드를 호출할 것이고 레포지토리에서는 그 메서드를 실행할 것이기 때문. 그럼에도 서비스는 필요하다. 이유는 후술! 레포지토리 만들기 src 디렉토리 내에 messages.repository.ts와 messages.service.ts를 만든다. 루트 디렉토리에는 messages.json 파일을 만든다. 내용은 비워둔다. (안 만들면 찾을 파일이 없어서 오류발) ...

2023년 10월 6일 · 6 분 · 배준수

Nest CLI로 프로젝트 생성하기

App setup 이번엔 이전과 다르게 Nest CLI를 이용해 프로젝트를 시작해보겠다. 새로운 디렉토리에서 시작하자. 새 폴더를 만들고 터미널에서 이동한다. npm install -g @nestjs/cli 를 입력하자. 오류뜨면 맨앞에 sudo를 추가한다. 설치가 끝나면 nest new {프로젝트이름}을 입력하고 npm을 선택한다. messages라는 이름으로 짓겟다. 끝나고 나면 우리가 일일이 만들었던 저번보다 훨씬 많은 파일이 자동적으로 생성된 것을 볼 수 있다! 계획 이번에 만들 앱(모바일 X)은 일반 JSON 파일에 저장된 메시지를 검색하고 저장하는 것. 3개의 route가 예상된다. 각 route가 pipe, guard, controller, service, repository 중 무엇이 필요한지 생각해보자. ...

2023년 10월 5일 · 3 분 · 배준수

NestJS 기초

scratch에서 시작한다. Nest 기초 시작 및 설치하기 npm init -y 로 package.json 생성한다. 그 후 종속성 5개를 설치한다. "@nestjs/common": "^7.6.17" : Nest에서 함수, 클래스 등 대다수를 가져온다. "@nestjs/core": "^7.6.17" "@nestjs/platform-express": "^7.6.17" : HTTP 요청을 다루기 위해 Nest가 ExpressJS 사용하도록 해준다. "reflect-metadata": "^0.1.13" : decorator "typescript": "^4.3.2" : 사용할 언어 TS(Typescript) 컴파일러 세팅 루트 디렉토리에 다음과 같이 tsconfig.json 파일을 만든다. 1 2 3 4 5 6 7 8 { "compilerOptions": { "module": "commonjs", "target": "es2017", "experimentalDecorators": true, "emitDecoratorMetadata": true } } HTTP 요청과 응답 사이에 서버에서 발생하는 일 요청 (in Nest) ...

2023년 10월 5일 · 4 분 · 배준수

요청 데이터의 Validation

요청 데이터의 Validation(타당성) 검사 Decorator로 요청 데이터 접근하기 HTTP 요청 3가지로 구성 Start line : POST /messages/5?validate=true HTTP/1.1 Headers : Host: localhost:3000, Content-Type: application/json Body : {"content": "hi there"} Nest의 경우 decorator 이용 POST /messages/5?validate=true HTTP/1.1 5 : @Param(‘id’) validate=true : @Query() Headers는 @Headers() Body 는 @Body() 위와 같이 decorator를 이용하면 된다. messages.controller.ts 의 컨트롤러를 다시 작성해 보자. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // messages.controller.ts import { Controller, Get, Post, Body, Param } from '@nestjs/common'; @Controller('messages') // class decorator export class MessagesController { @Get() // method decorator listMessages() {} @Post() createMessage(@Body() body: any) { // @Body, @Param : argument decorator console.log(body); } @Get('/:id') getMessage(@Param('id') id: string) { console.log(id); } } 이제 API Client로 확인해보자. ...

2023년 10월 5일 · 4 분 · 배준수