πŸ“— Angular Hybrid Rendering

2022λ…„ 10μ›” 27일
7λΆ„

이전 κΈ€μ—μ„œ CSR, SSR, SSG에 λŒ€ν•΄ 각각의 차이점에 λŒ€ν•΄μ„œ 닀뀄 λ³΄μ•˜μŠ΅λ‹ˆλ‹€. Angular, React, Vueμ—μ„œ 각각의 λ°©μ‹μœΌλ‘œ μ΄λŸ¬ν•œ λ Œλ”λ§ λ°©μ‹μœΌλ‘œ κ΅¬ν˜„μ„ ν•  μˆ˜κ°€ μžˆλŠ”λ°μš”. λŒ€ν‘œμ μœΌλ‘œ AngularλŠ” Universal, ReactλŠ” NextJs, VueλŠ” Nuxt 등을 많이 μ‚¬μš©ν•˜λŠ” 것 κ°™λ„€μš”. AngularλŠ” κ΅­λ‚΄μ—μ„œ 인기가 많이 μ—†μ–΄μ„œμΈμ§€ ν•΄λ‹Ή λ‚΄μš©μ„ λ‹€λ£¨λŠ” 글이 μ—†λŠ”λ“―ν•˜μ—¬ 이번 κΈ°νšŒμ— μ œκ°€ μ‚¬μš©μ„ 해보고 κ°„λ‹¨ν•˜κ²Œλ‚˜λ§ˆ μ •λ¦¬ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

λ Œλ”λ§ μ’…λ₯˜μ— λŒ€ν•œ 글은 μ—¬κΈ°λ₯Ό μ°Έκ³ 

κ²°λ‘ λΆ€ν„° λ§μ”€λ“œλ¦¬λ©΄ ꡉμž₯히 μ‰½μŠ΅λ‹ˆλ‹€!

λ¨Όμ € κ°„λ‹¨ν•˜κ²Œ κ°œλ… μ •λ„λ§Œ λ‹€μ‹œ 짚고 λ„˜μ–΄κ°€κ² μŠ΅λ‹ˆλ‹€.

PreRendering

μš°λ¦¬μ—κ²Œ κ°€μž₯ μ΅μˆ™ν•œ ν΄λΌμ΄μ–ΈνŠΈ λ Œλ”λ§(CSR) 방식은 잘 μ•„μ‹€ ν…Œκ³ , μ„œλ²„μ‚¬μ΄λ“œ λ Œλ”λ§(SSR)은 각 νŽ˜μ΄μ§€μ— λŒ€ν•œ μš”μ²­μ„ λ°›μœΌλ©΄ λΈŒλΌμš°μ € 엔진을 λŒ€μ‹ ν•΄μ„œ μ„œλ²„μ—μ„œ Nodeκ°€ λ Œλ”λ§ν•˜κ³  결과물을 ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ μ „λ‹¬ν•΄μ£ΌλŠ” 것이고, 사전 λ Œλ”λ§(PreRendering, SSG) 말 κ·ΈλŒ€λ‘œ 미리 λ Œλ”λ§μ„ 해놓고 μ„œλ²„μ—μ„œ ν•΄λ‹Ή νŽ˜μ΄μ§€μ— λŒ€ν•œ μš”μ²­μ΄ 였면 미리 λ Œλ”λ§ν•΄λ‘μ—ˆλ˜ νŽ˜μ΄μ§€λ₯Ό 전달!

자 이제 λˆ„κ΅¬λ„ μ•Œλ €μ£Όμ§€ μ•Šμ•˜λ˜, Angular Universal을 μ΄μš©ν•΄ ν•˜μ΄λΈŒλ¦¬λ“œ λ Œλ”λ§μ„ κ΅¬ν˜„ν•΄ λ³΄κ² μŠ΅λ‹ˆλ‹€.

Universal

hybrid-rendering-app μ΄λΌλŠ” μƒˆλ‘œμš΄ ν”„λ‘œμ νŠΈλ₯Ό μƒμ„±ν•˜κ³  universal packageλ₯Ό μΆ”κ°€ν•΄μ€λ‹ˆλ‹€.

ng new hybrid-rendering-app
 
ng add @nguniversal/express-engine

@nguniversal/express-engine을 μΆ”κ°€ ν•΄μ£Όλ©΄ main.server.ts, app.server.module.tsκ³Ό 같은 λ­”κ°€ λͺ»λ³΄λ˜ νŒŒμΌλ“€μ΄ μƒκ²¨λ‚˜λŠ” 것을 λ³΄μ‹€μˆ˜ μžˆμŠ΅λ‹ˆλ‹€. μš°λ¦¬λŠ” μ§€κΈˆκ» λΈŒλΌμš°μ € ν™˜κ²½μ—μ„œ ν΄λΌμ΄μ–ΈνŠΈ λ Œλ”λ§μ„ μ‚¬μš©ν–ˆμ§€λ§Œ, 이제 λΈŒλΌμš°μ € ν™˜κ²½μ΄ μ•„λ‹Œκ³³μ—μ„œ λ Œλ”λ§μ„ ν•΄μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— Nodeκ°€ 싀행해쀄 파일이 ν•„μš”ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

package.json νŒŒμΌμ„ 보면 처음 λ³΄λŠ” scripts듀도 확인 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

    "dev:ssr": "ng run hybrid-rendering-app:serve-ssr",
    "serve:ssr": "node dist/hybrid-rendering-app/server/main.js",
    "build:ssr": "ng build && ng run hybrid-rendering-app:server",
    "prerender": "ng run hybrid-rendering-app:prerender"

ν‚€κ°’λͺ…칭을 보면 λŒ€μΆ© 어떀것을 ν•˜λŠ”κ²ƒμ΄κ² κ΅¬λ‚˜.. ν•˜λŠ” μ •λ„μ˜ 감은 μ˜€μ…¨μ„ κ²λ‹ˆλ‹€.

λ¨Όμ € prerendering을 해보기 μœ„ν•΄ route νŽ˜μ΄μ§€κ°€ ν•„μš”ν•œλ°, about와 contact λͺ¨λ“ˆμ„ μΆ”κ°€ν•˜κ³  λΌμš°ν„°μ— 등둝 μ‹œμΌœλ³΄κ² μŠ΅λ‹ˆλ‹€.

각각의 μ»΄ν¬λ„ŒνŠΈλ₯Ό 생성해 router에 등둝해도 λ˜μ§€λ§Œ μ•„λž˜μ™€ 같은 λͺ…λ Ήμ–΄λ₯Ό 톡해 μ‰½κ²Œ μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. (Angular ν”„λ ˆμž„μ›μ˜ μž₯점 이기도 ν•˜μ£ , λ³΅μž‘ν•΄ λ³΄μ΄μ§€λ§Œ 체계적이닀? ^^;)

ng g m about --route about --module app
 
ng g m contact --route contact --module app

Run

λ°”λ‘œ 사전 λ Œλ”λ§μ„ 해보죠!

npm run prerender

0101

dist 디렉토리λ₯Ό λ³΄μ‹œλ©΄ server, browser λ‘κ°œμ˜ λ””λ ‰ν† λ¦¬λ‘œ λ‚˜λˆ„μ–΄μ Έ μžˆλ„€μš”. server/main.js 이 파일이 nodeμ—μ„œ μ‹€ν–‰ν•΄μ£ΌλŠ” 파일이 λ˜λŠ”κ²ƒμ΄κ³ μš”, browser 디렉토리 내뢀에 μžˆλŠ” νŒŒμΌλ“€μ΄ λ Œλ”λ§λœ νŒŒμΌλ“€μž…λ‹ˆλ‹€. 그런데 index.html 파일만 μžˆλŠ”κ²Œ μ•„λ‹ˆκ³  router에 λ“±λ‘ν•œ about, contact의 index.htmlνŒŒμΌλ„ 각각의 디렉토리에 생성이 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
각각의 νŽ˜μ΄μ§€ μš”μ²­μ΄ 였면 미리 λžœλ”λ§ν•΄λ‘” index.htmlνŒŒμΌμ„ μ „λ‹¬ν•˜κΈ° μœ„ν•¨μ΄μ£ .

Options

그리고 angular.json 파일의 μ˜΅μ…˜μ •λ³΄λ₯Ό μ΄μš©ν•΄μ„œ μ›ν•˜λŠ” νŽ˜μ΄μ§€λ§Œ 사전 λ Œλ”λ§μ„ ν•΄λ‘˜μˆ˜κ°€ μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ about νŽ˜μ΄μ§€λ§Œ 사전 λ Œλ”λ§μ„ 해두고 μ‹Άλ‹€. 그럼 "guessRoutes": false, "routes" 배열에 λ Œλ”λ§ν•  νŽ˜μ΄μ§€λ§Œ μΆ”κ°€ν•΄μ€λ‹ˆλ‹€.

projects > hybrid-rendering-app > architect > prerender

"options" : {
  "guessRoutes": false,
  "routes": [
    "/about"
  ]
}

"routesFile": "./routes.txt" νŒŒμΌμ— κ²½λ‘œλ“€μ„ μ„€μ •ν• μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

더 μžμ„Έν•œ options μ •λ³΄λŠ” μ—¬κΈ°μ—μ„œ 확인해 μ£Όμ„Έμš”

이제 node둜 ν•΄λ‹Ή jsνŒŒμΌμ„ μ‹€ν–‰ν•΄μ£Όλ©΄ λ©λ‹ˆλ‹€.

Server Start

node dist\hybrid-rendering-app\server\main.js

Node Express server listening on http://localhost:4000

μ„œλ²„λ₯Ό ꡬ동해주고 λΈŒλΌμš°μ €μ— μ ‘μ†ν•΄μ„œ Network 탭을 μ‚΄νŽ΄ 보면 각 λΌμš°νŒ…μ— μ ‘κ·Όν•  λ•Œλ§ˆλ‹€ ν•΄λ‹Ή λ¬Έμ„œλ₯Ό λ‹€μš΄λ°›λŠ” 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

main
mainmain

about
aboutabout

contact
contactcontact

졜초 μ ‘μ†μ‹œ index.html νŒŒμΌμ„ λ°›μ•„ κ·Έμ•ˆμ—μ„œ javascript νŒŒμΌμ— μ˜ν•΄ λ™μ μœΌλ‘œ λ¬Έμ„œλ₯Ό λ³€κ²½ν•˜λŠ” SPAλ°©μ‹κ³ΌλŠ” 달리 λΌμš°ν„° μ ‘κ·Όμ‹œ 사전에 λ Œλ”λ§λœ λ¬Έμ„œλ₯Ό μ„œλ²„μ—μ„œ μ „λ‹¬ν•΄μ£Όκ²Œ λ©λ‹ˆλ‹€.

거의 변경이 μ—†λŠ” νŽ˜μ΄μ§€λ“€μ˜ 경우 μ΄λ ‡κ²Œ 사전에 λ Œλ”λ§μ„ 해두면 μ„±λŠ₯적인 λΆ€λΆ„μ—μ„œ 맀우 효휼적일 κ²ƒμ΄μ§€λ§Œ, νŽ˜μ΄μ§€ λ‚΄μš©μ΄ 자주 변경이 λœλ‹€κ±°λ‚˜ κ²Œμ‹œνŒ 같은 동적인 λΌμš°νŒ…μ„ μ‚¬μš©ν•œλ‹€λ©΄, options에 λ Œλ”λ§ν•  νŽ˜μ΄μ§€λ§Œ λͺ…μ‹œν•΄μ£Όλ©΄ μ„ νƒμ μœΌλ‘œ 사전 λ Œλ”λ§μ„ ν•  수 있게 λ˜λŠ” 것 μž…λ‹ˆλ‹€.