HTTP ?
HTTP : HyperText Transfer Protocol
-> HTML 파일을 전송하는 프로토콜이라는 의미를 갖습니다.
기본적으로 HTTP 통신은 클라이언트 측에서 필요한 데이터가 있다면 서버에게 요청하고,
서버는 그 데이터에 응답한 뒤 바로 연결이 종료되는 방식입니다.
최근에는 Keep Alive 옵션을 사용하여 일정 기간 동안 연결을 유지하는 방식으로도 통신이 가능해졌다고 합니다
Socket 통신과 달리 HTTP 통신은 단방향 통신이기 때문에
클라이언트만 서버에게 요청할 수 있습니다! (서버는 클라이언트에게 요청 불가 ㅠㅠ)
바로 연결이 종료된다는 특징을 보면 서버의 부하를 줄여준다는 것을 알 수 있습니다
왜냐! Socket 처럼 계속 연결을 유지하는 것이 아니고
원하는 요청에 대해서만 응답한 뒤 연결이 끊기기 때문입니다.
그러므로 서버가 다른 요청에 대해서도 원활하게 처리할 수 있는 겁니다!
HTTP 메시지
클라이언트가 서버에 요청을 할 때에는 일정한 형식에 맞춰서 요청해야 합니다.
또한 텍스트 기반의 메시지로 변환해야 하죠.
이 메시지 형식을 HTTP 메시지라고 합니다!
PC에서 도메인을 입력하거나 특정 링크를 클릭하여 원하는 페이지로 이동하는 순간을 생각해 봅시다!
이 때 우리가 보낸 요청은 일정한 형식을 갖춘 텍스트 기반 메시지로 변환되어 웹 서버에 전달됩니다.
이 메시지 형식을 HTTP 메시지라고 부르는 겁니다!
HTTP 메시지는 크게 요청 메시지와 응답 메시지로 분류됩니다.
두 메시지는 다시 라인 / 헤더 / 바디로 구성되어 있습니다.
요청 메시지 : 라인 (요청 라인) / 헤더 (요청 헤더) / 공백 라인 / 바디 (본문 - 요청 메시지)
응답 메시지 : 라인 (상태 라인) / 헤더 (응답 헤더) / 공백 라인 / 바디 (본문 - 응답 메시지)
라인
메시지의 가장 기본적인 내용 (응답 / 요청 여부, 메시지 전송 방식, 상태) 등이 작성 됨
메시지의 첫 줄은 무조건 라인 영역!
반드시 한 줄로 작성(정형화)되어야 함
형식 : (전송 메소드) (경로) HTTP/(버전)
POST /user/join HTTP/1.1
헤더
메시지 본문에 대한 메타 정보가 들어가는 부분
필요에 맞게 여러 줄로 작성됩니다.
라인과 달리 길이가 유동적이기 때문에 바디와 구분을 짓기 위한 공백 라인이 들어가게 됩니다.
HTTP 메시지의 첫 번째 한 줄 공백이 바로 헤더와 바디를 구분하는 경계선!
여기서 Host와 Content-Type이라는 Key 값을 채워야 합니다.
Host : 도메인 및 포트번호 - 두 개 이상의 도메인에 연결되어 있는 서버일 경우, 어느 도메인으로 요청이 들어왔는지 구분하기 위함
Content-Type : 메시지 바디 타입
- POST 방식일 경우 application/x-www-form-urlencoded
// 로컬 호스트, POST 사용 예시
Host: localhost
Content-Type: Content-Type: application/x-www-form-urlencoded
바디
실제로 보내는 메시지 본문 내용으로, 역시 길이가 유동적
이 때, 바디에 들어가는 메시지 형식은 헤더의 Content-Type에서 설정한 타입과 일치해야 합니다!
그리고 데이터들을 &를 사용하여 연결한 뒤 본문에 넣습니다.
account=swift@swift.com&password=1234&grant_type=password
application/x-www-form-urlencoded 타입일 경우 특수문자 처리를 해주어야 합니다!
특수문자의 경우에는 URLEncoding 형식으로 변환해야 합니다.
그렇다면 사용하는 이유는??
song=soundOfSilence
singer=simon&garfunkel
이런 데이터를 HTTP 메시지의 본문에 넣는다고 생각해 봅시다.
&로 데이터를 연결하기 때문에 아래와 같은 형식으로 서버에 전송하게 됩니다.
song=soundOfSilence&singer=simon&garfunkel
이 값을 받은 서버는 &를 기준으로 분리하겠죠?? 그렇게 되면...
song=soundOfSilence
singer=simon
garfunkel
요청에서 의도한 것과 다른 결과가 나와버렸습니다!!
요청에서는 simon&garfunkel가 하나의 값인데 garfunkel를 따로 분리해 버린 것이죠 ㅠㅠ
이러한 문제를 막기 위해서 simon&garfunkel 의 &는 변환을 해서 넘겨줘야 합니다.
실제 메시지 샘플(POST 방식)은 다음과 같습니다.
POST /userAccount/login HTTP/1.1
Host: swiftapi.rubypaper.co.kr:2029
Content-Type: application/x-www-form-urlencoded
account=swift%40swift.com&password=1234&grant_type=password
// @는 특수문자이기 때문에 %40으로 변경된 것!
이 샘플을 GET으로 바꾼다면??
GET /userAccount/login?account=swift@swift.com&password=1234&grant_type=password HTTP/1.1
Host: swiftapi.rubypaper.co.kr:2029
Cache-Control: no-cache
띠용?
메시지 본문이 사라지고, 거기에 있어야 할 값이 첫 번째 라인의 경로 뒤에 ? 문자열과 함께 연결되어 있습니다.
이처럼 GET 방식은 파라미터를 모두 URL 뒤에 연결하여 전달합니다!
또한 이렇게 연결된 파라미터를 쿼리 스트링이라고 합니다 :)
메시지 본문을 사용하지 않으므로 Content-Type 헤더가 사용되지 않아요
URL 뒤에 쿼리 스트링만 연결하면 되기 때문에 간결하게 정보를 전달할 수 있는 장점이 있습니다.
하지만 크기가 제한이 있기 때문에 주로 데이터를 요청할 경우 사용합니다.
또한 URL에 파라미터가 보이기 때문에 민감한 정보는 사용하지 않도록 주의해야 합니다!!
전송 방식
POST
주로 데이터 등록에 사용
메시지 바디를 통해 서버로 데이터 전달
특징 (GET은 모두 반대)
- 캐시되지 않음
- 브라우저 히스토리에 남지 않음
- 북마크 되지 않음
- 데이터 길이에 제한이 없음
GET
데이터 조회
서버에 전달하고 싶은 데이터는 query를 통해 전달
바디를 사용하여 데이터를 전달할 수는 있지만, 지원하는 곳이 별로 없어서 권장하지는 않는다고 함
query에 데이터를 넣기 uri에 데이터가 노출됨
따라서 파라미터에 민감한 정보를 다루면 안 됨 (보안)
* URI : 통합 자원 식별자(Uniform Resource Identifier)
- 인터넷에 있는 자원을 나타내는 유일한 주소
- 인터넷에서 요구되는 기본조건으로서 인터넷 프로토콜에 항상 붙어 다님
PUT
데이터가 있으면 대체하고 없다면 생성 -> 데이터 덮어쓰기
DELETE
데이터 삭제
PATCH
데이터의 일부만 변경
HTTP와 함께 Socket에 대한 이해도 있으면 좋을 것 같습니다!
Socket ?
Socket 통신은 한 번 연결에 성공한다면 그 연결에 계속 유지됩니다! (단, 네트워크가 끊기거나 임의로 끊지 않는다면)
실시간으로 데이터를 주고 받을 경우에는 연결(Connection)이 자주 끊어 지는 것보다는 계속해서 연결을 유지하는 것이 효율적입니다.
그러므로 채팅이나 실시간 스트리밍, RPG 게임등에 사용합니다.
또한 양방향 통신이기 때문에 클라이언트가 서버에게 요청하는 것은 물론,
서버가 클라이언트에게 요청을 할 수도 있습니다!
하지만 계속해서 연결을 유지하기 때문에 HTTP 통신에 비해 많은 리소스가 소모됩니다.
빈번하게 데이터를 주고 받는 환경이다 -> Socket 통신이 유리
그렇지 않은 경우다 -> HTTP 통신이 유리