일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- 스프링 mvc2 - 로그인 처리
- 자바의 정석 기초편 ch7
- 게시글 목록 api
- 타임리프 - 기본기능
- 스프링 입문(무료)
- 2024 정보처리기사 수제비 실기
- 자바의 정석 기초편 ch14
- 스프링 mvc1 - 서블릿
- 스프링 db1 - 스프링과 문제 해결
- 자바의 정석 기초편 ch1
- 스프링 db2 - 데이터 접근 기술
- 자바의 정석 기초편 ch12
- 스프링 고급 - 스프링 aop
- 자바의 정석 기초편 ch5
- 2024 정보처리기사 시나공 필기
- 코드로 시작하는 자바 첫걸음
- 자바의 정석 기초편 ch4
- jpa 활용2 - api 개발 고급
- 자바의 정석 기초편 ch8
- 스프링 mvc2 - 타임리프
- 자바의 정석 기초편 ch9
- 자바의 정석 기초편 ch11
- 스프링 mvc1 - 스프링 mvc
- 자바의 정석 기초편 ch6
- jpa - 객체지향 쿼리 언어
- 자바의 정석 기초편 ch13
- 자바의 정석 기초편 ch2
- 스프링 mvc2 - 검증
- @Aspect
- 자바의 정석 기초편 ch3
- Today
- Total
나구리의 개발공부기록
액츄에이터, 프로덕션 준비 기능이란?, 프로젝트 설정 및 액츄에이터 시작, 엔드 포인트 설정, 다양한 엔드포인트, 헬스 정보, 애플리케이션 정보, 로거, HTTP 요청 응답 기록, 액츄에이터와 보안 본문
액츄에이터, 프로덕션 준비 기능이란?, 프로젝트 설정 및 액츄에이터 시작, 엔드 포인트 설정, 다양한 엔드포인트, 헬스 정보, 애플리케이션 정보, 로거, HTTP 요청 응답 기록, 액츄에이터와 보안
소소한나구리 2024. 12. 6. 18:12출처 : 인프런 - 스프링 부트 - 핵심 원리와 활용(유료) / 김영한님
유료 강의이므로 정리에 초점을 두고 코드는 일부만 인용
1. 프로덕션 준비 기능이란?
1) 모니터링의 중요성
- 서비스를 운영할 때에는 장애는 언제든지 발생할 수 있기 때문에, 이에 빠르게 대응하기 위해서 모니터링(경계)을 잘 하는 것이 중요함
- 개발자가 애플리케이션을 개발할 때 기능 요구사항만 개발하는 것이 아니라 서비스를 실제 운영 단계에 올리게 되면 또 다른 중요한 업무가 있는데 바로 서비스에 문제가 없는지 모니터링하고 지표들을 심어서 감시하는 것임
- 이러한 비 기능적인 요구사항은 기획자나 고객의 요청사항으로 요구사항이 반영되지 않기 때문에 프로젝트 일정을 짜야할 때 이런 숨겨진 작업까지 고려해서 프로젝트 일정을 짜야함
- 운영 환경에서 서비스를 할 때 필요한 이런 기능들을 프로덕션 준비 기능이라함
- 즉 프로덕션을 운영에 배포할 때 준비해야 하는 비 기능적인 요소들을 뜻하며 지표(metric), 추적(trace), 감사(auditing), 모니터링 등이 있음
- 구체적으로는 애플리케이션이 현재 살아있는지, 로그 정보는 정상 설정 되었는지, 커넥션 풀은 얼마나 사용되고 있는지 등등을 확인할 수 있어야 함
- 스프링 부트가 제공하는 액추에이터는 이런 프로덕션 준비 기능을 매우 편리하게 사용할 수 있는 다양한 편의기능을 제공함
- 더 나가가서 마이크로미터, 프로메테우스, 그라파나 같은 최근 유행하는 모니터링 시스템과 매우 쉽게 연동할 수 있는 기능도 제공함
** 참고
- 액추에이터는 시스템을 움직이거나 제어하는데 쓰이는 기계 장치라는 뜻
2. 프로젝트 설정 및 액츄에이터 시작
1) 프로젝트 설정
(1) 프로젝트 설정 - build.gradle
- 제공된 프로젝트를 사용
- 스프링 부트로 제공된 프로젝트
- 사용된 라이브러리: Spring Boot Actuator, Spring web, Spring Data JPA, H2 Database, Lombok
- 테스트 코드에서 lombok을 사용할 수 있도록 설정을 추가
plugins {
id 'java'
id 'org.springframework.boot' version '3.0.2'
id 'io.spring.dependency-management' version '1.1.0'
}
group = 'hello'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator' //actuator 추가
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
//test lombok 사용
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
}
tasks.named('test') {
useJUnitPlatform()
}
2) 액츄에이터 시작
(1) 동작 확인
- 프로젝트 설정 시 액츄에이터 라이브러리를 추가 했으므로 애플리케이션 실행 후 localhost:8080/actuator로 접속하면 동작을 확인할 수 있음
- 포스트 맨으로 실행해도 결과를 확인할 수 있음
- health 결과를 제공하는 URL(localhost:8080/actuator/health)를 실행해보면 현재 서버가 잘 동작하고 있는지 애플리케이션의 헬스 상태를 나타냄
- 지금 눈에 보이는 기능은 헬스 상태를 확인할 수 있는 기능 뿐이며 액츄에이터는 헬스 상태 뿐만 아니라 수 많은 기능을 제공하는데 이런 기능이 웹 환경에서 보이도록 노출해야함
(2) application.yml 추가
- application.properties를 사용해도 되지만 실무에서 더 자주 사용하는 application.yml을 사용
- 액츄에이터 기능을 웹에 노출하도록 설정 추가
management:
endpoints:
web:
exposure:
include: "*"
(3) 동작 확인
- 실행해보면 액츄에이터가 제공하는 수 많은 기능을 확인할 수 있음 (너무 많아서 결과 생략)
- 액츄에이터가 제공하는 기능 하나하나를 엔드포인트라 하며 각각의 엔드포인트는 /actuator/{엔드포인트명}과 같은 형식으로 접근할 수 있음
- localhost:8080/actuator/health: 애플리케이션 헬스 정보
- localhost:8080/actuator/beans: 스프링 컨테이너에 등록된 빈 정보
3. 엔드 포인트 설정
1) 엔드 포인트 설정
(1) 엔드포인트를 사용하기 위한 과정
- 엔드포인트를 사용하려면 엔드포인트를 활성화하고 엔드포인트를 노출 하는 2가지 과정이 필요함
- 엔드포인트를 활성화 한다는 것은 해당 기능 자체를 사용할지 말지 on, off를 선택하는 것
- 엔드포인트를 노출하는 것은 활성화된 엔드포인트를 HTTP에 노출할지 아니면 JMX에 노출할지 선택하는 것임
- 즉 엔드포인트를 활성화하고 추가로 HTTP를 통해서 웹에 노출할지, JMX를 통해서 노출할지 두 위치에 모두 노출할지에 대해 노출 위치를 지정해 주어야 하며 활성화가 되어있지 않으면 노출도 되지 않음
- 대부분의 엔드포인트는 기본으로 활성화가 되어있으며 노출이 되어있지 않을 뿐임(shutdown 제외, 해당 엔드포인트를 호출하면 서버가 내려가버림)
- 따라서 어떤 엔드포인트를 노출할지 선택하기만 하면 되며 보통 JMX는 잘 사용하지 않으므로 HTTP에 어떤 엔드포인트를 노출할지 선택하면 됨
- 2강에서 application.yml에 입력한 설정이 모든 엔드포인트를 웹에 노출한 설정이였으며, 엔드포인트 활성화 + 엔드포인트 노출이 둘다 적용되어야 사용할 수 있음
(2) application.yml - shutdown 엔드포인트 활성화
- 특정 엔드포인트를 활성화 하려면 management.endpoint.{엔드포인트명}.enabled=true를 적용하면 됨
- 애플리케이션을 실행해보면 기존에는 없던 shutdown 엔드 포인트가 노출되어있는 것을 확인할 수 있음
- HTTP GET으로 호출하면 동작하지 않으므로 Postman 등을 활용해서 POST로 localhost:8080/actuator/shutdown을 호출하면 메시지와 함께 실제 서버가 종료되는 것을 확인할 수 있음
- 물론 이 기능은 매우 주의해서 사용해야 하며 그렇기 때문에 기본으로 비활성화 되어 있음
management:
endpoint:
shutdown:
enabled: true
endpoints:
web:
exposure:
include: "*"
(3) 엔드포인트 노출
- 스프링 공식 매뉴얼이 제공하는 엔드포인트 노출 설정 예제
- jmx에 health, info를 노출
- web에 모든 엔드포인트를 노출하지만 env, beans는 제외
management:
endpoints:
jmx:
exposure:
include: "health,info"
---
management:
endpoints:
web:
exposure:
include: "*"
exclude: "env,beans"
4. 다양한 엔드포인트
1) 다양한 엔드 포인트
- 각각의 엔드포인트를 통해서 개발자는 애플리케이션 내부의 수 많은 기능을 관리하고 모니터링 할 수 있음
- 스프링 부트의 actuator를 사용하는 것만으로도 이룬 수많은 기능이 제공되는 것이 개발자 입장에서는 매우 편리함
(1) 자주 사용하는 엔드포인트 목록
- beans: 스프링 컨테이너에 등록된 스프링 빈을 보여줌
- conditions: condition을 통해서 빈을 등록할 때 평가 조건과 일치하거나 일치하지 않는 이유를 표시함
- configprops: @ConfigurationProperties를 보여줌
- env: Environment 정보를 보여줌
- health: 애플리케이션 헬스 정보를 보여줌
- httpexchanges: HTTP 호출 응답 정보를 보여줌, HttpExchangeRepository를 구현한 빈을 별도로 등록해야 함
- info: 애플리케이션 정보를 보여줌
- loggers: 애플리케이션 로거 설정을 보여주고 변경할 수 있음
- metrics: 애플리케이션의 메트릭 정보를 보여줌
- mappings: @RequestMapping 정보를 보여줌
- threaddump: 쓰레드 덤프를 실행해서 보여줌
- shutdown: 애플리케이션을 종료함, 기본적으로 비활성화 되어있음
- 전체 엔드포인트 공식 매뉴얼
5. 헬스 정보
1) 헬스 엔드포인트
- 애플리케이션에 문제가 발생했을 때 문제를 빠르게 인지할 수 있음
(1) 기본 동작
- 헬스 정보는 단순히 애플리케이션이 요청에 응답할 수 있는지 판단하는 것을 넘어서 애플리케이션이 사용하는 데이터베이스가 응답하는지, 디스크 사용량에는 문제가 없는지와 같은 다양한 정보들을 포함해서 만들어짐
(2) application.yml - show-details 옵션
- management.endpoint.health.show-details=always를 application설정에 적용하면 헬스 정보를 더 자세히 볼 수 있음
- 해당 옵션을 적용하면 각각의 항목이 매우 자세하게 노출됨
management:
endpoint:
health:
show-details: always
(3) application.yml - show-components 옵션
- 너무 자세하게 노출되는 것이 부담스럽다면 show-components=always로 해당 옵션을 사용하면 됨
- 각 헬스 컴포넌트의 상태 정보만 간략하게 노출함
- 헬스 컴포넌트 중에 하나라도 문제가 생기면 전체 상태를 표시하는 status도 DOWN으로 표시가 됨
** 참고
- 액츄에이터는 db, mongo, redis, diskspace, ping과 같은 수 많은 헬스 기능을 기본으로 제공함
- 공식 매뉴얼
- 원하는 경우 직접 헬스 기능을 구현해서 추가할 수 있으나 직접 구현하는 일은 많지 않기 때문에 필요한 경우만 아래의 매뉴얼을 참고해서 구현하면 됨
- 직접 구현 매뉴얼
6. 애플리케이션 정보
1) Info 엔드포인트
- 애플리케이션의 기본 정보를 노출
(1) 기본으로 제공하는 기능들
- java: 자바 런타임 정보
- os: OS 정보
- env: Environment에서 info.로 시작하는 정보
- build: 빌드 정보, META-INF/build-info.properties파일이 필요함
- git: git정보, git.properties파일이 필요함
- env, java, os는 기본으로 비활성화 되어 있음
(2) application.yml - java, os
- management.info.<id>.enabled의 값을 true로 지정하면 활성화가 됨
- info는 특이하게 management.endpoint하위가 아니라 management 바로 다음에 info가 나오는것에 주의해야함
- 실행 후 엔드포인트에 접속해보면 java와 os의 정보가 노출되는 것을 확인할 수 있음
management:
info:
java:
enabled: true
os:
enabled: true
(3) application.yml - env
- Environment에서 info.로 시작하는 정보를 출력
- management.info.env.enabled: true를 추가하고 info정보를 추가한뒤 엔드포인트에 접속해보면 입력해둔 info 환경변수 정보들이 노출되는 것을 확인할 수 있음
management:
info:
env:
enabled: true
info:
app:
name: hello-actuator
company: guri
(4) build.gradle - build
- 빌드 정보를 노출하려면 빌드 시점에 META-INF/build-info.properties파일을 만들어야함
- gradle에 아래의 내용을 추가하고 빌드를 해보면 build 폴더안에 resources/main/META-INF/build-info.properties파일을 확인할 수 있음
- 파일 내용을 보면 애플리케이션의 기본 정보와 버전, 빌드 시간을 확인할 수 있음
- 엔드포인트에 접속해보면 파일의 정보처럼 build정보가 노출되는 것을 확인할 수 있음
// build.gradle에 추가
springBoot {
buildInfo()
}
// 생성된 build-info.properties 파일 내용
build.artifact=actuator
build.group=hello
build.name=actuator
build.time=2024-12-06T07\:33\:54.258335Z
build.version=0.0.1-SNAPSHOT
(5-1) build.gradle - git
- build와 유사하게 빌드 시점에 사용한 git 정보도 노출할 수 있으며 git정보도 노출하려면 git.properties 파일이 필요함
- 물론 프로젝트가 git으로 관리 되어있어야 하며 그렇지 않으면 빌드시 오류가 발생함
- build.gradle의 plugins에 아래처럼 입력하여 플러그인을 추가 후 커밋을 실행
- 빌드를 해보면 build 폴더안에 resources/main/git.properties파일을 확인할 수 있음
- 엔드포인트에 접속해보면 git의 branch와 commit 정보가 노출되는 것을 확인할 수 있음
- 애플리케이션을 배포할 때 다른 커밋이나 다른 브랜치의 내용이 배포된 경우가 되어기대와 전혀 다르게 동작할 때가 있는데 이럴때 큰 도움이 됨
// build.gradle의 plugins에 git 추가
plugins {
// ... 기존 설정 생략
id "com.gorylenko.gradle-git-properties" version "2.4.1" //git info
}
// 생성된 git.properties
git.branch=main
git.build.host=namo.local
git.build.user.email=hayani0000@gmail.com
git.build.user.name=nagul2
git.build.version=0.0.1-SNAPSHOT
git.closest.tag.commit.count=
git.closest.tag.name=
git.commit.id=92413f9a7dfbabfb1cfed96f966240556f3522a4
git.commit.id.abbrev=92413f9
git.commit.id.describe=
git.commit.message.full=start\n
git.commit.message.short=start
git.commit.time=2024-12-06T16\:40\:56+0900
git.commit.user.email=hayani0000@gmail.com
git.commit.user.name=nagul2
git.dirty=true
git.remote.origin.url=
git.tags=
git.total.commit.count=1
(5-2) application.yml - git
- git에 대한 자세한 정보를 노출하고 싶다면 application.yml에 옵션을 적용하면 됨
management:
info:
git:
mode: full
** 참고
- info의 사용자 정의 기능을 추가하고 싶으면 공식 매뉴얼을 참고하면 됨, 그러나 적용할 일은 많지 않음
- 매뉴얼
7. 로거
1) Loggers 엔드포인트
- 로깅과 관련된 정보를 확인하고 로깅 레벨을 실시간으로 변경할 수 있음
(1) LogController
- controller 패키지를 생성 후 작성
- 여러 레벨의 로그를 남기는 단순한 컨트롤러
package hello.controller;
@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";
}
}
(2) application.yml 설정 및 실행
- 로그 레벨을 hello.controller 패키지와 그 하위는 DEBUG 레벨로 출력하도록 설정하여 LogController 클래스가 DEBUG 레벨의 영향을 받도록 설정
- 애플리케이션을 실행 후 localhost:8080/log에 접속해보면 로그가 DEBUG 부터 error까지 출력되는 것을 확인할 수 있음
logging:
level:
hello.controller: debug
(3) loggers 엔드포인트 호출
- localhost:8080/actuator/loggers로 접속하여 엔드포인트를 호출
- 로그를 별도로 설정하지 않으면 스프링 부트는 기본으로 로그레벨을 INFO를 사용하여 실행 결과를 보면 ROOT의 configuredLevel이 INFO인 것을 확인할 수 있음
- application.yml 설정으로 hello.controller는 DEBUG로 설정했는데, 해당 부분의 결과를 보면 configuredLevel이 DEBUG로 설정 되었으며 그 하위인 LogController도 당연히 DEBUG 레벨이 적용된 것을 확인할 수 있음
(4) 더 자세히 조회하기
- 아래와 같은 패턴을 사용해서 특정 로거 이름을 기준으로 조회할 수 있음
- localhost:8080/actuator/loggers/{로거이름}
2) 실시간 로그 레벨 변경
(1) 실시간 로그 레벨 변경 상황 예시
- 로컬 PC는 로그 레벨을 TRACE나 DEBUG로 사용하고 개발 서버는 보통 DEBUG로 사용함
- 운영 서버는 요청이 매우 많아 로그도 많이 남기 때문에 DEBUG 로그까지 출력하게되면 성능이나 디스크에 영향을 주게되어 INFO 로그 레벨을 주로 사용함
- 그러나 운영중에 문제가 있어서 급하게 DEBUG나 TRACE로 로그를 남겨서 확인해야 하고 싶은 상황이 발생했다면 일반적으로는 로깅 설정을 변경하고 서버를 다시 시작해야함
- loggers 엔드포인트를 사용하면 애플리케이션을 다시 시작하지 않고 실시간으로 로그 레벨을 변경할 수 있음
(2) Postman - POST 요청
- 꼭 POST를 사용해야함
- 아래처럼 JSON으로 로그 레벨을 변경하고자할 엔드포인트의 URL로 POST 요청을 보내면 204 응답이 옴(별도의 응답 메시지는 없음)
- 변경 후 다시 GET으로 엔드포인트를 호출해보면 지정한 위치와 그 하위위치의 로그 레벨이 TRACE로 변경된 것을 확인할 수 있음
- localhost:8080/log로 접속하여 출력된 로그 결과를 봐도 trace 로그가 출력되어 로그레벨이 변경된 것을 확인할 수 있음
- 물론 서버를 껏다 키면 application.yml에 설정된 값으로 로그 레벨이 적용됨
{
"configuredLevel" : "TRACE",
}
8. HTTP 요청 응답 기록
1) httpexchanges
(1) 활성화
- HTTP요청과 응답의 과거 기록을 확인하고자 할때 해당 엔드포인트를 사용하면 됨
- HttpExchangeRepository 인터페이스의 구현체를 빈으로 등록하면 httpexchanges 엔드포인트를 사용할 수 있으며 해당 빈을 등록하지 않으면 활성화되지 않음
- 스프링 부트는 기본으로 InMemoryHttpExchangeRepository 구현체를 제공함
(2) ActuatorApplication - InMemoryHttpExchangeRepository 추가
- InMemoryHttpExchangeRepository는 최대 100개의 HTTP 요청을 제공하며 최대 요청이 넘어가면 과거 요청을 삭제함
- setCapacity()로 최대 요청수를 변경할 수 있음
- 구현체를 빈으로 등록하고 애플리케이션을 실행 후 엔드포인트를 호출해보면 지금까지 실행한 HTTP 요청과 응답 정보를 확인할 수 있음
package hello;
@SpringBootApplication
public class ActuatorApplication {
public static void main(String[] args) {
SpringApplication.run(ActuatorApplication.class, args);
}
@Bean
public InMemoryHttpExchangeRepository httpExchangeRepository() {
return new InMemoryHttpExchangeRepository();
}
}
** 참고
- 이 기능은 매우 단순하고 기능에 제한이 많기 때문에 개발 단계에서만 사용하고 실제 운영 서비스에서는 전문적인 모니터링 툴이나 핀포인트, Zipkin 같은 다른 기술을 사용하는 것이 좋음
- 영한님 개인적으로 핀포인트를 추천한다고 함
9. 액츄에이터와 보안
1) 보안 주의
- 액츄에이터가 제공하는 기능들은 애플리케이션의 내부 정보를 너무 많이 노출하여 공개 된 외부 인터넷 망에 액츄에이터의 엔드포인트를 공개하는 것은 보안상 좋은 방안이 아님
- 액츄에이터의 엔드포인트들은 외부 인터넷에서 접근이 불가능하게 막고 내부에서만 접근 가능한 내부망을 사용하는 것이 안전함
(1) 액츄에이터를 다른 포트에서 실행
- 외부 인터넷 망을 통해서 8080포트에만 접근할 수 있고 다른 포트는 내부망에서만 접근할 수 있다면 액츄에이터에 다른 포트를 설정하면됨
- application 설정에서 아래와 같이 설정하면 기존 8080포트에서는 액츄에이터를 접근할 수 없고 설정한 포트에서만 actuator를 접근할 수 있음
- 설정 후 애플리케이션을 실행하고 8080으로 액츄에이터를 접속해보면 에러페이지가 뜨고 설정한 포트인9292로 접속하면 액츄에이터가 실행되는 것을 확인할 수 있음
- 애플리케이션 실행 시 로그에도 9292 포트가 활성화 되는 것을 확인할 수 있음
management:
server:
port: 9292
(2) 액츄에이터 URL 경로에 인증 설정
- 포트를 분리하는 것이 어렵고 어쩔 수 없이 외부 인터넷 망을 통해서 접근해야 한다면 /actuator 경로에 서블릿 필터, 또는 스프링 시큐리티를 통해서 인증된 사용자만 접근 가능하도록 추가 개발이 필요함
(3) application.yml - 엔드포인트 경로 변경
- 엔드포인트의 기본 경로를 변경하려면 설정에서 아래의 형식으로 설정하면됨
- management.endpoints.web.base-path: "/{경로}"
- /actuator/{엔드포인트} 대신에 /manage/{엔드포인트}로 경로가 변경됨
management:
endpoints:
web:
base-path: "/manage"