
데이터베이스 브랜치에서 실행되는 컴퓨팅 (Compute)
요약
Neon의 새로운 기능인 'Neon Functions'를 통해 컴퓨팅과 데이터베이스를 동일한 리전에 배치하여 네트워크 지연 시간을 획기적으로 줄이는 방법을 소개합니다. 개발자는 복잡한 설정 없이 코드만으로 데이터베이스 브랜치와 밀접하게 연결된 서버리스 함수를 배포할 수 있습니다.
핵심 포인트
- 컴퓨팅과 DB를 동일 리전에 배치하여 쿼리 왕복 시간(Round Trip) 최소화
- Neon CLI와 설정 파일을 통한 간편한 서버리스 함수 배포 프로세스
- Hono, Drizzle ORM 등 표준 웹 프레임워크와 라이브러리 그대로 사용 가능
- 브랜치 단위의 URL 제공으로 데이터베이스 브랜치와 컴퓨팅의 완벽한 동기화
당신의 백엔드 코드가 데이터베이스와 비교했을 때 어디에서 실행되는지 물어본다면, 그 대답은 종종 "다른 어딘가"일 것입니다. 당신의 함수는 한 제공업체의 us-east-1에 있고, 당신의 Postgres는 완전히 다른 리전에 있으며, 모든 쿼리는 그 간극을 가로지릅니다. 대부분의 경우 하나의 쿼리는 무시할 수 있을 만큼 충분히 빠르기 때문에 이를 인지하지 못합니다. 그러다 어떤 요청이 8개의 쿼리를 순차적으로 실행하게 되면, 각 쿼리가 왕복 시간 (round trip)을 지불하게 되고, 갑자기 밀리초 단위로 끝나야 할 엔드포인트가 1초 가까이 걸리게 됩니다.
Neon의 2026년 6월 플랫폼 프리뷰의 일부인 Neon Functions는 다른 입장을 취합니다. 컴퓨팅을 데이터베이스 브랜치와 동일한 리전에서, 해당 브랜치에 범위가 지정된 URL에서 실행하는 것입니다. 이것은 이것이 당신에게 무엇을 가져다주는지에 대한 시리즈의 첫 번째 글입니다. 또한 이 이점은 측정 가능한 것이기 때문에 시연하기 가장 쉽습니다. 저는 작은 REST API를 배포하고 사소한 쿼리를 두 가지 방식으로 측정했습니다. 수치는 하단에 있으며, 그 차이는 매우 큽니다.
(동반 리포지토리, 직접 배포해 보세요: The-DevOps-Daily/neon-functions-demo.)
전체 백엔드가 하나의 설정 파일입니다
Neon은 CLI를 통해 스타터 템플릿을 제공합니다. REST API가 그중 하나입니다:
배포되는 내용은 neon.ts에 선언됩니다. 이 API의 경우 세 줄의 의도만 담겨 있습니다: src/index.ts를 가져와서 todos라는 이름의 함수로 실행하는 것입니다.
import { defineConfig } from '@neondatabase/config/v1';
export default defineConfig({
...
그 안에는 연결 문자열 (connection string)도 없고, 컴퓨팅을 위해 선택할 리전도 없으며, 예약할 URL도 없습니다. DATABASE_URL은 배포 시점에 주입되며, 함수는 자동으로 브랜치와 동일한 리전에 배치됩니다.
함수는 일반적인 웹 핸들러입니다
애플리케이션 코드에는 Neon 전용인 부분이 전혀 없습니다. 이는 커넥션 풀 (connection pool)을 통해 Postgres와 통신하는 표준 Hono 앱이며, 어떤 Node 호스트를 위해서든 작성했을 법한 동일한 코드입니다:
import { Hono } from 'hono';
import { drizzle } from 'drizzle-orm/node-postgres';
import { Pool } from 'pg';
...
neonctl deploy 이후, 해당 핸들러는 브랜치 범위의 URL (branch-scoped URL)에서 응답하며, 생성/조회 경로가 엔드 투 엔드 (end to end)로 작동합니다:
curl -X POST "$URL/todos" -H 'content-type: application/json' -d '{"text":"ship it"}'
# {"id":1,"text":"ship it","createdAt":"2026-06-25T16:17:10.692Z"} (201)
curl "$URL/todos"
...
"브랜치 범위의 URL (branch-scoped URL)"이라는 문구는 주의 깊게 살펴볼 가치가 있습니다. 현재 브랜치에서 새로운 브랜치를 열면, 해당 브랜치의 데이터를 대상으로 최신 코드를 실행하는 고유한 URL과 고유한 함수를 갖게 됩니다. 풀 리퀘스트 (pull request)를 위한 프리뷰 환경 (preview environment)은 더 이상 "프론트엔드와 공유 백엔드의 조합"이 아니라, 실제적이고 격리된 복사본이 됩니다. 이에 대해서는 나중에 포스트 하나를 통째로 할애할 예정입니다. 지금은 함수와 브랜치가 하나의 단위라는 점이 핵심입니다.
이제 거리를 측정해 봅시다
여기는 수치로 나타낼 수 있는 부분입니다. 함수는 핸들러 내부에서 30번의 SELECT 1 왕복 시간을 측정하여 중앙값 (median)을 반환하는 /db-latency 엔드포인트를 노출합니다. 함수가 브랜스와 동일한 리전에서 실행되기 때문에, 이것이 로컬 홉 (local hop)입니다:
curl "$URL/db-latency"
# { "from": "neon function (us-east-2, co-located with Postgres)",
# "runs": 30, "min_ms": 1.13, "median_ms": 1.19, "p95_ms": 1.62 }
겨우 1밀리초 (millisecond)가 조금 넘는 수준입니다. 그다음 저는 정확히 동일한 SELECT 1을, 정확히 동일한 데이터베이스에 대해, 유럽에 있는 머신(us-east-2에서 멀리 떨어진 이 사이트의 빌드 박스인 Raspberry Pi)에서 실행했습니다:
# 동일한 쿼리, 동일한 데이터베이스, 다른 대륙에 있는 머신에서 실행
# { "from": "europe -> us-east-2", "runs": 30,
# "min_ms": 130.46, "median_ms": 134.54, "p95_ms": 138 }
동일한 쿼리, 동일한 데이터베이스입니다. 바뀐 유일한 것은 호출자 (caller)가 어디에 위치하느냐뿐입니다.
동일한 쿼리이며 동일한 데이터베이스입니다. 바뀐 유일한 것은 호출자(caller)가 어디에 위치하느냐뿐입니다.

약 113배입니다. 이것은 단 한 번의 왕복(round trip)에 대한 수치입니다. 세션 읽기, 사용자 로드, 설정 가져오기 등의 요청과 추가로 세 개의 쿼리를 실행하는 경우, 순차적으로 이들을 실행하면 매번 쿼리마다 이 거리가 비용으로 청구됩니다. 1.2ms에서는 6개 쿼리 엔드포인트가 데이터베이스와 통신하는 데 약 7ms를 사용하고; 135ms에서는 거의 1초를 소비하며, 아무리 애플리케이션을 조정해도 해결할 수 없습니다. 왜냐하면 이 시간은 네트워크에 있기 때문입니다. 이것이 바로 코로케이트된 컴퓨팅(co-located compute)이 제거하는 세금(tax)입니다. 또한 많은 'serverless Postgres가 느리다'는 속설이 실제로 비롯된 곳이기도 합니다. 데이터베이스 자체가 아니라, 한 리전에서 다른 리전에 있는 데이터베이스에 콜드 스타트(cold start)할 때마다 연결하려는 함수 때문입니다.
비교를 공정하게 하자면: 실제 배포 환경은 유럽과 버지니아처럼 멀리 떨어져 있는 경우는 드뭅니다. 만약 Lambda와 데이터베이스가 모두 us-east-1에 있다면 격차는 더 작습니다. 하지만 '같은 리전에 위치'하는 것은 Neon Functions가 신중한 구성이 아닌 기본값으로 제공하는 정확한 속성이며, '더 작다'는 것이 '제로(zero)'를 의미하지는 않습니다.
무엇이고, 무엇이 아닌지
이것을 기반으로 무언가를 구축하기 전에 명확히 밝힐 몇 가지 사항들이 있습니다. 왜냐하면 이것은 private preview이며 명확한 한계가 있기 때문입니다.
Private preview, one region, new projects only. 모든 것이 AWS
us-east-2에 있으며 미리보기 내에서 생성된 프로젝트에서만 작동합니다. 오늘날 기존 프로덕션 데이터베이스에 대해 이 기능을 켤 수 없습니다.
그 외에는 다음과 같습니다:
- 이것은 작업 실행기(job runner)가 아니라 요청/응답(request/response) 함수입니다. API, 에이전트(agents), 웹훅(webhooks), 실시간 연결(streaming 및 long-lived sockets 지원, 단순한 빠른 응답뿐만 아니라 지원)을 위해 구축되었습니다. 백그라운드 작업(background work), 큐(queues), 재시도(retries), 스케줄(schedules)은 다른 종류의 컴퓨팅(compute)입니다. 이러한 기능은 Inngest나 QStash 같은 도구와 함께 사용하세요.
- 함수 메모리는 고정되어 있습니다 (프리뷰 단계에서 2048 MiB). 따라서 아직 모든 것을 조절할 수 있는 컴퓨팅 플랫폼은 아닙니다.
- 이는 Neon 방식의 약속(commitment)입니다. 함수를 선언하는 하나의 설정 파일이 편리한 이유는 바로 통합되어 있기 때문입니다. 이는 결합(coupling)을 의미하지만, 국소성(locality)과 브랜칭(branching)을 위해 이를 맞바꾼 것입니다.
대상 사용자
만약 귀하의 백엔드가 이미 컴퓨팅(compute)과 데이터베이스(database)가 동일한 리전에 신중하게 배치된 성숙한 코드형 인프라(infrastructure-as-code) 환경에 있다면, Neon Functions는 귀하가 가진 문제를 해결해주지 않습니다. 귀하는 이미 지연 시간을 줄이기 위한 비용을 지불했습니다.
이 기능이 도움이 되는 팀은 아직 그 단계에 도달하지 못한 팀들입니다. 즉, 별도의 결정이 내려지지 않아 컴퓨팅과 데이터베이스가 서로 다른 리전으로 분리된 사이드 프로젝트나 소규모 팀, 그리고 수동으로 연결하지 않고도 풀 리퀘스트(pull request)만으로 진정으로 격리된 백엔드를 생성하고 싶은 모든 사람입니다. 이들에게 "함수가 이 브랜치의 데이터를 사용하여, 이 URL에서, 데이터베이스 바로 옆에서 실행된다"는 것은 지연 시간(latency)과 구성 요소(moving parts)를 모두 줄여주는 실질적인 이점이며, 이는 직접 맞추어야 하는 설정이 아닌 기본값(default)으로 제공됩니다.
우리는 Neon은 단순한 Postgres가 아니라 백엔드 플랫폼이 되고 있습니다에서 더 큰 그림을 다루고 있으며, 이 시리즈의 나머지 부분에서는 브랜치 범위 함수(branch-scoped function)가 가능하게 하는 다른 기능들, 즉 스트리밍 에이전트(streaming agents), MCP 서버, 백엔드를 포함하는 프리뷰 환경(preview environments)에 대해 살펴봅니다. /db-latency 엔드포인트를 포함한 전체 데모는 여기에서 확인할 수 있습니다:
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기