본문 바로가기

전체 글

(741)
레디스는 왜 단일 스레드인데 빠른가 — 이벤트 루프와 I/O 스레드 레디스는 "단일 스레드인데 빠르다"는 말로 소개됩니다. 반은 맞고 반은 틀립니다. 명령을 실행하는 스레드는 하나가 맞습니다. 그러나 빠른 이유는 스레드 개수가 아닙니다. 소켓을 기다리지 않는 구조, 메모리 안에서 끝나는 자료구조, 시스템 콜을 줄이는 습관이 함께 만든 결과입니다.이 글은 레디스 소스(ae.c, server.c, networking.c)와 공식 문서를 따라가며 요청 하나가 어떤 순서로 처리되는지 풉니다. 그리고 같은 구조가 왜 KEYS * 한 번에 서비스 전체를 멈추게 하는지도 봅니다.■ 1. 레디스가 푸는 문제 — 스레드를 늘리지 않고 연결을 많이 받기전통적인 서버는 연결 하나에 스레드 하나를 붙입니다. 스레드는 read() 에서 데이터가 올 때까지 잠들어 있습니다. 연결이 만 개면 잠든..
도커 이미지 레이어와 빌드 캐시 원리 — whiteout·캐시 키 소스 한 줄만 고쳤는데 npm install 이 처음부터 다시 돕니다. 반대로 패키지를 올렸는데 빌드는 옛 버전을 그대로 씁니다. 둘 다 같은 원리에서 나옵니다. 도커 이미지는 변경분(tar)을 순서대로 쌓은 것이고, 빌드 캐시는 "부모 단계 + 이번 지시문"이 같으면 결과도 같다고 보는 규칙입니다. 이 두 가지를 정확히 알면 Dockerfile 순서를 왜 그렇게 짜야 하는지, rm 을 해도 이미지가 왜 안 줄어드는지가 한 번에 풀립니다.■ 이 구조가 푸는 문제컨테이너 이미지는 운영체제 파일 트리 전체를 담습니다. 서비스 이미지 열 개가 같은 기반 이미지를 쓴다면, 그 파일 트리를 열 번 저장하고 열 번 내려받는 것은 낭비입니다. 빌드도 마찬가지입니다. 의존성 설치가 몇 분 걸리는데, 소스 한 줄 바꿀 ..
토크나이저와 BPE 원리 — LLM 이 글자를 숫자로 바꾸는 법 LLM 은 글자를 읽지 않습니다. 정수 배열을 읽습니다. "안녕하세요"를 넣으면 모델 앞단에서 [14307, 171731] 같은 숫자 열로 바뀌고, 모델은 이 숫자들 다음에 올 숫자를 예측합니다. 이 변환을 맡는 것이 토크나이저입니다. GPT 계열을 비롯한 대부분의 LLM 토크나이저는 BPE(Byte Pair Encoding)라는 알고리즘을 바탕으로 합니다.토크나이저는 학습이 끝난 뒤 바뀌지 않는 부품이라 관심을 덜 받습니다. 그런데 API 요금이 토큰 수로 매겨지고, 컨텍스트 창도 토큰 수로 잽니다. 모델이 "strawberry 에 r 이 몇 개냐"는 질문에 약한 이유, 스트리밍 응답에서 한글이 � 로 깨지는 버그도 토크나이저 쪽에서 생깁니다. 이 글에서는 BPE 가 어휘를 어떻게 배우고, 새 문장을 ..
Zod 악성 커밋·Postgres 스토리지·S3 합의 — IT 뉴스 이번 주에는 공급망 공격, 데이터베이스 성능, 분산 시스템 설계, AI 에이전트 인프라 소식이 한꺼번에 나왔습니다. 개발자에게 직접 영향이 있는 소식 다섯 개를 골랐습니다. 소식마다 원문을 직접 확인했습니다.■ 오늘 소식 한눈에소식 | 분야 | 한 줄 요약 | 영향받는 사람----------------------------------------------------Zod 저장소에 악성 커밋 | 보안·공급망 | 탈취된 계정으로 원격 코드 로더를 심은 커밋이 main에 올라갔다가 되돌려짐 | Zod를 쓰는 모든 TS/JS 프로젝트, npm 배포 파이프라인 운영자Postgres가 아니라 스토리지가 느리다 | 데이터베이스 | 같은 인스턴스에서 로컬 NVMe가 gp3 EBS보다 처리량 9.24배 | 클라우드에서 ..
구조화된 출력(JSON 모드) 원리 — 제약 디코딩으로 형식 강제 ========================================LLM 응답을 코드로 받아 쓰는 순간, 문제는 내용보다 형식에서 먼저 터집니다. 프롬프트에 "JSON 으로만 답하세요"라고 써도 모델은 가끔 앞에 "물론입니다!"를 붙이고, 코드 펜스로 감싸고, 필수 키를 빼먹습니다. json.loads 가 예외를 던지면 재시도하고, 그래도 안 되면 정규식으로 긁어냅니다.구조화된 출력(Structured Outputs)은 이 문제를 생성 단계에서 없앱니다. 모델이 토큰을 고르기 직전에, 스키마상 나올 수 없는 토큰의 확률을 0으로 만듭니다. 이 방식을 제약 디코딩(constrained decoding)이라고 합니다. 이 글은 그 마스크가 어디서 오고, 어떻게 매 토큰마다 빠르게 계산되는지를 따라갑니다..
카프카 컨슈머 그룹 리밸런싱은 왜 멈춤을 만드나 — KIP-848 컨슈머 하나를 재배포했을 뿐인데 그룹 전체의 랙(lag)이 튀어 오릅니다. 로그에는 Revoke previously assigned partitions 와 Successfully joined group 이 번갈아 찍히고, 그 몇 초에서 몇 분 동안 아무도 메시지를 읽지 않습니다. 카프카 컨슈머 그룹 리밸런싱이 만드는 멈춤입니다.이 멈춤은 버그가 아닙니다. 고전(classic) 리밸런스 프로토콜이 일부러 세운 그룹 전체 동기화 장벽 때문에 생깁니다. 이 글은 그 장벽이 어디서 생기는지 요청 단위로 따라가고, 협력적(cooperative) 리밸런싱과 정적 멤버십이 장벽을 어떻게 줄였는지, 카프카 4.0 에서 GA 가 된 새 프로토콜(KIP-848)이 장벽을 어떻게 없앴는지 정리합니다.■ 1. 리밸런싱이 푸는..
자바 가상 스레드는 왜 가벼운가 — 마운트·피닝 원리 자바 21에서 가상 스레드(virtual thread)가 정식 기능이 됐습니다. "스레드를 백만 개 만들어도 된다"는 말이 함께 돌았습니다. 그런데 가상 스레드도 java.lang.Thread 입니다. 같은 클래스인데 왜 하나는 무겁고 하나는 가벼울까요. 답은 스레드의 스택이 어디에 있고, 누가 그 스레드를 CPU에 올리느냐에 있습니다. 이 글은 JEP 444와 OpenJDK 소스(VirtualThread.java, Poller.java)를 따라가며 가상 스레드가 멈췄다가 다시 도는 과정을 한 단계씩 풉니다.■ 1. 가상 스레드가 푸는 문제: 스레드 한 개 = OS 스레드 한 개기존 자바 스레드는 플랫폼 스레드입니다. new Thread() 하나가 OS 스레드 하나를 감쌉니다. 스레드의 일생 동안 OS ..
DNS 루트 KSK 교체·Bun AOT·C2y — 이번 주 IT 뉴스 어제(10월 11일) 인터넷의 맨 꼭대기 열쇠가 바뀌었습니다. DNS 루트 존이 이제 새 키 KSK-2024 하나로만 서명됩니다. 이번 주에는 이 소식 말고도 Bun 의 TypeScript AOT 컴파일 실험, 셸 설정 한 줄에 숨은 PATH 함정, C 표준의 정의되지 않은 동작(UB) 정리, Rust 와 다른 방식의 빌림 검사기, 작은 언어 모델로 "고르기만 하는" 결정 모델을 만드는 방법이 올라왔습니다. 개발자가 직접 확인하거나 써 볼 만한 것만 여섯 개 추렸습니다.■ 오늘 소식 한눈에소식 | 분야 | 한 줄 요약 | 영향받는 사람----------------------------------------------------루트 KSK 교체 완료 | 인프라·보안 | 10월 11일부터 루트 존이 KSK-..