HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🌟
Programmers 최종 플젝 6조
/
[프론트] TWL
[프론트] TWL
/
Firebase 동적 라우팅 미적용 현상
Firebase 동적 라우팅 미적용 현상
Firebase 동적 라우팅 미적용 현상

Firebase 동적 라우팅 미적용 현상

생성일
Dec 9, 2021 02:33 AM
태그
Next.js
deployment
Issue
Env Settings
작성자
해결 완료
해결 완료

🔥 문제

정적인 라우팅은 잘 나옵니다. 그러나 []를 활용한 동적 라우팅은 제대로 나오지 않습니다. 이유가 무엇일까요?
notion image

⭐ 해결 방법

모든 빌드의 힌트는 .next에 있었습니다.
.next에서 routes-manifest.json을 보면 다음과 같이 서술되어 있습니다.
{"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": [] }
 
여기서 주목할 것은 dynamicRoutes입니다.
해당 라우트의 경우, 별도로 regex 처리를 하여 재규정합니다.
따라서, 이를 처리하기 위해서 우리도 firebase.json에서 똑같은 방식으로 적용하면 되지 않을까?라는 아이디어를 얻었습니다.
따라서 다음과 같은 조작이 필요했습니다.
{ "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/([^/]+?)(?:/)?$" } ] } }
이제는 index.html의 원리도 알았기에, :path로 간단히 처리해줬습니다.
따라서 결과를 살펴볼까요?
 

결과

어ㅡ썸하게 동작하는군요!
notion image
 

👏🏻 참고자료

https://stackoverflow.com/questions/69057499/next-js-dynamic-routes-with-firestore-collection
https://github.com/firebase/firebase-js-sdk/discussions/4980