본문 바로가기

Spring

Spring Framework 와 Spring Boot (2)

안녕하세요! 지난 포스팅에 Spring Framework 와 Spring Boot 에 대한 내용을 포스팅하다 글이 길어져서 Spring Boot 에 대한 내용은 이번 포스팅에서 진행하도록 하겠습니다. 지난 포스팅과 이어지기 때문에 앞선 포스팅도 읽어주시면 감사하겠습니다!

 

https://wanglan.tistory.com/entry/Spring-Framework-%EC%99%80-Spring-Boot

 

Spring Framework 와 Spring Boot (1)

이번 포스팅에서는 Spring Framework 와 Spring Boot 에 대한 내용을 포스팅 해보려고 합니다. Spring Framework 의 등장 배경과 진화 과정, 장단점, 철학, 비판 등 Spring Boot 에 도달하기 까지의 과정을 알아보

wanglan.tistory.com

 

 


1. Spring Boot 란?

기존의 Spring Framework 도 기업용 Java 애플리케이션 개발을 위한 EJB 의 단점을 극복하고 새로운 시작인 '봄'을 의미하며 발전해온 프레임워크인데 마냥 '봄'같이 따스하지만은 않았습니다.

 

Spring Framework 의 한계

Spring  Framework 는 유연성과 확장성면에서 강력했지만, 다음과 같은 단점이 있었습니다.

1. 설정지옥
2. 의존성 충돌
3. 톰캣(Tomcat) 같은 웹 애플리케이션 서버(WAS)를 외부에서 직접 설치 및 설정해야 함
4. 프로젝트 시작이 어려움

 

위 네가지에 대한 이야기를 해보겠습니다.

 

초기 Spring Framework 는 XML 이나 Java 기반 설정을 너무 많이 요구했다고 합니다. 프로젝트를 시작도 하기전 XML 설정 파일을 수십~수백줄을 작성하고 개발을 시작해야한다면, 숙제를 해내기 위한 숙제를 받아하는 느낌이라는 생각도 듭니다. 아래의 코드를 정말 간단하게 보고 넘어가주시길 바랍니다.

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans     
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 컴포넌트 스캔 설정 -->
    <context:component-scan base-package="com.example.service"/>

    <!-- DataSource 설정 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test"/>
        <property name="username" value="root"/>
        <property name="password" value="1234"/>
    </bean>

    <!-- JPA EntityManager 설정 -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="packagesToScan" value="com.example.domain"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        </property>
    </bean>

    <!-- 트랜잭션 매니저 설정 -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

    <!-- 트랜잭션 어노테이션 활성화 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

 

이 코드는  앞선 포스팅에서 언급했던 IoC 컨테이너인 applicationContext 에 대한 설정을 하는 xml 파일이었습니다. 단순히 DB 를 연결하고, JPA 를 사용하는 설정인데도 최소 50~100줄을 넘어버립니다. 요즘이야 영특한 AI 모델을 사용하면 이런 번거로움이 약간 덜어질지는 모르겠지만, 과거에는 이런코드를 직접 작성하며 개발을 위한 준비를 했다고 생각하니 막막하기만 합니다.

 

그래도 Spring 4 이후부터는 Java 로 설정하는게 가능하게 되었습니다. 그래도 설정량은 여전히 많았습니다. 아래코드도 살짝만 읽고 넘어가셔도 됩니다.

@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = "com.example")
public class AppConfig {

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/test");
        ds.setUsername("root");
        ds.setPassword("1234");
        return ds;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setDataSource(dataSource());
        emf.setPackagesToScan("com.example.domain");
        emf.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        return emf;
    }

    @Bean
    public JpaTransactionManager transactionManager() {
        return new JpaTransactionManager(entityManagerFactory().getObject());
    }
}

 

XML 보다는 낫지만 여전히 DataSource, JPA, 트랜잭션 매니저 등 모든 걸 직접 작성해야할 때 였습니다. 이런 설정 지옥이라는 말이 괜히 나온 것이 아니라는 생각이 듭니다.

 

또한 두번째 포인트였던 의존성 충돌은, 라이브러리 버전 호환 문제를 개발자가 직접 해결해야 했던 단점이 있었고, 톰캣같은 웹 애플리케이션 서버도 직접 설치 및 설정하는 것도 번거로웠습니다. 이런 단점들이 모여 초기 작업이 개발자의 생산성을 저하시켰다고 합니다.

 

2. Spring Boot 의 등장 🚀

"Spring 을 더 쉽게, 빠르게, 편하게 쓰게 하자"
라는 모토로 2014년, Pivotal 에서 Spring Boot 를 발표하게 됩니다.

 

Spring Boot 는 기존 Spring Framework 의 기능은 그대로 유지하면서도, 설정을 자동화하고 기본값을 제공하여 생산성을 높인 프레임워크입니다.

 

Spring Boot 의 핵심 특징

기능 설명
Auto Configuration(자동 설정) 의존성에 따라 스프링 설정을 자동으로 구성
Starter Dependencies `spring-boot-starter-web` , `starter-data-jpa` 등 필요한 기능을 묶어서 제공
내장 웹 서버 톰캣, Jetty, Undertow 등 내장되어 외부 WAS 설치 필요 X
application.properties 설정 YAML 또는 properties 파일 한 곳에서 전체 설정 관리
쉬운 테스트 환경 테스트용 내장 DB, 프로파일 설정 등 쉽게 구성 가능
main() 메서드 실행 SpringApplication.run() 하나로 서버 실행 가능(jar 배포)

 

위의 특징 중 눈에 띄는 것은 Auto ConfigurationStarter Dependencies, application.properties 설정 이 세가지인 것 같습니다.

 

Auto Configuration (자동 설정) 이란?

Spring Boot가 classpath(클래스 경로)에 있는 의존성들을 자동으로 감지하고,
그에 맞는 Spring Bean 설정을 자동으로 구성해주는 기능입니다.

 

이것을 쉽게 말하면

"너가 어떤 라이브러리를 프로젝트에 넣었는지 보고,
내가 필요한 설정을 대신 만들어줄게!"

 

라고 말하는 개념입니다.

 

1. Spring Boot 에서는 build.gradle 에 등록한 의존성들이 전부 클래스패스에 자동으로 포함됩니다. 그리고 나서 내부적으로 `classpath:` 를 사용해서 자원을 찾습니다. 이렇게 H2, Web, JPA 등의 클래스패스에 존재하는 라이브러리를 확인하고 나서,
2. 특정 클래스의 설정이 존재하지 않으면 그 클래스를 자동 설정하고,

3. 개발자가 직접 설정한 Bean 이 있으면 자동 설정은 무시됩니다. 오버라이드가 가능하다는 얘깁니다.

 

대표적인 자동 설정 예시로 Spring WEB 에 관련된 설정을 들어보도록 하겠습니다. 코드는 아래와 같습니다.

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

 

dependencies 에 위의 한줄만 추가하면 Spring Boot 는 자동으로 다음을 설정합니다.

 

1. DispatcherServlet : 스프링 MVC 핵심 서블릿

2. RequestMappingHandlerMapping : URL 라우팅 설정

3. Embedded Tomcat : 내장 서버 구동

4. Jackson : JSON 변환기 기본 등록

 

각각의 의존성에 대한 내용을 자동으로 설정해주고, 만약 개발자가 오버라이딩 한 부분이 있다면 그 설정을 반영해주는 아주 똑똑한 기능이라고 할 수 있겠습니다.

또한 starter dependencies 는 위와 같은 다양한 라이브러리들의 의존성을 모아놓은 '모음집' 이라고 볼 수 있습니다.

 

// spring-boot-starter-web의 내부 의존성들
spring-boot-starter
spring-web
spring-webmvc
spring-boot-starter-json
spring-boot-starter-tomcat

 

실제로 starter 내부에는 위와 같은 다양한 의존성이 이미 포함되어 있는 것입니다.

 

여기까지의 내용으로 상상해보면, Spring Framework 가 요리를 위한 식재료가 다양하게 모여있는 슈퍼마켓이었는데 마트까지 가기위해 씻고, 운전하고, 가져오고 하는것이 힘들어서, Spring boot 라는 ssg 배송이 생긴 것 같은 느낌이네요. 그중에서 starter 는 각 식재료를 잘 다듬어서 한 곳에 모아둔 밀키트 같다고 생각이 듭니다.

 

근데 이 Starter 는 이런 단순히 모음집의 기능 뿐만 아니라, 버전 충돌 없이 Spring Boot BOM 이 호환성을 자동으로 정리해주고, 설정도 최소화 하며, 빠른 개발 시작도 가능한데 테스트 스타터까지 이용하면 Mock, Test 용 DB 도 자동 구성해서 할 수 있어 참 좋은 것 같습니다.

 

그리고 아까 상단에서 작성해 놓은 XML 파일 대신 모든 설정을 properties 나 YAML 파일 단 하나에 간단히 정리하여 설정할 수 있다는 점에서 Spring Boot 의 장점이 돋보이는 것 같습니다. 다음으론 이런 Spring Boot 프로젝트의 기본구조를 예시로 살펴보겠습니다.

 

예시: Spring Boot 프로젝트 기본 구조

src/
 └── main/
      ├── java/
      │    └── com.example.demo/
      │         ├── DemoApplication.java  ← main 진입점
      │         └── controller/
      │              └── HelloController.java
      └── resources/
           ├── application.properties     ← 설정 파일
           └── static/, templates/        ← 정적 파일 및 템플릿

 

기본적으로 `@SpringBootApplication` 어노테이션을 붙인 클래스 하나로 애플리케이션이 시작하게 됩니다.

 

이 어플리케이션은 내부적으로 다음 세가지 기능을 포함합니다.

  • @Configuration
  • @EnableAutoConfiguration
  • @ComponentSacn

`@Configuraion` 은 Java 클래스를 설정 파일로 인식하게 해줍니다.

@Configuration
public class AppConfig {
    @Bean
    public MyService myService() {
        return new MyService();
    }
}

 

위 코드에서 AppConfig 가 설정 클래스임을 Spring 한테 알려주고, Bean 으로 등록 가능하게 해줍니다.

 

 

`@ComponentScan` 은 지정한 패키지부터 하위 패키지를 스캔하여 Bean 으로 등록 합니다.

@ComponentScan(basePackages = "com.example")

 

자동으로 @Component, @Service, @Repository, @Controller 와 같은 어노테이션이 붙은 클래스를 찾고, Spring 컨테이너에 Bean 등록을 자동으로 해주게 됩니다. 이것은 @SpringBootApplication 이 선언된 패키지를 기준으로 하위만 스캔됩니다.

 

 

`@EnableAutoConfiguration` 은 의존성과 환경을 보고 필요한 Bean 을 자동으로 구성합니다.

@ConditionalOnClass, @ConditionalOnMissingBean 등에 따라 자동 등록 여부를 결정합니다. 예시로는 아까 언급한 `spring-boot-starter-web` 을 사용하면 DispatcherServlet, 톰캣 을 자동으로 설정하는 것입니다.

 

실제 실행 흐름 정리!

 

  1. main() 실행 → SpringApplication.run(...) 호출
  2. @SpringBootApplication → 세 가지 어노테이션 활성화
  3. @ComponentScan → 패키지 내 Bean 탐색 및 등록
  4. @EnableAutoConfiguration → 라이브러리 보고 필요한 Bean 자동 설정
  5. @Configuration → 수동 설정이 있을 경우 함께 등록
  6. 설정 완료 후 Spring Context(ApplicationContext) 초기화 → 서버 구동

 

3. Spring Boot 의 장단점

지금까지의 내용을 요약해보자면 Spring Boot 의 장점으로는

  • 빠른 개발 시작 : Spring Initializr로 즉시 프로젝트 시작 가능
  • 설정 최소화 : 필요한 설정만 추가하면 나머지는 자동 설정
  • 통합 개발 환경 : Spring Security, JPA, Redis 등 통합이 쉬움
  • 테스트 용이 : 테스트 프로파일 분리, 내장 DB 사용 가능

정도가 있습니다. 물론 MSA 구현에 유리하다는 것과 팀 단위 개발에도 효율적이라는 부가적인 장점도 있습니다.

 

하지만, 단점 또한 없진 않은 것 같습니다.

 

  • 자동 설정의 블랙박스화 : 내부 설정이 자동이기 때문에, 정확히 어떻게 동작하는지 이해가 어려움
  • 커스터마이징의 한계 : 특수한 설정이 필요한 경우 오히려 불편할 수 있음
  • 애플리케이션이 무거워질 수 있음 : 내장 서버, 여러 의존성이 포함되어 jar 크기가 커질 수 있음

위와 같은 단점 중, 제가 느꼈던 부분은 자동 설정의 블랙박스화 였던 것 같습니다.

 

처음 개발을 시작하면서 설명을 간단하게 들으면서 dependencies 에 한줄 씩 추가하고, "아 이렇게 한줄 추가하고 사용하는 거구나" 라고 단순히 알고 넘어갔었습니다. EJB 나 Spring Framework 과거버전에서 개발을 진행해보았더라면 Spring Boot 의 이점을 잘 이해하고, 내부 자동 설정을 전부 뜯어보지 않더라도 어느정도 흐름을 이해할 수 있었을 것 같습니다. (그러지 못했다는 아쉬움이 있습니다)

 

하지만 Spring Boot 를 처음으로 개발을 익히고 학습하는 주니어 개발자들은 이런 내용을 이론적으로 배우는 것 보다 실무적인 적용, 라이브러리 활용, 빠른 개발 등의 테크닉을 위주로 배우는 것 같습니다. 얼른 개발자가 되어 취업을 하고, 한명의 개발자로서 1인분을 하기 위해선 우선 실제 코드를 작성할 줄 알아야 하니까요.

 

하지만 시간을 들여 아주 기본적인 Spring Framework 와 Spring Boot 에 대한 내용을 알아두는 것도 좋을 것 같습니다. 현재는 Spring Boot 를 대부분의 Spring 기반 프로젝트에서 표준으로 사용하고 있지만, 설정 지옥에 빠지더라도 정말 복잡한 설정이 필요한 엔터프라이즈 시스템을 만들기 위해서 Spring Framework 를 채택하여 실무에서 개발을 하게 될 수도 있으니까요!

 

 

마무리로 요약하자면...

  • Spring Boot는 Spring Framework의 철학을 기반으로 하되, 현실적이고 실용적인 방식으로 개선된 프레임워크
  • 개발자가 비즈니스 로직에 집중할 수 있도록 많은 설정을 대신 처리
  • 빠른 개발, 쉬운 배포, 클라우드 환경에서의 확장성까지 고려한 "현대적인 Spring의 진화"

입니다. 긴 글 읽어주셔서 감사합니다.

 

 

728x90
반응형

'Spring' 카테고리의 다른 글

Java Spring 에서의 Bean 이란?  (4) 2025.04.12
Spring - JPA  (0) 2025.04.05
Spring Framework 와 Spring Boot (1)  (0) 2025.03.30
Spring - Redis의 Pub/Sub 및 WebSocket 구현하기  (4) 2024.12.17
Spring - DB 조회의 최적화  (2) 2024.11.27