Day 41 - React(TypeScript) 기반의 동적 UI 개발, 01

이유승·2025년 2월 2일

* 프로그래머스, 타입스크립트로 함께하는 웹 풀 사이클 개발(React, Node.js) 5기 강의 수강 내용을 정리하는 포스팅.

* 원활한 내용 이해를 위해 수업에서 제시된 자료 이외에, 개인적으로 조사한 자료 등을 덧붙이고 있음.

▶️ 스프린트 3 개괄

프로젝트 진행 목적

  • 환경 설정 : React.js 개발 환경 세팅.

  • 타입과 모델 : Type의 정의, 이를 기반으로 하는 Model 작성.

  • 데이터 흐름 : Data Flow. API 요청에서 렌더링까지 데이터의 흐름을 제어.

  • 상태 관리 : 컴포넌트에서의 상태state 관리, 그리고 ContextAPI와 전역 상태 관리 라이브러리Redux를 활용.

  • UI 패턴 : 모달Modal / 무한 스크롤 / 슬라이드 쇼 / DropDown / 탭 등등.. 각종 UI 패턴의 구현 및 원리.

  • 모바일 대응 : 반응형 웹은 기본.



▶️ React.js 프로젝트의 생성

보일러플레이트Boilerplate

  • 19세기, 증기 보일러를 제작할 때 사용하던 틀.

  • 나중에는 인쇄에 사용되는 인쇄판도 지창하는 용어로 발전.

  • 이 단어가 컴퓨터 프로그래밍에서도 사용되게 되었다.

  • 동작을 위해 반드시 포함되어야 하는 필수 내용, 보통 수정이 필요없이 작동하고 거의 그대로 가져다가 사용할 수 있는 내용들.

  • 간단하게 말하자면 프로젝트 개발에 필요한 필수 요소들을 미리 세팅해놓고, 필요할 때마다 그대로 설치해주기만 하면 편하지 않겠는가?

  • React.js의 보일러플레이트Boilerplate는 통상 2가지. CRA와 Vite.



CRA와 Vite

  • 두 개념의 차이는 이전 포스팅 참조.

  • 2025년을 기준으로 하자면.. CRA는 더 이상 사용하지 않는 것을 추천한다.



▶️ 스프린트 3 프로젝트 구조

  • 프로젝트 폴더 구조는 어떤 아키텍처를 사용하는지, 개발철학이 어떻게되는지에 따라 천차만별이다.

  • 자세한 내용은 이전 포스팅 참조.



일단 이번 스프린트 프로젝트 구조는 아래와 같다.

  • pages - Router에 대응되는 Page 컴포넌트들.
    - 여기 아래에 components들이 각각 위치한다.

  • components - 각 Page별 그리고 공통적으로 사용되는common component들.

  • utils - App에서 사용될 여러 함수들. Hook이 아니다.

  • hooks - Custom Hook으로 불리는 녀석들.

  • model - 이 서비스에서 다루는 데이터의 형태들을 정의.

  • api - API 함수들.



▶️ Package.json과 script, Config

"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
}
  • 각각의 script들은 (NPM 기준) 'npm run ~'의 명령어로 동작한다.

  • start는 로컬 서버에서 App을 실행시킨다. 브라우저의 'http://localhost:3000' 주소로 접근 가능.
    - 포트 번호는 .env 설정 후 PORT=4000처럼 설정하면 기본 포트를 변경할 수 있다.
    - 코드에서 변경사항이 감지되면? Hot Module Replacement(HMR) 를 통해 자동으로 화면을 갱신해준다.

  • build는 src 디렉토리의 React 코드들을 최적화된 정적 파일로 변환하여 build/ 폴더에 생성.
    - Webpack을 사용하여 코드 스플리팅(Code Splitting), 압축(Minification), 트리 셰이킹(Tree Shaking) 등의 최적화를 수행.
    - build된 정적 파일들은 호스팅(예: Netlify, Vercel, Firebase Hosting, AWS S3)에 배포할 수 있다.
    - npm run build -- --profile. React 16 이상에서는 프로파일링(Profiling) 모드를 활성화하여 성능 분석을 위한 정보를 얻을 수 있다.

  • test는 Jest 프레임워크를 사용하여 애플리케이션의 단위(Unit) 및 통합(Integration) 테스트를 실행.
    - 기본적으로 "Watch Mode"가 활성화되어 변경 사항이 발생할 때마다 자동으로 테스트가 재실행.
    - npm test -- --coverage 옵션을 사용하면 코드 커버리지 리포트를 생성할 수 있다.

  • eject는 CRA에서 제공하는 기본 Webpack, Babel, ESLint 등의 설정 파일을 프로젝트에 직접 노출.
    - 이후에는 CRA의 관리 없이 커스텀 설정을 직접 변경가능.
    - 다만, 이 작업은 되돌릴 수 없으며, eject를 실행하면 CRA의 업데이트를 더 이상 받을 수 없다.
    - 일반적으로 CRA 내부 설정을 수정해야 하는 특별한 경우에만 사용.



타입스크립트 Config



▶️ 라우터Router

  • 라우터Router? 클라이언트가 요청하는 경로(URL)와 HTTP 메서드(GET, POST 등)에 따라 알맞은 처리를 수행하는 역할.

  • URL 경로와 요청 메서드 매핑 / 미들웨어 기능도 수행 / 모듈화 가능 등의 특징을 지닌다.

  • 애플리케이션의 라우팅 시스템을 구성하는 핵심 요소.

  • 자세한 내용은 이전 포스팅 참조.

  • Router란? / React Router v6의 변화, BrowserRouter.



▶️ 모델과 API, 데이터 흐름

  • 도서 페이지에 필요한 모델은? 이번 프로젝트에서는 User / Book / Category / Cart / Order로 구성된다.

  • 이전에도 언급했던 내용인데.. 개발자의 취향, 작업 요구사항 등에 따라 프론트엔드에서 데이터가 어떤 구조로 전달되는지 '아키텍처'를 구성하는 방법은 천차만별이다.

  • 이번 프로젝트에서는..

컴포넌트 <-> Custom Hooks <-> API Function <-> 백엔드

  • 의 구조로 구성되어있다.
    - 필요에 따라서 중간에 React-Query 같은 추가 라이브러리가 더해질 수도 있다.



▶️ CORS?

  • CORS (Cross-Origin Resource Sharing)

  • 기본적으로 프론트엔드와 백엔드 사이에서 데이터를 주고받을 때에는.. '같은 도메인'에서의 요청-응답만 허용하도록 되어있다.

  • 그런데 실제 서비스에서 이용자와 서비스 제공자가 동일 위치일 수는 없다.

  • 그래서.. 서로 다른 위치에서 요청-응답을 주고받는 것을 허용해줄 필요가 있다.

  • 자세한 설명 및 해결 방법은 외부 포스팅 참조.



🎨레이아웃Layout

  • 웹 애플리케이션이나 웹사이트에서 각 요소들이 화면에서 배치되는 방식.

  • UI(User Interface) 요소들을 어떻게 정렬하고, 배치하고, 구성할지를 정의하는 개념.



📌 레이아웃의 핵심 요소

  • 레이아웃을 구성할 때 중요한 요소들을 정리하면 다음과 같다.

1️⃣ 컨테이너(Container)

  • 웹 페이지에서 주요 콘텐츠를 감싸는 요소.
  • div, section, article 등의 HTML 태그를 사용하여 레이아웃을 구성함.
  • 일반적으로 max-width, margin: auto 등을 활용하여 가운데 정렬을 적용.

2️⃣ 그리드 시스템(Grid System)

  • 행(Row)과 열(Column)로 화면을 나누어 배치하는 방식.
  • 예를 들어, CSS Grid, Flexbox, Bootstrap Grid 등이 있다.
  • 반응형(Responsive) 디자인에서 중요한 역할을 한다.

3️⃣ 내비게이션(Navigation)

  • 사용자 경험(UX)에서 중요한 요소로, 메뉴나 탭을 통해 사용자가 원하는 페이지로 이동할 수 있도록 함.
  • header, nav 태그 등을 사용하여 구현.

4️⃣ 사이드바(Sidebar)

  • 보조 정보나 추가적인 메뉴를 배치하는 공간.
  • 일반적으로 왼쪽 또는 오른쪽에 위치하며, aside 태그를 활용할 수 있음.

5️⃣ 메인 콘텐츠(Main Content)

  • 웹 페이지의 핵심 내용을 담는 영역.
  • main, section, article 등을 활용하여 구조를 나눌 수 있음.

6️⃣ 푸터(Footer)

  • 웹 페이지의 하단 영역으로, 회사 정보, 저작권, SNS 링크 등을 포함할 수 있음.
  • footer 태그 사용.



🏗️ 레이아웃을 구성하는 방법

  • 레이아웃을 만들 때 사용되는 기술과 방법은 다음과 같다.

🔹 CSS Flexbox

  • 한 방향(가로 또는 세로)으로 요소를 정렬하는 데 유용한 CSS 레이아웃 방식.
  • display: flex;를 사용하여 컨테이너 내부의 아이템을 정렬 가능.

주요 속성:

  • justify-content: 가로 정렬
  • align-items: 세로 정렬
  • flex-wrap: 줄바꿈 여부 설정

예제:

.container {
    display: flex;
    justify-content: center; /* 가로 중앙 정렬 */
    align-items: center; /* 세로 중앙 정렬 */
}

🔹 CSS Grid

  • 행과 열을 조합하여 2차원 배치가 가능한 강력한 레이아웃 시스템.
  • display: grid;를 사용하여 복잡한 레이아웃도 쉽게 구현 가능.

주요 속성:

  • grid-template-columns: 열의 개수 및 크기 설정
  • grid-template-rows: 행의 크기 설정
  • gap: 요소 간 간격 설정

예제:

.container {
    display: grid;
    grid-template-columns: 1fr 2fr 1fr;
    gap: 10px;
}

🔹 CSS Position

  • absolute, relative, fixed, sticky 등을 사용하여 특정 위치에 요소를 배치하는 방법.

🔹 미디어 쿼리 (Media Query)

  • 반응형(Responsive) 디자인을 적용할 때 사용.
  • 화면 크기에 따라 레이아웃을 다르게 조정할 수 있음.

예제:

@media (max-width: 768px) {
    .container {
        flex-direction: column;
    }
}



🖼️ 레이아웃 유형 (Layout Types)

  • 웹 페이지에서 흔히 사용되는 레이아웃 패턴은 다음과 같다.

🔹 레이아웃 유형

고정 레이아웃 (Fixed Layout)

  • 화면 크기에 관계없이 특정 크기로 고정
  • 데스크톱 전용 웹사이트

유동적 레이아웃 (Fluid Layout)

  • 화면 크기에 맞춰 요소 크기가 유동적으로 조정
  • 비율 기반의 CSS 설정

반응형 레이아웃 (Responsive Layout)

  • 다양한 화면 크기에 따라 다르게 보이도록 설정
  • 미디어 쿼리 활용

어댑티브 레이아웃 (Adaptive Layout)

  • 정해진 몇 가지 화면 크기에 맞춰 변화
  • 데스크톱, 태블릿, 모바일 버전이 각각 다르게 동작



▶️ CSS-in-JS, Styled-Components



Styled-Components의 글로벌 스타일(Global Styles)

  • 프로젝트 전반적으로 적용해야 하는 글로벌 스타일(Global Styles)이 필요할 때에는?

  • styled-components에서 제공하는 createGlobalStyle를 사용하면 된다.

import { createGlobalStyle } from "styled-components";

const GlobalStyle = createGlobalStyle`
  /* 생략... */
`;

export default GlobalStyle;
  • 이렇게 스타일 코드를 구성한 뒤, 아래처럼 최상위 컴포넌트에서 호출해주면 된다.
import React from "react";
import GlobalStyle from "./GlobalStyle";

function App() {
  return (
    <>
      <GlobalStyle /> {/* 글로벌 스타일 적용 */}
      <h1>Welcome to Styled Components!</h1>
    </>
  );
}

export default App;



테마(Theme)와 ThemeProvider

  • 테마?

  • 여러 사이트에서 제공하고 있는, 화이트/다크 모드 같은 기능은 어떻게 구현해야하는가?

export const lightTheme = {
  bgColor: "#ffffff",
  textColor: "#333333",
  accentColor: "#007bff",
};

export const darkTheme = {
  bgColor: "#333333",
  textColor: "#ffffff",
  accentColor: "#ffcc00",
};
  • 위와 같이 특정 '테마'에 따라 텍스트나 배경색 등의 CSS 속성을 '일치'시켜두고..
import React, { useState } from "react";
import { ThemeProvider } from "styled-components";
import { lightTheme, darkTheme } from "./theme";
import GlobalStyle from "./GlobalStyle";

function App() {
  const [isDark, setIsDark] = useState(false);

  return (
    <ThemeProvider theme={isDark ? darkTheme : lightTheme}>
      <GlobalStyle />
      <button onClick={() => setIsDark(!isDark)}>Toggle Theme</button>
      <h1>Styled Components Theme</h1>
    </ThemeProvider>
  );
}

export default App;
  • 이렇게 ThemeProvider와 State 제어를 통해 테마를 동적으로 적용할 수 있다.
    - 당연하지만 useState 이외에도 ContextAPI, Redux 등을 연계하여 구현하는 것도 가능하다.
profile
프론트엔드 개발자를 준비하고 있습니다.

0개의 댓글