Spring Boot (+ RESTful)

Spring Boot - Application 실행하기 / Spring Boot 동작 원리 / Spring Boot의 Annotation / @SpringBootConfiguration 의 상세 원리

wy-family 2024. 12. 13. 10:01

프로젝트 생성시 지정한 Package에

"프로젝트이름(Artifact) + Application" 형태의 자바 어플리케이션이 만들어진다.


 

이번에는 IntelliJ 에서 진행해보고자 한다.

 

나는 분명 Artifact 에 HelloBoot 라고 입력했는데, 만들어진 main class의 이름을 보면,
HelloBootApplication 이라고 나와있다.

 

일단, 이렇게 어플리케이션 open을 하고나면은 Java version check 부터 해보자.

 

확인했으니 이제 run 도 해보자.

run 해보고 나서 웹에서도 확인해보자.

그리고 뭔가 만들어놓은게 없으니 만들어야 한다.

Controller, templates/index.html 을 만들어주자.

 


Spring Boot 애플리케이션의 동작 원리는 다양한 구성 요소가 유기적으로 동작하여 애플리케이션을 실행하고 웹 요청을 처리하는 방식으로 이루어져 있습니다. Spring Boot 애플리케이션이 실행되는 과정을 순차적으로 설명하겠습니다.


1. 애플리케이션 시작: SpringApplication과 SpringApplication.run()

  • Spring Boot 애플리케이션은 일반적으로 main() 메서드에서 SpringApplication.run()을 호출하여 시작됩니다.
  • SpringApplication.run() 메서드는 다음 작업을 수행합니다:
    • Spring Container 생성: 스프링 애플리케이션 컨텍스트(주로 AnnotationConfigServletWebServerApplicationContext)를 초기화합니다.
    • Environment 설정: 애플리케이션 환경 변수를 로드합니다(application.properties, application.yml 포함).
    • AutoConfiguration 수행: @EnableAutoConfiguration을 통해 자동 설정 작업을 수행합니다.
    • Component Scan 수행: @ComponentScan을 통해 애플리케이션 내에서 컴포넌트를 스캔하고 필요한 Bean을 등록합니다.

2. Spring Container와 Application Context

  • Spring Container는 Bean의 생명 주기를 관리합니다. ApplicationContext는 컨테이너의 핵심 인터페이스로, Spring Boot에서는 주로 AnnotationConfigServletWebServerApplicationContext를 사용합니다.
  • 이 컨텍스트는 Bean 정의를 읽고 초기화하며, 이후 애플리케이션 전반에서 사용될 Bean들을 제공합니다.

3. @SpringBootApplication의 역할

  • @SpringBootApplication은 아래의 세 가지 주요 어노테이션의 조합입니다:
    • @SpringBootConfiguration: 스프링 설정 클래스를 지정합니다.
    • @EnableAutoConfiguration: 애플리케이션에 필요한 자동 설정을 활성화합니다. 예를 들어, 웹 서버 설정, 데이터베이스 연결 설정 등이 포함됩니다.
    • @ComponentScan: 특정 패키지와 그 하위 패키지에서 Bean을 검색합니다.

4. application.properties 또는 application.yml

  • Spring Boot 애플리케이션의 환경 설정을 정의하는 파일입니다.
  • 예: server.port = 8081로 설정하면 애플리케이션의 기본 포트를 8081로 변경합니다.
  • 이러한 설정은 Environment 객체에 로드되어 애플리케이션 전반에서 참조됩니다.

5. 웹 애플리케이션 실행: WebApplicationContext와 Front Controller

  • Spring Boot는 Servlet 컨테이너(예: Tomcat, Jetty)를 실행하며 웹 애플리케이션 컨텍스트를 구성합니다.
  • WebApplicationContext는 Servlet 환경에 특화된 애플리케이션 컨텍스트로, HTTP 요청 처리에 필요한 Bean을 관리합니다.
  • Front Controller 역할은 DispatcherServlet이 담당하며, 모든 HTTP 요청을 처리하고 적절한 로직으로 라우팅합니다.

6. 요청 처리 흐름

  1. HandlerMapping:
    • HTTP 요청 경로를 기준으로 적절한 핸들러(컨트롤러)를 찾아냅니다.
  2. Controller:
    • 사용자의 요청을 처리하고 필요한 비즈니스 로직을 수행하거나 데이터를 조회합니다.
  3. Repository:
    • Controller에서 요청한 데이터를 데이터베이스에서 가져오거나 저장하는 역할을 합니다.
  4. ViewResolver:
    • Controller에서 반환된 데이터를 기반으로 적절한 View(HTML, JSON 등)를 생성합니다.

7. POJO 기반 개발

  • Spring Boot는 POJO(Plain Old Java Object)를 기반으로 Bean을 작성하므로 간단한 Java 객체를 활용하여 복잡한 설정 없이도 애플리케이션을 개발할 수 있습니다.

8. AutoConfiguration과 컴포넌트 스캔

  • Spring Boot의 강력한 기능 중 하나는 자동 설정입니다.
    • 예: Spring Web Starter 의존성을 추가하면, @EnableAutoConfiguration이 자동으로 DispatcherServlet, HandlerMapping, ViewResolver 등을 설정합니다.
  • **@ComponentScan**은 개발자가 별도로 등록하지 않아도 @Component, @Service, @Repository 등의 어노테이션이 붙은 클래스를 Bean으로 등록합니다.

요약: Spring Boot 애플리케이션의 동작 원리

  1. SpringApplication.run()으로 애플리케이션 시작.
  2. Application Context 생성 및 환경 설정 로드.
  3. AutoConfiguration과 ComponentScan으로 필요한 Bean을 자동 등록.
  4. WebApplicationContext와 Front Controller를 통해 HTTP 요청 처리.
  5. HandlerMapping과 ViewResolver로 요청에 따른 응답 생성.

이렇게 Spring Boot는 최소한의 설정으로 강력하고 유연한 애플리케이션을 실행할 수 있게 합니다.


Spring Boot 에서 annotation 어노테이션 @ 에 대해서 설명해줄래?
Spring Boot에서 어노테이션(Annotation, @)은 클래스, 메서드, 필드, 매개변수 등에 추가 정보를 제공하기 위한 메타데이터로 사용됩니다. 스프링 프레임워크는 이 어노테이션을 기반으로 다양한 기능을 제공하며, Spring Boot에서는 특히 간결한 설정자동화된 작업을 위해 어노테이션이 널리 활용됩니다.

1. 어노테이션의 개념

  • Java의 어노테이션은 @ 기호로 시작하며, 코드에 의미나 설정을 부여합니다.
  • 컴파일러 또는 런타임 시 어노테이션을 읽고 해당 로직을 실행하거나 설정을 적용합니다.
  • Spring Boot에서는 어노테이션 기반으로 의존성 주입, 자동 구성, 요청 처리, 트랜잭션 관리 등을 수행합니다.

2. 어노테이션의 종류

1) Spring Core 어노테이션

Spring Framework와 Spring Boot에서 제공하는 주요 어노테이션:

a) 구성 관련 어노테이션

  • @SpringBootApplication
    • Spring Boot 애플리케이션의 진입점을 표시하며, 여러 어노테이션을 포함한 메타 어노테이션입니다.
    • 포함하는 어노테이션:
      • @SpringBootConfiguration: 설정 클래스를 지정.
      • @EnableAutoConfiguration: 자동 설정 활성화.
      • @ComponentScan: 특정 패키지의 Bean을 자동 검색.
  • @Configuration
    • 클래스가 Spring 설정 파일임을 나타냅니다. Java 기반으로 Bean 정의를 작성할 때 사용합니다.
  • @Bean
    • 메서드 레벨에서 사용되며, 메서드의 반환값을 Spring Bean으로 등록합니다.

b) 컴포넌트 등록 관련 어노테이션

  • @Component
    • 일반적인 Spring Bean으로 등록.
  • @Controller
    • MVC의 Controller 역할. HTTP 요청을 처리.
  • @Service
    • 비즈니스 로직을 구현한 클래스에 사용.
  • @Repository
    • 데이터 접근 계층(DAO)에 사용. 예외 변환 등의 추가 기능을 제공.

c) 의존성 주입 관련 어노테이션

  • @Autowired
    • 타입에 따라 의존성을 자동으로 주입합니다. 주로 필드, 생성자, 메서드에서 사용.
  • @Qualifier
    • 동일한 타입의 Bean이 여러 개 있을 때 특정 Bean을 선택하도록 지정.
  • @Value
    • 외부 설정 파일(application.properties 등)의 값을 주입.

d) AOP 관련 어노테이션

  • @Aspect
    • AOP에서 해당 클래스가 Aspect임을 나타냅니다.
  • @Before, @After, @Around
    • 메서드 실행 전후에 실행될 공통 로직 정의.

2) Spring Boot 관련 어노테이션

a) 자동 구성

  • @EnableAutoConfiguration
    • Spring Boot의 자동 설정 기능을 활성화합니다.

b) 테스트 관련

  • @SpringBootTest
    • 통합 테스트를 위한 설정을 제공합니다.
  • @MockBean
    • 테스트 시 특정 Bean을 Mock 객체로 대체합니다.

3) HTTP 요청 처리 관련 어노테이션

a) REST 컨트롤러

  • @RestController
    • Controller와 달리 JSON 데이터를 반환하는 클래스에 사용.
  • @RequestMapping
    • URL 경로를 매핑합니다. 클래스와 메서드 레벨 모두에서 사용 가능.
  • @GetMapping, @PostMapping, @PutMapping, @DeleteMapping
    • HTTP 메서드별 요청 매핑에 사용.

b) 요청과 응답

  • @PathVariable
    • URL 경로에 포함된 값을 매개변수로 매핑.
  • @RequestParam
    • URL 쿼리 파라미터를 매개변수로 매핑.
  • @RequestBody
    • HTTP 요청 본문을 매핑.
  • @ResponseBody
    • 반환값을 HTTP 응답 본문에 매핑.

4) 데이터와 트랜잭션 관련 어노테이션

  • @Entity
    • JPA 엔티티로 매핑.
  • @Table
    • 엔티티와 데이터베이스 테이블 간의 매핑 지정.
  • @Transactional
    • 메서드나 클래스의 트랜잭션 관리.

3. 어노테이션의 동작 원리

Spring Boot는 어노테이션을 통해 의미를 부여하고, 이를 런타임에 해석하여 애플리케이션 동작을 제어합니다.

  1. 리플렉션 사용
    • Java의 리플렉션(Reflection)을 사용하여 어노테이션 정보를 읽고, 관련 설정을 수행하거나 동작을 실행.
  2. 메타 어노테이션
    • 어노테이션이 다른 어노테이션을 포함하여 더 큰 의미를 제공.
    • 예: @SpringBootApplication은 @Configuration, @EnableAutoConfiguration, @ComponentScan 포함.

4. 어노테이션의 장점

  1. 간결한 설정: XML이나 Java 코드의 복잡한 설정을 줄여줍니다.
  2. 가독성: 코드와 설정이 한 곳에 있어 가독성과 유지보수가 용이합니다.
  3. 유연성: 다양한 환경에서 설정과 동작을 쉽게 변경 가능.

5. 자주 묻는 질문

1) 어노테이션 없이 개발이 가능한가요?

  • 가능하지만, 어노테이션이 없다면 XML 설정 파일과 많은 수작업 설정이 필요해져 개발 속도가 느려지고 가독성이 떨어집니다.

2) Spring Boot의 어노테이션은 사용자 정의가 가능한가요?

  • 네, Java의 @interface를 사용하여 사용자 정의 어노테이션을 작성할 수 있습니다.

Spring Boot는 어노테이션을 활용해 최소한의 코드로 강력한 기능을 제공하며, 이는 생산성과 유지보수성을 크게 향상시킵니다.


 

@SpringBootApplication 은 @SpringBootConfiguration 을 포함하고 있다고 했다.

그리고 @SpringBootConfiguration은 @Configuration 과 같은 형식의 어노테이션이다.

@Configuration은 환경 설정 파일들?

일단,

어떤 클래스에 @Configuration 어노테이션을 붙여주게 되면

이 클래스의 객체를 생성하라 라는 어노테이션이다.

예를 들어 보여주겠다.

 

일단,root application (여기서는 HelloBootApplication) 이 패키지가 있는 바로 아랫쪽에 패키지를 만들어야 어노테이션들이 해석이 된다.

 

@SpringBootApplication은 @SpringBootConfiguration을 포함하고 있는데, @configuration 가 붙어있는 이 어노테이션들을 해석하라라는 말이 된다. 확인을 해보려면, root application으로 가서 run 을 돌려보면,

실행된 것들을 잘 확인해보면, System.out.println("TestConfig"); 가 실행이 되었기 때문에 TestConfig 가 출력이 되는 걸 찾을 수 있을 것이다.

 

즉, TestConfig 클래스에서, new TestConfig() 해서 객체가 생성이 되었다는 뜻. 생성자가 호출이 되었다는 것.

@Configuration 이 붙이게 되면은 자동으로 해석을 해서 객체를 메모리에다가 만들어주는 구나

내가 뭔가 일을 하기 위해서 나하고 연결되어 있는 사람들을 먼저 준비를 시켜서 같이 일을 해야되니까,

마찬가지로 거기와 관련된 객체를 메모리에다가 올려야 되기때문에

자동으로 메모리에 올려야 되기 때문에 @Configuration을 붙여서 이 어노테이션이 붙어있는 애들을 자동으로 메모리에 올리도록 하는 것.

 

TestConfig 클래스 안에 @Bean 이라는 걸 추가해보자. (+ MyBean 클래스 추가)

 

@Bean 이라는 어노테이션도 객체를 생성하라는 어노테이션이다.

 

MyBean 이라는 클래스를 정의했다. 이 클래스를 사용하려면, new MyBean() 을 해가지고 객체를 생성을 해줘야 한다.

생성자가 호출이 되는지 확인하기 위해 sout 도 해주었다.

이 객체를 @Configuration 메모리에다가 올리고 싶다면, @Bean 을 저렇게 활용하는 것.

@Bean 어노테이션이 붙어있으면, 아래 메소드 myBean() 가 자동으로 실행이 된다. return 으로 new MyBean(); 을 갹체를 만드니까 메모리에 MyBean 객체가 올라가게 되는 것. MyBean 객체를 쓰고 싶으면, 언제든지 꺼내서 쓸 수가 있게 된다.

이런 걸 종속성, IoC, 종속 주입, Dependency Injection 의존성 주입이라는 그런 방법으로 메모리에 올라와 있는 객체를 끌어당겨다 쓸 수가 있는 것.

 

그럼 이제 확인을 해보자.

@Configuration 안에 있는 @Bean 이 해석이 되면, sout 해준, myBean() 도 TestConfig 아래에 떠야한다.

 

결론적으로, @Configuration 은 뭔가를 설정할 때, 이 어노테이션을 붙여주게 되면은 자동으로 메모리에 로딩이 된다, 이런 클래스들이 필요할때는 @Configuration 하면 되는 것이고, @SpringBootApplication 이 있으면 @Configuration 이 붙어있는 애들은 모두 실행이 된다는 것.

 

여기서 메모리 메모리 라고 말하고 있는 부분은, 객체가 생성되고 관리되는 메모리 공간은 Spring Container 을 의미함.


당신이 작성한 설명은 아주 상세하고, @SpringBootConfiguration 및 @Configuration 어노테이션의 역할과 작동 방식을 잘 다루고 있습니다. 이를 기반으로 조금 더 명확하게 정리하고 보완해드릴게요.


1. @SpringBootApplication과 @SpringBootConfiguration의 관계

  • @SpringBootApplication은 메타 어노테이션으로, 내부적으로 여러 어노테이션을 포함하고 있습니다.
    • 그중 하나가 바로 @SpringBootConfiguration입니다.
  • **@SpringBootConfiguration**은 @Configuration과 동일한 역할을 합니다.
    • 스프링 설정 클래스를 나타내며, 해당 클래스에 정의된 Bean들을 Spring Container에 등록합니다.

2. @Configuration의 역할

  • **@Configuration**은 설정 클래스를 나타내는 어노테이션으로, Spring Container에 필요한 Bean들을 등록할 때 사용됩니다.
  • 이 어노테이션이 붙은 클래스는 Spring이 런타임 시 읽어들이며, 해당 클래스의 메서드에서 반환된 객체(Bean)를 Spring Container에 등록합니다.

예시: TestConfig 클래스와 MyBean 클래스

@Configuration
public class TestConfig {

    public TestConfig() {
        System.out.println("TestConfig 생성자 호출");
    }

    @Bean
    public MyBean myBean() {
        System.out.println("myBean() 메서드 호출");
        return new MyBean();
    }
}

public class MyBean {
    public MyBean() {
        System.out.println("MyBean 생성자 호출");
    }
}
  1. @Configuration 클래스 생성
    • TestConfig 클래스에 @Configuration을 붙임으로써, 이 클래스가 Spring Container에 의해 처리됩니다.
    • Spring은 TestConfig의 인스턴스를 생성하고, 클래스 안의 @Bean 어노테이션이 붙은 메서드를 호출하여 Bean을 등록합니다.
  2. @Bean 메서드 호출
    • myBean() 메서드가 호출되면서 MyBean 객체가 생성됩니다.
    • 이 객체는 Spring Container에 등록되며, 다른 Bean에서 의존성 주입(Dependency Injection)으로 사용할 수 있습니다.

실행 결과

Spring Boot 애플리케이션을 실행하면:

TestConfig 생성자 호출
myBean() 메서드 호출
MyBean 생성자 호출

위와 같은 출력이 나타납니다. 이는 @Configuration 클래스와 @Bean 메서드가 정상적으로 동작했음을 의미합니다.


3. @SpringBootApplication이 @Configuration과 관련된 동작

  • @SpringBootApplication은 @SpringBootConfiguration을 통해 @Configuration의 역할을 포함합니다.
  • 애플리케이션 실행 시:
    • @SpringBootApplication은 자신이 속한 패키지와 하위 패키지를 자동으로 스캔(@ComponentScan)합니다.
    • 이 과정에서 @Configuration이 붙은 클래스와 그 안의 @Bean 메서드를 자동으로 처리합니다.

4. Spring Container와 메모리 관리

  • 설명에서 "메모리에 올라간다"라는 표현은 Spring Container에 등록된다는 의미로 해석할 수 있습니다.
  • Spring Container는 애플리케이션에서 사용할 객체(Bean)를 생성하고, 이를 관리하는 역할을 합니다.
  • 의존성 주입(Dependency Injection, DI)을 통해 다른 클래스에서 Spring Container에 등록된 객체를 쉽게 사용할 수 있습니다.

5. 종속성 주입의 예

  • 위에서 등록된 MyBean 객체를 다른 클래스에서 사용하는 예를 들어보겠습니다.
@Component
public class MyService {

    private final MyBean myBean;

    @Autowired
    public MyService(MyBean myBean) {
        this.myBean = myBean;
        System.out.println("MyService 생성자 호출");
    }
}
  1. MyService 클래스에서 의존성 주입
    • @Autowired를 통해 MyService는 Spring Container에 등록된 MyBean 객체를 주입받습니다.
    • 이로 인해 개발자는 객체를 직접 생성하거나 관리하지 않아도 됩니다.
  2. 실행 결과
TestConfig 생성자 호출
myBean() 메서드 호출
MyBean 생성자 호출
MyService 생성자 호출

6. 결론

  • @SpringBootConfiguration은 @Configuration과 동일하게 Spring Container에 설정 클래스를 등록하고, 필요한 Bean들을 정의하는 데 사용됩니다.
  • @Configuration 클래스 안의 @Bean 메서드는 Spring Container가 관리하는 객체를 생성하고 등록하는 핵심 메커니즘입니다.
  • Spring Boot 애플리케이션은 @SpringBootApplication을 통해 이러한 설정 클래스와 Bean들을 자동으로 처리하여 간편하게 애플리케이션을 실행할 수 있습니다.

@EnableAutoConfiguration 부터는 다음 게시글에서.