[Front-end] 개발자 공부

[개발 공부 55일차] "멋" 그 자체인 Next.js 덕질 시작

MOLLY_ 2024. 3. 13. 08:18
728x90

 

Next.js 로고부터 해서 공식 사이트, 그리고 서버 실행했을 때 그려지는 UI까지 '멋'이 없는 게 없다.. 에러도 잘 뜨고 끄떡하면 서버 종료 후 다시 켜야 하는 불편함이 있긴 하지만 그마저도 왠지 모를 간지로 인해 모두 상쇄가 된다.... 폴링 인 럽 해버린 Next.js,, 핵심 요약 및 정리, 오늘부터 시작해 보자

 

 

< 목차 >
1. Next.js란?
2.
Next.js 자동 설치 명령
3. 프로젝트 구조
4. Routing 기본
5. 금일 작성한 코드
6. 금일 소감

 

 

1. Next.js란?

공식 사이트도 너무 이쁨;

 

: Full-stack 웹 애플리케이션을 구축하기 위한 React 프레임워크

 

React 구성 요소를 사용하여 사용자 인터페이스를 구축하고, Next.js를 사용하여 추가 기능과 최적화를 수행한다. 내부적으로 Next.js는 번들링, 컴파일 등과 같이 React에 필요한 도구를 추상화하고 자동으로 구성한다. 이를 통해 구성에 시간을 낭비하는 대신 애플리케이션 구축에 집중할 수 있다.

 

[Next.js 공식 문서 Link] https://nextjs.org/docs

 

 

 

2. Next.js 자동 설치 명령

편-안

 

수동으로 설치하는 방법도 있는데 과정도 번거롭고 비효율적이라 특별한 목적이 있는 경우가 아니라면 자동 설치를 추천한다. 편-안 그 자체다.

 

 

자동 설치 명령어

npx create-next-app@latest

 

 

메시지 체크 및 설치

What is your project named? my-app
Would you like to use TypeScript? No / Yes
Would you like to use ESLint? No / Yes
Would you like to use Tailwind CSS? No / Yes
Would you like to use `src/` directory? No / Yes
Would you like to use App Router? (recommended) No / Yes
Would you like to customize the default import alias (@/*)? No / Yes
What import alias would you like configured? @/*

 

 

package.json - scripts 부분 설명

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  }
}

 

 

스크립트는 애플리케이션 개발의 다양한 단계를 나타낸다.

  • devnext dev 개발 모드에서 Next.js를 시작하기 위해 실행
  • buildnext build 프로덕션 용도로 애플리케이션을 빌드하기 위해 실행
  • start: next start Next.js 프로덕션 서버를 시작하기 위해 실행
  • lint: next lint Next.js의 내장 ESLint 구성을 설정하기 위해 실행

 

 

3. 프로젝트 구조

최상위 폴더

app App Router
pages Pages Router
public 제공된 정적 자산
src 선택적 애플리케이션 소스 폴더

 

 

최상위 파일

next.config.js Next.js 구성 파일
package.json 프로젝트 종속성 및 스크립트
instrumentation.ts OpenTelemetry 파일
middleware.ts Next.js 요청 미들웨어
.env 환경 변수
.env.local 로컬 환경 변수
.env.production 프로덕션 환경 변수
.env.development 개발 환경 변수
.eslintrc.json ESLint용 구성 파일
.gitignore Git 파일 및 폴더
next-env.d.ts Next.js용 TypeScript 선언 파일
tsconfig.json TypeScript용 구성 파일
jsconfig.json JavaScript용 구성 파일

 

 

App Routing 규칙

최근엔 Page Routing보다 최신 버전이면서도 많은 기능을 제공하는 App Routing을 더 많이 사용하는 추세다. 따라서, App Routing 규칙만 정리하였다. Page Routing 규칙에 대해서도 알고 싶다면 친절한 공식 문서를 참고하자

 

 

Routing Files

layout .js .jsx .tsx Layout
page .js .jsx .tsx Page
loading .js .jsx .tsx Loading UI
not-found .js .jsx .tsx Not found UI
error .js .jsx .tsx Error UI
global-error .js .jsx .tsx Global error UI
route .js .ts API endpoint
template .js .jsx .tsx Re-rendered layout
default .js .jsx .tsx Parallel route fallback page

 

 

Dynamic Routes (동적 경로)

: 동적으로 페이지의 경로를 생성하고 관리하는 기법

 

URL의 일부분이 변수로 사용되어, 같은 페이지 구조로 다양한 내용을 표시할 수 있도록 한다. 예를 들어, /products/[id]라는 경로는 다양한 id 값에 따라 다른 정보를 보여줄 수 있다.

[folder] Dynamic route segment
[...folder] Catch-all route segment
[[...folder]] Optional catch-all route segment

 

 

* segment (세그먼트)

: 동적 경로(dynamic route)를 구성하는 변수 부분

URL에서 동적으로 변화하는 값을 처리하기 위해 사용되는데, 대괄호([])로 둘러싸인 이름을 통해 표현된다. 세그먼트는 경로의 일부분으로, 다양한 값을 동적으로 받아 해당 값에 기반한 페이지를 생성하거나 데이터를 불러올 때 사용된다.

 

예시

/products/[productId]

 

여기서 [productId]는 세그먼트다. 이 세그먼트는 URL에서 /products/1, /products/2 등으로 접근할 때마다 다른 productId 값을 가지게 되며, 이 값을 기반으로 해당 상품의 정보를 불러와 동적으로 페이지를 생성한다.

 

 

 

경로 그룹 및 개인 폴더

(folder) Routing에 영향을 주지 않는 그룹 경로
_folder Routing에서 폴더 및 모든 하위 세그먼트 선택

 

 

 

4. Routing 기본

모든 애플리케이션의 뼈대는 Routing이다.

Routing의 기본 개념과 Next.js에서 Routing을 처리하는 방법에 대해 알아보자

 

[Next.js] Routing

 

  • Tree (트리): 계층 구조를 시각화하기 위한 규칙 (ex. 상위 및 하위 구성 요소가 있는 구성 요소 트리, 폴더 구조 등)
  • Subtree (하위 트리): 새 루트(첫 번째)에서 시작하여 잎(마지막)에서 끝나는 트리의 일부
  • Root (루트): 루트 레이아웃과 같은 트리 또는 하위 트리의 첫 번째 노드
  • Leaf (리프): URL 경로의 마지막 세그먼트와 같이 자식이 없는 하위 트리의 노드

 

 

  • URL Segment: 슬래시 / 로 구분된 URL 경로의 일부
  • URL Path: 도메인 뒤에 오는 URL의 일부 (segments로 구성)

 

App Router는 Page Router보다 우선순위가 높다. 따라서 디렉토리 간 경로는 동일한 URL 경로로 확인돼선 안 되며 충돌을 방지하기 위해 Build 시간 오류가 발생한다.

 

 

폴더 및 파일의 역할

Next.js는 다음과 같은 파일 시스템 기반 Router를 사용한다.

 

 

  • Folder: 경로를 '정의'하는 데 사용된다. 경로는 Root 폴더부터 파일이 포함된 최종 Leaf 폴더까지 파일 시스템 계층 구조를 따라가는 중첩된 폴더의 단일 경로다.
  • File: 경로 구간에 표시되는 'UI'를 만드는 데 사용

 

경로의 각 폴더는 경로 세그먼트를 나타낸다. 각 경로 세그먼트는 URL 경로의 해당 세그먼트에 맵핑된다.

 

 

 

5. 금일 작성한 코드

고양이 정보 불러옴

 

src/app/rendering/page.tsx

import CSR from '@/components/CSR';
import React from 'react';

const RenderingTestPage = () => {
    return (
        <div>
            <h1>4가지 렌더링 방식을 테스트합니다.</h1>
            <CSR />
        </div>
    );
};

export default RenderingTestPage;

 

 

src/components/CSR.tsx

'use client';

import React, { useEffect, useState } from 'react';
import type { RandomCatInfo } from '@/types';

const CSR = () => {
    const [cat, setCat] = useState<RandomCatInfo | null>(null);

    useEffect(() => {
        const fetchCat = async () => {
            const response = await fetch(`https://catfact.ninja/fact`);
            const catInfo: RandomCatInfo = await response.json();
            setCat(catInfo);
        };

        fetchCat();
    }, []);

    if (!cat) {
        return <div>로딩중...</div>;
    }

    return (
        <div className="mt-8">
            <div className="border p-4 my-4">
                <div className="flex gap-8">
                    <div>
                        <h2 className="text-xl font-bold">Cat Information</h2>
                        <p className="text-white-600">{cat.fact}</p>
                        <p className="text-white-600">{cat.length}</p>
                    </div>
                </div>
            </div>
        </div>
    );
};

export default CSR;

 

 

src/components/ISR.tsx

import React from 'react';
import type { RandomCatInfo } from '@/types';

const ISR = async () => {
    const response = await fetch(`https://catfact.ninja/fact`, {
        next: {
            revalidate: 5,
        },
    });

    const catInfo: RandomCatInfo = await response.json();

    return (
        <div className="mt-8">
            <div className="border p-4 my-4">
                <div className="flex gap-8">
                    <div>
                        <h2 className="text-xl font-bold">Cat Information</h2>
                        <p className="text-white-600">{catInfo.fact}</p>
                        <p className="text-white-600">{catInfo.length}</p>
                    </div>
                </div>
            </div>
        </div>
    );
};

export default ISR;

 

 

src/components/SSG.tsx

import React from 'react';
import type { RandomCatInfo } from '@/types';

// SSG TEST : 아무것도 하지 않으면 SSG!
const SSG = async () => {
    // (1) 첫 번째 방법 : 아무 옵션도 부여 X
    const response = await fetch(`https://catfact.ninja/fact`, {
        // (2) 두 번째 방법: force-cache
        cache: 'force-cache',
    });

    const catInfo: RandomCatInfo = await response.json();

    return (
        <div className="mt-8">
            <div className="border p-4 my-4">
                <div className="flex gap-8">
                    <div>
                        <h2 className="text-xl font-bold">Cat Information</h2>
                        <p className="text-white-600">{catInfo.fact}</p>
                        <p className="text-white-600">{catInfo.length}</p>
                    </div>
                </div>
            </div>
        </div>
    );
};

export default SSG;

 

 

src/components/SSR.tsx

// src>components>rendering>SSR.tsx
import React from 'react';
import type { RandomCatInfo } from '@/types';

const SSR = async () => {
    const response = await fetch(`https://catfact.ninja/fact`, {
        cache: 'no-cache',
    });

    const catInfo: RandomCatInfo = await response.json();

    return (
        <div className="mt-8">
            <div className="border p-4 my-4">
                <div className="flex gap-8">
                    <div>
                        <h2 className="text-xl font-bold">Cat Information</h2>
                        <p className="text-white-600">{catInfo.fact}</p>
                        <p className="text-white-600">{catInfo.length}</p>
                    </div>
                </div>
            </div>
        </div>
    );
};

export default SSR;

 

 

 

6. 금일 소감

 

아니 이렇게 재미난 걸 이제서야 배우다니.. 재밌는데 멋까지 있잖아?.. 말이 되나 이게?... 하면 할수록 재밌는데 말이 되나 이게? 어제 졸리고 피곤했던 새벽에 억지로 과제 강행했으면 이 재미를 모르고 넘어갈 뻔했다. 

 

강의 듣는 나

 

어제 엄청난 피곤 이슈로 과제 제대로 못해서 오늘 실시간 강의 들은 횟수 제외하고도 3~4번을 재청강하고 빡집중해서 과제 완료해서 재제출했다. 코드 따라 작성하는 것부터 과제하는 순간까지... 모든 순간이 너였.. 아니 너무 재밌어서 시간 가는 줄 모르고 푹 빠져서 했다. Next.js,,, 나를 반하게 하다니... 왜케 재밌는 건데.. 밤새웠는데 하나도 안 피곤하고 진심으로 너무 재밌다 ㅋㅋㅋㅋ 오늘까지 해서 남은 개인 과제 모두 다 끝내고 제출해야겠다.

 

728x90