과제 체크포인트
기본과제
- 코드가 Prettier를 통해 일관된 포맷팅이 적용되어 있는가?
- 적절한 줄바꿈과 주석을 사용하여 코드의 논리적 단위를 명확히 구분했는가?
- 변수명과 함수명이 그 역할을 명확히 나타내며, 일관된 네이밍 규칙을 따르는가?
- 매직 넘버와 문자열을 의미 있는 상수로 추출했는가?
- 중복 코드를 제거하고 재사용 가능한 형태로 리팩토링했는가?
- 함수가 단일 책임 원칙을 따르며, 한 가지 작업만 수행하는가?
- 조건문과 반복문이 간결하고 명확한가? 복잡한 조건을 함수로 추출했는가?
- 코드의 배치가 의존성과 실행 흐름에 따라 논리적으로 구성되어 있는가?
- 연관된 코드를 의미 있는 함수나 모듈로 그룹화했는가?
- ES6+ 문법을 활용하여 코드를 더 간결하고 명확하게 작성했는가?
- 전역 상태와 부수 효과(side effects)를 최소화했는가?
- 에러 처리와 예외 상황을 명확히 고려하고 처리했는가?
- 코드 자체가 자기 문서화되어 있어, 주석 없이도 의도를 파악할 수 있는가?
- 비즈니스 로직과 UI 로직이 적절히 분리되어 있는가?
- 코드의 각 부분이 테스트 가능하도록 구조화되어 있는가?
- 성능 개선을 위해 불필요한 연산이나 렌더링을 제거했는가?
- 새로운 기능 추가나 변경이 기존 코드에 미치는 영향을 최소화했는가?
- 코드 리뷰를 통해 다른 개발자들의 피드백을 반영하고 개선했는가?
- (핵심!) 리팩토링 시 기존 기능을 그대로 유지하면서 점진적으로 개선했는가?
심화과제
- 변경한 구조와 코드가 기존의 코드보다 가독성이 높고 이해하기 쉬운가?
- 변경한 구조와 코드가 기존의 코드보다 기능을 수정하거나 확장하기에 용이한가?
- 변경한 구조와 코드가 기존의 코드보다 테스트를 하기에 더 용이한가?
- 변경한 구조와 코드가 기존의 모든 기능은 그대로 유지했는가?
- (핵심!) 변경한 구조와 코드를 새로운 한번에 새로만들지 않고 점진적으로 개선했는가?
과제 셀프회고
배포 링크
https://chan9yu.github.io/front_6th_chapter2-1/
과제를 하면서 내가 제일 신경 쓴 부분은 무엇인가요?
기존 기능을 절대 깨뜨리지 않기
과제를 진행하면서 가장 무서웠던 게 혹시 내가 놓친 케이스가 있어서 기능이 깨질까..? 였습니다. 그래서
- 항상
pnpm test:basic,pnpm test:advanced실행한 상태에서 리팩토링 - 작은 변경도 직접 브라우저에서 테스트
- 특히 복잡한 할인 로직은 다양한 시나리오를 수동으로 체크
실제로 findProductById 함수의 파라미터 순서를 잘못 바꾸는 실수로 테스트가 실패한 적이 있었는데, 변경을 단계적으로 진행한 덕분에 금방 파악하고 수정할 수 있었습니다.
코드를 읽는 사람을 배려하는 구조 만들기
코드는 작성 시간보다 읽는 시간이 훨씬 길다고 생각합니다. 따라서 **이 코드를 처음 보는 사람이 얼마나 쉽게 이해할 수 있을까?**를 중심에 두고 구조를 고민했습니다.
- 함수명만으로도 역할을 유추할 수 있게 작성 (
hasEnoughStock,generateProductOptionText등) - 관련 있는 코드는 최대한 가까이 배치 (feature별 디렉토리로 정리)
- 복잡한 조건은 의미 있는 변수명으로 분리하여 의도 명확하게 표현
AI와 협업하면서도 스스로 이해하고 검증하기
이번 과제에서는 AI를 정말 많이 활용했습니다. 단순 질의응답에서 시작해 점점 더 효율적인 협업 방식을 찾게 되었습니다
Claude 웹 → Claude Desktop → Claude Code
- Claude 웹: "리팩토링을 어떻게 시작해야 할까요?" 같은 개괄적인 질문
- Claude Desktop: 코드 일부 복사하여 “이 함수 리팩토링 아이디어 줄래?”
- Claude Code: 프로젝트 전체를 연결해 실시간으로 파일 읽고 수정
특히 Claude Code를 정말 만족하면서 사용했는데요
- 전체 프로젝트 맥락을 이해한 상태에서 정확한 제안
- 파일 간 의존성과 흐름을 고려한 구조 개선
- 직접 코드 수정까지 가능해져 작업 속도가 크게 향상됨
단, 무조건 신뢰하지 않고 항상 검증하며 사용했습니다
- AI가 제안한 코드를 한 줄씩 직접 읽고 이해한 후 적용
- TypeScript 타입 관련 제안은 특히 더 신중하게 검토
- 최종적으로는 내가 모든 코드를 설명할 수 있는 상태가 되도록 노력
AI 활용 협업 노하우 (내 방식 정리)
- 요청은 최대한 구체적으로!
- ❌ "이 함수를 리팩토링해주세요"
- ✅ "이 함수의 중복된 할인 계산 로직을 별도 함수로 분리해주세요"
- 제안된 코드라도 반드시 테스트로 검증
- 모르면 꼭 물어보기: "왜 이렇게 작성했나요?"
과제를 다시 해보면 더 잘 할 수 있었겠다 아쉬운 점이 있다면?
처음 리팩토링을 시작할 때는 매직 넘버 제거부터 시작했는데, 작업 중간에 이걸 feature 단위로 나누려면 이 부분도 바꿔야 하네... 같은 재수정 작업이 생기면서 비효율이 발생했습니다.
앞으로는 작업 전에 전체 구조를 파악 후 목표 구조를 먼저 설계해 두고 시작하는 게 더 효율적일 거라고 느꼈습니다.
(사실 제일 아쉬운 건 이번 주 회사가 너무바빠서..ㅠㅠㅠㅠㅠ 과제 투자할 시간이 없었다는 거? 😭)
리뷰 받고 싶은 내용이나 궁금한 점
이런 식으로 feature별로 나누는 게 맞는가?
현재는 src/features/ 구조로 구성했습니다.
의도는 다음과 같았는데요
공통 로직은 분리하고, 각 기능마다 응집도 높은 구조로 만들기 → 전체 가독성 향상
하지만 진행하면서 다음과 같은 의문이 생겼습니다
app-state에 전역 상태를 몰아넣은 구조가 적절한가?- feature 간 의존성(
shopping-cart에서product-selection타입 참조 등)이 생기는 게 괜찮은가? - 실무에서도 이런 구조를 쓰는가?
항상 폴더구조에 대해 고민이 많이 되는거 같아요 실무에서는 어떻게 사용해야 좋은 구조를 가질 수 있는지...
FSD 구조도 많이 들어는봤지만, 실제로 적용한 경험이 없어서 궁금합니다~
과제 피드백
안녕하세요 찬규님! 4주차 과제 잘 진행해주셨네요 ㅎㅎ 고생하셨습니다!
app-state에 전역 상태를 몰아넣은 구조가 적절한가?
전역 상태를 몰아넣는 방법은 좋다고 생각해요! 다만 전역 상태를 props를 통해 계속 하위 컴포넌트로 전달하는 방식은 사실 좋은 방법이 아니라고 생각해요.
불필요한 렌더링이 계속 발생하기 때문이죠 ㅎㅎ 그래서 이럴 때 상태관리 라이브러리를 통해 관리하면 좋답니다!
feature 간 의존성(shopping-cart에서 product-selection 타입 참조 등)이 생기는 게 괜찮은가?
상호 참조(shopping-cart가 product를 참조하고, 다시 product가 shopping-cart를 참조)가 생기는게 아니라면 무방하다고 생각합니다! 자연스러운 현상이지 않을까 싶네요!
실무에서도 이런 구조를 쓰는가?
저희 팀은 이렇게 작성하는 편입니다 ㅎㅎ 다만 feature라는 이름을 직접적으로 사용하진 않고 있어요.
중요한건 feature가 아니라 "응집도" 라고 생각합니다. 응집도를 높일 수 있다면 어떤 구조든 상관없다고 생각해요!
지금은 응집도가 높은 형태로 구성해주셔서 사실 feature인지 아닌지는 중요하지 않은 것 같네요 ㅎㅎ
다만 조금 아쉬운 점은 basic의 코드를 advanced에서 재활용하면 좋았을텐데 이게 아쉬워요!
가령, basic의 service가 advanced에는 없다거나.. 똑같은 이름의 service여도 내부를 보면 코드가 아예 다르네요..!