개요
Spring Boot에는 개발 경험을 조금 더 즐겁게 만들어 줄 수 있는 spring-boot-devtools 모듈을 제공한다. Devtools는 모든 개발 프로젝트에 추가할 수 있으며, 개발 시점에 추가적인 기능을 제공한다.
사용방법
Maven
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
Gradle
dependencies {
developmentOnly("org.springframework.boot:spring-boot-devtools")
}
주의사항
- spring-boot-devtools는 다중 모듈 프로젝트에서 클래스 로드 등 문제가 발생할 수 있다.
- spring-boot-devtools는 패키징 된 애플리케이션을 실행할 때는 자동으로 비활성화한다.
- java -jar 명령으로 시작되거나 특별한 클래스 로더로 시작되는 경우는 자동으로 production application으로 간주하고 비활성화된다.
- -Dspring.devtools.restart.enavled=true를 사용하여 강제로 spring-boot-devtools를 활성화할 수 있다.
- Production 환경에서는 보안의 위협으로 Devtools를 비활성화해야 한다.
- Maven을 사용하는 경우 optional 설정을 true로 설정하고, Gradle의 경우 developmentOnly로 설정해야 다른 모듈에 spring-boot-devtools가 자동으로 적용되는 것을 방지할 수 있다.
- 리패키징된 아카이브에는 기본적으로 spring-boot-devtools가 포함되지 않기 때문에 추가가 필요한 경우 별도로 설정해야 한다.
Property Defaults
Spring Boot의 여러 라이브러리는 성능을 위해 캐시를 사용한다.(e thymeleaf, ...) 캐시를 사용하면 Production환경에서는 유익하지만 개발 과정에서는 캐시 때문에 서버를 재시작하는 경우가 많다. 이러한 이유로 spring-boot-devtools는 기본적으로 캐시를 비롯한 로그 출력 등 개발 시점에 필요한 환경 설정을 자동으로 설정해 준다.
spring-boot-devtools에서 지원하는 기본값을 사용하지 않으려면 spring.devtools.add-properties를 사용하여 설정할 수 있다.
Name | Default Value |
server.error.include-binding-errors | always |
server.error.include-message | always |
server.error.include-stacktrace | always |
server.servlet.jsp.init-parameters.development | true |
server.servlet.session.persistent | true |
spring.docker.compose.readiness.wait | only-if-started |
spring.freemarker.cache | false |
spring.graphql.graphiql.enabled | true |
spring.groovy.template.cache | false |
spring.h2.console.enabled | true |
spring.mustache.servlet.cache | false |
spring.mvc.log-resolved-exception | true |
spring.reactor.netty.shutdown-quiet-period | 0s |
spring.template.provider.cache | false |
spring.thymeleaf.cache | false |
spring.web.resources.cache.period | 0 |
spring.web.resources.chain.cache | falss |
추가적인 내용은 문서를 참고한다 : https://docs.spring.io/spring-boot/reference/using/devtools.html#using.devtools.property-defaults
Automatic Restart
spring-boot-devtools를 사용하면 classpath에 파일이 변경되면 자동으로 변경된 파일을 감지하고 애플리케이션을 재시작한다. 이는 IDE에서 작업할 때 코드 변경에 대한 빠른 피드백 루프를 제공하기 때문에 유용하게 사용할 수 있다. static assets나 view template은 파일이 변경되어도 재시작하지 않는다.
spring-boot-devtools를 사용해서 애플리케션을 실해하면 아래와 같이 devtools관련 로그가 추가되는 것을 볼 수 있다.
(Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable)
2025-02-07T22:09:08.261+09:00 INFO 1308 --- [devtools] [ restartedMain] org.igooo.DevtoolsApplication : Starting DevtoolsApplication using Java 21.0.5 with PID 1308 (/Users/igooo/Documents/workspace/devtools/build/classes/java/main started by igooo in /Users/igooo/Documents/workspace/devtools)
2025-02-07T22:09:08.262+09:00 INFO 1308 --- [devtools] [ restartedMain] org.igooo.DevtoolsApplication : No active profile set, falling back to 1 default profile: "default"
2025-02-07T22:09:08.272+09:00 INFO 1308 --- [devtools] [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2025-02-07T22:09:08.272+09:00 INFO 1308 --- [devtools] [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2025-02-07T22:09:08.517+09:00 INFO 1308 --- [devtools] [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
2025-02-07T22:09:08.522+09:00 INFO 1308 --- [devtools] [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2025-02-07T22:09:08.522+09:00 INFO 1308 --- [devtools] [ restartedMain] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.34]
2025-02-07T22:09:08.534+09:00 INFO 1308 --- [devtools] [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2025-02-07T22:09:08.535+09:00 INFO 1308 --- [devtools] [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 263 ms
2025-02-07T22:09:08.618+09:00 INFO 1308 --- [devtools] [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2025-02-07T22:09:08.627+09:00 INFO 1308 --- [devtools] [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'
2025-02-07T22:09:08.630+09:00 INFO 1308 --- [devtools] [ restartedMain] org.igooo.DevtoolsApplication : Started DevtoolsApplication in 0.496 seconds (process running for 0.769)
IDE를 사용하여 파일을 변경하면 자동으로 애플리케이션을 재시작한다.
(Restarting due to 2 class path changes (0 additions, 0 deletions, 2 modifications))
2025-02-07T22:15:45.082+09:00 INFO 1390 --- [devtools] [ File Watcher] rtingClassPathChangeChangedEventListener : Restarting due to 1 class path change (0 additions, 0 deletions, 1 modification)
2025-02-07T22:15:45.085+09:00 INFO 1390 --- [devtools] [ Thread-5] o.s.b.w.e.tomcat.GracefulShutdown : Commencing graceful shutdown. Waiting for active requests to complete
2025-02-07T22:15:45.091+09:00 INFO 1390 --- [devtools] [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown : Graceful shutdown complete
2025-02-07T22:15:45.123+09:00 INFO 1390 --- [devtools] [ restartedMain] org.igooo.DevtoolsApplication : Starting DevtoolsApplication using Java 21.0.5 with PID 1390 (/Users/igooo/Documents/workspace/devtools/build/classes/java/main started by igooo in /Users/igooo/Documents/workspace/devtools)
2025-02-07T22:15:45.124+09:00 INFO 1390 --- [devtools] [ restartedMain] org.igooo.DevtoolsApplication : No active profile set, falling back to 1 default profile: "default"
2025-02-07T22:15:45.170+09:00 INFO 1390 --- [devtools] [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
2025-02-07T22:15:45.171+09:00 INFO 1390 --- [devtools] [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2025-02-07T22:15:45.171+09:00 INFO 1390 --- [devtools] [ restartedMain] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.34]
2025-02-07T22:15:45.173+09:00 INFO 1390 --- [devtools] [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2025-02-07T22:15:45.173+09:00 INFO 1390 --- [devtools] [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 49 ms
2025-02-07T22:15:45.193+09:00 INFO 1390 --- [devtools] [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2025-02-07T22:15:45.196+09:00 INFO 1390 --- [devtools] [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'
2025-02-07T22:15:45.197+09:00 INFO 1390 --- [devtools] [ restartedMain] org.igooo.DevtoolsApplication : Started DevtoolsApplication in 0.082 seconds (process running for 20.293)
2025-02-07T22:15:45.198+09:00 INFO 1390 --- [devtools] [ restartedMain] .ConditionEvaluationDeltaLoggingListener : Condition evaluation unchanged
Triggering a restart
STS나 IntelliJ IDEA와 같은 IDE를 사용하면 classpath에 파일이 변경되면 자동으로 서버를 재시작한다.
- STS의 경우 별도의 설정이 필요 없이 자동으로 파일이 변경되면 서버는 재시작한다.
- IntelliJ IDEA의 경우 Setting > compiler > Build project automatically, Setting > Advenced Settings > Compiler > Allow auto-make to start even if developed application is currently running 옵션을 활성화해야 사용할 수 있다.
Restart vs Reload
Spring Boot에서 재시작은 두 개의 클래스 로더를 사용하여 자동한다. 변경되지 않는 클래스는(ex third-party jars) 기본 클래스 로더에 로드되고, 개발 중인 클래스는 재시작 클래스 로더에 로드된다. 애플리케이션이 재시작되면 재시작 클래스 로더가 사라지고 새 클래스 로더가 생성된다. 이러한 방식은 기본 클래스 로더가 이미 사용 가능한 상태로 준비되어 있기 때문에 애플리케이션 재시작이 일반적으로 cold start보다 훨씬 바르게 동작한다.
Logging Changes in Condition Evaluation
기본적으로 애플리케이션이 다시 시작될 때마다 evaluation delta를 보여주는 보고서가 기록된다. 이 보고서는 Bean의 추가/삭제, 설정 변경 사항에 대한 내용을 보여준다.
report 설정을 비활성화하려면 아래 속성을 사용해서 제어할 수 있다.
spring.devtools.restart.log-condition-evaluation-delta=false
Excluding Resources
기본적으로 /META-INF/maven, /META-INF/resources, /resources, /static, /public, /templates의 파일은 변경이 되어도 재시작하지 않는다. 아래 속성을 사용하여 변경할 수 있다.
spring.devtools.restart.exclude=static/**,public/**
Whatching Additional Paths
Excluding(재외) 설정과는 반대로 classpath에 없는 파일을 변경할 때 애플리케이션을 다시 시작해야 하면 아래 속성을 사용하여 결로를 추가할 수 있다.
spring.devtools.restart.additional-paths
Disabling Restart
재시작 기능을 사용하지 않으려면 spring.devtools.restart.enabled 속성을 사용하여 비활성화할 수 있다. 대부분의 경우 application.propertis 파일에 속성을 설정한다.(재시작 로드가 초기화되지만 파일 변경 사항은 감시하지 않는다.)
Using a Trigger File
IDE로 작업하는 경우 변경된 파일을 지속적으로 감지하여 재시작되지만, 특정 시점에만 재시작을 트리거하는 것을 선호할 수 있다. 아래 속성을 사용하여 트리거 파일을 지정하여 재시작을 설정할 수 있다.
src/main/resources/.reloadtrigger <= 파일 생성
spring.devtools.restart.trigger-file=.reloadtrigger
LiveReload
spring-boot-devtools 모듈에는 리소스가 변경되면 브라우저 새로고침을 트리거하는 내장형 LiveRealod 서버가 포함되어 있다.(LiveReload server is running on port 35729) LiveReload 브라우저 확장 프로그램은 Chrome, Firefox 및 Safari에서 무료로 제공된다.
참고
https://docs.spring.io/spring-boot/reference/using/devtools.html
'dev > spring' 카테고리의 다른 글
Spring AI를 사용하여 당근 상품 등록 기능 개발하기 (0) | 2025.02.16 |
---|---|
Spring AI 영수증 이미지 처리하기 (0) | 2025.01.21 |
Spring Boot + Testcontainers 테스트 빠르게 실행하기 (1) | 2025.01.16 |
Spring gRPC (0) | 2025.01.11 |
[Spring] Redisson으로 분산락 구현하기(Distrubuted Lock) (1) | 2024.11.21 |