개발 방법론 & 아키텍쳐

React 프로젝트에서 재활용 및 공통화 전략(UI/UX)

atomicdev 2024. 10. 2. 15:09
728x90

React 프로젝트에서 재활용 및 공통화 전략

React는 컴포넌트 기반 아키텍처로 재사용성이 높은 코드를 쉽게 작성할 수 있는 구조입니다. 특히, 대규모 프로젝트에서는 여러 부분에서 코드의 중복을 최소화하고 유지보수를 용이하게 하기 위해 코드의 재활용 및 공통화가 중요한 전략 중 하나입니다. 이번 블로그에서는 React 프로젝트에서 재활용할 수 있는 공통 요소들을 효율적으로 관리하고 구현하는 방법에 대해 설명하고, 몇 가지 구체적인 사례를 예시로 들어봅니다.

React 프로젝트에서 재활용

1. 재활용 가능한 컴포넌트 설계 전략

1-1. 프레젠테이셔널 컴포넌트와 컨테이너 컴포넌트 분리

React 컴포넌트를 두 가지 역할로 나누어 생각할 수 있습니다. 프레젠테이셔널 컴포넌트(Presentational Components)는 단순히 UI를 나타내는 역할을 하고, 컨테이너 컴포넌트(Container Components)는 비즈니스 로직과 데이터를 다룹니다. 이 둘을 분리함으로써 재사용성을 극대화할 수 있습니다.

  • 프레젠테이셔널 컴포넌트: UI만을 담당하고, 상태나 비즈니스 로직과는 분리됩니다. 여러 곳에서 같은 UI를 사용할 때 재사용할 수 있습니다.
  • 컨테이너 컴포넌트: 데이터와 비즈니스 로직을 다루며, 프레젠테이셔널 컴포넌트에 데이터를 전달해 UI를 렌더링합니다.

예시 코드:

// Presentational Component
const Button = ({ label, onClick }) => {
  return <button onClick={onClick}>{label}</button>;
};

// Container Component
const SubmitButtonContainer = () => {
  const handleClick = () => {
    console.log('Button clicked!');
  };

  return <Button label="Submit" onClick={handleClick} />;
};

1-2. 컴포넌트 Props 활용

컴포넌트가 동적으로 다양한 기능을 수행하게 하려면, Props를 잘 활용하는 것이 중요합니다. 예를 들어, 스타일이나 동작을 Props로 전달함으로써 다양한 시나리오에서 동일한 컴포넌트를 재사용할 수 있습니다.

예시 코드:

const Card = ({ title, content, footer }) => {
  return (
    <div className="card">
      <h3>{title}</h3>
      <p>{content}</p>
      {footer && <div className="card-footer">{footer}</div>}
    </div>
  );
};

// 재사용 예시
<Card title="Card 1" content="This is the first card." />
<Card title="Card 2" content="This is the second card." footer="Footer text" />

2. 스타일링의 재활용

2-1. CSS Modules

CSS Modules는 컴포넌트에 고유한 스타일을 적용하면서 전역 CSS 충돌을 방지하는 방법입니다. 이를 통해 스타일을 재사용하고, 여러 컴포넌트 간에 공통 스타일을 쉽게 적용할 수 있습니다.

예시 코드:

/* Card.module.css */
.card {
  padding: 16px;
  background-color: white;
}

.cardFooter {
  margin-top: 10px;
  font-size: 14px;
  color: gray;
}
import styles from './Card.module.css';

const Card = ({ title, content }) => {
  return (
    <div className={styles.card}>
      <h3>{title}</h3>
      <p>{content}</p>
    </div>
  );
};

2-2. Styled Components 또는 Emotion

Styled Components는 CSS-in-JS 방식으로 컴포넌트 수준에서 스타일을 정의하고 재사용할 수 있도록 도와줍니다. 이를 통해 재사용 가능한 UI 요소를 쉽고 간결하게 작성할 수 있습니다.

예시 코드:

import styled from 'styled-components';

const Button = styled.button`
  padding: 10px;
  background-color: ${props => (props.primary ? 'blue' : 'gray')};
  color: white;
`;

<Button primary>Primary Button</Button>
<Button>Secondary Button</Button>

3. 상태 관리의 재활용

3-1. Context API와 Custom Hook 활용

상태 관리 로직을 공통화하여 여러 컴포넌트에서 재사용할 수 있는 방법 중 하나가 Context API와 Custom Hook입니다. 전역 상태 관리가 필요한 경우, Context API를 통해 상태를 여러 컴포넌트에서 공유하고 관리할 수 있습니다.

Custom Hook 예시:

import { useState, useContext, createContext } from 'react';

const AuthContext = createContext();

export const useAuth = () => {
  return useContext(AuthContext);
};

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);

  const login = (username) => {
    setUser({ name: username });
  };

  return (
    <AuthContext.Provider value={{ user, login }}>
      {children}
    </AuthContext.Provider>
  );
};

AuthProvider를 이용한 재사용:

// App.js
import { AuthProvider, useAuth } from './auth';

function Login() {
  const { login } = useAuth();

  return (
    <button onClick={() => login('John Doe')}>Login</button>
  );
}

function UserProfile() {
  const { user } = useAuth();

  return user ? <div>Welcome, {user.name}!</div> : <div>Please login</div>;
}

function App() {
  return (
    <AuthProvider>
      <Login />
      <UserProfile />
    </AuthProvider>
  );
}

export default App;

3-2. Redux 또는 Zustand 활용

대규모 애플리케이션에서 상태 관리가 더 복잡해지면 Redux나 Zustand와 같은 상태 관리 라이브러리를 사용할 수 있습니다. 이들은 중앙에서 상태를 관리하며, 필요한 부분에서만 데이터를 주고받음으로써 효율적인 상태 관리를 도와줍니다.

4. API 통신 재활용

4-1. Axios 인스턴스화

API 호출은 대부분의 애플리케이션에서 필수적인 부분입니다. 이때 Axios와 같은 HTTP 클라이언트를 사용하여 공통 API 호출 로직을 인스턴스화함으로써 여러 컴포넌트에서 재사용할 수 있습니다.

예시 코드:

import axios from 'axios';

const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 1000,
  headers: { 'Authorization': 'Bearer token' }
});

export const getData = () => apiClient.get('/data');
export const postData = (data) => apiClient.post('/data', data);

재사용된 API 호출 예시:

import { getData } from './api';

function DataComponent() {
  useEffect(() => {
    getData().then(response => {
      console.log(response.data);
    });
  }, []);

  return <div>Data Loaded</div>;
}

5. 재사용 가능한 유틸리티 함수

프로젝트 전반에 걸쳐 사용되는 공통 유틸리티 함수나 헬퍼 함수들을 따로 분리해 관리하는 것이 효율적입니다.

예시 코드:

// utils/format.js
export const formatCurrency = (value) => {
  return `$${value.toFixed(2)}`;
};

// 사용 예시
import { formatCurrency } from './utils/format';

const PriceDisplay = ({ price }) => {
  return <div>{formatCurrency(price)}</div>;
};

결론

재활용 가능한 코드를 작성하고 공통화 전략을 세우는 것은 React 프로젝트에서 필수적인 부분입니다. 이로 인해 유지보수가 쉬워지고, 코드의 중복을 최소화할 수 있으며, 개발 생산성이 크게 향상됩니다. 컴포넌트 재사용, 스타일링 재활용, 상태 관리, API 통신 재활용 등 다양한 방면에서 재사용 가능한 패턴을 적용해보세요.

728x90