01. 웹과 브라우저
주소를 입력한 순간부터 화면에 픽셀이 찍히기까지, 무엇이 오가는지 정리합니다.
URL, DNS, HTTP 요청과 응답
주소는 여러 조각으로 이루어집니다.
https://kangbit.github.io/learn/frontend/?tab=css#section
└─┬─┘ └────────┬────────┘└──────┬─────┘└───┬───┘└──┬──┘
프로토콜 호스트 경로 쿼리 프래그먼트프래그먼트(# 뒤)는 서버로 가지 않습니다. 브라우저가 혼자 처리합니다.
호스트 이름은 그대로 쓸 수 없으므로 IP 주소로 바꿔야 합니다. 이 변환을 DNS가 합니다. 운영체제 캐시, 공유기, 통신사 서버를 차례로 거치며 찾습니다.
dig kangbit.github.io +short주소를 찾으면 TCP 연결을 맺고 요청을 보냅니다.
GET /learn/frontend/ HTTP/1.1
Host: kangbit.github.io
Accept: text/htmlHTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Cache-Control: max-age=600
<!doctype html>...상태 코드는 앞자리로 성격이 갈립니다.
| 범위 | 뜻 | 자주 보는 것 |
|---|---|---|
| 2xx | 성공 | 200, 201, 204 |
| 3xx | 다른 곳으로 | 301, 302, 304 |
| 4xx | 요청 쪽 문제 | 400, 401, 403, 404 |
| 5xx | 서버 쪽 문제 | 500, 502, 503 |
304는 "바뀐 게 없으니 캐시를 쓰라"는 응답입니다. 본문이 비어 있어 빠릅니다.
연결 재사용과 HTTP 버전
HTTP/1.1은 한 연결에서 요청을 하나씩 처리합니다. 앞 요청이 느리면 뒤가 막힙니다. 그래서 브라우저가 연결을 여러 개 엽니다(보통 호스트당 6개).
HTTP/2는 한 연결에서 여러 요청을 동시에 주고받습니다. 파일을 잘게 쪼개도 손해가 적어집니다.
개발자 도구 Network 탭의 Protocol 열에서 확인할 수 있습니다.
HTTPS
가운데에서 내용을 보거나 바꾸지 못하도록 암호화합니다. 인증서로 "이 서버가 진짜 그 도메인인지"도 확인합니다.
HTTPS가 아니면 쓸 수 없는 기능이 많습니다.
Service Worker, 위치 정보, 카메라·마이크, 클립보드 읽기localhost는 예외로 취급되어 개발 중에는 그냥 동작합니다.
HTML, CSS, JavaScript가 전달되는 흐름
HTML을 먼저 받고, 파싱하다가 만나는 리소스를 추가로 요청합니다.
<link rel="stylesheet" href="/style.css" /> <!-- 파싱을 막습니다 -->
<script src="/app.js"></script> <!-- 다운로드와 실행 모두 파싱을 막습니다 -->
<script src="/app.js" defer></script> <!-- 파싱과 병렬로 받고, 끝난 뒤 실행 -->
<script src="/app.js" async></script> <!-- 받는 즉시 실행, 순서 보장 없음 -->defer는 순서를 지키며 문서 파싱이 끝난 뒤 실행됩니다. 대부분의 스크립트에 맞습니다. async는 다른 코드와 무관한 분석 스크립트 같은 것에 씁니다.
CSS는 기본적으로 렌더링을 막습니다. 스타일이 적용되지 않은 화면이 잠깐 보이는 것을 피하기 위해서입니다.
DOM, CSSOM과 렌더링 과정
HTML은 DOM 트리로, CSS는 CSSOM으로 변환됩니다. 둘을 합쳐 화면에 그릴 트리를 만듭니다.
HTML → DOM ┐
├→ 렌더 트리 → 레이아웃 → 페인트 → 합성
CSS → CSSOM┘| 단계 | 하는 일 |
|---|---|
| 레이아웃 | 각 요소의 크기와 위치를 계산합니다 |
| 페인트 | 색, 테두리, 그림자를 칠합니다 |
| 합성 | 레이어를 겹쳐 최종 화면을 만듭니다 |
display: none인 요소는 렌더 트리에 들어가지 않습니다. visibility: hidden은 자리를 차지하므로 들어갑니다.
무엇을 바꾸느냐에 따라 다시 하는 단계가 달라집니다. 이 차이가 성능과 직결되며 09. 브라우저 심화와 성능에서 자세히 다룹니다.
개발자 도구
처음에 익숙해져야 할 탭은 셋입니다.
Elements — 지금 화면의 DOM을 보여 줍니다. HTML 소스가 아니라 현재 상태입니다. JavaScript가 바꾼 결과가 반영되어 있어서, 소스와 다른 것이 정상입니다.
Styles 패널에서는 어떤 규칙이 적용되고 무엇이 덮였는지 볼 수 있습니다. 취소선이 그어진 것은 다른 규칙에 밀린 선언입니다.
Console — 오류와 로그가 모입니다. $0으로 Elements에서 선택한 요소를 바로 집을 수 있습니다.
$0; // 선택된 요소
$$("button"); // querySelectorAll의 축약Network — 무엇을 언제 받았는지 봅니다. 확인할 것은 상태 코드, 크기, 시간, 그리고 캐시에서 왔는지 여부입니다. Disable cache를 켜면 첫 방문자의 상황을 볼 수 있습니다.
Preserve log를 켜지 않으면 페이지 이동 시 기록이 사라집니다. 로그인 리다이렉트를 디버깅할 때 필요합니다.
Git으로 변경 사항 기록하기
작업 단위로 기록을 남겨 두면 되돌리고 비교할 수 있습니다.
git init
git add .
git commit -m "할 일 목록 마크업 작성"
git log --oneline
git diff
git switch -c feature/filter커밋은 하나의 의미 단위로 끊습니다. "작업 중"처럼 뭉뚱그린 커밋이 쌓이면 나중에 어디서 무엇이 바뀌었는지 찾을 수 없습니다.