📚 TLDR
서비스를 개발하다 보면, 새로운 기능을 만드는 만큼이나, 기존의 코드를 다시 보고 다른 사람이 짠 코드를 살펴보는 시간이 많아졌습니다. 가벼운 해커톤이나, 동아리 프로젝트처럼 기간을 정해두고 하는 프로젝트성 개발과 달리 완성을 시키고 계속 유지보수 해나가야 하는 개발을 하다 보니 '아.. 리팩토링 해야 하는데..'라는 생각이 절로 들게 됩니다.
이제 와서 생각해 보면, '컨벤션을 좀 더 꼼꼼히 할걸', '코드리뷰 할 때, 이런이런 부분에 대해서는 의견을 나눠볼걸'과 같은 생각이 들긴 하지만, 그것도 1년 정도 한 프로젝트만 개발하고 코드를 보고 또 보면서 서비스를 발전시키다 보니 느껴지는 부분이지 그때의 제가 생각조차 못할 부분이지 않나 싶기도 합니다. 여러 후회와 그 후회를 바탕으로 발전시켜 나갈 부분 중, 이번에는 "리팩토링"과 그 리팩토링을 하기 위해 필요했던 지식에 대해 정리해보려고 합니다.
"아... 리팩토링 해야 하는데"
는 제가 서비스를 개발하면서 줄곧 입에 달고 살았던 말과 생각입니다만, 막막함이 있었습니다. Clean Code에서 말하는 순수함수가 React에서 적용될 수 있나? 사이드 이펙트를 어떻게 줄일 수 있지? 내 코드를 고쳐야 할거 같은데? 지금은 상태도 너무 많고 기능을 고치면 다른 페이지에 영향을 가는 거 같은데? 같은 생각이 들었지만, 어디서 어디까지 어떻게 고쳐야 하지?? 하는 고민을 길게 가졌고, 고민을 해결하기 위해 best practices를 검색해 보며 다른 서비스의 코드를 읽고 아티클과 강의를 보면서 이해했던 개념에 대해 이번 아티클을 시작으로 정리해 보자 합니다.
무엇을 기준으로 파일을 묶을 것인가?
코드 파일을 무분별하게 두는 건, 서비스의 규모가 커지면 커질수록 불편함을 야기하게 됩니다. 즉, 특정 주제를 기준으로 폴더를 묶을 필요가 있습니다. 하지만 그 기준을 어떻게 잡는 게 좋을까요? 리액트 폴더 구조에 정답은 없지만, 몇몇 유명한 디자인 패턴을 활용한 예시들이 있습니다.
이전 프로젝트에서 Atomic Design Pattern을 한번 도입해 본 경험이 있습니다. 해당 페턴을 이해하고 도입할 때까지만 해도 개념자체가 어렵다고 생각하지는 않았지만, 막상 도입해 보니 여러 문제가 있었습니다.
- 우선 해당 폴더 구조는 UI 폴더를 나누는 기준이었습니다. UI를 구성한 폴더 내에 상태와 기능들이 섞이면서, UI 재사용성은 개선되었지만, 이는 아주 작은 단위 (Atom)까지 정도였습니다. 단위가 커져갈수록 비슷하지만 기능과 UI가 조금 다르거나, 혹은 해당 기능을 관리하기 위해 features와 같은 폴더를 분리하기 시작하면서, 코드 관리 측면에서는 여전히 불편함이 있었습니다.
- 1번에서도 그랬지만 결국 Organism 이 갖는 기준이 너무 모호했습니다. 어디까지 Organism인지? 페이지별, UI별 Organism을 어떻게 얼마나 만들 것 인지는 모호했고, 이 모호함은 결국 Organism이 혼잡해지고 코드를 관리하는 데는 여전히 불편했습니다.
이전과 같은 문제를 반복하지 않기 위해서는, UI뿐 아니라 기능과 서버로부터 CRUD를 하고 test를 하는 등의 모든 코드들에 대해서 폴더를 나누는 기준이 필요했습니다.
비즈니스 / 도메인 로직
비즈니스 로직은 도메인 로직이라고도 불리며, 서비스에서 해결하려고 하는 문제를 처리하는 로직을 의미합니다. 특정 도메인이나 비즈니스 문제와 직접적으로 관련된 규칙, 계산, 데이터 변환 등을 의미합니다.
'장소 상세 보기 페이지에서 내 여행계획에 추가할 때, 장소와 관련된 메모가 남아있다면 가져와 여행계획 장소에 추가해 주세요'
'여행 계획의 일자를 설정할 때, 오늘을 기준으로 이전날짜를 선택했다면 해당 팝업을 표시해 주세요'
예를 들기 위해 제가 전달받았었던 기획 측 요청사항을 가져와봤습니다. 각각의 요청사항들은 저희 서비스에서 발생할 수 있는 문제에 대해 어떻게 처리할 것인지 적혀있으며, 모든 여행 서비스에서 발생하는 문제이자 해결하는 방법은 아닙니다. 저희 서비스에서 해결하고자 하는 "비즈니스 규칙"이며, 이를 해결하는 로직이 비즈니스 로직이 됩니다.
폴더를 나누는 기준
위의 예시는 프론트엔드 개발자가 받은 UI관련 비즈니스 규칙이지만, 여행계획을 어떻게 데이터를 저장하고, 과거일 때 어떻게 관리하는 등등의 많은 비즈니스 규칙에 대해 주로 백엔드에서 받아오게 됩니다. 그렇다면 해당 비즈니스와 관련된 것들에 대해 폴더를 묶으려고 할 수 있습니다.
위의 예시를 통해 보자면, 여행계획에 추가하거나 일자를 설정하는 것과 관련하여 TripPlan 같은 폴더 내부에 setDates, updateDates, addPlace, addMemo와 같은 기능을 정리하고, TripPlan Type을 생성 및 관리할 수 있습니다. TripPlan / Place처럼 폴더를 묶고 폴더 내 관련 UI나 기능을 추상적으로 정의 한 다음, 가져오는 UI에서 사용하는 방식을 고안해 볼 수 있습니다.
이는 소프트웨어 공학에서 말하는 유지보수성을 높이기 위해 "결합도는 낮게, 응집도는 높게" 구성하는 방식에도 해당합니다. 기존에 코드가 분산되어 있을 때는 여행 계획 관련 로직을 수정하기 위해 여러 폴더를 다녔다면, 지금은 TripPlan이라는 폴더 내에 관련 비즈니스 로직이 모여 있기에 손쉽게 찾을 수 있으며 유지보수가 편리해집니다. 결합도가 낮고 응집도가 높을 때 얻을 수 있은 이점을 가져갈 수 있습니다.
마무리
디테일한 폴더 나누는 내용에 대해서는 차근차근 다뤄보려고 합니다. 일단 비즈니스 로직을 기준으로 폴더를 정하여 관련 기능과 UI를 한 군데 모아 응집도를 높이는 개념에 대해 정리해 보았습니다. 프로젝트의 규모가 커질수록 pages/components/hooks/feature/utils... 등등 복잡한 폴더 사이에서 원하는 코드를 찾는데 오랜 시간이 걸리신다면 참고해 보기 좋은 개념이라고 생각합니다.
'React' 카테고리의 다른 글
[React] 뒤로가기 시 상태 유지하기 ( useNavigationType, popstate ) (1) | 2024.11.15 |
---|---|
[React] 웹뷰로 연결된 Android Stuiod / IOS 에 데이터 주고받기 ( 브릿지 통신 ) (0) | 2024.11.11 |
[AWS] Sub Domain 연결하기 (5) | 2024.10.31 |
[React + Vite + Nginx + Docker + AWS] 를 활용하여 배포 해봅시다! (0) | 2024.06.05 |
[React, Typescript] Intersection Observer를 활용하여, 사용자 화면에 맞게 변화하는 컴포넌트 만들기 (1) | 2024.05.14 |