우아한테크코스 레벨2 에서 매트가 주관한 스터디로, 모든 개발자를 위한 HTTP 웹 기본 지식 스터디를 진행중이다.
이 포스팅에서는 스터디에 PR을 날릴 내용과 함께 스터디 시간에 얻어간 내용을 적을 예정이다.
PR에 적을 내용은 아래와 같다.
- 인프런 강의를 듣고 요약한 내용
- 인프런 강의 QNA를 보고 공부한 내용
- 책/구글링을 통해 추가적으로 공부한 내용
매주 주말에 작성할 예정이며, 월요일에 스터디를 진행하고 추가로 내용을 더 기록할 예정이다.
1. 인터넷 네트워크
우리는 인터넷 네트워크를 통해 수많은 통신을 하고 있다.
당장 모르는 내용이 생겨 구글링을 할 때도, 새로운 맛집을 찾기 위해 네이버 지도를 킬 때에도 우리는 항상 네트워크를 연결하여 요청을 보내고 응답을 받고 있다.
이번 시간에는 네트워크 통신이 어떠한 과정으로 이루어져 있는지 간단하게 알아볼 것이다.
클라이언트에서 Hello, world! 내용을 서버에게 전달하려 한다.
여기서 클라이언트/서버의 의미는 front-end, back-end의 의미가 아니다.
여기선 요청을 보내는 주체를 클라이언트, 응답을 보내주는 주체를 서버로 지칭한다.
클라이언트에서 Hello, world! 를 서버에게 보내기 위해 인터넷의 노드들은 서버에게 도착 가능한 노드들을 찾아 서로 통신하여 서버에게 Hello, world!를 넘겨준다. 이제 서버에서도 클라이언트에게 정상적으로 도착했다는 것을 알려주기 위해 전 과정과 동일하게 패킷을 보내준다. 이렇게 통신을 해주기 위해선 인터넷의 약속, 즉 프로토콜이 존재해야 한다.
프로토콜
통신을 하기 위한 일종의 약속이다. Internet Protocol을 줄여 IP라고도 부른다.
Hello, world!를 전송하기 위해선 전송 데이터 뿐만 아니라 출발지 IP, 도착지 IP, 기타 내용들도 함께 패킷에 담겨있어야 요청/응답이 가능하다. 그래야 요청 주체, 응답 주체를 확인할 수 있기 때문이다.
그런데 우리는 주소창을 칠 때, kth990303.tistory.com 과 같이 도메인 주소를 치지, 포트 번호를 일일이 치지 않는다. 어떻게 컴퓨터는 도착지 IP를 알아내어 응답을 보내주는 것일까?
이는 사용자가 입력한 도메인 값(kth990303.tistory.com)을 브라우저에서 `도메인 네임 서버(DNS)`에서 포트 번호를 찾아주기 때문에 가능한 것이다. 네임 서버는 도메인과 포트번호를 매핑한 테이블을 제공해주는 서버이기 때문이다. 이 도메인 네임 서버에서 포트 번호를 찾아 목적지로 패킷을 전송하는 것이다.
IP 프로토콜만의 한계
그러나 IP 프로토콜만의 통신은 한계가 존재한다. 바로 비연결성, 비신뢰성, 프로그램 구분 부분에서 발생한다.
비연결성이란, 패킷을 받을 대상이 없거나 서비스 불능 상태일 때에도 패킷을 전송한다는 점이다.
비신뢰성이란, 중간에 패킷이 사라지거나 패킷이 순서대로 오지 않는 경우를 의미한다. 이는 데이터를 일정 묶음으로 나눈 단위가 패킷이기 때문이다. Hello, world! 를 보낼 때에도 하나의 패킷이 아닌 Hello, 패킷과 world! 패킷과 같이 두 개의 패킷으로 나누어서 보내줄 수 있다. 이 때, Hello, 패킷의 크기가 너무 커서 전송속도가 world! 패킷보다 비교적 느리다면, 클라이언트의 의도와 다르게 서버쪽에선 world! Hello, 와 같은 데이터를 받을 위험이 존재하게 된다. 그 외에 노드 장애, 다중 경로 라우팅으로 인한 패킷 유실 및 지연도착도 가능하다.
(다만, ip header에 존재하는 fragment offset를 통해 수신 측에서 패킷의 순서 재조립, 추가데이터 여부 등은 확인이 가능하다고 하긴 하다.)
프로그램 구분에서 발생하는 한계는, 같은 IP에서 동시에 통신하는 애플리케이션이 존재할 때 발생할 수 있는 한계를 의미한다. 요즘 우리는 유튜브 음악을 틀어놓으면서 인텔리제이로 코딩하기도 하고, 동시에 카카오톡도 실행시켜놓고, 슬랙도 켜놓고, 깃허브도 켜놓고 등등... 동시에 통신하지 않는 경우를 찾기가 더 어려울 정도이다. 이 때 IP 프로토콜만으론 어떻게 이러한 경우를 구분지을지 어려울 수 있다고 한다.
TCP, UDP
이러한 한계를 보완하기 위해 등장한 것이 바로 TCP이다.
인터넷 프로토콜의 4계층인 애플리케이션 계층, 전송 계층(TCP, UDP), 인터넷 계층(IP), 네트워크 인터페이스 계층을 설명해줌과 동시에, TCP 정보를 담아서 어떻게 패킷을 생성하는지 설명해주는 좋은 그림이다.
IP 프로토콜만으로는 한계가 존재했던 부분을, 패킷 내부에 TCP 정보를 담아줌으로써 보완해주는 것을 확인할 수 있다.
TCP는 전송 지향 프로토콜(Transmission Control Protocol)로, 3-way handshake로 연결지향적인 성격을 가져 IP 프로토콜만의 한계였던 비연결성을 보완해준다. 또한, 데이터 전달 보증과 순서 보장을 해주어 비신뢰성 한계도 보완해준다. 이러한 부분들 덕분에 현재는 대부분 TCP를 사용한다고 한다.
1. 클라이언트 -> 서버로 SYN을 보냄.
2. 서버가 클라이언트 요청을 수락함과 동시에, 접속 요청을 함. SYN + ACK (서버 입장에선 서버가 클라이언트, 클라이언트가 서버임.)
3. 클라이언트가 서버의 요청을 수락. ACK
(참고로, tcp의 checksum 필드를 확인하여 손상된 메시지를 받았을 경우 ACK가 아닌 NAK을 보내준다.)
위와 같이 연결이 완료된 이후에야 데이터를 서로 주고받게 된다.
따라서 비신뢰성, 비연결성 문제가 사라지게 된다.
요즘은 최적화로 인해 3번 ACK를 보낼 때 데이터도 같이 보내준다고 한다.
참고로 TCP 흐름 제어 방식으론 Stop and wait(순서가 올바르지 않은 패킷이 오면 stop하고 wait), Sliding Window(수신 측의 수신가능 데이터양을 미리 알음으로써, 응답 패킷의 양을 그에 맞게 보내주는 방법) 방법으로 순서를 보장하고 효율성을 높인다고 한다. TCP 연결을 종료할 때에는 FIN, ACK, FIN, ACK를 주고받는 4-way handshake가 일어난다고 한다.
UDP는 사용자 데이터그램 프로토콜(User Datagram Protocol)로, 데이터 전달 보증이나 순서 보장이 되지 않는다. 기능 또한 IP 프로토콜과 다를 바가 없다. 대신, IP 프로토콜에 PORT 정보와 체크섬(메시지가 제대로 왔는지 검증. hash값과 유사)이 추가돼있다. 그렇기 때문에 신뢰성이 보장돼야 하는 데이터를 보낼 때엔 TCP를, 간단한 데이터를 빠르게 보내고 싶을 때는 UDP를 사용한다. 또한, UDP는 하얀 도화지에 비유되기도 한다. 기능이 단순하고 빠르기 때문에 UDP에 별도의 최적화 및 추가작업을 하여 사용자 입맛에 맞게 사용할 수 있기 때문이다. 이러한 점 덕분에 최근에 UDP가 각광받고 있다고 한다.
PORT
TCP/IP 패킷에는 출발지 및 도착지 IP와 PORT 정보가 존재하여 통신이 가능하다. 그럼 PORT라는 것은 도대체 무엇일까?
위 그림 한장으로 포트에 대한 설명을 바로 끝낼 수 있을 듯하다.
포트는 같은 IP 내에서 프로세스를 구분할 수 있도록 해준다.
예를 들어 웹서버 http의 경우 디폴트 포트번호가 80이고, https의 경우 디폴트 포트번호가 443이다.
실제로 kth990303.tistory.com:80 에 접속하거나 https://kth990303.tistory.com:443 으로 접속하면 잘 접속되나, https://kth990303.tistory.com:80 에 접속하면 잘못된 응답이라며 에러가 발생한다.
localhost:8080, 이 주소 뭔가 익숙하지 않은가? 톰캣같은 WAS 서버들은 보통 8080 포트를 사용하기 때문이다.
이처럼 tcp/ip 패킷에 ip와 포트번호까지 같이 존재하기 때문에 동일 IP에서의 여러 프로세스들 사이에서도 통신이 원활하게 가능하다.
DNS
도메인 네임 시스템(DNS) 덕분에 우리는 IP 주소와 포트번호를 입력해서 통신하지 않고 도메인주소만 입력하면서 통신할 수 있다.
도메인 네임 서버에서 도메인과 IP, PORT를 매핑한 테이블을 제공해주기 때문이다. IP 주소는 기억하기 어렵기도 하고, 일부 변경이 일어날 수 있다는 단점들이 있었는데, 이를 DNS가 보완해준 것이다.
2. URI와 웹 브라우저 요청 흐름
URI
URI(Uniform Resource Identifier)은 말 그대로 리소스를 식별할 수 있는 유니폼을 뜻한다.
근데 URI도 들어본 것 같고, URL도 들어본 듯한데, 둘의 차이점은 무엇일까?
URL은 우리가 흔히 생각하는 도메인 주소 (kth990303.tistory.com/311)이며, URN은 리소스의 이름 (kth990303의 코딩 블로그)이다. 다만, URN만으로는 특정 리소스를 찾는 것이 불가능에 가깝기 때문에 URL, URI라는 개념을 훨씬 많이 사용한다.
URI는 식별의 개념에 가깝고, URL은 주소의 개념에 가깝다. 예를 들어 kth990303.tistory.com/index.html은 명확하게 확장자까지 나타내주는 주소이자, 다른 리소스들 사이에서 명확하게 식별이 가능하므로 URI, URL 둘 다 맞다. 그러나, kth990303.tistory.com/index는 식별은 가능하지만, 명확한 주소는 아니므로 URI는 맞지만 URL은 아니다. 서버에서 별도의 처리를 해주어 자동으로 .html 파일을 보여주긴 하지만, 엄밀히 존재하는 파일은 아니기 때문이다.
URI가 좀 더 상위개념이라고 이해하면 편할 듯하다.
URL 문법
이 포스팅의 URL을 살펴보면서 URL 문법을 익혀보자.
호스트명에는 주로 도메인 주소를 입력한다. 도메인 주소가 아닌 IP값을 입력해도 된다.
https의 기본 포트번호는 443이며, 이는 생략이 가능하다.
그렇기 때문에 우리는 kth990303.tistory.com:443이 아닌 kth990303.tistory.com으로 바로 접속이 가능한 것이다.
패스(path)는 리소스 경로이다. 패스 뒤에 쿼리스트링이 존재할 수도 있다.
웹 브라우저 요청 흐름
클라이언트가 서버에게 특정 리소스를 요청할 때 어떠한 일이 발생하는지 알아보자. 먼저, URI를 입력받으면 DNS로 호스트명을 바탕으로 조회하고, 포트를 확인하며(ex. https: 443) 웹 브라우저에서 HTTP 요청 메시지를 생성한다. HTTP 요청 메시지에는 GET, POST와 같은 HTTP method, URI 등의 정보가 담겨있다. 그 다음으로 SOCKET 라이브러리를 이용하여 커넥션을 TCP/IP로 맺게 하여, OS 계층에서 3-way handshake로 서버와 연결한다. OS의 TCP 계층에 왔으므로 TCP/IP 패킷을 생성해준다. 이제 인터넷으로 요청 패킷을 보낸다. 서버에 요청 패킷이 도착하게 되면 패킷 껍데기는 버리고 HTTP 요청 메시지를 서버에서 해석한다. 마지막으로, 서버에서 응답 패킷을 동일한 방식으로 클라이언트에게 보내주면 우리가 원하는 응답을 얻을 수 있다.
느낀 점
- 애플리케이션 계층, OS 계층, 네트워크 인터페이스 계층을 통해 HTTP 메시지가 전달되는 과정을 조금이나마 알게 되서 만족스럽기도 하지만 조금 어렵기도 하다.
- IP, PORT, URI, URL에 대한 개념을 보다 명확하게 이해할 수 있어서 좋았다.
- DNS를 18학년도 6월 모평 국어 지문에서 봤을 때 무슨 소린지 몰랐는데, 여기서 보니까 보다 잘 이해되는 듯하다. 이 영상을 보고 모평을 봤다면 좋았을텐데 조금 아쉽다 ㅎㅎ
- 실무에서 UDP를 사용할 때, 어떠한 추가적인 최적화 및 작업을 해주는지 궁금하다. 아직 모르는 것, 배울 점들이 산더미인 듯.
- HTTP message, 빨리 배우고 싶다!
출처:
https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC
매트 스터디에서 배운 내용을 기록한 나의 레포지토리
https://github.com/kth990303/2022-http-web-basic-for-all-developer
'CS > Http, Network' 카테고리의 다른 글
[매트 스터디] 5주차 HTTP 헤더2 - 캐시와 조건부 요청 (0) | 2022.06.01 |
---|---|
[매트 스터디] 4주차 HTTP 헤더 1 - 일반 헤더 (0) | 2022.05.22 |
[매트 스터디] 3주차 HTTP 메서드 활용 & HTTP 상태코드 (2) | 2022.05.15 |
[매트 스터디] 2주차 HTTP 기본 & HTTP 메서드 (0) | 2022.05.09 |
[Network] 인터넷 프로토콜 요약본 (0) | 2021.04.25 |