08. 리액트(React)
2024-01-25(목)
사이드 프로젝트에 프론트엔드 투입이 되었는데 React를 사용해 프로젝트를 한 적이 없어 따로 공부를 하는 중인데
기록으로 남겨놓을려고 한다.
리액트(React)란?
페이스북에서 개발한 오픈 소스 자바스크립트 라이브러리로, 사용자 인터페이스(UI)를 만들기 위해 주로 활용된다.
리액트는 가상 돔(Virtual DOM) 기술을 기반으로 하고 있어서 효율적인 UI 업데이트를 가능하게 한다. 이러한 특징들이
리액트의 인기를 증가시키고 있다.
등장 배경
사용자 인터페이스를 보다 쉽게 관리하고 효율적으로 업데이트하기 위한 목적에서 비롯되었다.
기존의 프론트엔드 개발에서 UI를 동적으로 다루는 것은 복잡한 일이었는데, 리액트는 이를 간편화하고 개발자들이 유지보수를 더 쉽게 할 수 있도록 도와주었다.
특징
- 가상 돔(Virtual DOM):
리액트의 핵심 개념 중 하나로, 실제 돔(Document Object Model)과 동일한 구조를 가지지만 메모리 상에 존재하는
가상의 돔. UI 업데이트 시에 전체 돔을 다시 그리는 것이 아니라, 변경된 부분만 실제 돔에 적용하여 효율적인 렌더링을 가능케 합다. 이를 통해 성능 향상과 빠른 UI 업데이트를 달성할 수 있습니다. - 컴포넌트 기반 아키텍처:
리액트는 컴포넌트 기반 아키텍처를 채택하고 있다. 컴포넌트는 재사용 가능하며 독립적으로 관리할 수 있는
UI 조각을 나타낸다. 컴포넌트 기반으로 개발하면 코드의 재사용성이 높아지며, 유지보수가 용이. - JSX (JavaScript XML):
JSX는 자바스크립트의 확장 문법으로, 리액트에서 UI를 작성하기 위해 사용됨. XML과 유사한 구조로,
간결하면서도 가독성이 높은 코드를 작성할 수 있다. JSX 코드는 바벨(Babel)과 같은 도구를 사용하여 일반
자바스크립트 코드로 변환된다. - 단방향 데이터 바인딩:
단방향 데이터 바인딩을 지원하여 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달할 수 있다. 데이터의 흐름이 단일 방향으로 유지되어 예측 가능하며, 디버깅이 용이. - 생명주기 메서드(Lifecycle Methods):
컴포넌트의 생명주기에 따라 실행되는 메서드들이 있다. componentDidMount, componentDidUpdate, componentWillUnmount 등의 메서드를 활용하여 컴포넌트의 행위를 제어할 수 있다. - 상태 관리(State Management)와 프론트엔드 라이브러리/프레임워크와의 통합:
리액트는 상태를 관리하기 위해 내장된 state 객체를 제공. 상태의 변경은 UI를 다시 렌더링 하는 데 사용된다.
다른 상태 관리 라이브러리(예: Redux)와의 통합이 쉽고, 다양한 생태계와 호환성을 가지고 있다.
예제
1. 간단한 상태 관리 및 컴포넌트의 생명주기 메서드
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
// 초기 상태 설정
this.state = {
count: 0,
};
}
componentDidMount() {
console.log('컴포넌트가 마운트되었습니다.');
}
componentDidUpdate(prevProps, prevState) {
console.log('컴포넌트가 업데이트되었습니다.');
console.log('이전 상태:', prevState);
console.log('현재 상태:', this.state);
}
componentWillUnmount() {
console.log('컴포넌트가 언마운트되었습니다.');
}
handleIncrement = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<h2>카운터: {this.state.count}</h2>
<button onClick={this.handleIncrement}>증가</button>
</div>
);
}
}
export default Counter;
※ 간단한 카운터를 구현, Counter 클래스는 Component를 상속받아 구현되었고, 컴포넌트의 생명주기 메서드(componentDidMount, componentDidUpdate, componentWillUnmount)를 사용하여 로그를 출력.
2. 컴포넌트
import React from 'react';
import Counter from './Counter';
function App() {
return (
<div>
<h1>리액트 예제</h1>
<Counter />
</div>
);
}
export default App;
※ Counter 컴포넌트를 App 컴포넌트에서 불러와 사용하고 있다.
3. Redux: 상태 관리를 위한 라이브러리로, 리액트와 함께 많이 사용된다.
먼저, 프로젝트에 Redux를 설치.
npm install redux react-redux
상태 변경을 일으키는 작업은 액션을 통해 이뤄진다. 액션은 일종의 이벤트로, 상태를 변경하는 요청을 나타낸다.
액션 생성자는 액션을 생성하는 함수.
// actions.js
export const increment = () => {
return {
type: 'INCREMENT',
};
};
export const decrement = () => {
return {
type: 'DECREMENT',
};
};
리듀서(Reducer): 리듀서는 액션에 따라 상태를 어떻게 변경할지를 정의하는 함수이다.
// reducers.js
const counterReducer = (state = { count: 0 }, action) => {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 };
case 'DECREMENT':
return { count: state.count - 1 };
default:
return state;
}
};
export default counterReducer;
스토어(Store): 앱의 상태를 저장하고, 상태에 변화를 일으키는 액션을 받아 리듀서를 호출하여 상태를 업데이트.
// store.js
import { createStore } from 'redux';
import counterReducer from './reducers';
const store = createStore(counterReducer);
export default store;
컴포넌트에서 Redux 사용: 리액트 컴포넌트에서 Redux를 사용하려면 react-redux 라이브러리의 Provider 컴포넌트를 사용하여 앱을 감싸고, connect 함수를 사용하여 상태와 액션을 컴포넌트에 연결.
// CounterComponent.js
import React from 'react';
import { connect } from 'react-redux';
import { increment, decrement } from './actions';
const CounterComponent = ({ count, increment, decrement }) => {
return (
<div>
<h2>카운터: {count}</h2>
<button onClick={increment}>증가</button>
<button onClick={decrement}>감소</button>
</div>
);
};
const mapStateToProps = (state) => {
return {
count: state.count,
};
};
export default connect(mapStateToProps, { increment, decrement })(CounterComponent);
Redux를 사용하는 최상위 컴포넌트: 앱의 최상위 컴포넌트를 Provider로 감싸고, 스토어를 제공.
// App.js
import React from 'react';
import { Provider } from 'react-redux';
import CounterComponent from './CounterComponent';
import store from './store';
const App = () => {
return (
<Provider store={store}>
<div>
<h1>Redux 예제</h1>
<CounterComponent />
</div>
</Provider>
);
};
export default App;