매주 스프링 부트 핵심 가이드 를 읽으며 이전에 궁금했거나, 새롭게 알게 된 내용들을 정리할 예정이다.
(이번 주는 11~12장을 읽었다.)
어플리케이션을 개발하고 운영하는 단계에 접어들면 정상적으로 동작하는지 모니터링하는 환경이 매우 중요해진다. 스프링 부트에서는 엔드포인트나 JMX(Java Management eXtensions, 실행중인 어플리케이션의 상태를 모니터링하고 설정을 변경할 수 있게 해준다. JMX를 통해 관리를 하려면 Managed Beans를 생성해야 한다.)를 통해 어플리케이션을 모니터링하고 관리할 수 있는 기능을 제공한다.
액추에이터 의존성을 추가하고, application.properties
파일에 다양한 속성을 추가하여 설정이 가능하다. 엔드포인트(모니터링을 사용하는 경로)는 활성화와 노출 여부를 설정 가능하다. 예시는 다음과 같다.
## shutdown 활성화, caches 비활성화
management.endpoint.shutdown.enabled=true
management.endpoint.caches.enabled=false
## Endpoint 노출 설정
## 모든 기능을 노출하나 threaddump와 heapdump 제외
## HTTP 설정
management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=threaddump, heapdump
## JMX 설정
management.endpoints.jmx.exposure.include=*
management.endpoints.jmx.exposure.exclude=threaddump, heapdump
이러한 엔드포인트들은 어플리케이션에 관한 민감한 정보를 포함하고 있으므로 노출 설정을 신중하게 고려할 필요가 있다.
가동 중인 어플리케이션의 정보를 볼 수 있다. 제공하는 정보는 어플리케이션에서 몇 가지 방법을 거칠 수 있으나 application.properties
파일에 info.
로 시작하는 속성 값들을 정의하는 것이 가장 쉬운 방법이다. 값을 정의한 뒤 서버주소/actuator/info
URL에 접근하면 정의한 속성 값을 바탕으로 생성된 정보가 JSON
형태로 제공된다.
어플리케이션의 상태를 확인할 수 있으며, 주로 네트워크 계층에서 L4 레벨(Loadbalancing, 전송 계층에서의 부하 분산) 에서 상태를 확인하기 위해 사용된다.
스프링 컨테이너에 등록된 빈의 전체 목록을 JSON 형식으로 보여준다. 그러나 워낙 많은 빈이 자동으로 등록되기 때문에 한 눈에 내용을 파악하기는 어렵다.
자동설정(AutoConfiguration) 내역을 확인한다. 크게 positiveMatches
와 negativeMatches
로 구분되며 자동설정의 @Conditional
에 따라 평가된 내용을 표시한다.
스프링의 환경 변수 정보를 확인한다. 기본적으로 application.properties
파일의 변수들이 표시되며 OS, JVM 의 환경변수도 함께 표시된다.
어플리케이션의 로깅 레벨 수준의 설정을 확인한다. GET
메소드로 호출하면 확인이 가능하며 POST
메소드로 호출하면 로깅 레벨을 변경할 수도 있다.
기존 기능에 내용을 추가하거나, 새로운 엔드포인트를 개발하는 방식으로 구현하며,@Endpoint
가 명시된 클래스를 이용하여 구현할 수 있다.
MSA(MicroService Architecture) 는 한 서버에 하나의 주요 기능을 담으므로, 다른 서버의 기능을 사용하고 싶은 경우가 발생한다. 이럴 때 다른 서버에서 결과를 받아야하는 경우도 있는데, 이때 사용하는 것이 RestTemplate이다.
다양한 방법이 있으나 가장 보편적인 방법은 UriComponentsBuilder
를 사용하는 방법이다.
// 경로 변수 방식
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:8080")
.path("/api/{name}")
.encode()
.build()
.expand("MyName")
.toUri();
// 쿼리 파라미터 방식
URI uri2 = UriComponentsBuilder
.fromUriString("http://localhost:8080")
.path("/api/param")
.queryParam("name", "myName")
.encode()
.build()
.toUri();
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.getForEntity(uri, String.class);
return responseEntity.getBody();
GET 방식과 유사하지만 Request 헤더와 바디가 필요한 경우 다음과 같이 작성한다.
RequestEntity<PersonDto> request = RequestEntity
.post(uri)
.header("HEADER", "my header")
.body(personDto);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<PersonDto> response = restTemplate.exchange(requestEntity, PersonDto.class);
실제 운영환경의 어플리케이션은 정식 스프링 부트의 버전보다 낮은 경우가 많아 RestTemplate을 많이 사용하지만, 최신 버전에서는 RestTemplate이 지원 중단되어 WebClient를 사용할 것을 권고한다. 이러한 흐름에 맞춰 둘 다 알고 있는 것이 좋겠다.
WebClient를 생성하는 방법에는 크게 두가지가 있다.
create()
메소드를 통한 생성builder()
를 이용한 생성WebClient는 우선 객체를 생성한 후 요청을 전달하는 방식으로 동작한다. builder()
를 통해 baseUrl()
메소드에서 기본 URL을 설정하고 defaultHeader()
메소드로 헤더의 값을 설정한다. 일반적으로 WebClient
객체를 이용할 때 객체를 생성하고 재사용하는 방법으로 구현하는 것이 좋다. 한번 빌드된 WebClient
는 변경할 수 없으나 Webclient.mutate()
메소드를 사용하면 복제 가능하다.