소개
스프링부트 개발을 더욱 쾌적하게 해주는 도구이다. 대표적인 기능으로는 다음과 같은 기능이 있다.
스프링 부트 Restart
: 재시작 시간을 단축해준다.자동 재시작
: 클래스 패스에 있는 파일이 변경되었을 때, 자동으로 애플리케이션을 재시작한다.LiveReload
: 리소스 변경사항을 브라우저에 즉각 반영해준다.캐시 무효화
: 디폴트 설정으로 동작하는 캐싱 기능들을 꺼준다.
Restart vs Reload
스프링부트는 재시작할 때 2개의 클래스 로더를 사용한다. base classloader 와 restart classloader 가 있다. 서드파티 라이브러리와 같은 변하지 않는 클래스는 base classloader 에 로드되고, 내가 현재 개발하는 클래스들은 restart classloader 에 로드된다. 애플리케이션이 재시작되면 restart classloader 가 던져지고, 새로운 restart classloader 가 만들어진다. 이 방식은 그냥 시작하는 "cold starts" 보다는 일반적으로 훨씬 빠르다. 왜냐하면 base classloader 는 바뀔 필요가 없기 때문이다.
JRebel from ZeroTurnaround와 같은 기술을 이용하면 훨씬 빠르게 재시작이 가능하다. 클래스가 로드될 때 재작성함으로써 새로 고침을 더 쉽게 할 수 있다.
클래스 로딩 이슈 진단
- 스프링 부트의
Restart
기능은 대부분의 프로젝트에서는 잘 동작하지만, 멀티 모듈 프로젝트에서 클래스 로딩 이슈를 일으킬 때도 있다. - 그럴 땐 아래의 설명을 읽고
Restart
를 끄거나,Restart
클래스 로더를 커스터마이징하면 된다.
Restart(재시작) 비활성화하기
- 위에서 언급한 스프링 부트의
Restart
(재시작) 기능을 끄고 싶다면,application.properties
에서spring.devtools.restart.enabled
를 이용해 끌 수 있다.- 여전히 restart classloader 는 동작하지만, 파일 변화 감지는 안 한다.
- 완전히
Restart
기능을 끄고 싶다면, 스프링부트 앱이 시작되기 전에 아래와 같이 시스템 프로퍼티를 설정해야 한다.
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(MyApplication.class, args);
}
}
Restart 클래스 로더 커스터마이징
META-INF/spring-devtools.properties
파일을 작성함으로써, restart classloader 에 뺄 것과 넣을 것을 정할 수도 있다.
restart.exclude.companycommonlibs=/mycorp-common-[\\w\\d-\\.]+\\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w\\d-\\.]+\\.jar
캐싱 무효화
템플릿 엔진은 파싱된 템플릿 파일을 이용하고, 스프링 MVC는 정적 리소스를 서빙할 때 캐싱 헤더를 추가한다. 캐싱은 프로덕션에서는 많은 이익을 주지만, 개발 단계에서는 생산성을 떨어트릴 수 있다. spring-boot-devtools 는 여러가지 캐싱을 기본적으로 꺼둔다.
참고 - 캐싱 무효화를 사용하기 싫다면?
application.properties
에서 spring.devtools.add-properties
의 값을 false
로 하면 기본 설정값을 사용하지 않을 수 있다.
자동 재시작
클래스 패스에 있는 파일이 변경될 때마다 애플리케이션이 재시작된다. 빠른 피드백 루프를 제공해줄 수 있다. 기본적으로, 디렉토리를 가리키는 클래스 패스 엔트리 변화를 모니터링한다. 정적 자원, 뷰 템플릿과 같은 리소스들은 재시작이 필요 없다.
참고 - 제외 리소스 (Excluding Resources)
/META-INF/maven
, /META-INF/resources
, /resources
, /static
, /public
, /templates
과 같은 디렉토리에 있는 리소스들을 바꾸었다면, 재시작을 할 필요 없이 Live Reload 하면 된다.
만일 이러한 제외 리소스들을 커스터마이징하고 싶다면, application.properties
에 아래의 속성을 추가하면 된다.
spring.devtools.restart.exclude=static/**,public/**
만일 기본 값은 유지하면서 추가적으로 제외 리소스를 추가하고 싶다면 spring.devtools.restart.additional-exclude
를 대신 쓰면 된다.
재시작 Triggering 하기
devtools 는 클래스 패스 리소스를 모니터링한다. 클래스 패스를 업데이트 하기 위해서는 어떤 IDE를 사용하냐에 따라 다르다.
- IntellijIDEA 에서는 프로젝트를 빌드하면 된다. (
Build > Build Project
) - 빌드 플러그인을 사용하면,
mvn compile
,gradle build
명령어를 이용하자.- 빌드 플러그인을 이용하려면
forking
을enable
상태로 두어야 한다.
- 빌드 플러그인을 이용하려면
로그 리포트 끄기
spring.devtools.restart.log-condition-evaluation-delta=false
- 재시작 시에
condition evaluation delta
로그를 끈다.- 위 로그는 스프링 부트
auto-configuration
에서의 변경사항을 나타내는 로그이다.
- 위 로그는 스프링 부트
추가 경로 watch 하기
- 클래스 패스 외에 다른 경로를 watch 하고 싶다면 설정한다.
spring.devtools.restart.additional-paths
를application.properties
에 등록하고 이용하면 된다.
트리거 파일 만들어서 재시작하기
만일 매번 클래스 패스 파일이 변경될 때마다 재시작되는 것이 싫다면, 트리거 파일 하나를 두고 그 파일이 바뀔 때 재시작할 수도 있다.
src
+- main
+- resources
+- .reloadtrigger
위 경로에 넣어주면 된다.
spring.devtools.restart.trigger-file=.reloadtrigger
src/main/resources/.reloadtrigger
파일이 업데이트되면 재시작된다.
IDE restart 지원
Intellij 공식 문서를 참고하여, restart 시점을 맘대로 정할 수 있다.
Live Reload
자동 재시작이 활성화된 상태에서 LiveReload 를 이용할 수 있다. spring-boot-devtools
모듈은 리소스가 변경되었을 때, 브라우저를 새로고침하는 내장된 LiveReload 서버를 포함한다. LiveReload 브라우저 익스텐션은 Chrome, Firefox, Safari 에서 이용 가능하다.
LiveReload 서버는 한번에 하나만 구동 가능하다. 앱을 시작하기 전에 다른 LiveReload 서버가 동작중이지 않은 것을 확실히 체크하자. IDE에서 여러 애플리케이션을 시작하면, 첫번째만 LiveReload 서버가 지원된다.
JRebel을 이용하면, automatic restart는 꺼지니 주의하자. 대신 나머지는 잘 동작한다.
주의사항들
역직렬화에 관련된 이슈
표준 ObjectInputStream
에 의해 역직렬화되는 오브젝트들이 있을 때 Restart 기능을 사용하면 잘 동작하지 않는다. 이럴 때는 ConfigurableObjectInputStream
를 Thread.currentThread().getContextClassLoader()
와 함께 사용할 필요가 있을 수 있다.
몇몇 서드파티 라이브러리들은 context classloader를 고려하지 않고 역직렬화를 한다. 만일 이러한 문제를 발견했다면, 작성자에게 수정을 요청하자.
프로덕션 동작과 관련된 주의점
spring-boot-devtools
는 프로덕션에서는 비활성화 된다.java-jar
와 같은 명령어로 실행된 애플리케이션은 프로덕션 레벨에서 실행됐다고 보아spring-boot-devtools
가 비활성화된다.
- VM 옵션에
-Dspring.devtools.restart.enabled=true
를 줘서 프로덕션 레벨에서도 켤 수 있다. - 프로덕션 레벨에서
spring-boot-devtools
를 켜면 보안상의 취약점이 생길 수 있으니 절대 켜면 안된다.-Dspring.devtools.restart.enabled=false
로 확실히 끌 수 있다.
Gradle Configuration을 지키자
- gradle에서
developmentOnly
설정으로 적용하자.- 프로젝트를 사용하는 다른 모듈에게 '과도적(transitively)'으로 사용되지 않기 위해서이다.
- 재패키징된 아카이브는
devtools
를 기본으로 포함하지 않는다.
AspectJ weaving과 관련된 주의사항
AspectJ weaving 을 사용하면 Automatic restart 는 적용되지 않는다.
'프레임워크 > 스프링 프레임워크' 카테고리의 다른 글
DispatchServlet.doDispatch() 함수 끝까지 따라가서 HandlerMapping 과 HandlerAdapter 알아보기 (0) | 2023.01.30 |
---|---|
스프링 객체 검증 (Validation) 적용하기 (0) | 2022.05.29 |
asciidoctor 를 통한 Spring REST Docs 자동 생성 세팅하기 (2) | 2022.05.18 |
Spring REST Docs + asciidoctor 로 문서 자동 생성해보기 (0) | 2022.05.15 |
AutoConfigureMockMvc 에서 한글이 제대로 인식되지 않을 때 (0) | 2022.04.03 |