웹 개발

서버 + 프론트 장애 추적 가이드

Blue_bull 2025. 4. 26. 20:46

 

Ⅰ . 한눈에 보기

 

1. 로그 레벨의 의미와 운영 기준

  • TRACE: 극세밀 디버깅 (거의 안 씀)
  • DEBUG: 개발 중 흐름 확인 (개발환경 전용)
  • INFO: 정상 동작 기록 (운영환경에도 기록)
  • WARN: 주의 상황 경고 (운영 모니터링)
  • ERROR: 실패, 장애 기록 (운영 필수)

로그 레벨은 "상황별 역할 구분"이지 "단계적 흐름"이 아니다.


2. 특급 개발자의 로그 사용법

  • TRACE는 극한 디버깅용
  • DEBUG는 내 디버깅용 (운영에서는 끈다)
  • INFO는 정상 흐름 기록용
  • WARN은 위험 신호 감지용
  • ERROR는 시스템 실패 기록용 (스택트레이스 필수)

3. '추적성, 보안, 성능'을 고려한 로그 작성 4대 원칙

  • 누가-무엇을-언제를 남긴다.
  • 민감 데이터는 절대 기록하지 않는다.
  • for문, 자주 호출 함수에는 디버그 로깅 주의.
  • 구조화된(JSON) 로그로 남긴다.

4. 로그 작성/운영 심화 전략 7단계

  1. 구조화된(JSON) 로그 작성
  2. Context 정보 (userId, ip 등) 항상 포함
  3. Correlation ID 삽입
  4. 민감 데이터 완전 차단
  5. 로그 레벨별 파일 분리 저장
  6. 로깅 비용 최적화
  7. 운영환경에서는 비동기 로깅 적용

5. 각 심화 항목의 구체적 적용법

  • JSON 형태로 로그 작성 예시
  • Spring Boot MDC로 Context 정보 삽입
  • 필터(Filter)에서 Correlation ID 생성
  • 민감 데이터 로깅 차단 (@JsonIgnore)
  • Logback으로 레벨별 파일 분리 설정
  • if (logger.isDebugEnabled())로 불필요한 연산 차단
  • AsyncAppender로 비동기 로깅 구현

6. 프론트엔드와 백엔드 비동기 로깅 구분

구분  특징
프론트엔드 (React, Vue 등) 브라우저 자체 비동기 구조라 별도 비동기 로깅 필요 없음
백엔드 (Spring Boot 등) 동기 로깅은 병목이 생길 수 있어 AsyncAppender로 비동기 처리 필요

7. 백엔드에서 비동기 로깅이 필수인 이유

  • 서버는 초당 수백~수천 요청을 처리
  • 동기 로그로 디스크 I/O 병목 발생
  • AsyncAppender로 메모리 버퍼 처리 후 비동기 기록
  • 고성능 서버도 디스크는 병목이 되므로 초기부터 대비 필요

8. 로그 작성 심화 핵심 총정리

  • 로그는 추적성·보안·성능·운영 최적화를 위한 필수 자산
  • 개발 중 DEBUG/INFO 사용, 운영 중 INFO/WARN/ERROR만 사용
  • JSON 구조화 + Context 삽입 + Correlation ID 기반 추적
  • 서버는 반드시 비동기 로깅 적용

9. MDC + Correlation ID를 Spring Boot에 적용하기

  • 요청마다 UUID 생성 → MDC 저장 → 로그에 자동 삽입
  • application.properties나 logback-spring.xml로 패턴 추가 설정
  • 로그는 Console, InfoFile, ErrorFile로 레벨별 분리 저장
  • AsyncAppender로 비동기 로깅 처리

10. 서버+프론트 장애 추적 아키텍처 설계

  • 프론트 오류(Sentry) + 서버 오류(Sentry/로그 시스템) 모두 추적
  • 모든 요청에 Correlation ID 삽입
  • 장애 발생 시 Slack, Email, PagerDuty로 자동 알림 설정 가능

11. 서버-프론트 추적 연결 방법 (Correlation ID 연동)

  • 프론트 axios 요청에 X-Correlation-Id 헤더 추가
  • 서버 Filter에서 읽어 MDC에 넣기
  • 양쪽에서 동일한 ID를 기준으로 장애 발생 흐름 추적

12. 최종 정리: 실전 운영 시스템을 위한 3대 원칙

  • 서버/프론트 장애를 끊김 없이 추적할 수 있게 만든다.
  • 모든 요청은 Correlation ID로 연결해 식별한다.
  • 장애 발생 시 5분 안에 "문제 위치"를 추적할 수 있게 준비한다.

 

 

 

Ⅱ. 자세한 내용

 

1. 로그 레벨 별 의미 정리

로그 레벨 사용 목적 (언제 사용?) 운영 환경에서 다루는 방법
TRACE 아주 세밀한 디버깅 (함수 입출력, 반복문 내부 값 등) 거의 사용하지 않음. 특정 디버깅 전용.
DEBUG 개발 중 코드 흐름 확인, 파라미터 값, 계산 과정 출력 개발환경만 사용. 운영 서버에서는 끈다.
INFO 정상 동작 기록 (ex. 로그인 성공, 결제 완료) 운영 환경에서도 기록. 시스템 정상 상태 추적용.
WARN 주의 필요한 상태 (ex. 디스크 80% 이상, API 응답 지연) 운영 서버 모니터링 경고용. 필요 시 알람 설정.
ERROR 예외 발생, 요청 실패, 장애 발생 반드시 운영 서버에 기록. 장애 추적 필수 항목.

로그 레벨은 상황별로 골라 쓰는 역할 구분이지, 단계적으로 거치는 순서는 아니다.


2. 로그 사용법

1. TRACE는 거의 안 쓴다

  • 함수 들어갈 때마다 trace("Entering function X") 같은 걸 찍지만
  • 현실에서는 너무 많아서 프로젝트 크리티컬 디버깅할 때만 잠깐 킨다.

2. DEBUG는 오직 "내가 디버깅할 때"만 쓴다

  • 예를 들어 로그인 함수 디버깅할 때:
logger.debug("로그인 요청: email={}, password={}", email, password);
  • 운영 서버에는 DEBUG 출력 금지
    -> application-prod.properties에서 root=INFO 이상만 찍는다.

3. INFO는 서비스 흐름 기록용이다

  • 사용자가 어떤 행동을 했는지는 꼭 남긴다.
  • 예를 들어:
logger.info("User {} logged in successfully", userId);
logger.info("Payment completed: orderId={}", orderId);
  • 나중에 감사(Audit)나 문제 추적할 때 굉장히 중요해진다.

4. WARN은 문제 징조다

  • 심각한 에러는 아니지만 조치가 필요한 상황
  • 예시:
logger.warn("Disk usage high: {}%", diskUsage);
logger.warn("Third-party API 응답 느림: responseTime={}ms", responseTime);
  • 운영 환경 모니터링이 WARN부터 반응하게 설계하기도 한다.

5. ERROR는 실패했다는 뜻이다

  • 비즈니스 로직 예외, DB 연결 실패, 서버 내부 에러
  • 무조건 스택 트레이스 포함해서 남긴다:
try {
    ...
} catch (Exception e) {
    logger.error("DB 연결 실패", e);
}
  • 나중에 어떤 에러가 어디서 났는지 찾을 때 필수

3. '추적성, 보안, 성능'을 고려한 방법

체크 항목 실천 방법 (설명)
로그 남길 때 누구(User), 무엇(Order), 언제(Time)을 꼭 남긴다.
민감 데이터 절대 로그로 출력하지 않는다. (ex. 비밀번호, 주민번호)
성능 고려 for문 안이나 자주 호출되는 함수 안에 debug 이상 쓰지 않는다.
구조화된 로그 JSON 형태로 로그를 찍어서 분석 가능하게 한다. (ex. Logstash 연동 대비)

최종 요약

개발할 때는 DEBUG, 운영할 때는 INFO 이상만 남긴다.
문제 징조는 WARN, 확실한 실패는 ERROR로 명확하게 구분한다.
누가 무엇을 언제 했는지 추적할 수 있게 로그를 작성한다.


 

 

 

 

4. 로그 작성/운영 전략

번호 핵심 전략 설명
1 구조화된 로그(Structured Logging) 로그를 사람이 읽는 문장 대신 JSON 형식으로 남긴다. → 운영에서 자동 분석, 검색이 가능해진다.
2 Context(문맥) 정보를 항상 포함 요청별로 userId, ip, requestId(추적ID) 를 항상 로그에 남긴다. → 분산 서버에서도 한 번에 추적 가능.
3 Correlation ID(요청 식별자) 사용 하나의 HTTP 요청마다 고유 ID를 부여해서, API-DB-외부연동 흐름을 끈처럼 추적할 수 있게 한다.
4 민감 정보 완전 차단 로깅 레벨이 낮더라도 비밀번호, 카드번호는 아예 코드에서 출력 시도조차 못하게 한다. (ex. @JsonIgnore, 로거 필터링)
5 로그 레벨 다층화 (Multi-Level Logging) INFO: 정상 흐름 / WARN: 이상징후 / ERROR: 실패 기록 / DEBUG: 개발용 상세 디버깅 레벨별 파일 분리 가능하게 설정
6 로깅 비용 최적화 if (logger.isDebugEnabled()) {} 같은 조건문으로, 디버그 로그 불필요한 계산을 막는다.
7 운영환경에서는 비동기 로깅 Logback AsyncAppender를 써서, 로그 기록이 메인 스레드를 막지 않게 한다.

5. 각 항목의 구체적 설명

1. 구조화된 로그(JSON 예시)

{
  "timestamp": "2025-04-26T15:00:00Z",
  "level": "INFO",
  "userId": 42,
  "action": "LOGIN_SUCCESS",
  "ip": "192.168.0.1",
  "requestId": "abc123"
}

(→ Kibana, Datadog 같은 곳에서 필터 검색이 바로 가능)


2. Context 정보 자동으로 넣는 방법

  • Spring에서는 MDC (Mapped Diagnostic Context)를 활용
  • 코드 예시:
import org.slf4j.MDC;

MDC.put("userId", userId);
MDC.put("requestId", requestId);
logger.info("사용자가 로그인했습니다.");
MDC.clear();

(→ 이러면 모든 로그에 userId, requestId가 자동으로 찍힘)


3. Correlation ID를 HTTP 요청마다 생성

  • Spring Filter에 고유한 UUID를 넣고 관리
  • 외부 API, DB 호출에도 같이 넘겨주면 전체 흐름 추적 가능

4. 민감 정보 보호

  • DTO나 Entity에 @JsonIgnore 걸기
  • 또는 로거 찍기 전에 직접 민감 필드를 null 처리

5. 레벨별 파일 분리 저장

  • 예를 들어 Logback 설정:
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <file>logs/info.log</file>
  ...
  <filter class="ch.qos.logback.classic.filter.LevelFilter">
    <level>INFO</level>
    <onMatch>ACCEPT</onMatch>
    <onMismatch>DENY</onMismatch>
  </filter>
</appender>

(→ info.log, error.log 따로 남기기)


6. 로깅 최적화 (디버그 비용 줄이기)

if (logger.isDebugEnabled()) {
    logger.debug("DB 조회 결과: {}", expensiveOperation());
}

(→ 안 그러면 debug 찍지 않더라도 expensiveOperation()이 호출돼서 낭비 발생)


7. 비동기 로깅

  • Logback AsyncAppender 사용:
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
  <appender-ref ref="INFO_FILE"/>
</appender>

(→ 로그 찍는 동안 메인 로직이 지연되지 않게 비동기화)


요약

"운영/디버깅/성능/보안/분석까지 한 번에 고려해서, 로그를 '운영 가능 자산'으로 만든다. 단순히 로그를 찍는 것이 아닌,
운영과 장애 대응 까지 설계한다."

 

 

 

 

\


6. 7단계 비동기 로깅(Async Logging)구분

구분 특징 비고
프론트엔드
(React, Vue 등)
주로 브라우저 콘솔(console.log) 기반으로 로깅. 별도 비동기 로깅은 필요 없음. 브라우저가 애초에 비동기 이벤트 기반이기 때문에 별도
Async 로깅 불필요.
백엔드
(Spring Boot, Node.js 등)
서버는 파일/DB에 로그를 기록할 때 동기 방식이면 처리 지연 위험. AsyncAppender 등으로 비동기 로깅 설정 → 메인 요청 흐름과 로그 기록을 분리해야 성능 보장.

7. 백엔드에서 비동기 로깅을 하는 이유

항목 내용
서버 요청 특성 서버는 1초에 수백~수천 건 요청을 처리함.
문제점 매번 FileWriter 같은 동기 방식으로 로그를 쓰면, 디스크 I/O 대기 때문에 요청 처리 지연 발생.
비동기 로깅 이유 로그 쓰기를 별도 스레드(비동기)로 넘겨서, 메인 요청은 빨리 끝내고 로그는 "나중에" 기록하게 함.
도구 예시 Spring Boot에서는 AsyncAppender, Logback 비동기 설정 등을 사용.

 

항목 설명
1. 현재 사용자가 적어도 사용자가 1000명이어도, 갑자기 2배, 10배 늘어날 수 있음. (서비스는 "확장성"을 기본으로 설계해야 함)
2. 로그는 시스템 부하를 야금야금 누적시킴 특히 트래픽 급증/스파이크(특정 시간대에 몰림) 때, 동기 로그면 서버가 "I/O 병목"으로 급격히 느려질 수 있음.
3. 비동기 로깅은 거의 부하가 없다 AsyncAppender는 메모리 버퍼에 잠깐 쌓았다가 별도 스레드로 쓰기 때문에 메인 성능에 미치는 영향이 극히 적다.
4. 고성능 서버라도 방심하면 안 됨 CPU, 메모리 여유가 있어도, 디스크 쓰기는 I/O 특성상 절대 빠를 수 없음. (특히 HDD라면 더 심각)
5. 나중에 구조 변경할 필요 없음 초기에 비동기 로깅을 깔끔히 해두면, 서비스가 성장할 때 "로깅 시스템 개선"에 시간을 쓸 필요가 없음.

 

"메인 요청 처리"는 빠르게 끝내고, "로그 기록"은 나중에 한다.

  비동기 로깅은 서버가 빠르게 요청을 처리할 수 있도록 "로그 쓰기 작업을 분리"하는 기술

 


8. 로그 작성 심화 핵심 총정리

로그 레벨 5단계 TRACE: 극세밀 디버깅 / DEBUG: 개발 흐름 확인 / INFO: 정상 흐름 기록 / WARN: 주의 상황 / ERROR: 실패, 장애 발생
로그 작성 4대 원칙 ① 누가-무엇을-언제 기록, ② 민감 데이터 금지, ③ 성능 고려(for문 주의), ④ 구조화된(JSON) 로그 작성
심화 7단계 전략 1. JSON 구조화2. Context(userId, ip 등) 포함3. Correlation ID로 요청 흐름 추적4. 민감 정보 완전 차단5. 로그 레벨별 파일 분리6. 로깅 비용 최적화7. 운영환경 비동기 로깅 (AsyncAppender)
비동기 로깅 구분 백엔드(Spring Boot 등 서버)만 필요. 프론트(React 등)는 별도 비동기 로깅 필요 없음.
로그를 모으는 이유 문제 추적, 보안 감시, 운영 안정성 확보, 성능 개선, 감사 대응

요약

"로그는 단순 출력이 아니라, 추적성·보안·성능·운영을 최적화해 시스템을 살아있는 자산으로 만드는 필수 요소다."
"백엔드는 로그를 운영 자산을 관리하고, 프론트엔드는 사용자 오류 추적(Sentry)만 신경 쓰면 된다. 좋은 로그는 문제를 예방하고, 나쁜 로그는 문제를 은폐한다."


적용

  • 개발 중에는 DEBUG와 INFO를 잘 활용해서 흐름 파악
  • 운영 서버는 반드시 INFO, WARN, ERROR만 기록하고 모니터링
  • JSON 구조화 + Context + Correlation ID를 항상 기본 세팅
  • 서버는 비동기 로깅으로 성능 최적화
  • 로그를 남기는 이유를 항상 의식하면서 기록

 

9. MDC + Correlation ID를 Spring Boot에 적용하는 법

1-1. Correlation ID 자동 생성 필터 만들기

HTTP 요청마다 고유 ID(UUID)를 만들고, MDC에 심는다.

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.UUID;

@Component
public class CorrelationIdFilter implements Filter {

    private static final String CORRELATION_ID = "correlationId";

    @Override
    public void doFilter(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        try {
            String correlationId = UUID.randomUUID().toString();
            MDC.put(CORRELATION_ID, correlationId); // MDC에 저장
            chain.doFilter(request, response);       // 다음 필터로 넘김
        } finally {
            MDC.remove(CORRELATION_ID);               // 요청 완료 후 정리
        }
    }
}

  "@Component로 등록된 CorrelationIdFilter라는 "필터 클래스"를 만들어 등록하면(서버에 적용하면) 요청마다 correlationId가 자동으로 생성된다. 모든 로그에 correlationId가 따라붙는다."

단계 설명
1 CorrelationIdFilter 클래스를 작성한다.
2 @Component를 붙여서 Spring Bean으로 등록한다.
3 서버가 요청을 받을 때마다 이 필터가 작동한다.
4 요청마다 고유한 UUID를 생성하고 MDC.put()으로 저장한다.
5 이후 찍히는 모든 로그에 correlationId가 자동으로 포함된다. (※ 로그 포맷 설정 필요)

1-2. Logger 설정 (로그 포맷 수정)

로그 패턴에 correlationId를 추가해야 보인다.

application.properties 또는 logback-spring.xml 설정

logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - [correlationId:%X{correlationId}] %msg%n

출력 예시:

2025-04-26 15:35:22 [http-nio-8080-exec-1] INFO  com.example.MyService - [correlationId:abc123] 회원가입 성공: userId=1

10. logback-spring.xml 심화 예시 (레벨별 파일 분리 + 비동기 로깅)

src/main/resources/logback-spring.xml

<configuration>
    <!-- 콘솔 출력용 -->
    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - [correlationId:%X{correlationId}] %msg%n</pattern>
        </encoder>
    </appender>

    <!-- info 레벨 파일 저장 -->
    <appender name="InfoFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/info.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/info.%d{yyyy-MM-dd}.log</fileNamePattern>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - [correlationId:%X{correlationId}] %msg%n</pattern>
        </encoder>
    </appender>

    <!-- error 레벨 파일 저장 -->
    <appender name="ErrorFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/error.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/error.%d{yyyy-MM-dd}.log</fileNamePattern>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - [correlationId:%X{correlationId}] %msg%n</pattern>
        </encoder>
    </appender>

    <!-- Async 비동기 설정 -->
    <appender name="AsyncInfo" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="InfoFile"/>
    </appender>

    <appender name="AsyncError" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="ErrorFile"/>
    </appender>

    <!-- logger 설정 -->
    <root level="INFO">
        <appender-ref ref="Console"/>
        <appender-ref ref="AsyncInfo"/>
        <appender-ref ref="AsyncError"/>
    </root>
</configuration>

  Info 로그는 logs/info.log에, Error 로그는 logs/error.log에, 비동기로 빠르게 기록, 모든 로그에 correlationId가 자동으로 붙음


흐름 요약

[HTTP 요청 수신]
    ↓
[Filter] CorrelationId 생성 → MDC에 저장
    ↓
[Service/Controller] Logger 찍음 → MDC에서 correlationId 자동 삽입
    ↓
[logback] AsyncAppender로 info.log, error.log 비동기 기록
    ↓
[필요하면 Kibana, Datadog 등으로 분석]

 

요약

"모든 로그에 correlationId를 자동으로 남기고, 레벨별 비동기 분리 저장까지 해야 서비스 운영에 적합한 로그 시스템이다."

 

 


11. 서버+프론트 장애 추적 아키텍처

전체 그림 흐름

[사용자 브라우저]
    ↓
[프론트엔드 (React, Next.js)]
    ↓  (오류 발생시 Sentry 등으로 자동 보고)
[Sentry (Frontend)]
    ↓
[프론트에서 서버로 API 요청]
    ↓
[백엔드 (Spring Boot)]
    ↓  (API 실패, 서버 오류 발생시 로그 + 모니터링 전송)
[Sentry (Backend) or Log 시스템 (ELK, Datadog)]
    ↓
[알림 시스템 (Slack, Email, PagerDuty)]

세부 아키텍처 구체화

구성 요소 역할
프론트 (React) - 사용자 에러(try-catch, window.onerror) 자동 감지- Sentry에 에러 전송 (userId, page URL 등 포함)
서버 (Spring Boot) - 모든 API 요청에 Correlation ID 삽입- API 실패/에러 발생 시 로그 + Sentry 전송- 운영 장애 모니터링용 로그 남김
Sentry
(Frontend + Backend)
- 오류 모니터링 & 실시간 알림- userId, requestId, 오류 스택 자동 기록
로그 시스템
(ELK, Datadog)
- 모든 정상/오류 로그 기록 및 검색- 장애 패턴 자동 감지
알림 시스템
(Slack, Email 등)
- 특정 수준 이상의 오류(WARN, ERROR) 발생 시 개발팀에 즉시 알림

12. 프론트와 백엔드 모두 "추적 가능"하게 만들기

Correlation ID 연동 (서버 ↔ 프론트)

1. 프론트에서 요청할 때, 서버로 Correlation ID를 같이 보낸다.

// axios 예시
axios.get("/api/data", {
  headers: {
    'X-Correlation-Id': correlationId, // 프론트에서도 UUID 하나 만들어서
  }
})

 

2. 서버(Spring Boot)는 이 헤더를 받아서 로그에 넣는다.

// Filter에서 Correlation ID 읽기
String correlationId = request.getHeader("X-Correlation-Id");
if (correlationId == null) {
    correlationId = UUID.randomUUID().toString(); // 없으면 새로 생성
}
MDC.put("correlationId", correlationId);

 

"이 오류가 프론트 요청의 어느 것과 연결되어 있는지" 서버-프론트를 "한 줄"로 연결해서 추적 가능.


프론트 Sentry 설정 예시

import * as Sentry from "@sentry/react";

Sentry.init({
  dsn: "https://examplePublicKey@sentry.io/projectId",
  integrations: [
    new Sentry.BrowserTracing(),
    new Sentry.Replay(),
  ],
  tracesSampleRate: 1.0,
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
});
  • 자동으로 API 요청 실패, JS 오류, 사용자 클릭 경로까지 기록
  • userId 설정도 추가 가능:
Sentry.setUser({ id: userId });

서버 Spring Boot Sentry 연동 예시

<!-- build.gradle 또는 pom.xml -->
<dependency>
    <groupId>io.sentry</groupId>
    <artifactId>sentry-spring-boot-starter</artifactId>
    <version>6.28.0</version>
</dependency>
# application.yml
sentry:
  dsn: https://examplePublicKey@sentry.io/projectId
  environment: production
  traces-sample-rate: 1.0
  • Exception이 터지면 자동으로 Sentry에 전송
  • Correlation ID까지 함께 보내려면 SentryEventProcessor를 커스터마이징 가능

장애 발생 시 흐름 (예시)

  1. 유저가 버튼 클릭 → API 호출
  2. 프론트에서 오류 발생 → Sentry(Frontend)에 에러 자동 전송
  3. 서버(API) 호출 중 에러 → 로그 + Sentry(Backend)로 에러 전송
  4. Sentry 대시보드에서 오류 발생 기록
  5. 특정 조건 (ex. ERROR 수 > 10개)이 넘으면 Slack으로 자동 알림
  6. 개발자는 Correlation ID를 기준으로 프론트-서버 전체 요청 흐름을 추적하며 원인 분석

아키텍처 요약

계층 장애 추적 방법
프론트엔드 Sentry로 JS 에러/이벤트 수집, Correlation ID 함께 기록
서버(Spring Boot) API 에러 + 시스템 오류를 로그 + Sentry로 수집
공통 모든 요청에 Correlation ID 삽입해서 "한 줄"로 전체 흐름 연결
통합 모니터링 Sentry, Kibana, Slack 경고 알림으로 빠르게 대응

요약

"서버와 프론트를 Correlation ID로 연결하고, 장애를 '끊기지 않고' 추적할 수 있으면 상용 서비스 운영 수준의 시스템 운영이 가능하다."

 


정리

  • 서버/프론트 장애 추적을 끊김 없이 한 줄로 잇는다.
  • 모든 요청은 Correlation ID로 식별할 수 있어야 한다.
  • 장애 발생 시, 5분 안에 "어디서 문제인지" 찾을 수 있게 준비한다.

추가로 고려해 볼 주제

  • Slack, Email, PagerDuty로 자동 장애 알림 연동하는 방법
  • 장애 발생 패턴을 자동 감지해서 알림 트리거 만드는 법
  • API별 SLA (응답 시간 목표) 설정 및 로그 모니터링하는 법