MDC가 뭐길래 traceId를 관리할까?
·
Infra
Spring Boot 프로젝트에서 @RestControllerAdvice로 에러를 한곳에서 처리하고, 로그에 traceId를 남기고 싶을 때가 있다. 이때 많은 사람들이 흔히 하는 실수가 있다. 바로 “Advice 안에서 traceId를 만들고 로깅하는 것”이다. 겉보기엔 간단하지만, traceId는 요청 전체를 추적하기 위한 값이기 때문에 예외가 터진 시점이 아니라, 요청이 들어온 시점에 만들어야 한다. 그래야 “요청 시작 → 서비스 로직 → 응답/예외 처리” 모든 로그가 같은 traceId로 묶인다.그래서 등장하는 개념: MDC (Mapped Diagnostic Context)MDC는 로그에 문맥(Context)을 담는 기능이다.각 스레드마다 독립적인 key-value 맵을 가지고 있어서 “현재 요청..
비동기/ 동기가 뭐길래..
·
CS/OS
백엔드 개발을 하다 보면 동기(synchronous), 비동기(asynchronous)라는 말을 정말 자주 듣게 된다. 멀티플렉싱을 공부할 때도 그렇고, Spring을 쓰다 보면 “이건 동기로 할까, 비동기로 할까?” 같은 이야기를 계속 하게 된다. 그런데 막상 누가 설명해보라고 하면 어딘가 애매해진다. 대충은 아는 것 같은데, 정확히 말로 풀기는 어렵다. 그래서 이번에는 이 개념들을 한 번 제대로 정리해보려고 한다. 프로그래밍 관점에서 시작해서 I/O 관점, 그리고 백엔드 아키텍처 관점까지 이어서 보면서 동기와 비동기를 다시 정렬해보는 게 목표다. 이미 들어본 이야기들이 많겠지만, 이번 글에서는 “왜 이렇게 이해하는 게 맞는지”에 조금 더 집중해보려고 한다. 쉬운코드를 보면서 들었던 내용들을, 내 나름..
I/O Multiplexing: Reactor 와 Proactor (IOCP)
·
CS/OS
앞선 글에서는 select, poll, epoll을 중심으로 Reactor 패턴 기반의 I/O 멀티플렉싱을 살펴보았다. Reactor 모델에서는 커널이 “지금 I/O를 수행할 수 있다”는 준비 상태(ready) 를 알려주고, 실제 read() / write() 호출은 애플리케이션이 직접 수행한다는 특징이 있었다. 하지만 모든 운영체제가 이 방식만을 사용하는 것은 아니다. 특히 Windows 환경에서는 전혀 다른 접근 방식을 취하는데, 바로 Proactor 패턴이다. 이번 글에서는 Reactor와 대비되는 개념으로서 Proactor 패턴, 그리고 그 대표적인 구현체인 IOCP(I/O Completion Port) 에 대해 살펴본다.Proactor 패턴이란?Proactor 패턴의 핵심은 한 문장으로 정리할 ..
I/O Multiplexing: Select, Poll, 그리고 Epoll
·
CS/OS
Select 와 Poll 다시보기I/O 멀티플렉싱을 구현하는 방식에는 여러 가지가 존재한다. 그중 가장 오래된 방식이 select와 poll인데, 이들은 내부적으로 모든 소켓을 순회하며 상태를 확인하는 구조를 가지고 있어 성능상의 한계가 뚜렷하다. 이러한 특성 때문에 현대의 고성능 서버 환경에서는 앞서 설명한 방식들과 함께 잘 사용되지 않는 편이다. 저번에 non-blocking에서 멀티플렉싱 i/o에 대해서 설명할 때 나타낸 그림이다위 그림에서 나타난 방식 역시 엄밀히 따지면 select와 poll이 사용하는 구조를 그대로 따른다. 두 방식의 차이는 본질적인 동작 방식의 차이라기보다는 API 인터페이스와 내부 자료구조의 차이에 가깝다. 즉, 멀티플렉싱이라는 관점에서 보면 select와 poll은 거의 ..
Block I/O vs Non-Block I/O 무슨 차이지..?
·
CS/OS
동기/비동기 처리를 이해하기 위해 먼저 짚고 넘어가야 할 개념인 것 같아 I/O에 대해 정리해본다.I/O 개념 정리동기/비동기 처리를 이해하기 위해 먼저 짚고 넘어가야 할 개념이 바로 I/O다. 이를 정리해보자. I/O란 쉽게 말해 데이터의 입출력(Input/Output)을 의미한다. 우리가 알고 있듯이 운영체제(OS) 환경에서는 CPU가 데이터 연산을 담당하고, RAM은 데이터를 임시로 저장하며, 디스크는 영구 저장소 역할을 하는 등 각 구성 요소가 역할을 나누어 작업을 처리한다. 따라서 특정 작업을 수행하기 위해 데이터가 한 요소에서 다른 요소로 이동하게 되는데, 이때 발생하는 데이터 이동 과정을 I/O라고 한다.Block I/OBlocking I/O에서는 I/O 작업을 요청한 프로세스나 스레드가 해..
Java에서 Map/Set/Hash가 헷갈린다…(3)
·
Java
사실 Hash는 Map이나 Set과 같은 컬렉션 유형이 아니다. 그럼에도 처음에 헷갈렸던 이유는, Map이나 Set의 구현체를 주입할 때 항상 HashMap, HashSet처럼 Hash라는 이름이 함께 등장하기 때문이었다. 그래서 Hash도 Map이나 Set처럼 하나의 컬렉션 타입이라고 착각하기 쉬웠다. 하지만 Hash는 Map이나 Set과 같은 역할을 담당하는 개념이 아니라, 데이터를 어떻게 저장하고 빠르게 찾을 것인가에 대한 구현 전략이다. 즉, Map과 Set은 “무엇을 표현하는가”에 대한 개념이고, Hash는 “그 개념을 어떻게 효율적으로 구현할 것인가”에 대한 방식이다.Map과 Set은 역할, Hash는 전략Map은 Key–Value 관계를 저장하는 컬렉션이고, Set은 중복을 허용하지 않는 값..