리액트로 복잡한 테이블 구축하기, 리치 데이터 테이블을 위한 필터링, 페이징, 정렬 처리

리액트(React)는 사용자 인터페이스를 구축하기 위한 가장 인기 있는 라이브러리 중 하나입니다.
특히, 데이터를 시각화하는 데 있어 테이블을 구축하는 것은 사용자 경험을 향상시키는 중요한 요소입니다.
본 강좌에서는 리액트를 이용하여 복잡한 데이터를 관리하는 테이블을 구축하는 방법에 대해 살펴보겠습니다.
이 테이블은 필터링, 페이징, 정렬 기능을 포함하여, 사용자가 데이터를 효율적으로 탐색할 수 있도록 돕습니다.

1. 프로젝트 설정

리액트 프로젝트를 시작하기 위해서는 create-react-app을 사용하여 간단하게 설정할 수 있습니다.

npx create-react-app rich-data-table

프로젝트 디렉토리로 이동한 후 필요한 패키지를 설치합니다.

cd rich-data-table
npm install axios react-table

2. 데이터 준비

통상적으로 복잡한 데이터는 외부 API를 통해 불러옵니다.
이번 예제에서는 가상의 사용자 데이터를 JSON 형태로 이용하겠습니다.

const data = [
    { id: 1, name: 'John Doe', age: 28, email: 'john@example.com' },
    { id: 2, name: 'Jane Smith', age: 34, email: 'jane@example.com' },
    { id: 3, name: 'Mike Johnson', age: 45, email: 'mike@example.com' },
    // ... 추가 데이터
];

3. 테이블 컴포넌트 만들기

데이터 테이블을 만들기 위해 React Table 라이브러리를 사용합니다.
이 라이브러리는 매우 유연하고 편리한 API를 제공합니다.
다음은 기본적인 테이블 컴포넌트를 설정하는 코드입니다.

import React from 'react';
import { useTable, useFilters, usePagination, useSortBy } from 'react-table';

const DataTable = ({ columns, data }) => {
    const {
        getTableProps,
        getTableBodyProps,
        headerGroups,
        rows,
        prepareRow,
        state,
        setFilter,
        gotoPage,
        pageCount,
        canNextPage,
        canPreviousPage,
        nextPage,
        previousPage,
        page,
    } = useTable(
        {
            columns,
            data,
        },
        useFilters,
        useSortBy,
        usePagination
    );

    return (
        
setFilter('name', e.target.value)} placeholder="Filter by name" /> {headerGroups.map(headerGroup => ( {headerGroup.headers.map(column => ( ))} ))} {rows.map(row => { prepareRow(row); return ( {row.cells.map(cell => { return ; })} ); })}
{column.render('Header')} {column.isSorted ? column.isSortedDesc ? ' 🔽' : ' 🔼' : ''}
{cell.render('Cell')}
{' '} {' '} {' '}
); };

4. 컬럼 정의하기

테이블의 컬럼을 정의하여 데이터 구조에 맞게 렌더링합니다. 아래 코드를 보면, 테이블의 각 컬럼은 제목과 렌더링 방법을 정의하고 있습니다.

const columns = [
    {
        Header: 'ID',
        accessor: 'id', // accessor is the "key" in the data
    },
    {
        Header: 'Name',
        accessor: 'name',
    },
    {
        Header: 'Age',
        accessor: 'age',
    },
    {
        Header: 'Email',
        accessor: 'email',
    },
];

5. App 컴포넌트에 통합하기

마지막으로, 모든 것을 App 컴포넌트에 통합합니다.

import React from 'react';
import DataTable from './DataTable'; // DataTable 파일 경로에 따라 수정

function App() {
    const data = [/* JSON 데이터 */];
    const columns = [/* 컬럼 정의 */];

    return (
        

리치 데이터 테이블

); } export default App;

6. 결론

이 강좌에서는 리액트와 React Table 라이브러리를 사용하여 필터링, 페이징, 정렬 기능이 포함된 복잡한 데이터 테이블을 구축하는 방법에 대해 알아보았습니다.
이 같은 테이블은 대규모 데이터 세트를 효과적으로 관리하고 쉽게 탐색할 수 있도록 도와줍니다.
다음 단계로는 사용자 정의 스타일링, 더 복잡한 필터링, 다른 데이터 소스 통합 등을 시도해 보시기 바랍니다.

리액트는 강력하고 유연한 프레임워크이므로, 여러분의 다양한 요구 사항에 맞추어 확장할 수 있는 기능을 제공합니다.
이 강좌가 여러분의 리액트 개발에 도움이 되기를 바랍니다.

다양한 지도 API, Google Maps, Leaflet, Mapbox의 장단점 비교

웹 애플리케이션을 개발할 때 지도 기능은 사용자에게 매우 중요한 요소입니다. 다양한 지도 API가 존재하며, 각 API는 고유한 특징과 장단점을 가지고 있습니다. 이 글에서는 Google Maps, Leaflet 및 Mapbox 이 세 가지 주요 지도 API의 차이점을 비교하고 어떤 상황에서 각각의 API를 사용해야 하는지에 대해 탐구해보겠습니다.

1. 지도 API란?

지도 API(Application Programming Interface)는 개발자가 지도와 관련된 기능을 웹 애플리케이션에 통합할 수 있도록 하는 인터페이스입니다. 이러한 API를 통해 개발자는 위치 정보, 경로 탐색, 장소 검색 등의 다양한 기능을 쉽게 구현할 수 있습니다.

2. Google Maps API

2.1 개요

Google Maps API는 Google에서 제공하는 지도 서비스로, 매우 방대한 데이터와 다양한 기능을 제공합니다. 사용자 위치 기반 서비스, 경로 탐색, 장소 검색 및 거리 계산 등 여러 기능을 지원합니다.

2.2 장점

  • 풍부한 데이터: 전 세계의 방대한 지도 데이터를 제공, 장소 정보와 거리 데이터를 포함합니다.
  • 신뢰성: Google의 인프라를 기반으로 하여 안정적이고 빠른 성능을 보장합니다.
  • 상세한 커스터마이징: 마커, 경로 및 정보 창 등의 UI 요소를 커스터마이징 할 수 있습니다.
  • 장소 정보: POI(관심지점)에 대한 정보와 리뷰를 쉽게 조회할 수 있습니다.

2.3 단점

  • 비용: 일정량 이상의 요청에 대해 비용이 발생하며, 대규모 프로젝트에서는 비용이 부담이 될 수 있습니다.
  • 사용 약관: Google의 사용 약관이 엄격하여 상업적 용도에 제한이 있을 수 있습니다.

2.4 예제 코드

다음은 Google Maps API를 사용하여 간단한 지도를 생성하는 예제 코드입니다.

        <!DOCTYPE html>
        <html>
        <head>
            <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
            <style>
                #map {
                    height: 400px;
                    width: 100%;
                }
            </style>
        </head>
        <body>
            <div id="map"></div>
            <script>
                function initMap() {
                    var myLatLng = {lat: -25.363, lng: 131.044};
                    var map = new google.maps.Map(document.getElementById('map'), {
                        zoom: 4,
                        center: myLatLng
                    });
                    var marker = new google.maps.Marker({
                        position: myLatLng,
                        map: map,
                        title: 'Hello World!'
                    });
                }
                window.onload = initMap;
            </script>
        </body>
        </html>
        

3. Leaflet

3.1 개요

Leaflet은 오픈 소스 JavaScript 라이브러리로, 주로 모바일 친화적인 인터랙티브한 지도를 만드는 데 사용됩니다. 간단하고 직관적인 API를 제공합니다.

3.2 장점

  • 경량화: 비교적 작은 파일 크기로 빠른 로딩 속도를 자랑합니다.
  • 오픈 소스: 무료로 사용 가능하며, 커뮤니티에 의해 지속적으로 발전하고 있습니다.
  • 사용 용이성: 쉽게 배울 수 있는 API로, 빠르게 시작할 수 있습니다.

3.3 단점

  • 데이터 품질: Google Maps에 비해 장소 정보 및 지도 데이터의 정확성이 떨어질 수 있습니다.
  • 기능 제한: 고급 기능이 필요할 경우 추가적인 플러그인을 사용해야 할 수도 있습니다.

3.4 예제 코드

다음은 Leaflet을 사용하여 지도를 생성하는 예제 코드입니다.

        <!DOCTYPE html>
        <html>
        <head>
            <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
            <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
            <style>
                #map {
                    height: 400px;
                    width: 100%;
                }
            </style>
        </head>
        <body>
            <div id="map"></div>
            <script>
                var map = L.map('map').setView([-25.363, 131.044], 4);
                L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                    maxZoom: 19,
                }).addTo(map);
                var marker = L.marker([-25.363, 131.044]).addTo(map)
                    .bindPopup('Hello World!')
                    .openPopup();
            </script>
        </body>
        </html>
        

4. Mapbox

4.1 개요

Mapbox는 사용자 정의 가능한 인터랙티브한 맵을 만들 수 있는 플랫폼으로, 주로 데이터 시각화와 정교한 사용자 경험 요구에 적합합니다.

4.2 장점

  • 커스터마이징: 디자인을 원하는 대로 변경할 수 있으며, CSS 스타일을 적용할 수 있습니다.
  • 데이터 시각화: 복잡한 데이터 시각화에 강력한 도구를 제공합니다.
  • Mapbox Studio: 사용자 친화적인 인터페이스를 제공하여 지도를 쉽게 디자인하고 관리할 수 있습니다.

4.3 단점

  • 비용: 기본 사용은 무료지만, 대규모 사용 시 요금이 발행될 수 있습니다.
  • 개발 문서: 학습 곡선이 있으며, 문서가 다소 복잡할 수 있습니다.

4.4 예제 코드

다음은 Mapbox를 사용하여 지도를 생성하는 예제 코드입니다.

        <!DOCTYPE html>
        <html>
        <head>
            <link href="https://api.mapbox.com/mapbox-gl-js/v2.6.1/mapbox-gl.css" rel="stylesheet" />
            <script src="https://api.mapbox.com/mapbox-gl-js/v2.6.1/mapbox-gl.js"></script>
            <style>
                #map {
                    height: 400px;
                    width: 100%;
                }
            </style>
        </head>
        <body>
            <div id="map"></div>
            <script>
                mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';
                const map = new mapboxgl.Map({
                    container: 'map',
                    style: 'mapbox://styles/mapbox/streets-v11',
                    center: [131.044, -25.363],
                    zoom: 4
                });
                const marker = new mapboxgl.Marker()
                    .setLngLat([131.044, -25.363])
                    .setPopup(new mapboxgl.Popup().setText('Hello World!'))
                    .addTo(map);
            </script>
        </body>
        </html>
        

5. 각 API의 선택 기준

지도 API를 선택할 때, 특정 조건과 요구 사항에 따라 선택 기준이 달라질 수 있습니다. 다음은 고려해야 할 주요 요소입니다.

  • 비용: 프로젝트의 예산에 따라 무료 API 또는 유료 API를 선택할 수 있습니다.
  • 기능: 필요한 기능 및 데이터 세트가 어떤 것인지 평가해야 합니다.
  • 디자인: 사용자 인터페이스와 디자인 요구 사항에 따라 맞춤형 지도가 필요한 경우 Mapbox와 같은 옵션이 좋습니다.
  • 데이터 정확성: 많이 사용되는 장소 정보 및 경로 정보를 우선시해야 하는 경우 Google Maps가 유리할 수 있습니다.
  • 사용 용이성: 개발자 경험에 따라 쉬운 API를 선호하는 경우 Leaflet이 적합할 수 있습니다.

6. 결론

Google Maps, Leaflet, Mapbox는 각각의 장단점이 있으며, 프로젝트의 요구 사항과 개발자의 편의성에 따라 적합한 API를 선택해야 합니다. 먼저 필요 기능을 명확히 하고, 그에 맞는 옵션을 선택함으로써 효과적인 지도 기능을 웹 애플리케이션에 통합할 수 있습니다. 최종 선택은 요구 사항, 예산 및 개발 환경 등을 종합적으로 고려하여 신중히 결정해야 합니다.

React Router로 페이지 이동 관리하기, 페이지 보호와 인증 관련 라우팅

리액트 애플리케이션에서 사용자가 페이지를 이동할 수 있도록 관리하는 것은 매우 중요합니다. React Router는 이러한 페이지 이동을 간편하게 구현할 수 있게 해주는 라이브러리입니다. 이를 통해 SPA(Single Page Application) 구현 시 복잡한 URL 경로를 쉽게 관리하고, 네비게이션을 수행할 수 있습니다. 이 글에서는 React Router의 기본 개념, 설치 방법, 라우팅 활용, 그리고 페이지 보호 및 인증 관련 라우팅 구현에 대해서 자세히 알아보겠습니다.

1. React Router란?

React Router는 리액트 애플리케이션에서 유연하게 라우팅을 관리할 수 있도록 도와주는 라이브러리입니다. 이를 통해 사용자는 URL에 따라 다양한 컴포넌트를 동적으로 렌더링할 수 있습니다. React Router를 사용하여 각각의 URL 경로에 컴포넌트를 매핑하고, SPA에서도 전환 시 페이지가 새로고침되지 않은 것처럼 매끄러운 사용자 경험을 제공합니다.

2. React Router 설치하기

React Router를 설치하기 위해 npm 또는 yarn을 사용할 수 있습니다. 아래와 같은 명령어로 설치할 수 있습니다:

npm install react-router-dom

또는

yarn add react-router-dom

3. React Router 기본 사용법

React Router의 기본적인 사용 방법을 살펴보겠습니다. 먼저, 기본적인 세팅을 위해 App.js 파일을 수정합니다.

3.1. 기본적인 라우트 구성

아래는 간단한 라우팅 예제입니다:


import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';

const Home = () => <h2>홈 페이지</h2>;
const About = () => <h2>소개 페이지</h2>;
const NotFound = () => <h2>404 페이지 없음</h2>;

const App = () => {
    return (
        <Router>
            <nav>
                <ul>
                    <li><Link to="/">홈</Link></li>
                    <li><Link to="/about">소개</Link></li>
                </ul>
            </nav>
            <Switch>
                <Route path="/" exact component={Home} />
                <Route path="/about" component={About} />
                <Route component={NotFound} />
            </Switch>
        </Router>
    );
};

export default App;

위 예제에서 BrowserRouter는 라우터의 최상위 컴포넌트로, Route 컴포넌트를 통해 각 경로와 컴포넌트를 매핑합니다. Switch는 하나의 경로에 대해서만 렌더링할 수 있도록 해줍니다.

3.2. URL 매개변수 사용하기

URL에 매개변수를 추가하여 동적인 라우팅을 구현할 수 있습니다. 다음은 향상된 예제입니다:


const User = ({ match }) => {
    return <h2>유저 ID: {match.params.id}</h2>;
};

const App = () => {
    return (
        <Router>
            <Switch>
                <Route path="/user/:id" component={User} />
            </Switch>
        </Router>
    );
};

위와 같이 path="/user/:id"를 설정하면 /user/1와 같은 URL에서 ID를 추출하여 해당 사용자 정보를 표시할 수 있습니다.

4. 페이지 보호 및 인증 관련 라우팅

일부 페이지는 인증된 사용자만 접근할 수 있도록 제한할 때가 많습니다. 이때는 인증 상태를 관리하고, 사용자의 권한에 따라 라우팅을 제어하는 것이 중요합니다. 다음은 페이지 보호를 구현하는 방법입니다.

4.1. 인증 상태 관리하기

우선, 간단한 인증 상태를 관리하기 위해 React의 상태 관리를 사용할 수 있습니다. 아래의 예는 인증과 로그아웃 함수를 구현하여 상태를 관리하는 방법입니다:


import React, { useState } from 'react';
import { BrowserRouter as Router, Route, Switch, Redirect, Link } from 'react-router-dom';

const AuthContext = React.createContext();

const AuthProvider = ({ children }) => {
    const [isAuthenticated, setIsAuthenticated] = useState(false);

    const login = () => setIsAuthenticated(true);
    const logout = () => setIsAuthenticated(false);

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

4.2. 인증된 사용자를 위한 Route 컴포넌트 생성하기

이제 인증된 사용자만 접근할 수 있는 라우트를 구현할 차례입니다. PrivateRoute라는 컴포넌트를 생성하여 인증 상태에 따라 라우팅을 제어합니다:


const PrivateRoute = ({ component: Component, ...rest }) => {
    const { isAuthenticated } = React.useContext(AuthContext);

    return (
        <Route {...rest} render={props => 
            isAuthenticated ? <Component {...props} /> : <Redirect to="/" />
        } />
    );
};

4.3. 전체 라우트 구성

이제 위의 모든 요소를 조합하여 전체 애플리케이션 라우팅을 구성할 수 있습니다:


const Dashboard = () => <h2>대시보드</h2>;

const App = () => {
    return (
        <AuthProvider>
            <Router>
                <nav>
                    <ul>
                        <li><Link to="/">홈</Link></li>
                        <li><Link to="/dashboard">대시보드</Link></li>
                    </ul>
                </nav>
                <Switch>
                    <Route path="/" exact component={Home} />
                    <PrivateRoute path="/dashboard" component={Dashboard} />
                </Switch>
            </Router>
        </AuthProvider>
    );
};

위 코드에서 사용자가 대시보드 페이지를 요청할 경우, 인증되지 않은 상태라면 홈으로 리다이렉트됩니다.

4.4. 로그인 및 로그아웃 구현하기

이제 로그인 기능을 구현하여 사용자가 인증을 받을 수 있도록 합니다:


const Login = () => {
    const { login } = React.useContext(AuthContext);
    
    const handleLogin = () => {
        login();
    };
    
    return <button onClick={handleLogin}>로그인</button>;
};

4.5. 전체 애플리케이션

이제 최종적으로 모든 컴포넌트를 합친 전체 애플리케이션은 다음과 같습니다:


const App = () => {
    return (
        <AuthProvider>
            <Router>
                <nav>
                    <ul>
                        <li><Link to="/">홈</Link></li>
                        <li><Link to="/dashboard">대시보드</Link></li>
                        <li><Link to="/login">로그인</Link></li>
                    </ul>
                </nav>
                <Switch>
                    <Route path="/" exact component={Home} />
                    <Route path="/login" component={Login} />
                    <PrivateRoute path="/dashboard" component={Dashboard} />
                </Switch>
            <Router>
        </AuthProvider>
    );
};

5. 결론

React Router는 SPA 애플리케이션에서 페이지 전환을 관리하는 강력한 도구입니다. 페이지 이동을 용이하게 하고, 조건부 렌더링을 통해 인증 및 권한 관리 기능까지 제공할 수 있습니다. 이번 글을 통해 기본적인 라우팅에서 페이지 보호 및 인증 라우팅까지 다양한 기능을 구현하는 방법을 배웠습니다. 이러한 내용은 실제 프로젝트에서도 매우 유용하게 적용될 수 있으니, 직접 실습해 보시기를 권장합니다.

CSS와 스타일링, CSS 모듈을 이용한 컴포넌트 스타일링

리액트(React)는 컴포넌트 기반의 라이브러리로, 웹 애플리케이션을 효율적으로 개발할 수 있게 도와줍니다. 이러한 컴포넌트 기반 구조 덕분에 재사용성과 유지보수성이 뛰어난 애플리케이션을 만들 수 있습니다. 하지만, 컴포넌트를 스타일링하는 것은 종종 복잡한 문제로 여겨집니다. 다양한 스타일링 방법 중에서 특히 CSS 모듈(CSS Modules)을 이용한 스타일링은 컴포넌트에 고유한 스타일을 부여할 수 있는 효과적인 방법입니다. 이 글에서는 CSS와 스타일링에 대해 설명하고, CSS 모듈을 활용한 리액트 컴포넌트 스타일링에 대해 심층적으로 탐구해 보겠습니다.

CSS의 기초 이해하기

CSS(카스케이딩 스타일 시트)는 HTML 문서의 프레젠테이션을 정의합니다. 기본적으로 CSS는 선택자(selector)와 속성(property)으로 구성되어 있습니다. 선택자는 스타일을 적용할 HTML 요소를 지정하고, 속성은 적용할 스타일의 유형을 정의합니다. 예를 들어:

p {
    color: blue;
    font-size: 16px;
}

위의 코드에서 ‘p’는 선택자이고, ‘color’와 ‘font-size’는 속성입니다. CSS는 HTML 문서에 링크되거나 내장될 수 있으며, 다양한 CSS 기법을 통해 스타일을 적용할 수 있습니다.

CSS 모듈이란?

CSS 모듈은 CSS 파일을 모듈화하여 각 컴포넌트에 독립적인 스타일을 정의할 수 있는 방법입니다. 전통적인 CSS 방식에서는 클래스 이름의 충돌과 전역 스타일이 문제가 될 수 있었으나, CSS 모듈을 사용하면 이러한 문제를 해결할 수 있습니다.

CSS 모듈은 기본적으로 다음과 같은 장점이 있습니다:

  • 스타일 캡슐화: 각 컴포넌트의 스타일이 서로 격리되어 있어서 이름 충돌을 방지할 수 있습니다.
  • 재사용성: 컴포넌트에 특정된 스타일을 쉽게 재사용할 수 있습니다.
  • 유지보수 용이성: 스타일의 변경이 다른 컴포넌트에 영향을 미치지 않기 때문에 유지보수가 용이합니다.

CSS 모듈 설정하기

리액트 프로젝트에서 CSS 모듈을 사용하려면, 기본적으로 설정이 필요합니다. Create React App으로 프로젝트를 생성하면, CSS 모듈이 기본적으로 지원됩니다. CSS 모듈을 사용하기 위해서는 파일 이름의 뒤에 ‘.module.css’를 붙여야 합니다. 다음은 CSS 모듈을 설정하는 방법입니다:

// ExampleComponent.module.css
.container {
    background-color: lightgray;
    border: 1px solid gray;
    padding: 16px;
}
.title {
    color: navy;
    font-size: 24px;
}

이제 리액트 컴포넌트에서 이 CSS 모듈을 사용할 수 있습니다:

// ExampleComponent.js
import React from 'react';
import styles from './ExampleComponent.module.css';

const ExampleComponent = () => {
    return (
        

Hello, CSS Modules!

); }; export default ExampleComponent;

CSS 모듈을 이용한 스타일링

이제 CSS 모듈을 적용하여 리액트 컴포넌트를 스타일링하는 예제를 살펴보겠습니다. 먼저, 간단한 리액트 애플리케이션을 위해 CSS 모듈 파일과 컴포넌트를 생성합니다.

1. CSS 모듈 파일 생성

// styles.module.css
.button {
    background-color: blue;
    color: white;
    padding: 10px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    transition: background-color 0.3s ease;
}

.button:hover {
    background-color: darkblue;
}

2. 리액트 컴포넌트 생성

// Button.js
import React from 'react';
import styles from './styles.module.css';

const Button = ({ label, onClick }) => {
    return (
        
    );
};

export default Button;

위의 Button 컴포넌트는 CSS 모듈을 사용하여 버튼에 스타일을 적용합니다. 버튼은 기본적으로 파란색 배경을 가지며, 마우스를 올렸을 때 다크 블루 색으로 변합니다.

3. Button 컴포넌트 사용하기

이제 Button 컴포넌트를 다른 컴포넌트에서 사용할 수 있습니다:

// App.js
import React from 'react';
import Button from './Button';

const App = () => {
    return (
        

리액트 CSS 모듈 예제

); }; export default App;

스타일 동적 부여하기

리액트의 강력한 기능 중 하나는 상태(state)를 사용하여 동적으로 스타일을 변경할 수 있다는 점입니다. CSS 모듈은 조건부 렌더링과 결합하여 보다 풍부한 인터페이스를 만들어 줍니다. 다음 예제는 버튼이 클릭될 때 스타일을 변경하는 방법을 보여줍니다:

// ToggleButton.js
import React, { useState } from 'react';
import styles from './styles.module.css';

const ToggleButton = () => {
    const [isClicked, setIsClicked] = useState(false);

    const handleClick = () => {
        setIsClicked(!isClicked);
    };

    return (
        
    );
};

export default ToggleButton;

이 예제에서 버튼이 클릭될 때마다 isClicked 상태가 변경되고, 이 상태에 따라 버튼의 스타일이 바뀝니다. styles.active는 버튼을 클릭했을 때 추가하는 스타일입니다.

검증 및 디버깅

스타일링과 관련된 문제는 종종 발생할 수 있습니다. CSS 모듈을 사용할 때 발생할 수 있는 일반적인 문제는 클래스 이름이 잘못 매핑되는 것입니다. 이를 확인하기 위해서는 개발자 도구를 열어 제공된 클래스 이름을 검토해야 합니다. CSS 모듈이 동작하는지 확인하기 위해 불필요한 클래스가 남아 있는지, 원하는 대로 스타일이 적용되었는지 확인합니다.

결론

CSS 모듈을 사용하면 리액트 애플리케이션의 스타일링을 보다 효율적으로 진행할 수 있습니다. 각 컴포넌트에 고유한 스타일을 부여하여 충돌을 방지하고, 유지보수를 쉽게 합니다. 이 글에서는 CSS 모듈의 기본 개념부터 시작하여 기본적인 설정과 동적 스타일링 방법까지 살펴보았습니다. 리액트 개발을 진행하면서 CSS 모듈을 활용하면 더욱 세련되고 깔끔한 UI를 구현할 수 있습니다. 앞으로의 프로젝트에서 CSS 모듈을 적극 활용해 보세요!

고급 상태 관리 Redux 사용하기, Redux Toolkit을 활용한 효율적인 코드 작성

현대 웹 애플리케이션에서 상태 관리는 필수적인 요소입니다. 특히 대규모 애플리케이션에서는 상태 관리 라이브러리를 사용하지 않으면 복잡한 상태를 일관되게 유지하기 어려워집니다. Redux는 이러한 문제를 해결하기 위해 널리 사용되는 상태 관리 라이브러리 중 하나입니다. 이번 글에서는 Redux의 기본 개념과 Redux Toolkit을 사용해 효율적으로 상태 관리 코드를 작성하는 방법에 대해 설명하겠습니다.

1. Redux란 무엇인가?

Redux는 JavaScript 애플리케이션의 상태를 효율적으로 관리하기 위한 라이브러리입니다. Redux의 핵심 아이디어는 애플리케이션의 전체 상태를 중앙 집중식 저장소(Store)에 보관하고, 상태를 변경하는 모든 작업은 Action을 통해서만 이루어진다는 것입니다. Redux는 다음과 같은 세 가지 기본 원칙을 따릅니다:

  • 단일 진실의 원천(Single Source of Truth): 애플리케이션의 상태는 오직 하나의 스토어에만 존재합니다.
  • 상태는 읽기 전용(Read-Only): 상태는 직접 수정할 수 없으며, 상태 변경을 위해서는 액션을 발행해야 합니다.
  • 변경은 순수 함수(Pure Functions)를 통해 이루어짐: 상태 변경은 리듀서라는 순수 함수를 사용하여 수행됩니다.

2. Redux의 핵심 개념

2.1 Store

Store는 애플리케이션의 상태를 저장하는 객체입니다. Store는 상태를 조회하거나, 액션을 디스패치하고, 리스너를 등록하여 상태 변경을 알림 받을 수 있는 메서드를 제공합니다.

2.2 Action

Action은 상태 변화의 의도를 나타내는 객체입니다. Action 객체는 ‘type’ 속성과 (필요시) ‘payload’를 포함하여 만들어집니다. 예를 들어, 사용자 정보를 업데이트 하는 액션은 다음과 같을 수 있습니다:

const updateUserAction = {
        type: 'UPDATE_USER',
        payload: { name: 'John', age: 30 },
    };

2.3 Reducer

Reducer는 action의 type에 따라 새로운 상태를 반환하는 순수 함수입니다. 상태를 어떻게 변경할지를 결정합니다. 아래는 사용자 정보를 관리하는 간단한 리듀서입니다:

const userReducer = (state = { name: '', age: 0 }, action) => {
        switch (action.type) {
            case 'UPDATE_USER':
                return {
                    ...state,
                    ...action.payload,
                };
            default:
                return state;
        }
    };

3. Redux Toolkit 소개

Redux Toolkit은 Redux 애플리케이션을 더 쉽게 설정하고 작성할 수 있도록 돕기 위해 만들어진 공식 툴킷입니다. Redux Toolkit을 사용하면 보일러플레이트 코드를 줄이고, 더 직관적인 API를 사용할 수 있습니다. Redux Toolkit을 사용하면 다음과 같은 작업을 쉽게 수행할 수 있습니다:

  • 상태, 리듀서, 액션을 간단하게 정의할 수 있는 createSlice를 제공
  • 비동기 로직을 처리하기 위한 createAsyncThunk를 제공
  • 스프레드 연산자를 사용하여 상태를 업데이트 할 필요 없이 전체 상태를 쉽게 관리 할 수 있는 configureStore를 제공

4. Redux Toolkit 설정하기

Redux Toolkit을 사용하여 React 애플리케이션에 Redux를 설정하는 방법을 살펴보겠습니다. 아래 단계에 따라 진행합니다:

4.1 의존성 설치

우선, Redux Toolkit과 React-Redux를 설치해야 합니다:

npm install @reduxjs/toolkit react-redux

4.2 Slice 생성하기

다음으로, createSlice를 사용하여 slice를 생성합니다. 아래 예시는 ‘user’ slice를 생성하는 방법입니다:

import { createSlice } from '@reduxjs/toolkit';

const userSlice = createSlice({
    name: 'user',
    initialState: { name: '', age: 0 },
    reducers: {
        updateUser: (state, action) => {
            state.name = action.payload.name;
            state.age = action.payload.age;
        },
    },
});

export const { updateUser } = userSlice.actions;
export default userSlice.reducer;

4.3 Store 설정하기

Slice를 생성한 후, 이를 포함하는 store를 설정합니다:

import { configureStore } from '@reduxjs/toolkit';
import userReducer from './userSlice';

const store = configureStore({
    reducer: {
        user: userReducer,
    },
});

export default store;

5. React 컴포넌트와 Redux 연결하기

Redux store를 React 컴포넌트와 연결하기 위해 Provider를 사용합니다. 다음 예제는 Redux 상태를 사용하여 사용자 정보를 표시하는 방법을 보여줍니다:

import React from 'react';
import { Provider, useSelector, useDispatch } from 'react-redux';
import store, { updateUser } from './store';

const UserComponent = () => {
    const user = useSelector((state) => state.user);
    const dispatch = useDispatch();

    const handleChangeUser = () => {
        dispatch(updateUser({ name: 'Jane', age: 25 }));
    };

    return (
        

User Info:

Name: {user.name}

Age: {user.age}

); }; const App = () => ( ); export default App;

6. 비동기 작업 처리하기

Redux Toolkit의 createAsyncThunk를 사용하여 비동기 작업을 처리할 수 있습니다. 아래 예제는 데이터를 비동기적으로 가져오는 예제입니다:

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';

export const fetchUserData = createAsyncThunk('user/fetchUserData', async () => {
    const response = await fetch('https://api.example.com/user');
    return response.json();
});

const userSlice = createSlice({
    name: 'user',
    initialState: { name: '', age: 0, loading: false },
    reducers: {},
    extraReducers: (builder) => {
        builder
            .addCase(fetchUserData.pending, (state) => {
                state.loading = true;
            })
            .addCase(fetchUserData.fulfilled, (state, action) => {
                state.loading = false;
                state.name = action.payload.name;
                state.age = action.payload.age;
            });
    },
});

export default userSlice.reducer;

7. Redux DevTools

Redux DevTools는 애플리케이션의 상태 변경을 추적하고 디버깅하는 데 유용한 도구입니다. Redux Toolkit을 사용할 때 DevTools를 쉽게 설정할 수 있습니다:

const store = configureStore({
    reducer: {
        user: userReducer,
    },
    // Enable Redux DevTools just by adding this line
    devTools: process.env.NODE_ENV !== 'production',
});

8. 결론

Redux와 Redux Toolkit을 사용하면 복잡한 상태 관리를 보다 유연하게 처리할 수 있으며, 명확하고 효율적인 코드를 작성할 수 있습니다. 특히, Redux Toolkit의 도구들을 활용하면 보일러플레이트 코드를 줄이고, 코드 유지보수가 쉬워집니다. 이러한 도구들을 활용해 보며 더 나은 React 애플리케이션을 만들어 보십시오.