[Spring Boot] 에러 로그를 이메일로 자동 전송하기 – SMTP + Logback 연동

2025. 3. 23. 19:10·Springboot

📌 상황

프로젝트를 진행하면서 프론트와 백엔드 간의 API 연동이 활발해졌고,

그 과정에서 백엔드에서 처리하지 못한 예외로 수정 작업이 종종 발생했다.

에러가 발생한 직후 빠르게 대응할 수 있도록,

에러 로그가 발생하면 개발자에게 즉시 이메일로 알림을 보내는 구조를 도입했다.


🧱 환경 정보

  • Spring Boot: 3.4.2
  • spring-boot-starter-mail: 3.4.2
  • 메일 서버: Gmail SMTP 사용
  • 로그 시스템: Logback (Spring Boot 기본)
  • 로그 분석 스케줄러: Spring @Scheduled

1. 📦 의존성 추가

먼저 메일 기능을 사용하기 위해 아래와 같이 의존성을 추가했다.

implementation 'org.springframework.boot:spring-boot-starter-mail'

2. 📝 Logback 설정 – logback-spring.xml

로그를 파일로 저장하고, 에러 발생 시 메일로 전송하도록 설정한다.

<configuration>
    <property name="LOG_PATH" value="logs" />

    <!-- 로그 파일 저장 (일자별) -->
    <appender name="DAILY_ROLLING_FILE_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/app.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/app.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 에러 로그를 이메일로 전송 -->
    <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
        <smtpHost>smtp.gmail.com</smtpHost>
        <smtpPort>587</smtpPort>
        <username>${GMAIL_USERNAME}</username>
        <password>${GMAIL_PASSWORD}</password>
        <STARTTLS>true</STARTTLS>
        <to>${GMAIL_USERNAME}</to>
        <from>${GMAIL_USERNAME}</from>
        <subject>[ALERT] Spring App Log 경고 발생</subject>
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </layout>
        <threshold>ERROR</threshold>
    </appender>

    <!-- 콘솔 출력 (선택) -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 전체 로그 설정 -->
    <root level="INFO">
        <appender-ref ref="DAILY_ROLLING_FILE_APPENDER" />
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="EMAIL" />
    </root>
</configuration>
  • EMAIL Appender는 에러 로그(LEVEL: ERROR) 발생 시 지정된 이메일로 전송한다.
  • Gmail SMTP를 사용하며, Gmail 보안 설정에서 앱 비밀번호 또는 OAuth 설정이 필요하다.

3. 📬 커스텀 이메일 전송 (선택적 로그 감지)

Logback 설정은 모든 ERROR 로그를 전송하지만,

실제로는 특정 오류에 대해서만 알림이 필요할 수 있다.

예: Redis 토큰 저장 실패 등 중요 로직

그래서 @Scheduled로 주기적으로 로그를 확인하고,

특정 키워드가 포함된 로그만 메일로 전송하도록 구성했다.

@Component
@RequiredArgsConstructor
public class LogMonitor {

    @Value("${spring.mail.username}")
    private String sendToEmail;
    private final JavaMailSender mailSender;

    @Scheduled(fixedDelay = 3600000)  // 1시간마다 실행
    public void checkLogFile() throws IOException {
        Path logPath = Paths.get("logs/app.log");
        if (!Files.exists(logPath)) return;

        List<String> lines = Files.readAllLines(logPath);
        LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");

        for (String line : lines) {
            try {
                String timestamp = line.substring(0, 23);
                LocalDateTime logTime = LocalDateTime.parse(timestamp, formatter);

                if (logTime.isAfter(oneHourAgo) && line.contains("redis refresh token 저장 오류 발생")) {
                    sendEmail(line);
                    break; // 중복 전송 방지
                }
            } catch (Exception ignored) {}
        }
    }

    private void sendEmail(String logMessage) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setTo(sendToEmail);
        message.setFrom(sendToEmail);
        message.setSubject("[ERROR 발생] Spring 로그 알림");
        message.setText("🚨 로그에서 다음과 같은 오류가 감지되었습니다:\\n\\n" + logMessage);
        mailSender.send(message);
    }
}

  • logs/app.log에서 최근 1시간 이내의 로그만 필터링
  • "redis refresh token 저장 오류 발생" 메시지가 있으면 알림 전송
  • 중복 전송을 방지하기 위해 한 건만 처리 후 break

✅ 결과

설정된 조건에 따라 다음과 같은 방식으로 알림 메일을 받을 수 있다:

구분 설명

제목 [ERROR 발생] Spring 로그 알림
본문 오류 로그 내용 (스택 트레이스 또는 커스텀 메시지)
수신 개발자 이메일 (Gmail 등)

 

 

 

🔧 개선점 및 향후 계획

현재는 로그 정보를 단순 파일 형태로 저장하고,

스케줄러가 해당 로그 파일을 **라인 단위로 전부 순회(full scan)**하며 에러 여부를 탐지하고 있다.

이 방식은 구조가 단순하다는 장점이 있지만,

로그가 많아질수록 탐색 시간도 선형적으로 증가하게 된다.

또한, 로그 데이터에 대한 시계열 분석이나 조건별 필터링이 제한적이기 때문에

성능 및 분석 측면에서 아쉬움이 있다.


📉 현재 방식의 한계

  • 매 스캔 시 로그 파일 전체를 읽기 때문에 비효율적
  • 로그의 시간 범위 필터링이 어려움 (첫 줄부터 전체 확인 필요)
  • 정렬, 집계, 시각화 등의 분석 기능이 미흡
  • 에러 유형별 통계나 추세를 알기 어려움

📈 개선 계획: Elasticsearch 도입

이를 보완하기 위해, 다음 단계로는 Elasticsearch 기반 로그 분석 시스템을 구축할 계획이다.

  • 로그 데이터를 Elasticsearch에 저장하고,
  • Kibana 시각화를 통해 실시간 모니터링 및 분석이 가능하도록 개선할 예정이다.
  • 시계열 데이터로 저장된 로그는 기간 필터, 쿼리 검색, 집계 분석 등 다양한 기능을 제공하므로, 정확한 원인 분석, 에러 추적, 안정성 점검이 쉬워진다.

🎯 기대 효과

  • 검색 속도 개선: full scan 없이 시간대 검색 가능
  • 정확한 오류 감지 및 분석: 다양한 쿼리 조합 가능
  • 로그 시각화: 에러 패턴과 발생 추세를 한눈에 파악
  • 운영 안정성 확보: 문제 발생 시 더 빠르게 대응 가능

'Springboot' 카테고리의 다른 글

[Spring AOP] Spring AOP를 통한 Controller 요청 로그 작성  (0) 2025.04.26
[Spring] 요청 데이터 처리 원리  (0) 2025.03.26
[Spring + Redis] 비밀번호 설정 및 Lettuce 연결 설정 정리  (0) 2025.03.21
[스프링부트] ObjectMapper JsonNode Object로 변환  (0) 2025.03.12
[SpringSecurity] BCrypt 비밀번호 인증 구현  (0) 2025.03.12
'Springboot' 카테고리의 다른 글
  • [Spring AOP] Spring AOP를 통한 Controller 요청 로그 작성
  • [Spring] 요청 데이터 처리 원리
  • [Spring + Redis] 비밀번호 설정 및 Lettuce 연결 설정 정리
  • [스프링부트] ObjectMapper JsonNode Object로 변환
코딩 못하는 감자
코딩 못하는 감자
  • 코딩 못하는 감자
    코딩 못하는 감자의 기록
    코딩 못하는 감자
  • 전체
    오늘
    어제
    • 분류 전체보기 (91)
      • Kubernetes (10)
      • Github Action (1)
      • Docker, Container (3)
      • Springboot (26)
      • Baekjoon (4)
      • 명품 운영체제 (9)
      • 데이터베이스 (2)
      • JSP (3)
      • 안드로이드프로그래밍 (1)
      • 미니프로젝트 (1)
      • 용어정리 (0)
      • 소프트웨어공학 (3)
      • 운영체제 (2)
      • Flutter (0)
      • Git (1)
      • HTTP (0)
      • RAG (1)
      • Database (2)
      • FastAPI (1)
      • Elasticsearch (7)
      • Redis (0)
      • JPA (5)
      • Linux (1)
      • MCP (1)
  • 블로그 메뉴

    • 홈
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    엘라스틱서치 인덱스
    elasticsearch 커스텀분석기
    elasticsearch analyzer
    응답 로그
    mcp #model context protocol #claude desktop #mcp claude연동 #claude 파일 시스템 연동
    Dockerfile
    SpringBoot
    fuzziness
    elasticsearch ngram
    엘라스틱서치 인덱스 복사
  • hELLO· Designed By정상우.v4.10.3
코딩 못하는 감자
[Spring Boot] 에러 로그를 이메일로 자동 전송하기 – SMTP + Logback 연동
상단으로

티스토리툴바