Dev / App

Lambda@Edge 고급 로깅 제어 기능

Lambda@Edge

10 min read
Lambda@Edge 고급 로깅 제어 기능

안녕하세요 여러분!
이번 글에서는 Lambda@Edge의 고급 로깅 제어 기능에 대해서 다루려고 합니다.

기능을 탐색하기에 앞서, 우선 Lambda@Edge는 어떤 서비스인지부터 살펴봅시다!

Lambda@Edge는 Amazon CloudFront의 기능 중 하나로서 애플리케이션의 사용자에게 더 가까운 위치에서 코드를 실행하여 성능을 개선하고 지연 시간을 단축할 수 있게 해주는 서비스인데요!

예를 들어 우리가 어떤 웹사이트나 앱을 이용할 때 그 정보가 아주 멀리 떨어진 나라에 있다면, 우리에게 도달하기까지 시간이 걸릴 수 있어요.

Amazon CloudFront는 전 세계에 있는 엣지 서버에 콘텐츠를 미리 저장해두고, 사용자와 가장 가까운 서버에서 빠르게 전달해주는 역할을 합니다. 마치 가까운 물류창고에서 바로 배송하는 것처럼요.

하지만, 콘텐츠 전달 외에도 다음과 같은 처리가 필요할 수 있는데요,

이런 작업은 원래 원본 서버에서 실행되었지만,
Lambda@Edge를 통해 CloudFront의 엣지 서버에서 바로 코드를 실행할 수 있게 되었습니다.

또한 Lambda@Edge를 사용하면 전 세계 여러 위치에 있는 인프라를 프로비저닝하거나 관리하지 않아도 되며,
사용한 컴퓨팅 시간만큼만 비용을 지불하고, 코드가 실행되지 않을 때는 요금이 부과되지 않는다고 해요.

1. 본격적으로, 고급 로깅 제어 기능?

2025년 4월 14일, AWS에서 Lambda@Edge의 고급 로깅 제어 기능을 발표했습니다.

이제 AWS Lambda@Edge는 AWS Lambda의 고급 로깅 제어 기능을 통해 엣지에서 함수 로그를 캡처, 처리, 사용하는 방식을 개선하도록 지원하는데요!

이 기능을 통하여 로깅 데이터를 보다 효과적으로 제어하여 애플리케이션 동작을 좀 더 쉽게 모니터링하고 문제를 신속하게 해결할 수 있게 되었습니다.

2. 실습해봅시다!

① 우선 Lambda 함수를 생성하고 CloudFront 배포에 연결하du Lambda@Edge를 배포를 해줍니다.

코드 보기
'use strict';

exports.handler = (event, context, callback) => {
console.log("=== Lambda@Edge 애플리케이션 로그 레벨 테스트 시작 ===");

// TRACE: 가장 상세한 흐름 추적용
console.trace("[TRACE] 함수 시작");

// DEBUG: 디버깅을 위한 상세 데이터 출력
console.debug("[DEBUG] event 구조:\n" + JSON.stringify(event, null, 2));

// INFO: 정상적인 흐름 설명
console.info("[INFO] 요청이 정상적으로 수신되었습니다.");

// WARN: 비정상은 아니지만, 주의가 필요한 상황
console.warn("[WARN] 이것은 경고 로그입니다. 기능에는 영향 없습니다.");

// ERROR: 오류 발생 상황 시뮬레이션 (하지만 실행 계속됨)
try {
    throw new Error("테스트용 에러입니다.");
} catch (err) {
    console.error("[ERROR] 예외 발생: " + err.message);
}

// FATAL: 실제로는 console.fatal이 없으므로 log로 대체
console.log("[FATAL] FATAL 수준의 로그입니다. 치명적 오류처럼 로그만 출력됩니다.");

// 실험 쿠키 처리 로직 (기존 로직 유지)
const request = event.Records[0].cf.request;
const headers = request.headers;

const cookieExperimentA = 'X-Experiment-Name=A';
const cookieExperimentB = 'X-Experiment-Name=B';
const pathExperimentA = '/experiment-group/control-pixel.jpg';
const pathExperimentB = '/experiment-group/treatment-pixel.jpg';

let experimentUri;
if (headers.cookie) {
    for (let i = 0; i < headers.cookie.length; i++) {
        const val = headers.cookie[i].value;
        if (val.includes(cookieExperimentA)) {
            console.info("[INFO] A 실험군 쿠키 발견");
            experimentUri = pathExperimentA;
            break;
        } else if (val.includes(cookieExperimentB)) {
            console.info("[INFO] B 실험군 쿠키 발견");
            experimentUri = pathExperimentB;
            break;
        }
    }
}

if (!experimentUri) {
    console.info("[INFO] 쿠키 없음 → 랜덤 할당");
    experimentUri = Math.random() < 0.5 ? pathExperimentA : pathExperimentB;
}

request.uri = experimentUri;
console.info("[INFO] 최종 request.uri: " + request.uri);

console.trace("[TRACE] 함수 종료");
console.log("=== Lambda@Edge 애플리케이션 로그 레벨 테스트 끝 ===");

callback(null, request);

};

② Lambda 함수의 로깅 구성에서 JSON을 선택하고, 애플리케이션 로그 레벨과 시스템 로그 수준을 최고로 하여 저장되는 로그를 살펴보겠습니다.

③ JSON 형식의 애플리케이션 및 시스템 로그를 확인할 수 있습니다.

☑️ 애플리케이션 로그 레벨

애플리케이션 로그의 JSON 형식

☑️ 시스템 로그 레벨

시스템 로그의 JSON 형식

2-4. 로그 예시는 다음과 같습니다!

애플리케이션 로그

Node.js Lambda 함수 로깅 및 모니터링

  • "timestamp" - 로그 메시지가 생성된 시간
  • "level" - 메시지에 할당된 로그 수준
  • "message" - 로그 메시지의 내용
  • "requestId" - 함수 간접 호출의 고유한 요청 ID
{
    "timestamp": "2025-07-13T10:34:27.626Z",
    "level": "TRACE",
    "requestId": "988fc8b2-5516-47bb-ba3e-efbba0d620ab",
    "message": "[TRACE] 함수 시작"
}
{
    "timestamp": "2025-07-13T10:34:27.626Z",
    "level": "TRACE",
    "requestId": "988fc8b2-5516-47bb-ba3e-efbba0d620ab",
    "message": "[TRACE] 함수 종료"
}
{
    "timestamp": "2025-07-13T10:34:27.626Z",
    "level": "DEBUG",
    "requestId": "988fc8b2-5516-47bb-ba3e-efbba0d620ab",
    "message": "[DEBUG] event 구조:\n{\n  \"Records\": [\n    {\n      \"cf\": {\n        \"config\": {\n          \"distributionDomainName\": \"dnl8fxr1twnt5.cloudfront.net\",\n          \"distributionId\": \"E3S1C2W6YFYK28\",\n          \"eventType\": \"origin-request\",\n          \"requestId\": \"KuzoRmMGKWaF_NDgYgecnEg_cRe5cY1phQzrUdoJq4sVboPd1AetsQ==\"\n        },\n        \"request\": {\n          \"clientIp\": \"170.106.163.84\",\n          \"headers\": {\n            \"x-forwarded-for\": [\n              {\n                \"key\": \"X-Forwarded-For\",\n                \"value\": \"170.106.163.84\"\n              }\n            ],\n            \"user-agent\": [\n              {\n                \"key\": \"User-Agent\",\n                \"value\": \"Amazon CloudFront\"\n              }\n            ],\n            \"via\": [\n              {\n                \"key\": \"Via\",\n                \"value\": \"1.1 f9c59ce0e830fcb72cbcdb26622739f0.cloudfront.net (CloudFront)\"\n              }\n            ],\n            \"accept-encoding\": [\n              {\n                \"key\": \"Accept-Encoding\",\n                \"value\": \"gzip\"\n              }\n            ],\n            \"pragma\": [\n              {\n                \"key\": \"Pragma\",\n                \"value\": \"no-cache\"\n              }\n            ],\n            \"upgrade-insecure-requests\": [\n              {\n                \"key\": \"Upgrade-Insecure-Requests\",\n                \"value\": \"1\"\n              }\n            ],\n            \"host\": [\n              {\n                \"key\": \"Host\",\n                \"value\": \"xxxxxx-s3.s3.ap-northeast-2.amazonaws.com\"\n              }\n            ],\n            \"cache-control\": [\n              {\n                \"key\": \"Cache-Control\",\n                \"value\": \"no-cache\"\n              }\n            ]\n          },\n          \"method\": \"GET\",\n          \"origin\": {\n            \"s3\": {\n              \"authMethod\": \"none\",\n              \"customHeaders\": {},\n              \"domainName\": \"xxxxxx-s3.s3.ap-northeast-2.amazonaws.com\",\n              \"path\": \"\",\n              \"readTimeout\": 30,\n              \"responseCompletionTimeout\": 0\n            }\n          },\n          \"querystring\": \"\",\n          \"uri\": \"/\"\n        }\n      }\n    }\n  ]\n}"
}
{
    "timestamp": "2025-07-13T10:34:27.626Z",
    "level": "INFO",
    "requestId": "988fc8b2-5516-47bb-ba3e-efbba0d620ab",
    "message": "=== Lambda@Edge 애플리케이션 로그 레벨 테스트 시작 ==="
}
{
    "timestamp": "2025-07-13T10:34:27.626Z",
    "level": "INFO",
    "requestId": "988fc8b2-5516-47bb-ba3e-efbba0d620ab",
    "message": "[INFO] 요청이 정상적으로 수신되었습니다."
}
{
    "timestamp": "2025-07-13T10:34:27.626Z",
    "level": "INFO",
    "requestId": "988fc8b2-5516-47bb-ba3e-efbba0d620ab",
    "message": "[INFO] 최종 request.uri: /experiment-group/treatment-pixel.jpg"
}
{
    "timestamp": "2025-07-13T10:34:27.626Z",
    "level": "INFO",
    "requestId": "988fc8b2-5516-47bb-ba3e-efbba0d620ab",
    "message": "=== Lambda@Edge 애플리케이션 로그 레벨 테스트 끝 ==="
}
{
    "timestamp": "2025-07-13T10:34:27.615Z",
    "level": "WARN",
    "message": "AWS Lambda plans to remove support for callback-based function handlers starting with Node.js 24. You will need to update this function to use an async handler to use Node.js 24 or later. For more information and to provide feedback on this change, see https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/issues/137. To disable this warning, set the AWS_LAMBDA_NODEJS_DISABLE_CALLBACK_WARNING environment variable."
}
{
    "timestamp": "2025-07-13T10:34:27.626Z",
    "level": "WARN",
    "requestId": "988fc8b2-5516-47bb-ba3e-efbba0d620ab",
    "message": "[WARN] 이것은 경고 로그입니다. 기능에는 영향 없습니다."
}
{
    "timestamp": "2025-07-13T10:34:27.626Z",
    "level": "ERROR",
    "requestId": "988fc8b2-5516-47bb-ba3e-efbba0d620ab",
    "message": "[ERROR] 예외 발생: 테스트용 에러입니다."
}
{
    "timestamp": "2025-07-13T10:34:27.626Z",
    "level": "INFO",
    "requestId": "988fc8b2-5516-47bb-ba3e-efbba0d620ab",
    "message": "[FATAL] FATAL 수준의 로그입니다. 치명적 오류처럼 로그만 출력됩니다."
}
{
    "time": "2025-07-13T10:34:27.466Z",
    "type": "platform.initStart",
    "record": {
        "initializationType": "on-demand",
        "phase": "init",
        "runtimeVersion": "nodejs:22.v48",
        "runtimeVersionArn": "arn:aws:lambda:us-east-1::runtime:3319d7328c2e45f97764ca1c004269cab40102f3f1c188ec9a509d8e9c5db574",
        "functionName": "us-east-1.xxxxxx-LambdaEdge-test",
        "functionVersion": "5",
        "instanceId": "2025/07/13/[5]205436cde12d49e4be8e45f0443d912c",
        "instanceMaxMemory": 134217728
    }
}
{
    "time": "2025-07-13T10:34:27.620Z",
    "type": "platform.initRuntimeDone",
    "record": {
        "initializationType": "on-demand",
        "phase": "init",
        "status": "success"
    }
}
{
    "time": "2025-07-13T10:34:27.620Z",
    "type": "platform.initReport",
    "record": {
        "initializationType": "on-demand",
        "phase": "init",
        "status": "success",
        "metrics": {
            "durationMs": 154.494
        }
    }
}
{
    "time": "2025-07-13T10:34:27.624Z",
    "type": "platform.start",
    "record": {
        "requestId": "988fc8b2-5516-47bb-ba3e-efbba0d620ab",
        "functionArn": "arn:aws:lambda:us-east-1:782621889128:function:us-east-1.xxxxxx-LambdaEdge-test:5",
        "version": "5"
    }
}
{
    "time": "2025-07-13T10:34:27.692Z",
    "type": "platform.runtimeDone",
    "record": {
        "requestId": "988fc8b2-5516-47bb-ba3e-efbba0d620ab",
        "status": "success",
        "spans": [
            {
                "name": "responseLatency",
                "start": "2025-07-13T10:34:27.624Z",
                "durationMs": 48.63
            },
            {
                "name": "responseDuration",
                "start": "2025-07-13T10:34:27.673Z",
                "durationMs": 0.082
            },
            {
                "name": "runtimeOverhead",
                "start": "2025-07-13T10:34:27.673Z",
                "durationMs": 19.26
            }
        ],
        "metrics": {
            "durationMs": 68.163,
            "producedBytes": 845
        }
    }
}
{
    "time": "2025-07-13T10:34:27.693Z",
    "type": "platform.report",
    "record": {
        "requestId": "988fc8b2-5516-47bb-ba3e-efbba0d620ab",
        "metrics": {
            "durationMs": 68.582,
            "billedDurationMs": 69,
            "memorySizeMB": 128,
            "maxMemoryUsedMB": 75,
            "initDurationMs": 154.494
        },
        "status": "success"
    }
}

3. 마무리

이번 기능을 통해 Lambda@Edge에서도 더욱 정밀한 디버깅이 가능해질 것 같습니다.문제를 빠르게 파악하고, 안정적인 서비스를 제공하는 데 큰 도움이 될 것으로 기대됩니다.

CDN도 안랩클라우드메이트와 함께, 어떠실까요?
감사합니다. 😊

Share This Post

Check out these related posts

개발팀의 애자일 도입 이야기2

개발팀의 애자일 도입 이야기 1

Amazon CloudWatch RUM