R2 기술 소개서

React로 개발한 웹 어드민 서비스 R2 프로젝트에 대한 설명입니다.
R2
1. 배경
2018년 6월에 캠페인 관리를 위한 Revenue가 만들어졌다. 이후 필요한 기능이 있을 때마다 짱짱 개발자들은 페이지를 개발했다(CAP, Admin). 나중에는 사용자가 각 페이지를 방문해야하는 불편한 상황이 발생했다. 한 페이지로 관리했으면 좋겠다는 의견이 나왔고, 9월부터 Revenue2(R2) 개발이 시작되었다.
2. 주요 기능
- 캠페인, 연동의 운영 및 관리
- 연동의 차단 및 블락
- 리포트, 정산을 위한 통계 자료 제공
3. 사용 기술
간단한 설명과 함께 R2의 주요 기술을 나열했다.
3.1. create-react-app
명령어 한 줄로 프로젝트 기본 구조, 모듈, package.json 스크립트 (run / build / test)를 만들어준다. R2 역시 이것으로 생성되었다.
eject
npm run eject
를 실행하면 손 쉽게 eject 할 수 있다(자유도 100%). 현재 R2는 eject하지 않고 플러그인을 사용하는 중이다. 이유는 다음과 같다.
-
- version control
- create-react-app(이하 cra)은 react를 실행하는데에 필요한 모든 모듈을 관리해준다. 예를 들어 cra가 webpack2를 적용했고, 우리도 적용하고 싶다면 cra의 버전만 업데이트하면 된다. eject한 상태라면 관련된 모든 모듈을 직접 업데이트 해야한다.
-
- package.json
- eject 후, 잠겨있던 모듈이 밖으로 나온다. 보이지 않았던 모듈의(babel, eslint, webpack) 정보를 package.json에서 볼 수 있다. 현재 프로젝트에 특수적으로 필요한 모듈을 직관적으로 알기 어렵다는 단점이 있다.
-
- extra configs, code
- 가장 먼저 눈에 띄는 부분이다. eject 후, script와 cofing 폴더 그리고 대략 10개의 파일이 생긴다. 그 파일들은 50~200줄의 코드로 되어있는데, 대부분의 경우 지원되지 않는 기능을 추가하기 위해 5줄정도의 코드를 추가한다.
-
- configure webpack, babel presets
- 위의 불편함을 감수하고 eject를 했다면, Webpack, Babel, ESLint 등등의 모든 것들을 제약없이 설정할 수 있는 장점이 있다.
3.2. redux
Flux의 데이터 흐름
Redux의 이해를 돕기 위해, Redux의 모티브인 Flux의 단방향 데이터 흐름을 이해하고자 한다.
- view에서 user가 interaction(event)을 발생한다.
- event가 정의된 action을 dispatcher로 전송한다.
- dispatcher는 데이터와 상태의 흐름을 관리하는 콜백 로직을 실행한다.
- 로직이 실행되면서 모든 action을 store로 전달한다.
- store는 action에 따라서 state를 업데이트한다.
- 업데이트 된 state에 따라 view를 그린다.
Redux의 데이터 흐름
Redux는 Flux를 모티브로 생성되었기 때문에 Flux인 듯 Flux아닌 Flux같은 요소가 있다. 차이점은 다음과 같다.
- dispatcher가 사라졌다.
- dispatcher의 빈 자리를 middleware가 채워준다. action은 middleware로 전달된다.
- middleware에서 비동기 로직 처리, api 호출 등의 역할을 한다.
- store는 로직이 없는 single object이다. 어떤 state로 바꿔야 할지 어떻게 알 수 있을까? reducer로 알 수 있다.
- middleware에서 reducer로 액션을 보내주면, state를 바꿔주는 순수 함수(pure function)를 사용한다.
- 새로운 state에 따라 view를 그린다.
3.3. redux-saga
Redux의 데이터 흐름 파트에서 언급된 middleware 중 한 가지이다. 비동기 작업을 한 번에 관리하는 것이 특징이다. 또, 서버통신 때 발생하는 side effect 처리, store에 도달 하기전 action을 핸들링 한다. action의 listner라고 생각할 수 있다. pure object로만 반환한다.
action listening snippet
1
2
3
4
5
6
function* watchUserEvent() {
while(true) {
const {rcvDataFromContainer} = yield take(ActionTypes.UserEventAction);
yield fork(apiName, rcvDataFromContainer);
}
}
Tip
- 필자는 react-saga의 real-world가 도움이 되었다.
- 여러 개의 saga를 사용할 경우
call
대신fork
를 사용해야한다. 왜냐하면fork
는 saga를 호출하고 다음 스텝으로 이동하도록 디자인되어있기 때문이다.call
은 saga가 완료될때까지 블락된다.
3.4. ant-design
알리바바가 개발한 디자인 컴포넌트다. 알투에 적용한 후기는 다음과 같다.
- 디자인이 깔끔하다.
- 커스터마이징이 편하다.
- 문서가 잘 되어있다.
- 깃헙 활동이 활발하다.
- eject없이 less를 적용(Advanced Guides) 할 때 react-app-rewired 모듈을 설치해야 했다.
3.5. biz-chart
ant-design이 개발한 ant-deign-pro에서 사용한 데이터 시각화 오픈소스이다. antvis(알리페이가 자회사인 Ant)의 G2와 React를 기반으로 만들어졌다. 아직 영어로 번역되지 않았기 때문에 문서 보는 것이 불편할 수 있다. 하지만 사용할 때 큰 지장은 없다.
3.6. travis
알투는 여러가지 방법의 배포를 시도했고, 지금은 travis를 사용중이다.
3.7. git-flow
git-flow
모듈을 사용중이다. develop과 master 브랜치는 직접 push하지 않고, feature/release/hotfix 기능을 사용하여 merge 하고있다.
4. 커뮤니케이션, 협업 방법
4.1. Slack
회사에서 전사적으로 슬랙을 사용중이기 때문에 대부분의 커뮤니케이션은 슬랙으로 한다.
4.2. Trello
- 개발자들의 이슈를 공유한다.
- 개발 상황을 공유한다.
- 프런트엔드, 백엔드의 개발 또는 수정사항을 요청한다.
4.3. Jira
- 사용자의 이슈를 공유한다.
- 알투를 사용하면서 필요하거나 개선하고 싶은 기능을 요청한다.
- 버그를 신고한다.
5. 폴더 구조
src
├── api : 서버에 데이터를 요청한다.
├── components : presentational 컴포넌트의 모음이다. container 컴포넌트에서 props로 데이터를 받고 보여주는 역할만 한다. 직접적인 로직은 실행하지 않는다.
├── constant : redux와 saga, container를 연결해주는 action을 정의한다.
├── containers : state를 관리하고(redux state 아님), 직접 개발한 함수와 서버에서 받은 데이터를 presentational 컴포넌트로 전달하고 렌더링한다. 이벤트가 발생하면 saga에 정의된 액션으로 전달한다.
├── reducers : redux의 state를 정의하고, 데이터가 들어오면 state의 값을 변경한다.
├── sagas : container 컴포넌트에서 전달받은 액션에 api를 매핑시킨다.
└── store : saga와 reducer를 적용한 redux store를 생성한다.
6. 참고 자료