LabHub

SSR — 서버가 먼저 그린다 · 문자열과 그 함정 · 실습

문자열을 안전하게 만든다

LabHub 에서 이어서 보기

목표

서버 렌더링을 문자열을 만드는 일로 직접 해 보면서, 거기서 나오는
세 가지 — XSS · 하이드레이션 불일치 · 캐시 유출 — 를 막습니다.

만들 것

/root/work/ssr/render.mjs 하나입니다. 프레임워크도 npm 도 쓰지 않습니다.

| export | 계약 |
|---|---|
| renderShell() | 데이터 없이도 유효한 문서 셸 |
| escapeHtml(s) | 다섯 글자 치환 (& 를 먼저) |
| render(state) | 내용이 든 완성 HTML. 순수 함수 |
| renderState(state) | <script type="application/json"> 상태 태그 |
| renderStream(state) | async generator — 셸부터 흘려보낸다 |
| cacheControl(state) | 로그인 여부에 따른 Cache-Control 값 |

state 는 이런 모양입니다.

{ title: "제목", items: ["가", "나"], user: { name: "홍길동" } | null }

확인

cd /root/work/ssrnode -e "import('./render.mjs').then(m => console.log(m.render({title:'t',items:['a']})))"

단계

1. renderShell()
2. render(state) — 내용이 HTML 안에
3. escapeHtml& 를 먼저
4. renderState</script> 탈출 막기
5. 순수성 — Date.now/Math.random 금지
6. renderStream — 셸 먼저
7. cacheControl
8. 정리 → 08-notes.md

참고

5단계 채점기는 Date.nowMath.random 을 **호출할 때마다 다른 값을
주도록 바꿔치기한 뒤** 두 번 렌더해 비교합니다. 렌더 안에서 그것들을
부르고 있으면 바로 드러납니다.

단계 8개

  1. 셸부터
  2. 첫 HTML 안에 내용이 있어야 한다
  3. 사용자 데이터를 이스케이프한다
  4. 초기 상태를 안전하게 심는다
  5. 렌더 함수를 순수하게
  6. 셸을 먼저 흘려보낸다
  7. 개인화된 페이지를 캐시하지 않는다
  8. 셋을 정리한다