> ## Documentation Index
> Fetch the complete documentation index at: https://blog.nvim.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Spring Boot 글은 어디부터 읽으면 좋을까요?

> Spring과 Spring Boot를 처음 만날 때 헷갈리는 지점을, 객체 생성부터 자동 설정과 운영 흐름까지 한 줄로 이어서 읽는 입구예요.

> Spring Boot는 편한데, 편한 만큼 **내가 안 한 일을 누가 했는지**가 잘 안 보일 때가 있어요.

컨트롤러 하나 만들었을 뿐인데 서버가 뜨고, JSON이 나가고, 설정 파일이 읽히고, 데이터베이스 연결까지 준비되는 장면을 보면 이런 생각이 들죠.

> "이거 편하긴 한데, 내부에서 뭐가 움직이는 거지?"

이 Spring Boot 글들은 그 질문을 따라가려고 만든 길이에요. Annotation 이름을 먼저 외우기보다, **내가 작성한 코드**와 **Spring Boot가 대신 준비한 일**을 나눠서 보는 데 집중할게요.

처음 읽는 분은 "아, 그래서 서버가 뜨는구나" 정도만 잡아도 충분해요. 하지만 이 카테고리는 거기서 멈추지 않을 거예요. 같은 장면을 한 번 더 내려가서 **누가 결정했는지**, **어느 시점에 객체가 만들어지는지**, **어떤 경계에서 기대와 다르게 동작하는지**, **실무에서는 무엇을 확인해야 하는지**까지 같이 볼 거예요.

***

## 지금은 여기서 시작하면 돼요

글이 많아 보여도 앞에서 잡은 개념이 뒤 글의 기준점이 되도록 이어져 있어요. 처음이라면 아래 순서대로 읽는 흐름이 가장 자연스러워요.

* [왜 Spring과 Spring Boot가 필요했을까요?](/spring-boot/why-spring-and-boot-exist)\
  객체를 직접 만들고 연결하던 코드가 왜 Spring 컨테이너로 옮겨갔는지, 그리고 Spring Boot가 어떤 반복 설정을 덜어주는지 큰 그림부터 잡아요.

* [Spring Boot 프로젝트는 처음에 무엇을 만들어줄까요?](/spring-boot/spring-boot-init-and-project-shape)
  Spring Initializr와 `spring init`으로 만든 첫 프로젝트의 선택지, 빌드 파일, `main` 클래스, 패키지 구조, DevTools의 역할을 살펴봐요.

* [IoC, DI, AOP는 왜 Spring을 읽는 세 가지 기준점일까요?](/spring-boot/spring-three-principles-ioc-di-aop)
  제어의 역전, 의존성 주입, 관점 지향 프로그래밍을 어려운 정의보다 먼저 코드 책임의 이동으로 잡아봐요.

* [main 메서드 하나가 어떻게 실행 중인 앱이 될까요?](/spring-boot/main-method-to-running-app)
  `SpringApplication.run`이 환경을 준비하고 컨테이너를 만들고 웹 서버를 띄우는 큰 흐름을 따라가요.

* [ApplicationContext와 Bean은 왜 Spring이 소유한 객체일까요?](/spring-boot/application-context-and-beans)
  Spring 컨테이너가 빈 정의를 모으고 실제 객체를 만들고 연결하는 흐름을, 생명주기와 scope까지 이어서 살펴봐요.

* [컴포넌트 스캔과 Bean 등록은 왜 가끔 내 클래스를 못 찾을까요?](/spring-boot/component-scan-and-bean-registration)
  컴포넌트 스캔, `@Bean`, 조건부 등록이 각각 어떤 방식으로 빈을 등록하는지 보고, Spring Boot가 클래스를 못 찾는 흔한 이유를 정리해요.

* [의존성 주입은 실제 코드에서 어떻게 읽어야 할까요?](/spring-boot/dependency-injection-in-real-code)
  생성자 주입, 선택적 의존성, 여러 빈 후보, 순환 의존성을 실제 서비스 코드 흐름으로 읽고 field injection이 오래 갈수록 불리해지는 이유를 살펴봐요.

* [AOP 프록시와 Annotation은 왜 기대와 다르게 동작할까요?](/spring-boot/aop-proxy-and-annotation-behavior)
  `@Transactional` 같은 Annotation이 단순한 표시가 아니라 프록시를 통과하는 호출에서 동작하는 이유와 self-invocation 함정을 살펴봐요.

* [스타터와 자동 설정은 왜 버전과 설정을 대신 맞춰줄까요?](/spring-boot/auto-configuration-and-starters)
  starter, BOM, dependency management, auto-configuration, 조건 평가 리포트를 통해 의존성 하나가 어떻게 실행 설정으로 이어지는지 살펴봐요.

* [application.yml과 profile은 설정을 어떻게 바꿔줄까요?](/spring-boot/configuration-properties-profiles-and-secrets)
  외부 설정, Config Data, profile, 환경 변수, Configuration Properties, 검증, secret 경계를 한 흐름으로 읽어봐요.

* [Spring Boot 4와 3은 무엇이 달라졌을까요?](/spring-boot/boot-4-and-boot-3-baseline-map)
  Spring Boot 4.x와 3.5.x의 기준선을 Java, Spring Framework, Jakarta EE, Servlet 컨테이너, starter, 테스트 의존성 관점에서 비교해요.

* [웹 요청은 Spring MVC 안에서 어떤 순서로 지나갈까요?](/spring-boot/web-request-lifecycle-mvc)
  DispatcherServlet, HandlerMapping, argument resolution, validation, HttpMessageConverter, exception handling까지 Spring MVC 요청 흐름을 한 번에 따라가요.

* [REST API 설계와 에러 계약은 왜 컨트롤러 코드보다 먼저일까요?](/spring-boot/rest-api-design-and-error-contracts)
  DTO, request와 response 모양, Bean Validation, Problem Details, error code, API versioning을 클라이언트와 서버의 약속으로 읽어봐요.

* [JSON과 Jackson 3는 왜 API 호환성의 핵심일까요?](/spring-boot/json-jackson3-and-migration-from-jackson2)
  Spring Boot 4.x의 Jackson 3 기본 흐름, JsonMapper, Jackson 2 마이그레이션, 날짜와 enum과 unknown field가 API 계약에 주는 영향을 살펴봐요.

* [Todo API 첫 커밋은 어떻게 차근차근 만들까요?](/spring-boot/source-backed-todo-api-first-commit)
  Spring CLI로 Java 21, Gradle wrapper 기반 프로젝트를 만들고 생성된 파일 확인부터 controller, service, repository, validation, 테스트까지 첫 커밋 흐름으로 따라가요.

* [Spring MVC와 WebFlux는 언제 다르게 선택해야 할까요?](/spring-boot/spring-mvc-vs-webflux)
  Spring MVC와 WebFlux를 구버전/신버전 관계가 아니라 blocking I/O, non-blocking I/O, thread model, 라이브러리 선택의 차이로 읽어봐요.

* [WebSocket과 STOMP는 언제 실시간 연결에 필요할까요?](/spring-boot/websocket-and-stomp)
  HTTP 요청-응답과 오래 열린 WebSocket 연결의 차이, STOMP destination, message broker, `@MessageMapping`, SockJS fallback을 Spring Boot 흐름으로 읽어봐요.

* [RestClient, WebClient, HTTP Interface는 언제 다르게 써야 할까요?](/spring-boot/http-clients-restclient-webclient-http-interface)
  서버가 다른 서버를 호출할 때 `RestClient`, `WebClient`, HTTP Interface를 어떻게 고르고, timeout과 retry를 어디에 두어야 하는지 outbound API 경계로 읽어봐요.

* [데이터 접근은 JDBC, JPA, R2DBC 중 무엇을 골라야 할까요?](/spring-boot/data-access-map-jdbc-jpa-r2dbc)
  JDBC와 `JdbcClient`, Spring Data JDBC, JPA, Spring Data repository, R2DBC를 최신순이 아니라 문제 모양과 실행 모델로 고르는 법을 살펴봐요.

* [JPA Entity 상태와 영속성 컨텍스트는 왜 헷갈릴까요?](/spring-boot/jpa-entity-state-and-persistence-context)
  Entity가 새 객체, 관리되는 객체, 분리된 객체, 삭제 예정 객체로 바뀌는 흐름을 영속성 컨텍스트, dirty checking, lazy loading, N+1, auditing과 함께 읽어봐요.

* [트랜잭션 경계와 롤백은 왜 Annotation 하나로 끝나지 않을까요?](/spring-boot/transaction-boundaries-and-rollback)
  `@Transactional`이 시작되는 위치, commit과 rollback이 결정되는 시점, propagation과 self-invocation이 기대를 흔드는 이유를 service 경계와 테스트까지 이어서 살펴봐요.

* [Schema migration은 왜 Flyway와 Liquibase로 관리할까요?](/spring-boot/schema-migration-flyway-liquibase)
  테이블과 컬럼 변경을 서버 코드처럼 버전으로 남겨야 하는 이유를 Flyway, Liquibase, migration history, 배포 순서, rollback 기대까지 이어서 살펴봐요.

* [복잡한 query는 Querydsl과 Specification 중 무엇으로 풀어야 할까요?](/spring-boot/querydsl-specification-and-complex-query)
  Spring Data JPA에서 derived query method, `@Query`, Specification, Querydsl을 언제 나눠 쓰는지 검색 조건, join, pagination, sorting 경계로 살펴봐요.

* [Redis cache와 session은 왜 성능을 올리면서 버그도 만들까요?](/spring-boot/redis-cache-and-session)
  Spring Boot에서 Redis cache와 Spring Session Redis를 같은 저장소처럼 보되, TTL, invalidation, key prefix, 분산 session 경계로 나누어 읽어봐요.

* [MongoDB와 Elasticsearch는 왜 JPA보다 빠른 DB가 아닐까요?](/spring-boot/mongodb-elasticsearch-and-nosql-boundaries)
  MongoDB, Elasticsearch, document model, search index를 JPA 대체재가 아니라 서로 다른 데이터 문제를 푸는 도구로 나누어 읽어봐요.

* [Spring Security는 왜 filter chain부터 봐야 할까요?](/spring-boot/spring-security-filter-chain-first)
  Spring Boot에 Security starter를 넣었을 때 모든 요청이 왜 갑자기 잠기고, 인증과 인가와 CSRF와 CORS가 filter chain 안에서 어떻게 나뉘는지 살펴봐요.

* [JWT와 OAuth2 Resource Server는 왜 로그인 구현과 다를까요?](/spring-boot/jwt-oauth2-and-resource-server)
  JWT access token, OAuth2 login, resource server, issuer, JWK Set, scope, refresh token 경계를 Spring Security 요청 흐름으로 나누어 읽어봐요.

* [Method Security와 도메인 권한은 어디에 둬야 할까요?](/spring-boot/method-security-and-domain-permission)
  URL 규칙만으로 부족해지는 소유권 검사, method security, `@PreAuthorize`, `@PostAuthorize`, 도메인 권한 판단을 service 경계에서 읽어봐요.

* [Auth API는 실무 프로젝트처럼 어떻게 설계할까요?](/spring-boot/source-backed-auth-api)
  Spring Boot 4와 Java 21로 회원가입, Basic 자격 증명 교환, JWT Bearer 보호 API, refresh token 회전, JDBC 저장소, ProblemDetail을 구현하고 공개 저장소의 실행 가능한 코드와 15개 테스트로 확인해요.

* [테스트는 unit, slice, integration을 어떻게 나눠야 할까요?](/spring-boot/testing-map-unit-slice-integration)
  Spring 없는 unit test, MVC와 JDBC slice, 전체 bean graph를 여는 integration test, 실제 port를 여는 server test가 각각 무엇을 증명하고 놓치는지 살펴봐요.

* [Testcontainers와 WireMock은 무엇을 진짜로 바꿔줄까요?](/spring-boot/testcontainers-wiremock-and-contract-tests)
  실제 PostgreSQL을 띄우는 Testcontainers, 외부 HTTP를 재현하는 WireMock, 서비스 사이 약속을 검증하는 contract test를 서로 다른 test 경계로 나누어 읽어봐요.

* [Actuator의 health와 metrics는 운영에서 무엇을 알려줄까요?](/spring-boot/observability-actuator-health-metrics)
  Health, info, metrics, Prometheus endpoint를 서로 다른 운영 질문으로 나누고, liveness와 readiness와 안전한 공개 범위를 살펴봐요.

* [Micrometer tracing과 correlation ID는 한 요청을 어떻게 찾을까요?](/spring-boot/micrometer-tracing-logs-and-correlation-id)
  Metric에서 발견한 이상 징후를 trace와 log로 좁히고, trace ID, span ID, MDC, context propagation, sampling으로 여러 service를 지난 요청 하나를 찾아가요.

* [Auth API에 metrics와 tracing을 실제로 어떻게 붙일까요?](/spring-boot/source-backed-observability-api)
  기존 Auth API에 Actuator, Prometheus Counter, OpenTelemetry tracing, Jaeger, 작은 downstream을 붙이고, async context 단절과 장애 추적을 실제 실행 결과로 확인해요.

* [Application Event는 같은 앱 안에서 무엇을 느슨하게 만들까요?](/spring-boot/application-events-internal-messaging)
  `ApplicationEventPublisher`, `@EventListener`, `@TransactionalEventListener`로 component를 분리하고, 동기 실행과 transaction phase와 전달 한계를 함께 살펴봐요.

* [Kafka와 RabbitMQ는 event를 어떻게 다르게 전달할까요?](/spring-boot/messaging-kafka-rabbitmq-and-events)
  Spring Boot에서 process 밖으로 message를 보내고, Kafka의 partition과 RabbitMQ의 exchange·queue를 비교하면서 idempotency, retry, dead-letter, ordering을 함께 설계해요.

새 글도 앞선 내용을 길게 반복하기보다, “누가 결정했고, 언제 실행됐고, 어느 경계에서 기대와 달라졌는가?”라는 질문을 이어갈게요.

***

## 이 길에서 계속 붙잡을 질문

Spring Boot를 읽을 때는 기능 이름보다 질문을 먼저 잡는 편이 덜 헷갈려요.

* 내가 만든 클래스는 누가 객체로 만들까요?
* 필요한 객체는 누가 생성자에 넣어줄까요?
* `main` 메서드 하나가 왜 웹 서버 시작으로 이어질까요?
* 스타터(starter)를 넣으면 왜 여러 라이브러리가 같이 따라올까요?
* 자동 설정(auto-configuration)은 언제 적용되고, 언제 물러날까요?
* 테스트에서는 왜 실행할 때와 다른 컨텍스트가 뜰까요?
* Annotation 하나를 붙였는데 실제로는 프록시(proxy), 조건(condition), 컨텍스트(application context) 중 어디가 움직인 걸까요?
* 운영에서 문제가 났을 때 로그, 설정, 빈 목록, 조건 평가 리포트 중 무엇부터 봐야 할까요?

이 질문들이 뒤 글들의 기준점이 될 거예요.

```mermaid theme={null}
flowchart LR
    A[내가 작성한 코드<br /><small>Controller, Service, Repository</small>]
    B[Spring 컨테이너<br /><small>객체 생성과 연결</small>]
    C[Spring Boot<br /><small>스타터와 자동 설정</small>]
    D[실행 중 애플리케이션<br /><small>요청 처리와 운영</small>]

    A --> B --> C --> D
```

이 그림의 핵심은 역할 분리예요. 개발자는 애플리케이션의 행동을 쓰고, Spring은 객체를 만들고 연결하고, Spring Boot는 반복되는 설정과 실행 기본값을 준비해요.

***

## 자, 정리해볼까요?

<Info title="Spring Boot 글은 이렇게 읽으면 돼요">
  * 처음이라면 위 목록을 차례대로 읽는 게 가장 자연스러워요.
  * 이 카테고리는 Annotation 암기보다 **프레임워크가 대신 한 일**을 보이게 만드는 데 집중해요.
  * 각 글은 쉬운 장면에서 시작하되, 나중에 인용해도 버틸 수 있도록 메커니즘과 실패 경계까지 함께 남겨요.
  * 실제 파일명은 번호 없는 안정적인 slug를 쓰고, 읽는 순서는 `docs.json`의 navigation에서 관리해요.
</Info>

그럼 첫 글부터 시작해볼까요?

<a href="/spring-boot/why-spring-and-boot-exist">첫 글 읽기</a>
