2022우아한형제들_우테코

[우테코] Lv. 2 다시뭐먹지 구현

chsua 2023. 5. 3. 17:05

배경지식

01. 점심 뭐먹지와 동일한 ui이다. 

02. 레스토랑을 추가하고 삭제하는 기능은 구현하지 않으며 클릭했을 때 모달창이 켜지는 것만 실행된다.

03. 기존에 바닐라로 구현한 것을 리액트로 구현한다.

04. 리액트를 접해보지 않은 사람들을 위해 익숙한 이전 미션을 다시 해보며, 기능도 줄어들었다.

05. 리액트 온보딩 같은 느낌이라서 짧은 미션기간이었다. 1단계가 화-목/ 2단계가 금-월었다. 

06. 1단계는 class형으로 컴포넌트를 작성했다. 2단계는 이를 function형으로 수정했다.


 이번에 처음 리액트를 만졌기 때문에 걱정이 많았는데 페어가 리액트를 잘 다루고 파일분리를 잘하는 크루라서 도움을 많이 받았다. 사실 거의 배우는 시간이었다고 할 수 있을 정도로 따라가는 시간이 많았는데, 아예 리액트를 처음 접하는 상황에서 많이 물어보면서 코드를 짤 수 있어서 좋았다. 다만 혼자서 이를 고치면서, 그리고 코멘트를 받으면서 계속 공부해야 함을 느꼈다.

 

1번째 Push

설계 의도

* 컴포넌트란 기능을 하거나 혹은 영역적으로 목적이 달라 명확한 분리가 필요하다고 생각이 될 때 하나의 컴포넌트로 보았습니다.

* 각 컴포넌트는 자신과 관련된 이벤트를 가지고 있도록 만들었습니다.

* 카테고리 필터/정렬 버튼처럼 내용물은 다르나 같은 태그/기능을 하는 것은 common에 공통 템플릿..?을 만들고, 필요로 하는 컴포넌트가 이것을 불러와 내용을 넣도록 만들었습니다.

    > 예. CategoryFilter 컴포넌트 중 <Select / > 예. RestaurantDetailModal 컴포넌트 중 <Modal / > 상위 컴포넌트에 속한 하위 컴포넌트는 상위컴포넌트 폴더 안에 위치합니다.

 

 

궁금한 점과 그에 대한 답변

위에 언급한 것처럼 컴포넌트는 독립된 기능이 있거나 혹은 명확하게 -다른 기능을 하는-영역을 분리하기 위해 컴포넌트로 만든다고 생각합니다만, 음식점 아이콘은 두 조건에 해당하지 않지만 컴포넌트로 만들었습니다. svg로 사용하기 위함인데, 이렇게 컴포넌트로 만들지 않으면 react element-라고 표현하는 것이 맞을까요?-로 인식되지 않는 것 같습니다. 그냥 문자열이 되어 태그처럼 들어가게 되지 않는 것 같은데 이처럼 컴포넌트라고 보기는 어려우나 태그로 사용하고 싶은 경우에는 어떻게 해야 할까요? 기존 바닐라자바스크립트에서 했던 것처럼 element.insert...등의 방식으로 텍스트도 넣을 수도 있지만 리액트에서 이 방법을 사용하는 것은 이상하다고 느껴집니다.

> 음 통일과 리액트 컴포넌트처럼 잘 활용하고 싶은 마음은 너무 좋으나 아직은 리액트와 친숙하지 않아 딱 떠오르지 않으시는 것 같아요. 이 부분은 방법이 너무 다양한데 일단 하드코딩과 같은 행위를 제거해보자 관점으로 시작해보셨으면 좋겠어요

피드백을 받고 이게 무슨 이야기일지 고민을 했었다. 하지만 아직 하드코딩이 무엇인지조차 정의내리지 못한 상태라서 따로 방법이 생각나지 않았다. 시간이 조금 지난 지금은 어느정도 방법이 생각나기도 한다. 만약 다시 한다면 

1. svg를 파일로 저장한다.

2. 각 svg를 임포트해서 사용되는 keyword와 연결짓는다. 

import { ReactComponent as Bear } from "../asset/bear.svg";

const img = {
	bear: Bear ; 
}

3. 필요한 곳에서 img.bear으로 사용한다.

일단 이런식으로 사용한다면 필요한 곳에서 곰에서 토끼로 바뀐다면 "img.rabbit"으로 사용할 수 있다.

그럼 하드코딩으로 사용하는 것이 아니지 않을까 조금 짐작해본다.

 

 

컴포넌트가 많아지고 파일 깊이가 길어질수록 하달하는 정보가 많아지는데, 만약 맨 상위에 state가 있고 맨 하단의 컴포넌트에서 이를 수정하게 된다면 거치는 파일이 너무 많아 보기에도, 성능으로도 좋은지 잘 모르겠습니다. 이를 위한 따른 프로그램이나 라이브러리 등이 있는 것 같기는 하지만 리액트로, 컴포넌트로 하면서 발생하는 어쩔 수 없는 문제점인가 아니면 제 설계에 따라 해결할 수 있는 문제인가 생각이 듭니다. 컴포넌트를 잘게 쪼개고 계층화할수록 이 문제가 심해질 것 같습니다. 이게 맞는 고민의 방향인지 잘 모르겠습니다.

> 네 맞아요. 리액트를 추월하고자하는 비슷한? 라이브러리나 프레임워크들은 대부분 성능부터 공격합니다. 예상하신 부분이 맞고요. 그걸 대응하기 위한 역할을 프론트엔드 개발자가 하는거죠

state를 관리하고 계속 내려주기 때문에 번거로워지고 하는 것들이 내가 구조를 잘못 짜서 그런게 아니라는 데에 위안을 받았다. 우테코의 교육방식 자체가 어려움을 겪게 하고 이를 해결하기 위한 방법을 제시하는 느낌이 강한데 내가 느끼는 어려움이 그런 의도된 어려움이라는 데에서 위안을 얻었다.

 

 

타입 컨벤션에서 i-를 사용하지 말라고 알고 있습니다. 지금까지 -type, -interface로 타입명을 작성해왔는데 이를 그냥 이름으로 붙이자니 그냥 변수명이랑 혼동이 되지 않을까 생각이 듭니다. 예로 아래처럼 타입을 파스칼로 똑같이 작성하는 경우가 있습니다. //이전방식 type FruitType = apple | orange | banana ; const fruit : FruitType = apple ; //바꾼다면? type Fruit = apple | orange | banana ; const fruit : Fruit = apple ; type/interface를 붙이지 않는다면 type명은 어떻게 지어야 될지 잘 모르겠습니다.. 보통 타입이 쓰이는 변수와 동일하게 쓰고 파스칼로 바꾸어 작성하시나요?

저는 그렇게 혼동되지는 않네요. 규칙과 기준을 잡아나가고 본인만의 색을 가지는게 좋아요. 다만 묘사라는 행위 관점으로 봤을때 -Type, I-과 같은 것들이 붙으면 오히려.. 인지 부조화가 오지 않을까요? 그런 역할을 하는 것들은 :, extends, implements와 같은 타입 문법을 통해 해석하심이 옳다고 생각합니다.

문제가 되었던 부분은 component와 그에 사용되는 타입을 정의할 때 비슷한 의미이기 때문에 헷갈리는 경우가 많았다는 것이다. 그동안 타입스크립트를 사용하며 -type/ -interface를 붙이는 경우가 많았는데 i-를 붙이는 것과 달리 지적 받은 경험이 없었다. 그래서 그냥 사용했던 것인데 페어가 이를 지양하자고 하여 "헷갈리지 않을까?"의문이 들어 리뷰어에게 물어봤다. 결과적으로는 페어도, 다른 크루도, 리뷰어도 이를 지양하는 데에 찬성했다. 

그러자 오히려 나는 그런 생각이 들었다. 내가 type/interface를 뒤에 붙이려고 했던 것은 아집이지 않았을까. 행동을 고치기 싫어서 대는 핑계였다는 생각이 들었다. 간혹 이런 상황이 생긴다면 내 아집이지는 않은지 다시 생각해봐야겠다.

 

 


 

2번째 Push

설계 의도

* class component를 function component로 수정

* select option constant array를 constant 파일로 이동

* 초기 데이터 패치 파일 분리 이벤트 위임 말고 각 아이템에 이벤트 부여하기

 

리뷰어  답변

솔직히 드릴 피드백이 별로 없네요 아주 잘하셨습니다. 여러가지로 시도하는 것도 의미 있었고 아쉬운 부분은 소소하게 있었지만 코멘트 리뷰 남긴 것들 꼭꼭 잘 판단하고 소화해보세요 :) 현재는 domain/*-Sevice와 분리된 듯 만든 파일 내부에 포함된 커스텀 훅 때문에 구조가 애매모호한 감이 있는데 담부터는 그 부분만 잘 반영해보시면 더 잘하실 수 있을 것 같네요.

 아직 훅을 분리하는게 어렵다. 훅이라는 것이 무엇인지 잘 모르겠다. 이번에는 state를 가지고 있는 컴포넌트가 매우 적어서 분리하는 것이 어렵지 않았지만 여기서 더 많아진다면 혼란스러워질 것 같다는 생각이 들었다. 

 

 


 

기억에 남는 코멘트

(... 이벤트 위임을 위해 data-id를 부여한 상황에서)
> 애초에 리액트에 이벤트 위임이 필요할까요?!

..? 왜 이벤트 위임이 안 필요하지? 라고 생각했다. 

알고보니 리액트에서 onclick등으로 이벤트를 붙이는 거는 html처럼 그 요소에 붙이는 것이 아닌 이미 가장 상위 컴포넌트에 이벤트 위임을 거는 것이라고 한다. 때문에 바닐라에서는 하나하나 element에 이벤트를 붙이면 무거워지고 비싸기 때문에 이벤트 위임을 쓰지만 리액트에서는 하나하나 붙여도 아무런 상관이 없는 것이다. 구동 방식이 다르니 이런 차이가 이었다. 리액트에 대해 공부를 해야겠다는 생각이 들었던 지점이었다. 

 

- 참고자료

 

({description ? ( <p className="restaurant__description text-body">{description}</p> ) : null} 부분에서...)
> 조건부 렌더링은 &&만으로 가능한 것도 아시죠?!

이건 알고 있던 부분이긴 한데 재미있게 느껴졌던 부분이다. 바닐라로 만드는 경우 null/undefined이 나오면 그대로 렌더링되는데 리액트에서는 알아서 나오지 않는다. 더불어서 [1,2,4...]이런 배열 역시 그리는 경우 바닐라와 다르게 프린트된다. 그래서 바닐라에서 하던 방식을 그대로 사용하면 "굳이..?"싶은 상황이 있는데 이를 위해, 더 간결하게 작성하고 무의미한 코드를 없애기 위해 리액트를 공부해야 한다고 느꼈다.