ํ์ฌ ๊ตฌ์ฑ ์์๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ๋ ๋๋งํ๊ธฐ ์ ์ 404
ํ์ด์ง๋ฅผ ๊น๋ฐ์ด๋ post/:id
๊ฒฝ๋ก์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ์ฒ์์๋ post/id
ํ์ด์ง์์ ์ฑ ์ํ๋ฅผ filter
๋ก ํ์ธํ๋ ๊ฒ์ด ์์ ๋ผ์ฐํ
์ ์ฌ์ฉํ์ฌ ํ์๋์ด์ผ ํ๋ ๊ตฌ์ฑ ์์๊ฐ ๋ฌด์์ธ์ง ํ์ธํ๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ด redux ๊ด๋ จ ๋ฌธ์ ๋ผ๊ณ ์๊ฐํ์ต๋๋ค.
slack ์ฑ๋์์ ์ด์ ๋ํด ๋ ผ์ํ ํ ๊ฐ ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ์ ๊ฒ์ํ๋ ๋ ๋ค๋ฅธ API ํธ์ถ์ ์ถ๊ฐํ์ง๋ง ์ฌ์ ํ ๋์ผํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์์ ๋น ๋ฅด๊ฒ ๋ฐ๊ฒฌํ์ต๋๋ค. ๋๋ ์ด๊ฒ์ด ์ ์ด๋ ํ ๋ช ์ ๋ค๋ฅธ ๊ฐ๋ฐ์์๊ฒ ๋ฐ์ํ๋ค๋ ๊ฒ์ ์๊ณ ์์ผ๋ฏ๋ก ๋๊ตฌ๋ ์ง ์ฌ๋ฐ๋ฅธ ๋ฐฉํฅ์ผ๋ก ๋๋ฅผ ๊ฐ๋ฆฌํฌ ์ ์๋์ง ๊ถ๊ธํฉ๋๋ค. ๋ค์์ ๋ง๋ค์๋ ์ด ๊ฐ์ธ ํฌํธํด๋ฆฌ์ค๋ฅผ ๋ง๋ฌด๋ฆฌํ๋ ค๊ณ ํฉ๋๋ค.
์๋์์ ์ ํํ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ๋ณผ ์ ์์ต๋๋ค. ํน์ ๊ฒ์๋ฌผ์ด ๋ ๋๋ง๋ ๋๋ง๋ค ๊น๋ฐ์ด๋ 404๋ฅผ ์ ์ธํ๊ณ ๋ชจ๋ ๊ฒ์ด A1์ผ๋ก ๋ณด์ ๋๋ค.
๋ด๊ฐ ์ป์ ์ด์ ์ ์์ฒญ๋์ง๋ง ์ด์ ๊ฐ์ ์ฌ์ํ ๋ฌธ์ ๋ก ์ธํด ์ฝ๊ฐ ์์ํดํ์ต๋๋ค ๐ค . ์ด์จ๋ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ ๊ณตํ ์ ์์ผ๋ฉด ์๋ ค์ฃผ์ญ์์ค. ๊ฐ์ฌํฉ๋๋ค ๐
๊ฐ์ ๋ฌธ์ +1
๋งํฌ ๊ตฌ์ฑ ์์๋ฅผ ํด๋น URL์ ์ด๋ป๊ฒ ๋ ๋๋งํฉ๋๊น? <Link href="/post/1">
๋๋ <Link href="/post?id=1" as="/post/1">
์
๋๊น?
ํ์ฌ <Link prefetch href={
/blog/${x.id} } />
์์ต๋๋ค. ๋๋ ๊ณผ๊ฑฐ์ <Link prefetch href={
/blog/${x.id} } as={
/blog/${x.id} } />
๋ฅผ ์๋ํ๊ณ ๋ฐฉ๊ธ ๋ค์ ์ฐ๊ฒฐํ์ต๋๋ค. ์ฌ์ ํ ๊ฐ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
href
๋ฐ as
์ํ์ ๋์ผํ์ง ์์์ผ ํฉ๋๋ค. href
๋ ์ค์ URL์
๋๋ค. pages/blog.js
์๊ณ id๋ฅผ ์ฟผ๋ฆฌ๋ก ์์ ํ๋ฉด href
๋ /blog?id=${x.id}
href
์ด์ด์ผ ํ๊ณ as
๋ ์ด ๊ฒฝ์ฐ /blog/${x.id}
๊ทํ์ ์์ ์ฌ์ฉ์ ์ ์ URL์
๋๋ค.
@sergiodxa ์ด ์ฝ๋๋ฅผ ์ ์๋ฆฌ์ ๋ฃ์์ต๋๋ค.
<Link href={`/blog?id=${x.id}`} as={`blog/${x.id}`}>
<a>Read Post</a>
</Link>
์ด์ URL์ id
๋ฅผ ์ถ๊ฐํ๋ฉด์ ํด๋ฆญํ ๋๋ง๋ค /blog
ํ์ด์ง๋ฅผ ๋ค์ ๋ ๋๋งํฉ๋๋ค.
@tgrecojs ์ด ์ฝ๋ ์กฐ๊ฐ์ด ๋์์ด
const href = `/journal?home=${this.state.article.path[0]}&articlePath=${this.state.article.path[1]}&file=${this.state.article.path[2]}`
const as = `/journal/${this.state.article.path[0]}/${this.state.article.path[1]}/${this.state.article.path[2]}`
https://www.someURL.com/journal/articlePath/morePath/evenMorePath
๋ก ๋ ๋๋ง๋ฉ๋๋ค.
๋ด ๋ฌธ์ ๊ฐ ์๋ @ugiacoman ๊ฒฝ๋ก๊ฐ ์ด๋ป๊ฒ ์๋ํ๋์ง ์ดํดํฉ๋๋ค. ๋ด ์ด๊ธฐ ๋ณด๊ณ ์์์ ๋ณผ ์ ์๋ ๊ฒฝ์ฐ ๊ฐ ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ๋ก ์ฑ๊ณต์ ์ผ๋ก ์ด๋ํ๊ณ ์์ง๋ง ๋ฌธ์ ๋ ์ด์ํ 404
์ค๋ฅ์
๋๋ค.
@tgrecojs ์์ https://github.com/sergiodxa/next-custom-query (๋ฐฐํฌ: https://next-custom-query.now.sh/blog)๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ณผ ์ ์์ต๋๋ค. ์์์ ์ค๋ช
ํ ๋๋ก next/link
๊ตฌ์ฑ ์์๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์ ๋ก๋ํ์ง ์๊ณ ์ฌ์ฉ์ ์ ์ URL์ 404๋ก ๋ง๋ญ๋๋ค.
@sergiodxa ๊ฐ์ฌํฉ๋๋ค! ๋ฐฉ๊ธ ํ์ธํ๊ณ ํ์ฌ ping ์ค์ธ Google ๋ธ๋ก๊ฑฐ API์ ๋ํ ๋น๋๊ธฐ ํธ์ถ์ ์ถ๊ฐํ์ต๋๋ค. ์๋์์ ๊ฒฝ๋ก๋ฅผ ํ์ํ๊ณ ์์ง๋ง ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ๋ก๋ํ์ง ์๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
์ ๊ฑฐ๋ GIF
์ด์ ์ด ๋ฌธ์ ๋ ๋ด ์ฒซ ๋ฒ์งธ ์๊ฒฌ์ ํ์๋ ๊ฒ๊ณผ๋ ์ด ๋ฌธ์ ๋ฅผ ์ฝ๊ฐ ๋ค๋ฅด๊ฒ ์ฌํํ ๊ฒ์
๋๋ค. ์ฒ์ ์ด ๋ฌธ์ ์ ๋ถ๋ช์ณค์ ๋ ๋๋ redux๋ฅผ ์ฌ์ฉํ๊ณ ์๊ณ ์ ํ๋ฆฌ์ผ์ด์
์ํ๊ฐ post/id
ํ์ด์ง๋ฅผ ์ ๋ฌํ์ง ์๊ธฐ ๋๋ฌธ์ด๋ผ๊ณ ์๊ฐํ์ต๋๋ค. ์ด๋ก ์ธํด ๊ทํ๊ฐ ๋ง๋ ์ฑ์ ํตํฉํ ๊ฒ์ฒ๋ผ ๊ฐ ๊ฒ์๋ฌผ์ ๋ํด ์๋ก์ด API ํธ์ถ์ ํตํฉํ๊ฒ ๋์์ง๋ง ์ฌ์ ํ ๋์ผํ ๋ฌธ์ ๊ฐ ์์์ ๋ฐ๊ฒฌํ์ต๋๋ค.
๊ทํ์ ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ๋ถ๊ธฐํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค ๐ฌ ์ฌ๊ธฐ์์ ๋ด ์ฝ๋๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค -> https://github.com/tgrecojs/next-custom-query-async . ๋น์ ์ ์๊ฐ์ ์๋ ค์ฃผ์ธ์! ๐
ํ๋ก์ ํธ๋ฅผ ํฌํฌํ ๋ usageLimits ์ค๋ฅ ๋ฉ์์ง์ ํจ๊ป ๋์ผํ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ์๋ง๋ ๊ทธ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ ์ด์ ์ผ ๊ฒ์ ๋๋ค.
ํ์ธ. ๋ด์ผ ์กฐ๊ธ ๋ ์กฐ์ฌํด ๋ณด๊ฒ ์ต๋๋ค๋ง, ์ ๊ฐ ์ด์๋ฅผ ์ด์์ ๋ ์ฌ๋ฆฐ ์์์ด /blog/:id
๋ผ์ฐํธ์์ API ์์ฒญ์ ํ๊ณ ์์ง ์๋ค๋ ์ ์ ์ง์ ํ๊ณ ์ถ์ต๋๋ค. ๋์ /blog
๊ฒฝ๋ก ์ ํ์์ ์์ง๋ ๋ด redux ์ ์ฅ์์ ๊ฒ์๋ฌผ์ ํํฐ๋งํ๋ฏ๋ก ์ด ๋ฌธ์ ์ ๋๋ฌํ ์ด์ ๊ฐ ๋ ์ ์์ต๋๋ค. ๋ด redux-store์ ๊ด๋ จ์ด ์๋ค๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์ ๋ ๋ฒ์งธ API ํธ์ถ( blog/:id
๋ด๋ถ์์ ์ํ๋จ)๋ง ๊ตฌํํ์ง๋ง ๋์ผํ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง๋ง ๋ด ์ฝ๋์ ํ์ฌ ๊ตฌํ์ ์๋๋๋ค.
๋์ผํ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ๋ค๋ ๊ฒ์ ๊นจ๋ซ์๋ง์ API ํธ์ถ์ ํ๋๋ง ์ฌ์ฉ(Inside /blog
)ํ ๋ค์ id๋ก ํ์ํ ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ์ ํํฐ๋งํ๋ ๊ฒ์ผ๋ก ๋ค์ ์ ํํ์ต๋๋ค.
@sergiodxa ์ฌ์ฉ๋ ์ ํ์ด ์๋์ ํ์ธํ ์ ์์ต๋๋ค. id
์ด ํญ์ /blog/:id
๊ฒฝ๋ก๋ก ์ฌ๋ฐ๋ฅด๊ฒ ์ ๋ฌ๋๋ ๊ฒ์ ์๋์ ์ ์ ์์ต๋๋ค... ์์ ์ค์ธ 400
์ค๋ฅ๋ฅผ ์ฒจ๋ถํ์ต๋๋ค. id
์ด ์ ์๋์ง ์์์ผ๋ฉฐ (์ด ๊ฒฝ์ฐ) ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์๋์ ๋ค๋ฅธ ๋์์์ ํฌํจ์์ผฐ์ต๋๋ค. ์ ์ด๋ฐ ์์ผ๋ก ํ๋ํ๋์ง์ ๋ํ ์๊ฐ์ด ์์ต๋๊น? ์ด ์ ์ฅ์ ๋ด์์ <Link />
ํ๊ทธ๋ฅผ ๋ณ๊ฒฝํ์ง ์์์ง๋ง ์ฌ์ ํ ๋ฌธ์ ๊ฐ ์์ต๋๋ค ๐ฌ .
๋ค์ ๋งํ์ง๋ง, ์์ ๋น๋์ค๋ https://github.com/sergiodxa/next-custom-query์์ ์์ฑํ ์์ ๋ฆฌํฌ์งํ ๋ฆฌ ๋ด์์ ์ค๋ฅ๋ฅผ ์ฌํํ๋ ๊ฒ์ ๋ณด์ฌ์ค๋๋ค.
์ฌ์ฉ์ ์ง์ ๊ฒฝ๋ก ์์ด๋ 404๊ฐ ๊น๋ฐ์
๋๋ค. ๋ค์ ์ฝ๋๋ฅผ ์ฌ์ฉํ์ฌ pages/
orders.js
๋ผ๋ ํ์ผ๋ง ์์ต๋๋ค.
import { Component } from 'react';
class Orders extends Component {
render() {
return (
<div>
<h2>My Orders</h2>
</div>
)
}
}
export default Orders;
๊ฝค ์ค์ํ ๋ฌธ์ ์ธ ๊ฒ ๊ฐ์ต๋๋ค ๐
๋๋ ๊ทธ๊ฒ์ ๋ณต์ ํ๋ ค๊ณ ์๋ํ๊ณ URL ๋์ ํํ ์ฌ๋์๊ฐ ์๊ธฐ ๋๋ฌธ์ /orders
๋ก ์ด๋ํ๋ฉด 404๊ฐ ํ์๋์ง ์์ง๋ง /orders/
๋ก ์ด๋ํ๋ฉด ํ์๋ฉ๋๋ค. 404๊ฐ ์ฝํ
์ธ ์ ์ ๊น๋ฐ์ด๋ฉฐ ์ด๋ ๊ฐ๋ฐ ๋ฐ ํ๋ก๋์
๋ชจ๋์์ ๋ฐ์ํฉ๋๋ค.
์ ์ด๊ฒ์ ์๋ ค์ง ๋ฌธ์ ์ ๋๋ค. https://github.com/zeit/next.js/issues/1189
๋ด ๋ฌธ์ ๋ ํํ ์ฌ๋์๋ก ์ธํด ๋ฐ์ํ์ง ์์์ผ๋ฏ๋ก ๋ค๋ฅธ ๊ฒ์ด ์์ด์ผ ํฉ๋๋ค. ๋ง๋์?
๋ด ์ฝ๋๋ฅผ ์ฝ๊ฐ ๋ณ๊ฒฝํ์ผ๋ฉฐ prefetch
์ฌ์ฉํ๋ ๋ฒ์ ๊ณผ ์ฌ์ฉํ์ง ์๋ ๋ฒ์ ์ 2๊ฐ์ง ๋ฒ์ ์ ๋ฐฐํฌํ์ต๋๋ค. ๋ ์์ฉ ํ๋ก๊ทธ๋จ ๋ชจ๋ ์ด์ post/:id
๊ฒฝ๋ก๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ๋ก๋ํ ์ ์์ต๋๋ค.
๋งํฌ์์ prefetch
๋ฅผ ์ฌ์ฉํ๋ฉด ์ด์ ๊ฐ ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ์ ๋ํ ๋งํฌ๋ฅผ ๋ ๋๋งํ ๋ Page Does Not Exist Error
๋ฐ์ํฉ๋๋ค. ์๋์์ ๋ด ์ฝ์์ ์คํฌ๋ฆฐ์ท์ ๋ณผ ์ ์์ต๋๋ค.
ํ๋ฆฌํ์น๋ฅผ ์ฌ์ฉํ์ง ์์ผ๋ฉด ์์ ํ์๋ ์ค๋ฅ๋ ๋ ์ด์ ์กด์ฌํ์ง ์์ง๋ง ์์ฉ ํ๋ก๊ทธ๋จ์ ๋ ๋๋งํ์ง ์์ต๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ์ฒ์ ๊ฒ์ํ์ ๋ ๋ด ๊ตฌ์ฑ ์์๋ ๊ฐ post/:id
๊ตฌ์ฑ ์์์ ๋ํด ๋ธ๋ก๊ทธ๋ฅผ ์ด๊ธฐํํ๊ณ ์์์ต๋๋ค. ๊ทธ ์ดํ๋ก ๊ฐ๋ณ ๊ฒ์๋ฌผ์ด ๋ ๋๋ง๋์ง ์๋ ๊ฒ์ ์ ๊ฑฐํ์ต๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ์ง๋จํ๋ ๋ฐ ๋์์ด ๋๋ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ ๊ณตํ ์ ์๋์ง ์๋ ค์ฃผ์ธ์. ๐ค
@tgrecojs ๊ฑฐ์ ๋๊ฐ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. prefetch
๋ ๋ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง ๋ชปํ์ต๋๋ค.
๋ด๊ฐ ์ป๋ ํ๋์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ด๊ฒ์ด ๋ฌธ์ ๋ฅผ ๋๋ฒ๊น ํ๋ ๋ฐ ๋์์ด ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค!
์ถ๊ฐ ์ ๋ณด: ๋
ธ๋ v6.10.3
, Chrome Version 60.0.3112.90
ํธ์ง: https://datahub.now.sh/ ํ ์คํธํ ์ ์๋๋ก ์ฑ์ ๋ฐฐํฌํ์ต๋๋ค. ์ด ๋์์ด ์๋ ๋งํฌ๋ /@[username]์ ๋๋ค.
@Theo- ๊ทธ ๋ค์/๋งํฌ์ href๋ user?id=1
/user?id=1
๋์ /current/path/user?id=1
๋์ /user?id=1
,ํ์ง๋ง ํ์ด์ง๊ฐ ๋ค์๋ก๋ ํ ๋ ์๋ฒ์ ๋ ๋๋ง ๋๋ฌธ์ ๊ทธ๊ฒ์ ์ ์๋ํฉ๋๋ค.
@sergiodxa ํด๋์ต๋๋ค. ๊ฐ์ฌํฉ๋๋ค!
@tgrecojs ๋์ผํ ๊น๋ฐ์ด๋ 404 ๋์์ด ์์์ต๋๋ค. ์ ๊ฒฝ์ฐ์๋ ํด๋ผ์ด์ธํธ์์ ์๋ํ์ง ์๋ ํ๊ฒฝ ๋ณ์๊ฐ ์๋ ๋งํฌ๊ฐ ์์ผ๋ฏ๋ก 404์ด์ง๋ง ์๋ฒ์์๋ ์๋ํ์ต๋๋ค. https://medium.com/the-tech-bench/next-js-environment-variables-d2f6ea1a1dca๋ก ํด๊ฒฐํ์ต๋๋ค
@andreaskeller ํ , ํ์ธํ๊ฒ ์ต๋๋ค. ๊ฐ์ฌํฉ๋๋ค!!! ์ ๋ ํ์ฌ ์ฑ์ด ์๋ฒ ๋ ๋์ผ ๋๋ง .env ๋ณ์๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. dotenv๋ฅผ ์ฌ์ฉํ์ฌ CSR ๋๋ SSR์ธ์ง ํ์ธํ๋ ๊ณ ์ฐจ ๊ตฌ์ฑ ์์๊ฐ ์์ต๋๋ค. SSR์ธ ๊ฒฝ์ฐ ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ์ ๊ธฐ๋กํ๋ ๋ฐ ํ์ํ ๊ธฐ๋ฅ์ ์ ๋ฌํฉ๋๋ค.
์, ์ด๋ฏธ ๋ณ์๊ฐ ์ ๋๋ก ์๋ํ๊ณ ์์ต๋๋ค. ๋ด BLOGGER_API_KEY
๋ฅผ ๊ฐ์ ธ์ค๋ HOC๋ฅผ ์ฌ์ฉํ์ฌ ๋ด /blog
๊ฒฝ๋ก๋ฅผ ๋ ๋๋งํ๊ณ ์์ผ๋ฏ๋ก ํด๋น ์์ ์์ ์๋ํฉ๋๋ค.... ๋ด /post/:id
s ํ์ ํ์ด์ง๋ ์๋ฌด ๊ฒ๋ ์ฌ์ฉํ์ง ์์ต๋๋ค. ํ๊ฒฝ ๋ณ์.
์กฐ๊ธ ๋ ํํค์น ์์ ์ ๋๋ค. ๋ฐ๋ผ๊ฑด๋ ๋๋ ๊ทธ๊ฒ์ ๋ฐ๋ฅ์ ๋๋ฌํ ์ ์์ต๋๋ค!
์ฌ๊ธฐ์์ ๋ฐ์ํ๋ ๋๋ถ๋ถ์ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ด ๋ฌธ์ ์ ๋ํด์๋ ์์ ํ๊ฒ ์ต๋๋ค https://github.com/zeit/next.js/issues/1189
์ง๊ธ ๋ซ๊ณ ์์ต๋๋ค. ํ์ง๋ง ํต์ฌ์ ์ผ๋ก ํด์ผ ํ ์ผ์ด ์์ผ๋ฉด ์๋ ค์ฃผ์ญ์์ค.
@sergiodxa ์ด์ ฏ๋ฐค ๋ํ์ ๋ฐ๋ผ ๋ด ๋ฌธ์ ๋ฅผ ๋ณด์ฌ์ฃผ๋ lil barebones ์ฑ์ ๋ง๋ค์์ต๋๋ค. ๊ถ๊ธํ ์ ์ด ์์ผ๋ฉด ์๋ ค์ฃผ์ธ์! ๋๋ ๊ทธ๊ฒ๊ณผ ๊ด๋ จ๋ ๋ชจ๋ ๊ฒ์ ๋ํด ๋น์ ์ ๊ธฐ์๊ฒ ํ ๊ฒ์ ๋๋ค! ๐
๊ณ ์ ๋์ง ์์์ต๋๋ค.
๋๋ ๊ฐ์ ๋ฌธ์ ๊ฐ ์์ง๋ง ์ฌ์ฉ์ ์ ์ ๊ฒฝ๋ก๊ฐ ์์ต๋๋ค. /pages/pipeline.tsx๊ฐ ์๊ณ /pipeline url์ด ์ ๋๋ก ์๋ํ๋ ๋์ /pipeline/์ด 404๋ก ๊น๋ฐ์ด๊ณ "getInitialProps"๋ฅผ ํธ์ถํ์ง ์๊ณ ๋ด ํ์ด์ง๋ฅผ ๋ก๋ํ๋ ค๊ณ ํฉ๋๋ค(์๋ฒ์์ 404์๊ธฐ ๋๋ฌธ์!).
@ex3ndr ์ด๊ฒ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ง ํ์คํ์ง ์์ง๋ง ๋น์ทํ ๋ฌธ์ ๊ฐ ์์ด์ ํด๊ฒฐํ์ต๋๋ค.
https://github.com/zeit/next.js#disabling -file-system-routing
๋ค์ ๊ธฐํ๋ ์ฌ์ฉ์ ์ง์ ๊ฒฝ๋ก๊ฐ ์ ์ค๋๊ธฐ ์ ์ ํ์ผ ์์คํ ์ ํด์ ํ๋ ค๊ณ ์๋ํ๋ ๊ฒ์ ๋๋ค.
@moaxaca ๋ด ์์ ์ ์ฌ์ฉ์ ์ง์ ๋ผ์ฐํ ์ด ํ์ํ๊ธฐ ๋๋ฌธ์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ํด๊ฒฐํ์ต๋๋ค. ๋ฐฉ๊ธ ๋ค์ ํญ๋ชฉ์ ์์ ํ ๋นํ์ฑํํ์ต๋๋ค.
์ ๋ ์ด ๋ฌธ์ ๋ฅผ ๋ณด๊ณ ์์ต๋๋ค. @moaxaca ์ ์๋ฃจ์
์ด ์ ์๊ฒ ํจ๊ณผ๊ฐ ์์์ต๋๋ค. Link
๊ตฌ์ฑ ์์๋ฅผ ์ฌ์ฉํ์ง๋ง ๋์ ๋ค์ ๊ฒฝ๋ก์ pushRoute
๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋๋ก ์ ํํ์ต๋๋ค.
๊ธฐ๋ณธ ์:
import { connect } from 'react-redux'
import { Router } from '../routes'
// ----
export default class Link extends React.Component {
handleClick(evt, url) {
evt.preventDefault()
Router.pushRoute(url)
}
render() {
const { url, title } = this.props
return (
<a href={ url} onClick={ (evt) => this.handleClick(evt, url) }>{title}</a>
)
}
}
์ด๊ฒ์ ์์๋ด๋ ๊ฒ ๊ฐ๊ณ ์ค๋ฅ ๊น๋ฐ์์ด ํ์๋์ง ์์ต๋๋ค. ํ์ง๋ง ์กฐ๊ธ ๋น ๋ฅธ ๋๋์ ๋๋ค.
๋ฌธ์ ์ ์ฅ
๋๋ ์ ์ ๊ฐ์ ๋ฌธ์ ๊ฐ ์์๊ณ ํด๊ฒฐํ ์์์์ต๋๋ค. ๋๋ ์ต์คํ๋ ์ค ์๋ฒ ์ค์ ์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ์ฌ๋ฐ๋ฅธ ํ์ด์ง๋ก ๋ก๋ํ๊ธฐ ์ ์ 404 ํ์ด์ง๊ฐ ๊น๋ฐ์ด๋ ์ด์ ๋ ๋ด ํ์ด์ง ์ฌ๋ฌ๊ทธ๊ฐ ๋ด ๊ตฌ์ฑ ์์ ์ด๋ฆ๊ณผ ์ผ์นํ์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ด ์ฝ๋๊ฐ ์์ผ๋ฉด 404๊ฐ ๊น๋ฐ์ ๋๋ค.
server.get('/search', (req, res) => {
const actualPage = '/search_results'
const queryParams = { filters: req.query }
app.render(req, res, actualPage, queryParams)
})
/search
์ ๋ด actualPage
๊ฐ์ด ๋ค๋ฆ
๋๋ค.
๊ตฌ์ฑ ์์ ๋ฐ actualPage
๊ฐ์ ์ด๋ฆ์ search
๋ด ํ์ด์ง ์ฌ๋ฌ๊ทธ์ ๋์ผํ๊ฒ ๋ฐ๊พธ๋ฉด 404๋ฒ์ ๊น๋ฐ์์ด ์ฌ๋ผ์ง๋๋ค. ์๋ ์์
์ฝ๋๋ฅผ ์ฐธ์กฐํ์ญ์์ค.
server.get('/search', (req, res) => {
const actualPage = '/search'
const queryParams = { filters: req.query }
app.render(req, res, actualPage, queryParams)
})
์ด์ ๋ ๋ค /search
์์ต๋๋ค.
๋ด ์์ด ์น๊ตฌ๋ค์๊ฒ ๋ฏธ์ํฉ๋๋ค.
next.config.js
useFileSystemPublicRoutes
์์ฑ์ ํ์ธํ๋ ๊ฒ์ด ์ข์ต๋๋ค. false์ด๋ฉด server.js์ ๋ชจ๋ ๊ฒฝ๋ก ์ฒ๋ฆฌ๊ธฐ๋ฅผ ์ง์ ์ ์ํด์ผ ํจ์ ์๋ฏธํฉ๋๋ค.
์ด๊ฒ์ ๋๋ฅผ ์ํด ๊น๋ฐ์ด๋ 404๋ฅผ ์์ ํฉ๋๋ค.
<Link href="/somepage?id=value" as="/somepage/value">
server.get("/somepage/:id", (req, res) => {
return app.render(req, res, "/maps", { id: req.params.id })
})
const { id } = this.props.url.query
๋ฐ๋ผ์ ์ด ์ง๋ฌธ์ ํ ๋ฒ๋ง ๋ตํ์๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
href
=> pages
๋๋ ํ ๋ฆฌ ๋ด๋ถ์ ๊ฒฝ๋ก + ์ฟผ๋ฆฌ ๋ฌธ์์ด
as
=> ๋ธ๋ผ์ฐ์ URL ํ์์ค์ ๋ ๋๋ง๋จ
์์:
/products/:id
๋ผ๋ URL์ด ์์ต๋๋ค.
pages/product.js
๋ง๋ค์์ต๋๋ค.export default class extends React.Component {
static async getInitialProps({query}) {
console.log('SLUG', query.slug)
return {}
}
render() {
return <h1>The product page</h1>
}
}
/products/:id
์ pages/product.js
๋ฐ ์ ๊ณต id
์ ์ผํ์ผ๋ก query
getInitialProps์์ :server.get("/products/:slug", (req, res) => {
return app.render(req, res, "/product", { slug: req.params.slug })
})
next/link
์ฌ์ฉํฉ๋๋ค.<Link href="/product?slug=something" as="/products/something">
href
๋ฐ as
๋ฅผ ๋ช
์์ ์ผ๋ก ์ ๊ณตํด์ผ ํ๋ ์ด์ ๋ Next.js๊ฐ ํด๋ผ์ด์ธํธ ์ธก์ ๋ค๋ฅธ ํ์ด์ง๋ฅผ ์ธ์ํ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์
๋๋ค. ์ฐ๋ฆฌ๋ ๋ชจ๋ ํ์ด์ง์ ๋งค๋ํ์คํธ๋ฅผ ํด๋ผ์ด์ธํธ ์ธก์ ๋ณด๋ด์ง ์์ผ๋ฉฐ ํ์ ๊ฒฝ๋ก๋ ํ์ฅ ๊ฐ๋ฅํ ์ง์ฐ ๋ก๋๋ฉ๋๋ค.
๋ชจ๋ ๊ฒฝ๋ก์ ๋ฏธ๋ฆฌ ์ ์๋ ๋งค๋ํ์คํธ๋ฅผ ์ ์กํ์ฌ href
๋ฐ as
๋ฅผ ์ ๊ณตํ๋ ์ถ์ํํ๋ ์ปค๋ฎค๋ํฐ ํจํค์ง๊ฐ ์์ต๋๋ค
https://github.com/fridays/next-routes
๋ํ ๋ ๋๋ง 404๋ ๋ ์ด์ Next.js์ ๊ธฐ๋ณธ ๋์์ด ์๋๋๋ค. ๋์ ์์ญ ๊ธฐ๋ฅ์ ๋ํ ํ์ด์ง๋ฅผ ๋ค์ ๋ก๋ํฉ๋๋ค.
Tim, ์์ ํ ๋ช ํํ ์ค๋ช ๊ฐ์ฌํฉ๋๋ค!
@timneutkens
๋งํฌ์ href ๋ฐ as. ๋๋ ๋ค๋ฅธ ๊ฐ์ ์ ๋ฌํฉ๋๋ค. href
์ ๊ฐ๊ณผ as
์ ๊ฐ์ ์ด๋ป๊ฒ ์ป์ ์ ์์ต๋๊น?
๋๋ ๋ฐ๋ชจ๋ฅผ ํ
์คํธํฉ๋๋ค. req.params.slug ๊ฐ as
์ ๊ฐ์ด ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด href
์ ๊ฐ์ ์ด๋ป๊ฒ ์ป์ ์ ์์ต๋๊น?
@timneutkens ๋น์ ์ ์ ๋ฅผ ๊ตฌํด์ฃผ์์ต๋๋ค ๋ด ๋ฌธ์ ์ ๋ํด ๋ช ์๊ฐ ๋์ ๊ณ ํต์ค๋ฝ๊ฒ ๊ฒ์ํ๋์ง ๋ชจ๋ฆ ๋๋ค :D
๋งํฌ ๊ตฌ์ฑ ์์๋ฅผ ํด๋น URL์ ์ด๋ป๊ฒ ๋ ๋๋งํฉ๋๊น?
<Link href="/post/1">
๋๋<Link href="/post?id=1" as="/post/1">
์ ๋๊น?
์ด๊ฒ์ ๋ฌธ์์ ๋ฃ์ด์ผ ํฉ๋๋ค. :๊ธฐ์จ:
@sergiodxa
๋ฐ๋ผ์ ์ด ์ง๋ฌธ์ ํ ๋ฒ๋ง ๋ตํ์๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
href
=>pages
๋๋ ํ ๋ฆฌ ๋ด๋ถ์ ๊ฒฝ๋ก + ์ฟผ๋ฆฌ ๋ฌธ์์ด
as
=> ๋ธ๋ผ์ฐ์ URL ํ์์ค์ ๋ ๋๋ง๋จ์์:
/products/:id
๋ผ๋ URL์ด ์์ต๋๋ค.
pages/product.js
๋ง๋ค์์ต๋๋ค.export default class extends React.Component { static async getInitialProps({query}) { console.log('SLUG', query.slug) return {} } render() { return <h1>The product page</h1> } }
- Express ๋๋ ๋ค๋ฅธ ์๋ฒ์ ๊ฒฝ๋ก๋ฅผ ์ถ๊ฐํฉ๋๋ค. ์ด๊ฒ์ SSR์ ๊ฒฝ์ฐ _only_์ ๋๋ค. ์ด๊ฒ์ด ํ ๊ฒ์ ๋๋ค ๊ฒ์ URL ๊ฒฝ๋ก์ ๋๋ค
/products/:id
์pages/product.js
๋ฐ ์ ๊ณตid
์ ์ผํ์ผ๋กquery
getInitialProps์์ :server.get("/products/:slug", (req, res) => { return app.render(req, res, "/product", { slug: req.params.slug }) })
- ํด๋ผ์ด์ธํธ ์ธก ๋ผ์ฐํ ์ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด
next/link
์ฌ์ฉํฉ๋๋ค.<Link href="/product?slug=something" as="/products/something">
href
๋ฐas
๋ฅผ ๋ช ์์ ์ผ๋ก ์ ๊ณตํด์ผ ํ๋ ์ด์ ๋ Next.js๊ฐ ํด๋ผ์ด์ธํธ ์ธก์ ๋ค๋ฅธ ํ์ด์ง๋ฅผ ์ธ์ํ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ฐ๋ฆฌ๋ ๋ชจ๋ ํ์ด์ง์ ๋งค๋ํ์คํธ๋ฅผ ํด๋ผ์ด์ธํธ ์ธก์ ๋ณด๋ด์ง ์์ผ๋ฉฐ ํ์ ๊ฒฝ๋ก๋ ํ์ฅ ๊ฐ๋ฅํ ์ง์ฐ ๋ก๋๋ฉ๋๋ค.๋ชจ๋ ๊ฒฝ๋ก์ ๋ฏธ๋ฆฌ ์ ์๋ ๋งค๋ํ์คํธ๋ฅผ ์ ์กํ์ฌ
href
๋ฐas
๋ฅผ ์ ๊ณตํ๋ ์ถ์ํํ๋ ์ปค๋ฎค๋ํฐ ํจํค์ง๊ฐ ์์ต๋๋คhttps://github.com/fridays/next-routes
๋ํ ๋ ๋๋ง 404๋ ๋ ์ด์ Next.js์ ๊ธฐ๋ณธ ๋์์ด ์๋๋๋ค. ๋์ ์์ญ ๊ธฐ๋ฅ์ ๋ํ ํ์ด์ง๋ฅผ ๋ค์ ๋ก๋ํฉ๋๋ค.
๋ค์๊ณผ ๊ฐ์ ๋ชฉ๋ก ํค๋ ๋ฐฐ์ด๋ง ์์ผ๋ฉด ๋ฌด์์ ํ ์ ์์ต๋๊น?
[
home: '/home',
about:'/about',
post: 'post/:post_id?'
]
.
๋ค์์๋ as's
๊ฐ๋ง ์ป์ ์ ์์ง๋ง href
์ด๋ป์ต๋๊น? ๊ณ ๋ง์
๋น์ ์ด ์ฌ์ฉํ๋ ๊ฒฝ์ฐ router.push()
๋์ <Link>
์ด๋ป๊ฒ ๋์ผํ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค?
@justinmchase ๋ฐฉ๊ธ ๊ฐ์ ๋ฌธ์ ๊ฐ์์์ต๋๋ค. ์์ง ํ์ธํ์ง ์์ ๊ฒฝ์ฐ ๋ค์ ๋ผ์ฐํฐ ์ค๋ช ์๋ฅผ ํ์ธํ์ญ์์ค.
Router.push(url, as, options)
๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
Router.push('/post/[pid]', '/post/abc')
@timneutkens ZEIT.now์์ next.js ์ฑ์ ํธ์คํ
ํ๊ณ ์ถ์ง๋ง ์ต์คํ๋ ์ค ์๋ฒ๋ฅผ ์คํํ ์ ์๋ ์ต์
์ด ์์ต๋๋ค. ์ง๊ธ ๋ด ์์ URL์ ์์ด๋ฒ๋ฆฌ๊ณ param=value¶m=value
๋ง ํ ์ ์์ต๋๊น ์๋๋ฉด ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด ์์ต๋๊น? Sergio๊ฐ ๊ฒ์ํ ์ ๋ ์ ๋งํด ๋ณด์ด์ง ์์ต๋๋ค.
๋์ ๊ฒฝ๋ก๋ฅผ ์๋ํ์ง๋ง ์ด์ ๋จ์ผ ํ์ด์ง ์์ฉ ํ๋ก๊ทธ๋จ์ด ์์๋๊ณ ๋ค์๊ณผ ๊ฐ์ ๋งํฌ๊ฐ ์์ต๋๋ค.
<Link href={`/integration?slug=${slug}`} as={`/integration/${slug}`}>
์ด์ http://localhost :8080/_next/static/development/pages/integration.js๊ฐ 404 not found๋ฅผ ๋ฐํํ๊ธฐ ๋๋ฌธ์ ์ ์ฒด ํ์ด์ง๋ฅผ ๋ค์ ๋ก๋ํฉ๋๋ค.
@timneutkens ZEIT.now์์ next.js ์ฑ์ ํธ์คํ ํ๊ณ ์ถ์ง๋ง ์ต์คํ๋ ์ค ์๋ฒ๋ฅผ ์คํํ ์ ์๋ ์ต์ ์ด ์์ต๋๋ค. ์ง๊ธ ๋ด ์์ URL์ ์์ด๋ฒ๋ฆฌ๊ณ
param=value¶m=value
๋ง ํ ์ ์์ต๋๊น ์๋๋ฉด ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด ์์ต๋๊น? Sergio๊ฐ ๊ฒ์ํ ์ ๋ ์ ๋งํด ๋ณด์ด์ง ์์ต๋๋ค.
๋์ ๊ฒฝ๋ก์๋ ์ฌ์ฉ์ ์ง์ ์๋ฒ๊ฐ ํ์ํ์ง ์์ต๋๋ค( https://nextjs.org/docs/routing/dynamic-routes ์ฐธ์กฐ).
@timneutkens ๋น ๋ฅธ ํ์ ์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ๋์ ๊ฒฝ๋ก๋ฅผ ์๋ํ์ง๋ง ๋จ์ผ ํ์ด์ง ์์ฉ ํ๋ก๊ทธ๋จ์ด ์ค๋จ๋ฉ๋๋ค(์
๋ฐ์ดํธ ์ฐธ์กฐ). ๊ฐ๋ฐ ๋ชจ๋์ ๋ด package.json ์คํฌ๋ฆฝํธ์์ next
ํ์ฌ ๋ก์ปฌ๋ก ์คํํฉ๋๋ค.
์ฝ๋๊ฐ ์๋ pages/integration/index.js
๋ฐ ๋ค์๊ณผ ํจ๊ป pages/integration/[slug].js
ํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ต๋๋ค.
import ProductDetailPage from './index'
export default ProductDetailPage
๊ทํ๊ฐ ์ค๋ช
ํ ๊ฒ์ ์ํํ๋ ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ์ pages/integration/[slug].js
๊ทธ๋ฆฌ๊ณ ๋ค์๊ณผ ๊ฐ์ด ๋งํฌํฉ๋๋ค.
<Link href={`/integration/[slug]`} as={`/integration/${slug}`}>
์๋ ํ์ธ์ ์ ๊ฐ ์ด๊ฑธ ์ ๋ถ๋ฅผ์ง ์ฌ์ญค๋ด๋ ๋ ๊น์?
Router.push( '/about?id=1234','/about')
id๋ฅผ ๊ฒ์ํ ์ ์๊ณ ๋ด๊ฐ ์ฌ์ฉํ๋ ํ์ด์ง๋ [...index].js์
๋๋ค. ์ด๋ ๋ค์ค ๋์ catch all ํ์ด์ง์ด์ง๋ง ๋์ ํ์ด์ง๊ฐ ์๋ ๋ค๋ฅธ ํ์ด์ง๋ก ์ฐ๊ฒฐํ๋ฉด car.js ์์ ๊ฐ ์ ๋๋ก ์๋ํ ์ ์์ต๋๋ค. Vehicle.js๋ก ํธ์..
๋ด ๋์ catch all ํ์ด์ง๋ก ํธ์ํ ๋ค์ ID๋ฅผ ๋ง์คํฌํ๊ณ ์ฌ์ ํ ๊ฒ์ํ ์ ์๋ ๋ ์ข์ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๋ฐ๋ผ์ ์ด ์ง๋ฌธ์ ํ ๋ฒ๋ง ๋ตํ์๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
href
=>pages
๋๋ ํ ๋ฆฌ ๋ด๋ถ์ ๊ฒฝ๋ก + ์ฟผ๋ฆฌ ๋ฌธ์์ดas
=> ๋ธ๋ผ์ฐ์ URL ํ์์ค์ ๋ ๋๋ง๋จ์์:
/products/:id
๋ผ๋ URL์ด ์์ต๋๋ค.pages/product.js
๋ง๋ค์์ต๋๋ค./products/:id
์pages/product.js
๋ฐ ์ ๊ณตid
์ ์ผํ์ผ๋กquery
getInitialProps์์ :next/link
์ฌ์ฉํฉ๋๋ค.href
๋ฐas
๋ฅผ ๋ช ์์ ์ผ๋ก ์ ๊ณตํด์ผ ํ๋ ์ด์ ๋ Next.js๊ฐ ํด๋ผ์ด์ธํธ ์ธก์ ๋ค๋ฅธ ํ์ด์ง๋ฅผ ์ธ์ํ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ฐ๋ฆฌ๋ ๋ชจ๋ ํ์ด์ง์ ๋งค๋ํ์คํธ๋ฅผ ํด๋ผ์ด์ธํธ ์ธก์ ๋ณด๋ด์ง ์์ผ๋ฉฐ ํ์ ๊ฒฝ๋ก๋ ํ์ฅ ๊ฐ๋ฅํ ์ง์ฐ ๋ก๋๋ฉ๋๋ค.๋ชจ๋ ๊ฒฝ๋ก์ ๋ฏธ๋ฆฌ ์ ์๋ ๋งค๋ํ์คํธ๋ฅผ ์ ์กํ์ฌ
href
๋ฐas
๋ฅผ ์ ๊ณตํ๋ ์ถ์ํํ๋ ์ปค๋ฎค๋ํฐ ํจํค์ง๊ฐ ์์ต๋๋คhttps://github.com/fridays/next-routes
๋ํ ๋ ๋๋ง 404๋ ๋ ์ด์ Next.js์ ๊ธฐ๋ณธ ๋์์ด ์๋๋๋ค. ๋์ ์์ญ ๊ธฐ๋ฅ์ ๋ํ ํ์ด์ง๋ฅผ ๋ค์ ๋ก๋ํฉ๋๋ค.