[에러로그] Vue 과제 에러 로그

Jade·2023년 4월 29일
1

에러로그

목록 보기
2/2
post-thumbnail

최근 회사에서 회사 페이지를 클론 코딩 해보는 과제들을 수행하고 있다.
Vue에 좀 더 익숙해지는 데 많은 도움이 된다.
오늘은 사실 출장으로 만족할 만큼 과제를 수행하지 못한 것 같아서 마무리를 하려고 했는데, 마무리를 지으려고 보니...^^... 고쳐야 할 부분이 많아서 내내 노트북을 붙잡고 있었다.
따로 작성하고 있는 업무 일지에도 작성했고, 회사 코드는 직접적으로 게시할 수 없지만 간략하게 벨로그에도 알게된 점들을 남겨두면 좋을 것 같아서 TIL을 작성해본다.

에러 로그

🐝 얕은 복사와 깊은 복사

Vuex store에서 가져온 데이터를 spread 연산자로 복사해서 사용하고 있었는데, spread 연산자는 1차원 배열에서는 깊은 복사를 하지만, 배열 내부에 객체가 있는 형태일 때는 얕은 복사를 행하게 된다. 내가 복사하는 데이터는 배열 내부에 객체가 있는 형태였다.

이 점을 간과하고 코드를 짰었고, 내가 원한 건 깊은 복사가 된 새로운 배열(요소들은 객체)에 새로운 속성들을 추가하는 것이었지만, 그렇지 않았기 때문에 do not mutate vuex stroe state outside mutation handlers 라는 에러를 만나게 됐다. (Vuex 상태들은 mutation 함수를 사용해서만 변경이 가능하다.)

깊은 복사를 수행한 것처럼 아예 새로운 배열을 만들고 싶다면 forEach를 사용해 원본 배열을 순회하면서 복사 및 속성 추가를 할 것이 아니라 map을 사용해 아예 새롭게 구성한 객체 요소들을 담은 새로운 배열을 리턴해줄 수 있었다.

(원래 2차원 정도의 깊이를 복사할 때 json 형태로 바꾸어 복사하거나, 아예 2차원 깊이까지 복사를 하는 함수를 만드는 방법이 있다고는 하는데 내가 코드를 작성하는 상황에서는 유용한 방법이 아니었다.)



🐝 cannot read property of undefined

과제를 하면서 정말 많이 보게 되는 에러 중 하나인데 이번에는 데이터를 post 요청 보낼 때와 get 할 때의 데이터 형식이 약간 달라서 만나게 됐다.

막연하게 post 요청할 때 보내는 형식과 get 요청으로 받는 형식이 같겠지 생각했었는데, post 요청을 할 때는 id 값이 담긴 배열을 보내고, get 요청으로 받아온 데이터에서는 서버에서 해당 id 값으로 해당하는 데이터들이 객체로 담긴 배열을 보내주고 있었다.

이런 부분은 아무래도 실사용하는 복잡한 데이터와 api를 처음 마주하기 때문에 겪는 문제인 것 같은데, api 문서나 이미 사용되고 있는 다른 페이지들을 참고해 보완하면 될 것 같다.

이렇게 잘 모르는 부분들을 처음에는 하나하나 찾아보는 것이 피로도가 쌓이는 부분이기는 하지만 꼭 필요한 과정이라고 생각하기 때문에 앞으로도 좀 귀찮더라도 잘 살펴보면서 과제든 프로젝트든(맡겨주신다면!) 해결해나가야지!



🐝 event emit을 컴포넌트 밖에서 하기

props는 리액트에도 있는 개념이라 익숙한데, event emit은 이름만 들었을 때 좀 생소한 느낌이기는 했다. (리액트에도 비슷한 state lifting up이 있기는 하지만)

vue를 공부할 때 event emit 예시로 봤던 건 자식 컴포넌트 파일의 매서드 속성에서 함수를 addNumber: function() {this.$emit('pass')}과 같이 작성해주면, 이 자식 컴포넌트를 사용하는 부모 컴포넌트에서 v-on:하위 컴포넌트에서 발생한 이벤트 이름="상위 컴포넌트의 메서드 이름"과 같이 작성하는 간단한 예시였다.

과제에서는 좀 더 복잡했는데, 실제로 부모 컴포넌트의 html 코드에 <자식 컴포넌트/>와 같은 코드가 없는 경우였다. 버튼을 클릭했을 때 특정 컴포넌트가 띄워지도록 하는 매서드만 존재했다.



🐝 데이터 누락 조심하기

데이터들을 v-for문으로 돌려놓고 렌더링을 확인했는데, 각 섹션별로 데이터가 꼭 하나씩 누락된 것을 확인할 수 있었다. 뭐지...? 하면서 코드를 다시 살펴봤는데, 삼항연산자를 잘못 사용한 것이었다.

객체에 특정 키가 존재하면 키의 value(배열임)에 push로 순회하고 있는 배열의 요소를 넣어주고, 아닌 경우 새롭게 해당 키를 생성해서 해당 차례의 배열 요소를 넣어주어야 했는데, 새롭게 키를 생성할 때 빈 배열을 할당했기 때문에 생긴 문제였다.



🐝 methods, computed, watch

computed로 고쳤던 method들 중 다시 method가 된 함수도 있고, watch를 이용해 데이터의 변화를 추적하기로 했다. computed는 결국 연관되는 data가 변경될 때만 캐싱된 값이 변경된다. 처음에는 사용하는 computed의 값이 변경되더라도 해당 값들이 업데이트 될 거라고 생각했어서 대부분의 매서드들을 computed로 변경했었는데 나중에 새롭게 추가된 경력 데이터가 있어도 computed가 두번째 적용되는 부분부터는 갱신이 되지않는 것을 보고 깨달았다. (헤딩을 직접 해봐야 아는 타입인가 나는…^^) 아… computed는 오직 연관된 data가 변경될 때만 갱신이 되는구나…

computed는 data의 값을 변경시킬 수 없으므로 각 computed 값들을 data에 저장해줄 수도 없었다. 그럼 이 computed 값들을 다시 다 매서드로 변경시켜야 하는건가… 하다가 문득 watch가 생각났다.

watch는 computed와 다르게 계속해서 어떤 데이터를 감시하고 있는 속성이다. computed에 작성되었던 함수들을 methods로 조금 옮기고, 데이터 가공을 watch에서 해준다면 Vuex store에서 가져온 데이터가 변경이 되었을 때 가공 과정을 다시 실행시켜 화면을 바로 바로 갱신해줄 수 있을 것이라고 생각했다.

watch 내부에서는 data를 업데이트 해주는 것도 가능하다.

watch에 대해 좀 더 알아보니 watch는 ‘언제 변하는지 예측하기 어려울 때’ 사용하면 좋다는 문장이 있었는데, 이 경우가 언제 경력 데이터가 업데이트 될 지 모르는 상황이므로 잘 맞는 상황이구나, 하고 이해할 수 있었다.

computed는 연관되는 data가 완전히 있고, 그 data에 대해 복잡한 연산을 수행해야하는데, 그 연산의 비용을 줄이고 싶을 때 사용하면 되겠다. (두 가지를 통용해 사용할 수 있는 경우도 분명히 있을텐데, 그럴 때는 computed가 더 적절하다고 할 수 있다 - 캐싱을 하기 때문에 계속해서 감시하는 watch보다 더 비용이 덜 든다)




느낀점

  • 확실히 이번 과제는 이전 과제보다 복잡하기도 했고, 주어진 정보도 적어서 + 가공해야 하는 데이터도 복잡한 편이어서 많이 헤맸던 것 같다. 하지만 이렇게 헤맨 덕분에 처음보는 컴포넌트를 어떻게 이해해야 하는지도 좀 더 공부해볼 수 있었고, computed, watch, event emit 같은 애매하고 알고 있던 개념들에 대한 이해도도 높일 수 있었다.

  • 앞으로 좀 더 공부해야 할 것이 있다면 아무래도 Vuex의 사용이나, nuxt.js의 사용과 같은 부분을 좀 더 공부하면 좋을 것 같고, 디폴트 컴포넌트들 this. 컴포넌트이름 으로 불러올 수 있는 녀석들을 꽤 많이 사용되기 때문에 그렇게 해놓은 것 같아서 해당 코드들을 정리해둔 js 파일들을 세세하게 읽어보는 것도 좋을 것 같다.

  • Vue 개발자 도구에서 computed 데이터들을 콘솔에 찍어보지 않아도 실시간으로 잘 계산되었는지 확인할 수 있어서 좋았다. 근데 가끔은 콘솔에 직접 찍어봐야 하는 경우들도 분명 있으니 두 도구들을 잘 섞어서 사용하면 좋을듯 !

profile
키보드로 그려내는 일

0개의 댓글