[NCP] Cloud Function 기반 Slack 알림을 활용한 Object Storage 자동화 관리

Object Storage의 Lifecycle 기능을 활용해 데이터를 효율적으로 관리하고, Cloud Function을 통해 삭제된 데이터에 대해 Slack 실시간 알림을 설정하는 실습을 진행해보도록 하겠다. 

원래는 Archive Storage의 Lifecycle을 Cloud Function과 함께 사용해 관리하는 방법을 소개하려고 했습니다. 하지만 API 비용을 분석한 결과, 대규모 데이터가 아닌 경우 가격 효율성이 떨어진다고 판단하여, 먼저 소규모 데이터 관리를 위한 방법을 다루고자 한다. 주로 다음과 같은 경우에 많이 사용할 수 있습니다.

  • 주기적 데이터 백업 및 삭제
    서비스 운영 중에 생성되는 백업 데이터를 Object Storage에 일정 기간 보관하고 이후 삭제하는 경우이다. 예를 들어, 하루나 일주일 단위로 백업된 데이터를 Object Storage에 저장하고, Lifecycle 규칙을 통해 30일 후 자동 삭제되도록 설정하면 저장 공간을 확보하면서도 데이터를 효율적으로 관리할 수 있다. 
  • 임시 파일 관리
    대용량 파일을 사용자들이 업로드하는 서비스에서 임시 파일이나 작업 파일을 일정 기간 저장하고 나중에 삭제하는 사례이다.예를 들어, 사용자가 파일을 업로드하고 작업을 완료한 후, Object Storage에 남아있는 임시 파일이 7일 후 삭제되도록 하면 자동화된 파일 관리를 통해 저장 공간을 절약할 수 있다.
  • 이미지/미디어 캐시 데이터 관리
    사이트나 앱에서 사용자에게 제공하기 위해 생성되는 미디어 파일 캐시 데이터를 Object Storage에 보관할 수 있다. 예를 들어, 각 사용자가 업로드한 이미지를 변환하여 저장한 후, 일정 시간이 지난 후 삭제하거나 갱신하도록 설정할 수 있다. 이를 통해 필요할 때만 파일을 유지하며 저장 공간을 절약한다. 

앱의 상황에 따라 다르지만, 법적 요구 사항으로 인해 장기 보존이 필요한 데이터나 보존 기간이 매우 긴 데이터의 경우 Archive Storage를 사용하는 것이 적합하다. 반면, 보존 기간이 1년 이하인 데이터는 Object Storage로 관리하고, 필요 없을 시 바로 삭제하는 것이 비용 절감과 데이터 관리 효율성 측면에서 유리할 수 있다. 다음내용이 무조건적이 아니라 예시일 뿐이다. 

다음과 같은 실습 순서로 진행해보도록 하겠다. 

  1. Object Storage 생성 및 Lifecycle 설정
  2. Slack incoming web hook 토큰 생성(과정은 생략)
  3. Cloud Function Trigger 생성
  4. Cloud Function Action 생성
  5. Object Storage의 Delete 이벤트 트리거를 통한 Cloud Function 액션 테스트

1. Object Storage 생성 및 Lifecycle 설정

Object Storage를 생성하고, 경로를 폴더 형태로 구분하여 lifecycle 정책을 적용하겠다. 현재는 테스트만 진행할 예정이므로, Object Storage의 권한은 모두 공개 설정으로 진행하였다. 

다음과 같이 정책 유형은 '만료 삭제'로 설정한다. '이관'이나 '이관 후 삭제'는 Archive Storage와 연동할 때 사용하는 옵션이다. 이 폴더에 있는 backup 이름의 리소스는 30일이 지나면 자동으로 삭제되도록 lifecycle을 구성한다. 접두어는 필요에 따라 자유롭게 지정하면 된다.

2. Slack incoming web hook 토큰 생성

Slack에 알림을 설정하려면 Slack Webhook API가 필요하다. Webhook 발급 방법은 다양한 블로그나 공식 문서에 자세히 나와 있으므로 여기서는 생략한다.

참고자료 : https://api.slack.com/messaging/webhooks

다음과 같이 Slack incoming Webhook을 추가하였습니다. Slack incoming Webhook URL은 따로 메모해둔다.

3. Cloud Function Action 생성

Object Storae의 Delete 이벤트에 트리거 해줄 것이다. 

트리거 종류는 Object Storage로 설정하겠다. Cloud Function의 디폴트 파라미터는 JSON 형식이지만, 이번 실습에서는 코드에 직접 파라미터 값을 지정할 예정이므로 별도로 설정하지 않겠다.

조금 전에 생성한 버킷을 지정한 후 이벤트를 생성하도록 하겠다. 

Delete 이벤트 외에도 객체 생성(Create)에 대한 전체 이벤트를 설정할 수 있다. 하지만 이번 실습에서는 Delete 이벤트만 사용할 것이기 때문에 해당 항목만 지정하겠다. 또한 필터를 사용하여, backup이라는 이름을 포함한 파일에 대해서만 트리거가 작동하도록 설정하였다. 

다음과 같이 Delete 이벤트에 대한 트리거가 정상적으로 생성되었다. 이제 Cloud Function의 Action을 생성할 차례이며, 참고로 트리거와 액션의 생성 순서는 바뀌어도 무관하다.

4. Cloud Function Action 생성

좀 전에 생성해준 트리거를 연동시켜준다. 

패키지는 사용하지 않고 일반 액션으로 구성하겠다. 소스 코드에는 아래 코드를 그대로 입력하면 되고, Slack Webhook URL은 webhookURL 변수에 미리 발급받아둔 값을 직접 넣으면 된다. 디폴트 파라미터는 생략하였지만, 변수 정의가 많아질 경우에는 이를 활용해 코드의 재사용성을 높이는 것도 좋은 방법이다.

const https = require('https');

exports.main = async (event) => {
    console.log('Received event:', JSON.stringify(event, null, 2)); // 수신된 이벤트 로그

    const webhookUrl = ''; 

    // 이벤트에서 필요한 정보 추출
    const bucketName = event.container_name; // 버킷 이름
    const objectName = event.object_name;     // 삭제된 객체 이름
    const eventType = event.event_type;       // 이벤트 타입

    // Slack으로 보낼 메시지 설정
    const message = {
        text: `A file has been deleted: *Bucket:* ${bucketName}, *Object:* ${objectName}, *Event Type:* ${eventType}`
    };

    console.log('Slack message:', JSON.stringify(message, null, 2)); // Slack 메시지 로그

    const data = JSON.stringify(message);
    const options = {
        hostname: 'hooks.slack.com',
        path: new URL(webhookUrl).pathname,
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Content-Length': Buffer.byteLength(data), // Buffer.byteLength로 길이 계산
        },
    };

    return new Promise((resolve, reject) => {
        const req = https.request(options, (res) => {
            let responseBody = '';

            res.on('data', (chunk) => {
                responseBody += chunk;
            });

            res.on('end', () => {
                console.log(`Slack response: ${responseBody}`); // Slack 응답 로그
                resolve({
                    statusCode: res.statusCode,
                    body: responseBody,
                });
            });
        });

        req.on('error', (e) => {
            console.error(`Error: ${e.message}`); // 오류 로그
            reject({
                statusCode: 500,
                body: `Error: ${e.message}`,
            });
        });

        req.write(data);
        req.end();
    });
};

Cloud Function은 private 서브넷의 kr2 영역에서만 지원된다. 따라서 해당 기능을 사용하려면 kr2 영역에 private 서브넷을 생성한 뒤, NAT Gateway를 연결해 외부 통신이 가능하도록 라우팅 설정을 해야 한다. 서브넷과 NAT Gateway 간의 라우팅 구성 과정은 생략하겠으며, Cloud Function의 리소스는 기본값(Default)으로 설정해 진행하도록 하겠다.

Cloud Funtion의 리소스 정보
- Timeout
기본값: 60,000 ms (60초)
설정 가능 범위: 500 ms ~ 300,000 ms

- Memory
기본값: 256 MB
설정 가능 범위: 128 MB ~ 1,024 MB

Cloud Function에 액션과 트리거 설정이 완료되었다. 현재 설정된 Lifecycle 정책은 30일이 지나야 삭제 이벤트가 발생하므로, 테스트를 위해 Object Storage에 backup 네이밍 파일을 직접 업로드한 뒤 수동으로 삭제하여 Cloud Function이 정상적으로 작동하는지 확인해보도록 하겠다.

5. Object Storage의 Delete 이벤트 트리거를 통한 Cloud Function 액션 테스트

Action에 대한 테스트는 별도로 실행하여 미리 테스트를 진행할 수 있다. 

액션 테스트를 실행 해본 결과 액션은 정상적으로 작동하는것을 확인할 수 있다.

다음은 바로 Delete 이벤트에 트리거가 잘되었는지 테스트해보도록 하겠다. 

backup의 이름이 된 파일을 Object Storage에 올리고 삭제해보도록하겠다. 

backup 파일을 삭제하였더니, Delete 이벤트 트리거가 정상적으로 작동하여 Slack으로 알림이 전송되었다. 트리거의 경로를 test/backup_으로 지정해두었기 때문에, 해당 경로의 파일명에 대해서만 알림을 받을 수 있다.

Lifecycle 정책이 지정되어 있으므로, 설정된 기간이 경과하여 파일이 자동으로 삭제되는 경우에도 동일하게 Slack 알림을 받을 수 있을 것이다.

'NCP' 카테고리의 다른 글

[NCP] Global DNS 도메인 매핑  (0) 2024.12.31
[NCP] Secret Manager API  (0) 2024.12.31
[NCP] SSL VPN  (0) 2024.12.31
[NCP] STS를 통한 임시자격 증명  (0) 2024.12.31
[NCP] 블록 스토리지 확장법(KVM, XEN)  (0) 2024.12.31