5-1. 프로젝트 생성 및 리액트 라우터 / 리덕스 설정
프로젝트 생성
먼저 create-react-app
을 통하여 프로젝트를 생성하세요.
$ create-react-app heurm-client
핵심 라이브러리 설치
그리고, 해당 디렉토리로 이동하여 주요 모듈들을 설치하겠습니다.
$ yarn add react-router-dom react-redux redux redux-actions immutable styled-components open-color
NODE_PATH 적용
파일을 불러올 때 상대경로뿐만이 아닌 절대경로로도 파일을 불러 올 수 있도록 package.json 의 scripts
를 수정하세요.
package.json
"scripts": {
"start": "NODE_PATH=src react-scripts start",
"build": "NODE_PATH=src react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
값을 설정 한 다음, 개발서버를 실행하세요.
$ yarn start
.jsconfig.json 생성
절대 경로로 불러온 파일도, IDE 에서 자동완성이 제대로 되도록 .jsconfig.json 파일을 프로젝트 루트 디렉토리 만들어주겠습니다.
.jsconfig.json
{
"compilerOptions": {
"baseUrl": "./src"
}
}
디렉토리 만들기
이번 프로젝트의 디렉토리 구조는 다음과 같습니다:
- components: 프리젠테이셔널 컴포넌트들이 위치합니다
- containers: 컨테이너 컴포넌트들이 위치합니다
- lib: 프로젝트에서 필요한 함수들을 여기에 저장합니다
- pages: 라우트 관련 컴포넌트들이 위치합니다
- redux: 리덕스 관련 코드가 위치합니다
위 디렉토리들을 src 폴더 안에 미리 만들어주세요.
불필요한 파일 제거
다음 파일들을 제거하세요:
- App.css
- App.test.css
- logo.svg
pages 디렉토리에 라우트 전용 컴포넌트 준비하기
라우트에서 사용 할 컴포넌트들을 미리 만들겠습니다. Auth
컴포넌트와 Home
컴포넌트를 만들고, 내용에는 텍스트를 그대로 렌더링하세요.
pages/Auth.js
import React, { Component } from 'react';
class Auth extends Component {
render() {
return (
<div>
Auth
</div>
);
}
}
export default Auth;
pages/Home.js
import React, { Component } from 'react';
class Home extends Component {
render() {
return (
<div>
Home
</div>
);
}
}
export default Home;
그 다음엔, 라우트 인덱스를 만들어줍니다.
/pages/index.js
export { default as Home } from './Home';
export { default as Auth } from './Auth';
라우트 설정
라우트를 App 컴포넌트에서 정의를 하도록 하겠습니다. 기존의 내용을 다 비우고, 새로 컴포넌트를 만들어서 다음과 같이 라우트들을 정의하세요.
src/App.js
import React, { Component } from 'react';
import { Route } from 'react-router-dom';
import { Home, Auth } from 'pages';
class App extends Component {
render() {
return (
<div>
<Route exact path="/" component={Home}/>
<Route path="/auth" component={Auth}/>
</div>
);
}
}
export default App;
이 다음에는, Root 컴포넌트를 만들어서 BrowserRouter 를 통해 라우터를 구성하세요.
src/Root.js
import React from 'react';
import { BrowserRouter, Route } from 'react-router-dom';
import App from './App';
const Root = ({store}) => {
return (
<BrowserRouter>
<Route path="/" component={App}/>
</BrowserRouter>
);
};
export default Root;
props 로 리덕스 스토어를 받도록 설정하였습니다. 추후 index.js 에서 리덕스 스토어를 생성 한 후 Root 컴포넌트에 전달을 해주고, Provider 컴포넌트를 이 파일에서 설정하도록 하겠습니다.
이제 프로젝트 엔트리 파일 (src/index.js) 에서 App 대신에 Root 를 정의하세요.
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Root from './Root';
import registerServiceWorker from './registerServiceWorker';
import './index.css';
ReactDOM.render(<Root />, document.getElementById('root'));
registerServiceWorker();
이제 브라우저에서 http://localhost:3000/ 페이지와 http://localhost:3000/auth 페이지를 열어서 Home / Auth 텍스트가 제대로 보여지는지 확인하세요.
리덕스 설정
우리는 리덕스쪽 코드는 ducks 구조를 따르도록 하겠습니다. redux 디렉토리에 modules 디렉토리를 만들고, base.js 파일을 생성하세요. 이 모듈은, 프로젝트의 기반에 관련된 상태를 관리합니다. 예를들어서, 헤더의 렌더링 여부 혹은 유저메뉴 나타남 여부 등을 관리하게됩니다.
앞으로 유저관련 모듈과 회원인증 관련 모듈도 만들게 됥 텐데 이번 섹션에선 일단 base 모듈을 먼저 만들어두겠습니다.
src/redux/modules/base.js
import { Map } from 'immutable';
import { handleActions, createAction } from 'redux-actions';
const SET_HEADER_VISIBILITY = 'base/SET_HEADER_VISIBILITY'; // 헤더 렌더링 여부 설정
export const setHeaderVisibility = createAction(SET_HEADER_VISIBILITY); // visible
const initialState = Map({
header: Map({
visible: true
})
});
export default handleActions({
[SET_HEADER_VISIBILITY]: (state, action) => state.setIn(['header', 'visible'], action.payload)
}, initialState);
그 다음엔, 모듈을 위한 인덱스를 만들겠습니다. 이 인덱스파일에선 combineReducers
를 통해 모듈안의 리듀서들을 하나로 합쳐주겠습니다. 지금은 비록 모듈이 이미 하나밖에 없긴 하지만, 추후 모듈들을 더 만들 것 입니다. 인덱스파일에서 리듀서들을 하나로 합쳐서 내보내세요.
src/redux/modules/index.js
import { combineReducers } from 'redux';
import base from './base';
export default combineReducers({
base
});
이제, 스토어를 생성하는 함수를 만들어서 redux/configureStore.js 에 저장하도록 하겠습니다. 지금은 미들웨어와 react-hot-loader 를 아직 적용하지 않았으므로 다음과 같이 간단하게 코드를 작성하면 되며, 추후 다시 수정을 할 것 입니다.
src/redux/configureStore.js
import { createStore } from 'redux';
import modules from './modules';
// Todo: 미들웨어, react-hot-loader 적용
const configureStore = (initialState) => {
const store = createStore(modules, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
return store;
}
export default configureStore;
이제, 프로젝트 엔트리파일에서 스토어를 생성하고, Root 컴포넌트의 props 로 전달하겠습니다.
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Root from './Root';
import registerServiceWorker from './registerServiceWorker';
import './index.css';
import configureStore from 'redux/configureStore';
const store = configureStore();
ReactDOM.render(<Root store={store}/>, document.getElementById('root'));
registerServiceWorker();
그 다음엔 Root 컴포넌트를 열어서 Provider 를 최상위 컴포넌트로 설정하고 props 로 전달받은 store 를 넣으세요.
src/Root.js
import React from 'react';
import { BrowserRouter, Route } from 'react-router-dom';
import App from './App';
import { Provider } from 'react-redux';
const Root = ({store}) => {
return (
<Provider store={store}>
<BrowserRouter>
<Route path="/" component={App}/>
</BrowserRouter>
</Provider>
);
};
export default Root;
자, 이제 리액트 라우터와 리덕스의 설정이 완료되었습니다. 리덕스 개발자 도구를 열어서 상태가 잘 정의되었는지 확인하세요.