오랜만

거의 한달만에 Nest를 스터디하는 것 같은데? 벌써부터 많은 걸 까먹었지만, 그래도 기록이 있어 어디부터 하면 되는지 정도는 알 수 있었다.


1. 13버전부터 디테일해진 렌더링

Next의 13버전부터 라우팅이 컴포넌트 단위로 바뀌면서, Server Component 또는 Cline Component로 분리하여 작업할 수 있게 되었다.

12 버전으로 공부했을 때, 항상 빌드를 할 때 말썽이었던 문제가 Server 렌더링이 먼저 되면서, 자꾸 page의 클라이언트 관련 컴파일이 안된다는 오류를 일으켰었는데 이러한 문제가 해결될지 기대가 되는 바이다.


2. app 이하 컴포넌트는 기본적으로 서버 컴포넌트이다

서버 렌더링인지 확인하기 위해 간단한 실험을 한다.

// app > rendering > page.tsx

export default function Home() {
    console.log("서버 컴퍼넌트 일때만 콘솔에 표시")

    return (
        <h1>렌더링 테스트</h1>
    )
}

터미널의 콘솔창에는 메시지가 보이지만, 브라우저의 콘솔에는 메시지가 보이지 않았기에 기본적으로 서버 렌더링으로 처리하는 걸 알 수 있다.

image-20231023165422610

따라서, 기본적으로 node 환경에서 지원하는 모듈을 사용할 수 있다. 당연한 사실이지만, 브라우저와 관련된 모듈과 상태(useEffect, useState)를 사용할 수 없다.

그래서 브라우저 위 동작과 관련된 모듈은 클라이언트 컴포넌트 위에 작업해야 한다.


3. 클라이언트 컴포넌트 만들기

프로젝틀 할 때마다 드는 생각이지만, 나는 코드를 짤때 기능단위보다는 논리단위로 작성하기 때문에, 유지보수와 디버깅이 복잡했다. 그리고 프레임워크에서 기능단위의 작성방식을 강제하지 않다보니, 어디서부터 잘라서 작업해야하는지 막막할때가 있었다.

그러던 중 Next에서 컴포넌트를 서버와 클라이언트로 엄격히 구분하는 기능이 시사하는 바가 바로 ‘컴포넌트의 재사용화’임을 알게 되었다. 코드를 작성할 때, 돌아가게만 하기 보다는 늘 필요한 기능을 어디서부터 어떻게 사용할지를 고민하며 작성하는 습관을 이번 실습부터라도 들이는게 좋을 것 같다.

순서 1. 먼저 app 이하에 컴포넌트를 관리하는게 아니라, src 이하에 components 경로를 새로 생성하여, 이곳에서 재사용 가능한 컴포넌트들을 관리하도록 하자

image-20231023170547028


순서 2. 그냥 작성하면, 서버 컴포넌트로 인지하기 때문에, 다음과 같이 스크립트 최상단에 use client를 작성한다

// src > components > ColorChanger.tsx

'use client' // 1. 서버 컴포넌트로 지정

import { useState } from "react"

export default function ColorChange() {
    const [color, setColor] = useState("red");
    const colorChanger = () => {
        if (color === "red") {
            setColor("yellow");
            return;
        }

        setColor("red");
    }
    return <div onClick={colorChanger} style=>
        {color}
    </div >
}
  1. ‘use client’가 없으면 클라이언트 관련 모듈을 사용할 수 없다

순서 3. 클라이언트 컴포넌트를 작동시키고 싶은 서버 컴포넌트로 이동하여, 클라이언트 컴포넌트를 추가하여 사용할 수 있다.

// app > rendering > page.tsx

import ColorChanger from '../components/ColorChanger'

export default function Home() {
    console.log("서버 컴퍼넌트 일때만 콘솔에 표시")

    return (<>
        <h1>렌더링 테스트</h1>
        <ColorChanger /> // 클라이언트 컴포넌트 추가하여 사용
    </>
    )
}

서버 컴포넌트는 무엇인가?

서버 컴포넌트는 서버에서 빌드될 때, 실행되는 컴포넌트를 말한다.

프로젝트 구조에서 app 하위 폴더에 있는 컴포넌트는 ‘서버 컴포넌트’이다. 그래서, node.js에서 제공하는 라이브러리를 사용할 수 있지만, 리액트에서 제공하는 클라이언트 관련 라이브러리나 브라우저 관련 기능은 사용할 수 없다. 아래는 그 예시이다

순서 1-1. 파일 읽기는 node.js 서버사이드에서만 사용이 가능하기 때문에, 테스트용으로 읽기용 파일(test.txt)과 서버 컴포넌트(app > page.tsx)에 아래와 같이 코드를 작성한다

// root > public > test.txt

이 파일은 서버 컴포넌트에서만 보입니다
// src > app > page.tsx

// 1. node 라이브러리 임포트
const fs = require('fs');
const path = require('path');
// ... 1

... 생략 ...

// 2. public 경로의 test.txt 파일 읽기
const fullPath = path.join(process.cwd(), 'public', 'test.txt')
fs.readFile(fullPath, 'utf8', (err: any, data: string) => {
  if (err) {
    console.error('파일 읽기 중 오류 발생: ', err);
    return
  }
  console.log(data);
})

... 생략 ...

순서 1-2. 브라우저에 해당 경로로 접속하면, 터미널에서만 파일에서 읽어온 메시지가 출력되고, 브라우져에서는 출력되지 않는다

[터미널에서만 파일읽기로 가져온 결과가 출력]

image-20230911165820898


2. 서버 컴포넌트 안에서 필요한 부분만 클라이언트 컴포넌트로 구성하자

앞에서 app 하위 폴더의 컴포넌트는 서버 컴포넌트라고 했는데, 클라이언트 컴포넌트가 필요하다면 어떻게 해야할까? 먼저, ‘1. 서버 컴포넌트에서 클라이언트 컴포넌트로 구성할 파일을 생성한다’, ‘2. 클라이언트 컴포넌트임을 Next에 알려 빌드 시, 에러를 피한다’. 아래는 그 예시이다.

클릭할 때마다, 컴포넌트의 색이 교체하는 코드를 작성해보겠다.

순서 2-1. src 경로에 components 경로(앞으로 여기에 클라이언트 컴포넌트를 생성할 것임.)를 추가하고, 리액트 컴포넌트(ColorChangeComponent)를 생성한다.

// src > components > ColorChangeComponent.tsx

'use client' // 1. 넥스트에 클라이언트 컴포넌트임을 알려줌
import { useState, useEffect } from 'react';

export default function ColorChangeComponent() {
    const [clicked, setClicked] = useState(false);
    const barHandler = () => {
        setClicked(!clicked);
    }
    const [color, setColor] = useState('orange');


    useEffect(() => {
        if (clicked) return setColor('green');

        setColor('orange');
    }, [clicked])
    return (
        <div
            onClick={barHandler}
            style=>
            Click me!</div>
    );
}

순서 2-2. 서버 컴포넌트에 클라이언트 컴포넌트를 임포트한다

// src > app > page.tsx

// 1. 클라이언트 컴포넌트 임포트
import ColorChangeComponent from "@/components/ColorChangeComponent";


export default function Home() {
  return (
    <>
      <ColorChangeComponent />
    </>
  )
}

다음에 다루게 될 것

  • Next.js 복습(2): 렌더링

태그:

카테고리:

업데이트:

댓글남기기