ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 레거시 스프링의 설정방식과 구조가 스프링부트에서는 어떻게 보완되었을까?
    java spring boot 2025. 5. 17. 16:08

    개요

    Spring Boot 도입 후 발생할 수 있는 구조적, 설정적 차이를 사전에 공유함으로써 개발 환경 변화에 대한 혼란을 최소화하고, 향후 유지보수 및 신규 개발 시 참고 자료로 활용하기 위함입니다. 

     

    목차

    1.스프링, 스프링부트란?

    2.스프링부트는 스프링의 어떤점들을 보완하였을까?

      1)컴포넌트 스캔

      2)웹 애플리케이션 구성

      3)웹 애플리케이션 실행

      4)스프링 외부 라이브러리 클래스 빈 선언

      5)IOC 컨테이너 관리

      6)라이브러리 버전 관리

      7)스프링프레임워크 구동을 위한 필수 라이브러리들

    3.스프링부트 실행순서

    4.스프링부트에서 추가된 핵심기능

      1)엑츄에이터

     

    1.스프링, 스프링부트란?

    1)스프링

    자바 기반의 오픈 소스 애플리케이션 프레임워크

    2)스프링부트

    스프링을 쉽게 사용할 수 있게 해주는 도구이다. 본질은 스프링 프레임워크

     

    2.스프링부트는 스프링의 어떤점들을 보완하였을까?

    1)컴포넌트 스캔

    A.스프링에서의 컴포넌트 스캔

    다음과 같이 servlet-context.xml 파일에 컴포넌트 스캔 태그를 작성해줘야한다.

    <context:component-scan base-package="klago.nonprofit.controller" />
    <context:component-scan base-package="klago.nonprofit.dao" />
    <context:component-scan base-package="klago.nonprofit.service" />

     

    B.스프링부트에서의 컴포넌트 스캔

    다음과 같이 main() 메서드가 포함된 클래스에 선언된 @SpringBootApplication 어노테이션 내부의 @ComponentScan 어노테이션이 자동으로 컴포넌트 스캔기능을 수행해준다. 즉 개발자가 컴포넌트 스캔 설정 작업을 직접할 필요가 없다.

     

    단! 컴포넌트 스캔은 해당 클래스가 위치한 패키지를 기준으로 하위 패키지에 선언된 빈들만 대상으로 스캔을 진행한다.

     

    위 프로젝트를 기준으로 보면 com.example.demo 패키지 하위에 선언된 빈들만 스캔대상이 된다.

    만약 com.example2.demo 패키지를 생성하고 그 하위에 스프링 빈 클래스를 생성하면 스캔대상이 되지 않는다.

     

    2)웹 애플리케이션 구성

    A.스프링에서의 웹 애플리케이션 구성

    다음과 같이 DispacherServlet 생성, url 매핑, servlet-context.xml 연결

    ,ContextLoaderListener 및 root-context 구성 등을 web.xml 파일에 개발자가 직접 작성해야한다.

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:config/spring/root-context.xml
        </param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:config/spring/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

     

    B.스프링부트에서의 웹 애플리케이션 구성

    WAR 파일로 패키징하여 외부 톰캣에 배포할 경우(스프링 사용시), 톰캣은 web.xml을 읽어 애플리케이션 초기화를 수행합니다. 하지만 스프링부트는 web.xml을 대체하기 위해 Java 기반의 설정 방식을 사용합니다. 그리고 이 설정은 이미 스프링부트 내부 로직에 포함되어져있어 개발자는 별도의 설정파일 작성 없이 애플리케이션을 구동할 수 있다.

     

    3)웹 애플리케이션 실행

    A.스프링 애플리케이션 실행

    스프링 웹 애플리케이션을 개발할때는 먼저 서버에 톰캣같은 was 를 설치해준다. 그리고 was 에서 동작하도록 서블릿 스펙에 맞춰진 코드를(스프링프레임워크는 서블릿 스펙을 기반으로 동작함) 작성하고 war 형식으로 빌드해서 war 를 만든다. 그리고 이렇게 만들어진 war 를 was 에 전달해서 배포하는 방식으로 애플리케이션이 동작했다.

     

    B.스프링부트 애플리케이션 실행

    스프링부트는 애플리케이션 코드 안에 톰캣과 같은 was가 라이브러리로 내장되어있다. 개발자는 코드를 작성하고 jar 로 빌드한 다음에 해당 jar 를 원하는 위치에서 실행하기만 하면 was 도 함께 실행된다. 쉽게 말해 재발자는 main() 메서드만 실행하면 되고 서버에 was 설치나 ide(이클립스,인텔리제이) 같은 개발 환경에서 was 와 연동하는 복잡한 일을 수행하지 않아도된다.

     

    실제 구동되는 톰캣 객체가 어디에 선언되어있는지 확인하려면

     TomcatServletWebServerFacotory 클래스의 getWebServer 메서드를 확인해보면 된다.

    그리고 this.getTomcatWebServer 메서드를 끝까지 따라가보면 톰캣을 실행하는 로직이 구현되어있다.

     

     

    그리고 디버깅모드로 this.tomcat.start() 를 실행했을때 아래 로그가 찍히면서 톰캣이 실행되는것을 확인할 수 있다.

     

    4)스프링 외부 라이브러리 클래스 빈 선언

    A.스프링에서의 외부 라이브러리 클래스 빈 선언

    다음과 같이 dataSoruce, jdbcTemplate, sqlSessionFactory 를 IOC 컨테이너에 생성해서 

    사용하려면 스프링 빈으로 선언해줘야한다.

    <bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource">
    	<constructor-arg ref="dataSourceSpied" />
    	<property name="logFormatter">
    		<bean class="net.sf.log4jdbc.tools.Log4JdbcCustomFormatter">
    			<property name="loggingType" value="MULTI_LINE" />
    			<property name="sqlPrefix" value="SQL : " />
    		</bean>
    	</property>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    	<property name="dataSource" ref="dataSource" />
    	<property name="configLocation" value="classpath:/mybatis-config.xml" />
            <property name="mapperLocations" value="classpath:/mappers/**/*Mapper.xml" />
    </bean>

     

    B.스프링부트에서의 외부 라이브러리 클래스 빈 선언

    스프링부트에서는 외부 라이브러리의 클래스를 사용하기위해 빈 선언을 따로 하지않는다. 

    왜냐 자동 구성(auto-configuration)이라는게 도입됐기 때문이다.

     

    다음과 같이 JdbcTemplate, TransactionManager, DataSource 를 주입한 후 객체가 생성됐는지 확인하는 테스트 코드를 작성했다.

    근데 로그를 보면 객체가 생성된걸 볼 수 있다. 분명히 JdbcTemplate, TransactionManager, DataSource 빈들을 특정파일에 선언하지 않았는데 어떻게 주입이 되고 객체가 생성된걸까? 이는 앞서 말한 자동 구성 덕분이다. (IOC 컨테이너에 존재하지 않는 빈들은 자동 주입이 되지않음)

     

    자동 구성 동작원리

    아래 의존성을 다운받으면 org.springframework.boot:spring-boot-autoconfigure:2.7.18 라이브러리가 다운로드된다. 

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

     

    그리고 해당 라이브러리에 수많은 클래스 패키지들이 존재하는걸 확인할 수 있다.

     

    많은 패키지 클래스들중 /jdbc/jdbcTemplateAutoConfiguration 를 살펴보겠다.

    그리고 여기서 중요한 2개의 어노테이션을 알아보겠다.

    @AutoConfiguration : 자동 구성(Auto Configuration) 클래스임을 Spring Boot에게 명확하게 알리는 어노테이션

    @import : {} 안에 기재된 클래스 설정들도 같이 사용하겠다. 쉽게 말하면 기재된 클래스들도 자동 구성 클래스로 간주하겠다.

     

    import 에 기재되어있던 JdbcTemplateConfiguration 클래스를 살펴보니 configuration + bean 조합으로 빈을 선언해둔걸 확인할 수 있다.

     

    그리고 이러한 자동 구성 클래스로 선언된 클래스 내부에 선언된 빈들은 스프링부트 구동시 모두 자동으로 ioc 컨테이너에 등록되게된다. 이를 통해 우리는 jdbcTemplate 를 직접 빈 선언하지 않고도 해당 클래스를 주입해서 사용할 수 있었던것이다.

     

    이때 의문이 하나 든다. 아니 스프링부트는 main 메서드가 존재하는 클래스가 포함된 패키지 내에 선언된 빈들만 오토 스캔으로 ioc 컨테이너에 생성하는데 어떻게 라이브러리에 있는 빈들도 ioc 컨테이너에 생성된걸까?

    그 역할은 바로 @EnableAutoConfiguration 어노테이션에서 수행을 해준다. 해당 어노테이션은 외부 라이브러리의 자동 구성 클래스를 탐지하고 등록해주는 역할을 수행해준다.

     

     

    그럼 EnableAutoConfiguratoin 은 어떻게 외부 라이브러리의 자동 구성 클래스를 탐지할까?

     

    org.springframework.boot:spring-boot-autoconfigure:2.7.18 라이브러리 구조를

    살펴보면 META-INF/spring/org.springframework.boot.autoconfigure

    .AutoConfiguration.imports 라는파일이 존재하는것을 확인할 수 있다.

     

    EnableAutoConfiguration 어노테이션은 파일에 기재된 모든 설정파일들을 참고하여 해당 클래스들에 선언된 빈들을 ioc 컨테이너에 생성해주는것이다

    아까 ioc 컨테이너에 생성된 jdbcTemplate 설정 파일도 존재하는것을 확인할 있다.

     

    5)IOC 컨테이너 관리

    A.스프링에서의 IOC 컨테이너 관리

    스프링은 보통 root-context.xml, servlet-context.xml 총 2개의 IOC 컨테이너를 계층적으로관리한다. 

    B.스프링부트에서의 IOC 컨테이너 관리

    스프링부트의 @SpringBootApplication은 @Configuration, @ComponentScan,

    @EnableAutoConfiguration을 포함하고 있어 스프링 애플리케이션에서 필요한 대부분의 설정과 빈 등록을 자동으로 처리합니다. 이 덕분에 스프링부트는 별도의 컨텍스트 분리 없이 하나의 통합된 IoC 컨테이너만을 관리합니다.

    이 부분은 확신이 안서서 영한님께 여줘봤는데 맞다고 알려주셨다! 외쳐 갓영한

     

     

    6)라이브러리 버전 관리

    A.스프링에서의 라이브러리 버전 관리

    다음과 같이 개발자가 각 라이브러리의 버전을 직접 명시해야 하며, 다양한 라이브러리를 함께 사용할 경우 버전 충돌이나 호환성 문제도 자주 발생했습니다. 이러한 문제를 해결하기 위해 개발자는 많은 시간을 라이브러리 버전 관리에 할애해야 했습니다.

     <spring.maven.artifact.version>4.3.16.RELEASE</spring.maven.artifact.version>
     <spring.maven.artifact.security.version>4.2.5.RELEASE</spring.maven.artifact.security.version>
     <spring.maven.artifact.webflow.version>2.4.7.RELEASE</spring.maven.artifact.webflow.version>
     <spring.validation.version>0.9</spring.validation.version>
     <spring.maven.artifact.version>4.3.16.RELEASE</spring.maven.artifact.version>

     

    B.스프링부트에서의 라이브러리 버전 관리

    스프링부트에서는 io.spring.dependency-management 이라는 플러그인 존재한다.

     

     io.spring.dependency-management 플러그인이란?

    Gradle에서 Spring Boot BOM(Bill of Materials)을 사용할 수 있도록 도와주는 플러그인입니다.

    이 플러그인을 사용하면 Spring Boot가 정의한 버전 범위를 자동으로 적용할 수 있습니다. 그리고 이것을 bulild.gradle > plugins 에 추가하면 dependencies에 기재한 라이브러리들의 버전을 spring boot 버전과 호환되는 버전들을 찾아서 알아서 다운로드 해줍니다. 즉 dependencies 에 라이브러리 버전을 직접 기재하지 않아도 됩니다.

    plugins {
    	id 'java'
    	id 'org.springframework.boot' version '2.7.18'
    	id 'io.spring.dependency-management' version '1.1.7'
    }
    group = 'com.ohmyfun'
    version = '0.0.1'
    java {
    	toolchain {
    		languageVersion = JavaLanguageVersion.of(21)
    	}
    }
    repositories {
    	mavenCentral()
    }
    dependencies {
    	implementation 'org.springframework.boot:spring-boot-starter-web'
    	testImplementation 'org.springframework.boot:spring-boot-starter-test'
    	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
    	//security
    	implementation 'org.springframework.boot:spring-boot-starter-security'
    	testImplementation 'org.springframework.security:spring-security-test'
    	//lombok
    	compileOnly 'org.projectlombok:lombok'
    	annotationProcessor 'org.projectlombok:lombok'
    	//jpa
    	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    	//mariadb driver
    	implementation 'org.mariadb.jdbc:mariadb-java-client'
    	//oauth2
    	implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' 
            //jwt
    	implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
    	implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
    	implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5'
    }

    단! JWT 토큰 관련 라이브러리같은 경우 Spring Boot BOM(Bill of Materials)에 포함되지 않는 라이브러리들이라 버전을 직접 기재해줘야한다.

     

    7)스프링프레임워크 구동을 위한 필수 라이브러리들

    A.스프링에서 애플리케이션을 구동하기 위해 선언해야하는 라이브러리들

    스프링 프로젝트를 구동하려면 수많은 라이브러리들이 pom.xml 에 기재되어있어야한다.

    <!-- Spring MVC -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- Servlet API (Tomcat이 제공하므로 provided) -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <!-- JSP / JSTL 지원 -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>${jstl.version}</version>
    </dependency>

     

    B.스프링부트에서 애플리케이션을 구동하기 위해 선언해야하는 라이브러리들

    spring-boot-starter-web 이라는 라이브러리1개만 dependencies 에 기재해두면 해당 라이브러리에 스프링부트 프로젝트를 기동하기 위한 다양한 라이브러리들이 포함되어있어 스프링부트 프로젝트를 재빨리 개발할 수 있게된다.

    dependencies {
    	implementation 'org.springframework.boot:spring-boot-starter-web'
    	testImplementation 'org.springframework.boot:spring-boot-starter-test'
    }

     

    3.스프링부트 실행순서

    1) SpringApplication.run() 호출

       - 스프링 부트의 실행 시작점

     

    2) SpringApplication 인스턴스가 ApplicationContext 생성

       - 일반적으로 AnnotationConfigServletWebServerApplicationContext 생성됨

     

    3) ApplicationContext 초기화

       - ComponentScan 수행 (프로젝트 내부 빈 등록)

       - AutoConfiguration 처리 (외부 라이브러리 빈 등록)

     

    4) WebServer(내장 톰캣) 생성

       - TomcatServletWebServerFactory → Tomcat 객체 생성

     

    5) DispatcherServlet 생성 및 등록

       - DispatcherServlet은 스프링 MVC의 핵심 프론트 컨트롤러

       - DispatcherServlet, ApplicationContext를 연결

     

    6) DispatcherServletRegistrationBean 에 의해 URL 매핑 처리

       - DispatcherServlet을 서블릿 컨테이너에 등록

       - DispatcherServlet url 매핑 일반적으로 "/" 로 등록되어 모든 요청을 처리

     

    7) WebServer (Tomcat) start()

       - 내장 톰캣이 실행되어 HTTP 요청 대기 상태로 진입

     

    스프링부트 실행 순서 그림

     

    4.스프링부트에 추가된 핵심기능

    1.엑츄에이터

    애플리케이션의 내부 상태를 모니터링할 수 있도록 도와주는 라이브러리입니다. Spring Boot 애플리케이션에 대한 다양한 메트릭스헬스 체크애플리케이션 정보를 노출하며, 이를 외부 시스템이 수집할 수 있도록 여러 엔드포인트 형태로 제공

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

     

    2.엔드포인트

    애플리케이션의 특정 기능이나 리소스에 접근할 수 있는 HTTP URL 경로를 의미합니다. Spring Actuator는 이러한 엔드포인트를 통해 애플리케이션 상태 정보를 REST API 형태로 제공하여, 외부 시스템이 이 데이터를 접근하고 사용할 수 있게 합니다.

    1)/actuator/health: 애플리케이션의 상태 정보(UP, DOWN)을 반환

     

    2)/actuator/metrics: JVM프로세스 CPU 사용량, HTTP 요청 횟수등의 다양한 메트릭을 제공

     

    3.메트릭

    시스템의 성능, 상태, 그리고 동작을 수치적으로 표현한 데이터입니다. 

    Spring Actuator, Prometheus, Grafana와 함께 사용될 때, 메트릭은 애플리케이션의 상태를 모니터링하고 성능을 분석하는 데 매우 중요한 역할을 합니다. 즉 메트릭도 액츄에이터의 구성 요소 중 하나로, 가장 자주 사용되는 정보입니다.

    1)/actuator/metrics/jvm.memory.used: jvm 메모리 사용량 조회

     

    139035312 bytes ÷ (1024 × 1024) = 약 132.55 MB 사용중

     

    4.프로메테우스

    메트릭 같은경우 조회시 그 순간의 시스템 성능,상태 데이터만 확인할 수 있다. 따라서 과거의 메트릭정보도 조회하기 위해선 과거의 메트릭정보를 저장하고 메트릭db 역할을 수행하는 프로메테우스가 필요하다. 프로메테우스는 메트릭을 수집, 저장하는 서버이기 때문에 설치후 계속 운용해놓아야한다. 기본포트는 9090

     

    5.그라파나

    그라파나는 프로메테우스와 연동하여 수집된 메트릭 데이터를 시각화하여 대시보드로 확인할 수 있는 도구입니다. 그라파나 또한 서버이기 때문에 설치후 계속 운용해놓아야한다. 기본포트는 3000

    위 사진처럼 프로메테우스에서 수집한 메트릭 정보(CPU 사용량) 을 그라파나 대시보드로 확인할 수 있다.

     

    공부자료

    https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC%EC%9B%90%EB%A6%AC-%ED%99%9C%EC%9A%A9

    'java spring boot' 카테고리의 다른 글

    boot 구조 및 메인화면 실행  (0) 2022.09.21
    spring start project  (1) 2022.09.21
    스프링부트  (0) 2019.12.24
Designed by Tistory.