본문 바로가기

개발/Linux & DevOps

운영중인 텔레그램 알람 시스템에 Naverworks 알람 붙이기

출처: 네이버웍스

1. 배경

기존 시스템에서는 장애나 주요 이벤트 발생 시
Socket 기반 알람을 통해 내부 모니터링 채널로 메시지를 전송하고 있었다.

하지만 운영이 안정화될수록 다음 요구사항이 생겼다.

  • 장애 알람을 사내 메신저(NaverWorks) 로도 받고 싶다
  • 기존 Socket 알람 로직은 수정하지 않고 유지하고 싶다
  • 알람 채널은 앞으로 더 늘어날 가능성이 있다

즉, 단순히 “NaverWorks API를 하나 더 붙이는 문제”가 아니라
알람 시스템 자체를 확장 가능한 구조로 만드는 문제였다.


2. 단순 연동의 문제점

가장 쉬운 접근은 다음과 같다.

if (type == SOCKET) { sendSocket(message); } else if (type == NAVER_WORKS) { sendNaverWorks(message); }

하지만 이 방식은 곧 한계를 드러낸다.

  • 채널이 늘어날수록 조건문 증가
  • 메시지 포맷이 채널마다 다름
  • 테스트 범위 급격히 증가
  • 기존 로직 수정이 불가피

운영 중인 시스템에서는 가장 피해야 할 구조다.


3. 설계 방향

이번 확장에서 세운 원칙은 다음과 같다.

  1. 알람 채널은 언제든 추가될 수 있다
  2. 기존 Socket 알람은 손대지 않는다
  3. 채널별 메시지 포맷 책임을 명확히 분리한다
  4. 설정과 구현을 최대한 분리한다

이를 위해 다음 구조를 선택했다.


4. 전체 구조 개요

AlarmManager
└─ CompositeAlarmSender
        ├─ SocketAlarmSender
       └─ NaverWorksAlarmSender

AlarmMessageBuilder
└─ NaverWorksPayloadRouter
       ├─ TextMessageBuilder
       └─ FlexResultReportBuilder

핵심은 두 가지다.

  • Sender 계층: “어디로 보낼 것인가”
  • Payload 계층: “어떤 형태로 보낼 것인가”

5. CompositeAlarmSender

여러 알람 채널을 동시에 또는 선택적으로 처리하기 위해
CompositeAlarmSender를 도입했다.

public class CompositeAlarmSender implements AlarmSender { 
    private final List senders; 
    
    @Override 
    public void send(AlarmMessage message) { 
    	for (AlarmSender sender : senders) { sender.send(message); } 
    } 
}

 

이 구조 덕분에:

  • 새로운 알람 채널 추가 시
    • Sender만 구현하면 됨
  • 기존 로직 수정 없음 (OCP 준수)

6. NaverWorksAlarmSender

NaverWorks 전송은 Socket과 성격이 완전히 다르다.

  • HTTP POST 기반
  • SSL 검증 이슈 발생 가능
  • 사용자 / 채널 단위 전송 필요

이를 모두 NaverWorksAlarmSender 내부로 캡슐화했다.

주요 고려 사항:

  • SSL 우회 옵션을 설정으로 분리
  • 단일 사용자 전송 / 채널 전송 분기 처리
  • 외부 API 실패 시 기존 알람 흐름에 영향 최소화

7. Payload 분리 전략

NaverWorks 메시지는 상황에 따라 포맷이 다르다.

  • 단순 텍스트 알림
  • 배치 결과 요약 리포트 (Flex 메시지)

이를 위해 NaverWorksPayloadRouter를 두고
메시지 성격에 따라 Builder를 분기했다.

public Payload build(AlarmMessage message) { 
	if (message.isResultReport()) { 
    	return flexResultReportBuilder.build(message); 
    } 
    return textMessageBuilder.build(message); 
}

👉 Sender는 전송만 책임지고,
👉 Payload 구성은 Builder가 책임진다


8. 설정 분리

NaverWorks 관련 설정은 별도 YAML로 분리했다.

  • alarm-naverworks.yaml
  • 토큰, 채널, SSL 옵션 관리
  • 내부 설정 로딩 전용 InternalNaverWorksConfig

이를 통해:

  • 환경별 설정 분리
  • 운영 중 설정 변경 용이
  • 보안 관리 수월

9. 결과 및 정리

이번 확장을 통해 얻은 효과는 명확하다.

  • 기존 Socket 알람 로직 무변경
  • NaverWorks 채널 안전하게 추가
  • 향후 Slack / SMS 확장도 동일 패턴 적용 가능

알람 시스템은 한 번 만들고 끝나는 영역이 아니라
운영이 길어질수록 계속 확장되는 영역이다.

처음부터 확장을 고려한 구조가
결국 운영 비용을 가장 크게 줄여준다.

반응형