Skip to content

Conversation

@daehyunk1m
Copy link

@daehyunk1m daehyunk1m commented Dec 8, 2025

제출 링크

과제 체크포인트

기본과제

목표 : 전역상태관리를 이용한 적절한 분리와 계층에 대한 이해를 통한 FSD 폴더 구조 적용하기

  • 전역상태관리를 사용해서 상태를 분리하고 관리하는 방법에 대한 이해
  • Context API, Jotai, Zustand 등 상태관리 라이브러리 사용하기
  • FSD(Feature-Sliced Design)에 대한 이해
  • FSD를 통한 관심사의 분리에 대한 이해
  • 단일책임과 역할이란 무엇인가?
  • 관심사를 하나만 가지고 있는가?
  • 어디에 무엇을 넣어야 하는가?

체크포인트

  • 전역상태관리를 사용해서 상태를 분리하고 관리했나요?
  • Props Drilling을 최소화했나요?
  • shared 공통 컴포넌트를 분리했나요?
  • shared 공통 로직을 분리했나요?
  • entities를 중심으로 type을 정의하고 model을 분리했나요?
  • entities를 중심으로 ui를 분리했나요?
  • entities를 중심으로 api를 분리했나요?
  • feature를 중심으로 사용자행동(이벤트 처리)를 분리했나요?
  • feature를 중심으로 ui를 분리했나요?
  • feature를 중심으로 api를 분리했나요?
  • widget을 중심으로 데이터를 재사용가능한 형태로 분리했나요?

심화과제

목표: 서버상태관리 도구인 TanstackQuery를 이용하여 비동기코드를 선언적인 함수형 프로그래밍으로 작성하기

  • TanstackQuery의 사용법에 대한 이해
  • TanstackQuery를 이용한 비동기 코드 작성에 대한 이해
  • 비동기 코드를 선언적인 함수형 프로그래밍으로 작성하는 방법에 대한 이해

체크포인트

  • 모든 API 호출이 TanStack Query의 useQuery와 useMutation으로 대체되었는가?
  • 쿼리 키가 적절히 설정되었는가?
  • fetch와 useState가 아닌 선언적인 함수형 프로그래밍이 적절히 적용되었는가?
  • 캐싱과 리프레시 전략이 올바르게 구현되었는가?
  • 낙관적인 업데이트가 적용되었는가?
  • 에러 핸들링이 적절히 구현되었는가?
  • 서버 상태와 클라이언트 상태가 명확히 분리되었는가?
  • 코드가 간결하고 유지보수가 용이한 구조로 작성되었는가?
  • TanStack Query의 Devtools가 정상적으로 작동하는가?

최종과제

  • 폴더구조와 나의 멘탈모데일이 일치하나요?
  • 다른 사람이 봐도 이해하기 쉬운 구조인가요?

과제 셀프회고

+12-8
에이전트 페어 프로그래밍을 위한 문서 세팅과 에이전트 세팅
클로드와 함께 에이전트 세팅과 프롬프트 문서를 다듬었더니 v5에 와선 나름 괜찮은 시스템이 된 것 같은데,
지난 주차와 같은 환경에선 거의 제대로 동작하지 않았다. 과제의 유형 케이스에 따라 성능이 갈릴 것으로 추측.

태스크 매니저 에이전트 사용시 결과물

좋은 질문들이에요! 하나씩 힌트를 드릴게요.

  ---
  💡 힌트

  1. DialogHeader 타입

  DialogHeader는 <div> 요소를 반환하고 있어요. 어떤 HTML
  요소의 속성을 상속받아야 할까요?

  힌트: DialogContentProps가 HTMLDivElement를 사용한 것처럼,
   동일한 패턴을 적용해보세요.

  ---
  2. highlightText 함수 위치

  JSX를 반환하는 함수의 위치에 대한 고민이시네요.

  질문을 던져볼게요:
  - highlightText는 어떤 도메인에서 사용되나요? (Post?
  Comment? 둘 다?)
  - 이 함수가 검색 기능과 관련있다면, 어느 레이어가
  적절할까요?

  FSD 관점에서 생각해보세요:
  - shared/lib → 도메인에 독립적인 순수 유틸리티
  - shared/ui → 도메인에 독립적인 UI 컴포넌트
  - features/search → 검색 기능과 관련된 로직

  ---
  3. API 함수들 분류

  나열하신 함수들을 도메인별로 분류해보세요:

  | 도메인     | 함수  |
  |---------|-----|
  | Post    | ?   |
  | Comment | ?   |
  | User    | ?   |
  | Tag     | ?   |

  이렇게 분류하면 어느 레이어에 배치해야 할지 힌트가 보일
  거예요.

  추가 질문:
  - 이 함수들은 shared/api에 가야 할까요, 아니면
  entities/post/api에 가야 할까요?
  - FSD의 의존성 방향을 생각해보세요!

+12-9
760줄짜리 PostsManagerPage.tsx를 분석했다. 타입 정의,
API 호출, 상태 관리, UI 렌더링이 한 파일에 다 들어있었다.
"이걸 어떻게 나누지?"라는 막막함이 있었는데, FSD
레이어별로 하나씩 분리하면 된다는 걸 깨달았다.

Button, Card, Dialog 등 공통 UI 컴포넌트를 shared/ui로 분리했다.
DialogHeader 타입을 뭘로 해야 하나 고민했는데,
렌더링하는 요소(div)에 맞춰 HTMLDivElement로 하면 된다는 걸 알았다.
highlightText 함수 위치도 고민이었는데, 검색 기능에
종속적이니까 features/search로 가는 게 맞았다.

+12-10
entities 레이어 구성 완료
Post, User, Comment, Tag 4개 도메인을 분리했다.
model/types.ts에 타입, api/index.ts에 fetch 함수를 넣었다.
가장 고민했던 건 PostWithAuthor 타입 위치였다. Post +
User 조합인데 entities에 두면 서로 참조하게 돼서 FSD 규칙 위반이었다.
결국 "조합은 상위 레이어에서"라는 원칙으로 features에 두기로 했다.
API 함수도 순수하게 통신만 하고,
상태 업데이트(setPosts 같은)는 features에서 하는 게 맞다는 걸 배웠다.

+12-11
FSD 전체 레이어 구성 완료. shared → entities → features → widgets →
pages.
처음엔 "왜 이렇게 나누지?"였는데, 막상 완성하고 보니
"이 코드 어디 있지?"가 "당연히 저기 있겠지"로 바뀌었다.
의존성 방향이 한쪽으로만 흐르니까 수정할 때 영향 범위가 예측
가능해졌다.
구조가 곧 문서가 된다는 말을 이해했다.

이번 과제를 통해 이전에 비해 새롭게 알게 된 점이 있다면 적어주세요.

@x 패턴이라는 게 있다는 걸 처음 알았다.
PostWithAuthor처럼 Post + User를 조합한 타입을 어디에 둬야 할지 한참 고민했는데,
entities 간 참조가 필요할 때 @x 폴더로 명시적으로 표현하면 된다는 걸 배웠다.
FSD가 단순히 폴더 규칙이 아니라 "의존성을 어떻게 표현할 것인가"에 대한 철학이라는 게 와닿았다.

본인이 과제를 하면서 가장 애쓰려고 노력했던 부분은 무엇인가요?

"왜 이렇게 나눠야 하는가"를 이해하려고 노력했다.
처음엔 FSD 폴더 구조를 그냥 따라 만들면 되는 줄 알았는데, 막상 코드를 옮기다 보니 "이건 shared인가 entities인가?" 같은 판단이 계속 필요했다.

아직은 막연하다거나 더 고민이 필요한 부분을 적어주세요.

각 레이어마다의 경계가 아직 좀 모호하다.
"재사용 가능한 UI 조합"이면 widgets인데, post-filter처럼 기능이 섞인 건 어디로 가야 하는지.
일단은 "사용자 행동 = features, 데이터 표시 조합 = widgets"으로
구분했는데 맞는지 확신이 없다.

캐싱 전략도 더 파봐야 할 것 같다. staleTime을 1분으로 설정해놨는데, 실제 서비스에서는 어떤 기준으로 정해야
하는지 감이 안 온다.

이번에 배운 내용 중을 통해 앞으로 개발에 어떻게 적용해보고 싶은지 적어주세요.

다음 프로젝트에서는 처음부터 FSD 구조로 시작해보고 싶다.
이번엔 760줄짜리 컴포넌트를 나중에 쪼갠 거라 삽질이 많았는데,
처음부터 레이어 구분하면서 시작하면 훨씬 수월할 것 같다.

그리고 TanStack Query + Jotai 조합도 괜찮았다.
서버 상태는 Query로, 클라이언트 상태는 Atom으로 분리하니까
"이 상태는 어디서 관리하지?"라는 고민이 사라졌다.
낙관적 업데이트도 이번에 처음 적용해봤는데, 사용자 경험 차이가 커서
앞으로는 CRUD 있는 곳에 기본으로 넣어볼 생각이다.

챕터 셀프회고

클린코드와 아키테쳑 챕터 함께 하느라 고생 많으셨습니다!
지난 3주간의 여정을 돌이켜 볼 수 있도록 준비해보았습니다.
아래에 적힌 질문들은 추억(?)을 회상할 수 있도록 도와주려고 만든 질문이며, 꼭 질문에 대한 대답이 아니어도 좋으니 내가 느꼈던 인사이트들을 자유롭게 적어주세요.

클린코드: 읽기 좋고 유지보수하기 좋은 코드 만들기

  • 더티코드를 접했을 때 어떤 기분이었나요? ^^; 클린코드의 중요성, 읽기 좋은 코드란 무엇인지, 유지보수하기 쉬운 코드란 무엇인지에 대한 생각을 공유해주세요

1333줄짜리 단일 파일에 장바구니 계산 로직과 쿠폰 적용, 상품 관리, UI 상태가 전부 한 곳에 뒤섞여 있었습니다. "이 코드에서 할인 로직만 수정하려면 어디를 봐야하지?" 싶은 막막함이 있었습니다.

유지보수하기 쉬운 코드란 결국 변경의 영향 범위가 예측 가능한 코드라고 생각합니다. 1333줄짜리 파일에서는 한 줄 고치면 어디에 영향을 줄지 몰랐는데, 역할별로 분리하고 나니 "이건 여기만 고치면 되겠구나"가 명확해졌습니다.

결합도 낮추기: 디자인 패턴, 순수함수, 컴포넌트 분리, 전역상태 관리

  • 거대한 단일 컴포넌트를 봤을때의 느낌! 처음엔 막막했던 상태관리, 디자인 패턴이라는 말이 어렵게만 느껴졌던 시절, 순수함수로 분리하면서 "아하!"했던 순간, 컴포넌트가 독립적이 되어가는 과정에서의 깨달음을 들려주세요

디자인 패턴", "순수함수"라는 말은 알지만 이 엉킨 코드에 어떻게 적용할지 감이 안 왔습니다.

"아하!" 모먼트는 순수함수를 분리했을 때 다가왔습니다. calculateItemTotal은 CartItem을 받아서 가격을 리턴하면 끝이었습니다.
useState도 필요 없고, 컴포넌트도 몰라도 됩니다. 이렇게 계산 로직을 models/ 폴더에 빼놓으니 "할인 로직 수정? 여기만 보면 되겠구나"가 명확해졌습니다.
결국 "결합도를 낮춘다"는 건 관심사를 분리하는 단순한 원칙을 지키는것이라는 걸 깨달았습니다.

응집도 높이기: 서버상태관리, 폴더 구조

  • "이 코드는 대체 어디에 둬야 하지?"라고 고민했던 시간, FSD를 적용해보면서의 느낌, 나만의 구조를 만들어가는 과정, TanStack Query로 서버 상태를 분리하면서 느낀 해방감(?)등을 공유해주세요

앞으로 새 프로젝트 시작할 때 FSD 기반으로 폴더 구조 잡을 것 같습니다.
"이 코드 어디 있지?"가 "당연히 저기 있겠지"로 바뀌는 경험이 좋았습니다. 앞으론 새로운 팀원이 합류해도 구조만 보면 바로 이해할 수 있을 것 같다라는 확신이 들었습니다.

TanStack Query를 쓰는 경험도 좋았습니다.
useState + useEffect로 fetch하면 의도치 않은 사이드이펙트를 잡느랴 오래걸렸는데 선언적으로 "이 데이터가 필요해"만 적으면 캐싱, 리프레시, 에러 핸들링이 다 따라오니까 좋았습니다.

리뷰 받고 싶은 내용이나 궁금한 것에 대한 질문

@x 패턴 사용이 적절했는지 궁금합니다

---

export interface PostWithAuthor extends Post {
  author?: User
}

Post와 User의 합성 타입인 PostWithAuthor 타입의 위치가 고민됐었습니다.

엔티티는 최대한 순수하게 두려고 최소 피쳐 레이어 이상에서 합성하려고 했는데 PostWithAuthor가 여러 feature에서 사용하는 타입이라 어디다가 위치해야할지 헷갈렸습니다.

문서를 찾아보니 비즈니스 엔티티 간의 상호 참조 패턴 중에 Cross-import(@x)를 사용하는 방법(참조: https://feature-sliced.design/kr/docs/guides/examples/types#%EB%B9%84%EC%A6%88%EB%8B%88%EC%8A%A4entity%EC%99%80-%EC%83%81%ED%98%B8-%EC%B0%B8%EC%A1%B0)이 있었고.

최종적으론 `entities/post/@x/with-user.ts`에 뒀는데, 개인적으로 `as unknown as User` 같은 느낌이라 영 맘에 들진 않았습니다. 그냥 features 레이어에서 정의하는 게 더 나았을까요?

코치님의 상황에선 어떻게 접근하셨을지 궁금합니다.

daehyunk1m and others added 24 commits December 7, 2025 01:13
- .claude/ 폴더 구조 생성 (agents, commands, state)
- 학습 목표 및 태스크 목록 정의
- FSD 아키텍처 참고 문서 추가
- CLAUDE.md, SETTING.md 설정 파일 추가
- gh-pages 패키지 추가
- 기존 패키지 버전 업데이트
- shared/ui 레이어 구성: Button, Card, Dialog, Input, Select, Table, Textarea 컴포넌트 분리
- shared/lib 구조 생성
- features/search 구조 생성 (highlightText)
- 기존 components/index.tsx 삭제
- PostsManagerPage import 경로 업데이트
- tsconfig, vite alias 설정 추가

WIP: 타입 에러 수정 필요
- jotai: 전역 상태 관리를 위한 패키지
- @types/node: Node.js 타입 정의
- /start 명령어: 세션 시작 및 로그 생성
- /end 명령어: 세션 종료 및 로그 업데이트
- task-manager 에이전트에 세션 관리 역할 추가
- .gitignore 수정: .claude/state/logs/ 추적 허용
- CLAUDE.md 명령어 목록 업데이트
- 버전 v5 → v6 업그레이드
- 폴더 구조에 session 로그 추가
- task-manager 에이전트 정의에 세션 관리 역할 추가
- 슬래시 커맨드 5개 → 7개 (start, end 추가)
- 상태 파일에 세션 로그 템플릿 추가
- CLAUDE.md 템플릿 업데이트
- 완료 안내 템플릿 업데이트
- Quick Reference 업데이트
- 세션 로그 종료 시간 및 상태 업데이트
- progress.json lastUpdated 갱신
- *.tsbuildinfo 파일 gitignore에 추가
- PR 템플릿 포맷팅 정리 및 셀프회고 내용 추가

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- shared/ui 컴포넌트 타입 수정 (HTMLAttributes → InputHTMLAttributes 등)
- shared/api 구성 (client.ts, types.ts)
- entities/post, entities/user 도메인 타입 정의
- PostsManagerPage import 경로 및 타입 적용
- TypeScript 빌드 성공

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Post, User, Comment, Tag 도메인별 폴더 구조 구성
- model/types.ts: 각 도메인별 타입 정의 (PostsData, UsersData 등)
- api/index.ts: 각 도메인별 API 함수 분리 (fetchPosts, addPost 등)
- index.ts: public API export 구성
- PostsManagerPage.tsx: import 경로를 @/entities/*로 변경
- shared/api/types.ts: 공통 Data 타입 추가

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- 세션 로그 업데이트 (커밋 해시 추가)
- progress.json 업데이트

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- features 레이어 6개 피처 폴더 구조 생성 (add-post, edit-post, delete-post, post-filter, comment-section, user-info)
- user-info 피처: UserInfoModal, UserProfile 구현
- add-post 피처: AddPostModal 구현
- edit-post 피처: EditPostModal 구현
- @x 패턴 적용: PostWithAuthor 타입을 entities/post/@x/with-user.ts로 이동
- entities/post/api에서 pages 의존성 제거
- widgets 레이어 추가 (PostTable)
- HighlightText를 shared/ui로 이동

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- post-filter 피처 완성 (합성 컴포넌트 패턴 적용)
  - PostFilter, Search, ByTag, BySort, ByOrder 컴포넌트 분리
- comment-section 피처 완성
  - Comments, AddCommentModal, EditCommentModal 분리
- delete-post 피처 삭제 (entities/post/api에 deletePost만 유지)
- 세션 로그 업데이트

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Jotai 라이브러리 도입 및 Atom 설계
- 5개 도메인별 Atom 생성 (post, comment, user, tag, post-filter)
- 모든 컴포넌트에 useAtom/useAtomValue/useSetAtom 적용
- PostsManagerPage Props Drilling 완전 제거 (17개 useState → 1개)
- 컴포넌트 간 결합도 감소 및 상태 관리 일원화

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- widgets 레이어 FSD 구조로 재구성 (post-filter, post-table, page-navigation, post-detail)
- pages 레이어 FSD 구조 적용 (posts-manager)
- app 레이어 구성 (layouts, providers, styles)
- TanStack Query 설치 및 Provider 설정
- 모든 API 호출을 useQuery/useMutation으로 마이그레이션
- 각 도메인별 queries.ts 생성 (post, comment, user, tag)
- 미사용 파일 정리 (Legacy.tsx, useRouting.ts, components 폴더)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Posts/Comments CRUD 시 캐시 직접 업데이트 (DummyJSON mock API 대응)
- Posts에 Users 데이터 병합하여 author 정보 표시
- 태그별 게시물 필터링 (fetchPostsByTag) 구현
- 검색 기능 TanStack Query 연동 (useSearchPostsQuery)
- 정렬 기능 구현 (sortBy, sortOrder 적용)
- URL query params 동기화 복원
- PostDetailModal 열기 기능 수정
- UserProfile에 author prop 전달

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- front_lite_chapter3-3 → front_7th_chapter3-3

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- 개발 환경: /api (Vite proxy)
- 프로덕션 환경: https://dummyjson.com (직접 호출)
- shared/api/config.ts에서 API_BASE_URL 관리

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- usePostsQuery에 staleTime 추가 (1분간 fresh 상태 유지)
- pull_request_template.md 심화과제 체크박스 완료 처리
- Task 10 완료 로그 추가

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- useUpdatePostMutation: onMutate에서 즉시 UI 반영, onError에서 롤백
- useDeletePostMutation: onMutate에서 즉시 UI 반영, onError에서 롤백
- useLikeCommentMutation: 좋아요 클릭시 즉각적 피드백, 실패시 롤백

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant