리액트 컴포넌트 구조에 대한 패턴을 다루는 글입니다.
Container & Presentation
하나의 컴포넌트를 Container, Presentation 컴포넌트로 분리해서 관리하는 방식으로 데이터를 관리하는 로직은 Container, 데이터를 받아 화면에 보여주는 부분은 Presentation에 해당합니다.

Container 컴포넌트
- State, API호출, 이벤트 처리 등 데이터와 기능적인 부분에 대한 작업을 담당합니다.
- 화면에 반영할 결과값(변화된 state값, API결과로 가져온 데이터 등)은 하위에 있는 Presentation 컴포넌트에 Props로 전달합니다.
Presentation 컴포넌트
- UI를 담당합니다.
- Container로 부터 받은 데이터를 화면에 직접 반영합니다.
Presentation & Container 디자인 패턴 장점
- Presentation 컴포넌트를 재사용할 수 있다.
- 컴포넌트별로 역할을 분리해서 코드 구조를 이해하기 쉬워짐.
- 하나의 Container 컴포넌트에 하나의 Presentation 컴포넌트만 내려주는것이 아니라, 다른 Presentation 컴포넌트에 내려주면서 상태를 공유할수도 있음.
Presentation & Container 디자인 패턴 단점
- 컴포넌트를 분리하면서 용량이 증가함(미미하지만 분리된 코드가 많아지면 영향을 줄 수 있음)
- Container에서 Presentation으로 데이터를 props로 전달하는 과정에서 중복되는 패턴이 생김 -> 가독성이 떨어질 수 있음
- 계층으로 나뉘어있는 패턴이기 때문에 설계변경시 대처가 어려울수 있다.
Atomic
가장 작은 컴포넌트인 원자(Atoms)부터 시작해 분자(Molecules), 유기체(Organisms), 템플릿(Templates), 페이지(Pages)로 이루어지는 패턴

- 원자(Atoms) : UI를 구성하는 가장 작은 요소,(ex) 버튼, 아이콘, 인풋, 라디오버튼 등)
- 분자(Molcules) : 여러개의 원자가 보여 형성된 컴포넌트. 분자 단위부터는 역할이 명확해지고 재사용 가능한 단위가 된다. 분자보다 커지면 재사용성이 떨어질 수 있으므로 단순함을 유지해야한다.
- 유기체(Organisms) : 분자들이 결합된 컴포넌트, 재사용성을 고려하지 않음, (ex) 헤더, 푸터, 상품 목록)
- 템플릿(template) : 유기체들이 모여 페이지 구조나 레이아웃을 구성한 것
- 페이지(pages) : 템플릿에 실제 데이터 반영되어 완성된, 하나의 페이지
Atomic 디자인 패턴 장점
- 컴포너트 재사용성이 극대화 될 수 있다.
- 계층구조가 단순해서 설계변경이 있을때 쉽게 유지보수 할 수 있다.
Atomic 디자인 패턴 단점
- 코드가 길어지면 컴포넌트가 복잡해져 가독성이 떨어진다.
- 전역상태관리를 하지않으면 props drilling이 일어나 실행흐름을 파악하기 어려워 지고 코드가 복잡해진다.
디자인 패턴에 대한 생각
devpost 프로젝트를 진행할때 이러한 컴포넌트 패턴에 대해 생각하고 적용한것은 아니였지만 이미 Atomic 패턴과 유사한 형태로 컴포넌트를 관리하고 있었다. 위에 나와있는 단점과 같이 프로젝트를 진행하면서 코드가 길어졌을때 가독성이 안좋아졌고, 렌더링을 하는 부분은 컴포넌트로 분리해 코드를 줄이고, 기능을 담당하는 로직은 hooks로 따로 빼서 재사용할수 있는 형태로 정리해서 관리했다. 그리고 대부분의 컴포넌트가 styled-component로 인해 코드가 길어지기 때문에 전부 styles.js 파일로 분리해서 import하는 방식으로 관리했다.
container & presentation 패턴은 역할을 분리해서 관리할수있다는 장점은 좋았지만 기본적으로 컴포넌의 변경사항이 생겼을때 상하구조의 흐름을 파악하면서 수정을 해야 하기때문에 선호되지는 않았다. 간혹 redux-hooks(useSelector, useDispatch)를 사용하지 않고 redux를 사용해서 상태를 props로 내려주는 방식이나 context api를 사용해서 render props 패턴으로 props를 내려주는 방식이 container & presentation 패턴과 유사하다는 생각이 들었지만 useSelector, useDispatch를 포기하고 그러한 방식을 썻을때 유리한점이 무엇인지는 잘 모르겠다.
개인적으로는 '어떤 디자인 패턴을 유지하는가' 보다 확장성 좋고 수정이 편리한 방식으로 코드를 유지하는것이 중요하다고 생각한다. 위에서 말한 두가지 패턴외에도 컴포넌트 패턴은 여러가지가 있을 수 있고 리액트는 웹 전체를 담당하는 것이 아니라 view를 담당하는 부분이기 때문에 너무 엄밀하게 패턴을 유지하기에는 충돌이 생길 가능성도 있겠다라는 생각도 든다.