URI는 URL(locator)과 URN(name)으로 분류될 수 있다.
- URL: 리소스가 있는 위치를 지정한다.
- URN: 리소스에 이름을 부여한다.
URL은 리소스의 위치를 나타내며, 그 위치는 변할 수 있다. 반면 URN은 리소스에 대한 고유한 이름을 부여하지만, 리소스를 찾을 수 있는 방법이 보편화되지 않아 실제로 잘 사용되지 않는다.
따라서 URN은 일상적으로 사용되지 않으며, URL이 더 많이 사용된다. 그 결과, 실제로 URI와 URL은 같은 의미로 사용되는 경우가 많다.
URL 분석
https://www.google.com/search?q=coldplay&hl=ko
URL의 전체 문법은 다음과 같다:
scheme://[userinfo@]host[:port][/path][?query][#fragment]
- 프로토콜 (scheme): https
- 호스트명 (host): www.google.com
- 포트 번호 (port): 443 (생략 가능, https는 기본적으로 포트 443 사용)
- 경로 (path): /search
- 쿼리 파라미터 (query): q=hello&hl=ko
추가 정보
- http: 기본 포트는 80
- https: 기본 포트는 443 (보안을 추가한 http)
- userinfo@: 사용자 정보와 인증을 위한 부분이나, 거의 사용되지 않음
- #fragment: HTML 내부 북마크로 사용되며, 서버에 전송되지 않는 정보
개발포트 vs 배포포트
개발 포트와 배포 포트의 차이점은 주로 운영 환경에서의 권한과 보안에 있다. 개발 포트(예: 8080)는 주로 로컬 개발 환경에서 사용되며, 관리자 권한 없이 쉽게 사용할 수 있는 포트이다. 반면, 배포 포트(예: 80, 443)는 운영 서버에서 사용되며, 특권 포트로 지정되어 있어, 이를 사용하기 위해서는 관리자 권한이 필요하다. 또한, 배포 포트는 보통 HTTP(80)와 HTTPS(443) 프로토콜을 처리하며, 보안 인증서와 방화벽 설정이 필수적인 반면, 개발 포트는 보안 설정이 덜 필요하고 빠르게 개발 및 테스트하기 위한 용도로 사용된다.
웹 브라우저 요청 흐름
https://www.google.com/search?q=coldplay&hl=ko
위와 같은 url 접속시 다음과 같은 HTTP 요청 메세지가 생성된다.
GET /search?q=hello&hl=ko HTTP/1.1
Host: www.google.com
- 웹 브라우저가 HTTP 메시지를 생성하고, 이를 Socket 라이브러리를 통해 전달한다.
- 소켓에서 TCP/IP 연결(IP, PORT)을 설정하고 이를 운영체제(OS)로 전달한다.
- 운영체제(OS)에서 TCP/IP 패킷을 생성하고, HTTP 메시지를 포함한 패킷을 만든다. (HTTP에 덧씌워져 전송된다)
- LAN 드라이버와 LAN 장비를 통해 인터넷 망으로 TCP/IP 패킷이 전송된다.
- 서버에 도달한 패킷은 서버에서 처리되며, HTTP 응답 메시지와 함께 2345절차를 포함한 응답 패킷이 서버에서 전송된다.
- 웹 브라우저는 응답 패킷을 수신하고, 이를 처리하여 사용자에게 결과를 표시한다.
이러한 과정을 통해 웹 브라우저가 사용자의 요청을 서버로 보내고, 서버는 그에 대한 응답을 다시 보내는 구조가 이루어진다.
HTTP 요청 과정
-
웹 브라우저가 URL을 입력 받음
- 사용자가 웹 브라우저에 URL을 입력하거나 링크를 클릭하면 웹 브라우저가 HTTP 메시지를 생성한다.
-
HTTP 요청 메시지 생성
- 웹 브라우저는 HTTP 요청 메시지(메서드, URL, HTTP 버전, 헤더, 본문)를 생성하고, DNS 요청을 수행한다.
-
DNS 요청 (도메인 이름 해석)
- 입력된 도메인 이름을 IP 주소로 변환하기 위해 DNS 서버에 질의한다.
- 웹 브라우저는 먼저 로컬 DNS 캐시를 확인하고, 없다면 DNS 서버에 요청을 전송한다.
- DNS 응답을 받아 해당 도메인의 IP 주소를 획득하고, 웹 브라우저가 Socket 라이브러리를 통해 TCP 연결을 요청한다.
-
TCP 연결 설정
- IP 주소와 포트 번호(기본 HTTP 포트 80, HTTPS 포트 443)를 사용하여 TCP 소켓을 생성하고, TCP 연결을 설정한다 (3-way handshake).
- 클라이언트(웹 브라우저)가 서버에 SYN 패킷을 전송하고, 서버는 SYN-ACK 패킷으로 응답한다. 클라이언트는 ACK 패킷을 보내며 논리적 연결이 설정된다.
-
HTTP 요청 전송
- TCP 연결이 설정되면, 웹 브라우저는 HTTP 요청 메시지를 소켓을 통해 서버로 전송한다.
- 운영체제(OS)는 TCP/IP 패킷을 생성하고, HTTP 메시지를 포함시킨다.
-
패킷 전송
- 운영체제의 네트워크 스택이 HTTP 메시지를 TCP 세그먼트로 캡슐화하고, 이를 IP 패킷으로 캡슐화한다.
- LAN 드라이버와 LAN 장비를 통해 인터넷 망으로 패킷을 전송한다.
- IP 패킷은 이더넷 프레임으로 캡슐화되어 로컬 네트워크를 통해 라우터로 전달되며, 라우터를 통해 인터넷으로 전송된다.
서버 응답 과정
-
패킷이 서버에 도착
- 인터넷을 통해 서버에 도달한 패킷은 서버의 네트워크 인터페이스(ex. Spring의 Tomcat)로 전달된다.
- 서버는 TCP/IP 패킷을 분해하여 HTTP 요청 메시지를 추출한다.
- 서버의 네트워크 스택은 IP 패킷을 TCP 세그먼트로, TCP 세그먼트를 HTTP 메시지로 분해한다.
-
웹 서버가 HTTP 요청을 처리
- 웹 서버(예: Apache Tomcat, Nginx)는 HTTP 요청을 받아 처리하고, 요청된 자원을 준비한다.
- 필요한 경우 서버 애플리케이션(예: Spring)이 동작하여 요청을 처리한다.(비즈니스 로직 처리)
- 서버는 HTTP 응답 메시지를 생성한다.
-
HTTP 응답 메시지 생성
- 서버는 HTTP 상태 코드, 헤더, 본문 등을 포함한 HTTP 응답 메시지를 생성한다.
- 생성된 HTTP 응답 메시지는 TCP/IP 패킷으로 캡슐화된다.
-
응답 패킷 전송
- HTTP 응답 메시지는 TCP 세그먼트로, TCP 세그먼트는 IP 패킷으로 캡슐화된다.
- 응답 패킷은 인터넷을 통해 클라이언트로 전송된다.
-
응답 패킷을 클라이언트가 받음
- IP 패킷이 인터넷을 통해 클라이언트(웹 브라우저)로 전송된다.
- 웹 브라우저는 응답 패킷을 받는다.
-
클라이언트 네트워크 인터페이스 처리
- 클라이언트의 네트워크 인터페이스(ex. 이더넷 포트)로 도착한 패킷은 운영체제의 네트워크 스택을 통해 처리된다.
- TCP 세그먼트는 HTTP 메시지로 분해된다.
-
웹 브라우저가 HTTP 응답 메시지 처리
- 웹 브라우저는 HTTP 응답 메시지를 받아 HTML, CSS, JavaScript, 이미지 등을 렌더링하여 사용자에게 출력한다.
추가 고려 사항
HTTPS 연결 시 추가 단계
HTTPS 요청의 경우, TCP 연결 설정 후 SSL/TLS 핸드셰이크가 진행되어 보안 연결이 설정된다. 이 과정에서 클라이언트와 서버는 대칭 키를 교환하여 암호화된 통신을 수행할 준비를 한다. 이후 암호화된 채널을 통해 데이터가 안전하게 전송된다. 핸드셰이크 과정은 보안 인증서 교환 및 서버 인증과 같은 추가적인 보안 절차가 포함된다.
캐싱
클라이언트나 서버에서 캐싱된 데이터를 사용하는 경우, 요청과 응답 과정이 일부 생략될 수 있다. 예를 들어, 클라이언트가 이전에 요청한 데이터가 캐시되어 있다면, 클라이언트는 서버에 요청하지 않고 캐시된 데이터를 바로 사용할 수 있다. 서버 측에서도 동일한 방식으로 캐시를 활용하여 불필요한 데이터 처리 및 응답 시간을 줄일 수 있다.
프록시 서버
프록시 서버를 사용하는 경우, 요청과 응답은 프록시 서버를 경유한다. 프록시 서버는 클라이언트와 서버 사이의 중개자 역할을 하며, 보안, 속도 향상, 로드 밸런싱 등을 위한 추가적인 기능을 제공할 수 있다. 프록시 서버는 클라이언트와 서버의 요청/응답 데이터를 변형하거나 저장하여 후속 요청에서 재사용할 수도 있다. 이 과정에서 클라이언트는 실제 서버와 직접 통신하지 않고 프록시 서버를 통해 요청을 처리한다.
정리
네트워크를 이용한 클라이언트-서버 간의 요청과 응답 과정은 여러 단계로 이루어져 있어 매우 복잡하고 시간비용이 크다. 클라이언트의 요청이 네트워크를 거쳐 서버에 도달하고, 서버는 이를 처리하여 다시 클라이언트에게 응답을 보내기까지의 과정에서 여러 네트워크 스택과 프로토콜을 거쳐야 한다. 이 과정에서 발생하는 데이터 전송, 패킷 처리, 프로토콜 해석 등의 시간이 서버 어플리케이션의 비즈니스 로직을 처리하는 시간보다 상대적으로 더 많이 소요될 수 있다. 따라서, 네트워크 통신은 시스템 성능에 있어 중요한 시간적 비용 요소로 작용하며, 이러한 과정을 최적화하는 것이 시스템 효율성을 높이는 데 중요한 역할을 한다.