렌더러 & 라우트
3.1 Render
Next.js 렌더링
Next.js에서 지원하는 다양한 렌더링 방식에 대한 설명입니다. 각 렌더링 방식은 상황에 맞게 사용될 수 있으며, 성능 및 사용자 경험에 영향을 미칩니다.
SEO 적용이 크게 중요하지 않거나 데이터 pre-rendering이 필요없다면 CSR
매 요청마다 화면이 달라지면서 서버 사이드로 렌더링을 하고자 한다면 SSR
정적 문서로 충분한 화면이면서 빠른 HTML 문서 반환이 필요하다면 SSG
컨텐츠가 동적이지만 자주 변경되지 않는 경우 ISR
SSR (Server Side Rendering)
SSR은 사용자가 요청할 때마다 서버에서 HTML을 생성하고 클라이언트에 전송하는 방식입니다. 초기 로딩 시 SEO와 최신 데이터를 요구하는 페이지에 적합합니다.
주요 특징:
서버에서 HTML을 생성하여 클라이언트에 전달
초기 페이지 로드 시 완전한 HTML 제공
SEO에 유리
페이지 요청 시마다 서버에서 렌더링 수행
사용 예:
CSR (Client Side Rendering)
CSR은 서버에서 전달된 기본 HTML에 JavaScript를 로드하여 브라우저에서 동적으로 콘텐츠를 렌더링하는 방식입니다. 사용자와 상호작용이 많은 페이지에서 적합합니다.
주요 특징:
첫 페이지 로드 시 빈 HTML이 전송되며, 이후 JavaScript가 데이터를 로드합니다.
초기 로드가 빠르지만, 콘텐츠 표시까지 시간이 걸릴 수 있습니다.
파일 상단에 'use client;'를 적어줍니다.
사용 예:
SSG (Static Site Generation)
SSG는 빌드 시점에 HTML을 생성하여 CDN에 배포하는 방식입니다. 데이터가 자주 변하지 않는 정적 콘텐츠에 적합합니다.
주요 특징:
HTML이 빌드 시에 생성되므로 매우 빠른 로딩 속도를 제공합니다.
정적 파일로 배포되므로 서버 부하가 적습니다.
SEO에 유리합니다
사용 예:
ISG (Incremental Static Generation)
SSR은 사용자가 요청할 때마다 서버에서 HTML을 생성하고 클라이언트에 전송하는 방식입니다. 초기 로딩 시 SEO와 최신 데이터를 요구하는 페이지에 적합합니다.
주요 특징:
SSG와 유사하게 빌드 시점에 HTML을 생성
특정 간격으로 페이지를 재생성하여 최신 데이터 반영
성능이 뛰어나면서도 최신 데이터 제공 가능
사용 예:
3.2 Route
Next.js 라우팅
Next.js 13버전 이상에서 사용되는 App Router의 라우팅 방법을 소개합니다.
용어

트리: 계층적 구조를 시각화하기 위한 규칙. 예를 들어, 부모 및 자식 컴포넌트가 있는 컴포넌트 트리, 폴더 구조 등.
서브트리: 새로운 루트(첫 번째)에서 시작하여 리프(마지막)에서 끝나는 트리의 일부.
루트: 트리 또는 서브트리의 첫 번째 노드, 예를 들어 루트 레이아웃.
리프: 자식이 없는 서브트리의 노드, 예를 들어 URL 경로의 마지막 세그먼트.

URL 세그먼트: 슬래시로 구분된 URL 경로의 일부.
URL 경로: 도메인 이후에 오는 URL의 일부로, 세그먼트로 구성됨.
경로 생성하기
Next.js는 파일 시스템 기반의 라우터를 사용하여 폴더를 경로 정의에 사용합니다.
각 폴더는 URL 세그먼트에 매핑되는 경로 세그먼트를 나타냅니다.

page.tsx
파일은 경로 세그먼트를 공개적으로 접근할 수 있도록 합니다.

이 예에서, /dashboard/analytics
URL 경로는 해당 page.tsx
파일이 없기 때문에 공개적으로 접근할 수 없습니다. 이 폴더는 컴포넌트, 스타일시트, 이미지 또는 다른 콜로케이트 파일을 저장하는 데 사용할 수 있습니다.
파일 규칙
Next.js는 중첩 경로에서 특정 동작을 가진 UI를 생성하기 위해 일련의 특수 파일을 제공합니다:
| 세그먼트와 자식에 대한 공유 UI |
| 경로의 고유한 UI로 경로를 공개적으로 접근 가능하게 만듭니다. |
| 세그먼트와 자식에 대한 로딩 UI |
| 세그먼트와 자식에 대한 Not Found UI |
| 세그먼트와 자식에 대한 오류 UI |
| 글로벌 오류 UI |
| 서버 사이드 API 엔드포인트 |
| 특수한 재렌더링된 레이아웃 UI |
| [병렬 경로]에 대한 폴백 UI |
컴포넌트 계층 구조
특수 파일에 정의된 React 컴포넌트는 특정 계층 구조로 렌더링됩니다:
layout.js
template.js
error.js
(React 오류 경계)loading.js
(React 서스펜스 경계)not-found.js
(React 오류 경계)page.js
또는 중첩layout.js

중첩 경로에서는 세그먼트의 컴포넌트가 부모 세그먼트의 컴포넌트 내부에 중첩됩니다.

3.3 Fetch
Next.js Data Fetching
Next.js 13부터 도입된 App Router는 서버 컴포넌트와 클라이언트 컴포넌트를 명확히 구분하여 사용할 수 있게 해줍니다. 이로 인해 데이터 페칭과 캐싱 전략도 각각 다르게 적용할 수 있습니다. 아래는 서버 컴포넌트와 클라이언트 컴포넌트에서 데이터 페칭과 캐싱을 다루는 방법에 대한 설명입니다.
서버 컴포넌트에서 데이터 페칭 및 캐싱
서버 컴포넌트는 서버에서 렌더링되며, 데이터 페칭을 위해 fetch 함수
를 사용할 수 있습니다. 서버 컴포넌트는 클라이언트에게 HTML을 반환하기 전에 데이터를 가져올 수 있기 때문에, 초기 로딩 성능이 향상됩니다.
fetch 함수 사용 예시
캐싱
Next.js의 fetch 함수는 기본적으로 캐싱을 지원합니다. fetch 함수의 두 번째 인자로 캐싱 옵션을 설정할 수 있습니다. 예를 들어, cache 옵션을 사용하여 캐싱 동작을 제어할 수 있습니다.
캐싱 옵션
no-store: 항상 최신 데이터를 가져옵니다.
force-cache: 캐시된 데이터를 사용하고, 없으면 네트워크 요청을 합니다.
only-if-cached: 캐시된 데이터가 있을 때만 사용합니다.
클라이언트 컴포넌트에서 데이터 페칭 및 캐싱
클라이언트 컴포넌트는 브라우저에서 실행되며, 데이터 페칭을 위해 axios
와 같은 라이브러리를 사용할 수 있습니다. 클라이언트 컴포넌트에서는 SWR
이나 TanStack Query
와 같은 라이브러리를 사용하여 캐싱을 관리할 수 있습니다
TanStack Query를 사용한 데이터 페칭 및 캐싱 예시
3.4 State (Server)
서버 상태
Next.js 애플리케이션에서 서버 상태 관리는 클라이언트와 서버 간의 데이터 동기화를 효율적으로 처리하는 데 중요한 역할을 합니다. 서버 상태는 서버에서 관리되는 데이터로, 클라이언트에서 직접 수정할 수 없으며 서버와의 통신을 통해서만 변경할 수 있습니다
서버 상태 관리의 중요성
데이터 일관성 유지: 서버 상태 관리를 통해 클라이언트와 서버 간의 데이터 일관성을 유지할 수 있습니다.
성능 최적화: 서버 상태를 효율적으로 관리하면 불필요한 네트워크 요청을 줄이고, 캐싱을 통해 성능을 최적화할 수 있습니다.
사용자 경험 향상: 서버 상태를 적절히 관리하면 사용자에게 더 빠르고 일관된 경험을 제공할 수 있습니다.
서버 상태 관리 도구
1. SWR (Stale-While-Revalidate)
SWR은 Vercel에서 개발한 React Hooks 라이브러리로, 데이터 페칭을 간단하게 만들고 캐싱을 자동으로 관리해줍니다. SWR은 "Stale-While-Revalidate" 전략을 사용하여 빠른 데이터 로딩과 최신 데이터 동기화를 동시에 처리합니다.
주요 기능
자동 캐싱 및 재검증: 데이터가 오래되면 자동으로 재검증합니다.
포커스 재검증: 사용자가 브라우저 탭을 다시 활성화할 때 데이터를 자동으로 재검증합니다.
폴링: 주기적으로 데이터를 갱신할 수 있습니다.
사용 예시
2. TanStack Query (React Query)
TanStack Query는 서버 상태 관리를 위한 강력한 라이브러리로, 데이터 페칭, 캐싱, 동기화 및 서버 상태 관리를 간편하게 처리할 수 있습니다.
주요 기능
자동 캐싱 및 백그라운드 데이터 갱신: 데이터를 자동으로 캐싱하고 백그라운드에서 갱신합니다.
쿼리 무효화: 특정 조건에서 쿼리를 무효화하고 데이터를 다시 가져올 수 있습니다.
병렬 및 의존성 쿼리: 병렬로 여러 쿼리를 실행하거나, 특정 쿼리가 완료된 후 다른 쿼리를 실행할 수 있습니다.
사용 예시
3.5 State (Client)
클라이언트 상태
클라이언트 상태 관리는 사용자 인터페이스와 관련된 상태를 관리하는 데 중요한 역할을 합니다. 클라이언트 상태는 서버와의 통신 없이도 클라이언트 측에서 직접 관리되고 변경될 수 있는 상태를 의미합니다.
각 컴포넌트에서는 지역 상태 (
useState
,useRef
)로 상태를 관리합니다.전역 상태를 관리하기 위해서 기본 제공되는
React Context API
를 사용할수 있고, 다양한 상태관리 라이브러리(zustand
,jotai
,recoil
,redux
)를 사용할 수 도있습니다.
클라이언트 상태 관리의 중요성
상태 일관성 유지: 클라이언트 상태 관리를 통해 컴포넌트 간의 상태 일관성을 유지할 수 있습니다.
성능 최적화: 불필요한 렌더링을 줄이고, 필요한 부분만 업데이트하여 성능을 최적화할 수 있습니다.
코드 구조 개선: 상태 관리를 중앙화하여 코드의 가독성과 유지보수성을 높일 수 있습니다.
클라이언트 상태 관리 도구
1. Context API
React Context API는 프로젝트의 상위/하위 컴포넌트 간 데이터 공유 방식입니다. useContext
는 React의 내장 훅으로, 컴포넌트 트리 전체에 데이터를 전역적으로 전달할 수 있게 해줍니다. 간단한 상태 관리에 적합하며, 별도의 라이브러리 설치가 필요 없습니다.
주요 특징
간단하고 직관적: 기본적인 전역 상태 관리에 적합합니다.
내장 기능: 별도의 라이브러리 설치가 필요 없습니다.
성능 문제: 상태가 변경될 때마다 모든 하위 컴포넌트가 다시 렌더링될 수 있습니다.
React에서 발생하는 문제점인
Props drilling
을 해결하기 위한 수단입니다.

2. Zustand
Zustand는 간단하고 직관적인 API를 제공하는 상태 관리 라이브러리로, 작은 크기와 빠른 성능을 자랑합니다. 전역 상태를 쉽게 관리할 수 있게 해줍니다.
주요 특징
typescript로 작성되었습니다.
redux를 축소화시킨 느낌으로 redux와 유사합니다.
provider가 필요없어 상태 변경 시 불필요한 리랜더링을 최소화합니다.
보일러플레이트가 거의 없습니다.
한 개의 중앙에 집중된 형식의 스토어 구조를 활용하면서, 상태를 정의하고 사용하는 방법이 단순합니다.
Flux 패턴으로 동작합니다.

3.6 Configs
Next.js 프로젝트의 루트 폴더에 위치한 설정 파일들에 대한 설명입니다. 이 파일들은 프로젝트의 빌드, 스타일링, 코드 포맷팅, 타입스크립트 설정 등을 관리합니다.
next.config.mjs
next.config.mjs
파일은 Next.js 설정을 정의합니다.
tsconfig.json
tsconfig.json
파일은 TypeScript 설정을 정의합니다.
postcss.config.js
postcss.config.js
파일은 PostCSS 설정을 정의합니다. PostCSS는 CSS를 변환하는 도구로, 다양한 플러그인을 통해 CSS를 처리할 수 있습니다. 주로 Tailwind CSS와 같은 도구와 함께 사용됩니다.
prettier.config.js
prettier.config.js
파일은 Prettier 설정을 정의합니다. Prettier는 코드 포맷터로, 일관된 코드 스타일을 유지하는 데 도움을 줍니다.
tailwind.config.js
tailwind.config.js
파일은 Tailwind CSS 설정을 정의합니다. Tailwind CSS는 유틸리티 퍼스트 CSS 프레임워크로, 빠르게 스타일링을 할 수 있게 해줍니다.
3.7 Env
Next.js 환경변수(env)
Next.js에서 환경 변수는 어플리케이션을 구성하는 동안 또는 어플리케이션이 실행 중일 때 사용되는 외부 구성 옵션입니다. 이러한 변수들은 보안 정보(예: API 키), 연결 설정, 플래그 및 다양한 실행 환경에 대한 세부 정보와 같은 중요한 데이터를 저장하는 데 사용됩니다. 환경 변수의 사용은 소스 코드 내에 구성 데이터를 하드코딩하는 것을 방지하고, 보안을 강화하며, 개발 및 프로덕션 환경 간에 쉽게 전환할 수 있는 능력을 제공합니다.
환경 변수를 사용해야 하는 이유
보안: 민감한 정보가 버전 제어 시스템에 노출되지 않아 응용 프로그램을 잠재적인 위협으로부터 보호할 수 있습니다.
환경 구분: 다양한 환경(예: 개발, 생산)에 대해 코드베이스를 변경하지 않고도 다른 설정을 사용할 수 있습니다. 이를 통해 쉬운 전환과 일관된 성능을 달성할 수 있습니다.
코드 이식성 및 깔끔함: 구성 세부 사항이 내장되지 않은 코드는 더 깔끔하고 논리에 집중됩니다. 이로 인해 코드의 가독성이 향상되고 동일한 코드베이스를 다른 환경에서 다른 구성으로 사용할 수 있어 이식성이 높아집니다.
변경의 용이성: 비밀 또는 구성이 변경된 경우 코드를 변경하고 응용 프로그램을 다시 배포하는 것보다 환경 변수를 업데이트하는 것이 훨씬 쉽고 안전합니다.
환경 변수 사용 방법
환경별 파일 분리
각각 로컬 / 개발 / 운영 환경에서 사용할 환경변수를 다른 파일로 분리하여 관리합니다
.env.local
.env.dev
.env.prod
브라우저에 변수 노출
브라우저에서 사용되는 변수는 NEXT_PUBLIC_
접두사를 붙여야 합니다. 그러나 이러한 변수는 공개적으로 접근할 수 있으므로 민감한 정보를 담지 않아야 합니다.
환경 변수 사용
process.env
네임스페이스를 사용하여 액세스할 수 있습니다
.env.local 예시
AUTH 관련한 설정과, 서버 URL 그리고 브라우저에서 노출되는 NEXT_PUBLIC 접두어를 가진 서버 URL, RECAPTCHA KEY, COPY & CUT, 루트 메뉴이름 옵션등이 존재합니다.
3.8 Auth
Auth - next-auth
NextAuth는 Next.js 애플리케이션에서 인증을 쉽게 구현할 수 있도록 도와주는 라이브러리입니다. 다양한 인증 제공자(Google, Facebook, GitHub 등)를 지원하며, 사용자 정의 인증 로직도 쉽게 추가할 수 있습니다.
next-auth가 5버전 부터는 auth.js로 이름이 변경되었는데, 아직 불안정하여 4.24.10 버전을 사용하였습니다.
auth.ts
auth.ts
모든 인증 관련 로직을 처리하는 핵심 파일입니다.
Providers
providers
는 사용자가 로그인할 때 사용할 수 있는 인증 제공자를 정의합니다. NextAuth는 다양한 제공자를 지원하며, 각 제공자는 고유한 설정이 필요합니다.환경변수
NEXTAUTH_SECRET
를 선언하여 토큰 정보를 encrypt, decrypt할때 사용합니다.encRSA
함수를 이용하여 비밀번호를 RSA 암호화합니다.환경변수
NEXTAUTH_URL
로 Chamomile 로그인 API를 호출합니다.response로 받은 accessToken, refreshToken을 반환합니다.
Callbacks - jwt
jwt
콜백은 JSON Web Token(JWT)을 생성하거나 갱신할 때 호출됩니다로그인 이후에 user정보와, 만료시간을 token에 저장해줍니다
refresh token 강제 갱신 trigger 발생시에 토큰 재발급 함수(getNewRefreshToken)를 호출합니다.
환경변수
NEXTAUTH_REFRESH_TIME
에 정의된 시간(기본 300초) 이하로 만료시간이 남으면, 토큰 재발급 함수(getNewRefreshToken)를 호출합니다.
Callbacks - session
session
콜백은 세션이 생성되거나 갱신될 때 호출됩니다.브라우저에서 useSession을 호출할때 사용되며, 브라우저에서 노출되는 세션 객체를 반환합니다.
gnb-info
handleRefreshToken
함수에서 update()를 호출하여 auth.ts의 jwt함수의 trigger로 'update' 값을 전달하여 토큰 재발급 합니다.signOut
을 호출하여 세션을제거하고 로그아웃합니다.
middleware
middleware
에서 매 요청시 토큰을 확인하고, 토큰이 있으면 그대로 반환, 토큰이 없으면 login 페이지로 redirect합니다.
3.9 i18n
i18n(internationalization)
Next.js에서 다국어를 제공하는 방법에 대한 내용입니다.
react-i18next
react-i18next
는 React 애플리케이션에서 국제화(i18n)를 쉽게 구현할 수 있도록 도와주는 라이브러리입니다.react-i18next의 app router에 적용하는 방법을 참고하여 적용하였습니다.
i18next app router 공식 가이드사용 라이브러리
다국어 처리
선택된 언어는 url의 첫번째 세그먼트([lng])에 위치합니다.
예시) chamomile.com
/ko
/login, chamomile.com/en
/login
middleware.ts
middleware에서 라우팅 기반의 언어를 설정, 예외처리 합니다.
언어 설정
: acceptLanguage.languages(languageList);를 통해 지원하는 언어 목록을 설정합니다. 클라이언트의 쿠키에서 언어 설정을 가져오고(req.cookies.get(cookieName)), 쿠키에 설정된 언어가 없으면 Accept-Language 헤더에서 언어를 가져옵니다. 쿠키와 헤더 모두에서 언어를 찾지 못하면 기본 언어(fallbackLng)를 사용합니다.지원하지 않는 언어 경로 리다이렉션
: 요청된 경로가 지원하는 언어 목록(languageList)에 포함되지 않으면, 기본 언어 경로로 리다이렉트합니다. 예를 들어, /es/some-path가 지원되지 않는 경우, /en/some-path로 리다이렉트합니다.참조(referer) 기반 언어 설정
:요청 헤더에 referer가 있는 경우, 참조 URL에서 언어를 추출하여 쿠키에 저장합니다. 이를 통해 사용자가 이전에 방문한 페이지의 언어 설정을 유지할 수 있습니다.
language-selector.tsx
LanguageSelector 컴포넌트에서는 지원하는 언어를 렌더링하며, 언어를 선택할 시에 라우팅 변경하여 다국어를 선택할 수 있게 합니다.
/src/app/i18n/locales 폴더
언어 번역 json파일이 위치하는 폴더입니다. /locales/[lng]/[namespace].json
형태로 존재합니다.
ko(한국어)
en(영어)
ja(일본어)
zh(중국어)
vi(베트남어)
it(이탈리아어)
client.ts
i18next 설정 및 React용 useTranslation 커스텀 훅
i18next를 초기화하고, 백엔드 및 로컬 번역 리소스를 병합하여 다국어 지원을 제공합니다.
페이지(컴포넌트)에서 사용 예시
useTransaction
훅에 언어코드(params.lng
)와 네임스페이스(namespace
)를 설정합니다.메시지에 변수 삽입 (interpolation)
메시지에 key(
{0}
,{1}
,{userName}
등)가 포함되어 있으면 변수를 삽입할 수 있습니다.
3.10 Typescript
TypeScript는 정적 타입을 제공하여 코드의 안정성과 가독성을 높여줍니다.
타입 정의 위치 및 규칙
타입 정의는 src/types/ 폴더 아래에 파일을 생성하여 관리합니다. menu.ts, user.ts 등의 파일을 생성하여 각 파일에 타입을 정의합니다.
각 컴포넌트 내에서만 사용하는 타입은 컴포넌트 상단에 정의하여 사용합니다.
Typescript 컨벤션
Props 컨벤션
주요 타입
원시 타입 (Primitive Types)
string
: 문자열 타입number
: 숫자 타입boolean
: 불리언 타입null
: 널 타입undefined
: 정의되지 않은 타입
React 컴포넌트 관련 타입
ReactNode
: 렌더링 가능한 모든 타입 (JSX, 문자열, 숫자 등)
이벤트 핸들러 타입
MouseEvent
: 마우스 이벤트 타입ChangeEvent
: 입력 값 변경 이벤트 타입
KeyboardEvent
: 키보드 이벤트 타입FormEvent
: 폼 이벤트 타입
클릭 핸들러에서 사용하는 타입
MouseEvent<HTMLButtonElement>
: 버튼 클릭 이벤트 타입
상태 관리 관련 타입
SetStateAction<타입>
: setState 함수의 인자 타입Dispatch<SetStateAction<타입>>
: setState 함수 타입
**.d.ts 파일
d.ts 파일은 TypeScript에서 타입 선언 파일로 사용됩니다. 이 파일은 주로 타입 정의를 확장하거나 커스터마이징하기 위해 사용됩니다.
d.ts 파일은 TypeScript 컴파일러에게 특정 모듈이나 라이브러리의 타입 정보를 제공하여, 코드 작성 시 타입 안전성을 높이고, 코드 자동 완성 기능을 개선하는 데 도움을 줍니다.
3.11 package.json
package.json은 Node.js 프로젝트의 메타데이터와 종속성(dependencies)을 관리하는 데 사용됩니다.
scripts
로컬 환경에서 개발서버를 시작할 때
개발 환경에서 개발 서버를 시작할 때
프로젝트를 빌드합니다. Next.js 애플리케이션을 프로덕션 환경에 배포할 수 있도록 최적화된 정적 파일로 빌드합니다.
빌드된 프로젝트를 시작합니다. next build 명령어로 빌드된 파일을 사용하여 프로덕션 서버를 시작합니다.
dependencies, devDependencies
dependencies는 애플리케이션이 실행될 때 필요한 패키지를 정의합니다
devDependencies는 개발 환경에서만 필요한 패키지를 정의합니다.
패키지 추가
패키지 삭제
package-lock.json
생성된 node modules 폴더의 정보를 담고있는 파일
npm을 사용해서 node_modules 트리나 package.json 파일을 수정하게 되면 자동으로 생성/수정
package-lock.json 파일이 생성되는 시점의 의존성 트리에 대한 정확한 정보를 포함
3.12 Layout
웹 화면 레이아웃 구성요소에 대한 설명입니다
GNB (Global Navigation Bar)
GNB는 웹 사이트의 전역 탐색 바를 의미합니다. 일반적으로 페이지 상단에 위치하며, 사이트의 주요 섹션으로 이동할 수 있는 링크를 포함합니다. GNB는 사용자가 사이트 내에서 쉽게 탐색할 수 있도록 도와줍니다.
주요 기능:
사이트의 주요 섹션으로의 빠른 이동
로고 및 브랜드 아이덴티티 표시
사용자 로그인/로그아웃, 프로필 접근 등의 사용자 계정 관련 기능
LNB (Left Navigation Bar)
LNB는 왼쪽 탐색 바를 의미합니다. 페이지의 왼쪽에 위치하며, 현재 섹션 내에서의 세부 항목으로 이동할 수 있는 링크를 포함합니다. LNB는 사용자가 특정 섹션 내에서 세부 항목을 쉽게 탐색할 수 있도록 도와줍니다.
주요 기능:
현재 섹션 내의 세부 항목으로의 빠른 이동
섹션 내의 계층 구조 표시
사용자가 현재 위치를 쉽게 파악할 수 있도록 도움
Header
Header는 페이지의 상단에 위치한 영역으로, GNB와 함께 사이트의 주요 정보를 표시합니다. 일반적으로 사이트의 로고, 검색 바, 사용자 계정 정보 등을 포함합니다.
주요 기능:
사이트의 로고 및 브랜드 아이덴티티 표시
검색 기능 제공
사용자 계정 정보 및 알림 표시
FNB (Footer Navigation Bar)
FNB는 페이지의 하단에 위치한 탐색 바를 의미합니다. 사이트의 주요 섹션으로 이동할 수 있는 링크와 추가적인 정보(예: 저작권 정보, 연락처 정보 등)를 포함합니다.
주요 기능:
사이트의 주요 섹션으로의 빠른 이동
저작권 정보 및 법적 고지 사항 표시
연락처 정보 및 소셜 미디어 링크 제공
Page Header
Page Header는 특정 페이지의 상단에 위치한 영역으로, 해당 페이지의 제목 및 주요 정보를 표시합니다. 사용자가 현재 어떤 페이지에 있는지 명확하게 인식할 수 있도록 도와줍니다.
주요 기능:
페이지 제목 및 주요 정보 표시
페이지의 목적 및 내용을 간략히 설명
Breadcrumb
Breadcrumb는 사용자가 현재 위치한 페이지의 경로를 표시하는 탐색 도구입니다. 일반적으로 페이지 상단에 위치하며, 사용자가 사이트 내에서 이동한 경로를 시각적으로 표시합니다.
주요 기능:
사용자가 현재 위치한 페이지의 경로 표시
사용자가 이전 페이지로 쉽게 이동할 수 있도록 도움
사이트의 계층 구조를 시각적으로 제공
3.13 UI : L-UI
Introduction
캐모마일의 UI 컴포넌트 라이브러리는 L-UI를 사용합니다. L-UI는 Lotte Innovate 디자인 가이드를 적용한 전사 표준 UI 라이브러리입니다.
주요 특징
웹 표준 및 접근성 준수
Headless UI Library인 radix-ui를 사용하여 웹 접근성을 보장합니다.
정부 UI/UX 가이드라인을 준수하여 개발되었습니다.
다양한 컴포넌트
62가지 이상의 UI 컴포넌트와 6가지의 차트를 제공합니다.
일관된 디자인
모든 컴포넌트와 차트에 공통 Props (Color, Radius, Scaling, Weight, Appearance, Size)를 적용하여 디자인의 통일성을 유지합니다.
다크모드에서도 표준화된 색상을 적용하여 모든 컴포넌트에 일관되게 적용합니다.
스토리북 통합
Storybook을 통해 문서화된 컴포넌트의 모습을 볼 수 있습니다.
npm 패키지 배포
npm 패키지로 배포되어, 프로젝트에 쉽게 설치하고 사용할 수 있습니다.
Installation
또는
Usage
프로젝트 App 진입 파일에 다음 줄을 추가해줍니다.
Theme
각 컴포넌트들은 공통 Props를 개별적으로 적용할 수도 있고, 테마를 통해 컴포넌트의 스타일을 한번에 변경할 수도 있습니다.
L-UI는 테마 컨텍스트를 제공하여 Color
, Radius
, Scaling
, Weight
를 모든 컴포넌트에 동일한 스타일을 지정할 수 있습니다.
ThemeProvider
를 프로젝트의 가장 가까운 layout.tsx
파일에 추가해야 합니다.
이렇게 하면 ThemeProvider
가 해당 레이아웃 내의 모든 컴포넌트에 테마 상태를 제공할 수 있습니다.
테마를 변경하려면 useTheme
훅을 사용합니다.
useTheme
훅은 현재 테마와 테마를 업데이트할 수 있는 함수를 제공합니다.
테마가 적용되었지만 일부 컴포넌트는 스타일을 다르게 하고 싶은 경우, 각 컴포넌트에 직접 Props를 전달하여 스타일을 재정의할 수 있습니다.
3.14 Style : TailwindCSS
Tailwind CSS 컨벤션 및 가이드
Tailwind CSS는 유틸리티 퍼스트 CSS 프레임워크로, 빠르고 쉽게 스타일링을 할 수 있도록 도와줍니다. 이 가이드는 tailwind.config.js
파일을 바탕으로 작성되었습니다.
className 예시
레이아웃
Flexbox:
flex
,flex-row
,flex-col
,justify-center
,items-center
Grid:
grid
,grid-cols-1
,grid-cols-2
,gap-4
Spacing:
p-4
,m-4
,mt-4
,mb-4
,ml-4
,mr-4
Spacing:
p-4
,m-4
,mt-4
,mb-4
,ml-4
,mr-4
,px-4
,py-4
,mx-4
,my-4
배경 및 테두리
Background Color:
bg-white
,bg-gray-100
,bg-blue-500
Border:
border
,border-2
,border-gray-300
,rounded
,rounded-full
텍스트
Typography:
text-sm
,text-lg
,text-xl
,text-2xl
,font-bold
,font-semibold
Text Color:
text-gray-700
,text-blue-500
,text-white
Text Alignment:
text-left
,text-center
,text-right
크기
Width:
w-1/2
,w-full
,w-screen
Height:
h-1/2
,h-full
,h-screen
반응형 디자인
Responsive Prefixes:
sm:
,md:
,lg:
,xl:
예:
sm:text-sm
,md:text-lg
,lg:text-xl
,xl:text-2xl
커스텀 값
Tailwind CSS에서는 p-[value]
, m-[value]
와 같은 형태로 커스텀 값을 사용할 수 있습니다. 이 방법을 사용하면 Tailwind의 기본 스케일 외의 값을 사용할 수 있습니다.
Global CSS 파일에 정의
Tailwind CSS를 사용하는 프로젝트에서 global.css 파일을 사용하여 전역 스타일을 정의할 수 있습니다. 예를 들어, 기본적인 HTML 요소의 스타일을 정의할 수 있습니다.
Tailwind Config 파일에 커스텀 색상 정의
Tailwind CSS를 사용하는 프로젝트에서 global.css 파일을 사용하여 전역 스타일을 정의할 수 있습니다. 예를 들어, 기본적인 HTML 요소의 스타일을 정의할 수 있습니다.
이렇게 정의한 커스텀 색상은 Tailwind CSS 클래스에서 사용할 수 있습니다.
3.15 Form : React Hook Form
react-hook-form 컨벤션 및 가이드
Introduction
react-hook-form은 React의 훅을 사용하여 폼 상태와 유효성 검사를 관리하는 라이브러리입니다. 이 라이브러리는 간단하고 직관적인 API를 제공하여 폼을 쉽게 관리할 수 있게 해줍니다.
사용 이유
성능 최적화:
react-hook-form
은 폼 상태를 최소한으로 리렌더링하여 성능을 최적화합니다.간단한 API: 직관적이고 사용하기 쉬운 API를 제공합니다.
유효성 검사: 다양한 유효성 검사 방법을 지원합니다.
작은 번들 크기: 가벼운 라이브러리로, 번들 크기를 최소화합니다.
기본 문법
react-hook-form
을 사용하여 폼을 생성하는 기본적인 방법은 다음과 같습니다:
이 프로젝트에서 react-hook-form을 사용한 컴포넌트
프로젝트에서 react-hook-form
을 사용하여 만든 컴포넌트는 다음과 같습니다:
<FormItemTextField />
<FormItemSelect />
<FormItemRadio />
<FormItemFile />
<FormItemCheckbox />
<SearchForm />
각 컴포넌트들은 react-hook-form
의 기본 Props인 field
, required
등을 전달 받아 폼 형식으로 구현됩니다.
폼 구현 예제
위의 컴포넌트들을 사용하여 폼을 구현하는 방법은 다음과 같습니다:
에러 핸들링과 제출 방법
폼 제출 시 에러 핸들링과 제출 방법은 handleSubmit
함수를 사용하여 처리할 수 있습니다. handleSubmit
함수는 두 개의 콜백 함수를 인수로 받습니다: 하나는 제출 성공 시 호출되는 함수이고, 다른 하나는 에러 발생 시 호출되는 함수입니다.
onSubmit
함수
onSubmit
함수는 폼 데이터가 유효할 때 호출됩니다. 이 함수에서 폼 데이터를 처리할 수 있습니다.
onError
함수
onError
함수는 폼 데이터가 유효하지 않을 때 호출됩니다. 이 함수에서 에러를 처리할 수 있습니다.
폼 상태 관리
react-hook-form
은 폼 상태를 관리하기 위한 다양한 기능을 제공합니다.
isDirty
isDirty
를 사용하여 폼이 수정되었는지 여부를 확인할 수 있습니다.
dirtyFields
dirtyFields
는 수정된 필드들을 포함하는 객체입니다. 각 필드의 이름을 키로 사용하여 해당 필드가 수정되었는지 여부를 확인할 수 있습니다.
isValid
isValid
는 폼의 모든 필드가 유효한지 여부를 나타냅니다. 모든 필드가 유효할 때 true
가 됩니다.
isSubmitting
isSubmitting
은 폼이 제출 중인지 여부를 나타냅니다. 폼이 제출되는 동안 true
가 됩니다.
isSubmitted
isSubmitted
는 폼이 한 번이라도 제출되었는지 여부를 나타냅니다. 폼이 제출된 후 true가 됩니다.
errors
errors
는 폼 필드의 유효성 검사 오류를 포함하는 객체입니다. 각 필드의 이름을 키로 사용하여 해당 필드의 오류 메시지를 확인할 수 있습니다.
touchedFields
touchedFields
는 사용자가 상호작용한 필드들을 포함하는 객체입니다. 각 필드의 이름을 키로 사용하여 해당 필드가 터치되었는지 여부를 확인할 수 있습니다.
그 외 주요 기능들
react-hook-form
은 폼을 관리하고 유효성 검사를 수행하기 위한 다양한 훅과 컴포넌트를 제공합니다. 여기에는 Controller
, useForm
, useFormContext
, watch
등이 포함됩니다.
useForm
useForm
훅은 폼을 관리하기 위한 기본 훅입니다. 이 훅은 폼 상태와 유효성 검사를 관리하는 데 필요한 메서드와 객체를 반환합니다.
Controller
Controller
컴포넌트는 비제어 컴포넌트를 react-hook-form
과 함께 사용할 수 있도록 도와줍니다. Controller
는 render
prop을 사용하여 폼 필드를 렌더링하고, 폼 상태와 유효성 검사를 관리합니다.
useFormContext
useFormContext
훅은 폼 컨텍스트를 사용하여 중첩된 컴포넌트에서 폼 상태와 메서드에 접근할 수 있도록 합니다. 이 훅은 FormProvider
컴포넌트와 함께 사용됩니다.
watch
watch
훅은 폼 필드의 값을 관찰하고, 값이 변경될 때마다 업데이트를 받을 수 있도록 합니다. 특정 필드나 모든 필드의 값을 관찰할 수 있습니다.
3.16 Date : Day.js
date 라이브러리 - dayjs
dayjs
는 JavaScript 날짜 라이브러리로, 날짜와 시간을 쉽게 다룰 수 있도록 도와줍니다. moment.js
와 유사한 API를 제공하지만, 더 가볍고 빠른 성능을 지원합니다.
날짜 표시
날짜 변경
날짜 더하기
날짜 빼기
3.17 Grid : TanStack Table
Grid - Tanstack Table Guide
Introduction
L-UI 의 Table
컴포넌트는 Tanstack Table
을 커스텀하여 사용합니다.
TanStack Table은 React 애플리케이션에서 유연한 테이블을 구성할 수 있도록 도와주는 라이브러리입니다. 이전에는 react-table
로 알려져 있었으며, 다양한 기능과 높은 성능을 제공하여 복잡한 테이블을 쉽게 구현할 수 있습니다.
주요 기능
정렬: 컬럼별 정렬 기능 제공
페이징: 데이터 페이징 처리
필터링: 데이터 필터링 기능
그룹화: 데이터 그룹화 기능
확장: 행 확장 기능 제공
선택: 행 선택 기능 제공
TanStack Table 선정 이유
프로젝트에서 TanStack Table을 사용하는 이유는 다음과 같습니다:
유연성: 다양한 기능을 손쉽게 커스터마이징할 수 있습니다.
성능: 대용량 데이터 처리에 최적화되어 있습니다.
확장성: 필요한 기능을 쉽게 확장할 수 있습니다.
커뮤니티 지원: 활발한 커뮤니티와 풍부한 문서 지원을 받습니다.
Usage
useReactTable
을 커스터마이징한 useGrid
훅과 L-UI
에서 Table
, @tanstack/react-table
을 활용하여 만든 그리드 컴포넌트 <Grid />
을 함께 사용합니다.
Tanstack Table 기타 속성
Column Visibility 설정
그리드 컬럼에 대한 숨김 여부는
useGrid()
에initialState
onColumnVisibilityChange
속성을 통해 처리할 수 있습니다.
더 자세한 사항은 TanstackTable 공식 문서에서 자세하게 볼 수 있습니다.
TanStack Table 사용 시 주의점 ‼️
데이터 상태관리
리액트 개발 환경에서 Grid에 전달되는
data
와columns
는 stable한 상태로 제공되어야 합니다. 그렇지 않은 경우 무한 루프를 발생시킬 수 있습니다.data
와columns
은React.useMemo()
,React.useState()
을 사용해야 합니다.해당 내용은 그리드 데이터 참조 가이드에서 자세하게 볼 수 있습니다.
columns
의 동적 변경
특정 상황에서는
columns
를 동적으로 변경해야 할 필요가 있을 수 있습니다.이 경우
useState
를 사용하는 것이 적절합니다. 예를 들어, 사용자가 컬럼을 동적으로 추가하거나 제거할 수 있는 기능을 구현하려는 경우useState
를 사용하는 것이 더 적합합니다.
이 외에도 Tanstack Table에서 제공하는 다양한 함수와 옵션은 Tanstack Table 공식 문서를 참고하세요.
L-UI상에서 테마 적용과 간단한 예시는 L-UI Grid 스토리북 가이드를 참고하세요.
3.18 Editor : TinyMCE
Editor - Tinymce Guide
Introduction
L-UI
의 Editor
컴포넌트는 Tinymce
을 커스텀하여 사용합니다.
TinyMCE는 웹 애플리케이션에서 사용할 수 있는 강력한 WYSIWYG(What You See Is What You Get)
HTML 에디터입니다. 사용자가 텍스트를 입력하고 포맷팅할 수 있는 인터페이스를 제공하며, 다양한 기능과 플러그인을 통해 확장할 수 있습니다.
TinyMCE
는 오픈 소스이며, 현재는 다양한 상용 플랜도 제공하고 있습니다. L-UI
의 Editor
는 무료 플랜을 기반으로 커스텀되어 있습니다.
주요 기능
텍스트 포맷팅: 굵게, 기울임, 밑줄, 글자 색상 등 다양한 텍스트 포맷팅 기능 제공
리스트: 순서 있는 리스트와 순서 없는 리스트 생성
링크: 하이퍼링크 삽입 및 편집
이미지: 이미지 삽입 및 편집
표: 표 삽입 및 편집
플러그인: 다양한 플러그인을 통해 기능 확장 가능
테마: 다양한 테마와 스킨을 통해 에디터의 외관 커스터마이징 가
TinyMCE 선정 이유
프로젝트에서 TinyMCE를 사용하는 이유는 다음과 같습니다:
사용자 친화적: 직관적인 사용자 인터페이스를 제공하여 사용자가 쉽게 사용할 수 있습니다.
풍부한 기능: 기본적인 텍스트 편집 기능 외에도 다양한 고급 기능을 제공합니다.
확장성: 플러그인 시스템을 통해 기능을 쉽게 확장할 수 있습니다.
커스터마이징: 테마와 설정을 통해 에디터의 외관과 동작을 커스터마이징할 수 있습니다.
커뮤니티 지원: 활발한 커뮤니티와 풍부한 문서 지원을 받습니다.
Usage
기본적인 Editor 컴포넌트 사용방법 입니다.
language
props로 에디터의 언어를 변경합니다.
한국어
, 영어
, 중국어
, 일본어
, 베트남어
, 이탈리아어
를 지원하며 기본 값은 영어
입니다.
필요한 기능만 선택적으로 로드할 수 있습니다.
이 외에도 TinyMCE에서 제공하는 다양한 함수와 옵션은 TinyMCE 공식 문서를 참고하세요.
L-UI상에서 테마 적용과 간단한 예시는 L-UI Editor 스토리북 가이드를 참고하세요.
3.19 Menus
Menus - 메뉴 렌더링
메뉴 렌더링은 전체 레이아웃/라우팅에 밀접하게 연관되어 있습니다.
Gnb, Lnb, MdiTabs, PageHeaderBreadcrumb, GnbMenu, LnbLogo 컴포넌트에서 사용되며, 여러 컴포넌트에서 광범위하게 상태를 참조하므로, menu store에서 전역적으로 관리합니다.
Menu Utils
buildMenuTree
: 주어진 메뉴 아이템 리스트를 트리 구조로 변환합니다.selectLogoAndGnbMenus
: 주어진 메뉴 트리에서 menuName이 환경변수 NEXT_PUBLIC_ROOT_MENU_ID에서 지정한 메뉴를 logoMenu로 지정하고, 나머지 메뉴들을 gnbMenus로 지정하여 반환합니다.filterMenuTree
: 검색어에 따라 메뉴를 필터링하는 함수입니다. 해당하는 메뉴와 연관된 메뉴는 남기고, 전혀 관계없는 메뉴는 필터링합니다.getDefaultMenu
: 주어진 메뉴 아이템 배열에서 기본 메뉴를 찾는 함수입니다.findMenuByPathname
: 주어진 메뉴 아이템 배열에서 주어진 경로와 일치하는 메뉴를 찾는 함수입니다.findCurrentMenuAndParents
: 주어진 메뉴 아이템 배열에서 현재 메뉴와 상위 부모 메뉴들을 찾는 함수입니다.findMenuByUri
: 주어진 경로(pathname)와 일치하는 메뉴 항목을 찾는 함수입니다.createSvgIcon
: 메뉴 이름(title)을 받아 해당 이름의 첫 글자를 포함한 SVG 아이콘을 생성하는 함수입니다.
Menu Fetch
Gnb
컴포넌트에서leftMenuList
queryKey로 호출하여 fetch합니다.메뉴리스트는 변하지 않고 계속 사용할수 있으므로, gcTime staleTime 무한대로 주어 캐싱후 다시 fetch하지 않도록합니다.
Menu Parsing & Menu Tree
Gnb
컴포넌트에서menuList
데이터가 로드되면, buildMenuTree로 트리형태로 만들고, NEXT_PUBLIC_ROOT_MENU_ID 상에 정의돈 메뉴는LogoMenu
(로고 누르면 나오는 루트메뉴), 나머지 메뉴들은GnbMenus
로 할당해줍니다.
메뉴 상태를 도식화 하면 아래와 같습니다.
Rendering Lnb
Gnb
메뉴에서 선택한 메뉴의 하위 항목들은lnbMenus
상태로 저장되며,Lnb
컴포넌트에서 이lnbMenus
데이터가 로드되면, 메뉴명 검색 로직을 거쳐filteredMenus
가 최종 Lnb에 렌더링 됩니다.L-UI에서 제공하는 Sidebar 컴포넌트를 활용하여 렌더링됩니다.
기존
Chamomile Admin Vue
에서 사용하던 menu 경로가 Pascal Case인 관계로pascalToKebabCase
함수를 사용하여 pathname을 변경시켜줍니다.메뉴의 하위 메뉴가 있는 경우 없는경우를 구분하여 각각
<Sidebar.Item />
<Sidebar.SubMenu />
으로 렌더링합니다.현재
pathname
과 비교하여 일치하거나 상위메뉴인 경우에는 active 처리해줍니다.탭 최대 20개를 고려하여, 20개를 초과하면 페이지 이동을 하지않고, 20개 이하일땐
router.push()
로 화면 이동합니다.
MdiTabs
MDI Tabs에서도 MenuStore의 메뉴정보들을이용해서 TabItem을 만들어주고 렌더링합니다.
Tab Item들을 추가/삭제 할때에도 메뉴 정보가 필요합니다.
PageHeaderBreadcrumb
L-UI에서 제공하는 Breadcrumb 컴포넌트를 활용하여 렌더링됩니다.
findCurrentMenuAndParents
를 사용하여 현재 메뉴와 부모 메뉴를 찾고 브레드크럼 목록을 설정합니다.즐겨찾기 추가/삭제 로직이 포함되어 있습니다.
3.20 MdiTabs : React Activation
MDI는 Multiple Document Interface의 약자로, 하나의 애플리케이션 창 안에서 여러 개의 문서나 화면을 탭 형태로 열 수 있게 해주는 인터페이스를 의미합니다. react-activation
과 react-chrome-tabs
를 사용하여 구현하였습니다.
react-activation: 페이지 전환 시 컴포넌트의 상태를 유지하기 위해 사용하였습니다.
react-chrome-tabs: 사용자에게 친숙한 UX를 제공하기 위해, 구글 Chrome과 유사한 Tab을 제공해주는 react-chrome-tabs를 사용하여 MDI Tab을 구현하였습니다.
react-activation
MDI를 구성하려면, 활성회된 메뉴 목록이 탭에 표시되어야하며, 화면 이동을 하더라도 작업을 하던 화면의 상태가 유지 되어야합니다.
<AliveScope />
는 KeepAlive 컴포넌트들이 상태를 공유할 수 있는 범위를 정의합니다.<KeepAlive />
는 특정 컴포넌트의 상태를 유지하고 복원하는 역할을 합니다
mdi-tabs.tsx (react-chrome-tabs)
드래그 앤 드롭: 탭을 드래그하여 순서를 변경할 수 있습니다.
탭 닫기: 탭을 닫을 수 있는 기능을 제공합니다.
탭 추가: 새로운 탭을 추가할 수 있습니다.
Page Stack
Page Stack은 store/page-stack.ts 에서 관리됩니다.
3.21 reCAPTCHA
캐모마일에서는 Google reCAPTCHA v2 를 사용하고 있습니다.
1. reCAPTCHA v2 개요
reCAPTCHA v2의 2가지 방식
Checkbox reCAPTCHA: 사용자가 "I'm not a robot" 체크박스를 클릭합니다. 이 방식은 사용자가 사람임을 확인하기 위해 추가적인 작업을 요구할 수 있습니다.
Invisible reCAPTCHA: 사용자가 특정 작업을 수행할 때(예: 폼 제출) 자동으로 트리거됩니다. 사용자는 추가적인 작업을 수행하지 않아도 됩니다.
2. reCAPTCHA v2 설정
Google reCAPTCHA 사이트 등록
Google 계정 로그인
"새 사이트 등록" 클릭
정보 입력
라벨: 사이트 식별 명
reCAPTCHA 유형: "테스트(v2)"를 선택 -> "로봇이 아닙니다." 체크박스 선택
도메인: reCAPTCHA를 사용할 도메인
"제출" 버튼을 클릭
사이트 키와 비밀 키 생성
3. ReCaptcha 컴포넌트 사용 방법
.env 설정
#ReCaptcha NEXT_PUBLIC_RECAPTCHA_SITE_KEY="['2. reCAPTCHA v2 설정'에서 받은 사이트 키]"컴포넌트 JSX 설정
reCAPTCHA 결과를 onResponse 를 통해서 받아서 사용
3.22 Copy & Cut
1. 기능 설명
이 기능은 웹 페이지에서 텍스트를 복사하거나 잘라내는 것을 방지합니다. 사용자가 복사 또는 잘라내기 동작을 시도할 때, 기본 동작이 차단되고 경고 메시지가 표시됩니다.
2. 기능 활성화 방법
환경 변수 설정
## Copy & Cut 방지 유무 NEXT_PUBLIC_COPY_CUT=true