클라우드 서버에 jar 를 통해 배포하는 과정에서 애플리케이션을 정상적으로 종료하는 것에 대한 고려를 하지 못했다. kill -9 이 아닌 kill 을 통해 종료 요청을 보내는 것도 방법이지만 운영 환경에서 용이하게 관리할 수 있도록 shutdown endpoint 를 구현하기로 하였다.
비정상적인 종료와 정상적인 종료
Linux 환경을 기준으로 kill -9 을 통해 프로세스를 종료시킨다면, 프로세스는 현재 진행 중인 요청도 마무리하지 못하고 강제 종료되게 된다. 이는 비정상적인 종료로 데이터 손실이나 파일 손상과 같은 부작용을 초래할 수 있다.
정상 종료는 제어된 방식으로 애플리케이션을 종료하여 진행 중인 작업을 완료하고 시스템을 해제하고 데이터 무결성을 보장하며 종료할 수 있다.
정상적으로 종료하는 방법은 여러가지가 있지만 그 중 나는 actuator 에서 제공하는 shutdown endpoint 를 사용할 것이다.
spring actuator 사용하기
spring actuator 를 사용하면 애플리케이션 모니터링 / 지표 수집 / 트래픽 상태를 편리하게 확인할 수 있게 된다.
이를 활성화하기 위해서는 아래와 같은 의존성을 추가해야한다.
- Gradle
implementation 'org.springframework.boot:spring-boot-starter-actuator'
- Maven
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
spring actuator 는 다양한 엔드포인트를 제공하며 공식문서에서 자세한 내용을 확인할 수 있다.
우리는 이를 참고로 특정 endpoint 에 대한 노출을 허락할 건지 설정해야하며, 모든 엔드포인트에 대한 노출을 허락할 수도 있다. 하지만 이는 원치 않은 정보까지 모두 외부로 노출되게 된다.
- application.properties
# health 와 info 에 대한 엔드포인트 노출 허용
management.endpoints.web.exposure.include=health,info
# 모든 엔드포인트에 대한 노출 허용 ( 보안상 권장 X )
management.endpoints.web.exposure.include=*
여기서 shutdown endpoint 를 사용하기 위해서는 추가 옵션이 필요하다.
- application.properties
management.endpoints.web.exposure.include=shutdown # 노출시킬 엔드포인트에 shutdown 추가
management.endpoint.shutdown.enabled=true # shutdown endpoint 활성화
shutdown endpoint 에 대해서
위의 설정을 마쳤다면 잘 동작하는 지 확인하기 위해 /actuator/shutdown 에 POST 요청을 해보자.
$ curl 'http://localhost:8081/actuator/shutdown' -i -X POST

실행 결과로 acutuator 에서 응답받은 메시지와 애플리케이션이 종료되었음을 확인할 수 있었다.

그런데 왜 shutdown endpoint 만 추가 옵션이 필요할까?
그 이유는 shutdown endpoint 가 기본적으로 disable 상태이기 때문이다.
운영 환경에서 아무런 인증 없이 해당 endpoint 를 활성화 한다면 검증되지 않는 사용자에 의해 서비스가 중지될 수도 있는 위험에 처해진다. 이에 대한 해결방안으로 나는, 관리자 ROLE 을 만들어 해당 권한을 가진 소유자에 한해서만 shutdown endpoint 에 접근이 가능하도록 관리 할 생각이다.
참고
https://www.baeldung.com/spring-boot-shutdown
https://bootcamptoprod.com/spring-boot-graceful-shutdown/
https://techblog.woowahan.com/9232/
'Web' 카테고리의 다른 글
| [JPA] 양방향 순환 참조 (0) | 2023.12.24 |
|---|---|
| [Spring] 예외 코드 Enum 으로 관리하기 (0) | 2023.12.17 |
| [Spring] RestTemplate 과 WebClient (0) | 2023.12.03 |
| [Spring] Swagger 에 JWT 설정하기 (0) | 2023.11.26 |
| [Spring] Spring 3.x + Swagger 설정 (0) | 2023.11.19 |