ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 기초 네트워크와 HTTP
    Network 2023. 3. 29. 01:03

    김영한님의 강의를 보며 중간중간 메모하며 정리했던 것들을 기록한 것입니다.

     

    #HTTP
    통신 규약인 프로토콜의 하나로서 현재는 모든 것이라고 해도 과언이 아닐 만큼 많은 곳에서 HTTP로 통신을 하고 있다.
    HTTP도 역시 TCP위에서 통신을 한다. 
    가장 많이 쓰이는 버전은 HTTP1.1버전이며 HTTP2,3은 성능 개선에 집중한 버전이기에 HTTP1.1을 잘 아는 게 중요하다.(HTTP3은 UDP기반이다.)
    HTTP의 기본은 클라이언트-서버 구조이다. 클라이언트는 복잡한 비즈니스 로직이나 DB에 관해선 몰라도 되며 UI, UX에만 집중을 하면 되고, 서버는 비즈니스 로직, 데이터 그리고 트래픽이 증가했을 때 어떻게 고도화 할 것인지 아키텍쳐등 다른 곳에 집중을 하면 되기에 클라이언트, 서버를 구분함으로써 각각 독립적으로 발전할 수 있다.

    ## 무상태 프로토콜
    Stateful, stateless 상태 유지와 무상태가 있다. 
    상태유지를 하여 클라이언트와 서버가 통신을 한다면 서버는 클라이언트의 상태를 유지하고 있어야하므로 갑작스럽게 장애가 일어나 서버가 중단되는 경우 유연한 대처가 불가능하다.
    무상태로 통신을 한다면 필요한 정보들은 클라이언트 쪽에서 쿠기나 세션을 이용해 저장하고 서버는 클라이언트의 상태를 따로 유지하지 않는다. 이렇게 될 경우 서버의 개수를 무한히 늘리는 게 가능하며 서버에 장애가 생겼을 경우 유연한 대처가 가능하다. 무상태를 유지하니 서버가 바뀌어도 문제가 없기 때문이다.

    ### 비연결성
    무상태로 통신을 하게 되면 html을 받을 때 TCP로 요청을 한 뒤 연결이 되면 html파일을 내려받고 받은 뒤엔 연결을 종료한다. 연결을 유지하고 있을 경우엔 서버자원을 효율적으로 사용하지 못하기 때문이다. 하지만 html을 받고 종료하고 css를 받고 종료하고 연결하고 종료하는 데에도 시간이 걸리기 때문에 HTTP에서는 persistent connections로 연결 상태를 지속함으로써 문제를 해결한다. 지속 시간은 내부적으로 설정할 수 있다. 서버 개발자들이 가장 어려워하는 업무는 같은 시간에 발생하는 이벤트이다. 6시에 이벤트가 있다고 가정해보자. 그럼 수만명의 사람들이 6시 00분 00초에 버튼을 누른다. 이 경우 stateful하게 서버를 구축했다면 큰 장애가  생긴다. 그래서 첫화면엔 무상태로 구현할 수 있는 로그인이 없는 페이지를 놔두고 다음 페이지를 클릭하게 만들게 설계를 한다. 그러면 서버를 증설하는것도 쉽다.


    #### HTTP API 설계
    리소스에 집중하자. 미네랄을 캐라. 미네랄에만 집중. 여기선 미네랄이 리소스. 캐라는 리소스가 아니다.
    리소스와 행위를 분리.
    URI는 리소스만 식별한다
    리소스 URI, 컨트롤 URI(동사사용가능)
    리소스 : 회원
    행위 : CRUD
    행위는 HTTP 메서드인 GET, POST로 구분한다.
    * GET : 리소스 조회, 서버에 전달하고 싶은 데이터는 query(쿼리 파라미터, 쿼리 스트링)를 통해서 전달
    * POST : 요청 데이터 처리, 주로 등록에 사용, 서버가 아직 식별하지 않은 새 리소스 생성, 다른메서드로 처리하기 애매한 경우에도 쓰임
    * PUT : 리소스를 대체, 해당 리소스가 없으면 생성. 덮어쓰기의 개념. 완전히 대체한다. 기존 리소스는 아예 없어진다.(기존 필드도 삭제됨)
    * PACTH : 리소스 부분 변경. 수정 개념
    * DELETE : 리소스 삭제
    * HEAD : GET과 동일하지만 메시지 부분을 제외하고, 상태 줄과 헤더만 반환
    * OPTIONS : 대상 리소스에 대한 통신 가능 옵션(메서드)를 설명(주로 CORS에서 사용)
    * CONNECT : 대상 자원으로 식별되는 서버에 대한 터널을 설정
    * TRACE : 대상 리소스에 대한 경로를 따라 메시지 루프백 테스트를 수행

    멱등 : 한번 호출하든 열번 호출하든 결과값은 똑같다.
    POST는 멱등이 아니다.
    거의 GET만 캐시로 사용된다
     



    정적 데이터 조회
    GET메서드 사용.
    정적 데이터는 쿼리 파라미터 없이 리소스 경로로 단순하게 조회 가능

    동적 데이터 조회
    GET메서드 사용.
    주로 검색, 게시판 목록에서 정렬 필터
    조회 조건을 줄여주는 필터, 조회 결과를 정렬하는 정렬 조건에 주로 사용됨.
    쿼리 파라미터로 데이터 전 HTML Form 데이터 전송(GET,POST 지원)
    Content-Type : application/x-www-form-urlencoded 사용
    - - form의 내용을 메시지 바디를 통해서 전송(키-밸류, 쿼리 파라미터 형식)
    - - 전송 데이터를 url encoding 처리
    HTML Form은 GET 전송도 가능
    Content-Type: multipart/form-data
    - - 파일 업로드 같은 바이너리 데이터 전송시 사용
    - - 이름 그대로 다른 종류의 여러 파일과 폼의 내용 함께 전송 가능
    POST로 등록할 경우 클라이언트는 URI를 모른다. 서버에서 만들어주기때문

    Api 설계에 좋은 연습 방법이 있는 사이트
    https://restfulapi.net/resource-naming

    ##### HTTP 상태코드
    200 - OK 성공적
    201 - 요청 성공해서 새로운 리소스가 생성됨
    202 - 요청이 접수되었으나 처리가 완료되지 않았음. 배치 처리 같은 곳에서 사용되나 잘안쓰임
    204 - 서버가 요청을 성공적으로 수행했지만, 응답 페이로드 본문에 보낼 데이터가 없음. 예로 웹문서 편집기의 save버튼
    ---

    3xx - 해당 url이 더 이상 존재하지 않는 경우, PRG패턴의 경우, 특수 리다이렉션. 서버에서 해당 코드와 새로운 url을 보내주고 클라이언트는 자동으로 이동한다.
    *영구적 리다이렉션*
    301 - 영구적인 url 이동. 리다이렉트시 요청 메서드가 GET으로 변하고 본문이 제거될 수 있음

    308 - 리다이렉트시 메서드, 본문 유지.하지만 실무에선 이런 경우는 거의 없다. 
     
    *일시적인 리다이렉션*
    리소스의 URI가 일시적으로 변경된 경우라서 검색엔진 등에서 URL을 변경하면 안됨.

    302 - 리다이렉트시 요청 메서드가 GET으로 변하고 본문이 제거될 수 있음

    307 - 302와 기능은 같지만 리다이렉트시 요청 메서드와 본문 무조건 유지

    303 - 302와 기능은 동일하지만 요청메서드가 GET으로 변경.

    *PRG Post Redirect Get*
    예) POST로 주문후에 새로 고침으로 인해 중복 주문 방지
    POST로 주문후에 주문 결과 화면을 GET메서드로 리다이렉트
    새로고침해도 결과 화면을 GET으로 조회
    중복 주문 대신에 결과하면만 GET으로 조회

    *기타 리다이렉션*
    304 - 캐시를 목적으로 사용
    클라이언트에게 리소스가 수정되지 않았음을 알려주고 클라이언트는 로컬 PC에 저장된 캐시를 재사용한다.(캐시로 리다이렉트)
    로컬 캐시를 사용해아하므로 응답에 메시지 바디를 포함하면 안됨

    ---
    4xx 클라이언트 오류

    클라이언트가 이미 잘못된 요청, 데이터를 보내기 때문에 똑같은 재시도를 해도 실패함. 복구 불가.

    400 bad request
    클라이언트가 잘못된 요청을 해서 서버가 요청을 처리할 수 없음
    요청 구문, 메시지 등등 오류기 때문에 클라이언트는 요청 내용을 다시 검토하고, 보내야함

    401 unauthorized
    클라이언트가 해당 리소스에 대한 인증이 필요함
    인증, 인가가 필요할 경우

    403 forbidden
    서버가 요청을 이해했지만 승인을 거부함
    인증은 되지만 인가가 안될때

    404 not found
    요청 리소스를 찾을 수 없음
    ---
    5xx - 서버 오류
    서버가 복구되면 해결될 수 있기 때문에 재시도하면 성공할 수도 있음 

    500 internal server error
    서버 문제로 발생한 오류
    503 service unavailable
    서비스 이용 불가

    ---
    *협상(컨텐츠 네고시에이션)*
    클라이언트가 선호하는 표현 요청

    Accept : 클라이언트가 선호하는 미디어 타입 전달
    Accept-Charset : 클라이언트가 선호하는 문자 인코딩
    Accept-Encoding : 클라이언트가 선호하는 압축 인코딩
    Accept-Language: 클라이언트가 원하는 언어를 요청. 다중 언어 지원 서버라면 Content-Language로 원하는 언어를 전송함.
    *협상과 우선순위1*
    예) GET/event
          Accept-Language:ko-KR;ko;q=0.9,en-US;q=0.8 처럼 1에 가까운 순서로 우선순위가 있음
    *협상과 우선순위2*
    구체적인 것이 우선이다.
    *협상과 우선순위3*
    구체적인 것을 기준으로 미디어 타입을 맞춘다.
    ---
    ###### 전송 방식
    *단순 전송 Content-Length*
    바로 정보들을 전송하는 방법
    *압축 전송 Content-Encoding*
    압축하여 전송하는 방법.압축 정보를 제공해야함
    *분할 전송 Transfer-Encoding*
    바이트 수만큼 분할하여 전송함
    *범위 전송 Range, Content-Range*
    전송 중 접속이 끊겼거나 문제가 생겼을 때 지정해준 범위만큼 전송 받을 수 있음
    ---
    일반 정보

    Referer 이전 웹 페이지 주소
    A -> B로 이동하는 경우 B를 요청할 때 Referer : A를 포함해서 요청
    유입 경로 분석 가능.

    User-Agent 유저 에이전트 애플리케이션 정보
    통계 정보
    어떤 종류의 브라우저에서 장애가 발생하는지 파악 가능

    Server 요청을 처리하는 ORIGIN 서버의 소프트웨어 정보
    응답에서 사용

    Date 메시지가 발생한 날짜와 시간 응답에서 사용
    ---
    특수 정보

    Host 요청한 호스트 정보(도메인).필수
    하나의 서버에서 가상호스팅으로 여러개의 도메인을 사용하는 경우가 있을 수도 있어서 필수임.

    Location 페이지 리다이렉션
    3xx 코드 참조

    Allow 허용 가능한 HTTP 메서드(잘 안쓰임)

    Retry-After 유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간
    ---
    *인증*
    인증 메커니즘 마다 헤더에 들아가는 정보가 다르기 때문에 공부가 필요함
    HTTP의 Authorization은 메커니즘에 상관없이 헤더에 제공하는 것.
    ---
    *쿠키*
    HTTP는 무상태 프로토콜이다. 요청과 응답이 끝나면 연결을 끊기 때문에 회원이 로그인을 했더라도 서버에선 알 방법이 없다. 쿠키를 사용하지 않고 이 문제를 해결하기 위해선 클라이언트가 요청할 때마다 정보를 전달해야되는데 이는 보안에도 위험이 있고 무엇보다 개발이 힘들어진다.
    그래서 쿠키란 게 등장하였다. 쿠키는 클라이언트가 요청을 했을 때 서버에서 set cookie를 통해 쿠키를 설정해준다. 클라이언트는 이 쿠키를 쿠키저장소에 보관한 뒤부턴 모든 요청에 쿠키를 자동으로 같이 전달한다. 자동으로 쿠키를 전달하기 때문에 너무 많은 곳에 쿠키를 사용하면 트래픽 과부하를 초래하기 때문에 꼭 필요한 정보에만 쿠키를 사용하여야한다. 사용자 로그인 세션 관리.

    세션 쿠키 : 만료 날짜를 생략하면 브라우저 종료시 쿠키는 사라짐.
    영속 쿠키 : 만료 날짜를 지정할 시 해당 날짜까지 유지.

    도메인을 지정한 경우 서브 도메인까지 쿠키는 적용되지만 생략한 경우에는 해당 도메인에서만 쿠키가 적용됨
    ---
    *캐시*

    캐시가 없으면 클라이언트는 서버에 요청을 보내고 데이터를 다운로드 받는다. 재요청을 보냈을 때 데이터가 변경되지 않아도 똑같이 다운로드 받게 된다. 이는 비용적으로도 속도로도 좋지 않기 때문에 캐시란 게 존재한다.
    캐시를 적용하면 캐시 유효시간 동안 네트워크를 사용하지 않아도 되기 때문에 비싼 네트워크 사용량을 줄일 수 있고, 속도도 매우 빠르다.

    캐시의 유효시간이 지나도 데이터가 변경되지 않았으면 다운로드에 비용이 발생하고 비효율적이기 때문에 검증헤더와 조건부 요청을 사용한다.
    서버는 요청을 받으면 응답할 때 HTTP헤더에 Last-Modified 정보를 주고 클라이언트는 유효시간이 끝났을 때 서버에 if-Modified-since를 헤더에 추가해서 검증을 받는데 이때 변경이 일어나지 않았다면 이 조건식은 거짓이 되므로 200 성공 코드가 아닌 304 실패 코드를 보냄으로써 캐시가 있는 곳으로 리다이렉션을 시켜서 캐시에 있는 데이터를 사용한다. 하지만 이 방식은 데이터 기반의 로직이 아니라 날짜 기반의 로직이라 수정은 했더라도 데이터가 변경되지 않았을 경우에도 데이터를 다시 다운로드 받게되는 문제가 있다. 그래서 ETag를 사용하여 데이터의 해쉬값이나 서버에서 임의로 정한 값을 ETag에 달아주고 헤더에 포함을 한다. 그래서 클라이언트가 요청을 보낼 때 if-none-match 정보를 서버에 보내게 된다. 유효시간이 지났더라도 ETag의 값이 같다면 캐시에 있는 데이터를 계속 사용할 수 있으며 이때도 304 코드를 응답하고 HTTP 헤더만 전송하고 body는 전송하지 않는다.

    *Cache-Control 캐시지시어*

    Cache-Control: max-age 
    -캐시 유효 시간, 초단위
    Cache-Control:no-cache
    -데이터는 캐시해도 되지만, origin서버에 검증하고 사용해야함
    Cache-Control:no-store
    -데이터에 민감한 정보고 있으므로 저장하면 안됨(메모리에서 사용하고 최대한 빨리 삭제)

    Pragma, Expires도 있지만 하위호환이기 때문에 Cache-Control에서 모두 가능함.

    캐시를 저장하면 안되는 경우엔 무효화 응답을 해야한다.
    Cache-Control:no-cache, no-store, must-revalidate.
    혹시 모를 하위 버전의 요청을 대비해 Pragma:no-cache

    No-cache는 프록시 캐시 서버와 origin서버가 네트워크 단절로 서버 접근이 불가할 경우 오래된 데이터라도 보여주지만 must-revalidate는 프록시 캐시서버와 origin 서버가 단절되면 504 코드를 응답하게 되어있다.

Designed by Tistory.