Static Pages와 Dynamic Pages

 

 

  • Web Server와 WAS(Web Application Server)의 차이점을 알아보기 전에 Static Pages와 Dynamic Pages의 차이점을 알아야합니다.

 

Static Pages

 

  • 사용자의 HTTP 요청을 통해서 전달받은 URL과 일치하는 image, html, css, javascript등과 같은 파일에 대해서 그대로 응답해주는 방식을 말합니다.




Dynamic Pages

 

  • 사용자의 HTTP 요청을 통해서 전달받은 URL 그리고 추가적인 정보를 통해서 그에 걸 맞는 Contents를 동적으로 생성하여 응답하는 방식을 말합니다.




웹 서버와 WAS 차이

 

웹 서버

 

  • Web Server는 사용자의 요청에 따라서 컴퓨터에 저장되어 있는 파일을 응답하는 Static Pages 역할만 가능합니다.

 

  • 웹 서버의 종류로는 대표적으로 Apache, Nginx, IIS 등이 있습니다.




WAS(Web Application Server)

 

 

  • WAS는 jsp, servlet, php, DB Connection 등을 실행시킬 수 있는 프로그램이 내장되어 있어서 사용자에 요청에 따라서 동적인 페이지를 만들어서 응답할 수 있어 Dynamic Pages 역할도 가능합니다.

 

  • 웹 컨테이너(Web Container) 혹은 서블릿 컨테이너(Serblet Container)라고도 불립니다.

 

  • WAS는 Dynamic Pages 뿐만 아니라 로드밸런싱, fail over(장애 극복),무중단 배포 또한 가능합니다.

 

  • WAS의 종류로는 대표적으로 Tomcat, JBoss 등이 있습니다.




Cookie란?

 

  • Cookie는 서버가 사용자 웹 브라우저에 전송하는 작은 데이터 조각입니다. 웹 브라우저는 서버로부터 받은 데이터 조각들을 저장해 놓았다가 서버에 요청할 때 Cookie에 저장된 데이터를 같이 전송합니다.




Cookie 사용 목적

 

  • Session을 발급하고 Cookie에 Session ID를 담아 클라이언트에 전송함으로써 로그인 상태를 유지할 수 있습니다.

 

  • 사용자만의 셋팅 값 또는 테마 등의 데이터를 저장할 수 있습니다.

 

  • 쿠키에 담긴 사용자의 인터넷 사용기록을 이용하여 맞춤 광고를 제공할 수 있습니다.




Set-Cookie와 Cookie 헤더

 

  • 서버는 HTTP 요청에 대한 응답을 할 때 Set-Cookie 헤더를 이용해서 Cookie에 저장할 데이터를 전송할 수 있습니다.

 

  • 웹 브라우저는 서버에 요청할 때 Cookie 헤더를 이용해서 Cookie에 저장된 데이터를 요청에 담을 수 있습니다.




Cookie 속성

 

  • Domain과 Path는 Cookie가 사용될 수 있는 Domain과 Path를 의미합니다.

 

  • Secure는 HTTPS를 사용하는 경우에만 Cookie를 사용할 수 있습니다.

 

  • HttpOnly는 XSS 공격을 방지하기 위해 JavaScript와 Document.Cookie API로 접근할 수 없게 하는 속성입니다.




Cookie의 종류

 

  • Session Cookie는 메모리에만 저장되며 브라우저 종료 시 삭제합니다.

 

  • Persistent Cookie는 디스크에 저장하여 브라우저가 종료되어도 유지되는 Cookie입니다. 주로 Session ID를 저장할 때 사용합니다.

 

  • Secure Cookie는 HTTPS로 통신할 경우에만 사용하는 Cookie입니다.

 

  • Third-Party Cookie는 방문한 도메인과 다른 도메인의 쿠키로서 주로 맞춤 광고에 사용되는 쿠키입니다.




Cookie의 단점

 

  • 요청 시 쿠키의 값을 그대로 보내기 때문에 유출 및 조작 당할 위험이 존재합니다.

 

  • 4KB의 용량 제한이 있습니다.

 

  • 웹 브라우저 마다 지원 형태가 다르며 브라우저간의 공유가 불가능합니다.

 

  • 쿠키의 사이즈가 커질수록 네트워크의 부하가 상승합니다.




Session

 

  • 세션이란 상호 연결 상태 정보를 공유함으로써 가상의 연결 상태를 구현하는 기법입니다.

 

  • 웹 에서는 사용자가 로그인했을 때 Session을 발급하고 SessionID를 Set-Cookie 헤더를 이용해 클라이언트에게 공유하여 Session을 유지합니다.

 

  • Session은 사용자의 요청이 있을 때마다 SessionID로 DB에서 Session을 조회해야 하는 추가적인 작업이 필요하다는 단점이 있습니다.




Session 방식의 단점

 

  • 사용자의 Session ID를 탈취하여 서버에 접속할 수 있습니다.( 이를 위해서는 IP 제한 또는 접속 기기 제한을 이용해 추가적인 보안이 필요합니다. )

 

  • 요청마다 SessionID로 DB에 저장된 Session을 조회해야 하기 때문에 DB 서버의 부하가 상승합니다.




토큰 인증 방식

 

  • Token 기반 인증 시스템은 사용자가 로그인하였을 때 서버가 클라이언트에게 세션 정보가 담긴 토큰을 부여하고, 클라이언트의 매 요청마다 서버는 토큰이 유효한지만 검사하는 인증 기술입니다. Session에 대한 정보를 서버에서 관리하지 않기 때문에 Session 데이터 조회로 인한 서버의 부하를 없앨 수 있습니다.




Token 방식의 단점

 

  • 쿠키/세션과 다르게 토큰 자체의 데이터 길이가 길어, 인증 요청이 많아질수록 네트워크 트래픽이 증가합니다.

 

  • Payload 자체는 암호화되지 않기 때문에 유저의 중요 정보는 담을 수 없습니다.

 

  • 토큰을 탈취당하면 대처하기 어렵습니다. 그렇기 때문에 필수적으로 사용 기간 제한을 설정해야 합니다.




JWT( JSON Web Token )

 

  • JWT(JSON Web Token)란 토큰 인증 방식에 사용되며, 인증에 필요한 정보들을 암호화시킨 JSON 토큰을 의미합니다.




JWT 구조

 

  • JWT는 Base64 URL-safe로 인코딩 되어있으며 '.' 을 구분자로 3 가지의 문자열인 Header, Payload, Signature로 구분됩니다.

 

  • Header에는 서명 암호화 알고리즘과 토큰 유형이 담겨져있습니다.

 

  • Payload에는 발행자, 만료 시간 등의 클라이언트 Session에 대한 정보가 담겨져 있습니다.

 

  • Signature에는 Base64Url(Header) + . + Base64Url(Payload) + server's key에다가 Header에 있는 알고리즘 방식으로 암호화한 결과값이 저장되어 있습니다. server's key는 오직 서버만 알고있기 때문에 Signature를 통해서 해당 Token이 조작되었는지 여부를 확인할 수 있습니다.




JWT 장점

 

  • 서버가 Session에 대한 별도의 저장 공간을 사용할 필요가 없습니다.

 

  • 서버와 클라이언트간의 완전한 Stateless 구조를 갖기 때문에 확장성이 우수합니다.

 

  • 모바일 어플리케이션과 호환성이 좋습니다.




JWT 단점

 

  • Payload에 중요한 데이터를 담지 않도록 주의해야 합니다.

 

  • 토큰의 크기 때문에 네트워크 트래픽이 증가할 수 있습니다.

 

  • 토큰 자체가 탈취 당할 수 있기 때문에 토큰에 대한 유효기간을 지정해야 합니다.




Refresh Token

 

  • JWT만을 사용할 경우 헤커가 사용자의 JWT를 탈취할 수 있습니다. 그렇기 때문에 Access Token과 Refresh Token 두개를 발급하여 실제 인증에 사용되는 Access Token의 유효기간을 짧게하고 만약, 만료되었다면 Refresh Token을 이용해서 재발급 받을 수 있도록 합니다. Refresh Token 또한 탈취 당할 수 있기 때문에 Access Token을 새로 발급 받을 때마다 새로운 Refresh Token을 발급하여 Refresh Token을 갱신시키는 방법을 주로 사용합니다. 이를 Refresh Token Rotation( RTR ) 이라 합니다.


  • Refresh Token을 서버쪽에서 관리하여 사용자의 JWT를 갱신시켜주는 방법도 있습니다. 어떻게 본다면 Refresh Token을 서버에서 관리하는 것은 결국 서버에서 Session을 관리하는 단점과 동일하게 볼 수도 있습니다. 하지만, 서비스가 커짐에 따라서 필요한 사용자 정보가 커지지만 Refresh Token은 그대로이기 때문에 Session을 직접 관리하는 것보다는 훨씬 서버에 부하가 적습니다.




JWT vs Cookie & Session

 

  장점 단점
Cookie & Session 서버에서만 Session에 대한 정보를 관리할 수 있고 네트워크 부하 낮음 세션 저장소 사용으로 인한 DB 서버 부하가 큼
JWT 서버에서 인증을 위해 별도의 Session 저장소가 필요없으며 완전한 Stateless 구조로 확장성이 우수 토큰이 클 수록 네트워크 트래픽이 증가




RUDP( Reliable UDP )란?

 

  • RUDP( Reliable UDP )란 신뢰할 수 있는 UDP로서 UDP를 랩핑하여 안전한 송.수신을 구현한 프로토콜을 말합니다.

 




RUDP를 사용하는 여러가지 이유

 

  • TCP보다 빠르고 안정적인 송.수신 프로토콜을 구현하기 위해 사용합니다.

 

  • TCP는 IP와 포트를 기준으로 연결을 수립하지만 RUDP는 프로그래머가 어떻게 구현하느냐에 따라서 연결 기준을 변경할 수 있습니다. 이러한 장점은 이동할 때마다 중계기가 변경되어 IP가 바뀌는 모바일 환경에서 매우 이점이 있습니다. 예를들어서 대중교통을 이용하면서 TCP 통신을 하는 모바일 게임을 즐기고 있다면 중계기가 바뀔 때마다 연결이 끊길 것입니다.




RUDP 구현에 필요한 스펙

 

  • TCP의 3-way-handshake와 같이 연결할 PC간의 연결 정보를 교환하여 세션을 수립하는 작업이 필요합니다.

 

  • UDP는 송신하려는 데이터의 크기를 그대로 네트워크 계층으로 전달하기 때문에 네트워크 계층에서 MTU 사이즈 초과로 분할되는 것을 방지하기 위해서 송신하려는 데이터의 크기를 조절하여 사용해야 합니다.

 

  • TCP가 오류 제어, 흐름 제어, 혼잡 제어를 통해서 안전한 송.수신을 구현한 것처럼 RUDP에도 이와 같은 스펙이 구현되어야 합니다.




TCP 네이글 알고리즘( Nagle Algorithm )이란?


  • TCP의 네이글 알고리즘이 활성화 되어있는 상태에서 데이터를 송신할 때 바로 송신하지 않고 최대 MSS( TCP 세그먼트 페이로드의 최대 크기를 의미하며 보통 1460byte입니다. )크기 만큼 데이터를 버퍼링하여 송신합니다.




네이글 알고리즘을 사용하는 이유


  • 송신할 데이터를 버퍼링하지 않고 Send 버퍼에 데이터가 적재될 때마다 송신한다면 패킷 마다 TCP 헤더, IP 헤더, 이더넷 헤더가 붙기 때문에 네트워크 트래픽량이 증가됩니다. 그렇기 때문에 송신할 데이터는 최대한 버퍼링하여 한 번에 송신하는 것으로 네트워크 트래픽을 줄일 수 있습니다.




네이글 알고리즘이 활성화 되었을 때 데이터 전송 조건


  • 송신하려는 데이터가 MSS 크기만큼 버퍼링 되었을 때 송신합니다.

  • 버퍼링하는 도중에 일정 시간이 지났다면 MSS 크기만큼 버피링 되어 있지 않더라도 송신합니다.

  • 데이터를 버퍼링 하는 도중에 상대방으로부터 ACK가 왔다면 MSS 크기만큼 버퍼링 되어 있지 않더라도 데이터를 송신합니다.




네이글 알고리즘의 단점


  • 송신하려는 데이터를 MSS만큼 버퍼링하고 송신하기 때문에 매우 빠른 응답성을 요구하는 격투 게임같은 경우에서는 사용자가 딜레이를 느낄 수 있습니다.




네이글 알고리즘을 비활성화하는 방법


  • setsockopt 함수를 통해 TCP_NODELAY 옵션을 주면 네이글 알고리즘을 비활성화 할 수 있습니다.




TCP의 세 가지 제어 기능

 

  • TCP는 흐름 제어, 오류 제어, 혼잡 제어 이 세 가지 제어 기능으로 안정적인 1:1 송.수신을 구현합니다. 이러한 기능들 덕분에 TCP를 사용할 경우 상위 레이어에만 개발에 집중할 수 있습니다.




흐름 제어

 

  • 흐름 제어는 상대방의 window size를 고려하여 송신 데이터의 크기를 조절하고 응답에 상관없이 window size만큼 데이터를 연속적으로 송신하는 기능을 담당합니다.




Stop and wait

 

 

  • 데이터를 송신하면 상대방이 데이터를 잘 수신 받았는지 여부를 확인하기 위해 ACK 응답을 기다립니다. ACK 응답의 Acknowledge Number를 통해서 수신 여부 및 정말로 보낸 데이터 만큼 잘 수신 받았는지를 확인할 수 있습니다.




Sliding window

 

 

  • sliding window는 TCP가 3-way-hasdshake 과정에서 알아냈던 상대방의 window size만큼 수신 응답을 기다리지 않고 데이터를 연속적으로 보내며 수신자 측은 지금까지 수신받았던 데이터 크기와 Sequence Number를 기반으로 Acknowledge Number를 셋팅하여 한 번에 응답합니다. 이러한 기능 덕분에 TCP의 패킷 당 송.수신 확인 응답으로 인한 지연을 줄일 수 있습니다.




오류 제어

 

  • TCP는 일정시간 수신자에게 응답이 없거나 송신 데이터가 잘못되어 NACK(Negative Ack)로 응답이 올 경우 자동으로 재전송하는 ARQ(Automatic Repeat Request) 기법을 사용합니다. 그리고 TCP는 Checksum과 Sequence Number, Acknowledge Number를 이용해서 송.수신 데이터의 오류를 검출하며 Go Back N, Selective Repeat을 혼합한 형태로 오류 제어를 합니다.(Stop and Wait 전송 속도가 매우 느리고 효율이 낮아서 사용되지 않습니다.)




Stop and Wait

 

 

  • 데이터를 송신하고 수신자로부터 일정시간 동안 ACK 응답이 없어 timeout이 되거나 NACK가 올 경우 전송했던 데이터를 재전송합니다.




Go Back N ( GBN )

 

 

  • Go Back N 방식은 위와 같이 sliding window를 이용해 연속적으로 데이터를 보내다가 timeout으로 데이터가 유실되었음을 인지하거나 수신자로부터 NACK 응답이 왔을 경우 문제가 발생된 데이터부터 다시 재전송하는 방식을 말합니다. 구현은 간단하지만 잘못된 데이터부터 모두 다시 보내야 한다는 단점이 있습니다.




Selective Repeat( SR )

 

 

  • Selective Repeat은 모든 응답에 대해서 ACK를 보내고 누락되거나 잘못된 패킷에 대해서만 NACK를 통해 재전송 요청을 합니다. 중간에 잘못되거나 누락된 패킷이 재전송되어 수신할 경우 기존에 받았던 패킷들과 순서에 맞게 재조합을 해야하기 때문에 추가적인 작업과 버퍼가 필요합니다. 또한 모든 패킷에 대한 응답이 필요하기 때문에 네트워크 트래픽이 증가될 수 있습니다.

 

  • 데이터를 연속적으로 송신하다가 중간의 데이터가 유실되어 동일한 ACK가 지속적으로 올 경우 timeout을 기다리지 않고 데이터가 유실되었다고 판단하여 재전송합니다.




혼잡 제어

 

 

  • 통신하는 네트워크 내의 트래픽이 과도하게 증가하여 송.수신이 원활하게 이루어지지 않는 상태를 혼잡이라고 합니다. TCP가 패킷 유실률 그리고 응답 속도를 종합하여 혼잡도를 판단합니다. 그리고 혼잡 제어는 네트워크의 혼잡한 현상을 방지하고 제거하기 위해 사용되는 기능입니다.




Awnd( Advertised window )와 Cwnd( Congention window)

 

  • Awnd는 실제로 수신자가 한 번에 데이터를 수신받을 수 있는 최대 버퍼 크기를 의미합니다.

 

  • Cwnd는 TCP가 네트워크 혼잡도에 따라서 실제로 수신자에게 한 번에 송신할 수 있는 데이터 크기를 의미하며, 최대 크기는 Awnd입니다.




Slow Start

 

  • TCP는 처음 연결직후 Cwnd의 사이즈를 1로 하고 임계 지점을 Awnd의 1/2로 합니다. 수신자로부터 ACK 응답을 받을 때마다 Cwnd 사이즈를 2베씩 증가시켜가며 Cwnd가 임계 지점에 도달했다면 ACK 응답을 받을 때마다 1씩 증가시켜 Awnd 크기 만큼 증가시킵니다.

 

  • timeout이 발생되었다면 네트워크가 혼잡하다고 판단하여 Cwnd를 1로 하고, 임계 지점의 크기를 반으로 줄인 후 다시 Slow Start 방식으로 Cwnd를 증가시킵니다.




Fast Retransmit( 빠른 재전송 ) & Fast Recovery( 빠른 회복 )

 

  • sliding window를 통해서 패킷을 송신하는 도중에 중간 패킷이 유실되어 수신자가 유실전 패킷에 대한 ACK를 3번 연속으로 보내게 될 경우 timeout을 기다리지 않고 유실된 패킷을 재전송합니다. 이러한 방식을 Fast Restransmit이라 하며, 이를 통해 TCP는 네트워크의 혼잡함을 인지하여 Cwnd를 1이 아닌 1/2로 줄이며 해당 지점을 임계 지점으로 설정합니다. 이후 ACK를 받을 때마다 1씩 최대 Awnd만큼 증가시키며 이를 Fast Recovery 라고 합니다.




3-way-handshake

 

 

  • 3-way-handshake는 TCP로 데이터를 송.수신하기 전에 1:1 연결하려는 PC간에 연결 정보를 교환함으로써 연결을 수립하는 과정을 말합니다.




3-way-handshake 과정

 

    1. 클라이언트는 connect() 함수를 호출하여 listen 상태의 서버에게 응답 패킷의 SYN 플래그를 활성화하고 임의의 Sequence Number를 담고 연결 정보와 같이 SYN 패킷을 송신합니다. 이 때 클라이언트의 연결 상태는 SYN-SENT 상태가 됩니다.

 

    1. SYN 패킷을 받은 서버는 수신 받은 패킷의 Sequence Number를 확인하고 응답하는 패킷에 SYN, ACK 플래그를 활성화하고 클라이언트의 Sequence Number에 1을 더하여 Acknowledgment Number를 셋팅합니다. 그리고 패킷에 임의의 Sequence Number와 연결정보와 같이 SYN/ACK 패킷을 송신합니다. 이 때 서버의 연결 상태는 SYN-RECEVED 상태가 됩니다.

 

    1. 서버의 응답을 받은 클라이언트는 ESTABLISHED 상태가 되어 연결 완료 상태가 되며, 서버에게 SYN-ACK 패킷에 담긴 Sequence Number에 1을 더하여 응답 패킷의 Acknowledgment Number를 셋팅하고 ACK 플래그를 활성화 후 응답을 합니다.

 

    1. 클라이언트의 응답을 받은 서버는 ESTABLISHED 상태가 되어 TCP 최종 연결이 완료됩니다.




3-way-handshake가 필요한 이유

 

  • 상호 연결정보를 교환할 때 얻은 Sequence Number, Acknowledgment Number, Window Size를 통해서 패킷이 몇 번째 패킷인지 그리고 패킷을 어디까지 수신 받았는지를 확인할 수 있습니다. 내가 송신한 패킷에 대한 ACK를 확인하여 상대방이 내가 송신한 패킷을 어디까지 수신 받았는지 확인하여 재전송 및 다음 패킷을 송신합니다.

    Window Size는 Sliding Window에 사용됩니다. Sliding Window는 응답이 오지 않아도 상대방의 Window Size 만큼 데이터를 송신하고 상대방은 수신 받은 여러개의 패킷에 대해서 하나의 ACK로 응답합니다. 이로 인해 ACK를 기다림으로써 발생되는 딜레이 및 네트워크 트래픽량을 줄일 수 있습니다.




4-way-handshake

 

 

  • 4-way-handshake는 1:1 연결된 TCP 세션간의 연결을 끊기 위한 과정을 말합니다.




4-way-handshake 과정

 

    1. 연결을 종료하려는 쪽이 close() 함수를 호출하여 FIN 플래그가 활성화된 패킷을 상대방에게 송신하며 이때 연결 상태는 FIN_WAIT_1 상태가 됩니다.

 

    1. FIN 패킷을 수신받은 쪽은 FIN 패킷의 Sequence Number에 1을 더하여 Acknowledgment Number에 셋팅하여 ACK 패킷으로 응답하며 이때 연결 상태는 CLOSE_WAIT 상태가 됩니다.

 

    1. FIN 패킷에 대한 ACK를 받은쪽은 FIN_WAIT_2 연결 상태가 되며, 상대방이 FIN 패킷을 송신하기만을 기다립니다.

 

    1. CLOSE_WAIT 상태에서 close() 함수를 호출하면 상대방에게 FIN 패킷을 송신하며 연결 상태는 LAST_ACK 상태가 됩니다.

 

    1. FIN_WAIT_2 상태에서 FIN 패킷을 받은쪽은 FIN 패킷의 Sequence Number에 1을 더하여 Acknowledgment Number에 셋팅하여 ACK 패킷으로 상대방에게 응답 후 연결 상태는 TIME_WAIT 상태가 됩니다.

 

    1. LAST_ACK 상태에서 FIN에 대한 응답은 받으면 연결 상태가 CLOSED 상태가 되어 TCP 연결이 종료됩니다.




4-way-handshake가 필요한 이유

 

  • 4-way-handshake 연결 종료 절차를 통해 상호 세션을 정리하는 과정을 수행할 수 있습니다. 하지만, FIN 패킷을 처음으로 보내는 PC는 TIME_WAIT이 남아 해당 IP에 대한 PORT를 한동안 사용할 수 없게 됩니다.

    이러한 TIME_WAIT이 남는 이유는 연결 종료 후에 동일한 포트가 바로 재사용되어 새로운 세션이 수립되었을 때 이전에 연결되었었던 상대방이 송신한 패킷이 뒤늦게 수신되어 잘못 처리될 수 있는 확률이 있기 때문에 TIME_WAIT을 통해서 해당 포트가 재사용되지 않도록 합니다.

    하지만, TIME_WAIT이 없다 하더라도 위와 같은 불상사가 발생할 확률은 매우 희박합니다. 왜냐하면 TCP는 안전한 송.수신을 보장하기 때문에 Sequence Number와 Acknowledgment Number가 일치해야 처리할 수 있기 때문입니다.




ARP( Address Resolution Protocol )란?

 

  • ARP( Address Resolution Protocol)이란 IP주소를 이용해 내부망 PC들의 MAC주소를 조회하는 프로토콜입니다.




ARP 과정

 

  • 1. 송신하려는 메시지의 목적지 IP주소에 대응하는 MAC주소를 알아내기 위해 ARP 브로드 캐스팅을 합니다.

 

 

  • 2. 내부망의 PC들은 ARP 패킷을 확인하여 자신의 IP주소와 동일하다면 자신의 MAC주소를 포함하여 응답합니다.

 

 

  • 3. 응답받은 PC는 MAC주소를 확인하여 목적지 MAC주소를 셋팅하여 메시지를 송신합니다. 그리고 MAC주소를 ARP 테이블에 저장하여 이후 목적지 IP주소를 대상으로 데이터를 송신할 때 재사용합니다.

 

 

 

 

ARP 테이블이란?

 

 

  • 메시지를 송신할 때마다 MAC주소를 알아 내기 위해 ARP를 사용하는 것은 네트워크 트래픽의 낭비입니다. ARP를 통해 알아낸 MAC주소를 IP주소와 맵핑하여 일정 시간동안 로컬 PC의 ARP 테이블에 저장하여 재사용합니다.

 

  • windows의 cmd창에서 arp -a 명령어를 통해 arp 테이블에 저장된 IP주소와 MAC주소를 조회할 수 있습니다.




RARP( Reverse Address Resolution Protocol )

 

  • RARP( Reverse Address Resolution Protocol )란 MAC주소를 이용해 내부망의 IP주소를 조회하는 프로토콜입니다.




ARP 스푸핑( Spoofing )

 

 

  • 동일한 네트워크 망에 있는 해커가 GARP( gratuitous ARP )를 이용해 라우터에게 공격 대상의 IP주소와 자신의 MAC주소를 맵핑하여 송신하고, 공격자에게는 게이트 웨이 IP주소와 자신의 MAC주소를 맵핑하여 송신합니다. 그러면 위 이미지에서와 같이 공격 대상자는 외부망에 메시지를 송신할 때마다 해커의 PC를 거치게 되고 모든 외부에서 해당 공격 대상자의 PC로 들어오는 메시지에 대해서 해커의 PC를 거치게 됩니다.

 

  • 위와 같은 공격이 가능한 이유는 ARP는 자체적으로 IP주소와 MAC주소를 검증하는 기능이 없기 때문입니다.




GARP( gratuitous ARP )

  • GARP( gratuitous ARP )는 ARP 테이블 갱신 및 IP 주소 충돌 감지를 하기위해 사용되는 프로토콜입니다.

 

 

CORS( Cross-Origin Resource Sharing )란?

 

  • CORS( Cross-Origin Resource Sharing )는 추가 HTTP 헤더를 사용하여 다른 출처와 자원을 공유할 수 있도록 브라우저에게 알려주는 정책입니다. CORS 동작 방식에 따라서 Preflight Request, Simple Request, Credential Request로 나뉩니다. 이러한 정책이 필요한 이유는 브라우저의 SOP( Same-Origin Policy ) 보안 때문이며, SOP는 아래에서 설명하겠습니다.




출처( Origin )란?

 

 

  • 출처( Origin )란 위 URI 구성에 나와있듯이 Protocol, Host, Port를 묶어서 표현한 것을 의미합니다.




SOP( Same-Origin Policy )

 

  • 현재 출처와 다른 출처( Origin )와의 리소스를 공유하는 것을 제한하는 정책입니다.




SOP가 필요한 이유

 

 

  • SOP(Same-Origin Policy)가 필요한 대표적인 이유로는 XSS(Cross-Site Scripting) 공격이 있습니다. XSS는 해커가 서버에 악의적인 스크립트를 심어서 사용자가 이를 조회했을 때 해커가 작성한 스크립트를 실행하여 자신의 세션 정보와 같이 중요한 정보가 해커의 서버로 송신되는 상황을 방지하기 위함입니다. 

    SOP는 동일한 Origin을 대상으로만 Request를 허용하기 때문에 위와같이 사용자가 해커가 심어놓은 스크립트를 실행한다 하더라도 사용자의 정보가 다른 Origin으로 탈취되는 상황을 방지할 수 있습니다.




CORS가 필요한 이유

 

  • 모든 요청을 동일한 서버에 한다면 CORS는 필요하지 않습니다. 하지만, 아래와 같은 이유로 CORS를 이용하여 다른 출처로 요청하여 리소스를 공유하는 상황이 생길 수 있습니다.




프론트와 백엔드의 서버 분리

 

  • 현대 웹 애플리케이션는 빠른 서비스를 위해 서버가 크게 프론트와 백엔드로 나누어졌습니다. 클라이언트 측에서 요청을 하는 순간 프론트 서버의 응답을 받아 랜더링이 되고, 데이터는 백엔드 서버에 요청하여 받아오게 되는 흐름은 다른 출처간의 리소스 공유를 막는 SOP 때문에 처리의 한계를 가졌습니다.




다른 출처의 데이터 사용

 

  • 웹 구현시 REST API를 통해 다른 출처의 데이터를 요청해 리소스를 공유하는 경우가 많아졌습니다.




마이크로 서비스 아키텍쳐

 

  • 트래픽양이 증가하면서 서버 한대로는 물리적으로 버티기 힘들어졌고 여러개 서버의 필요성이 대두되었습니다. 예를들어서 A 서버는 로그인 처리를 위한 서버, B 서버는 주문만 받는 서버처럼 하나의 서버가 특정 기능만을 수행하도록 분할하여 관리할 수 있습니다.




Preflight Request

 

  • 기본적으로 브라우저는 요청을 보낼 때 바로 보내지 않고, 먼저 Preflight Request를 보내 서버와 잘 통신되는지 확인 후 본 요청을 보냅니다. Preflight Request를 보낼 때 HTTP 메소드를 OPTIONS로 하여 요청합니다.




Prefligh Request를 이용한 통신 과정

 

 

1. 자바스크립트의 fetch() 메서드를 통해 리소스를 요청합니다.




2. 브라우저는 서버로 OPTIONS 메서드로 Preflight Request를 보냅니다.

 

  • Origin 헤더에 자신의 출처를 넣습니다.

 

  • Access-Control-Request-Method 헤더에 실제 요청에 사용할 메소드를 설정합니다.

 

  • Access-Control-Request-Headers 헤더에 실제 요청에 사용할 헤더들을 설정합니다.




3. Preflight Request를 받은 서버는 어떤 것을 허용하는지에 대한 정보를 헤더에 담아 응답합니다.

 

  • Access-Control-Allow-Origin 헤더에 허용되는 Origin을 설정합니다.

 

  • Access-Control-Allow-Methods 헤더에 허용되는 메소드들의 목록을 설정합니다.

 

  • Access-Control-Allow-Headers 헤더에 허용되는 헤더들의 목록을 설정합니다.

 

  • Access-Control-Max-Age 헤더에 해당 예비 요청이 브라우저에 캐시될 수 있는 시간을 초 단위로 설정합니다.




4. 응답받은 브라우저는 헤더를 확인하여 해당 요청이 안전한지 확인하고 본 요청을 보냅니다.




5. 이후 요청에는 Access-Control-Max-Age에 설정된 시간만큼 캐시하여 Preflight Request를 생략합니다.




Simple Request

 

  • Simple Request는 메서드와 헤더 정보들을 확인하여 보안적으로 안전한 요청이라면 Preflight Request를 생략하고 바로 서버에 본 요청을 하는 방식입니다.

    이 요청을 받은 서버는 응답 헤더에 Access-Control-Allow 헤더들을 설정하여 응답하면 브라우저가 CORS 정책 위반 여부를 검사합니다. 즉, 조건에 맞다면 Preflight Request를 생략하고 응답 데이터의 Access-Control-Allow 헤더들이 올바른지 확인하여 응답 거부 여부를 결정합니다.




Simple Request를 이용한 통신 과정

 

 

  • Simple Request는 아래 3가지 조건을 충족할 때만 Reflight Request를 생략하여 이루어지며, 아래와 같이 까다로운 조건 때문에 Simple Request가 되는 경우가 상당히 드뭅니다.




Simple Request 4 가지 조건

 

  • 요청의 메소드는 GET, HEAD, POST만 허용합니다.

 

  • Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width 헤더일 경우에만 적용됩니다.

 

  • Content-Type 헤더가 application/x-www-form-urlencoded, multipart/form-data, text/plain만 허용합니다.


  • 클라이언트가 credentials 옵션을 설정하지 않아야 합니다. (즉, 자격 증명 정보를 서버로 전송하지 않아야 합니다.)




Credential Request

 

  • 인증된 요청은 클라이언트에서 서버에게 자격 인증 정보( Credential )를 실어 요청하는 것을 말합니다. 여기서 말하는 자격 인증 정보란 쿠키에 저장되어 있는 SessionID 또는 Authorization 헤더에 설정하는 JWT와 같은 Token 값 등을 말합니다. 이러한 인증된 요청을 다른 출처로 요청할 때에는 서버는 Access-Control-Allow 헤더에 더 구체적인 응답이 필요합니다.

 




인증된 요청을 하는 방법

 

옵션 값
설명
same-origin(기본값) 같은 출처간의 요청에만 인증 정보를 담음
include 모든 요청에 인증 정보를 담음
omit 모든 요청에 인증 정보를 담지 않음




credentials 설정

 

fetch("https://example.com:8888", {
  method: "POST",
  credentials: "include",
  body: JSON.stringify({
    name: "devhun",
  }),
});




인증된 요청에 대한 서버 응답 방법

 

  • 서버도 마찬가지로 인증된 요청에 대해서는 일반적인 CORS 요청과는 다르게 처리해야합니다. 응답 헤더를 아래와 같이 설정하지 않는다면 응답 받은 브라우저는 CORS 정책에 의해 요청이 거부됩니다.




응답 헤더 설정

 

  • 응답 헤더의 Access-Control-Allow-Credentials 항목을 true로 설정해야 합니다.

 

  • 응답 헤더의 Access-Control-Allow-Origin의 값에 와일드 카드("*")는 사용할 수 없습니다.

 

  • 응답 헤더의 Access-Control-Allow-Methods의 값에 와일드 카드("*")는 사용할 수 없습니다.

 

  • 응답 헤더의 Access-Control-Allow-Headers의 값에 와일드 카드("*")는 사용할 수 없습니다.




HTTP 표현( Representation ) 헤더

 

  • 표현 헤더는 HTTP 메시지 바디 데이터에 대한 형식을 지정할 수 있으며, 요청과 응답에서 사용할 수 있습니다.




Content-Type

 

  • 표현 데이터의 형식




Content-Encoding

 

  • 표현 데이터의 압축 방식




Content-Language

 

  • 표현 데이터의 자연 언어( 영어인지 한국어인지 )




Content-Length

 

  • 표현 데이터의 길이




HTTP 협상( Negotiation ) 헤더

 

  • 클라이언트가 선호하는 표현으로 응답해달라고 서버측으로 요청할 때 사용합니다. 협상 헤더는 요청시에만 사용합니다.

 

  • 협상 헤더에 따라서 우선순위 q value를 주어서 서버에서 첫 번째 협상에 실패하였을 때 다음으로 우선순위가 높은 협상을 찾아서 응답합니다.

 

  • 구체적인 것이 우선순위가 높습니다. 예를들어서 Accept: text/*, text/plain 에서 text/plain의 우선순위가 더 높습니다.




Accept

 

  • 클라이언트가 선호하는 미디어 타입




Accept-Charset

 

  • 클라이언트가 선호하는 문자 인코딩




Accept-Encoding

 

  • 클라이언트가 선호하는 압축 인코딩




Accept-Language

 

  • 클라이언트가 선호하는 자연 언어




HTTP 전송 방식 헤더

 

  • HTTP는 전송 방식에 따라서 사용하는 헤더가 달라집니다.




단순 전송

 

  • Content-Length만을 이용하여 단순한 메시지 body에 대한 크기를 기재합니다.




압축 전송

 

  • Content-Encoding 헤더를 통해 압축 방식을 지정하여 압축 후에 송신하며, Content-Length를 같이 지정합니다.




분할 전송

 

  • Transfer-Encoding 헤더를 통해서 메시지 바디를 분할하여 전송할 수 있습니다.

 

  • Transfer-Encoding은 분할된 바디에 메시지 길이가 기재되기 때문에 Content-Length는 사용하지 않습니다.




범위 전송

 

  • Content-Range를 이용해서 수신받을 리소스의 범위를 지정하여 요청할 수 있습니다. 즉, 이미지를 절반만 수신받은 후 연결이 끊겼을 때 처음부터 다시 받는 것으로 요청하는 것이 아닌 절반 이후 범위를 요청할 수 있습니다.




일반 정보 헤더

 

From

 

  • 유저 에이전트의 이메일 정보를 담아서 요청할 때 사용합니다.




Referer

 

  • 현재 요청된 페이지의 이전 웹 페이지 주소를 기재하여 요청할 때 사용합니다. 해당 정보를 통해서 서비스 제공자는 유입 경로를 분석할 수 있습니다.

 

  • 사실 Referer는 오타이고 Referrer가 맞는데 이미 오타 버전으로 http를 배포가 되었기 때문에 현재는 고칠 수 없는 상황입니다.




User-Agent

 

  • 클라이언트 애플리케이션 정보를 담는 헤더입니다. 서비스 제공자는 브라우저 통계정보를 분석할 때 유용합니다.




Server

 

  • 프록시나 캐시 서버가 아닌 실제로 서비스 제공하는 서버의 소프트웨어 정보를 Server 헤더에 담아서 응답합니다.




Date

 

  • 메시지가 발생한 날짜와 시간을 Date 헤더에 담으며 응답에서만 사용됩니다.




특별한 정보 헤더

 

Host

 

  • 요청한 호스트 도메인 정보를 담는 헤더로서 요청에서 사용됩니다.

 

  • 하나의 서버가 여러개의 도메인을 운영하고 있을 때 서버가 어떤 도메인으로 요청하는 것인지 구별하기 위해 사용합니다.




Location

 

  • 웹 브라우저는 3xx 응답의 결과에 Location 헤더가 있으면, Location 위치로 자동 redirect

 

  • 201( Created )에서도 Location 헤더를 사용할 수 있으며 생성된 리소스의 URI를 뜻합니다.




Allow

 

  • 허용 가능한 HTTP 메서드를 알려줄 때 사용하는 헤더입니다. 주로 405( Method Not Allowed ) status code를 응답하면서 Allow 헤더를 사용합니다.




Retry-After

 

  • 유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간을 알려줄 때 사용합니다. 시간이나 초단위로 알려줄 수 있습니다.




HTTP 인증 헤더

 

Authorization

 

  • 클라이언트 인증 정보를 서버에 전달할 때 사용합니다.




WWW-Authenticate

 

  • 클라이언트가 요청 시 인증에 실패할 경우 응답을 통해 401 status code와 인증 방법 알려줄 때 사용합니다.




HTTP 쿠키 헤더

 

Set-Cookie

 

  • 서버에서 클라이언트로 쿠키 전달(응답)할 때 사용합니다.

 

  • set-cookie시 expires로 만료일 또는 path를 통한 특정 경로에 대해서만 허용할 수 있는등 제약조건을 걸 수 있습니다.

 

  • Secure를 적용하면 https인 경우에만 전송합니다.




Cookie

 

  • 클라이언트가 서버에서 받은 쿠키를 저장하는데, 이 때 저장된 Cookie 데이터를 HTTP 요청시 Cookie 헤더에 담아 서버로 요청할 때 사용합니다.




캐시와 조건부 요청 관련 헤더

 

cache-control

 

  • cache-control 헤더에 max-age를 적용하면 지정된 시간만큼 브라우저 캐시에 저장되어 네트워크를 통한 요청을 하지 않고 클라이언트는 브라우저 캐시에 저장된 데이터를 사용합니다.

 

  • cache-control 헤더에 no-cache를 적용하면 항시 원(original) 서버에 데이터가 변경되었는지를 확인하여 브라우저 캐시를 사용하라는 응답을 할 때 사용합니다.

 

  • cache-control 헤더에 no-store를 적용하면 데이터에 민감한 정보가 있으므로 저장하지 말고 사용 후 최대한 빨리 삭제하라는 응답을 할 때 사용합니다. 즉, no-store는 해당 응답 데이터에 대한 캐시 기능을 완전히 비활성화 시키는 것을 말하빈다.

 

  • cache-control 헤더에 public을 적용하면 캐시 서버에 저장되어도 되는 데이터를 응답할 때 지정합니다.

 

  • cache-control 헤더에 private을 적용하면 캐시 서버에 저장되면 안 되는 데이터를 응답할 때 지정합니다. ( 특히 사용자 정보 ) 즉, private 지시자를 포함한 응답은 해당 사용자의 브라우저에만 캐시될 수 있으며, 다른 사용자의 브라우저 또는 캐시 서버에는 캐시되지 않습니다.

 

  • cache-control 헤더에 s-maxage를 적용하면 프록시 캐시에 저장되는 리소스의 만료시간을 지정할 수 있습니다.

 

  • cache-control의 no-cache 같은 경우는 프록시 서버와 원서버가 연결이 끊겼을 때 프록시 서버가 가지고 있는 과거 데이터를 응답하는 반면에 cache-control 헤더에 must-revalidate를 적용하면 프록시 서버와 원 서버의 통신이 끊겼을 때 프록시 서버는 504( Gateway Timeout ) status code를 응답합니다.




Last-Modified & If-Modified-Since

 

  • Last-Modified 헤더에는 서버에서 클라이언트로 응답할 때 리소스의 마지막 수정일을 지정하여 응답합니다.

 

  • If-Modified-Since 헤더는 클라이언트에서 서버로 리소스를 다시 요청할 때 캐시에 저장되었던 응답받은 리소스의 마지막 수정일을 기재하여 요청합니다.

 

  • 서버가 If-Modified-Since 헤더를 통해서 리소스가 수정되지 않았음을 확인하였다면 리소스를 재전송하지 않고 304( Not Modified ) status code로 message body를 생략하여 응답합니다. 이를 통해 클라이언트는 캐시에 저장된 리소스를 재사용할 수 있으며, 네트워크 트래픽량을 줄일 수 있습니다.

 

  • If-Modified-Since를 요청받은 서버는 날짜만을 가지고 컨텐츠의 수정 여부를 판단하기 때문에 만약, A->B 다시 B->A 로 컨텐츠가 수정되었다면 결론적으로 컨텐츠는 수정되지 않았지만 서버는 컨텐츠가 수정된 것으로 판단한다는 단점이 있습니다.




ETag & If-None-Match

 

  • ETag는 서버가 캐시가 가능한 리소스에 고유한 버전 또는 해시값을 설정할 수 있습니다.

 

  • 클라이언트는 If-None-Match를 통해서 응답받았던 리소스에 대한 ETag 값을 담아 요청합니다. 그리고 서버는 If-None-Match 헤더를 확인하여 ETag를 비교하고 컨텐츠가 수정되지 않았다면 304( Not Modified ) status code와 메시지 body를 생략한 패킷을 응답합니다.

 

  • ETag & If-None-Match는 서버에서 관리되는 리소스 버전을 사용하기 때문에 클라이언트는 서버의 캐시 메커니즘을 파악할 수 없다는 장점이 있습니다.




HTTP 상태 코드란?

 

  • 클라이언트가 보낸 요청의 처리 결과에 대한 상태를 응답에서 알려주는 기능입니다.




상태 코드 종류

 

  • 1xx( Information ) : 요청이 수신되어 처리중( 1xx는 잘 사용되지 않음 )

 

  • 2xx( Successful ) : 요청 정상 처리

 

  • 3xx( Redirection ) : 요청을 완료하려면 추가 행동이 필요

 

  • 4xx( Client Error ) : 클라이언트 오류, 잘못된 문법등으로 서버가 요청을 수행할 수 없음

 

  • 5xx( Server Error ) : 서버 오류, 서버가 정상 요청을 처리하지 못함




2xx( Successful )

 

201 Created

 

  • 클라이언트 요청에 리소스를 생성하였을 경우 헤더에 Location 필드를 추가하여 리소스에 대한 경로를 추가할 수 있습니다.




3xx( Redirection )

 

  • 웹 브라우저는 3xx 응답의 결과에 Location 헤더가 있으면, Location 위치로 redirect 합니다. 주로 302 status code를 사용합니다.




304 Not Modefied

 

  • 브라우저에 캐시된 데이터를 사용하기 위해 사용합니다. 즉, 클라이언트가 요청했는데 리소스가 수정되지 않았음을 알려줌으로써 클라이언트가 로컬 PC에 저장된 캐시를 재사용합니다.

 

  • GET, HEAD 요청시에 사용하며 304 응답은 로컬 캐시를 사용해야 하므로 응답에 메시지 바디를 포함하면 안 됩니다.




+ Recent posts