반응형

리액트 컴포넌트 설계 패턴 정리, 주의해서 잡아야 할 뼈대

리액트 컴포넌트 설계 패턴 정리, 주의해서 잡아야 할 뼈대

처음 리액트 화면을 만들 때는 일단 동작만 되면 된다고 생각하기 쉽죠. 그런데 조금만 커지면 프롭이 길어지고 상태가 꼬이고, 같은 UI가 여기저기 복붙되면서 유지보수가 확 불편해집니다. 그래서 컴포넌트 설계 패턴을 미리 잡아두는 게 꽤 중요해요.

저는 이 글을 정리하면서, 작은 화면 하나를 붙였다 떼는 식으로 여러 번 돌려봤습니다. 결과는 비슷했어요. 구조를 잘 잡은 화면은 수정이 편했고, 대충 넘긴 화면은 금방 무거워졌습니다. 진짜 그랬어요.

기초: 리액트 컴포넌트는 왜 쪼개야 할까

리액트 공식 문서를 확인하면, 화면을 작은 조각으로 나누고 조각을 다시 조합하는 흐름이 핵심으로 나옵니다. 이때 중요한 건 단순히 파일을 나누는 게 아니에요. 책임을 나누는 것입니다. 입력을 받는 역할, 화면을 그리는 역할, 상태를 들고 있는 역할이 섞이면 금방 복잡해져요.

간단합니다.

  • 보여 주기만 하는 컴포넌트
  • 상태를 관리하는 컴포넌트
  • 공통 동작을 묶는 컴포넌트
  • 여러 UI를 조합하는 상위 컴포넌트

이 네 가지를 분리해 두면, 나중에 수정할 때 손이 덜 갑니다. 예전엔 하나의 컴포넌트에 다 넣는 경우가 많았는데, 그때는 버튼 하나 바꾸는 일도 꽤 번거로웠어요. 반대로 지금은 흐름이 보여요. 입력은 위에서, 표시만 아래에서. 끝.

⚠️

화면이 복잡해질수록 “한 컴포넌트가 한 일만 한다”는 원칙이 더 빛납니다. 상태를 무조건 위로 끌어올리기보다, 필요한 곳에만 두는 쪽이 대체로 더 낫습니다.

조금 더 깊이 들여다보기

여기서 많이 쓰는 패턴은 크게 네 갈래로 보면 편합니다. 이름은 어렵게 보여도, 실제로는 꽤 단순해요.

패턴 쓰는 때 장점 주의점
표시 전용 분리 화면만 보여 줄 때 재사용이 쉽다 상태를 넣지 말아야 한다
상태 끌어올리기 여러 컴포넌트가 같은 값을 쓸 때 값이 한곳에서 맞는다 너무 위로 올리면 오히려 무거워진다
합성 겉모양은 같고 안이 바뀔 때 조합이 유연하다 프롭 이름을 너무 많이 만들면 복잡하다
자식 요소 주입 틀은 같고 내용만 바뀔 때 레이아웃 재사용이 좋다 구조가 흐려지지 않게 봐야 한다

돌이켜보면, 저는 프롭 드릴링이 길어질 때 합성을 먼저 떠올립니다. 그때는 몰랐는데, 공통 틀을 만들고 안쪽만 바꾸는 방식이 생각보다 강력하더라고요. 공식 문서를 확인하면 이런 방향을 자주 권하는데, 이유가 있어요. 나중에 화면이 늘어나도 설계가 덜 흔들리거든요.

또 하나. 상태 관리가 애매할 때는 “정말 이 값이 여기서 필요하냐”를 한 번만 더 봐야 합니다. 잘 모르겠지만 대부분의 꼬임은 상태를 너무 일찍, 너무 멀리 올려 둔 데서 시작하더라고요.

실전 적용 사례

에센셜이 가장 자주 정리하는 흐름은 이겁니다.

  1. 먼저 표시 요소를 나눕니다
  2. 그다음 상태가 필요한 범위를 찾습니다
  3. 반복되는 뼈대를 합성으로 묶습니다
  4. 마지막에 공통 동작만 훅으로 뽑습니다

이 순서로 가면 생각보다 덜 흔들려요. 예를 들어 목록 화면에서 카드, 필터, 정렬, 빈 화면이 한데 얽혀 있으면 처음엔 빨라 보이지만, 수정이 시작되면 바로 느려집니다. 이럴 때는 카드 표시, 목록 제어, 데이터 가공을 분리하는 게 좋습니다. 살짝 번거로워 보여도, 나중에 훨씬 편해요.

공식 릴리스 노트에 따르면 리액트 18.2.0 이후로도 개발 방식의 핵심은 비슷합니다. 컴포넌트는 작게, 동작은 예측 가능하게, 경계는 분명하게. 이 방향이 잘 맞습니다.

또 한 가지 실전 포인트가 있어요. 개발 모드에서 함수가 두 번 불린 것처럼 보여서 “버그다!” 하고 놀라는 경우가 있는데, 이건 리액트의 개발 모드 동작과 연결된 경우가 많습니다. GitHub 이슈 트래커에 따르면 facebook/react의 24502번 이슈처럼 이런 혼란이 오래 이야기돼 왔어요. 저는 이런 상황을 만나면 렌더 안에서 부작용이 돌고 있는지 먼저 봅니다. 의외로 거기서 풀립니다.

공개 토론에서도 비슷한 얘기가 반복됩니다. 예를 들면 Stack Overflow의 composition vs inheritance in react 질문도 결국 같은 결론으로 모여요. 상속보다 조합이 더 잘 맞는다는 쪽이죠.
참고 링크:

  • https://react.dev/learn/thinking-in-react
  • https://github.com/facebook/react/releases/tag/v18.2.0
  • https://stackoverflow.com/questions/28269603/composition-vs-inheritance-in-react
  • https://github.com/facebook/react/issues/24502

오늘 배운 것 핵심 정리

짧게 묶으면 이렇습니다.

  • 컴포넌트는 기능이 아니라 책임 기준으로 나누기
  • 상태는 필요한 곳에만 두기
  • 반복되는 틀은 합성으로 묶기
  • 표시와 동작을 섞지 않기
  • 개발 모드의 이상 동작처럼 보이는 현상은 먼저 구조를 의심하기

이 흐름만 잡아도 화면이 훨씬 덜 지저분해집니다. 뭔가 거창한 비법이라기보다, 계속 유지할 수 있는 습관에 가깝죠.

마무리

리액트 컴포넌트 설계 패턴 정리는 결국 “어떻게 나눌까”보다 “어떻게 덜 꼬이게 만들까”에 더 가깝습니다. 처음엔 단순해 보여도, 화면이 커질수록 이 차이가 꽤 커져요. 오늘은 표시 전용 분리, 상태 끌어올리기, 합성, 자식 요소 주입 이 네 가지부터 잡아 보시면 됩니다.

끝까지 읽어주셔서 고맙습니다. 궁금한 점은 댓글로 알려주세요. 이 글이 조금이라도 도움이 됐다면 다음 글도 기대해 주세요.

자주 묻는 질문

Q. 리액트 컴포넌트는 얼마나 잘게 나누는 게 좋나요?
A. 한 컴포넌트가 한 가지 책임만 자연스럽게 가지면 됩니다. 너무 잘게 쪼개서 오히려 읽기 어려워지면 그건 과한 편이에요.

Q. 합성과 자식 요소 주입은 언제 쓰면 좋나요?
A. 겉틀은 같은데 안쪽 내용만 달라질 때 좋습니다. 공통 레이아웃을 재사용하려는 상황에서 특히 유용해요.

Q. 상태를 위로 올리는 건 항상 좋은가요?
A. 아니요. 여러 컴포넌트가 같은 값을 봐야 할 때만 올리는 편이 낫습니다. 무조건 올리면 오히려 복잡해질 수 있어요.

Q. 개발 모드에서 두 번 실행되는 것처럼 보이면 어떻게 하나요?
A. 먼저 렌더 안에 부작용이 들어갔는지 보세요. 호출 위치를 정리하면 대부분 해결 실마리가 나옵니다.

Q. 초보자에게 가장 먼저 추천할 패턴은 뭔가요?
A. 표시 전용 컴포넌트 분리와 상태 끌어올리기부터요. 이 두 가지만 잘해도 구조가 꽤 안정됩니다.

#리액트 #컴포넌트설계 #합성패턴 #프롭드릴링 #웹개발

반응형
Posted by no_name
: