[스프링 부트 정리] 스프링 부트 살펴보기

스프링 부트 정리 관련글
- 스프링 부트 살펴보기 (현재 게시글)
- 독립 실행형 Servlet Application
- 독립 실행형 Spring Application
- DI와 테스트, 디자인 패턴
- 자동 구성 기반 Application
- 조건부 자동 구성
- 외부 설정을 이용한 자동 구성
- Spring JDBC 자동 구성 개발
- 스프링 부트 자세히 살펴보기
더보기

@🪻사담 (정리하는 이유)

회사에서 JSP/Servlet 기반 자체 프레임워크에서 스프링부트 프레임워크로 변환하는 작업을 하고 있다.

변경하는 프로젝트에서 모듈 하나에 참여하게 되었고, 그러다보니 자연스레 부서 내 백엔드 교육 담당자로 지정이 되면서 주니어들 뿐만 아니라 시니어들도 가르치게 되어버렸다... (고통받는 중니어)

 

주니어들에게 교육할 때에는 기본원리까지 설명하지 않아도 되었지만(사실 설명하더라도 못따라오는 사람들이 있더라🥲)

시니어들은 백엔드 리드다 보니 아키텍쳐 설계, 기술 표준화, 관리, 운영 및 장애 대응을 해야하므로 단순히 우리 회사에서 어떤 방식으로 스킬을 사용하는지에 대한 교육이 아니라 그 내부까지 교육해야 한다고 생각한다.

 

나도 교육자로써 모르면 안되고, 시니어 분들도 직급이 있으니 나보다 모르면 안되는... 약간 지식대결 하는 기분ㅋㅋㅋ.

그래서 연휴동안 알고있던 내용을 다시 정리하기로 했다.

 

강의는 토비의 스프링 부트 - 이해와 원리를 참고했다!

관련 Git Repository 보러가기👀


🌱스프링 부트(Spring Boot)란?

스프링 부트는 스프링 기반으로 독립 실행형 애플리케이션을 손쉽게 개발할 수 있도록 도와주는 도구 모음이다.
기존 스프링 프레임워크가 가진 복잡한 설정과 배포 과정을 단순화해 신경 쓰지 않고도, 실무 환경에서 빠르게 사용할 수 있도록 만들어졌다.

스프링 부트는 새로운 기술이 아니다.
스프링 부트는 스프링 위에서 동작하는 확장판에 가깝다.

"스프링은 옛날 거, 스프링 부트는 최신 거"라는 식의 구분은 잘못된 이해다.
스프링 부트는 여전히 스프링의 철학과 구조 위에 존재한다.

💡 스프링 ≠ 스프링부트

⚙️Containerless의 의미

스프링 부트의 핵심 개념 중 하나가 Containerless, 즉 “컨테이너를 의식하지 않아도 된다”는 점이다.
서버리스(Serverless)와 비슷한 개념으로, 개발자가 직접 톰캣 같은 웹 컨테이너를 설치하고 설정하지 않아도 된다는 뜻이다.

🧱컨테이너(Container)란?

‘컨테이너’는 단순히 프로그램을 담는 상자가 아니다.
스프링에서 말하는 IoC 컨테이너는 객체(Bean)의 생성과 생명주기를 관리하는 역할을 하고,
웹 환경에서는 여기에 더해 서블릿 컨테이너(Servlet Container)가 존재한다.

 

서블릿 컨테이너는 클라이언트의 요청을 받아 적절한 서블릿(웹 컴포넌트)에 연결하고,
그 결과를 다시 응답으로 돌려주는 일을 한다.
대표적인 서블릿 컨테이너가 바로 Tomcat이다.

 

즉, 웹 애플리케이션은 기본적으로 아래와 같은 구조로 동작한다.
👉 요청 → 서블릿 컨테이너 → 서블릿 → 응답

스프링 컨테이너와의 관계

스프링 컨테이너는 서블릿 컨테이너 뒤에서 동작한다.
서블릿이 요청을 받으면 스프링 컨테이너에 전달하고 스프링 컨테이너는 내부의 여러 Bean 중 하나를 선택해 요청을 처리하게 한다.

이때 스프링 컨테이너는 단순히 객체를 관리하는 수준을 넘어, 의존성 주입(Dependency Injection)이나 AOP 같은 스프링의 핵심 기능을 수행한다.

@warning
다만, 스프링 컨테이너는 서블릿 컨테이너를 대체할 수는 없다.
자바의 웹 기술 표준을 따르려면, 서블릿 컨테이너는 반드시 존재해야 한다.

기존 스프링의 한계

과거에는 스프링 애플리케이션을 실행하려면 톰캣 같은 서블릿 컨테이너를 별도로 설치하고 설정해야 했다.

  1. 톰캣 같은 서블릿 컨테이너 설치
  2. web.xml 작성
  3. WAR(Web Application Archive) 형태로 패키징
  4. 톰캣에 수동 배포

이런 과정이 필수였다.

작은 프로젝트를 띄우기에도 진입장벽이 높았고, 설정 실수로 인해 에러가 자주 발생했다.

개발자 입장에서는 불필요한 환경 설정에 너무 많은 시간을 써야 했다.

스프링 부트가 해결한 것

스프링 부트는 이 문제를 단 한 줄로 해결했다.

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


이 코드 하나로

  • 내장 톰캣(Embedded Tomcat)이 자동으로 실행되고
  • 서블릿 컨테이너 설정이 자동 구성되며
  • 스프링 컨테이너가 초기화된다.

톰캣을 따로 설치하거나 WAR로 배포할 필요도 없이 그냥 java -jar app.jar 명령 한 번이면 서버가 뜨며 JAR 파일 하나로 바로 실행 가능한 독립 실행형 애플리케이션이 되는 것이다.

 

이렇게 컨테이너가 내부적으로 동작하지만 개발자는 그 존재를 의식하지 않아도 되는 형태를 흔히 Containerless 개발 방식이라고 부른다.

즉, "컨테이너가 없다"가 아니라 "컨테이너를 신경 쓸 필요가 없다"는 의미다.

개발자는 비즈니스 로직 개발에만 집중하면 되고, 서버 구동 환경에 대한 복잡한 고민은 스프링 부트가 대신 처리한다.

비교 정리

구분 스프링(Spring) 스프링 부트(Spring Boot)
실행 방식 외부 톰캣에 WAR 배포 내장 톰캣 자동 실행 (JAR)
설정 XML 기반 복잡한 설정 자동 설정 (Auto Configuration)
주요 목적 프레임워크 제공 실행 가능한 애플리케이션 개발
구조 서블릿 컨테이너 + 스프링 컨테이너 내장 서블릿 컨테이너 + 스프링 컨테이너
실행 예시 tomcat/bin/startup.sh java -jar app.jar
더보기

@사실 현재 회사는 WAR 배포가 아닌 직접 실행 방식이다ㅎㅎ

 

이런 식으로 server.xml이나 web.xml 등에 명시해서 직접 호출한다👀


🔍정리

스프링 부트는 스프링을 더 실용적이고 빠르게 사용할 수 있도록 만들어진 결과물이다.

  • 내장 컨테이너로 서버 설정을 없애고
  • 자동 설정(Auto Configuration) 덕분에 복잡한 배포 절차가 사라졌고
  • XML 대신 Annotatin 기반의 설정으로 훨씬 직관적인 개발이 가능해졌다.

결국 스프링 부트는 "스프링을 실무에서 바로 쓸 수 있는 수준으로 단순화한 도구"라고 할 수 있다.


🧭 Opinionated Configuration

= 스프링 부트의 설계 철학

스프링 프레임워크는 태생부터 유연함을 철학으로 삼았다.
원하는 기술을 자유롭게 조합하고, 모든 설정을 개발자가 직접 선택할 수 있다.
그래서 스프링 문서에는 "not opinionated" ─ 즉 특정한 방식에 얽매이지 않는다는 표현이 등장한다.

이런 자유도는 강력한 장점이지만, 동시에 개발자에게 부담을 만든다.

  • 선택의 폭이 넓은 만큼 설정의 부담이 크다.
  • 프로젝트 시작 시 기술 스택, 라이브러리, 버전, 설정 등 수많은 결정을 내려야 한다.
  • 초기 환경 구성에 많은 시간 소모된다.

결국 유연함은 곧 결정해야 할 것들이 많다는 뜻이다.

💡 스프링 부트의 해법

스프링 부트는 이런 문제를 해결하기 위해 Opinionated Configuration(의견 있는 설정) 이라는 개념을 도입했다.

"기술적인 고민은 우리가 대신할게. 개발자는 비즈니스 로직에 집중해."

이 철학의 핵심은 검증된 베스트 프랙티스(best practice)를 기본값으로 제공한다는 데 있다.
스프링 부트는 수많은 프로젝트와 실제 운영 사례를 통해 가장 안정적이고 많이 사용되는 조합을 기본 구성(Default)으로 제시(내장)하고 있다.

덕분에 개발자는 복잡한 설정 없이도 바로 개발에 착수할 수 있고 기술적인 세부 조정보다 비즈니스 로직 구현에 집중할 수 있다.

⚙️ 스프링 부트가 대신 결정해주는 것들

  • 기술 스택 선택
    • 어떤 라이브러리와 구현체를 사용할지 스프링 부트가 기본으로 정해준다.
    • 예를 들어, spring-boot-starter-data-jpa를 추가하면 Hibernate가 자동 포함된다.
  • 버전 관리
    • 각 라이브러리의 호환 버전을 spring-boot-dependencies에서 통합 관리한다.
    • 개발자가 버전 충돌을 일일이 맞출 필요가 없다.
  • Starter 제공
    • spring-boot-starter-web, spring-boot-starter-security처럼 관련된 라이브러리들을 하나의 묶음으로 제공한다.
    • 필요한 기능을 Starter 단위로 쉽게 추가할 수 있다.
  • 기본 설정 자동화 (Auto Configuration)
    • 애플리케이션 실행 시, 현재 프로젝트 환경에 맞는 설정을 자동으로 적용한다.
    • 예: spring-boot-starter-web이 있다면 DispatcherServlet, 내장 톰캣, Jackson 등이 자동 등록된다.

🔄 커스터마이징의 자유

Opinionated하다고 해서 강제적이라는 뜻은 아니다.

제공되는 기본값은 시작점일 뿐이며, 원한다면 언제든지 덮어쓰거나 변경할 수 있다.

  • application.yml을 통해 기본 설정을 재정의
  • Bean 등록 또는 @Configuration을 사용해 직접 설정 주입
  • 내장 설정을 끄고, 직접 구성 요소를 교체 가능

심지어 스프링 부트를 제거하고 순수 스프링 프로젝트로 재구성할 수도 있다.

구분 스프링(Spring) 스프링 부트(Spring Boot)
철학 Not Opinionated (유연함 중심) Opinionated (검증된 기본 구성 제공)
초점 개발자가 모든 설정 결정 베스트 프랙티스 기반 자동 구성
장점 자유로운 기술 선택 빠른 시작, 설정 최소화
단점 초기 설정 복잡 기본 동작 이해 필요
커스터마이징 필수 선택 (Default 위에 덮어쓰기 가능)

🌐 스프링 부트의 내부 동작 이해

: HTTP 요청/응답 구조 부터 톰캣 실행 까지 

웹 애플리케이션을 개발할 때 가장 기본이 되는 건 HTTP 요청과 응답의 구조를 정확히 이해하는 것이다.

요청과 응답은 단순히 데이터를 주고받는 통로가 아니라, 내가 만든 서버가 어떤 순간에 어떤 데이터를 받아서, 어떤 형태로 돌려주는지를 보여주는 핵심 단서다.

1) HTTP 요청(Request)과 응답(Response) 구조

HTTP 통신은 요청(Request)응답(Response) 두 가지 메시지로 이루어진다.

📥 Request

구성요소 설명
Request Line Method + Path + HTTP Version
Headers 요청의 부가 정보 (Host, User-Agent 등)
Message Body 클라이언트가 서버로 보내는 실제 데이터

📤 Response

구성요소 설명
Status Line HTTP Version + Status Code + Status Text
Headers 응답 부가 정보 (Content-Type 등)
Message Body 서버가 클라이언트로 보내는 실제 데이터

예시

http -v ":8080/hello?name=Spring"

요청(Request)

GET /hello?name=Spring HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8080
User-Agent: HTTPie/3.2.1

응답(Response)

HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 12
Content-Type: text/plain;charset=UTF-8
Date: Sun, 05 Oct 2025 17:34:15 GMT

Hello Spring

이처럼 요청과 응답의 구조를 보면 아래의 내용을 명확하게 확인할 수 있다.

  • 어떤 메서드가 실행되었는지
  • 어떤 데이터가 전송되었는지
  • 어떤 타입으로 응답이 내려왔는지
💡 개발 중에는 HTTPie, curl, Postman 같은 도구로 실제 요청/응답을 모니터링하면서, 의도한 대로 동작하는지 반드시 검증하는 습관이 중요하다.

2) 간단한 Spring Boot 예제

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello(String name) {
        return "Hello " + name;
    }
}

@RestController 덕분에 return 값(String) 이 자동으로 HTTP 응답의 Body 로 매핑되고 스프링이 Content-Type(text/plain;charset=UTF-8)까지 자동으로 지정해준다.

스프링부트는 이걸 가능하게 하기 위해 내부적으로 톰캣(Servlet Container)을 띄운다.

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

SpringApplication.run() 한 줄로 아래의 내용이 한 번에 실행되는 것이다

  • 서블릿 컨테이너(Tomcat) 실행
  • 스프링 컨테이너(ApplicationContext) 초기화
  • Controller, Service, Repository 등록

3) 스프링부트가 없다면?

public class ServerApplication {
	public static void main(String[] args) {
		// 아무것도 안 함
	}
}

이렇게 단순한 main만 실행하면 아무 일도 일어나지 않는다.

스프링부트가 없다면 우리가 직접 서블릿 컨테이너(ex: 톰캣)을 띄워야 한다.

(이 부분은 다음 게시글에서!)


🔍정리

단계 설명
1 HTTP 요청과 응답의 구조를 이해한다
2 실제 요청/응답을 도구로 모니터링한다
3 @RestController로 스프링이 응답을 자동 생성하는 구조를 익힌다
4 스프링부트 없이 직접 톰캣을 띄워본다
5 스프링부트가 이 모든 과정을 대신 처리해준다는 걸 체감한다

 


결국 Spring Boot 는 "서블릿 컨테이너 실행 + 스프링 컨테이너 초기화 + 애플리케이션 설정 자동화" 를 한 번에 처리해주는 Containerless 환경의 엔진이다.
우리가 한 줄로 띄우는 SpringApplication.run() 안에는 사실 수많은 설정과 초기화 로직이 숨어 있다.