레이블이 네트워크/인 게시물을 표시합니다. 모든 게시물 표시
레이블이 네트워크/인 게시물을 표시합니다. 모든 게시물 표시

금요일

Nginx 502 Bad Gateway 에러 완벽 해결법

AWS Lambda Task Timed Out 에러 해결 — 타임아웃 원인 6가지와 실무 대응법

🔍 검색 키워드: AWS Lambda timeout 해결, Lambda Task timed out after 해결, Lambda 타임아웃 에러, Lambda 함수 느림 원인, AWS Lambda 3초 제한 해결, Lambda cold start 해결

Lambda를 운영하다 보면 CloudWatch 로그에서 이런 메시지를 맞닥뜨리게 된다.

REPORT RequestId: abc123  Duration: 3000.21 ms  Billed Duration: 3000 ms
ERROR	Task timed out after 3.00 seconds

함수는 실행됐는데 응답 없이 죽어버렸다. 처음엔 당황���럽지만 원인은 거의 정해져 있다.


증상

  • CloudWatch 로그에 Task timed out after X.XX seconds 출력
  • Lambda 함수가 응답을 반환하지 않고 강제 종료됨
  • 간헐적으로만 발생하거나, 특정 요청에서 반드시 발생
  • API Gateway 연동 시 502 Bad Gateway 또는 504 Gateway Timeout 함께 발생

원인 1: 기본 타임아웃(3초)이 너무 짧다

Lambda 함수의 기본 타임아웃은 3초다. 이게 문제다. DB 쿼리 한 번, 외부 API 호출 한 번만 해도 금방 넘어간다.

확인 방법:

aws lambda get-function-configuration --function-name my-function \
  --query 'Timeout'
# 출력: 3

해결: 콘솔에서 [구성] → [일반 구성] → [편집] → 타임아웃 값을 늘린다.
CLI로 변경하려면:

aws lambda update-function-configuration \
  --function-name my-function \
  --timeout 30
⚠️ 주의: 타임아웃 증가는 최후의 수단이다. 먼저 왜 느린지를 찾아야 한다.

원인 2: DB 연결이 매 요청마다 새로 맺어진다

가장 많이 보는 패턴이다. Lambda 핸들러 쳸안에서 DB 커넥션을 생성하면 요청마다 TCP 핸드셰이크 + 인증 과정을 반복한다. RDS 기준으로 연결 하나 맺는 데 수백 ms가 날아간다.

나쁜 패턴:

def handler(event, context):
    conn = psycopg2.connect(host=..., dbname=..., user=..., password=...)  # 매번 생성
    cursor = conn.cursor()
    cursor.execute("SELECT ...")
    return cursor.fetchall()

좋은 패턴:

import psycopg2

# 핸들러 밖 — 컨테이너가 살아있는 동안 재사용
conn = psycopg2.connect(host=..., dbname=..., user=..., password=...)

def handler(event, context):
    cursor = conn.cursor()
    cursor.execute("SELECT ...")
    return cursor.fetchall()

Lambda 컨테이너가 재사용되는 Warm 상태에서는 전역 변수가 유지된다. 커넥션을 핸들러 밖에 두면 같은 컨테이너 인스턴스에서 재사용된다.

RDS를 쓰고 있다면 RDS Proxy 도입을 검토한다. 커넥션 풀링을 프록시가 대신 처리해줘서 Lambda와 RDS 사이의 커넥션 폭발 문제도 같이 해결된다.


원인 3: 외부 API 호출 병목 접근하연동 해에서 없다

// 이 코드는 외부 API가 응답 안 하면 Lambda 타임아웃까지 기다린다
const response = await axios.get('https://some-api.example.com/data');

외부 서비스가 느리거나 다운된 경우, 설정된 타임아웃까지 Lambda가 하염없이 대기한다.

수정 (JavaScript):

const response = await axios.get('https://some-api.example.com/data', {
  timeout: 5000,  // 5초 안에 응답 없으면 에러
});

수정 (Python):

import requests

response = requests.get(
    'https://some-api.example.com/data',
    timeout=(3.0, 10.0)  # (connect timeout, read timeout)
)

원인 4: 순차 API 호출을 직렬로 처리화고 있다

// 이러면 A + B + C 호출 시간이 전부 합산된다
const userInfo = await fetchUser(userId);
const orderInfo = await fetchOrder(userId);
const reviewInfo = await fetchReview(userId);

병렬 처리로 개선:

const [userInfo, orderInfo, reviewInfo] = await Promise.all([
  fetchUser(userId),
  fetchOrder(userId),
  fetchReview(userId),
]);

독립적인 API 호출이라면 Promise.all로 묶으면 가장 느린 요청 시간 하나로 줄어든다.


원인 5: Cold Start + VPC 설정

Lambda를 VPC 안에 넣으면 Cold Start 시간이 크게 늘어난다. CloudWatch Logs에서 Init Duration이 표시되면 Cold Start다.

REPORT RequestId: abc123  Duration: 850.00 ms  Billed Duration: 851 ms
       Init Duration: 612.38 ms

대응 방법:

  • VPC가 필요 없다면 빼는 게 제일 낫다
  • 꼭 필요하다면 Provisioned Concurrency 사용 (미리 컨테이너를 띄워둠)

원인 6: 메모리 부족 → CPU 부족

Lambda에서 메모리와 CPU는 연동된다. 메모리를 늘리면 CPU도 더 할당된다. CloudWatch Metrics에서 Max Memory Used를 확인한다.

aws lambda update-function-configuration \
  --function-name my-function \
  --memory-size 1024

진단 체크리스트

확인 항목 방법
타임아웃 설정값 확인AWS 콘솔 → 함수 → 일반 구성
Cold Start 여부CloudWatch Logs에서 Init Duration 검색
VPC 설정 여부함수 구성 → VPC 섹션
메모리 사용량CloudWatch → Max Memory Used
외부 호출 병목AWS X-Ray 트레이싱 활성화 후 확인
DB 커넥션 위치코드에서 커넥션이 핸들러 안에 있는지 확인

X-Ray로 병목 찾기

CloudWatch Logs만으로는 어디서 느린지 파악이 어렵다. AWS X-Ray를 활성화하면 함수 내 각 구간의 소요 시간을 추적할 수 있다.

from aws_xray_sdk.core import xray_recorder, patch_all
patch_all()  # boto3, requests, psycopg2 등 자동 추적

def handler(event, context):
    with xray_recorder.in_subsegment('db-query'):
        result = query_database()
    return result

정리

Lambda 타임아웃 에러는 대부분 이 순서로 접근하면 해결된다.

  1. CloudWatch Logs에서 Init Duration 유무로 Cold Start 여부 확인
  2. X-Ray 트레이싱 켜고 어느 구간에서 시간이 먹히는지 파악
  3. DB 커넥션이 핸들러 안에 있으면 밖으로 빼기
  4. 외부 API 호출에 명시적 timeout 설정
  5. 순차 호출을 Promise.all / asyncio.gather로 병렬화
  6. 그래도 안 되면 메모리 늘리거나 타임아웃 값 상향

타임아웃 값 늘리는 게 제일 빠른 임시방편이긴 하지만, 근본 원인을 안 잡으면 요금만 늘어난다. 특히 RDS 커넥션 관리와 외부 API timeout 설정은 Lambda 쓰면서 기본 중의 기본이다.


관련 글: Kubernetes OOMKilled 에러 해결 — exit code 137 원인과 메모리 설정

목요일

AWS Lambda Cold Start 완벽 해결 가이드 — 지연 원인과 최적화 전략

🔍 검색 키워드: AWS Lambda cold start 해결, Lambda 콜드 스타트 최적화, Lambda 응답 지연 원인, Provisioned Concurrency 설정, Lambda 함수 초기화 시간 단축

AWS Lambda Cold Start 완벽 해결 가이드 — 지연 원인과 최적화 전략


증상: 첫 요청만 유독 느리다

Lambda 기반 API에서 이런 현상이 보인다.

일반 응답: 50~100ms
첫 번째 요청 / 트래픽 없다가 재요청: 1500~3000ms

CloudWatch 로그를 보면:

REPORT RequestId: abc-123  Duration: 1823.45 ms  Billed Duration: 1824 ms
       Memory Size: 512 MB  Max Memory Used: 128 MB
       Init Duration: 1654.23 ms

Init Duration이 실제 함수 실행 시간보다 훨씬 길다. 이것이 콜드 스타트(Cold Start)다.


원인 분석: Lambda 실행 생명주기

Lambda는 요청이 없을 때 컨테이너를 종료한다. 새 요청이 들어오면 다음 단계를 거친다.

  1. 컨테이너 생성 — Lambda 실행 환경(마이크로VM) 할당
  2. 런타임 초기화 — Node.js / Python / JVM 등 런타임 부팅
  3. 코드 초기화 — 핸들러 외부 코드 실행 (import, DB 연결, 설정 로드)
  4. 핸들러 실행 — 실제 요청 처리

1~3 단계가 "콜드 스타트"다. 이후 일정 시간 안에 다시 요청이 오면 4단계만 실행하는 "웜 스타트(Warm Start)"가 된다.

런타임별 콜드 스타트 시간

런타임 평균 콜드 스타트
Python 3.x~200ms
Node.js 18.x~250ms
Go~50ms
Java 17 (JVM)~1000~3000ms
Java 17 (GraalVM Native)~150ms
.NET 6~500ms

JVM 기반이 압도적으로 느리다. Spring Boot on Lambda는 이 문제의 대표적인 사례다.


해결방법

해결 1 — 핸들러 외부에서 초기화 (재사용 최대화)

# ❌ 잘못된 패턴: 매 요청마다 DB 연결
def handler(event, context):
    db = pymysql.connect(host=os.environ['DB_HOST'], ...)  # 매 요청마다 연결
    result = db.execute("SELECT ...")
    db.close()
    return result

# ✅ 올바른 패키-��팭: 요청마 항됐 ₔ DB 연결
import pymysql
import os

# 콜드 스타트 웄 해 벰헐 실행l 이후 재사용볠
db = pymysql.connect(
    host=os.environ['DB_HOST'],
    user=os.environ['DB_USER'],
    password=os.environ['DB_PASSWORD'],
    database=os.environ['DB_NAME'],
    cursorclass=pymysql.cursors.DictCursor
)

def handler(event, context):
    with db.cursor() as cursor:
        cursor.execute("SELECT ...")
        return cursor.fetchall()
// Node.js — SDK 클흼스이 언트도 외부초기화
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');

// 콜드 스타트 시 읐 번 생성, 이후 재사용트 시 한 번 생성, 이후 재사용
const dynamo = new DynamoDBClient({ region: 'ap-northeast-2' });

exports.handler = async (event) => {
    const result = await dynamo.send(new GetItemCommand({ ... }));
    return result;
};

해결 2 — 배포 패키지 최소화

# Node.js — esbuild로 번들링 (tree-shaking)
esbuild src/handler.ts --bundle --platform=node --target=node18 \
  --outfile=dist/handler.js --minify

# 패키지 크기 확인 (목표: 압축 기준 5MB 이하)
du -sh ./dist

해결 3 — 메모리 최적화 (CPU와 비례)

Lambda는 메모리 설정에 비례해 vCPU를 할당한다. 메모리를 늘리면 초기화도 빨라진다.

# AWS CLI로 메모리 설정 변경
aws lambda update-function-configuration \
  --function-name my-function \
  --memory-size 1024

# 콜드 스타트 비교 (동일 코드)
# 128 MB → Init: 1200ms
# 512 MB → Init: 400ms
# 1024 MB → Init: 180ms

해결 4 — Provisioned Concurrency 설정

콜드 스타트를 완전히 없애는 방법. 미리 초기화된 컨테이너를 대기시킨다.

# Provisioned Concurrency 설정
aws lambda put-provisioned-concurrency-config \
  --function-name my-function \
  --qualifier prod \
  --provisioned-concurrent-executions 5

# Auto Scaling으로 트래픽에 따라 자동 조절
aws application-autoscaling register-scalable-target \
  --service-namespace lambda \
  --resource-id function:my-function:prod \
  --scalable-dimension lambda:function:ProvisionedConcurrency \
  --min-capacity 2 \
  --max-capacity 20

해결 5 — Warm-up 스케줄러 (저비용 대안)

# 핸들러에서 warmup 요청 처리
def handler(event, context):
    if event.get('source') == 'serverless-plugin-warmup':
        print('WarmUp - Lambda is warm!')
        return {'statusCode': 200, 'body': 'warm'}

    # 실제 처리
    return process(event)

정리표

방법 효과 비용 적합한 상황
핸들러 외부 초기화 재사용 극대화 무료 항상 적용
패키지 최소화 초기화 시간 단축 무료 항상 적용
메모리 증가 초기화 속도 향상 미미 128~512MB 구간
Provisioned Concurrency 콜드 스타트 제거 높음 상시 트래픽 API
Warm-up 스케줄러 웜 상태 유지 낮음 간헐적 트래픽
VPC 제거/RDS Proxy ENI 지연 제거 RDS Proxy 비용 DB 접근 Lambda

모니터링

# CloudWatch에서 콜드 스타트 추적
# INIT_DURATION이 있는 로그  = 콜드 스타트 콜드 스타트 발생
aws logs filter-log-events \
  --log-group-name /aws/lambda/my-function \
  --filter-pattern "INIT_DURATION" \
  --start-time $(date -d '1 hour ago' +%s000)

콜드 스타트 최적화는 "없애기"보다 "허용 가능한 수준으로 관리하기"가 현실적 목표다. 핸들러 외부 초기화와 패키지 최소화는 무조건 적용하고, SLA 요구사항에 따라 Provisioned Concurrency 여부를 결정하면 �

토요일

asua 공유기 초기화 방법

공유기 설정을 잡다가 AP모드를 킨 후 접속이 제대로 안되는 문제로 초기화 진행함
우선 앱 스토어에서 "ASUS Router"앱을 먼저 받아두고 아래 절차대로 진행 했을때 빠르게 공유기 설정을 다시 잡을수 있었음.
  1. 공유기 전원 버튼을 눌러서 전원 끔
  2. WPS버튼을 누른체로 전원을 다시 켬
  3. WPS버튼을 계속 누른체로 전원이 켜지고 램프가 정상적으로 들어오는걸 확인
  4. WPS버튼에서 손을 뗀 후 라우터 부팅이 제대로 된걸 확인
  5. 디바이스에서 Wifi 켬
  6. 기본으로 ASUS_2G 라우터가 보안이 안 걸린체로 뜸. 현재 아무나 다 우리집 공유기를 접속해서 쓸 수 있는 상황이 벌어지고 있는것
  7. ASUS Router 앱 접속하여 안내대로 그대로 진행하면 됨. 한글 번역이 좀 아쉽긴 해도 진행 하는데 문제가 될 부분은 없었음. or  wifi켠 채로 http://router.asus.com/Main_Login.asp 한글로 환경설정 가능함

수요일

aws ec2 파일질라 연결

파일질라를 통한 AWS EC2 접속

내가 하고 있는 프로젝트 테스트서버로 AWS에 올릴라고 알아보다가 쓰는 포스팅(인터넷에 잘못된 정보가 너무 많다 후...)

mac 쓰는 분들은 .ppm 파일 그대로 사용해도 됨
제목으로 구글링해보면 대부분 ppk 파일 넣어야 되는걸로 시작하는 포스팅들 뿐인데 putty 안 쓰는 사람은 굳이 이렇게 할 필요 없고 ppk 파일 만들려고 시간 허비할 필요 없음
aws ec2 서버 생성 후 pem 파일이 있어야 되는게 전제 조건임
  1. 파일질라 실행 > 상단 메뉴 편집 > 설정 클릭
    enter image description here
  2. 빨간 박스 접속관리자 실행
    enter image description here
  3. 접속 정보 설정 (호스트 및 사용자 및 비밀번호 입력 하면 됨)
    enter image description here
ec2 접속 후 파일 업로드 실행 시 권한 없음으로 파일 업로드가 안되는 경우 발생. 터미널로 권한 추가 후 재 시도하면 파일 업로드 정상적으로 됨. 터미널로 ec2 접속 후 다음 명령어 순차적으로 실행
  • sudo su
  • chmod -R 777 “폴더명”

ec2 brew 설치

  1. ec2 터미널 접속
  2. 우분투를 설치했음으로 다음 명령어 순차적으로 실행

금요일

FTP error 553

디렉토리 소유자와 업로드 하려는 계정 사용자가 서로 상이해서 발생되는 문제
터미널 접속
chown -R ftp접속계정사용자명 대상디렉토리명
예를 들어 chown -R admin /home
폴더 지정이 잘못 되면 안내메시지가 출력 됨으로 폴더 확인 하면 되고
정상적으로 명령어 실행시 바로 업로드 해보면 정상적으로 되는걸 확인 할 수 있음