Backend

7 posts

좋은 이슈 리포트는 어떻게 만들어지는가New

지난 “조용히 비어버린 값 하나에서 시작한 ORM 메이저 업그레이드 검증 전략” 포스팅을 이렇게 맺었다. 같은 사례의 업스트림 이슈는 찾지 못했다. 재현 조건을 좁히고 “버그”로 볼지 “진단 메시지 개선 요청”으로 볼지 스스로 먼저 결론을 낸 뒤, 최소 재현 저장소와 함께 제보해볼 생각이다. 어제 그 이슈를 올렸다. 09-21 13:51 — 이슈 등록 (mikro-orm#8292) 09-21 14:12 — 다른 컨트리뷰터가 PR 등록 (mikro-orm#8293), 이슈로부터 21분 09-22 02:25 — 메인테이너 머지, 이슈 종료 정작 내가 쓴 코드는 한 줄도 없다. 고친 것은 다른 사람이고, 나는 재현과 이슈 본문만 썼다. 이 글은 사내에서 우회로 덮어둔 문제를 업스트림 이슈로 옮기기까지의 기록이다. 그리고 왜 이 이슈가 21분 만에 PR로 이어졌는지, 그 이유라고 생각하는 것들을 남긴다.…

Backend
5 min0 2026.09.22
좋은 이슈 리포트는 어떻게 만들어지는가

조용히 비어버린 값 하나에서 시작한 ORM 메이저 업그레이드 검증 전략New

최근 사내 패키지 업데이트와 더불어 NestJS 12+ / MikroORM v7+ 로 버전 업데이트를 진행했다. 대부분은 타입 에러를 지우고 변경된 API를 따라가는, 예상 범위 안의 작업이었다. 그 과정에서 유독 오래 붙잡고 있었던 문제가 하나 있었다. MikroORM 업데이트 중, 임베디드 값 객체(Value Object)로 매핑한 필드가 특정 조회 경로에서만 조용히 비어버리는 현상이었다. 에러도 불분명했고, 타입 에러조차 나지 않았다. 컴파일은 통과하고 런타임에서만 값이 사라지는 형태라, e2e 시나리오가 아니었다면 아마 조용히 배포되어 운영에서 마주쳤을 문제였다. 이와 더불어 자연스럽게 따라온 질문이 있었다. 다른 지점에서도 같은 성격의 이슈가 더 있지 않을까? 그래서 e2e…

Backend
6 min0 2026.09.18
조용히 비어버린 값 하나에서 시작한 ORM 메이저 업그레이드 검증 전략

53분짜리 크론 하나에서 시작한 배포 종료 설계

한동안 배포할 때 사람이 기다리는 시간이 있었다. (한.. 오전 09:00 ~ 10:00 사이쯤?) 이메일을 보내는 크론 하나가 한 회차에 53분 걸렸기 때문이다. 그게 도는 중에 배포하면 발송이 중간에서 끊길 것 같아, 끝나기를 기다렸다가 배포한 적이 있다. 서비스는 Kubernetes 위에서 돌고 ArgoCD 가 롤링 업데이트로 배포한다. 새 파드가 준비되면 구 파드는 정해진 유예 시간 안에 사라진다. 53분짜리 작업이 그 안에 끝날 수는 없으니, 기다리는 쪽을 사람이 맡고 있었던 셈이다. 처음엔 이걸 성능 문제로 봤다. 크론이 느리니 빠르게 만들면 되는 일이라고. 그런데 실행 시간을 분해해보니 대부분이 의도적으로 넣은 대기 였다. 메일 서버의 rate limit 에 걸려 발송이 거부되는 것을 막기 위해 한 건과 다음 건 사이에 간격을 두고 있었다. 성능을 위해 줄여도 되는 값이 아니라, 발송이 성립하기 위한 조건이었다. 이 크론은 v1 서비스에서 v…

Backend
6 min0 2026.09.08
53분짜리 크론 하나에서 시작한 배포 종료 설계

복합 인덱스는 언제 필요할까?

복합 인덱스는 여러 컬럼을 묶어 추가하면 조회 성능이 좋아지는 기능이라고 생각하기 쉽다. 하지만 실제로는 컬럼의 개수보다 애플리케이션이 데이터를 어떤 조건으로 찾고, 어떤 순서로 정렬하며, 어떤 단위로 나누어 반환하는지가 더 중요하다. 예를 들어 다음과 같은 조회가 있다고 가정해보자. 특정 상태()의 데이터만 조회한다. 기본 키()를 기준으로 최신순 정렬한다. 페이지 단위로 결과를 반환한다. 데이터가 적을 때는 단일 인덱스만으로도 큰 문제가 발생하지 않을 수 있다. 하지만 데이터가 쌓이고 호출량이 증가하면, 데이터베이스는 인덱스를 사용하고도 최종 결과보다 훨씬 많은 데이터를 읽거나 별도의 정렬 작업을 수행하게 된다. 그렇다면 복합 인덱스는 어떤 상황에서 필요하고, 어떤 기준으로 설계해야 할까?…

Backend
3 min0 2026.08.09
복합 인덱스는 언제 필요할까?

이벤트 소싱을 적용하기 전에 반드시 고민해봤어야 할 것들

우리 서비스의 주문 도메인에는 조금 특이한 특징이 하나 있다. 일반적인 상품 주문과 달리 SNS 마케팅 주문은 하나의 주문이 여러 개의 실행 단위로 쪼개진다. 예를 들어 “좋아요” 주문이 들어오면 시스템 내부에서는 다음과 같은 일들이 순차적으로 발생한다. 주문이 생성된다 결제 및 포인트 차감이 이루어진다 주문 상태가 “진행중”으로 변경된다 좋아요 작업이 여러 번에 나뉘어 실행된다 각 실행 결과가 개별 로그로 기록된다 모든 작업이 끝나면 주문 상태가 “완료”로 변경된다 이 과정에서 우리는 주문 하나를 처리하기 위해 수백, 많게는 수천 건의 실행 로그를 쌓고 있었다. 또한, 이 로그들은 단순한 디버깅 용도가 아니었다. 운영에서는 이 로그를 기준으로 주문 진행 상황을 판단했고 CS…

Backend
4 min0 2026.01.06
이벤트 소싱을 적용하기 전에 반드시 고민해봤어야 할 것들

NestJS Kafka emit(), 어디까지 성공했다고 말할 수 있을까?

현재 재직 중인 회사에서는 SNS 마케팅을 하나의 상품으로 만들어 판매하는 서비스를 운영하고 있다. 기업이나 개인 사용자는 인스타그램, 블로그, 유튜브 등 다양한 SNS 채널을 대상으로 좋아요, 팔로워, 조회수와 같은 마케팅 상품을 주문할 수 있고 서비스는 이 주문을 실제 SNS 마케팅 작업으로 연결해주는 역할을 한다. 이 과정은 단순히 “주문을 하나 처리하는 것”에서 끝나지 않는다. 주문 생성 결제 및 포인트 차감 주문 상태 관리 SNS 마케팅 작업 집행 경우에 따라 외부 마케팅 솔루션 업체와의 연동 까지 이어지는 여러 단계의 처리 흐름이 존재한다. 특히, SNS 마케팅 작업은 자사에서 운영하는 서버가 직접 처리하기도 하고, 상황에 따라서는 외부 SNS 마케팅 플랫폼(공급자) 에 주문을 전달해 처리를 위임하기도 한다. 이처럼 하나의 주문이 여러 서버, 때로는 외부 시스템까지 거쳐 처리되는 구조이기 때문에 서비스 전반은 자연스럽게 마이크로서비스 아키텍처(MSA…

Backend
5 min0 2025.12.20
NestJS Kafka emit(), 어디까지 성공했다고 말할 수 있을까?

MikroORM v6.6 – 무엇이 달라졌나?

MikroORM 6.6.0은 눈에 띄는 대규모 기능 추가는 아니지만, “엔티티의 캡슐화와 일관성을 지켜주는 기능”이 정식 지원되었다는 점에서 상당히 의미 있는 릴리스라 생각한다. 이번 포스팅에서는 우리 팀이 채택한 컨벤션인 private 필드 + get/set accessor를 이용한 프로퍼티 관리 관점으로 이번 릴리즈 내용을 정리해보려한다. 공식 릴리스 노트 https://github.com/mikro-orm/mikro-orm/releases/tag/v6.6.0 버그 픽스가 아닌 피쳐 목록만 확인해보면 아래와 같다. core: allow control over relation filters in entity definition 기존 MikroORM에는 글로벌/엔티티 단위 필터(SoftDeleteFilter 등)가 있었지만, 특정 relation…

Backend
3 min0 2025.12.01
MikroORM v6.6 – 무엇이 달라졌나?