
소개
Spring Boot는 Spring 생태계에서 생산성을 높이기 위해 만들어진 프레임워크로, 의존성 스타터(starters), 자동 구성(auto-configuration), 그리고 운영·테스트 지원을 통해 빠르게 애플리케이션을 개발하도록 돕습니다. 이 문서에서는 변하지 않는 핵심 개념을 정리하고 실무에서 고려해야 할 트레이드오프를 설명한 뒤, 간단한 REST 예제를 통해 실제 설정과 실행 방법을 제시합니다.
핵심 개념
다음은 Spring Boot를 이해하는 데 가장 안정적인 개념들입니다.
1) Starters
스타터는 관련 의존성을 묶은 편의 패키지입니다. 예: spring-boot-starter-web은 Spring MVC, Jackson, 내장 톰캣 등을 포함합니다.
2) Auto-configuration
자동 구성은 클래스패스와 설정(properites)에 따라 빈을 등록합니다. 기본 설정은 빠른 시작을 돕지만, 때로는 명시적 설정이 필요합니다.
3) Dependency management / BOM
Spring Boot는 BOM을 통해 라이브러리 버전을 관리합니다. 보통 spring-boot-starter-parent 또는 dependencyManagement를 사용해 안정적인 버전 조합을 유지합니다.
4) Actuator & 운영
Actuator는 헬스체크, 메트릭, 환경 정보 등 운영에 필요한 엔드포인트를 제공합니다. 기본적으로는 일부만 활성화되어 있지만, 노출 시 보안 설정이 필수입니다.
5) 테스트 지원@SpringBootTest, @WebMvcTest 등 테스트 슬라이스는 필요한 컨텍스트만 로드하게 해 더 빠른 테스트를 가능하게 합니다.
트레이드오프 (Tradeoffs)
Spring Boot는 생산성을 많이 올려주지만, 몇 가지 트레이드오프를 이해해야 합니다.
생산성 vs 제어
자동 구성은 빠르게 시작하게 하지만, 내부에서 어떤 빈이 등록되는지 모르고 개발하다가 문제를 진단할 때 어려움이 생깁니다. 복잡한 커스터마이징이 필요하면 자동 설정을 부분적으로 비활성화하거나 명시적으로 구성하는 편이 낫습니다.
메모리와 시작 시간
전통적인 JVM 배포(특히 fat jar)는 런타임 메모리와 초기 시작 시간이 클 수 있습니다. 이 문제를 완화하기 위해 AOT(natively compiled images), 빌드팩을 이용한 컨테이너 이미지 최적화, 또는 모듈화 전략을 사용할 수 있지만, 각각 빌드 복잡도(네이티브 빌드시 리플렉션 구성 등)나 이미지 크기/운영 복잡도와 같은 비용이 따릅니다.
Opinionated vs 유연성
Spring Boot의 의견 기반(opinionated) 설정은 표준적인 사용에는 유리하지만, 비표준 아키텍처(예: 특정 리액티브 스택과 동작 방식 결합)에서는 제한을 느낄 수 있습니다. 이 경우 기본 스타터를 사용하지 않거나 필요한 부분만 선택해 구성하는 것이 안전합니다.
모놀리식 vs 마이크로서비스
Spring Boot는 단일 애플리케이션을 빠르게 만들기에 좋습니다. 마이크로서비스로 나눌 때는 서비스 경계, 배포 자동화, 인프라(서비스 메시, API 게이트웨이, 분산 트레이싱) 비용을 고려해야 합니다.
실전 예제: 간단한 REST 서비스 만들기
아래 예제는 Maven 기반의 최소 Spring Boot 애플리케이션입니다. 핵심 파일과 실행 방법을 포함합니다.
1) pom.xml (핵심 부분)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2) Application 클래스
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
3) 간단한 REST 컨트롤러
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, Spring Boot!";
}
}
4) application.properties (기본 운영 설정 예)
# Actuator: 제한된 엔드포인트만 노출
management.endpoints.web.exposure.include=health,info
# 서버 포트
server.port=8080
5) 빌드 및 실행
# 개발 서버 실행
mvn spring-boot:run
# 패키징
mvn clean package
# 실행
java -jar target/demo-0.0.1-SNAPSHOT.jar
# Buildpack 기반 컨테이너 이미지 생성 (Cloud Native Buildpacks 이용)
mvn spring-boot:build-image -Dspring-boot.build-image.imageName=demo:latest
6) 테스트 예시(간단한 WebMvc slice)
package com.example.demo.controller;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(HelloController.class)
class HelloControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void helloReturnsGreeting() throws Exception {
mockMvc.perform(get("/api/hello"))
.andExpect(status().isOk())
.andExpect(content().string("Hello, Spring Boot!"));
}
}
운영·배포 고려사항 및 권장 사항
- 보안: Actuator, Swagger 등은 운영에서 노출 범위를 엄격히 제한하고 인증·인가를 적용하세요.
- 설정 관리: 환경별 프로퍼티는 프로파일(profile)이나 외부 구성 서비스(예: Vault, Config Server)로 분리하세요.
- 리소스 최적화: 컨테이너 환경에서는 JVM 힙/GC 설정과 이미지 레이어 최적화를 통해 메모리와 시작 시간을 개선하세요.
- 네이티브 빌드: 시작 시간과 메모리 이점을 위해 AOT/native 이미지를 고려할 수 있으나, 네이티브 빌드는 리플렉션·직렬화 설정 등 추가 작업이 필요합니다.
맺음말
Spring Boot는 생산성과 생태계 통합 측면에서 강력한 도구입니다. 자동 구성과 스타터는 빠른 개발을 보장하지만, 복잡한 요구사항이나 성능 제약이 있을 때는 구성의 투명성, 테스트 전략, 빌드/배포 옵션을 신중히 설계해야 합니다. 위의 예제와 권장 사항을 바탕으로 프로젝트 특성에 맞는 균형점을 찾으시기 바랍니다.