요청과 응답의 약속, HTTP

디우·2022년 6월 22일
0

4월 29일을 마지막으로 블로그 글 포스팅이 약 2달간 멈추었다.
여러가지 상황들이 있었다. 우테코 레벨2가 생각보다 레벨1에 비해서 많이 힘들었다는 점과 함께 현재 본인의 경우 우테코와 함께 학교를 병행하고 있어 생각보다 나만의 시간이 많이 생기지 않았다.
짧은 우테코 방학 2주간의 시간을 활용하여 공부한 내용을 정리하려고 했지만, 쌓여있던 피로감이나 무력감으로 방학 시작과 동시에 무엇을 하기가 쉽지 않았다.
앞으로 며칠 동안은 레벨2동안 학습한 내용에 대해서 정리하면서 레벨2 인터뷰를 준비하는 블로그 글을 포스팅하며 배운 것들을 정리하고 기록해보려고 한다.


클라이언트와 서버

우리가 다음과 같이 브라우저를 통해서 '우아한형제들' 홈페이지에 접속한다.

즉 우리는 브라우저를 통해서 우아한형제들 서버에 접속을 요청하고, 응답으로써 위와 같은 페이지를 받게 되는 것이다.
이를 터미널을 통해서 서버로 요청을 보내면 다음과 같은 문자열들, 즉 HTML 코드를 받게 되는게 이를 이쁘게 렌더링 해주는 역할은 웹 브라우저가 수행하여 앞서와 같이 이쁜 페이지를 볼 수 있는 것이다.

정리하면 서버-클라이언트 구조란 데이터를 저장하고 관리하는 서버부분과 해당 서버에 접속하여 데이터를 열람하는 클라이언트 부분으로 구성된 네트워크 구조 를 말한다.
이 때, 서버와 클라이언트는 1:N (일대다) 구조로 연결된다. 다시 말해 한 대의 서버에 다수의 클라이언트가 달라붙어서 서비스를 이용하는 것이다.
그리고 이러한 서버-클라이언트 구조 에서 앞서 보인 것과 같이 브라우저를 통해서 서버로 요청을 보내고 응답으로 웹 페이지를 받는 통신은 HTTP(HyperText Transfer Protocol)이라는 프로토콜을 통해서 웹(Web, www) 상에서 정보를 주고 받을 수 있게 해준다.


HTTP?

HTTP란 HyperText Transfer Protocol의 약자로 이름 그대로 HyperText 즉 HTML로 만들어진 문서인 웹문서를 서버에서 클라이언트로 전송하는 프로토콜이라는 뜻이다.
이런 HTTP는 TCP/IP 4계층에서 애플리케이션 계층에 속하며 해당 계층에 속하는 다른 프로토콜로는 FTP, SMTP, DNS 등이 존재한다. 그 중에서도 HTTP가 이렇게 인기가 많고 대중화가 될 수 있었던 이유는 웹이 온-디멘드(on-demand) 방식으로 동작한다는 점이다. 즉, 사용자가 원할 때 원하는 것을 수신받을 수 있었기 때문이며 HTTP의 특징이라고 볼 수 있다.

이러한 HTTP에 대해서 잠깐 정리를 해보자.
(더 자세한 내용은 본인이 정리한 노션 페이지를 통해서 참고해 볼 수 있다.)

  • HTTP는 메시지의 구조 및 client와 server가 메시지를 어떻게 교환하는지를 정의하고 있다.
  • 웹 페이지(web page)는 객체들로 구성되어있는데, 각 객체(object)는 단순히 단일 URL로 지정할 수 있는 하나의 파일(HTML파일, 이미지, 오디오 클립 등)이다. 대부분의 웹 페이지는 기본 HTML파일과 여러 참조 객체들로 구성된다.
  • 웹 브라우저는 HTTP의 클라이언트 측을 구현, HTTP의 서버 측을 구현하는 웹 서버는 URL로 각각을 지정할 수 있는 웹 객체를 가지고 있다.
  • HTTP는 웹 클라이언트가 웹 서버에게 웹 페이지를 어떻게 요청하는지와 서버가 클라이언트로 어떻게 웹 페이지를 전송하는지를 정의한다.
  • HTTP는 TCP를 전송 프로토콜(전송계층 프로토콜)로 사용한다.
  • 클라이언트는 HTTP 요청 메시지를 소켓 인터페이스로 보내고 소켓 인터페이스로 부터 HTTP응답 메시지를 받는다. 마찬가지로 HTTP 서버는 소켓 인터페이스로부터 요청 메시지를 받고 응답 메시지를 소켓 인터페이스로 보낸다.
  • HTTP는 데이터의 손실 또는 TCP가 어떻게 손실 데이터를 복구하고 네트워크 내부에서 데이터를 올바른 순서로 배열하는지 고려하지 않는다.
  • 서버가 클라이언트에게 요청 파일을 보낼 때, 서버는 클라이언트에 관한 어떠한 상태정보도 저장하지 않는다.(stateless)
    → HTTP 서버는 클라이언트에 대한 정보를 유지하지 않으므로 HTTP를 비상태 프로토콜(stateless protocol)이라고 한다. (상태를 기억하겠다하면 프로토콜이 복잡해진다. 필요시 '쿠키'를 이용)

HTTP와 관련하여 알아야 할 것

HTTP와 관련하여 알아야 할 것에는 위에서 잠깐 정리한 개념들 이외에도 굉장히 다양하지만, 우선 4가지 키워드에 대해서 정리하려고 한다.
이 4가지 키워드는 URL(URI)HTTP method, header, status code 이며 해당 키워드에 대해서 그림으로 배우는 HTTP & Network basic (우에노 센) 라는 책을 참고하였다.

URL(URI)

우리는 앞서 웹 브라우저에서 주소창에 https://www.woowahan.com/을 입력하여 "우아한형제들" 홈페이지에 접속하였었다. 이 때 웹 페이지를 표시하기 위해 입력한 위의 주소가 바로 URL 이다.
즉, URL(Uniform Resource Locator)은 네트워크 상에서 자원이 어디 있는지를 알려주기 위한 공통된 규약으로, 웹 리소스에 대한 참조이다. 즉, 웹 페이지를 찾기 위한 주소를 말한다. 우리는 보통 웹 사이트 주소를 위해서 URL을 사용하지만 이 뿐만 아니라 컴퓨터 네트워크상의 자원을 모두 나타낼 수 있다.

그렇다면 URI(Uniform Resource Identifier)는 무엇일까?

  • Uniform : 통일된 서식을 결정하는 것으로, 여러 가지 종류의 리소스 지정 방법을 같은 맥락에서 구별없이 취급할 수 있게 한다.
  • Resource : 말 그대로 자원을 일컫으며, 식별 가능한 모든 것이라고 볼 수 있다. 즉, 웹 페이지 문서 뿐 아니라 이미지 등도 다른 것과 구별 가능하다면 모두 리소스로 볼 수 있는 것이다.
  • Identifier : 식별 가능한 것을 참조하는 오브젝트이며 식별자이다.
    즉, URI란 스키마를 나타내는 리소스를 식별하기 위한 식별자 라고 이야기할 수 있다. 쉽게 말하면 인터넷에 있는 자원을 나타내기 위한 유일한 주소(식별자)를 말한다.

URI와 URL의 설명에서 알 수 있겠지만, URL은 URI에 포함되는 개념이다.
예시를 보면 https://example/user/dwoo 의 경우 URL은 https://example/user까지고 원하는 정보에 도달하기 위한 식별자 dwoo를 포함하면 URI이다. 즉, https://example/user/dwoo는 URI이지만 URL은 아니다. URL은 자원의 위치를 나타내 주는 것이고, URI는 자원의 식별자이기 때문이다.

이러한 URI는 프로토콜(protocol), 호스트(host), 포트번호(port), 경로(path), 쿼리스트링(query string)으로 구성된다.

"http://example:8080/user?name=dwoo" 와 같은 URI가 있다고 할 때 이를 구분해보면 다음과 같다.

  • http : 프로토콜(protocol)
  • example : 호스트(host, domain)
  • 8080 : 포트번호(port)
  • user : 경로(path)
  • name=dwoo : 쿼리스트링(query string)

HTTP method

HTTP는 HTTP 메소드라는 것이 존재한다. 이는 클라이언트가 웹 서버에게 사용자 요청의 목적이나 종류를 알리는 수단으로 최초에는 GET 메소드만 존재하였었지만, 형재는 다양하게 존재한다.
즉, HTTP method는 HTTP 통신에서 클라이언트가 서버에 요구하는 요청의 종류를 나타내고 있다고 이해할 수 있다.

HTTP method는 총 9가지 종류가 있으며 이 중에서 자주 쓰이는 메소드는 GET, POST, PUT, PATCH, DELETE 5가지가 존재하며 이 외에도 HEAD, OPTIONS, CONNECT, TRACE가 존재한다.

  • GET(리소스 조회) : GET 메소드는 요청 URI로 식별되는 리소스를 가져오도록 요청한다. 이 때 서버로 데이터를 전송하고 싶으면 query string을 통해서 전달한다.

  • POST(데이터 전송) : 주로 서버로 데이터를 전송하기 위해서 사용한다. GET과는 달리 메시지 바디를 통해서 서버로 데이터를 전달한다. 주로 신규 리소스를 등록할 때 사용한다.

  • PUT(리소스 대체) : POST와 유사한 전송 구조를 가지기 때문에 헤더 이외에 메시지(데이터)가 함께 전송된다. 이 때 리소스가 존재하면 대체하고 리소스가 없으면 생성한다. 즉 쉽게 말해 데이터를 덮어쓴다.

  • PATCH(리소스 일부 수정) : PATCH는 PUT과 마찬가지로 리소스를 수정할 때 사용하지만, 다른 점은 덮어쓰기 보다는 리소스의 일부만을 변경한다는 것이다. 즉, PATCH는 리소스를 일부분만 변경할 수 있다.

  • DELETE(리소스 삭제) : 리소스를 제거할 때 사용할 때 사용한다. 보통 응답으로 204(No Content) 상태코드를 돌려받는다.

  • HEAD : GET과 동일하지만, 메시지 부분을 제외하고 헤더만 조회해온다. HEAD는 보통 URI 유효성과 리소스 갱신 시간을 확인하는 목적등으로 사용된다.

  • OPTIONS : 대상 리소스에 대한 통신 가능 옵션을 확인하기 위해 사용한다. 즉, 요청 URI로 지정한 리소스가 제공하고 있는 메소드를 조회하기 위해 사용한다.

  • CONNECT : 대상 자원으로 식별되는 서버에 대한 터널을 설정한다. CONNECT 메소드는 프록시에 터널 접속 확립을 요구함으로써, TCP 통신을 터널링 시키기 위해서 사용한다. 주로 SSL, TLS 등의 프로토콜로 암호화 되어 있는 것을 터널링 시키기 위해서 사용한다.

  • TRACE : 경로를 조사한다. TRACE 메소드는 웹 서버에 접속해서 자신에게 통신을 되돌려 받는 루프백(loop-back)을 발생시킨다. 즉 클라이언트는 TRACE 메소드를 사용함으로써, 요청을 보낸 곳에 어떤 요청이 가공되어 있는지 등을 조사할 수 있다. 하지만 XST(크로스 사이트 트레이싱)과 같은 보안상의 문제가 있어 보통 사용되지 않는다.

이러한 HTTP 메소드에는 속성이라는 특징이 있으며, 안전(Safe Mehtods), 멱등(Idempotent Methods), 캐시가능(Cacheable Methods)가 있다.

  • 안전(Safe) : 계속해서 메소드를 호출해도 리소스를 변경하지 않는다는 의미이다. 주요 메소드 중에는 GET메소드가 안전하다고 볼 수 있다.

  • 멱등(Idempotent) : 100번을 호출해도 10,000번을 호출해도 동일한 결과를 얻는다는 것을 의미한다. GET, PUT, DELETE는 멱등하다고 볼 수 있지만, POST나 PATCH는 멱등하지 않다.

  • 캐시가능(Cacheable) : 캐시가능하다는 말은 말 그대로 캐싱을 해서 성능을 올릴 수 있다는 의미이다. GET, HEAD, POST, PATCH가 캐시가능하지만 실제로는 GET과 HEAD만 주로 캐싱이 사용된다고 한다.

HTTP 요청과 응답에는 반드시 메시지 헤더가 포함되어 있는데, 메시지 헤더에는 클라이언트나 서버가 요청과 응답을 처리하기 위한 정보들이 포함되어 있다.

HTTP 요청과 응답 메시지의 구조는 동일하다.

HTTP 요청 메시지의 포맷은 요청 라인과 헤더라인 그리고 공백라인 이후에 개체 몸체가 온다. (GET 방식에서는 비어있고, POST방식에서만 사용된다.)

이 때 첫 라인에 해당하는 요청 라인은 3가지 필드를 가지며, method 필드, URL 필드, 그리고 HTTP 버전 필드를 가지며 예시는 다음과 같다. GET /somedir/page.html HTTP/1.1

헤더 라인에는 Host 즉 호스트를 명시하며 웹 프록시 캐시에서 필요한 정보를 포함할 수 있고, User-agent, Accept-language가 포함될 수 있다. User-agent는 브라우저 타입을 명시하며, Accept-language는 어떤 언어를 요구하는지를 나타낸다.

Content-Type이라는 헤더 필드 명은 메시지 바디의 오브젝트 타입을 가리키며 text/html, application/json 등의 값이 올 수 있다.

Accept 어떤 데이터 타입을 허용할지를 나타내는 것이다. 즉, 브라우저가 요청 메시지의 Accept 헤더 값을 application/json이라고 설정했다면 클라이언트는 웹서버에게 json 데이터만 처리할 수 있으니 해당 형식으로 응답을 돌려달라고 요청하는 것과 같다.

Server 헤더는 메시지가 어떤 웹 서버에 의해 만들어졌음을 이야기하며, Content-Length는 엔티티 바디의 사이즈(단위: 바이트)를 나타낸다.

Cookie 헤더 필드는 클라이언트가 HTTP의 상태 관리 지원을 원할 때 서버로부터 수신한 쿠키를 이후의 리퀘스트에 포함해서 전달하는 용도로 사용한다.

마지막으로 Location은 클라이언트를 지정한 URI에 리다이렉트 하겠다는 의미로 사용되며 3xx(리다이렉션) 또는 201 상태 응답과 함께 제공될 때만 의미를 제공한다.

이외에도 굉장히 많은 HTTP Header가 존재하지만, 모두 다루기는 어려우므로 사용할 때마다 찾아보는 것이 좋겠다는 생각을 한다.

Status Code

클라이언트가 서버를 향해 요청을 보낸 후, 서버에서 그 요청에 대한 결과를 돌려줄 때 결과가 어떻게 되었는지를 알려주기 위해 상태코드(status code)를 사용한다.

상태코드는 3자리 숫자를 사용하며 숫자의 맨 첫번째 수로 상태코드를 클래스로 구분하여 관리하며 다음과 같다.

  • 1xx(Informational) : 요청을 받아들여 처리중
  • 2xx(Success) : 요청을 정상저긍로 처리하였음
  • 3xx(Redirection) : 요청을 완료하기 위해서 추가 동작이 필요함
  • 4xx(Client Error) : 서버는 요청에 대해서 이해 불가능
  • 5xx(Server Error) : 서버가 요청을 처리하는데 실패

HTTP 상태 코드는 RFC2616에 실려있는 것만 해도 40종류가 있고 확장을 포함하면 60종류 이상이 되기도 하지만 실제 자주 사용하는 것에는 14종류 정도가 존재하며 이를 정리하면 다음과 같다.

2xx 성공(Success)

200번대는 성공을 의미한다.

  • 200 OK : 클라이언트가 보낸 요청을 서버가 정상 처리하였음을 나타낸다.
    이 때, 상태 코드와 함께 돌아오는 정보는 메소드에 따라 다르며, GET의 경우에는 요청한 리소스에 대응하는 엔티티가 응답으로 오게 된다.
  • 201 Created : 요청이 성공해서 새로운 리소스가 생성되었음을 의미한다.
  • 202 Accepted : 요청이 정상적으로 접수되었으나 처리가 완료되지 않았음을 의미한다.
  • 204 No Content : 이 응답은 서버가 요청에 대해서 처리하는데에는 성공했지만, 조회되는 데이터가 없음을 나타낸다. 응답 엔티티 바디를 포함하지 않는다.
    해당 응답코드는 클라이언트에서 서버에 정보를 보내는 것으로 족하고, 클라이언트에 대해서 새로운 정보를 보낼 필요가 없는 경우에 사용한다.
  • 206 Partial Content : 이 응답은 Range에 의해서 범위가 지정된 요청에 대해 서버가 부분적 GET 요청을 받았음을 나타낸다. 응답에는 Content-Range로 지정된 범위의 엔티티가 포함되게 된다.

3xx 리다이렉트(Redirection)

300번대는 리다이렉션으로 location 헤더가 있으면 location 위치로 자동 이동하는 것을 말한다.

  • 301 Moved Permanently : 요청된 리소스에 새로운 URI가 부여되어, 이후로 해당 리소스를 참조하는 URI를 사용해야 한다는 것을 의미한다.
  • 302 Found : 요청된 리소스에는 새로운 URI가 할당되어 있기 때문에, 그 URI를 참조해주길 바란다는 의미를 나타내고 있다. 301과 비슷하지만 302의 경우에는 영구적인 이동이 아닌 일시적인 것을 의미한다.
  • 303 See Other : 요청에 대한 리소스가 다른 URI에 있기 때문에 GET메소드를 통해서 얻어야한다는 것을 나타낸다. GET 메소드로 얻어야 한다고 명확하게 되어 있는 점이 302와는 다르다.
    예를 들어, POST 메소드로 액세스한 처리 결과를 별도의 URI에 GET 메소드로 리다이렉트 시키고 싶은 경우에 GET 메소드를 명확히 하기 위해 303이 사용된다.
  • 304 Not Modified : 조건부 리퀘스트를 했을 때 리소스에 대해서 서버는 요청 데이터가 변경되지 않았을 경우에 대해서 304를 반환한다.
  • 307 Temporary Redirect : 리다이렉트시 요청 메소드와 본문을 유지한다. (요청 메소드를 변경하면 안된다.)

4xx 클라이언트 에러(Client Error)

400번대는 클라이언트의 잘못으로 에러가 발생햇음을 나타낸다.

  • 400 Bad Request : 클라이언트의 요청이 잘못되어 서버가 해당 요청을 처리할 수 없음을 나타낸다.
  • 401 Unauthorized : 해당 요청에는 인증이 필요하다는 것을 나타낸다.
  • 403 Forbidden : 요청된 리소스의 액세스가 거부되었음을 나타낸다. 서버 측은 거부에 대한 이유를 분명히 할 필요가 잇는데, 이유를 명확하게 하는 경우에는 엔티티 바디에 기재해서 유저 측에 표시한다.
  • 404 Not Found : 요청된 리소스가 서버에 없다는 것을 나타낼 때 사용한다.
    그 외에도 서버 측에서 해당 요청에 대해 거부하고 싶지만 그 이유를 분명히 하고 싶지 않은 경우에도 사용한다.

5xx 서버 에러(Server Error)

500번대는 서버의 원인으로 요청을 처리할 수 없음을 나타낸다.

  • 500 Internal Server Error : 서버가 요청을 처리하는 도중에 에러가 발생하였음을 나타낸다.
  • 503 Service Unavaliable : 일시적으로 서버가 과부하 상태가 되거나 점검등의 이유로 요청을 처리할 수 없음을 나타낸다. (서비스 이용 불가)

이러한 상태 코드는 꼭 현재 상황과 일치하지 않을 수 있으며, 웹 애플리케이션에서 애플리케이션 에러가 발생한 경우에도 상태 코드로는 200 OK 가 응답과 함께 되돌아올 수 있다.


이로써 레벨2에는 Spring 에 대해서 학습하는 기간이었다. 그 중 클라이언트와 웹서버의 통신의 기본이 되는 HTTP를 가장 먼저 정리하였다. 아직도 HTTP에 대해서 깊이 있게 그리고 모든 내용을 알고 있지는 않다. 하지만 기본이 되는 내용은 다시 한 번 정리하면서 상기시키는 과정을 통해서 완전히 내 것으로 만드는 과정이 필요하다고 생각되어 이렇게 정리하게 되었다.

profile
꾸준함에서 의미를 찾자!

0개의 댓글