[week12] React(TypeScript) 기반의 동적 UI 개발(4) - 04/01

Kyulee·2026년 4월 1일

TIL 

목록 보기
60/90
post-thumbnail

지난 시간에 이어 북스토어 프로젝트를 계속 진행하겠습니다. 이번 시간에는 라우팅 설정, 데이터 모델 정의, 서버 통신, 그리고 회원가입 폼 구현까지의 과정을 정리했습니다.


1. 라우트 작성 (React Router Dom)

화면을 이동하기 위해서는 URL을 사용합니다. URL과 화면 컴포넌트를 일치시키는 라우팅 작업을 위해 react-router-dom 패키지를 활용합니다. 타입스크립트 환경에서는 타입 정의가 필요하므로 @types/react-router-dom 도 함께 설치해야 합니다.

pnpm install react-router-dom
pnpm install -D @types/react-router-dom

createBrowserRouter 함수로 경로(path)와 컴포넌트(element)를 연결하고, RouterProvider 컴포넌트로 화면에 렌더링합니다.

import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import Layout from './components/layout/Layout';
import Home from './views/Home';
import Detail from './views/Detail';

const router = createBrowserRouter([
  {
    path: '/',
    element: (
      <Layout>
        <Home />
      </Layout>
    ),
  },
]);

function App() {
  return (
    <BookStoreThemeProvider>
      <ThemeSwitcher />
      <Layout>
        <RouterProvider router={router} />
      </Layout>
    </BookStoreThemeProvider>
  );
}

export default App;

Layout 컴포넌트로 각 페이지를 감싸면 헤더와 푸터를 라우트 단위로 공통 적용할 수 있습니다. 경로마다 어떤 컴포넌트가 보일지 한눈에 파악되는 구조라 유지보수에도 유리합니다.


2. 모델 정의

서버와 통신할 때 프론트엔드에서 어떤 형태의 데이터를 받을지 미리 정의해 두는 것이 중요합니다. 이러한 타입(인터페이스)들을 모아서 관리하는 곳이 models 폴더입니다.

파일 이름을 지을 때는 user.model.ts 처럼 확장자 앞에 역할을 명시하면 구분하기 편리합니다.

// src/models/user.model.ts
export interface User {
  id: number;
  email: string;
  password?: string;
}

자바스크립트처럼 매번 데이터의 존재 여부를 런타임에 확인하는 대신, 미리 인터페이스를 만들어 타입을 지정해두면 개발 단계에서 오류를 미리 방지할 수 있습니다. 서버 응답 구조가 바뀌었을 때도 타입 에러로 바로 확인할 수 있어서 디버깅이 훨씬 수월해집니다.


3. API 통신과 데이터 레이어

Axios 설치 및 기본 설정

서버와 통신하는 방법에는 여러 가지가 있지만, 이번 프로젝트에서는 axios 라이브러리를 활용합니다.

npm install axios

axios 인스턴스를 미리 만들어두면 baseURL, 인터셉터 등을 한 곳에서 관리할 수 있어 편리합니다.

// src/api/axios.ts
import axios from 'axios';

const axiosInstance = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
});

export default axiosInstance;

CORS 에러

백엔드 서버와 연결하는 과정에서 CORS 에러가 발생할 수 있습니다. CORS는 브라우저가 다른 출처(Origin)의 리소스 요청을 제한하는 보안 정책입니다.

이 문제는 프론트엔드가 아닌 백엔드 서버 측에서 CORS 정책을 허용해 주는 방식으로 해결해야 합니다. 프론트엔드에서 임의로 우회하려 하면 안 되고, 서버가 응답 헤더에 Access-Control-Allow-Origin 을 포함해야 합니다.

데이터 레이어 분리

API 호출 로직을 컴포넌트 안에 직접 작성하면 코드가 금방 복잡해집니다. api 폴더를 따로 만들어 서버 통신 함수를 분리해두면 재사용성과 테스트 용이성이 높아집니다.

// src/api/auth.ts
import axiosInstance from './axios';
import type { User } from '../models/user.model';

export const fetchUserInfo = async (): Promise<User> => {
  const response = await axiosInstance.get('/users/me');
  return response.data;
};

4. 회원가입

React Hook Form

회원가입 같은 폼(Form) 화면을 만들 때 기본 onChange 와 제출 로직을 일일이 작성하면 코드가 매우 길어집니다. 이를 보완하기 위해 react-hook-form 라이브러리를 사용합니다.

npm install react-hook-form

useForm() 훅은 다음과 같은 유용한 기능을 제공합니다.

반환값역할
register입력값을 추적하고 유효성 검사 규칙을 연결합니다
handleSubmit제출 이벤트를 관리합니다
formState.errors유효성 검사 에러 메시지를 확인합니다
profile
안녕하세요 매일의 배움을 기록으로 자산화하는 개발자 이규현입니다 😊

0개의 댓글