[Next.js 12] 확장성 높은 커머스 구축하기
Next.js 를 사용한 사례
[Next.js 12] 확장성 높은 커머스 구축하기

Pre-rendering 와 SEO의 상관관계
CSR만 제공한다면, Client(브라우저) 처럼 동작하지 않는 검색엔진의 경우 아무런 데이터도 조회해 갈 수 없다. 하지만 Pre-render를 해두면 Client처럼 동작하지 않는 검색엔진에게 필요한 데이터를 제공할 수 있다.
Next.js 가 제시하는 4가지 Data Fetching 방법
- SSR — Server Side Render — getServerSideProps — 서버에서 그린다. 서버 부하가 많다.
- CSR — Client Side Render — 따로없음(useState, useEffect 등..?) — 클라이언트가 그린다.
- SSG(Recommended) — Static-Site Generation — getStaticProps(with getStaticPaths) — 정적인 사이트를 생성한다, 데이터를 가져와서 그려둔다. SSG를 보려면 build를 해야한다. 즉, 빌드하는동안 데이터를 다 fetching 해와서 정적페이지를 다 생성해 버렸다. 빌드하는 머신 자체 즉, 서버에서 그려둔다. 이 말은 곧 서버 부하가 적다. 빌드타임에 정적사이트를 생성한다. ‘yarn dev’ 로는 SSR 처럼 동작한다.
- ISR — Incremental Static Regeneration — (특정 주기로) 데이터를 가져와서 다시 그려둔다. SSG + SSR의 장점을 사용할 수 있다.
SSR 과 SSG 차이점
- SSR은 요청시마다 pre-render
- SSG는 빌드타임에 pre-render
SSG 2 가지 상황
- Page의 내용물이 외부 데이터에 의존적인 상황(getStaticProps)
- Page Paths 까지 외부 데이터에 의존적인 상황(getStaticPaths)
pages 구조
- pages — url과 일대일 대응
Dynamic Routes
하나의 파일로 여러 페이지
- [slug] — 와일드카드
- 다중 [slug] — /[slug]/[slug].js 또는 […slug].js
- 옵셔널 [[…slug]].js
SSG 시 생성할 목록 → getStaticPaths (paths 배열 반환) 에서 가져온다.
도구: md 파싱 / date format → remark & remark-html /date-fns
getStaticPaths fallback → 빌드시 생성되지 않은 page에 대한 처리
- false — 404 페이지를 보여준다.
- true — 준비한 로더(ex. 로딩중…)를 보여줬다가 데이터가 로드되면 그제서야 화면을 보여준다.
- ‘blocking’ — true와 유사하다. 빌드시점에 생성되지 않은 경로는 404 페이지가 생성되지 않는다. 대신, 첫번째 요청에 대해 SSR을 수행하고 생성된 HTML을 반환한다.
getStaticProps fallback — ‘blocking’은 언제 사용할까?
‘blocking’은 로딩 indicator를 보여주지 않고 바로 요청 페이지를 로드하고 보여준다. UX 관점에서 보면, 요청 페이지가 지연 시간이 적게 걸리는 페이지인 경우, layout shift 를 피할 수 있으므로 ‘blocking’ 을 사용하는 것이 좋은 선택일 수 있다. (짧은시간 이라 하더라도 로딩중… 이라는 문구가 보이면 UX가 떨어진다고 느끼는 유저가 있을수 있기 때문이다. 그래서 차라리 로딩 indicator를 보여주지 않는게 나을 수 있다.)
Router
- Next.js 의 router는 file-system 기반
- src/pages/index.js 혹은 pages/index.js
useRouter
- router.query
- router.push
Shallow Routing
- getServerSideProps / getStaticProps 를 다시 실행하지 않고, 현재 상태를 잃지 않고 url을 바꾸는 방법
url을 바꾸는 3가지 방식
동일한 url에 대해
- location.replace(“url”): 로컬 state 유지 안됨(리렌더)
- router.push(url): 로컬 state 유지 / data fetching 발생
- router.push(url, as, {shallow: true}): 로컬 state 유지/ data fetching 없음
Next.js 가 제공하는 API Routes
- pages/api/*
Dynamic API Routes
- 예시 — pages/api/user-info/[uid].js
- req.query 로 꺼낼 수 있다.
API Middlewares
내장 Middleware의 기능
- req.cookies
- req.query
- etc
req/res 관련 다양한 기능들은 Middleware 들을 활용할 수 있다.
- 예시 — CORS 이슈에 대응할 수 있는 미들웨어를 추가해서 api를 구성할 수 있다.
Response
- res.status(code)
- res.json(body): serializable object
- res.redirect(code, url)
- res.send(body): string/object/Buffer
‘fs’는 Server-side 에서만 가능하다.
Link 컴포넌트
<a href="/posts/first-post">첫번째 글</a>
<Link href="/posts/first-post"><a>첫번째 글</a></Link>
a 태그와 다르게 Link 태그는 페이지 안에서 필요한 부분만 fetch 해온다.
Client Side navigate
브라우저에서 url을 직접 쳐서 이동하는 것과 달리 JS 상에서 page 컴포넌트를 교체하는 것. html이 reload 되지 않음. 예시 — background-color를 body에 주고 navigate 해보기. (a태그를 사용했을 때는 색상이 유지되지 않는 반면, Link태그를 사용하면 색상이 유지된다.)
Automatic Code Spliting — 최적화
- 특정 페이지에 접근 할 때, 해당 페이지를 그릴때 필요한 chunk만 로드
- 페이지 이동을 할 땐 목적지 페이지에 필요한 chunk만 추가 로드
Prefetching
스크롤해서 Viewport 에 Link 컴포넌트가 노출되는 순간 href로 연결된 페이지의 chunk를 미리 로드한다.
public/
정적 리소스를 Next.js로 서빙하기 위한 디렉토리
- robots.txt (예시 — https://www.reddit.com/robots.txt)) — 검색엔진의 크롤러가 수집할 수 있게 허용한 항목들을 결정해 놓은 리스트
- images — 태그의 src에 경로를 적을때, public 이 루트 디렉토리 가 된다.
<img src="/images/profile.jpg />
<Image src="/images/profile.jpg />
Image 컴포넌트
- Resizing(responsive 사이즈)
- Lazy load(Viewport에 들어오면 로드)
- 그외 optimization(webp 형태)
- CLS(Cumulative Layout Shift) — 누적 레이아웃 이동 을 최소화 한다. (특정 컴포넌트의 변경이나 등장에 다른 DOM 트리까지 리로드 되는 현상)
Head 컴포넌트
Metadata
웹 문서로서 제공하는 메타 정보들
- <title>제목</title>
- <Image />
- <description />
- 등 og(open graph) 태그
- <icon />
- third party script (예시 — Google Analytics 등)
YAML Front Matter
Metadata 표기 방식. Gray-matter 로 파싱.
Script 컴포넌트
- strategy: 로드 전략
- onLoad: 로드가 끝났을때 할 행동 정의
Styling
1. styled-jsx
2. CSS Modules
Global CSS
https://nextjs.org/learn/basics/assets-metadata-css/polishing-layout
- pages/_app.js 만들고
- styles/global.css 만들고 전역으로 적용할 스타일을 정의하고
- _app.js 에서 import ‘../styles/global.css’ 입력
페이지별로 Pre-rendering 방식을 선택할 수 있다.
- getStaticProps 를 사용하면 SSG
- getServerSideProps 를 사용하면 SSR
실제 코드에서 console.log 를 작성해서 확인 가능하다.
// SSR 예시
export async function getServerSideProps() {
const allPostsData = getSortedPostsData()
return {
props: {
allPostsData
}
}
}
// SSG 예시
export async function getStaticProps() {
const response = await fetch('http://localhost:3000/api/posts')
const json = await response.json()
return {
props: {
allPostsData: json.allPostsData
}
}
}
CSR 확인은 어떻게 해야할까? ‘파일을 읽어오는 것’은 서버에서만 가능하다. 따라서 파일을 읽어오려고 하면 , Failed to compile 에러가 뜰 것이다. 해결책은 API Routes 를 사용하면 된다.
// fs를 사용하는 함수는 Server-side 에서만 동작해야 한다. (getSortedPostsData)
// pages/api/posts.js
import { getSortedPostsData } = from '../../lib/posts'
export default function handler(req, res) {
const allPostsData = getSortedPostsData()
res.status(200).json({allPostsData})
}
// CSR 예시
const [allPostsData, setAllPostsData] = useState([])
useEffect(()=>{
fetch('/api/posts')
.then(res => res.json())
.then(data => setAllPostsData(data.allPostsData))
}, [])
*getSortedPostsData 함수 예시는 https://nextjs.org/learn/basics/data-fetching/blog-data 에서 확인 가능하다.
*SSG(getStaticProps)는 dev 환경에서는 SSR 처럼 실행된다. build 를 해야 확인 가능하다.
데이터를 가져오는 함수 getSortedPostsData 의 확장
- 다른 file 조회
- 외부 api 요청
- DB 조회
SSG 를 사용하면 좋은 페이지
- Marketing pages
- Blog posts
- E-commerce product listings
- Help and documentation
적용 여부 선택 기준
사용자가 페이지를 요청하기 전에 pre-render 할 수 있는가?
- Yes — SSG
- No — SSR || ISR || CSR
SSG의 2가지 케이스
- 외부 데이터 없이 pre-rendering (without data)
- 외부 데이터를 가져와서 pre-rendering (with data)
Next.js의 심화
Compiler — 언어를 다른언어로 변환
- SWC (speedy web compiler)— babel(Transpiler)의 17배, terser(Minifier — mangle&compress)의 7배 빠르다고 한다. 병렬처리를 고려한 Rust 라는 언어로 만들어졌다.
Preview mode — 쿠키를 이용해서 getStaticProps 를 요청시(request time)에도 이용
- setPreviewData — 쿠키 셋업.
- 활용사례 — CMS 페이지에서 내가 쓴 글을 유저는 못보고 나만 볼 수있게 하고자 하는 경우
Dynamic Import — 컴포넌트를 Lazy load 하는 방법. 초기 청크 사이즈 줄이기
- nextjs/dynamic
Suspense — Promise resolved 되어야 렌더
Automatic Static Optimization — 알아서 정적 파일과 동적 파일 구분
- 정적페이지는 .html 로
- 요청에 맞춰 동작하는 페이지는 .js 로
- getInitialProps 나 getServerSideProps 가 있다면 .js
router.query
- client-side 페이지의 경우 js 의 hydration 이후에 query 값을 읽을 수 있다.
Static HTML Export — 의도적으로 정적 파일로 export 가능
- Next.js 프로젝트를 정적인 파일들로만 Build 하는 것
- CDN 등에 올려서 서비스 제공 가능
- 단, Node.js 서버가 있어야 동작하는 기능들은 포기해야 한다
Custom App
- 상태 유지 / Page Component Wrapper
Custom Document
- 서버에서 실행하는 것. 모든 페이지에 공통인 영역(meta tag 등)
Custom Error Page
- Error 코드별로 원하는 에러 페이지 노출(404.js 등)
performance 측정
- web.dev
- reportWebVitals
Error Handling
- 에러 바운더리 컴포넌트
Data Fetching API
- getInitialProps
- getServerSideProps
- getStaticProps
Router Link API
next.config.js
Author들의 액션 통일
- lint-staged
- husky
원하는 기능을 찾아가는 방법
- 서비스를 찾아서 inspector 로 살펴보거나
*구글크롬 웹브라우저를 사용한다면 따라 만들고 싶은 웹사이트에서 검사도구를 열어서 div의 className을 보면 라이브러리 이름 키워드를 알 수 있다.
- 키워드를 찾아서 npm 에서 검색하거나
- 라이브러리를 찾아서 npm trends 로 찾아보거나
- 마땅한 라이브러리를 못찾으면 커스텀하거나 component ui 를 찾아본다
Infinite scroll 은 스크롤이 하단에 도달했는지 판단이 필요
- 그 판단을 위해 scroll event 를 활용할 수도 있고,
- intersection observer 를 활용할 수도 있다.(조금 더 효율적)
- scroll event 를 활용하면 잦은 호출을 방지하기 위해 throttle 을 적용하거나 requestAnimationFrame(rAF)를 활용하는 것이 좋다.
무한스크롤을 했을 경우
- React 에서 한 화면에 너무 많은 컴포넌트를 들고 있는 경우가 발생
- 로드한 컴포넌트가 늘어날록 느려지는 현상이 발생할 수 있음
- 그럴 때는 Virtual Scroll(가상 스크롤)을 활용할 수 있음
*Virtual Scroll(가상 스크롤) — 한 화면에서 다룰 컴포넌트 갯수 제한. n개의 컴포넌트만 그리게 한다. 이 요소를 재활용 할 수 있도록 해줌. 예를들면, 더보기 할때마다 9개가 불려올 경우 최대 18개만으로 돌려막기를 하는셈이다.
타 프로젝트의 prettier 설정 그대로 가져오기
yarn add -D prettier- .prettierrc
- .prettierignore
- prettier-fix 명령 추가(package.json > scripts)
jsconfig.json(절대경로) 생성 후 아래 설정을 추가하면,
{"compilerOptions": {"baseUrl": "src"}
import 땡땡땡 from ‘../../땡땡땡/땡땡’ 에서 상대경로 부분을 지울 수 있다. 즉, ‘땡땡땡/땡땡’ 만 남길 수 있다.
추천하는 vscode 익스텐션
- react snippets
- eslint
- prettier
- ctrl + shift + P > Open User Settings > settings.json 에 아래 코드 추가
"editor.guides.bracketPairs": "active",
"editor.bracketPairColorization.enabled": true
- Open Settings > format on save
- “default formatter” 입력 > HTML > “Format:Enable” 에 체크표시
참조
- 패스트캠퍼스 [Next.js 완전정복] — 확장성 높은 커머스 구축하기
메타데이터
- post_id
- adf89166cdcf
- slug
- next-js-12-확장성-높은-커머스-구축하기-adf89166cdcf
- url
- https://medium.com/@jeongrolee.tech/next-js-12-%ED%99%95%EC%9E%A5%EC%84%B1-%EB%86%92%EC%9D%80-%EC%BB%A4%EB%A8%B8%EC%8A%A4-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-adf89166cdcf
- canonical_url
- https://medium.com/@jeongrolee.tech/next-js-12-%ED%99%95%EC%9E%A5%EC%84%B1-%EB%86%92%EC%9D%80-%EC%BB%A4%EB%A8%B8%EC%8A%A4-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-adf89166cdcf
- author_url
- https://medium.com/@jeongrolee.tech
- status
- ok
- fetched_at
- 2026-06-27 18:20:27