과제 체크포인트
https://elli-lee.github.io/front_6th_chapter2-1/
기본과제
- 코드가 Prettier를 통해 일관된 포맷팅이 적용되어 있는가?
- 적절한 줄바꿈과 주석을 사용하여 코드의 논리적 단위를 명확히 구분했는가?
- 변수명과 함수명이 그 역할을 명확히 나타내며, 일관된 네이밍 규칙을 따르는가?
- 매직 넘버와 문자열을 의미 있는 상수로 추출했는가?
- 중복 코드를 제거하고 재사용 가능한 형태로 리팩토링했는가?
- 함수가 단일 책임 원칙을 따르며, 한 가지 작업만 수행하는가?
- 조건문과 반복문이 간결하고 명확한가? 복잡한 조건을 함수로 추출했는가?
- 코드의 배치가 의존성과 실행 흐름에 따라 논리적으로 구성되어 있는가?
- 연관된 코드를 의미 있는 함수나 모듈로 그룹화했는가?
- ES6+ 문법을 활용하여 코드를 더 간결하고 명확하게 작성했는가?
- 전역 상태와 부수 효과(side effects)를 최소화했는가?
- 에러 처리와 예외 상황을 명확히 고려하고 처리했는가?
- 코드 자체가 자기 문서화되어 있어, 주석 없이도 의도를 파악할 수 있는가?
- 비즈니스 로직과 UI 로직이 적절히 분리되어 있는가?
- 코드의 각 부분이 테스트 가능하도록 구조화되어 있는가?
- 성능 개선을 위해 불필요한 연산이나 렌더링을 제거했는가?
- 새로운 기능 추가나 변경이 기존 코드에 미치는 영향을 최소화했는가?
- 코드 리뷰를 통해 다른 개발자들의 피드백을 반영하고 개선했는가?
- (핵심!) 리팩토링 시 기존 기능을 그대로 유지하면서 점진적으로 개선했는가?
심화과제
- 변경한 구조와 코드가 기존의 코드보다 가독성이 높고 이해하기 쉬운가?
- 변경한 구조와 코드가 기존의 코드보다 기능을 수정하거나 확장하기에 용이한가?
- 변경한 구조와 코드가 기존의 코드보다 테스트를 하기에 더 용이한가?
- 변경한 구조와 코드가 기존의 모든 기능은 그대로 유지했는가?
- (핵심!) 변경한 구조와 코드를 새로운 한번에 새로만들지 않고 점진적으로 개선했는가?
과제 셀프회고
저는 이번 과제가 유독 어려웠습니다.. 어게인 1주차 느낌입니다. 왜 이렇게 어려웠을까를 지금와서 생각해보니, 우선 여전히 바닐라 자바스크립트로 DOM을 직접 다루는건 너무 어렵습니다. DOM을 어떻게 다뤄야 원하는 결과를 만들 수 있는지가 제 머리속에 명확하지 않았는데, 거대한 더티코드 어디선가 뭔가 DOM 조작을 하고 있는 것 같은데 그 흐름을 찾기가 어려웠습니다.
또 어디서부터 손을 대야할 지 감이 잘 안왔습니다. 제일 마음에 안드는 부분부터 조금씩 건드려 보다가, QNA를 듣고" 조금 더 시야를 크게 넓혀서 리액트 처럼 리팩토링하자!" 라는 생각이 들어서 처음부터 다시 과제를 진행했는데요... 두번째 리팩토링 과정도 처음과 크게 다르지 않았던 것 같습니다.
basic 과제는 그래도 AI를 최대한 덜 사용하려고 노력했고, 고치면서도 이렇게 리팩토링하는게 맞나? 하는 생각을 수없이 했는데요, 그 과정이 힘들었지만 재밌기도 했습니다.
과제를 하면서 내가 제일 신경 쓴 부분은 무엇인가요?
-
팀 컨벤션 맞추고 맞춘 컨벤션에 맞게 코드 작성하기 basic 과제를 시작하기 전에 팀 코어타임에 모여서 팀 코드 컨벤션을 정했습니다. 4,7팀 팀원분들이랑 의견을 나누면서 컨벤션을 정하는 시간이 정말 재밌었고, 의견이 충돌했을 때 저와 다른 의견을 가지신 분들의 합리적인 이유를 듣는것도 좋았습니다. 팀장님이신 하늘님께서 팀 컨벤션을 바탕으로 eslint와 prettier 설정 파일을 공유해주셔서 해당 설정을 프로젝트에 적용했고, 과제를 수행하면서도 컨벤션에 맞게 코드를 작성하기 위해 신경썼습니다.
-
리액트스럽게 리팩토링하는건 대체 무엇인가! 심화과제에서 활용할 수 있게 기본과제를 최대한 리액트스럽게 리팩토링 해야한다고 힌트를 주셨고, 리액트스러운게 무엇일까? 리액트처럼 리팩토링 한다는 건 뭘까를 많이 고민했습니다.
많이 고민해서
- JSX를 흉내 내기 위해 템플릿 문자열 + map + join을 적극 활용, html 리턴하도록 구성
- 가능한 한 불변성 유지하기 (
state.cart = [...state.cart, newItem]등) - DOM 참조 의존도 최소화:
document.querySelector최소화, id/class 대신 구조로 제어 - 전체 DOM을 리렌더링하므로 최소 DOM diffing 구조로 설계 (React처럼은 못하더라도)
- 이벤트 위임 방식 적용
- use~ hook으로 로직 분리하기
정도로 이해했는데요, 리액트처럼 리팩토링 한다는게 어떤건지 언어로는 이해를 했어도 그렇게 실제로 구현하는 건 또 다른 문제였습니다. 분명 저 부분들을 계속 신경쓰면서 리팩토링을 했는데 결과를 돌아보니 지켜진게 거의 없는 것 같습니다.
그래도 심화과제를 진행하면서 리액트로 코드를 짜다 보니 제가 기본 과제 수행 중 어느 부분을 잘못 설계했고, 덜 쪼갰는지 등등을 알 수 있었습니다.
과제를 다시 해보면 더 잘 할 수 있었겠다 아쉬운 점이 있다면 무엇인가요?
basic 과제를 진행 할때는 사실 DOM API 조작에 대한 이해도 부족했고, 어디서 어떤 일이 일어나는 건지 코드 자체를 잘 이해하지 못해서 리팩토링을 계획적이고 구조적으로 큰 틀을 잡고 진행하지 못했고, 그냥 그때그때 보이는 걸 조금씩 고쳤습니다. 조금씩 고치다가 마지막에 결과물을 돌아보니, 불규칙한 모양의 돌을 반질반질한 하트 모양으로 조각하고 싶었으나 거칠거칠한 삼각형으로 조각한 느낌입니다. 헤매는 시간도 많았고, 심화과제로 리액트로 바꿔보기도 했고, 솔루션 코드도 본 지금은 그래도 조금 더 감이 오는 것 같습니다. 다시한번 과제를 진행해서 큰 틀을 잡고 구조적으로 리팩토링을 해보면 조금 더 나은 결과가 나올 것 같습니다. 또, 클린코드 챕터에 걸맞게 이번 과제하면서 놓쳤던 많은 부분들을 (매직넘버 남아있음, ui 덜 쪼갰음, DOM API 많이 씀, for문을 map으로 못바꿈, 전역변수 적절하게 처리하지 못함 등등) 더 챙기면서 할 수 있을 것 같습니다.
리뷰 받고 싶은 내용이나 궁금한 것에 대한 질문 편하게 남겨주세요 :)
DOM API 대신 리액트 컴포넌트처럼 html을 반환하라는 함수를 만들라고 하셨던게 이런 방식이 맞을까요...? 리액트로 바꾸려다 보니까 그대로 못쓰고 직접 div 태그 만들고 className 붙여야 하던데... 제가 잘 이해하지 못한건지 궁금함니다..!
function ProductSelector() {
const container = document.createElement('div');
container.className = 'mb-6 pb-6 border-b border-gray-200';
container.innerHTML = `
<select id="product-select" class="w-full p-3 border border-gray-300 rounded-lg text-base mb-3"></select>
<button id="add-to-cart" class="w-full py-3 bg-black text-white text-sm font-medium uppercase tracking-wider hover:bg-gray-800 transition-all">Add to Cart</button>
<div id="stock-status" class="text-xs text-red-500 mt-3 whitespace-pre-line"></div>
`;
return container;
}
과제 피드백
"...왜 이렇게 어려웠을까를 지금와서 생각해보니, 우선 여전히 바닐라 자바스크립트로 DOM을 직접 다루는건 너무 어렵습니다." 맞습니다. 사실 유진이 뿐만 아니라 모든 웹 개발자들이 같은 생각을 했습니다. DOM API는 너무 어렵고 후지다고요. 그래서 처음에 만들어진게 jQuery였습니다. 적어도 jQuery는 DOM을 다루는 방식에 있어서 매우 간결하고 수준높은 표현력을 보여줬거든요.
"...뭔가 DOM 조작을 하고 있는 것 같은데 그 흐름을 찾기가 어려웠습니다." 그렇죠. 역시 DOM 조작은 DOM 조작 그 자체에서 한계를 느꼈습니다. 우리의 사고흐름은 HTML을 그리고 동작을 하면 HTML이 변경이 되는 건데 그 중간 과정을 사고해서 변경해야한다는건 어려운 개념이었죠.
그러면서 React와 같이 html과 유사한 개념을 작성하고 수정할 수 있는 개념으로 확장이 되었습니다. 이번에 리액트스럽게 사고해보라고 한건 지난 js개발 패러다임의 변화 역사들을 이해할 수 있기를 바랬어요.
"basic 과제는 그래도 AI를 최대한 덜 사용하려고 노력했고, 고치면서도 이렇게 리팩토링하는게 맞나? 하는 생각을 수없이 했는데요, 그 과정이 힘들었지만 재밌기도 했습니다." 아주 아주 잘했습니다. 이렇게 하는 맞나? 라는 고민 그 자체를 반복하는게 곧 성장이죠. 이게 정답이야 라고 알려주고 작성하는건 수학 문제를 답지를 보고 베껴쓰는것 밖에 안되요. 물론 그것도 학습이 되겠지만 내가 정말로 고민해보고 머리를 써보는 것만큼일수가 없죠. 학습을 하는 과정에서는 결과의 속도보다 과정의 질이 더 중요하다 생각합니다. (그렇지만 과제의 시간이 부족한 부분에 대해서는 미안해요 ^^;)
"그래도 심화과제를 진행하면서 리액트로 코드를 짜다 보니 제가 기본 과제 수행 중 어느 부분을 잘못 설계했고, 덜 쪼갰는지 등등을 알 수 있었습니다." 맞아요. 아마 리액트를 사용하면서 이게 왜 이렇게 만들어졌을까? 라는 생각은 많이 해보지 않았을거에요. 그런데 그 과정을 한번 접하고 나니 리액트가 조금 달리 보이지 않나요? 원리를 이해하게 되면 뭔가 더 선명해지는 그런 안경을 쓴 기분이 들거에요!
"헤매는 시간도 많았고, 심화과제로 리액트로 바꿔보기도 했고, 솔루션 코드도 본 지금은 그래도 조금 더 감이 오는 것 같습니다." 좋습니다. 앞으로 더 많은 코드를 만나게 될거고 솔직히 DOM으로 개발하는 코드를 만나게 되는 경우는 거의 없을 거에요. 이 개념적 원리를 이해하는 접근법을 이해했다면 이러한 방식으로 앞으로 코드를 만날 때 "이건 왜 이렇게 만드려고 했을까?" 라는 점들을 의식해서 생각해보면 훨씬 더 빨리 익힐 수 있을거에요.
Q) DOM API 대신 리액트 컴포넌트처럼 html을 반환하라는 함수를 만들라고 하셨던게 이런 방식이 맞을까요...? 리액트로 바꾸려다 보니까 그대로 못쓰고 직접 div 태그 만들고 className 붙여야 하던데... 제가 잘 이해하지 못한건지 궁금함니다..!
=> 잘했습니다. outerHTML을 쓸 수 도 있고 template을 이용해서 full html을 반환하거나 string만 반화하고 리렌더링시 html을 활용하거나 할 수도 있겠지만 어차피 패러다임이 넘어간 이상 어떻게든 크게 상관없었답니다. 과제의 취지는 바닐라스크립트를 잘 하는 건 아니었으니까요.
수고하셨습니다. 5주차 과제도 화이팅입니다