안녕하세요. 이번 시간에는 HTTP 메서드에 대해 알아보겠습니다.
지난 시간 요청 메시지의 시작줄에 GET이라는 단어가 들어있는 것을 보셨을 것입니다.
GET https://www.zerocho.com HTTP/1.1
위 한 줄을 볼 때, 어떤 생각이 드시나요?(아무 생각이 없어도 괜찮습니다...) GET이라는 단어가 가져오다라는 뜻이기 때문에 느낌상 https://www.zerocho.com 페이지를 가져오라는 것같지 않나요? 실제로 인터넷 주소창에 주소를 치는 행위는 해당 주소에 대해 GET 요청을 하는 것입니다. 크롬 주소창에 www.naver.com이라고 치면 GET www.naver.com HTTP/1.1 요청을 보내는 셈이죠.
이렇게 요청을 할 때 주소와 함께 HTTP 메서드를 같이 보낼 수 있습니다. 자주 쓰는 HTTP 메서드는 GET, POST, PUT, PATCH, DELETE 정도가 있습니다. (OPTIONS, HEAD, CONNECT, TRACE)도 있습니다.
GET, POST, PUT, PATCH, DELETE 단어의 뜻을 잘 생각해보세요. GET은 가져오다, POST는 게시하다, PUT은 집어넣다, PATCH는 고치다, DELETE는 지우다입니다. 따라서 해당 주소에 대한 어떤 동작을 하려고 할 때 알맞은 HTTP 메서드를 사용하면 되는 겁니다. DELETE zerocho.com하면 제 블로그를 지우는 요청인 것입니다(제 블로그를 지우지 말아주세요 ㅠㅠ). 실제로 요청만 보낸다고 이루어지는 것은 아니고요. 서버가 요청을 검증한 후, 유효하면 실행됩니다.
HTML을 배우신 분들은 이미 이러한 메서드들을 사용하고 계셨습니다. HTML 폼에서는 method 속성으로 GET과 POST를 사용할 수 있죠. action에는 주소가 들어가고요. 보통 새로운 글을 등록할 때 POST로 설정하고 폼을 사용하지 않으셨나요? 즉, 지금까지 POST action주소 HTTP/1.1로 요청을 보내온 것입니다(요청 메시지 시작줄). 인풋 태그 데이터들은 요청의 본문에 들어가고요.
HTML 폼을 쓰셨던 분들은 GET과 POST만 쓰셨겠지만, 실제로는 요청을 보낼 때 PUT, PATCH, DELETE 등 더 자세한 동작을 정의할 수 있습니다. 보통 PUT은 전체 수정(대체), PATCH는 부분 수정, DELETE는 제거 요청 시 사용합니다. 주소를 자원이라고 보고, 메서드를 동사라고 보는 개발 방식이 바로 REST 입니다.
예를 들어 GET /user라고 하면, 사용자들의 정보를 가져온다는 의미가 되고, DELETE /user/5 라고 요청을 보내면 아이디가 5인 사용자를 제거하라는 뜻이 되는 셈이죠.
GET과 DELETE을 제외한 POST, PUT, PATCH는 요청을 보낼 때 본문을 같이 보낼 수 있습니다. GET과 DELETE도 본문을 넣어 보내는 것이 가능은 하지만 GET과 DELETE의 본문은 어떻게 처리해야한다는 정의가 없기 때문에(서버가 본문을 무시하는 것이 권장됩니다), GET이나 DELETE 요청 시에는 본문을 같이 보내지 않습니다.
다음은 제 서비스인 MYFIT의 POST 요청입니다.
Request Payload 부분이 본문 부분입니다. 저건 크롬이 보기 좋게 표시한 것이고 실제로는 다음과 같이 요청이 전달될 것입니다.
POST myfit.xyz/male/upper HTTP/1.1
Accept-encoding: gzip
Accept-language: ko-KR
...
{data:{type: "UPPER_ANALYZE_REQUEST", brand: "MYFIT" ... }
이번 요청에는 헤더 다음에 본문이 들어가는 것이죠. 서버는 저 본문을 받아 파싱(해석)한 후 사용하게 됩니다.
만약 GET에 데이터를 담아 보내고 싶다면 어떻게 할까요? 위 이미지에서 Query String Parameters 보이시나요? 저 부분은 myfit.xyz/male/upper?test=false에서 ? 뒷 부분(test=false)입니다. 이렇게 주소 뒤에 ?를 붙인 후 키=값&키=값 식으로 데이터를 보냅니다. GET 요청은 본문 대신 주소에 쿼리스트링으로 데이터를 동봉하는 것입니다. 예를 들어 사용자를 이름순으로 가져오고 싶다면 GET /users?sort=name HTTP/1.1요청을 보내면 되겠죠? GET /users?sort=name&filter=developer&limit=100 HTTP/1.1처럼 쿼리스트링 간에 &로 구별도 가능합니다.
나머지 HEAD, OPTIONS, TRACE, CONNECT에 대해서도 알아보겠습니다. 쓰는 사람들 빼고는 자주 보기 힘든 메서드입니다.
HEAD는 요청에서 헤더만 가져올 때 사용합니다. 단, 헤더가 GET 요청의 헤더입니다. HEAD https://www.zerocho.com HTTP/1.1 요청을 보낸다면, GET https://www.zerocho.com HTTP/1.1 요청을 보내고 헤더만 가져오는 것과 동일합니다. 언제 사용해야할지는 잘 모르겠습니다.
OPTIONS 요청은 CORS 문제에서 많이 보셨을 것입니다. OPTIONS는 서버가 어떤 메서드를 지원하는지 알아볼 때 사용됩니다. OPTIONS https://myfit.xyz HTTP/1.1 요청을 보내면 GET과 HEAD만 오지만, OPTIONS https://myfit.xyz/modal/order HTTP/1.1 요청을 보내면 GET, HEAD, POST가 옵니다. /modal/order는 실제로 POST 요청도 지원합니다.
또한, CORS 상황에서는 다른 도메인 서버에 먼저 OPTIONS 요청을 날린 뒤, 그 서버가 요청을 허용하면 실제 요청(GET, POST 등)을 날립니다. OPTIONS 요청은 그냥 간단하게 서버에 실제 요청을 보내기 전에 서버를 테스트해보는 용도라고 보시면 됩니다.
TRACE랑 CONNECT는 진짜 쓰이는 곳에서만 쓰입니다. 저도 아직 한 번도 명시적으로 써본적이 없습니다. TRACE는 핑퐁 테스트같은 데 쓰이고, CONNECT는 양뱡향 통신을 할 때 쓰이는 모양입니다.
지금까지 HTTP 메서드들에 대해 알아봤습니다. GET, POST, PUT, PATCH, DELETE, OPTIONS 정도만 알아두시면 됩니다. 남은 요청/응답 메시지 시작줄의 구성 요소는 버전과 HTTP 상태 코드입니다. 버전은 나중에 1.1 버전과 2 버전을 비교하겠습니다. HTTP 상태 코드는 이 강좌 에서 했으므로 넘어갑니다. 시작줄을 다 다뤘으니, 이제 헤더 차례입니다. 다음 시간에는 요청의 유명한 헤더들에 대해 알아보겠습니다!