푸른영혼의 별 | Tech Blog
Java Backend Engineer의 기술 블로그입니다.
Spring Boot, MSA, JPA, Kafka, Kubernetes 등 실무 경험을 공유합니다.
주요 프로젝트: Settlement MSA · ASAT · GitHub
Posts (총 261편 · 1 / 27 페이지)
-
-
-
*GitHub PAT 만료* 로 *13 pod* 가 *동시에 죽었다* — *GHCR 인증 사고* 와 *재발 방지 3 패턴*
“2 일 전 부터 *13 pod 가 ImagePullBackOff 였습니다”* — 우리 클러스터 의 모니터링 알림 이 조용히 누적 되다가 오늘 눈에 띄게 보였다.
원인 은 Kubernetes 도, Docker 도, ArgoCD 도 아니었다. GitHub Personal Access Token (PAT) 이 만료 된 것. 클러스터 의 *모든 namespace 에 동일한 ghcr-pull secret 이 수동 kubectl create 로 분산 되어 있어서, 그 토큰 만료 가 *체감 적으로 *13 pod 동시 죽음 으로 드러났다.
더 고통스러운 발견 : 다른 정상 동작 처럼 보이는 pod 들 도 같은 만료된 토큰 을 가지고 있었다. 그들은 *image 가 노드 에 *이미 cached 되어 있어 imagePullPolicy: IfNotPresent 덕분에 조용히 살아 있는 것. 다음 *rolling update / 노드 재시작 의 시점 에 전부 동시 죽을 시한 폭탄.
이 글은 그 사고 의 *진단 과정, 해결 의 즉시 조치, 그리고 *재발 방지 의 3 패턴 — SOPS+ArgoCD 분배, default ServiceAccount 자동 패치, Kyverno 자동화 (미래) — 를 현장 의 깊이 로 정리한다.
-
*아키텍처 *vs *SOLID *vs *의존성 역전 (DIP) *vs *의존성 주입 (DI)* — *4 개 가 *왜 *자꾸 *섞이는가*
“아키텍처 가 *중요하다” 와 “SOLID 를 *지켜야 한다” 와 “DIP 를 *적용 했다” 와 “Spring 의 *DI 를 *쓴다” 를 같은 *뜻 으로 말하는 사람과 *이 4 개 가 *서로 다른 *층 의 서로 다른 *개념 이라고 말하는 사람은 *PR 리뷰 를 완전히 다르게 *한다.
4 개 는 *서로 *포함 / 실현 / 근거 의 관계 다. 아키텍처 는 시스템 전체 의 경계와 흐름, SOLID 는 클래스/모듈 수준 의 5 가지 *설계 원칙, DIP 는 SOLID 의 *D — 추상화 의 *방향 에 대한 원칙, DI 는 DIP 를 *실현 하는 구현 기법 중 하나. 위 → 아래 로 추상도 가 *낮아지고 *구체성 이 *높아진다.
이 글은 4 개 의 *경계 를 그려 흔한 *오해 (예: “DI = DIP”, “SOLID = 아키텍처”, “Spring 쓰면 *아키텍처 좋아짐”) 를 분해 한다. Java + Spring 기준 예제 로 같은 *코드 가 4 개 *층 에서 각자 *무엇을 *해결 했는지 를 보인다.
-
*객체지향* 의 *핵심 가치* — *역할 · 책임 · 협력* 의 *진짜 의미* 와 *settlement 에서 의 *살아있는 적용***
“객체지향이 뭐예요?” 라고 물으면 대부분 “클래스, 상속, 다형성, 캡슐화” 라고 답한다.
그런데 알란 케이 (Alan Kay) — 객체지향이라는 단어를 만든 사람 은 말했다 :
“I’m sorry that I long ago coined the term ‘objects’ for this topic because it gets many people to focus on the lesser idea. The big idea is messaging.”
“오래전 ‘objects’ 라는 용어를 만든 것을 후회한다. 사람들이 *더 작은 개념 에 집중하게 만들었다. 진짜 큰 아이디어 는 *메시징”*
-
*객체 지향 개발* 에서 *테스트 를 학습* 한다는 것 의 *의미* — *JUnit 을 외우는 일* 이 아니라 *생각 의 형태 를 바꾸는 일**
“테스트 를 학습 한다” — 처음 듣는 신입 에게 이 말 은 JUnit 의 어노테이션 을 외우는 일 처럼 들린다.
@Test,assertEquals,Mockito.when().thenReturn()의 문법 학습.그러나 *9 년 을 지나고 보면 이 단어 의 *진짜 의미 는 전혀 다른 영역 에 있다. *테스트 를 배운다 는 것은 내 코드 의 *형태 자체 를 바꾸는 학습. 내 객체 가 *어떻게 *남과 대화 하는지, 어디서 *경계 가 깨지는지, 무엇이 *내 책임 이고 무엇이 *남의 책임 인지 를 눈에 보이는 형태 로 드러내는 학습*.
즉 *테스트 의 학습 은 객체 지향 의 학습 의 다른 이름.
-
*CPU 와 *DB* 의 *관계* — *메모리 와 *SSD* 를 *포함* 해서 *하드웨어 → 기계어 → 어셈블리 → 자바* 4 단 으로 *내려간다*
“DB 가 *느리다” 라고 말하는 사람과 *“이 SELECT 가 *L3 미스 → DRAM 1 회 + SSD random read 1 회 + JIT 컴파일 안 된 ResultSet 루프 라서 느리다” 라고 말하는 사람은 *프로파일러를 *완전히 다르게 *읽는다.
DB 한 줄 의 *결과 가 *Java 의 *Long id 에 들어오기까지 — CPU → L1 → L2 → L3 → DRAM → NVMe SSD → 페이지 캐시 → DB 버퍼풀 → JDBC → JIT → JVM Heap — 최소 8 개 의 *계층 을 통과 한다. 각 계층 의 지연 시간 (latency) 은 수십 배 / 수천 배 / 수십만 배 로 불연속 적 으로 튄다.
이 글은 그 한 줄 이 어떻게 *흐르는지 를 하드웨어 → 기계어 → 어셈블리 (x86-64) → 자바 (JDBC + JIT) 의 4 단 추상화 로 내려가 *분해 한다. 4 단 을 동시에 *볼 수 있게 되면 *프로파일러의 *flame graph 도, DB 의 *EXPLAIN ANALYZE 도, GC 로그 도 같은 *언어 로 읽힌다.
-
*APM* 과 *응답 시간 분포* — *백엔드 서버 개발자* 의 시각 에서 *왜 평균 이 거짓말 인가*
“우리 평균 응답 200ms 인데요”. 그런데 사용자 한 명 이 Slack 으로 “왜 *오늘 결제 가 *10 초씩 걸리냐” 한다.
둘 다 사실. 평균 이 200ms 라는 것 이 99 명 이 *50ms 인데 1 명 이 *15,000ms 라는 극단 적 분포 와 수학적 으로 동일 할 수 있다.
백엔드 서버 개발자 의 책임 은 평균 을 보는 것 이 아니라 *분포 를 보는 것. 그리고 *그 분포 의 *long tail 이 왜 길어졌는지 를 추적 가능 하게 만드는 것 — 그 도구 가 APM.
-
*Kubernetes 의 로드밸런서* — *L4 (Service) vs L7 (Ingress)* 의 *네트워크 계층* 과 *알고리즘 의 *진실*
L4 (Service) 의 kube-proxy 는 iptables 모드 = *랜덤 선택, IPVS 모드 = round-robin. L7 (Ingress) 의 nginx-ingress = round-robin, Traefik = weighted round-robin. 같은 “로드밸런서” 라도 계층과 도구 에 따라 알고리즘 이 다르다.* -
*AI 코드 PR* 머지 전, *7 가지 질문* — *vibe coding 의 *마지막 게이트***
AI 가 만든 코드의 PR 머지 전 던져야 할 7 가지 질문 — 신뢰할 수 없는 입력 / 동시 요청 / 경계값 / 외부 의존 다운 / 100만 건 데이터 / 도메인 규칙 / 로그·알람. Rule of thumb: “이게 운영에서 죽을 수 있는 5 가지 시나리오는?” — 머지 전 항상.