Gatsby: gatsby.js๋กœ ์•ฑ ๋นŒ๋“œ : ๋‹จ์ ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

์— ๋งŒ๋“  2017๋…„ 09์›” 28์ผ  ยท  37์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: gatsbyjs/gatsby

์•ˆ๋…•ํ•˜์„ธ์š”,

gatsby.js๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น ์•ฑ์„ ๋นŒ๋“œ ํ•œ ๋‹ค์Œ AWS S3 ๋ฐ CloudFront๋ฅผ ํ†ตํ•ด ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

node.js ์•ฑ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ๊ณผ ๋น„๊ตํ•  ๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜์žˆ๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

gatsby.js๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ๊ฐ„๋‹จ ํ•ด ๋ณด์ด๋ฉฐ ์ด๋ ‡๊ฒŒํ•˜๋ฉด ๋‚ด ์ฝ˜ํ…์ธ  ์›น ์‚ฌ์ดํŠธ๋ฅผ ๋‚ด ์•ฑ๊ณผ ์‰ฝ๊ฒŒ ํ†ตํ•ฉ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์นœ์• ํ•˜๋Š”,
๋‹ค๋‹ˆ์—˜

question or discussion

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

Woah woah woah @barbush ๋‚˜๋Š” ์ •๋ง๋กœ ๋‹น์‹ ์ด ์ด๋Ÿฐ ์งˆ๋ฌธ์„ ์น˜์•ˆํ•˜๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”์ฐํ•œ ์งˆ๋ฌธ (์ด๊ฒƒ์ด ์•„๋‹˜)์ด๋ผ๋ฉด ๋ฌด์‹œํ•˜๊ณ  ๊ทธ ์‚ฌ๋žŒ์—๊ฒŒ ๋งํ•˜๋Š” ๊ฒƒ์ด ๋‚ซ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ๋Š” ์ด์™€ ๊ฐ™์€ ์งˆ๋ฌธ์— ์‘๋‹ตํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

๊ท€ํ•˜์˜ ์งˆ๋ฌธ์— @bolus . Gatsby๋Š” ๋ฐ˜์‘ ์•ฑ ๋ฐ ๊ธฐํƒ€ ์›นํŒฉ / ๋ฐ˜์‘ ์„ค์ •์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ๊ณผ ์ƒ๋‹นํžˆ ์œ ์‚ฌํ•˜๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์›น ์•ฑ์„ ๋นŒ๋“œํ•˜๋Š” ๋ฐ ์™„๋ฒฝํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. examples ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋ณด๋ฉด redux ์˜ˆ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์€ Apollo์™€ ํ•จ๊ป˜ ๊ทธ๊ฒƒ์„ ์•„์ฃผ ์„ฑ๊ณต์ ์œผ๋กœ ์‚ฌ์šฉํ–ˆ๋‹ค๊ณ ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์˜ graphql ์‚ฌ์šฉ์ด ๊ทธ๋“ค์˜ ๊ฒƒ๊ณผ ์ถฉ๋Œํ•˜๊ธฐ ๋•Œ๋ฌธ์— Relay๋Š” gatsby์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์ง€๋งŒ ์•ž์œผ๋กœ๋Š” ์‰ฝ๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜์žˆ์„ ๊ฒƒ์ด๋ผ๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์•„๋Š” ๊ฐ€์žฅ ํฐ ๋‹จ์ ์€ ๋‹น์‹ ์ด "ํŽ˜์ด์ง€"๋ฅผ ๋งŒ๋“ค๊ณ  ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋งŒ์•ฝ ๋‹น์‹ ์ด ํŽ˜์ด์ง€๊ฐ€์—†๋Š” ์ง์„ ์  ์ธ ์•ฑ์„ ๋” ๋งŽ์ด ๋นŒ๋“œํ•œ๋‹ค๋ฉด ๊ทธ๊ฒƒ์€ ๋‹น์‹ ์—๊ฒŒ ๋งŽ์€ ๊ฒƒ์„์ฃผ์ง€ ์•Š๊ณ  ๋‹น์‹ ์˜ ์ž์œ ๋„ ์–ด๋Š ์ •๋„ ์ œํ•œ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ CRA์™€ ๊ฐ™์€ ๋” ๋ฐ”๋‹๋ผ ์„ค์ •์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ "ํŽ˜์ด์ง€"๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒฝ์šฐ gatsby๋Š” ์•ฑ์˜ ๋น ๋ฅธ ๋ถ€ํŒ…์„ ์œ„ํ•ด ์ž๋™ ์ฝ”๋“œ ๋ถ„ํ•  ๋ฐ ์ •์  SSR์„ ์–ป์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค.

์ข€ ๋” ๊ณต์‹์ ์ธ ํŠธ๋ ˆ์ด๋“œ ์˜คํ”„ ๋ฌธ์„œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์‹ถ์ง€๋งŒ ๊ทธ๋™์•ˆ ์—ฌ๊ธฐ์—์„œ ์งˆ๋ฌธ์„ ๋ฐ›๊ฒŒ๋˜์–ด ๊ธฐ์ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  37 ๋Œ“๊ธ€

๊ท€ํ•˜์˜ ์˜๊ฒฌ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค, @barbush. 68 ๋‹จ์–ด๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์„ ์ค„์€ ๋ชฐ๋ž์Šต๋‹ˆ๋‹ค.

ํ—ค๋“œ ๋ผ์ธ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ๊ฒƒ์„ ๋งํ•ฉ๋‹ˆ๋‹ค. gatsby.js๋กœ ์•ฑ์„ ๋นŒ๋“œ ํ•  ๋•Œ ์–ด๋–ค ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์•ฑ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ์งˆ๋ฌธ์€-gatsby.js๊ฐ€ ์ •์  ์›น ์‚ฌ์ดํŠธ ์ƒ์„ฑ์— ์ตœ์ ํ™”๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ค ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚˜์ค‘์— ์ €๋ฅผ ๋ฌผ๋ฆด ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?
๋‚˜์—๊ฒŒ ๊ฝค ๊ตฌ์ฒด์ ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Woah woah woah @barbush ๋‚˜๋Š” ์ •๋ง๋กœ ๋‹น์‹ ์ด ์ด๋Ÿฐ ์งˆ๋ฌธ์„ ์น˜์•ˆํ•˜๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”์ฐํ•œ ์งˆ๋ฌธ (์ด๊ฒƒ์ด ์•„๋‹˜)์ด๋ผ๋ฉด ๋ฌด์‹œํ•˜๊ณ  ๊ทธ ์‚ฌ๋žŒ์—๊ฒŒ ๋งํ•˜๋Š” ๊ฒƒ์ด ๋‚ซ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ๋Š” ์ด์™€ ๊ฐ™์€ ์งˆ๋ฌธ์— ์‘๋‹ตํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

๊ท€ํ•˜์˜ ์งˆ๋ฌธ์— @bolus . Gatsby๋Š” ๋ฐ˜์‘ ์•ฑ ๋ฐ ๊ธฐํƒ€ ์›นํŒฉ / ๋ฐ˜์‘ ์„ค์ •์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ๊ณผ ์ƒ๋‹นํžˆ ์œ ์‚ฌํ•˜๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์›น ์•ฑ์„ ๋นŒ๋“œํ•˜๋Š” ๋ฐ ์™„๋ฒฝํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. examples ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋ณด๋ฉด redux ์˜ˆ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์€ Apollo์™€ ํ•จ๊ป˜ ๊ทธ๊ฒƒ์„ ์•„์ฃผ ์„ฑ๊ณต์ ์œผ๋กœ ์‚ฌ์šฉํ–ˆ๋‹ค๊ณ ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์˜ graphql ์‚ฌ์šฉ์ด ๊ทธ๋“ค์˜ ๊ฒƒ๊ณผ ์ถฉ๋Œํ•˜๊ธฐ ๋•Œ๋ฌธ์— Relay๋Š” gatsby์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์ง€๋งŒ ์•ž์œผ๋กœ๋Š” ์‰ฝ๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜์žˆ์„ ๊ฒƒ์ด๋ผ๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์•„๋Š” ๊ฐ€์žฅ ํฐ ๋‹จ์ ์€ ๋‹น์‹ ์ด "ํŽ˜์ด์ง€"๋ฅผ ๋งŒ๋“ค๊ณ  ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋งŒ์•ฝ ๋‹น์‹ ์ด ํŽ˜์ด์ง€๊ฐ€์—†๋Š” ์ง์„ ์  ์ธ ์•ฑ์„ ๋” ๋งŽ์ด ๋นŒ๋“œํ•œ๋‹ค๋ฉด ๊ทธ๊ฒƒ์€ ๋‹น์‹ ์—๊ฒŒ ๋งŽ์€ ๊ฒƒ์„์ฃผ์ง€ ์•Š๊ณ  ๋‹น์‹ ์˜ ์ž์œ ๋„ ์–ด๋Š ์ •๋„ ์ œํ•œ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ CRA์™€ ๊ฐ™์€ ๋” ๋ฐ”๋‹๋ผ ์„ค์ •์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ "ํŽ˜์ด์ง€"๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒฝ์šฐ gatsby๋Š” ์•ฑ์˜ ๋น ๋ฅธ ๋ถ€ํŒ…์„ ์œ„ํ•ด ์ž๋™ ์ฝ”๋“œ ๋ถ„ํ•  ๋ฐ ์ •์  SSR์„ ์–ป์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค.

์ข€ ๋” ๊ณต์‹์ ์ธ ํŠธ๋ ˆ์ด๋“œ ์˜คํ”„ ๋ฌธ์„œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์‹ถ์ง€๋งŒ ๊ทธ๋™์•ˆ ์—ฌ๊ธฐ์—์„œ ์งˆ๋ฌธ์„ ๋ฐ›๊ฒŒ๋˜์–ด ๊ธฐ์ฉ๋‹ˆ๋‹ค.

@KyleAMathews : ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ œ๊ฐ€ ์ฐพ๋˜ ๋ฐ”๋กœ ๊ทธ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฝ˜ํ…์ธ  ์ค‘์‹ฌ ์›น ์‚ฌ์ดํŠธ (๋ธ”๋กœ๊ทธ, ํŒ๋งค ํŽ˜์ด์ง€, ๋ฌธ์„œ ๋“ฑ)๋ฅผ ๋งŒ๋“ค ๊ณ„ํš์ด๋ฉฐ, ๋‹จ์ˆœ์„ฑ์„ ์œ„ํ•ด ๋™์ผํ•œ ๋„๋ฉ”์ธ์— ๋ช‡ ๊ฐœ์˜ ์ž‘์€ ๋‹จ์ผ ํŽ˜์ด์ง€ ์•ฑ์„ ํ˜ธ์ŠคํŒ…ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

Gatsby๊ฐ€ ์ด๊ฒƒ์— ์ด์ƒ์ ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ๋‹น์‹ ์˜ ์ž์œ ๋ฅผ ๋‹ค์†Œ ์ œํ•œ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค

์ œ ์‚ฌ์šฉ ์‚ฌ๋ก€์—๋Š” ๋ฌธ์ œ๊ฐ€๋˜์ง€ ์•Š์ง€๋งŒ ์–ด๋–ค ์ œํ•œ ์‚ฌํ•ญ์„ ์˜ˆ์ƒ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ์–ด๋ ค์šด์ง€ ๋ง์”€ํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

Gatsby๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค, btw., Gatsby๋Š” ์ •๋ง ๋ฉ‹์ ธ ๋ณด์ž…๋‹ˆ๋‹ค! :)

ํ•˜์ง€๋งŒ ์ œ๊ฐ€ ๊ธฐ๋Œ€ํ•  ์ˆ˜์žˆ๋Š” ์ œํ•œ ์‚ฌํ•ญ๊ณผ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ์–ด๋ ค์šด์ง€ ๋ง์”€ํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

Gatsby๋Š” ๊ฐ€๋Šฅํ•œ ํ•œ ๋‹จ์ˆœํ•˜๊ณ  ๊ฒธ์† ํ•ด ์ง€๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๋ฏ€๋กœ ํŠนํžˆ Gatsby๊ฐ€ ์„ค๊ณ„ ํ•œ ์ฝ˜ํ…์ธ  / ํŽ˜์ด์ง€ ์›น ์‚ฌ์ดํŠธ๋ฅผ ์ˆ˜ํ–‰ ํ•  ๋•Œ ์ œํ•œ์— ๋ถ€๋”ชํžˆ์ง€ ์•Š์•„์•ผํ•ฉ๋‹ˆ๋‹ค.

Gatsby๋Š” ์›น ์•ฑ๊ณผ ์‚ฌ์ดํŠธ ์•„์ด๋””์–ด๋ฅผ ํ˜ผํ•ฉํ•˜์—ฌ ๊ฐ€๋Šฅํ•œ ํ•œ ์‰ฝ๊ฒŒ ์ •๋ง ๋น ๋ฅธ ์‚ฌ์ดํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ธฐ์œ„ํ•œ ์ด์ƒ์ ์ธ ๊ฐœ๋ฐœ ๋ฐ ์ƒ์‚ฐ ๋„๊ตฌ๋ฅผ ์šฐ๋ฆฌ ๋งˆ์Œ ์†์— ๋งŒ๋“ค์–ด ๋‚ด๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

"ํŽ˜์ด์ง€"๋ชจ๋ธ์—์„œ ๋ฒ—์–ด๋‚˜๋Š” ๋ฐฉ์‹์œผ๋กœ React๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์—๋งŒ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค (์˜ˆ : ๋” ๋งŽ์€ ์ž์œ ํ˜• ์•ฑ). ํ•˜์ง€๋งŒ ๊ฑฐ๊ธฐ์—์„œ๋„ Gatsby์—๋Š” ๋” ํฐ ์‚ฌ์ดํŠธ https://www.gatsbyjs.org/docs/creating-and-modifying-pages/#creating -client-only-routes ๋‚ด์— ์•ฑ์„ ์‰ฝ๊ฒŒ ํฌํ•จ ํ•  ์ˆ˜์žˆ๋Š” ํƒˆ์ถœ๊ตฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์™„๋ฒฝ ํ•ด ๋ณด์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ํ•œ ๋ฒˆ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

์•ˆ๋…•ํ•˜์„ธ์š” @KyleAMathews ์™€ @bolus

์—ฌ๊ธฐ์— ์ƒˆ๋กœ์šด ๋ฌธ์ œ๋ฅผ ์—ฌ๋Š” ๋Œ€์‹  ์ปจํ…์ŠคํŠธ์˜ ๊ธฐ์›์ „ ์ฃผ์„ heheh

๋‚ด /app (ํด๋ผ์ด์–ธํŠธ ์ „์šฉ ๊ฒฝ๋กœ) ๋‚ด๋ถ€์—์„œ SPA (๋กœ๊ทธ์ธ / ๋กœ๊ทธ ์•„์›ƒ / ๋Œ€์‹œ ๋ณด๋“œ)๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ๋‚ด๋ถ€์— ์ƒˆ ๋ผ์šฐํ„ฐ๋ฅผ ์ƒ์„ฑํ•ด์•ผํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด ์–ด๋–ป๊ฒŒ๋ฉ๋‹ˆ๊นŒ? ๋งž์Šต๋‹ˆ๊นŒ?

์ด ์œ ์Šค ์ผ€์ด์Šค @KyleAMathews ์—์„œ ๋ฌด์—‡์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๊นŒ? ์•„๋‹ˆ๋ฉด _ ๋” ๋ฐ”๋‹๋ผ ์ ‘๊ทผ ๋ฐฉ์‹ _์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์„๊นŒ์š”?

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค

@fernandes checkout https://www.gatsbyjs.org/docs/creating-and-modifying-pages/#creating -client-only-routes โ€” ์งˆ๋ฌธ์ด ๋” ์žˆ์œผ๋ฉด ์•Œ๋ ค์ฃผ์„ธ์š”!

์•ˆ๋…•ํ•˜์„ธ์š”, @KyleAMathews ๋น ๋ฅธ ๋‹ต์žฅ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค

ํ† ์š”์ผ ๋‚ด๋‚ด ๊ฐœ์ธ ๋น„์™€ ๋†€์•˜๊ณ ,์ด ์˜ˆ์ œ๋ฅผ ํ™•์ธํ•˜๊ณ  ๋‹ค์‹œ ํ•˜๋‚˜ ...

๋‚ด๊ฐ€ํ•˜๋ ค๋Š” ๊ฒƒ์€ https://github.com/fernandes/react-boilerplate๋ฅผ ๊ฐ€์ ธ ์™€์„œ /app ์— ํด๋ผ์ด์–ธํŠธ ์ „์šฉ ๊ฒฝ๋กœ๋กœ ๋„ฃ์œผ์‹ญ์‹œ์˜ค.

์ด ์ƒ์šฉ๊ตฌ๋Š” ๋‹ค์Œ์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.
๋ฐ˜์‘ / redux (ํ•ซ ๋ฆฌ๋กœ๋”ฉ ํฌํ•จ) / ๋ฐ˜์‘ ๋ผ์šฐํ„ฐ redux

๋‚˜๋Š” JS์— ๋Œ€ํ•œ ๊ฒฝํ—˜์ด ๋งŽ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ๋†“์นœ ์„ธ๋ถ€ ์‚ฌํ•ญ ์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค .. ๋‹ค์‹œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

react-boilerplate์™€ ๊ฐ™์€ ๋‚ด๋ถ€์— Gatsby๋ฅผ ๋„ฃ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. Gatsby๋Š” ๋นŒ๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‚ฌ์ดํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค. ๋Œ€์‹  Gatsby ์•ˆ์— "์•ฑ"๋ถ€๋ถ„์„ ๋„ฃ์œผ์‹ญ์‹œ์˜ค.

์˜ˆ, ๊ทธ๊ฒŒ ์ œ๊ฐ€ ์˜๋ฏธ ํ•œ ๋ฐ”์ž…๋‹ˆ๋‹ค ... ๊ฐœ์ธ ๋น„๋Š” ๋‚ด ๋ชจ๋“  ์›น ์‚ฌ์ดํŠธ์™€ ํŽ˜์ด์ง€๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  react-boilerplate ์€ ํด๋ผ์ด์–ธํŠธ ์ „์šฉ ๊ฒฝ๋กœ๋กœ /app ์•„๋ž˜์˜ ๊ฐœ์ธ ๋น„ ๋‚ด๋ถ€์— ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. ๊ทธ ์Šคํƒ, ํŠนํžˆ react-router-redux)?

Gatsby๋Š” ์ด๋ฏธ ๋ชจ๋“  webpack / Babel / ๊ธฐํƒ€ ๊ตฌ์„ฑ์„ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ ๋ถ€ํŠธ ์ŠคํŠธ๋žฉ ํ”„๋กœ์ ํŠธ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@KyleAMathews ๋‚˜๋Š” redux + apollo ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ž‘๋™ํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ ์ „์šฉ ์•ฑ์„ ์–ป๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„ ๋ƒˆ์Šต๋‹ˆ๋‹ค .. ๋‹ต์žฅ์„ ๋ณด๋‚ด ์ฃผ์…”์„œ ๋Œ€๋‹จํžˆ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ๐Ÿ˜‰ ๐Ÿ‘

@KyleAMathews ์—ฌ๊ธฐ์— ์ž‘์€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์ „์šฉ ํŽ˜์ด์ง€ ๋‚ด์—์„œ graphql apollo ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€๋งŒ ํด๋ผ์ด์–ธํŠธ ์ธก์—๋งŒ ํ•ด๋‹น๋ฉ๋‹ˆ๋‹ค (๋กœ๊ทธ์ธํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ).ํ•˜์ง€๋งŒ Gatsby๋Š” ์ธ๋ฑ์Šค ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค. ๋นŒ๋“œ์‹œ; ๋ฌผ๋ก  ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ

์ด HTML ์ƒ์„ฑ์„ ๊ฑด๋„ˆ ๋›ฐ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ œ์•ˆ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ตœ์‹  ์ •๋ณด:
https://www.gatsbyjs.org/packages/gatsby-plugin-create-client-paths/๋ฅผ ์‚ฌ์šฉํ•˜๊ณ 

๊ทธ ํ”Œ๋Ÿฌ๊ทธ์ธ ์ƒ์„ฑ deletePage ์— ๋”ฐ๋ผ page.path ... ํ™•์‹คํ•˜์ง€๊ฐ€ ๐Ÿ˜„ ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•,ํ•˜์ง€๋งŒ ๋‚ด ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋Œ€ํ•ด ์ž‘์—…ํ•˜๋Š” ๊ฒฝ์šฐ (์˜ˆ, ์ง€๊ธˆ์€ ๋งŒ๋“ค ํ•„์š”, ๊ทธ๊ฒƒ์€ ์™„๋ฒฝํ•˜๊ฒŒ ์ž‘๋™ํ•˜๊ณ ๋ฅผ ํ•ญ์ƒ ๋‚ด app/index.html ๋ณด๋‚ด๋Š” nginx์˜ ๋ฆฌ๋””๋ ‰์…˜ ๊ทœ์น™์ด์ง€๋งŒ ์ด์ „ ์•ฑ์—์„œ ์ •ํ™•ํžˆ ์ˆ˜ํ–‰ ํ•œ ์ž‘์—…์ž…๋‹ˆ๋‹ค ...

๋‚˜๋Š” ๊ฐœ์ธ ๋น„์— ์ ์  ๋” ์ต์ˆ™ํ•ด์ง€๊ณ  ์žˆ๊ณ , ๋‚ด๊ฐ€ํ•˜๋Š” ๋ชจ๋“  ์ง„์ „์ด ๋” ํ–‰๋ณตํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๊ณ ๋ฐฑ ํ•  ํ•„์š”๊ฐ€์žˆ๋‹ค ... ๊ต‰์žฅํ•œ ์ž‘์—… @KyleAMathews !! ๐Ÿ‘

@KyleAMathews ์—ฌ๊ธฐ ๊ท€์ฐฎ๊ฒŒํ•ด์„œ ๋ฏธ์•ˆํ•˜์ง€๋งŒ ํด๋ผ์ด์–ธํŠธ ์ธก ๋ผ์šฐํŒ…์— ๋Œ€ํ•ด ๋ฌผ์–ด๋ณผ ์ˆ˜์žˆ๋Š” ์ข‹์€ ์žฅ์†Œ ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋‚ด ์‚ฌ์šฉ ์‚ฌ๋ก€์—์„œ๋Š” firebase์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ณ  ์žˆ์ง€๋งŒ ์‚ฌ์šฉ์ž๊ฐ€ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—์ด ๋ฐ์ดํ„ฐ๋Š” ๋นŒ๋“œ์‹œ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ Gatsby Page (์˜ˆ : / podcasts)์—์„œ cDM์˜ firebase์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์‰ฝ๊ฒŒ ์ฟผ๋ฆฌ ํ•  ์ˆ˜ โ€‹โ€‹์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์„ธ๋ถ€ ์ •๋ณด ํŽ˜์ด์ง€ (์˜ˆ : / podcast / : id)๋กœ ์ด๋™ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์กฐ๊ธˆ ์žƒ์–ด๋ฒ„๋ฆฐ ๋ถ€๋ถ„์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ๊ฒฝ๋กœ๋ฅผ ํด๋ผ์ด์–ธํŠธ ์ธก ๋ผ์šฐํŒ…์— ์œ„์ž„ํ•ด์•ผํ•ฉ๋‹ˆ๊นŒ?

/app ํ’๊ฒฝ ํ•ด์น˜์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๋Š” ๊ทธ ์•„๋ž˜์— SPA๋ฅผ ๋‘˜ ์ˆ˜์žˆ๋Š” ์žฅ์†Œ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ž„์„ ์ดํ•ดํ•˜์ง€๋งŒ ๋‚ด๊ฐ€ํ•˜๋ ค๋Š” ์ž‘์—…์— ๋Œ€ํ•ด์„œ๋Š” ๊ณผ์ž‰ ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ฐœ์ธ ๋น„์—์„œ ์ผ ํ•ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ณณ์—์„œ ํ›Œ๋ฅญํ•œ ๊ฒฝํ—˜์ด์—ˆ์Šต๋‹ˆ๋‹ค. :)

@gafemoyano ๊ฐ€ /podcast/:id ๋Œ€ํ•œ ๊ฒฝ๋กœ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ์‚ฌ์šฉ์ž๊ฐ€ ์ž‘์—…ํ•˜๋Š” ๋™์•ˆ ๋งŒ๋“  ํŒŸ ์บ์ŠคํŠธ๊ฐ€ ์žˆ๋‹ค๋ฉด ์™„์ „ํžˆ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•œ ๊ฐ€์ง€ ๋‹จ์ ์€ ํŒŸ ์บ์ŠคํŠธ ํŽ˜์ด์ง€๋ฅผ ์ง์ ‘ ๋ฐฉ๋ฌธํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์˜ TTFP ์†๋„๊ฐ€ ๋Š๋ ค์ง„๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์ œ ์„œ๋ฒ„์—์„œ HTML์„๋กœ๋“œํ•˜์—ฌ๋กœ๋“œ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋นŒ๋“œ์‹œ ์กด์žฌํ•˜๋Š” ํŒŸ ์บ์ŠคํŠธ ํŽ˜์ด์ง€๋ฅผ ์ •์ ์œผ๋กœ ๋ Œ๋”๋ง ํ•œ ๋‹ค์Œ ์‚ฌ๋žŒ๋“ค์ด ๋งŒ๋“ค ๋•Œ ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋” ๋งŽ์€ ๊ฒƒ์„ ์ฆ‰์„์—์„œ ์ƒ์„ฑ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€์—์žˆ๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ํฅ๋ฏธ ๋กœ์›€ โ€” Gatsby https://www.gatsbyjs.org/docs/building-apps-with-gatsby/๋กœ ์•ฑ์„ ๋นŒ๋“œํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ์ด ์ƒˆ ๋ฌธ์„œ ํŽ˜์ด์ง€๋ฅผ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ—ค์ด @KyleAMathews ์ด๊ฒƒ์ด ๊ณต์‹์ ์ธ "ํด๋ผ์ด์–ธํŠธ ์ธก ๋ฌธ์ œ"๊ฐ€ ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— hahah ํŒŸ ์บ์ŠคํŠธ ํ”„๋ก ํŠธ ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ๋ฅผ ๋ชจ๋‘ ์ œ์–ด ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ๊ณ ๋ คํ•  ๋•Œ์ด ํŒŸ ์บ์ŠคํŠธ ๋ฌธ์ œ์— ๋Œ€ํ•ด ๊ณ ๋ คํ•ด ์™”๋˜ ๋˜ ๋‹ค๋ฅธ ์‚ฌํ•ญ์€ ํŠน์ • ํŽ˜์ด์ง€ ๋งŒ ์žฌ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ? ? ๋˜๋Š” ๋นŒ๋“œ๋ฅผ ์บ์‹œํ•˜๊ณ  ์ˆ˜์ • ๋œ ๋‚ด์šฉ ๋งŒ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ ์ž‘๋™ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

https://github.com/gatsbyjs/gatsby/issues/3444 ๊ด€๋ จ ๊ฐ€๋Šฅ

https://github.com/gatsbyjs/gatsby/issues/3260#issuecomment -352856214์— ์ €์žฅํ•  ํ‚ค / ๊ฐ’ ์บ์‹œ API์— ๋Œ€ํ•ด ๋Œ“๊ธ€์„ ๋‹ฌ์•˜์Šต๋‹ˆ๋‹ค. ๋ ˆ์ด์•„์›ƒ + ํŽ˜์ด์ง€ ์ฝ˜ํ…์ธ ๊ฐ€์žˆ๋Š” ๊ฒฝ์šฐ ๋ฐ์ดํ„ฐ ๋ฐ ์‹œ๊ฐ)

@KyleAMathews ๋‹ต์žฅ์„ ํ•˜์ง€ ์•Š์•„์•ผํ•ฉ๋‹ˆ๋‹ค .

` // page.matchPath is a special key that's used for matching pages
  // only on the client.
  if (page.path.match(/^\/podcasts/:id/)) {
    page.matchPath = "/podcasts/:id";

    // Update the page.
    createPage(page);
  }

๊ทธ๋Ÿฌ๋‚˜ ์˜คํžˆ๋ ค ์˜ˆ์ œ์— ํ‘œ์‹œ๋œ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

```
// page.matchPath๋Š” ํŽ˜์ด์ง€ ์ผ์น˜์— ์‚ฌ์šฉ๋˜๋Š” ํŠน์ˆ˜ ํ‚ค์ž…๋‹ˆ๋‹ค.
// ํด๋ผ์ด์–ธํŠธ์—์„œ๋งŒ.
if (page.path.match (/ ^ / app /)) {
page.matchPath = "/ app / : path";

// Update the page.
createPage(page);

}

And on app/index.js I would define my routes by importing from ReactRouter directly:

'react-router-dom'์—์„œ {Switch, Route} ๊ฐ€์ ธ ์˜ค๊ธฐ
const AppIndex = () => (







)
```

/ app / podcasts / : id๋ฅผ ๋ฐฉ๋ฌธํ•˜์—ฌ ๊ตฌ์„ฑ ์š”์†Œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ ์˜ค๊ธฐ ์œ„ํ•ด ๊ฒฝ๋กœ์˜ : id ๋ถ€๋ถ„์— ์•ก์„ธ์Šค ํ•  ์ˆ˜์žˆ๋Š” PodcastDetails๋ฅผ ๋ Œ๋”๋ง ํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

๊ฐ„๋‹จํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค๋กœ ๋ถˆํŽธ์„ ๋ผ์ณ ๋“œ๋ ค ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ์˜ˆ์ œ๋กœ๋Š” ์•Œ์•„๋‚ผ ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์ด ๊ฐœ์ธ ๋น„๋กœํ•˜๋Š” ์ผ์ด ์ƒ๋‹นํžˆ ํ”ํ•˜๋‹ค๋ฉด ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์•ฑ์˜ ์˜ˆ๋ฅผ ํฌํ•จํ•ด์•ผํ• ๊นŒ์š”? ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๊ธฐ๊บผ์ด ๋„์™€ ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ @KyleAMathews๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ์ง€์› ํ•ด์ฃผ์…”์„œ ๋‹ค์‹œ ํ•œ ๋ฒˆ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

์˜ˆ์ œ์—์„œ ๊ฒฝ๋กœ์˜ app ๋ถ€๋ถ„์€ ์ž„์˜์ ์ž…๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๋ชจ๋“  ์ด๋ฆ„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์˜ˆ : podcasts .

์˜ˆ์ œ ์‚ฌ์ดํŠธ๊ฐ€ ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. :-) ๊ณง ์‹œ๊ฐ„์ด ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ์ด๋ฏธ ํ•ด๊ฒฐ ํ•œ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์„ ์ดˆ๋Œ€ํ•˜์—ฌ ์ƒ˜ํ”Œ ์ฝ”๋“œ๋ฅผ ๊ณต์œ ํ•˜์„ธ์š”!

์—ฌ๊ธฐ์— ๋ช‡ ๊ฐ€์ง€ ์ƒ˜ํ”Œ ์ฝ”๋“œ๋ฅผ ์‹œ๋„ํ•˜๊ณ 

ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
๋‚ด๊ฐ€ ์—ฌ๊ธฐ์„œ ์„ค๋ช…ํ•œ ํ•˜๋‚˜
๊ฐ„๋‹จํžˆ ๋งํ•ด, ํ”„๋กœ๋•์…˜ ์šฉ์œผ๋กœ ๋นŒ๋“œํ•˜๊ณ  /app/ ๋””๋ ‰ํ† ๋ฆฌ ์•„๋ž˜์˜ ๊ฒฝ๋กœ (์˜ˆ : localhost:9000/app/posts/1 ๋“ค์–ด๊ฐ€ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์ƒˆ๋กœ ๊ณ ์น˜๋ฉด 404 ๋นˆ ํŽ˜์ด์ง€๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
localhost:9000/app/ ์—์„œ ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ ๊ณ ์น˜๋ฉด ์ œ๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.
gatsby-plugin-create-client-paths ๋Œ€ํ•œ prefixes ๊ตฌ์„ฑ์ด ์ž˜๋ชป๋˜์—ˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

module.exports = {
  ...
  plugins     : [
    {
      resolve: `gatsby-plugin-create-client-paths`,
      options: {prefixes: [`/app/*`]},
    },
    ...
};

๋˜ ๋‹ค๋ฅธ ๋ฌธ์ œ๋Š” (๋ฌธ์ œ์ธ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Œ) <Route /> ์„ <BrowserRouter> ๋ž˜ํ•‘ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
ํ”„๋กœ๋•์…˜ ์šฉ์œผ๋กœ ๋นŒ๋“œ ํ•  ๋•Œ (๊ฐœ๋ฐœ์ด ์ž˜ ์ž‘๋™ ํ•จ) "๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ก์— DOM์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค"๋ผ๋Š” ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. Gatsby๊ฐ€ ๋…ธ๋“œ ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰๋˜๊ณ  ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์—†์œผ๋ฏ€๋กœ window ๋“ฑ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ <BrowserRouter> ๋žฉ์„ ์ œ๊ฑฐํ–ˆ๋Š”๋ฐ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.
์ €๋Š” React๋ฅผ ์ฒ˜์Œ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ์— ๋Œ€ํ•œ ์ ์ ˆํ•œ ํ•ด๊ฒฐ์ฑ…์ธ์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋„์›€์„ ๋ฐ›๊ณ  ์‹ถ์–ด์š” :)

@danielemesh ์•ˆ๋…•ํ•˜์„ธ์š” Daniel. ๋‚ด ๊ฐœ์ธ ๋น„ ์•ฑ์„ ๋‹ค์‹œ ์ž‘์—… ํ•  ์‹œ๊ฐ„์ด ์—†์—ˆ์ง€๋งŒ ์†Œ์Šค ์ฝ”๋“œ์—์„œ ๋ณผ ์ˆ˜์žˆ๋Š” ๊ฒƒ์€ /pages ๋‚ด์— /app/* ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋ฐฐ์น˜ํ–ˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด๊ฒƒ์ด ์–ด๋””๋กœ ๊ฐ€์•ผํ• ์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. src/ ๋””๋ ‰ํ† ๋ฆฌ์— ๋„ฃ์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ž‘๋™ํ•˜๋Š”์ง€ ์•Œ๋ ค์ฃผ์„ธ์š”!

๊ฑด๋ฐฐ!

@gafemoyano๊ฐ€ ์‹œ๋„ํ–ˆ์ง€๋งŒ ์ž‘๋™ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.
๊ฐœ์ธ ๋น„๋Š” ์ธ์‹ํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค ..

๊ฐ์‚ฌ!

๋‚˜๋Š” ๋ช‡๋ช‡ ํ”Œ๋Ÿฌ๊ทธ์ธ์— ์ง๋ฉดํ•˜์—ฌ ๋‚ด ๊ฒƒ์„ ์ž‘์„ฑํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค (์›๋ž˜ ํ”Œ๋Ÿฌ๊ทธ์ธ์—์„œ 100 % ๋นŒ๋ ค ์˜ด), ์šด ์ข‹๊ฒŒ๋„ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  ๊ฐœ์ธ ๋น„ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šธ ์ˆ˜์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ถ”์ถœํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ๋ฌธ์ œ๋Š” app ๋‚ด๋ถ€์˜ bc์— SSR์—์„œ ์ฒ˜๋ฆฌํ•ด์„œ๋Š” ์•ˆ๋˜๋Š” graphql ์ฟผ๋ฆฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

@KyleAMathews ์˜ˆ์ œ ์‚ฌ์ดํŠธ์˜ ์˜๋ฏธ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์–ด๋”˜๊ฐ€์— ์ถ”๊ฐ€ ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ๋‚ด๊ฐ€ ํ•  ์ˆ˜์žˆ์–ด ..

gatsby-config.js

plugins: [
    `app-layout`, // I set my layout
    {
      resolve: `app-client-only`, // I handle app pages
      options: { prefixes: [`/app/*`] },
    },
  ],

plugins / app-layout / gatsby-node.js

// Implement the Gatsby API โ€œonCreatePageโ€. This is
// called after every page is created.
exports.onCreatePage = ({ page, boundActionCreators }) => {
  const { createPage } = boundActionCreators;

  if (page.path.match(/^\/app/)) {
    // It's assumed that `app.js` exists in the `src/layouts/` directory
    page.layout = "app";
  }

  return true;
};

plugins / app-client-only / gatsby-node.js

// Prefixes should be globs (i.e. of the form "/*" or "/foo/*")
const validatePrefixEntry = prefix => {
  if (!prefix.match(/^\//) || !prefix.match(/\/\*$/)) {
    throw Error(
      `Plugin "gatsby-plugin-client-only-paths" found invalid prefix pattern: ${
        prefix
      }`
    )
  }
}

exports.onCreatePage = ({ page, store, boundActionCreators }, { prefixes }) => {
  const { createPage, deletePage } = boundActionCreators
  const re = {}
  prefixes.forEach(validatePrefixEntry)

  return new Promise(resolve => {
    // Don't set matchPath again if it's already been set.
    if (page.matchPath || page.path.match(/dev-404-page/)) {
      resolve()
    }

    prefixes.some(prefix => {
      if (!re[prefix]) {
        // Remove the * from the prefix and memoize
        const trimmedPrefix = prefix.replace(/\*$/, ``)
        re[prefix] = new RegExp(`^${trimmedPrefix}`)
      }

      // Ensure that the path ends in a trailing slash, since it can be removed.
      const path = page.path.match(/\/$/) ? page.path : `${page.path}/`

      if (path.match(re[prefix])) {
        page.matchPath = prefix.replace(/\*$/, `:path`)
        if (path != '/app/') {
          // <<<<<<<<<<<<<<<<< here is my modification >>>>>>>>>>>>>>>>>>>>>>>
          // do not try to process on SSR, user needs to be logged to
          // consume GraphQL API and render `app` pages correctly
          deletePage(page)
          // <<<<<<<<<<<<<<<<< here is my modification >>>>>>>>>>>>>>>>>>>>>>>
        }
        // createPage(page)
        return true
      }

      return false
    })

    return resolve()
  })
}

๋”ฐ๋ผ์„œ์ด ๋ฌธ์ œ๊ฐ€ @KyleAMathews ์™€ 100 % ๊ด€๋ จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€

pages / app / index.js :

import CreateSchedule from './components/CreateSchedule'
import ViewSchedule from './components/ViewSchedule'
...
  <ApolloProvider client={client}>
        <Provider store={store}>
          <Switch>
            <Route exact path="/app" component={CreateSchedule} />
            <Route path="/app/:id" component={ViewSchedule} />
          </Switch>
        </Provider>
      </ApolloProvider>

gatsby-node.js

exports.onCreatePage = async ({ page, boundActionCreators }) => {
  const { createPage } = boundActionCreators

  // page.matchPath is a special key that's used for matching pages
  // only on the client.
  if (page.path.match(/^\/app/)) {
    page.matchPath = '/app/:path'

    // Update the page.
    createPage(page)
  }
}

์šด์—†์ด gatsby-plugin-create-client-paths ํ”Œ๋Ÿฌ๊ทธ์ธ๋„ ์‚ฌ์šฉํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

๋‚ด CreateSchedule ๊ตฌ์„ฑ ์š”์†Œ๋Š” 404ing ์—†์ด๋„ ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค : https://www.appointmentscheduler.org/app

ViewSchedule ๊ฒฝ๋กœ / ๊ตฌ์„ฑ ์š”์†Œ์— ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค : https://www.appointmentscheduler.org/app/1b42d8e8-66b5-4a8d-a0b5-fd4bb13bed09

์•„ ๊ทธ๋ฆฌ๊ณ  404๋Š” ๋นŒ๋“œ ๋œ ํ›„์— ๋งŒ โ€‹โ€‹๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ ์„œ๋ฒ„์—๋Š”์ด ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์–ด๋–ค ์•„์ด๋””์–ด?

@rozenmd ์„œ๋ฒ„ ๋ผ์šฐํŒ…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. netlify๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ gatsby-plugin-netlify ์„ (๋ฅผ) ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ž๋™์œผ๋กœ ์„œ๋ฒ„ ๋ผ์šฐํŒ… ๊ตฌ์„ฑ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค (netlify-identity-widget์ด ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์‚ฌ์ดํŠธ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐ ์ •ํ™•ํžˆ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค)

๋Œ€๋ฐ•!
๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค @pieh!
๋‚ด๊ฐ€ ์‚ฌ์šฉํ•œ netlify ์Šคํƒ€ํ„ฐ (https://github.com/konsumer/gatsby-starter-bootstrap-netlify)์— gatsby-config.js์— 'gatsby-plugin-netlify' ๊ฐ€)์—†๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ๋ฐฐํฌํ•˜๋ฉด์ด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค .๐Ÿ˜„

@KyleAMathews Gatsby๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ž ์žฌ์ ์œผ๋กœ ํ•œ ๊ฐ€์ง€ ์ถ”๊ฐ€ ๋ฌธ์ œ๋Š” Gatsby์˜ ์ „์ฒด API๋ฅผ ํ•œ ๋ฒˆ์— ๋น ๋Š” ํŠน์„ฑ์œผ๋กœ ์ธํ•ด API๊ฐ€ ํ˜ธ์ŠคํŒ…๋˜๋Š” ์„œ๋ฒ„์—์„œ 503 (์„œ๋น„์Šค ๊ฑฐ๋ถ€) ์‘๋‹ต์ด ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ž…๋‹ˆ๋‹ค. ์ ‘๊ทผํ•˜๋‹ค. ๋‚˜๋Š” ํ˜„์žฌ GoDaddy ํ˜ธ์ŠคํŒ…์—์„œ ์ด๊ฒƒ์„ ๊ฒฝํ—˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. 'gatsby develop'์„ ์‹คํ–‰ํ•˜๋ฉด ์ตœ๋Œ€ ๋™์‹œ ์—ฐ๊ฒฐ ์ œํ•œ์— ์ฆ‰์‹œ ๋„๋‹ฌํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์‹ค์ œ๋กœ ์ง„ํ–‰๋˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? ๋กœ์ปฌ์—์„œ๋Š” ํ›Œ๋ฅญํ•˜๊ฒŒ ์ž‘๋™ํ•˜์ง€๋งŒ (๋ถ„๋ฆฌ ๋œ Drupal> Gatsby) GoDaddy์—์„œ ํ˜ธ์ŠคํŒ… ํ•  ๋•Œ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ํŒ์ด๋ผ๋„ ๋Œ€๋‹จํžˆ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@ cf73 GoDaddy DNS๋ฅผ Netlify์™€ ๊ฐ™์€ Gatsby์— ๋” ์ ํ•ฉํ•œ ๊ฒƒ์œผ๋กœ ์ง€์ •ํ•ด ๋ณด์…จ์Šต๋‹ˆ๊นŒ?

@rozenmd ๋ฅผ ๋ช…ํ™•ํžˆํ•˜๊ธฐ ์œ„ํ•ด drupal ํ—ค๋“œ๋ฆฌ์Šค CMS๋Š” GoDaddy์—์„œ ํ˜ธ์ŠคํŒ…๋ฉ๋‹ˆ๋‹ค. Gatsby ์‚ฌ์ดํŠธ๋Š” ์—ฌ์ „ํžˆ ๋กœ์ปฌ์—์„œ ์‹คํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋‚ด๊ฐ€ ๋‹น์‹ ์„ ์˜คํ•ดํ•˜์ง€ ์•Š๋Š” ํ•œ, Netlify๊ฐ€ ์–ด๋–ป๊ฒŒ ๋„์šธ ์ˆ˜ ์žˆ๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์–ด์š”?

@ cf73 https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-drupal/src/gatsby-node.js๋Š” ์•„๋งˆ๋„ ์–ด๋–ค ์ข…๋ฅ˜์˜ ๋Œ€๊ธฐ์—ด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์šฐ๋ฆฌ๋Š” better-queue ๋‹ค๋ฅธ ๊ณณ์—์„œ๋Š”) Promise.all ๋Œ€์‹  ๋™์‹œ ์š”์ฒญ์„๋ณด๋‹ค ๊ด€๋ฆฌํ•˜๊ธฐ ์‰ฌ์šด ๊ฒƒ์œผ๋กœ ์ œํ•œํ•ฉ๋‹ˆ๋‹ค. ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์‹ญ๋‹ˆ๊นŒ?

@pieh yes ๋‚˜๋Š” ๋” ๋‚˜์€ ๋Œ€๊ธฐ์—ด์˜ ์‚ฌ์šฉ์„ ๋ณด์•˜๊ณ  ๊ดœ์ฐฎ์€ ์†”๋ฃจ์…˜์ฒ˜๋Ÿผ ๋“ค๋ฆฝ๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ๋‚ด๊ฐ€ ์Šค์Šค๋กœ ํ•  ์ˆ˜๋Š” ์—†์„ ๊นŒ๋ด ๋‘๋ ต๋‹ค. ๋‚ด๊ฐ€ ์ž‘์—…์ค‘์ธ ๋Œ€ํ˜• ํด๋ผ์ด์–ธํŠธ ํ”„๋กœ์ ํŠธ์˜ 503 ์˜ค๋ฅ˜๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ์—ฌ๊ธฐ์—์„œ ์šฐ์—ฐํžˆ ์šฐ์—ฐํžˆ ๋ฐœ๊ฒฌํ–ˆ๋‹ค. Gatsby๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค. ๋งˆ๊ฐ์ผ์ด ์ด‰๋ฐ•ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์•ž์œผ๋กœ ๋ช‡ ์‹œ๊ฐ„ ๋˜๋Š” ๊ธฐ๊ปํ•ด์•ผ ๋‹ค์Œ ๋‚  ์ •๋„์—์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์—†๋‹ค๋ฉด ๋‹ค๋ฅธ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์ฐพ์•„์•ผํ•ฉ๋‹ˆ๋‹ค. ๋ˆ„๊ตฌ๋“ ์ง€์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ฆ‰์‹œ ํ•  ์ˆ˜์žˆ๋Š” ์ž‘์—… (ํ•„์š”ํ•œ ๊ฒฝ์šฐ ํ˜ธ์ŠคํŒ… ์ „ํ™˜ ํฌํ•จ)์„ ์ œ์•ˆ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๊ฒ€์ฆ ๋œ drupal + ํ˜ธ์ŠคํŒ… + Gatsby ์›Œํฌ ํ”Œ๋กœ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

@ cf73 ๋งˆ๊ฐ์ผ์— ๋Œ€ํ•ด ๋Š๋‚๋‹ˆ๋‹ค

@pieh ๋Œ€๋‹จ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค, ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค !!

@KyleAMathews ์ €๋Š” ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ดํŠธ์—์„œ ์ž‘์—…ํ•˜๋Š” ๋™์•ˆ ์ ˆ๋ฐ•ํ•œ ๋ฌธ์ œ์— ์ง๋ฉดํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. Stack์€ Gatsby์˜ graphiql์— ๋Œ€ํ•œ Drupal JSON-API์ž…๋‹ˆ๋‹ค. ๋…ธ๋“œ์— ์ธ์ˆ˜๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค (์ฒจ๋ถ€ ์ฐธ์กฐ). ๋‚ด๊ฐ€ ๋งํ•  ์ˆ˜์žˆ๋Š” ํ•œ, ์ด๊ฒƒ์€ Gatsby์˜ Drupal ์Šคํ‚ค๋งˆ๊ฐ€ ์™„์ „ํžˆ ๊ตฌ์ฒดํ™”๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๊นŒ? ์•„๋‹ˆ๋ฉด ๋‹จ๊ณ„๋ฅผ ๋†“์น˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? ๊ธด๊ธ‰ํ•˜๊ณ  ๋งŽ์€ ๋„์›€์„ ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!
unknown-arg

์ฟผ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์•„์•ผํ•ฉ๋‹ˆ๋‹ค.

NodeArticle(id: { eq: GUID }) {
  id
  ...otherFields
}

ID๋กœ allNodeArticle ๋ฅผ ํ•„ํ„ฐ๋ง ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ํ•˜๋‚˜๋งŒ ์„ ํƒํ•˜๋Š” ๊ฒฝ์šฐ NodeArticle ์ง์ ‘ ์ฟผ๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ๋” ๊น”๋”ํ•ฉ๋‹ˆ๋‹ค.

@KyleAMathews ์ •๋ง ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ์ด๊ฒƒ์ด ๋‹ค๋ฃจ๋Š” ๋ฌธ์„œ๋ฅผ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚˜๋Š” ์ง€๊ธˆ๊นŒ์ง€ ์ด๊ฒƒ์„ ๋ณด์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค ... Gatsby๊ฐ€ Drupal๊ณผ ๋Œ€ํ™”ํ•˜๋Š” ๋ฐฉ์‹์— ๊ณ ์œ ํ•ฉ๋‹ˆ๊นŒ, ์•„๋‹ˆ๋ฉด ๋ฐฉ๊ธˆ ๋†“์นœ GraphQL์˜ ํ•ต์‹ฌ ํ‘œ์ค€ ๋™์ž‘์ž…๋‹ˆ๊นŒ? ์†Œ์Šค ํ”Œ๋Ÿฌ๊ทธ์ธ๊ณผ ํ•จ๊ป˜ ์ด์™€ ๊ฐ™์€ ์†Œ์Šค ๋ณ„ ๋ฌธ์„œ๋ฅผ ๋” ๋ˆˆ์— ๋„๊ฒŒ ํ™๋ณดํ•˜๋Š” ์•„์ด๋””์–ด๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์ด๊ฒƒ์€ drupal ํŠน์ •์ด ์•„๋‹Œ gatsby ํ•ต์‹ฌ ๊ธฐ๋Šฅ (๋ฃจํŠธ ์ฟผ๋ฆฌ ์ˆ˜์ค€ ํ•„ํ„ฐ๋ง ์ˆ˜ํ–‰)์ž…๋‹ˆ๋‹ค. ์†Œ์Šค ํ”Œ๋Ÿฌ๊ทธ์ธ์€ graphql ์Šคํ‚ค๋งˆ๋ฅผ ์ •์˜ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์ œ๊ณตํ•˜๋Š” "์›์‹œ"๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ gatsby core๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์ž…๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰