문제점
우린 다양한 게임을 만들어서 추가하기 보다는 사과게임에 다양한 모드를 추가해서 새로운 재미를 제공하고 싶었다.
모드의 추가는 기존 게임의 룰을 지키면서 확장이 이루어지는 것.
그렇다면 공통적인 부분을 묶고, 다른 부분만 잘 분리한다면 변경과 확장이 쉬워지고 개발비용을 줄일 수 있다고 생각했고 이렇게 확장할 수 있는 구조를 만들고 싶었다.
사과게임에서 공통적으로 묶어야 하는 부분은?
게임에서 변경되지 않고 공통적으로 묶을 수 있는 부분은 게임의 룰 이라고 생각한다.
이런 예시로 테트리스를 예로 들어볼 수 있다.
- 정해진 모양의 블럭이 랜덤한 순서로 내려온다.
- 블럭은 시간에 따라 아래로 내려온다.
- 가로로 1줄이 꽉 차게 되면 해당 줄을 지우고 점수를 얻는다.
그렇다면 테트리스에 물리법칙을 적용해 확장한다면?
이상한 모양새가 되었지만 게임의 룰은 착실하게 지키고 유저도 이 게임에 적응하는데 오래걸리지 않는다.
그러면 사과게임의 게임 룰은?
- 사과가 생성된다.
- 드래그를 한다.
- 사과들을 드래그 영역 내부에 넣는다.
- 드래그가 끝나면 드래그 영역 내부의 사과들의 숫자를 더한다.
- 10이면 점수를 얻고 드래그 영역 내부의 사과들을 제거한다.
- 일정시간 후 게임 종료.
황금사과 모드를 넣어서 확장한다면?
- 사과가 생성된다 사과중 1개는 황금사과.
- 드래그를 한다.
- 사과들을 드래그 영역 내부에 넣는다.
- 드래그가 끝나면 드래그 영역 내부의 사과들의 숫자를 더한다.
- 10이면 점수를 얻고 드래그 영역 내부의 사과들을 제거한다.
- 황금사과가 제거되면 있었다면 게임판을 새로고침 해준다.
- 일정시간 후 게임 진행사항 채점 후 게임 종료.
중복되는 영역을 재사용할 수 있을 것 같다.
이런 확장을 위해선 중복되는 영역을 분리해야 했는데 이 과정이 너무 어려웠고 왜 어려운지 고민하고 분석하게 되었다.
왜 분리가 어려울까?
위 사진이 사과게임의 구조를 핵심 부분만 간략하게 나타낸 그림이다.
Hook에서는 Apple 객체 배열(Apple[])을 상태로 관리하고 해당 배열이 변화해야하는 행위들을 게임 메니저가 처리하고 다시 Hook에 넘겨 Hook은 Apple 객체 배열을 업데이트 한다.
이런 구조의 문제점이 뭘까?
Hook에서 상태를 업데이트 하지만 상태를 변화시키는 로직은 게임 메니저에 존재한다.
상태와 직접 연관된 로직이 바깥에 있다는 말이고 Hook은 상태를 게임 메니저에 넘겨줘야 한다.
이런 구조는 응집도가 떨어지고 Hook과 게임 메니저의 결합도는 매우 커진다.
Hook과 게임 메니저의 결합도가 커진다는건 재사용하기 어려워지고 변경과 확장이 어려워진다는 말이 된다.
산탄총 수술문제
만약 Apple을 수정한다고 하면 Apple객체를 배열로 관리하는 Hook에서도 수정이 일어나야 하고 Hook에게 상태를 넘겨받는 게임 메니저도 수정이 일어나야 한다.
기능을 추가한다고 하면 게임 메니저에 메서드를 추가하고 Hook에서 호출하고 상태를 넘겨주는 코드가 추가 되어야 한다.
상태와 직접 연관된 로직은 Hook 바깥에 있고 상태를 업데이트 하는 로직은 Hook내부에 있으니 응집도가 낮아지고 문제 발생시 진단을 어렵게 한다.
재사용성이 떨어짐
새로운 게임 모드를 개발한다고 했을 때 기존에 만들어진 사과게임에서 필요한 부분을 재사용 하고싶지만 결합도가 높아진 Hook과 게임 메니저는 이걸 어렵게 만든다.
왜 이런상황이 발생했을까??
리액트를 뷰(View)로써 바라보지 못했다.
지금까지 해왔던 프로젝트나 대부분의 사람들은 비즈니스 로직을 처리하기 위해 훅이나 컴포넌트를 조합해서 사용하고 나도 그렇게 사용해왔다.
하지만 게임이라는 특수한 도메인을 만나게 되면서 많은 비즈니스로직이 프론트엔드로 넘어오게 되었고 이걸
리액트에 녹여내야 한다고 생각했던게 이런 결과를 만들어낸것 같다.
리액트는 프레임워크가 아니다 어느순간 이걸 잊고 살았던 것 같다.
대부분의 비즈니스로직은 Hook과 상태로 처리를 해오다 보니 리액트를 DOM을 쉽게 조작하기 위한 창구의 역할로 보지 못하고 이런 커다란 도메인을 리액트에서 처리해야 한다고 생각을 해버린것 같다.
사용자 인터페이스를 구축하기 위한 자바스크립트 라이브러리 —React 공식 홈페이지
다음 글에서는 이런점을 해결하고 확장가능한 구조를 위해 리액트에서 도메인로직을 분리해 모듈화 하고 계층화된 프론트엔드 어플리케이션으로 바꾸는 과정을 적어보겠다.