본문 바로가기

Spring Boot의 역할

Spring Boot가 서버·의존성·자동 구성·외부 설정을 조립하는 방식과 재정의 경계를 이해합니다.

Spring Framework는 객체를 만들고 연결하는 컨테이너와 웹 MVC 같은 핵심 기능을 제공합니다.

그러나 내장 웹 서버, 라이브러리 버전 조합, JSON 변환기, 설정 파일, 실행 JAR까지 개발자가 하나씩 연결하면 첫 프로젝트를 띄우기 전에 결정할 일이 많습니다.

Spring Boot는 Spring 애플리케이션을 빠르게 시작할 수 있도록 검증된 의존성 조합과 기본 설정을 제공하는 도구입니다.

스타터는 한 기능에 필요한 라이브러리를 묶고, 자동 구성은 클래스 경로·설정·사용자 빈을 보고 필요한 기본 빈을 등록합니다.

Boot가 Spring을 대체하는 것은 아닙니다.

Spring 위에서 반복 조립을 줄이고, 애플리케이션이 필요한 부분만 빈이나 속성으로 바꾸게 합니다.

BOOT · INPUTS AND CONDITIONAL DEFAULTS

자동 구성은 입력 조건에 맞는 기본값을 제안한다

Boot는 Spring의 반복 조립을 줄입니다. 스타터가 제공한 클래스패스, 환경·속성, 사용자 빈 정의를 보고 기본 구성을 선택합니다.

필수 클래스 불일치와 사용자 빈 양보는 다르다공식 HSQLDB 내장DataSource 사례에서 다른 필수조건과 자동구성지원이 준비됐다고 가정한다. 클래스 없음은 해당내장기본값제외, 클래스있음은 사용자DataSource 여부에 따라 사용자빈양보 또는기본등록후보로갈린다. 두결정은 논리를 설명하며 실제조건평가내부순서를 고정하지 않는다. 등록은 연결·스키마·준비성공의 증거가 아니다. mobile도같은6노드5관계다.내장 DB 후보지원·다른 조건 준비HSQLDB 클래스있음?조건 불일치내장 기본값 없음사용자 DataSource빈 있음?기본 빈 등록연결 검사는 별도사용자 빈 사용기본값은 양보없음있음없음있음
필수 클래스 불일치와 사용자 빈 양보는 다르다공식 HSQLDB 내장DataSource 사례에서 다른 필수조건과 자동구성지원이 준비됐다고 가정한다. 클래스 없음은 해당내장기본값제외, 클래스있음은 사용자DataSource 여부에 따라 사용자빈양보 또는기본등록후보로갈린다. 두결정은 논리를 설명하며 실제조건평가내부순서를 고정하지 않는다. 등록은 연결·스키마·준비성공의 증거가 아니다. mobile도같은6노드5관계다.내장 DB 후보지원·다른 조건 준비HSQLDB 클래스있음?조건 불일치내장 기본값 없음사용자 DataSource빈 있음?기본 빈 등록연결 검사는 별도사용자 빈 사용기본값은 양보없음있음없음있음

입력 · 선택할 근거

  1. 클래스패스

    스타터는 관련 의존성의 묶음입니다. 필요한 기능 후보를 제공하지만 무조건 활성화하지 않습니다.

  2. 환경 · 프로퍼티

    애플리케이션 유형과 속성 값이 구성의 적용 조건을 결정합니다.

  3. 사용자 빈 정의

    해당 조건이 검색하는 역할·타입의 사용자 정의가 있으면 기본 빈이 양보할 수 있습니다.

결과 · 기본값의 소유자

  1. 조건 불일치 → skip

    요구 클래스가 없거나 기능 조건이 맞지 않으면 해당 기본값을 등록하지 않습니다.

  2. 사용자 정의 → back-off

    OnMissingBean 조건에 맞는 사용자 빈이 있으면 기본값은 만들지 않습니다. 사용자 빈은 남습니다.

  3. 조건 일치 → 기본 빈 등록

    빈 생성·검증·서버 시작 등은 이어서 확인합니다. 조건 일치만으로 애플리케이션 준비가 증명되지 않습니다.

조건 보고서의 일치/불일치와 실제 빈 그래프·시작 실패를 함께 봅니다. 기본값 교체에는 속성·커스터마이저·사용자 빈 등 요구에 맞는 작은 확장 지점을 선택합니다.


반복 조립 문제

내장 서버를 만들고 포트를 정한 뒤 서블릿 컨텍스트에 Spring 디스패처를 등록하고 루트 컨텍스트 생명 주기를 묶어야 합니다.

라이브러리 버전이 어긋나면 컴파일은 되지만 시작 시 NoSuchMethodError가 날 수 있습니다.

운영 환경마다 구성 파일과 로그, 단계적 종료도 필요합니다.

src/main/java/board/boot/AssemblyInventory.java
package board.boot;

import java.util.List;

public final class AssemblyInventory {
    record Step(String owner, String failureSignal) { }

    public static void main(String[] args) {
        var steps = List.of(
                new Step("web server", "port bind failure"),
                new Step("servlet container", "mapping missing"),
                new Step("Spring context", "bean creation failure"),
                new Step("dependency graph", "linkage error"),
                new Step("operations", "health unknown"));
        System.out.printf("assemblySteps=%d firstFailure=%s%n",
                steps.size(), steps.getFirst().failureSignal());
    }
}
AssemblyInventory 실행
assemblySteps=5 firstFailure=port bind failure

Boot는 이 단계를 없애는 것이 아니라 라이브러리가 검증한 구성에 맡깁니다.

실패가 사라지지 않고 조건 보고서와 시작 예외로 더 일찍 보입니다.

원 AssemblyInventory는 다섯 설명 값을 List에 넣고 크기와 첫 항목의 문자열을 출력하는 순수 Java 목록입니다. 서버·서블릿·Spring을 실제 조립하거나 포트를 열지 않습니다. firstFailure도 관측한 최초 장애가 아니라 목록 첫 failureSignal의 이름입니다. 이 출력과 뒤 BoardApplication의 실제 컨텍스트 시작을 구별하세요.


스타터·의존성 관리

스타터는 빈 JAR 하나가 기능을 구현한다기보다 관련 의존성을 한 의도로 모읍니다.

Web MVC 스타터는 MVC, JSON, 로깅, 내장 서버 조합을 일관된 버전 집합에서 가져옵니다. Bean Validation 구현은 필요한 경우 별도 검증 스타터로 추가합니다.

애플리케이션은 Boot BOM이 관리하는 의존성에 버전을 반복하지 않습니다.

관리 밖 라이브러리는 버전을 직접 선택하고 CVE·Java 호환성을 책임집니다.

전이 의존성 재정의를 추가하면 왜 Boot 관리 범위를 벗어났는지 기록하고 의존성 분석 결과와 기본 구동 검증을 남깁니다.

스타터를 모두 넣는 방식은 클래스 경로를 키우고 원치 않는 자동 구성을 활성화합니다.

실제 기능 기준으로 선택하고 사용하지 않는 데이터베이스 드라이버나 Actuator 메트릭 내보내기 구현체를 제거합니다.


조건부 자동 구성

Boot는 후보 구성 목록을 읽고 현재 환경 조건에 맞는 빈을 등록합니다.

MVC 클래스가 있고 리액티브 클래스가 없는지, 사용자 빈이 이미 있는지, 속성이 켜졌는지 같은 조건이 입력입니다.

사용자 빈이 있으면 자동 구성의 기본 빈이 물러나는 규칙이 핵심 재정의 확장 지점입니다.

@SpringBootApplication은 구성, 컴포넌트 스캔, 자동 구성 활성화를 묶습니다.

메인 클래스 패키지 위치가 스캔 루트가 되므로 기본 패키지나 스캔 범위가 너무 넓은 패키지에 두면 불필요한 타입을 탐색합니다.

자동 구성을 이해할 때 빈 이름만 찾지 말고 조건 평가 보고서를 읽습니다.

긍정 일치, 부정 일치, 무조건 적용되는 클래스를 구분하면 “왜 만들어졌나”와 “왜 안 만들어졌나”를 같은 방식으로 설명할 수 있습니다.

예시 공식 자동 구성 설명의 내장 DB 사례로 읽어 봅시다. 필요한 HSQLDB 클래스가 있고 자동 구성 지원과 다른 필수 조건도 맞으면 기본 DataSource를 등록할 후보가 생깁니다. 같은 역할의 사용자 DataSource 빈을 직접 등록하면 해당 기본값은 물러나며 사용자 빈은 남습니다. 필요한 클래스가 없다는 경우와 사용자 빈이 있어서 양보한다는 경우는 기본값이 없다는 결과는 같아도 이유가 다릅니다.

모든 자동 구성이 임의의 사용자 빈 하나 때문에 꺼지는 것은 아닙니다. 어떤 역할·타입을 검색하는 조건인지 보고서에서 찾아야 합니다. 위 MVC·리액티브 문장도 조건 입력의 예이며, 두 기술이 함께 있는 클래스 경로의 최종 애플리케이션 유형을 이 한 문장으로 결정하지 않습니다.


SpringApplication 준비 과정

실행 인자, 시스템 속성, 환경 변수, 구성 데이터를 환경으로 모으고 애플리케이션 타입을 판단한 뒤 컨텍스트를 만들고 새로 고침합니다.

리스너와 초기화기, 실행기가 서로 다른 생명 주기 단계에서 동작합니다.

src/main/java/board/boot/BoardApplication.java
package board.boot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BoardApplication {
    public static void main(String[] args) {
        SpringApplication.run(BoardApplication.class, args);
    }
}

메인은 짧지만 빌드 클래스 경로와 애플리케이션 속성이 실행 입력입니다.

테스트에서 다른 메인 소스를 쓰면 스캔과 자동 구성 범위가 달라질 수 있으므로 실제 애플리케이션 클래스로 최소 구성 컨텍스트를 시작해 검증합니다.


재정의 가능한 기본값

포트, JSON 동작, 오류 노출, 연결 풀 크기를 기본값 그대로 쓸 수 있지만 운영 환경 요구에 맞는지 확인합니다.

재정의는 사용자 빈, 속성, 커스터마이저, 제외 중 가장 작은 확장 지점을 사용합니다.

자동 구성 클래스 전체를 복사하면 업그레이드 이점을 잃습니다.

제외는 특정 기본값이 애플리케이션 아키텍처와 맞지 않을 때 사용하고 이유와 대체 빈을 남깁니다.

시작만 통과하려고 제외를 늘리면 필수 기능이 빠질 수 있습니다.

Boot 버전 업그레이드에서는 릴리스 마이그레이션 안내서, 의존성 차이, 조건 보고서 차이, 통합 테스트를 확인합니다.

컴파일 성공만으로 생성된 구성 의미가 같다고 보지 않습니다.


시작·실행 진단 분리

빈 정의 충돌, 누락 클래스, 유효하지 않은 구성 속성은 시작에 실패시키는 것이 안전합니다.

DB 일시 장애처럼 실행 중 변할 상태는 상태와 재시도로 표현할 수 있습니다.

필수 스키마가 없는데 준비 완료로 표시하지 않습니다.

시작 시간, 빈 개수, 조건 결과, 웹 서버 포트를 기준선으로 두면 스타터 추가가 애플리케이션에 미친 영향을 찾기 쉽습니다.

디버그 보고서를 운영 환경의 모든 부팅에 무제한 출력하지 않고 문제 재현 환경에서 활성화합니다.

수동 조립과 Boot 기본값을 비교할 때 “설정 파일 수”만 세지 않습니다.

첫 HTTP 응답까지 걸린 시간, 잘못된 속성이 시작 단계에서 차단되는지, 단계적 종료 중 유실된 요청, 의존성 업그레이드 후 조건 변화까지 같은 인수 시나리오로 측정합니다.

관례가 이 증거를 안정적으로 제공할 때만 유지하고, 요구가 달라지면 가장 작은 사용자 정의 확장 지점으로 수정합니다.


연습 문제

Boot 없이 MVC 서버를 조립할 때 필요한 단계와 Boot가 제공하는 대응 추상화를 표로 만드세요.

각 기본값을 그대로 쓸 조건, 사용자 빈으로 재정의할 조건, 완전히 제외할 조건을 회원 게시판 요구에 맞게 정하세요.

해설 보기

기본값 선택은 기능 존재 여부뿐 아니라 운영 결과를 포함합니다.

예를 들어 내장 서버는 그대로 쓰더라도 스레드·타임아웃·단계적 종료를 작업 부하로 검증합니다.

package board.boot;

public record BootDecision(
        String capability,
        Choice choice,
        String evidence
) {
    public enum Choice { DEFAULT, OVERRIDE, EXCLUDE }

    public BootDecision {
        if (capability.isBlank() || evidence.isBlank()) {
            throw new IllegalArgumentException("decision evidence required");
        }
    }
}

결정에는 재검토 트리거와 담당 테스트를 추가해 버전 업그레이드 때 다시 평가합니다.

독립 확인: 다른 필수 조건은 모두 맞습니다. A는 HSQLDB 클래스 있음·사용자 DataSource 없음, B는 클래스 있음·사용자 DataSource 있음, C는 클래스 없음입니다. 해당 내장 기본 DataSource의 등록 여부와 기본값이 없는 이유를 구분하세요. B에서 사용자 빈이 만들어졌다는 사실만으로 실제 DB 연결 성공도 증명되나요?

풀이 확인

A는 해당 기본 빈의 등록 후보가 됩니다. B는 사용자 정의에 양보하므로 기본 빈은 만들지 않고 사용자 빈을 사용합니다. C는 클래스 조건이 맞지 않아 그 내장 기본값을 등록하지 않습니다. B의 빈 존재는 역할이 연결됐다는 증거이며 연결·스키마·준비 상태 검사는 별도로 해야 합니다. 조건 일치→빈 생성→실제 동작은 서로 다른 단계입니다.