본문 바로가기

개발노트/JAVA

[Spring][IntelliJ] SpringBoot HotSwap with IntelliJ [2019-02-19 Updated]

참고 : https://stackoverflow.com/questions/35895730/spring-boot-devtools-static-content-reloading-does-not-work-in-intellij

https://docs.spring.io/spring-boot/docs/current/reference/html/howto-hotswapping.html


1. build.gradle 파일의 의존관계 설정 (spring-boot-devtools)

compile('org.springframework.boot:spring-boot-devtools')


2. 인텔리J 설정(Ctrl + Alt + S)

Settings > Build, Execution, Deployment > Compiler 메뉴에서 Build project automatically 체크

3. Registry 값 변경

Ctrl + Alt + Shift + /

를 누르면 나오는 메뉴에서 Registry 를 선택하고 아래와 같이

compiler.automake.allow.when.app.running 레지스트리 값을 true로 변경(체크 하면 됨)


4. 인텔리J 를 재부팅 하고 확인해보기



--- 추가 내용 ---

잘 안 되길래 좀 헤멨다가 다시 정리한 글.


Spring Boot Hot swap using spring-devtools with intelliJ

Description

어플리케이션이 실행 중인 상태에서 클래스 파일이나 정적 자원들을 수정할 경우, 매번 서버를 재시작해주어야 하는 불편함이 있는데, 개발 단계에서는 hot swap 을 적용하여 시간을 아낄 수 있음

Process

  1. IntelliJ 설정

    1. Settings > Build, Execution, Deployment > Compiler 에서 “Build project automatically” 옵션에 체크 후 OK

    2. Ctrl + Shift + Alt + / 를 타입하면 Registry 를 조회/편집할 수 있는 메뉴가 나온다. Registry 를 눌러서 compiler.automake.allow.when.app.running 키 값을 찾아서 체크해준다.

    3. Rerun IntelliJ

  2. Spring Boot 설정

    1. dependencies 추가

      1. compile('org.springframework.boot:spring-boot-devtools')

    2. application.yml (또는 application.properties)에 속성 값 설정

      1. spring.devtools.livereload.enabled=true

      2. spring.devtools.restart.enabled=true

      3. spring.thymeleaf.cache=false

  3. 스프링 부트 어플리케이션 실행 방법

    1. gradle bootRun 으로 해도 스프링 부트 어플리케이션은 실행되지만 hot swap은 적용이 안 되었음

    2. 따라서 hot swap을 적용시키고 싶으면 main() 메소드를 갖는 main class를 실행해주어야 함. main class를 실행시키면 잘 되는 것을 확인했음.




2019-02-19 추가 내용


Class Hotswap 이 잘 안 된다는 제보를 보고 저도 다시 삽질을 좀 해봤습니다.

아래의 몇줄로 요약하니, 도움이 되기를 바랍니다.


1. spring.devtools.restart.enabled=false 로 설정


2. IntelliJ Run/Debug Configuration 에서 On 'Update' action : "Hot swap classes and update trigger file if failed" 및 on frame deactivation : "Update classes and resources" 지정


3. 스프링 부트 앱을 디버그 모드로 실행



4. 클래스 코드 수정 후, 브라우저(또는 IntelliJ가 아닌 다른 window)를 클릭하면 on frame deactivation 에 지정한 동작이 실행됩니다. 이 때, 클래스가 변경되면 reload 할거냐고 묻는 dialog 가 뜨는데, "다시 묻지 않기"에 체크를 한 후 "Yes"를 선택하시면 그 다음부터 컴파일/빌드/hotswap이 되는 몇초만 기다리면 Container 재기동 없이 변경된 class가 실행됩니다.


이 때, on frame deactivation 이 아니라 on 'Update' action 에 지정한 동작을 발동시키기 위해서는 "Ctrl + F10" 의 키맵이 할당된 "Run" > "Update XXXApplication application" 을 클릭하면 되고, 디버그 모드일 경우에는 "Run" > "Reload changed classes" 메뉴가 활성화 되어 있으므로 이걸 실행시켜도 됩니다. 

사실, 아까 On 'Update' action : "Hot swap classes and update trigger file if failed" 의 설정을 하였기 때문에, "Run" > "Update XXXApplication application" 자체가 "Run" > "Reload changed classes" 에 대한 alias 가 되었다고 볼 수 있습니다.




  • 2017.11.02 16:05

    비밀댓글입니다

  • 2018.08.13 14:54

    비밀댓글입니다

    • Favicon of https://lhb0517.tistory.com Mr.star 2018.08.13 16:12 신고

      spring dev tools의 경우엔 리소스에 대해서만 핫 스왑이 적용되고, 클래스의 경우엔 오토 리스타트가 되요. 클래스 핫 스왑에 대해선 스프링 로디드(spring loaded)에 대해 알아보세요.

  • Favicon of https://brad903.tistory.com Brad Lee 2018.11.15 17:13 신고

    와 감사합니다!!! 정말 도움 많이 되었어요:)

  • Favicon of https://web2eye.tistory.com 성건희 2018.12.15 16:24 신고

    도움 많이 됬어요! 감사합니다

  • DK 2019.01.16 00:17

    IntelliJ + SpringBoot 2.1.x + Gradle 진행중인데 본문대로 했는데 아무리 해도 자바클래스 수정 후엔 컨테이너가 재기동 되면서 맵핑도 먹통이 되버리더군요. 수정한 부분 핫스왑 역시 안되고..

    혹시 저랑 같은 증상이신 분은 그냥
    application.yml 설정을

    spring:
    --devtools:
    ---livereload:
    ----enabled: true
    ---restart:
    ----enabled: false
    --thymeleaf:
    ---cache: false

    위와 같이 해주고 (restart false!) 클래스 파일 수정한다음에 Ctrl+Shift+F9 로 재컴파일 후 클래스 리로드 하면 자동 핫스왑은 아니라도 수동 핫스왑은 되실겁니다;

    • Favicon of https://lhb0517.tistory.com Mr.star 2019.01.16 00:29 신고

      오 보충 설명 감사합니다. devtools 라는 모듈 특성상 스프링의 코어 모듈들이랑 호환이 안 맞는 부분도 있고, ide에서 실행하는 것과 os에서 gradle bootrun 하는 것의 실행 환경(파라미터 등등)이 조금씩 다르기 때문에 기대하는 액션이 안 나올 경우 하나씩 하나씩 확인이 필요한 것 같습니다. spring loaded가 클래스 핫스왑은 잘 됐던 기억이 있는데 어떤 분들은 한 프로젝트에서 devtools와 spring loaded 함께 쓰시기도 하더라고요. devtools가 가끔 특정 프로덕션 런타임환경에서 문제를 일으키는 경우도 있는 점 등 유의해야할 게 많은 것 같습니다.

      저도 다시 한 번 삽질을 해봐야겠네요 ㅎㅎ

    • DK 2019.01.16 15:16

      spring:
      devtools:
      livereload:
      enabled: true

      요렇게만 설정하니까 톰캣이 자동 restart 하면서 Condition evaluation unchanged 라는 메시지 뜨고 클래스 수정 사항이 별도 재컴파일 없이 반영되네요. 회사에서는 이렇게 되는데..
      집에서는 톰캣 restart 되고나서 url 이 안먹는.. 뭔가 환경설정 싱크를 잘못 해둔듯 ㅜㅜ

    • Favicon of https://lhb0517.tistory.com Mr.star 2019.02.19 13:34 신고

      안녕하세요?

      Nice 한 방법은 아니지만 저도 다시 조금의 삽질을 해봤습니다.

      처음 DK 님께서 말씀하신 것처럼 완전 hotswap 이 잘 안 되더라고요.

      IntelliJ 2018.3
      Spring boot 2.0.5.RELEASE 버전
      이구요.

      첫번째 방법 - 수동 hotswap

      1. spring.devtools.restart.enabled=false 설정 (컨테이너 자동 재시작 방지)
      2. IntelliJ 에서 스프링 부트 앱을 디버그 모드로 실행(Shift + F9) java 클래스 코드 수정
      3. Run > Reload changed classes 클릭
      (저는 Ctrl + Shift + F5 키맵 할당)

      두번째 방법 - 자동 hotswap (반자동?)

      1. spring.devtools.restart.enabled=false 설정 (컨테이너 자동 재시작 방지)
      2. Run/Debug Configurations 에서 On frame deactivation 항목에 "Update classes and resources" 를 선택
      3. 스프링 부트 앱을 디버그 모드로 실행 후 java 클래스 코드 수정
      4. 브라우저 클릭 (intelliJ frame 을 비활성화) : 이 순간에 재컴파일/빌드가 수행 됨
      5. Reload Changed Classes for XXXApplication 다이얼로그가 뜨는데, "Do not show this dialog in the future" 에 체크한 후 "Yes" 선택

      이렇게 정리할 수 있을 것 같습니다.

      핵심은 devtools.restart 를 끄고 디버그 모드로 실행시키는 것인 것 같습니다.

    • Favicon of https://lhb0517.tistory.com Mr.star 2019.02.19 13:42 신고

      Edit Configurations 메뉴에서 보시면 "On 'Update' action" 항목과 "On frame deactivation" 항목 가장 오른쪽에서 툴팁을 보실 수 있는데요.

      "Hot swap classes and update trigger file if failed" 라는 항목 아래에

      "In debug mode" vs "Otherwise" 로 구분되어 있기도 합니다.

      debug 모드로 실행시키면 trigger 파일 지정 없이 모든 파일에 대해서 변경이 감지되면 hot swap 을 시도하도록 되어있네요.

    • dddd 2020.02.16 16:43

      DK님 말씀대로 ctrl+shift+f9로 재컴파일하는 방법은.. devtools 의존성 받지 않은상태, 그리고 application.properties 설정을 안했을때도 되는 방법이네요... (hot swap관련해서 아무 설정안하고 인텔리제이 설치하자마자 바로 사용해도 가능한 방법;;)

      hot swap이 가능할려면 코드 수정 후 브라우저에서 새로고침 누르면 바로 수정된 코드가 반영되야 할것같은데요 이게 인텔리제이에서 안되네요

  • hello 2019.03.27 10:59

    intellij 정적 리소스 reload가 안되서 너무 불편합니다... (css, html 코드 수정)
    뭐처럼 intellij 넘어왔는데 이것 때문에 몇일째 삽질중이고 구글링하면서 10번은 계속 해본거 같은데 적용이 안 되고 있습니다...
    위 글에 처음부터 추가내용까지 적용해봤는데 reload가 안 되고 있습니다.

    일단 sts로 작업하고 있어야겠습니다... 혹시 팀뷰어로 한번 봐주시면 안될까요ㅠ.ㅠ??

    • Favicon of https://lhb0517.tistory.com Mr.star 2019.03.27 12:37 신고

      혹시 뷰 템플릿 엔진으로 타임리프 말고 다른 거 쓰시는 건 아니신가요?

    • hello 2019.03.27 13:17

      Handlebars(hbs)사용하고 있습니다. 아 이것때문에 안되는걸까요??

      springboot로 처음 개발해 보고 있는데 jsp만 사용해봤습니다... 타임리프를 사용하면 정적 리소스 reload 되나요?!

    • Favicon of https://lhb0517.tistory.com Mr.star 2019.03.27 14:41 신고

      cache 가 켜져있을 가능성이 있을 것 같아요. 글 본문에는 thymeleaf.cache=false 로 되어있는데 핸들바에 맞게 handlebars.cache=false(?) 같은 형식의 설정으로 바꿔서 사용하시면 안 되는 원인의 가능성을 하나 줄이실 수 있을 것 같아요.

    • hello 2019.03.27 16:31

      덕분에 적용했습니다 ㅠ.ㅠ!!!!! 감을 못 잡고 있었는데 어딜 봐야 할지 알려주셔서 잘 적용이 됬습니다. 감사합니당~!

    • Favicon of https://lhb0517.tistory.com Mr.star 2019.03.27 16:36 신고

      적용하셨다니 다행입니다. 알려주셔서 감사합니다.

  • 녹쌕 2019.04.16 14:56

    핫스왑 관련해서 어제부터 검색했었는데 이제야 문제해결 시켜주는 글을 발견했네요...감사합니다.

  • ㅋㅌㅊㅍ 2019.07.08 13:42

    bootRun 왜 아무도 안알려주는거햐 . . ㅠ !
    덕분에 한시간헤멘거 알아갑니다!

  • 밭매는할매 2019.12.16 03:49

    SpringBoot DevTools의 livereload 기능을 제대로 못쓰고 있었는데, 덕분에 해결했습니다.
    감사합니다.

  • bluewow 2020.03.06 17:24

    저는 js 파일이 compile 이 안되서 고생했는데요

    결과적으로는 Resource patterns 에(Setting -> Compiler) js 패턴을 추가하여 수정하였습니다

    유용한 정보 감사합니다