버대리 React 개발기
안녕하세요 버즈니에서 프론트엔드 개발을 하고 있는 에반입니다. 올해가 되면서 회사가 주 40시간 근무 할당제가 되면서(버즈니 좋아요) 직원들의 출,퇴근 관리 시스템이 필요하게 되어 사내 토이프로젝트 형식으로 사내 근태 관리 시스템을 만들게 되어 그 개발기를 한번 적어보고자 합니다.
개발 스택?
처음 프로젝트를 시작하게되면서 React는 무조건 사용해야겠다고 생각했습니다. 현재 서비스하고 있는 홈쇼핑모아에서는 사실상 적용하기에 무리가 있었고 백오피스 관리자쪽에서만 작년부터 조금씩 공부하여 일부 적용해보는 상태였는데 마침 이 프로젝트가 똭 나타나면서 그동안 공부했던 내용을 써먹어보자 생각하게 되면서 결정하게 되었습니다.
프로젝트는 직원들이 자신의 출근 및 퇴근,외출과같은 액션을 수행할수있는 Client, 인사관리자가 직원들의 출근기록을 볼 수 있고 수정 및 편집이 가능한 CMS, 그리고 이 모든 행동들을 기록하고 볼 수있도록 해주는 API 세분류로 나누어서 개발을 진행하게 되었습니다.
결정된 프로젝트의 개발스택은 이렇습니다. Client - React, Typescript, Webpack, ES6 CMS - React, Redux, Webpack, ES6 API - Flask…어..음..
어떤게 필요한가?
먼저 필요로 하는게 무엇인지를 알고자 인사담당자에게 필요로하는 기능을 최대한 상세히 물었습니다.
- 버즈니 구성원이 출근/퇴근/외출/복귀와 같은 액션을 할 수 있어야 한다.
- 클라이언트의 대시보드에는 해당 직원의 오늘 일한 시간, 주간 일한 시간을 볼 수있어야 한다.
- 클라이언트의 페이지에서 해당 직원의 출근시간을 볼 수 있어야 한다.
- 클라이언트 페이지에서 내 지각내역, 야근내역등을 확인할 수 있어야한다.
이렇게 필요로하는 기능을 큼지막하게 물어본 후에 대충 어떤 모양이 좋을지 레이아웃을 짜고 디자이너의 손을 거쳐 이런 페이지가 나오게 되더군요 짜잔!
본격 React로 개발(삽질) 시작하기
React로 개발하게 되면서 국내의 개발 블로그들의 도입기나 React강좌를 많이 보게 되었는데 거의 대부분(한 90%?)이 추천하는 글이 React Docs의 Thinking in React 라는 글이었습니다. 저도 마찬가지로 React 페이지를 안되는 영어로 한번 정독하면서 보게 되었고 다른 블로그에서 강조하게되면서 다시 한번더 자세히 내용을 들여다 볼 수 있었습니다.
요는 리액트처럼 생각하라는 건데 기존의 개발해왔던 방식을 생각해 보자면(제방식입니다..) 먼저, 1) 전체적인 HTML 레이아웃을 작성한다.(CSS 작업 포함) 2) Javascript와 Jquery를 이용하여 페이지에 필요한 Data를 세팅해준다. 3) 페이지에서 일어나는 Action(Event?)에 대한 Listener함수를 만들어 jquery를 활용하여 적절하게 액션에 맞는 DOM조작을 해준다.
이렇게 3단계로 분류하여 보통 Frontend를 개발하는게 내 기존방식이었다면,
React같은경우는, 1) 화면을 작은 컴포넌트 단위로 나누기 2) Prop를 통한 단방향의 정적 버전 만들기 3) 작은 State부터시작해 전체 State의 적용 4) 역방향 데이터 흐름 추가
의 4단계방식으로의 개발 방식을 말해줍니다. 사실 사전 준비로 목업 데이터를 준비하라는 말이 있는데, 지금 하고있는 프로젝트가 딱히 목업용 데이터를 만들정도의 규모는 아니었기에 그냥 진행했습니다.
Step1. 화면을 작은 컴포넌트 단위로 나누기
역시 남들이 그러하듯 먼저 그림을보고 큰 화면에서부터 작은 단위까지 최대한 나눌수 있는 만큼 나누는 작업을 먼저 진행하였습니다. 그리고 나서 큰 기능으로 나뉘는 부분은 Container로 따로 만들어 두었습니다.
그냥 디자인된 화면만 봤을땐 간단하네라는 생각이 들었는데 막상 나누고 보니 꽤 많았습니다.
Step2. Prop을 통한 단방향의 정적 버전 만들기
화면을 컴포넌트 단위로 쪼개고 나서 해야할 일은 바로 부모 컴포넌트로부터 해서 자식에게로 데이터를 넘겨주는 것입니다. (부모에서 자식으로만 데이터를 전달 하기 때문에 단방향입니다.) 이 과정을 Prop값을 넘겨준다고 하는데 예를 들자면, 위의 화면을 봤을 때 ‘임근화 정상출근’이라는 데이터가 오려면 서버에서 이 사람이 제대로 출근했는가를 판단해서 데이터를 API형태로 전달해주게 됩니다. 이런 데이터를 해당 컴포넌트(화면상 Status컴포넌트)에서 호출해서 가져오는 방법도 있겠지만 그렇게 되면 View에만 집중하던 Component의 영향이 Data쪽에도 신경쓰게되면서 복잡해지기에 보통은 상위에서 데이터를 처리한 후에 필요한 자식 Component로 Prop를 통해 전달하게 됩니다. 저는 MainContainer라는 Container를 하나 만들어서 API로 받는 데이터를 입맛에 맞도록 가공한 후 Prop으로 전달하는 방법을 썼습니다.
이전에 React로 개발했을때 가장 많이 겪었던 문제중 하나가 Props로 받은 데이터값을 착각해 나오는 TypeError였습니다. 이번에 그런 문제를 방지하고자 Typescript를 도입해봤는데 처음 interface를 미리 작성할때는 굉장히 귀찮고 이걸 왜쓰지라는 생각을 했었습니다. 그리고 그 이후에 cms버전을 할때는 redux를 사용하면서 Typescript랑 같이 사용하기가 너무 복잡하여 제외하고 개발했었는데 그때서야 왜 Typescript가 좋은지 체감이 되고 확실히 타입체킹만으로도 오류가 많이 발생 안하는것을 느낄수 있었습니다. 따로 깊게 Typescript를 공부해보거나 다뤄보지는 않았지만 이런 에러의 방지목적만으로도Typescript로의 개발선택은 좋은 것 같습니다.
Step3. 작은 State부터 시작해 전체 State를 적용하기
Component내에서 사용될 데이터를 저장하거나 데이터가 이벤트나 액션에 따라 바뀔때 이러한 상태를 state라는 곳에 저장하고 변경하고 갱신하도록 합니다. 저는 props가 부모로부터 데이터를 받는거라면 state는 받은데이터 또는 생성된 데이터를 보관하는 거라고 생각했습니다. 버대리의 경우 액션이나 이벤트가 많지않아서 거의 대부분은 props로 받은 값을 보여주기만 하면되는 구조입니다. 따라서, 원래는 가장 작은 단위의 Component부터 State가 필요한가를 보고 작성하면서 가장 최상위까지 State를 적용하라고 되어있지만 실제로 State를 작성한 부분은 3~4군데 밖에 되지 않기에 저같은 경우는 그냥 필요한 부분만 State를 사용했습니다.
문제는 얘가 달려야 된답니다..ㅠㅠ 나도 뛰쳐나가고싶다.. 아무튼 쟤를 달리게하기 위해 처음에는 react-spirite-animation이나 image-animation 관련 라이브러리를 찾아봤는데.. 원하는 기능이 없거나 typescript가 지원되지 않아 직접 만들어야 되는 상황이 왔습니다. (React 라이브러리인데 Typescript지원을 하지 않으면 어떻게 써야 하죠..?) 어차피 여러장의 이미지를 바꿔가면서 보여주기만 하면 되는 거였기 때문에 Runner라는 컴포넌트 내에 state를 만들고 FrameNo(현재 프레임 번호) , FrameTime(한 프레임당 시간값), animationState(애니메이션 상태)라는 상태를 만들었습니다. 그리고나서 props로 현재 유저의 상태를 받아와 ‘출근’ 상태가 되면 애니메이션의 상태를 run으로 바꿔주고 해당하는 프레임수나 시간값도 미리 지정해둔값으로 변경해줍니다. 그리고 setTimeout 함수를 이용해 프레임 시간값마다 frame번호를 하나씩 올리면서 이미지를 바꿔주면
짠 얘가 이렇게 달립니다..뭔가 뿌듯합니다..
Step4. 역방향 데이터 흐름을 추가
React는 단방향으로 데이터를 전달하는데 왜 이런 단계가 있지? 라는 생각을 처음에 했습니다. 그런데 만들다보니 이해가되는게 사용자의 input을 담당하는 컴포넌트에서 저장한 데이터를 또 다른 어딘가의 컴포넌트에서 사용되어야 한다면 하단부터 다시 위로 데이터를 전달하여 최상위까지 간다음 다시 필요로하는 컴포넌트로 받은 데이터를 props로 전달해야합니다. 버대리 프로젝트에선 아래 하단의 출근, 퇴근, 외출, 복귀 버튼을 눌렀을때 이런 상황이 나타났는데 아래 버튼 액션에 따라서 위의 그림과 상태값이 바뀌어야 합니다.
데이터가 돌고돌고돌다보면 저도 돕니다..
가령 ‘‘퇴근’‘버튼을 누르면 ‘‘퇴근’‘이라는 상태값을 최상위로 보내고 최상위에서 다시 Runner 컴포넌트와 Status 컴포넌트로 보내 데이터의 변경을 알려주면 해당하는 애니메이션과 상태값으로 바뀌도록 합니다. 버대리같은 경우는 그렇게 복잡한 구조가 아니어서 어려움없이 처리하였지만, 규모가 큰 프로젝트나 컴포넌트간의 데이터를 사용하는게 많은 프로젝트라면 데이터의 흐름을 처리하는데 오히려 복잡하고 어려워질수 있다고 생각했고 이런 생각들이 다음 프로젝트인 cms 버전 에서는 Redux를 도입하는 계기가 되었습니다.
이렇게 단계별로 개발하면서 당시에는 무엇이 좋은지 전혀 느끼질 못했습니다. 그러나 완성 후 피드백 반영과 유지보수에서 많은 장점들이 드러나기 시작했습니다.
- 코드가 깔끔해지고 일원화됨
- Component 단위로 쪼개져있어 문제가 있을때 해당하는 부분을 찾기가 쉽다.
- ES6문법으로 외부 라이브러리 import의 편리함
- 타입스크립트의 도입으로 인한 생산성 향상 및 변수값의 예측
- Component 의 재사용성증가
와 같은 장점들이 있었습니다.
결론
글로는 설명할 수 없지만 개발하는 기간이 생각보다 꽤 길었고 어려운점도 많아서 그만큼 완성도 있고 제대로 만들어보자라는 생각으로 진행한 프로젝트라 막상 마치고 나니 꽤 많은 뿌듯함이 몰려왔습니다. 최근에 Frontend 개발 트렌드들이 빠르게 바뀌어가고 그런 흐름들을 단순히 블로그나 커뮤니티에서만 봐오면서 나랑은 거리가 먼 얘기겠지라고만 생각하다가 직접 이렇게 기회가 되어 만들어보게 되면서 지금까지의 생각을 많이 깰 수 있었던 계기가 되었습니다. 뭐 제가 늦은거일수도 있지만 아직도 저처럼 이런 흐름에 편승해 따라가기 어려워 한다거나 두렵다면
너무 어렵게 생각하지 말고 일단 도전해보길 권해보고 싶습니다.