최신 글
-
배치 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
-
코루틴 Thread confinement 기법
스레드의 동시 상태변경 문제는 코루틴에서도 동일하게 접할 수 있다.상태공유를 코루틴 간에 무분별하게 하면, thread-safe 하지 못한 코드가 작성될 수 있다.따라서 아래처럼 임계영역은 하나의 스레드 컨텍스트로 제한할 수 있다. 이를 Thread confinement이라 한다.Completed 100000 actions in 474 ms 임계영역에 진입할 때마다 싱글 스레드 컨텍스트로 전환시키는 위와 같은 방법을 fine-grained 방식이라 한다. 다음에 소개할 coarse-grained 방식보다 상대적으로 느리다. Completed 100000 actions in 9 ms 위 방식은 coarse-grained 방식이라 한다. 애초에 임계영역에 진입하기 전에 임계영역을 호출하는 함수 자체를 싱..
2024.10.28
-
[Kotlin, Jackson] @JsonCreator 로 enum 값 유연하게 역직렬화
Spirng 개발을 하다 보면 json 직렬화에는 기본으로 jackson 라이브러리를 사용하게 된다. 다른 API 통신, FE 클라이언트와 통신할 때 제일 많이 쓰는 포맷이 json일 듯하다. Java 에는 enum 클래스를 지원해서 상수값을 편하게 관리할 수 있는데, 대외 통신 시 직렬화 작업을 할 때 그 값이 꼭 Enum에 정의한 값이 아니어도 가능해야할 때가 있다. 예를 들어 enum에는 성별을 MEN, FEMALE로 정의했지만, 호출 단에서는 M, F로 정의해서 보낸다던지 등이다. 따라서 아래처럼 직렬화를 실패하게 된다. 그러나 Jackson 라이브러리는 @JsonCreator 애노테이션을 지원한다. 아래처럼 선언해주면 역직렬화 시 enum을 유연하게 생성할 수 있다. 이제 아래와 같은 테..
2024.08.09
-
[Kotlin] runBlocking vs coroutineScope
코루틴은 Structured Concurrency 원칙을 따른다. Structured Concurrency이란 새로운 코루틴은 반드시 CoroutineScope 안에서만 생성 (런치)될 수 있다는 것으로 코루틴의 범위를 제한하는 메커니즘이다. 코루틴의 범위를 제한하고 코루틴의 라이프사이클을 관리하는 인터페이스는 kotlinx.coroutines.CoroutineScope이다. Scope builder Scope builder란 코루틴의 범위를 나타내는 인터페이스 CorotuineScope을 생성하고, 그 안에서 생성된 모든 코루틴 (자식 코루틴)이 완료될 때까지 기다리는 빌더 함수 (람다)를 말한다. 코루틴 스코프의 최상위 코루틴 (부모 코루틴)은 블로킹된다. 스코프 빌더는 크게 2가지 runBlock..
2024.08.02
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
-
[Java] JDK 21 Virtual Threads 톺아보기
목차 OS 스레드와 Java Platform Thread Java Virtual Thread Virtual Thread 사용해 보기 Virtual Thread 효율적으로 사용하기 Java 21에 새롭게 추가된 Virtual Thread에 대해 알아본다. 먼저, 가상 스레드를 일목요연하게 정리해 주신 카카오 안정수(James.star)님께 감사드린다. 아래 링크를 통해 영상을 볼 수 있다. https://youtu.be/vQP6Rs-ywlQ 추가로 Oracle에서 제공한 Virtual Thread 문서를 참고하여 가상 스레드를 정리해 보았다. 예시코드는 모두 아래 깃헙에서 볼 수 있다. https://github.com/gihyeon6394/hello-java-virtualthread GitHub - gi..
2024.01.04
-
ELK 스택으로 구축하는 로그 수집, 시각화
목차모니터링 방법과 ELK 스택구축해 보기모니터링 방법과 ELK 스택 어제 8시 즈음 회원 서버 로그 좀 봐볼까? (회원 서버만 10대인데요?) 애플리케이션이 많아질수록 개발자 (관리자)가 조회해야 하는 애플리케이션 관련 데이터가 급격히 늘어난다. metric, 로그 데이터와 같은 것들이다. 애플리케이션이 한 개이고, 레플리카도 하나라면 직접 서버에 접속해 로그 파일을 추적해 보면 되지만, 여러 대인 상황에서는 쉽지 않다. APM (Application Performance Monitoring) 솔루션을 사용하면 애플리케이션의 실시간 모니터링이 가능하다. 성능 관련 데이터는 실시간에 가깝게 조회되어야 하는 데이터지만, 로그나 사용자 추적 데이터 (히스토리, 페이지 이동 이력 등)는 성격이 다르다...
2024.07.24
-
[JPA] JPA와 @Transactional
@Transactional은 Spring AOP를 기반으로 동작하는 프락시이기 때문에 AOP에 대한 이해가 없다면 먼저 이해한 뒤 보길 바란다. 아래 두 포스팅을 참고해도 좋다. 2023.12.02 - [Programming/JAVA] - [Java] AOP 1편 - 핵심 기술 Proxy, Dynamic proxy, Factory bean [Java] AOP 핵심 기술 - Proxy, Dynamic proxy, Factory bean 목차 AOP란 프락시(Proxy)의 정의, 프락시 패턴 다이내믹 프락시 다이내믹 프락시 예제 한계 스프링의 ProxyFactoryBean : 어드바이저 Spring 3대 기술 (DI, PSA, AOP) 중 하나인 AOP는 프락시 기반으로 동작한 kghworks.tistory..
2023.12.03
-
[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
-
[Java] JPA N+1 원리 이해하기
목차 N+1 문제 정의 N+1 원인 1. 연관관계의 주인이 누구인가 N+1 원인 2. JPQL은 연관객체의 fetchType을 모른다 N+1 해결방법 정리 참고 포스팅에는 아주 간단히 아래 2개의 테이블을 사용한다. @Entity @Table(name = "team") public class Team { @Id private String id; private String name; @OneToMany(mappedBy = "team", fetch = FetchType.LAZY) private List members = new ArrayList(); // 생략 } @Entity @Table(name = "member") public class Member { @Id private String id; priv..
2023.11.14
-
[클라우드] 가상화 - 클라우드 컴퓨팅의 핵심 기술
목차 가상화란 가상화 구성요소 가상화 방식 가상화란? 컴퓨터 분야에서 가상이란 말이 붙으면 logical의 동의어로 물리적으로 실체가 있지 않은 무언가를 뜻한다. 가상화는 컴퓨터를 하나의 인스턴스(머신)의 개념으로 간주하여 물리적인 컴퓨터를 인스턴스(머신) 수준으로 가상화한 것을 말한다. 즉 IT 리소스를 논리적으로 분할하는 기술이다. 왜 가상화를 하나? 컴퓨터를 인스턴스로 가상화하여 하나의 컴퓨터 (Host)에서 1개 이상의 가상 컴퓨터를 논리적으로 운용할 수 있기 때문이다. 가상화를 통해 하나의 물리적 하드웨어에 여러 개의 컴퓨터 (인스턴스, 머신)를 운용할 수 있다. 가상화는 굳이 클라우드 컴퓨팅 기술을 사용하지 않더라도 가능하다. 가상화를 할 수 있는 프로그램을 Host 컴퓨터에 설치한다면 해당 ..
2023.10.25
-
[Database] 인덱스 (Index) 1장 : 필요성과 기본 컨셉
특정 DBMS에 대한 인덱스 구조가 아닌 데이터베이스 시스템 자체에 대한 인덱스에 대해 정리한다. 기본 개념, 종류와 메커니즘에 대해 말하겠다. 전체적인 흐름은 데이터베이스 시스템 (Abraham Silberschatz , Henry F. Korth , S. Sudarshan 저)의 14장 Indexing을 따른다. 1개 이상의 DBMS에서 인덱스를 생성해봤고, 인덱스에 대한 이해가 어느 정도 있다면 더 수월하게 포스팅을 읽어나갈 수 있을 것이다. 첫 번째 포스팅으로 데이터베이스에서 인덱스의 필요성과 기본 콘셉트를 정리한다. 목차 인덱스의 필요성 좋은 인덱스를 판별하는 기준 search key 인덱스 생성하기 인덱스의 필요성 데이터베이스의 인덱스를 책의 색인에 비유하곤 한다. 책의 색인 데이터베이스 인덱..
2023.10.12