Next.js로 jQuery 포트폴리오 업그레이드하기 - 초기설정, 퍼블리싱 편
2020년 취업 초반에 만들었던 jQuery 포트폴리오를 Next.js로 업그레이드하면서 적는 Next.js 고군분투기
처음 취업 준비 때 막무가내로 만들었던 포트폴리오.
어떤 한 사이트를 참고해가며 클론코딩을 만든 포트폴리오였 습니다.
나름 php도 붙여가며 회원가입, 로그인기능도 붙여놨지만 유지보수를 안하기도 했고 어찌저찌하여 내 손을 떠나게 되었는데, 그 때 막 퍼블리싱을 배우던 때라 jQuery로 성능도 생각하지 않고 냅다 코딩했던 기억만 있어요.
다시 코드를 까보니 넘나 더러워서.... 언젠가 업그레이드 해야겠다고 생각한 거 지금 react, next.js 배우고 있는 김에 업그레이드해봐야겠다고 결심했습니다.
- https://aainterior.com.ua/를 클론코딩한 사이트 입니다.
🍽️ next.js로 선택한 이유
구글 폰트 내장 지원
해당 파일을 보면, css를 파악하는데 좀 시간이 오래 걸렸습니다.
나름 reset.css
도 적용하고 레이아웃은 레이아웃대로, 잘 분리했다고 생각했는데 폰트 설정도 다 모여있고 해서 파일 관리하기가 복잡해보였어요.
실제로 퍼블리싱 할 때 직접 구글 폰트 찾거나 아니면 폰트 파일을 다운로드 받아서 임포트 해주고... 그걸 font-face로 지정해주고 하는 과정이 번거롭게 느껴졌습니다.
구글 폰트가 내장으로 지원된다는 점은 이런 면에서 매력적이었어요!
빠른 로딩속도 개선
아무래도 인터랙티브한 UI들은 jQuery
로 DOM을 직접 지정하여 인터랙션을 준 것들이라서 소스가 무겁다고 판단했습니다.
Next.js
는 자동 코드 분할과 최적화된 빌드 시스템을 제공하여 성능을 최적화하기 때문에 이는 사용자 경험을 크게 개선할 수 있을 거라고 생각했어요.
React
생태계 활용
React
를 실무에서 적용해본 적이 없고 경험을 많이 쌓고 싶다고 생각한 찰나에 마침 Next.js
를 입문하고 있었습니다.
원페이지의 동적 데이터 교환이 없는 페이지여서 Next.js
의 특장점을 살리는 프로젝트는 아니겠지만 그래도 React 생태계를 활용한다는 점에서 매력을 느껴 결정하게 되었어요.
SEO 최적화
굳이 React로 하지 왜 Next.js
로? 라는 생각이 들 수 있다고 생각합니다.
그럼에도 불구하고 Next.js
를 선택한 그 이유는 다음과 같습니다.
jQuery로 작성한 포트폴리오에서 meta태그로 검색엔진에 잘 걸릴 수 있게 설정을 해두었는데, 그런 면에서 Next.js
가 SEO 측면에서 도움이 되지 않을까 생각했습니다.
CSS module 사용가능
처음 next앱을 셋팅할 때 css module로 사용할 수 있도록 지정해주었는데요, tailwind같은 프레임워크를 사용하지 않았던 이유는 css 디자인 비중이 높아서 였습니다. 이미지요소도 많았지만, 커스텀해서 스타일을 지정해주어야하는 부분이 많았고, css 모듈에 대해 좀 더 알아보고 싶어서 선택했습니다.
🍽️ 프로젝트 세팅
자 그럼 프로젝트를 세팅해봅시다. Next.js simple tutorial 보러가기
npx create-next-app@latest
🍽️ meta tag 세팅
meta tag를 설정해 봅시다.
export const metadata: Metadata = {
title: "rowanna porfolio 2020",
description: "next.js로 업데이트 한 jQuery 포트폴리오 입니다.",
keywords:
"나원지, 포트폴리오, portfolio, rowanna, 웹퍼블리셔, 웹퍼블리셔 포트폴리오",
icons: {
icon: "/favicon-128.jpg",
},
openGraph: {
title: "Wonji Na Portfolio",
description: "웹 퍼블리셔 나원지의 포트폴리오 사이트입니다.",
images: "/meta-img.jpg",
},
};
여기서 이미지 경로는 src/public이 아니라 public에 파일을 넣어둡니다. 기존의 favicon.ico는 삭제해 주었습니다.
🍽️ 폴더 구조 세팅
다음 구조는 src/app
디렉토리의 구조입니다.
/app
├── layout.tsx
├── page.tsx
├── components/ # ✅ 컴포넌트 모음 폴더
│ ├── ui/ # ✅ (1) UI 공통 컴포넌트
│ │ ├── Button/ # ✅ Button 컴포넌트 폴더
│ │ │ ├── Button.tsx
│ │ │ └── Button.module.css
│ │ └── index.ts # UI 컴포넌트들을 한 번에 export
│ │
│ ├── layout/ # ✅ (2) 레이아웃 관련 컴포넌트
│ │ ├── Header/ # ✅ Header 컴포넌트 폴더
│ │ │ ├── Header.tsx
│ │ │ └── Header.module.css
│ │ ├── Footer/ # ✅ Header 컴포넌트 폴더
│ │ │ ├── Footer.tsx
│ │ │ └── Footer.module.css
│ │ └── index.ts
│ │
│ ├── sections/ # ✅ (3) 특정 페이지에 포함되는 섹션 컴포넌트
│ │ ├── Main/ # ✅ Main 컴포넌트 폴더
│ │ │ ├── Main.tsx
│ │ │ └── Main.module.css
│ │ └── Info/ # ✅ Info 컴포넌트 폴더
│ │ ├── Info.tsx
│ │ └── Info.module.css
│ └── index.ts # 모든 컴포넌트들을 한 번에 export
│
├── styles/ # 전역 스타일
├── public/ # 정적 파일 (이미지, 폰트 등)
└── ...
import Layout from "@/app/components/layout";
import Main from "@/app/components/sections/Main/Main";
export default function Container() {
return (
<>
<Layout>
<Main />
</Layout>
</>
);
}
위처럼 모든 컴포넌트를 component
폴더의 Container
에 넣고 최종 page.tsx
에서 아래와 같이 임포트 했습니다.
import Container from "@/app/components";
export default function Home() {
return <Container></Container>;
}