Home 1주차 - 공통컴포넌트,상품옵션 구현 회고
Post
Cancel

1주차 - 공통컴포넌트,상품옵션 구현 회고

📃구현 CheckList!!

  • 상품 옵션 세트를 추가, 삭제 기능
  • 상품 옵션 세트 내 옵션 추가, 삭제 기능
  • 옵션 내 추가옵션 추가, 삭제 기능
  • 환율 바꾸기 기능
  • 세금 적용

📖과제 설명

이번 과제는 페어프로그래밍하면서 하나의 컴포넌트를 개발하는 것이 아니라 각자 맡은 영역을 분배하여 구현하고 한 페이지에 각자 구현한 컴포넌트를 쌓는 과제였다. 팀원들과 공통된 컴포넌트를 나누고 나는 가장 기본적인 틀인 SettingFrame, SettingFrame안에 중복되는 SettingFrameItem를 맡았다.
개인적인 구현사항은 상품을 얼마에 팔것인지를 정하고 다양한 옵션에 따른 가격을 정하는 상품옵션이었다.

🎭TopDown vs BottomUp

나는 평소에 가장 작은 단위인 컴포넌트에서 점점 컴포넌트 크기를 키워가는 BottomUp방식을 사용해왔다. 그렇기에 이번에도 BottomUp방식으로 컴포넌트를 개발했다. 디자인은 내가 생각하는 대로 됐지만, 이벤트를 적용할 때 쉽게 적용되지 않았다.

컴포넌트 하나하나에 이벤트를 걸어주기도, 가장 상위에 이벤트를 적용해보기도 했지만, 구현에 어려움을 느꼈다. 시간을 많이 소요했으나 완성하지 못했기 때문에 이거는 설계에서 실패했다고 생각하게 됐다. UI는 BottomUp방식이 적합하다고 판단했으나 리액트에서는 단방향 데이터 통신이기 때문에 데이터흐름대로 설계하려면 TopDown 방식이 효율적이라고 생각했다.

TopDown방식으로 생각하니 데이터 설계가 필요하다고 느꼈다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 상품옵션
productOptions = [옵션세트1,옵션세트2,옵션세트3,...]
// 옵션 세트 id값 추가
optSet = {
	이미지: 파일,
	옵션: [옵션1, 옵션2, 옵션3,...]
}
// 옵션 id값 추가
option = {
	옵션명: string,
	상품정상가: number,
	할인율: number,
	상품판매가: number,
	재고: number,
	과세유무: string,
	추가옵션: [추가옵션1, 추가옵션2,...]
}
// 추가옵션 id값 추가
addtionOption = {
	추가옵션명: string,
	추가옵션정상가: number,
}

이처럼 데이터를 설계하고 배열이 필요한 부분에서 중복되는 부분을 찾게 되고 어떻게 이벤트를 걸까 고민하게 되어 id값을 추가하여 productOption의 속성에 맞는 id와 target.id와 같으면 이벤트를 작동시키는 방법을 생각하게 되어 상품옵션 기능을 구현했다.

productOption

😊명확한 코드 작성하기

frame1

frame2










SettingFrame(빨간색으로 칠해져있는 부분)은 각자의 콘텐츠를 넣는 틀이고, SettingFrameItem(보라색으로 칠해져있는 부분)은 SettingFrame내부의 공통되는 틀이다. SettingFrameItem은 모두 일정하고 필수로 사용하지 않아도 되는 부분이었지만, SettingFrame은 상품옵션과 같이 일정하지 않은 부분이 있으므로 어떻게 하면 공통적인 부분만 남기고 다른 부분을 추가하는 고민을 했다.

아래는 각 컴포넌트에 따른 사용법을 나타낸 코드이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 상품 기본 정보
function BasicInfo() {
	// ...
	return (
		<SettingFrame title="상품기본정보">
		{/* ... */}
		</SettingFrame>
        );
}

// 상품 옵션
function ProductOption() {
	// ...
	return (
            <SettingFrame
            title="상품옵션"
            isBackground  //배경색 필요
            isButton  // 버튼 필요
            onClick={Clickhandler}
            onChange={handleChange}>
            {/* ... */}
            </SettingFrame>
        );
}

최근 읽기 좋은코드가 좋은 코드다라는 책을 읽고 “다른 사람이 내 코드를 보면 어떻게 이해할까?” 라는 고민했다. 마침 이번 과제에서 팀원이 내가 만든 코드를 보고 적용하는 기회를 얻게 되어 props 내용을 어떻게 해야 잘 작성할 수 있을까 고민하게 됐다.

책에선 불리언 이름 고치기라는 소주제를 다룬 부분을 읽었는데, 불리언값의 의미를 명확하게 하려고 is, has, can, should를 붙이면 좋다고 읽었고 나도 이 부분에 동감하고 자주 사용하는 is를 접두어로 붙여 isBackground, isButton으로 정했다.

🤸‍♂️Hook과 컴포넌트 분리

커스텀 훅을 정의할 때 중요한 것은 코드의 중복을 줄이고 재사용성을 높이며 코드를 효율적으로 관리하기 위함이라고 학습했다. 이번 상품옵션의 추가, 삭제, 수정 부분의 로직이 컴포넌트 내에서 너무 길어졌기 때문에 코드를 효율적인 관리의 필요성을 느꼈다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// ProductOption.jsx
function ProductOption() {
	const [state, setState] = useState([]);
	const newOptSet = () => ({ /* ...*/});
	const newOption = () => ({ /* ...*/});
	const newOptAddition = () => ({ /* ...*/});
	const handleAdd = ({ name, id }) => { /* ...*/});
	const handleDelete= ({ name, id }) => { /* ...*/});	
	const handleChange= ({ name, id }) => { /* ...*/});	
	const ClickHandler = (e) => {
		//...
		handleAdd(/*...*/);
		handleDelete(/*...*/);
	};

	return (
            <SettingFrame
            title="상품옵션"
            isBackground  //배경색 필요
            isButton  // 버튼 필요
            onClick={Clickhandler}
            onChange={handleChange}>
                    {/* ... */}
            </SettingFrame>
        );
}

ProductOption 내부에 이렇게나 많은 로직을 포함하게 됐다. 이는 코드를 작성하면서 가독성을 떨어 트릴 뿐만 아니라 상수를 매번 생성하는 건 불필요하다 느꼈다. 그래서 이를 아래와 같은 코드로 분리했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// hook/productOption.js
const newOptSet = () => ({ /* ...*/});
const newOption = () => ({ /* ...*/});
const newOptAddition = () => ({ /* ...*/});
	
const useProductState = () => {
	const [state, setState] = useState([]);
	const handleAdd = ({ name, id }) => { /* ...*/});
	const handleDelete= ({ name, id }) => { /* ...*/});	
	const handleChange= ({ name, id }) => { /* ...*/});	
	const ClickHandler = (e) => {
		//...
		handleAdd(/*...*/);
		handleDelete(/*...*/);
        };

	return {state, ClickHandler, handleChange};
};

// ProductOption.jsx
function ProductOption() {
	const {state, ClickHandler, handleChange} = useProductState();

	return (
            <SettingFrame
            title="상품옵션"
            isBackground  //배경색 필요
            isButton  // 버튼 필요
            onClick={Clickhandler}
            onChange={handleChange}>
                    {/* ... */}
            </SettingFrame>
        );
}

만약 상품 옵션과 같은 로직이 있는 경우 이처럼 커스텀훅을 선언하여 사용하게 되면 컴포넌트를 선언할 때 어렵지 않다고 생각한다.

-- Missing configuration options! --