푸른영혼의 별 | Tech Blog
Java Backend Engineer의 기술 블로그입니다.
Spring Boot, MSA, JPA, Kafka, Kubernetes 등 실무 경험을 공유합니다.
주요 프로젝트: Settlement MSA · ASAT · GitHub
Posts (총 269편 · 3 / 27 페이지)
-
*kubectl run* 한 줄 의 *뒷 이야기* — *Scheduler · Kubelet* *두 개의 Watch-Reconcile 루프* 가 *느슨하게 *춤추는 방식*
kubectl run echo –image=… 한 줄. Enter. 몇 초 뒤 Pod 가 Running.
이 사이 에 무슨 일 이 일어나는가. 이 한 줄 이 왜 *Scheduler 와 Kubelet 사이 의 두 개의 *독립적 루프 로 처리* 되는가. 왜 그 둘 은 *서로를 직접 호출 하지 않는가. *왜 *어느 쪽이 죽어도 *다른 쪽 이 계속 * 인가.
-
*컨테이너 오케스트레이션* — *DEIS / Rancher / Mesos / Nomad / Swarm* 의 *전쟁사* 와 *우리 가 실제로 *쓰고 있는 *Kubernetes 의 *기능 들*
컨테이너 오케스트레이션 전쟁 (2014~2018) 의 5 후보 — 그리고 살아남은 K8s. 이 글은 그 *전쟁사 와 우리가 실제로 쓰는 K8s 의 기능 을 다룬다.* -
*쿠버네티스의 *논리적 단위 12종 — *Pod / ReplicaSet / Deployment / StatefulSet / DaemonSet / Job / Node / Namespace / Endpoint / Volume / Service / Ingress* 를 *한 장의 *지도* 로 *연결* 한다
쿠버네티스 의 *논리적 단위 — 좌측 워크로드 계열 (Pod / ReplicaSet / Deployment / StatefulSet / DaemonSet / Job), 우측 컨텍스트 계열 (Node / Namespace / Endpoint / Volume / Service / Ingress). 이 12 개 가 어떻게 *서로 참조 하고 어느 축 에 속하는지 를 분해 한다.* -
*쿠버네티스* 의 *유용성* — *온프레미스* 와 *클라우드* 의 *비대칭 비교*
“쿠버네티스 는 *클라우드 회사 가 *클라우드 회사 를 위해 *만든 *툴 인데, 왜 *내 *온프레미스 5 대 노드 에 *깔고 있을까?” — 이 질문 은 모순 처럼 보이지만 *사실은 *쿠버네티스 의 *진짜 매력 을 드러내는 질문 이다.
쿠버네티스 는 *2014 년 Google 에서 *Borg 의 오픈소스 자녀 로 세상 에 나왔다. 그래서 *클라우드 의 자식 처럼 보이지만, 그 본질 은 *추상화 그 자체 — “내 워크로드 가 *어떤 인프라 에서 돌든 *같은 방식 으로 기술 / 배포 / 운영 가능 하다”* 는 선언. 그 선언 이 *클라우드 에서 *극대화 되고 온프레미스 에서 *다른 종류의 가치 를 만든다*.
이 글은 온프레미스 K8s (k3s, kubeadm, RKE2, OpenShift) 와 클라우드 K8s (EKS, GKE, AKS) 의 유용성 을 *동일 한 7 가지 축 에서 비대칭 비교 한다. 내 6 노드 K3s 클러스터 운영 경험 + 클라우드 production 경험 을 교차해서 정리.
-
*보안* 의 *7 기둥* — *인증 / 인가 / 암호화 / 위변조 검증 / 방화벽 / 감사 로그 / 시큐어 코딩*
“보안 은 *문제 가 생긴 후에 *생각 하는 것” — 이 발상 자체 가 문제 의 시작 이다.
보안은 기능 이 아니라 속성. 한 번 *추가 하고 끝 나는 것이 아니라 모든 계층 에 *얇게 *스며들어야 하는 *횡단 관심사 (cross-cutting concern). 인증 가 *되어 있어도 *인가 가 *허술 하면 뚫리고, 인가 까지 다 잡았어도 *암호화 안 된 통신 으로 세션 토큰 이 새면 의미 없다.
그래서 보안은 7 가지 기둥 으로 각각 따로 *동시에 설 수 있어야 한다 — 어느 하나 가 무너져도 *다른 6 개 가 *받쳐주는 *defense in depth.
이 글은 백엔드 개발자 의 *현실적 관점 에서 7 기둥 각각 의 *왜 → 어떻게 → Spring Boot 코드 → 함정 까지 체계적 으로 *분해 한다.
-
*논블로킹 I/O 서버* — *C10K* 부터 *Reactor 패턴*, *epoll / io_uring*, *Netty / Node.js / Nginx* 까지
“왜 *Node.js 는 *싱글 스레드 인데 동시 접속 10 만 을 처리 하는가?”* — 이 질문 의 답 은 Node.js 가 아니라 그 아래 의 *epoll 에 있다.
블로킹 I/O 서버 는 “1 connection = 1 thread” 라는 직관적 모델 위에서 만들어졌다. 2000 년대 초 까지 그것 으로 충분 했다. 그런데 *C10K (concurrent 10,000 connections) 가 현실 이 되자 그 모델 은 *벽 에 부딪쳤다. 스레드 1 만 개 의 컨텍스트 스위치 와 스택 메모리 가 서버 를 *죽였다.
논블로킹 I/O 서버 는 완전히 다른 철학 으로 답했다. “스레드 가 *I/O 를 기다리지 않게 한다” — event loop 하나 가 수만 connection 을 돌아가며 *상태 확인, 준비 된 것만 처리. Nginx 의 *4 worker 가 *10 만 동시 접속 을 처리하는 물리적 근거.
이 글은 C10K 문제 → select/poll/epoll/kqueue/io_uring 진화 → Reactor 패턴 → Netty/Node.js/Nginx 구현 → 백프레셔 → Virtual Thread 와 의 비교 까지 논블로킹 I/O 서버 의 *모든 층 을 분해 한다.
-
*Prometheus* 가 *수집* 하고 *Grafana* 가 *대답* 한다 — *서버 죽었나?* 5 가지 질문 의 *PromQL + 대시보드*
“지금 서버가 죽었나?” — 새벽 3 시 에 이 질문 에 5 초 안 에 답할 수 있어야 운영 이다.
Prometheus 와 Grafana 의 짝 은 그 질문 의 표준 답 이 되었다. 그런데 둘이 어떻게 협업 하는지 — Prometheus 가 *무엇 을 *어떻게 수집 하고, Grafana 가 *그것 을 *어떻게 *질문 으로 변환 하는지* — 를 *모르면 대시보드 는 *예쁜 그래프 의 *모음 일 뿐, 진짜 질문 에 *답하지 못한다.
이 글은 8 가지 핵심 메트릭 (CPU / Memory / Disk / HTTP 요청 수 / 에러율 / 응답 시간 / DB 커넥션 / 컨테이너 상태) 이 Prometheus 로 *어떻게 수집 되는지, 그리고 Grafana 가 *5 가지 운영 질문 — 지금 서버가 죽었나? CPU 가 너무 높나? 응답이 느려졌나? 에러율이 올라갔나? 트래픽이 늘었나? — 에 어떻게 답하는지 를 PromQL 한 줄 한 줄 까지 분해 한다.
-
*Virtual Thread* 와 *Carrier Thread* 의 *관계* — *mount / unmount* 메커니즘 과 *pinning* 의 *물리*
“Virtual Thread 는 경량 스레드 다” — 맞는 말 이지만 반쪽 짜리 설명 이다. Virtual Thread 가 *경량 인 이유 는 그 자체로 *가벼워서 가 아니라 실제로 *CPU 를 *돌리는 스레드 가 *따로 있기 때문 이다.
그 따로 있는 스레드 가 Carrier Thread — 플랫폼 스레드 (전통적인 OS 스레드) 의 작은 풀. 수십만 개 의 Virtual Thread 가 수십 개 의 Carrier Thread 위에서 돌아 가며 *마운트 / 언마운트 된다.
이 마운트 / 언마운트 가 *어떻게 작동 하는지 모르면 —
synchronized하나 가 전체 carrier pool 을 잠궈서 Virtual Thread 의 *모든 이점이 *사라지는 *pinning 의 물리적 이유 를 이해 할 수 없다.이 글은 JDK 21 (JEP 444 finalized) ~ JDK 24 (JEP 491) 기준 으로 Virtual Thread 와 *Carrier Thread 의 관계 — Continuation primitive, mount/unmount 시점, pinning 의 *원인 과 *처방, carrier pool 크기, 실전 안티 패턴 — 까지 런타임 관점 에서 분해 한다.
-
*I/O 병목* 어떻게 *해결* 하지? — *디스크 / 네트워크 / DB* 의 *공통 패턴* 과 *층별 처방*
“코드 는 *맞는데 느리다”* — 백엔드 가 *느린 *원인 의 *90% 는 연산 이 *아니라 *I/O 다.
디스크 읽기 80 μs. DB 쿼리 한 번 5 ms. HTTP 외부 호출 한 번 50 ms. CPU 가 *0.25 ns 안에 한 사이클을 도는 4 GHz 시대 에 I/O 한 번 은 수십만 ~ 수억 사이클 을 기다리는 일 이다.
그런데 I/O 병목 은 CPU 처럼 *한 가지 자원 이 아니다. 디스크 / 네트워크 / 데이터베이스 / 파일시스템 / 메모리 매핑 — 서로 다른 *물리적 자원 이 서로 다른 *방식으로 *터지고, 해결책 도 각자 *다르다.
이 글은 I/O 병목 의 *6 가지 패턴 을 진단 → 원인 → 처방 으로 정리하고, Spring Boot / JVM 워크로드 에서 실제로 손이 가는 *해결책 을 층별 로 분해한다.
-
*프로세스* 라는 *추상화* — *CPU · 메모리 · 스레드 · 코어* 가 *어떻게 한 점* 에서 만나는가
CPU 에서 시작 해 보자. 성능 코어 8 + 효율 코어 4. 메인보드 의 *커패시터 는 수명 을 결정한다. *메모리 는 휘발성 이지만 수십 년 가는 반도체. 프로그램 은 디스크 위의 파일. 그런데 — 파일 이 어떻게 동작 하는가. 디스크 의 *바이트 더미 가 어떻게 *키 입력 에 반응 하고 네트워크 패킷 을 받아 *DB 에 쓰는 동적 존재* 가 되는가.
그 변환점 이 프로세스. 정적 파일 → 동적 실행 의 경계. 그리고 *프로세스 안 에서 스레드 가 진짜 일 을 코어 에 던진다.