BullMQ의 delayed job이 실제로 어떻게 동작하는지 궁금하셨나요? Polling 방식일까요? 아니면 다른 방식일까요? 이 글에서는 BullMQ의 소스코드를 직접 분석하여 delayed job이 event-driven 방식으로 동작하며, Redis의 BZPOPMIN blocking primitive를 사용한다는 것을 확인합니다. TypeScript 코드가 어떻게 컴파일되고 실행되는지, Redis와 어떻게 통신하는지까지 깊이 파고 들어봅니다.
폼 빌더 서비스에서 조건부 로직 기능을 구현하며, 조건이 연쇄적으로 적용되는 경우와 사용자가 답변을 변경할 때 발생하는 상태 관리 문제를 해결한 과정을 공유합니다.
console.log가 어떻게 동작하는지 Node.js 소스 코드 레벨에서 완전히 파헤쳐본다. JavaScript 레벨의 console.log 구현부터 포맷팅, Stream 쓰기, C++ 바인딩, libuv까지 전체 실행 흐름을 실제 소스 코드와 함께 단계별로 분석한다. 각 단계에서 어떤 코드가 실행되는지, 왜 그렇게 구현되었는지를 깊이 있게 다룬다.
console.log의 성능을 실제로 측정하고 분석한다. 다양한 시나리오에서의 성능 테스트 결과를 바탕으로 병목 지점을 파악하고, 실제 서버 환경에서의 부하 테스트를 수행한다. 그리고 프로덕션 환경에서 사용할 수 있는 최적화 방안들을 제시한다.
Spring WebFlux에서 Kotlin Coroutine으로의 마이그레이션을 통해 코드 가독성과 유지보수성을 향상시킬 수 있다. Coroutine을 사용하면 예외 처리가 직관적이고 디버깅이 쉬워지며, 코드가 간결해진다. 마이그레이션 과정에서는 Controller, Service, Repository 레이어의 변화를 포함하여, 의존성 설정과 트랜잭션 처리 방법도 개선된다. 최종적으로 Coroutine을 사용하는 것이 코드의 가독성과 개발자 경험을 크게 향상시킨다.
Google Sheet API의 rate limit으로 인한 데이터 유실 문제를 해결하기 위해 Redis 버퍼링, 배치 처리, 슬라이딩 윈도우 rate limiter를 활용한 안정적인 연동 시스템을 구축한 과정을 소개합니다.
동일한 설문 폼을 여러 회차에 걸쳐 사용할 때 URL 변경으로 인한 마케팅 데이터 분산 문제를 해결하기 위해, Redis 캐싱과 MongoDB를 활용한 고정 URL 매핑 미들웨어를 구현한 과정을 소개합니다.
AWS SES를 활용한 자동화된 이메일 발송 시스템을 구축했습니다. 대량 메일 발송, AWS SNS와 Lambda를 통한 반송/불만 처리, 블랙리스트 관리 등 실제 운영 환경에서 필요한 기능들을 구현한 과정을 공유합니다.
마이크로서비스 환경에서 비즈니스 로직을 외부 의존성으로부터 보호하기 위해 헥사고날 아키텍처를 적용했습니다. Domain, Application, Adapter 계층으로 명확히 분리하고, Port와 Adapter 패턴으로 유연한 구조를 만든 실전 사례를 공유합니다.
JPA에서 지연 로딩과 JOIN FETCH의 차이를 설명하며, 과제 취소 기능 구현을 통해 성능 비교를 진행했다. 지연 로딩은 필요할 때 데이터를 로딩하는 반면, JOIN FETCH는 연관된 엔티티를 한 번의 쿼리로 조회하여 성능을 개선한다. 실제 성능 측정 결과, JOIN FETCH를 사용했을 때 약 32-43%의 성능 향상이 있었다. 조건부로 사용되는 연관 엔티티에는 지연 로딩을, 항상 함께 사용되는 경우에는 JOIN FETCH를 사용하는 것이 바람직하다.
Native Query를 Kotlin JDSL로 마이그레이션하면서 확장 함수 패턴을 도입했습니다. 일반 join을 fetchJoin으로 변경하여 N+1 쿼리 문제를 해결하고, 데이터베이스 레벨에서 직접 집계 연산을 수행하여 쿼리 성능을 개선했습니다. Kotlin JDSL의 타입 안전성과 확장 함수 패턴을 활용하여 유지보수성을 크게 향상시켰습니다.
Multi-Repo 구조의 마이크로서비스에서 코드 중복 문제를 해결하기 위해 Common Package를 도입한 경험을 공유합니다. Mono-Repo vs Multi-Repo 고민, Common Package 설계 원칙, GitHub Packages 배포, 그리고 실제 적용 과정에서 얻은 교훈을 담았습니다.
MongoDB의 멀티 도큐먼트 트랜잭션을 Node.js에서 안전하게 구현하기 위해 AsyncLocalStorage와 Mongoose 미들웨어를 사용하는 방법을 설명하며, 자동 세션 관리, 재시도 메커니즘, 에러 처리 및 성능 최적화의 중요성을 강조합니다. 다양한 구현 방식을 비교하고, @Transactional 데코레이터를 통해 복잡한 비즈니스 로직을 안전하게 처리하는 방법을 제시합니다.
HikariCP 대시보드에서 Connection Timeout이 27회 발생하는 문제를 발견했습니다. 원인은 N+1 쿼리 문제와 작은 Connection Pool 크기였습니다. 배치 조회로 N+1 쿼리를 해결하고 Connection Pool 크기를 5에서 20으로 증가시켜 Timeout을 0으로 만들었습니다. 쿼리 수는 161개에서 3개로 98% 감소했습니다.
Kafka 메시지 처리를 위해 각 토픽마다 개별 컨슈머 그룹을 구성하고, 커스텀 데코레이터(@Consume)를 통해 컨트롤러의 특정 메서드를 Kafka Consumer로 등록하는 방법을 설명합니다. NestJS에서 데코레이터는 마킹, 조회, 등록의 3단계로 동작하며, 이를 통해 독립적인 오프셋 관리, 맞춤형 소비 로직, 리밸런싱 영향 최소화 등의 장점을 제공합니다.
여러 알림 채널(이메일, 카카오톡, Discord)을 지원하는 Notification Service에서 팩토리 패턴을 적용한 실전 사례입니다. 채널별로 다른 구현을 가진 Provider들을 Factory를 통해 동적으로 선택하여 확장하기 쉽고 유지보수하기 좋은 구조를 만든 과정을 공유합니다.
낙관적 락은 충돌이 적을 때 사용되며, 저장 시 버전을 확인하여 충돌을 감지한다. Spring Data R2DBC를 통해 자동으로 버전 관리가 이루어지고, 동시성 충돌 발생 시 재시도 메커니즘이 작동한다. 장점으로는 읽기 성능과 동시성 처리, 데드락 방지가 있으며, 단점으로는 충돌 시 재시도 필요성과 복잡성이 있다.
Pino는 프로덕션 환경에서 널리 사용되는 고성능 로깅 라이브러리다. 이 글에서는 Pino의 실제 소스 코드를 분석하고, 실제 벤치마크 결과를 통해 언제, 왜 Pino가 유리한지 파헤쳐본다. JSON 직렬화 최적화, 비동기 로깅, SonicBoom을 통한 고속 쓰기, 그리고 실제 I/O 환경에서의 성능 차이를 실제 코드와 벤치마크 결과와 함께 살펴본다.
JPA는 블로킹 I/O 모델을 사용하여 각 요청마다 별도의 스레드를 할당하고, 높은 동시성에서 많은 메모리와 스레드가 필요하다. 반면 R2DBC는 논블로킹 I/O 모델로 적은 수의 스레드로 많은 요청을 처리하며, 메모리 사용이 적고 높은 성능을 보인다. JPA는 복잡한 관계 매핑과 자동 쿼리 생성에 유리하고, R2DBC는 높은 동시성 요구사항과 리액티브 스택에 적합하다.
마이크로서비스 환경에서 여러 서비스를 거치는 결제 프로세스를 Saga 패턴으로 구현했습니다. PG 승인, Order 생성, 완료 처리의 각 단계에서 실패 시 보상 트랜잭션을 실행하여 데이터 일관성을 유지하는 실전 사례를 공유합니다.
소켓 API 문서화를 위해 AsyncAPI를 도입했습니다. nest-asyncapi의 한계를 극복하기 위해 데코레이터 기반 메타데이터 수집과 동적 AsyncAPI 스펙 생성 시스템을 직접 구현한 과정을 공유합니다.
단순 CRUD 개발은 이제 AI도 혼자 할 수 있는 시대입니다. 하지만 복잡한 비즈니스 로직이 필요한 경우, 요구사항이 명확해질 때까지 AI와 대화하여 비즈니스 요구사항을 정의한 후 개발을 시작하는 것이 중요합니다. s-class 프로젝트에 GitHub Spec-Kit 방법론을 도입하여 개발 효율과 정확도를 크게 향상시킨 실전 경험을 공유합니다.
Spring Mail과 JavaMailSender를 활용하여 SMTP 프로토콜로 이메일을 전송하는 시스템을 구축했습니다. HTML 템플릿 기반 이메일, 파라미터 치환, Gmail SMTP 설정 등을 중심으로 실제 구현 과정을 공유합니다.
DDoS 공격을 겪고 나서 알게 된 모니터링의 가치. 실제 운영 환경에서 발생한 문제 상황을 바탕으로, Spring Boot에 Prometheus + Grafana 모니터링을 구축하는 과정을 스토리텔링 형식으로 공유합니다.
DTO는 계층 간 데이터 전송을 위한 가변 객체로, API 요청/응답에 주로 사용되며 검증 로직이 최소화된다. 반면, VO는 값 자체를 표현하는 불변 객체로, 데이터의 목적과 특성이 다르다.
Spring의 @Transactional 어노테이션은 선언적 트랜잭션 관리 기능을 제공하며, Propagation 옵션을 통해 트랜잭션의 동작 방식을 설정할 수 있다. 주요 Propagation 옵션으로는 REQUIRED, REQUIRES_NEW, SUPPORTS, MANDATORY, NOT_SUPPORTED, NEVER, NESTED가 있으며, 각 옵션은 트랜잭션의 참여 및 생성 방식에 따라 다르게 작동한다. 실제 프로젝트에서의 활용 예시와 성능 최적화 팁도 포함되어 있으며, AOP 프록시 패턴을 기반으로 내부 구현 원리를 설명한다.