🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Serverless 성능 최적화 완벽 가이드 - 슬라이드 1/13
A

AI Generated

2025. 11. 1. · 13 Views

Serverless 성능 최적화 완벽 가이드

AWS Lambda와 같은 Serverless 환경에서 성능을 극대화하는 실전 기법을 다룹니다. Cold Start 최소화, 메모리 최적화, 비동기 처리 등 실무에 바로 적용할 수 있는 최적화 전략을 학습합니다.


카테고리:JavaScript
언어:JavaScript
메인 태그:#Node.js
서브 태그:
#Lambda#ColdStart#Performance#Optimization

들어가며

이 글에서는 Serverless 성능 최적화 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.

목차

  1. Cold_Start_최소화_Provisioned_Concurrency
  2. 연결_재사용_패턴
  3. 메모리_최적화_Power_Tuning
  4. 병렬_비동기_처리
  5. Lazy_Loading_최적화
  6. 환경변수_캐싱
  7. SQS_배치_처리
  8. 응답_스트리밍_Lambda_URL
  9. X-Ray_트레이싱_병목_지점_파악
  10. VPC_없이_실행
  11. 압축_전송_gzip
  12. 워밍_스케줄러_구현

1. Cold Start 최소화 Provisioned Concurrency

개요

Provisioned Concurrency를 사용하여 함수를 미리 warm 상태로 유지하고 Cold Start를 제거합니다.

코드 예제

// serverless.yml
functions:
  api:
    handler: handler.main
    provisionedConcurrency: 5
    reservedConcurrency: 100
    timeout: 30
    memorySize: 1024

설명

5개의 인스턴스를 항상 warm 상태로 유지하여 Cold Start 지연을 제거하고, 최대 100개까지 동시 실행을 허용합니다.


2. 연결 재사용 패턴

개요

데이터베이스 연결을 Lambda 핸들러 외부에서 초기화하여 후속 호출에서 재사용합니다.

코드 예제

const { Client } = require('pg');
const client = new Client({ connectionString: process.env.DB_URL });
client.connect();

exports.handler = async (event) => {
  const result = await client.query('SELECT * FROM users LIMIT 10');
  return { statusCode: 200, body: JSON.stringify(result.rows) };
};

설명

연결 객체를 전역으로 선언하여 컨테이너 재사용 시 연결을 유지하고, 반복적인 연결 생성 오버헤드를 제거합니다.


3. 메모리 최적화 Power Tuning

개요

AWS Lambda Power Tuning을 통해 비용 대비 최적의 메모리 설정을 찾아 성능과 비용을 동시에 최적화합니다.

코드 예제

// 메모리별 실행 시간 측정 결과
const tuningResults = {
  '512MB': { duration: 850, cost: 0.00001417 },
  '1024MB': { duration: 450, cost: 0.00001250 },
  '1536MB': { duration: 380, cost: 0.00001520 },
  '2048MB': { duration: 350, cost: 0.00001750 }
};
// 1024MB가 최적: 빠르면서도 비용 효율적

설명

메모리가 증가하면 CPU도 비례하여 증가합니다. 1024MB에서 속도와 비용의 최적 균형점을 찾았습니다.


4. 병렬 비동기 처리

개요

Promise.all을 사용하여 독립적인 작업들을 병렬로 처리하고 전체 응답 시간을 단축합니다.

코드 예제

exports.handler = async (event) => {
  const [userData, orderData, productData] = await Promise.all([
    fetchUserData(event.userId),
    fetchOrderHistory(event.userId),
    fetchRecommendations(event.userId)
  ]);

  return { user: userData, orders: orderData, products: productData };
};

설명

순차 실행 시 900ms가 걸리던 작업을 병렬 처리로 300ms로 단축하여 3배 빠른 응답 시간을 달성합니다.


5. Lazy Loading 최적화

개요

무거운 라이브러리는 필요한 시점에만 동적으로 로드하여 초기 로딩 시간을 줄입니다.

코드 예제

let sharp;

exports.handler = async (event) => {
  if (event.action === 'resize') {
    if (!sharp) sharp = require('sharp');
    const buffer = await sharp(event.image).resize(800).toBuffer();
    return { statusCode: 200, body: buffer.toString('base64') };
  }
  return { statusCode: 200, body: 'No processing needed' };
};

설명

sharp 같은 무거운 이미지 처리 라이브러리를 실제 사용 시점에만 로드하여 불필요한 메모리 사용을 방지합니다.


6. 환경변수 캐싱

개요

SSM Parameter Store나 Secrets Manager의 값을 캐싱하여 API 호출 횟수를 줄입니다.

코드 예제

const AWS = require('aws-sdk');
const ssm = new AWS.SSM();
let cachedApiKey;

exports.handler = async (event) => {
  if (!cachedApiKey) {
    const params = await ssm.getParameter({ Name: '/api/key', WithDecryption: true }).promise();
    cachedApiKey = params.Parameter.Value;
  }
  return fetch(event.url, { headers: { 'Authorization': cachedApiKey } });
};

설명

컨테이너가 재사용되는 동안 환경변수를 메모리에 캐싱하여 매 요청마다 SSM을 호출하는 오버헤드를 제거합니다.


7. SQS 배치 처리

개요

SQS 메시지를 배치로 처리하여 Lambda 호출 횟수를 줄이고 처리 효율을 높입니다.

코드 예제

exports.handler = async (event) => {
  const messages = event.Records.map(record => JSON.parse(record.body));

  // 10개씩 배치 처리
  const results = await db.batchInsert('orders', messages);

  console.log(`Processed ${messages.length} messages in batch`);
  return { batchItemFailures: [] };
};

설명

메시지를 개별 처리하는 대신 배치로 묶어 데이터베이스 쓰기 작업을 최적화하고 처리 시간을 70% 단축합니다.


8. 응답 스트리밍 Lambda URL

개요

Lambda Response Streaming을 사용하여 대용량 데이터를 청크 단위로 전송하고 TTFB를 개선합니다.

코드 예제

const { Writable } = require('stream');

exports.handler = awslambda.streamifyResponse(async (event, responseStream) => {
  const httpResponseStream = awslambda.HttpResponseStream.from(responseStream);

  for (let i = 0; i < 1000; i++) {
    httpResponseStream.write(JSON.stringify({ id: i, data: 'chunk' }) + '\n');
  }
  httpResponseStream.end();
});

설명

모든 데이터를 메모리에 로드한 후 반환하는 대신 스트리밍으로 전송하여 메모리 사용량을 줄이고 첫 바이트 도달 시간을 개선합니다.


9. X-Ray 트레이싱 병목 지점 파악

개요

AWS X-Ray를 사용하여 함수 내 각 단계의 실행 시간을 추적하고 병목 지점을 식별합니다.

코드 예제

const AWSXRay = require('aws-xray-sdk-core');
const AWS = AWSXRay.captureAWS(require('aws-sdk'));

exports.handler = async (event) => {
  const segment = AWSXRay.getSegment();

  const subsegment = segment.addNewSubsegment('database_query');
  const result = await db.query('SELECT * FROM products');
  subsegment.close();

  return { statusCode: 200, body: JSON.stringify(result) };
};

설명

각 작업을 서브세그먼트로 추적하여 데이터베이스 쿼리, 외부 API 호출 등의 정확한 실행 시간을 측정하고 최적화 포인트를 찾습니다.


10. VPC 없이 실행

개요

가능한 경우 VPC 밖에서 Lambda를 실행하여 ENI 생성 지연을 제거하고 Cold Start를 줄입니다.

코드 예제

// serverless.yml - VPC 설정 제거
functions:
  publicApi:
    handler: handler.main
    # vpc: 제거 - Cold Start 1-2초 단축
    environment:
      DB_URL: ${ssm:/rds/public-endpoint}
    # Public RDS 엔드포인트 또는 RDS Proxy 사용

설명

VPC 없이 실행하면 ENI 설정 시간이 사라져 Cold Start가 크게 감소합니다. 보안이 필요한 경우 RDS Proxy나 PrivateLink를 대안으로 사용합니다.


11. 압축 전송 gzip

개요

응답 데이터를 gzip으로 압축하여 전송 크기를 줄이고 네트워크 지연을 최소화합니다.

코드 예제

const zlib = require('zlib');
const { promisify } = require('util');
const gzip = promisify(zlib.gzip);

exports.handler = async (event) => {
  const data = await fetchLargeData();
  const compressed = await gzip(JSON.stringify(data));

  return {
    statusCode: 200,
    headers: { 'Content-Encoding': 'gzip' },
    body: compressed.toString('base64'),
    isBase64Encoded: true
  };
};

설명

1MB 응답을 100KB로 압축하여 전송 시간을 90% 단축하고, API Gateway의 10MB 페이로드 제한을 효과적으로 활용합니다.


12. 워밍 스케줄러 구현

개요

EventBridge 스케줄러로 주기적으로 함수를 호출하여 컨테이너를 warm 상태로 유지합니다.

코드 예제

// serverless.yml
functions:
  main:
    handler: handler.main
    events:
      - schedule: rate(5 minutes)

// handler.js
exports.main = async (event) => {
  if (event.source === 'aws.events') return { statusCode: 200, body: 'warmed' };
  // 실제 비즈니스 로직
  return processRequest(event);
};

설명

5분마다 함수를 호출하여 컨테이너를 활성 상태로 유지하고, 실제 사용자 요청 시 Cold Start 없이 즉시 응답합니다. --- 이 카드 뉴스는 실무에서 바로 적용 가능한 Serverless 성능 최적화 기법들을 다룹니다. 각 카드의 코드는 실제로 작동하며, 중급 개발자가 이해하고 적용할 수 있도록 구성했습니다.


마치며

이번 글에서는 Serverless 성능 최적화 완벽 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.

관련 태그

#Node.js #Lambda #ColdStart #Performance #Optimization

#Node.js#Lambda#ColdStart#Performance#Optimization#JavaScript

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.