오용하기 어려운 API 설계
Source: Dev.to
API 소비자에 대한 가정
API를 설계할 때 다음을 가정하지 마세요:
- 소비자가 문서를 꼼꼼히 읽을 것이라고.
- 입력이 항상 유효할 것이라고.
- 호출이 올바른 순서로 이루어질 것이라고.
대신 다음을 가정하세요:
- 누군가가 이를 오해할 것이다.
- 누군가가 검증을 건너뛸 것이다.
- 누군가가 생각 없이 예시를 복사‑붙여넣기 할 것이다.
좋은 API는 “올바르게 사용될 것”에 의존하지 않습니다. 디자인 자체가 올바름을 강제합니다.
모호한 API는 오용을 초래한다
나쁜 예
POST /updateUser
이게 무엇을 업데이트하나요?
- 이름?
- 이메일?
- 비밀번호?
- 모두?
더 나은 예
PATCH /users/{id}/email
이제:
- 의도가 명확합니다.
- 범위가 제한됩니다.
- 오용이 어려워집니다.
엔드포인트가 “너무 많은 일을” 할 수 있다면 결국 잘못된 일을 하게 됩니다. 시니어 엔지니어는 잘못된 상태가 존재할 수 없는 API를 설계하려고 합니다.
일관된 상태를 위한 설계
문제 있는 페이로드
{
"status": "active",
"deleted": true
}
사용자는 활성이면서 삭제될 수 없습니다. API는 이러한 모순된 입력을 거부해야 합니다.
원하는 설계
- API는 충돌하는 필드를 받아들이지 않는다.
- 데이터 모델이 불가능한 상태를 방지한다.
API가 모순된 데이터를 허용한다면 버그는 클라이언트가 아니라 설계에 있습니다.
잘못된 입력 처리
무음 동작 (위험)
- 누락된 필드 → 기본값 적용
- 잘못된 입력 → 무시
- 부분 실패 → 성공 응답
이렇게 하면 버그가 보이지 않게 됩니다.
권장 접근법
- 잘못된 입력을 크게 거부한다.
- 명확한 오류 메시지를 반환한다.
- 빠르고 일찍 실패한다.
API는 명시적인 오류를 통해 소비자에게 올바른 사용법을 가르쳐야 합니다.
“매직” 동작 피하기
매직 API는 처음엔 편리해 보이지만 나중에 고통스럽습니다.
매직 동작 예시
- 자원을 자동으로 생성한다는 사실을 알리지 않는다.
- 제한 없이 조용히 재시도한다.
- 숨겨진 플래그에 따라 동작을 바꾼다.
중요한 일이 발생한다면 명시적으로 드러내세요.
멱등성 및 안전한 재시도
실제 시스템에서는:
- 요청이 재시도된다.
- 클라이언트가 타임아웃된다.
- 네트워크가 실패한다.
API를 두 번 호출했을 때 의도치 않은 부작용이 발생한다면 프로덕션에서 문제가 됩니다.
설계 지침
- 반복 요청이 안전해야 한다.
- 중복 호출이 상태를 손상시키지 않는다.
- 클라이언트가 복잡한 재시도 로직을 가질 필요가 없다.
이것만으로도 많은 프로덕션 사고를 예방할 수 있습니다.
오해 방지
6개월 후에 당신의 API를 사용하는 사람은:
- 당신이 아닐 수도 있다.
- 원래 맥락을 모를 수도 있다.
- 압박을 받고 있을 수도 있다.
스스로에게 물어보세요:
- 이 API가 오해될 수 있나요?
- 잘못된 순서로 호출될 수 있나요?
- 오용이 데이터 손상을 일으킬 수 있나요?
답이 “예”라면 재설계하세요.
실제 버그 사례
POST /processPayment
두 번 호출 → 이중 청구.
더 나은 설계
- 의도와 실행을 분리한다.
- 멱등성 키를 요구한다.
- 부작용을 명시한다.
초기에 조금 더 노력하면 나중에 사고를 크게 줄일 수 있습니다.
최종 요약
API는 단순한 엔드포인트가 아니라 계약입니다. 잘 설계된 API는:
- 잘못될 수 있는 경우를 제한한다.
- 올바른 사용을 명확히 보여준다.
- 잘못된 사용을 어렵게 만든다.
- 인간 오류로부터 시스템을 보호한다.
시니어 엔지니어는 단순히 동작하는 API를 설계하지 않습니다 — 오용하기 어려운 API를 설계합니다.