들어가며
먼저 링크 서비스에 기획에 대해서 가볍게 설명하려고 한다

Leenk 서비스는, Leets라는 동아리를 운영하는 입장에서 생각했을때 동아리 원들의 커뮤니케이션 수단을 개발해서 제공해준다면 어떨까 ?? 라는 생각이 들어 시작하게된 서비스다
예쁜 디자인 + 랜딩 사이트 만들어주셔서 개큰감사 🙇🏻♂️ (Shout out to 도연, 한별)
https://leets-makers.framer.website/
Leets Makers
Gachon University IT Collaboration Club, Leets Makers' Landing Page - Made by. Makers' Designer, Doaeng.
leets-makers.framer.website


동아리원들이 자유롭게 사진을 공유하고, 모각작과 같은 링크를 생성하면서 특정 게시글을 신고할 수 있는 기능이 필요하여 도입하게 되었다 + TMI로 지금 생각해보면 정말 필요한 기능이였는가? 라는 생각도 들지만, 아래 사진에 나와있듯이 앱 출시 리젝 사유중에 " 신고 및 차단 기능이 존재해야함 " 이라는 내용이 있었어서 도입을 결정하게 되었다 🐵

구현한 플로우
서론이 조금 길었지만, 다시 돌아와서 이번 포스팅에서 다룰 내용은 " 링크 신고하기 기능 " 이다. 유저가 신고하기 버튼을 누르면 Slack의 Webhook을 활용해서, 운영진의 슬랙으로 알림이 오는 로직으로 구현을 하였다

1. 슬랙 웹훅 URL 환경변수 추가
먼저 아래의 앱추가를 눌러준다

그 다음 아래처럼 생긴 웹훅 앱을 사용하고싶은 채널에 추가해주면 된다



그 다음 yml 파일에 아래 처럼 선언하여, 위에서 복사한 웹훅 URL을 주입받는다고 이해해주면 된다
slack:
webhook_url: ${SLACK_WEBHOOK_URL}
2. LeenkReportRequest 입력 DTO 추가
public record LeenkReportRequest(
@NotBlank
@Size(max = 100)
String report
) {
}
기본 세팅이 끝난 뒤엔 먼저 위에 뷰에서도 나와있듯이, 신고 사유를 입력받을 수 있도록 LeenkReportRequest를 추가해주었다
3. reportLeenk 비즈니스 로직 구현
@Transactional(readOnly = true)
public void reportLeenk(Long userId, Long leenkId, LeenkReportRequest request) {
User user = userGetService.findById(userId);
Leenk leenk = leenkGetService.findById(leenkId);
notionDatabaseService.sendLeenkReport(request.report(), user.getId(), leenk.getId());
slackWebhookService.sendLeenkReport(request.report());
}
또한 실제 존재하는 유저인지, 링크인지 조회해오면서 예외처리를 진행해주고 노션 데이터베이스와 슬랙 웹훅에 알림을 전송하는 로직을 구현했다 (노션 데이터베이스에도 저장하는 이유는 예상치 못한 장애 발생시에도 유실 방지 + 신고가 들어오면 회의때 쉽게 트래킹하기 위함)
4. sendLeenkReport로 슬랙에 신고 내용 전송
public void sendLeenkReport(String report) {
String formatted = "*[링크 신고]*\n```" + report + "```";
slackRestClient.post()
.uri(webhookUrl)
.header("Content-Type", "application/json")
.body(Map.of("text", formatted))
.retrieve()
.toBodilessEntity();
}
SlackWebhookService에서 선언한 메서드인데, webhookUrl을 환경변수로 주입받아서 슬랙으로 전송할 최소 페이로드: {"text": "메시지"} 를 설정해주고, 위 코드를 보면 알 수 있듯이 json 형식으로 자유롭게 커스텀 할 수 있다고 생각해주면 된다
마치며

위처럼 유저가 신고하기를 누르면, 슬랙에서 정상적으로 트래킹을 할 수 있었다

+ 추가로, 비슷한 플로우로 링크 서비스 자체에 대한 피드백도 위처럼 받을 수 있도록 구현해놓아서, 실제 사용자의 의견을 신속하게 받을 수 있도록 하였다
Discord Webhook 과의 차이점
바로 이전 게시글인데, Discord Webhook의 구현 플로우가 궁금하다면 아래 링크를 참고해주면 더 좋을거같다
https://huncozyboy.tistory.com/57
디스코드를 활용한 500 에러 알림 자동화 (Webhook)
들어가며지금 해당 API 500 뜨는데 원인 알 수 있을까요지금 오류 로그 한번만 확인해주실래요 ??해당 API 500 뜨는데 원인이 뭘까요백엔드로 다른 파트와 개발을 진행하다보면, 플젝을 진행하면서
huncozyboy.tistory.com
개인적으로 슬랙은 디스코드와 비교해서 JSON 문법이 엄격해서 테스트할때 잘못 보내면 400 에러가 나오는 경우가 더 많았었다. Block Kit 등 복잡한 구조를 공식 지원해주는 것은 장점이라고 생각했었다. 디스코드는 JSON 형태라기보다는, 텍스트 마크다운과 코드블럭을 기본 지원해주어서 표현 부분이 조금 다르다는 생각도 들었다 👀
또한 추가로 찾아보다가 알게된 정보인데, Slack은 4,000자까지 UI 잘림 없이 잘 반환되지만, Discord는 2,000자 제한이 있기 때문에 긴 로그같은 내용은 분할하거나 파일로 첨부하는 방식도 있다고 나와있었다
채팅 기능이나, 매칭 기능, 알림 기능 등등에서 DLQ를 활용할 수 있듯이, 슬랙에서는 레이트 리밋 시 HTTP 429 + Retry-After 헤더로 백오프 로직을 짤 수 있고, 디스코드에서는 429 retry_after 기반으로 재시도 로직을 짤 수 있어 트래픽 병목이 생긴다면 해당 내용까지 고려해주면 더 좋은 설계가 될 수 있을거라고 생각했었다 👍🏻
참고한 자료
https://support.discord.com/hc/ko/articles/228383668
https://api.slack.com/messaging/webhooks
'Spring > Webhook' 카테고리의 다른 글
| 디스코드를 활용한 500 에러 알림 자동화 (Webhook) (1) | 2025.08.28 |
|---|