8개월 차, 아직도 컴포넌트 분리를 헷갈리는 이유

8개월 차, 아직도 컴포넌트 분리를 헷갈리는 이유

8개월 차, 아직도 컴포넌트 분리를 헷갈리는 이유

오늘도 코드리뷰에서 혼났다

출근하자마자 슬랙 알림. 심장이 쿵 내려앉았다.

“이신입님, 이 컴포넌트 너무 크지 않나요? 분리하면 좋을 것 같은데요.”

민수 선배다. 항상 친절하게 말하지만 그게 더 무섭다. 어제 올린 PR이었다. UserProfile.jsx 파일. 300줄짜리.

“아… 네네 수정하겠습니다.”

일단 답장부터. 그리고 코드를 다시 봤다. 뭘 분리하라는 건지 솔직히 모르겠다. 전부 프로필 관련 코드인데.

프로필 사진, 이름, 소개, 팔로우 버튼, 게시글 목록, 좋아요 수. 다 유저 프로필이잖아. 그럼 UserProfile 컴포넌트에 있는 게 맞는 거 아닌가.

근데 선배는 분리하래.

8개월 됐다. 근데 아직도 모르겠다. 컴포넌트를 어떻게 나누는 게 정답인지.

부트캠프 때는 간단했다. 헤더는 Header.jsx, 버튼은 Button.jsx. 그게 끝이었다. 근데 실무는 다르다.

UserProfile.jsx를 열면 그 안에 또 뭐가 들어가야 하는지. ProfileHeader? ProfileInfo? UserAvatar? FollowButton? 어디까지가 한 덩어리고 어디서부터 분리해야 하는지.

그냥 다 한 파일에 쓰면 안 되나. 길어도 Ctrl+F 하면 찾을 수 있는데.

선배들이 말하는 ‘재사용성’

“재사용 가능하게 만들어야죠.”

코드리뷰 댓글에 항상 나오는 말. 재사용성.

근데 뭘 재사용한다는 건지 모르겠다. 이 프로필 페이지는 프로필 페이지에서만 쓰는데. 다른 데서 언제 쓴다고.

FollowButton을 분리했다. 그럼 다른 페이지에서도 팔로우 버튼 쓸 수 있으니까 재사용 가능한 거다. 이해했다고 생각했다.

근데 일주일 뒤 또 지적받았다.

“ProfileInfo도 분리하면 좋을 것 같아요.”

ProfileInfo는 이름이랑 소개 보여주는 부분. 이건 어디서 재사용해. 프로필 페이지에서만 쓰는데.

물어봤다. 용기 내서.

“선배님, 근데 ProfileInfo는 프로필에서만 쓰지 않나요?”

“지금은 그렇죠. 근데 나중에 모달에서도 쓸 수도 있고, 카드 형태로 보여줄 수도 있잖아요.”

나중에. 모달. 카드.

모르겠다. 나중은 언제고 모달은 아직 없는데 지금 분리하라는 건가.

그래서 분리했다. ProfileInfo.jsx. 그 안에 이름이랑 소개만 넣었다. 30줄.

30줄짜리 파일을 만드는 게 맞나. components 폴더 열 때마다 파일이 수십 개다. 뭐가 뭔지 모르겠다.

Button.jsx, CustomButton.jsx, StyledButton.jsx, PrimaryButton.jsx. 다 버튼인데 뭐가 다른 건지. 누가 정리 좀 해줬으면 좋겠다.

컴포넌트 분리의 기준이 뭔데

구글링했다. “React 컴포넌트 분리 기준”.

블로그마다 다르다.

어떤 글은 “50줄 넘으면 분리하세요”래. 그럼 난 이미 300줄인데 6개로 쪼개야 하나.

어떤 글은 “단일 책임 원칙”이래. 하나의 컴포넌트는 하나의 일만. 그게 뭔데. 프로필 보여주는 게 한 가지 일 아닌가.

어떤 글은 “props가 5개 넘으면 분리”래. 그럼 지금 당장 분리해야 할 게 10개는 넘는다.

유튜브도 봤다. 영상마다 다르다.

“작게 쪼갤수록 좋습니다.” vs “너무 잘게 쪼개면 오히려 복잡해져요.”

둘 다 맞는 말 같은데 반대다. 뭘 믿어야 하지.

ChatGPT한테 물어봤다. 코드 붙여넣고 “이거 어떻게 분리하면 좋을까요?”

3가지 방법을 알려줬다. 전부 다른 방법. 어느 게 정답이래.

“상황에 따라 다릅니다.”

상황. 그 상황을 내가 모르는데 어떡하라고.

분리했더니 props 지옥

결국 분리했다. UserProfile을 5개로 쪼갰다.

ProfileHeader, ProfileAvatar, ProfileInfo, FollowButton, PostList.

뿌듯했다. 이제 각 파일이 50줄 정도. 깔끔하다. PR 올렸다.

“props drilling이 너무 심한 것 같아요.”

뭐라고.

UserProfile에서 userId를 받아서 ProfileHeader한테 넘기고, ProfileHeader가 또 ProfileAvatar한테 넘기고, ProfileAvatar가 이미지 URL 받아오려고 또…

props가 3단계를 내려간다. userId -> ProfileHeader -> ProfileAvatar -> 실제 사용.

“Context API 쓰시거나 상태관리 라이브러리 고려해보세요.”

Context API. 배웠다. 근데 언제 쓰는 건지 모르겠다. 이 정도면 쓰는 건가. 아직 안 쓰는 건가.

Zustand? Recoil? Redux는 너무 어렵다고 하던데. 뭘 선택해야 하나.

일단 물어봤다. 또.

“선배님, 이거 Context 써야 할까요?”

“음… 지금은 괜찮을 것 같은데요. 나중에 상태가 복잡해지면 그때 고민해봐요.”

나중에. 또 나중에.

그래서 원래대로 돌렸다. props 3개만 넘기게. 근데 그러니까 ProfileHeader가 너무 많은 일을 한다고 또 지적받았다.

“ProfileHeader가 너무 많은 책임을 가지고 있네요.”

책임. 또 책임.

뭐가 책임인지 모르겠다. 그냥 props 전달하는 건데. 이것도 책임인가.

결국 정답은 없다는 걸 깨달았다

3주 걸렸다. 한 페이지 리팩토링하는 데.

처음 300줄 UserProfile.jsx는 이제 10개 파일이 됐다. components/profile 폴더에 들어가면 파일이 즐비하다.

ProfileHeader.jsx ProfileAvatar.jsx ProfileBadge.jsx ProfileInfo.jsx ProfileBio.jsx FollowButton.jsx FollowStats.jsx PostList.jsx PostItem.jsx PostImage.jsx

10개. 원래 하나였는데.

깔끔한가. 모르겠다. 파일 찾으려고 왔다 갔다 하는 게 더 불편한 것 같기도 하다.

근데 민수 선배는 좋다고 했다.

“이제 훨씬 읽기 좋네요. 수고했어요.”

읽기 좋다고. 진짜 그런가. 난 아직도 헷갈리는데.

어제 신입이 한 명 더 들어왔다. 나보다 3개월 늦게. 이름은 김신입.

“선배님, 컴포넌트 어떻게 나누는 게 좋아요?”

물어봤다. 나한테. 선배라고.

“음… 재사용 가능하게? 그리고 너무 길어지면 분리하고…”

내가 하는 말이 민수 선배랑 똑같다. 웃겼다.

근데 김신입이 물었다.

“그럼 몇 줄 정도가 적당한가요?”

“그게… 상황에 따라 달라요.”

이 말을 내가 하고 있다. 3주 전에 제일 듣기 싫었던 말을.

아직도 모르지만 조금 알 것 같기도 하다

오늘도 컴포넌트 분리했다. 새로운 기능. 장바구니 페이지.

처음부터 나눴다. ShoppingCart.jsx 하나에 다 쓰지 않았다.

CartHeader, CartItem, CartSummary, CheckoutButton.

4개로 시작했다. 200줄이 4개 파일, 50줄씩.

PR 올리기 전에 스스로 봤다. CartItem이 좀 긴 것 같다. 80줄.

분리했다. CartItemImage, CartItemInfo, CartItemQuantity.

혼자 했다. 지적받기 전에.

뿌듯했다. 조금. 아주 조금.

그리고 민수 선배가 approve 눌렀다. 댓글 없이.

댓글 없는 게 제일 좋은 거다. 배웠다.

여전히 모른다. 정확한 기준 같은 건. 몇 줄에서 나누고, 어떤 이름을 붙이고, props를 몇 개까지 넘기고.

근데 계속 하다 보니까 감이 생긴다. 이 정도면 분리해야겠다. 이건 하나여도 되겠다.

틀릴 때도 있다. 많다. 근데 틀리면 또 고치면 된다. 3주 걸려도 되고.

8개월 차. 아직도 주니어. 컴포넌트 분리는 여전히 어렵다.

근데 3개월 전보다는 덜 어렵다. 그게 성장인가 보다.

내일도 분리하겠지. 또 헷갈리겠지. 그래도 해본다.


김신입한테 알려줄 건 생겼다. “일단 해봐. 틀려도 돼.”