Nodejs

슬랙으로 RSS 알림 보내기 (4) - 슬랙에 메시지 전송하기

Seongmin 2025. 2. 26. 21:46
반응형

지난 글에서는 RSS 피드를 가져오는 방법에 대해 살펴보았습니다. 이번 글에서는 가져온 RSS 피드를 슬랙으로 알림을 보내는 기능을 구현해보겠습니다.

  1. 프로젝트 설정
  2. RSS 피드 가져오기
  3. 슬랙에 메시지 전송하기
  4. 중복 알림 방지하기
  5. 배포

1. 슬랙 봇 생성 및 설정

슬랙 앱 생성

외부에서 슬랙으로 메시지를 보내려면 봇을 생성해야 합니다. 봇은 사용자를 대신하여 슬랙에 메시지를 전송하거나 특정 작업을 자동으로 수행하는 역할을 합니다. 이번 글에서 사용할 @slack/web-api 라이브러리는 봇을 활용해 슬랙에 메시지를 전송합니다.

 

먼저, 슬랙 앱을 생성해야 합니다. 슬랙 API 페이지에 접속하여 오른쪽 상단에 있는 “Your Apps”를 클릭합니다.

슬랙 API 페이지

"Create New App"을 클릭하여 앱을 생성합니다.

Your Apps 페이지

 

이어서 나오는 팝업에서는 "From scratch"를 선택하고 App Name과 워크스페이스를 선택하여 앱을 생성합니다.

 

Create New App 팝업

“From a manifest”는 설정이 미리 정의되어 있는 Manifest 파일을 업로드하여 한번에 설정하는 방식으로 주로 여러 개의 슬랙 워크스페이스에 동일한 설정을 적용할 때 사용합니다. ”From scratch”는 설정 페이지에서 하나씩 구성하는 방식으로 슬랙 API를 처음 접하는 사용자에게 적합니다.

 

슬랙 권한 설정

앱 생성을 완료했다면, 슬랙 봇이 채널에 메시지를 전송할 수 있도록 권한을 부여해야 합니다.

 

Features -> OAuth & Permissions로 이동합니다.

Feature -> OAuth & Permissions

 

아래로 조금 내리면 "Scopes" 부분이 있습니다. 여기서 "Bot Token Scopes"에 아래의 권한을 추가합니다.

  • channels:read
  • chat:write
  • chat:write:public

Features -> OAuth & Permissions의 Scopes

 

OAuth Token 생성

@slack/web-api 라이브러리를 사용하려면 OAuth 토큰이 필요합니다. 이 토큰을 발급받으려면 생성한 앱을 슬랙에 추가해야 합니다.

 

Features -> OAuth & Permissions로 이동하면 "OAuth Tokens" 부분에 "Install to ..." 버튼이 있는 것을 확인할 수 있습니다. 하지만, 클릭해보면 "<App Name> 앱에 설치할 봇 사용자가 없습니다"라는 에러 메시지가 보이는데요.

Features -> OAuth & Permissions의 OAuth Tokens

 

이는 앱에 봇 사용자가 설정되지 않았기 때문입니다. 슬랙에서 OAuth 토큰을 발급받으려면 앱에 봇 사용자를 추가해야 합니다. 이를 해결하기 위해서 Features -> App Home으로 이동합니다.

Features -> App Home

 

"Your App's Presence in Slack" 부분에서 Edit을 클릭하여 이름을 입력하고 봇 사용자를 추가합니다. 꼭 Display Name과 Default username을 모두 입력해 주세요. Display Name만 입력해도 완료된 것 처럼 보이지만, 실제로는 봇 사용자가 추가되지 않습니다.

Features -> App Home의 Your App’s Presence in Slack

 

추가가 완료 되었다면, 아래와 같이 입력한 봇 사용자의 이름이 표시됩니다. 봇 사용자의 이름이 보이지 않는다면 모든 내용을 입력한 게 맞는지 확인한 후 다시 시도해 주세요.

봇 사용자 추가

 

다시 Features → OAuth & Permissions로 이동하여 "OAuth Tokens" 부분에 "Install to ..." 를 클릭하면 슬랙에 앱을 추가할 수 있습니다. 추가가 완료 되었다면 아래와 같이 OAuth 토큰을 확인할 수 있습니다.

Features → OAuth & Permissions의 OAuth Tokens

 

2. 슬랙 메시지 전송

이제 프로젝트로 돌아와서 @slack/web-api 라이브러리를 사용하여 슬랙에 메시지를 전송하는 기능을 구현하겠습니다.

 

먼저, @slack/web-api를 설치합니다.

$ pnpm add @slack/web-api

 

.env 파일을 생성한 후 위에서 발급한 OAuth 토큰을 아래와 같이 추가합니다.

[.env]

SLACK_OAUTH_TOKEN=<YOUR_OAUTH_TOKEN>

 

배포 시 환경변수를 Lambda에 등록하기 위해서 serverless.yml 파일을 수정해야 합니다. Lambda에 환경변수를 등록하려면 functions 부분에 environment 속성을 추가합니다. .env 파일은 서버리스 프레임워크에서 자동으로 인식하기 때문에 별도의 처리가 필요하지 않습니다.

[serverless.yml]

...

functions:
  notifyAll:
    handler: src/handler.notifyAll
    events:
      - schedule: rate(1 hour)
    environment:
      SLACK_OAUTH_TOKEN: ${env:SLACK_OAUTH_TOKEN}

 

이제 슬랙에 메시지를 보내는 기능을 담당하는 서비스를 만듭니다. src/service 폴더 아래에 slack.service.ts 파일을 생성한 후, 아래와 같이 작성합니다. 슬랙 Web API는 한 번에 여러 개의 메시지를 보내는 기능을 제공하지 않으므로, 이를 처리하기 위해 sendAll 메소드를 추가했습니다. 또한, 채널당 초당 1개의 메시지만 보낼 수 있는 제한이 있기 때문에 메시지를 보내는 간격을 조절하기 위해서 딜레이 하는 부분을 추가하였습니다.

[src/service/slack.service.ts]

import { WebClient } from '@slack/web-api';

class SlackService {
  private readonly _client: WebClient;
	
  constructor() {
    this._client = new WebClient(process.env.SLACK_OAUTH_TOKEN);
  }
	
  async send(args: { channel: string; text: string }): Promise<void> {
    await this._client.chat.postMessage(args);
  }
	
  async sendAll(args: { channel: string, texts: string[] }): Promise<void> {
    const { channel, texts } = args;
    for await (const text of texts) {
      await this.send({ channel, text });
      await new Promise((resolve) => setTimeout(resolve, 1500));
    }
  }
}

export const slackService = new SlackService();

 

이제 GitHubReleaseNotificationService에서 SlackService를 활용하여 슬랙에 메시지를 전송하는 부분을 추가합니다.

[src/service/github-release-notification.ts]

...

// add
import { slackService } from './slack.service';

export class GitHubReleaseNotificationService {
  ...
  
  // add
  private generateMessages(args: {
    packageName: string;
    items: FeedItem[];
  }): string[] {
    const { packageName, items } = args;
    const messages = items.map(({ version, link }) => {
      return `<!channel>\n🚀 새로운 ${packageName} 릴리스가 도착했습니다!\n버전: ${version}\n링크: ${link}`;
    });
    return messages;
  }
	
  async run(): Promise<void> {
    const feedSources = await this.loadFeedSources();
    for await (const feedSource of feedSources) {
      const { packageName, sourceUrl, slackChannelId } = feedSource;
      
      // RSS 피드 조회
      const items = await this.parseRSS(sourceUrl);
      
      // 중복 알림 제거
      // 알림 전송
      // add
      const slackMessages = this.generateMessages({
        packageName,
        items,
      });
      await slackService.sendAll({ 
        channel: slackChannelId,
        texts: slackMessages
      });
      
      // 알림 내역 저장
    }
  }
}

 

지금까지 작성한 코드를 테스트 하기 위해 sls invoke 명령어를 사용하여 함수를 실행합니다. 실행 후 슬랙 채널에 알림이 정상적으로 도착했는지 확인합니다.

$ sls invoke local --function notifyAll

알림이 도착했습니다!

 

 

다음 글에서는

이번 글에서는 슬랙 봇을 생성하고, @slack/web-api 라이브러리를 활용하여 슬랙에 메시지를 보내는 기능을 구현했습니다. 다음 글에서는 DynamoDB를 활용하여 중복 알림을 방지하고, 알림 내역을 저장하는 기능을 구현해 보겠습니다.

 

2025.02.15 - [Nodejs] - 슬랙으로 RSS 알림 보내기 (1) - 개요

2025.02.19 - [Nodejs] - 슬랙으로 RSS 알림 보내기 (2) - 프로젝트 설정

2025.02.23 - [Nodejs] - 슬랙으로 RSS 알림 보내기 (3) - RSS 피드 가져오기

2025.02.26 - [Nodejs] - 슬랙으로 RSS 알림 보내기 (4) - 슬랙에 메시지 전송하기

2025.03.01 - [Nodejs] - 슬랙으로 RSS 알림 보내기 (5) - 중복 알림 방지하기

2025.03.03 - [Nodejs] - 슬랙으로 RSS 알림 보내기 (6) - 배포

반응형