목차
1. 왜 중앙화된 로그 시스템이 필요할까?
마이크로서비스 환경에서 장애가 발생하면 곤란한 상황에 빠질 수 있다. 현재 나의 devnote를 예로 들면 요청 하나를 추적하기 위해 6개의 서비스 컨테이너에 각각 접속해 로그 파일을 뒤지는 것은 상당히 비효율적일것이다. 이 문제를 해결하기 위해 모든 서비스의 로그를 한곳으로 모아 검색하고 분석할 수 있는 중앙화된 로그 시스템으로 ELK 스택을 구축했다.
2. Devnote 프로젝트의 로그 아키텍처
로그는 Filebeat → Logstash → Elasticsearch → Kibana 순서로 흐르도록 구성했다. 각 컴포넌트는 아래처럼 명확한 역할을 수행한다.
MSA 서비스 → 호스트의 로그 파일 → Filebeat (수집) → Logstash (가공) → Elasticsearch (저장/색인) → Kibana (시각화/검색)
3. 1단계: 로그 포맷 통일하기
먼저 6개 서비스가 모두 동일한 형식으로 로그를 남기도록 application.yml의 로깅 패턴을 통일했다.
특히 [${spring.application.name}] 부분을 추가하여 로그 한 줄만 봐도 어떤 서비스에서 발생했는지 명확히 알 수 있도록 했다.
logging:
pattern:
file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - [${spring.application.name}] %msg%n"
4. 2단계: Filebeat로 로그 수집하기
Filebeat는 각 서버에 설치되어 로그 파일의 변경을 감지하고 수집하는 경량 에이전트다. docker-compose.yml의 volumes 설정을 통해 서버의 로그 디렉터리(/home/gunwook/app/devnote/logs)를 Filebeat 컨테이너의 /var/log/msa로 연결했다. filebeat.yml에는 이 경로의 모든 *.log 파일을 감시하도록 설정하여 모든 서비스의 로그를 수집했다.
5. 3단계: Logstash로 로그 파싱 및 정제하기
Filebeat가 보낸 텍스트 로그는 그 자체로 분석하기는 어렵다. Logstash는 이 비정형 데이터를 구조화된 JSON 데이터로 가공하는 역할을 한다. logstash.conf의 filter 플러그인에 grok 패턴을 사용하여, 1단계에서 정의한 로그 포맷에 맞춰 로그를 파싱했다. 이것을 통해서 service_name, log_level 등 의미 있는 필드를 추출하여 Elasticsearch에 저장할 수 있었다.
# logstash.conf
filter {
grok {
match => { "message" => "%{...} - \[%{DATA:service_name}\] %{GREEDYDATA:log_message}" }
}
}
6. 4단계: Kibana에서 로그 검색 및 시각화하기
이제 Kibana 대시보드에 접속하여 msa-logs-* 인덱스 패턴을 생성했다. 이제 단일 검색창에서 service_name: "user-service" AND log_level: "ERROR" 와 같은 KQL 쿼리를 통해 수많은 로그 중에서 원하는 내용을 곧바로 찾아낼 수 있게 되었다.
7. 느낀점
ELK 스택을 구축하기 전에는 장애 추적이 쉽지 않은 작업이었지만 이제는 오히려 간단한 작업이 되었다. 중앙화된 로그 시스템은 단순히 편리함을 넘어서 MSA의 안정성과 운영 효율성을 향상시켜주는 필수적인 기술이라고 느껴졌다.
'[데브노트] 웹 프로젝트 (devnote.kr)' 카테고리의 다른 글
Kafka와 AI로 콘텐츠 자동 수집 및 분류 시스템 만들기 (0) | 2025.09.16 |
---|---|
개인 프로젝트에 MSA를 도입한 이유 (0) | 2025.09.10 |
Devnote 프로젝트 (0) | 2025.09.10 |
남건욱's 공부기록