Skip to main content

Command Palette

Search for a command to run...

어떤 React 디자인 패턴이 적절한 것일까 ?

Updated
4 min readView as Markdown

Moved my blog! 👉 https://www.youngminss-log.com

들어가면서 🙋🏻‍♂️

요즘 저는 과기부에서 주관하는 "소프트웨어 마에스트로 13기" 활동과 "IT 연합 동아리 YAPP" 활동을 병행하며 살고 있습니다.

이 중 YAPP 동아리 활동에서 한창 개발 단계인 과정 속에서 발생한 이슈에 대해서 고민해보고 팀원 들과 결론을 내린 이야기를 풀어보기 위해서 해당 글을 작성하게 되었습니다.

React 디자인 패턴은 현재(2022.07 기준)도 일반화 된 틀이 있는 시점은 아닌 것 같고, 그만큼 다양한 디자인 패턴들이 검색을 해보면 다양하게 언급되는 것을 알 수 있을 것입니다.

image.png

그 중, YAPP 프로젝트에서 저희 프론트엔드 팀원들 사이에서 언급된 React 디자인 패턴 2가지에 대한 이슈에 대해 살펴보겠습니다.

문제의 상황 🤔

저의 동아리 팀원 중 프론트엔드 개발자는 세 명이 존재합니다. 각자 본인이 공부하거나 현업에서 적용해오던 React 컴포넌트 디자인 패턴 기준이 있었습니다.

먼저, 제가 프로젝트에 적용하고 있던 컴포넌트 디자인 패턴에 가장 가까운 것은 Container - Presenter 패턴 이었습니다. 그로 인한 하나의 컴포넌트에 대한 폴더 구조 예시를 살펴보면 다음과 같습니다.

ComponentA
- index.tsx             // ComponentA`s Container 🔍
- ComponentAView.tsx    // ComponentA`s Presenter 🔍
- ComponentA.styled.ts  // ComponentA`s Styled Component (by.emotion)
- ComponentA.type.ts    // ComponentA`s Types
// ComponentA/index.tsx

...
import ComponentAView from './ComponentAView';

const ComponentA = () => {

  // 데이터 or 작업들

  return <ComponentAView {...props 로 내려줄 데이터 및 작업들} />;
};

export default ComponentA;
// ComponentA/ComponentAView.tsx

const ComponentAView = (props: propsType) => {

  return ( ... );  // View 는 Container 로 부터 내려받은 데이터 or 작업 바인딩
};

export default ComponentAView;

해당 방식을 통해서 추구하고자 한 궁극적인 목표는 로직과 단순한 뷰를 최대한 분리해서 관리(= 관심사의 분리, IoC) 를 실천하고 싶다는 것이었습니다. 프로젝트를 시작한 초기에는 모르겠지만, 점차 프로젝트 규모가 커진다는 것을 전제했을 때 하나의 컴포넌트 안에 로직과 뷰가 함께 존재할 수록 컴포넌트가 비대해지고 그만큼 유지보수하기 힘들 수 있다고 생각했기 때문입니다.

...

이와 비슷한 관점에서 다른 팀원이 추구하고 있던 방식에 가장 가까운 것은 Custom Hook 패턴 이었습니다. 그로인한 하나의 컴포넌트에 대한 폴더 구조 예시를 살펴보면 다음과 같습니다.

ComponentA
- index.tsx             // ComponentA 🔍
- ComponentA.styled.ts  // ComponentA`s Styled Component (by.emotion)
- ComponentA.type.ts    // ComponentA`s Types

...
hooks/useMyCustomHook.tsx
import { useMyCustomHook } from "hooks/useMyCustomHook"

const ComponentA = () => {

  const { ... } = useMyCustomHook(...);    // 커스텀 훅을 통해서 데이터 or 작업을 받음

  return ( ... );    // 커스텀 훅을 통해 얻어낸 데이터 or 작업을 바인딩
};

export default ComponentA;

앞선 Container - Presenter 패턴 처럼 로직을 담당하는 Container 컴포넌트가 뷰를 담당하는 Presenter 컴포넌트를 감싸는 형태가 아닌, 하나의 컴포넌트 형태이면서 복잡한 로직들은 Custom Hook 을 통해 단순히 호출해서 필요한 데이터와 작업들을 받고 뷰에 바인딩해서 렌더링하는 방식입니다.

...

일단, 두 방식이 프로젝트를 진행하는 데 당장 크게 문제를 일으키는 이슈는 아니긴 합니다. 중요한 것은 어찌되었든 팀끼리 하나의 방식을 통일 하는 것이 당장에 이슈였습니다.

나의 생각 정리 💆🏻‍♂️

나의 생각 정리 이후 팀원에게 공유

image.png

팀원들의 답변

image.png

image.png

마치며...

해당 이슈가 오프라인에서 이야기에서 나올 당시에는 위에 첨부한 팀원들에게 공유한 저의 생각 정리만큼 정돈된 의견을 잘 전달하지 못했다고 생각들었습니다. 그래서 위와 같이 좀 더 관련된 내용을 조사하고 정리해서 공유를 하게 되었고, 이와 같은 사례를 이 글에 공유하게 되었습니다.

결과적으로는 Custom Hook 패턴 방식으로 진행하는 것으로 컨벤션을 통일하기로 했고 대략적인 구조는 다음과 같습니다.

ComponentA
- index.tsx             // ComponentA 🔍
- ComponentA.styled.ts  // ComponentA`s Styled Component (by.emotion)
- ComponentA.type.ts    // ComponentA`s Types
- useCustomHook1.tsx    // ComponentA`s 에만 사용되는 Custom Hook (여러 개일 수 있음)
- ...

...
hooks/
- 여러 컴포넌트들이 공유가능 Custom Hook 들은 hooks 디렉터리에서 관리

덕분에 이번 기회를 통해서 VAC(View Asset Component) 패턴 이라는 것을 새로 알게 되었고, 당장 진행 중인 프로젝트에는 적용하진 못하고 있지만 이후 리팩터링 과정에서 또는 새로운 프로젝트를 진행하면서 FE 와 UI 를 좀 더 체계적으로 분리해서 관리하고 싶을 때 시도해보고 싶습니다.

이와 별개로 이번 이슈를 통해 팀원들과 이야기하며 제가 공감하게 된 내용은 다음과 같습니다.

💡 다양한 디자인 패턴이 있지만 정답은 없습니다. 단지 그 때 우리의 상황에 가장 알맞은 방식을 추구하는 것이 최선입니다.

cf. 깃헙 커밋 메시지 컨벤션, 코드 포맷팅 등과 함께 이러한 컴포넌트 디자인 패턴 또한 프로젝트 시작에 앞서 컨벤션을 통일하는 것이 가장 바람직하다고 생각이 들었습니다. (프로젝트 시작 전에 결정되면 가장 좋고, 빠르면 빠를수록 좋은 것 같습니다 😂)

감사합니다.


참고 자료

K

You've come this far and I think that's great, keep chasing your dreams and one day you'll reach the top and then you'll see how great you've become . https://iogamesio.org

More from this blog

[코어 자바스크립트] 02.실행 컨텍스트

실행 컨텍스트 실행 컨텍스트(execution context) 는 실행할 코드에 제공할 환경 정보들을 모아넣은 객체 ( JavaScript 가 왜 동적 언어인지 성격을 가장 잘 파악할 수 있는 개념 ) 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고, 이를 콜 스택(call stack) 에 쌓아올렸다가, 스택 자료구조처럼 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환...

Sep 25, 20228 min read

[JS 딥다이브] Iterable 객체

개요 JS 개발을 하다보면, Iterator, Array-like 같은 키워드를 볼 수 있고, 이런 자료형이어야 작동하는 프로세스들을 볼 수 있었을 것이다. JS ES6+ 에는 새로운 문법이나 Built-in Object 뿐만 아니라, protocols(표현법들)도 추가되었다. 이 protocol은 일정 규칙만 충족한다면, 어떠한 객체에서 의해서도 구현될 수 있다. 이러한 프로토콜은 2가지가 있다. Iterable protocol Iter...

Aug 27, 20229 min read

npm 과 yarn 은 뭐가 다를까 ?

개요 이전 시간에 npm 과 npx 에 대해 비교해봤다. 이번에는 npm과 yarn 에 대해 비교해본다. 평소에 JS 프로젝트를 진행하면서 npm 으로 패키지를 관리하는데, 뭔가 무겁다 정도의 느낌을 받을 정도로 개발을 해왔던, 조금이라도 그런 느낌을 받았다면 이 포스팅이 조금은 도움이 되리라. 본론 📍 npm 이전 시간에 "정의"에 대해서는 정리를 하였으니 간략하게. Node Package Manager(Javascript Node...

Aug 20, 20223 min read

Youngmin's Blog

11 posts