Summary


이 글은 미션을 수행하며 학습했던 컴포넌트 분리 기준에 대한 내용을 정리한 것입니다. 컴포넌트 분리에 대한 절대적인 기준이 없어 여러 선행자분들의 의견을 참고하고자 아래 3가지 강의를 참고해 공통적인 부분을 거르고, 이후 개인적인 의견을 간단히 남기고자 하였습니다.

 

첫 두 강의의 공통점은, "컴포넌트를 쪼개는 절대적 기준 같은 것은 없다. 하지만 상대적으로 잘 쪼개는 컴포넌트 분리 기준은 존재한다."는 것이었는데요, 두 분 모두 '유지보수를 쉽게 하는'것에 기준을 두고 컴포넌트 분리를 설명하신 것이 인상 깊었습니다. 유지보수를 쉽게 하려면 어떻게 해야할까요? 데이터를 미래에 변할 수 있는 것과 상대적으로 잘 변하지 않을 데이터를 구분하는 것이었습니다.

 

조금 더 구체적으로는, 첫 강의자인 원지혁님은 컴포넌트의 구성을 스타일, 로직, 전역상태, 리모드 데이터 스키마(데이터)로 분리하셨고, 유지보수를 위해 변화가 가장 잘 일어나는 데이터 모델에 따라 컴포넌트 분리를 해주는 것을 추천하셨습니다. 두 번째 강의의 한재엽님은 변하는 것에 앞서 설명된 데이터를 데이터계산과 상호작용으로 나누셨습니다. 결국 둘 다 데이터 관리부분인데 처음부터 제공되는 데이터냐, 사용자의 액션이 있어야 계산되는 데이터냐에 따라 한 번 더 나누신듯하다. 변하는 부분을 데이터, 변하지 않는 부분을 UI로 잡고 분리한다는 점에서 원지혁님과 의견이 같았습니다. 두 강의자분 다 컴포넌트 분리의 기준을 유지보수로 잡고 계시고, 상대적으로 잘 변하는 것, 즉 컴포넌트가 다루는 데이터를 기준으로 컴포넌트를 분리하는 것을 제안하신다는 데에서 동일했습니다.

 

결론적으로, 저도 유지보수를 쉽게하는 컴포넌트 분리 기준으로 데이터 모델을 잡는 것에 설득되었습니다. 이 데이터를 변경가능성이 높은 데이터인지, 그렇지 않은 데이터인지 - 즉, 도메인 관련인지 아닌지로 나누는 방법이 좋다는 것도 이해하였습니다. 더하여 데이터는 훅스, UI관련은 컴포넌트, 상태관리는 store 등으로 나누는 기준에 동의합니다. 앞으로 리액트를 활용한 개발에 있어서 컴포넌트 분리는 이러한 기준으로 하고자 합니다. (하지만 컴포넌트 분리에 절대적인 기준이 없는 만큼 이 글을 보시는 분들의 다양한 의견에도 열려있습니다.)

 


강의

당근마켓, 원지혁 - 컴포넌트, 다시 생각하기


요약

  • 바라보기: React 컴포넌트의존성 - React 컴포넌트를 만드는데 필요한 것들은 어떤 것들이 있을까?
    • 기능적 분류(Type): props 와 hooks
    • 특징적 분류(Feature):
      • 스타일(컴포넌트의 스타일, src/components/Something.css)
      • 로직(UI조작에 필요한 커스텀 로직, src/components/Something.useInfinityScroll.ts),
      • 전역 상태(현재 UI를 표현하기 위해 유저의 액션을 통해 초래된 상태, src/store.ts)
      • 리모트 데이터 스키마(API 서버에서 내려주는 데이터의 모양, https://examples.com/api/v2/articles/json)
    • React 컴포넌트의 숨은 의존성
      • 한 컴포넌트에 정보를 추가한다고 하자. 그 컴포넌트에 새로운 props 를 추가하면 된다.
      • 하지만, 그게 끝이 아니다. 숨은 의존성이 존재한다. 타겟 컴포넌트와 루트 컴포넌트 사이의 props들의 추가 수정이 필연적일 수 밖에 없다. props drilling 없이 따로 store를 둔다해도 페이지 기반 라우팅을 한다면 결국 root 컴포넌트에 의존할 수 밖에 없을 것이다. 즉, 해당 컴포넌트에 새로운 정보(의존성)를 추가하기 위해서는 root 컴포넌트 수정도 필연적이다.
  • 함께 두기(co-locate): 이러한 의존성들을 어떻게 정리할 수 있을까?
    • 원칙1 - 비슷한 관심사라면 가까운 곳에(Keep Locality)
      • 한 컴포넌트에 필요한 스타일과 로직은 함께 두기 쉽다.
      • 전역상태는 여러 컴포넌트가 공유하고 있기 때문에 특정 컴포넌트와 함께 두기 어렵다.
      • 리모트 데이터 스키마 함께두기는 좀 더 복잡하므로 원칙2로 따로 분류해보자.
    • 원칙2 - 데이터를 ID 기반으로 정리하기 (Abstraction by Normalization)
      • 데이터 정규화(Normalization) 이라고도 한다.
        • yarn add mormalizer : 정규화를 도와주는 라이브러리
        • 하지만 여전히 숨은 의존성 문제는 존재한다: 사용 컴포넌트의 상위 컴포넌트에서 id 값을 정확히 받아와야 한다.
      • 글로벌 아이디(Global Id): 모델명을 따로 넘길 필요 없이 ID값만 가지고 특정 데이터를 유일하게 식별할 수 있도록 하는 체계.(상위 컴포넌트에서 ID값을 받아올 필요가 없다.)
        • 예시: 첫번째는 필요한 데이터를 바깥(./store.ts)에서 받아오고 있고, 두번째에서는 GlobalId를 이용해서 id 데이터를 같은 컴포넌트 안에 둘 수 있다! (16:02)
        • 도우미: 전역 객체 식별 (Global Object Identification, GOI): (17:02)
  • 이름 짓기(Naming): 프롭스 네이밍(Props Naming)에 대해서 생각해보자.
    • 원칙3 - 의존한다면 그대로 드러내기(Make Explicit)
      • 프로필 컴포넌트 - User 와 User가 의존하고 있는 Image, 이렇게 크게 2가지 데이터에 의존하고 있다. 2번째는 User와 Image의 의존성까지 보여주는 이름짓기를 활용해 더 직관적으로 의존성을 알 수 있다!
      • 하지만 위와 같이 한 컴포넌트에서 여러 모델의 정보(User 컴포넌트 내에 user 뿐 아니라 image 정보도 받아오고 있다.)를 표현하는 것은 일종의 관심사 분리가 제대로 안되었다는 일종의 신호이기도 하기에 아래와 같이 수정해주면 더욱 좋다.
    • 재사용하기(Reuse): 개발할 때 편리하기 위한 것보다 변경할 때 편리하기 위해 = 유지보수에 편하기 위해!
      • 변화하는 부분을 미리 예측하고 컴포넌트를 나누는게 중요하다.
        • 대부분의 변화는 리모트 데이터 스키마가 변화하는 방향을 따라서 움직인다.
        • 그렇다면 어떻게 변하는 것들과 변하지 않는 것들을 분리할 수 있을까?
    • 원칙4 - 데이터 모델 기준으로 컴포넌트 분리하기, Separating Components by Data model
      • 같은 모델을 의존하는 컴포넌트: 재사용
      • 다른 모델을 의존하는 같은 컴포넌트: 분리
  • 결론(Conclusion)
    • 원칙 요약
      • 원칙1 - 비슷한 관심사라면 가까운 곳에
      • 원칙2 - 데이터를 Id 기반으로 정리하기
      • 원칙3 - 의존한다면 그대로 드러내기
      • 원칙4 - 모델 기준으로 컴포넌트 분리하기
    • 추가
      • 이러한 위 4가지 원칙을 강제해서 리액트 클라이언트 개발을 더 편하게 해주는 GraphQL 데이터 레이어 프레임워크 Relay 를 소개해주시면서 강의를 마치셨다.

강의

토스슬래시, 한재엽: Effective Component 지속 가능한 성장과 컴포넌트


요약

  • 무엇이 변경될지 알았다면… 변경은 예측불가하다. 그래서 변경은 예측하지 말고 대응해야 한다.
  • 변경에 대응하기: 변경에 유연하게 대응하도록 컴포넌트를 나누기
    • 만들다보니 페이지가 커지고, 이 커진 코드를 ‘적당히’ 나누기 → ‘적당히’: 변경에 유연하게 대응하도록
    • 어떻게 하면 변경에 유연하게 대응하도록 컴포넌트를 분리할 수 있을까?
      1. Headless 기반의 추상화하기: 변하는 것 vs 상대적으로 변하지 않는 것
      2. 한 가지 역할만 하기: 또는 한가지 역할만 하는 컴포넌트의 조합으로 구성하기
      3. 도메인 분리하기: 도메인을 포함하는 컴포넌트와 그렇지 않은 컴포넌트 분리하기
  • Headless 기반의 추상화하기
    • 컴포넌트는 크게 3가지 역할을 한다:
      • 데이터 관리: 외부에서 받은 데이터, 상태과 같은 내부 데이터를 어떻게 관리하는지
      • UI 관리: 그러고 이러한 데이터를 어떻게 유저에게 보여줄지(UI)
      • 상호작용: UI를 기반으로 어떻게 사용자와 상호작용할지
    • 데이터와 UI의 분리. 컴포넌트를 구성하는데 필요한 데이터를 계산해야 하는데 이 역할을 use~훅스에 위임한다. 이러한 use~훅스는 UI를 관심사에서 제외하고 오직 데이터를 모듈화 하는데에만 집중할 수 있다.
    • UI와 상호작용 분리: 상호작용 부분도 역시 훅스로 만들어 관리한다.
  • 한 가지 역할만 하기(Composition)
  • 도메인 분리하기
    • UI패턴 공통화
  • 결론: 컴포넌트 분리시 고민해야 하는 것
    • 의도가 무엇인가? 분리하면 어떻게 좋아지는가?
    • 이 컴포넌트의 기능은 무엇인가?: 어떤 데이터를 다루는가?
    • 어떻게 표현되어야 하는가?

강의

당근마켓 원지혁 : 그래서 DECLARATIVE가 뭔데?


Declarative UI 패턴을 통해 자바스크립트를 마치 마크업짜듯 작성할 수 있게 되었다 → HTML, CSS / JavaScript 가 아니라 “관심사(정보)”를 기준으로 분리하게 되었다.

정보는 트리구조가 아니다! (함수형-순서형이 아니다!) 정보는 그래프 형태이다!

 

단일 진실 공급원 Single source of Truth

특정 상태가 변경되었을 때, 다른 부수효과를 최소로 하기 위해 단일 상태로 만들자. → ID 하나만 가지고 찾자. (Normalization) React가 UI에 대한 HOW를 제공한다면, GraphQL은 데이터에 대한 HOW를 제공한다.

 

선언적으로 데이터 요청하기 Declarative Data Fetching

리액트 컴포넌트는 데이터에 의존한다. 리액트는 어떤 정보(WHAT)가 필요한지만 요청한다. GraphQL 같은 라이브러리는 데이터를 어떻게(HOW)를 담당해 알아서 데이터를 처리해 넘겨준다. 결국 **선언적(Declarative)**란 공통된 HOW를 잘 분석해서 꺼내고 이를 통해 내 코드에 WHAT을 잘 뭉치는 과정. 이를 위해 HOW와 WHAT을 잘 가르는 안목이 필요하다.

 

'Programming > 웹 프론트엔드' 카테고리의 다른 글

[React] 비동기함수 Hook으로 다루기  (0) 2023.05.30

+ Recent posts