요청 메소드
이 문서에서는 전통적인 요청 방식인 GET, POST에 대한 이해와 활용법에 대해서 살펴본다.
Last updated
이 문서에서는 전통적인 요청 방식인 GET, POST에 대한 이해와 활용법에 대해서 살펴본다.
Last updated
요청 메소드(Request method)
란 클라이언트가 웹 서버에게 요청의 목적과 종류를 알리는 수단이다. 요청 메소드는 GET, POST뿐 아니라 HEAD, PUT, DELETE, OPTIONS, TRACE, CONNECT등 다양하지만 대부분의 웹서버는 보안상의 이유로 GET, POST (혹은 OPTIONS) 만을 허용하므로 전통적인 웹은 GET, POST를 기반으로 구성된다.
OPTIONS는 GET, POST, HEAD 요청이 아닌 다른 요청들을 보낼 경우 해당 요청이 전송 가능한지 확인하기 위하여 사전에 검사하는 요청 방식이다.
HTTP 요청은 편지에 비교할 수 있다. 편지는 크게 편지봉투와 편지지로 나눌 수 있으며, 각각 작성하는 내용이 다르다. 편지봉투는 편지의 올바른 전송을 위한 정보(ex - 수신,발신인 정보)를 작성하며 편지지는 실제로 전달하고 싶은 내용을 작성한다. 이를 HTTP 요청에 비교하면 다음과 같이 표현할 수 있다.
편지봉투 - Message Header
편지지 - Message Body
실제 메세지의 형태는 다음처럼 하나로 이루어져 있으며, Header와 Body 사이에는 빈 줄이 하나 포함되도록 설계되어 있다.
구체적인 방식에 따라 Body가 존재하거나 존재하지 않을 수 있다.
GET 요청은 서버의 자원을 가져오기 위한 방식이다. 서버에서 특정 페이지를 불러오기 위한 대부분의 요청이 GET 요청 형태이다. 다음 내용은 H'academy 메인페이지에 대한 요청 메세지이다.
GET 요청은 Message body를 가질 수 없다. 위 메세지에서 첫 줄을 제외한 나머지 부분은 모두 요청 헤더(Request Header)이며, name : value
형식으로 작성되어 있다. 페이지를 불러오면서 전달해야할 내용이 있다면 주소를 이용하여 요청 파라미터(Request Parameter) 혹은 경로변수(Path Variable) 형태로 서버에 전달해야 한다.
Spring Controller에서는 GET 요청을 다음 Annotation으로 처리한다.
@RequestMapping(value="주소", method=RequestMethod.GET)
@GetMapping("주소")
2번의 경우 Spring 5 이상의 환경이 필요하다.
또한 요청 파라미터와 경로 변수를 각각 다음 Annotation으로 처리한다.
요청 파라미터 - @RequestParam
, @ModelAttribute
경로 변수 - @PathVariable
, @ModelAttribute
캐싱 기능 설정
GET 요청은 캐싱 기능을 설정하여 응답 속도를 향상시킬 수 있다. 캐싱 기능을 사용하면 한 번 접속한 페이지의 내용을 브라우저에 캐시하여 재 요청 시 차이점을 비교하여 추가 요청 전송 여부를 판단한다.
POST 요청은 서버에 데이터를 전송하기 위한 방식이다. 따라서 Message Body를 가질 수 있다. Message Body에 작성될 내용의 형태는 Content-Type
헤더로 표시하며, 내용의 크기는 Content-Length
헤더로 작성한다.
Spring Controller에서 POST 요청 데이터를 처리하기 위해 다음 Annotation을 제공한다.
@RequestMapping(value="주소", method=RequestMethod.POST)
@PostMapping("주소")
또한 전송되는 데이터를 다음 Annotation으로 처리할 수 있다.
@RequestParam
, @ModelAttribute
POST 요청의 경우 전송되는 Message Body가 Percent encoding 처리되기 때문에 웹서버에서 별도의 Encoding 처리 코드를 작성하거나 도구를 설정해야 한다.
Spring은 CharacterEncodingFilter를 통해 원하는 형태로의 인코딩이 가능하도록 지원한다.
Content-Type
헤더에는 Message Body의 형태를 기입한다. 다음 종류가 있다.
application/x-www-form-urlencoded
multipart/form-data
text/plain
요청 파라미터와 같은 형의 데이터, 알파벳이 아닌 값은 Percent encoding 처리된다. <form>
태그에서 post 전송 시 기본값이다. key=value
가 세트로 전송되어 하나의 key
에 하나의 value
가 매핑된다.
파일과 같이 보낼 정보가 많아서 application/x-www-form-urlencoded로 전송이 불가능한 경우 사용하는 방식이다. boundary
헤더에 설정된 값을 경계선으로 하여 내부에 데이터를 담도록 구성되어 있다. Spring에서는 MultipartResolver
에 의해 처리된 결과물을 MultipartRequest
또는 MultipartFile
형태로 받을 수 있다.
일반 텍스트를 전송할 때 사용한다.
앞서 살펴본 GET과 POST 요청은 각자의 특징이 존재한다. 이것을 웹에서 어떻게 조화롭게 사용할 것인가를 고민하기 위해 홈페이지의 기능을 다음과 같이 크게 구분해본다.
데이터를 입력해서 등록한다.
등록된 데이터를 조회한다
등록된 데이터를 수정한다
등록된 데이터를 삭제한다
1번은 Create, 2번은 Read, 3번은 Update, 4번은 Delete에 해당하는 작업이다. 첫 글자를 합쳐서 CRUD라고 한다. 레거시 웹은 이 네 가지를 이용하여 대부분의 기능을 구현한다.
Create - 회원 가입, 게시글 작성, 상품 등록 등
Read - 회원 정보, 회원 목록, 게시글 목록, 게시글 검색, 게시글 상세, 상품 목록, 상품 상세정보 등
Update - 회원정보 수정, 비밀번호 변경, 게시글 수정, 상품정보 변경
Delete - 회원 탈퇴, 게시글 삭제, 상품정보 삭제
등록과 수정의 경우 정보를 입력해야 하기 때문에 두 개의 페이지가 필요하다. 조회/검색의 경우 한 개의 페이지가 필요하고, 삭제의 경우도 부가 기능을 구현하지 않는다면 정보 입력이 필요하지 않아 한 개의 페이지로 처리 가능하다.
최근들어 한 페이지에서 모든 작업을 구현하는 SPA 방식이 유행하면서 하나의 페이지에서 무수히 많은 기능들을 구현하려 하는 경향이 있다. 이는 웹의 응용 방식이며 GET, POST 외에도 PUT, DELETE 등 다양한 방식을 사용하여 처리한다. 지금 다룰 내용이 아니므로 생략한다.
하나의 페이지만 필요한 경우에는 GET/POST를 원하는 대로 사용하면 되며 다음 특징을 주의하면 된다.
GET 방식은 <a>
, <script>
, <form>
등 다양한 방식으로 요청 생성이 가능하다.
GET 방식은 주소와 요청 파라미터를 포함하여 256 byte까지 작성이 가능하다.
POST 방식은 데이터 전송에 대한 크기 제약이 없다.
POST 방식은 새로고침을 누를 경우 데이터가 재전송 되며 브라우저에 확인창이 출력된다.
등록이나 수정처럼 입력 페이지를 포함하여 두 개의 페이지가 필요한 경우는 다음과 같은 주소 설계가 가능하다.
입력 페이지와 처리 페이지의 주소를 다르게 하여 GET, POST 요청을 자유롭게 사용
입력 페이지와 처리 페이지의 주소를 맞추고 GET, POST 요청을 구분하여 사용
레거시 웹의 주소 설계 방식은 SOA(Service Oriented Architecture)
를 따른다. 주소를 봤을 때 어떤 기능인지 떠올라야 한다. 다음 예시를 통해 비교할 수 있다. 예시에서는 회원 가입을 각각의 방식에 맞게 설계하였을 때 주소의 형태를 살펴볼 수 있다.
1번 방식
입력 페이지 - /member/join_input
처리 페이지 - /member/join_process
2번 방식
입력 페이지 - /member/join[GET]
처리 페이지 - /member/join[POST]
일반적으로 1번보다 2번 방식을 더 선호하는 이유는 다음과 같다.
주소를 동일하게 하여 기능의 통일성을 강조할 수 있다.
보안에 가장 취약한 GET 요청이 Database와 연결된 요청이 되지 않도록 한다.
따라서 GET → 입력페이지 → POST → 등록/수정
형태의 처리 방식으로 처리하고, 모든 작업을 마치면 현재 페이지에 머무는 것이 아닌 다른 페이지로 Redirect 처리하는 형태로 페이지를 설계한다.
Redirect에 대한 자세한 내용은 다음 문서를 참고한다.