TIL

Spring Boot AOP 사용하여 Slack 사용자 멘션하기

everyday-spring 2024. 10. 18. 13:44

특정 이벤트가 발생하면 자동으로 알림이 가는 방식

@Component
public class SlackNotifier {

    @Value("${slack.webhook.url}")
    private String slackWebhookUrl;

    private final RestTemplate restTemplate = new RestTemplate();

    public void sendSlackNotification(String title, String message) {
        Map<String, Object> payload = new HashMap<>();

        String formattedMessage = "*" + title + "*\n" + message;

        payload.put("text", formattedMessage);
        payload.put("username", "Spring Trello Event");
        payload.put("icon_emoji", ":smiley:");

        try {
            restTemplate.postForEntity(slackWebhookUrl, payload, String.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

RestTemplate을 사용하여 슬랙으로 알람을 전송

SlackWebHookURI는 slack에서 설정 하여 발급받을 수 있다

payload 설정으로 알람을 보내는 아이디와 이모티콘을 설정했다
전송할 내용은 text로 담는다

 

    @Pointcut(
            "execution(* com.sparta.springtrello.domain.workspace.service.WorkspaceService.addMember(..))")
    public void addMemberPointcut() {}

 

알람을 원하는 메소드에 포인트컷을 설정

 

@AfterReturning(value = "addMemberPointcut()", returning = "result")
    public void logAddMemberSuccess(org.aspectj.lang.JoinPoint joinPoint, Object result) {
        Object[] args = joinPoint.getArgs();

        AuthUser authUser = (AuthUser) args[0];
        Object workspaceId = args[1];
        Object role = args[3];

        String title = "Workspace Add User Event";

        User user = (User) result;
        String userTag = "<@" + user.getSlackId() + ">";

        String authTag = "<@" + authUser.getSlackId() + ">";

        String message =
                String.format(
                        "- Workspace ID : %s \n- Role : %s \n- 추가한 사용자 : %s \n- 추가된 사용자 : %s",
                        workspaceId, role, authTag, userTag);

        sendNotification(title, message);
    }

@AfterReturning 을 사용하여 메소드가 정상적으로 종료한 경우에만 알람을 보낸다

로그인 한 AuthUser의 슬랙 아이디 값과 출력값으로 받은 User의 슬랙 아이디 값으로 멘션기능을 사용한다

<@SlackID> 구조로 넣으면 해당 유저가 태그된다

SlackId값은 회원가입 시에 입력하여 DB에 유지하고 있다

 

private void sendNotification(String title, String message) {
        try {
            slackNotifier.sendSlackNotification(title, message);
            log.info("Slack notification sent: {}", message);
        } catch (Exception e) {
            log.error("Failed to send Slack notification: {}", e.getMessage());
        }
    }

title과, message를 인자값으로 넘겨 슬랙 알람을 전송한다

title값은 Bold효과를 주기 위해 따로 구분 하였다

 

문제사항! 슬랙 알림 시스템의 유지보수, 확장성 한계

  • 현재 시스템은 특정 메소드 호출 후 슬랙 알림을 보내는 방식으로 각 서비스가 강하게 결합된 구조를 가지고 있어 유지보수와 확장성에 한계가 있다.
  • Try
    • EDA를 도입해 이벤트 기반으로 알림을 분리하여 각 기능이 독립적으로 작동할 수 있도록 개선한다. 메소드 실행 후 이벤트가 발생하면 이를 감지하는 이벤트 리스너가 비동기적으로 슬랙 알림을 처리하는 방식을 적용하면 유지보수와 확장성을 확보할 수 있다.