JHeeJinDev 님의 상세페이지[6팀 장희진] Chapter 2-1. 클린코드와 리팩토링

배포 링크

https://jheejindev.github.io/front_6th_chapter2-1/

과제 체크포인트

기본과제

  • 코드가 Prettier를 통해 일관된 포맷팅이 적용되어 있는가?
  • 적절한 줄바꿈과 주석을 사용하여 코드의 논리적 단위를 명확히 구분했는가?
  • 변수명과 함수명이 그 역할을 명확히 나타내며, 일관된 네이밍 규칙을 따르는가?
  • 매직 넘버와 문자열을 의미 있는 상수로 추출했는가?
  • 중복 코드를 제거하고 재사용 가능한 형태로 리팩토링했는가?
  • 함수가 단일 책임 원칙을 따르며, 한 가지 작업만 수행하는가?
  • 조건문과 반복문이 간결하고 명확한가? 복잡한 조건을 함수로 추출했는가?
  • 코드의 배치가 의존성과 실행 흐름에 따라 논리적으로 구성되어 있는가?
  • 연관된 코드를 의미 있는 함수나 모듈로 그룹화했는가?
  • ES6+ 문법을 활용하여 코드를 더 간결하고 명확하게 작성했는가?
  • 전역 상태와 부수 효과(side effects)를 최소화했는가?
  • 에러 처리와 예외 상황을 명확히 고려하고 처리했는가?
  • 코드 자체가 자기 문서화되어 있어, 주석 없이도 의도를 파악할 수 있는가?
  • 비즈니스 로직과 UI 로직이 적절히 분리되어 있는가?
  • 코드의 각 부분이 테스트 가능하도록 구조화되어 있는가?
  • 성능 개선을 위해 불필요한 연산이나 렌더링을 제거했는가?
  • 새로운 기능 추가나 변경이 기존 코드에 미치는 영향을 최소화했는가?
  • 코드 리뷰를 통해 다른 개발자들의 피드백을 반영하고 개선했는가?
  • (핵심!) 리팩토링 시 기존 기능을 그대로 유지하면서 점진적으로 개선했는가?

심화과제

  • 변경한 구조와 코드가 기존의 코드보다 가독성이 높고 이해하기 쉬운가?
  • 변경한 구조와 코드가 기존의 코드보다 기능을 수정하거나 확장하기에 용이한가?
  • 변경한 구조와 코드가 기존의 코드보다 테스트를 하기에 더 용이한가?
  • 변경한 구조와 코드가 기존의 모든 기능은 그대로 유지했는가?
  • (핵심!) 변경한 구조와 코드를 새로운 한번에 새로만들지 않고 점진적으로 개선했는가?

과제 셀프회고

과제를 하면서 내가 제일 신경 쓴 부분은 무엇인가요?

과제 요청사항에 적혀 있듯이, 이번 과제에서는 AI를 활용하는 연습을 하며, 기존 코드를 큰 틀은 유지한 채 점진적으로 리팩토링하는 방식으로 접근했습니다. AI와 마치 협업하듯이 리팩토링의 방향성을 설정하고, 작은 단위부터 차근차근 개선해 나가며, 항상 "내가 어떤 목적과 이유로 리팩토링을 진행하는지"를 명확히 전달하려고 노력했습니다. 처음에는 '이거 컴포넌트별로 폴더 분리해줘'와 같은 포괄적인 질문을 던지기도 했지만, AI가 제 의도를 정확히 파악하지 못하고 엉뚱한 답변을 내놓는 시행착오를 겪었습니다. 이 과정을 통해 **"AI에게 구체적인 맥락과 목표를 제시해야 효율적인 결과를 얻을 수 있다"**는 것을 깨달았고, 점차 질문의 방식을 다듬어갔습니다.

진행한 리팩토링 단계

  • 1단계: docs 문서 읽기 및 기존 코드 분석

  • 2단계: 변수 선언 방식 개선 (var -> const, let)

  • 3단계: 컴포넌트 단위로 코드 분리 및 재설계

  • 4단계: 타입스크립트 인터페이스와 타입을 정의

  • 5단계: 명령형 DOM 조작을 상태 기반 렌더링으로 전환

  • 6단계: 비즈니스 로직과 UI 로직을 분리하여 서비스 레이어 구축

  • 7단계: 최종 코드 정리

문제점 및 해결 방향

  1. 긴 코드를 한 번에 AI에게 요청 → 분석 오류 발생

문제점: AI에게 처음 긴 바닐라 JS 코드를 제시하며, "이 코드의 문제점과 점진적으로 개선해나갈 방향을 구체적으로 알려달라"고 요청했습니다. 그러나 코드가 너무 길고 복잡해서인지, AI는 전체 코드를 제대로 분석하지 못하고 중간에 응답을 멈추거나 아예 엉뚱한 답변을 내놓는 오류를 보였습니다.

해결 방향: 전체 코드를 한 번에 던지는 대신, 코드의 특정 부분(예: main() 함수의 DOM 생성 부분)을 발췌하여 "이 부분을 React 컴포넌트로 바꾸려면 어떻게 해야 하나?"와 같이 구체적인 질문 단위로 나누어 요청했습니다.

  1. AI가 요청의 맥락을 완벽히 이해하지 못하고, 기계적인 코드 변환만 시도함

문제점: var를 const 또는 let으로 바꿔달라는 요청에 대해, AI는 모든 변수를 일관되게 바꾸지 못하거나 적절하지 않은 곳에 var를 남겨두는 등 불완전한 결과를 내놓았습니다.

해결 방향: AI에게 추상적인 요청은 비효율적임을 깨닫고, "재할당되지 않는 변수는 const로, 재할당되는 변수는 let으로 변경해달라"와 같이 더 명확한 기준을 제시해 원하는 결과를 얻어냈습니다.

  1. 컴포넌트 간 데이터 흐름 및 상호작용 설계가 부족함

문제점: AI는 ProductPicker나 CartItem과 같은 컴포넌트의 뼈대는 잘 만들어주었지만 AI는 단일 파일만 보고 판단하기 때문에, 전반적인 흐름이나 의도를 놓치는 경우가 많았습니다. 예를 들어, 특정 컴포넌트 리팩토링 시 전역 상태나 부모 컴포넌트와의 관계를 고려하지 않고 수정 제안을 하는 경우가 있었습니다.

해결 방향: 단일 파일이 아닌 맥락 전체를 설명해주는 "지금 이 컴포넌트는 어디서 쓰이고, 무슨 역할을 하며, 어떤 제약이 있다" 등을 먼저 설명준 후, 리팩토링 요청을 하였습니다.

과제를 다시 해보면 더 잘 할 수 있었겠다 아쉬운 점이 있다면 무엇인가요?

이번 과제를 수행하면서 처음에는 점진적으로 AI에게 질문하며 협업하듯 진행했지만, 시간이 부족해 나중에는 많은 부분을 AI에게 의존하게 된 경험은 아쉬웟다고 생각합니다ㅠㅠ

이번 과제를 다시 한다면, 더 잘할 수 있었을 아쉬운 점

이번 과제를 진행하면서 처음에는 '점진적 리팩토링'이라는 큰 목표만 가지고 AI와 협업을 시작했습니다. 하지만, 막상 진행하면서 '어떤 부분을 지켜야 하는지'에 대한 명확한 규칙이 없으니, AI에게 질문할 때마다 저의 기준이 흔들리는 경험을 했습니다. 이러한 경험을 바탕으로, 이번 과제를 다시 한다면 더 잘할 수 있었을 아쉬운 점들을 정리해보았습니다.

  1. 시작부터 명확한 원칙을 정하지 못했던 점 만약 처음부터 동작 유지, 관심사 분리, 테스트 통과와 같은 절대적인 원칙들을 정해놓고 시작했더라면, 훨씬 더 효율적이고 일관된 결과물을 만들 수 있었을 것입니다. 원칙을 정해놓지 않고 초반에 포괄적인 질문을 하다보니 의도치 않게 기능의 일부가 바뀌거나 검증이 어려워지는 결과를 낳았습니다. 다음에는 시작 전에 명확한 원칙을 세우는 것을 최우선으로 해야 할것 같습니다.

  2. 리팩토링 시작 전에 큰 그림부터 그리지 못한 점 처음에는 긴 코드를 통째로 AI에게 넘기거나, var를 let이나 const로 바꾸는 등 지엽적인 수정부터 시작했습니다. 그렇게 접근하다 보니 코드 전체 구조에 대한 이해 없이 표면적인 수정만 반복하게 됐고, AI의 답변이 기대에 못 미칠 땐 스스로 해결하느라 더 많은 시간을 쓰게 됐습니다.

개선 방안: 앞으로는 먼저 구현하려는 기능이 무엇인지, 어떤 흐름으로 동작해야 하는지 큰 틀부터 AI에게 질문하고 설계를 함께 고민할 예정입니다. 전체적인 구조가 정리된 상태에서 리팩토링을 시작하면 훨씬 수월할 것 같습니다.

  1. AI에게 질문하는 방식이 서툴러서 비효율적인 결과가 많았던 점 시간에 쫓기다 보니 "이 코드 리액트로 바꿔줘" 같은 포괄적인 요청을 자주 했습니다. 그러다 보니 AI가 의도를 정확히 파악하지 못해 엉뚱한 코드가 나오기도 했습니다. 또한 복잡한 로직이 담긴 코드를 통째로 넘겨주었을 때, AI가 만들어준 코드는 동작은 잘했지만 함수 길이가 너무 길고 여러 로직이 뒤섞여 있어 가독성이 떨어지는 경우가 있었습니다.결국 다시 디버깅하거나 손수 고치는 데 시간을 더 쓰게 됐습니다.

개선 방안: 맥락과 목적을 분명히 전달하는 것이 중요하다고 느꼈습니다. '어떤 부분이 문제고, 어떤 방향으로 개선하고 싶다'는 구체적인 문제 상황과 원하는 방향을 함께 설명하며 더 협업하는 방식으로 질문할 계획입니다. 이를 통해 AI가 팀의 코딩 컨벤션이나 규칙을 더 잘 이해하고 반영하도록 유도할 수 있을 것 같다는 생각입니다.

  1. 리팩토링을 너무 작은 단위의 수정에서 시작한 부분 처음에는 기존 코드를 유지한 채 변수 선언만 바꾸거나, 아주 간단한 함수만 리팩토링하는 식으로 접근했습니다. 물론 점진적인 개선이라는 의미는 있었지만, 궁극적으로 React나 TypeScript가 가진 장점(컴포넌트 기반, 상태 기반 렌더링, 타입 안정성)을 충분히 살리지는 못했습니다.

개선 방안: 결국 중요한 것은 코드의 기능을 정확히 파악하고, 그것을 프레임워크의 철학에 맞게 재구성하는 설계 과정이라고 생각했습니다. 다음번에는 기존 코드를 단순히 옮기는 대신, 기능 중심으로 다시 설계하여 구조적으로 더 나은 방향으로 리팩토링할 것입니다. '재설계'를 통해 더 효율적이고 확장 가능한 코드를 만들어야겠다고 느꼈습니다.

리뷰 받고 싶은 내용이나 궁금한 것에 대한 질문 편하게 남겨주세요 :)

  1. '변수 선언 방식 개선'부터 시작해 '컴포넌트 분리', '상태 기반 렌더링', '서비스 레이어 분리'와 같은 7단계의 리팩토링 과정을 거쳤습니다. ‘변수 선언 개선’처럼 작은 단위의 수정부터 시작하면 변경 범위를 최소화하면서 점진적으로 리팩토링을 진행할 수 있다는 장점이 있고, 반대로 ‘컴포넌트 분리’처럼 먼저 큰 그림을 그리면 전체 구조를 빠르게 잡고 나머지 세부 사항들을 정리하기 수월하다는 장점도 있다고 느꼈습니다. 이 두 접근 방식 모두 장단점이 있는 것 같아 실제로는 어떤 방식이 더 효과적인지 혼란스러웠습니다. 아직 리팩토링 우선순위를 판단하는 경험이 부족하다 보니, 제가 선택한 순서가 적절했는지 조언을 듣고 싶습니다.

  2. 가장 어려웠던 부분은 **'바닐라 JS의 명령형 로직을 React의 선언형 방식으로 어떻게 자연스럽게 전환할까?'**였습니다. 예를 들어, 기존 전역 변수로 관리되던 상태를 React 컴포넌트의 useState 훅으로 옮기는 과정에서, UI 로직과 비즈니스 로직을 분리하는 것이 쉽지 않았습니다. 기존 코드를 새로운 프레임워크(React)로 전환할 때, 가장 먼저 파악하고 분리해야 할 '핵심'은 무엇이라고 생각하시나요?

과제 피드백

수고하셨습니다. :) "...AI와 마치 협업하듯이 리팩토링의 방향성을 설정하고, 작은 단위부터 차근차근 개선해 나가며, 항상 "내가 어떤 목적과 이유로 리팩토링을 진행하는지"를 명확히 전달하려고 노력했습니다" 훌륭합니다. 아주 과제의 취지를 잘 이행해주었다 생각합니다.

특히나 "AI에게 구체적인 맥락과 목표를 제시해야 효율적인 결과를 얻을 수 있다"**는 것을 깨달았고, 점차 질문의 방식을 다듬어갔습니다." 라는 점에서 매우 뿌듯하네요. AI에게 내가 원하는 바를 아주 구체적인 형태의 결과를 요청하는 것도 중요하지만 그걸 어떻게 진행해야할지 그 길까지도 선명하게 알려주어야 맥락이 틀어지지 않고 기존의 동작이 문제없을수 있는 방향으로 알려줘야 하는 것이죠

구체적인 예시들이 너무나 훌륭하네요. 인간은 구체적인걸 생각하기를 싫어하도록 설계되어 있어서 모호하고 막연하게 말하는걸 좋아하는지라 이 구체적으로 요구한다라는 기술이 정말로 에너지가 많이 들고 어려운 기술이죠. 그러나 컴퓨터는 완벽하게 구체적이지 않으면 동작하지 않기에 개발자의 전문성이 빛나지는 순간이라 생각합니다. 과제를 통해 이 인사이트를 느꼈다니 너무 좋네요.

아쉬운 점들이라고 썼지만 "시작부터 명확한 원칙을 정하지 못했던 점", "리팩토링 시작 전에 큰 그림부터 그리지 못한 점", "AI에게 질문하는 방식이 서툴러서 비효율적인 결과가 많았던 점" 등이 이미 다 본인이 느끼고 배운것이 된 것 같네요. 아주 좋습니다.

Q) 1 '변수 선언 방식 개선'부터 시작해 '컴포넌트 분리', '상태 기반 렌더링', '서비스 레이어 분리'와 같은 7단계의 리팩토링 과정을 거쳤습니다.
‘변수 선언 개선’처럼 작은 단위의 수정부터 시작하면 변경 범위를 최소화하면서 점진적으로 리팩토링을 진행할 수 있다는 장점이 있고,
반대로 ‘컴포넌트 분리’처럼 먼저 큰 그림을 그리면 전체 구조를 빠르게 잡고 나머지 세부 사항들을 정리하기 수월하다는 장점도 있다고 느꼈습니다.
이 두 접근 방식 모두 장단점이 있는 것 같아 실제로는 어떤 방식이 더 효과적인지 혼란스러웠습니다.
아직 리팩토링 우선순위를 판단하는 경험이 부족하다 보니, 제가 선택한 순서가 적절했는지 조언을 듣고 싶습니다.

=> 정석적인 방식이라면 변경해도 문제가 없고 영향도가 낮지만 확실한 소소한 것들을 시작으로 분리가 가능하게 결합도를 낮추는 것을 먼저 진행하는 것이 좋습니다. 그리고 분리가 가능하도록 만들었다면 응집도를 높여가면서 있어야 할 곳에 두는 것이 그 다음이긴 하죠.

=> 하지만 '전체 구조를 빠르게 잡고 나머지 세부 사항들을 정리하기 수월하다'는 것처럼 정해진 구조대로 분리를 해두면 편해지는 것도 있습니다. 특히 뷰와 데이터의 분리와 같이 완벽히 보편화된 구조는 분리를 해두는 것도 좋죠

=> 중요한건 이때에도 단순히 분리를 하는게 아니라 현재 코드의 동작을 그대로 유지하면서도 분리가 가능한 구조를 먼저 만들어 두고 큰 구조를 나누고 하는 식의 방식입니다. 완전히 나 분리를 한 다음 조립하진 않더라도 분리 -> 조립 이라는 순서는 지키면 좋겠죠!

=> 일단 분리해두고 에러가 나든 말든 다 만든 다음에 짜잔하고 테스트 굴려가면서 완성할거야만 아니라면 언제나 문제없는 코드내에서 분리 -> 재배치 -> 조립과 같은 식의 사이클을 탈수 있다면 순서는 요령껏 하셔도 무방합니다

Q) 가장 어려웠던 부분은 '바닐라 JS의 명령형 로직을 React의 선언형 방식으로 어떻게 자연스럽게 전환할까?'였습니다. ... 기존 코드를 새로운 프레임워크(React)로 전환할 때, 가장 먼저 파악하고 분리해야 할 '핵심'은 무엇이라고 생각하시나요?

=> 제가 농담삼아 말하는 React의 추구미가 무엇인지 이해하는 것입니다. React에서 이상적으로 생각하는 구조와 계층을 이해하고 그에 맞게 분리하는거죠. 이것은 그동안의 프론트엔드의 역사와도 관계가 있습니다. 사실 React의 추구미라기 보다는 FE의 추구미인것이죠. 뷰와 데이터를 분리하고 컨트롤러 대신 데이터 변경감지를 통한 자동 DOM 업데이트, 상태와 파생데이터의 분리, 도메인과 비 도메인의 분리, 컴포넌트의 계층 구조, 부수효과의 격리 등 그동안 화면을 메인으로 하는 개발의 패러다임이 갖춰지면서 만들어진 계층과 모듈과 데이터 흐름을 이해하는 것이 핵심입니다. 그걸 React가 만들어진 결과를 통해서 이해하게 된다면 다른 프레임워크나 다른 코드의 구성들도 그러한 시각으로 바라볼수 있는거겠죠

앞으로 5주차 6주차를 거치면서 계층과 모듈, 결합도와 응집도에 대해서 찬찬히 이해해나가보도록 합시다.

수고하셨습니다!