17P by GN⁺ 3일전 | ★ favorite | 댓글 3개
  • API 인증 서비스를 제공하는 Unkey가 Cloudflare Workers 기반 서버리스 아키텍처에서 Go 기반 상태 유지 서버로 전환하여 성능과 아키텍처 복잡도 문제를 해결
  • 새로운 구조는 6배 빠른 응답 속도와 함께 복잡한 캐싱 우회 방법 및 데이터 파이프라인 오버헤드를 제거
  • 서버리스 환경에서는 함수 호출 간 영속적 메모리 보장이 없어 모든 캐시 읽기가 네트워크 요청을 필요로 했고, p99 기준 30ms 이상의 캐시 레이턴시가 발생
  • 분산 시스템에서 단순한 애플리케이션 아키텍처로 전환하면서 셀프 호스팅이 가능해졌고, 플랫폼 독립성을 확보, 개발자 경험도 대폭 개선
  • 서버리스는 비정기적 워크로드나 단순한 요청/응답 패턴에는 적합하지만, 일관된 저지연이 필요하거나 영속적 상태 관리가 필요한 경우 상태 유지 서버가 더 효과적임

서버리스 한계와 성능 병목

  • Unkey는 API 인증이 요청 경로의 핵심에 있어 수 밀리초 단위의 지연이 사용자 경험에 직접 영향을 주는 구조였음
  • Cloudflare Workers의 전 세계 엣지 배포와 자동 확장성은 매력적이었지만, 캐시 지속성 부재와 네트워크 요청 지연이 문제로 드러남
  • 캐싱 문제

    • 서버리스 함수는 호출 간 지속 메모리가 없어, 캐시 조회마다 외부 네트워크 요청이 필요함
      • Cloudflare 캐시 조회 p99 지연이 30ms 이상으로 측정됨
      • 여러 계층의 캐시(SWR, Redis 등)를 쌓아도 근본적으로 ‘0번의 네트워크 요청’보다 빠를 수 없음
    • 결과적으로 목표했던 10ms 미만 응답을 달성할 수 없었음
  • SaaS 결합 문제

    • 서버리스는 인프라 관리 부담을 줄여주지만, 실제로는 추가 SaaS 도구들이 필수가 됨
      • 캐시 → Redis, 배치 처리 → Queue, 로그 → Durable Objects 등
      • 각 서비스는 지연·비용·장애점을 추가함
    • Cloudflare Durable Objects, Queues, Workflows 등을 혼합 사용하면서도 실질적 복잡성은 오히려 증가
  • 데이터 파이프라인 문제

    • 서버리스는 휘발성 환경이므로 모든 호출마다 데이터를 즉시 플러시해야 함
      • 이벤트·로그·메트릭을 처리하기 위해 복잡한 버퍼링 및 중계 서비스를 직접 구축해야 했음
    • 예:
      • chproxy를 통해 ClickHouse로 로그 배치 전송
      • Axiom으로 로그 전송 시 속도 제한(rate limit)을 우회하기 위해 별도 버퍼링 서버 구축
    • 결과적으로 단순한 분석 기능조차 분산 이벤트 처리 시스템 수준의 복잡도를 초래함

상태 기반 서버로의 전환

  • Go 기반 상태 서버(v2)를 도입하면서, 메모리 내 배치 및 주기적 플러시가 가능해짐
    • 추가 서비스나 복잡한 파이프라인이 필요 없음
    • 유지보수성·디버깅·로컬 테스트가 크게 단순화됨
  • 성능 결과

    • /v1/keys.verifyKey/v2/keys.verifyKey 비교 결과 지연 시간 6배 감소
    • Cloudflare 전역 POP 300개보다 적은 인프라에서도 사용자 체감 성능은 크게 향상됨

성능 외 이점

  • 셀프 호스팅(Self-Hosting)

    • Cloudflare 런타임에 종속되어 있어 고객이 Unkey를 셀프 호스팅할 수 없었음
      • Workers 런타임이 기술적으로 오픈소스이지만, 로컬 실행(개발 모드에서도)이 극도로 어려움
    • 표준 Go 서버로 전환하면서 셀프 호스팅이 간단해짐
      • docker run -p 8080:8080 unkey/api 명령어만으로 실행 가능
      • 특수 런타임이나 복잡한 설정 불필요
    • 개발자들이 이제 몇 초 만에 전체 Unkey 스택을 로컬에서 실행할 수 있어 디버깅과 테스트가 훨씬 쉬워짐
    • 로컬 개발 및 디버깅 속도 비약적으로 향상
  • 개발자 경험 개선

    • 서버리스에서 겪던 한계:
      • 함수 실행 제약 고려 필요
      • 호출 간 상태 유지 어려움
      • 분산 로그 디버깅 복잡
      • 로컬 테스트 환경 불편
    • 상태 서버로 전환하며 이러한 복잡성 세금(Complexity Tax) 해소
  • 플랫폼 독립성 확보

    • Cloudflare 생태계에 더 이상 종속되지 않음
      • 어디에나 배포 가능
      • 어떤 데이터베이스든 사용 가능
      • 런타임 호환성 걱정 없이 타사 서비스 통합 가능

마이그레이션 전략과 교훈

  • 마이그레이션을 시간이 지나며 누적된 API 설계 문제를 수정하는 기회로 활용
    • 새 v2 API가 기존 v1과 함께 실행되며, 고객들이 지원 중단 기간 동안 두 버전 모두 사용 가능
  • 서버리스를 유지하는 한 가지 장점은 사용량이 제로로 감소해도 v1 API를 실행하는 비용이 많이 들지 않아 무료 마이그레이션 기간을 확보
  • 유지한 것들

    • 서버리스 접근 방식의 모든 것을 버리지는 않음
      • 글로벌 엣지 배포: AWS Global Accelerator를 사용하여 전 세계적으로 낮은 레이턴시 유지
      • 자동 스케일링: Fargate가 서버리스 제약 없이 스케일링 처리
  • 레이트 리미터 성능 향상

    • 서버리스 모델에서는 속도, 정확성, 비용 간 상당한 트레이드오프가 필요했고 분산 특성상 세 가지 모두 달성이 거의 불가능
    • 상태 유지 서버와 인메모리 상태로 더 빠르고 정확하며 운영 비용도 절감하는 레이트 리미터 구축

서버리스가 적합한 경우(그리고 적합하지 않은 경우)

  • 서버리스가 적합한 경우

    • 비정기적 워크로드: 지속적으로 실행되지 않을 때 제로 스케일링 경제성이 탁월
    • 단순한 요청/응답 패턴: 영속적 상태나 복잡한 데이터 파이프라인이 불필요할 때
    • 이벤트 주도 아키텍처: 인프라 관리 없이 이벤트에 응답하는 데 탁월
  • 서버리스가 부적합한 경우

    • 일관된 저지연이 필요할 때: 외부 네트워크 종속성이 성능을 저하
    • 영속적 상태가 필요할 때: 무상태성을 우회하는 작업이 복잡성을 증가
    • 고빈도 워크로드: 호출당 과금 모델이 비경제적
    • 세밀한 제어가 필요할 때: 플랫폼 추상화가 제약이 될 수 있음
  • 복잡성 비용

    • 마이그레이션의 가장 큰 교훈은 플랫폼 제약을 우회하는 작업의 복잡성 비용 이해
    • 서버리스에서 구축한 것들

      • 무상태성을 우회하기 위한 정교한 캐싱 라이브러리
      • 데이터 배치 처리를 위한 여러 보조 서비스
      • 메트릭 수집을 위한 복잡한 로그 파이프라인
      • 로컬 개발을 위한 정교한 우회 방법
    • 상태 유지 서버에서는

      • 위의 모든 것이 사라짐
      • 여러 움직이는 부품을 가진 분산 시스템에서 단순한 애플리케이션 아키텍처로 전환
      • 때로는 제약을 우회하는 것보다 다른 기반을 선택하는 것이 최선의 솔루션

다음 단계

  • 현재 Global Accelerator 뒤의 AWS Fargate에서 실행 중이지만 이는 임시 방편
  • 내년에 고객(그리고 Unkey 자체)이 원하는 곳 어디서나 Unkey를 실행할 수 있게 해주는 자체 배포 플랫폼 "Unkey Deploy" 출시 예정
  • 상태 유지 Go 서버로의 전환은 Unkey를 진정으로 이식 가능하고 셀프 호스팅 가능하게 만드는 첫 단계
  • 구현 세부사항은 GitHub 저장소의 오픈소스로 공개

저도 한때는 거의 서버리스 신봉자처럼 서버리스 아키텍처를 처발처발했었는데 요즘은 ec2 한개에 rds 한개로 만들어진 구조를 더 선호합니다. 그리고 차차 필요한걸 하나씩 떼구요. 서버리스 도입은 많이 고민하고 하게 됐습니다.
여러가지 이유가 있지만 팀에 서버리스 지식이 없는 사람이 한명만 있어도 소통/유지보수 비용이 상당히 증가하더라구요. 그리고 다시 서버를 굴려보니 서버리스가 생각보다 싸거나 생각보다 편하지 않았다는걸 새삼 느꼈습니다.

Hacker News 의견
  • 몇 년간 serverless 환경(주로 amazon lambda, 그리고 다른 것도)을 사용한 경험자로서, 저자 의견에 적극 동의함
    serverless가 어느 부분에서는 일을 덜어주지만, 동시다발적으로 "인위적으로 생기는 문제들"을 해결하느라 다른 분야에서 일이 늘어남
    나의 한 사례는 업로드 용량 제한 문제였음
    기존 애플리케이션을 serverless로 이전했을 때, 대용량 고객 데이터 import를 위해 API 엔드포인트를 만들고 백그라운드 작업자를 붙이면 충분할 거라고 생각했음
    하지만 "api gateway"(코드를 호출하는 프록시)에서는 100MB 이상은 업로드가 불가능했고, 제한 변경이 가능한지 문의했더니 단순히 고객에게 더 작은 파일로 나눠서 업로드하도록 하라고 안내받음
    기술적으로는 그럴싸하게 들릴 수 있지만, 실제 고객이 업로드 방식을 바꿀 리 없다는 점이 현실임
    "진공상태에서는 잘 동작한다"는 느낌에 가까우며, 이론상 멋진 것 같지만 실제로 해 보면 serverless로 전환해 절감한 시간과 비용을 결국은 serverless 특유의 문제를 해결하느라 재투입하게 됨

    • 이 문제를 해결하려면 presigned S3 URL을 제공해야 함
      사용자가 S3에 직접 업로드한 뒤 업로드 결과를 보내주도록 하거나, 파일 이름을 request id로 구분하는 방법 등으로 연동할 수 있음
      AWS 환경을 오래 써본 입장에서 이런 점이 성가시기는 한데, 임의 파일 업로드 API를 열어두면 DoS 공격 위험이 크기 때문에 100MB 제한 자체는 이해 가능한 부분임
      다만 요즘 인터넷 속도가 빨라진 걸 생각하면 100MB 기준은 다소 시대에 뒤처진 느낌임
      그래도 언젠가는 제한이 필요하다고 생각함

    • 우리 회사는 한때 AWS SSL 인증서 부서를 대표하는 고객이었음
      Vanity URL(커스텀 도메인)을 지원하려니 도메인마다 SSL 인증서가 필요했는데, 수천 개가 필요했음
      AWS의 인증서 관리 도구는 수백 개 규모까지만 쾌적했기 때문에, 이 문제가 해결될 때까지 3개월 정도 걸렸음
      AWS의 일부 서비스가 극소수 고객의 수요에 맞춰 빨리 대응하지 못한다는 점이 놀라웠음

    • 처음엔 Lambda가 엄청 가능성 있어 보여서 도입했지만, 결국 모든 Lambda 프로젝트를 포기하고 필요에 따라 컨테이너 환경으로 옮겼음
      Lambda도 Node 런타임을 1~2년마다 업그레이드해야 하고, 컨테이너를 쓰면 그 주기를 스스로 결정할 수 있기 때문에 더 유연함

    • 컴퓨터 공학에서 가장 어려운 문제는 한 컴퓨터에서 다른 컴퓨터로 파일 복사하는 것임

    • 미래의 독자를 위해 참고자료를 남김
      "tus" 업로더와 endpoint를 사용하면 업로드 시 분할, 이어받기 등 기능이 제공되어 이런 제한을 극복하기에 적합함
      https://tus.io/

  • 기사에서 설명한 것처럼, serverless는 분명히 그 나름의 용도가 있음
    하지만 대부분의 애플리케이션에는 적합하지 않다고 생각함
    특별한 상황이 아니라면 serverless를 핵심 인프라로 쓸 계획이 없음
    실제로는 오히려 인프라 관리가 더 번거로워진다는 인상임
    플랫폼마다 요구사항이 다르고, 테스트/개발 방식도 제각각이라 매번 애매하고 로컬 테스트도 어려움
    추상화 레이어도 각 플랫폼마다 함정이 있고 진짜 표준이 존재하지 않음
    도커 이미지로 실행 파일을 패키징하는 게 더 편하고, 환경 세팅도 적당히 추상화할 수 있어 내겐 더 자연스러운 개발 환경임
    리눅스 환경과 파일시스템 수준의 최소한의 추상화가 가장 효율적이라 느껴짐
    필요하면 해당 이미지를 서버로 띄워놓고 온디맨드 혹은 항상 대기 상태로 운영할 수도 있음

    • 지난 10년간 유행한 여러 기술 트렌드를 보면, 대형 기업이 자기 규모에서만 실질적으로 존재하는 문제를 해결하려 썼던 기술이 인기몰이 하는 경우가 많았음
      사례로 GraphQL, react, Tailwind, NextJS 등 여러가지가 해당됨
      어떤 도구든 모든 문제에 만능으로 통하는 것은 아니며, 자신의 상황과 문제에 대해 경험과 이해를 바탕으로 선택하는 것이 중요함

    • 지금 내가 얼마나 "재미있게" amazon lambda 앱을 로컬에서 실행해보려 시도하는 중인지 말해주고 싶을 정도임
      배포 전에 테스트하려고 하니 도전 과제 그 자체임

    • Knative(Kubernetes용 Serverless)는 컨테이너를 직접 받아줌
      표준 패키징 포맷이기 때문에 다양한 플랫폼으로 쉽게 이동할 수 있음

    • 그 팀은 실제로 애플리케이션이 아니라 상태를 가진 서버 애플리케이션에 통합될 라이브러리를 개발하고 있었음
      성능상의 장점도 authentication을 고객 환경 근처에서 처리한 덕분이지, serverless 그 자체 덕분은 아님

    • 사실 모든 "serverless" 플랫폼이 도커 이미지를 받아주지 않나?
      Cloud Run은 지원하는 것으로 알고 있음
      실은 “serverless function”이 너무 많은 것을 추상화해서 생기는 현상에 대한 우려임

  • ClickHouse는 수천 번의 작은 insert를 싫어해서, 우리는 chproxy라는 Go 서비스로 이벤트를 모아서 대량 batch로 보냄
    각 Cloudflare Worker가 chproxy에 analytic 이벤트를 보내면, chproxy가 모아 ClickHouse로 대량 전송함
    ClickHouse 데이터에 한정해서 굳이 별도 서비스를 따로 만든 대신, 비동기 insert 기능도 있었는데 왜 그걸 안 썼는지 궁금함
    https://clickhouse.com/docs/optimize/asynchronous-inserts

  • 개발자들은 "간편하게 해준다는" 툴들에 파묻혀 있는 느낌임
    사실 대부분의 문제는 가장 기본적인 도구(컴파일러, bash 스크립트, 라이브러리)로도 쉽게 풀림
    이처럼 도구에 집착하다 보니 회사와 개발자 모두에게 오히려 해가 될 때가 있음

    • 내 생각엔, 2013년의 Docker야말로 마지막으로 정말로 보편적이고 긍정적인 변화를 준 도구였음
      이후로는 어느 회사에는 도움이 될 수 있지만, 모든 회사에 다 적용하려다가 오히려 생산성이 깨지거나 시스템이 무너지는 사례가 많음
      요즘 Cloudflare같은 곳에서는 v8 isolates가 '차세대 docker'가 될 것처럼 밀고 있지만, 일부 워크로드엔 저격이지만 모든 곳에 맞는 건 아님
      "docker 이미지를 받아서 인터넷에 띄워준다"는 패턴이 너무 강력해서 2040년에도 여전히 제일 센 방식일 거라고 봄

    • 근본기를 아는 사람이 점점 드물어진 것도 문제임
      스택 대부분을 제삼자 서비스에 외주를 주는 식으로 업무가 진행되고, 정작 직접 만든 건 핵심 애플리케이션 일부뿐임
      심지어 그것조차 AI가 작성하게 될 수 있음
      업계 전체가 "학습된 무력감"을 키우고 있는 중임

    • 생각보다 많은 사람들이 컴파일러, bash 스크립트, 라이브러리를 잘 모름

    • AWS lambda는 너무 쌀 정도임

    • 인지도 제고 용도로는 도움이 됨!
      bash 스크립트 써서 Staff 등급까지 올라간 사람은 본 적 없음

  • "vercel security checkpoint"에게 묻고 싶음
    아이폰에서 proton VPN과 Firefox Focus 조합으로 캘리포니아, 캐나다 exit 노드로 접속하면 code 99 "Failed to verify your browser" 오류가 반복적으로 발생함
    뭐가 문제임?

    sfo1::1760587368-8k6JCK3uO27oMpuTbnS4Hb3X2K9bVsc
    
  • 이 쓰레드는 내 생각을 확신하게 만듦
    serverless라는 용어 자체가 워낙 정의가 모호해서, 이름 자체가 넌센스라고 느낌
    결국 서버는 여전히 존재함
    "전기가 없는" 이라는 표현처럼, 실제로는 전기를 쓴다는 점과 비슷함
    이름만 바뀌었을 뿐, 실제로 무슨 일이 벌어지는지 말해주지 않는 느낌임

  • "serverless가 나쁘다"는 결론이 전부는 아니라고 생각함
    더 중요한 교훈은, 서비스에 종속성이 있다면 서비스를 클라이언트 가까이 옮기더라도 그 종속성까지 같이 옮기지 않으면 end-to-end 경험이 의외로 느려진다는 점임
    필연적으로 종속성과 가까운 곳에서 빌드하는 것이 낫고, 부족하다면 모든 종속성을 클라이언트 가까이 옮기거나 동기화해야 하지만, 실제로는 그 과정이 너무나 복잡해지는 경우가 많음

    • 이게 무조건 적용되는 규칙인지 잘 모르겠음
      종속성을 어떻게, 얼마나 자주 쓰는지에 따라 다르고, DB라면 서버와 가까워야 할지, 클라이언트와 가까워야 할지 용도마다 다름
      어떤 사용 시나리오에선 빠른 응답이 필요하고, 어떤 건 느려도 괜찮음
      서버나 클라이언트에서 뭘 캐싱할 수 있냐에 따라 쪼갤 수도 있음
      꼭 이분법적으로 생각할 일은 아니라고 생각함
  • 최고 가격대비 성능비를 원한다면, 직접 인스턴스를 세팅해서 필요한 일을 자기가 직접 처리하는 것이 정답임
    클라우드 업체들이 과도한 청구 마법사가 되게 둘 필요 없음

  • 현재 우리가 "지역 최대치(local maximum)"에 도달한 것은, 도커 컨테이너를 표준 환경/배포물로 삼고 필요시 비밀값만 주입하는 식임
    이렇게 하면 로컬 테스트가 쉽고, 인프라 자동화, 재현성 등 주요 이점은 대부분 살릴 수 있음
    serverless는 대부분의 앱에는 과한 접근이지만, 일부 앱에는 잘 어울림
    특히 자체 인프라가 필요 없는 간단한 유틸리티나 온디맨드 서비스, 규모가 큰 stateless 앱에는 serverless가 더 잘 어울릴 수 있음
    serverless가 반드시 단순용도에만 쓰인다는 건 아니며, "전통적인 웹앱" 모델과 serverless 플랫폼 사이에는 근본적인 모순이 있다고 생각함

    • 이제 misterio를 받아볼 준비가 된 것 같음
      https://github.com/daitangio/misterio
      간단한 stareless 도커 클러스터 래퍼임
      나의 홈랩에서 시작했는데, 반향이 커졌음

    • Docker는 마치 microservices와 비슷함
      일부 앱에는 적합하지만, 업계 표준처럼 과대포장된 경향이 있음
      Docker를 남발하면 보안 패치와 운영 부담이 생기는데, 무턱대고 모든 프로젝트에 쓰면 리스크 관리에 실패함
      의존성 문제도 이제는 전역 설치를 안 하는 패턴으로 대다수 개발자가 해결함
      예전만큼 Docker가 필수는 아니지만 여전히 대세임
      호스팅 제공 업체 입장에서는 Docker 도입으로 마진이 최소 10%는 증가할 거라고 예상함
      누군가가 아래에서 지적한 "도구 집착"에 Docker도 포함된다고 느껴짐

  • 요점은 serverless가 안 통한다는 게 아니라, 저자들이 자기들이 구축하고 있는 기반을 잘 몰랐던 것임
    지연 민감한 API를 stateless edge runtime에 올리는 건 초심자급 실수고, 그 결과로 겪은 고통은 충분히 예측 가능한 상황임

    • 내 경험상, 클라우드 서비스의 문제 대부분은 아키텍처 오용이나 오해에서 비롯됨
      좀 더 신중한 설계를 했으면 피할 수 있었던 인적 문제임
      단, 문제는 대부분 클라우드 벤더들이 그럴듯한 마케팅으로 제품을 홍보하고 실제 성능 수치는 숨기고 있다는 점임
      정말로 Lambdas가 내 워크로드에 충분히 빠른지, AWS RDS 외부 복제가 적합한지는 테스트 해보기 전까지 모름
      AWS의 실제 성능은 직접 벤치마크 해야 한다는 걸 경험을 통해 배움

    • 저자들이 이해하지 못했다는 게 포인트가 아니라, 누군가가 공유한 정보 자체가 가치 있음

    • 이게 "초보 실수"라고만 볼 수 없을 것 같음
      실제로 엔지니어들은 특정 방식이 실무에 적합하지 않다는 걸 알고 있고, 관리자가 "요즘 방식이니까" 식으로 손쉽게 밀어붙이는 경우가 흔함
      혹은 시간과 비용 제한 때문에 "덜 나은 선택"을 할 수밖에 없을 때도 있음
      또는 정말 원래 구현 팀이 제대로 몰랐던 것일 수도 있지만, 어쨌든 이런 스토리를 나누는 게 우리 전체 커뮤니티 발전에 큰 도움이 된다고 생각함

    • 내 경험상 어떤 확실한게 필요하면(빠른 자동 확장, 짧은 지연, CPU, 디스크, 네트워크 속도 등) 직접 EC2 인스턴스를 관리하는 게 가장 확실함
      제어권을 넘기고 성능 향상을 기대했다간 고칠 수 없는 병목을 맞게 됨

    • 결국 저자들이 "오늘의 10,000명 중 한 명"임을 인정하는 셈임
      https://xkcd.com/1053/
      개인적으로 이런 정보와 실수를 공유해준 것에 고마움을 느낌

엔지니어링은 항상 비용의 싸움임
초반에는 프로토타이핑 이나 비지니스 구축하는데 시간을 줄이는데 사용하고
나중에는 최적화 하면서 비용읗 줄여야 함
이런 글 자체가 자신이 얼마나 엔지니어가 아닌지를 증명하는 것
이러런