전체 글 364

Sequelize - bigint를 사용하는 방법? (+ underscored)

DB에 bigint로 저장된 컬럼을 API에서 꺼내서 그대로 사용하면 바이트 부족으로 인해서 데이터가 손실됩니다..!! Sequelize에서는 아래와 같이 dialectOptions의 supportBigNumbers를 정의해서, 손실을 방지할 수 있고, bigNumberStrings를 정의해서 string으로 받을 수도 있습니다. import { Sequelize } from "sequelize"; const shopDB = new Sequelize( "shopDB", "root", "root", { host: "localhost", dialect: "mysql", pool: { max: 10, min: 0, acquire: 5000, idle: 10000, }, timezone: "+09:00", di..

Server/Node.js 2022.01.11

Clean Code - 부울(Boolean) 매개변수는 절대 피하라!

부울 매개변수를 사용하는 경우 클린 코드를 읽다가 부울 인수를 절대로 사용하지 말라는 강력한 주장을 보게 되었습니다. 부끄럽게도 전날 프로젝트를 개발하면서 함수 인수로 boolean을 사용하게 수정했는데 말이죠..ㅎㅎ.. 함수의 인수로 부울(Boolean)을 사용하게 되면 해당 인수가 참인지 거짓인지에 따라서 다른 동작을 한다는 말이 되는데, 그러면 가독성도 나쁘고, 책임도 모호해집니다! 그래서 두개의 함수로 분리하는 것이 좋은 것 같습니다. 적용 방안 제가 작성한 기존의 코드는 아래와 같습니다. (설명을 위해 조금 수정했습니다.) 관리자 API Controller findAllWithNotActivated = async ( req: Request, res: Response ) => { const res..

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

Effective Java - 생성자 대신 정적 팩토리 메서드를 사용하라!

정적 팩토리 메서드 저는 클래스를 작성할 때 객체를 인스턴스화 하는 코드를 작성할 때는 무조건 생성자를 사용했었어요! Effective 자바의 내용 중에 생성자 대신 정적 팩토리 메서드를 사용하는 것을 검토해봐야 한다는 논의가 있었는데 좋은 내용 같아서 가지고 왔어요! 팩토리 메서드란 객체를 생성하는 메서드를 말합니다! 정적 팩토리 메서드는 객체를 생성하지 않고, 정적 메서드를 활용해서 객체를 만드는 방법이겠네요 ! 정적 팩토리 메서드를 사용하는 이유 1. 이름을 가질 수 있다. 생성자는 클래스명을 이름으로 하고, 클래스 하나당 생성자 1개 밖에 둘 수 없기에 어떤 객체를 생성하는 지 직관적이지 않습니다. public class Car{ String brand; String color; public Ca..

Language/Java 2022.01.02

MySQL - 인덱스 타는지 체크 방법 (+개선 방법, 인덱스를 타게 하는 방법)

MySQL 인덱스 타는지 확인하는 방법 mysql에서는 인덱스를 여러 개 걸었을 때 하나밖에 타지 않습니다. 그래서, 인덱스를 적절하게 걸어주지 않으면 데이터가 커졌을 때 트래픽이 튀거나 슬로우쿼리 등 문제가 될 확률이 거의 99%입니다. 인덱스를 타는 지 확인하는 방법은 MySQL의 Explain을 사용하는 것입니다. explain은 쿼리의 실행 계획을 반환해주므로 쿼리 튜닝, 성능 분석, 전략 수집 등의 기초가 됩니다 ! 사용 방법은 SELECT문 앞에 explain을 붙여주면 됩니다. explain select * from booking where resource_id=1 and start_time > NOW() order by rand(); 실행계획 분석 직접 쿼리문을 실행해보니 아래와 같은 결과..

Database/SQL 2022.01.01

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

대규모 서비스 - I/O 부하 (느려졌다고 무조건 서버 증설? No!)

부하 종류 일반적으로 부하는 크게 두 가지로 분류됩니다. CPU 부하 I/O 부하 CPU 부하는 무언가를 계산할 때 일어나는 부하를 말합니다. CPU 부하의 규모조정은 간단합니다. 같은 구성의 서버를 늘리고, 로드밸런서로 분산을 시키면 됩니다. 반면, I/O 부하의 규모조정은 어렵습니다. I/O 부하란, 입력, 출력에 생기는 부하를 말합니다. 예를 들어, DB에 접근할 때 DB의 레코드 데이터를 출력하거나, DB에 데이터를 입력할 때 생기는 부하입니다. (I/O 부하를 해결하기 위해서 각 OS마다 캐시를 이용해서 메모리를 추상화 합니다.) 부하 파악 sar 명령어(sar command)로 CPU 사용률과 I/O 대기율을 확인할 수 있습니다. %user는 사용자 모드에서의 CPU 사용률이고, %system..