<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>seeun&apos;s tech blog</title><description>Backend Engineer 김세은의 기술 블로그. Kotlin, Spring Boot, NestJS, MongoDB, 분산 시스템, 아키텍처 경험을 기록합니다.</description><link>https://blog.seeun.site/</link><language>ko-KR</language><item><title>7,600줄 Lambda 오케스트레이터 이전기: 복잡함의 정체는 15분 타임아웃이었다</title><link>https://blog.seeun.site/posts/lambda-to-temporal-llm-pipeline/</link><guid isPermaLink="true">https://blog.seeun.site/posts/lambda-to-temporal-llm-pipeline/</guid><description>LLM 리포트 생성 파이프라인의 완료 이벤트가 조용히 유실되는 버그를 추적하다가, 7,600줄짜리 오케스트레이터의 복잡함 대부분이 Lambda 15분 타임아웃을 우회하기 위한 코드였음을 알게 됐습니다. 버그를 고치는 대신 실행 기반을 Temporal로 옮기고, 91곳의 정규식 사후 정제를 Spring AI structured output 계약으로 대체한 과정입니다.</description><pubDate>Mon, 06 Jul 2026 00:00:00 GMT</pubDate><category>Temporal</category><category>AWS Lambda</category><category>Spring AI</category><category>Structured Output</category><category>LLM</category><category>Kotlin</category><category>Workflow Engine</category><category>마이그레이션</category></item><item><title>뭘 만들지도 모른 채 시작해서, 돈 받는 프로덕트가 되기까지 14개월</title><link>https://blog.seeun.site/posts/one-person-product-14-months/</link><guid isPermaLink="true">https://blog.seeun.site/posts/one-person-product-14-months/</guid><description>2025년 5월, 뭘 만들지도 정하지 못한 채 시작한 프로젝트가 14개월 뒤 결제와 교사 매칭, AI 리포트 생성이 돌아가는 유료 프로덕트가 됐습니다. 그 사이에 아키텍처를 두 번 접었고, 상품 하나를 만들었다 제거했고, 장애를 겪었습니다. 만든 것보다 접은 것 중심으로 정리한 회고입니다.</description><pubDate>Mon, 06 Jul 2026 00:00:00 GMT</pubDate><category>회고</category><category>프로덕트</category><category>1인 개발</category><category>Kotlin</category><category>Spring Boot</category><category>MSA</category><category>모듈러 모놀리스</category><category>Temporal</category></item><item><title>Spring AI 내부에서 본 Anthropic 구조화 출력·프롬프트 캐싱, 그리고 비용을 거두는 Advisor</title><link>https://blog.seeun.site/posts/spring-ai-anthropic-prompt-caching/</link><guid isPermaLink="true">https://blog.seeun.site/posts/spring-ai-anthropic-prompt-caching/</guid><description>Temporal 워크플로에 Spring AI를 붙이면서 내부를 들여다봤습니다. useProviderStructuredOutput()이 Anthropic 네이티브 outputConfig로 나가는 경로, 프롬프트 캐싱을 켰지만 read가 0이라 손해였던 이유, 그리고 .entity()가 가린 토큰·비용을 CallAdvisor로 거둔 방법입니다. 2부작 중 2편입니다.</description><pubDate>Fri, 26 Jun 2026 00:00:00 GMT</pubDate><category>Spring AI</category><category>Anthropic</category><category>Kotlin</category><category>Spring Boot</category><category>Prompt Caching</category><category>Structured Output</category><category>LLM</category><category>Cost</category></item><item><title>진단 리포트 생성을 SQS·Lambda에서 Temporal 워크플로로 옮긴 이유</title><link>https://blog.seeun.site/posts/sqs-lambda-to-temporal/</link><guid isPermaLink="true">https://blog.seeun.site/posts/sqs-lambda-to-temporal/</guid><description>진단 리포트 생성을 SQS+Lambda 이벤트 파이프라인으로 돌렸습니다. 동시성 한도, 큐 백로그 지연, 흩어진 오케스트레이션 세 가지가 걸렸고 이걸 Temporal 워크플로로 옮기면서 생성 로직을 한 메서드 안으로 모았습니다. 2부작 중 1편입니다.</description><pubDate>Fri, 26 Jun 2026 00:00:00 GMT</pubDate><category>Temporal</category><category>Spring AI</category><category>Kotlin</category><category>Spring Boot</category><category>SQS</category><category>Lambda</category><category>Workflow</category><category>Orchestration</category></item><item><title>Querydsl/JPA에서 Exposed DSL로 옮기며 kapt를 걷어낸 이유</title><link>https://blog.seeun.site/posts/querydsl-jpa-to-exposed-kapt-removal/</link><guid isPermaLink="true">https://blog.seeun.site/posts/querydsl-jpa-to-exposed-kapt-removal/</guid><description>Querydsl/JPA 기반 persistence를 Exposed DSL로 옮긴 작업은 단순한 ORM 교체가 아니었습니다. Kotlin 빌드에서 kapt와 생성 코드를 걷어내고, persistence 경계를 더 명시적으로 만든 전환이었습니다.</description><pubDate>Sun, 21 Jun 2026 00:00:00 GMT</pubDate><category>Kotlin</category><category>Spring Boot</category><category>Exposed</category><category>Querydsl</category><category>JPA</category><category>kapt</category><category>Gradle</category><category>Persistence</category></item><item><title>ArchUnit으로 반복되는 경계 리뷰 줄이기</title><link>https://blog.seeun.site/posts/archunit-boundary-tests/</link><guid isPermaLink="true">https://blog.seeun.site/posts/archunit-boundary-tests/</guid><description>Architecture test는 설계를 대신해주는 도구가 아닙니다. 사람이 매번 확인하던 경계 위반을 빌드에서 먼저 드러내는 안전장치에 가깝습니다.</description><pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate><category>Kotlin</category><category>Spring Boot</category><category>ArchUnit</category><category>Architecture Test</category><category>DDD</category></item><item><title>Bounded Context 기준으로 Kotlin/Spring 도메인 모듈을 나눈 이유</title><link>https://blog.seeun.site/posts/bounded-context-domain-modules/</link><guid isPermaLink="true">https://blog.seeun.site/posts/bounded-context-domain-modules/</guid><description>큰 도메인 모듈 하나로는 경계를 지키기 어렵습니다. s-class-backend에서 bounded context 기준으로 domain module을 나누며 배운 점을 정리합니다.</description><pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate><category>Kotlin</category><category>Spring Boot</category><category>DDD</category><category>Bounded Context</category><category>Gradle</category><category>Architecture Test</category></item><item><title>Spring Boot 커스텀 어노테이션으로 레이어 아키텍처 명확하게 표현하기</title><link>https://blog.seeun.site/posts/spring-custom-annotation-layer-architecture/</link><guid isPermaLink="true">https://blog.seeun.site/posts/spring-custom-annotation-layer-architecture/</guid><description>Spring Boot의 메타 어노테이션 원리를 활용해 @UseCase, @DomainService, @Adaptor 커스텀 어노테이션을 만들고, 레이어 아키텍처의 역할을 코드에 명시적으로 표현하는 방법을 도입 전/후 비교와 함께 정리합니다.</description><pubDate>Sat, 21 Mar 2026 00:00:00 GMT</pubDate><category>Spring Boot</category><category>커스텀 어노테이션</category><category>메타 어노테이션</category><category>레이어드 아키텍처</category><category>Kotlin</category><category>@Component</category><category>클린 아키텍처</category></item><item><title>대기열 없이 정확한 시간에 알림 보내기: Spring Quartz TaskDeadlineJob 적용기</title><link>https://blog.seeun.site/posts/quartz-scheduled-notification-system/</link><guid isPermaLink="true">https://blog.seeun.site/posts/quartz-scheduled-notification-system/</guid><description>Spring Quartz(JDBC JobStore, Cluster)로 supporters-service 예약 알림을 구현한 실전기. TaskDeadlineJob 중심으로 등록/취소/실행 흐름과 Pub/Sub 연동 패턴을 코드로 정리합니다.</description><pubDate>Mon, 09 Mar 2026 00:00:00 GMT</pubDate><category>Quartz</category><category>Spring Quartz</category><category>예약 알림</category><category>TaskDeadlineJob</category><category>JDBC JobStore</category><category>Pub/Sub</category><category>Kotlin</category><category>Supporters Service</category></item><item><title>Spring Quartz 내부 구현으로 이해하는 동적 스케줄링</title><link>https://blog.seeun.site/posts/spring-quartz-dynamic-scheduling-internals/</link><guid isPermaLink="true">https://blog.seeun.site/posts/spring-quartz-dynamic-scheduling-internals/</guid><description>Spring Quartz 내부 구현을 따라가며 동적 스케줄링이 가능한 이유를 분석합니다. scheduleJob/rescheduleJob/deleteJob 흐름, QRTZ_* 테이블, Cluster 락, misfire 처리까지 실무 관점으로 정리합니다.</description><pubDate>Mon, 09 Mar 2026 00:00:00 GMT</pubDate><category>Spring Quartz</category><category>동적 스케줄링</category><category>Quartz Internals</category><category>JDBC JobStore</category><category>Cluster</category><category>Misfire</category><category>Kotlin</category><category>Spring Boot</category></item><item><title>BULLMQ Delayed Job 톺아보기</title><link>https://blog.seeun.site/posts/bullmq-delayed-job-internal/</link><guid isPermaLink="true">https://blog.seeun.site/posts/bullmq-delayed-job-internal/</guid><description>BullMQ의 delayed job이 실제로 어떻게 동작하는지 궁금하셨나요? Polling 방식일까요? 아니면 다른 방식일까요? 이 글에서는 BullMQ의 소스코드를 직접 분석하여 delayed job이 event-driven 방식으로 동작하며, Redis의 BZPOPMIN blocking primitive를 사용한다는 것을 확인합니다. TypeScript 코드가 어떻게 컴파일되고 실행되는지, Redis와 어떻게 통신하는지까지 깊이 파고 들어봅니다.</description><pubDate>Fri, 06 Feb 2026 00:00:00 GMT</pubDate><category>BullMQ</category><category>Delayed Job</category><category>Redis</category><category>Event-driven</category><category>BZPOPMIN</category><category>Lua Script</category><category>TypeScript</category><category>Node.js</category><category>Job Queue</category></item><item><title>Kotlin JDSL 마이그레이션과 Fetch Join을 통한 N+1 문제 해결</title><link>https://blog.seeun.site/posts/kotlin-jdsl-migration-fetch-join/</link><guid isPermaLink="true">https://blog.seeun.site/posts/kotlin-jdsl-migration-fetch-join/</guid><description>Native Query를 Kotlin JDSL로 마이그레이션하면서 확장 함수 패턴을 도입했습니다. 일반 join을 fetchJoin으로 변경하여 N+1 쿼리 문제를 해결하고, 데이터베이스 레벨에서 직접 집계 연산을 수행하여 쿼리 성능을 개선했습니다. Kotlin JDSL의 타입 안전성과 확장 함수 패턴을 활용하여 유지보수성을 크게 향상시켰습니다.</description><pubDate>Mon, 02 Feb 2026 00:00:00 GMT</pubDate><category>Kotlin JDSL</category><category>JPA</category><category>N+1 쿼리</category><category>Fetch Join</category><category>성능 최적화</category><category>Spring Boot</category><category>Kotlin</category><category>확장 함수</category></item><item><title>N+1 쿼리 최적화와 Connection Pool 튜닝으로 해결한 Connection Timeout 문제</title><link>https://blog.seeun.site/posts/n1-query-optimization-connection-pool/</link><guid isPermaLink="true">https://blog.seeun.site/posts/n1-query-optimization-connection-pool/</guid><description>HikariCP 대시보드에서 Connection Timeout이 27회 발생하는 문제를 발견했습니다. 원인은 N+1 쿼리 문제와 작은 Connection Pool 크기였습니다. 배치 조회로 N+1 쿼리를 해결하고 Connection Pool 크기를 5에서 20으로 증가시켜 Timeout을 0으로 만들었습니다. 쿼리 수는 161개에서 3개로 98% 감소했습니다.</description><pubDate>Sun, 01 Feb 2026 00:00:00 GMT</pubDate><category>N+1 쿼리</category><category>Connection Pool</category><category>HikariCP</category><category>성능 최적화</category><category>Spring Boot</category><category>Kotlin</category><category>JPA</category><category>배치 조회</category></item><item><title>DDoS 공격을 겪고 나서 알게 된 모니터링의 가치</title><link>https://blog.seeun.site/posts/spring-prometheus/</link><guid isPermaLink="true">https://blog.seeun.site/posts/spring-prometheus/</guid><description>DDoS 공격을 겪고 나서 알게 된 모니터링의 가치. 실제 운영 환경에서 발생한 문제 상황을 바탕으로, Spring Boot에 Prometheus + Grafana 모니터링을 구축하는 과정을 스토리텔링 형식으로 공유합니다.</description><pubDate>Sun, 01 Feb 2026 00:00:00 GMT</pubDate><category>Prometheus</category><category>Spring Boot</category><category>모니터링</category><category>Observability</category><category>Micrometer</category><category>Grafana</category><category>Kotlin</category></item><item><title>마이크로서비스에서 Common Package를 도입하게 된 계기와 경험</title><link>https://blog.seeun.site/posts/microservices-common-package/</link><guid isPermaLink="true">https://blog.seeun.site/posts/microservices-common-package/</guid><description>Multi-Repo 구조의 마이크로서비스에서 코드 중복 문제를 해결하기 위해 Common Package를 도입한 경험을 공유합니다. Mono-Repo vs Multi-Repo 고민, Common Package 설계 원칙, GitHub Packages 배포, 그리고 실제 적용 과정에서 얻은 교훈을 담았습니다.</description><pubDate>Fri, 30 Jan 2026 00:00:00 GMT</pubDate><category>마이크로서비스</category><category>Common Package</category><category>Multi-Repo</category><category>GitHub Packages</category><category>Kotlin</category><category>Spring Boot</category><category>코드 중복</category><category>공통 라이브러리</category></item><item><title>console.log는 어떻게 동작할까?</title><link>https://blog.seeun.site/posts/console-log-internal-mechanism/</link><guid isPermaLink="true">https://blog.seeun.site/posts/console-log-internal-mechanism/</guid><description>console.log가 어떻게 동작하는지 Node.js 소스 코드 레벨에서 완전히 파헤쳐본다. JavaScript 레벨의 console.log 구현부터 포맷팅, Stream 쓰기, C++ 바인딩, libuv까지 전체 실행 흐름을 실제 소스 코드와 함께 단계별로 분석한다. 각 단계에서 어떤 코드가 실행되는지, 왜 그렇게 구현되었는지를 깊이 있게 다룬다.</description><pubDate>Wed, 28 Jan 2026 00:00:00 GMT</pubDate><category>nodejs</category><category>console.log</category><category>internal</category><category>source-code</category><category>logging-series</category></item><item><title>console.log 성능 측정과 최적화: 실제 서버에서의 부하 분석</title><link>https://blog.seeun.site/posts/console-log-performance-optimization/</link><guid isPermaLink="true">https://blog.seeun.site/posts/console-log-performance-optimization/</guid><description>console.log의 성능을 실제로 측정하고 분석한다. 다양한 시나리오에서의 성능 테스트 결과를 바탕으로 병목 지점을 파악하고, 실제 서버 환경에서의 부하 테스트를 수행한다. 그리고 프로덕션 환경에서 사용할 수 있는 최적화 방안들을 제시한다.</description><pubDate>Wed, 28 Jan 2026 00:00:00 GMT</pubDate><category>nodejs</category><category>console.log</category><category>performance</category><category>optimization</category><category>logging-series</category></item><item><title>Pino는 어떻게 구현되어 있을까? 내부 코드와 실제 벤치마크 분석</title><link>https://blog.seeun.site/posts/pino-internal-analysis/</link><guid isPermaLink="true">https://blog.seeun.site/posts/pino-internal-analysis/</guid><description>Pino는 프로덕션 환경에서 널리 사용되는 고성능 로깅 라이브러리다. 이 글에서는 Pino의 실제 소스 코드를 분석하고, 실제 벤치마크 결과를 통해 언제, 왜 Pino가 유리한지 파헤쳐본다. JSON 직렬화 최적화, 비동기 로깅, SonicBoom을 통한 고속 쓰기, 그리고 실제 I/O 환경에서의 성능 차이를 실제 코드와 벤치마크 결과와 함께 살펴본다.</description><pubDate>Wed, 28 Jan 2026 00:00:00 GMT</pubDate><category>nodejs</category><category>pino</category><category>logging</category><category>performance</category><category>internal</category><category>logging-series</category></item><item><title>헥사고날 아키텍처로 비즈니스 로직 보호하기: s-class 프로젝트 실전 사례</title><link>https://blog.seeun.site/posts/hexagonal-architecture/</link><guid isPermaLink="true">https://blog.seeun.site/posts/hexagonal-architecture/</guid><description>마이크로서비스 환경에서 비즈니스 로직을 외부 의존성으로부터 보호하기 위해 헥사고날 아키텍처를 적용했습니다. Domain, Application, Adapter 계층으로 명확히 분리하고, Port와 Adapter 패턴으로 유연한 구조를 만든 실전 사례를 공유합니다.</description><pubDate>Mon, 26 Jan 2026 00:00:00 GMT</pubDate><category>헥사고날 아키텍처</category><category>hexagonal architecture</category><category>포트 앤 어댑터</category><category>클린 아키텍처</category><category>Kotlin</category><category>Spring Boot</category></item><item><title>팩토리 패턴으로 알림 채널 확장하기: Notification Service 실전 사례</title><link>https://blog.seeun.site/posts/notification-channel-factory-pattern/</link><guid isPermaLink="true">https://blog.seeun.site/posts/notification-channel-factory-pattern/</guid><description>여러 알림 채널(이메일, 카카오톡, Discord)을 지원하는 Notification Service에서 팩토리 패턴을 적용한 실전 사례입니다. 채널별로 다른 구현을 가진 Provider들을 Factory를 통해 동적으로 선택하여 확장하기 쉽고 유지보수하기 좋은 구조를 만든 과정을 공유합니다.</description><pubDate>Mon, 26 Jan 2026 00:00:00 GMT</pubDate><category>팩토리 패턴</category><category>factory pattern</category><category>전략 패턴</category><category>strategy pattern</category><category>알림 시스템</category><category>Kotlin</category><category>Spring Boot</category></item><item><title>Saga 패턴으로 분산 트랜잭션 처리하기: Payment Service 실전 사례</title><link>https://blog.seeun.site/posts/saga-pattern-distributed-transaction/</link><guid isPermaLink="true">https://blog.seeun.site/posts/saga-pattern-distributed-transaction/</guid><description>마이크로서비스 환경에서 여러 서비스를 거치는 결제 프로세스를 Saga 패턴으로 구현했습니다. PG 승인, Order 생성, 완료 처리의 각 단계에서 실패 시 보상 트랜잭션을 실행하여 데이터 일관성을 유지하는 실전 사례를 공유합니다.</description><pubDate>Mon, 26 Jan 2026 00:00:00 GMT</pubDate><category>saga pattern</category><category>분산 트랜잭션</category><category>마이크로서비스</category><category>보상 트랜잭션</category><category>Kotlin</category><category>Spring Boot</category></item><item><title>GCP Pub/Sub으로 구축하는 마이크로서비스 비동기 알림 시스템</title><link>https://blog.seeun.site/posts/gcp-pubsub-notification-system/</link><guid isPermaLink="true">https://blog.seeun.site/posts/gcp-pubsub-notification-system/</guid><description>마이크로서비스 아키텍처에서 동기식 HTTP 호출의 한계를 해결하기 위해 GCP Pub/Sub을 도입하여 비동기 알림 시스템을 구축했습니다. lms-service와 payment-service에서 notification-service로의 알림 전송을 Pub/Sub을 통해 처리하여 서비스 간 결합도를 낮추고 안정성을 높였습니다.</description><pubDate>Sun, 25 Jan 2026 00:00:00 GMT</pubDate><category>GCP Pub/Sub</category><category>비동기 처리</category><category>마이크로서비스</category><category>알림 시스템</category><category>Spring Boot</category><category>Kotlin</category><category>메시지 큐</category></item><item><title>멀티테넌시 LMS 서비스 구축: Organization Subdomain 기반 아키텍처</title><link>https://blog.seeun.site/posts/multi-tenant-lms-architecture/</link><guid isPermaLink="true">https://blog.seeun.site/posts/multi-tenant-lms-architecture/</guid><description>멀티테넌시 LMS 서비스를 구축하면서 Organization Subdomain 기반 라우팅과 도메인 설계를 통해 각 조직의 데이터를 안전하게 격리하는 아키텍처를 구현했습니다. OrganizationIdArgumentResolver를 통한 자동 OrganizationId 추출과 Shared Database 전략을 중심으로 설명합니다.</description><pubDate>Sun, 25 Jan 2026 00:00:00 GMT</pubDate><category>멀티테넌시</category><category>LMS</category><category>아키텍처</category><category>Subdomain</category><category>Spring Boot</category><category>Kotlin</category><category>도메인 설계</category></item><item><title>Spring Mail로 구축하는 SMTP 이메일 전송 시스템</title><link>https://blog.seeun.site/posts/spring-mail-smtp-email/</link><guid isPermaLink="true">https://blog.seeun.site/posts/spring-mail-smtp-email/</guid><description>Spring Mail과 JavaMailSender를 활용하여 SMTP 프로토콜로 이메일을 전송하는 시스템을 구축했습니다. HTML 템플릿 기반 이메일, 파라미터 치환, Gmail SMTP 설정 등을 중심으로 실제 구현 과정을 공유합니다.</description><pubDate>Sun, 25 Jan 2026 00:00:00 GMT</pubDate><category>Spring Mail</category><category>SMTP</category><category>이메일 전송</category><category>JavaMailSender</category><category>Gmail</category><category>템플릿</category><category>Kotlin</category></item><item><title>PostgreSQL jsonb 타입을 Hibernate에서 처리하기: hypersistence-utils 활용</title><link>https://blog.seeun.site/posts/postgresql-jsonb-hibernate/</link><guid isPermaLink="true">https://blog.seeun.site/posts/postgresql-jsonb-hibernate/</guid><description>Spring Boot와 Hibernate를 사용하여 PostgreSQL의 jsonb 타입을 다룰 때 발생하는 타입 불일치 문제를 해결한 경험을 공유합니다. hypersistence-utils 라이브러리를 활용해 간단하고 안전하게 jsonb 컬럼을 Map 타입으로 매핑하는 방법을 설명합니다.</description><pubDate>Fri, 23 Jan 2026 00:00:00 GMT</pubDate><category>PostgreSQL</category><category>Hibernate</category><category>JPA</category><category>jsonb</category><category>Kotlin</category><category>Spring Boot</category></item><item><title>GitHub Actions Reusable Workflows로 GitOps 패턴 구현하기</title><link>https://blog.seeun.site/posts/github-actions-gitops/</link><guid isPermaLink="true">https://blog.seeun.site/posts/github-actions-gitops/</guid><description>여러 마이크로서비스를 운영하다 보면 각 서비스마다 비슷한 배포 파이프라인을 중복으로 관리하게 됩니다. GitHub Actions의 Reusable Workflows를 활용해 중앙에서 배포 로직을 관리하고, 각 서비스에서는 간단한 설정만으로 배포를 트리거할 수 있는 GitOps 패턴을 구축했습니다.</description><pubDate>Thu, 22 Jan 2026 00:00:00 GMT</pubDate><category>GitHub Actions</category><category>GitOps</category><category>Reusable Workflows</category><category>CI/CD</category><category>Cloud Run</category><category>GCP</category></item><item><title>폼 빌더 조건부 로직 구현: 동적 질문 표시와 상태 관리 전략</title><link>https://blog.seeun.site/posts/conditional-logic/</link><guid isPermaLink="true">https://blog.seeun.site/posts/conditional-logic/</guid><description>폼 빌더 서비스에서 조건부 로직 기능을 구현하며, 조건이 연쇄적으로 적용되는 경우와 사용자가 답변을 변경할 때 발생하는 상태 관리 문제를 해결한 과정을 공유합니다.</description><pubDate>Wed, 21 Jan 2026 00:00:00 GMT</pubDate><category>조건부 로직</category><category>폼 빌더</category><category>비즈니스 로직</category><category>설문조사</category><category>상태 관리</category><category>동적 폼</category></item><item><title>Google Sheets API 연동: Rate Limit 대응과 데이터 유실 방지 전략</title><link>https://blog.seeun.site/posts/gem-google-sheet/</link><guid isPermaLink="true">https://blog.seeun.site/posts/gem-google-sheet/</guid><description>Google Sheet API의 rate limit으로 인한 데이터 유실 문제를 해결하기 위해 Redis 버퍼링, 배치 처리, 슬라이딩 윈도우 rate limiter를 활용한 안정적인 연동 시스템을 구축한 과정을 소개합니다.</description><pubDate>Wed, 21 Jan 2026 00:00:00 GMT</pubDate><category>Google Sheets</category><category>API</category><category>Rate Limit</category><category>Redis</category><category>배치 처리</category><category>데이터 동기화</category><category>Queue</category><category>재시도</category></item><item><title>마케팅 트래킹을 위한 고정 URL 구현: Redis 캐싱과 미들웨어 설계</title><link>https://blog.seeun.site/posts/gem-pined-link/</link><guid isPermaLink="true">https://blog.seeun.site/posts/gem-pined-link/</guid><description>동일한 설문 폼을 여러 회차에 걸쳐 사용할 때 URL 변경으로 인한 마케팅 데이터 분산 문제를 해결하기 위해, Redis 캐싱과 MongoDB를 활용한 고정 URL 매핑 미들웨어를 구현한 과정을 소개합니다.</description><pubDate>Wed, 21 Jan 2026 00:00:00 GMT</pubDate><category>마케팅</category><category>트래킹</category><category>고정 URL</category><category>Redis</category><category>캐싱</category><category>UTM</category><category>데이터 분석</category></item><item><title>AWS SES로 이메일 발송 시스템 구축하기: 대량 발송과 반송 처리 전략</title><link>https://blog.seeun.site/posts/gem-ses/</link><guid isPermaLink="true">https://blog.seeun.site/posts/gem-ses/</guid><description>AWS SES를 활용한 자동화된 이메일 발송 시스템을 구축했습니다. 대량 메일 발송, AWS SNS와 Lambda를 통한 반송/불만 처리, 블랙리스트 관리 등 실제 운영 환경에서 필요한 기능들을 구현한 과정을 공유합니다.</description><pubDate>Wed, 21 Jan 2026 00:00:00 GMT</pubDate><category>AWS SES</category><category>이메일</category><category>메일 발송</category><category>Nestjs</category><category>SNS</category><category>Lambda</category><category>AWS SDK</category><category>템플릿</category></item><item><title>배치 시스템 성능 분석: Grafana와 APM으로 메모리 누수와 이벤트 루프 지연 진단하기 (1)</title><link>https://blog.seeun.site/posts/measure-1/</link><guid isPermaLink="true">https://blog.seeun.site/posts/measure-1/</guid><description>운영 중인 애플리케이션의 성능과 지표를 제대로 측정하지 않았던 문제를 인식하고, Grafana와 Elastic APM을 활용해 메모리, CPU, 네트워크, 이벤트 루프 지연 등을 분석한 결과를 공유합니다.</description><pubDate>Wed, 21 Jan 2026 00:00:00 GMT</pubDate><category>모니터링</category><category>성능 측정</category><category>메모리</category><category>CPU</category><category>Node.js</category><category>APM</category></item><item><title>배치 시스템 성능 분석: 배치 vs 즉시 처리 시뮬레이션과 하이브리드 접근법 (2)</title><link>https://blog.seeun.site/posts/measure-2/</link><guid isPermaLink="true">https://blog.seeun.site/posts/measure-2/</guid><description>비동기 큐를 활용한 배치 작업이 메모리 누수의 주요 원인임을 확인했습니다. 배치 방식과 즉시 적재 방식을 시뮬레이션하여 각각의 장단점을 분석하고, 스케줄러 제거와 Redis 버퍼 최적화를 통한 하이브리드 접근 방식을 제안합니다.</description><pubDate>Wed, 21 Jan 2026 00:00:00 GMT</pubDate><category>모니터링</category><category>배치 처리</category><category>Google Sheets</category><category>데이터 수집</category><category>Queue</category><category>스케줄링</category></item><item><title>배치 시스템 성능 분석: 이벤트 기반 큐 설계와 Dead Letter Queue 에러 처리 (3)</title><link>https://blog.seeun.site/posts/measure-3/</link><guid isPermaLink="true">https://blog.seeun.site/posts/measure-3/</guid><description>스케줄러를 제거하고 이벤트 기반 큐 시스템으로 전환했습니다. Redis 버퍼에 ID만 저장하는 방식으로 메모리를 최적화하고, BullMQ를 활용한 배치 처리, 슬라이딩 윈도우 rate limiter, Dead Letter Queue를 통한 에러 처리까지 포함한 전체 설계를 소개합니다.</description><pubDate>Wed, 21 Jan 2026 00:00:00 GMT</pubDate><category>모니터링</category><category>성능 분석</category><category>데이터 분석</category><category>대시보드</category></item><item><title>배치 시스템 성능 분석: 개선 임팩트 측정과 개발자 성장 회고 (4)</title><link>https://blog.seeun.site/posts/measure-4/</link><guid isPermaLink="true">https://blog.seeun.site/posts/measure-4/</guid><description>큐 시스템 개선의 임팩트를 메모리, CPU, 네트워크, 이벤트 루프 지표로 측정하고 분석했습니다. 또한 기술 코드/설계, 기술 운영, 제품, 커뮤니케이션 관점에서 프로젝트를 회고하며 개발자로서의 성장을 점검합니다.</description><pubDate>Wed, 21 Jan 2026 00:00:00 GMT</pubDate><category>모니터링</category><category>성능 최적화</category><category>Node.js</category><category>이벤트 루프</category><category>메모리 최적화</category></item><item><title>MongoDB CSFLE로 개인정보 필드 암호화 구현: AWS KMS 연동과 접근 감사 로깅</title><link>https://blog.seeun.site/posts/mongodb-csfle/</link><guid isPermaLink="true">https://blog.seeun.site/posts/mongodb-csfle/</guid><description>MongoDB Client-Side Field Level Encryption(CSFLE)과 AWS KMS를 활용해 개인정보 필드 암호화 시스템을 구축했습니다. CsfleService, AnonymousApplicantService, RevealLoggerInterceptor를 통한 암호화/복호화 및 접근 감사 로깅 구현 과정을 공유합니다.</description><pubDate>Wed, 21 Jan 2026 00:00:00 GMT</pubDate><category>MongoDB</category><category>암호화</category><category>CSFLE</category><category>보안</category><category>Field-Level Encryption</category><category>AWS KMS</category></item><item><title>MongoDB WriteConflict 해결: MVCC 이해와 트랜잭션 동시성 제어</title><link>https://blog.seeun.site/posts/mongodb-write-conflict/</link><guid isPermaLink="true">https://blog.seeun.site/posts/mongodb-write-conflict/</guid><description>지원서 수정 기능 개발 중 MongoDB WriteConflict와 Race Condition 문제를 마주했습니다. WiredTiger의 MVCC 메커니즘을 이해하고, 단일 트랜잭션과 분산 락을 활용해 동시성 문제를 해결한 과정을 상세히 설명합니다.</description><pubDate>Wed, 21 Jan 2026 00:00:00 GMT</pubDate><category>MongoDB</category><category>Write Conflict</category><category>MVCC</category><category>트랜잭션</category><category>동시성</category></item><item><title>WebSocket API 문서화: AsyncAPI 커스텀 구현과 동적 스펙 생성 시스템</title><link>https://blog.seeun.site/posts/socket-asyncapi/</link><guid isPermaLink="true">https://blog.seeun.site/posts/socket-asyncapi/</guid><description>소켓 API 문서화를 위해 AsyncAPI를 도입했습니다. nest-asyncapi의 한계를 극복하기 위해 데코레이터 기반 메타데이터 수집과 동적 AsyncAPI 스펙 생성 시스템을 직접 구현한 과정을 공유합니다.</description><pubDate>Wed, 21 Jan 2026 00:00:00 GMT</pubDate><category>WebSocket</category><category>AsyncAPI</category><category>API 문서화</category><category>Nestjs</category><category>소켓</category><category>이벤트 기반</category><category>데코레이터</category></item><item><title>MongoDB Atlas Search Index: 한국어 검색과 고급 검색 기능</title><link>https://blog.seeun.site/posts/mongodb-search-index/</link><guid isPermaLink="true">https://blog.seeun.site/posts/mongodb-search-index/</guid><description>MongoDB Atlas Search Index는 한국어 검색과 고급 검색 기능을 지원하는 Apache Lucene 기반의 검색 엔진으로, Text Index보다 평균 40% 더 빠른 성능을 제공합니다. 이 글에서는 Atlas Search Index의 개념, 설정 방법, 한국어 검색 최적화 전략, 마이그레이션 방법 및 실무 활용 전략을 다루며, 다양한 검색 쿼리 작성법과 성능 최적화 기법도 포함되어 있습니다.</description><pubDate>Sun, 11 Jan 2026 00:00:00 GMT</pubDate><category>MongoDB</category><category>Atlas Search</category><category>Search Index</category><category>Full-Text Search</category></item><item><title>MongoDB Text Index로 빠른 텍스트 검색 구현하기</title><link>https://blog.seeun.site/posts/mongodb-text-index/</link><guid isPermaLink="true">https://blog.seeun.site/posts/mongodb-text-index/</guid><description>MongoDB Text Index는 대량의 데이터에서도 빠르고 정확한 텍스트 검색을 가능하게 하며, $regex보다 성능이 우수합니다. 하나의 컬렉션에 하나의 Text Index만 생성할 수 있으며, 필드별 가중치 설정을 통해 검색 품질을 향상시킬 수 있습니다. 검색 점수를 활용하여 결과를 관련성 순으로 정렬할 수 있으며, 고급 검색 기능이 필요할 경우 Atlas Search Index를 고려해야 합니다.</description><pubDate>Sat, 10 Jan 2026 00:00:00 GMT</pubDate><category>MongoDB</category><category>Text Index</category><category>Full-Text Search</category><category>Database</category><category>Indexing</category><category>Performance</category></item><item><title>Spring @Transactional 완전 정리: Propagation 옵션과 내부 구현 원리</title><link>https://blog.seeun.site/posts/transactional/</link><guid isPermaLink="true">https://blog.seeun.site/posts/transactional/</guid><description>Spring의 @Transactional 어노테이션은 선언적 트랜잭션 관리 기능을 제공하며, Propagation 옵션을 통해 트랜잭션의 동작 방식을 설정할 수 있다. 주요 Propagation 옵션으로는 REQUIRED, REQUIRES_NEW, SUPPORTS, MANDATORY, NOT_SUPPORTED, NEVER, NESTED가 있으며, 각 옵션은 트랜잭션의 참여 및 생성 방식에 따라 다르게 작동한다. 실제 프로젝트에서의 활용 예시와 성능 최적화 팁도 포함되어 있으며, AOP 프록시 패턴을 기반으로 내부 구현 원리를 설명한다.</description><pubDate>Wed, 31 Dec 2025 00:00:00 GMT</pubDate><category>AOP</category><category>JPA</category><category>Spring</category></item><item><title>JPA 지연 로딩 vs JOIN FETCH: 성능 비교와 선택 가이드</title><link>https://blog.seeun.site/posts/jpa-lazyloading-vs-join-fetch/</link><guid isPermaLink="true">https://blog.seeun.site/posts/jpa-lazyloading-vs-join-fetch/</guid><description>JPA에서 지연 로딩과 JOIN FETCH의 차이를 설명하며, 과제 취소 기능 구현을 통해 성능 비교를 진행했다. 지연 로딩은 필요할 때 데이터를 로딩하는 반면, JOIN FETCH는 연관된 엔티티를 한 번의 쿼리로 조회하여 성능을 개선한다. 실제 성능 측정 결과, JOIN FETCH를 사용했을 때 약 32-43%의 성능 향상이 있었다. 조건부로 사용되는 연관 엔티티에는 지연 로딩을, 항상 함께 사용되는 경우에는 JOIN FETCH를 사용하는 것이 바람직하다.</description><pubDate>Mon, 22 Dec 2025 00:00:00 GMT</pubDate><category>JPA</category><category>LazyLoading</category><category>Join</category></item><item><title>Google Gemini CLI 오픈소스 기여: 토큰 에러 핸들링 시스템 구현</title><link>https://blog.seeun.site/posts/gemini-cli-opensource-contribute/</link><guid isPermaLink="true">https://blog.seeun.site/posts/gemini-cli-opensource-contribute/</guid><description>Google Gemini CLI 오픈소스 프로젝트에 기여하여 토큰 에러 핸들링 시스템을 구현하였습니다. 이 시스템은 자동 복구 및 재시도 메커니즘을 통해 긴 입력에 대한 처리 문제를 해결하며, 사용자 친화적인 에러 메시지와 실시간 토큰 모니터링 기능을 제공합니다. 또한, 다양한 에러 형태를 지원하고, 성능 최적화를 위해 비동기 처리 및 지수 백오프를 적용하였습니다. 향후 스마트 컨텍스트 압축 및 실시간 대시보드와 같은 추가 기능을 고려하고 있습니다.</description><pubDate>Sun, 28 Sep 2025 00:00:00 GMT</pubDate><category>gemini</category><category>google</category><category>test</category></item><item><title>MongoDB 멀티 도큐먼트 트랜잭션: AsyncLocalStorage와 Mongoose 미들웨어 활용</title><link>https://blog.seeun.site/posts/multi-document-transaction/</link><guid isPermaLink="true">https://blog.seeun.site/posts/multi-document-transaction/</guid><description>MongoDB의 멀티 도큐먼트 트랜잭션을 Node.js에서 안전하게 구현하기 위해 AsyncLocalStorage와 Mongoose 미들웨어를 사용하는 방법을 설명하며, 자동 세션 관리, 재시도 메커니즘, 에러 처리 및 성능 최적화의 중요성을 강조합니다. 다양한 구현 방식을 비교하고, @Transactional 데코레이터를 통해 복잡한 비즈니스 로직을 안전하게 처리하는 방법을 제시합니다.</description><pubDate>Mon, 10 Mar 2025 00:00:00 GMT</pubDate><category>MongoDB</category><category>transaction</category><category>AsyncLocalStorage</category><category>Nodejs</category><category>Mongoose</category><category>Nestjs</category></item><item><title>NestJS AOP로 Kafka Consumer 데코레이터 만들기</title><link>https://blog.seeun.site/posts/nestjs-aop-kafka-consumer-decorator/</link><guid isPermaLink="true">https://blog.seeun.site/posts/nestjs-aop-kafka-consumer-decorator/</guid><description>Kafka 메시지 처리를 위해 각 토픽마다 개별 컨슈머 그룹을 구성하고, 커스텀 데코레이터(@Consume)를 통해 컨트롤러의 특정 메서드를 Kafka Consumer로 등록하는 방법을 설명합니다. NestJS에서 데코레이터는 마킹, 조회, 등록의 3단계로 동작하며, 이를 통해 독립적인 오프셋 관리, 맞춤형 소비 로직, 리밸런싱 영향 최소화 등의 장점을 제공합니다.</description><pubDate>Fri, 03 Jan 2025 00:00:00 GMT</pubDate><category>Nestjs</category><category>AOP</category><category>Decorator</category><category>kafka</category></item></channel></rss>