본문 바로가기
FE/next

[Next.js] 직접 Next.js 개발환경 구축하기

by s0ojin 2024. 2. 25.

 

 

 

 

 

 

본 글은 <모던 리액트 DEEP DIVE>도서의 내용을 바탕으로 작성되었습니다.

 

 

 

 

 

 

create-react-app과 create-next-app은 각각 리액트와 넥스트 애플리케이션을 손쉽게 만들기 위한 CLI도구이다. 애플리케이션 구축에 필요한 대부분의 작업을 대신 해주기 때문에 편하고 빠르게 앱을 만들 수 있겠지만 공부에는 도움되지 않는다. 또한 23년 1월, 리액트팀이 cra는 리액트 어플리케이션을 만드는 보일러플레이트 CLI가 아니라 여러 리액트 기반 프레임워크를 제안하는 런처 형태로 변경될 예정이라고 밝힌 만큼, 직접 개발환경을 구축해보는 것도 좋은 경험이 될 것이다.

 

create-next-app 없이 하나씩 구축하기


모든 Node.js 프로젝트와 마찬가지로 가장 먼저 할 일은 package.json을 만드는 것이다. package.json파일은 직접 생성해도되지만, npm init을 실행하면 package.json을 만드는 CLI를 실행할 수 있다.

$ npm init

 

그 다음에는 react, react-dom, next를 설치해준다.

$ npm i react react-dom next

 

그리고 devDependencies에 필요한 패키지를 설치한다. 여기서는 typescript, 필요한 타입들, eslint등을 설치하게된다.

npm i @types/node @types/react @types/react-dom eslint eslint-config-next typescript --save-dev

 

tsconfig.json 작성하기


필요한 라이브러리들을 설치했다면, 이제 타입스크립트 코드를 작성하기 위한 준비를 해야한다. npm설정을 package.json에서 하는것처럼, 타입스크립트 설정은 tsconfig.json에 기록한다. 

// tsconfig.json

{
    // $schema를 작성하면 해당 json파일이 무엇을 의미하고, 어떤 값이 들어갈 수 있는 지 알려준다.
    // 아래에서 자동완성을 사용할 수 있다. 
    "$schema": "https://json.schemastore.org/tsconfig.json",
    // TS-> JS로 컴파일할 때 사용하는 옵션
    "compilerOptions": {
        // 변환을 목표로하는 언어 버전
        "target": "es5",
        
        // 폴리필을 붙여 Promise나 Map과 같은 객체들도 지원할 준비를 마쳤다고 해도, ts가 그 존재에 대해 모를 것이다.
        // 이 경우 가장 최신의 버전을 의미하는 ESNext를 추가하면
        // target은 es5라 할지라도 신규 기능에대한API를 확인할 수 있어 에러가 발생하지 않게된다. 
        "lib": ["DOM", "DOM.Iterable", "ESNext"],
        
        // TS가 JS파일 또한 컴파일할지 결정. 주로JS->TS 마이그레이션 과정에서 파이링 혼재되었을 경우 사용하는 옵션
        "allowJs": true,
        
        //라이브러리에서 제공하는 d.ts에 대한 검사여부 결정.
        // 프로젝트 컴파일 시간이 길어지므로 일반적으로 꺼놓음
        "skipLibCheck": true,
        
        // 타입스크립트의 엄격모드 제어.
        // alwaysStrict: 모든 js파일에 use strict 추가
        // strictNullChecks: 엄격한 null검사 활성화 -> null과 undefined 엄격 구별
        // strictBindCallApply: call,bind, apply에 대해 정확한 인수를 요구
        // strictFuntionTypes: 함수타입 엄격검사
        // strictPropertyInitialization: 클래스 내부 프로퍼티에 값할당 할때 타입 검사
        // noImplicitAny: 타입 명시하지 않으면 any를 넣지않고 에러발생
        // noImplicitThis: this추론 어려울 때 any넣지않고 에러발생 
        // useUnknownInCatchVariables: catch구문에서 잡은 변수에 any대신 unknown할당
        "strict": true,

        // 파일 대소문자 구별
        "forceConsistentCasingInFileNames": true,
        
        //컴파일하지않고, 타입 체크만 수행
        "noEmit": true,

        // CommonJS 방식으로 보낸 모듈을 ES모듈방식의 import로 가져올 수 있게 해줌
        "esModuleInterop": true,

        // 모듈설정: CommenJS는 require을, ESNext는 import사용
        "module": "ESNext",

        // 모듈 해석 방식
        "moduleResolution": "node",

        // JSON파일을 import할 수 있게 해줌, allowJS도 자동으로 켜짐
        "resolveJsonModule": true,

        // import나 export가 없다면 단순 스크립트파일로 인식해 이러한 파일이 생기지 않게해줌
        "isolatedModules": true,
        
        // tsx파일에 JSX를 어떻게 컴파일할지 설정
        // react: 기본값, React.createElement로 변환
        // react-jsx: 리액트17이후 등장. react/jsx-runtime을 사용해 변환하는데,
        // 이 방식으로 사용하면 React.createElement를 사용하지 않아 파일 상단에 'react'를 적을 필요없음
        // react-jsxdev: react-jsx와 동일하지만 디버깅 정보가 추가됨
        // preserve: 변환하지 않고 유지함
        // react-native: 네이티브에서 사용하는 방식으로, 역시 변환하지않고 유지함
        "jsx": "preserve",

        // 마지막 컴파일 정보를 저장해두었다가 다음에 비용이 가장 적게 드는 방식으로 컴파일수행
        "incremental": true,

        // 모듈을 찾을 때 기준이 되는 디렉토리
        "baseUrl": "src",

        // path에 alias지정
        "paths": {
            "#pages/*": ["pages/*"],
            "#hooks/*": ["hooks/*"],
            "#types/*": ["types/*"],
            "#components/*": ["components/*"],
            "#utils/*": ["utils/*"],
        }
    },
    // 컴파일 대상에 포함시킬 목록
    "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
    // 컴파일에서 제외시킬 목록
    "exclude": ["node_moduls"]
}

 

next.config.js 작성하기


이번에는 next 설정을 위한 next.config.js를 만들어보자. next.config.js가 제공하는 설정파일은 버전별로 조금씩 다르니사용가능한 옵션을 확인하고 싶다면 깃허브 저장소를 방문하자.

/** @type {import('next').NextConfig} */
const nextConfig = {
    // 리액트의 엄격모드 활성화
    reactStrictMode: true,

    // 일반적으로 보안 취약점으로 취급되는 X-Powered_By 헤더 제거
    poweredByHeader: false,

    // 빌드 시에 eslint무시
    eslint: {
        ignoreDuringBuilds: true,
    },
}

module.exports = nextConfig

 

ESLint와 Prettier설정하기


앞서 eslint와 eslint-config-next를 설치했지만 이는 잠재적 문제를 확인만할 뿐 스타일링을 정의해 주지는 않는다. 일반적인 ESLint 작업을 수행하기 위해 가장 설치 및 설정이 쉬운 @titicaca/eslint-config-triple을 설치해 사용하자

$ npm i @titicaca/eslint-config-triple --save-dev

 

스타일 설정하기


$ npm i styled-components
$ npm i @types/styled-components --save-dev

스타일드 컴포넌트를 설치하고, swc에 styled-components를 사용한다는 것을 알리기 위해 next.config.js에 styledComponents: true를 추가한다. 

추가로 pages/_document.tsx의 Head에  styled-components를 사용하기 위한 ServerStyleSheet를 추가한다.

 

애플리케이션 코드 작성


기본적인 폴더구조는 다음과 같고, 애플리케이션 구동에 필요한 파일은src 내부에 있다.

 

pages: Next.js에서 예약어로 지정해두고 사용하는 폴더로, 이 폴더의 하위 내용은 모두 실제 라우터가 된다.

/: 메인

/todos/:id: 상세페이지

components: 페이지 내부에서 사용하는 컴포넌트를 모아둔 폴더

hooks: 사용자정의 훅을 모아둔 폴더

types: 서버 응답 타입 등 공통으로 사용하는 타입을 모아둔 폴더

utils: 애플리케이션 전역에서 공용으로 사용하는 유틸성 파일을 모아둔 폴더

 

 

마지막으로, Next.js 실행, 빌드, 린트와 관련된 명령어를 package.json에 기재하면 모든 준비는 끝이다. 

 //package.json
 
 //생략
 "scripts": {
    "dev": "next dev",
    "start": "next start",
    "build": "next build",
    "lint": "eslint . --fix",
    "prettier": "prettier . --write"
  },
  
//생략

 

References


  • 도서 <모던 리액트 DEEP DEVE>

 

 

댓글