본문 바로가기
CS/컴퓨터 네트워크

[Network] CH1. 웹 브라우저가 메시지를 만든다

by persi0815 2025. 1. 6.
성공과 실패를 결정하는 1%의 네트워크 원리를 읽고 정리한 내용입니다. 

 

목차

  1. HTTP 리퀘스트 메시지를 작성한다.
  2. 웹 서버의 IP 주소를 DNS 서버에 조회한다.
  3. 전 세계의 DNS 서버가 연대한다.
  4. 프로토콜 스택에 메시지 송신을 의뢰한다.

 

1️⃣ HTTP 리퀘스트 메시지를 작성한다.

사용자가 브라우저에 URL을 입력하면 브라우저가 URL을 해독한다.

브라우저: 웹 서버에 액세스, 파일을 다운로드/업로드, 메일의 클라이언트 등 기능을 가지고 있다.
즉, 몇개의 클라이언트 기능을 겸비한 복합적인 클라이언트 소프트웨어이다.
→ 어느 것을 사용하여 데이터에 액세스하면 좋은지 판단해야 한다.

 

URL의 맨 앞에는 항상 액세스 대상에 따른 프로토콜을 명시해줘야 한다.

  • 프로토콜이란 데이터 출처에 액세스 하는 방법을 의미한다.
  • 액세스 대상이 웹 서버라면 HTTP 프로토콜을 사용하여 액세스 하는 것이다.
HTTP(HyperTest Transfer Protocol) 프로토콜로 웹 서버에 액세스 하는 경우
http: + // + (웹 서버명) + / + (디렉토리 명) + / + .. + (파일 명)  * 디렉토리 명과 파일명은 생략 가능하다
위와 같은 형식을 사용한다. 

 

액세스 대상에 따라 URL을 사용하는 방식이 다르다.

  • 웹서버나 FTP 서버에 액세스 할때는 도메인 명이나 파일의 경로명을 포함시킨다.
  • 메일 서버의 경우에는 보내는 상대의 메일 주소를 URL에 포함시킨다.

즉 이렇듯, 액세스 대상에 따라 프로토콜과 URL에 들어가는 요소들과 형식이 다르다.

 

브라우저는 받은 URL을 해독하여 웹 서버에 보내는 리퀘스트 메시지를 작성한다.

 

[전체 흐름]

 

액세스 대상에 따라 정해진 URL 형식에서 각 요소들을 분리하며 URL을 해독하는데, 해당 과정에서 액세스 하는 정확한 대상(서버, 파일명 등)이 판명된다.

이후, 브러우저는 프로토콜(액세스 방법)을 사용하여 리퀘스트 메시지를 가지고 해당 서버에 액세스한다.

 

리퀘스트 메시지 안에는 ‘무엇(URI = 액세스 대상)’을 ‘어떻게 해서(메소드)’ 하겠다는 내용이 들어 있다.

  • http 1.1 메서드: get, post, head, options, put, put, delete, trace, connect
리퀘스트 메시지
<메소드> <URL> <HTTP_버전> // 리퀘스트 라인 -> 리퀘스트의 대략적인 내용 알 수 있음
<필드명>:<필드값>  // 메시지 헤더 시작
<필드명>:<필드값>  -> 한개의 헤더 필드를 통해 리퀘스트의 부가적 정보 나타냄. 정말 다양한 종류의 헤더 존재. 
			   // 메시지 헤더 종료 -> 공백 행까지가 메시지 헤더가 됨
<메시지_본문> -> 클라이언트에서 서버에 송신하는 데이터​

 

리퀘스트 메시지가 웹 서버에 도착하면, 웹 서버는 안에 쓰여있는 내용을 해독한 후, URL와 메소드를 판단, 요구에 따라 동작하고, 결과 데이터를 응답 메시지에 저장한다.

 

응답 메시지에는 실행 결과가 성공했는지 실패했는지에 대한 status code가 쓰여있다.

응답 메시지
<HTTP 버전> <스테이터스_코드> <응답_문구> -> 코드(숫자)는 컴퓨터, 문구는 사람에게 결과를 알리는 용도
<필드명>:<필드값>  // 메시지 헤더 시작
<필드명>:<필드값>
			   // 메시지 헤더 종료
<메시지_본문> -> 서버에서 클라이언트에 송신하는 데이터로, 바이너리 데이터로 취급​

 

응답 메시지는 클라이언트에게 반송되고, 브라우저가 메시지 안에서 데이터를 추출하여 화면에 표시한다.

  • 페이지에 문장 외에 <img>나 <video>와 같은 이미지나 영상 태그가 포함된 경우, 태그 정보를 처리하지 않고 공백으로 남겨둔 채, 모든 문장을 먼저 출력한다. 이후 각 태그에 대해 별도로 웹 서버에 접근하여 데이터를 가져오도록 동작한다. 이는 리퀘스트 메시지에 쓰는 URI는 한 개만으로 결정되어 있기 때문이다.
    • 이처럼 파일을 한 번에 한 개씩만 읽을 수 있기에 여러개의 파일을 읽기 위해서는 파일 개수 + 1(문장 파일) 개의 리퀘스트 메시지를 서버에 보내야 한다. 서버는 여러개의 리퀘스트가 한개의 페이지를 구성하는지 아닌지 전혀 쓰지 않는다. 그저 한개의 리퀘스트에 대해 한개의 응답만 돌려보낸다.

 

2️⃣ 웹 서버의 IP 주소를 DNS 서버에 조회한다.

브라우저는 메시지를 네트워크에 송출하는 기능은 없기에 메시지를 만든 후, OS에 의뢰하여 액세스 대상의 웹 서버에게 송신한다.

 

OS에 송신 의뢰시 도메인 명이 아닌 IP 주소로 메시지를 받을 상대를 지정해야 하기 때문에,

URL 안에 쓰여있는 서버의 도메인명(www.naver.com)에서 IP주소를 조사한다.

이후, IP주소를 가지고 OS가 네트워크 송신을 처리하여 목적지까지 요청을 배달한다.

 

TCP/IP
서브넷이라는 작은 네트워크들은 라우터들로 이어져 전체 네트워크를 이룬다.
서브넷은 허브에 몇 대의 PC가 접속된 것이라고 생각해도 된다.

IP 주소는 네트워크 번호와 호스트 번호가 합쳐져 구성되는데, 이에 따라 액세스 대상의 위치를 파악하고 서버까지 운반을 하게 된다.
우선, 송신측이 속한 서브넷 안에 있는 허브(L2 스위치)가 운반을 하고, 송신측에서 가장 가까운 라우터(first hop router)로 이동시킨다. 이후, 해당 라우터는 다음 라우터를 판단하고, 그곳으로 보내도록 지시하면 서브넷 안의 허브가 지정된 다음 라우터까지 메시지를 보낸다. 해당 과정을 반복하며 최종 목적지에 도착하게 된다.

 

IP 주소는 32비트의 디지털 데이터로, 8비트(1바이트)씩 점으로 구분하여 10진수로 표기한다. 위에서 말했듯, 네트워크를 식별하는 네트워크 번호와 호스트를 식별하는 호스트 번호가 합쳐져 구성이 되는데, 두개의 요소를 구분하는 데에 있어서 Netmask 라는 정보를 ip 주소에 덧붙인다.

  • 넷마스크의 크기가 클수록 네트워크의 수는 증가하지만, 각 네트워크에 할당할 수 있는 호스트의 수는 줄어든다. 이는 호스트 주소의 경우의 수가 감소하기 때문이다.

예를 들어 Netmask가 /24라면, ip는 10.1.2.3/24 라고 표기가 되며, 아래 사진과 같이 Netmask가 1인 부분을 따져보면 네트워크 번호가 나오고, 나머지 부분을 따져보면 호스트 번호를 도출해낼 수 있다.

 

호스트 부분 부분의 비트가 모두 0인 경우는 서브넷 자체를 나타내고,

호스트 부분 부분의 비트가 모두 1인 경우는 서브넷에 있는 기기 전체에 패킷을 보내는 브로드캐스트를 나타낸다.

 

[URL에 도메인 명이 아닌 IP를 입력한다면?]

브라우저는 OS에 IP 주소를 전달해 네트워크 송신 요청을 한다. 따라서 URL에 도메인명이 아닌 IP 주소를 직접 입력해도 올바르게 작동한다. 그러나 사람이 IP 주소를 기억하거나 이해하기 어려운 반면, 도메인명은 직관적이고 가시성이 높아 널리 사용된다. 쉽게 말해, IP 주소는 고유하거나 특정 로직에 따라 할당될 수 있는데, 그렇게 할당된 IP에 이를 식별하기 쉽도록 도메인명이라는 별칭을 붙일 수 있다. (예: AWS의 Route53)

 

[OS가 도메인명을 가지고 송신 요청하면 어떨까?]

반대로, OS가 도메인명을 직접 사용해 송신 요청을 하면 어떨까? 생각이 들지만, 문제가 발생한다. 도메인명은 수십 바이트에서 최대 255바이트에 이르는 문자열을 사용하기 때문에 IP 주소(4바이트)보다 훨씬 크기가 크다. 이렇게 크기가 커지면 라우터에 부하가 증가하고, 데이터를 운반하는 과정에서 더 많은 시간이 소요되어 네트워크 성능이 저하된다.

 

결국, URL에서는 사용자 편의를 위해 도메인명을 사용하고, 라우터는 네트워크 효율성을 위해 IP 주소를 사용하는 것이 표준화되었다. 도메인명과 IP 주소 간의 매핑DNS(Domain Name System)을 통해 해결할 수 있다.

 

다시 돌아와서, 도메인 명을 가지고 IP 주소를 찾아내려면 가장 가까운 DNS 서버에 특정 도메인명에 해당하는 IP를 요청하면 된다.

 

그렇다면, 브라우저는 어떻게 DNS 서버를 조회할 수 있을까?

DNS 서버를 조회한다는 말은 DNS 서버에게 조회 메시지(요청)을 보내고, 거기서 반송되는 응답 메시지를 받는 것이다. 즉, DNS 서버에 대한 클라이언트로 동작한다고 말할 수 있다. 이러한 DNS 서버에 대한 클라이언트에 해당하는 것을 (DNS) 리졸버라고 한다. 리졸버는 Socket 라이브러리에 들어있는 부품화한 프로그램이며, DNS의 원리를 사용하여 IP를 조사하는 name resolution을 실행한다.

 

리졸버의 프로그램명과 웹 서버의 이름을 쓰기만 하면 브라우저가 리졸버를 호출할 수 있는데, 이렇게 되면 제어가 브라우저에서 리졸버의 내부로 넘어간다. 제어권을 잃은 브라우저는 동작이 일시적으로 정지하고, 제어권을 얻은 리졸버는 HTTP 리퀘스트 메시지 만드는 것과 유사하게 조회 메시지를 만든다. 이후, (데이터를 송수신 하는 기능이 없는) 리졸버가 OS 내부에 포함된 프로토콜 스택을 호출, 송신을 의뢰하여 DNS 서버에 조회 메시지를 보내고나면, 액세스 대상의 웹 서버가 dns 서버에 등록되어 있으면 DNS 서버에서 클라이언트로 응답 메시지가 돌아온다. 응답 속에는 IP 주소가 포함되어있고, 프로토콜 스택을 경유한 리졸버는 IP를 추출해 브라우저에서 지정한 메모리 영역에 써넣게 된다. 그러면 이제 브라우저는 메모리 영역에서 IP를 추출해 OS에게 HTTP 리퀘스트 메시지와 함께 전해주며 송신을 의뢰하게 된다.

 

리졸버가 DNS 서버에 메시지를 송신할 때도 DNS 서버의 IP주소가 필요한데, DNS의 IP 주소는 컴퓨터에 미리 설정되어 있으므로 조사할 필요는 없다.

 

3️⃣ 전세계의 DNS 서버가 연대한다.

리졸버가 만들어 프로토콜 스택이 송신하는 리퀘스트 메시지에는 이름, 클래스, 타입 정보가 포함되어 있다.

 

이름은, 서버나 메일 배송 목적지와 같은 이름이다.

클래스는 과거 인터넷 이외에도 네트워크의 이용까지 검토하여 이를 식별하기 위한 정보인데, 현재는 인터넷 이외의 네트워크의 이용은 소멸되었으므로 클래스는 항상 인터넷을 나타내는 값이 들어간다.

 

타입은 어떤 종류의 정보가 지원되는지를 나타내는데, 해당 타입에 따라 클라이언트에 회답하는 정보의 내용이 달라진다. → 다양한 정보를 취급할 수 있다

  • CNAME(Canonical Name): 하나의 도메인 이름에 별칭(닉네임)을 붙이는 데 사용된다. 예를 들어, www.example.com이 example.com을 가리키도록 설정하면, CNAME 레코드를 통해 하나의 IP 주소에 여러 이름을 매핑할 수 있다.
  • NS(Name Server): 도메인을 관리하는 DNS 서버의 IP 주소를 등록한다. 이 레코드는 특정 도메인에 대한 요청을 처리할 책임이 있는 네임 서버를 지정한다.
  • SOA(Start of Authority): 도메인과 관련된 기본 정보를 제공한다. 여기에는 도메인의 관리자 이메일, 데이터의 갱신 주기, 만료 시간 등 도메인 속성에 대한 정보가 포함된다.
  • A(Address): 도메인 이름을 IPv4 주소로 변환하는 데 사용된다. 예를 들어, example.com이 192.0.2.1이라는 IP 주소를 가리키는 경우 A 레코드를 사용한다.

DNS 서버는 이 세가지 정보에 대응하여 클라이언트에 회답하는 항목을 등록해 두었다. 등록 내용에서 조회 메시지에 해당하는 것을 찾아 클라이언트에게 회답하게 된다.

 

이처럼 DNS 서버는 서버에 등록된 도메인명과 IP 주소의 대응표를 조사하여 IP주소를 회답한다.

 

이전에 조회 메시지를 받은 DNS 서버에 이름과 IP주소가 등록되어있는 경우를 가정하고 설명했는데, 인터넷에는 막대한 수의 서버가 있으니, 이러한 모든 정보를 한대의 DNS 서버에 등록할 수 없다. 그래서 조회 메시지를 받은 DNS 서버에 필요한 정보가 등록되어있지 않은 경우가 생긴다.

DNS 서버에 정보가 등록되어있지 않다면? 어떻게 정보를 찾아서 응답해줄까?

정답은 ‘정보를 분산시켜서 다수의 DNS 서버에 등록하고, 다수의 DNS 서버가 연대하여 정보가 저장된 위치를 찾아낸다’이다.

 

DNS 서버에 저장되는 도메인은 계층적 구조를 가진다. www.naver.com 같은 경우에 이름이 점으로 구분되어있는데, 해당 점이 계층을 구분한다. www 서버 위에 naver 도메인 위에 com 도메인이 있는 것이다. 이렇게 계층화된 도메인의 정보를 서버에 등록하는데, 한 개의 도메인 정보는 일괄적으로 한개의 DNS 서버에 등록하게 된다. 그리고, 한대의 DNS 서버에는 복수 도메인의 정보를 등록할 수 있다. 다만, 우선 쉬운 이해를 위해 한대의 DNS 서버에 하나의 도메인 정보를 등록할 수 있다고 가정하겠다.

 

각 도메인의 정보는 해당 도메인이 있는 DNS 서버에 등록이 된다. 그런데 도메인이 점차 커지게 되어 하나의 도메인 정보가 하나의 DNS 서버에 미처 다 저장이 되지 않는다면, 하위 도메인을 만들어, DNS 서버를 도메인별로 분리할 수 있다. 사실, 우리가 사용하고 있는 거의 모든 도메인이 여러 뎁스의 하위 도메인으로 이루어져있다.

ex) https://persi.site → https://wish.persi.site

 

그러면, 이제 액세스 대상의 웹 서버가 어느 DNS 서버에 등록되어 있는지 찾아내는 방법에 대해 알아보자.

 

하위의 도메인을 담당하는 DNS 서버의 IP 주소를 상위의 DNS 서버에 등록한다. 그리고, 상위의 DNS 서버를 또 그 상위의 DNS 서버에 등록하는 식으로 차례대로 등록을 하다보면, 상위의 서버에 가면 하위의 모든 DNS 서버의 IP 주소를 알 수 있고, 거기에서 조회 메시지를 보낼 수 있다.

 

최상위의 도메인은 루트 도메인이라고 하는데, 루트 도메인에는 이름이 없어서 보통 생략하지만, 명시적으로 사용해야 할 경우에는, 경로 끝에 마치표를 찍어서 루트 도메인을 나타낸다. 루트 도메인 DNS 서버에 com 혹은 net 혹은 site 등의 하위 도메인을 등록하여 루트 도메인에서 차례로 아래쪽으로 거슬러 내려갈 수 있다.

 

또한, 루트 도메인의 DNS 서버를 인터넷에 존재하는 DNS 서버에 전부 등록해야 한다. 그러면 어느 DNS 서버든 루트 도메인에 접근할 수 있게 되고, 어딘가의 DNS 서버에서 다른 DNS 서버에 액세스 할 때 루트 도메인을 경유한 후, 하위 도메인으로 이동해서 최종적으로 원하는 DNS 서버에 도착하게 된다.

 

루트 도메이인의 DNS 서버에 할당된 IP 주소는 전 세계에 13개 밖에 없고, 잘 변경되지 않으므로 등록하는 과정은 간편하다. 실제로 루트 도메인의 DNS 서버에대 한 정보는 DNS 서버 소프트웨어와 함께 설정 파일로 배포되어 소프트웨어를 설치하면 자동으로 등록이 완료된다고 한다.

 

클라이언트와 가장 가까운 DNS 서버는 도메인에 맞는 서버로 가기 위해 여러 DNS 서버들에게 순차적으로 조회 메시지를 보내게 되는데, 각 DNS 서버들은 다음 DNS 서버의 IP을 알려주고, 가장 가까운 DNS 서버는 응답받은 DNS 서버의 IP에게 또다시 요청을 하게 된다. 해당 과정을 반복하다 원하는 DNS 서버에 도착하게 되고, 가장 가까운 DNS 서버는 원하는 도메인에 해당하는 서버의 IP를 받게 되고, DNS 서버는 클라이언트로 IP가 담긴 응답 메시지를 보내게 되는 것이다. 프로토콜 스택을 경유한 리졸버는 IP를 추출해 브라우저에서 지정한 메모리 영역에 써넣게 된다. 이러써 클라이언트(브라우저)는 웹 서버의 IP주소를 알고, OS를 통해 서버에게 네트워크 송수신을 요청할 수 있게 된다.

 

설명은 하나의 DNS 서버에 하나의 도메인에 대한 정보만 저장하고 있다고 나와있는데, 사실은 여러 도메인에 대한 정보를 담을 수 있으므로, 상위와 하위의 도메인이 같은 DNS 서버에 등록하는 경우가 있다. 이 경우에 상위의 DNS 서버를(에서) 조회할 때 하위 DNS 서버를 한개 건너뛰고, 다시 그 하위의 DNS 서버에 관한 정보가 돌아오게 된다.

 

또한, 캐시를 사용하면 취상위 루트 도메인에서 차례대로 따라간다는 원칙대로 움직이지 않을 수 있다. DNS 서버는 한 번 조사한 이름을 캐시에 기록할 수 있는데, 조회한 이름에 해당하는 정보가 캐시에 있으면 해당 정보를 회답하게 되어 속도가 더 빨라진다. 조회한 이름이 도메인에 등록되지 않았다는 정보 또한 캐시에 보존할 수 있다. 다만, 캐시에 정보를 저장 후, 등록 정보가 변경된다면 잘못된 정보를 반환할 수 있기에 DNS 서버에 등록되는 정보에는 유효기한을 설정하고, 캐시에 저장한 데이터의 유효 기간이 지나면 캐시에서 삭제하면 된다. 또한, 조회에 회답할 때 정보다 캐시에 저장된 것인지, 아니면 등록처 DNS 서버에서 회답한 것인지 알려준다.

 

캐시 관련 경험

  • KOPIS의 대규모 데이터 반환 API를 요청할 때, 스웨거(브라우저 기반 환경)에서 504 Gateway Timeout 오류가 발생하는 문제가 있었다. 이 오류는 서버에서 대규모 데이터를 처리하는 데 시간이 오래 걸려 응답이 정해진 시간 내에 반환되지 못했기 때문이었다. 이후 API를 반복적으로 호출했지만, 캐시에 저장된 값이나 요청 처리 지연으로 인해 동일한 504 오류가 계속 반환되었다.
  • HTTP에서는 서버가 반환하는 리소스의 마지막 수정 날짜와 시간을 Last-Modified 헤더에 저장한다. 이후, 클라이언트가 해당 리소스를 요청할 때 서버는 리소스가 변경되지 않았을 경우 304 Not Modified 응답을 반환한다.

 

4️⃣ 프로토콜 스택에 메시지 송신을 의뢰한다.

위에서 언급했던 것 처럼, IP 주소를 조사했다면, 액세스 대상 웹 서버에 메시지를 송신하도록 OS의 내부에 있는 프로토콜 스택에 의뢰한다.

OS 내부의 프로토콜 스택에 메시지 송신 동작을 의뢰할 때는 Socket 라이브러리 프로그램 부품을 결정된 순번대로 호출한다.

아래는 메시지 송수진 동작의 이미인데, 파이프 같은 통로를 통해 데이터가 흐르면서 상대측에 도착하게 된다. 어느쪽에서 쏟아부어도 상관없고, 양방향으로 데이터를 흘릴 수 있다. 해당 파이프는 송수진 동작 전 데이터 송수신을 하는 양자 사이를 파이프로 연결하는 동작이 필요하다.

 

파이프 양끝의 데이터 출입구를 소켓이라고 부르는데, 서버에서 해당 소켓을 만들고(1. 소켓 생성) 클라이언트가 파이프를 연결하기를 기다려야 한다. 서버가 기다리는 동안 클라이언트는 자신도 소켓을 만들고, 소켓에서 파이프를 늘려 서버측의 소켓에 연결(2. 접속)한다. 이로써 양쪽의 소켓이 연결되면 준비가 완료된 것이고, 소켓에 데이터를 쏟아부으면 반대편으로 데이터가 전송이 된다.(3. 데이터 송수신)

해당 과정들은 애플리케이션 자체가 하는 것이 아니라 프로토콜 스택에 의뢰해서 진행된다. 의뢰 동작은 소켓 라이브러리에 넣은 프로그램 부품을 호출하여 실행된다.!!!

 

송수신이 끝나면 파이프가 분리가 되는데, 어느측에서 먼저 분리를 하든 상관이 없고, 한쪽에서 분리하면 다른 한쪽도 분리가 된다. 이후 소켓을 말소하여 통신 동작이 종료가 된다. (4. 연결 끊기)

 

전 과정은 각각 Socket 라이브러리의 socket(), connect(), write(), read(), close() 통해 진행된다.

 

1) 소켓의 작성 단계 - socket()

클라이언트측의 소켓을 만들때는 소켓 라이브러리의 socket라는 프로그램 부품만 호출하면 된다. 그러면 제어권이 socket 내부로 넘어가서 (복잡한 과정을 통해….) 소켓을 만들게 되고, 해당 과정이 끝나면 다시 애플리케이션에게 제어권이 돌아온다.

 

소켓이 생기면 디스크립터라는 것이 돌아오고, 애플리케이션은 이를 메모리에 기록해둔다.

  • 디스크립터: 서버안에서 소켓을 식별하기 위해 사용하는 번호표 같은 것으로, 한 대의 컴퓨터에 복수의 소켓이 존재할 수 있다.

디스크립터를 사용하여 접속 동작이나 데이터 송수신 동작을 실행하게 되는데, 디스크립터를 보여주면 프로토콜 스택이 어느 소켓을 사용하여 접속할지 또는 데이터를 송수신할지 판단할 수 있다.

 

2) 파이프를 연결하는 접속 단계 - connect()

클라이언트가 만든 소켓을 서버측의 소켓에 접속하도록 프로토콜 스택에 의뢰한다.

connect()에 디스크립터, 서버의 ip 주소, 포트 번호를 지정한 후 호출한다.

  • 프로토콜 스택은 통지받은 디스크립터를 보고 애플리케이션 내에서 어느 소켓을 서버측의 소켓에 접속할지 판단하여 접속 동작을 실행한다.
    • 디스크립터는 컴퓨터 한 대의 내부에서 소켓을 식별하기 위해 필요한 것이다.
  • ip는 네트워크에 존재하는 각 컴퓨터를 식별하기 위해 각각에 서로 다른 값을 할당한 것이라, ip 주소로는 소켓까지 지정할 수 없다. 이때 ip 주소와 함께 포트번호를 사용하여 어느 컴퓨터의 어느 소켓과 접속할지 지정할 수 있다.
    • 포트번호는 접속 상대측에서 소켓을 식별하기 위해 사용한다.
  • 클라이언트측에서 서버측의 디스크립터를 사용하여 서버측의 소켓을 지정할 수 없다. 그래서 클라이언트 측에 알리는 중간 과정이 필요한데, 이 과정을 포트 번호가 하는 것이다. 즉, 포트번호를 가지고 클라이언트는 서버의 애플리케이션 소켓에 접속 요청을 할 수 있게 된 것이다.
    • 서버는 포트 번호 통해 요청을 수신한 뒤, 내부적으로 디스크립터를 생성하여 각 클라이언트와의 연결을 관리한다.

 

  • 서버측의 포트 번호는 애플리케이션의 종류에 따라 미리 결정된 값을 사용한다. 예를 들면 웹은 80번, 메일은 25번(destination port)을 사용한다. 이렇게 미리 결정된 포트번호를 지정하면 번호에 대응하는 서버 애플리케이션의 소켓에 접속할 수 있다.
    • 브라우저 같은 경우에는 ip와 port가 모두 같아도 별개의 요청과 응답을 받을 수 있는데, 그 이유는 클라이언트 측 포트 번호(source port) 때문이다.
    • 동일한 서버(IP와 포트)로 여러 요청을 보내도, 각 요청은 클라이언트의 서로 다른 소스 포트 번호를 사용하므로 서로 다른 연결로 구분된다.
    • 클라이언트측의 소켓 포트 번호는 소켓 만들대 프로토콜 스택이 적당한 값을 골라서 할당한다. 그리고 해당 값을 프로토콜 스택이 접속 동작을 실행할 대 서버측에 통지한다.

connect를 호출하면 프로토콜 스택이 접속 동작을 실행하는데, 상대와 연결되면, 프로토콜 스택은 연결된 상태의 ip 주소나 포트번호 등의 정보를 소켓에 기록하여 송수신이 가능한 상태가 된다!

 

포트번호만 가지고도 서버 안에서 소켓을 구분할 수 있는거 아니야? 디스크립터가 왜 필요해?

  • 포트 번호는 서버 애플리케이션을 식별하는데, 하나의 애플리케이션에 속한 여러 연결을 구분하지 못한다.
  • Source port는 서버가 연결을 구분하는 정보 중 하나일 뿐이며, 추가적인 정보들이 필요하다. 디스크립터는 서버 내부에서 각 연결을 효율적을 관리하기 위한 식별자다.

 

3) 메시지를 주고 받는 송 수신 단계 - write(), read()

[송신 단계]

소켓에서 데이터를 쏟아 부으면 상대측의 소켓에 데이터가 도착한다. 그러면 애플리케이션은 소켓을 직접 다룰 수 있으므로 write()통해 프로토콜 스택에 일을 의뢰한다.

 

애플리케이션은 송신 데이터(URL을 바탕으로 만든 리퀘스트 메시지)를 메모리에 준비하고, write를 호출할 때 디스크립터와 송신데이터를 지정한다.

→ 프로토콜 스택이 송신 데이터를 서버에게 송신한다.

  • 소켓에는 연결된 상태가 기록되어 있어 디스크립터로 소켓을 지정하면 상대가 판명된다.

→ 서버는 수신한 후, 내용 조사하고 처리 후 응답 메시지를 반송한다.

 

[수신 단계]

read()를 통해 프로토콜 스택에 수신을 의뢰하는데, 수신한 응답 메시지를 저장하기 위해 애플리케이션의 메모리 영역(수신 버퍼)을 지정한다.

→ 응답 메시지가 돌아올때 read가 받아서 수신 버퍼에 저장

→ 수신 버퍼에 저장한 시점에서 메시지를 애플리케이션에 건네주게 된다.

 

4) 연결 끊기 단계 - close()

송수신이 끝나고 close()라는 프로그램 부품을 호출하여 연결 끊기 단계로 들어가도록 의뢰한다. 그러면 소켓 사이를 연결한 파이프와 같은 것이 분리되고 소켓도 말소된다.

 

http 프로토콜에서 응답 메시지의 송신을 완료했을때 웹 서버측에서 close를 호출하여 연결을 끊는다. 이것이 클라이언트에게 전달되어 클라이언트도 연결 끊기 단계로 들어간다.

이때 브라우저가 read로 수신 동작을 의뢰하면 read는 데이터를 건네주는 대신, 연결이 끊겼다는 사실을 브라우저에게 통지하고, 브라우저 또한 close를 호출하여 연결 끊기 단계에 들어간다.

 

이처럼 데이터 하나하나를 별도의 것으로 취급하여 1개의 데이터를 읽을 때마다 접속, 리퀘스트 메시지 송신, 응답 메시지 수신, 연결 끊기라는 동작을 반복하는데, 서버에서 복수의 데이터를 읽을 때 비효율적으므로 한번 접속 후 연결 끊지 않고 복수의 리퀘스트와 응답 주고받기를 실행하는 방법도 마련되었다. (HTTP 1.1) 이 경우에는, 리퀘스트할 데이터가 없어진 상태에서 브라우저에서 연결 끊기 동작에 들어갈 수 있다.

 

 

참고자료

https://product.kyobobook.co.kr/detail/S000000559964

 

1%의 네트워크 원리 | Tsutomu Tone - 교보문고

1%의 네트워크 원리 | 성공과 실패를 결정하는 1%의 네트워크 원리 (2nd Edition(개정1판 10쇄))이 책만큼 네트워크의 구조와 작동 원리에 대해 체계적으로 설명한 책은 없다! 이 책은 네트워크 기술을

product.kyobobook.co.kr

 

'CS > 컴퓨터 네트워크' 카테고리의 다른 글

[Network] VM Network Options  (0) 2024.12.30