리액트를 공부한지 약 2~3개월이 되었는데, 이전에는 단순히 CRA(create-react-app)로 리액트 프로젝트를 생성하고 책이나 강의를 통해 따라서 구현하곤 했다. 그런데 팀이 생기고 협업을 진행하다보니, 프로젝트를 진행할 때 어떤 패턴을 사용할 것인지, 폴더 구조는 어떻게 이룰 것인지에 대한 생각을 하게 되었다.
혼자서 리액트를 공부하거나 클론 앱 등을 만들 때는 단순히 CRA로 제작이 가능하고 전체 구조를 확인하기 편하지만, 실제 실무에서는 사이트 규모에 따라 엄청나게 많은 컴포넌트로 구성이 되어있을 것이고 이후에 내가 투입 되어 이를 다 파악해야 하는 상황도 있을 것이다.
최초 설계 시 의도와 계획, 가이드가 명확하지 않다면 이후 실무처리 과정에서 리액트 구성요소들은 엄청나게 비대하고 복잡해지게 될 것이다. 또한, 정리를 해두지 않으면 이후에 재사용 가능한 컴포넌트가 있음에도 불구하고 활용을 못하는 사태가 벌어질 수 있다.
이러한 문제들을 해결하기 위해서는 프로젝트 구축 전 충분한 고민과 기준을 가지고 설계를 계획하는 것이 중요할 것이다. 또한 내 후임자가 왔을 때, 내 설계 기준을 충분히 이해할 수 있도록 하고, 같이 작업하는 사람이 여럿일 경우 기준을 공유할 수 있도록 가이드가 있어야 할 것이다.
따라서 리액트 컴포넌트와 폴더 구조에는 어떤 것이 있는지 알아보고자 한다.
Presentation-Container Component
패턴은 과거에 자주 언급되고 활용되었던 패턴이다. Container Component
에서 데이터를 처리하고, Presentation Component
에서 데이터를 출력하는 형태로, UI와 로직을 분리하여 관리하는 패턴이다. 이유는 하나의 컴포넌트에 api 호출, 이벤트 함수, 로직 등 모든 것이 담겨있으면 파일 하나하나가 엄청 커지고, 유지보수 또한 힘들어질 수 있기 때문이다. 하지만 처음 이 패턴을 소개한 Dan Abramov는 2019년을 기준으로 현재는 이 패턴을 사용하지 말라고 언급하고 있다. Hook
이 등장하며 임의의 분리없이 똑같은 일을 할 수 있기 때문이다.
Custom hooks
는 위의 Presentation-Container Component
패턴에서 로직을 hooks로 관리하는 것이다. hooks로 로직을 관리하면 UI 재사용, 로직 재사용까지 가능해진다.
custom hooks
는 로직이 렌더링과 분리되어 있어 이 둘을 연결하는 것은 사용자의 몫이다. 컴포넌트를 올바르게 구현하려면 컴포넌트의 동작 방식에 대한 깊은 이해가 필요하다.
아토믹 디자인은 원자, 분자, 유기체, 템플릿, 페이지로 효과적인 인터페이스 시스템을 만드는 것이다. 웹 사이트의 구성 블록이 HTML 요소들이며 이 요소들은 원자로 볼 수 있다. 원자가 결합되어 분자가 되는 것처럼 HTML 요소들은 결합되어 복잡한 페이지를 형성한다.
원자(Atoms) - 버튼, 제목, 텍스트 입력 필드(모든 컴포넌트들의 기초가 되는 블록, 더 이상 분해될 수 없는 필수 요소)
분자(Molecules) - 2개 이상의 원자로 구성, 하나의 단위로 함께 동작하는 UI 컴포넌트의 단순한 그룹
유기체(Organisms) - 분자, 원자 또는 다른 유기체의 그룹으로 구성된 비교적 복잡한 그룹, 이 유기체들은 인터페이스의 개별적인 영역을 형성
템플릿(Templates) - 컴포넌트들을 배치하고 설계의 구조를 보여줌
페이지(Pages) - 실제 컨텐츠들을 배치한 UI를 보여줌, 템플릿의 구체화된 인스턴스
아토믹 구조는 UI 재사용성이 매우 뛰어나다. 하지만 디자인 시스템 구축을 위한 초기 비용이 많이 들고, 로직과 State들을 page 단위에서 props로 내려줘야하는 단점이 있다.
리액트는 다양한 폴더 구조가 있다.
자주 사용되는 폴더들은 다음과 같다. 폴더 구조는 리액트 공식문서에서 제시된 구조 두 가지를 예로 살펴보자.
common/
Avatar.js
Avatar.css
APIUtils.js
APIUtils.test.js
feed/
index.js
Feed.js
Feed.css
FeedStory.js
FeedStory.test.js
FeedAPI.js
profile/
index.js
Profile.js
ProfileHeader.js
ProfileHeader.css
ProfileAPI.js
css, js, 테스트 파일을 기능이나 라우트로 분류된 폴더에 같이 두는 방법이다.
api/
APIUtils.js
APIUtils.test.js
ProfileAPI.js
UserAPI.js
components/
Avatar.js
Avatar.css
Feed.js
Feed.css
FeedStory.js
FeedStory.test.js
Profile.js
ProfileHeader.js
ProfileHeader.css
비슷한 파일끼리 묶어주는 방법이다.
또한, 폴더 구조를 정할 때 유의할 점은 너무 많은 중첩을 피하는 것이다.
이렇게 다양한 리액트의 컴포넌트 패턴, 폴더 구조들을 살펴보았는데 그러면 컴포넌트 패턴, 폴더 구조는 어떻게 설계해야할까?
리액트는 수많은 컴포넌트로 이루어져있기 때문에 컴포넌트를 잘 설계하는 것이 리액트 프로젝트를 잘 설계하는 것에 큰 비중을 차지한다.
각 컴포넌트 패턴과 폴더 구조의 장단점을 고려하여 해당 프로젝트에 알맞은 패턴, 구조를 계획하는 것은 정말 중요할 것이다.
너무 좋은 글입니다. 감사해요!