본문 바로가기
Backend2024년 6월 18일5분 읽기

API 버전 관리 전략 — URL vs Header vs Content Negotiation

YS
김영삼
조회 667

API 버전 관리가 필요한 이유

API는 한번 공개되면 클라이언트가 의존하게 됩니다. 응답 구조 변경, 필드 삭제, 동작 변경 등 Breaking Change가 발생할 때, 기존 클라이언트를 깨뜨리지 않으면서 새 버전을 제공해야 합니다.

1. URL Path 버전 관리

const express = require('express');
const app = express();

const v1Router = express.Router();
v1Router.get('/users', (req, res) => {
  res.json({ users: [{ name: 'Kim', email: 'kim@test.com' }] });
});

const v2Router = express.Router();
v2Router.get('/users', (req, res) => {
  res.json({
    data: [{ fullName: 'Kim', email: 'kim@test.com', avatar: null }],
    meta: { total: 1, page: 1 }
  });
});

app.use('/api/v1', v1Router);
app.use('/api/v2', v2Router);

2. Custom Header 버전 관리

function apiVersion(req, res, next) {
  const version = req.headers['x-api-version'] ||
                  req.headers['api-version'] || '1';
  req.apiVersion = parseInt(version);
  next();
}

app.use(apiVersion);

app.get('/api/users', (req, res) => {
  if (req.apiVersion >= 2) {
    return res.json({
      data: [{ fullName: 'Kim', email: 'kim@test.com' }],
      meta: { total: 1 }
    });
  }
  res.json({ users: [{ name: 'Kim', email: 'kim@test.com' }] });
});

3. Content Negotiation (Accept Header)

app.get('/api/users', (req, res) => {
  const accept = req.headers.accept || '';
  const match = accept.match(/application\/vnd\.myapi\.v(\d+)\+json/);
  const version = match ? parseInt(match[1]) : 1;

  if (version >= 2) {
    res.type('application/vnd.myapi.v2+json');
    return res.json({ data: [{ fullName: 'Kim' }], meta: { total: 1 } });
  }
  res.type('application/vnd.myapi.v1+json');
  res.json({ users: [{ name: 'Kim' }] });
});

전략 비교표

기준URL PathCustom HeaderContent Negotiation
직관성높음중간낮음
RESTful낮음중간높음
캐싱쉬움Vary 헤더 필요Vary 헤더 필요
브라우저 테스트쉬움어려움어려움
도입 난이도낮음중간높음
대표 사용자Stripe, GoogleAzureGitHub API v3

Deprecation 전략

app.use('/api/v1', (req, res, next) => {
  res.set('Deprecation', 'true');
  res.set('Sunset', 'Sat, 01 Mar 2025 00:00:00 GMT');
  res.set('Link', '; rel="successor-version"');
  next();
}, v1Router);

선택 가이드

  • 공개 API / 다수 외부 클라이언트: URL Path 방식이 가장 안전하고 직관적입니다.
  • 내부 API / 마이크로서비스 간 통신: Header 방식으로 URL을 깔끔하게 유지하세요.
  • Breaking Change가 드문 경우: 버전 관리 대신 Additive Change 원칙(필드만 추가)으로 단일 버전을 유지하세요.
  • 어떤 방식이든, Sunset/Deprecation 헤더와 명확한 마이그레이션 가이드를 제공하세요.

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록