-
Nextjs13을 활용한 간단한 심리테스트 만들기Front-End 2023. 3. 23. 23:06
2022년 10월 26일 수요일 Vercel에서 Nextjs의 새로운 버전인 Nextjs13을 발표하였습니다.
ChatGPT와 GPT4에 물어봐도 명확하게 답변해주지 못하는 따끈따끈하고도 최신 기술인데요.
평소에 SSR프레임워크도 써보고 싶었고 Nextjs13 공부도 할 겸 간단한 심리테스트를 구현해 보았습니다.
사실 Nextjs 써보진 않았지만 평소에 해보고 싶은 게 있으면 앞뒤 안재고 무작정 도전하는 스타일이라서 이번에도 사이드 프로젝트에 그대로 투입하였습니다. 그래서 굉장히 우당탕탕 이슈도 많았고 별것 아닌 거에도 많이 헤매었었는데요. 프로젝트 초기 세팅부터 써본 것들 위주로 간단히 후기 남기고 기록으로 남기려고 합니다.🙂
혹시나 Nextjs13 찍먹 해보고 싶은 분들께 이 글이 조금이나마 도움이 되셨으면 좋겠습니다.
🏗️ 프로젝트 세팅
제가 심리테스트를 만들기 위해 사용한 FE 기술 SPEC은 다음과 같습니다.
- Nextjs 13 : 전반적인 구조 및 레이아웃 구성
- React 18 : CSR component 구성
- typescript : 직관적인 타입 명시
- tailwind css : 생산성 향상을 위한 CSS 프레임워크 사용
이 글에서는 심리테스트 만드는 방법에 대해서는 자세히 기술하지는 않을 예정이라서 간단히 소개만 하고 넘어가도록 하겠습니다. 프로젝트가 궁금하시다면 아래 링크를 참조해 주세요~!
https://github.com/chucoding/dream-power-game
🦴 Nextjs13을 사용한 패키지 구조
파일 시스템 라우터는 Next.js에서 가장 사랑받는 기능 중 하나입니다.
react router와 다르게 라이브러리를 별도로 설치하거나 라우팅 함수를 사용하지 않고도 폴더 안에 파일을 생성하면 애플리케이션에서 즉시 경로를 생성할 수 있는 기능이죠.
Next.js 12 버전까지만 해도 pages 폴더가 대신했지만 13 버전 이후부터는 app 디렉터리가 그 기능을 대신합니다.
저는 13.1.6 버전을 사용 중인데 아직까지는 pages폴더와 app 폴더를 공존해서 사용할 수 있습니다.
저는 이번 프로젝트에서는 app 폴더만을 사용해 프로젝트 기반을 다졌습니다.
제가 생각했을 때 app 폴더의 장점으로는 패키징이 비교적 깔끔하다는 점입니다.
기존에 Nextjs12를 오래 익숙하게 사용하시던 분이라면은 왼쪽의 프로젝트 구조가 좀 더 맘에 들고 깔끔하다고 생각할 수 있을 것 같습니다. 하지만 저는 이전 사이드 프로젝트에서 동료가 만들어놓은 Nextjs12를 잠깐 봤었는데 _app, _document처럼 파일 앞에 언더바(_)가 붙는 것이 조금 눈엣가시였습니다. 그래서 Nextjs13의 프로젝트 구조를 보자마자 정말 깔끔하고 직관적이다라는 생각을 했습니다.
위의 패키지구조에 따른 파일 시스템 라우팅 예제를 살펴보면 app폴더 바로 아래 page.tsx가 루트("/") 경로가 되고 result/[score]/page.tsx는 ("/result/[score]")의 경로를 갖게 됩니다.
https://dream.swygbro.com/result/64
page.tsx 이외의 다른 페이지의 기능은 다음과 같습니다.
- head.tsx : meta, 스크립트 등의 태그를 정의하는 헤더 코드 작성
- layout.tsx : 페이지에 대한 공유 레이아웃을 정의할 수 있는 기능
- page.tsx : 페이지 코드 작성
💡 Nextjs13 layout 사용하기
저는 심리테스트를 만드는 만큼 레이아웃 기능을 최대한 활용해 보려고 시도했습니다.
여러 페이지에 공통 스타일과 구성 요소를 적용하려고 루트 레이아웃에 페이지 배경과 전체크기를 맞춰놓았습니다.
위와 같이 구성해놓으면 페이지를 좌우로 늘리거나 해도 고정 크기로 만들 수 있습니다.
뿐만 아니라 app 폴더 바로 아래 layout을 이런 식으로 잡아놓으면 그 아래 하위 페이지들도 전부 해당 레이아웃을 갖기 때문에 추가적으로 레이아웃을 구성해 줄 필요가 없습니다.
하지만 문제는 더 복잡한 CSS를 Root layout에 구현해 놓았을 경우에는 페이지 별로 디자인을 다르게 구성할 때 많은 고생이 동반됩니다. 저 같은 경우에는 처음에 Root layout에 padding을 넣어놓았다가 다른 한 페이지에서만 padding을 빼고 싶었는데 부모 레이아웃을 무시하거나 props로 받으려고 했는데 적용이 안 돼서 방법을 찾다가 포기하고 결국에는 각 페이지별로 각각 padding을 넣어서 해결하였습니다. 😢
아래는 ChatGPT에게 부모 레이아웃을 무시할 수 있는 방법이 있는지에 대해 물어봤는데 정확하지 않는 코드를 답변합니다.
⚓ Nextjs13 컴포넌트간 이동 구현하기
페이지 간의 이동은 파일 시스템 라우터를 사용하면 되지만 컴포넌트 간의 라우팅은 어떻게 처리해야 될까요?
React를 배우셨다면 컴포넌트에서 다른 컴포넌트로 이동시 router 또는 link를 사용해 이동해야 된다는 것을 알고 계실 겁니다.
nextjs12와 다른 점은 nextjs13 버전부터는 컴포넌트 라우팅시 next/router 대신 next/navigation을 사용해야 합니다.
그리고 next/navigation 사용 시에는 다음과 같이 꼭 'use client'를 파일 최상단에 붙여서 Client Component임을 명시해주어야 합니다.
'use client'; import { usePathname, redirect, useRouter } from 'next/navigation'; export default function Page() { const router = useRouter(); const path = usePathname() || ""; const score = parseInt(path.substring(8), 10); if (isNaN(score) || score < 0 || score > 100) { redirect("/"); } return ( <button onClick={() => router.push('/')}> 테스트 다시하기 </button> ); }
위의 코드는 꿈력 측정 테스트의 결과페이지 코드 한 부분을 발췌해 왔는데요.
next/navigation 라이브러리 안에는 usePathname, redirect, useRouter 등 다양한 커스텀 훅을 사용할 수 있습니다.
단, 주의할점은 layout에 next/navigation을 사용할 수 없습니다.
저는 계속 layout에 라우팅 코드를 넣으려고 시도했었는데요. 라우팅 코드는 반드시 page에 삽입해야 합니다.
✏️ Nextjs13 폰트 사용하기
next/font는 사실 제가 가장 써보고 싶었던 기능입니다. 자동으로 폰트를 최적화해 주고 특히 Google폰트 사용 시 빌드할 때 폰트 파일을 다운로드하여 배포 후에도 브라우저에서 따로 Google로 요청을 보내지 않는다는 장점이 있습니다.
그러나 저는 프로젝트에서 Google폰트를 쓰지 않고 원하는 폰트가 따로 있어서 localFont를 사용하려고 했습니다.
import localFont from '@next/font/local'; const myFont = localFont({ src: './my-font.woff2' }); <html className={myFont.className}>
위의 코드는 vercel에서 가이드하고 있는 코드입니다. 그러나 막상 사용해 보면 굉장한 불편한 점이 있습니다.
첫 번째로는 폰트 파일을 app폴더 내에 위치시켜야 한다는 점입니다. 폰트최적화를 위해 빌드시점에 읽을 수 있어야 되기 때문으로 추측됩니다. 저는 보통 public폴더 바로 아래 fonts폴더에 ttf파일들을 넣어 사용했었는데 이렇게 사용할 경우 경로를 못 읽는 점을 주의하셔야 합니다.
두 번째로는 첫 렌더링시 폰트 파일을 전부 다운로드하지 못해 fallback 폰트로 적용된다는 점입니다.
아마 많은 사람들이 첫 화면부터 폰트가 적용되길 바랄것 같은데요. beta버전이라 그런지 아직까지는 이런 점들이 조금 아쉬움으로 많이 남는 것 같습니다.
그래서 다시 원초적인 방법으로 돌아와 global.css에서 불러와서 사용하였습니다.
아래 소스코드의 url 부분에 폰트 경로를 넣어주면 사용하실 수 있습니다.
ex) public/fonts 폴더 아래 넣은 경우에는 /fonts/폰트명.ttf
@tailwind base; @tailwind components; @tailwind utilities; @font-face { font-family: "GangwonEdu_OTFBoldA"; src: url("https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2201-2@1.0/GangwonEdu_OTFBoldA.woff") format("woff"); font-weight: normal; font-style: normal; }
🕺🏻 프로젝트 후기
직장인이라 바쁜 와중에 짧은 기간 동안 Nextjs13 공부하면서 프로젝트 만들기가 쉽지 않았는데 완성할 수 있었던 것은 좋은 기획자 분을 만나 멋진 기획과 디자인을 해주셔서 인 것 같고 또 SWYG라는 플랫폼에서 배포를 간편하게 할 수 있어서 이었던 것 같습니다.
또 한, 모르는 게 있으면 거의 ChatGPT한테 도움을 요청하면서 개발하였기 때문에 비교적 단기간에 빠르게 완성할 수 있었던 것 같습니다. 하지만 단점은 Nextjs13 버전에 대해 ChatGPT에게 물어보면 엉뚱한 대답을 내놓습니다.(특히 navigation 물어볼 때 옛날버전으로 대답합니다) 그래서 유연하게 대처하는 게 많이 필요합니다.
확실히 Nextjs13을 찍먹 해보면서 느낀 점은 프로젝트 구조를 이쁘게 잡을 수 있다는 점이 가장 마음에 들었고 또 기회가 된다면 Turbopack도 써보고 좀 더 최적화된 웹을 구현해 볼 수 있는 시간을 가지면 좋겠다는 생각이 듭니다:)
'Front-End' 카테고리의 다른 글
해커톤에서 사용할 수 있는 다양한 프론트엔드(react, next) 빌드 및 배포 방법 (0) 2024.06.29 Storybook 도입할 수 있을까? (0) 2023.01.31 웹 접근성 지침 적용방법 (IR 기법) (0) 2022.02.17 jsrender 사용시 화면이 나오다 만 경우 (0) 2021.03.02