2022우아한형제들_우테코

[우테코] Lv. 1 영화리뷰 구현 - 2단계

chsua 2023. 4. 5. 17:10

배경지식!

01. 추가해야 하는 기능이 여럿 있었다. 모달창을 키고 끄는것. 무한 스크롤로 수정. 별점주기 기능(로컬 스토리지 활용)

02. 모달과 별점은 이전에 했던 것과 유사하여 크게 어렵지는 않았으나 무한 스크롤이 좋은 자료가 없어서 좀 헤맸다. 역시 좋은 자료는 영어로 되어 있다. 후

03. 개인적인 일정으로 인해서 시간이 없었다. 월요일까지 제출인데 토요일 오후에 시작하였다. 


1번째 Push

설계 의도

* 각 컴포넌트 안 함수들은 그 컴포넌트 밖으로 내보이지 않기

* 각 컴포넌트에서 관련 이벤트 부여하기 가능한 이벤트를 삭제/재등록하지 않기

* 무한 스크롤 이벤트에서 옵저버 이벤트를 app.ts에 배치하여 최초 랜더링 시 이벤트 세팅

* itemList 에 이벤트를 부여해서 모달 여는 이벤트 위임시키기

* 모달 안 닫기버튼/별점 영역 이벤트를 삭제/재등록하지 않게 하기 위해 innerHTML이 아닌 value/textContent를 수정 로직을 단순화하고자 노력

* 기존 showMovieList에서 호출 위치를 인수로 받아 처리했던 것을 showMovieList()를 요청하는 것으로 수정 모달을 키고 별점을 저장하기 위해 movieData 생성

 

질문 & 리뷰

* 이벤트 렌더링마다 붙이기 vs 각 elem 수정하기
모달 안 닫기버튼/별점 영역 이벤트를 삭제/재등록하지 않게 하기 위해 innerHTML이 아닌 value/textContent를 수정 에서 궁금한 부분이 있습니다. 모달 내부에서 이벤트를 붙이는 방식에는 세 가지 방식이 있다고 생각합니다.

    1) [모달 내 elem에 이벤트를 붙이는 경우] innerHTML으로 객체정보를 포함한 템플릿을 넣고 이벤트를 붙여주는 방법
    2) [모달 내 elem에 이벤트를 붙이는 경우] 각각 elem 마다 value/textContent를 바꾸어주는 방법 (제가 선택한 방법)
    3) [모달자체에 이벤트를 붙이는 경우] innerHTML으로 객체정보를 포함한 템플릿을 넣고 이벤트 위임으로 이벤트를 감지하는 방법

여기서 2번과 3번은 이벤트를 한 번만 붙여도 되고, 1번은 렌더링 마다 붙여줘야 합니다. 2번은 각 elem를 각각 수정하기 때문에 코드도 더러워지고 reflow가 많이 발생할 것 같습니다. 일단 이벤트를 한번만 붙이는 데에 집중하여 2번을 선택하였습니다만 현 상황에서는 3번이 제일 좋은 방식인 것 같습니다. 다만, 모달창 안에 이벤트가 늘어난다면(혹은 중복된다면) 모달창 안 이벤트리스너의 매우 복잡해질 것 같아서 무조건적으로 옳은 방법은 아니라고 생각됩니다. 혹시 이러한 경우에 어떤 방식을 취하실 지 궁금합니다.

> 모달 뿐만 아니라 다른 곳에서도 동일한 고민이 될 수 있을 것 같은데, 저라면 3번의 이벤트 위임 방식을 차용하되, 이벤트를 위임하는 컨텍스트를 최대한 좁게 가져갈 것 같습니다. 단위를 페이지, 모달로 두는 것보다 더 작은 컨테이너 단위로 컴포넌트를 운용할 수 있다면 3번에 대한 단점을 덜 수 있지 않을까 생각해요

 

 

반응성 웹의 기준
찾아본 글마다 반응성 웹을 위한 기준(min/max-width)이 달랐습니다. 핸드폰마다 길이다 다르고, 같은 기종이더라도 세로, 가로에 따라 길이가 달라지기도 해서 어느 것을 기준으로 잡아야 하는지 잘 모르겠습니다. 혹시 리뷰어께서 생각하시는 기준이 있으신가요?

> 말씀하신 것처럼 모든 기기에 딱 맞는 앱을 만드는 것은 꽤 힘든 작업입니다. 이 부분은 앱의 성격이나 타겟 기기마다 다양하게 달라질 수 있는 부분이겠지만, 기본적으로 각각의 ui는 화면 너비에 따라 최대한 유동적으로 움직이고 특정 B.P(Break Point)에서 적절히 레이아웃을 변경시켜주는 것이 이상적인 방법이라고 생각합니다. 평소 자주 사용하는 사이트들을 들어가서 직접 화면 너비를 조정해보며 화면이 어떤 식으로 변하는지 유심히 확인해보면 이해하실 수 있을 것 같습니다!

 

싱글톤 패턴
일전에 달아주신 리뷰에서 객체를 class로 수정하라는 조언을 해주셨습니다. 그래서 이 부분을 싱글톤으로 만들어보았습니다. 하지만 싱글톤이 안티패턴이라고 말하기도 합니다. 여러 단점이 있다고는 하지만 지금 상황에서 가장 효과적으로 사용할 수 있는 패턴이기도 하고, 아직 단점을 느끼지 못해서 왜 지양되어야 하는지 체감하지 못하고 있습니다. 혹은 바닐라 자바스크립트라서 사용하기 편하지만, 다른 프레임워크를 사용한다면 더 효과적으로 데이터/상태를 관리할 수 있어 굳이 단점이 있는 싱글톤을 지양하라고 하는 것일지 궁금합니다.

> 장, 단점과 사용례를 다룬 아티클을 많이 찾아보시면서 기준을 만드는 것을 권장 드리지만 이해를 돕기 위해 단적인 예를 들자면, 만약 어떠한 데이터 객체가 싱글톤 패턴으로 작성되어 어디서든 접근 가능하고 내부 상태를 get, set할 수 있을 때 ui 간 렌더링되는 데이터의 싱크가 안맞는 경우를 예시로 들 수 있을 것 같습니다.

function component1 () {
  return `<div>${singleton.getState();}</div>`
}

function component2 () {
  singleton.setState();
  return `<div>${singleton.getState();}</div>`
}

function app () {
  component1();
  component2();
}

다만 말씀하신 것처럼 현재 앱의 규모를 비추어보았을 때 싱글톤의 이러한 단점이 와닿기에는 이르다고 생각합니다. 사용하는데 크게 무리가 없다면 사용해도 무방하나 어떤 도구나 패턴을 사용하기 전에 간단한 장단점이라도 비교해보는 습관을 들여보시면 좋을 것 같습니다.

 

 

리뷰 리뷰

어디서부터 손을 대야 할 지 모르겠는게 제일 어렵다.. 아무튼 이번에 2단계를 진행하면서 제일 먼저 했던 것은 기존의 item-list를 렌더링하는 과정을 바꾼 것이었다. 랜더링을 해야하는 이벤트 호출 장소에서 키워드를 주어 어떤 곳인지 알려줬고, 그걸 받아서 show에서 처리를 했는데 이를 직접 pageData를 수정한 다음에 그냥 show를 키워드 없이 호출하는 방식으로 수정했다. 그렇게 진행이 되면서 불필요한 if문을 제거할 수 있었다.

더불어서 다른 사람들이 많이 했던 방식이고, 또 리뷰어께서 말하셨던 것인데 모달창에서 이벤트를 없애지 않기 위해 모든 textContent를 바꾸는 것은 아닌 것 같다. 그래서 이벤트 위임으로 수정을 했다. 


2번째 Push

설계 의도

* 기존 장르 상수 객체를 API를 받아와서 진행하기

* 모달창 이벤트 위임하기

 

질문 & 리뷰

기존 토글을 유틸함수로 만든 것에 대해 명확하게 읽히지 않는다는 리뷰
> 말씀해주신 부분을 생각하다가 토글이 껐다 켰다하는 것인데 토글이란 이름이 동일하게 사용되어 끄는 것인지, 키는 것인지 헷갈린다는 생각을 했습니다. 때문에 동일한 내용을 담았지만 함수의 이름을 on/off로 구분지어 코드를 읽을때 파악이 쉽도록 만들었는데, 이렇게 하는 것도 괜찮은 것인지 혹은 동일한 내용이니 지양되어야 하는 코드인지 궁금합니다.

이름만 on, off일 뿐, 정확한 시점에 호출해야 해당 동작을 보장받을 수 있기 때문에 (e.g. toggle.off만 호출한다면 반대로 동작할 듯 하네요) 올바른 이름이 아닌 것 같습니다. 또한 껐다 키는 동작을 toggle이라는 동작으로 일축한 것인데 그 이점을 역행하는 것처럼 보이네요!

 

(무한 스크롤을 위한 옵저버가 페이지데이터에 위치한 것에 대해) intersection observer를 상태로 유지하고 있어야하는 이유가 있을까요?  또한 이것은 화면 상의 특정 요소를 관측하여 이벤트를 동작시키도록 고안된 api이기 때문에 도메인보다는 ui를 위한 별도의 유틸로 빼는 것이 좋지 않을까 싶네요
> 옵저버를 실행/정지시키기 위해서는 현재 페이지와 토탈 페이지가 필요합니다. 유틸함수로 분리한다면 유틸함수에서 데이터를 �임포트하게 되는데, 그것은 유틸이 아니게 되는 것으로 생각하여 앱으로 재배치 하겠습니다!

현재 페이지와 토탈 페이지는 callback을 실행시키기 위한 조건으로 보이는데 이 조건을 callback으로 옮기거나 옵저버를 실행시키는 조건을 옵저버 유틸의 인자로 받는 방법도 고려해볼 수 있을 것 같습니다. 임포트를 하지 않고 의존성을 주입받는 관점으로 고민해보시면 좋겠네요~!

 

( 장르 상수 객체에 대해) 데이터의 계층을 두는 식으로 해서 객체의 프로퍼티 만으로 어떤 값을 의미하는지 나타낼 수 있으면 좋겠습니다.
> 영화 객체에서 id(숫자)가 value로 들어가있습니다. value를 찾기 위해 모든 key값을 찾고, 그 key값을 돌며 value를 찾아야한다고 알고 있는데 그런 작업이 비효율적이지 않을까 생각이 들어 수정하지 않았습니다.
더불어 제가 적용하지는 못했지만, 교육 중에 api를 받아와서 내가 사용하고자 하는 정보를 담은 객체로 재생성하라는 이야기가 있었습니다. 여러 api를 받아온다면 획일적인 자료구조가 아니니 이런 과정을 거쳐 제 도메인에 맞게 가공하라는 이야기였습니다.
이 이야기에 따르면 api별 영화 객체들을 각 api별 장르 id를 담은 파일에서 [key: number(id)]: "genre"로 장르를 찾아 업무규칙에 맞게 수정해 한곳에 모아 사용한다면 더 효율적이지 않나 상상해보았습니다. 물론 제가 업무경험이 없고 규모가 큰 데이터를 다루어본 경험이 없어 놓지고 있는 부분이 있을 것 같습니다. 혹시 이런 구조에 대해서는 어떻게 생각하시나요?

설명만으로는 구조가 잘 그려지지 않아 예시가 있었으면 좋겠습니다. 그리고 객체의 depth가 늘어남에 따라 특정 value를 찾는 것이 비효율적일 수 있다 말씀 주셨는데 다음과 같이 객체에 id가 있는지 찾는 코드를 작성해보면

const genre = {}
const findId = 28

// 1 현재의 구조
const isExist = Object.keys(genre).some(key => key === findId)

// 2 제안드린 구조
const isExist = Object.values(genre).some(({ key }) => key === findId)

이런 식으로 Object의 메서드를 활용하여 동일한 시간 복잡도로 문제를 해결할 수 있습니다.

대부분 자료구조를 1 depth로 flat하게 가져가긴 하나 객체의 메타정보와 응집도가 더 필요할 경우는 2 depth까지는 종종 관리하기도 합니다. 다만 현재처럼 id를 키값으로 두는 경우는 협업을 하는 입장에서 GENRE를 가져다 쓸 때 매번 key가 의미하는 값이 무엇인지 찾아야하니 오히려 작업 + 소통하는 측면에서 비효율성을 초래할 수 있을 것 같습니다.

 

리뷰 리뷰

2번째 푸시는 사실 기대했던 것은 아니었다. 월요일 마감에 거의 다 되어서 제출을 했기 때문에 그냥 머지를 해준다고 해도 크게 이상할 게 없던 상황이라고 생각했기 때문이다. 그래서 감사한 마음이 있었다. 두 번째 푸쉬에서는 구조를 새로 리팩토링하기 보다는 기존에 받은 리뷰들을 수정하는 방식으로 갔는데, 그 중 이해가 가지 않는 부분에 대해 여쭤보았다. 다소 의사소통이 잘 되지 않아서 아쉬운 부분도 있었지만 납득이 가는 부분도 많았다. 여전이 왜 이렇게 하는 것이 좋을지 의아한 부분들이 있지만 다른 사람들의 코드를 살펴보면서 조금 더 고민을 해보고 다른 사람들에게도 물어봐야겠다고 생각이 든다.