스프링은 자바 기반의 엔터프라이즈 애플리케이션 개발을 손쉽게 만들어주는 프레임워크입니다. 객체 지향적인 설계 원칙을 자연스럽게 따르도록 지원함으로써 대규모 애플리케이션 개발에 효과적입니다.
public class A {
B b = new B();
}
위와 같이 클래스 A에서 직접 B 객체를 생성할 경우, 클래스 간 결합도가 높아지고 테스트나 유지보수가 어려워집니다.
public class A {
private B b;
}
스프링에서는 객체 생성 및 관리 책임을 스프링 컨테이너에 위임합니다. 개발자는 단지 객체를 사용할 준비만 하고, 실제 생성은 프레임워크가 담당합니다. 이러한 구조를 제어의 역전이라 부릅니다.
의존성 주입은 IoC의 구현 방식 중 하나로, 객체 간의 의존성을 외부에서 주입해주는 방식입니다.
public class A {
@Autowired
B b;
}
@Autowired 애너테이션을 통해 스프링 컨테이너가 관리하는 Bean을 자동으로 주입받을 수 있습니다. 개발자는 객체의 생성 방식을 몰라도 사용할 수 있어 코드가 훨씬 유연해집니다.
스프링 컨테이너는 애플리케이션 구동 시 필요한 객체(Bean)를 생성하고, 이들의 생명주기를 관리합니다. 또한, DI 기능을 통해 의존 객체를 주입해주는 역할을 수행합니다.
| 역할 | 설명 |
|---|---|
| 객체 생성 (Bean 관리) | @Component, 자동 구성 등을 통해 등록된 클래스 인스턴스를 생성 |
| 의존성 주입 (DI 지원) | @Autowired 등을 통해 필요한 객체를 주입 |
| 생명주기 관리 | 생성 → 초기화 → 사용 → 소멸 단계까지 관리 |
스프링 컨테이너가 관리하는 객체를 Bean(빈)이라고 합니다. 빈으로 등록하는 방법에는 여러 가지가 있지만, 대표적으로 아래와 같이 @Component 애너테이션을 사용합니다.
@Component
public class MyBean {}
위 클래스는 myBean이라는 이름으로 스프링 컨테이너에 등록되며, 다른 클래스에서 DI를 통해 사용할 수 있습니다.
AOP는 로직을 핵심 관점(core concern)과 부가 관점(cross-cutting concern)으로 나누어 모듈화하는 방법론입니다.
핵심 관점: 계좌 이체, 회원 가입 등 주요 비즈니스 로직
부가 관점: 로깅, 트랜잭션, 보안 등 반복되는 부가 기능
AOP를 적용하면 이러한 부가 기능을 별도로 분리하여 재사용성과 유지보수성을 향상시킬 수 있습니다.
PSA는 다양한 기술을 사용하는 환경에서도 일관된 프로그래밍 모델을 제공하기 위한 스프링의 추상화 전략입니다.
예를 들어, 데이터 접근 기술을 JDBC에서 JPA로 변경하더라도 코드 수정이 최소화됩니다. 마찬가지로 서블릿 컨테이너를 톰캣에서 언더토우로 교체해도 기존 비즈니스 로직에는 영향이 없습니다.
| 개념 | 설명 |
|---|---|
| IoC (제어의 역전) | 객체의 생성과 제어를 프레임워크가 담당 |
| DI (의존성 주입) | 외부에서 객체를 주입받아 사용하는 방식 |
| AOP (관점 지향) | 핵심/부가 관점을 나누어 모듈화하는 프로그래밍 |
| PSA (서비스 추상화) | 다양한 기술에 대한 일관된 접근 방식 제공 |
전통적인 스프링 프레임워크는 강력한 기능을 제공하지만, 설정이 복잡하고 러닝 커브가 비교적 높다는 단점이 있습니다. 이러한 불편함을 해결하고자 등장한 것이 스프링 부트(Spring Boot)입니다.
스프링 부트는 스프링 애플리케이션을 더 빠르고 간편하게 개발할 수 있도록 도와주는 도구입니다.
자동 구성(Auto Configuration): 복잡한 설정 파일 없이 기본 설정 자동 적용
스타터 제공: 기능별 의존성 패키지를 묶어 관리
내장 WAS 지원: 톰캣, 제티, 언더토우 등 내장, 별도 설치 없이 실행 가능
JAR 실행 지원: java -jar 명령어로 바로 실행 및 배포 가능
액츄에이터 제공: 모니터링 및 관리 기능 통합 제공
XML 설정 불필요: 대부분의 설정을 자바 코드로 처리
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.0'
}
group = 'me.park'
version = '1.0'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
test {
useJUnitPlatform()
}
| 항목 | 설명 |
|---|---|
plugins | 스프링 부트 플러그인 및 의존성 자동 관리 플러그인 등록 |
repositories | 외부 의존성 다운로드를 위한 저장소 설정 |
dependencies | 프로젝트 기능에 필요한 의존성 지정 |
스타터는 특정 기능에 필요한 의존성들을 묶어놓은 라이브러리 집합입니다. 일일이 라이브러리를 개별로 추가할 필요 없이 스타터 하나로 일괄 적용할 수 있습니다.
| 스타터명 | 설명 |
|---|---|
spring-boot-starter-web | REST API 및 Spring MVC 기반 웹 개발을 위한 구성 |
spring-boot-starter-test | JUnit 기반 테스트 기능 제공 |
spring-boot-starter-validation | 유효성 검사(Validation) 기능 제공 |
spring-boot-starter-actuator | 애플리케이션 모니터링 및 헬스 체크 기능 |
spring-boot-starter-data-jpa | ORM 기반 데이터 접근(JPA) 기능 지원 |
스프링 부트 3는 자바 17 이상을 요구하며, 자바의 최신 문법 기능과 매우 잘 통합됩니다.
String query = """
SELECT * FROM "items"
WHERE "status" = "ON_SALE"
ORDER BY "price";
""";
String result = """
{
"id": %d,
"name": "%s"
}
""".formatted(2, "juice");
record Item(String name, int price) {}
Item item = new Item("juice", 3000);
System.out.println(item.price()); // 3000
데이터 전달을 목적으로 하는 객체를 더 빠르고 간편하게 만들기 위한 기능
레코드는 상속을 할 수 없고 파라미터에 정의한 필드는 private final로 정의됨
getter 자동 생성
if (obj instanceof Integer i) {
System.out.println("정수 값: " + i);
}
static double getIntegerValue(Object o) {
return switch(o) {
case Double d -> d.intValue();
case Float f -> f.intValue();
case String s -> Integer.parseInt(s);
default -> 0d;
}
}
Servlet, JPA의 네임 스페이스가 Jakarta로 대체
GraalVM 기반의 스프링 네이티브 공식 지원
@SpringBootApplication
public class SpringBootDeveloperApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDeveloperApplication.class, args);
}
}
이 클래스는 자바의 main() 메서드와 같은 역할을 합니다. (여기서 스프링 부트가 시작됨)
이 애너테이션 하나로 스프링 부트 애플리케이션 구동에 필요한 대부분의 설정이 자동 구성됩니다.
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
...
}
| 구성 요소 | 설명 |
|---|---|
@SpringBootConfiguration | 스프링 부트 설정 클래스 표시 (@Configuration 상속) |
@EnableAutoConfiguration | 자동 설정 활성화, 자동 설정으로 등록되는 빈을 읽고 등록 |
@ComponentScan | 사용자 정의 빈 탐색 및 등록 |
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, Spring Boot!";
}
}
@RestController 는 @Controller + @ResponseBody 를 포함한 애너테이션
HTTP 요청을 해당 메서드와 연결하는 라우팅 역할을 수행
@Controller가 @Component 를 포함하고 있어 빈으로 자동 등록됨