REST API URL에 동사를 사용하면 안 되는 이유

Ashley Innocent

Ashley Innocent

13 March 2026

REST API URL에 동사를 사용하면 안 되는 이유

Apidog 엔터프라이즈

온프레미스 배포

SSO & RBAC

SOC 2 준수

Apidog Enterprise 살펴보기

요약

REST API URL은 동사(행위)가 아닌 명사(리소스)를 포함해야 합니다. HTTP 메서드(GET, POST, PUT, DELETE)가 동사 역할을 합니다. /getUser 또는 /createOrder와 같은 행위 동사를 사용하는 것은 REST 원칙을 위반하고, 일관성을 해치며, API 유지보수를 어렵게 만듭니다. 현대 PetstoreAPI는 전반적으로 리소스 지향적인 URL을 사용합니다.

소개

상태별로 애완동물을 검색하는 API 엔드포인트를 설계하고 있습니다. 첫 번째 본능은 GET /findPetsByStatus?status=available일 수 있습니다. 이는 서술적이고 명확하며 정확히 무엇을 하는지 알려줍니다. 하지만 이것은 잘못된 설계입니다.

REST API는 URL에 동사가 아닌 명사를 사용해야 합니다. HTTP 메서드가 동사 역할을 합니다. GET /pets?status=available이 올바른 설계입니다. URL은 리소스(pets)를 나타내고, 메서드는 행위(get)를 나타냅니다.

구 Swagger Petstore는 /pet/findByStatus/pet/findByTags와 같은 엔드포인트에서 이러한 실수를 저질렀습니다. URL에 이러한 행위 동사를 사용하는 것은 REST 원칙을 위반하고 유지보수 문제를 야기합니다. 현대 PetstoreAPI는 리소스 지향적인 URL을 일관되게 사용하여 이 문제를 해결했습니다.

💡
REST API를 구축하거나 테스트 중이라면, Apidog는 URL 디자인을 검증하고, 엔드포인트 동작을 테스트하며, API가 REST 규칙을 따르는지 확인하는 데 도움이 됩니다. OpenAPI 사양을 가져와 URL에 동사 사용 여부를 확인하고, 설계 문제를 조기에 파악할 수 있습니다.
button

이 가이드에서는 왜 동사가 REST URL에 속하지 않는지, 리소스 지향적인 엔드포인트를 설계하는 방법, 그리고 현대 PetstoreAPI가 이를 올바르게 구현하는 방법을 배울 것입니다.

REST API의 동사 문제

URL에 행위 동사를 사용하는 것은 RPC(원격 프로시저 호출) 방식으로 생각하고 있음을 나타내며, REST 방식이 아닙니다.

RPC 스타일 URL (잘못된 예)

POST /createUser
GET /getUser?id=123
PUT /updateUser
DELETE /deleteUser?id=123
GET /findUsersByRole?role=admin
POST /sendEmail
GET /calculateTotal

이러한 URL은 동작을 설명합니다. 함수 호출처럼 읽힙니다: createUser(), getUser(), sendEmail().

REST 스타일 URL (올바른 예)

POST /users
GET /users/123
PUT /users/123
DELETE /users/123
GET /users?role=admin
POST /emails
GET /orders/123/total

이러한 URL은 리소스를 설명합니다. HTTP 메서드가 동작을 제공합니다.

왜 이것이 중요한가

일관성: REST URL은 예측 가능한 패턴을 따릅니다. 리소스 이름을 알면 모든 엔드포인트를 알 수 있습니다:

동사 기반 URL에서는 모든 엔드포인트가 고유합니다. 따를 패턴이 없습니다.

확장성: API가 성장함에 따라 동사 기반 URL은 증가합니다:

리소스 지향적인 URL은 쿼리 파라미터를 사용합니다:

하나의 엔드포인트가 모든 필터링을 처리합니다.

HTTP 메서드가 동사 역할을 하는 이유

REST는 HTTP의 내장 동사를 활용합니다. 자신만의 동사를 만들 필요가 없습니다.

HTTP 메서드는 CRUD 작업에 매핑됩니다

POST   → 생성 (Create)
GET    → 읽기 (Read)
PUT    → 업데이트 (Update, 교체)
PATCH  → 업데이트 (Partial, 부분)
DELETE → 삭제 (Delete)

이러한 메서드는 정의된 의미를 가집니다. GET은 안전하고 멱등적입니다. POST는 리소스를 생성합니다. DELETE는 리소스를 제거합니다.

예시: 사용자 관리

잘못된 예 (URL에 동사 사용):

POST /createUser
GET /getUser?id=123
POST /updateUser
POST /deleteUser

각 작업이 다른 URL을 사용합니다. HTTP 메서드는 의미를 전달하지 않습니다.

올바른 예 (HTTP 메서드를 동사로 사용):

POST /users           ← 사용자 생성
GET /users/123        ← 사용자 가져오기
PUT /users/123        ← 사용자 업데이트
DELETE /users/123     ← 사용자 삭제

URL은 동일하게 유지됩니다. 메서드가 변경됩니다.

HTTP 메서드 사용의 이점

1. 캐싱: GET 요청은 캐시될 수 있습니다. 브라우저와 프록시는 이를 알고 있습니다. POST /getUser를 사용하면 캐싱이 작동하지 않습니다.

2. 멱등성: PUTDELETE는 멱등적입니다. 여러 번 호출해도 한 번 호출한 것과 동일한 효과를 가집니다. 이는 재시도 로직에 중요합니다.

3. 안전성: GET은 안전합니다—상태를 변경하지 않습니다. 도구와 크롤러는 GET 엔드포인트를 안전하게 호출할 수 있습니다.

4. 표준 준수: HTTP 클라이언트, 프록시 및 캐시는 HTTP 메서드를 이해합니다. 그들은 사용자 정의 동사를 이해하지 못합니다.

Swagger Petstore의 실제 예시

구 Swagger Petstore는 여러 동사 기반 엔드포인트를 포함하고 있습니다.

예시 1: 상태별 애완동물 찾기

Swagger Petstore (잘못된 예):

GET /pet/findByStatus?status=available

문제점:

현대 PetstoreAPI (올바른 예):

GET /pets?status=AVAILABLE

이점:

전체 구현은 현대 PetstoreAPI REST 문서를 참조하세요.

예시 2: 태그별 애완동물 찾기

Swagger Petstore (잘못된 예):

GET /pet/findByTags?tags=tag1,tag2

현대 PetstoreAPI (올바른 예):

GET /pets?tags=friendly,trained

예시 3: 사용자 로그인

Swagger Petstore (잘못된 예):

GET /user/login?username=john&password=secret

여러 문제점:

현대 PetstoreAPI (올바른 예):

POST /auth/login
Content-Type: application/json

{
  "username": "john",
  "password": "secret123"
}

이점:

현대 PetstoreAPI가 이 문제를 해결하는 방법

현대 PetstoreAPI는 전반적으로 리소스 지향적인 URL을 사용합니다.

애완동물 관리

GET /pets                    ← 모든 애완동물 목록 가져오기
GET /pets?status=AVAILABLE   ← 상태별로 필터링
GET /pets?species=dog        ← 종별로 필터링
GET /pets/{id}               ← 특정 애완동물 가져오기
POST /pets                   ← 새 애완동물 생성
PUT /pets/{id}               ← 애완동물 업데이트
PATCH /pets/{id}             ← 부분 업데이트
DELETE /pets/{id}            ← 애완동물 삭제

동사 없음. 리소스와 HTTP 메서드만 사용합니다.

주문 관리

GET /orders                  ← 주문 목록 가져오기
GET /orders/{id}             ← 주문 가져오기
POST /orders                 ← 주문 생성
PUT /orders/{id}             ← 주문 업데이트
DELETE /orders/{id}          ← 주문 취소
GET /orders/{id}/items       ← 주문 항목 가져오기

복잡한 작업

CRUD 모델에 깔끔하게 매핑되지 않는 작업의 경우, 현대 PetstoreAPI는 서브 리소스를 사용합니다:

POST /orders/{id}/payment    ← 주문 결제 처리
POST /orders/{id}/shipment   ← 주문 배송 생성
POST /pets/{id}/adoption     ← 입양 절차 시작

이것들은 여전히 리소스 지향적입니다. /orders/{id}/payment는 주문에 대한 결제 리소스를 나타냅니다.

동사가 필요해 보일 때

일부 작업은 CRUD 모델에 맞지 않습니다. URL에 동사 없이 이를 처리하는 방법은 다음과 같습니다.

검색 작업

잘못된 예:

GET /searchPets?query=labrador

올바른 옵션 1 (쿼리 파라미터):

GET /pets?search=labrador

올바른 옵션 2 (검색 리소스):

GET /pets/search?q=labrador

올바른 옵션 3 (QUERY 메서드):

QUERY /pets
Content-Type: application/json

{
  "query": "labrador",
  "filters": {
    "status": "AVAILABLE"
  }
}

현대 PetstoreAPI는 복잡성에 따라 세 가지 패턴을 모두 지원합니다.

계산

잘못된 예:

GET /calculateShipping?weight=10&destination=NY

올바른 예:

GET /shipping-estimates?weight=10&destination=NY

리소스는 "배송 견적"이며, 계산 동작이 아닙니다.

일괄 작업

잘못된 예:

POST /batchDeletePets

올바른 예:

DELETE /pets?ids=1,2,3

또는 배치 리소스를 사용합니다:

POST /pets/batch-operations
Content-Type: application/json

{
  "operation": "delete",
  "ids": [1, 2, 3]
}

상태를 변경하는 작업

잘못된 예:

POST /activateUser
POST /deactivateUser

올바른 예:

PATCH /users/{id}
Content-Type: application/json

{
  "status": "ACTIVE"
}

상태 변경은 리소스에 대한 업데이트입니다.

Apidog로 URL 디자인 테스트하기

Apidog는 REST API 디자인을 검증하고 URL에서 동사 사용을 감지하는 데 도움이 됩니다.

현대 PetstoreAPI 가져오기

  1. 현대 PetstoreAPI OpenAPI 사양 가져오기
  2. Apidog가 자동으로 테스트 케이스 생성
  3. 엔드포인트 구조 및 이름 지정 검토

URL에서 동사 확인

Apidog에서 사용자 정의 유효성 검사 규칙을 생성합니다:

// URL에 일반적인 동작 동사가 포함되어 있는지 확인
const verbs = ['get', 'create', 'update', 'delete', 'find', 'search',
               'calculate', 'process', 'send', 'fetch'];
const url = request.url.toLowerCase();

for (const verb of verbs) {
  if (url.includes(`/${verb}`)) {
    throw new Error(`URL contains verb: ${verb}. Use resource-oriented URLs instead.`);
  }
}

엔드포인트 일관성 테스트

Apidog는 관련 엔드포인트가 일관된 패턴을 따르는지 확인할 수 있습니다:

✓ GET /pets
✓ POST /pets
✓ GET /pets/{id}
✓ PUT /pets/{id}
✓ DELETE /pets/{id}

모두 동일한 기본 리소스(/pets)를 사용합니다.

현대 PetstoreAPI와 비교

현대 PetstoreAPI를 참조로 사용합니다:

  1. 자신의 API와 현대 PetstoreAPI를 모두 Apidog로 가져옵니다.
  2. 엔드포인트 구조를 나란히 비교합니다.
  3. 불일치 및 동사 사용을 식별합니다.
  4. REST 원칙에 맞게 API를 리팩토링합니다.

마이그레이션 전략

URL에 동사가 있는 기존 API가 있다면, 마이그레이션 방법은 다음과 같습니다.

전략 1: 버전 관리

올바른 URL을 사용하여 새 API 버전을 생성합니다:

# 구 API (v1)
GET /api/v1/findPetsByStatus?status=available

# 새 API (v2)
GET /api/v2/pets?status=available

하위 호환성을 위해 v1을 유지하고, v2로의 마이그레이션을 권장합니다.

전략 2: 별칭 지정

일시적으로 이전 및 새 URL을 모두 지원합니다:

# 구 URL (사용 중단)
GET /pet/findByStatus?status=available

# 새 URL (권장)
GET /pets?status=available

응답에서 사용 중단 경고를 반환합니다:

{
  "data": [...],
  "warnings": [
    {
      "code": "DEPRECATED_ENDPOINT",
      "message": "이 엔드포인트는 사용 중단되었습니다. 대신 GET /pets?status=available을 사용하세요.",
      "sunset": "2027-01-01"
    }
  ]
}

전략 3: 리디렉션

간단한 마이그레이션에는 HTTP 301 리디렉션을 사용합니다:

GET /pet/findByStatus?status=available
→ 301 영구 이동 (Moved Permanently)
Location: /pets?status=available

이것은 GET 요청에는 작동하지만 POST, PUT 또는 DELETE에는 작동하지 않습니다.

결론

REST API URL은 동사(행위)가 아닌 명사(리소스)를 포함해야 합니다. HTTP 메서드가 동사 역할을 합니다. 이 원칙은 일관성 있고 확장 가능하며 유지보수 가능한 API를 생성합니다.

구 Swagger Petstore는 /pet/findByStatus와 같은 엔드포인트로 이를 위반했습니다. 현대 PetstoreAPI/pets?status=AVAILABLE과 같이 전반적으로 리소스 지향적인 URL을 사용하여 이 문제를 해결했습니다.

주요 내용:

리소스 지향적인 URL 디자인의 전체 예시는 현대 PetstoreAPI 문서를 참조하세요.

자주 묻는 질문

REST URL에서 동사를 사용할 수 있는 경우가 있습니까?

거의 없습니다. 어떤 작업이 정말로 리소스 모델에 맞지 않는다면(예: /search 또는 /login), 동사가 허용될 수도 있습니다. 하지만 95%의 경우, 리소스로 모델링할 수 있습니다.

/login/logout은 어떻습니까?

이들은 흔히 예외로 간주됩니다. 많은 API가 /auth/login/auth/logout을 사용합니다. 또는 리소스로 모델링할 수도 있습니다: POST /sessions (로그인) 및 DELETE /sessions/{id} (로그아웃).

복잡한 쿼리는 어떻게 처리해야 합니까?

간단한 필터링에는 쿼리 파라미터를 사용하세요: /pets?status=available&species=dog. 복잡한 쿼리에는 QUERY HTTP 메서드 또는 검색 리소스(예: POST /pets/search)를 사용하세요.

내 작업이 CRUD에 매핑되지 않으면 어떻게 해야 합니까?

서브 리소스로 모델링하세요. POST /processPayment 대신 POST /orders/{id}/payment를 사용하세요. 결제는 주문과 관련된 리소스입니다.

URL이 리소스 지향적인지 어떻게 테스트합니까?

Apidog를 사용하여 OpenAPI 사양을 가져오고 URL에서 동사를 확인하세요. 현대 PetstoreAPI를 참조하여 API 구조를 비교하세요.

/pets/search 또는 /pets?search=query 중 무엇을 사용해야 합니까?

둘 다 허용됩니다. /pets?search=query는 기본적인 검색에 더 간단합니다. /pets/search 또는 QUERY /pets는 여러 파라미터를 사용하는 복잡한 검색에 더 적합합니다.

동사 기반 URL에서 마이그레이션하려면 어떻게 해야 합니까?

API 버전 관리(/v1/findPets 대신 /v2/pets), 사용 중단 경고 추가, 그리고 클라이언트에게 마이그레이션할 시간을 주세요. 자세한 내용은 마이그레이션 전략 섹션을 참조하세요.

현대 PetstoreAPI는 URL에 동사를 사용합니까?

현대 PetstoreAPI는 URL에 동사 사용을 피합니다. 검색, 필터링, 인증과 같은 작업은 리소스로 모델링되거나 쿼리 파라미터를 사용합니다. 예시는 REST API 문서를 확인하세요.

Apidog에서 API 설계-첫 번째 연습

API를 더 쉽게 구축하고 사용하는 방법을 발견하세요