모니터링 시스템 및 시큐어 코딩
Updated:
운영 단계의 애플리케이션은 개발 단계와 다르게, 실제 사용자 요청과 실제 장애 상황을 맞닥뜨리게 된다. 이때 가장 중요한 것은 문제를 빨리 알아차리고, 원인을 빠르게 좁혀 나가는 능력이다. 이를 위해 필요한 것이 모니터링이다.
모니터링은 단순히 그래프를 예쁘게 보는 기능이 아니다. 핵심 목적은 다음과 같다.
- 시스템의 상태를 실시간으로 파악
- 장애를 조기에 감지
- 성능 병목 지점 식별
- 로그를 통한 원인 분석
- 운영 안정성 확보
또한 웹 애플리케이션 개발은 항상 해커들의 타겟이 되므로, 기능 구현만큼이나 취약점을 이해하고 막는 것이 중요하다.
모니터링 개요
모니터링이란 시스템의 성능, 안정성, 가용성을 지속적으로 관찰하고 측정하는 과정이다. 여기서 중요한 것은 문제를 감지하고 대응 가능한 상태를 만든다는 점이다.
모니터링의 중요성
모니터링이 필요한 이유는 명확하다.
- 문제 예방: 장애가 터진 뒤에 대응하는 것이 아니라, 터지기 전에 이상 징후를 확인할 수 있다.
- 빠른 대응: CPU 급증, 메모리 부족, 에러율 증가 같은 현상을 빠르게 포착할 수 있다.
- 성능 최적화: 어떤 API가 느린지, 어떤 자원이 병목인지 수치로 확인할 수 있다.
- 사용자 경험 향상: 사용자는 “서버가 왜 느린지”보다 “지금 느리다”를 먼저 체감한다. 모니터링은 그 문제를 줄이는 기반이다.
- 비즈니스 연속성 확보: 서비스 중단 시간을 줄이고 운영 신뢰성을 높인다.
모니터링의 범위
모니터링은 한 가지 대상만 보는 것이 아니다. 보통 다음 다섯 영역을 함께 본다.
- 서버 모니터링: CPU, 메모리, 디스크, 네트워크
- 애플리케이션 모니터링: 요청 수, 응답 시간, 에러율, 스레드 상태, 로그
- 네트워크 모니터링: 트래픽, 대역폭, 지연 시간
- 데이터베이스 모니터링: 연결 수, 느린 쿼리, 자원 사용량
- 보안 모니터링: 비정상 접근, 공격 시도, 취약점 징후
Spring Boot Actuator
Spring Boot Actuator는 스프링 애플리케이션 내부 상태를 확인할 수 있게 해주는 도구이다. 애플리케이션의 헬스 상태, 메트릭, 환경 정보, 로깅 정보 등 쉽게 확인할 수 있다. Actuator는 다음과 같은 의존성을 추가야 사용할 수 있다.
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-web'
Actuator는 기본적으로 여러 엔드포인트를 제공한다. 이러한 엔드포인트는 /actuator 경로 하위에 위치하며, 각각의 엔드포인트는 다양한 정보를 제공한다.
- /actuator/health: 애플리케이션의 상태 확인
- /actuator/metrics: 메트릭 정보 제공
- /actuator/loggers: 로거 레벨 조회 및 변경
- /actuator/env: 환경 변수와 설정 확인
- /actuator/beans: 스프링 빈 목록 확인
- /actuator/threaddump: 스레드 덤프 확인
- /actuator/httptrace: 최근 HTTP 요청 및 응답 추적
기본적으로 모든 엔드포인트가 활성화되어 있지 않을 수 있으므로, application.properties 파일을 사용하여 필요한 엔드포인트를 활성화하거나 비활성화해야 한다. 설정 옵션은 다음과 같다.
- never: 헬스 체크 상세 정보를 절대 표시하지 않음
- always: 모든 사용자에게 헬스 체크 상세 정보를 항상 표시
- when_authorized: 인증된 사용자에게만 헬스 체크 상세 정보를 표시
spring.application.name=sample
server.port=8080
#모든 엔드포인트 노출 설정
management.endpoints.web.exposure.include=*
#헬스 체크 엔드포인트 상세 정보 표시 설정
management.endpoint.health.show-details=always
# 이 설정은 /actuator/health 엔드포인트에서 헬스 체크 정보를 항상 상세히 보여주도록 설정
# 기본적으로, 헬스 체크 엔드포인트는 요약된 상태 정보만 제공하며, 상세 정보는 노출되지 않음
주의사항 및 권장사항
모든 엔드포인트를 노출하는 설정은 개발 및 테스트 환경에서는 유용할 수 있지만, 운영 환경에서는 보안 위험을 증가시킬 수 있다. 그래서 필요한 엔드포인트만 노출하는 것을 권장한다. 또한 헬스 체크 엔드포인트에서 상세 정보를 항상 노출하는 설정 역시 운영 환경에서는 민감한 정보를 포함할 수 있으므로, show-details설정을 when_authorized 옵션을 사용하는 것이 좋다.
Actuator 접근 포트만 다른 포트로 설정하여 보호할 수 있다.
# 애플리케이션의 기본 포트를 8080으로 설정
server.port=8080
# Actuator 엔드포인트를 19090 포트에서 서비스하도록 설정
management.server.port=19090
Spring Security를 사용하여 민감한 엔드포인트에 접근 제어를 설정하는 것이 좋다. 예를 들어, /actuator 경로에 대한 보안 설정을 추가할 수 있다.
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/actuator/**").authenticated()
.and()
.httpBasic();
}
}
Spring 프로젝트를 만든 후 dependency와 application.properties 파일을 위와 같이 해주면 다음과 같이 볼 수 있다.

Prometheus
Prometheus는 메트릭 수집과 저장을 담당하는 오픈소스 모니터링 도구이다. 핵심은 시계열 데이터를 다룬다는 점이다. 즉, “지금 CPU 사용량이 얼마인가?”보다 “시간에 따라 CPU 사용량이 어떻게 변했는가?”를 보는 데 강하다.
Prometheus의 주요 구성 요소는 다음과 같다.
- Prometheus 서버
- 메트릭을 주기적으로 scrape하여 시계열 데이터베이스에 저장하는 핵심 컴포넌트이다.
- 시계열 데이터베이스(Time Series Database, TSDB)는 시간에 따라 변화하는 데이터를 효율적으로 저장하고 조회할 수 있도록 최적화된 데이터베이스이다.
- Exporter
- Prometheus가 이해할 수 있는 형식으로 메트릭을 노출해 주는 도구이다.
- 예를 들어, Node Exporter (서버의 시스템 메트릭 수집), PostgreSQL Exporter (PostgreSQL 메트릭 수집), Spring boot의 micrometer-registry-prometheus 디펜던시가 있다.
- Pushgateway
- 배치 작업처럼 짧게 실행되고 끝나는 작업의 메트릭을 푸시 방식으로 전달할 때 사용한다.
- 일반적으로 지속적으로 실행되지 않는 작업에서 사용된다.
- Alertmanager
- 조건에 맞는 경고(alert)를 처리하고 Slack, 이메일 등으로 알림을 보낸다.
- Grafana
- Prometheus 데이터를 시각화하는 대표 도구이다.
실습
먼저 기존 프로젝트에 Prometheus Dependency를 추가한 뒤, application.properties에도 prometheus 설정을 추가한다.
runtimeOnly 'io.micrometer:micrometer-registry-prometheus'
management.endpoint.prometheus.enabled=true
http://localhost:8080/actuator/prometheus에 접속하면 프로메테우스 매트릭스를 확인할 수 있다.

이후, 프로젝트 폴더가 있는 위치에 prometheus 폴더를 새로 만든 후, prometheus.yml을 생성한다.
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'spring-boot'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['host.docker.internal:8080']
host.docker.internal은 Docker에서 제공하는 특수한 DNS 이름으로, Docker 컨테이너가 호스트 머신(즉, Docker를 실행하는 컴퓨터)의 네트워크 서비스에 접근할 수 있도록 한다. 이를 통해 컨테이너 내부에서 호스트 머신의 네트워크 주소를 참조할 수 있다.
이제 Docker를 이용해서 실행해본다.
docker run -d --name=prometheus -p 9090:9090 -v C:\Users\dbsau\monitor\prometheus\prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus

localhost:9090에 접속하면 Prometheus가 실행되는 것을 확인할 수 있다.

이후 Spring 프로젝트를 실행하고 Targets로 들어가면 다음과 같이 확인할 수 있다.

댓글남기기