HTTP 메서드의 활용

Aiden·2022년 2월 25일
1

HTTP

목록 보기
10/13
post-thumbnail

총 두 번의 포스팅에 걸쳐, HTTP 메서드의 기본적인 개념부터 각 메서드들의 특징, 메서드의 속성들에 대해 알아보았다.

이번 포스팅에서는 지금까지 살펴본 HTTP 메서드들이 실제로 어떻게 활용될 수 있는지에 대해 알아보고, 클라이언트가 서버에 데이터를 보내는 방법에 대해 각 상황별로 정리해보고자 한다.

먼저, 클라이언트가 서버에 데이터를 전송하는 방법부터 정리해보자.


클라이언트 서버 데이터 전송


이전 HTTP 메서드 포스팅에서 다양한 그림들을 통해 HTTP Method 에 대해 알아보았는데, 서버가 클라이언트에게로 응답 메시지 Body 에 데이터를 담아 전송하는 예시가 대부분이었다.
이는 클라이언트가 서버에게 데이터에 대한 처리를 요청하면, 서버가 이에 대한 결과를 반환하는 형식에 대해 주로 다뤄왔기 때문이다.

따라서, 반대로 클라이언트에서 서버로 데이터를 전송하고자 하는 상황들과 그 방법에 대해 정리하고 넘어가는 과정이 필요하다고 생각했다.

📌 이제부터 설명하는 모든 내용은 클라이언트에서 서버로 데이터를 전송하는 상황을 의미한다.


💡 데이터 전달 방식

📌 데이터 전달 방법

  • 쿼리 파라미터 활용
  • 메시지 Body 활용

우선, 클라이언트에서 서버로 데이터를 전송하기 위한 방법에는 크게 두 가지가 있다.

✅ 쿼리 파라미터

첫 번째는 메시지의 URL 을 명시할 때, 쿼리 파라미터에 전달하고자하는 데이터를 함께 넣어주는 방법이다. 이 방법은 주로 GET 메서드에서 사용되며, 검색 필터 데이터를 서버에 함께 전달하는 경우에 자주 활용된다.

위 그림처럼, GET 메서드 뒤의 URL 에 쿼리 파라미터 ( ?q=hello&hl=ko ) 를 붙여 서버로 전송할 수 있다. 예시는 'hello' 에 대한 한국어 검색결과를 조회하기 위한 쿼리 파라미터이다.
물론, GET 메서드에서도 Body 에 데이터를 담아 전송할 수 있지만, 지원하지 않는 서버가 많기 때문에 권장되지 않는 방법이다.

✅ 메시지 Body

두 번째는 메시지의 Body 에 전달하고자 하는 데이터를 담아 전송하는 방법이다. POST PUT PATCH 메서드를 사용할 때, 요청의 대상이 되는 데이터를 담아 서버로 전송하기 위해 활용된다.

위 그림에서는 POST 메서드와 함께 Body 에 데이터를 담아 서버에 전송함으로서, /members 라는 URL 에 새로운 데이터의 등록을 요청하는 메시지임을 유추해볼 수 있다.
즉, 회원 가입, 상품 주문, 리소스 등록 및 변경 등 특정 데이터에 대한 처리를 요청하는 경우에는 주로 Body 에 데이터를 담아 전송하는 방법을 채택한다.


💡 4 가지 케이스

📌 클라이언트에서 서버로 데이터를 전송하는 4 가지 케이스

  • 정적 데이터 조회
  • 동적 데이터 조회
  • HTML Form
  • HTTP API

클라이언트가 데이터를 전달하는 방법에는 쿼리 파라미터 를 활용하거나, 메시지 Body 를 활용하는 방법이 있었다.
그렇다면 클라이언트가 이 두 가지 방법을 활용하여 데이터를 전송하는 경우에 대해 4 가지 케이스로 정리해보자.

정적 데이터 조회

먼저, 정적 데이터를 조회하는 경우이다.
사실, 정적 데이터를 조회할 때는 서버에 데이터를 전달해줄 필요가 없지만, 이후 3 가지 케이스에 대한 이해를 돕기 위해 추가해주었다.

정적 데이터를 조회하는 경우는 주로 이미지나 정적인 텍스트 문서에 대해 요청하는 상황을 의미한다. 이 때는, GET 메서드 뒤에 리소스의 URL 만 명시해주면, 쿼리 파라미터나 Body 에 추가적인 데이터를 담아주지 않더라도 정상적으로 원하는 리소스를 받아올 수 있다.

위 예시에서는 추가적인 데이터없이 GET 메서드 뒤에 '/static/star.jpg' 라는 이미지의 위치 URL 을 명시해주었고, 서버에서는 정상적으로 이미지 파일을 Body 에 담아 응답 메시지를 생성해주었음을 알 수 있다. 응답 메시지의 Body 에 담긴 긴 문자열은 이미지 파일의 바이너리 데이터이다.

동적 데이터 조회

동적 데이터를 조회하는 경우에는, 정적 데이터와는 다르게 서버에 데이터를 함께 전송해주어야 한다. 따라서 이 때는 쿼리 파라미터나 Body 에 데이터를 담아 메시지를 생성하게 된다.

예시에서는, '/search' 라는 URL 뒤에 쿼리 파라미터로 검색 필터에 대한 데이터를 추가해주었다. 이후, 서버에서는 요청 메시지의 쿼리 파라미터를 기반으로 검색 결과를 필터해서 동적으로 생성된 결과를 반환하게 된다.

이렇듯, GET 을 활용한 데이터 조회의 경우는 정적 데이터와 동적 데이터로 나뉘게 되는데, 정적 데이터일 때는 쿼리 파라미터를 작성하지 않으며, 동적 데이터를 조회할 때는 쿼리 파라미터에 검색 필터나 정렬 조건과 같은 데이터를 담아 전송하는 것이 일반적이다.

HTML Form

다음 케이스는 html<form> 태그를 활용하여 입력값을 받아 서버로 전송하는 경우이다.

아래의 html 코드 예시를 보자.

<form action="/save" method="post">
  <input type="text" name="username" placeholder="username"/>
  <input type="text" name="age" placeholder="age"/>
  <button type="submit">Submit</button>
</form>

위와 같이 html<form> 태그를 작성하면 아래와 같은 입력폼이 생성되며,

Submit

각 입력폼에 데이터를 입력하고 제출하면, 입력된 데이터가 서버로 전송된다.

이 경우, 입력된 데이터로 생성된 메시지는 다음과 같다.
(username 에는 "kim", age 에는 "20" 을 입력했다고 가정한다.)

html 코드의 action 속성값과 method 속성값은 각각 URL 과 메서드를 결정하게 되고, 폼에 입력된 데이터는 쿼리 파라미터와 유사한 형태로 Body 에 담겨있는 모습을 확인할 수 있다.

이렇듯, 순수한 html 로 폼을 구현하였을 경우에도 클라이언트의 입력데이터를 서버에 전송해줄 수 있다. 따라서 단순히 html 로 구현된 회원가입 폼이나, 상품 주문, 데이터 변경 및 수정과 같은 작업들은 위와 같은 메시지 생성 과정을 통해 입력데이터를 전송하게 된다.

⛔ 추가적으로 이렇게 단순한 html 폼을 활용해 데이터를 서버로 전송할 경우에는 GETPOST 메서드만 사용이 가능하다.

✅ HTTP API

마지막 케이스는 HTTP API 를 설계하여 데이터를 전송하는 경우이다.

📌 HTML FormHTTP API ?

  • 앞서 살펴본 html form 을 활용한 케이스는 폼에 입력된 데이터를 전송하여 html 의 응답결과를 반환받게 되는 반면, HTTP API 는 일반적으로 JSON 과 같은 데이터를 응답결과로 반환받는다는 점에 있어 차이가 있다.
  • 즉, JSON 과 같은 데이터 형식을 반환한다면 HTTP API 이고, html 을 반환한다면 html form 의 경우로 요약할 수 있을 것이다.
  • 또한, html form 을 사용할 경우 GETPOST 만 사용이 가능했던 반면,
    HTTP API 를 사용할 경우 모든 메서드를 사용할 수 있다는 것도 중요한 차이점이다.

일반적으로 HTTP APIhtml 이 존재하지 않는 백엔드 시스템 간의 통신에 사용되기도 하며, 모바일 앱 클라이언트의 데이터 전송 시에도 활발하게 사용된다.
또한, 웹 클라이언트AJAX 와 같은 자바스크립트를 활용한 비동기 통신에서도 html form 대신 HTTP API 를 사용한다.

이렇게 다양한 곳에서 활용되는 HTTP API 는 모든 메서드를 활용할 수 있다는 장점을 가지고 있으며, 각 메서드의 설계 시에는 앞선 케이스들과 동일한 데이터 전달 방식을 사용한다.

  • GET : 쿼리 파라미터 사용
  • POST PUT PATCH : 메시지 Body 사용

위 그림에서는 POST 메서드를 활용하여 Body 에 담긴 JSON 포맷의 데이터 처리를 서버에 요청하고 있다. 예전에는 XML 데이터를 주로 사용했지만 가독성과 같은 불편함이 있어 최근에는 JSON 데이터를 사실 상 표준으로 사용하고 있다고 한다.

이렇게 클라이언트가 서버에게 데이터를 전달하는 두 가지 방법과 4 가지 케이스에 대해 알아보았다. 이제부터는 실제로 HTTP Method 가 활용되는 예시들을 살펴보며, 컬렉션과 스토어, Control URI 에 대한 개념들을 살펴보도록 하자.



HTTP API 설계 예시


💡 회원 관리 시스템

📌 Requirements

  • POST 기반 등록
  • 회원 목록 조회
  • 회원 등록
  • 회원 조회
  • 회원 수정
  • 회원 삭제

먼저, 회원 관리 시스템의 5 가지 기능을 HTTP API 로 설계하는 예시를 확인해본다.

훌륭한 설계를 위해서 우리는 각 기능에서 리소스만을 추출해 URI 를 설계하여야 하며, 대상 리소스에 수행하고자하는 행위에 따라 적절한 메서드를 사용하여 다음과 같이 구현할 수 있다.

  • 회원 목록 조회 GET /members
  • 회원 등록 POST /members
  • 회원 조회 GET /members/{id}
  • 회원 수정 PATCH /members/{id} ✅ PUT POST
  • 회원 삭제 DELETE /members/{id}

여기서 눈여겨봐야할 점은 설계된 각각의 URI 들이 'members' , 'members/{id}' 와 같이 리소스만 정확하게 추출해냈다는 점, 회원 등록의 경우 POST 메서드를 사용하였다는 점, 회원 수정PATCH 를 사용하였다는 점이다.

우선, 리소스 추출에 대한 내용은 HTTP Method 를 중점적으로 다루었던 지난 포스팅에서 자세히 설명했던 부분이다. 짧게 요약하면, URI 는 리소스를 유일하게 식별하는 식별자이기 때문에 그 본질은 '리소스 식별' 에 있다는 것이다.

따라서, '회원 목록 조회' 의 경우, '회원 목록' 까지가 리소스이고, '조회' 와 같은 행위와 관련된 부분은 메서드로 처리해주는 것이 이상적인 설계 방법이 될 것이다.
위의 설계 예시에서도 '회원 목록' 은 members 로, 목록 내 각 '회원' 들에 대해서는 id 값을 활용하여 정확한 리소스의 위치를 지정할 수 있도록 설계된 것을 확인할 수 있다.

다음은 회원 수정PATCH 를 사용하였다는 점이다.
회원 정보를 수정할 수 있는 메서드는 PATCH 뿐 아니라, PUTPOST 로도 충분히 가능하다. 그렇다면 예시에서는 왜 굳이 PATCH 를 사용하였을까?

이는 PATCHPUT 의 특징을 떠올려보면 해답을 찾을 수 있다.
PUT 은 기존 리소스를 완전히 대체하는 메서드로서, 부분 변경이 불가능하다. 따라서, 리소스의 부분 변경을 위해서는 리소스의 모든 내용을 다시 작성한 뒤 변경하고자 하는 부분만을 수정하여 전송해야 하는 번거로움이 있다. 반면에, PATCH전송한 데이터에 해당하는 컬럼만 부분적으로 수정이 가능한 메서드이기 때문에 리소스의 모든 내용을 다시 작성해야 할 필요가 없어 간편하다.

또한, 기존에 존재하지 않는 리소스를 변경하려는 시도가 있을 경우, PUT 은 그대로 신규 리소스를 생성하게 되지만, PATCH 는 기존 리소스가 존재하지 않을 경우 오류를 발생시킨다. 이는 데이터의 무결성이나 일관성의 유지에 있어 의도치 않은 실수를 예방할 수 있는 장점으로 작용할 수도 있다.

즉, 정보를 안전하게 수정하기 위한 목적에는 PATCH 메서드가 가장 적합하다는 것이다.

마지막으로, POST 를 사용한 회원 등록 기능을 자세히 들여다보자.
회원 등록 기능은 예시에서 POST 메서드를 사용하도록 설계되어 있고, URL 은 '/members' 로 설계되어 '회원' 이 아닌 '회원 목록' 을 가리키고 있다. 그렇다면 등록될 회원이 가지게 될 정확한 id 값은 어디에서 지정해주는 걸까?
이는 지난 포스팅에서 언급했던 부분이기도 한데, POST 로 신규 리소스를 생성하게 될 경우 리소스의 정확한 위치는 서버에서 결정하게 된다.
즉, 클라이언트는 신규 리소스의 정확한 URI 를 알 수 없기 때문에 회원 정보들이 관리되는 저장소(예시에서는 '회원 목록')의 URI 까지만 명시해주고, 리소스가 생성된 정확한 URI(예시에서는 'id')는 서버에서 지정해주는 것이다.

📌 컬렉션(Collection)

이 때, 회원 정보들이 관리되는 저장소컬렉션이라고 한다.
컬렉션은 서버에서 관리하는 리소스 디렉토리로서, 서버가 리소스의 URI 를 직접 생성하고 관리한다.
때문에 클라이언트는 리소스가 생성될 정확한 위치를 설정할 수 없고, 컬렉션의 URI 만을 명시하여 리소스의 생성 및 관리를 서버에게 전적으로 맡기게 되는 것이다.
예시에서는 '/members' 의 '회원 목록' 이 컬렉션이 될 것이다.

이렇게 회원 관리 시스템의 예시를 통해 PUTPATCH 의 차이에 대해서 알아볼 수 있었고, POST 를 사용하여 신규 리소스를 등록할 경우 컬렉션을 사용하게 된다는 점도 알게 되었다.

그렇다면 클라이언트에서, 생성될 신규 리소스의 정확한 위치를 지정해주고 싶다면 어떤 방법을 사용할 수 있을까?
이러한 경우에는, 서버에서 관리하는 컬렉션을 사용해선 안되기 때문에 POST 메서드가 아닌 PUT 메서드를 활용하여 신규 리소스를 생성해줄 수 있다.
이에 대한 자세한 내용은 아래 예시를 통해 확인해보자.


💡파일 관리 시스템

📌 Requirements

  • PUT 기반 등록
  • 파일 목록 조회
  • 파일 등록
  • 파일 조회
  • 파일 삭제
  • 파일 대량 등록

이번에는 파일 관리 시스템의 HTTP API 설계 예시이다.
구현된 HTTP APIURI 는 다음과 같다.

  • 파일 목록 조회 GET /files
  • 파일 등록 PUT /files/{filename}
  • 파일 조회 GET /files/{filename}
  • 파일 삭제 DELETE /files/{filename}
  • 파일 대량 등록 POST /files

파일 목록인 files 와 파일명인 filename 으로 리소스만을 정확하게 추출해낸 훌륭한 URI 설계라고 볼 수 있다.

그렇다면, 이전의 예시와 다른 점은 무엇일까?
언뜻 보기에는 회원 관리 시스템 예시와 다른 점이 없어보이지만, 가장 큰 차이점은 신규 리소스의 등록이 PUT 메서드를 통해 이루어진다는 점이다.

사실 파일 관리 시스템에서는 PUT 메서드를 활용해 신규 리소스를 등록하는 것이 POST 를 활용하는 것보다 적절할 수 있다. 새로운 파일을 생성할 때 이름이 같은 파일은 덮어쓰고 생성해야 하며, 기존에 존재하지 않는 파일은 신규 파일로 생성해주어야 하기 때문이다.
이러한 파일 관리 시스템의 특성은 리소스를 완전히 대체하는 PUT 의 특징과 너무나도 잘 들어맞는다.

이제, 이 점에 주목해 POST 기반 등록과 PUT 기반 등록의 차이에 대해 알아보도록 하자.

이전 회원 관리 시스템에서는 POST 메서드를 통해 신규 리소스를 생성하였으며, 따라서 클라이언트에서 리소스 생성 위치를 직접 지정해줄 수 없기 때문에 컬렉션의 URI 를 명시해주었다.

반면, 지금의 파일 관리 시스템 예시에서는 PUT 메서드를 통해 신규 리소스를 생성하고 있으며, 클라이언트에서 리소스가 생성될 위치를 정확하게 지정해주고 있음을 확인할 수 있다. '/files/{filename}' 으로 파일 목록 내 파일명까지 명시해주고 있기 때문이다.

📌 스토어(Store)

이렇게, PUT 메서드를 활용해 신규 리소스를 등록할 때는 클라이언트에서 생성될 리소스의 정확한 URI 를 알고 직접 지정해주어야 하는데, 이를 스토어라 한다.
스토어는 컬렉션과 반대로 클라이언트가 관리하는 리소스 저장소로서, 클라이언트가 직접 리소스의 URI 를 설정하고 관리하게 된다. 예시에서는 '/files' 의 '파일 목록' 이 스토어가 될 것이다.

즉, 컬렉션이 아닌 스토어를 사용하기 때문에 서버에서 리소스의 위치를 지정해줄 수 없어 클라이언트가 정확한 위치를 지정 및 생성해주어야 한다. 또한, 스토어는 클라이언트가 관리하는 저장소이기 때문에 클라이언트만이 리소스의 정확한 위치를 지정해줄 수 있다.

정리하면, POSTPUT 기반 등록의 차이는 URI 를 생성하는 주체에 있다. POST 를 사용할 경우, 컬렉션에 의해 서버에서 URI 를 결정하게 되고, PUT 을 사용할 경우, 스토어에 의해 클라이언트에서 URI 를 결정하게 되는 것이다.



HTML Form 설계 예시


💡 회원 관리 시스템

📌 Requirements

  • html 만 사용 가능
  • 회원 목록
  • 회원 등록 폼
  • 회원 등록
  • 회원 조회
  • 회원 수정 폼
  • 회원 수정
  • 회원 삭제

마지막으로 html form 의 회원 관리 시스템 설계 예시를 확인해보자.

앞서 이야기했듯이, html form 의 경우에는 GETPOST 만 사용이 가능하다.
물론, AJAX 와 같은 기술을 사용하면 다른 메서드들도 활용할 수 있지만, 여기서는 순수 html 만 사용이 가능하다는 전제가 있기 때문에 GETPOST 만 사용하여 위의 기능들을 설계하여야 한다.

이렇게 극단적으로 제한된 메서드를 가지고 어떻게 7 가지 기능들을 모두 구현해낼 수 있을까?

해답은 POST 에 있다.
POST만능 메서드로서 클라이언트와 서버가 사전에 약속한 작업을 수행하기 때문에, 입력되는 각 리소스와 메서드마다 수행할 작업을 정의해주기만 하면 성공적으로 7 가지 기능에 대해 모두 구현해낼 수 있다.

그럼 바로 URI 구현 결과를 확인해보자.

  • 회원 목록 GET /members
  • 회원 등록 폼 GET /members/new
  • 회원 등록 POST /members/new ✅ /members
  • 회원 조회 GET /members/{id}
  • 회원 수정 폼 GET /members/{id}/edit
  • 회원 수정 POST /members/{id}/edit ✅ /members/{id}
  • 회원 삭제 POST /members/{id}/delete

다양한 메서드를 활용한 이전 예시들보다는 확실히 복잡하긴 하지만, 성공적으로 7 가지 기능에 대해 단 2 개의 메서드로 구현해낼 수 있다.

먼저, GET 을 사용한 기능들부터 확인해보자.
회원 목록회원 등록 폼, 회원 조회회원 수정 폼은 데이터나 특정 폼화면을 요청하는 작업이기 때문에 GET 메서드가 정상적으로 사용되었음을 확인할 수 있다.

다음은, POST 를 사용한 기능들이다.
회원 등록, 회원 수정, 회원 삭제의 모든 기능들이 모두 POST 메서드로 설계되었으므로, 각 기능들을 구분하기 위해 리소스의 URI 를 서로 다르게 설계해주었다.
따라서, 서버에서는 같은 POST 메서드이더라도 리소스의 URI 가 다르기 때문에 사전에 약속한 작업을 각각 구분하여 진행할 수 있을 것이다.

이렇게 메서드의 사용에 제약이 있거나 특정 메서드를 사용하기 애매할 경우에는 POST 메서드를 대신 사용하여 기능을 구현해낼 수 있다.

📌 컨트롤 URI(Control URI, Controller)

하지만 여기서 의문점이 생길 수 있다.
분명히 URI 를 설계할 때는 리소스만을 추출하여 설계하고, 대상 리소스에 수행할 행위는 메서드로 표현하여야 한다고 설명해왔는데, 위의 예시에서는 'new', 'edit', 'delete' 와 같은 '행위' 들이 URI 에 포함되어 있는 모습을 확인할 수 있다.

바로 이렇게, '동사' 로 된 URI컨트롤 URI 혹은 Controller 라고 부르며, 메서드의 사용이 제한되어 있는 경우나 특정 메서드로 해결하기 애매한 경우에는 어쩔 수 없이 Controller 를 사용하여 URI 를 설계하기도 한다.

실제로 , 실무에서는 구현해야 하는 기능이 굉장히 많고, 다양한 상황에서의 제약이 항상 존재하기 때문에 이러한 컨트롤 URI 를 자주 사용하게 된다고 한다. 이는 html form 설계 뿐 아니라, HTTP API 를 설계할 때도 마찬가지이다.
하지만 최대한 리소스만을 추출하여 URI 를 설계할 수 있도록 노력하고, 리소스만을 활용하여 설계할 수 없는 불가피한 상황에서만 컨트롤 URI 를 사용하는 태도가 지향되어야 한다.


이렇게 HTTP Method 의 설계 예시들을 마지막으로, 메서드 포스팅을 마치게 되었다.

사실 최선의 URI 설계법은 아직까지도 다양한 토론이 이루어지고 있고, 각각의 방법들이 장단점을 가지고 있어 하나의 Best Practice 란 존재하지 않을 수도 있다.
또한, 설계하는 애플리케이션이나 데이터의 특성에 따라서도 Best Practice 는 항상 달라질 수 있다.

결국, 컨트롤 URI 사용과 POST 메서드의 무분별한 사용을 지양하는 등 우리가 지금까지 살펴보았던 URI 설계방법은 최근 들어 권장되는 하나의 패러다임일 뿐, 그것이 왕도일 수는 없는 것이다.
앞으로 더 나은 Practice 들이 계속해서 나올 것이고, 패러다임은 항상 바뀔 수 있기 때문이다.

따라서 우리가 할 수 있는 일은 각 메서드에 대한 기본 개념을 탄탄히 쌓고, 특징과 속성에 대해 정확하게 파악해 다양한 방법론들을 특정 상황에 유연하게 적용할 수 있는 능력을 쌓는 일이 될 것이다.

이것으로 메서드 포스팅을 마치고,
다음 포스팅에서는 HTTP 의 상태 코드에 대해서 다룰 예정이다.



출처


  • 김영한 님의 강의 모든 개발자를 위한 HTTP 웹 기본 지식 을 정리한 포스팅입니다.

0개의 댓글