배경지식!
01. 컴포넌트란 무엇일까. 컴포넌트 중심 개발이 미션 목표
02. 주어진 탬플릿으로 보다 원활한 css but 많아진 기능구현
03. 지금까지 중 제일 시간이 부족. 3일 중 마지막날에 이르기까지 못한 기능구현
04. 설계.. 했다고 생각했는데 어디까지가 도메인이죠?
1. PR 메세지
1. 구상
* 컴포넌트 분리: 컴포넌트를 처음 접했습니다. 때문에 컴포넌트가 무엇인지를 익히는 것이 가장 우선이었습니다. 페어와 이야기한 끝에 컴포넌트를 html 태그 중 기능을 가지는 것으로 정의하고 이를 하나의 파일로 만들었습니다. 해당 컴포넌트 파일은 컴포넌트를 랜더링할 수 있게 템플릿을 가지고 있고, 이벤트-모달창을 키거나, 필터를 하는 등-를 가지고 있는 경우 이벤트를 부여하는 함수를 포함했습니다.
* 레스토랑 리스트 = 도메인: 도메인을 분리해야 하지만 하지못했습니다. 대신 필터, 정렬, 추가 등의 기능이 최종적으로 레스토랑 리스트를 변형 시키는 것이기 때문에 이 파일에서 도메인을 많이 수행하고 있습니다. 더불어 각 이벤트가 부여되는 과정에서 도메인이 산발적으로 흩어져 있습니다.
* 최종적으로 인덱스를 호출하면 앱이 호출되고, 앱은 처음 화면을 랜더링하고 이벤트를 부여합니다. 이후 이벤트 발생에 따라 진행이 됩니다.
로컬 스토리지는 미션사항에 있어 적용했습니다.
2. 생각한 점
* 최초에 설계할때 레스토랑과 레스토랑 리스트를 클래스로 만들었습니다. 해서 레스토랑 리스트는 레스토랑 클래스를 가지고 있었고, 앱은 레스토랑 클래스를 가지고 있었습니다. 하지만 이 과정에서 필터, 정렬 같은 이벤트리스너에서 레스토랑 모음에 접근할 수 있는 방법이 없었습니다. 때문에 이를 객체 안 배열로 레스토랑 모음을 저장하도록 만들었고, 객체는 객체답게에서 외부에서 자칫 객체 안의 정보를 수정할 수 있다는 점을 지적하는 것을 이용해 밖에서 객체 안 내용을 수정할 수 있도록 만들어 해결했습니다. 클래스로 모음을 만드는 경우 다른 곳에서 부르기가 어려워 이런 방법을 택했지만, 변형될 수 있는 위험이 굉장히 높다고 생각합니다. 이보다 더 나은 방법이 무엇일지, 아니면 위험을 낮출 수 있는 방법이 있을지 궁금합니다.
* 컴포넌트는 무엇일까요. 컴포넌트는 재활용의 의미가 크다고 합니다. 하지만 저의 코드로는 그런 의미는 살리지 못한 것 같습니다. 컴포넌트가 재활용으로 의미를 가진다면 어디까지 내용을 비워야 하는 걸까요? 모달창을 키는 컴포넌트다 라고 한다면 모달창의 정보를 인수로 받아 인수 모달창을 키는 컴포넌트로 만든다면 재활용성이 높은 컴포넌트일까요? 근본적으로 유틸함수가 UI를 가진다면 그게 컴포넌트일까요? 컴포넌트는 탬플릿을 꼭 가지고 있어야 할까요? 이런 컴포넌트 중심의 개발은 html를 모두 js에서 랜더링하는 걸까요? 컴포넌트와 도메인을 분리하는 것이 가능할까 다른 크루들에게 물어보았을 때 일단 이번 미션에서는 분리하지 못했다, 그게 가능할까? 하는 의견이 많았습니다. 이벤트 리스너를 부여하는 것이 컴포넌트 파일 안에서 일어난다면 도메인과 분리가 가능한지도 잘 모르겠습니다.
3. 아쉬운 점
* 익숙하지 않은 개념이라 초반에 헤맨 시간이 많습니다. 설계를 하면서 이야기를 많이 나누었고, 이해했다고 생각을 했는데 자꾸 길을 잃어 이야기를 하는 시간이 길었습니다. 때문에 기한 내에 기능구현이 가능할지도 의문이었고, 리팩토링, 유틸함수화, 상수화 등 다른 부분을 신경쓸 겨를이 없었습니다. 잘 짜인 돌아가지 않는 코드보다는 돌아가는 쓰레기가 낫다는 말을 위안삼아 일단 기능구현을 목표로 하였습니다. 이번 미션 목표 중 하나였던 UI의 테스트는 물론 도메인 테스트도 작성하지 못했다는 것이 제일 아쉽습니다. 기능구현을 우선 작성했다보니 테스트코드를 만들고자 했을 때 단위테스트를 하기 굉장히 어려운 코드가 되었습니다... 이 부분은 리팩토링을 하며 테스트코드를 만들도록 하겠습니다.
* 앞서 작성한 것처럼 리팩토링, 유틸함수화, 상수화 등을 하지 못했습니다. 특히 컴포넌트를 보면 굳이 이렇게 해야 하나? 싶은 부분이 많은데 해당 부분을 분리하고 싶습니다..
* 생각한 점에서 작성한 것처럼 처음에 레스토랑을 클래스로 만들었습니다. 이 부분이 로컬 스토리지를 사용하는 데에 걸림돌이 되었습니다. 시간이 없어 차선책으로 필요한 부분을 다시 객체로 돌려 사용했습니다만 애당초 이를 객체로 사용하고 관련된 함수를 따로 분리했다면 하는 아쉬움이 있습니다.
2. 피드백 + 내 생각
템플릿이란..? 사람 대 사람 그리고 모든 집단이 형성하는 언어와 단어들이 존재하는데요. 리뷰이님이 생각하는 템플릿, 개발에서의 템플릿, 그 외에 템플릿 등등.. 템플릿이 어떻게 불리우는지 고민해보시면 좋겠어요 일단 제 개인적으로 느낀 것은.. 템플릿 역할만 잘 하고 있는 경우도 있고요. 템플릿이 여기까지 한다고..? 그 이상을 하는 경우도 보입니다.
> 템플릿에 대한 고민은 사실 하지 않았다. 나에게 템플릿이라는 것은 무언가를 표현하기 위한 틀이라고 생각했고, 여기에서는 HTML, 기능을 제외한 element라고 생각했다.
> 이 피드백에서 다른 사람과 혼동이 있으셨는지 아니면 내 코드를 보고 말씀해주신 것인지 모르겠다.
또한 App/render() vs SomeComponent/template() 하는 역할도 상당히 비슷해보이는데 무슨 차이가 있을까요?
> 렌더과 템플릿.. 우선 템플릿은 기능을 담기위한 element 명세라고 생각했고, 렌더은 그를 그리는 동적인 활동이라고 생각했다. 때문에 렌더를 위해 템플릿이 필요하며, 템플릿은 그림, 렌더는 그림을 그리는 행위로 비유 가능하다.
함수 내부 변수 함수 네이밍이 이미 적절한데 불필요하게 내부 변수를 만들고 바로 반환하는 경우가 잦은데 어떻게 생각하시나요? 계속 result라는 내부 변수를 만들고 반환하는 습관이 있으신 것 같은데 이미 함수 네이밍만으로 설명이 충분한 경우가 있어요. 개인적인 성향이 있을 수 있지만 한번 고려해보세요 :)
> 알고리즘 습관이다. 알고리즘을 하다보면 함수를 여러 개 만들 일이 없고 변수명도 크게 신경쓰지 않아도 문제가 없다. 처음 알고리즘을 배우며 결과를 result로 두는 경우를 많이 보다보니 이게 습관이 들어 자꾸 관습적으로 쓰는 경우가 있다. 아래 코드를 예시로 들어주셨는데, 이런 습관이 있다는 것을 자꾸 잊어 챙겨야겠단 생각이 들었다. 더불어서 이런 예시를 들어주면 직관적으로 아! 이렇게 바꿀 수 있겠구나 싶어서 도움이 많이 되었다.
> 이렇게 줄여서 쓰는 이유가 무엇일까? 생각해보면 변수에 지정한다는 것은 메모리를 사용한다는 뜻이고 코드의 길이가 길어지며 그것을 따라가는 인지적 에너지 소모, 비용이 발생이 일어난다고 느껴졌다. 신경을 써야겠다.
// case1
const list = restaurantList.map((item) => {
const restaurant = new Restaurant(item);
return restaurant;
});
// case2
const list = restaurantList.map((item) => {
return new Restaurant(item);
});
// case3
const list = restaurantList.map((item) => new Restaurant(item));
디렉터리 구조 아쉬운 것은 재사용성이 너무 떨어지고 계층이 구분되지 않는 정말 플랫한 구조라는 것입니다. 물론 디렉터리 구조만으로 앱의 구조와 계층을 설명할 수는 없겠지만.. 조금 아쉬운 마음은 드네요. 누가봐도 내부 로직은 import, export를 통해 복잡하게 섞여있고 계층이 나뉘어져있답니다. 다만.. 디렉터리 구조는 플랫한.. 1depth로 되어있죠. 즉 누가봐도 상하관계와 계층적인 구조가 나뉜 컴포넌트들인데 같은 계층처럼 한 디렉터리에 모두 담겨져있답니다
> 이건 나도 아쉬운 부분이었다. 너무 막 만든 느낌이 드는데, 어쩔 수 없었다고 핑계를 대본다.. 휴.. 아무튼 여기서 말하는 상하관계/ 계층적 구조는 무엇일까. 다른 사람들을 보니 부모 컴포넌트, 자식 컴포넌트 등 포함하고 있는대로 계층을 구분해주는 것 같았다. 근데 이렇게 꼭 해야하는 것일까 생각도 들었다. 내가 문제가 된 부분은 레스토랑 리스트가 너무 많은 데이터, 역할, 도메인을 가지고 있다는 것인데, 그게 계층구조와 관련되었다기보단 도메인/UI 분리가 안된 것에 가깝다고 느꼈기 때문이다. 개괄적으로 잘 보기 위해서 폴더 등으로 구분 짓는 것이 아니라 상위 컴포넌트가 하위 컴포넌트를 가져야 한다는 이해가 잘 가지 않는다.
컴포넌트 구조 일관성을 정말 잘 지켜주셨습니다. 때로는 클래스, 때로는 리터럴 객체로 구분하여 사용하셨던데 그 이유가 아직 잘 이해되는건 아니지만 그래도 일종의 규격을 만들고 잘 지키고 있어 좋네요 다만 template()의 존재, setEvent()에 너무나 많은 로직이 있다는 것은 더 고민해보고 수정해보셨으면 좋겠습니다. 타입 타입 재활용이 잘되고 있지 못해서 그 부분도 한번 고려해보세요 :)
> 여기서 말하는 클래스/ 객체 구분은 앞서 PR 메세지에 작성했던 것들이다. 클래스로 작성을 했다가 문제점이 발생했고, 수정을 하고자 했지만 시간이 없어 일단 할 수 있는 선으로 수습하고 보냈다는 것. 나 역시도 아쉽던 부분이다. 클래스로 작성하는 것은 어쩌면 프리코스때 습관이기도 한데, 데이터가 여기저기 사용된다는 것을 고려하지 못하고 작성했던 패착이라고 생각한다.
> setEvent()에 무언가 많이 있다.. 컴포넌트 파일 안에 그 역할과 관련된 함수들을 모두 넣다보니 이렇게 되어버렸다. 이건 2차로 수습하면서 제일 수정하고 싶은 부분이었다. 다만, 여전히 고민이었던 것이 어디까지가 도메인인가 하는 부분이었다. 관련된 로직을 인수로 넣자니 그럼 컴포넌트가 껍데기에 가깝지 않은가 생각이 들고, 아예 안에 넣자니 너무 무거워지고 만다. 컴포넌트가 무엇인가, 어디까지 맡는가를 정의내리지 못해서 오는 문제이다.
결과적으로 받은 피드백은
1. 파일, 폴더의 계층화
2. 간략하게, 알아보기 쉽게 함수쓰기 : 무의미한 변수 정의 후 바로 리턴 자제
3. 로직 중 undefined가 발생하기 쉬운 부분 validation 처리
아쉬운 부분이 많고 테스트도 못해 불편하던 미션이다.
미션 구현에만 급급해버렸다.
'2022우아한형제들_우테코' 카테고리의 다른 글
[우테코] Lv. 1 런치 구현 - 2단계 (0) | 2023.03.14 |
---|---|
[우테코] Lv. 1 런치 구현 - 1단계(2차) (1) | 2023.03.14 |
[우테코] Lv. 1 로또 구현 - 2단계(웹) 2차 PR 후기_최종 (0) | 2023.02.27 |
[우테코] 어쩌다 면담 (0) | 2023.02.24 |
[우테코] Lv. 1 로또 구현 - 2단계(웹) 1차 PR 후기 (1) | 2023.02.24 |