헷갈리는 Upstream과 Downstream

헷갈리는 Upstream과 Downstream

소프트웨어 문서를 읽다 보면 “upstream 서버에 장애가 났다”, “downstream consumer가 영향을 받는다” 같은 표현이 수시로 튀어나오는데요. 그때마다 “그래서 어느 쪽이 어느 쪽이지?” 하며 잠깐 멈칫한 경험, 저만 있는 건 아닐 거예요. nginx 설정의 upstream 블록, dbt의 downstream 모델, Debian/Ubuntu의 계보처럼 결이 완전히 다른 자리에서 같은 단어가 쏟아지니 한 번에 감을 잡기가 쉽지 않습니다.

이 글은 그 혼란의 뿌리를 짚어보고, 실무에서 두 용어가 쓰이는 대표 쓰임새를 한 번에 정리합니다. 방향 감각만 잡아두면 nginx 설정, 리눅스 배포판 계보, 라이브러리 호환성 논의, 데이터 파이프라인까지 같은 어휘로 사고할 수 있게 돼요.

출발점은 강물 은유

Upstream과 downstream의 원 의미는 단어 그대로 “강물의 상류·하류”입니다. 소프트웨어 세계가 이 은유를 그대로 차용하면서, 데이터가 흐르는 방향을 기준으로 상류와 하류를 정했어요.

  • 상류(upstream): 데이터의 원천(source), 내가 기대어 쓰는 쪽
  • 하류(downstream): 데이터의 소비자(consumer), 내 변경이 파급되는 쪽

이 기준 하나만 머리에 박아두면 어지간한 상황에선 헷갈리지 않습니다. “물(데이터)은 원천에서 바다(소비자)로 흐른다”는 한 줄로 충분해요.

graph LR
    A["원천 Source<br/>upstream"] -->|응답·데이터 흐름| M[중간 단계] -->|응답·데이터 흐름| B["소비자 Consumer<br/>downstream"]
    B -.요청이 거슬러 올라감.-> M -.요청이 거슬러 올라감.-> A

왜 직관이 뒤집힌 것처럼 느껴지나

이 용어가 헷갈리는 이유가 있습니다. 일상적으로 우리는 “클라이언트에서 서버로 올라간다”는 감각을 가지고 있거든요. 이 직관대로라면 서버가 “위쪽=상류”처럼 느껴지는데, 다행히 네트워크 용법도 같은 결론을 내놓습니다.

  • 일상 직관: 요청이 클라이언트에서 서버로 “올라간다” → 서버가 상류
  • 강물 은유: 데이터가 원천 서버에서 소비자로 “흘러내린다” → 원천 서버가 상류

두 은유가 우연히 같은 결론을 내놓으니 단순한 2-tier 구조에서는 혼란이 잘 드러나지 않아요. 문제는 프록시가 끼거나 파이프라인이 여러 단계로 늘어날 때 터집니다. 이때부터는 “올라간다” 직관이 흔들리고, 데이터 원천이 어디냐를 따지는 강물 은유만 꾸준히 들어맞아요. 네트워크·시스템 엔지니어링 표준이 강물 쪽으로 굳어진 배경입니다.

Upstream이 쓰이는 자리

“내가 의존하는 원천”을 가리키는 용어답게, upstream은 내가 데이터를 받아오는 쪽을 설명할 때 자주 나옵니다.

리버스 프록시 세계의 용법이 가장 대표적이에요. nginx 설정을 보면 이런 식으로 나옵니다.

nginx upstream 설정 예시
upstream backend {
  server api.example.com:8080;
  server api.example.com:8081;
}

server {
  location / {
    proxy_pass http://backend;
  }
}

nginx 입장에서 “내가 요청을 넘겨 응답을 받아오는 쪽”이 upstream입니다. Envoy, HAProxy 같은 다른 프록시·게이트웨이도 같은 어휘를 씁니다. “upstream 헬스 체크”, “upstream 커넥션 풀” 같은 표현이 여기서 나와요. 이 맥락에서 리버스 프록시가 왜 굳이 중간에 끼어 있어야 하는지, 포워드 프록시와는 어떻게 다른지가 궁금해지면 프록시 서버와 리버스 프록시 서버의 차이를 먼저 읽어보시면 그림이 맞춰집니다.

두 번째는 의존성 이야기에서입니다. 오픈소스 프로젝트나 패키지 매니저 문서에서 “upstream project”, “upstream maintainer” 라는 표현을 자주 보는데, “내가 기대어 쓰는 원천 프로젝트”라는 뜻이에요. React를 쓰는 앱의 관점에서는 React가 upstream이고, 내 앱은 downstream입니다. “upstream에 이슈를 보고해야 한다”는 말이 “원천 프로젝트 쪽에 버그 리포트를 올려야 한다”로 읽히는 이유예요.

OAuth·인증 문서에서도 자주 나옵니다. MCP 서버가 GitHub API 데이터를 중계하는 구조를 예로 들면, GitHub API가 upstream API입니다. MCP 스펙이 “받은 토큰을 그대로 upstream API에 넘기지 말라”고 경고하는 대목도 같은 용법이에요. 자세한 배경은 MCP Authentication에서 Token Passthrough 안티 패턴을 다룰 때 풀어뒀습니다.

Downstream이 쓰이는 자리

반면 downstream은 “내 변경이 흘러 들어가는 쪽”을 말할 때 자주 쓰여요. Upstream보다 빈도는 낮지만, 몇몇 분야에서는 거의 관용어로 굳어 있습니다.

가장 일상적인 쓰임새는 데이터 파이프라인입니다. Airflow, dbt, Dagster 같은 워크플로우 도구에서 뒤에 오는 단계를 downstream이라고 부르거든요.

graph LR
    A["raw_events<br/>(upstream)"] --> B[staging_sessions] --> C[daily_metrics] --> D["대시보드<br/>(downstream)"]

“이 staging 모델을 바꾸면 downstream 대시보드가 전부 깨진다” 같은 문장이 일상적으로 오가요. dbt에서 dbt run --select +daily_metrics+ 같은 + 연산자로 upstream/downstream을 선택하는 것도 같은 개념입니다.

라이브러리·SDK 개발도 빼놓을 수 없어요. API를 바꿀 때 영향을 받는 사용자를 “downstream consumers” 라고 부르는데, 오픈소스 이슈 트래커에서 거의 관용어처럼 쓰입니다. “Breaking change가 downstream에 미치는 영향을 먼저 평가하자”는 문장이 대표적이에요. 라이브러리 저자 입장에서는 자기 패키지를 쓰는 모든 앱이 downstream이고, 앱 개발자 입장에서는 자기 앱이 downstream에 해당합니다.

리눅스 배포판의 계보도 이 용어를 씁니다. “Ubuntu는 Debian의 downstream이다”, “Rocky Linux는 RHEL의 downstream이다” 같은 표현이 익숙하실 텐데요. 원류 프로젝트에서 갈라져 나온 파생 프로젝트를 가리킬 때 쓰는 용법이에요.

graph LR
    A["Debian<br/>(upstream)"] --> B[Ubuntu] --> C["Linux Mint<br/>(downstream)"]

이벤트 스트리밍에서도 downstream이 자주 보입니다. Kafka·Pulsar·NATS 같은 메시징 시스템에서 프로듀서가 쏜 이벤트를 받아 소비하는 쪽을 downstream consumer라고 부르죠.

graph LR
    P["주문 서비스<br/>(Producer · upstream)"] --> T[Kafka Topic]
    T --> C1[결제 서비스]
    T --> C2[알림 서비스]
    T --> C3[분석 서비스]
    subgraph downstream consumers
      C1
      C2
      C3
    end

“스키마를 바꾸기 전에 downstream consumer들에게 먼저 알려야 한다”는 문장이 여기서 나옵니다. Kafka Schema Registry 같은 도구가 등장한 이유도 downstream 호환성 관리 때문이에요.

마지막으로 CDN·캐싱 계층입니다. Varnish, Fastly, Cloudflare 같은 환경에서 사용자에 가까운 캐시를 downstream이라고 부릅니다.

graph LR
    O["origin server<br/>(upstream)"] --> M[midtier cache] --> E["edge cache<br/>(downstream)"] --> U[사용자]

“downstream 캐시를 무효화한다”는 표현이 “사용자 가까이에 있는 에지 캐시를 털어낸다”는 뜻이에요. Cloudflare Images Transformations처럼 에지에서 변환·캐싱하는 제품을 다룰 때도 같은 어휘가 나옵니다.

다섯 쓰임새를 관통하는 한 가지 원리

지금까지 살펴본 장면들을 묶어보면 공통 원리가 보여요. “내 변경이 미치는 파급 영향의 방향”이 곧 downstream입니다.

  • nginx upstream: 내가 요청을 보내 응답을 받아오는 쪽 → 내가 기대는 원천
  • 라이브러리 upstream: 내가 의존하는 원천 프로젝트
  • 파이프라인 downstream: 내 모델이 깨지면 영향을 받는 쪽
  • 배포판 downstream: 원류 업데이트가 흘러 내려가는 쪽
  • 컨슈머 downstream: 내가 쏜 이벤트가 도달하는 쪽
  • CDN downstream: 내가 보낸 응답이 캐시되는 쪽

“받는 쪽 = 소비자 = downstream”, “주는 쪽 = 원천 = upstream”이라고 외워두면 거의 틀리지 않습니다. 반대로 실무적으로 “upstream은 내가 받을 것을 고민할 때, downstream은 내 변경의 파급을 고민할 때” 주로 등장해요. 문장을 읽다가 어느 방향인지 막힐 땐 “이 문장이 원천 걱정인가, 파급 걱정인가?”를 한 번 스스로 물어보면 됩니다.

한국어에서의 표기 관습

실무 문서에서 한국어로 옮길 때 재미있는 비대칭이 있습니다. “하류 서비스”라고 쓰면 어색하지만 “다운스트림 컨슈머”는 자연스럽게 읽히거든요. 영어 원문을 그대로 받아들여 음차로 쓰는 쪽이 관행으로 굳어 있어요.

한국어 기술 문서에서 자주 보이는 표기를 정리하면 이런 모습입니다.

  • 상류 API / upstream API / 업스트림 API — 세 표현 모두 통용되지만, 실무에서는 “업스트림”이 가장 흔해요.
  • downstream consumer / 다운스트림 컨슈머 — “하류 컨슈머”라고 쓰는 경우는 거의 없어요.
  • upstream 프로젝트 / 원류 프로젝트 — 오픈소스 쪽에서 “원류”가 종종 쓰여요.

글을 쓰실 땐 독자층에 따라 선택하시면 됩니다. 네트워킹·데이터 엔지니어링 독자라면 음차 표기(“업스트림”)가 편하게 읽히고, 일반 개발자 대상이라면 “상류 API (upstream API)“처럼 괄호 병기가 친절해요.

방향을 다시 한번 점검하기

정리 겸 한 가지 체크 장면으로 마무리해볼게요. React Query를 쓰는 프론트엔드 앱에서 백엔드 API를 호출하는 상황을 떠올려봅시다.

graph LR
    A["프론트엔드 앱<br/>(A)"] -->|요청| B["React Query<br/>(B)"] -->|요청| C["백엔드 API<br/>(C)"] -->|요청| D["PostgreSQL<br/>(D)"]
  • React Query(B) 입장에서 upstream은? → 백엔드 API(C)
  • 백엔드 API(C) 입장에서 upstream은? → PostgreSQL(D)
  • 백엔드 API(C) 입장에서 downstream은? → React Query(B)와 프론트엔드(A)
  • PostgreSQL(D) 입장에서 downstream은? → 백엔드 API(C)

각 지점에서 “내가 데이터를 받아오는 원천 쪽”을 찾으면 상류이고, “내가 데이터를 흘려보내는 소비자 쪽”을 찾으면 하류입니다. 이 구도가 익숙해지면 대부분의 기술 문서가 한층 편하게 읽혀요.

마치며

Upstream과 downstream은 처음 마주칠 때는 방향이 뒤바뀐 것처럼 느껴지지만, 강물 은유 하나만 붙잡고 있으면 어디서든 꾸준히 작동하는 용어입니다. “데이터의 원천이 상류, 소비자가 하류”라는 기준 한 줄만 기억해두셔도 nginx 설정부터 dbt 파이프라인, 오픈소스 이슈 트래커, Cloudflare CDN 문서까지 같은 어휘로 읽어낼 수 있어요.

이 방향 감각은 인프라·아키텍처 논의에서 특히 자주 필요합니다. OAuth에서 MCP 서버가 upstream API 토큰을 어떻게 다뤄야 하는지 궁금하시면 MCP Authentication을, 기업 환경에서 내부 API를 프록시하는 Zero Trust 구조가 궁금하시면 Cloudflare Access를 이어서 읽어보시길 권합니다. 비슷하게 방향이 헷갈리는 HTTP 헤더 용어는 Host, Origin, Referer 총정리에서 풀어두었으니 함께 참고해보세요.

This work is licensed under CC BY 4.0 CC BY

개발자를 위한 뉴스레터

달레가 정리한 AI 개발 트렌드와 직접 만든 콘텐츠를 전해드립니다.

Discord