간단한 로그인, 회원가입, 투두리스트를 구현해보면서
Next.js 공부할 겸 혼자Next.js + Redux-Toolkit + styled-components
환경을 세팅해보기로 헀다.
먼저 Next.js 프로젝트를 생성한다.
# Next.js 프로젝트 생성 with TypeScript
npx create-next-app
Ok to proceed? (y) y
✔ What is your project named? # 프로젝트 이름
✔ Would you like to use TypeScript with this project? No / Yes # TypeScript 사용할 것인지 선택
✔ Would you like to use ESLint with this project? No / Yes # Eslint 설정할 것인지 선택
# yarn으로 Next.js 프로젝트 생성
yarn create next-app --typescript
# 프로젝트 실행
npm run dev
다음으로는 기본적으로 많이 사용하는 airbnb eslint
설정을 적용해준다.
일단 아래와 같이 airbnb eslint
관련 패키지와 TypeScript 사용시 더 설치해줘야 하는 패키지들을 함께 설치해준다.
# eslint airbnb 관련 패키지 설치
npx install-peerdeps -D eslint-config-airbnb
# TypeScript 사용시 설치해야 할 패키지들
npm install -D typescript eslint-config-airbnb-typescript @typescript-eslint/eslint-plugin @typescript-eslint/parser
아래 블로그를 참고하여 .eslintrc.json 파일을 설정해주었다.
🔗 밑바닥부터 Next.js 개발 환경 구축하기 - All in One
// .eslintrc.json
{
"root": true,
"env": {
"browser": true,
"es6": true,
"node": true,
"jest": true
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": "latest",
"sourceType": "module",
"project": "./tsconfig.json"
},
"ignorePatterns": ["jest.*.js"],
"extends": [
"airbnb",
"airbnb-typescript",
"airbnb/hooks",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:@next/next/recommended",
"plugin:prettier/recommended",
"plugin:jest/recommended"
],
"plugins": ["prettier", "@typescript-eslint", "jest", "import"],
"rules": {
"prettier/prettier": ["error", { "endOfLine": "auto" }],
"import/extensions": [
"error",
{
"tsx": "never",
"ts": "never",
"js": "never",
"jsx": "never"
}
],
"react/react-in-jsx-scope": 0,
"react/jsx-props-no-spreading": 0
}
}
다음으로는 prettier 관련 패키지도 설치해주고, 간단히 prettierrc.json 파일도 설정해준다.
npm install -D prettier eslint-plugin-prettier eslint-config-prettier
// prettierrc.json
{
"singleQuote": true,
"arrowParens": "always",
"semi": true,
"useTabs": false,
"tabWidth": 2,
"printWidth": 80,
"trailingComma": "all"
}
기존 React에선 styled-components
사용시 해당 패키지만 설치해주면 되지만 Next.js에선 next.config.js
파일 설정을 따로 또 해줘야 한다.
npx i -D styled-components @types/styled-components styled-reset
next.config.js
파일에 compiler: { styledComponents: true }
추가해주기!
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
compiler: {
styledComponents: true,
},
};
module.exports = nextConfig;
GlobalStyle
파일은 기존 React 플젝과 같이 추가해준다.
// styles/GlobalStyle.tsx
import { createGlobalStyle } from "styled-components"
import reset from "styled-reset"
const GlobalStyle = createGlobalStyle`
${reset}
:root {
--main-bgc: #0d1117;
...
}
body {
width: 100%;
}
* {
box-sizing: border-box
}
a {
text-decoration: none;
}
`
export default GlobalStyle;
원래 index.ts
에 적용하던 <GlobalStyle />
컴포넌트를 pages 폴더 내의 _app.tsx
파일에 설정해준다.
첨에 _app.tsx
파일 필요없는 초기 파일인 줄 알고 삭제했다가 다시 만들어 줬다,,ㅎ
🖐 _app.tsx
파일은 공통 레이아웃 같은 것들을 추가해서 설정해주는 파일이라구 한다.
// pages/_app.tsx
// 공통 레이아웃 추가해주기 (ex. Header, GlobalStyle, Redux ...)
import type { AppProps } from "next/app";
import Header from "../components/layouts/Header/Header";
import GlobalStyle from "../styles/GlobalStyle";
import { wrapper } from "../store/store";
function App({ Component, pageProps }: AppProps) {
return (
<>
<GlobalStyle /> // <- Add here!!
<Header />
<Component {...pageProps} />
</>
);
}
export default wrapper.withRedux(App);
다음으로는 Reudx-Toolkit
설정을 해주었다.
기본 React
플젝에서 설정과 React x TypeScript
에서의 설정과 또 약간 다르게 설정해주어야 한닷,,
아래 블로그를 참고해서 설정해주었다.
🔗 Next.js + Redux toolkit + Typscript
기본 React 플젝에서 설치해주는 패키지들 + next-redux-wrapper 패키지를 더 설치해준다.
npm i redux react-redux @types/react-redux @reduxjs/toolkit next-redux-wrapper
slice 파일은 기존 React 플젝에 설정한 것처럼 설정해준다.
// store/authSlice.ts
import { createSlice } from "@reduxjs/toolkit"
export interface AuthState {
isLogin: boolean;
}
const initialState: AuthState = {
isLogin: false
}
export const authSlice = createSlice({
name: "auth",
initialState,
reducers: {
login: (state: AuthState) => {
state.isLogin = true;
},
logout: (state) => {
state.isLogin = false;
},
},
})
export const { login, logout } = authSlice.actions
export default authSlice.reducer
store.ts
파일 설정이 좀 다른데 next-redux-wrapper
패키지 내의 createWrapper
로 감싸줘야 하는 부분을 더 추가해준닷
// store/store.ts
import {
configureStore,
combineReducers,
AnyAction,
CombinedState,
} from '@reduxjs/toolkit';
import { createWrapper, HYDRATE } from 'next-redux-wrapper';
import authSlice, { AuthState } from './authSlice';
import { Reducer } from '@reduxjs/toolkit';
export interface RootState {
auth: AuthState;
}
const RootReducer = (
state: RootState,
action: AnyAction
): CombinedState<RootState> => {
if (action.type === HYDRATE) return { ...state, ...action.payload };
const combinedReducer = combineReducers({
auth: authSlice
});
return combinedReducer(state, action);
};
// -------> Add here!
const makeStore = () =>
configureStore({
reducer: RootReducer as Reducer<CombinedState<RootState>, AnyAction>,
devTools: process.env.NODE_ENV === 'development',
});
export const wrapper = createWrapper(makeStore);
_app.tsx
파일에서는 wrapper.withRedux()
로 컴포넌트를 감싸준다.
// pages/_app.tsx
import type { AppProps } from "next/app";
import { wrapper } from "../store/store";
function App({ Component, pageProps }: AppProps) {
return (
<>
...
<Component {...pageProps} />
</>
);
}
export default wrapper.withRedux(App); // <- Add here!!
위와 같이 하면 기본적인 초기 세팅은 끝났고, React에서 많이 사용하는 Link, Navigate 기능 사용법이 Next.js에선 좀 달라서 기록 ✍️
React 플젝에서 useNavigate()
를 통해 다른 페이지로 이동하는 기능을 Next.js에선 useRouter
를 통해 구현할 수 있다. useRouter()
를 선언한 후 ~.push(’/~’)
를 통해 사용하면 된다.
import { useRouter } from 'next/navigation';
export default function Page() {
const router = useRouter();
return (
<button type="button" onClick={() => router.push('/dashboard')}>
Dashboard
</button>);
}
🔗 Routing: Linking and Navigating | Next.js
Link 기능은 next 내에 있는 link를 import해서 사용하면 된다.
<Link to=”/~”>
처럼 사용했던 기존 React 에서와는 다르게 Next.js에서는 <Link href=”/~”>
로 작성해서 사용하면 된다.
import Link from "next/link";
export default function HomePage() {
return (
<>
<Link href="/logi ">Login</Link>
</>
);
}