본문 바로가기
Developer/Spring & Backend

Legacy System 및 Spring Boot Migration 및 Cloud 전환 전략

by 르무엘 2026. 1. 28.

1. Spring Boot로 전체 시스템 이행을 위한 전략적 접근

2. Servlets 기반 구조를 Spring Boot 구조로 전환하는 방법

3. Spring 4에서 Spring Boot 최신 버전으로 전환 시 고려사항

4. MyBatis 3의 호환성 및 Spring Boot 연동 방안

5. Tomcat 9을 내장 톰캣으로 전환하는 절차와 설정

6. 성능 개선 측면에서 Spring Boot의 장점과 이행 시 유의점

7. 클라우드 이행 관점에서 추천되는 아키텍처

8. 단계별 마이그레이션 로드맵 제안

 

1. Spring Boot로 전체 시스템 이행을 위한 전략적 접근

레거시 시스템을 Spring Boot로 마이그레이션할 때는 단계적이고 신중한 전략이 필요합니다. 먼저 현재 시스템의 아키텍처와 구성요소를 면밀히 분석하세요. 사용 중인 Java 버전(현재 Java 8)과 프레임워크(Spring 4 등)가 **목표 환경(Spring Boot 최신 버전 및 클라우드)**에서 호환되는지 확인해야 합니다. 예를 들어 Spring Boot 3은 Java 17 이상과 Jakarta EE 9 이상의 스택을 요구하므로, Java 업그레이드라이브러리 호환성 점검이 선행되어야 합니다. 기존 코드에서 javax 패키지를 사용하는 부분은 Jakarta 패키지로 변경하는 등의 조치가 필요합니다.

이행 전략으로는 한 번에 전체를 교체하는 빅뱅 방식보다는, 기존 비즈니스 로직을 유지하면서 점진적으로 Spring Boot로 전환하는 리팩토링 우선 전략이 권장됩니다. 예컨대, 현재 애플리케이션을 모듈별로 나누어 하나씩 Spring Boot로 전환하며 레거시와 신규 코드를 공존시키는 방식입니다. 이러한 접근은 대규모 재작성보다 리스크가 적고, 필요시 Strangler Fig 패턴 등을 활용해 구 시스템의 일부 기능을 새 시스템으로 조금씩 대체해나갈 수 있습니다.

또한 초기 단계에서 핵심 모듈에 대한 PoC(Proof of Concept)을 통해 Spring Boot 전환의 문제점을 미리 파악하고 해결하는 것이 좋습니다. 전체 전환 계획을 수립할 때는 데이터베이스, 연동 시스템, 배포 파이프라인 등 모든 계층에 걸친 영향도를 고려하세요. 마지막으로 전환 과정 전반에 걸쳐 광범위한 테스트 계획(회귀 테스트, 부하 테스트 등)을 마련하여 기능 및 성능 회귀가 없도록 검증해야 합니다.

2. Servlets 기반 구조를 Spring Boot 구조로 전환하는 방법

Servlet API를 직접 사용하는 기존 웹 구조는 Spring MVC 패턴으로 재구성하여 Spring Boot에 적합하게 전환해야 합니다. 구체적으로, 개별 HttpServlet 클래스는 Spring MVC의 컨트롤러(controller) 클래스로 변환됩니다. 각 서블릿의 doGet, doPost 로직은 해당 메서드에 대응되는 @Controller 또는 @RestController 클래스의 메서드로 옮기고, URL 매핑은 @RequestMapping/@GetMapping 등의 애노테이션으로 지정합니다. 예를 들어 Servlet의 doGet(HttpServletRequest req, HttpServletResponse res) 메서드는 Spring MVC에서 @GetMapping이 붙은 메서드로 변경하고, req.getParameter("param") 호출 부분은 @RequestParam 매개변수로 대체하는 식입니다. 이렇게 하면 HttpServletRequest/Response에 직접 의존하던 코드를 제거하고 Spring이 요청 파라미터 바인딩과 응답 처리를 자동으로 해줄 수 있습니다. 또한 응답은 PrintWriter로 쓰는 대신 메서드 리턴값(예: 문자열 뷰 이름이나 JSON 객체)을 통해 처리하고, 필요한 경우 @ResponseBody나 ResponseEntity를 사용하여 REST 응답을 생성합니다.

Spring Boot에서는 기본적으로 DispatcherServlet 등 웹 관련 설정을 자동으로 구성하므로, 수동으로 서블릿을 등록하거나 web.xml에 디스패처를 정의할 필요가 없습니다. 특히, Spring Boot의 spring-boot-starter-web를 추가하면 내장 톰캣과 함께 Spring MVC 디스패처 서블릿이 자동 설정되어 웹 요청을 처리하게 됩니다. 따라서 기존 web.xml에 정의된 서블릿 매핑이나 리스너 설정들은 대부분 불필요해지며, 필요한 경우 Java Config나 Spring Boot 설정으로 전환하면 됩니다.

View 처리 측면에서는, 만약 기존에 JSP를 사용했다면 Spring Boot에서 그대로 JSP를 사용할 수도 있지만 추가 설정이 필요합니다. 권장되는 방법은 Thymeleaf 등의 템플릿 엔진을 사용하는 것이지만, JSP를 지속 사용하는 경우 뷰 리졸버(ViewResolver) 설정을 application.properties에 지정해야 합니다. 예를 들어 JSP 파일이 /WEB-INF/views/ 아래 위치한다면, 아래와 같이 설정합니다:

 
spring.mvc.view.prefix=/WEB-INF/views/ spring.mvc.view.suffix=.jsp

위와 같은 설정으로 Boot 환경에서 JSP를 문제없이 로드할 수 있습니다. 정적 리소스(css, js 등)는 /static 또는 /public 경로에 두면 별도 설정 없이 제공되며, 기존 mvc:resources 설정은 이러한 디렉토리 구조로 대체됩니다.

 

또한 Spring Boot로 전환하면서 **필터(Filter)**나 인터셉터와 같은 웹 요소도 재구성해야 합니다. 기존 javax.servlet.Filter 구현체는 @Component를 붙여주거나 FilterRegistrationBean으로 등록하면 되고, Spring MVC 인터셉터는 WebMvcConfigurer를 구현하여 addInterceptors() 메서드로 등록할 수 있습니다. 이러한 작업을 통해 Servlets 기반 코드를 Spring Boot 구조로 자연스럽게 녹여낼 수 있습니다.

 

3. Spring 4에서 Spring Boot 최신 버전으로 전환 시 고려사항

Spring Boot는 Spring Framework를 기반으로 개발을 단순화한 프레임워크이므로, Spring 4에서 전환할 때 설정 방식과 라이브러리 관리의 차이를 유의해야 합니다. 주요 고려사항은 다음과 같습니다:

  • 스타터 의존성 및 Maven 설정: Spring Boot에서는 다수의 의존성을 하나로 묶은 Starter를 제공하여 의존성 관리를 간소화합니다. 예를 들어, 웹 관련 기능을 위해 과거에는 spring-webmvc, tomcat 라이브러리 등을 각각 추가했다면, Boot에서는 spring-boot-starter-web 하나로 대신합니다. 이 스타터에는 Spring MVC, 내장 톰캣, JSON 처리 등 웹 애플리케이션에 필요한 핵심 라이브러리가 모두 포함됩니다. Boot의 Starter 부모 POM을 사용하면 공통 의존성 버전을 관리해주므로, 기존 pom.xml에서 명시적으로 버전을 지정했던 Spring 및 서드파티 라이브러리 의존성 선언은 제거하거나 Boot에 맞게 조정해야 합니다.
  • 설정 파일과 프로파일: Spring 4에서는 XML 또는 자바 설정 + *.properties 파일 조합으로 환경 설정을 했을 것입니다. Spring Boot에서는 기본적으로 프로젝트 리소스 경로에 application.properties 또는 application.yml 파일을 두고 애플리케이션 설정을 관리합니다. Boot는 이 파일을 자동으로 로드하며, 별도의 PropertyPlaceholderConfigurer 설정 없이 @Value 또는 @ConfigurationProperties 등을 통해 값을 주입할 수 있습니다. 프로파일별 설정은 application-{profile}.properties 형태로 작성하면 Boot가 활성 프로파일에 따라 자동 적용합니다. 따라서 기존 Spring 4의 PropertyPlaceholderConfigurer나 @PropertySource 사용 부분은 Boot 방식으로 단순화됩니다.
  • 자동 구성과 애노테이션 처리: Spring Boot는 자동 설정(Auto-Configuration) 기능을 통해 클래스패스의 라이브러리에 따라 필요한 빈을 자동 등록합니다. 예를 들어 Spring Boot에서 spring-boot-starter-web를 포함하면 DispatcherServlet이나 RequestMappingHandlerMapping 등이 자동으로 설정되고, 별도로 <mvc:annotation-driven>이나 @EnableWebMvc를 선언할 필요가 없습니다. Boot의 메인 클래스에는 일반적으로 @SpringBootApplication 애노테이션을 사용하는데, 이 하나의 애노테이션이 기존 Spring의 @Configuration, @EnableAutoConfiguration, @ComponentScan을 모두 포함합니다. 즉, Boot의 메인 클래스가 있는 패키지 이하를 자동으로 컴포넌트 스캔하여 @Component, @Controller, @Service 등의 빈을 찾고 등록합니다. 별도로 Spring 4에서 사용하던 <context:component-scan>이나 <context:annotation-config> 설정은 더 이상 필요하지 않으며, Boot 메인 클래스 패키지 구조를 잘 정의하는 것만으로 동일한 효과를 얻습니다.
  • XML 설정 이관: 기존 Spring 4 프로젝트에서 사용한 XML 설정이 있다면, 가능하면 자바 코드 기반 설정으로 변환하는 것이 좋습니다. Boot에서는 XML 설정을 지양하지만, 필요한 경우 @ImportResource를 이용해 기존 XML을 불러올 수도 있습니다. 따라서 레거시 프로젝트의 spring-*.xml (예: dispatcher-servlet.xml, applicationContext.xml 등)에 정의된 빈들을 검토하여, Boot 환경에서 제공하는 자동 설정으로 대체할 수 있는지 판단하고, 필요한 빈은 @Bean이나 스타터 의존성으로 대체합니다. 예를 들어 Spring 4 XML에서 설정했던 InternalResourceViewResolver나 CommonsMultipartResolver 같은 빈은 Boot에서는 application.properties 설정으로 대체하거나 자동구성이 제공됩니다.
  • 의존성 버전 및 Jakarta 전환: Spring 4에서 Spring Boot 최신 버전(예: Spring Boot 3.x)으로 올라올 때는 Jakarta EE 네임스페이스로 전환된 사항을 꼭 확인해야 합니다. Spring Boot 3(SF 6)은 서블릿 API 등을 포함한 Java EE 라이브러리가 javax에서 jakarta로 변경되었습니다. 따라서 기존 코드나 라이브러리가 javax.servlet 같은 패키지를 쓰고 있다면, 대응되는 jakarta.servlet API로 변경해야 합니다. 예를 들어 Spring MVC의 DispatcherServlet도 Spring 6에서는 Jakarta Servlet API를 요구하므로, 기존에 javax.servlet로 작성된 필터나 서블릿 관련 코드는 컴파일 에러가 발생할 수 있습니다. 이 부분은 주로 import 문 수정과 라이브러리 업그레이드로 해결하며, Boot로 마이그레이션 시 자동으로 처리되지는 않으므로 개발자가 직접 수정해야 합니다. 다행히 Spring Boot 3 마이그레이션을 도와주는 도구(Eclipse Transformer 등)도 있어 이러한 패키지 변환을 지원하기도 합니다.
  • 기타 변경사항: Spring 4 -> Spring Boot/Spring 6 환경에서 일부 애노테이션이나 설정 방식이 달라진 경우가 있습니다. 예를 들어 Spring 4에서 사용되던 @Autowired(required=false) 등의 옵션 처리, @PostConstruct 동작 등이 Spring 6에서도 지원되지만, Java 9 이상의 모듈 시스템 영향으로 리플렉션 관련 설정에 변화가 있을 수 있습니다. 또한 Spring 5부터 기본적으로 Java 8의 함수형 스트림 API나 Optional 등을 많이 활용하므로, 레거시 코드에서도 Java 8 스타일로 리팩토링하면 Boot 이행 후의 코드를 현대화하는 데 도움이 됩니다.

정리하면, Spring Boot로 전환 시에는 설정 파일의 통합 및 단순화, 의존성 관리 일원화(starter 사용), 자동 설정 활용, 그리고 Jakarta 패키지 대응에 중점을 두어야 합니다. 이러한 사항들을 미리 계획하고 대비하면 Spring 4 기반 코드를 Spring Boot 최신 환경으로 비교적 수월하게 이식할 수 있습니다.

 

4. MyBatis 3의 호환성 및 Spring Boot 연동 방안

현재 사용 중인 MyBatis 3는 Spring Boot 환경에서도 충분히 호환되며, Boot와 쉽게 연동할 수 있습니다. Spring Boot용 MyBatis 스타터 라이브러리를 사용하면 수동 설정을 최소화하면서 MyBatis를 통합할 수 있습니다. 우선 pom.xml에 MyBatis Spring Boot Starter 의존성을 추가합니다. 예를 들어 Maven 기준으로 아래와 같습니다:

 
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.3.1</version> <!-- Boot 3.x에 호환되는 최신 버전 --> </dependency>

위 스타터를 추가하면 MyBatis의 SqlSessionFactorySqlSessionTemplate 등이 Spring Boot에 의해 자동 구성되며, MyBatis와 관련된 여러 빈(bean)들을 수동으로 등록할 필요가 없습니다.

데이터베이스 연결은 Spring Boot의 일반적인 방식대로 application.properties에서 설정하면 됩니다. 예를 들어 HikariCP(DataSource 기본풀) 설정과 DB URL, 계정정보를 지정합니다:

 
spring.datasource.url=jdbc:mysql://<HOST>:<PORT>/<DB명> spring.datasource.username=<계정> spring.datasource.password=<비밀번호> spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

Boot 3.x의 기본 DB 커넥션 풀은 HikariCP이며, 이는 성능과 안정성이 뛰어나므로(MyBatis도 별도 설정 없이 이 풀을 사용) 바로 활용하면 됩니다. 기존에 사용하던 Tomcat JDBC Pool 등에서 전환되는 것이며, HikariCP는 경량이라 레거시 대비 커넥션 풀 성능이 향상될 수 있습니다.

MyBatis 설정의 경우, 매퍼 XML과 매퍼 인터페이스를 Boot에 인식시켜야 합니다. MyBatis Spring Boot Starter는 mybatis.configuration.* 및 mybatis.mapper-locations 등의 프로퍼티로 설정을 제공합니다. 예를 들어 application.properties에 MyBatis 관련 패키지와 매퍼 XML 경로를 지정할 수 있습니다:

 
mybatis.type-aliases-package=com.example.project.domain # VO/DTO 등이 있는 패키지 mybatis.mapper-locations=classpath:mapper/*.xml # 매퍼 XML 파일 위치

위와 같이 설정하면 Boot 실행 시 해당 패키지의 클래스에 대해 별칭을 등록하고, 지정된 경로의 XML들을 모두 읽어 MyBatis 매퍼로 인식합니다. 또한 MyBatis 매퍼 인터페이스에는 @Mapper 애노테이션을 붙여주면(Spring Boot가 해당 애노테이션을 스캔) 구현체 없이도 Mapper 빈이 자동 등록됩니다. 만약 패키지 단위로 일괄 스캔하고자 한다면 Boot 메인 클래스에 @MapperScan("com.example.project.mapper")을 추가하여 매퍼 인터페이스를 찾아 등록할 수도 있습니다.

레거시 Spring 4에서는 SqlSessionFactoryBean, MapperScannerConfigurer 등을 XML이나 자바 설정으로 등록했을 가능성이 있는데, Boot 환경에서는 위 스타터가 이러한 작업을 자동으로 처리합니다. 다만 트랜잭션 관리는 여전히 Spring의 @Transactional을 그대로 사용하면 되고, Boot가 Datasource를 자동으로 감지하여 DataSourceTransactionManager를 빈으로 등록하므로 특별한 설정 없이도 MyBatis에서 Spring 트랜잭션을 사용할 수 있습니다.

호환성 측면에서 MyBatis 3 자체는 최신 Spring/Spring Boot와 호환되므로 큰 문제가 없습니다. MyBatis에서 Java EE에 의존하는 부분이 거의 없기 때문에(JDBC 기반) Jakarta 전환 이슈도 적습니다. 다만 MyBatis 관련 부가 라이브러리나 플러그인 중 Spring 4 전용으로 작성된 것이 있다면(예: MyBatis-Spring의 예전 버전) 최신 버전으로 올려야 합니다. 예를 들어 MyBatis-Spring 라이브러리는 Boot 스타터에 내장된 버전을 따르게 되므로, 호환성을 위해 Boot에 맞는 스타터 버전을 사용하면 됩니다. (Spring Boot 3.x에 대응하는 MyBatis 스타터 3.x 버전이 존재합니다.)

요약하면, MyBatis 연동 방안은:

  • Spring Boot용 MyBatis 스타터 추가 (의존성 관리 용이)
  • DB 연결정보 및 MyBatis 설정을 application.properties에 정의
  • @Mapper 또는 @MapperScan으로 매퍼 인터페이스 등록
  • 필요 시 커스텀 MyBatis 설정은 application.properties의 MyBatis 프로퍼티나 @Configuration 클래스를 통해 적용

이런 방식으로 설정하면 MyBatis를 Spring Boot에서 무리 없이 활용할 수 있습니다. MyBatis를 그대로 쓰면서도, 향후 필요에 따라 Spring Data JPA로 일부 전환하거나 복합적인 데이터 접근을 구현할 여지도 생기므로, MyBatis 모듈을 분리하여 의존성을 관리하면 유지보수에도 도움이 될 것입니다.

 

 

5. Tomcat 9을 내장 톰캣으로 전환하는 절차와 설정

현재 Tomcat 9에 WAR를 배포하는 방식을 **Spring Boot의 내장 톰캣(Embedded Tomcat)**으로 전환하면 배포와 실행 방식이 크게 단순화됩니다. 전환 절차는 다음과 같습니다:

  1. 의존성 변경 및 빌드 설정: Spring Boot로 마이그레이션하면서 Maven/Gradle 빌드 설정을 Boot 스타일로 변경해야 합니다. Maven 기준으로 부모를 spring-boot-starter-parent로 지정하고, spring-boot-starter-web 의존성을 추가했다면 이미 내장 톰캣이 포함된 것입니다. Boot 스타터 웹에 Tomcat이 기본 포함되어 있으며, 별도로 Tomcat 의존성을 명시할 필요가 없습니다. 다만, 기존 Tomcat 서버 라이브러리나 Servlet API 의존성 (예: javax.servlet-api, tomcat-embed-core 등)을 pom에서 제거하거나 provided로 변경해야 합니다. Boot에서 내장 톰캣을 사용할 때는 이러한 라이브러리가 중복되지 않도록 정리합니다.
  2. 실행 가능한 JAR로 패키징: Spring Boot 애플리케이션은 보통 독립 실행 JAR로 패키징합니다. 이를 위해 Maven의 Spring Boot 플러그인을 설정해야 합니다. pom.xml의 <build><plugins> 섹션에 아래와 같이 추가합니다:위 플러그인은 Maven 패키징 단계에서 실행가능한 JAR (또는 WAR)로 재포장(repackage)하는 역할을 합니다. 이 설정을 하면 mvn package 수행 시 Boot 애플리케이션이 내장 톰캣을 포함한 fat jar 형태로 생성됩니다. 이후 이 JAR 파일만으로 어플리케이션을 실행(java -jar)할 수 있게 됩니다.
  3.  
    <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin>
  4. WAR 배포에서 JAR 실행으로 전환: Boot로 전환하면서 반드시 WAR를 써야 하는 게 아니라면, JAR 실행으로 운영하는 것이 일반적입니다. 이를 위해 위와 같이 패키징을 JAR로 설정하고 (pom.xml 기본 packaging이 jar), 메인 클래스에 public static void main 메서드로 SpringApplication.run(...)을 호출하는 진입점을 두면 됩니다. 만약 호환성 등 이슈로 WAR 배포가 필요하다면, Spring Boot도 WAR 형태로 빌드해 외부 Tomcat에 배포할 수 있지만, 권장되는 방식은 내장 톰캣을 활용하는 JAR입니다. 내장 톰캣을 쓰면 특정 앱 서버 환경에 종속되지 않고 컨테이너화(Docker 등)하기도 수월합니다.
  5. 설정 변경: 내장 톰캣으로 전환할 때, 서버 포트나 컨텍스트 경로 등의 설정을 application.properties로 옮길 수 있습니다. 기본적으로 Boot 내장 톰캣은 포트 8080으로 동작하며, 변경하려면 server.port=포트번호를 설정합니다. 컨텍스트 경로도 server.servlet.context-path=/경로 속성으로 지정 가능합니다. 기존 Tomcat의 server.xml에서 설정하던 스레드 풀 크기 등의 튜닝 파라미터도 필요하면 application.properties에서 server.tomcat.max-threads 등의 속성으로 조정할 수 있습니다. 예를 들어 server.tomcat.max-threads=200 등의 설정이 그것입니다.
  6. JNDI 및 기타 Tomcat 전용 설정 이관: 레거시 환경에서 Tomcat에 JNDI 리소스를 정의해 쓰고 있었다면, Boot에서는 이를 직접 DataSource로 명시적으로 설정하거나 Spring Cloud Config/Vault 같은 외부 설정으로 관리해야 합니다. Boot 내장 톰캣도 JNDI를 지원할 순 있으나, 클라우드 환경에서는 애플리케이션 내 설정이나 클라우드 플랫폼의 설정 관리 서비스를 사용하는 편이 더 일반적입니다. 예를 들어 AWS 환경이라면 RDS 연결 정보를 애플리케이션 설정으로 두고, JNDI를 쓰지 않는 식입니다. Boot로 마이그레이션하면서 가능하면 JNDI 의존성을 제거하고 설정을 표준화하는 것을 권장합니다.
  7. 로그 및 기타 설정: Boot는 기본 로깅으로 Logback을 내장하고 있습니다. 만약 Tomcat에서 별도로 설정하던 접근로그(Access Log) 등은 Boot의 Tomcat 설정으로 켤 수 있습니다 (server.tomcat.accesslog.enabled=true 등). 또한 배포 환경별로 다른 설정(예: Prod와 Dev의 설정 차이)은 Boot의 프로파일 기능이나 별도 설정 파일을 통해 관리하면, 하나의 JAR로 다양한 환경에 대응할 수 있습니다.

정리하면, 내장 톰캣으로의 전환은 Spring Boot 프로젝트 구조를 따르고 JAR로 패키징함으로써 이뤄집니다. 이렇게 하면 배포 시에 외부에 Tomcat 9를 설치하고 WAR를 배포하는 절차 없이, 빌드 결과물(JAR)을 원하는 서버나 컨테이너 환경에 복사하여 실행만 하면 되므로 DevOps 면에서 효율성이 높아집니다. 특히 클라우드 (쿠버네티스나 컨테이너 기반) 환경에서는 이 방식이 표준적입니다. Boot 내장 톰캣은 성능이나 기능 면에서도 Tomcat 9와 동일한 엔진으로 동작하므로 별도 이슈는 없지만, 세션 관리나 인코딩 설정 등 Tomcat 전역 설정이 있었다면 application.properties나 코드 상에서 세팅해주는 것을 잊지 않아야 합니다.

 

6. 성능 개선 측면에서 Spring Boot의 장점과 이행 시 유의점

Spring Boot로 마이그레이션하는 주요 목표 중 하나가 성능 개선인 만큼, Boot 기반으로 전환함으로써 얻을 수 있는 이점과 주의할 점을 살펴보겠습니다.

성능 개선 장점:

  • 업그레이드된 스택의 이점: Spring Boot 최신 버전은 기반 Spring Framework와 Java 버전의 향상을 그대로 누릴 수 있습니다. Java 17+의 성능 최적화(향상된 GC, JIT 등)와 Spring 5/6의 개선된 내부 구현으로 인해 전반적인 처리 효율이 좋아집니다. Netflix의 사례를 보면, Spring Boot 3 + Java 17 업그레이드 이후 애플리케이션의 부하 처리 성능이 향상되고 리소스 비용을 크게 절감한 사례가 있습니다. (Netflix는 수천 개의 마이크로서비스를 Boot 3로 올리는 작업을 통해 배치 작업 부트 시간 단축 등으로 수십만 달러의 비용을 절감했다고 보고했습니다.) 이처럼 최신 Spring Boot로의 이행은 빠른 부팅 시간, 낮은 메모리 소비, 높은 처리량 등으로 이어질 수 있습니다.
  • 내장 기술의 성능 최적화: Spring Boot는 기본 설정으로도 상당히 최적화된 구성요소를 사용합니다. 예를 들어, 데이터베이스 커넥션 풀로 Boot 2부터 HikariCP를 기본 사용하고 있는데, HikariCP는 현재 가장 가벼우면서 빠른 커넥션 풀로 평가됩니다. 레거시 시스템이 tomcat-jdbc나 DBCP 등 비교적 무거운 풀을 썼다면, Boot 전환 후 커넥션 풀이 HikariCP로 바뀜에 따라 DB연결 성능과 안정성이 개선될 수 있습니다. 또 다른 예로, Spring Boot의 기본 HTTP 메시지 컨버터나 쓰레드풀 설정 등이 대체로 효율적으로 튜닝되어 있어, 특별히 문제가 없으면 기본값을 활용하는 것만으로도 좋은 성능을 낼 수 있습니다.
  • 경량화 및 모듈화: Boot로 전환하면서 불필요한 라이브러리나 미사용 컴포넌트를 걷어내는 리팩토링을 병행하게 됩니다. 이 과정에서 애플리케이션이 경량화되고 메모리 사용량이나 클래스 로딩 시간 등이 감소하는 효과가 있습니다. 또한 Boot에서는 필요한 모듈만 의존성으로 포함하면 되므로, 과거 레거시 환경에서 관성적으로 포함되던 필요없는 라이브러리를 줄여 클린한 런타임 환경을 만들 수 있습니다.
  • 스케일 아웃 용이: 성능 개선은 단일 인스턴스의 처리량 향상뿐만 아니라 확장성을 통해서도 달성됩니다. Spring Boot 애플리케이션은 완전히 stateless하게 개발하기 용이하고, Docker 등의 이미지로 만들어 수평 확장하기 좋습니다. 클라우드 환경에서 부하에 따라 손쉽게 인스턴스를 증설하고 로드밸런싱 할 수 있으므로, 결과적으로 성능(처리량, 가용성)이 개선됩니다. (Spring Boot 자체가 성능을 마법처럼 높이는 것은 아니지만, 마이크로서비스 아키텍처클라우드 오토스케일링을 도입하기 쉽게 만들어 궁극적으로 더 높은 성능과 신뢰성을 얻을 수 있습니다.)
  • 각종 부가 기능: Spring Boot는 Actuator를 통해 애플리케이션의 상태와 메트릭을 노출할 수 있고, Spring Boot Admin, Micrometer 등을 활용하면 모니터링 및 성능 진단이 쉬워집니다. 이를 통해 병목 지점을 빠르게 찾아 튜닝할 수 있으므로, 지속적인 성능 개선 사이클을 돌리기에도 용이합니다. 또한 캐싱 추상화(@Cacheable)나 비동기 처리(@Async) 지원 등이 내장되어 있어, 애플리케이션 차원의 성능 최적화 기법을 더 손쉽게 적용할 수 있습니다.

이행 시 유의점:

  • 자동 구성의 오버헤드 관리: Spring Boot의 편의성은 자동 구성이지만, 필요 없는 기능까지 로딩되지 않도록 주의해야 합니다. 스타터 의존성을 추가하면 관련 빈들이 모두 올라오는데, 예를 들어 spring-boot-starter-web을 쓰면 서블릿 컨테이너와 웹 관련 여러 빈들이 등록됩니다. 만약 사용하지 않을 기능(예: JSP 템플릿엔진 등)이 있다면 의존성에서 제외(exclude)하거나 설정으로 끄는 것이 좋습니다. 불필요한 빈을 많이 로드하면 메모리 사용량 증가와 부트 시간 증가로 이어져 성능에 악영향을 줄 수 있습니다. 따라서 자동 구성의 포함/제외 설정 (spring.autoconfigure.exclude 등)을 통해 필요한 것만 쓰도록 튜닝합니다.
  • JVM 및 GC 튜닝: Boot로 이전하면서 Java 버전이 올라간다면(8 -> 17) JVM 옵션이나 GC 알고리즘이 바뀔 수 있습니다. 메모리 관리 측면에서 기존에 설정해둔 옵션이 있다면 재검토하고, Java 17의 G1 GC 기본값 등이 애플리케이션에 잘 맞는지 모니터링해야 합니다. 성능 테스트를 통해 Heap 사이즈, GC 튜닝 등을 조정하는 작업도 병행하십시오.
  • 프레임워크 변경에 따른 쿼리 성능: MyBatis 자체는 동일하지만, 혹시 JPA나 기타 프레임워크로 일부 전환한다면 Lazy 로딩이나 연관관계 처리 등에서 쿼리 패턴이 달라져 성능 변화가 있을 수 있습니다. 현재는 MyBatis 유지한다고 하니 큰 문제는 없겠으나, SQL 튜닝 포인트는 기존과 동일하게 관리되어야 합니다. Boot로 바뀌어도 결국 DB I/O가 성능의 큰 부분을 차지할 것이므로, MyBatis 쿼리 성능과 인덱스 최적화 등은 계속 모니터링합니다.
  • 대용량 트래픽 테스트: 새로운 Boot 기반 시스템을 배포하기 전에 반드시 부하 테스트를 실시해봐야 합니다. Spring Boot로 전환하면서 (특히 분산 환경, 마이크로서비스화 시) 발생할 수 있는 네트워크 부하, 서비스 간 호출 지연 등을 점검해야 합니다. 또한 레거시와 성능 비교를 통해 **성능 지표(Throughput, Latency)**가 개선되었는지 수치화할 필요가 있습니다. 만약 Boot 이행 후 초기에는 성능 이슈가 나타난다면, 이는 설정의 디폴트 값 차이나 환경 차이일 수 있으므로 스레드풀 크기, DB커넥션풀 크기, 타임아웃 등 파라미터를 조정해볼 필요가 있습니다.
  • 메모리 Footprint 변화: Boot 애플리케이션은 실행 파일(JAR)에 라이브러리를 다 포함하므로 메모리 사용이 약간 늘 수 있지만, 반대로 불필요한 외부 서버를 안 띄우기에 경량이라고 볼 수도 있습니다. 반드시 Java 힙 및 메모리 설정(Xmx 등)을 재조정하여 새로운 환경에 맞게 최적화를 진행하세요. 특히 컨테이너 환경에서는 컨테이너 메모리 제한에 맞게 설정하는 것이 중요합니다.

요약하면, Spring Boot 도입으로 성능상의 이점(업그레이드된 프레임워크, 기본 튜닝, 수평확장 용이성 등)을 얻을 수 있지만, 최대한 활용하려면 세밀한 튜닝과 테스트가 따라줘야 합니다. 이행 과정에서는 기능 개선뿐 아니라 성능 목표치에 맞추어 프로파일링하고, 병목을 제거하면서 진행하면 최종적으로 레거시 대비 향상된 성능을 달성할 수 있을 것입니다.

 

 

 

 

 

7. 클라우드 이행 관점에서 추천되는 아키텍처

Spring Boot로 전환한 이후 클라우드 환경에 배포할 때는 기존 모놀리틱 구조를 클라우드 네이티브 아키텍처로 최적화하는 것이 중요합니다. 일반적으로 다음과 같은 아키텍처 전략을 권장할 수 있습니다:

 

  • 마이크로서비스 기반 설계: 레거시 시스템이 크고 일체화된 모놀리식이라면, 이를 적절히 도메인별로 분리하여 마이크로서비스로 구성하는 방안을 고려합니다. Spring Boot는 마이크로서비스 아키텍처에 최적화되어 있어, 작은 단위의 서비스 여러 개로 나누더라도 개발과 배포가 수월합니다. 각각의 서비스는 RESTful API를 통해 통신하게 하고, 독립적으로 배포/스케일링 가능하도록 설계합니다. 이렇게 하면 특정 기능에 트래픽이 집중될 때 해당 서비스만 확장하여 자원을 효율적으로 활용할 수 있고, 장애 발생 시 전체 시스템이 아닌 일부 서비스에 국한시켜 탄력성과 안정성이 높아집니다.
  • API 게이트웨이 도입: 다수의 마이크로서비스로 구성될 경우, 외부 클라이언트는 여러 서비스의 엔드포인트를 알 필요 없이 API 게이트웨이를 통해 일원화된 접근을 할 수 있습니다. Spring Cloud Gateway나 Netflix Zuul과 같은 게이트웨이를 사용하면 라우팅, 인증/인가, 모니터링, 서킷브레이커 등의 크로스커팅 Concern을 게이트웨이에서 처리할 수 있습니다. 그림에서도 클라이언트 요청이 Spring Cloud Gateway를 거쳐 내부 서비스로 전달되는 구조를 보여줍니다. 이를 통해 각 서비스는 비즈니스 로직에만 집중하고 공통 기능은 게이트웨이에 위임할 수 있습니다.
  • 구성 관리(Config): 클라우드 환경에서는 환경별 설정 값을 애플리케이션 코드와 분리하고 중앙 관리하는 것이 중요합니다. Spring Cloud Config Server를 도입하면 각 마이크로서비스의 설정을 git이나 저장소에 모아두고 중앙 집중형 구성 관리를 구현할 수 있습니다. 각 서비스는 Config Server로부터 자신의 환경설정을 받아오므로, 환경변수가 변경되어도 서비스 재배포 없이 반영할 수 있습니다. 예를 들어 DB 연결정보나 기능 토글 값 등을 Config 서버에서 관리하면 유용합니다. Boot Actuator와 연계하면 runtime에 /refresh로 설정 리로드도 가능합니다. 클라우드 벤더의 설정 관리 서비스(AWS SSM Parameter Store, Azure App Config 등)를 활용하는 것도 대안입니다만, Spring Cloud Config을 쓰면 애플리케이션 단에서 일관된 방법으로 설정을 다룰 수 있습니다.
  • 서비스 디스커버리(Registry): 서비스가 증가하면 서로의 위치(IP/Port)을 동적으로 알아야 합니다. 서비스 레지스트리를 통해 각 서비스 인스턴스의 위치를 등록/탐색하는 메커니즘을 둡니다. Spring Cloud Netflix의 Eureka Server를 사용하면 손쉽게 서비스 등록/발견 기능을 구현할 수 있습니다. Eureka 서버를 구축하고 각 Boot 서비스에 @EnableEurekaClient를 적용하면, 서비스들은 부팅 시 Eureka에 자신의 주소를 등록하고, 다른 서비스 호출 시 Eureka로부터 대상 서비스의 최신 주소를 조회합니다. 이를 통해 쿠버네티스나 AWS ECS 등 동적으로 IP가 바뀌는 환경에서도 안정적으로 서비스 통신이 가능합니다. (만약 쿠버네티스같이 자체 서비스 디스커버리가 있는 플랫폼이라면 Eureka 없이 K8s 서비스 DNS를 활용할 수도 있습니다. 선택은 인프라에 따라 달라집니다.)
  • Spring Cloud 기타 구성요소: 필요한 경우 서킷 브레이커(Resilience4j 혹은 Spring Cloud Circuitbreaker), 분산 트레이싱(Spring Cloud Sleuth + Zipkin), API 게이트웨이(앞서 언급), 配置中心/서비스 메쉬(Istio 등) 등을 도입하여 클라우드 네이티브 패턴을 구현할 수 있습니다. 예를 들어 그림에서는 Zipkin Server로 각 서비스의 호출 추적을 중앙관리하고 있는 모습도 있습니다. Spring Boot 애플리케이션에 Spring Cloud Sleuth를 추가하면 자동으로 TraceID, SpanID가 붙어 로깅되고 Zipkin으로 전송되어, 마이크로서비스간 호출 흐름을 한눈에 파악할 수 있습니다. Circuit Breaker는 마이크로서비스 일부 장애가 전파되지 않도록 해주며, Resilience4j 라이브러리를 통해 구현할 수 있습니다. Boot와 Spring Cloud 환경에서는 이처럼 마이크로서비스 패턴 구현을 지원하는 풍부한 툴킷(Spring Cloud Netflix, Spring Cloud Alibaba 등)이 있으므로 필요에 따라 조합하면 됩니다.
  • 컨테이너 및 오케스트레이션: 클라우드 이행에서는 컨테이너화가 거의 필수입니다. Spring Boot는 독립 JAR로 실행되므로 Docker 이미지로 만들기 용이합니다. 멀티스테이지 빌드 등을 활용하여 경량 이미지를 만들고(Kubernetes 사용 시 init container나 sidecar로 Config나 Vault 연동도 가능), Kubernetes나 ECS 등에 배포하여 운영하는 방안을 권장합니다. 이때 각 서비스별로 Replicas를 조절하며 오토스케일링을 설정하고, ConfigMap/Secret으로 환경설정을 주입하는 형태로 운영하면 좋습니다. Boot는 쿠버네티스와도 잘 어우러지며, Spring Boot Actuator의 liveness/readiness 프로브를 이용해 Kubernetes의 헬스체크와 연동도 가능합니다.
  • REST API 디자인: 클라우드에서는 각각의 서비스가 RESTful API (또는 gRPC 등)를 통해 통신합니다. REST API는 명확한 경로와 HTTP 메서드로 설계하고, API 스펙은 명세서(OpenAPI/Swagger)로 관리하면 협업에 용이합니다. Boot에서는 springdoc-openapi 같은 라이브러리를 쓰면 자동으로 API 문서를 생성할 수 있어 유용합니다. 또한 REST API 디자인 시 DTO와 엔티티 분리, 에러 처리 표준화 등을 신경써서, 서비스 간 계Contract가 명확하도록 합니다. 이러한 API 우선 설계는 향후 다른 클라이언트(모바일, 외부 파트너 등)와 통신하거나 시스템을 확장하는 데 기반이 됩니다.
  • 상태 관리: 클라우드 환경에서는 무상태(stateless) 서비스를 지향해야 합니다. 세션이나 파일을 로컬에 저장하지 말고, 필요하면 Redis 같은 외부 저장소를 써서 세션 클러스터링을 구현합니다. Spring Boot에서는 Spring Session 등을 이용해 Redis 세션 스토리지를 사용할 수 있습니다. 또한 파일 업로드 등도 클라우드 스토리지(S3 등)를 이용하고 애플리케이션 인스턴스는 상태를 갖지 않도록 설계합니다. 이러면 새로운 인스턴스를 자유롭게 추가하거나 종료해도 서비스 일관성에 문제가 없습니다.

Spring Cloud 사용 여부에 대해서는, 현재 시스템 규모와 필요성에 따라 선택하면 됩니다. 마이크로서비스 아키텍처를 본격 도입한다면 Spring Cloud의 구성요소(Eureka, Config, Gateway 등)를 사용하는 것이 개발 생산성과 표준화에 이점이 있습니다. Spring Cloud는 마이크로서비스 구축을 위한 종합 플랫폼 역할을 하므로, 팀 내에 해당 기술 스택에 대한 이해도가 있다면 적극 활용을 고려하세요. 다만 서비스 규모가 작거나 Kubernetes 등의 플랫폼 기능으로 대체 가능하다면, Spring Cloud를 꼭 사용하지 않더라도 됩니다. 예를 들어 Kubernetes 사용 시에는 자체 서비스 디스커버리와 ConfigMap 등이 있으므로 Eureka나 Spring Cloud Config 없이 구현 가능하며, Istio 서비스메쉬를 쓴다면 서킷브레이커/트레이싱 등을 별도 코드 수정 없이 제공받을 수도 있습니다. 결론적으로, 클라우드 이행 아키텍처는 Spring Boot 마이크로서비스 + 필요한 Spring Cloud 모듈 조합으로 구성하고, 인프라 플랫폼의 기능과 적절히 조화를 이루도록 설계하는 것을 권장합니다. 이를 통해 확장성과 안정성을 갖춘 클라우드 네이티브 애플리케이션으로 발전시킬 수 있습니다.

 

 

8. 단계별 마이그레이션 로드맵 제안

마지막으로, 위에서 논의한 내용을 종합하여 Spring Boot 전환 및 클라우드 이행을 위한 단계별 로드맵을 제안합니다. 전체 과정을 몇 개의 Phase로 나누고 각 단계에서 수행할 작업과 목표를 정의하면, 체계적으로 마이그레이션을 진행할 수 있습니다:

  1. 사전 분석 및 계획 수립: (Assessment & Planning)
    • 시스템 분석: 기존 레거시 시스템의 모듈 구성, 의존 관계, 사용 프레임워크/라이브러리 목록을 인벤토리합니다. 특히 Servlets, Spring 4, MyBatis, Tomcat 관련 설정과 코드들을 모두 정리하세요.
    • 기술 부채 파악: Deprecated되었거나 업그레이드가 필요한 부분(Java 8 -> 17, Spring 4 -> 6 등)을 식별합니다. 이 단계에서 잠재적인 문제(예: Jakarta 네임스페이스 변경으로 인한 컴파일 오류 예상 지점)를 예측해두면 좋습니다.
    • 마이그레이션 전략 결정: 전체를 한번에 전환할지, 모듈별로 점진 전환할지 결정합니다. 권장하듯이 점진적(refactoring-first) 접근을 선택하고, 우선 순위를 정합니다. 예를 들어 위험도가 낮고 공통 모듈인 부분부터 먼저 Boot로 옮기는 계획을 세울 수 있습니다. 또한 모놀리식 vs 마이크로서비스 재구조화 여부도 이 단계에서 큰 그림을 결정해야 합니다. 현재 시스템을 그대로 Boot로 옮긴 후 추후에 서비스를 분리할 것인지, 처음부터 일부 기능은 분리할 것인지 고려합니다.
  2. 개발 환경 준비 및 기본 구조 구성:
    • 개발 환경 업그레이드: Java 17 등 필요한 JDK를 설치하고, 팀원들의 개발 환경(Eclipse/IDEA 설정 등)이 새로운 버전에 맞게 세팅되도록 합니다. 또한 Spring Boot 3.x의 프로젝트 구조에 익숙해지도록 기본 템플릿을 하나 생성해보는 것도 좋습니다.
    • 프로젝트 변환(POM 설정): 기존 Maven 프로젝트의 pom.xml을 수정하여 spring-boot-starter-parent와 Spring Boot 스타터들을 추가합니다. 겹치는 Spring 라이브러리 의존성(예: spring-core, spring-webmvc 등)은 제외하거나 버전을 제거합니다.
    • 메인 클래스 생성: {Application}.java라는 SpringBootApplication 애플리케이션 클래스를 생성하고 @SpringBootApplication을 부여합니다. 여기서 기존 xml 설정을 대체할 기본 패키지 구조와 컴포넌트 스캔 범위를 정합니다. 메인 클래스의 main() 메서드에서 SpringApplication.run을 호출하여 실행 진입점을 설정합니다.
    • 테스트 빌드: 일단 Boot 애플리케이션 골격이 잡혔다면 mvn spring-boot:run 또는 IDE에서 실행하여 빈 로딩 테스트를 해봅니다. 아직 기능을 모두 이관하지 않더라도, 환경이 제대로 구축됐는지 확인합니다. 에러가 난다면 의존성 충돌이나 누락된 설정을 바로 잡습니다.
  3. 코드 및 설정 단계적 마이그레이션: (Refactor & Migrate)
    이 단계에서는 실제 애플리케이션의 기능들을 Spring Boot로 하나씩 옮겨옵니다.
    • 설정 이관: 먼저 설정 파일들을 이관합니다. 기존 *.properties 또는 XML에 있던 설정을 application.properties(또는 .yml)로 합칩니다. DB 연결정보, MyBatis 설정, 포트 등 핵심 설정을 옮겨놓습니다. 또한 XML 설정(예: 스프링 빈 정의)을 대부분 자바 설정으로 대체하거나 Boot 자동구성이 커버하도록 조정합니다. web.xml의 필터, 서블릿 설정 중 계속 필요한 것은 Spring Boot 방식으로 재등록합니다 (예: FilterRegistrationBean 활용).
    • 데이터 접근 레이어 이행: MyBatis 연동을 Spring Boot 환경으로 전환합니다. 위 4번 항목에서 설명한 대로 MyBatis 스타터를 적용하고 Mapper 인터페이스에 애노테이션을 추가해줍니다. 또한 트랜잭션 관리(@Transactional) 설정이 누락되지 않도록 Spring Boot 메인 클래스에 @EnableTransactionManagement가 필요하면 붙이거나(대부분 자동 설정됨), 서비스 클래스에 @Transactional을 유지합니다. 이때 Boot에 기본 포함된 HikariCP로 ConnectionPool이 바뀌므로, 커넥션 관련 설정(maxPoolSize 등)을 조정합니다.
    • 웹 레이어 이행: 컨트롤러 및 뷰 부분을 이관합니다. 기존 Servlets를 Spring MVC @Controller로 변경하고 URL 매핑을 애노테이션으로 처리합니다. JSP 뷰는 /templates나 기존 경로에 배치하고, 필요 시 ViewResolver 설정을 추가합니다. JSP 대신 Thymeleaf로 일부 변환을 검토할 수도 있습니다. 요청 필터나 인터셉터 로직은 Spring Boot에서 각각 Filter Bean이나 HandlerInterceptor로 등록하여 이어지도록 합니다. 웹 레이어 이행 후 Postman 등으로 기본적인 URL 응답을 테스트합니다.
    • 비즈니스 로직 및 기타: Service, Domain 계층의 코드는 대체로 변경 없이 동작할 것입니다. 다만 Spring 4 -> Spring 5/6 변경에 따라 @Autowired 동작이나 예외 처리 부분에서 미세한 차이가 있을 수 있으므로 컴파일 오류와 경고를 수정합니다. 예를 들어 @Autowired 필드 주입 대신 생성자 주입으로 리팩토링하는 등의 개선을 함께 진행하면 좋습니다. 또한 Spring 4에서 사용한 오래된 유틸(예: Apache Commons DBUtils 등)이 Java 8 스트림이나 새로운 라이브러리로 대체 가능한지 검토해보고, 성능에 도움된다면 교체합니다.
    • 공통 기능 마이그레이션: 로깅 설정(log4j -> logback), 보안 설정(Spring Security 사용 시 config 클래스 재작성), 스케줄러 사용 시 @Scheduled 설정 등 기타 모든 부분을 빠짐없이 옮깁니다. 특히 에러 처리 부분은 Boot에서는 기본 /error 매핑 등이 적용되므로, 기존에 custom exceptionResolver를 썼다면 Spring Boot @ControllerAdvice로 변경하는 등 처리가 필요합니다.
    • Jakarta 전환 검증: 코드 수준에서 javax -> jakarta 변경이 다 반영됐는지 마지막으로 점검합니다. 예를 들어 서블릿 필터 구현체에서 javax.servlet.Filter를 구현했다면 컴파일 오류가 날 것이므로 jakarta.servlet.Filter로 수정해야 합니다. 이런 부분을 IDE 검색 등으로 찾아 모두 수정합니다.
    Tip: 하나의 거대한 단계로 진행하기보다, 모듈별로 작은 단위로 위 작업을 반복 수행하는 것이 좋습니다. 예를 들어 "사용자 관리 기능부터 Boot로 전환 완료 -> 주문 관리 기능 전환 완료" 식으로 순차적으로 영역을 완료시키면 각 단계마다 애플리케이션이 점진적으로 Boot화 되고 테스트도 용이합니다. 이러한 incremental migration 방식은 문제 발생 시 디버깅 범위가 작아지고, 점진적 커밋/배포가 가능해져 리스크가 줄어듭니다. 가능하다면 기존 레거시 앱과 새 Boot 앱을 동시에 구동하여 일부 트래픽을 신버전으로 라우팅해보는 (블루그린 또는 카나리아 배포) 전략도 고려할 수 있습니다.
  4. 테스트 및 검증: (Testing & Validation)
    • 유닛 테스트: 이행한 코드에 대해 단위 테스트를 실행하여 기본적인 동작을 확인합니다. Spring Boot Test(slice 테스트나 @SpringBootTest)를 활용해 컨텍스트 로딩과 빈 주입이 정상인지 검증합니다. 레거시에서 사용하던 테스트 코드는 신규 프로젝트에 맞게 업데이트하여 재활용합니다.
    • 통합 테스트: MyBatis를 통한 DB 쿼리 실행, MVC 컨트롤러 응답 등을 통합 테스트합니다. Test용 임베디드 DB나 H2 등을 활용할 수도 있고, 실제 DB 개발계정에 연결하여 쿼리를 검증할 수도 있습니다. 주요 비즈니스 시나리오에 대한 테스트 케이스를 작성하여 기능 회귀 여부를 점검합니다.
    • 성능 테스트: JMeter나 Gatling 등을 이용해 전환된 서비스의 성능을 측정합니다. 동일 부하에서 레거시 대비 응답시간, 자원 사용량(CPU, Memory)을 모니터링해보고, 목표한 개선이 이루어졌는지 확인합니다. 만약 성능이 예상보다 낮다면 앞서 언급한 설정 튜닝을 다시 살펴봅니다 (예: 스레드 풀, DB 커넥션 풀, 객체 직렬화 방식 등).
    • 병행 운영 테스트: 가능하다면 새로운 Spring Boot 애플리케이션을 기존 환경과 병행 운영하여 결과를 비교합니다. 예를 들어 일부 테스트 사용자 트래픽을 Boot 버전에만 연결해 기능이 동일하게 동작하는지 본다든지, A/B 테스트를 통한 사용자 피드백을 받는 등의 방법입니다. 최종적으로 기능적으로나 비기능적으로 모두 레거시와 동등 또는 그 이상의 품질이 확인되어야 합니다.
  5. 배포 및 전환 실행: (Deployment & Cutover)
    • 클라우드 인프라 준비: AWS, Azure, GCP 등이든 Kubernetes든, 대상 클라우드에 필요한 자원을 세팅합니다. 예를 들어 AWS EKS 클러스터를 만들고, RDS나 필요한 매니지드 서비스도 준비합니다. 네트워크 구성 및 보안그룹/방화벽 설정도 검토합니다. CI/CD 파이프라인(Jenkins, GitHub Actions 등)을 구축하여 Spring Boot 애플리케이션을 도커 이미지로 빌드하고 배포하는 자동화를 마련합니다.
    • 모니터링 설정: 클라우드 환경에서 애플리케이션 모니터링을 위해 Prometheus, Grafana, CloudWatch, Application Insights 등 모니터링 도구를 붙입니다. Spring Boot Actuator의 엔드포인트(metrics, health 등)를 활용하여 지표를 수집하고, 로깅은 ELK 스택이나 Cloud Logging에 모아서 볼 수 있도록 설정합니다.
    • 릴리즈 전략 수립: 배포 시 가용성을 최대화하기 위해 배포 전략을 선택합니다. 블루-그린 배포, 롤링 업데이트, 카나리아 배포 중 환경에 맞는 방식을 적용합니다. 예를 들어 현재 두 대의 서버로 운영 중이라면, 먼저 한 대에 Boot 버전을 올리고 테스트한 뒤 문제가 없으면 다른 한 대를 전환하는 블루-그린 방식으로 무중단 배포를 시도할 수 있습니다. 실제 사용자 트래픽을 이전하기 전에 최종 리허설을 해보고 롤백 전략도 마련해 둡니다.
    • DNS/라우팅 전환: 새로운 Spring Boot 서비스로 완전히 전환할 준비가 되면 로드밸런서나 DNS 설정을 변경하여 트래픽을 레거시에서 Boot 서비스로 넘깁니다. 만약 마이크로서비스로 쪼갰다면, 각각의 서비스에 대한 라우팅을 API Gateway에서 신버전 서비스의 주소로 바꿉니다. 이 시점에 사용자에게는 전환이 투명하게 이뤄지도록 해야 합니다.
    • 최종 운영 및 모니터링: 전환 직후 시스템을 면밀히 모니터링합니다. CPU, 메모리, 에러 로그, 응답시간 등을 실시간 체크하여 이상 징후가 없는지 확인합니다. 문제가 발견되면 즉시 롤백할 수 있도록 대비하고, 심각한 문제가 없으면 일정 기간(예: 며칠~몇 주) 신중하게 관찰합니다.
  6. 사후 최적화 및 고도화:
    • 불필요한 구성 정리: 레거시를 완전히 종료했다면, 남은 미사용 인프라(Tomcat 9 서버, 옛 배포 스크립트 등)를 정리합니다. 또한 프로젝트 레포지토리에서 사용되지 않는 옛 설정 파일이나 클래스도 제거합니다.
    • 최적화: 운영 결과를 바탕으로 튜닝 작업을 이어갑니다. 예를 들어 메모리 Xmx 조정, GC 옵션 튜닝, Hotspot 난이도가 높은 쿼리 수정 등을 진행합니다. Spring Boot 전환으로 새롭게 생긴 가능성 (예: Redis 캐시 도입, MQ 비동기 처리 등)들을 검토하여 성능과 안정성을 더 높일 수 있습니다.
    • 개선 사이클: 클라우드 환경에서 요구되는 CI/CD 파이프라인을 정교하게 다듬고, 개발 팀의 운영 절차를 Boot 중심으로 문서화합니다. 또한 Spring Boot 및 사용 라이브러리의 정기 업그레이드 전략도 수립하여 (예: Spring Boot의 minor 업그레이드는 즉시 적용, major 업그레이드는 별도 프로젝트 등) 지속적으로 최신 기능과 보안 패치를 받을 수 있게 합니다.

위 로드맵은 상황에 따라 병행되거나 순서가 바뀔 수도 있지만, 큰 틀에서 분석 → 준비 → 전환 구현 → 테스트 → 배포 흐름으로 진행됩니다. 각 단계마다 명확한 완료 조건(예: "모든 테스트 통과", "성능 목표 달성", "무중단 배포 완료")을 정해두면 프로젝트 관리에 도움이 됩니다. 무엇보다 핵심은 작게 나누어 검증하며 진행하는 것입니다. 한 번에 모두 바꾸려 하면 위험이 크므로, 단계별로 결과물을 확인하고 다음 단계로 넘어가는 방식이 성공 확률을 높입니다. 이렇게 하면 예기치 못한 문제가 생겨도 범위를 좁혀 대응할 수 있고, 결국 관리 가능한, 검증된 단계들의 연속으로 대규모 전환을 완수할 수 있습니다.

각 단계를 완료할 때마다 관련 부서(QA, 운영 등)와 협업하여 승인(sign-off)을 받고 넘어가도록 하면 품질을 담보하면서 일정을 진행할 수 있습니다. 마지막으로, 마이그레이션 완료 후에는 성과를 측정하고 (성능 개선 수치, 장애 감소 등) 이를 공유함으로써 향후 시스템 개선 작업에 대한 피드백으로 삼으시면 좋겠습니다.

LIST