[TIL] SSR vs CSR ์ฐจ์ด

OROSYยท2021๋…„ 11์›” 13์ผ
10

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
18/18
post-thumbnail

๐Ÿ†š SSR vs CSR ์ฐจ์ด

์ตœ๊ทผ ๊ธฐ์ˆ  ๋ฉด์ ‘์—์„œ ํ•ญ์ƒ ๋“ฑ์žฅํ•˜๋Š” ์งˆ๋ฌธ, SSR๊ณผ CSR์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋งŒํผ ํ•ซํ•œ SPA์˜ ์›๋ฆฌ์ธ SSR(Server Side Rendering)๊ณผ CSR(Client Side Rendering)์— ๋Œ€ํ•ด ์‚ดํŽด๋ด…์‹œ๋‹ค.

๐ŸŽฑ SSR ์ •์˜

SSR(Server Side Rendering)์€ ๋ง์—์„œ ๋ฐ”๋กœ ์˜๋ฏธ๋ฅผ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„์ชฝ์—์„œ ๋ Œ๋”๋ง์„ ํ•œ๋‹ค๋ผ๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์—ฌ๊ธฐ์„œ '๋ Œ๋”๋ง'์„ ํ•œ๋‹ค๋Š” ๊ฒƒ์€ ๋ฌด์Šจ ์˜๋ฏธ์ผ๊นŒ์š”?

์ถœ์ฒ˜: The Benefits of Server Side Rendering Over Client Side Rendering

์ฒซ ๋ฒˆ์งธ์—์„œ ๋ณด์‹œ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ ์„œ๋ฒ„์—์„œ ๋ Œ๋” ๋  ์ค€๋น„๋ฅผ ๋๋งˆ์นœ ์ƒํƒœ๋กœ HTML ์‘๋‹ต์„ ๋ธŒ๋ผ์šฐ์ €(ํด๋ผ์ด์–ธํŠธ)์— ๋ณด๋‚ด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ ์˜๋ฏธ๊ฐ€ ๋ฐ”๋กœ ๋ Œ๋”๋ง์ด๋ผ๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์งš๊ณ  ๋„˜์–ด๊ฐ€์•ผํ•  ๋ถ€๋ถ„์€ ๋ธŒ๋ผ์šฐ์ €์˜ ๋ Œ๋”๋ง์ž…๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋งํ•˜๋Š” ๋ Œ๋”๋ง์˜ ์˜๋ฏธ๋Š” HTML, CSS, JavaScript ํŒŒ์ผ์„ ๋ฐ›์•„์™€ ์ด๋ฅผ ์ฝ๊ณ  ํŒŒ์‹ฑํ•ด์„œ ์‹คํ–‰ํ•œ ๊ฒฐ๊ณผ๋ฌผ๋กœ ํ™”๋ฉด์— ๊ทธ๋ ค๋‚ด๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง์— ์žˆ๋Š” ๋ Œ๋”๋ง์˜ ๋œป์€ ์ด์™€ ์ข€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง์—์„œ ์˜๋ฏธ๋ฅผ ๋”ฐ์ง€์ž๋ฉด, HTML ํŒŒ์ผ ๋‚ด์— ๋‚ด์šฉ์ด ์žˆ๋Š๋ƒ ์—†๋Š๋ƒ์ž…๋‹ˆ๋‹ค. ๋‚ด์šฉ์ด ์žˆ๋‹ค๋ฉด, ๋ Œ๋”๋ง์ด ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ HTML ํŒŒ์ผ ๋‚ด์— ๋‚ด์šฉ์ด ๋ชจ๋‘ ์žˆ์œผ๋ฏ€๋กœ ๋ธŒ๋ผ์šฐ์ €๋Š” ๋ฐ”๋กœ ํŽ˜์ด์ง€๋ฅผ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐ”๋กœ ๋ณด์—ฌ์ง€๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ดํ›„ ๋ธŒ๋ผ์šฐ์ €๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ ๋‹ค์šด ๋ฐ›์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ•ด๋‹น ํŒŒ์ผ์„ ์‹คํ–‰์‹œํ‚ค๋ฉด, ํŽ˜์ด์ง€์˜ ์ƒํ˜ธ์ž‘์šฉ์ด ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ๊ธฐ์–ตํ•ด์•ผํ•  ๋ถ€๋ถ„์€ ํŽ˜์ด์ง€๊ฐ€ ๋ณด์—ฌ์ง€๋Š” ๊ฒƒ์€ 2๋‹จ๊ณ„์—์„œ ๊ฐ€๋Šฅํ–ˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์ ์ด ๋ฐ”๋กœ ์„ค๋ช…ํ•˜๊ฒŒ ๋  CSR๊ณผ์˜ ๊ฐ€์žฅ ํฐ ์ฐจ์ด์ ์ž…๋‹ˆ๋‹ค.

๋ฌผ๋ก , JS ํŒŒ์ผ์€ ์ฝํžˆ๊ธฐ ์ „์ด๋ฏ€๋กœ ์ด๋ฅผ ๋‹ค์šด๋กœ๋“œ ๋ฐ›์•„์˜ค๋ฉด์„œ ์œ ์ €๋Š” ์ปจํ…์ธ ๋ฅผ ๋ณผ ์ˆ˜ ์ž‡์ง€๋งŒ, ์‚ฌ์ดํŠธ๋ฅผ ์กฐ์ž‘ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์ด ๋•Œ์˜ ์‚ฌ์šฉ์ž ์กฐ์ž‘์„ ๊ธฐ์–ตํ•˜๊ณ  ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. JS๊นŒ์ง€ ์„ฑ๊ณต์ ์œผ๋กœ ์ปดํŒŒ์ผ ๋˜์—ˆ๋‹ค๋ฉด, ๊ธฐ์–ตํ•˜๊ณ  ์žˆ๋˜ ์‚ฌ์šฉ์ž ์กฐ์ž‘์ด ์‹คํ–‰๋˜๊ณ , ์ด์ œ ์›นํŽ˜์ด์ง€๋Š” ์ƒํ˜ธ์ž‘์šฉ์ด ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค.

SSR์˜ ๊ฐœ๋…์€ ์ด์ •๋„๋กœ ํ•˜๊ณ , Client Side Rendering, CSR์— ๋Œ€ํ•ด ์•Œ์•„๋ด…์‹œ๋‹ค.

SSR ๊ธฐ์–ตํ•ด์•ผํ•  ์ 
Step2: Viewable
Step4: Interactable

โ›ฑ CSR ์ •์˜

CSR์€ ๋ง ๊ทธ๋Œ€๋กœ SSR๊ณผ ๋‹ฌ๋ฆฌ ๋ Œ๋”๋ง์ด ํด๋ผ์ด์–ธํŠธ ์ชฝ์—์„œ ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์„œ๋ฒ„๋Š” ์š”์ฒญ์„ ๋ฐ›์œผ๋ฉด ํด๋ผ์ด์–ธํŠธ์— HTML๊ณผ JS๋ฅผ ๋ณด๋‚ด์ฃผ๊ณ , ํด๋ผ์ด์–ธํŠธ๋Š” ๊ทธ๊ฒƒ์„ ๋ฐ›์•„ ๋ Œ๋”๋ง์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆผ์œผ๋กœ ํ•œ ๋ฒˆ ๋” ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ถœ์ฒ˜: The Benefits of Server Side Rendering Over Client Side Rendering

CSR(Client Side Rendering)์€ ์œ„์˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด 2๋‹จ๊ณ„์—์„œ ๋ฐ”๋กœ ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰ 4๋‹จ๊ณ„์—์„œ ๋ณผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ƒํ˜ธ์ž‘์šฉ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ ์ด์œ ๋Š” ์„œ๋ฒ„๊ฐ€ HTML ํŒŒ์ผ์„ ์ค„ ๋•Œ, ๋ Œ๋”๊ฐ€ ์ค€๋น„๊ฐ€ ๋œ ํŒŒ์ผ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ฆ‰, HTML ํŒŒ์ผ ์•ˆ์—๋Š” ์•„๋ฌด๋Ÿฐ ๋‚ด์šฉ์ด ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ ๋‚ด์šฉ์€ JS ํŒŒ์ผ์„ ๋ฐ›์•„ ์‹คํ–‰์„ ์‹œ์ผœ์•ผ ๊ทธ์ œ์„œ์•ผ ๋งŒ๋“ค์–ด์ง€๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

React๋ฅผ ์จ๋ณด์‹  ๋ถ„์€ ์•Œ๊ฒ ์ง€๋งŒ, React.createElement๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์…จ์„ ๊ฑฐ๋ผ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š”document.createElement์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ JS์—์„œ HTML ํƒœ๊ทธ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๋•Œ์— ํƒœ๊ทธ๊ฐ€ ๋ Œ๋”๋ง ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— SSR๊ณผ์˜ ๋šœ๋ ทํ•œ ์ฐจ์ด๋ฅผ ๋ณด์ด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ํŠนํžˆ, index.html ํŒŒ์ผ์˜ ๋ฐ”๋”” ํƒœ๊ทธ ์•ˆ์— <div id="root"></div>์™€ ๊ฐ™์ด div ํƒœ๊ทธ ํ•˜๋‚˜๋งŒ ๋ฉ๊ทธ๋Ÿฌ๋‹ˆ ์žˆ๊ณ  ์•„๋ฌด๋Ÿฐ ๋‚ด์šฉ์ด ์—†๋Š” ๊ฒƒ์„ ๋งŽ์ด ๋ณด์…จ์„ ๊ฑฐ๋ผ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์•„๋ฌด๊ฒƒ๋„ ์—†๋Š” ์ƒํƒœ๋กœ ์ „๋‹ฌ๋˜๋ฏ€๋กœ ์œ ์ €๋Š” ์•„๋ฌด๊ฒƒ๋„ ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ReactDOM.render(<App />, document.getElementById('root'));

๊ทธ๋Ÿฌ๋‚˜ ์ดํ›„, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ถ”๊ฐ€์ ์œผ๋กœ JS ํŒŒ์ผ์„ ๋‹ค์šด๋ฐ›๊ณ  ์‹คํ–‰ํ•˜๋ฉด ๊ทธ๋•Œ ๋˜์–ด index.js์—์„œ ์œ„์™€ ๊ฐ™์ด root ํƒœ๊ทธ๋ฅผ ํ™”๋ฉด์— ๋ Œ๋”๋ง, ๊ทธ๋ ค์ฃผ๊ฒŒ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด์— SSR์€ index.html ํŒŒ์ผ ๋‚ด์— ํ™”๋ฉด์— ๊ทธ๋ ค๋‚ด๋Š” ์ฝ”๋“œ๋“ค์ด ์ด๋ฏธ ์ž‘์„ฑ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— CSR๊ณผ ๋‹ฌ๋ฆฌ ํŽ˜์ด์ง€๊ฐ€ 2๋‹จ๊ณ„์—์„œ Viewableํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๐ŸŽข SSR, CSR ์ฐจ์ด

1. ์›น ํŽ˜์ด์ง€๋ฅผ ๋กœ๋”ฉํ•˜๋Š” ์‹œ๊ฐ„

์›น ํŽ˜์ด์ง€์˜ ๋กœ๋”ฉ์˜ ์ข…๋ฅ˜๋Š” ๋‘ ๊ฐ€์ง€๋กœ ๋‚˜๋ˆ„์–ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์›น ์‚ฌ์ดํŠธ์˜ ์ฒซ ํŽ˜์ด์ง€๋ฅผ ๋กœ๋”ฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋‹ค๋ฅธ ๋‚˜๋จธ์ง€๋ฅผ ๋กœ๋”ฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • ์ฒซ ํŽ˜์ด์ง€ ๋กœ๋”ฉ ์‹œ๊ฐ„
    CSR์˜ ๊ฒฝ์šฐ HTML, CSS์™€ ๋ชจ๋“  ์Šคํฌ๋ฆฝํŠธ๋“ค์„ ํ•œ ๋ฒˆ์— ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด SSR์€ ํ•„์š”ํ•œ ๋ถ€๋ถ„์˜ HTML๊ณผ ์Šคํฌ๋ฆฝํŠธ๋งŒ ๋ถˆ๋Ÿฌ์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ SSR์ด ๋” ๋น ๋ฆ…๋‹ˆ๋‹ค.

  • ๋‚˜๋จธ์ง€ ํŽ˜์ด์ง€ ๋กœ๋”ฉ ์‹œ๊ฐ„
    ์ฒซ ํŽ˜์ด์ง€๋ฅผ ๋กœ๋”ฉํ•œ ํ›„, ์‚ฌ์ดํŠธ์˜ ๋‹ค๋ฅธ ๊ณณ์œผ๋กœ ์ด๋™ํ•˜๋Š” ์‹์˜ ๋™์ž‘์„ ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค. CSR์€ ์ด๋ฏธ ์ฒซ ํŽ˜์ด์ง€ ๋กœ๋”ฉํ•  ๋•Œ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์„ ๊ตฌ์„ฑํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋ฐ›์•„์™”์œผ๋ฏ€๋กœ ๋น ๋ฆ…๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด, SSR์€ ์ฒซ ํŽ˜์ด์ง€๋ฅผ ๋กœ๋”ฉํ•œ ๊ณผ์ •์„ ์ •ํ™•ํ•˜๊ฒŒ ๋‹ค์‹œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ CSR์ด SSR๋ณด๋‹ค ๋น ๋ฅธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

2. SEO ๋Œ€์‘

๊ฒ€์ƒ‰ ์—”์ง„์€ ์ž๋™ํ™”๋œ ๋กœ๋ด‡์ธ 'ํฌ๋กค๋Ÿฌ'๋กœ ์›น ์‚ฌ์ดํŠธ๋ฅผ ์ฝ์–ด๋“ค์ž…๋‹ˆ๋‹ค. CSR์€ JS๋ฅผ ์‹คํ–‰์‹œ์ผœ ๋™์ ์œผ๋กœ ์ปจํ…์ธ ๊ฐ€ ์ƒ์„ฑ๋˜๊ธฐ ๋•Œ๋ฌธ์— JS๊ฐ€ ์‹คํ–‰๋˜์–ด์•ผ metadata๊ฐ€ ๋ฐ”๋€Œ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ด์ „ ํฌ๋กค๋Ÿฌ๋Š” JS๋ฅผ ์‹คํ–‰์‹œํ‚ค์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— SEO ์ตœ์ ํ™”๊ฐ€ ํ•„์ˆ˜์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ตฌ๊ธ€์ด ์ด๋Ÿฌํ•œ ์ด์œ ๋กœ JS ํŒŒ์ผ์„ ํ•ด์„ํ•ด์„œ ๋‚ด์šฉ์„ ์ฐพ์•„์ฃผ๊ธฐ ์‹œ์ž‘ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ํŠธ๋ Œ๋“œ๋ฅผ ๋ฐ”๊พธ๊ณ  ์žˆ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๋ฌผ๋ก , SSR์€ ์• ์ดˆ์— ์„œ๋ฒ„ ์‚ฌ์ด๋“œ์—์„œ ์ปดํŒŒ์ผ๋˜์–ด ํด๋ผ์ด์–ธํŠธ๋กœ ๋„˜์–ด์˜ค๊ธฐ ๋•Œ๋ฌธ์— ํฌ๋กค๋Ÿฌ์— ๋Œ€์‘ํ•˜๊ธฐ ์šฉ์ดํ•ฉ๋‹ˆ๋‹ค.

3. ์„œ๋ฒ„ ์ž์› ์‚ฌ์šฉ

SSR์ด ์„œ๋ฒ„ ์ž์›์„ ๋” ๋งŽ์ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋งค๋ฒˆ ์„œ๋ฒ„์— ์š”์ฒญ์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๐Ÿน ํ•ด๊ฒฐ ๋ฐฉ์•ˆ

์ด๋ ‡๊ฒŒ CSR, SSR์€ ๊ฐ๊ฐ์˜ ์žฅ๋‹จ์ ์ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ ์ ˆํ•œ ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉ์„ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ๋กœ๋Š” CSR์€ ๋„คํŠธ์›Œํฌ๊ฐ€ ๋น ๋ฅด๊ณ , ์„œ๋ฒ„์˜ ์„ฑ๋Šฅ์ด ์ข‹์ง€ ์•Š์„ ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‚ฌ์šฉ์ž์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ๊ฒƒ๋“ค์ด ๋งŽ์„ ๋•Œ๋‚˜ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ค˜์•ผ ํ•˜๋Š” ๋ฐ์ดํ„ฐ์˜ ์–‘์ด ๋งŽ์„ ๋•Œ ๋กœ๋”ฉ์ฐฝ์„ ๋„์šธ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ด๋Ÿฌํ•œ ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ˜๋Œ€๋กœ SSR์€ CSR์€ ํ•œ๋ฒˆ์— ๋ชจ๋“  ๊ฒƒ์„ ๋ถˆ๋Ÿฌ์˜ค์ง€๋งŒ SSR์€ ๊ฐ ํŽ˜์ด์ง€๋งˆ๋‹ค ๋‚˜๋ˆ  ๋ถˆ๋Ÿฌ์˜ค๋ฏ€๋กœ ๋„คํŠธ์›Œํฌ๊ฐ€ ๋Š๋ฆฌ๊ฑฐ๋‚˜, SEO๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ, ์›น ์‚ฌ์ดํŠธ๊ฐ€ ์ƒํ˜ธ์ž‘์šฉ์ด ๋ณ„๋กœ ์—†๋‹ค๋ฉด SSR์„ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

CSR + SSR ํ™˜๊ฒฝ ๊ตฌ์กฐ

๋˜ํ•œ, ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ CSR + SSR ํ™˜๊ฒฝ์„ ํ†ตํ•ด ๊ฐœ๋ฐœํ•˜๋Š” ํšŒ์‚ฌ๋“ค๋„ ๋งŽ์•„์กŒ์Šต๋‹ˆ๋‹ค.

์ถœ์ฒ˜: CSR ์•ฑ์—์„œ SSR + CSR ํ™˜๊ฒฝ์œผ๋กœ ์ด์ฃผํ•˜๊ธฐ

์ „์ฒด์ ์ธ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋„๋ฉ”์ธ ๋„ค์ž„์„ ํ†ตํ•ด NginX ์›น์„œ๋ฒ„์— ์ ‘๊ทผํ•˜๋ฉด NginX๋Š” EC2 ๋‚ด๋ถ€์˜ ๋‹ค๋ฅธ ํฌํŠธ์—์„œ ๋™์ž‘ํ•˜๊ณ  ์žˆ๋Š” express ์„œ๋ฒ„์— ์ ‘๊ทผํ•ฉ๋‹ˆ๋‹ค. express ์„œ๋ฒ„๋Š” ์ผ๋ถ€๊ฐ€ ์™„์„ฑ๋œ html ๋ฌธ์„œ๋ฅผ NginX๋ฅผ ํ•œ๋ฒˆ ๊ฑฐ์ณ์„œ express์™€ ๊ฐ™์€ WAS์™€ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ์‹์„ reverse proxy๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. reverse proxy๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์ง€๋งŒ, ์™ธ๋ถ€ ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ WAS๊ฐ€ ์–ด๋–ค ํฌํŠธ์—์„œ ๋™์ž‘ํ•˜๋Š”์ง€ ์ˆจ๊ฒจ ๋ณด์•ˆ์ ์œผ๋กœ ๊ฐ•ํ™”ํ•˜๊ธฐ ์œ„ํ•œ ๋ชฉ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ํ๋ฆ„์œผ๋กœ ์‚ฌ์šฉ์ž๋Š” ์–ด๋Š ์ •๋„ ํ™”๋ฉด์ด ๋งŒ๋“ค์–ด์ง„ html ๋ฌธ์„œ๋ฅผ ์ฒ˜์Œ ์‘๋‹ต์œผ๋กœ ๋ฐ›์•„๋ณผ ์ˆ˜๊ฐ€ ์žˆ๋Š”๋ฐ, ๋น„์–ด์žˆ๋Š” body๋ฅผ ์ฒซ html ์‘๋‹ต์œผ๋กœ ๊ฐ€์ ธ์˜ค๋Š” CSR๋ณด๋‹ค๋Š” ํ›จ์”ฌ ๋น ๋ฅธ ํ™”๋ฉด ๋กœ๋”ฉ ์†๋„๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

app.get('/', (req, res) => {
  const indexFile = path.resolve(path.join(__dirname, '../client/index.html'));

  const app = ReactDOMServer.renderToString(<App />);

  fs.readFile(indexFile, 'utf8', (err, data) => {
    if (err) {
      console.error('Something went wrong:', err);
      return res.status(500).send('Oops, better luck next time!');
    }

    const result = data.replace('<div id="root"></div>', `<div id="root">${app}</div>`)

    return res.send(result);
  });
}

๋ฆฌ์•กํŠธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๊ฐœ๋ฐœ์ž๋Š” express.js์—์„œ ๋Œ€๋žต ์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š”๋ฐ ReactDOMServer.renderToString์„ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์ ์„ ๋นผ๋ฉด CSR์—์„œ ๋ Œ๋”๋งํ•˜๋˜ ๋ฐฉ์‹๊ณผ ํฌ๊ฒŒ ๋‹ค๋ฅธ ๊ฒƒ์€ ์—†์Šต๋‹ˆ๋‹ค.

renderToString์€ ๋ฆฌ์•กํŠธ๊ฐ€ ์ปดํฌ๋„ŒํŠธ ๊ตฌ์กฐ๋ฅผ ํŒŒ์•…ํ•˜๊ณ  HTML string์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ๋™์ž‘์„ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ์ž‘์—…์„ ๋งˆ์น˜๋ฉด ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์—์„œ html์„ ๋ฐ›์•„์˜จ ๊ฒฐ๊ณผ๊ฐ€ ์ผ๋ถ€ ์™„์„ฑ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฒซ html์„ ๋ฐ›์•„์˜จ ์ด ์‹œ์  ์ดํ›„๋ถ€ํ„ฐ๋Š” ๋”๋Š” SSR์ด ์•„๋‹Œ CSR๋กœ ๋ฐ”๋€๋‹ˆ๋‹ค. ํŽ˜์ด์ง€ ์ด๋™๋„ SPA์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๋Š”๊ฒŒ ์ด๊ฒŒ ์–ด๋–ป๊ฒŒ ๊ฐ€๋Šฅํ•œ ๊ฒƒ์ผ๊นŒ์š”?

์ผ๋‹จ CSR + SSR ํ™˜๊ฒฝ์ด๋ฏ€๋กœ ์ฒซ html์„ ๋ฐ›์•„์˜จ ํ›„์—๋„ CSR ํ™˜๊ฒฝ์„ ๋™์ž‘์‹œํ‚ค๊ธฐ ์œ„ํ•œ JavaScript๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” script ํƒœ๊ทธ๊ฐ€ ์—ฌ์ „ํžˆ ๋“ค์–ด๊ฐ€์žˆ๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ html์„ ๋ฐ›์•„์˜จ ํ›„ JS ํŒŒ์ผ์„ ๊ฐ€์ ธ์™€ CSR๋กœ ๋™์ž‘์‹œํ‚ค๊ธฐ ๋•Œ๋ฌธ์— SSR์—์„œ CSR๋กœ์˜ ๋ณ€๊ฒฝ์ด ๊ฐ€๋Šฅํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ์˜ค๋Š˜์€ SPA์˜ ์›๋ฆฌ์ธ SSR, CSR์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์Šต๋‹ˆ๋‹ค. ํŠนํžˆ, ๊ธฐ์ˆ ๋ฉด์ ‘์—์„œ ์ž์ฃผ ๋“ฑ์žฅํ•˜๋Š” ์ฃผ์ œ์ด๋ฏ€๋กœ ์กฐ๊ธˆ ์ƒ์„ธํžˆ ์ •๋ฆฌํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ž๋ฃŒ ์ถœ์ฒ˜๋Š” ์•„๋ž˜์— ๋‚จ๊ฒจ๋“œ๋ฆฌ๋ฏ€๋กœ ๋”์šฑ ์ž์„ธํ•œ ๋‚ด์šฉ์„ ์›ํ•˜์‹œ๋Š” ๋ถ„์€ ๊ผญ ์ฐธ๊ณ ํ•ด์ฃผ์‹œ๊ธฐ ๋ฐ”๋ผ๊ฒ ์Šต๋‹ˆ๋‹ค.๐Ÿ™‡โ€โ™‚๏ธ๐Ÿ™‡โ€โ™‚๏ธ๐Ÿ™‡โ€โ™‚๏ธ

์ฐธ๊ณ  ์‚ฌ์ดํŠธ

SSR๊ณผ CSR์˜ ์ฐจ์ด
[BOAZ] SSR๊ณผ CSR ์ด ์˜์ƒ ํ•˜๋‚˜๋กœ ๋๋‚ด๊ธฐ! (SEO ํ•ด๊ฒฐ ํฌํ•จ)
์–ด์„œ ์™€, SSR์€ ์ฒ˜์Œ์ด์ง€? ๋„์ž… ํŽธ
CSR ์•ฑ์—์„œ SSR + CSR ํ™˜๊ฒฝ์œผ๋กœ ์ด์ฃผํ•˜๊ธฐ

profile
Life is a matter of a direction not a speed.

0๊ฐœ์˜ ๋Œ“๊ธ€