ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • aws sqs를 이용한 lambda로 fcm push 전송하기
    Backend/NestJS 2024. 1. 4. 18:37

     

    현재 Cron으로 특정 시간대에 push 알림이 동작한다.

    봇서버 하나에서 모든 처리를 다 해서, Message Queue를 이용해 lambda에서 푸시를 전송하기로 했다.

     

     


     

    목차

    1. AWS SQS 생성

    2. NestJS SQS 처리 코드 작성(producer / customer)

    3. AWS Lambda 코드 작성

    4. AWS Lambda 생성 및 설정

     


     

    1. AWS SQS 생성

     

     

     

    푸시 알림의 경우 FIFO일 필요가 없어서, 스탠다드를 선택했다.

    그리고 이름을 지정해준다.

    따로 더 설정할게 없으면 스크롤을 내려서 생성 버튼을 누른다.

     

    생성이 되었다면,

    Name, URL, Region을 복사해두자.

     

     


     

    2. NestJS SQS 처리 코드 작성(producer / customer)

     

    코드 작성에 앞서 아래 2개의 모듈을 설치해주자.

    aws-sdk의 경우 aws-cli가 설치되었다면 굳이 안해도 된다.

    $ pnpm install --save aws-sdk
    $ pnpm install --save @ssut/nestjs-sqs

     

     

    producer 모듈

    아까 복사해둔 값을 넣어주자.

    // modules/sqs/sqs-producer.module.ts
    
    import { Module } from '@nestjs/common';
    import { SqsModule } from '@ssut/nestjs-sqs';
    import * as AWS from 'aws-sdk';
    import { SqsMessageProducer } from './sqs-message-producer.service';
    
    // aws-cli 설치 후 configure 설정을 했다면 제외 해도 된다.
    AWS.config.update({
        region: "", // aws region
        accessKeyId: "", // aws access key id
        secretAccessKey: "" // aws secret access key
    });
    
    @Module({
        imports: [
            SqsModule.register({
                consumers: [],
                producers: [
                    {
                        name: "test", // SQS 이름
                        queueUrl: "", // SQS URL
                        region: ""
                    },
                ]
            })
        ],
        controllers: [],
        providers: [SqsMessageProducer],
        exports: [SqsMessageProducer]
    })
    export class SqsProducerModule { }

     

    producer 서비스 코드를 작성하자.

    // modules/sqs/sqs-message-producer.service.ts
    
    import { Injectable } from '@nestjs/common';
    import { SqsService } from '@ssut/nestjs-sqs';
    
    @Injectable()
    export class SqsMessageProducer {
        constructor(private readonly sqsService: SqsService) { }
        async sendMessage(body: any, queuename: string) {
            const message: any = {
                id: body.id,
                body,
                // groupId: "1",		// FIFO인 경우 추가 해야함
                // deduplicationId: "1"	// FIFO인 경우 추가 해야함
            };
            await this.sqsService.send(queuename, message);
        }
    }

     

     

     

    customer 관련 기능은 필요없으니 제외 한다.

    궁금한 경우 아래 레퍼런스를 참고하면 되겠다.

     

    레퍼런스 : https://levelup.gitconnected.com/scaling-your-nest-js-application-with-amazon-simple-queue-service-sqs-dac7f2d97648

     

     

    끝으로 app.module에 producer 모듈을 추가해주자.

    // app.module.ts
    
    import { Module } from '@nestjs/common';
    import { AppController } from './controllers/app.controller';
    import { AppService } from './app.service';
    ...
    import { SqsProducerModule } from './modules/sqs-producer.module';
    
    @Module({
      imports: [
      ...
        SqsProducerModule,
      ],
      controllers: [AppController],
      providers: [AppService],
    })
    export class AppModule { }

     

     

    자 이제 기본 코드는 끝났고,

     

    이제 큐에 값을 전송해보자.

    // modules/push/push.service.ts
    
    ...
    import { SqsMessageProducer } from '../sqs/sqs-message-producer.service';
    
    
    @Injectable()
    export class PushService {
      constructor(
      	...
        private readonly sqsProducer: SqsMessageProducer,
      ) { }
      
      
    ...
    
    // Send to SQS
     await this.sqsProducer.sendMessage({	
     	// JSON 양식은 자유다,
      id: 'TEST_PUSH',
      body: {
        token,
        title,
        message,
        contents
      }
    }, process.env.SQS_NAME);	// "test"
    
    
    ...
    
    
    }

     

     

     


     

    3. AWS Lambda 코드 작성

     

    // index.mjs
    
    import fcm from "firebase-admin"; // v11.4.1
    
    fcm.initializeApp({
      credential: fcm.credential.cert({	 // firebase-adminsdk.json 값 입력한다.
      "type": "",
      "project_id": "",
      "private_key_id": "",
      "private_key": "",
      "client_email": "",
      "client_id": "",
      "auth_uri": "",
      "token_uri": "",
      "auth_provider_x509_cert_url": "",
      "client_x509_cert_url": ""
      }),
    });
    
    async function sendDataMessage(
      fcm_token,
      title = "TEST_TITLE",
      msg = "TEST_MESSAGE",
      customContent
    ) {
    
      const message = {
        tokens: [fcm_token],
        notification: {
          title: title,
          body: msg,
        },
        data: customContent,
        apns: {
          payload: {
            aps: {
              "content-available": 1,
            },
          },
        },
      };
    
      try {
        const response = await fcm.messaging().sendMulticast(message);
        
        if (response.failureCount > 0) {
          return { success: false };
        }
        
        return { success: true };
        
      } catch (e) {
        console.error(`fcm send error: ${e}`);
        return { success: false, e };
      }
    }
    
    export const handler = async (event, context, callback) => {
    
      if (!event.Records || !event.Records[0] || !event.Records[0].body) {
        console.log("Empty push data!");
        return {
          statusCode: 1001,
          body: JSON.stringify("Empty push data!"),
        };
      }
    
      const eventData = JSON.parse(event.Records[0].body);
    
      const ret = await sendDataMessage(
        eventData.body.token,
        eventData.body.title,
        eventData.body.message,
        eventData.body.content
      );
    
      const response = {
        statusCode: 200,
        body: JSON.stringify(ret),
      };
      return response;
    };

     

      코드 작성이 끝났다면,

    npm 모듈을 설치해주고, .zip 압축해서 lambda 코드에 업로드 해주면 된다.

     

     


     

    4. AWS Lambda 생성 및 설정

     

     

     

    참고로 람다 생성은 간단하다.

     

    패키지를 설치하니 용량이 5MB를 넘어서 바로 업로드 할 수 없고 S3에 저장해서 업로드 했다.

     

    S3에 업로드된 파일 주소를 복붙하면 된다.

     

     

    업로드 성공!

    다음과 같은 경고는 무시하면된다. (용량이 커서 인라인으로 코드를 확인 하지 못한다는 말이다.)

     

    이제 SQS를 트리거 등록해야하는데,

    그전에 SQS 접근을 위한 permission 설정을 해주자.

     

     

    SQS 키워드로 검색해서 아래 정책을 추가해주자.

    'AmazonSQSReadOnlyAccess',

    'AWSLambdaSQSQueueExecutionRole'

     

     

    다시 돌아와서 Add trigger를 해주자.

     

    추가가 완료 되었다면, 오버뷰에서 확인 할 수 있다.

    나의 경우 테스트용으로 2개가 연결된 상태다.

     

     


    자 이제 실행 및 테스트를 해보면 된다.

    이 다음은 대응의 영역이니 생략한다.

     

    흐름은 아래와 같다.

    sqs producer -> send to SQS => trigger Lambda -> push!

     

    댓글

Designed by Tistory.