네트워크 기본지식 + HTTP API 정리
Web/Http

네트워크 기본지식 + HTTP API 정리

인터넷 네트워크

IP (Internet Protocol) : 인터넷 프로토콜

1. 비연결성

2. 비신뢰성

3. 여러 애플리케이션 동시구동시 구분

위 3개의 문제때문에 TCP 등장

 

TCP (Transmission Control Protocol)

1. 연결지향 (3 way handshake)

2. 순서 보장

3. 신뢰성 보장

 

UDP (User Datagram Protocol)

1. IP와 기능이 거의 같음

2. IP + PORT 정도

 

요즘에는 대부분 TCP를 사용하지만 UDP가 다시 떠오르고 있다. UDP를 최적화하여 사용하려고 하고있다.

 

PORT : 같은 IP 내에서 프로세스를 구분하게 해준다.

  • 0 ~ 65535 : 할당가능
  • 0 ~ 1023 : well known 포트
    - FTP : 20, 21
    - HTTP : 80
    - HTTPS : 443

DNS (Domain Name System)

IP는 바뀔 수 있고, 기억하기 어렵다.

그래서 도메인명을 지정해주고 해당 도메인 요청이 오면 IP주소를 반환한다.

 

  • URI (Uniform Resource Identifier) : 리소스를 다른 리소스들과 식별하는 방식
  • URL (Uniform Resource Locator) : 위치로 식별
  • URN (Uniform Resource Name) : 이름으로 식별

 

URI는 URL, URN으로 분류될 수 있다.

URN 식별은 보편화되지 않아서 현재 URI는 URL과 같다고 봐도 무방하다.

 

 

HTTP

 

현재 가장 많이 사용되는 버전은

HTTP/1.1 RFC7230~7235

 

http 특징

  • http는 클라이언트(요청하는쪽) 서버(응답하는쪽)을 분리한다.
    - 클라이언트 : ui, 디자인에 집중
    - 서버 : 비즈니스로직에 집중
  • 서버가 중간에 바뀌더라도 상관없도록 http는 무상태(Stateless) 프로토콜을 지향한다.
    - 실무에서는 서버를 최대한 무상태를 지향하고 어쩔 수 없는 경우 (로그인 세션관리)등은 최소한의 상태유지를 사용한다.
  • http는 비연결성을 보장한다
    - 그렇다고 tcp연결을 계속 끊는것이 아니라 한번의 tcp 연결로 여러번의 http통신을 지원하는 지속 연결 (Persistent Connections)를 사용한다.

 

http 메세지 구성

요청시작라인

request-line :

method (공백) request-target (공백) HTTP-version (엔터)

ex)

GET /search?q=hello&hl=ko HTTP/1.1

Host: www.google.com

 

응답헤더

(OSW : 띄어쓰기 허용)

( (공백) 없으면 띄어쓰기 불가 )

header-field :

field-name ":" OWS field-value OWS

ex)

HTTP/1.1 200 OK

Content-Type: text/html;charset=UTF-8

Content-Length: 3423

...(추가 다른 헤더)

 

메세지 바디 (실제 전송할 데이터)

byte로 표현할 수 있는 모든 데이터 전송 가능

ex)

 

http API URI 설계

 

원칙 : URL은 리소스만 구분하고 행동은 메서드로 구분한다.

 

  • 회원 목록 조회 : /members
  • 회원 조회 : /members/{id} , GET
  • 회원 등록 : /members/{id}, POST

 

메소드

- GET : 리소스 조회

- POST : 메세지바디로 서버에 데이터전달, 전달된 데이터로 신규 리소스 등록

 

  • POST는 모든 요청을 처리할 수 있다. 애매할땐 POST를 사용하자
  • POST는 모든 요청을 처리할 수 있지만 조회할땐 GET을 사용하는 것이 유리하다.
    이유 : 
  • 실무에서는 리소스만으로 URI설계를 못할 수도 있다. 최대한 리소스만 구분하고 어쩔 수 없을때 컨트롤 URI( URI에 행위 포함) 로 구분한다.

- PUT : 전달된 데이터로 리소스를 덮어쓴다. 리소스가 있으면 대체, 없으면 생성한다.

- PATCH : 리소스 부분변경. 하지만 PATCH를 지원하지 않는 서버가 아직 있으므로 그냥 POST를 사용한다.

- DELETE : 리소스 제거

 

POST vs PUT

PUT은 클라이언트가 리소스 위치를 알고 URI를 지정한다.

 

 

멱등 : 한 번 호출하든, 두 번 호출하든 100번 호출하든 결과가 똑같다.

GET, PUT, DELETE : 멱등 O

POST : 멱등 X (두 번 호출하면 같은 결제가 중복해서 발생할 수 있다.)

 

 

메서드 실제 사용

 

클라이언트 -> 서버 데이터 전송 2가지 방법

  1. 쿼리 파라미터
    - GET
    - 주로 정렬 필터 검색어
  2. 메세지 바디
    - POST, PUT, PATCH

클라이언트 -> 서버 데이터 전송 4가지 상황

  1. 정적 데이터 조회
    쿼리파라미터x 리소스 경로로 조회가능
  2. 동적 데이터 조회
    쿼리파라미터o GET에서 사용
  3. HTML Form
    GET POST만 지원
  4. HTTP API
    - 서버끼리, 앱, 웹클라이언트 와 통신
    - POST, PUT, PATCH, GET 다 사용
    - TEXT, XML, JSON ...

파일관리 시스템시 신규자원 등록 API 작성시 PUT 사용해야한다.

클라이언트가 직접 리소스의 URI를 지정하기 때문에.

ex) /files/star.jpg

 

 

 

정리

URI 설계할 때는 최대한 자원만 구분하고 어쩔 수 없을때는 컨트롤 URI를 사용해라

 

설계시 참고하면 좋은 사이트 : https://restfulapi.net/resource-nameing 

 

 

상태코드

클라이언트가 보낸 요청의 처리상태를 응답에서 알려주는 기능

 

  • 1xx (Informational) : 요청이 수신되어 처리중 (거의 사용 x)
  • 2xx (Successful) : 요청 정상 처리
  • 3xx (Redirection) : 요청을 완료하려면 추가 행동이 필요
  • 4xx (Client Error) : 클라이언트 오류
  • 5xx (Server Error) : 서버 오류

3xx 리다이렉션

URL은 바뀌었지만 이전에 쓰던 URL을 사용하는 user가 있을때 3xx 리다이렉션 상태코드를 이용해 새 URL로 유도한다.

  • 영구 리다이렉션
    원래의 URL를 더이상 사용하지 않을때 사용. (검색엔진에서도 변경을 인지한다)
    - 301 (Moved Permanently) : 리다이렉트시 요청 메서드가 GET으로 변한다.
    - 308 (Permanent Redirect) : 리다이렉트시 요청 메서드와 본문을 유지한다.
    URL이 변경되면 정보들도 변경될 수 있기 때문에 웬만하면 GET으로 돌리는 것이 낫다.
  • 일시적인 리다이렉션
    리소스의 URI가 일시적으로 변경 (검색엔진에서 URL을 변경하면 안된다)
    - 302 (Found) : 리다이렉트시 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있다.
    - 307 (Temporary Redirect) : 리다이렉트시 요청 메서드와 본문을 유지한다.
    - 303 (See Other) : 리다이렉트시 요청 메서드가 GET으로 변경된다.
    POST로 주문 후에 새로고침으로 인한 주문 방지를 위해 POST로 주문 후 주문 결과 화면을 GET 메서드로 리다이렉트한다.
    결론 : 자동 리다이렉션시에 GET으로 변해도 되면 그냥 302를 사용한다.

 

2xx, 4xx에러로 처리할 에러들을 5xx로 내면 안된다.

클라이언트 개발자와 정확한 소통을 위해 에러를 확실히 구분해주어야 한다.

 

 

HTTP 헤더

  • 협상 (콘텐츠 네고시에이션) : 클라이언트가 선호하는 표현을 Quality Values(q) 값을 이용해 전달한다.
  • 전송방식
    - 단순 전송
    - 압축 전송 : Content-Encoding : gzip
    - 분할 전송 : Transfer-Encoding : chunked (용량이 너무 커서 오래걸릴때 오는대로 바로 표시할 수 있다.)
    - 범위 전송 : Content-Range : bytes 1001-2000 / 2000
    일반 정보
    - From : 유저 에이전트의 이메일 정보
    - Referer : 이전 웹 페이지 주소
    - User-Agent : 유저 에이전트 애플리케이션 정보
    - Server : 요청을 처리하는 오리진 서버의 소프트웨어 정보
    - Date : 메시지가 생성된 날짜
  • 특별정보
    - Host : 요청한 호스트 정보(이동할 정확한 도메인 주소) (필수 헤더)
    - Location : 페이지 리다이렉션시 이동할 위치
    - Allow : 허용 가능한 HTTP 메서드 (상태코드 405에서 응답에 포함해야한다)
    - Retry-After : 유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간 (503일때 서비스가 언제까지 불능인지)
  • 쿠키
    2개의 헤더 사용
    응답시 Set-Cookie : user = 홍길동
    2번째부터 요청시 Cookie : user=홍길동
    - set-cookie (응답시 쿠키설정)
    - sessionId
    - expired (쿠기가 언제 만료되는지)
    - path (허용되는 path. 이 경로를 포함한 하위 경로 페이지만 쿠키 접근)
    - domain (이 도메인에서 쿠키 사용)
    - Secure (보안정보 담아둠)
    보안에 민감한 데이터는 저장하지 않는다.
    최소한의 정보만 사용한다 (세션 id, 인증 토큰..)

+ 쿠키 - 보안 헤더

  • Secure
    https인 경우에만 전송한다.
  • HttpOnly
    자바스크립트에서 접근불가하게 해 XSS 공격을 방지한다
  • SameSite
    요청 도메인과 쿠키에 설정된 도메인이 같은 경우에만 쿠키를 전송해 XSRF 공격을 방지한다.

* XSS 공격 (Cross-Site Scripting)

특정 사용자의 페이지에 스크립트를 추가해 자바스크립트로 접근가능한 정보를 취약사이트로 전송한다.

 

* XSRF 공격

쿠키만으로 인증하는 서비스의 취약점을 이용해 사용자 모르게 해당 서비스에 특정명령을 요청한다.

 

https://ohgyun.com/543 

 

XSS 와 XSRF 의 차이점

발생일: 2014.12.12 키워드: XSS, XSRF, CSRF 문제: JSON WebToken 에 관련된 아티클을 읽다가 토큰이 쿠키보다 나은 이유에 다음과 같은 항목이 있었다. "It's easier to deal with XSS than XSRF" 가만... XSS는..

ohgyun.com

 

캐시

비싼 네트워크 사용량을 줄이기 위해 브라우저에 캐시

 

캐시 시간 초과시 클라이언트의 데이터와 서버의 데이터가 같다면 캐시를 재사용할 수 있다. (다시 다운받지 않아도 됨)

 

데이터가 같은지 확인하는 방법 : 검증 헤더 추가

- 마지막 수정 날짜

ex)

서버에서 -> "Last-Modified : 2020년 11월 10일 10:00:00" 헤더 포함 응답

클라이언트에서 -> "if-modified-since: 2020년 11월 10일 10:00:00 헤더 포함 요청

두 데이터가 같으면 : 데이터가 아직 수정되지 않았다. -> 서버에서 응답시 HTTP body없이 헤더만 보낸다.


하지만 만약, 데이터를 수정해서 날짜가 다르지만 같은 데이터를 수정해서 데이터 결과가 똑같은 경우에는? 

 

ETag 헤더 사용.

캐시용 데이터에 임의의 고유한 버전 이름을 달아둔다.

요청시 ETag를 보내서 같으면 유지, 다르면 다시받는다.

 

확실한 캐시 무효화 응답

Cache-Control : no-cache, no-store, must-revalidate

Pragma: no-cache

위 둘 다 넣어줘야 한다.

 

  • no-cache : 항상 원 서버에 검증하고 사용한다.
  • no-store : 민감한 정보는 저장하지 않는다.
  • must-revalidate : 캐시 만료후 최초 조회시 원 서버에 검증한다. 원 서버 접근 실패시 반드시 오류가 발생한다.

 

no-cache이면 항상 원서버에서 검증하고 사용하는데, must-revalidate는 왜 쓸까?

원 서버와의 네트워크가 끊겼을때 no-cache는 오래된 데이터를 보여줄 가능성이 있다. 그래서 must-revalidate를 사용하면 원 서버에 접근 실패시 오류가 발생하기 때문에 둘 다 사용해야한다.