1. Spring Boot 소개
- Spring Boot
- Spring Framework
- Spring Framework Modules
- Spring Framework 특징
- Spring Boot 목표
- Spring Boot 시작
- Spring Boot 기능
- Spring Boot vs Spring Framework
2. Spring Boot 프로젝트 생성 및 실행
- Spring Boot 프로젝트 생성
- Spring Boot 프로젝트를 실행하는 여러가지 방법
3. Spring IoC
- IoC: Inversion of Control (제어 역전)
- Bean Factory
- ApplicationContext
- Spring Bean
- Bean 등록
- Stereotype Annotation
- Spring Bean 객체의 생명주기 설정
4. 의존성 주입 (Dependency Injection)
- DIP, IoC, DI 관계
- Spring DI (Dependency Injection)
1. Spring Boot 소개
Spring Boot
- Spring Boot == Framework.
- Framework: 원하는 기능을 구현하기 위하여, 일정한 형태(골격)을 제공.
- Library: 함수(기능)의 집합.
Spring Framework
- Spring is a opensource lightweight application framework that makes it easy to create Java enterprise applications
- 표준: Java enterprise 개발에 있어 사실상의 표준이다. Java EE를 기반으로 하며, 많은 Java 개발자들이 익숙하게 사용하고 있는 기술과 패턴을 채택.
- 신뢰성: 오랜 기간 동안 안정적으로 유지되어 왔으며, Pivotal과 같은 강력한 기업이 지원하는 강력한 커뮤니티가 있다.
- 생태계: Spring Boot/Cloud/Date 등 다양한 프로젝트와 라이브러리를 통해 다양한 영역에서 솔루션을 제공함.
Spring Framework Modules
Spring Framework 특징
- 경량 컨테이너로서, Spring Bean을 직접 관리한다.
- Spring Bean 객체와 Life Cycle을 관리.
(Spring Bean: Spring Container가 관리하는 중요 객체) - Container: Spring Bean 객체의 생성/보관/제거에 관한 모든 일을 처리.
- Spring Bean 객체와 Life Cycle을 관리.
- POJO(Plain Old Java Object) 기반의 Framework
- 일반적인 J2EE Framework와 비교하여, 특정한 interface를 구현하거나 상속을 받을 필요가 없다.
(c.f. Servlet API는 HttpServlet을 상속 받아야함) - 기존에 존재하는 라이브러리를 사용하기 편리하다 (자바 사용에 불편함이 없다)
- 일반적인 J2EE Framework와 비교하여, 특정한 interface를 구현하거나 상속을 받을 필요가 없다.
- 제어 역전(IoC: Inversion of Control)
- 제어권이 개발자가 아니라 Framework에 있다.
- DI: IoC의 구현 방식으로 객체의 의존성을 외부에서 주입하는 방법.
- 관점 지향 프로그래밍(AOP: Aspect-Oriented Programming)을 지원
- 복잡한 비즈니스 영역의 문제와 공통된 지원 영역의 문제를 분리할 수 있다.
- 문제 해결을 위한 집중.
- 서비스 추상화 (PSA: Portable Service Abstractions)
- 개발자가 특정 환경이나 기술에 종속되지 않고, 일관된 방식으로 서비스를 사용할 수 있도록 추상화를 제공.
- 코드를 간단하게 유지하면서도 다양한 기술과 서비스를 쉽게 전환 가능. (구현체 - implements만 갈아끼우면 됨)
더보기

Spring의 3대 요소
Spring의 3대 요소

- IoC: 객체의 생성 및 생명 주기를 개발자가 직접 관리하지 않고, 프레임워크(Spring 컨테이너)가 관리
ex) DI - AOP: 핵심 로직과 공통 기능(로깅, 트랜잭션 등)을 분리하여, 코드 중복 없이 횡단 관심사를 모듈화하는 프로그래밍 기법
ex) @ControllerAdvice에서 @ExceptionHandler로 동일한 에러 처리 - PAS: 다양한 기술(JDBC, 트랜잭션, 스케줄링 등)을 일관된 방식으로 사용할 수 있도록 인터페이스를 제공하는 Spring의 철학
ex) @Controller와 같이 편의성 제공
Spring Boot 목표
- java -jar 로 실행이 가능해야 한다.
- ex) java -jar target/demo-0.0.1-SNAPSHOT.jar
Spring Boot 시작
- Spring Framewok를 더 편하게 사용하기 위해서, Spring Boot 프로젝트 시작.
- Spring Boot는 내부적으로 Spring Framework 기반으로 동작.
Spring Boot의 기능
- 단독으로 실행 가능한 application 생성 (Framework도 5.0부터 가능)
- 실행형 jar, 실행형 war
- 내장형 Web Application Server 지원 (Framework도 5.0부터 가능)
- Tomcat, Jetty, Undertow, Netty for WebFlux
- 기본 설정된 Starter 모듈
- 의존성 (library dependency)
- 버전 호환성 보장 (dependencyManagement)
- 자동 설정 (Auto Configuration)
- 상용화에 필요한 통계, 상태점검 외부설정 지원 (Framework도 5.0부터 가능)
- Actuator (Health, metrics)
- 외부 설정
Spring Boot vs Spring Framework
- 라이브러리 의존성을 pom.xml에 직접 설정할 필요가 없다.
- spring-boot-starter-{module}만 설정하면 필요한 라이브러리 설정됨.
- 버전 정보를 직접 설정하고 테스트하지 않아도 된다.
- spring-boot-starter-parent에서 spring 모듈의 버전 및 3rd Party 라이브러리 버전도 제공.
- Web Application Server에 배포하지 않아도 된다.
- spring boot에서는 내장형 Web Application Server를 제공하기 때문에 이와 관련해서 따로 설정할 필요없다.
2. Spring Boot 프로젝트 생성 및 실행
Spring Boot 프로젝트 생성
- Spring Boot initializr 사용
- https://start.spring.io - 웹 기반 Spring Boot 프로젝트 생성 도구
Spring Boot 프로젝트를 실행하는 여러가지 방법
- Executable Jar/War
ex) mvn package / gradle bootjar
- Build Tool
ex) mvn spring-boot: run / gradle bootRun
3. Spring IoC
IoC: Inversion of Control (제어 역전)
- 프로그램의 제어 흐름이 프로그램 코드에 의해 결정되는 것이 아니라, 외부(ex. Framework)에서 결정된다는 개념
- 제어(아래 2개)를 Framework에게 맡긴다.
- 프로그램의 흐름
- 객체의 생성
- 개발자는 프로그램의 흐름이나, 객체 생성과 관련된 코드를 직접 작성하지 않는다.
- 개발자는 Framework가 제공하는 정의 방법을 사용하여 코드를 정의만 한다.
- Framework는 이 정의를 보고, 객체를 생성하고 코드가 동작하는 순서를 결정하여 실행한다.
Bean Factory
- Spring Framework의 핵심 컨테이너 중 하나이며, 스프링의 스펙이다.
- Bean Factory는 Spring IoC 컨테이너의 가장 기본적인 interface로, Bean의 생성 및 관리를 담당한다.
- 이를 통해 DI를 구현하며, Spring Application에서 객체의 생명주기와 구성을 관리하는 중요한 역할을 담당.
ApplicationContext
- Spring Framework에서 중앙 interface로, application의 설정 정보를 관리한다.
- Bean Factory 기능을 확장한 것으로, application의 이벤트 처리 / 리소스 로딩 / 메시지 지원 등의 기능을 제공.
- BeanFactory, ApplicationContext, Ioc Containerm, Spring Container 등 다 비슷한 개념이다.
Spring Bean
- ApplicationContext에 의해 관리되는 객체.
- Spring Framework에서 Application의 객체들을 Bean으로 등록하고, 이들의 생성/생명주기/의존성 관리 등을 컨테이너가 담당함.
- 일반적으로 annotation 등으로 DI가 이루어짐.
* JavaBeans
- Spring Bean과 전혀 다른 개념.
- Java Bean은 재사용 가능한 Component로, 기본 생성자를 가지며, Getter와 Setter 메소드를 통해 property에 접근할 수 있는 단순한 POJO를 의미.
* @ApplicationRunner
- Spring Application이 시작될 때 같이 실행되는 코드.
Bean 등록
1. @Configuration + @Bean
- 클래스에 @Configuration을 붙이고, Bean에 등록할 객체를 반환하는 메소드에 @Bean을 붙인다.
- @Configuration은 클래스 내의 @Bean이 붙은 메소드를 통해 Bean을 정의하고 생성.
- 클래스가 하나 이상의 @Bean 메소드를 포함하고 있으며, 이 메소드들이 Application Context에 Bean 정의를 제공한다는 걸 의미한다. (@Bean 메소드는 프로그래밍 방식으로 Bean 인스턴스를 생성하고 구성함)
2. @Component
- Bean에 등록한 클래스에 @Component를 붙인다.
- 클래스 자체를 Bean으로 등록.
- 클래스 레벨에서 사용되며, 해당 클래스의 instance를 Spring 컨테이너가 관리하는 Bean으로 등록.
(주로 Service, Repository, Controller와 같은 Stereotype Component에 사용됨)
/* 1. @Configuration + @Bean */
@Configuration
public class config {
@Bean
OrderReceiverBean orderReceiverBean() {
return new OrderReceiverBean();
}
@Bean
PaymentProcessorBean paymentProcessorBean() {
return new PaymentProcessorBean();
}
}
/* 2. @Component */
@Component
public class DeliveryServiceBean implements Employee {
@Override
public void start() {
System.out.println("배달 한다");
}
}
Stereotype Annotation
- 개발자가 application의 아키텍처에서 특정 클래스가 어떤 역할을 하는지를 명확히 표현하는 데 사용.
- 기능적으로 @Component와 동일한 역할.
- 역할에 맞는 annotation을 사용하여, 코드의 가독성과 유지 보수에 도움.
- @Controller: 클라이언트의 요청을 처리하고, View를 반환하는 역할.
- @Service: 비즈니스 로직을 처리.
- @Repository: DB와의 상호작용을 담당.
Spring Bean 객체의 생명주기 설정
1) Bean Scope
- 생명주기 종류
- singleton: ApplicationContext가 시작될 때 초기화되고, ApplicationContext가 종료될 때 소멸됨. 이는 애플리케이션 전체에서 단 하나의 인스턴스만을 유지함을 의미.
- prototype: 요청될 때마다 새로운 인스턴스가 생성. 생성된 각 인스턴스는 호출자에 의해 관리되며, Spring 컨테이너는 생성 이후에 이 인스턴스를 관리하지 않음.
- request(web): HTTP 요청 하나가 들어오고 나갈 때 까지 유지되는 스코프, 각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고, 관리된다.
- session(web): HTTP Session과 동일한 생명주기를 가지는 스코프
- application(web): 서블릿 컨텍스트( ServletContext )와 동일한 생명주기를 가지는 스코프
- websocket(web): 웹 소켓과 동일한 생명주기를 가지는 스코프
2) Singleton과 Prototype
- Singleton: Spring Bean 객체의 default.
- Prototype: Bean의 생성과 DI 까지는 Spring Container가 관리해주지만, 소멸은 관리해주지 않는다.
3) Bean의 생명 주기에 개입하기
- Spring Bean 생명주기
Spring IoC 컨테이너 생성 -> Spring Bean 생성 -> DI -> (초기화 콜백 메소드 호출) -> 사용 -> (소멸 전 콜백 메소드 호출) -> 스프링 종료 - Bean의 생명주기에 개입하는 3가지 방법
- Interface인 InitializingBean, DisposableBean을 구현 (afterPropertiesSet(), destroy() 오버라이딩)
- @Bean annotation 설정 사용 (@Bean의 scope에 init과 destroy 메소드 직접 지정)
- @Postconstruct, @PreDestroy 사용. -> 사용 권장
더보기
/* 1. InitializingBean, DisposableBean을 구현 (afterPropertiesSet(), destroy() 메소드 오버라이드) */
public class EnglishGreeting implements Greeting, InitializingBean, DisposableBean {
public EnglishGreeting() {
System.out.println("english java constructor");
}
@Override
public void sayHello() {
System.out.println("hello world");
}
// DisposableBean 구현
@Override
public void destroy() {
System.out.println("english DisposableBean destroy");
}
// InitializingBean 구현
@Override
public void afterPropertiesSet() {
System.out.println("english InitializingBean afterPropertiesSet");
}
}
/* 2. @Bean annotation 설정 사용 */
@Configuration
public class GreetingConfig {
@Bean(initMethod = "customInit", destroyMethod = "customDestroy")
Greeting englishGreeting() {
return new EnglishGreeting();
}
}
public class EnglishGreeting implements Greeting {
public EnglishGreeting() {
System.out.println("eng java constructor");
}
@Override
public void sayHello() {
System.out.println("hello world");
}
@Override
public void customInit() {
System.out.println("eng custom init");
}
@Override
public void customDestroy() {
System.out.println("eng custom custom destroy");
}
}
/* 3. @PostConstruct, @PreDestroy 사용 */
public class EnglishGreeting implements Greeting {
public EnglishGreeting() {
System.out.println("eng java constructor");
}
@Override
public void sayHello() {
System.out.println("hello world");
}
@PostConstruct
public void customPostConstruct() {
System.out.println("env PostConstruct");
}
@PreDestroy
public void customPreDestroy() {
System.out.println("env preDestroy");
}
}
위 3가지 방법을 동시에 실행하면?
- 순서
- @PostConstruct
- afterPropertiesSet()
- custom init() method
- @PreDestroy
- destroy()
- custom destroy() method
요약
더보기
IoC
- 개발 편의성을 올려주기 위한 디자인 패턴의 하나
- 프로그램의 제어 흐름이 프로그램 코드에 의해 결정되는 것이 아니라, 외부에서 결정
- 주요 객체의 생성 및 객체 간의 의존성을 사용자가 관리하지 않는다.
Spring
- Ioc 를 지원해주는 프레임워크 중 하나로 Bean 이라는 개념을 이용해서 이를 편하게 하고 있음
ApplicationContext
- Spring 에서 Ioc 패턴을 유지해주는 구현체
- Bean 의 생성, 등록, 관리를 해준다.
Bean
- ApplicationContext 에 의해서 관리되는 객체
- Spring 애플리케이션은 다양한 Bean 들이 상호작용하는 형태로 구성된다.
- Bean 은 생명주기를 가지며, 우리는 중간에 개입하는 메소드를 생성할 수 있다.
4. 의존성 주입 (Dependency Injection)
DIP, IoC, DI 관계
- DIP는 원칙이고, IoC는 원칙을 지키기 위한 패턴이고, DI는 패턴을 구현한 방법 중 하나이다.
- DIP: 상위 모듈이 하위 모듈에 의존관계를 가지면 안된다는 원칙.
- IoC: 프로그램의 흐름을 제어하는 주체가 프로그래머가 아닌 외부 시스템(ex. Framework)에 의해 결정된다는 개념.
- DI: 객체가 필요로 하는 의존성을 외부에서 직접 주입받는 것.
Spring DI (Dependency Injection)
- 프로그래밍에서 구성 요소간의 의존관계가 소스코드 내부가 아닌 외부의 설정파일 등을 통해 정의되게 하는 디자인 패턴 중 하나.
- IoC 패턴 중의 하나로, Object 간의 의존성을 낮추고 외부에서 객체를 생성하고 전달한다.
- DI는 디자인 패턴으로 IoC의 구현이다.
@AutoWired
- 객체가 필요한 곳을 알려준다.
- Spring에서 DI(등록한 Bean을 사용)하는 3가지 방법.
- Constructor Injection
- Setter Injection
- Field Injection
더보기
/* 1. Constructor Injection */
@Component
public class AppStartupRunner implements ApplicationRunner{
private Greeting greeting;
// 생성자에서 주입.
@Autowired
public void setGreeting(Greeting greeting){
this.greeting = greeting;
}
@Override
public void run(ApplicationArguments args){
greeting.sayHello();
}
}
/* 2. Setter Injection */
@Component
public class AppStartupRunner implements ApplicationRunner{
private Greeting greeting;
// setter 메소드에서 주입.
@Autowired
public void setGreeting(Greeting greeting){
this.greeting = greeting;
}
@Override
public void run(ApplicationArguments args){
greeting.sayHello();
}
}
/* 3. Field Injection */
@Component
public class AppStartupRunner implements ApplicationRunner{
@Autowired
private Greeting greeting;
@Override
public void run(ApplicationArguments args){
greeting.sayHello();
}
}
* Injection할 Bean을 더 명확하게 하고 싶다면?
@Primary
- Spring에서 자동 와이어링 시 여러 Bean 후보가 있을 경우, 해당 Bean이 우선적으로 선택.
@Qualifier
- 자동 주입 시 특정 Bean을 명시적으로 지정할 수 있게 해줌. 이름으로 Bean을 구분하여 주입할 때 사용.
/* 1. @Primary */
/* (1) @Configuration + @Bean */
@Configuration
public class GreetingConfig {
@Primary // 우선 순위 지정
@Bean
Greeting englishGreeting() {
return new EnglishGreeting();
}
@Bean
Greeting koreanGreeting() {
return new KoreanGreeting();
}
// 이름 등록
@Bean("myCustomBeanName")
Greeting japaneseGreeting() {
return new JapaneseGreeting();
}
}
/* (2) @Component */
@Primary // @Component 를 사용하는 경우에도 @Primary 를 사용할 수 있다.
@Component("myCustomBeanName") // 이름 등록
public class EnglishGreeting implements Greeting {
@Override
public void sayHello() {
System.out.println("hello world");
}
}
/* 2. @Qualifier */
public AppStartupRunner(Greeting greeting,
Greeting koreanGreeting,
Greeting japaneseGreeting,
Greeting myCustomBeanName,
//TODO-2 @Bean 에서 이름을 지정하지 않으면 자동으로 적절한 이름을 선택한다(메소드명)
@Qualifier("koreanGreeting") Greeting qKoreanGreeting,
@Qualifier("myCustomBeanName") Greeting qMyCustomBeanName,
//TODO-3 이름을 지정하는 경우 자동으로 이름을 지정하지 않는다.
//@Qualifier("japaneseGreeting") Greeting qJapaneseGreeting,
KoreanGreeting cKoreanGreeting,
JapaneseGreeting cJapaneseGreeting) {
this.greeting = greeting;
this.koreanGreeting = koreanGreeting;
this.japaneseGreeting = japaneseGreeting;
this.myCustomBeanName = myCustomBeanName;
this.qKoreanGreeting = qKoreanGreeting;
this.qMyCustomBeanName = qMyCustomBeanName;
this.cKoreanGreeting = cKoreanGreeting;
this.cJapaneseGreeting = cJapaneseGreeting;
}
출처: https://nhnacademy.dooray.com/share/pages/ABFgz8KgRv62A85x9KClUw
Spring Boot Core
nhnacademy.dooray.com
'Spring' 카테고리의 다른 글
[Spring Boot] 01. Spring Boot Core (3) - AOP(관점 지향 프로그래밍) * (0) | 2024.11.08 |
---|---|
[Spring Boot] @ConfigurationProperties 활성화시 @Profile 무시 에러 (0) | 2024.11.08 |
[Spring Boot] 01. Spring Boot Core (2) - 자동 구성과 외부 구성 (0) | 2024.11.06 |
[Spring Boot] Lombok (0) | 2024.11.06 |
[Spring Boot] 디자인 패턴 (0) | 2024.11.04 |