# 웹 아키텍쳐

## 글을 시작하며

요 근래에는 프론트엔드 뿐만 아니라 백엔드, 인프라 등 전반적인 아키텍쳐를 배우는 것이 너무나도 즐겁다. 풀스택 개발도 한번 해보고싶어서 풀스택을 공부하면서, 웹 아키텍쳐를 복습하고 공부해보면 자연스레 내가 배워야할 길잡이 역할도 해줄 수 있을거라고 생각이 되어 한번 웹 아키텍쳐에 대해 공부를 진행해보았다.

![Image](https://upload.cafenono.com/image/slashpageHome/20251130/144817_hULcDER8DN73E5Mq1U?q=80&s=1280x180&t=outside&f=webp)

## 웹이 어떻게 서빙 될까?

### 1. 브라우저는 캐싱된 DNS 기록들을 확인하고, IP 주소가 있는지 확인한다.

인터넷에 있는 모든 URL들에는 고유 IP들이 존재한다. 이 IP 주소를 통해서 해당 웹사이트를 호스팅하고 있는 서버 컴퓨터에 접근할 수 있다. 이때 DNS(Domain Name System)라는 개념이 나오는데, DNS(Domain Name System)은 URL들의 이름과 IP주소를 저장하고 있는 데이터베이스이다. 

DNS의 큰 목적은 사람들에게 편리함을 주는 것이다. 숫자로 된 IP 주소를 작성해도 원하는 웹사이트에 접속할 수 있지만, 매번 많은 자릿 수의 숫자들을 검색하는 과정은 매우 복잡하기 때문에 DNS는 사람들이 웹 사이트 주소에 쉽게 접속할 수 있게 매핑해주는 역할을 한다.

웹 사이트 이름을 브라우저에 검색을 하게 되면 내부적으로 브라우저는 DNS 기록을 4가지의 캐시에서 확인한다.

> DNS Query : 여러 다른 DNS 서버들을 검색해서 해당 사이트의 IP 주소를 찾는 과정 및 행위

1. 가장 먼저 브라우저 캐시(크롬, 파이어 폭스 등 브라우저 내부 DNS 캐시)를 확인한다. 브라우저는 일정기간 동안 (유저가 이전에 설정한 시간 동안)의 DNS 기록들을 저장하고 있다. DNS query가 이곳에서 가장 먼저 실행된다.

2. 그 다음으로 브라우저는 OS 캐시를 확인한다. 브라우저 캐시에 웹사이트 이름의 IP 주소가 발견되지 않았다면,

3. 브라우저는 systemcall을 통해 OS가 저장하고 있는 DNS 기록들의 캐시에 접근한다.

4.  그 다음에서는 router 캐시를 확인한다. 컴퓨터에 DNS 기록을 찾지 못했다면 브라우저는 DNS 기록을 캐싱하고 있는 router와 통신을 해서 찾으려고 한다.

> 여기서 라우트 캐시라고 함은, 로컬 네트워크 장비(공유기, 사내 라우터)와 같은 곳을 말한다.
그래도 못 찾는다면 마지막으로 ISP 캐시를 확인한다. ISP는 DNS 서버를 구축하고 있고 브라우저가 마지막으로 DNS 기록이 있기를 바라며 접근하게 된다.

> 여기서 ISP는 KT, SK 브로드밴드와 같은 인터넷 제공업체를 말한다.

### 2. (1번 과정에서 찾으면 좋겠지만) 만약 찾지 못했다면 ISP의 DNS 서버가 목적지를 호스팅하고 있는 서버의 IP 주소를 찾기 위해 DNS Query를 날린다.

목적지 서비스에 접속을 하고 싶다면, IP 주소를 반드시 알아야한다. DNS Query의 목적은 다른 DNS 서버들을 검색하여 해당 사이트의 IP 주소를 찾는 것이기 때문에, IP 주소를 찾을 때까지 DNS 서버에서 다른 DNS 서버를 오가면서 반복적으로 검색을 진행한다. 또는 못찾아서 에러가 발생할 때까지 계속 검색을 진행한다. 이러한 검색을 recursive search 라고한다.

ISP의 DNS 서버를 DNS recursor라고 부르며, 인터넷을 통해 다른 DNS 서버들에게 묻고 또 물어 도메인 이름의 올바른 IP 주소를 찾는데 책임을 가지고 있다. 이들은 웹사이트 도메인 이름 구조에 기반해 검색을 하기 때문이다.

> 다른 DNS 서버를 부르는 명칭은 네임 서버라고 한다.

도메인 이름 구조에 기반해서 검색한다고 하면, 이해하기 어려워보이지만 원리는 매우 간단하다.

![Image](https://upload.cafenono.com/image/slashpageHome/20251130/143650_JDb0cAoxDpKXOLCkY6?q=80&s=1280x180&t=outside&f=webp)

우리가 매번 마주하는 웹사이트의 URL들은 third-level domain, second-level domain, top-level domain을 가지고 있다. 각 레벨 별로 자신들만의 네임 서버가 존재하고, 여기서 DNS look up 프로세스 중에 DNS Query가 진행한다.

> DNS Lookup이란 무엇일까?

DNS Lookup이란 도메인 이름을 IP 주소로 바꾸는 과정을 말한다.

예로 들어 브라우저에 [https://www.example.com](https://www.example.com) 이라고 입력을 했을 경우,브라우저 및 OS가 [www.example.com](http://www.example.com) 이라는 이름의 IP에 대한 질의를 던지고 DNS Lookup을 시작한다. 순서대로 아래와 같은 과정을 진행한다.

1. 브라우저 내부 DNS 캐시

2. (실환경) OS 캐시, (로컬) hosts 파일

3. 로컬 네트워크의 DNS (공유기 등)

4. ISP / 회사 DNS 서버필요하다면 상위(권한을 가진) DNS 서버들

위 과정을 통해 `www.example.com` > `93.167.535.35`와 같은 IP 주소를 획득할 수 있다.

이 IP로 TCP 연결을 맺고, 그 다음 HTTP 요청 및 응답이 오간다.

원하는 목적지 도메인에 대하여 처음에 DNS recursor가 root name server에 연락을 한다.

root name 서버는 `.com` 도메인의 name server로 리다이렉트를 시킨다.

`.com` 네임 서버는 `[example.com](https://example.com)` 네임서버로 리다이렉트를 시킨다.

`[example.com](https://example.com)` 네임서버는 DNS 기록에서 `[www.example.com](https://www.example.com)`에 매칭되는 IP 주소를 찾고, DNS recursor로 보내게된다. 

> 어떤 방식으로 요청들이 오갈까?

이 모든 요청들은 작은 데이터 패킷들을 통해 보내진다. 패킷 안에는 보내는 요청의 내용과 DNS Recursor의 IP 주소가 포함되어있다. 이 패킷들은 원하는 DNS 기록을 가진 DNS 서버에 도달할 때까지 클라이언트와 서버를 여러번 오간다. 패킷들이 움직이는 것도 라우팅 테이블에 기반한다. 라우팅 테이블을 통해서 어떤 길로 가야 가장 빠른지를 확인할 수 있다. 만약 패킷이 도중에 loss 된다면 에러가 발생하게 된다.

### 3. IP를 찾았다면, 브라우저가 서버와 TCP Connection을 맺는다.

브라우저가 올바른 IP 주소를 받게 되면, 서버와 connection을 빌드하게 된다. 브라우저는 인터넷 프로토콜을 사용해서 서버와 연결된다. 인터넷 프로토콜 종류에는 여러가지가 존재하지만, HTTP 요청의 경우 일반적으로 TCP를 사용한다. 클라이언트와 서버 간 데이터 패킷들이 오가려면 TCP Connection이 되어야한다. TCP/IP three-way handshake라는 프로세스를 통해 클라이언트와 서버간 connection이 이뤄지게 된다.

1. 클라이언트 머신이 SYN 패킷을 서버를 보내고, connection을 열어달라고 요청한다.

2. 서버가 새로운 connection을 시작할 수 있는 포트가 존재한다면, SYN/ACK 패킷으로 응답한다.

3. 클라이언트는 SYN/ACK 패킷을 서버로부터 받으면, 서버에게 ACK 패킷을 보낸다.

이러한 과정이 끝나면 TCP Connection이 성공적으로 완성된다.

### 4. 브라우저가 웹 서버에 HTTP 요청을 한다.

TCP로 연결이 성공적으로 되었다면, 데이터를 전송하면 된다. 클라이언트의 브라우저는 GET 요청을 통해 서버에게 [www.example.com](http://www.example.com) 웹 페이지를 요구한다.

요청을 할 때 비밀 자료를 포함하던지, form을 제출하는 상황에서 POST 요청을 사용할 수도 있다.

이 요청을 할 때 다른 부가적인 정보들도 함께 전달이 된다.

- browser identification (User-Agent 헤더)

- 받아들일 요청의 종류 (Accept 헤더)

- 추가적인 요청을 위해 TCP Connection 유지를 요청하는 connection 헤더

- 브라우저에서 얻은 쿠키 정보

- 기타 등등

### 5. 서버는 요청을 받아 요청을 처리한 후, 응답 값을 생성한다.

서버는 웹 서버를 가지고 있다. 브라우저로부터 요청을 받고 request handler 에게 요청을 전달해 읽고, 응답 값을 생성하게 한다.

> request handler란 ASP.NET, PHP, Ruby 등으로 작성된 프로그램을 의미한다.

이 request handler는 요청과 요청의 헤더, 쿠키를 읽어서 요청이 무엇인지 파악하고 필요하다면 서버에 정보를 업데이트한다. 그 다음에 response를 특정한 포맷으로 (JSON, XML, HTML) 작성한다.

### 6. 서버가 HTTP Response를 보낸다.

서버의 response 에는 요청한 웹 페이지, status code, compression type(Content-Encoding) - 어떻게 인코딩이 되어있는지, 어떻게 페이지를 캐싱할지(Cache-Control), 쿠키 정보, 개인 정보등이 포함된다.

> 응답 값의 Status Code들

1xx는 정보만 담긴 메세지를 의미한다.

2xx는 데이터 통신 성공을 의미한다.

3xx는 클라이언트를 다른 URL로 리다이렉트 함을 의미한다.

4xx는 클라이언트 측에서 에러가 발생했음을 의미한다.

5xx는 서버 측에서 에러가 발생했음을 의미한다.

### 7. 브라우저가 HTML Content를 보여준다.

브라우저는 HTML Content를 브라우저 렌더링 파이프라인을 통해 단계적으로 보여준다. HTML, 이미지, CSS 등의 정적인 파일들은 브라우저에 의해 캐싱이 되어 나중에 해당 페이지를 방문할 때 다시 서버로부터 불러와지지 않도록 한다. 그 다음에는 최종적으로 `[www.example.com](https://www.example.com)`의 모습이 보이게 된다. 사실 내부적으로는 여러 과정들이 일어나지만, 이 모든 일들이 1초도 되지 않아 완료가 되는 것을 확인할 수 있다.

## 번외 : 그러면 로컬 환경은 어떤 방식으로 찾아가는거지?

로컬 환경도 동작 원리는 실서비스와 거의 같고, 스케일만이 줄어든 버젼이라고 생각하면 된다.

### 로컬 환경에서도 "DNS - IP - TCP - 응답" 의 과정은 같다.

> 예시로 개발중인 프론트엔드 서비스를 `http://localhost:5173`에 띄웠다고 한다면, 
아래와 같은 과정들이 일어난다.

1. 브라우저 주소 창에 입력
1. `http://localhost:5173`

2. DNS 단계
2. localhost 라는 호스트 명은 OS의 hosts 파일에 미리 등록되어있다.
2. `127.0.0.1 localhost`
2. 그래서 DNS 서버까지 가지 않고, 곧바로 `127.0.0.1` (루프백 IP)로 해석된다.

3. TCP 연결
3. 브라우저는 `127.0.0.1:5173` 으로 TCP 연결을 시도한다.이 포트를 사용자가 띄운 개발용 서버(Vite Dev Server, Webpack Dev Server, Node/Express, Spring Boot 등) 가 listen 처리를 하고 있다.

4. HTTP 요청 및 응답
4. 브라우저는 GET / 같은 요청을 전송한다.로컬 서버는 HTML, JS, CSS 또는 API JSON을 응답받는다.브라우저는 그 응답으로 화면을 그린다.

즉, 실서비스의 "웹 서버" 역할을 PC에서 가동중인 개발 서버가 대신하는 것 뿐, 흐름 자체는 동일하다.

호스트명 → IP (`127.0.0.1`) → 포트 → 로컬 웹 서버와 TCP 통신 → 응답을 브라우저에 렌더

### 프로덕션과 로컬 환경의 비교

**프로덕션 환경**

브라우저 → DNS → 공인 IP → 실제 서버(로드밸런서/웹서버/백엔드)와 TCP

**로컬 환경**

브라우저 → hosts → `127.0.0.1`→ 로컬에서 띄운 웹 서버(Vite, Node, Spring, etc.)와 TCP

## 글을 마치며

요새 프론트엔드 개발을 진행하면서 단순히 브라우저의 시각적인 엔드포인트 요소만을 개발하다보니 놓치는 부분들이 많은 것 같다. 전반적인 웹의 설계 및 아키텍쳐 흐름을 파악하고 또 기본 아키텍쳐 구조에서 더 나아가 사내 아키텍쳐는 어떤 방식으로 구조화가 되어있는지 계속해서 알아보려고 한다. 이 포스팅을 보는 프론트엔드 개발자들도 나와 같이 너무 해보고싶은 것들이 많다면 프론트엔드 이야기만이 아닌 다양한 웹 구조에 대해서 꾸준히 공부해보면 좋을 것 같다는 생각이 들었다.

---

## 레퍼런스

[3계층 구조(3 Tier- Architecture) 이해하기 [스마트인재개발원]](https://jaws-coding.tistory.com/9)

[[번역] Browser에 www.google.com을 검색하면 어떤 일이 일어날까?](https://devjin-blog.com/what-happen-browser-search/)

For the site tree, see the [root Markdown](https://slashpage.com/timmy.md).
