⭐️ 배경
프로젝트 진행 중,
🙋♀️ 프론트엔드: 백엔드 분들.. '500 Internal Server Error' 떴어요 ㅜㅜ
아!
프론트엔드는 백엔드 API 를 호출하는 사용자 입장이기 때문에,
내부 Log는 살펴볼 수 없다는 단점이 있다
(이 때문에 약 1시간 삽질하셨다고 한다...)
🙋♀️백엔드: 히힛 에러 코드(400번대) 노출 안해야 외부 위협에 안정적이겠지?
🙋♀️프론트엔드: 또 500 에러네... 뭐가 문제지?
문제를 해결하고자
'백엔드 스프링부트 서버 에러를 디스코드로 전송하자'
는 목표를 세웠다.
⭐️ 환경
백엔드 환경은 다음과 같다.
⭐️ 디스코드 웹훅
'백엔드 스프링부트 서버 에러를 디스코드로 전송하자'
라는 목적을 달성하기 위한 방법으로 디스코드 웹훅을 선택했다.
✅ 웹훅?
- 웹 서비스(서버)의 이벤트 데이터를 전달하는 HTTP 기반 콜백 함수
- API 통신 방식(polling / 웹훅) 중 하나
1️⃣일반적인 API 방식 (Polling)
- 클라이언트 ➔ 서버 호출
- 서버 이벤트 발생 시
: 서버에 이벤트가 발생했는지 클라이언트가 주기적으로 요청하여 알아냄 (클라이언트 측에서 호출 가능)
2️⃣웹훅 (역항향 API)
- 서버 ➔ 클라이언트 호출
- 이때 클라이언트의 URL = Callback URL
- 서버 이벤트 발생 시
: 서버 이벤트 발생 사실을 클라이언트로 요청 보냄 (서버 측에서 호출 가능)
✅ 디스코드 웹훅을 프로젝트에 어떻게 적용할까?
스프링부트 서버 에러를 디스코드로 전달하도록 한다!
즉,
웹훅 서버 = 스프링부트 웹 서버
웹훅 클라이언트 = 디스코드 서버
https://velog.io/@devlyny/Spring-AOP를-사용하여-Slf4j-로-로깅하기
Spring AOP를 사용하여 @Slf4j 로 로깅하기
서버 로깅, 저는 이렇게 합니다!
velog.io
구현 사항은 이 블로그를 참고하였는데,
스프링부트의 로깅은 기본적으로 콘솔에 나오는데,
이 로그 출력 부분을 콘솔 (기본) + 디스코드로 설정을 바꾼다고 생각하면 된다!
⭐️ 과정
1. 디스코드 웹훅 만들기
2. 스프링부트 에러를 디스코드로 전송
✅ 1. 디스코드 웹훅 만들기
1. 디스코드 서버 만들기
- 프로젝트 이름으로 서버를 자유롭게 만들어준다!
2. 디스코드 채널 만들기
- 방금 만든 서버 안에, 채널을 만들어준다.
- 이름은 마찬가지로 자유롭게 해도 된다 (나는 서버-에러로그 로 지어줬다)
3. 디스코드 웹훅 만들기
- 방금 만든 채널에 마우스 오버 ➔ [채널 편집] 클릭
- [채널 편집] ➔ [연동] ➔ [웹 후크 만들기]
- 웹 후크 생성 후, URL을 메모장에 저장해두자!
(이 URL이 웹훅 클라이언트 URL이다)
✅ 2. 스프링부트 에러를 디스코드로 전송
위에서
스프링부트 로깅을 콘솔 (기본) + 디스코드로 로깅 설정을 바꿔 구현한다고 언급하였다.
그러기 위한 방식으로
스프링부트 로깅을 설정하는 파일 (logback-spring.xml)을 수정하
1. gradle 파일 수정
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
dependencies {
// (생략)
implementation 'org.springframework.boot:spring-boot-starter-logging'
implementation 'com.github.napstr:logback-discord-appender:1.0.0'
}
2. application.yml 수정
# ... (생략)
logging:
discord-error:
webhook-url: (디스코드 웹훅 URL)
config: classpath:logback-spring.xml
위에서 생성한 디스코드 웹훅의 URL을 여기에 넣어준다 !
3. logback-spring.xml 파일 생성
스프링부트 로그 형식을 설정하는 파일이다!
<configuration>
<include resource="console-appender.xml"/>
<include resource="discord-error-appender.xml"/>
<appender-ref ref="ASYNC_DISCORD" />
<timestamp key="BY_DATE" datePattern="yyyy-MM-dd"/>
<!-- 로깅 테마 -->
<property name="LOG_PATTERN"
value="[%d{yyyy-MM-dd HH:mm:ss}:%-4relative] %green([%thread]) %highlight(%-5level) %boldWhite([%C.%M:%yellow(%L)]) - %msg%n"/>
<springProperty name="DISCORD_ERROR_WEBHOOK_URL" source="logging.discord-error.webhook-url"/>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="ASYNC_DISCORD" />
</root>
</configuration>
console, discord 두 곳으로 로그를 출력하도록 설정할 수 있다
4. console-appender.xml 파일 생성
<included>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
</included>
logback-spring.xml에서 정의한 LOG_PATTERN대로 콘솔로 출력하도록 명시한다.
LOG_PATTERN
value="[%d{yyyy-MM-dd HH:mm:ss}:%-4relative] %green([%thread]) %highlight(%-5level) %boldWhite([%C.%M:%yellow(%L)]) - %msg%n"/>
5. discord-error-appender.xml 파일 생성
<included>
<appender name="DISCORD" class="com.github.napstr.logback.DiscordAppender">
<webhookUri>${DISCORD_ERROR_WEBHOOK_URL}</webhookUri>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>
\n [ERROR LOG] ============================================================================
\n %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%logger{2}.%M:%L] - %ex{short}%n
</pattern>
</layout>
<username>[에러 발생]</username>
<tts>false</tts>
</appender>
<appender name="ASYNC_DISCORD" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="DISCORD" />
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
</included>
LOG_PATTERN은 콘솔과 비슷하지만, 색 지정과 같은 부분은 빠져있다
⭐️ 결과
에러 로그가 잘 뜨는 모습을 볼 수 있다 !
⭐️ 여담
1.
프론트엔드 분은 백엔드 지식을 잘 모르고,
'이게 왜 이렇게 되는 건가요?'라고 직접적으로 물어보는 것이 어려울 수 있다.
서로 이해시키기 위해 노력하고, 그 과정을 자동화 시킨다면
프로젝트에 큰 도움이 되지 않을까 생각한다.
2.
블로그를 참고하니, AOP를 적용해 로깅 적용대상 파일 / 로깅 메시지 커스터마이징할 수 있었다.
이번 경우에는 단순히 서버의 모든 에러 로그를 출력하려 하므로, AOP는 불필요하다 생각했다.
⭐️ 참고자료
웹훅 (토스 용어사전) https://docs.tosspayments.com/resources/glossary/webhook
AOP를 사용해 @Slf4j로 로깅하기 https://velog.io/@devlyny/Spring-AOP를-사용하여-Slf4j-로-로깅하기
'백엔드' 카테고리의 다른 글
[스프링부트] 디스코드 웹훅 (2) - API call 알림 (Interceptor, FeignClient) (0) | 2025.01.10 |
---|---|
[DB 해킹] MySQL DB 털린 썰 풉니다 (RECOVER_YOUR_DATA) (0) | 2024.12.23 |
MySQL 연결 - characterEncoding=utf8mb4 쓰지 마세요! (0) | 2024.12.12 |
[스프링부트] Soft delete 구현 (1) | 2024.12.09 |
[스프링부트] Spring Batch와 적용방법 (3) | 2024.12.09 |