Backend/🌱 Spring

Spring과 SpringBoot

HS0601 2026. 5. 5. 16:30

 

Spring공식문서는 이렇게 말한다

The Spring Framework provides a comprehensive programming and configuration model for modern Java-based enterprise applications

Spring Framework는 현대적인 Java 기반 엔터프라이즈 애플리케이션을 만들기 위한 프로그래밍 모델과 설정 모델을 제공한다.

 

영역 Spring이 해주는 일
객체 관리 객체를 직접 new 하지 않고 Spring Container가 관리
의존성 주입 Service가 Repository를 직접 만들지 않고 주입받게 함
트랜잭션 @Transactional로 DB 작업 단위를 관리
웹 MVC Controller, DispatcherServlet, RequestMapping 등 제공
데이터 접근 JDBC, ORM, JPA 연동 지원
테스트 Spring Context 기반 통합 테스트 지원
AOP 공통 관심사, 예: 트랜잭션, 로깅, 보안 처리

공식문서도 Spring Framework의 기능을 dependency injection, events, resources, i18n, validation, data binding, type conversion, SpEL, AOP, transactions, DAO support, JDBC, ORM, Spring MVC 등으로 나눠서 설명한다.

자바 객체들을 잘 조립하고, 웹/DB/트랜잭션 같은 서버 애플리케이션의 반복 인프라를 대신 관리해주는 기반 프레임워크다.

 

Spring의 핵심은 IoC Container

공식문서

ApplicationContext가 Spring IoC 컨테이너를 대표한다.

더보기

ApplicationContext란?

Spring IoC Container의 대표 인터페이스

Bean이란?

Spring Container가 생성하고 관리하는 객체

PostRepository postRepository = new PostRepository();
PostService postService = new PostService(postRepository);
PostController postController = new PostController(postService);

자바는 위 코드처럼 한다 즉 개발자가 객체를 직접 만들고 연결한다 그러나 Spring에서는 보통 아래와 같이 한다

@Service
public class PostService {
    private final PostRepository postRepository;

    public PostService(PostRepository postRepository) {
        this.postRepository = postRepository;
    }
}

겉으로 보면 new PostRepository()가 안 보인다 그렇다면 누가 만들었을까?

Spring Container가 만든다 

공식문서에 따르면 ApplicationContext는 Bean을 instantiating, configuring, and assembling하는 책임을 가진다. 즉 객체를 생성하고, 설정하고, 서로 조립한다.

눈으로 보는 숨은 구조

내 코드
  ├─ Controller 클래스
  ├─ Service 클래스
  ├─ Repository 클래스
  └─ Config 클래스

Spring ApplicationContext
  ├─ 어떤 클래스를 Bean으로 만들지 읽음
  ├─ 필요한 의존성 관계를 파악함
  ├─ 객체를 생성함
  ├─ 생성자에 필요한 객체를 넣어줌
  └─ 완성된 애플리케이션 구조를 실행 가능하게 만듦

Bean은 Spring이 관리하는 객체다

Spring IoC 컨테이너

In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans.

Spring에서 애플리케이션의 뼈대를 이루고 Spring IoC 컨테이너가 관리하는 객체를 Bean이라고 부른다.

 

일반 객체 Bean
내가 new로 만듦 Spring이 만듦
내가 생명주기 관리 Spring이 생명주기 관리
의존성 직접 연결 Spring이 의존성 연결
테스트에서 직접 조립 필요 Spring Context에서 주입 가능
프록시 적용 어려움 트랜잭션/AOP 프록시 적용 가능

 

예를들어 

@RestController
public class PostController { }

@Service
public class PostService { }

@Repository
public interface PostRepository extends JpaRepository<Post, Long> { }

이런 것들은 Spring이 Bean으로 관리하는 대상이 된다.

@Service를 붙이는 이유는 서비스니까 예쁘게 표시하려고가 아니라, Spring Container가 이 클래스를 애플리케이션 구성 요소로 인식하고 관리하게 하기 위해서다.

DI는 Spring이 객체를 대신 연결해주는 방식이다

Spring의존성관련  문식문서

Dependency injection (DI) is a process whereby objects define their dependencies

DI는 객체가 자신에게 필요한 의존성을 정의하고, 컨테이너가 그 의존성을 넣어주는 과정이다.

public class CommentService {
    private final CommentRepository commentRepository;

    public CommentService(CommentRepository commentRepository) {
        this.commentRepository = commentRepository;
    }
}

여기서 CommentService는 " 나는 CommentRepository가 필요해. 근데 내가 직접 만들지는 않을게. 누군가 넣어줘~”

이 구조의 장점은 공식문서에서 이렇게 설명한다 

DI를 쓰면 객체가 자기 의존성을 직접 찾지 않고 의존성의 위치나 구체 클래스를 몰라도 되기 때문에 테스트하기 쉬워진다.

특히 인터페이스나 추상 클래스에 의존하면 stub/mock 구현을 사용할 수 있다

그래서 Mockito 테스트에서 겪는 구조와 연결된다 

@Mock
CommentRepository commentRepository;

@InjectMocks
CommentService commentService;

이건 Spring Container를 안 띄우는 대신, Mockito가 비슷하게 가짜 Repository를 Service에 넣어주는 거다

 

상황 누가 의존성 주입함?
실제 Spring 실행 Spring Container
단위 테스트 Mockito Mockito
직접 Java 코드 개발자

Spring MVC는 Spring 안에 있는 웹 프레임워크다

SpringMVC공식문서

Spring Web MVC is the original web framework built on the Servlet API

Spring Web MVC는 Servlet API 위에 만들어진 Spring의 원래 웹 프레임워크다.

즉 Spring MVC는 Spring Framework 전체 중 웹 요청 처리 담당 부분이다

브라우저 / Postman
   ↓ HTTP 요청
DispatcherServlet
   ↓
Controller
   ↓
Service
   ↓
Repository
   ↓
DB

여기서 Spring MVC가 주로 해주는 일

기능 예시
URL 매핑 @GetMapping("/posts")
요청 파라미터 바인딩 @RequestParam, @PathVariable
JSON 요청 변환 @RequestBody
JSON 응답 변환 @ResponseBody, ResponseEntity
예외 처리 @ControllerAdvice, @ExceptionHandler
인터셉터 인증/인가 전처리
메시지 컨버터 Java 객체 ↔ JSON 변환

그래서 controller 테스트 시 MockMvc를 쓰는 건 단순히 메서드 테스트가 아니라 Spring MVC 요청 처리 흐름 일부를 흉내내는 테스트라고 보면된다 

그럼 Spring Boot는 뭐냐

SpringBoot  공식문서

Spring Boot helps you to create stand-alone, production-grade Spring-based applications

Spring Boot는 독립 실행 가능하고 운영 수준에 가까운 Spring 기반 애플리케이션을 만들도록 도와준다.

핵심 3단계

1. stand-alone : 혼자 실행 가능하다는 뜻

예전 Spring MVC 애플리케이션은 보통 WAR로 만들고, 외부 Tomcat에 배포했다.

외부 Tomcat 설치
  └─ WAR 배포
      └─ Spring MVC 애플리케이션 실행

Spring Boot는

java -jar app.jar
  └─ 내장 Tomcat 같이 뜸
      └─ Spring 애플리케이션 실행

공식문서도 Spring Boot 애플리케이션은 java -jar로 시작할 수 있다고 설명한다. 그래서 EC2에서 app.jar 실행하고 systemd로 관리했던 구조다.

2. production-grade : 운영 수준이라는 뜻

Spring Boot 공식문서의 목표에는 embedded servers, security, metrics, health checks, externalized configuration 같은 비기능 요구사항을 제공한다는 내용이 있다.

더보기

Externalized Configuration란?

application.yml, 환경변수, command line args 등으로 설정을 코드 밖에서 관리하는 방식

Embedded Server란?

애플리케이션 안에 포함된 Tomcat/Jetty/Undertow 같은 서버

이때, 비기능 요구사항이란

기능 요구사항 비기능 요구사항
게시글 작성 서버가 죽었는지 확인
댓글 조회 응답 시간이 느린지 확인
로그인 설정을 dev/prod로 분리
게시판 생성 로그/메트릭/헬스체크 제공

 

즉, Spring Boot는 게시글 CRUD를 쉽게 만든다가 전부가 아니라 애플리케이션을 실행, 배포, 관찰하기 쉽게 만들어준다

이게 바로 운영 관점에서의 Spring Boot의 가치

3.Spring-based : Spring 기반이라는 뜻

Spring Boot는 Spring 없이 독립적으로 존재하는 프레임워크가 아니다

Spring Boot 공식문서도 Spring Boot를 Spring-based applications를 만들도록 돕는다고 표현한다.

구조

Java
  ↓
Spring Framework
  ├─ IoC Container
  ├─ DI
  ├─ AOP
  ├─ Transaction
  ├─ Spring MVC
  └─ Data Access 지원
      ↓
Spring Boot
  ├─ Auto Configuration
  ├─ Starter Dependencies
  ├─ Embedded Tomcat
  ├─ Externalized Configuration
  ├─ Actuator
  └─ Executable Jar
더보기

Auto Configuration란?

classpath, 설정값, Bean 존재 여부 등을 보고 Boot가 자동으로 설정 Bean을 등록하는 기능

Spring Boot가 해주는 핵심 1: 자동 설정

SpringBoot 공식문서에서는 이렇게 말한다

Auto-configuration is non-invasive.

Auto-configuration은 침투적이지 않다. 즉 네가 직접 설정하면 Boot 기본 설정은 물러난다.

Spring Boot는 프로젝트 상태를 보고 판단한다. 예를들어

implementation 'org.springframework.boot:spring-boot-starter-web'

이걸 넣으면 Boot는 대충 이런 판단을 한다 

어? spring-webmvc가 classpath에 있네?
어? Servlet 기반 웹 애플리케이션이겠네?
그럼 Tomcat 띄우고
DispatcherServlet 등록하고
Jackson 메시지 컨버터 넣고
기본 Error 처리도 넣자.
더보기

Classpath란?

현재 애플리케이션이 사용할 수 있는 라이브러리/클래스 경로

그런데, 직접 Bean을 등록하면 boot는 아, 사용자가 직접 만들었네 그럼 내 기본값은 빠질게~라는 식으로 동작한다

@Bean
public ObjectMapper objectMapper() {
    return new ObjectMapper();
}

 

공식문서에서도 직접 DataSource Bean을 추가하면 기본 embedded database 지원이 물러난다고 설명한다.

그래서 Boot를 잘 쓰려면

  1. 기본값으로 빠르게 시작한다.
  2. 문제가 생기면 어떤 자동 설정이 적용됐는지 확인한다.
  3. 필요한 부분만 직접 Bean으로 덮어쓴다.

Spring Boot가 해주는 핵심 2: Starter

Starters are a set of convenient dependency descriptors

Starter는 편리한 의존성 묶음이다.

예를 들어 Boot 없이 Spring MVC를 직접 구성한다고 생각해볼 때, 웹 서버 만들려면 대충 이런 것들을 알아서 골라야 한다

spring-web
spring-webmvc
jackson
validation
tomcat
logging
...

근데 Spring Boot에서는 보통 이거 하나 넣는다

implementation 'org.springframework.boot:spring-boot-starter-web'

그러면 필요한 의존성들이 같이 들어온다.

 

spring-boot-starter-web은 대충 이런 의도를 가진 묶음이다

  • 웹 MVC 애플리케이션 만들 거지?
  • 그러면 MVC, JSON 변환, 내장 Tomcat, 검증, 로깅 같은 기본 묶음 넣어줄게.

spring-boot-starter-data-jpa는 이런 의도

  • JPA로 DB 접근할 거지?
  • 그러면 Spring Data JPA, Hibernate, JDBC 관련 기본 묶음 넣어줄게.

즉, Starter는 라이브러리 하나라기보다 필요한 라이브러리 조합을 Spring Boot 팀이 추천 세트로 묶어둔 것에 가깝다

Spring Boot가 해주는 핵심 3: 의존성 버전 관리

공식문서에 따르면 Spring Boot는 각 릴리스마다 지원하는 의존성 목록을 제공하고, 실제로는 빌드 설정에서 이런 의존성들의 버전을 직접 적지 않아도 Boot가 관리한다. 또한 Spring Boot를 업그레이드하면 관련 의존성들도 일관된 방식으로 업그레이드된다.

implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

버전을 안 적는다. 왜냐면 Spring Boot플러그인과 BOM이 이 Boot 버전에서는 이 라이브러리 버전 조합이 맞다를 관리해주기 때문이다

Spring Boot가 해주는 핵심 4: 내장 서버

SpringBoot 공식문서에서는 이렇게 말한다

Embed Tomcat, Jetty or Undertow directly

Tomcat, Jetty, Undertow를 애플리케이션 안에 직접 포함할 수 있다.

이게 Spring과 Spring Boot 차이 중 하나다

예전방식

1. 서버에 Tomcat 설치
2. WAR 파일 생성
3. Tomcat webapps에 배포
4. Tomcat이 애플리케이션 실행

Boot 방식

1. JAR 파일 생성
2. java -jar app.jar
3. JAR 안의 내장 Tomcat이 같이 실행

그래서 EC2에서 java -jar app.jar 혹은 systemd로 ExecStart=/usr/bin/java -jar /home/ubuntu/apps/coreboard/app.jar 

이런 식으로 운영할 수 있었던 것이다

Spring Boot가 해주는 핵심 5: @SpringBootApplication

SpringBoot 공식문서에서는 이렇게 말한다

Spring Boot에서 가장 많이 보는 게 아래 코드다

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

공식문서에 따르면 @SpringBootApplication 하나로 auto-configuration, component scan, extra configuration 정의를 활성화할 수 있다.

더보기

Component Scan란?

@Component, @Service, @Controller 등을 찾아 Bean으로 등록하는 과정

실제로 이 애노테이션은 크게 세 가지 의미를 합친 것

구성 의미
@SpringBootConfiguration 이 클래스가 설정 클래스임
@EnableAutoConfiguration Boot 자동 설정 켬
@ComponentScan 현재 패키지 기준으로 컴포넌트 스캔

공식문서도 @ComponentScan은 애플리케이션이 위치한 패키지에서 @Component scan을 활성화한다고 설명한다

그래서 패키지 위치가 중요하다.

com.example.coreboard
 ├─ CoreBoardApplication.java
 └─ domain
     ├─ post
     ├─ comment
     ├─ board
     └─ users

나쁜구조

com.example
 ├─ post
 └─ app
     └─ CoreBoardApplication.java

왜냐면 @SpringBootApplication이 붙은 클래스의 패키지를 기준으로 하위 패키지를 스캔하기 때문이다. Boot 공식문서도 main application class를 root package에 두는 것을 권장한다고 설명한다.

SpringApplication.run()은 뭐 하는 애냐

SpringApplication.run(CoreBoardApplication.class, args);

이 한 줄은 단순히 main 메서드 실행이 아니다.

더보기

1. 애플리케이션 타입 판단
   - Servlet 웹인가?
   - Reactive 웹인가?
   - 일반 애플리케이션인가?
2. ApplicationContext 생성
   - Spring IoC Container 준비
3. Environment 준비
   - application.yml
   - profile
   - command line args
   - OS 환경변수
4. BeanDefinition 로딩
   - @Component
   - @Service
   - @Repository
   - @Controller
   - @Configuration
   - @Bean
5. Auto Configuration 적용
   - classpath와 조건 기반으로 자동 설정 적용
6. Bean 생성 및 의존성 주입
   - Controller → Service → Repository
7. 내장 웹 서버 실행
   - Tomcat 등
8. 애플리케이션 준비 완료

그래서 Boot 애플리케이션을 실행했을 때 로그에 이런 게 뜨는 것이다.

Started CoreBoardApplication in ... seconds

그리고 만약 8080 포트가 이미 사용 중이면 Boot는 실패 분석 메시지를 제공한다. 공식문서에서도 port 8080이 이미 사용 중일 때 APPLICATION FAILD TO START와 함께 원인과 조치를 보여주는 예시를 든다.

이게 Spring Boot의 운영 친화적인 부분이다

 

Spring과 SpringBoot의 차이를 한 장으로 정리

 

구분 Spring Spring Boot
정체 기반 프레임워크 Spring 기반 애플리케이션을 쉽게 만드는 도구층
핵심 IoC, DI, AOP, MVC, Transaction Auto Configuration, Starter, Embedded Server, Actuator
설정 방식 직접 설정이 많음 기본 설정 자동 제공
실행 방식 외부 WAS 배포가 흔했음 java -jar 단독 실행 가능
의존성 관리 개발자가 조합 관리 Boot가 권장 버전 조합 관리
운영 기능 직접 붙여야 함 Actuator, metrics, health 등 제공
대체 관계 기반 Spring 위에서 동작
예시 ApplicationContext, @Service, @Transactional @SpringBootApplication, starter, auto config

 

더보기

Actuator란?

health check, metrics 등 운영용 기능을 제공하는 Spring Boot 모듈

Spring Boot를 쓰면 Spring을 몰라도 되냐?

No.

오히려 알아야 한다고 본다 왜냐면 Boot가 해주는 자동 설정의 결과물이 결국 Spring Bean이기 때문이다

예를들어

@Service
public class PostService { }

위 코드는 Spring 개념이다

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

위 코드는 Boot 개념이다

@Transactional
public void createPost(...) { }

위 코드는 Spring transactional/AOP 개념이다

spring:
  datasource:
    url: jdbc:mysql://...

위 코드는 Boot external configuration 개념이다

@Repository
public interface PostRepository extends JpaRepository<Post, Long> { }

위 코드는 Spring Data JPA + Boot 자동 설정이 같이 얽힌 구조다

 

더보기

Spring을 모르면
- 어노테이션 붙였는데 왜 안 되지?

Spring Boot만 모르면
설정은 어디서 자동으로 된 거지?

둘 다 알면
이 Bean은 component scan으로 등록됐고,
DataSource는 Boot auto-configuration으로 잡혔고,
TransactionManager는 JPA 설정 기반으로 등록됐고,
@Transactional은 프록시로 감싸져서 동작하겠네.

 

'Backend > 🌱 Spring' 카테고리의 다른 글

[스케줄링]Spring Scheduler로 임시 첨부파일 정리하기  (0) 2026.04.25
GlobalException & ErrorException  (0) 2026.01.12
MVC(Model–View–Controller)  (0) 2026.01.12
Spring Bean 생명 주기  (1) 2026.01.12
[Spring]API 로깅  (0) 2025.08.21