Server 121

Sequelize - 커스텀 메서드 (Custom method) 구현

ORM 패턴? ORM은 두 가지 패턴이 있습니다. Active Record (pattern)과 Data Mapper (Repository) pattern입니다. Active Record pattern은 엔터티가 CRUD 기능을 하는 메서드들을 프로퍼티로 가지고 있어서 Model이 자기가 가지고 있는 메서드(쿼리)를 실행하는 형태입니다. 반면, Data Mapper pattern(with Repository)은 모델과 메서드(쿼리)를 분리합니다. Repository를 따로 두고, Repository에서만 메서드를 구현합니다. Sequelize는 Active Record pattern입니다. 즉, 모델이 class method를 가지고 있어야 합니다. 그래서 우리는 User.findAll(), User.up..

Server/Node.js 2022.01.08

Sequelize - 일괄 등록, 일괄 수정 하기 (bulk create, bulk update)

일괄 등록 (bulkCreate) const result = await User.bulkCreate(usersDTO) 일괄 등록의 경우 Sequelize는 bulkCreate 메서드를 지원하고 있습니다. bulkCreate()를 이용해서 배열을 한 번에 insert 칠 수 있습니다. 일괄 수정 (bulkUpdate) Sequelize에서 일괄 수정을 하는 방법은 3가지가 있습니다. 한 가지씩 소개해드리겠습니다 ! 1. update const result = await User.update({ name: updateUsersDto.name }, { where: { id: { [Op.in]: updateUsersDto.users } } }); // UserDTO.ts export interface Updat..

Server/Node.js 2022.01.05

NodeJS - 전역 예외 핸들러 구현 (Custom global exception handler)

전역 예외 핸들러 저의 경우 Sequelize + express + nodejs의 프로젝트를 하고 있었는데, Sequelize가 500번대 예외를 뱉는 경우가 많았습니다. 해당 부분은 App단에서 최대한 검증을 해서 요청을 보내면 좋겠지만, 동시성 문제로 어쩔 수 없이 예외가 발생하기도 합니다. 요즘은 500번대 에러는 핸들링을 하는 것을 원칙으로 하는 기업이 많은 걸로 알고 있습니다. 특히 네이버 특정 계열사 Open API Reference에 보면 500번대 에러가 나오면 제보해달라는 내용이 있기도 하기도 합니다. 따라서, 해당 예외를 핸들링하고 싶었는데, 각 메서드에 여러개의 예외처리를 전부 공통적으로 붙이면 유지보수성이 떨어지니까, 전역 범위로 적용해야 했습니다. 스프링은 @ControllerAd..

Server/Node.js 2021.12.29

NodeJS - API Response를 snake case로 변환하기(DTO, Entity 필드는 camel case)

API Request, Response body를 snake_case로 변환 ? 데이터베이스의 테이블 스키마를 작성할 때는 주로 snake_case를 사용합니다. 또한, 최근 들어 API의 Request, Response body 컨벤션으로 snake_case를 사용하면서 통신하는 것이 많이 선호되고 있는 것 같습니다. 스프링은 Jackson 라이브러리를 사용해서 이를 쉽게 처리할 수 있는데, 아쉽게도 nodejs, express에서는 코드 한 줄로 이를 처리할 수 있는 방법이 없습니다. 방법은 2가지가 있습니다. 포스팅에서는 2번째 방법을 다룹니다. 1. DTO 및 엔터티를 전부 snake_case로 작성하는 방법 2. middleware를 사용해서 snake_case로 변환해주는 방법 (DTO 및 엔..

Server/Node.js 2021.12.27

NodsJS - BullMQ 사용 (대기열, 동시성 제어 등)

BullMQ BullMQ는 Redis를 기반으로 하고, kafka나 RabbitMQ보다 훨씬 가볍고 편리한 Message queue입니다. 현재 기준 Github Star 11.8K 정도 되고, 거의 매일같이 커밋이 올라오는 뜨거운 라이브러리입니다. 제가 BullMQ를 도입하게 된 이유는 잔량을 파악해서 순차적으로 작업을 실행해야 하는 일이 있었는데, 테이블 구조가 DB 락(Select... for update)을 걸 수가 없는 상황이었습니다. 그래서, 대기열을 따라서 순차적인 처리를 위해 도입했습니다. BullMQ를 도입하기 전에 kafka 도입을 검토했었는데, 앱 서버만해도 2개가 추가되고 (Producer, Consumer)랑 또 추가로 Zookeeper, kafka 등 띄울게 너무 많고 무거웠어요..

Server/Node.js 2021.12.25

NodeJS - 모델매퍼(ModelMapper) 사용 [Class transformer]

모델 매퍼(ModelMapper) 스프링의 경우 DTO와 엔터티간의 변환을 할 때 ModelMapper나 Mapstruct라는 라이브러리를 많이 사용합니다. 그러면, 객체가 가질 수 있는 프로퍼티는 옮겨지게 되고, 아닌 프로퍼티는 버려지게 되죠. JS는 그러한 역할이 없어서 상당히 불편했습니다. Interface를 고집한다는 점과 Class instance와 Literal object 간 변환이 어렵다는 점이 이유입니다. 그나마 쓸만한 라이브러리가 AutoMapper인데 사용하기가 어렵고 유지보수가 중지되었죠. 그래서 최근에 나와서 핫한 라이브러리 중 하나가 class-transformer입니다. 이 라이브러리는 ModelMapper 역할을 훌륭하게 수행할 수 있고, 상당히 강력하고 간단합니다. 최근 c..

Server/Node.js 2021.12.24

소규모 서비스와 대규모 서비스의 차이 + 스케일 업(scale-up), 스케일 아웃(scale-out)

스케일 업(scale-up), 스케일 아웃(scale-out) ? 대량의 서비스를 서버 1대로 처리할 수는 없게 됩니다. 더 많은 트래픽을 처리하기 위해서 스케일 업(서버의 성능을 업그레이드하는 것)과 스케일 아웃(서버의 대수를 늘려서 연결하는 것)이 있는데, 일반적으로는 스케일 아웃을 하게 됩니다. 왜냐하면 하드웨어 성능과 가격이 비례하지 않기 때문이죠. 대량생산되는 부품이 훨씬 싸기 때문이죠. 하지만, 스케일 아웃도 단점이 있습니다. 서버의 대수를 늘릴수록 관리가 힘들어지죠. 로드 밸런서로 연결해야 하기 때문에 엔드 포인트가 더 생기고 작업이 복잡해지는 것이죠. DB 동기화도 해야하구요. 동시성 제어도 힘듭니다. 이런 점 때문에 요즘 엔지니어들의 몸값이 비싸지는 것 같아요 ! 데이터 처리 데이터는 디..

Server 2021.12.22

NodeJS - JSON null필드를 Response에서 생략하는 방법!

const app = express(); // JSON null 필드 생략 app.set('json replacer', (k, v) => (v === null ? undefined : v)); 위와 같은 방법으로, 익스프레스에 json replacer를 정의해서 필요한 경우 null필드를 response에서 제외할 수 있습니다. ORM으로 sequelize나 type orm을 사용하는 경우에는 exclude, attributes 등을 사용해서 response를 원하는 범위로 조작할 수도 있습니다!

Server/Node.js 2021.12.21

Sequelize - 자식 테이블까지 한 번에 Insert 치는 방법 (Join Insert) + 상황에 따라 다른 쿼리를 날리는 방법

자식 테이블까지 Insert 하기 const result: Product = await Product.create(createProductDto, { include: includeStatement }); // ProducdtDto.ts export interface CreateProductDto { name: string; description?: string; count?: number; productImages?: ProductImageDto[]; } typescript 예시입니다. Sequelize의 include를 사용하면 관계를 맺고있는 자식 테이블까지 함께 insert를 칠 수 있습니다. hasOne이든 hasMany든 Sequelize가 그에 맞게 insert를 해줍니다 ! 상황에 다른 쿼리..

Server/Node.js 2021.12.19

Spring - 프로필 (Profile)

프로필이란 ? 유지보수 작업 중에는 서비스로 운영중인 DB를 사용할 수 없습니다. 그래서 로컬 개발 환경과 실제 서비스 환경은 동일하지 않는 경우가 많습니다. 개발할 때는 로컬 개발 환경에 맞게 데이터베이스 서버의 IP, 계정, 디렉터리 경로, URL등을 수정한 후에, 개발을 끝내고, 다시 실제 서비스 환경으로 변경한 후에 배포해야합니다. 이 때, 실수를 범할 수도 있고 불편하기 때문에 스프링이 제공하는 기능이 프로필(Profile)입니다. 프로필을 이용하면 개발용 프로필, 서비스용 프로필을 하나씩 만들고 원하는 프로필을 이용해서 스프링 컨테이너를 초기화할 수 있습니다. 즉, 프로필을 선택함에 따라 그에 걸맞는 설정을 적용할 수 있습니다. C언어의 #define, #if를 사용해서 국가나 환경에 따라 코..

Server/Spring 2021.01.29