최신 글
-
내가 헥사고날 아키텍처에 회의적인 이유
포트와 어댑터의 장점이 있다. 문제는 비용이다.그리고 AI Agent가 코드를 짜는 시대에, 나는 더 회의적이 되었다. 목차헥사고날이 해결하려는 진짜 문제 — 의존성의 방향레이어드 아키텍처가 "틀린" 게 아니다포트와 어댑터 — 이름부터 정확히실무에서 겪은 것 — 장점과 비용AI Agent 시대가 이 계산을 바꾼다언제 쓰고, 언제 쓰지 말아야 하는가결론참고 시작하기 전에헥사고날 아키텍처(Hexagonal Architecture): Alistair Cockburn이 2005년 정리한 스타일로, 애플리케이션 코어를 UI·DB·외부 시스템 같은 바깥 세계로부터 격리해, 사용자든 배치든 테스트든 동일하게 코어를 구동할 수 있게 만드는 것을 목표로 한다.포트와 어댑터(Ports & Adapters): 헥사고날의 ..
2026.09.04
-
카프카가 빠른 이유
목차Sequential I/O와 Page CacheZero-CopyBatching과 압축Partition = Lock-Free 병렬성네트워크 레이어종합 + 벤치마크참고Sequential I/O와 Page Cache카프카가 빠른 이유를 한 문장으로 말하면: 디스크에 sequential 하게만 접근하고, OS에게 캐싱을 맡긴다. 디스크의 물리학흔히 "디스크는 느리다"고 하지만, 이건 random access에 한정된 얘기다.HDD: random seek에 ~10ms가 걸리지만 sequential read는 200MB/s 이상 나온다. 같은 디스크에서 1000배 차이.SSD: random 4KB IOPS가 100K 수준이라 해도, sequential bandwidth는 3~7GB/s(NVMe)까지 간다. 여전..
2026.08.15
-
K8s + Spring Boot: Graceful Shutdown 제대로 이해하기
목차문제: Rolling Update 시 502가 나는 이유Spring Boot에서의 구현: 애플리케이션 계층K8s 배포 설정: 인프라 계층최종 설정 및 마무리문제: Rolling Update 시 502가 나는 이유Pod는 어떻게 죽는가Pod 삭제 요청이 API Server에 도달하면 두 가지가 동시에 실행된다. 핵심은 경로 A와 B가 비동기라는 것이다.Race Condition: 502의 정체preStop hook이 없으면 kubelet은 즉시 SIGTERM을 보낸다. Spring Boot는 SIGTERM을 받는 순간 새 요청 수신을 거부한다. 그런데 경로 B의 Endpoint 제거/전파는 아직 진행 중이다. kube-proxy가 iptables 규칙을 갱신하기까지, Ingress Controller가..
2026.08.12
-
배치 vs 마이크로배치 vs 스트리밍, 그리고 Flink
서버 개발자에게 "요청이 들어오면 즉시 응답한다"는 자연스러운 사고방식이다. 하지만 데이터 처리의 세계에서는 "언제 처리할 것인가" 자체가 아키텍처를 결정하는 첫 번째 질문이 된다.어제 하루치 주문 데이터를 집계해서 리포트를 만든다 → 배치최근 10초간 쌓인 클릭 로그를 모아서 대시보드를 갱신한다 → 마이크로배치사용자가 결제 버튼을 누른 바로 그 순간 이상 거래를 탐지한다 → 스트리밍 세 가지 모델은 "진화의 단계"가 아니다. 각각 고유한 트레이드오프를 가진 선택지다. 이 글에서는 세 모델의 차이를 명확히 정리하고, 스트리밍이 필요한 순간에 왜 Apache Flink가 강력한 선택지인지를 이야기한다.레이턴시처리 모델대표 기술일 단위BatchSpark, Hive분 단위Micro-batchSpark Stru..
2026.03.25
-
Data Skew 진단과 해결
Spark on Kubernetes 클러스터에서 ETL 잡을 돌리다 보면, 대부분의 Executor Pod는 멀쩡한데 딱 한두 개 Pod만 OOMKilled로 죽는 상황을 마주하게 된다. 로그를 열어보면 해당 Pod에 할당된 파티션의 데이터가 다른 파티션 대비 수십~수백 배 많다. 이것이 Data Skew 문제다. Data Skew는 Spark만의 문제가 아니다. 데이터를 키(key) 기반으로 분산하는 모든 시스템 — Kafka, Flink, DB 샤딩, MapReduce — 에서 동일한 구조적 원인으로 발생한다. 이 글에서는 Data Skew가 왜 발생하는지 근본 원인을 파악하고, Spark에서의 구체적 해결법과 함께 분산 시스템 전반에 적용 가능한 포괄적 전략을 다룬다.목차Data Skew란 무엇인..
2026.03.17
-
JVM Container OOMKilled 트러블슈팅 가이드
JVM 위에서 돌아가는 서비스를 Kubernetes/컨테이너로 운영하다 보면, OOMKilled라는 메시지를 한 번쯤 마주하게 된다. OOMKilled는 Linux 커널의 OOM(Out Of Memory) Killer가 메모리 한도를 초과한 프로세스를 강제 종료(SIGKILL) 하는 것을 말한다. 컨테이너 환경에서는 cgroup(Control Group — Linux 커널이 프로세스 그룹별로 CPU, 메모리 등 자원 사용량을 격리·제한하는 메커니즘)이 설정한 메모리 limit을 프로세스의 RSS(Resident Set Size — 프로세스가 실제로 점유하고 있는 물리 메모리 크기) + Page Cache(파일 I/O 시 커널이 디스크 데이터를 RAM에 캐싱해 둔 영역)가 초과하면 발생한다. 프로세스는 ..
2026.03.11
-
[Spring] ApplicationEventPublisher 테스트 (모킹)하기
테스트에서 ApplicationEventPublisher에 대한 모킹을 시도하던 중 여러 시행착오를 겪었다. ApplicationEventPublisher은 일반적으로 모킹이 불가 (e.g. @MockkBean)하며 테스트용 ApplicationEventPublisher 빈을 별도로 만들어 사용하거나 (1), 모킹 포기하고 스프링에서 제시하는 @RecordApplicationEvents로 검증해 보던가(2) 해야 한다. 목차문제 : ApplicationEventPublisher 모킹이 불가하다해결 1. ApplicationEventPublisher 모킹 없이, 테스트하는 방법 (스프링 제안)해결 2. ApplicationEventPublisher를 모킹 하기문제 : ApplicationEventPubli..
2025.08.20
-
MySQL 타임존 다루기
데이터베이스에 시각 (날짜) 관련 데이터를 저장하려다 보면 타임존에 대해 고민하게 된다. 국내 한정으로 서비스한다면 크게 고려하지 않는 부분이나, 글로벌 서비스를 고민한다면 필히 타임존을 고려하여 날짜데이터를 다루게 된다. 이번에는 MySQL 데이터베이스를 기준으로 날짜 데이터와 타임존을 어떻게 다룰 수 있는지 알아본다. 목차 MySQL의 날짜와 시간 DATETIME과 TIMESTAMP 다루어보기 MySQL의 날짜와 시간 MySQL의 날짜 타입 DATETIME, TIME : 컬럼 자체에 타임존 정보 없음. 클라이언트가 입력한 값 그 자체를 저장, 반환 TIMESTAMP : UTC로 저장되어 클라이언트에게 반환할 때는 타임존 변환을 거쳐 반환 MySQL이 관리하는 타임존 정보는 아래와 같다. syst..
2025.01.20
-
코루틴 스코프에서 스레드 블로킹 해보기
Replace this "Thread.sleep()" call with "delay()". suspend 함수에서 스레드 블로킹 함수를 호출하면 Replace this "Thread.sleep()" call with "delay()". 과 같은 경고 메시지가 출력된다. 코루틴은 suspend라는 개념을 지원해서 스레드를 블로킹하지 않고 스레드가 다른 코루틴을 실행할 수 있도록 하여 전체 처리량 (throughput)을 높일 수 있다. 따라서 suspend 블록에서 스레드를 블로킹하는 행위나 메서드 호출은 지양하는 것이 좋다. 코루틴 스코프에서 스레드를 블로킹했을 때 동작을 육안으로 확인해 보고자 코드를 작성해 봤다.singleThreadContext : 싱글 스레드 코루틴 context로 제한. 멀티..
2024.12.26
Engineering
-
JVM Container OOMKilled 트러블슈팅 가이드
JVM 위에서 돌아가는 서비스를 Kubernetes/컨테이너로 운영하다 보면, OOMKilled라는 메시지를 한 번쯤 마주하게 된다. OOMKilled는 Linux 커널의 OOM(Out Of Memory) Killer가 메모리 한도를 초과한 프로세스를 강제 종료(SIGKILL) 하는 것을 말한다. 컨테이너 환경에서는 cgroup(Control Group — Linux 커널이 프로세스 그룹별로 CPU, 메모리 등 자원 사용량을 격리·제한하는 메커니즘)이 설정한 메모리 limit을 프로세스의 RSS(Resident Set Size — 프로세스가 실제로 점유하고 있는 물리 메모리 크기) + Page Cache(파일 I/O 시 커널이 디스크 데이터를 RAM에 캐싱해 둔 영역)가 초과하면 발생한다. 프로세스는 ..
2026.03.11
-
Data Skew 진단과 해결
Spark on Kubernetes 클러스터에서 ETL 잡을 돌리다 보면, 대부분의 Executor Pod는 멀쩡한데 딱 한두 개 Pod만 OOMKilled로 죽는 상황을 마주하게 된다. 로그를 열어보면 해당 Pod에 할당된 파티션의 데이터가 다른 파티션 대비 수십~수백 배 많다. 이것이 Data Skew 문제다. Data Skew는 Spark만의 문제가 아니다. 데이터를 키(key) 기반으로 분산하는 모든 시스템 — Kafka, Flink, DB 샤딩, MapReduce — 에서 동일한 구조적 원인으로 발생한다. 이 글에서는 Data Skew가 왜 발생하는지 근본 원인을 파악하고, Spark에서의 구체적 해결법과 함께 분산 시스템 전반에 적용 가능한 포괄적 전략을 다룬다.목차Data Skew란 무엇인..
2026.03.17
-
K8s + Spring Boot: Graceful Shutdown 제대로 이해하기
목차문제: Rolling Update 시 502가 나는 이유Spring Boot에서의 구현: 애플리케이션 계층K8s 배포 설정: 인프라 계층최종 설정 및 마무리문제: Rolling Update 시 502가 나는 이유Pod는 어떻게 죽는가Pod 삭제 요청이 API Server에 도달하면 두 가지가 동시에 실행된다. 핵심은 경로 A와 B가 비동기라는 것이다.Race Condition: 502의 정체preStop hook이 없으면 kubelet은 즉시 SIGTERM을 보낸다. Spring Boot는 SIGTERM을 받는 순간 새 요청 수신을 거부한다. 그런데 경로 B의 Endpoint 제거/전파는 아직 진행 중이다. kube-proxy가 iptables 규칙을 갱신하기까지, Ingress Controller가..
2026.08.12
-
배치 vs 마이크로배치 vs 스트리밍, 그리고 Flink
서버 개발자에게 "요청이 들어오면 즉시 응답한다"는 자연스러운 사고방식이다. 하지만 데이터 처리의 세계에서는 "언제 처리할 것인가" 자체가 아키텍처를 결정하는 첫 번째 질문이 된다.어제 하루치 주문 데이터를 집계해서 리포트를 만든다 → 배치최근 10초간 쌓인 클릭 로그를 모아서 대시보드를 갱신한다 → 마이크로배치사용자가 결제 버튼을 누른 바로 그 순간 이상 거래를 탐지한다 → 스트리밍 세 가지 모델은 "진화의 단계"가 아니다. 각각 고유한 트레이드오프를 가진 선택지다. 이 글에서는 세 모델의 차이를 명확히 정리하고, 스트리밍이 필요한 순간에 왜 Apache Flink가 강력한 선택지인지를 이야기한다.레이턴시처리 모델대표 기술일 단위BatchSpark, Hive분 단위Micro-batchSpark Stru..
2026.03.25
-
[Message Brokers] Streaming data와 Pub / Sub system
목차 Streaming Data Streaming Data를 쿼리하는 방법 Algebraic Operations Publish / Subscribe system [참고] 트위터의 데이터 처리 방식 Streaming Data : 지속적인 데이터 흐름 웹 서비스에서의 데이터는 주로 데이터베이스 시스템에서 관리된다. Relational Database Management System (RDBMS, 관계형 데이터베이스)가 대표적이다. 데이터베이스에 저장된 데이터를 불러오기 위해 많은 client들이 질의 (query)하는데 이 질의를 지속적으로 (혹은 주기적으로) 해야 하는 데이터들이 있다. 예를 들면, SNS 게시글은 데이터가 추가될 때마다 엄청난 질의가 들어올 것이다. 호날두가 인스타그램에 글을 올리면 해당..
2023.11.25
-
[Database] 인덱스 (Index) 1장 : 필요성과 기본 컨셉
특정 DBMS에 대한 인덱스 구조가 아닌 데이터베이스 시스템 자체에 대한 인덱스에 대해 정리한다. 기본 개념, 종류와 메커니즘에 대해 말하겠다. 전체적인 흐름은 데이터베이스 시스템 (Abraham Silberschatz , Henry F. Korth , S. Sudarshan 저)의 14장 Indexing을 따른다. 1개 이상의 DBMS에서 인덱스를 생성해봤고, 인덱스에 대한 이해가 어느 정도 있다면 더 수월하게 포스팅을 읽어나갈 수 있을 것이다. 첫 번째 포스팅으로 데이터베이스에서 인덱스의 필요성과 기본 콘셉트를 정리한다. 목차 인덱스의 필요성 좋은 인덱스를 판별하는 기준 search key 인덱스 생성하기 인덱스의 필요성 데이터베이스의 인덱스를 책의 색인에 비유하곤 한다. 책의 색인 데이터베이스 인덱..
2023.10.12