Firebase 동적 라우팅 미적용 현상
Next.js
deployment
Issue
Env Settings
🔥 문제
정적인 라우팅은 잘 나옵니다. 그러나 []
를 활용한 동적 라우팅은 제대로 나오지 않습니다. 이유가 무엇일까요?
⭐ 해결 방법
모든 빌드의 힌트는 .next
에 있었습니다.
.next
에서 routes-manifest.json
을 보면 다음과 같이 서술되어 있습니다.
다들 코드가 깔끔해서, 충분히 이해했을 것 같다. (죄송합니다)
다시 깔끔하게 코드를 정돈하여 설명하겠습니다.
여기서 주목할 것은 dynamicRoutes
입니다.
해당 라우트의 경우, 별도로 regex
처리를 하여 재규정합니다.
따라서, 이를 처리하기 위해서 우리도 firebase.json
에서 똑같은 방식으로 적용하면 되지 않을까?라는 아이디어를 얻었습니다.
따라서 다음과 같은 조작이 필요했습니다.
이제는 index.html
의 원리도 알았기에, :path
로 간단히 처리해줬습니다.
따라서 결과를 살펴볼까요?
결과
어ㅡ썸하게 동작하는군요!
👏🏻 참고자료
{"version":3,"pages404":true,"basePath":"","redirects":[{"source":"/:path+/","destination":"/:path+","internal":true,"statusCode":308,"regex":"^(?:/((?:[^/]+?)(?:/(?:[^/]+?))*))/$"}],"headers":[],"dynamicRoutes":[{"page":"/event/[eventId]","regex":"^/event/([^/]+?)(?:/)?$","routeKeys":{"eventId":"eventId"},"namedRegex":"^/event/(?<eventId>[^/]+?)(?:/)?$"},{"page":"/event/[eventId]/create","regex":"^/event/([^/]+?)/create(?:/)?$","routeKeys":{"eventId":"eventId"},"namedRegex":"^/event/(?<eventId>[^/]+?)/create(?:/)?$"},{"page":"/event/[eventId]/reviews","regex":"^/event/([^/]+?)/reviews(?:/)?$","routeKeys":{"eventId":"eventId"},"namedRegex":"^/event/(?<eventId>[^/]+?)/reviews(?:/)?$"},{"page":"/shop/[shopId]","regex":"^/shop/([^/]+?)(?:/)?$","routeKeys":{"shopId":"shopId"},"namedRegex":"^/shop/(?<shopId>[^/]+?)(?:/)?$"},{"page":"/shop/[shopId]/create","regex":"^/shop/([^/]+?)/create(?:/)?$","routeKeys":{"shopId":"shopId"},"namedRegex":"^/shop/(?<shopId>[^/]+?)/create(?:/)?$"},{"page":"/user/[userId]","regex":"^/user/([^/]+?)(?:/)?$","routeKeys":{"userId":"userId"},"namedRegex":"^/user/(?<userId>[^/]+?)(?:/)?$"}],"staticRoutes":[{"page":"/","regex":"^/(?:/)?$","routeKeys":{},"namedRegex":"^/(?:/)?$"},{"page":"/history/events","regex":"^/history/events(?:/)?$","routeKeys":{},"namedRegex":"^/history/events(?:/)?$"},{"page":"/history/reviews","regex":"^/history/reviews(?:/)?$","routeKeys":{},"namedRegex":"^/history/reviews(?:/)?$"},{"page":"/likes/event","regex":"^/likes/event(?:/)?$","routeKeys":{},"namedRegex":"^/likes/event(?:/)?$"},{"page":"/likes/shop","regex":"^/likes/shop(?:/)?$","routeKeys":{},"namedRegex":"^/likes/shop(?:/)?$"},{"page":"/login","regex":"^/login(?:/)?$","routeKeys":{},"namedRegex":"^/login(?:/)?$"},{"page":"/owner/change","regex":"^/owner/change(?:/)?$","routeKeys":{},"namedRegex":"^/owner/change(?:/)?$"},{"page":"/owner/success","regex":"^/owner/success(?:/)?$","routeKeys":{},"namedRegex":"^/owner/success(?:/)?$"},{"page":"/profile/edit","regex":"^/profile/edit(?:/)?$","routeKeys":{},"namedRegex":"^/profile/edit(?:/)?$"},{"page":"/register","regex":"^/register(?:/)?$","routeKeys":{},"namedRegex":"^/register(?:/)?$"},{"page":"/register/success","regex":"^/register/success(?:/)?$","routeKeys":{},"namedRegex":"^/register/success(?:/)?$"}],"dataRoutes":[],"rewrites":[]}
{
"version": 3,
"pages404": true,
"basePath": "",
"redirects": [
{
"source": "/:path+/",
"destination": "/:path+",
"internal": true,
"statusCode": 308,
"regex": "^(?:/((?:[^/]+?)(?:/(?:[^/]+?))*))/$"
}
],
"headers": [],
"dynamicRoutes": [
{
"page": "/event/[eventId]",
"regex": "^/event/([^/]+?)(?:/)?$",
"routeKeys": { "eventId": "eventId" },
"namedRegex": "^/event/(?<eventId>[^/]+?)(?:/)?$"
},
{
"page": "/event/[eventId]/create",
"regex": "^/event/([^/]+?)/create(?:/)?$",
"routeKeys": { "eventId": "eventId" },
"namedRegex": "^/event/(?<eventId>[^/]+?)/create(?:/)?$"
},
{
"page": "/event/[eventId]/reviews",
"regex": "^/event/([^/]+?)/reviews(?:/)?$",
"routeKeys": { "eventId": "eventId" },
"namedRegex": "^/event/(?<eventId>[^/]+?)/reviews(?:/)?$"
},
{
"page": "/shop/[shopId]",
"regex": "^/shop/([^/]+?)(?:/)?$",
"routeKeys": { "shopId": "shopId" },
"namedRegex": "^/shop/(?<shopId>[^/]+?)(?:/)?$"
},
{
"page": "/shop/[shopId]/create",
"regex": "^/shop/([^/]+?)/create(?:/)?$",
"routeKeys": { "shopId": "shopId" },
"namedRegex": "^/shop/(?<shopId>[^/]+?)/create(?:/)?$"
},
{
"page": "/user/[userId]",
"regex": "^/user/([^/]+?)(?:/)?$",
"routeKeys": { "userId": "userId" },
"namedRegex": "^/user/(?<userId>[^/]+?)(?:/)?$"
}
],
"staticRoutes": [
{
"page": "/",
"regex": "^/(?:/)?$",
"routeKeys": {},
"namedRegex": "^/(?:/)?$"
},
{
"page": "/history/events",
"regex": "^/history/events(?:/)?$",
"routeKeys": {},
"namedRegex": "^/history/events(?:/)?$"
},
{
"page": "/history/reviews",
"regex": "^/history/reviews(?:/)?$",
"routeKeys": {},
"namedRegex": "^/history/reviews(?:/)?$"
},
{
"page": "/likes/event",
"regex": "^/likes/event(?:/)?$",
"routeKeys": {},
"namedRegex": "^/likes/event(?:/)?$"
},
{
"page": "/likes/shop",
"regex": "^/likes/shop(?:/)?$",
"routeKeys": {},
"namedRegex": "^/likes/shop(?:/)?$"
},
{
"page": "/login",
"regex": "^/login(?:/)?$",
"routeKeys": {},
"namedRegex": "^/login(?:/)?$"
},
{
"page": "/owner/change",
"regex": "^/owner/change(?:/)?$",
"routeKeys": {},
"namedRegex": "^/owner/change(?:/)?$"
},
{
"page": "/owner/success",
"regex": "^/owner/success(?:/)?$",
"routeKeys": {},
"namedRegex": "^/owner/success(?:/)?$"
},
{
"page": "/profile/edit",
"regex": "^/profile/edit(?:/)?$",
"routeKeys": {},
"namedRegex": "^/profile/edit(?:/)?$"
},
{
"page": "/register",
"regex": "^/register(?:/)?$",
"routeKeys": {},
"namedRegex": "^/register(?:/)?$"
},
{
"page": "/register/success",
"regex": "^/register/success(?:/)?$",
"routeKeys": {},
"namedRegex": "^/register/success(?:/)?$"
}
],
"dataRoutes": [],
"rewrites": []
}
{
"hosting": {
"public": "out",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"cleanUrls": true,
"rewrites": [
{
"regex": "^(?:/((?:[^/]+?)(?:/(?:[^/]+?))*))/$",
"destination": "/:path+.html"
},
{
"destination": "/event/[eventId].html",
"regex": "^/event/([^/]+?)(?:/)?$"
},
{
"destination": "/event/[eventId]/create.html",
"regex": "^/event/([^/]+?)/create(?:/)?$"
},
{
"destination": "/event/[eventId]/reviews.html",
"regex": "^/event/([^/]+?)/reviews(?:/)?$"
},
{
"destination": "/shop/[shopId].html",
"regex": "^/shop/([^/]+?)(?:/)?$"
},
{
"destination": "/shop/[shopId]/create.html",
"regex": "^/shop/([^/]+?)/create(?:/)?$"
},
{
"destination": "/user/[userId].html",
"regex": "^/user/([^/]+?)(?:/)?$"
}
]
}
}