CHAPTER 5 애플리케이션 설정과 검사
디버깅은 개발자로 입문할 때부터 배워서 개발자로 일하는 동안 개선하고 확장해야 할 기본 기량
이와 같이 중요함에도, 코드 디버깅은 애플리케이션 내 동작을 구축, 식별, 분리하는 한 단계에 불과합니다. 동적이고 분산된 애플리케이션이 많아지면 종종 다음 작업을 수행해야 합니다.
- 애플리케이션의 동적 설정과 재설정
- 현재 설정과 출처의 확인과 결정
- 애필리케이션 환경과 헬스 지표의 검사와 모니터링
- 실행 중인 애플리케이션의 로깅 수준을 일시적으로 조정해 오류 원인 식별
이 장에서는 스프링 부트에 내장된 설정 기능, 자동 설정 리포트와 함께 스프링 액추에이터로 애플리케이션 환경 설정을 유연하게 동적으로 생성, 식별, 수정하는 방법을 다룹니다.
5.1 애플리케이션 설정
많은 설정이 있고 유용하나, 이 장에서는 몇 가지 시나리오만 살펴보겠습니다.
- 명령 줄 인수
- OS 환경 변수
- 패키징된 애플리케이션 jar 안에 있는 애플리케이션 속성(application.properties와 YAML파일)
5.1.1 @Value
설정을 코드에 녹이는 가장 간단한 접근방식, 패턴 매칭과 SpEL(스프링 표현 언어)을 기반으로 구축되어 간단하고 강력
@Value("${greeting-name: Mirage}") // Mirage 는 properties에 값이 없을 경우 사용할 기본값
private String name;
5.1.2 @ConfigurationProperties
@Value 가 유연하지만 단점이 있기 때문에, 스프링 개발팀에서는 @ConfigurationProperties 를 만들었습니다. 불일치시 경고해줌
package com.thehecklers.sburrestdemo;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "greeting")
public class Greeting {
private String name;
private String coffee;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCoffee() {
return coffee;
}
public void setCoffee(String coffee) {
this.coffee = coffee;
}
}
5.2 자동 설정 리포트
application.properties 파일에 debug=ture 추가
Positive matches : 현재 활성화된 AutoConfiguration 목록
Negative matches : 현재 비활성화된 AutoConfiguration 목록
Exclusions : 예외처리 한 AutoConfiguration 목록
Unconditional classes : conditional 조건이 없는 AutoConfiguration 목록 (활성화된 것으로 보면 됨)
출처:
https://luvstudy.tistory.com/258
[파란하늘의 지식창고:티스토리]
Negative matches:
-----------------
AopAutoConfiguration.AspectJAutoProxyingConfiguration.JdkDynamicAutoProxyConfiguration:
Did not match:
- @ConditionalOnProperty (spring.aop.proxy-target-class=false) did not find property 'proxy-target-class' (OnPropertyCondition)
5.3 액추에이터
의존성 추가
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
GET 호출 해보면
GET <http://localhost:8080/actuator>
HTTP/1.1 200
Content-Type: application/vnd.spring-boot.actuator.v3+json
Transfer-Encoding: chunked
Date: Tue, 20 Feb 2024 11:10:16 GMT
Keep-Alive: timeout=60
Connection: keep-alive
{
"_links": {
"self": {
"href": "<http://localhost:8080/actuator>",
"templated": false
},
"health": {
"href": "<http://localhost:8080/actuator/health>",
"templated": false
},
"health-path": {
"href": "<http://localhost:8080/actuator/health/{*path}>",
"templated": true
}
}
}
Response file saved.
> 2024-02-20T201016.200.json
보안상 문제가 될 수 있기 때문에 조심해야 한다.
다음과 같은 내용을 application.properties 에 추가한다
management.endpoints.web.exposure.include=env, info, health
만약 엔드포인트를 많이 노출하면 실행시 다음과 같은 log가 찍힘
EndpointLinksResolver : Exposing 13 endpoint(s) beneath base path '/actuator'
GET <http://localhost:8080/actuator>
HTTP/1.1 200
Content-Type: application/vnd.spring-boot.actuator.v3+json
Transfer-Encoding: chunked
Date: Tue, 20 Feb 2024 11:14:40 GMT
Keep-Alive: timeout=60
Connection: keep-alive
{
"_links": {
"self": {
"href": "<http://localhost:8080/actuator>",
"templated": false
},
"beans": { => 생성한 모든 스프링 빈
"href": "<http://localhost:8080/actuator/beans>",
"templated": false
},
"caches-cache": {
"href": "<http://localhost:8080/actuator/caches/{cache}>",
"templated": true
},
"caches": {
"href": "<http://localhost:8080/actuator/caches>",
"templated": false
},
"health": { => health 정보
"href": "<http://localhost:8080/actuator/health>",
"templated": false
},
"health-path": {
"href": "<http://localhost:8080/actuator/health/{*path}>",
"templated": true
},
"info": {
"href": "<http://localhost:8080/actuator/info>",
"templated": false
},
"conditions": {
"href": "<http://localhost:8080/actuator/conditions>",
"templated": false
},
"configprops": {
"href": "<http://localhost:8080/actuator/configprops>",
"templated": false
},
"configprops-prefix": {
"href": "<http://localhost:8080/actuator/configprops/{prefix}>",
"templated": true
},
"env": { => 애플리케이션이 작동하는 환경의 무수한 측면 확인
"href": "<http://localhost:8080/actuator/env>",
"templated": false
},
"env-toMatch": {
"href": "<http://localhost:8080/actuator/env/{toMatch}>",
"templated": true
},
"loggers": { => 모든 컴포넌트의 로깅 수준
"href": "<http://localhost:8080/actuator/loggers>",
"templated": false
},
"loggers-name": {
"href": "<http://localhost:8080/actuator/loggers/{name}>",
"templated": true
},
"heapdump": { => 트러블 슈팅과 분석을 위해 힙 덤프 시작
"href": "<http://localhost:8080/actuator/heapdump>",
"templated": false
},
"threaddump": {=> 트러블 슈팅과 분석을 위해 쓰레 덤프 시작
"href": "<http://localhost:8080/actuator/threaddump>",
"templated": false
},
"metrics-requiredMetricName": {
"href": "<http://localhost:8080/actuator/metrics/{requiredMetricName}>",
"templated": true
},
"metrics": { => 애플리케이션에서 현재 캡처 중인 메트릭스
"href": "<http://localhost:8080/actuator/metrics>",
"templated": false
},
"scheduledtasks": {
"href": "<http://localhost:8080/actuator/scheduledtasks>",
"templated": false
},
"mappings": { => 모든 엔드포인트 매핑과 세부 지원 정보
"href": "<http://localhost:8080/actuator/mappings>",
"templated": false
}
}
}
health check 를 위해 프로퍼티에 다음 항목을 추가 후 재실행
management.endpoint.health.show-details=always
액추에이터로 health 엔드 포인트를 조회해보면
GET <http://localhost:8080/actuator/health>
HTTP/1.1 200
Content-Type: application/vnd.spring-boot.actuator.v3+json
Transfer-Encoding: chunked
Date: Tue, 20 Feb 2024 11:19:04 GMT
Keep-Alive: timeout=60
Connection: keep-alive
{
"status": "UP",
"components": {
"db": {
"status": "UP",
"details": {
"database": "H2",
"validationQuery": "isValid()"
}
},
"diskSpace": {
"status": "UP",
"details": {
"total": 511987150848,
"free": 388745297920,
"threshold": 10485760,
"path": "\\\\IdeaProjects\\\\SpringBootUpAndRunning-Spring-Boot-3\\\\java\\\\sbur-rest-demo\\\\.",
"exists": true
}
},
"ping": {
"status": "UP"
}
}
}
코드 뿐만 아니라 명령줄 인수등으로 값이 오버라이딩 될 수 있는데
액추에이터를 사용하면 데이터 기반으로 오류를 잡아내기 훨씬 간단해진다.
액추에이터는 실행 중인 스프링 부트 로깅 수준을 변경하는 것도 가능
기본값으로는 info 를 하고 있다가 문제 발생시 로깅 레벨을 Trace 로 올리는 것이 가능
5.4 마치며
- 애플리케이션을 동적으로 설정 및 재설정
- 현재 설정과 해당 출처를 결정/확인
- 애플리케이션 환경과 health 지표 검사, 모니터링
- 실시간으로 애플리케이션 로깅 수준을 일시적으로 조정해 근본원인 식별
'도서 > 프로그래밍' 카테고리의 다른 글
데이터베이스 액세스 - 처음부터 제대로 배우는 스프링 부트 [03] (0) | 2024.01.31 |
---|---|
첫 번째 REST API - 처음부터 제대로 배우는 스프링 부트 [02] (0) | 2024.01.23 |
스프링 부트 - 처음부터 제대로 배우는 스프링 부트 [01] (0) | 2024.01.22 |
[09][完] 쉽게 배우는 JSP 웹 프로그래밍 (0) | 2024.01.22 |
[08] 쉽게 배우는 JSP 웹 프로그래밍 (1) | 2024.01.21 |