[Next.js] app router에서 context api 사용

SUN·2025년 3월 24일
0

Next.js - app router

목록 보기
21/21

1. 소개

next.js app router에서 context api를 사용하는 법은 typescript와 같이 소개한다.

2. 코드 소개

1) context 파일 생성

  • MyContext.tsx
import React, { createContext, useContext, useState, ReactNode } from 'react';

interface MyContextType {
  data: string;
  setData: React.Dispatch<React.SetStateAction<string>>;
}

const MyContext = createContext<MyContextType | undefined>(undefined);

export const MyProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
  const [data, setData] = useState<string>('초기값'); // 기본값 설정

  return (
    <MyContext.Provider value={{ data, setData }}>
      {children}
    </MyContext.Provider>
  );
};

export const useMyContext = (): MyContextType => {
  const context = useContext(MyContext);
  if (!context) {
    throw new Error('useMyContext는 MyProvider 내부에서 사용되어야 합니다.');
  }
  return context;
};

인터페이스(타입) 정의

interface MyContextType {
  data: string;
  setData: React.Dispatch<React.SetStateAction<string>>;
}
  • data : 데이터의 타입을 명시
React.Dispatch<React.SetStateAction<string>>;

- React.Dispatch는 인자로 React.SetStateAction<string>를 받는다.
  • useState의 setter함수에 사용하는 함수로 ts에서 useState 자체에서는 setter 함수의 타입을 자동으로 추론하기 때문에 별도로 타입을 명시하지 않아도 작동하지만 context에서는 명시하는 것을 추천

    • React.SetStateAction : 상태를 새값으로 바꾸거나 이전 상태를 기반으로 새 값을 계산
    • React.Dispatch : 상태 업데이트 함수의 타입. React.SetStateAction를 인자로 받아 상태를 업데이트

context 생성

const MyContext = createContext<MyContextType | undefined>(undefined);
  • createContext:
    React의 createContext 함수를 사용하여 Context 객체를 생성합니다.

  • 초기값:
    초기값으로 undefined를 지정함으로써, 만약 Provider 없이 Context를 사용하려고 하면 에러를 발생시킬 수 있도록 설계되었습니다.

Provider 컴포넌트

export const MyProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
  const [data, setData] = useState<string>('초기값'); // 기본값 설정

  return (
    <MyContext.Provider value={{ data, setData }}>
      {children}
    </MyContext.Provider>
  );
};
  • 상태 관리:
    useState 훅을 사용해 data라는 상태와 이를 업데이트하는 setData 함수를 생성합니다. 초기값은 '초기값'으로 설정되어 있습니다.

  • Provider 역할:
    생성된 MyContext.Provider에 { data, setData }를 값으로 전달하여, 이 Provider 하위의 모든 컴포넌트가 해당 상태와 업데이트 함수를 사용할 수 있게 만듭니다.

  • Next.js 앱 라우터와의 통합:
    Next.js의 새로운 App Router 구조에서는 이 Provider를 최상위 레이아웃 파일에 래핑하여 페이지 전체에서 전역 상태에 접근할 수 있도록 합니다.

커스텀 훅

export const useMyContext = (): MyContextType => {
  const context = useContext(MyContext);
  if (!context) {
    throw new Error('useMyContext는 MyProvider 내부에서 사용되어야 합니다.');
  }
  return context;
};
  • useContext 사용:
    React의 useContext 훅을 사용해 현재 Context 값을 가져옵니다.

  • 안전성 체크:
    만약 Provider 밖에서 이 훅을 호출할 경우 context가 undefined가 되므로, 이를 감지하고 명확한 에러 메시지를 던져 개발자가 올바르게 Provider 내부에서 사용하도록 유도합니다.

  • 편의성:
    이 커스텀 훅을 사용하면 각 컴포넌트에서 useContext(MyContext)를 직접 호출할 필요 없이, 간단히 useMyContext()로 Context 값에 접근할 수 있습니다.


2) 전역 레이아웃에 Provider 적용 (app/layout.tsx)

리액트, 페이지 라우트 next.js는 가장 상위 파일인 app.tsx에 적용하지만 app router는 가장 상위 layout.tsx에 적용한다.

import './globals.css';
import { MyProvider } from '../contexts/MyContext';

export const metadata = {
  title: 'My Next.js App',
  description: 'App Router에서 Context API 사용 예시',
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ko">
      <body>
        {/* 앱 전체에 MyProvider 적용 */}
        <MyProvider>
          {children}
        </MyProvider>
      </body>
    </html>
  );
}

MyProvider를 불러와 상위 구조에 감싼다.


3. 데이터 저장(업데이트) 페이지

'use client';

import React from 'react';
import { useMyContext } from '../../contexts/MyContext';
import Link from 'next/link';

export default function SavePage() {
  const { setData } = useMyContext();

  const handleSave = () => {
    // 원하는 데이터를 저장(업데이트)합니다.
    setData('저장된 데이터입니다!');
  };

  return (
    <div>
      <h1>데이터 저장 페이지</h1>
      <button onClick={handleSave}>데이터 저장</button>
      <p>
        <Link href="/read">데이터 조회 페이지로 이동</Link>
      </p>
    </div>
  );
}

useMyContext를 사용하여 setData 함수를 가져온다.
setData 함수에 저장할 함수를 만들고 함수를 적용하면 저장된다.


4. 데이터 조회(꺼내쓰기) 페이지 (app/read/page.tsx)

// app/read/page.tsx
'use client';

import React from 'react';
import { useMyContext } from '../../contexts/MyContext';
import Link from 'next/link';

export default function ReadPage() {
  const { data } = useMyContext();

  return (
    <div>
      <h1>데이터 조회 페이지</h1>
      <p>저장된 데이터: {data}</p>
      <p>
        <Link href="/save">데이터 저장 페이지로 이동</Link>
      </p>
    </div>
  );
}

useMyContext를 가져와 data를 불러온다.
불러온 data를 원하는 곳에서 사용한다.

profile
안녕하세요!

0개의 댓글