티스토리 뷰
개발자가 애플리케이션을 개발할 때 기능 요구사항만 개발하는 것은 아니다. 서비스를 실제 운영 단계에 올리게 되면 개발자들이 해야하는 또 다른 중요한 업무가 있다. 바로 서비스에 문제가 없는지 모니터링하고 지표들을 심어서 감시하는 활동들이다.
운영 환경에서 서비스할 때 필요한 이런 기능들을 프로덕션 준비 기능이라 한다. 쉽게 이야기해서 프로덕션을 운영에 배포할 때 준비해야 하는 비 기능적 요소들을 뜻한다.
- 지표(metric), 추적(trace), 감사(auditing)
- 모니터링
좀 더 구체적으로 설명하자면, 애플리케이션이 현재 살아있는지, 로그 정보는 정상 설정 되었는지, 커넥션 풀은 얼마나 사용되고 있는지 등을 확인할 수 있어야 한다.
스프링 부트가 제공하는 액추에이터는 이런 프로덕션 준비 기능을 매우 편리하게 사용할 수 있는 다양한 편의 기능들을 제공한다. 더 나아가서 마이크로미터, 프로메테우스, 그라파나 같은 최근 유행하는 모니터링 시스템과 매우 쉽게 연동할 수 있는 기능도 제공한다.
액츄에이터
액츄에이터가 제공하는 프로덕션 준비 기능을 사용하려면 스프링 부트 액츄에이터 라이브러리를 추가해야 한다.
implementation 'org.springframework.boot:spring-boot-starter-actuator' // actuator 추가
기본 메인 클래스를 실행하고, http://localhost:8080/actuator
로 접속하면 아래와 같은 데이터를 확인할 수 있다.
localhost:8080/actuator 접속 결과
{
"_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
}
}
}
- 액츄에이터는
/actuator
경로를 통해서 기능을 제공한다.
http://localhost:8080/actuator/health
URL로 접속하면, 현재 서버가 잘 동작하고 있는지 애플리케이션의 헬스 상태가 나타낸다.
localhost:8080/actuator/health 접속 결과
{
"status": "UP"
}
지금 눈에 보이는 기능은 헬스 상태를 확인할 수 있는 기능 뿐이다. 액츄에이터는 헬스 상태 뿐만 아니라 수 많은 기능을 제공하는데, 이런 기능이 웹 환경에서 보이도록 하기 위해 application.yml
에 설정 정보를 작성해야 한다.
application.yml
management:
endpoints:
web:
exposure:
include: "*"
application.yml 설정 후, localhost:8080/actuator 접속 결과
{
"_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-path": {
"href": "http://localhost:8080/actuator/health/{*path}",
"templated": true
},
"health": {
"href": "http://localhost:8080/actuator/health",
"templated": false
},
"info": {
"href": "http://localhost:8080/actuator/info",
"templated": false
},
"conditions": {
"href": "http://localhost:8080/actuator/conditions",
"templated": false
},
"configprops-prefix": {
"href": "http://localhost:8080/actuator/configprops/{prefix}",
"templated": true
},
"configprops": {
"href": "http://localhost:8080/actuator/configprops",
"templated": false
},
"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": {
"href": "http://localhost:8080/actuator/metrics",
"templated": false
},
"metrics-requiredMetricName": {
"href": "http://localhost:8080/actuator/metrics/{requiredMetricName}",
"templated": true
},
"scheduledtasks": {
"href": "http://localhost:8080/actuator/scheduledtasks",
"templated": false
},
"mappings": {
"href": "http://localhost:8080/actuator/mappings",
"templated": false
}
}
}
- 액츄에이터가 제공하는 수 많은 기능을 확인할 수 있다.
- 액츄에이터가 제공하는 기능 하나하나를 엔드포인트라 한다.
health
는 헬스 정보를,beans
는 스프링 컨테이너에 등록된 빈을 보여준다.
- 각각의 엔드포인트는
/actuator/{엔드포인트명}
과 같은 형식으로 접근할 수 있다.http://localhost:8080/actuator/health
: 애플리케이션 헬스 정보를 보여준다.http://localhost:8080/actuator/beans
: 스프링 컨테이너에 등록된 빈을 보여준다.
엔드포인트 설정
엔드포인트를 사용하려면 다음 2가지 과정이 모두 필요하다.
- 엔드포인트 활성화
- 엔드포인트 노출
엔드포인트를 활성화 한다는 것은 해당 기능 자체를 사용할지 말지 on
, off
를 선택하는 것이다. 엔드포인트를 노출하는 것은 활성화된 엔드포인트를 HTTP에 노출할지 아니면 JMX에 노출할지 선택하는 것이다.
엔드포인트를 활성화하고 추가로 HTTP를 통해서 웹에 노출할지, 아니면 JMX를 통해서 노출할지 두 위치에 모두 노출할지 노출 위치를 지정해주어야 한다. 물론 활성화가 되어있지 않으면 노출도 되지 않는다.
그런데 엔드포인트는 대부분 기본으로 활성화(shutdown
제외) 되어 있는데, 노출이 되어 있지 않을 뿐이다. 따라서 어떤 엔드포인트를 노출할지 선택하면 된다. 참고로 HTTP와 JMX를 선택할 수 있는데, 보통 JMX는 잘 사용하지 않으므로 HTTP에 어떤 엔드포인트를 노출할지 선택하면 된다.
application.yml - 모든 엔드포인트를 웹에 노출
management:
endpoints:
web:
exposure:
include: "*"
"*"
옵션은 모든 엔드포인트를 웹에 노출하는 것이다.shutdown
엔드포인트는 기본으로 활성화 되지 않기 때문에 노출도 되지 않는다.- 엔드포인트 활성화 + 엔드포인트 노출이 둘다 적용되어야 사용할 수 있다.
application.yml - shutdown 엔드포인트 활성화
management:
endpoint:
shutdown:
enabled: true
endpoints:
web:
exposure:
include: "*"
- 특정 엔드포인트를 활성화 하려면
management.endpoint.{엔드포인트명}.enabled=true
를 적용하면 된다. - 기본으로 비활성화 되어 있고, 꼭 필요한 경우에만 사용하는 설정이다.
POST 요청이기 때문에 Postman을 이용해서 http://localhost:8080/actuator/shutdown
를 호출하면 실제 서버가 종료되는 것을 확인할 수 있다.


엔드 포인트 노출 제외
management:
endpoints:
web:
exposure:
include: "*"
exclude: "env,beans"
web
에 모든 엔드포인트를 노출하지만env, beans
는 제외한다.
다양한 엔드포인트
각각의 엔드포인트를 통해서 개발자는 애플리케이션 내부의 수 많은 기능을 관리하고 모니터링 할 수 있다. 다음은 자주 사용하는 기능 위주로 정리한 목록이다.
beans
: 스프링 컨테이너에 등록된 스프링 빈을 보여준다.conditions
:condition
을 통해서 빈을 등록할 때 평가 조건과 일치하거나 일치하지 않는 이유를 표시한다.configprops
:@ConfigurationProperties
를 보여준다.env
:Environment
정보를 보여준다.health
: 애플리케이션 헬스 정보를 보여준다.httpexchanges
: HTTP 호출 응답 정보를 보여준다.HttpExchangeRepository
를 구현한 빈을 별도로 등록해야 한다.info
: 애플리케이션 정보를 보여준다.loggers
: 애플리케이션 로거 설정을 보여주고 변경도 할 수 있다.metrics
: 애플리케이션의 메트릭 정보를 보여준다.mappings
:@RequestMapping
정보를 보여준다.threaddump
: 쓰레드 덤프를 실행해서 보여준다.shutdown
: 애플리케이션을 종료한다. 이 기능은 기본으로 비활성화 되어 있다.
헬스 정보
헬스 정보는 단순히 애플리케이션이 요청에 응답을 할 수 있는지 판단하는 것을 넘어서 애플리케이션이 사용하는 데이터베이스가 응답하는지, 디스크 사용량에는 문제가 없는지 같은 다양한 정보들을 포함해서 만들어진다.
헬스 정보를 더 자세히 보려면 아래 옵션을 지정하면 된다.
management:
endpoint:
health:
show-details: always
localhost:8080/actuator/health 접속 결과
{
"status": "UP",
"components": {
"db": {
"status": "UP",
"details": {
"database": "H2",
"validationQuery": "isValid()"
}
},
"diskSpace": {
"status": "UP",
"details": {
"total": 499963174912,
"free": 332786487296,
"threshold": 10485760,
"path": "/Users/seonghyun/Downloads/boot-source-20230228/start/actuator/.",
"exists": true
}
},
"ping": {
"status": "UP"
}
}
}
- 각각의 항목이 아주 자세하게 노출되는 것을 확인할 수 있다.
components.db.details.validationQuery
: DB가 현재 살아 있는지 확인하는 쿼리(JDBC 스펙)이다.
좀 더 간편하게 확인하고 싶다면, 다음 옵션을 사용하면 된다.
management:
endpoint:
health:
show-components: always
localhost:8080/actuator/health 접속 결과
{
"status": "UP",
"components": {
"db": {
"status": "UP"
},
"diskSpace": {
"status": "UP"
},
"ping": {
"status": "UP"
}
}
}
- 각 헬스 컴포넌트의 상태 정보만 간략하게 노출한다.
헬스 이상 상태
헬스 컴포넌트 중에 하나라도 문제가 있으면 전체 상태는 DOWN
이 된다.
{
"status": "DOWN",
"components": {
"db": {
"status": "DOWN"
},
"diskSpace": {
"status": "UP"
},
"ping": {
"status": "UP"
}
}
}
- 하나라도 문제가 있으면
DOWN
으로 보기 때문에 이 경우 전체 상태의status
도DOWN
이 된다.
애플리케이션 정보
info
엔드포인트는 애플리케이션의 기본 정보를 노출한다.
java
: 자바 런타임 정보os
: OS 정보env
:Environment
에서info.
로 시작하는 정보build
: 빌드 정보,META-INF/build-info.properties
파일이 필요하다.git
:git
정보,git.properties
파일이 필요하다.
env
, java
, os
는 기본으로 비활성화 되어 있다.
application.yml에 JAVA, OS 정보를 확인하는 내용 추가
management:
info:
java:
enabled: true
os:
enabled: true
localhost:8080/actuator/info 접속 결과
{
"java": {
"version": "17.0.5",
"vendor": {
"name": "Eclipse Adoptium",
"version": "Temurin-17.0.5+8"
},
"runtime": {
"name": "OpenJDK Runtime Environment",
"version": "17.0.5+8"
},
"jvm": {
"name": "OpenJDK 64-Bit Server VM",
"vendor": "Eclipse Adoptium",
"version": "17.0.5+8"
}
},
"os": {
"name": "Mac OS X",
"version": "13.2.1",
"arch": "x86_64"
}
}
java
,os
관련 정보를 확인할 수 있다.
빌드 정보를 노출하려면 빌드 시점에 META-INF/build-info.properties
파일을 만들어야 한다. 때문에 gradle
에 다음 내용을 추가해야 한다.
springBoot {
buildInfo()
}
추가 후, 빌드를 해보면 build
폴더안에 resources/main/META-INF/build-info.properties
파일을 확인할 수 있다.
build.artifact=actuator
build.group=com.hyuuny
build.name=actuator
build.time=2023-04-10T07\:02\:35.151253Z
build.version=0.0.1-SNAPSHOT
build
는 기본으로 활성화 되어 있기 때문에 이 파일만 있으면 바로 확인할 수 있다.
localhost:8080/actuator/info 접속 결과
"build": {
"artifact": "actuator",
"name": "actuator",
"time": "2023-04-10T07:02:35.151Z",
"version": "0.0.1-SNAPSHOT",
"group": "hello"
}
- 접속 결과를 통해서 애플리케이션의 기본 정보와 버전, 빌드된 시간을 확인할 수 있다.
로거
loggers
엔드포인트를 사용하면 로깅과 관련된 정보를 확인하고, 또 실시간으로 변경할 수도 있다.
LogController
@Slf4j
@RestController
public class LogController {
@GetMapping("/log")
public String log() {
log.trace("trace log");
log.debug("debug log");
log.info("info log");
log.warn("warn log");
log.error("error log");
return "ok";
}
}
- 여러 레벨을 로그를 남기는 단순한 컨트롤러이다.
application.yml 설정
logging:
level:
hello.controller: debug
hello.controller
패키지와 그 하위는debug
레벨을 출력하도록 했다.- 이제
LogController
클래스도debug
레벨의 영향을 받는다.
localhost:8080/log 접속 결과

- 접속 결과를 보면 기대한 것 처럼
DEBUG
레벨 까지 출력되는 것을 확인할 수 있다.
localhost:8080/actuator/loggers 접속 결과
"levels": [
"OFF",
"ERROR",
"WARN",
"INFO",
"DEBUG",
"TRACE"
],
"loggers": {
"ROOT": {
"configuredLevel": "INFO",
"effectiveLevel": "INFO"
},
"SQL dialect": {
"effectiveLevel": "INFO"
},
"_org": {
"effectiveLevel": "INFO"
},
"_org.springframework": {
"effectiveLevel": "INFO"
},
"hello": {
"effectiveLevel": "INFO"
},
"hello.ActuatorApplication": {
"effectiveLevel": "INFO"
},
"hello.controller": {
"configuredLevel": "DEBUG",
"effectiveLevel": "DEBUG"
},
"hello.controller.LogController": {
"effectiveLevel": "DEBUG"
},
}
}
- 로그를 별도로 설정하지 않으면 스프링 부트는 기본으로
INFO
를 사용한다. 접속 결과를 보면ROOT
의configuredLevel
가INFO
인 것을 확인할 수 있다. 따라서 그 하위도 모두INFO
레벨이 적용된다. - 앞서
hello.controller
를DEBUG
로 설정했다. 그래서 해당 부분에서configuredLevel
이DEBUG
로 설정된 것을 확인할 수 있다. 그리고 그 하위도DEBUG
레벨이 적용된다.
http://localhost:8080/actuator/loggers/{로거이름}
와 같은 패턴을 사용해서 특정 로거 이름을 기준으로 조회할 수 있다.
localhost:8080/actuator/loggers/hello.controller 접속 결과
{
"configuredLevel": "DEBUG",
"effectiveLevel": "DEBUG"
}
액츄에이터와 보안
액츄에이터가 제공하는 기능들은 우리 애플리케이션의 내부 정보를 너무 많이 노출한다. 그래서 외부 인터넷 망이 공개된 곳에 액츄에이터의 엔드포인트를 공개하는 것은 보안상 좋은 방안이 아니다. 액츄에이터의 엔드포인트들은 외부 인터넷에서 접근이 불가능하게 막고, 내부에서만 접근 가능한 내부망을 사용하는 것이 안전하다.
예를 들어서 외부 인터넷 망을 통해서 8080 포트에만 접근할 수 있고, 다른 포트는 내부망에서만 접근할 수 있다면 액츄에이터에 다른 포트를 설정하면 된다. 액츄에이터의 기능을 애플리케이션 서버와는 다른 포트에서 실행하려면 다음과 같이 설정하면 된다. 이 경우 기존 8080 포트에서는 액츄에이터를 접근할 수 없다
application.yml 설정
management:
server:
port: 9292
localhost:9292/actuator
로 접근해야 한다.
엔드포인트의 기본 경로를 변경하려면 다음과 같이 설정하면 된다.
application.yml 설정
management:
endpoints:
web:
exposure:
include: "*"
base-path: "/hyuuny"
/actuator/{엔드포인트}
대신에/hyuuny/{엔드포인트}
로 변경된다.
Reference
김영한. 스프링 부트 - 핵심 원리와 활용. 인프런.
'Spring' 카테고리의 다른 글
[Spring] 프로메테우스 (prometheus) (0) | 2023.04.14 |
---|---|
[Spring] 메트릭 (metric) (0) | 2023.04.13 |
[Spring] YAML , @Profile (0) | 2023.04.09 |
[Spring] 외부 설정 방법 (0) | 2023.04.06 |
[Spring] 외부설정과 프로필 2 (0) | 2023.04.03 |
- Total
- Today
- Yesterday
- 인프런
- 알고리즘
- 코틀린
- 그리디
- 스프링 부트
- 데이터베이스
- Spring
- 코테
- 파이썬
- 북클럽
- 노마드
- kotlin
- 백준
- Algorithm
- 김영한
- mysql 8.0
- 스프링
- 릿코드
- 정렬
- 리팩토링
- 구현
- 자료구조
- Real MySQL
- leetcode
- webflux
- spring boot
- 문자열
- 노마드코더
- MySQL
- 스프링부트
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |