Prography 사전과제

primav·2025년 2월 16일

React

목록 보기
31/35

🔥 Prography

https://prography.org/

부트캠프가 끝나고 새로운 프로젝트를 하고 싶어 동아리를 찾아보던 중에 Prography 라는 동아리를 발견했다.
사전 과제, 면접을 통해 심사가 이루어지는데 내가 지원한 Web 파트의 사전과제는 Prography 라는 사이트를 제작하는 것이다.
자바스크립트, 타입스크립트 중에 하나를 택하여 진행하면 되는데 나는 자바스크립트를 사용하여 이 사이트를 구현해보고자 한다.

아래는 내가 이 사이트를 구현하면서 알게된 점, 헷갈렸던 점을 작성한 글이다.

1. 환경설정

  • vite 설정
  • tailwind css 설정
  • index.html 변경 - 웹 이름, 이미지 설정

나는 스타일링을 할 때 명확하고 깔끔한 코드 작성을 위해 이름을 작성하는 데에 시간을 많이 쓰는 편이라, tailwindcss 를 사용하여 스타일링을 했다!

이번 프로젝트를 진행하면서 tailwind 가 업데이트가 되어서 바뀐 부분에 대해 학습하며 진행해보는 것이 목표이다!

2. TailwindCSS

📌 Tailwindcss 버전 업데이트

👀 TailwindCSS 적용을 위해 공식 문서를 확인해보니 버전이 업데이트 되었다!!

예전 했던 프로젝트와 달리 헤매는 부분이 많았는데, 새로운 버전으로 업데이트 되어서 문제가 발생했던 것 같다 ㅠㅠ
아래는 기존과 비교하여 어떤 부분이 달라졌는지에 대한 공식 문서와 내가 참고한 문서이다.

📌 tailwindcss 초기 설정

공식 문서 : https://tailwindcss.com/docs/installation/using-vite

  1. Tailwindcss 설치
    npm install tailwindcss @tailwindcss/vite

  2. @tailwindcss/vite 추가

✔️ vite.config.js

	import { defineConfig } from "vite";
	import react from "@vitejs/plugin-react";
	import tailwindcss from "@tailwindcss/vite";

	export default defineConfig({
  		plugins: [react(), tailwindcss()],
	});
  1. Tailwind를 CSS에 적용
    src 아래에 index.css 파일을 생성하여 아래 내용을 추가한 후, main.jsx에서 이 CSS 파일을 불러온다.
    (@import "tailwindcss" 만 사용하면 되며, 이것이 모든 Tailwind 스타일을 포함시킨다고 한다!)
✔️ index.css

	@import "tailwindcss";
✔️ main.jsx

	import "./index.css";

📌 theme 변수

공식 문서: https://tailwindcss.com/docs/theme

Tailwind는 맞춤형 디자인을 구축하기 위한 프레임워크이며, 다양한 디자인을 하려면 각기 다른 폰트, 색상, 그림자 등이 필요하다.

이러한 저수준의 디자인 결정을 디자인 토큰이라고 하며, Tailwind 프로젝트에서는 이러한 값을 테마 변수에 저장한다.

theme 변수란?

프로젝트에 존재하는 유틸리티 클래스에 영향을 미치는 지시어를 사용하여 정의되는 특수한 CSS 변수이다.

예를 들어, 내가 사용할 새로운 색상을 아래와 같이 추가할 수 있다.
그러면 이제 어디에서나 이 유틸리티 클래스를 사용할 수 있는 것이다.

✔️ 사용 방법

<div className="bg-mint-500">
  <!-- ... -->
</div>

Theme variable namespace

테마 변수는 네임스페이스에서 정의되며, 각 네임 스페이스는 하나 이상의 유틸리티 클래스 또는 변형 API 에 해당한다.

이러한 네임스페이스에서 새 테마 변수를 정의하면 새 해당 유틸리티와 변형을 사용할 수 있다!

3. 라우터 설정

  • 폴더 구조 정리
  • 필요한 페이지 확인
  • 각 페이지에 라우터 설정

📌 경로 단축

vite.config.js 에서 resolve.alias 부분을 추가하면, 복잡한 경로를 짧게 단축 시킬 수 있다.

ex)

import Button from "../../components/Button";

🅾️
import Button from "@components/Button";
✔️ vite.config.js
import { defineConfig <} from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";

export default defineConfig({
  plugins: [react(), tailwindcss()],
  resolve: {
    alias: [
      { find: "@", replacement: "/src" },
      { find: "@components", replacement: "/src/components" },
      { find: "@pages", replacement: "/src/pages" },
      { find: "@hooks", replacement: "/src/hooks" },
    ],
  },
});

📌 lazy

https://ko.react.dev/reference/react/lazy

lazy 란 코드 분할을 위해 사용되는 기능으로, 컴포넌트를 동적으로 가져와서 필요한 순간에 로드할 수 있도록 해준다.

코드분할

애플리케이션의 전체 JS 파일을 여러 개의 작은 번들로 나누어, 필요한 시점에 필요한 코드만 로드하는 기법이다.

즉, 한번에 모든 코드를 로드하는 것이 아니라 사용자가 필요한 부분만 불러오도록 하는 최적화 방법이다.

  • 초기 로딩 속도 개선
  • 불필요한 코드 로드 방지

👀 lazy 를 왜 사용해야 할까?

lazy를 사용하면 컴포넌트가 처음 렌더링될 때까지 해당 컴포넌트의 코드를 로딩하는 것을 지연할 수 있다.

📌 Router에 lazy 적용

  • lazy() 를 사용하면 해당 컴포넌트가 필요한 순간에만 로드된다.
  • Suspense 를 사용하여 로딩중일 때 보여줄 UI를 설정할 수 있다.

➡️ 사용자가 /about 페이지에 방문하기 전까지는 AboutPage.jsx 파일이 로드되지 않는다.
➡️ 초기 로딩 속도가 빨라진다!!

✔️ routes.jsx
import { lazy } from "react";
const Layout = lazy(() => import("@components/Layout"));

📌 라우터 설정

1. 라우터 정의

  • createBrowswerRouter 를 사용하여 라우터 생성
  • 라우터에 경로 지정
  • lazy 사용하여 초기 로딩 속도 빠르게

✔️ routes.jsx

import { lazy } from "react";
import { createBrowserRouter } from "react-router-dom";

const Layout = lazy(() => import("@components/Layout"));

const MainPage = lazy(() => import("@pages/MainPage"));
const AboutPage = lazy(() => import("@pages/AboutPage"));
const ProjectPage = lazy(() => import("@pages/ProjectPage"));
const ContactPage = lazy(() => import("@pages/ContactPage"));
const ApplyPage = lazy(() => import("@pages/ApplyPage"));

const router = createBrowserRouter([
  {
    path: "/",
    element: <Layout />,
    children: [
      { index: true, element: <MainPage /> },
      { path: "/about", element: <AboutPage /> },
      { path: "/project", element: <ProjectPage /> },
      { path: "/contact", element: <ContactPage /> },
      { path: "/apply", element: <ApplyPage /> },
    ],
  },
]);

export default router;

2. App 에 라우터 연결

  • RouterProvider 를 사용하여 라우터 연결
import { RouterProvider } from "react-router-dom";
// import { Suspense } from "react";
import router from "@/routes";

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

export default App;

📌 Outlet - 중첩 라우트

네비게이션, Footer 등 모든 페이지에서 사용되는 부분을 위해서 사용된다.
부모 컴포넌트 내부에 자식 라우트가 렌더링될 위치를 지정하는 역할이다.

페이지 전환 시에도 전체 페이지가 새로고침되지 않고, SPA의 특성을 유지할 수 있다!!

4. 폰트 설정

index.css 라는 테일윈드가 적용된 스타일링 파일에서 @base 부분에 사용하고자 하는 폰트를 적용시켜준다.

📌 layer base

💡 @layer base란?

Tailwind CSS 에거 기본 스타일 (글씨체 등)을 커스터마이징 할 수 있도록 제공하는 기능이다.

  • Tailwind 가 제공하는 기본 스타일을 추가하거나 덮어쓰기 할 수 있다.
  • 기본적인 폰트 설정을 적용하는 데 유리하다.
  • HTML 태그의 기본 스타일을 변경할 수 있다.
    (html, body, h1, p)

💡 @layer base vs @layer components vs @layer utilities

Layer설명
baseHTML 태그 등 기본 스타일을 변경하는 데 사용
components재사용 가능한 컴포넌트 스타일을 정의하는 데 사용 (ex: btn-primary)
utilitiesTailwind의 유틸리티 클래스를 직접 정의할 때 사용

CDN

CDN (콘텐츠 전송 네트워크)에서 제공하는 CSS 파일을 가져와서 스타일에 적용하는 방식으로, 외부 CSS 파일을 불러오는 방법 중 하나이다.

  • https://cdn.jsdelivr.net/... → CDN 서버에서 폰트 스타일을 가져오는 URL
  • @import url("...") → 해당 URL의 CSS 파일을 현재 CSS 파일에 포함
@import url("https://cdn.jsdelivr.net/npm/@qpokychuk/sf-pro-display@1.0.2/index.min.css");

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  html {
    font-family: "SF Pro Display", sans-serif;
  }
}

5. Header - 네비게이션

NavLink 속성을 이용하여 활성화된 경로에 따로 스타일링을 지정할 것이고, NavItem 이라는 컴포넌트를 생성하여 이를 처리할 생각이다!

1. 네비게이션 바 경로 연결

✔️ Header.jsx

import logo from "/images/logo_prography.png";
import NavItem from "@components/NavItem";

export default function Header() {
  return (
    <header className="h-20 flex items-center px-20 justify-between">
      <img src={logo} className="h-12" />
      
      <nav className="h-12 text-white flex items-center">
        <NavItem to="/about">About</NavItem>
        <NavItem to="/project">Project</NavItem>
        <NavItem to="/contact">Contact</NavItem>
        <NavItem to="/apply">11기 모집</NavItem>
      </nav>
    </header>
  );
}
  1. NavItem 컴포넌트 생성
✔️ NavItem.jsx

import { NavLink } from "react-router-dom";

export default function NavItem({ to, children }) {
  return (
    <NavLink
      to={to}
      className={({ isActive }) => (isActive ? "text-primary" : undefined)}
    >
      {children}
    </NavLink>
  );
}

❗️ 컴포넌트에서는 props 를 받을 때 꼭 유효성 검증을 해야한다!

✔️ NavItem.jsx

import PropTypes from "prop-types";

NavItem.propTypes = {
  to: PropTypes.string.isRequired,
  children: PropTypes.string.isRequired,
};

6. Form

📌 react-hook-form

React Hook Form을 사용하면 폼 컴포넌트의 상태 및 유효성 검사를 관리하는 데 필요한 코드 양을 대폭 줄일 수 있다.
폼 요소의 값이나 상태 변경에 대한 이벤트를 관리하기 위해 명시적인 이벤트 핸들러를 작성할 필요 없이, 단순히 Hook(useForm, useController, useWatch...)을 사용하여 관련 데이터를 추적하고 업데이트할 수 있다.

  • useForm
    React Hook Form의 핵심 함수로, 폼의 인스턴스를 생성하고 폼 데이터와 메서드를 제공한다.

  • register
    입력 필드를 React Hook Form에 등록한다. 입력 필드에 대한 유효성 검사 규칙, 기본값 등을 설정할 수 있다.

  • handleSubmit
    handleSubmit 함수는 폼 제출 시 실행할 함수를 정의한다. 이 함수는 유효성 검사를 수행하고, 제출할 데이터를 처리하는 로직을 작성할 수 있다.

  • errors
    유효성 검사 실패 시 해당 필드의 에러 메시지를 포함한다.

++ Git

💡 git clone vs git pull vs git fetch

  • git clone
    내 로컬 저장소에 git 레포지토리를 복사해올 때 사용한다.
    기존 프로젝트 레포지토리가 존재하고 그것을 복사해와야 하는 경우 사용하면 된다.

  • git pull
    최신 업데이트 된 레포지토리의 변경사항을 로컬 저장소에 불러와 병합하는 명령어이다.
    merge 까지 진행되는 것을 명심하자!

  • git fetch
    commit, push 이력과 같이 팀원들이 최근에 업데이트한 사항들을 가져온다.
    pull 과 달리 병합하지 않고, 상태만 동기화시키는 것을 명심하자! (merge x)

나의 경우에는 pull, fetch가 헷갈렸는데 fetch를 사용하면 생성된 브랜치를 볼 수 있다는 점에서 차이를 느꼈다.

0개의 댓글