Skip to content

[Week 05] 지영인 - 람다에서 SSE 를 흘리려고 런타임을 바꿨다 #24

Description

@yeongin-ji

1. 작업 내용

공개 API 를 받는 람다의 실행 모델을 serverless-express 에서
Lambda Web Adapter(LWA) 로 바꿨습니다. 9/6 운영 반영했고 배포 후
에러는 0건입니다.

바꾼 이유는 하나입니다. 기존 어댑터는 핸들러가 응답을 전부 모은 뒤
반환
하는 구조라, AI 답변을 토큰 단위로 흘려보내는 SSE 가 구조적으로
불가능했습니다. 엔진(ECS)은 이미 흘려보낼 수 있고 게이트웨이도 흘려보낼
수 있는데, 그 사이의 람다만 못 흘리는 상태였습니다.

런타임을 바꾸니 주변 설정도 따라 움직였습니다.

  • 함수 타임아웃 20초 → 900초 (사용자가 실제로 기다리는 시간을 정하는
    통합 타임아웃 29초는 그대로 두었습니다)
  • 전 함수에 걸려 있던 동시 실행 1 상한 해제 + 프로비저닝된 동시성 1
    (스트리밍은 응답이 열려 있는 내내 슬롯을 차지해서, 1 이면 동시 사용자
    상한이 1명이 됩니다)
  • Nest 부팅이 첫 요청 안에서 일어나던 것이 INIT 안으로 이동

로컬에서는 검증할 방법이 없었습니다. 람다 에뮬레이터에 스트리밍 호출
경로가 아예 없고 staging 도 만들지 않는 규약이라, 같은 템플릿으로 스택
이름만 바꾼 일회성 복제 스택을 세워 확인하고 통째로 삭제했습니다.

2. Deep Dive 해본 것

왜 못 흘렸는가. 람다 실행 환경의 구조와 수명(INIT / INVOKE)부터
다시 봤습니다. 핸들러가 결과를 반환하는 함수인 이상, 반환하기 전까지는
클라이언트에게 아무것도 갈 수 없습니다. 어댑터를 아무리 잘 만들어도
이 지점은 안 열립니다.

LWA 는 무엇을 다르게 하는가. 이벤트를 번역하는 대신 함수 안에서
평범한 웹서버를 그대로 띄우고 진짜 HTTP 로 중계합니다. 그 결과 진입점,
라우트 정의(SAM 이벤트 → OpenAPI 문서를 직접 작성), 호출자 IP 를 얻는
경로가 전부 바뀌었습니다.

스위치가 두 곳에 있다. 스트리밍을 켜는 설정이 함수 단위와 통합
단위 두 곳에 있고, 단위가 달라서 라우트별로 섞을 수가 없습니다. 짝이
어긋나면 상태코드 200, 헤더 정상, 본문만 비어서 옵니다.

콜드스타트 수치를 정확히. 총량은 평균 2.8초 → 4.1초로 늘었고,
최대값만 7.8초 → 4.1초로 줄었습니다. 개선이라고 부르면 오해입니다.
실제로 달라진 것은 부팅이 INIT 으로 모여 미리 치를 수 있게 된 것이고,
평시에는 PC 가 덮어 사용자가 0초를 기다립니다.

호출자 IP. 운영 로그에서 확인해 보니 소켓 주소는 전부 루프백이었고,
게이트웨이가 채운 헤더에서 읽어야 IP 별 상한이 제대로 걸립니다.

DB 연결. 프록시가 빌려주는 연결이 사실상 전부 특정 앱에 고정돼
있었습니다. 그러면 웜 환경 수가 그대로 DB 연결 수가 됩니다. 스트리밍을
열기 전에 다시 봐야 합니다.

3. 알게된 것

에러 없이 조용히 실패하는 자리가 있다. 스위치 짝이 어긋난 조합은
로그에 아무것도 남기지 않습니다. 200 이고 헤더도 멀쩡한데 본문만
없습니다. 그래서 배포 후에 바이트가 실제로 도착하는지 눈으로 확인하는
절차가 필요했습니다. 깨져도 에러가 안 나는 호출자 IP 도 같은 종류라
회귀 테스트를 붙였습니다.

복제 스택이 결함 둘을 잡았다. 둘 다 로컬에서는 재현되지 않고, 그대로
운영에 갔으면 둘 다 사고였습니다.

  1. 스트리밍 통합은 흔히 쓰는 것과 다른 API 버전을 요구합니다. 모르고
    갔으면 게이트웨이 갱신이 실패해 전 라우트가 영향을 받았습니다.
  2. 복제 스택이 워크플로 함수까지 만들면서 운영 DB·엔진·푸시에
    배선됐습니다. 확인용 스택이 운영 워크플로를 1분마다 전진시키고
    실사용자에게 푸시를 보낼 뻔했습니다.

기술로 안 닫히는 것이 남았다. 전 함수 동시 실행 1 은 조직 규약인데
이 함수만 예외로 두는 것을 문서로 남겨야 하고, 복제 스택 방식을 관행으로
삼을지도 기준이 필요합니다. 혼자 정할 수 있는 종류가 아니라서 스터디에서
같이 이야기하고 싶습니다.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions