Spring과 JVM 백엔드
주제 허브

프레임워크 뒤에서 무슨 일이 벌어지는지 설명할 수 있나

Spring과 JVM 백엔드

빈 생명주기와 프록시, 트랜잭션 이벤트, 배치 청크와 힙 덤프, ArchUnit으로 세운 가드레일. 스프링을 쓰는 글이 아니라 스프링이 왜 그렇게 동작하는지 파헤친 글을 모은다.

93편 직접 만들고 재 본 것 73 기술 블로그 리뷰 9 컨퍼런스 발표 리뷰 11 최근 글

직접 만들고 재 본 것

73편
  1. spring-internals-lab로 다시 읽는 Spring 1 - 이 프로젝트는 무엇을 검증하려는가
  2. Heap Dump가 가리킨 곳은 데이터가 아니라 영속성 컨텍스트였다: Tasklet에서 Chunk로, XSSF에서 SXSSF로
  3. 위반 480건 위에 아키텍처 규칙을 도입하기: 신규 코드는 100% 강제, 레거시는 점진 정리
  4. 왜 이벤트가 안 먹히지? @TransactionalEventListener가 무시되는 이유와 해결법
  5. 무너지는 Spring 서버 1 - CPU는 놀고 있는데 API가 느리다: 업스트림 하나가 무관한 엔드포인트를 죽이는 과정을 thread dump 세 장으로 읽기
  6. 커넥션과 세션 - 커넥션 풀이 실제로 아끼는 것
  7. 클래스 로딩과 기동 시간 - 리플렉션의 비용과 AOT가 바꾸는 것
  8. spring-internals-lab로 다시 읽는 Spring 2 - BeanDefinition과 등록 단계
  9. spring-internals-lab로 다시 읽는 Spring 5 - Bean lifecycle과 후처리기
  10. spring-internals-lab로 다시 읽는 Spring 4 - 의존성 주입과 후보 선택
  11. spring-internals-lab로 다시 읽는 Spring 8 - DispatcherServlet과 MVC 요청 흐름
  12. spring-internals-lab로 다시 읽는 Spring 6 - 프록시와 AOP
  13. spring-internals-lab로 다시 읽는 Spring 3 - refresh()와 Bean 생성 파이프라인
  14. spring-internals-lab로 다시 읽는 Spring 9 - Spring Boot는 무엇을 자동으로 조립하는가
  15. spring-internals-lab로 다시 읽는 Spring 7 - @Transactional의 실체
  16. 리액티브와 백프레셔 - WebFlux가 해결하는 것과 옮기는 것
  17. JIT 컴파일 - 계층 컴파일, 인라이닝, 역최적화
  18. spring-lite로 이해하는 Spring 구현 5 - MiniSpringApplication과 자동 설정 조립 방식
  19. 모듈러 모놀리스 - 경계를 코드로 강제하는 방법
  20. spring-lite로 이해하는 Spring 구현 4 - DispatcherServlet과 MVC 요청 처리 파이프라인
  21. spring-lite로 이해하는 Spring 구현 3 - ProxyFactory, @Transactional, JdbcTemplate 연결
  22. spring-lite로 이해하는 Spring 구현 2 - AnnotationConfigApplicationContext로 보는 IoC와 생명주기
  23. spring-lite로 이해하는 Spring 구현 1 - 프로젝트 구조와 설계 범위
  24. 시크릿 관리 - 로테이션과 주입 경로
  25. 가상 스레드를 켜서 37배 느려진 엔드포인트 - 핀닝과 상한 없는 admission을 재다
  26. Security 필터 체인 - 인증과 인가는 실제로 어디에 꽂히는가
  27. G1과 ZGC가 p99에 남기는 차이 - 300배 짧은 pause가 꼬리의 11%를 가져갔다
  28. GC 알고리즘 비교 - G1, ZGC, Shenandoah가 각자 무엇을 포기하는가
  29. 모듈식 모놀리스를 선택한 이유 — MSA의 유혹을 거부하기
  30. Spring Batch의 구조 - 청크, 파티셔닝, 재시작과 메타데이터
  31. 가상 스레드의 내부 - 스케줄러와 캐리어, 핀닝, 그리고 쓰지 않아야 할 때
  32. 프록시의 한계 - self-invocation, final, JDK와 CGLIB의 선택
  33. 동시성 도구의 비용 - synchronized, ReentrantLock, CAS가 경쟁에서 갈리는 지점
  34. ParityPay로 검증하는 결제 정합성 2 - 잠금을 필요 이상으로 오래 쥐고 있었다: 추론을 측정으로 바꾼 기록
  35. JWT의 구조와 검증 - 서명 알고리즘, 만료, 그리고 폐기의 한계
  36. 트랜잭션 전파 7종 - 각 옵션이 커넥션과 롤백에 남기는 결과
  37. 자바 메모리 모델 - happens-before, volatile, 그리고 final의 안전 공개
  38. 대량 배치 안정성을 높이기 위한 구조 개선: Part 1 - 시스템을 압박하기 시작한 배치
  39. 대량 배치 안정성을 높이기 위한 구조 개선: Part 2 - 전체 삭제 후 전체 등록 구조의 위험성
  40. 대량 배치 안정성을 높이기 위한 구조 개선: Part 3 - 청크 분할과 병렬 처리로 재설계하기
  41. 대량 배치 안정성을 높이기 위한 구조 개선: Part 4 - 분산 락이 있어도 레이스가 발생한 이유
  42. 대량 배치 안정성을 높이기 위한 구조 개선: Part 5 - 배타적 락과 조건부 해제로 순서를 보장하기
  43. 대량 배치 안정성을 높이기 위한 구조 개선: Part 0 - 왜 이 배치는 가끔 터질까?
  44. Shadow Release로 조회를 옮기기: MyBatis 결과와 QueryDSL 결과를 나란히 비교하며 전환한 기록
  45. 모든 도메인이 100% 정합성을 요구하지는 않는다: Post-Commit 이벤트와 재시도 3회 정책을 정한 기준
  46. 폴링 배치를 SQS 이벤트 파이프라인으로 바꾼 이유: 재시도, DLQ, 메시지 ID 멱등
  47. 정산이 진행되는 동안 기준 데이터 수정을 막는 방법: 상태 플래그와 AOP로 만든 경량 락
  48. @RestController는 무엇을 의미하는가
  49. @SpringBootApplication은 실제로 무엇을 하는가
  50. Spring Boot DevTools를 언제 써야 하는가
  51. Java의 Garbage Collection을 어떻게 이해해야 할까
  52. Spring Bean Lifecycle 정리
  53. 대용량 지분율 데이터 처리 성능 개선과 동시성 제어 전략
  54. JSP 기반 시스템의 구조적 문제를 해결한 아키텍처 전환기: MyBatis와 JPA 공존 환경의 데이터 정합성 전략
  55. 백엔드 시스템 로깅 베스트 프랙티스
  56. @TransactionalEventListener 빠른 체크 노트
  57. Spring에서 이해해야 할 JPA 아키텍처
  58. Spring에서 Java 21을 도입할 때 체크할 것
  59. JVM은 무엇을 하는가
  60. Statement와 PreparedStatement는 무엇이 다른가
  61. Spring AOP 핵심 정리
  62. @ControllerAdvice와 @RestControllerAdvice 정리
  63. Spring Data JPA에서 동적 쿼리를 다루는 방법
  64. Spring 예외 처리 전략 정리
  65. Spring 애플리케이션에서 예외를 설계하는 방법
  66. Filter, Interceptor, AOP의 차이와 선택 기준
  67. Spring과 JPA에서 Race Condition을 다루는 방법
  68. Spring의 IoC와 DI를 어떻게 이해할 것인가
  69. Spring 애플리케이션에서 페이지네이션을 설계하는 방법
  70. Querydsl을 사용하는 이유와 기본 패턴
  71. Connection Pool
  72. GraphQL with Spring Boot
  73. Spring Boot에서 외부 API 연동을 설계할 때 보는 것

기술 블로그 리뷰

9편
  1. 네이버 D2 「@RequestCache: HTTP 요청 범위 캐싱을 위한 커스텀 애너테이션 개발기」 리뷰 — 캐시의 수명을 '요청 하나'로 맞추면 TTL 고민이 사라진다, 그리고 @RequestScope가 안 되는 이유
  2. 우아한형제들 「Spring Batch와 Querydsl」 리뷰 — offset을 버린 Reader가 21분을 4분으로 만든 이유, 그리고 그 Reader가 답하지 않는 두 가지
  3. 컬리 「컬리의 입고 시스템이 외부 인입 데이터를 안전하게 동기화하는 방법」 리뷰 — 145회 재시도가 맞는 도메인과 재시도를 금지한 도메인, 그리고 발행부와 수신부가 각자 책임지는 구조
  4. 카카오 「잃어버린 리포트를 찾아서: 카카오 메시징 시스템의 경쟁 조건 문제와 안티 패턴 제거 과정」 리뷰 — 벤더가 8ms 만에 리포트를 보냈고, 우리는 101ms짜리 트랜잭션 안에 있었다
  5. 카카오 「메시징 서버의 스트레스 테스트 노하우와 AI가 덜어 준 부분」 리뷰 — 지표를 네 층으로 내려가 읽는 법, 그리고 LLM에게 맡긴 것과 맡기지 못한 것
  6. 야놀자 「RESTful API validation 자동화 하기」 리뷰 — 인터페이스 하나에서 검증·문서·타입을 뽑는 이유, 그리고 자동화가 없으면 누락이 필연이라는 문장
  7. 네이버 D2 「스마트스토어센터 Oracle에서 MySQL로의 무중단 전환기」 리뷰 — 두 DB에 동시에 쓰되 한쪽 실패는 무시하고, 읽기 트래픽을 복제해 성능을 재고, 6개월간 불일치를 0으로 만든 과정
  8. 네이버 D2 「CDC 복제 이후 오라클이 느려졌다? child cursor 폭증이 만든 예상치 못한 문제」 리뷰 — 같은 SQL인데 바인딩 타입이 다르면 Oracle은 다른 쿼리로 본다
  9. 카카오 「추가배포 없이 API의 case 통일시키기」 리뷰 — 받는 쪽이 자기 케이스에 맞춰 알아서 읽게 하면 배포 순서가 사라진다

컨퍼런스 발표 리뷰

11편
  1. SLASH 22 리뷰 - Java Native Memory Leak 원인을 찾아서: RSS와 NMT의 2GB 차이, jemalloc 프로파일, C2 컴파일러, Graal JIT
  2. TMC 25 리뷰 - '주식모으기' 서비스로 살펴보는 대용량 트래픽 처리 노하우: 200만 주문을 3,000건으로 접는 풀링 주문과 그 대가
  3. SLASH 24 리뷰 - 대규모 사용자 기반의 마이데이터 서비스 안정적으로 운영하기: 클러스터 단위 서킷 코디네이터, 웹소켓 얼리 리턴, 7일 배치 분산
  4. SLASH 24 리뷰 - Next 코어뱅킹, MSA와 MySQL로 여는 평생 무료 환전 시대: Oracle을 버린 이유, 30ms 환전, 자정에도 멈추지 않는 잔액 대사
  5. SLASH 23 리뷰 - 프로파일러로 시스템 성능 향상시키기: Pinpoint, 힙 덤프, jemalloc, async-profiler, strace, 그리고 커널 버전
  6. SLASH 23 리뷰 - 연결되면 비로소 보이는 것들: Pinpoint 코루틴 플러그인을 만들기 위해 코루틴 바이트코드를 읽다
  7. SLASH 23 리뷰 - 토스뱅크의 모던 FEP: 전문을 Kotlin 어노테이션으로, 리플렉션 코덱, Netty 논블로킹, Redis 폴링으로 액티브-액티브
  8. SLASH 22 리뷰 - 토스뱅크의 완전히 새로운 대출 시스템: Flyway + Hibernate validate, 대외기관 파이프라인, 연동 서킷과 대기열
  9. SLASH 21 리뷰 - 토스 서비스를 구성하는 서버 기술: 두 데이터센터 사이의 트래픽 이동, Istio 도입 후 남은 것, Kafka 두 클러스터
  10. SLASH 21 리뷰 - 테스트 커버리지 100%: 두 달의 비용, 1600개 테스트를 6초로, 그리고 100%여도 남는 버그
  11. SLASH 21 리뷰 - SRE 사례 소개: Redis 리밸런싱 ASK 에러, Memcached 재분배 실패, Prometheus가 바꾼 GC 패턴