Skip to content

Latest commit

 

History

History
57 lines (29 loc) · 16.5 KB

MEMOIRS.md

File metadata and controls

57 lines (29 loc) · 16.5 KB

Memoirs

프로젝트를 개발하면서 느꼈던 어려운 점과 부족한 점을 공유한다.

새로 도입한 부분

Automic Design

이번 프로젝트는 컴포넌트 디자인 패턴으로 Automic Design을 채택했다. 디자인 패턴을 단 한번도 사용해본 적이 없었지만 그럼에도 불구하고 Automic Design을 사용하기로 마음먹은 것은 예전에 React를 사용하여 프로젝트를 개발하면서 생긴 문제점을 해결하고 싶은 마음 때문이었다. 그 문제점 중 가장 불편했던 것 중에 하나는 컴포넌트의 내용이 조금만 달라지면 새로운 컴포넌트를 작성해야 했다는 점이었다. 같은 버튼을 만든다고 해도 버튼의 용도 그리고 버튼 텍스트가 달라지기만 해도 새로운 버튼 컴포넌트를 작성해야 하는 것이 시간을 낭비하는 원인 중 하나라고 생각되었다. 예전에 이것을 해결하지 못해서 이름만 다른 똑같은 컴포넌트를 여러개 import 하는 상황이 발생하게 되었다. 그러다보니 컴포넌트를 렌더링하는 코드 부분만 해도 길이가 길어지게 되었으며 다음 프로젝트를 하게 될 때는 이것을 해결해보고자 하는 마음이 크게 작용한 것 같다. 따라서 이 부분을 어떻게 해결할 수 있을까 검색을 하던 와중에 재사용 컴포넌트를 만드는 방법을 보게 되았고 더 나아가 이것을 효율적으로 이용할 수 있는 방법으로 Automic Design을 찾게 된 것이다.

Automic Design은 atoms | molecules | organisms | templates | pages로 총 5개의 구성요소를 가지며 컴포넌트를 작은부분으로 잘게 쪼개어 다시 재사용할 수 있게 하는 것이 핵심입니다. Tsufia 프로젝트에서는 가장 기본이 되는 요소(Heading, Span, Link, Button... 등)로 atom으로 바라보았으며 atom이 여러 개 모인 집단 (ButtonList, UnorderedList... 등)을 molecules로 구성하였습니다. atoms | molecules는 언제나 재사용될 것을 염두하여 props와 styled component를 활용해 스타일을 재구성하며 어떠한 로직도 포함하고 있지 않습니다. organisms에서는 재사용 가능한 atoms | molecules의 집합으로 구성되어 실제로 사용될 수 있는 컴포넌트를 구성합니다. templates에서는 prop을 받아 레이아웃을 담당하는 형태만을 가집니다. 마지막으로 pages에서는 실제 페이지를 담당하는 컴포넌트를 의미하며 페이지는 Container, Presenter로 구성되어 있습니다. Container에서는 페이지가 가지고 있는 모든 로직들을 가지고 있으며 해당 로직들은 Context에, 그리고 페이지 전역에서 사용하게 되는 상태들은 Redux에 담겨 추후에 어느곳에서든지 사용 가능합니다. Presenter에서는 페이지를 구성하게 되는 실질적인 컴포넌트를 해당 templates에 props를 제공하게 됩니다. 즉, atoms -> molecules -> organisms -> templates -> pages 순으로 컴포넌트가 구성되어 사용자에게 UI가 제공되는 것 입니다. 이러한 구조를 가지는 Automic Design을 사용하게 되면서 좋았던 점은 컴포넌트가 어느 부분에 속하는지만 봐도 구분된 역할이 명확해진다는 것과 한번 만든 재사용 컴포넌트는 다음에 다른 부분에서 활용되어 굉장히 편하다는 장점이 있었습니다. 하지만 Automic Design 역시 좋은 점만 가지고 있었던 것은 아니었고 여러가지 단점도 존재했다. 단점은 아래에서 설명하도록 하겠습니다.

Redux with Typescript

프로젝트에서 Automic Design을 사용할 때 생기게 되는 불편한 점은 props를 내려주는 것에 관련된 부분이라고 생각됩니다. Automic Design은 큰 컴포넌트를 잘게 쪼개는 것이 핵심이기 때문에 하나의 상태를 하위 컴포넌트로 전달하더라도 여러번을 거쳐야 하기 때문에 기능을 수정하는 일이 발생할 시, props를 일일이 수정해야 되므로 많은 시간을 소요하게 될 수도 있다는 점 입니다. 이 부분을 해결하기 위해서 Redux의 도움을 받기로 하였으며 이왕 사용하는 거 Type의 도움을 받을 수 있도록 typesafe-actions패키지를 설치하여 적절히 활용하였습니다. 상태를 Redux로 관리하게 되면서 로직에 관한 부분은 page의 container 컴포넌트에 모아서 작성할 수 있게 되었으며 추후에 useSelector메서드를 사용해 상태를 어느 컴포넌트에서든지 사용할 수 있게 되었습니다. 또한 Redux Devtools를 연동하여 사용하면서 테스트할 때 dispatch가 몇번 이루어지는지 어디까지 상태가 저장이 되었는지 확인할 수 있어 매우 편리하게 개발할 수 있었습니다. 누군가 Automic Design을 사용하고 싶다면 꼭 Redux를 사용하길 권할 정도로 좋은 경험을 한 것 같습니다.

프로젝트 진행 중 어려웠던 부분

Unfamilar Socket.io

이전까지 HTTP 통신을 주로하는 웹 개발을 많이 해왔었지만 소켓 통신은 눈과 귀로 보고 들은 적이 있어도 프로젝트에서 제대로 사용해볼 기회가 없었다. 그렇다보니 이번 프로젝트에서 처음 소켓을 이용해보면서 많은 시행착오를 겪을 수 밖에 없었다. 대부분의 정보는 공식문서 또는 구글과 유튜브에서 소켓에 관한 글과 영상을 읽어 내려가면서 감을 잡는 데 시간을 많이 투자하였다. 하지만 그 중에는 내가 찾으려는 정보가 없어 나 혼자서 해결해야 하는 경우도 있었는데 예를들어, 소켓을 사용해 방을 생성해야 하는 경우 대부분의 예제는 소켓을 이용해 방에 입장시키는 것으로 마무리했지만 나같은 경우에는 방에 관련된 새로운 url을 따서 할당하게 해주고 싶었다. 예를 들면 rooms/1와 같이 말이다. 실제로 적용해본 결과 방을 한번 입장하고 퇴장하는 것에 대해 문제는 없었지만 이러한 작업을 반복했을 때 문제가 발생했다. 방을 입장하고 퇴장하는 작업을 두번째 진행하게 되는 순간부터 방이 두개가 만들어지거나 이미 방이 삭제 되었으나 또다시 삭제하려는 듯한 행위가 발견되었다. 이는 리액트의 특징 때문이었는데 라우트를 이동할 때 소켓 이벤트가 해제되지 않아 여러번 중첩됨으로써 시작된 오류였던 것이었다. 소켓을 처음 사용해본 나로서는 어디서 문제가 발생하는지 찾기가 어려워 이렇게도 해보고 저렇게도 해보면서 여러번 삽질을 하게 된 후에야 그 이유를 알 수 있었다.

동기화

소켓 통신을 사용하면서 가장 어려웠던 부분은 동기화하는 부분이었다고 생각합니다. 예를 들어 Tsufia 프로젝트에서 사용자는 방에 입장한 자들과 방에 입장하지 않아 로비에 있는 자들로 구분할 수 있는데 누군가 방에 입장을 한다면 방에 이미 있던 유저에게 어떤 유저가 입장하는지 알려줘야 하며 반대로 방 바깥에 있는 로비 유저들에게도 역시 알려줘야 했다. 사실 이런 케이스들은 소켓 통신을 하면서 너무 흔하게 볼 수 있는 현상들이었지만 대상을 누구로 타겟팅하는지 미리 정해두지 않는다면 나중에 가서야 실수했다는 것을 깨닫고 수정해야 했던 기억이 난다. 아래는 동기화를 하면서 제가 겪었던 어려웠던 부분을 설명하는 예시입니다.

  • 사용자마다 다르게 게임 패치가 되었던 상황을 해결한 방법

    게임 투표를 통해 선택한 유저를 소켓을 통해 서버로 전달하였다. 하지만 어째선지 딱 한명의 유저만 선택한 유저를 서버에 전달하였다. 정확한 원인을 분석해보니 사용자마다 게임 패치 상황이 전부 달랐기 때문이었다. 각자 가지고 있는 카운트다운이 다르기 때문에 문제가 생긴 것 이었으며, 사용자 중 가장 빨리 카운트다운이 0가 되는 상황이 되면 다른 유저가 카운트다운이 0이 될 때까지 기다리지 않고 바로 이벤트를 발생시켜 버리는 것 같았다. 이를 해결하기 위해 방장의 카운트다운을 모든 유저에게 동기화하여 같은 카운트다운을 가질 수 있도록 하였다. 결과적으로 카운트다운이 같으니 모든 유저가 똑같은 state를 유지할 수 있게 되어 서버에 선택한 유저를 가져올 수 있었다.

방 연결 유지하기

Tsufia 프로젝트는 실시간으로 동작하는 마피아 게임을 만드는 것으로써 유저의 반응에 실시간으로 대응할 수 있게하고 싶었다. 이 말은 유저 한명에게 어떠한 문제가 생긴다고 해도 게임은 그대로 진행될 수 있어야함을 의미합니다. 이것이 지켜지기 위해서는 유저가 페이지 새로고침 및 나가기를 실행했을 때 그에 대한 해결책을 찾아야만 했습니다. 그 이유는 페이지 새로고침 및 나가기를 실행했을 때 소켓은 연결이 끊어짐을 의미하기 때문입니다. 방 안에서 이것이 실행된다면 게임이 중단되며 방은 망가지게 됩니다. 게임을 하고 있던 와중에 한명의 유저의 행동으로 인해 이처럼 되는 것을 원하지 않았고 게임이 계속 이어지던가 중단시켜 다시 게임을 시작할 수 있도록 만드는 것이 이 프로젝트의 가장 큰 숙제가 되었습니다.

처음에는 서버 측에서 Disconnect 이벤트가 발생할 때 방 나가기 또는 삭제 이벤트를 실행하도록 하였다. 모든것이 잘 되는 것처럼 보였지만 추후에 페이지를 새로고침 했을 경우에도 Disconnect 이벤트가 발생하여 이벤트를 발생하게 돠었다. 단지, 페이지를 새로고침할 때는 사용자가 속한 방과 게임을 삭제하면 안된다. 하지만 Socket의 문제점은 페이지가 새로고침 되거나 종료되어도 둘의 차이를 구분하지 못해 Disconnect 이벤트가 필연적으로 발생한다는 것이다. 이것을 해결하기 위해 RECONNECT 되는 시점까지의 기간을 3초로 잡고 그 안에 페이지를 다시 방문하지 않으면 브라우저가 닫힌 것으로 간주하여 방 나가기 및 삭제 이벤트를 발생시키도록 하였다.

프로젝트를 마치고 부족하거나 아쉬웠던 부분

로직 구성

현재 이 프로젝트는 Automic Design을 디자인 패턴으로 사용하게 되면서 Page별로 모든 로직이 Container파트에 구성하게 되었다. 이는 재사용 컴포넌트와 로직을 분리하여 재사용 컴포넌트가 어떠한 로직에도 의존하지 않게 하기 위함이다. 처음에는 로직과 UI가 분리되기 때문에 굉장히 좋은 방법이라고 생각했지만 점점 로직의 구성이 커가게 되면서 생각이 바뀌게 되었다. 로직이 너무 많은 탓에 추후에 찾으려는 함수를 찾는데 시간이 많이 걸리게 되었고 함수마다 어디서 사용되는지 알기가 점점 어려워지게 되었다. 지금 생각해보면 로직이 읽기 어렵게 된 것은 코드가 길어져서가 아니라 내가 코드를 잘못 구성한 것이 크다고 생각한다. 같은 용도의 이름만 다른함수가 너무 많았으며 쓰임새가 이어지는 함수끼리 모아두던가 페이지별로 나눠놓던가 했어야 했다고 생각된다.

며칠 전 클린코드에 관한 몇가지 유형을 살펴본 적이 있는데 내가 프로젝트를 만들면서 쓰던 버릇들의 대부분이 위배되고 있다는 것을 알게 되었다. 나는 코드를 깔끔하게 만들고 싶은 마음에 코드를 한줄이라도 줄이는 것에 목적을 두었지만 지금와서는 코드가 짧은 것이 중요한 것이 아니라 어떤 코드를 짜더라도 그 코드의 의미가 쉽고 명확하게 파악이 될 수 있도록 하는 것이 더 중요한 것 같다. 이 프로젝트의 모든 코드는 내가 전부 이해하고 응용하여 만든 프로젝트지만 아쉽게도 프로젝트가 마무리 된 상황에서 누군가가 나에게 어떤 코드에 대해 이해가 안가서 물어보러 온다면 나는 그 코드에 대해 바로 설명하지 못할 확률이 크다. 나 역시 그 코드가 어디에서 쓰였는지 왜 사용되었는지 확인해야 하기 때문이다. 내가 작성한 코드를 누군가가 확인했을 때 물어보지 않아도 이해가 될 수 있는 개발자가 되늘 날까지.. 화이팅이다.

Automic Design이 필요할까?

재사용 컴포넌트를 보다 쉽게 활용하기 위해서 Automic Design을 사용했다. atoms/molecules/organisms/templates/pages처럼 컴포넌트가 구분되어 있어 역할이 알기 쉽고 어디에 위치해 있는지 예상하기도 쉽다. 하지만 위 같은 장점이 있다고 하더라도 코딩하기 어렵게 만드는 단점이 한가지 있었는데 나한테 있어서는 스타일링 하는 부분이 가장 번거로웠다. 모든 컴포넌트를 가장 작은 단위로 쪼개서 크게 만들어간다는 것은 CSS를 하는 부분에 있어서도 마찬가지였다. 내가 방법을 몰라서 그런걸 수도 있겠지만 적어도 이 프로젝트에서 아토믹 디자인을 적용하면서 모든 재사용되는 컴포넌트들에 대하여 스타일에 대한 부분을 새로 지정하게 되었다. 똑같은 스타일링이라도 컴포넌트가 다르다는 이유만으로 스타일에 관한 코드를 따로 작성해 주어야 했었다. 아토믹 디자인을 하지 않았다면 스타일을 적용하는데 얼마 들지 않았겠지만 아토믹 디자인으로 설계하다보니 이 폴더 저 폴더 이동하면서 스타일에 관해 props를 만들고 스타일을 새로 짜는게 시간이 3배는 더 소요 되는 것 같았다. 사람들이 그래서 storybook 라이브러리를 사용한걸지도 모르겠다. 나도 다음에 UI를 테스트할 때 사용해보도록 해야겠다.

결록적으로 프로젝트가 굉장히 크다면 Automic Design을 사용하는 것도 나쁘지 않다고 생각한다. 큰 프로젝트일수록 Automic Design의 진가가 발휘할테지만 Tsufia 프로젝트처럼 10페이지 가량 되는 프로젝트에서는 오히려 Automic Design으로 설계하는데 시간이 더 들어가므로 비추천하고 싶다.

테스팅

안타깝게도 이번 프로젝트를 끝마칠때까지 테스트를 한 번도 하지 못했다. 첫번째로 소켓 프로토콜을 사용할 때는 어떻게 테스트 해야하는지 방법을 찾지 못했다는 것이고 두번째는 나의 생각보다 프로젝트 개발 기간이 매우 길어져 더 시간을 지체 하다가는 프로젝트를 끝마치지 못할 것 같다는 예감 때문이었다. 덕분에 1000번도 넘는 방을 만들었다 삭제했으며 중간부터는 너무 하드테스트를 하고 있다는 느낌이 들었다. 아마도 내가 소켓 기반 테스트를 할 줄 모르는 것일 뿐, 분명 이렇게 개발하는 것이 아닌 것만은 확실하다. 만약 내가 테스트와 함께 프로젝트를 개발할 수 있었다면 좀 더 빠르게 버그를 찾아내고 내가 알지 못한 오류를 찾는데 도움을 줘서 더 빨리 프로젝트를 마무리 할 수 있지 않았을까 하는 생각이 들기도 한다.

마지막으로

이번 프로젝트를 통해서 많은 것들을 알게 되었다. 특히나 아직 사용해보지 않았던 기술들(리덕스/context 훅 등)을 사용해보면서 많은 성장을 한 것 같다고 느꼈다. 그리고 지금까지 한 프로젝트 중 가장 많은 코딩을 하면서 지금까지 겪을 수 없던 문제점을 찾아낸 것으로 다음 내가 나아가야할 방향을 알 수 있게 되었다. 예전에는 코드가 적었기 때문에 간단한 룰을 지키기만 해도 코드를 알아보는 데에는 문제가 없었지만 이번 프로젝트를 끝내고서 내 코드를 다시 돌아봤을 때 객관적으로 남이 보면 코드의 역할이 무엇인지 설명해야할 부분이 너무나도 많다. 별다른 주석 없이도 다른 사람이 코드를 봤을 때 이해가 가며 재사용 가능한 함수들로 묶어내보고 싶다. 내가 클린 코드를 작성함으로써 다른 사람의 코딩 시간을 절약할 수 있도록 만들어내는 것이다. 아직은 좋은 코드를 녹여내리기엔 경험이 많이 부족한 것 같다. 책과 다른 사람의 코드를 봄으로써 더 좋은 코드로 만들어나가도록 하자.