김영한님의 모든개발자를 위한 HTTP 웹 기본 지식을 수강 후 해당 내용을 기반으로 작성한 글입니다.
클라이언트 <-> 서버 통신
데이터 전달 방식
1. 쿼리 파라미터를 통한 데이터 전송
- GET 메서드 사용
- 주로 검색어 정렬 필터
- 예시: 검색어, 게시판의 정렬 조건
2. 메시지 바디를 통한 데이터 전송
- POST, PUT, PATCH와 같은 HTTP 메서드의 바디를 사용
- 예시: 회원가입, 상품주문, 리소스 등록 & 변경
데이터 전송 방식
1. 정적 데이터 조회
- 쿼리 파라미터를 사용하지 않는다.
- 정적 데이터를 조회할 때는 추가적인 리소스가 필요하지 않아 URI로 단순하게 조회 가능
- 이미지, 정적 텍스트 문서와 같은 경우만 조회할 때.
- 조회에는 GET 메서드를 사용한다.
2. 동적 데이터 조회
- 쿼리파라미터를 사용하여 동적 데이터를 조회할 수 있다.
- 검색, 게시판 목록과 같은 곳에서 정렬이나 필터를 구현할 때
- GET 메서드로 쿼리 파라미터를 사용하여 데이터 전달
<form action="/save" method="post">
<input type="text" name="username" />
<input type="text" name="age" />
<button type="submit">전송</button>
</form>
웹 브라우저가 HTML form 태그를 읽고 요청 HTTP 메시지를 생성한다.
POST /save HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
username=kim&age=20
key-value 스타일로 바디에 데이터를 만들어서 전송
- 이 Content-Type은 폼 데이터를
key1=value1&key2=value2 형태로 URL 인코딩하여 HTTP 메시지의 바디에 담아 서버로 전송함을 의미
- 전송 데이터 url을 인코딩 처리
<form action="/members" method="get">
<input type="text" name="username" />
<input type="text" name="age" />
<button type="submit">전송</button>
</form>
요청 HTTP 메시지
GET /members?username=kim&age=20 HTTP/1.1
Host: localhost:8080
- multipart/form-data (파일 업로드)
<form action="/save" method="post" enctype="multipart/form-data">
<input type="text" name="username" />
<input type="text" name="age" />
<input type="file" name="file1" />
<button type="submit">전송</button>
</form>
요청 HTTP 메시지

- 바디가
-----XXX 으로 나누어져서 보내짐
- 파일 업로드 같은 바이너리 데이터 전송시 사용
- 다른 종류의 여러 파일과 폼의 내용을 함께 전송 가능하기 때문에 multipart
- HTML Form 전송은 GET, POST 메서드만 지원한다.
4. HTTP API
- 서버 to 서버 백엔드 시스템에서 통신하거나 웹, 앱 클라이언트 통신에도 사용된다.
- GET 메서드는 쿼리 파라미터로 데이터를 전달하고, POST, PUT, PATCH 메서드는 메시지 바디를 통해 데이터를 전송한다.
Context-Type: apllication/json 을 주로 사용하며 사실상 표준에 가까움
HTTP API 설계
컬렉션
- POST 메서드로 신규 자원 등록하는 경우, 자원의 저장소을 컬렉션이라고 한다.
- 클라이언트는 등록될 리소스의 URI를 몰라도 된다.
- 서버가 새로 등록될 리소스 URI를 생성하여 리소스 디렉토리를 관리
👉 RESTful API에서 컬렉션은 일반적으로 엔드포인트(예: /users, /products)에 여러 리소스를 포함하며, 서버가 새 리소스의 식별자를 생성하는 구조
스토어
- PUT 메서드로 자원을 등록하는 경우, 그 자원의 저장소을 스토어라고 한다.
- 클라이언트가 전송할 리소스의 URI을 알고 지정하여 전송해야 한다.
- 따라서 스토어는 클라이언트가 관리
- PUT은 멱등성(idempotency)을 가지므로, 동일한 요청을 여러 번 보내도 결과가 변하지 않는다.
실무에서는 POST 기반의 컬렉션을 사용하며 일부의 경우에 스토어를 사용한다.
-
GET, POST 메서드만 지원 (AJAX과 같은 기술을 사용한다면 해결이 가능)
-
예시: 회원
회원 목록: GET - /members
회원 등록 폼: GET - /members/new
회원 등록: POST - /members/new or /members
회원 등록 POST 메서드에서 리소스로 두 가지의 경우를 사용할 수가 있는데, 회원 등록 폼에 대한 리소스로 url을 맞추는 것이 실무에서 효율적일 때가 많다. (예를 들면, 회원 등록 폼에서 유효성 검증 과정에서 post의 결과를 get으로 다시 던져야 하는 경우)
컨트롤 URI
/members/new 에서 /new 에 해당하는 것이 컨트롤 URI
- RESTful 설계의 이상적인 패턴을 따르기 어렵거나, 애플리케이션 요구사항이 복잡할 때 실무적으로 자주 사용
- 최대한 RESTful API 설계를 하되, 필요한 경우에만 컨트롤 URI를 사용하자
- 컨트롤 URI는 동사로 표현
HTTP Status code
2xx
200 OK, 201 Created
- 신규 생성에 대한 요청 성공
- 생성된 리소스는 응답의 Location 헤더 필드로 식별
Location: /members/100
202 Accepted
- 클라이언트에서의 요청은 성공이지만 서버에서 처리가 완료되지 않은 경우
- 배치 처리 같은 곳에서 사용됨
예) 요청 접수 후 1시간 뒤에 배치 프로세스가 요청을 처리
204 No Content
- 서버가 요청을 성공적으로 수행했지만, 응답 페이로드 본문에 데이터가 없을 경우
예) 웹 문서 편집기의 save 버튼
save 버튼의 결과로 아무 내용이 없고, 같은 화면을 유지해야 한다.
결과 내용이 없어도 204 메시지로 성공을 인식할 수 있다.
3xx
301, 308
- 영구 리다이렉션을 하는 경우
- 리소스의 URI이 영구적으로 이동함을 의미하며 원래의 URL을 사용하지 않고 검색 엔진 등에서도 변경을 인지한다.
- 301 Moved Permanently: 리다이렉트시 요청 메서드가 GET으로 변할 수 있음(GET으로 변한다면 본문이 제거)
- 308 Prmanent Redirect: 301과 기능은 같으나 리다이렉트 요청시 요청 메서드(POST) 유지
302, 307, 303
- 일시적인 리다이렉션
- 리소스의 URI가 일시적으로 변경되는 것이기 때문에 검색 엔진 등에서 URL을 변경하면 안된다.
- 302 Found: 요청 메서드가 GET으로 변하고 본문이 제거될 수 있음 - 실무에서 기본 값으로 많이 사용
- 307 Temporary Redirect: 요청메서드(POST)와 본문이 변하지 않음
- 303 See Other : 요청 메서드가 GET으로 변경
PRG: Post/Redirect/Get
-
POST후 웹브라우저를 새로고침하는 경우, POST의 중복 요청이 발생할 수 있다!
-
이 때 중복 요청을 방지할 수 있는 것이 PRG
-
POST로 요청 후 결과 화면을 GET 메서드로 리다이렉트한다면 새로고침이 발생하더라도 결과 화면을 GET으로 조회하여 POST의 중복 요청을 방지할 수 있다.
-
중복 요청 방지뿐만 아니라, RESTful 설계에서 POST 요청을 데이터 생성/변경에만 사용하고, GET 요청을 데이터 조회에 사용하는 원칙을 따르게 한다.
👉 POST 요청 후 Redirect 하여 GET 메서드 호출
-
사용자 등록, 결제, 게시글 작성과 같은 상황에서 사용
👉 사용자가 게시글을 작성한 후 성공적으로 작성된 게시글의 상세 페이지로 리다이렉트하여 새로고침 시 중복 POST 요청방지
304 Not Modified
- 캐시를 목적으로 사용
- 클라이언트에게 리소스가 수정되지 않았음을 의미하는 코드
- 이 코드를 받게되면 클라이언트는 캐시를 재사용한다(캐시로 리다이렉트)
- 304 응답은 캐시를 재사용하는 의미이기 때문에 응답 메시지에 바디를 포함하지 않는다.
- 조건부 GET이나 HEAD 요청시 사용된다.
4xx
- 클라이언트의 요청에 잘못된 문법등과 같은 오류의 원인이 클라이언트에 존재할 때
- 재시도를 하더라도 이미 잘못된 요청으로 데이터를 보내고 있기 때문에 성공할 가능성이 없으나 5xx 오류에서의 재시도는 성공할 가능성이 있음.(원인이 서버에 있기 때문에)
400 Bad Request
- 요청 파라미터가 잘못되거나 자료형이 API 스펙이 맞지 않을 때
- 서버에서 철저하게 검증하고 구분하여 표현해야한다.
401 Unauthorized
- 인증이 되지 않은 경우
- 오류 발생 시 응답에 WWW-Authenticate 헤더와 함께 인증 방법을 설명해야 한다.
- 인증(Authentication): 로그인과 같이 본인이 누구인지 인증
- 인가(Authorization): 권한 부여(인증이 있어야 인가가 있음)
예: ADMIN
403 Forbidden
- 인증 자격은 있지만, 접근 권한이 불충분한 경우
예: 어드민등급이 아닌 사용자가 어드민 등급의 리소스에 접근하는 경우
404 Not Found
- 요청 리소스를 서버에서 찾을 수 없을 때(존재하지 않는 페이지)
- 클라이언트가 권한이 부족한 리소스에 접근할 때, 해당 리소스를 숨기고 싶을 때
5xx
- 서버 문제로 오류 발생
- 비즈니스 로직이 아닌 서버의 내부 로직에 문제가 터졌을 경우에만 해당 에러를 반환해야한다.
500 Internal Server Error
503 Service Unavailable
- 서비스 이용 불가
- 서버가 일시적으로 과부하가 되거나 예정된 작업으로 인해 잠시 요청을 처리할 수 없을 때
- Retry-After 헤더 필드로 얼마 뒤에 복구되는지 보낼 수 있다.