CEOS 에서 진행하는 프로젝트를 이제 곧 시작하게 된다.
우리는 고민 끝에 Next 도입의 필요성을 느꼈고, Next와 이에 최적화 되어있는 TailwindCSS를 사용하기로 하였다.
왜 Next를 선택하였나?
Next는 기본적으로 SSR(Server Side Rendering)에 최적화 되어있는 프레임워크라고 잘 알려져있다.
CSR(Client Side Rendering)
CSR은 우리가 흔히 알고있는 create-react-app 으로 쉽게 세팅할 수 있다.

위 사진은 CSR의 동작 방식을 나타낸다.
사용자가 페이지에 접속하면 클라이언트(브라우저)가 이를 인지하여 서버에 해당 데이터들(HTML, JS코드 등)을 요청한다. 브라우저가 데이터를 받게 되면 JS파일을 다운로드한 후 페이지를 보여준다. 모든 HTML 내용과 JS파일을 받아온 후 다운로드하여 보여지게 되므로 당연히 초기 페이지 렌더링 속도가 느릴 수 밖에 없다.
또한 초기 페이지를 우선 빈 페이지로 보여주기 때문에 검색엔진 최적화(SEO)에도 좋지 않다.
다만 한번에 모든 내용을 받아오므로 그 뒤에 요청되는 페이지는 클라이언트에서 처리하여 페이지 렌더링 속도가 빠르고, 페이지 간 속도 이동이 빠르다는 장점이 있다.
SSR(Server Side Rendering)
반면 SSR은 서버가 사용자에게 보여줄 페이지를 미리 구성한뒤 클라이언트로 전달해준다.

위 사진은 SSR의 동작 방식을 나타낸다.
사용자가 페이지에 접속하면 서버가 미리 구성된 페이지를 클라이언트에 전달해준다. 그러면 브라우저는 바로 페이지를 띄워주고, 그 후 해당 페이지의 JS파일을 다운로드하여 이미 띄워져있는 HTML과 합치게된다. 이를 Hydration 과정이라고 한다. 이러한 동작 덕분에 사용자는 초기페이지를 빠른 속도로 바라볼 수 있게된다.
또한 초기에 페이지가 빠르게 띄워지게 되므로 검색엔진 최적화(SEO)에도 유리하다.
다만 서버가 미리 페이지에 필요한 리소스를 준비해서 보내기에 서버에 부하가 다소 높고, 페이지별마다 해당 리소스를 그때그때 서버에서 가져오므로 CSR 방식보다 페이지 이동 속도가 더 걸린다는 단점이 있다.
이처럼 CSR, SSR 방식은 각각 장단점이 있고, 어느것이 더 좋다고 말할 수는 없다.
다만 우리의 프로젝트 기획 상 첫 화면을 빠르게 렌더링하여 사용자 경험을 높이고, 검색엔진이 우리 서비스를 잘 찾을 수 있도록 해야했기에 Next를 도입하기로 하였다.
✅Windows
✅Next.js
Next 14 설치
현재 기준 Next14 가 출시되었으므로 버전 14를 사용하기로 하였다.
npx create-next-app
위 명령어를 윈도우 기준 cmd 창에 입력한 후 프로젝트 명과 옵션들을 선택하여 시작한다. 나는 모두 디폴트로 설정되어 있는 옵션을 선택하였다.
디폴트 옵션을 선택하면 Typescript 와 TailwindCSS를 적용할 수 있는 환경이 만들어져 있을 것이다.
app 디렉토리 안에 styles 폴더를 하나 만들어서 그 안에 TailwindCSS 설정을 진행하였다.
tailwind.css
해당 이름의 파일을 app/styles 경로에 생성하여 아래와 같이 작성하였다.(파일 이름은 자유)
@tailwind base;
@tailwind components;
@tailwind utilities;
html {
font-size: 10px;
}
@tailwind는 directive로써 base, components, utilities 라는 layer directive를 사용할 수 있게 해준다.
- base: HTML 기본 태그(h1, p와 같은), reset rules에 적용된 기본 스타일을 위한 layer이다.
- component: class 기반 스타일을 선언하는 layer이며, third-party components를 스타일링할 때 유용하다. 또한 밑에서 익히는 utilities layer로 덮어씌울 수 있다.
- utilities: 다른 스타일을 덮어쓰는 일회용 class를 표현하는 layer이다. Tailwind CSS에서 제공하는 기본 utilities가 없을 때 사용합니다.
위에서 내가 선언해준 html 설정처럼 특정 layer를 지정하지 않고 스타일을 써주면 해당 내용은 항상 적용되게 된다. 즉 reset CSS를 지정할 때 layer를 지정하지 않고 작성하면 적용할 수 있다.
그런데 margin:0과 같은 속성은 base layer를 선언해줄 때 preflight으로 미리 주입이 된다. 따라서 나는 우선 1rem=10px를 지정해주기 위해 위처럼만 작성하고 추후에 global로 지정할 스타일이 있다면 나중에 작업하기로 하였다.
@layer를 사용하면 TailwindCSS에 우리가 커스텀한 내용을 알려줄 수 있다. 아래는 컴포넌트 Bucket의 커스텀 내용의 예시이다. 다른 layer도 사용법은 동일하다.
@layer components {
.bg-black {
background: black;
}
}
그러면 해당 스타일을 적용하려는 컴포넌트는 bg-black으로 접근할 수 있다.
base layer는 html의 특정 태그 스타일을 지정할 때, components layer는 컴포넌트의 더 복잡한 스타일을 지정할 때, utilities layer는 그 외의 스타일을 지정할 때 사용하면 좋다. utilities layer는 components layer을 override 하게된다.
간단한 사용법을 알아보았는데, 나는 @layer은 사용하지 않고 tailwind에서 제공하는 Plugin system을 활용하여 스타일의 재사용성을 높였다.
tailwind.config.ts
Next 프로젝트를 생성하면 기본적으로 해당 파일이 생성되어 있을 것이다.
아래와 같이 작성해주었다.
import { customColors } from "./app/styles/colors";
import plugin from "tailwindcss/plugin";
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./app/**/*.{js,ts,jsx,tsx,mdx,css}",
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
// Or if using `src` directory:
"./src/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
colors: customColors,
},
},
plugins: [
plugin(({ addUtilities }) => {
addUtilities({
".header-text": {
fontFamily: "Pretendard, sans-serif",
fontWeight: "400",
fontSize: "2rem",
lineHeight: "3rem",
letterSpacing: "-0.762px",
},
});
}),
],
};
content
content에 지정해준 경로와 확장자 파일에 해당 정보가 반영된다. 우리의 프로젝트는 .app/ 경로에서 작업이 이루어질 예정이다.
theme
해당 섹션에서 여러 속성들을 선언해줄 수 있다. 우선 나는 색깔에 대해서만 선언해주었다. 위와 같이 colors 에 색깔 파일을 지정해주었다. 아래는 색깔 파일의 예시이다.
export const customColors = {
"main-color-red": "#FF0000",
...
};
이와 같이 선언만 해주면 이름만 가져다가 사용할 수 있다.
예를 들어 특정 div 태그 안의 글자 색을 위에 선언한 "main-color-red" 로 사용하고 싶다면
<div className="text-main-color-red></div>
다음과 같이 선언만 해주면 tailwind.config.ts의 theme에서 선언해주었기 때문에 해당 파일에서 색깔을 읽어올 수 있다.. 자주 사용하는 색깔을 지정해주면 매우 편리한 기능이다.
plugins
위에서 소개한 layer를 사용하지 않고 tailwind.config.ts 파일의 plugins를 customizing하면 스타일의 재사용성을 높일 수 있다.
나는 addUtilities 를 사용하여 utilities layer만 지정하여 작성해 주었지만 base, components layer도 마찬가지로 addBase, addComponents 를 사용하여 스타일을 작성할 수 있다.
나는 utlities layer에 자주 사용하는 폰트 관련 스타일을 지정해준다. 위에는 그 예시이다. 만약 해당 폰트 스타일을 특정 div 태그의 글자에 적용하고 싶다면 마찬가지로 이름만 써주면 된다.
<div className="header-text"></div>
다음과 같이 text- 도 없이 그냥 이름만 써주면 지정해준 폰트 스타일이 해당 태그의 글자에 적용되게 된다.
마지막으로 나는 Pretendard 폰트를 사용하였는데, 선택한 폰트 스타일을 적용하려면 추가 작업이 필요하다.
font.css
app/styles 경로에 해당 파일을 생성한 후 아래와 같이 작성해주었다.(파일 이름은 자유)
/* Pretendard */
@font-face {
font-family: "Pretendard";
src: url("../common/assets/fonts/pretendard/Pretendard-Bold.woff2"),
url("../common/assets/fonts/pretendard/Pretendard-Bold.woff"),
url("../common/assets/fonts/pretendard/Pretendard-Bold.otf");
font-weight: 700;
font-style: normal;
}
@font-face {
font-family: "Pretendard";
src: url("../common/assets/fonts/pretendard/Pretendard-Medium.woff2"),
url("../common/assets/fonts/pretendard/Pretendard-Medium.woff"),
url("../common/assets/fonts/pretendard/Pretendard-Medium.otf");
font-weight: 500;
font-style: normal;
}
@font-face {
font-family: "Pretendard";
src: url("../common/assets/fonts/pretendard/Pretendard-Regular.woff2"),
url("../common/assets/fonts/pretendard/Pretendard-Regular.woff"),
url("../common/assets/fonts/pretendard/Pretendard-Regular.otf");
font-weight: 400;
font-style: normal;
}
@font-face
@font-face를 사용하여 우리의 서비스에 해당 글꼴을 적용할 수 있다.
font-family에는 선언하고자 하는 폰트의 이름을 선언해준 준다. 그 후 src 에 해당 폰트가 다운되어져 있는 경로를 써준다. 사용자마다 브라우저가 다르므로 사용할 수 있는 폰트의 확장자도 다르다. src의 가장 위에있는 파일부터 다운을 시도하여 다운받아지면 해당 파일을 사용하게 된다.

나는 위와 같이 폰트를 다운받아 해당 경로에 넣어놓았다.
그 후 font-weight와 font-style은 optional로 지정해주면 된다.
이제 tailwind의 기본적인 세팅은 마쳤다.
app 폴더 안에 layout.tsx 컴포넌트가 있을텐데 모든 페이지의 layout은 해당 파일을 따르게된다.
import "@styles/tailwind.css";
import "@styles/font.css";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
위와 같이 작성한 css 파일들을 import 해주면, 모든 페이지는 해당 layout 안에 들어가기 때문에 결국 모든 페이지에 해당 css 설정이 도달하게 된다.
Yarn berry
Yarn berry에 대해서는 이전 포스팅에서 소개를 했으므로 설정하는 방법은 링크를 참고하면 된다.
https://doyourbestcode.tistory.com/129
그런데 Next 에서는 Pnp 모드가 제대로 돌아가지 않았다. 이유를 모르겠어서 무한 구글링을 했지만 마땅한 해결책을 찾지 못했다. Next에서는 Pnp 모드를 제대로 지원해주지 않는다는 말도 있어서 우선 눈물을 머금고 .yarnrc.yml 파일에서 nodeLinker를 node_modules로 설정해주었다. 나중에 해결할 수 있다면 다시 수정해야겠다.
기본적인 Next 프로젝트를 시작하는 방법과 TailwindCSS를 세팅하는 방법을 적어보았다. 여러 사람들과 추후에 나에게도 많은 도움이 되었으면 좋겠다!!
'FrontEnd > Next' 카테고리의 다른 글
Next 성능 개선 일지 2 (Feat: FOUT, bundle-analyzer, Link prefetch) (0) | 2024.05.04 |
---|---|
Next 성능 개선 일지 1 (Feat: Lighthouse, Next/Image) (2) | 2024.04.18 |
Next 에서 소셜 로그인 구현하기(Feat : Cookie) (4) | 2024.03.14 |
Next 에서 데이터 관리하기 (Feat : Cache) (2) | 2024.03.09 |
CEOS 에서 진행하는 프로젝트를 이제 곧 시작하게 된다.
우리는 고민 끝에 Next 도입의 필요성을 느꼈고, Next와 이에 최적화 되어있는 TailwindCSS를 사용하기로 하였다.
왜 Next를 선택하였나?
Next는 기본적으로 SSR(Server Side Rendering)에 최적화 되어있는 프레임워크라고 잘 알려져있다.
CSR(Client Side Rendering)
CSR은 우리가 흔히 알고있는 create-react-app 으로 쉽게 세팅할 수 있다.

위 사진은 CSR의 동작 방식을 나타낸다.
사용자가 페이지에 접속하면 클라이언트(브라우저)가 이를 인지하여 서버에 해당 데이터들(HTML, JS코드 등)을 요청한다. 브라우저가 데이터를 받게 되면 JS파일을 다운로드한 후 페이지를 보여준다. 모든 HTML 내용과 JS파일을 받아온 후 다운로드하여 보여지게 되므로 당연히 초기 페이지 렌더링 속도가 느릴 수 밖에 없다.
또한 초기 페이지를 우선 빈 페이지로 보여주기 때문에 검색엔진 최적화(SEO)에도 좋지 않다.
다만 한번에 모든 내용을 받아오므로 그 뒤에 요청되는 페이지는 클라이언트에서 처리하여 페이지 렌더링 속도가 빠르고, 페이지 간 속도 이동이 빠르다는 장점이 있다.
SSR(Server Side Rendering)
반면 SSR은 서버가 사용자에게 보여줄 페이지를 미리 구성한뒤 클라이언트로 전달해준다.

위 사진은 SSR의 동작 방식을 나타낸다.
사용자가 페이지에 접속하면 서버가 미리 구성된 페이지를 클라이언트에 전달해준다. 그러면 브라우저는 바로 페이지를 띄워주고, 그 후 해당 페이지의 JS파일을 다운로드하여 이미 띄워져있는 HTML과 합치게된다. 이를 Hydration 과정이라고 한다. 이러한 동작 덕분에 사용자는 초기페이지를 빠른 속도로 바라볼 수 있게된다.
또한 초기에 페이지가 빠르게 띄워지게 되므로 검색엔진 최적화(SEO)에도 유리하다.
다만 서버가 미리 페이지에 필요한 리소스를 준비해서 보내기에 서버에 부하가 다소 높고, 페이지별마다 해당 리소스를 그때그때 서버에서 가져오므로 CSR 방식보다 페이지 이동 속도가 더 걸린다는 단점이 있다.
이처럼 CSR, SSR 방식은 각각 장단점이 있고, 어느것이 더 좋다고 말할 수는 없다.
다만 우리의 프로젝트 기획 상 첫 화면을 빠르게 렌더링하여 사용자 경험을 높이고, 검색엔진이 우리 서비스를 잘 찾을 수 있도록 해야했기에 Next를 도입하기로 하였다.
✅Windows
✅Next.js
Next 14 설치
현재 기준 Next14 가 출시되었으므로 버전 14를 사용하기로 하였다.
npx create-next-app
위 명령어를 윈도우 기준 cmd 창에 입력한 후 프로젝트 명과 옵션들을 선택하여 시작한다. 나는 모두 디폴트로 설정되어 있는 옵션을 선택하였다.
디폴트 옵션을 선택하면 Typescript 와 TailwindCSS를 적용할 수 있는 환경이 만들어져 있을 것이다.
app 디렉토리 안에 styles 폴더를 하나 만들어서 그 안에 TailwindCSS 설정을 진행하였다.
tailwind.css
해당 이름의 파일을 app/styles 경로에 생성하여 아래와 같이 작성하였다.(파일 이름은 자유)
@tailwind base;
@tailwind components;
@tailwind utilities;
html {
font-size: 10px;
}
@tailwind는 directive로써 base, components, utilities 라는 layer directive를 사용할 수 있게 해준다.
- base: HTML 기본 태그(h1, p와 같은), reset rules에 적용된 기본 스타일을 위한 layer이다.
- component: class 기반 스타일을 선언하는 layer이며, third-party components를 스타일링할 때 유용하다. 또한 밑에서 익히는 utilities layer로 덮어씌울 수 있다.
- utilities: 다른 스타일을 덮어쓰는 일회용 class를 표현하는 layer이다. Tailwind CSS에서 제공하는 기본 utilities가 없을 때 사용합니다.
위에서 내가 선언해준 html 설정처럼 특정 layer를 지정하지 않고 스타일을 써주면 해당 내용은 항상 적용되게 된다. 즉 reset CSS를 지정할 때 layer를 지정하지 않고 작성하면 적용할 수 있다.
그런데 margin:0과 같은 속성은 base layer를 선언해줄 때 preflight으로 미리 주입이 된다. 따라서 나는 우선 1rem=10px를 지정해주기 위해 위처럼만 작성하고 추후에 global로 지정할 스타일이 있다면 나중에 작업하기로 하였다.
@layer를 사용하면 TailwindCSS에 우리가 커스텀한 내용을 알려줄 수 있다. 아래는 컴포넌트 Bucket의 커스텀 내용의 예시이다. 다른 layer도 사용법은 동일하다.
@layer components {
.bg-black {
background: black;
}
}
그러면 해당 스타일을 적용하려는 컴포넌트는 bg-black으로 접근할 수 있다.
base layer는 html의 특정 태그 스타일을 지정할 때, components layer는 컴포넌트의 더 복잡한 스타일을 지정할 때, utilities layer는 그 외의 스타일을 지정할 때 사용하면 좋다. utilities layer는 components layer을 override 하게된다.
간단한 사용법을 알아보았는데, 나는 @layer은 사용하지 않고 tailwind에서 제공하는 Plugin system을 활용하여 스타일의 재사용성을 높였다.
tailwind.config.ts
Next 프로젝트를 생성하면 기본적으로 해당 파일이 생성되어 있을 것이다.
아래와 같이 작성해주었다.
import { customColors } from "./app/styles/colors";
import plugin from "tailwindcss/plugin";
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./app/**/*.{js,ts,jsx,tsx,mdx,css}",
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
// Or if using `src` directory:
"./src/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
colors: customColors,
},
},
plugins: [
plugin(({ addUtilities }) => {
addUtilities({
".header-text": {
fontFamily: "Pretendard, sans-serif",
fontWeight: "400",
fontSize: "2rem",
lineHeight: "3rem",
letterSpacing: "-0.762px",
},
});
}),
],
};
content
content에 지정해준 경로와 확장자 파일에 해당 정보가 반영된다. 우리의 프로젝트는 .app/ 경로에서 작업이 이루어질 예정이다.
theme
해당 섹션에서 여러 속성들을 선언해줄 수 있다. 우선 나는 색깔에 대해서만 선언해주었다. 위와 같이 colors 에 색깔 파일을 지정해주었다. 아래는 색깔 파일의 예시이다.
export const customColors = {
"main-color-red": "#FF0000",
...
};
이와 같이 선언만 해주면 이름만 가져다가 사용할 수 있다.
예를 들어 특정 div 태그 안의 글자 색을 위에 선언한 "main-color-red" 로 사용하고 싶다면
<div className="text-main-color-red></div>
다음과 같이 선언만 해주면 tailwind.config.ts의 theme에서 선언해주었기 때문에 해당 파일에서 색깔을 읽어올 수 있다.. 자주 사용하는 색깔을 지정해주면 매우 편리한 기능이다.
plugins
위에서 소개한 layer를 사용하지 않고 tailwind.config.ts 파일의 plugins를 customizing하면 스타일의 재사용성을 높일 수 있다.
나는 addUtilities 를 사용하여 utilities layer만 지정하여 작성해 주었지만 base, components layer도 마찬가지로 addBase, addComponents 를 사용하여 스타일을 작성할 수 있다.
나는 utlities layer에 자주 사용하는 폰트 관련 스타일을 지정해준다. 위에는 그 예시이다. 만약 해당 폰트 스타일을 특정 div 태그의 글자에 적용하고 싶다면 마찬가지로 이름만 써주면 된다.
<div className="header-text"></div>
다음과 같이 text- 도 없이 그냥 이름만 써주면 지정해준 폰트 스타일이 해당 태그의 글자에 적용되게 된다.
마지막으로 나는 Pretendard 폰트를 사용하였는데, 선택한 폰트 스타일을 적용하려면 추가 작업이 필요하다.
font.css
app/styles 경로에 해당 파일을 생성한 후 아래와 같이 작성해주었다.(파일 이름은 자유)
/* Pretendard */
@font-face {
font-family: "Pretendard";
src: url("../common/assets/fonts/pretendard/Pretendard-Bold.woff2"),
url("../common/assets/fonts/pretendard/Pretendard-Bold.woff"),
url("../common/assets/fonts/pretendard/Pretendard-Bold.otf");
font-weight: 700;
font-style: normal;
}
@font-face {
font-family: "Pretendard";
src: url("../common/assets/fonts/pretendard/Pretendard-Medium.woff2"),
url("../common/assets/fonts/pretendard/Pretendard-Medium.woff"),
url("../common/assets/fonts/pretendard/Pretendard-Medium.otf");
font-weight: 500;
font-style: normal;
}
@font-face {
font-family: "Pretendard";
src: url("../common/assets/fonts/pretendard/Pretendard-Regular.woff2"),
url("../common/assets/fonts/pretendard/Pretendard-Regular.woff"),
url("../common/assets/fonts/pretendard/Pretendard-Regular.otf");
font-weight: 400;
font-style: normal;
}
@font-face
@font-face를 사용하여 우리의 서비스에 해당 글꼴을 적용할 수 있다.
font-family에는 선언하고자 하는 폰트의 이름을 선언해준 준다. 그 후 src 에 해당 폰트가 다운되어져 있는 경로를 써준다. 사용자마다 브라우저가 다르므로 사용할 수 있는 폰트의 확장자도 다르다. src의 가장 위에있는 파일부터 다운을 시도하여 다운받아지면 해당 파일을 사용하게 된다.

나는 위와 같이 폰트를 다운받아 해당 경로에 넣어놓았다.
그 후 font-weight와 font-style은 optional로 지정해주면 된다.
이제 tailwind의 기본적인 세팅은 마쳤다.
app 폴더 안에 layout.tsx 컴포넌트가 있을텐데 모든 페이지의 layout은 해당 파일을 따르게된다.
import "@styles/tailwind.css";
import "@styles/font.css";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
위와 같이 작성한 css 파일들을 import 해주면, 모든 페이지는 해당 layout 안에 들어가기 때문에 결국 모든 페이지에 해당 css 설정이 도달하게 된다.
Yarn berry
Yarn berry에 대해서는 이전 포스팅에서 소개를 했으므로 설정하는 방법은 링크를 참고하면 된다.
https://doyourbestcode.tistory.com/129
그런데 Next 에서는 Pnp 모드가 제대로 돌아가지 않았다. 이유를 모르겠어서 무한 구글링을 했지만 마땅한 해결책을 찾지 못했다. Next에서는 Pnp 모드를 제대로 지원해주지 않는다는 말도 있어서 우선 눈물을 머금고 .yarnrc.yml 파일에서 nodeLinker를 node_modules로 설정해주었다. 나중에 해결할 수 있다면 다시 수정해야겠다.
기본적인 Next 프로젝트를 시작하는 방법과 TailwindCSS를 세팅하는 방법을 적어보았다. 여러 사람들과 추후에 나에게도 많은 도움이 되었으면 좋겠다!!
'FrontEnd > Next' 카테고리의 다른 글
Next 성능 개선 일지 2 (Feat: FOUT, bundle-analyzer, Link prefetch) (0) | 2024.05.04 |
---|---|
Next 성능 개선 일지 1 (Feat: Lighthouse, Next/Image) (2) | 2024.04.18 |
Next 에서 소셜 로그인 구현하기(Feat : Cookie) (4) | 2024.03.14 |
Next 에서 데이터 관리하기 (Feat : Cache) (2) | 2024.03.09 |