프레임워크 16

Typeorm querybuilder에서 bigint number로 받기

typeorm에서 querybuilder를 사용해서 데이터를 뽑아오는 작업을 했다. postgres에서 pk를 Bigint로 설정 후 querybuilder에서 받아오니 무조건 string으로 가져오는 문제가 있었다. 공식 문서를 찾아 보니 bigint가 string으로 넘어오는 것은 의도한 동작으로 보인다. https://typeorm.io/entities 하지만 타 ORM을 살펴보니 Bigint 타입은 바로 숫자로 사용이 되는 것으로 보였다. (JPA는 Long으로, Django는 정수 타입으로 바로 캐스팅) 그리고 기존의 개발된 코드를 보니 transformer를 사용해서 repository에서 바로 가져올 때는 number 타입으로 가져오는 것을 볼 수 있었다. 그래서 기존의 repository와..

NestJS Graceful shutdown

실행중인 NestJS를 종료하고 싶은데, 실행중인 작업이 있으면 종료하기 애매할 것이다. 해당 세션은 종료가 된 이후에 업데이트가 되어야 하기 때문이다. 이러한 문제를 NestJS는 shutdown에 관련한 인터페이스를 제공하여 SIGTERM 신호가 들어올 때의 동작을 정의한다. 구현 import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { ShutdownSignal } from '@nestjs/common'; const PORT = 3001; async function bootstrap() { const app = await NestFactory.create(AppModule); app.en..

Active Record , Data Mapper 패턴에 대하여

공부했던 것들에 대해서 계속 복습 중이다. 여기서는 서버 APP에서 DB의 데이터에 엑세스하는 접근 방식에 대해서 설명하고 있다. 주로 2가지의 패턴이 보이게 되는데, 이에 대한 차이점을 정리해 볼려고 한다. Active Record Pattern 모델 내에서 모든 쿼리(접근자) 메서드를 정의하고 모델 메서드를 통해서 객체의 CRUD를 한다. 이렇게 작성하게 되면 개발이 빨라진다. 하지만 DB와 애플리케이션 로직의 결합으로 인해서 단위 테스트를 하기가 어려워지고, 단일 책임 원칙에 위배된다는 문제도 생긴다. 단위 테스트의 경우에는 테스트를 위한 새로운 계층의 생성으로 해결이 가능할 수도 있으나, 단일 책임 원칙에 위배되는 점은 해결하기 힘들어 보인다. 아래의 예시를 보면 User라는 엔티티에 직접 fin..

[NestJS] JWT 인증과 Role 적용하기

JWT인증과 Role인증을 동시에 적용하는 로직을 만드는 연습을 해 보았다. JWT인증에 대해서 정리한 글은 아래의 링크에 나와 있다. https://tre2man.tistory.com/321 로그인 인증 부수기 최근들어 유저의 인증 로직 관련해서 보완해야 할 점이 보여서 수정 중, 이참에 로그인 인증 관련해서 한번 정리해 보고자 글을 작성한다. 배경 지식 먼저 인증과 인가에 대해서 구분을 하자. 인 tre2man.tistory.com JWT인증을 하기 전에 공식 문서를 잘 읽어 보자. NestJS는 공식문서가 잘 되어 있어서 꼼꼼하게 읽어 보는것이 좋다. https://docs.nestjs.com/security/authentication Documentation | NestJS - A progress..

[NestJS] 데이터 요청과 응답 사이의 Request lifecycle

NestJS를 쓰면서 갑자기 느낀 게 있었다. 바로 NestJS 내부에서 데이터의 흐름이 어떻게 되는지 궁금했다. Service단 에서의 데이터 흐름뿐 아니라 클라이언트에서 데이터를 요청한 이후 데이터를 응답할 때 까지의 흐름을 알고 싶었다. 그래서 공식 문서를 보며 정리하기로 했다. 공식 문서는 Request lifecycle이라고 하는데, 왠지 Data lifecycle이라는 이름이 더 맞는다. 참고로 express는 use 메서드에 온갖 미들웨어를 넣어버리는데, 이 때 데이터 흐름을 개발자가 직접 제어해 주어야 한다. express는 자유도는 매우 높은 프레임워크이나, 견고하고 가독성 좋은 코드를 만들기 힘들다. 데이터 흐름 1. 가드 미들웨어 다음으로 오는 가드는 데이터가 들어올 때 처음으로 데이..

[NestJS] Dependency Injection과 NestJS

최근들어 비교적 삶이 한가해져서, 미루기만 했던 지식들을 정리하는 시간을 가지기로 했다. 이번 포스트에서는 DI (Dependency Injection)과 NestJS에서 해당 기능을 사용하는 방법에 대해서 정리해 볼려고 한다. Dependency Injection 이란? 정의부터 알기 전에, 각 단어에 대해서 알아보자. Dependency는 의존성, Injection은 주입 이라는 단어이다. 각 단어에 대해서도 간단히 정리하자. 의존성 의존 관계를 가지는 것이다. 아래 TS 코드로 확인해 보자. class Human { meal = new Meal(); } class Meal {} 위 코드에서 Human 클래스는 Head 클래스를 내부에서 사용하게 되므로, Human 클래스는 Meal 클래스에 의존 관..

Prisma ORM 사용 시 읽기 전용 DB 사용하기

현재 NestJS + Prisma 조합으로 백앤드를 운영중이다. 요즘 읽기 부하가 늘어남에 따라 replica DB를 따로 생성하여 read 동작은 모두 replica DB에서, 나머지 동작은 master DB에서 사용하고 싶었다. 그래서 doc를 찾던 중, 아직은 prisma에서는 정식으로 replica DB를 지원하는 공식 문서는 없었다. prisma의 기본 정신이 빠른 백앤드 서버 제작을 목표로 해서 그런가? 이건 좀 많이 아쉬웠다. 옆동네 typeORM은 잘 지원해 주던데. 아직 오픈이슈인걸로 봐서는 언젠간 개발해 주지 않을까 싶다. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 "replication": { "master": { "host": "master..

[NestJS] Subscription과 Guard 사용하기

NestJS를 이용해서 실시간 통신을 구현해야 하는 상황이 주어졌다. 이를 위해서 실시간 통신에 관련한 자료를 찾아보니 WebSocket 관련한 자료가 많이 나왔다. 하지만 현재 사용중인 서버는 Graphql을 사용하므로, Graphql에서 지원하는 것들 위주로 찾아보니 Subscription이라는 기능을 발견했다. 이제 이를 이용해서 실시간 통신을 구현함과 동시에, HTTP Header를 이용해 보안까지 같이 챙겨보자. Subscription 이란? Subscription에 관해서 알아보기 전에 Rest API 와 GraphQL의 차이에 대해서 정말 간단히 정리해봐야겠다. Rest API와 GraphQL은 서버에 무언가를 요청하여 응답을 받을 수 있는 하나의 약속이라고 볼 수 있다. 하지만 둘의 사용 ..

[NestJS] Prisma db 여러개 연결하기

현재 서버의 데이터를 이용해서 의미있는 데이터를 만들고 싶었다. 하지만 이 작업을 수행하게 되면 DB에 자원이 많이 소모되기 때문에, 기존의 db를 새 db에 마이그레이션 한 이후 이 db에서 데이터를 추출하고 싶었다. 여기서 문제가 되는 것이 복사한 db에서 의미있는 값을 뽑아낸 뒤에 기존의 db에 바로 올리기 위해서는 한 대의 서버에 2개의 db를 연결해야 했다. 나는 NestJS + Prisma 를 사용하므로, Prisma에 대한 방법을 정리해 보았다. DB 2개 연결하기 Prisma에 DB를 연결하는 방법은 prisma.schema 파일에 db의 주소를 넣으면 된다. 현재 생성하는 db가 2번째 일 경우, 스키마에 새로 추가할 것이 output 항목이다. generate 명령어를 실행하게 되면 클..

[NestJS] DB 캐시 Redis 사용하기

현재 앱 운영이 순조롭게 되고 있는 것 같지만, 내부적으로 서버 응답 속도가 느리다는 문제가 꾸준히 있었다. 사실 이 문제는 AWS CloudWatch에서도 꾸준히 보고되었고 예전부터 해결해야 할 과제 중 하나였는데, 다른 작업들에 밀려 우선순위가 낮아졌다. 이제서야 이 문제를 해결하게 되었다. 현재 문제 상황 현재 운영 중인 데이터의 구조는 postgresql에서 부모 데이터에 자식 데이터가 1:n으로 물려 있는 형태이다. 여기서 부모 데이터는 15만개 정도의 row 데이터가 있고, 자식 데이터는 그것의 10배 정도의 row 데이터가 있다. 이 데이터는 사용자의 tz 기준으로 하루에 대한 데이터를 뽑아내야 한다. 여기서 문제가 되는 것은 time을 기준으로 데이터를 범위 검색을 하다 보니 하루에 대한 ..