이전에 vue를 사용해본적 없다가 써보게 되었다. 지원했던 회사에서 과제 조건으로 vue아니면 jquery를 사용해서 설계하라고 했기 때문이다. jquery는 정말 어쩔수 없는 경우 아니면 배우기 싫기 때문에 vue를 선택하게 되었다. vue와 react의 차이나 vue만의 장점을 따질 겨를도 없이 무작정 vue 홈페이지로 달려갔다.
react에서 component의 생애 주기를 처음에 배우는 것처럼 vue가 어떻게 동작 되는지 개념을 익힐 시간이 없기 때문에 그냥 무작정 cli를 설치했다. vue3를 사용했다. vue를 설치하고나서 react와 유사점을 찾아서 동작 방법을 익히기로했다. 분명 유사점과 차이점이 있을테니까. 주어진 시간이 짧다면 그 점을 공약하는게 쉬울 듯 했다.
일단 react는 javascript 파일에서 모든 것이 동작되는 것과 다르게 vue라는 확장자를 따로 만들어줘야한다.
<template></template>
<script></script>
<style></style>
vue는 구조가 정해져있다.
약간 react style component를 설치하지 않고 style에서 바로 관리하는 느낌이었다. html 태그가 늘어날 수록 id나 class의 수도 늘어나는데 나중에 이것을 관리하기가 너무 불편하다. react는 style component로 tag 자체를 component화 시켜서 바로 적용할 수 있는 장점이 있다.
vue는 html에서 style을 직접 작성하는 것처럼 되어있는데 global한 style과 scope로 나뉘어있는 것 같다. (global과 local과 같이...) scss를 사용하면 상태 관리를 그나마 편하게 할 수 있었다.
script를 사용하는게 제일 어려웠던 것 같다. name, props, data, methods, components, created, computed, watched와 같은 정해져있는 값이 있다. 마치 javascript의 class처럼 미리 선언된 구조를 빌려와 쓰는 것 같은 느낌이었다.(그렇다고 내가 객체 지향 언어를 썼다고 보기는 어렵다.)
props와 data에서 선언된 data는 this로 읽히기 때문에 method나 created에서 새로운 함수를 만들 경우에 화살표 함수를 쓰지 않는다. 화살표 함수와 this는 완전한 개념을 잘 모르기 때문에 공부하고 포스팅하기로 한다. 다만 화살표 함수는 this가 es5함수와 다르게 동작한다는 것만 알고 있다. 화살표 함수로 this를 사용하지 못하는 것은 아니지만 아마도 .bind나 .apply같은 함수를 사용해서 가리키고 있는 this가 무엇인지 정확하게 만들어줘야하는 것으로 알고 있다.(맞나?)
script에서 생성된 값은 template에서 v-bind, v-on, v-for등과 같은 vue의 문법으로 넘겨질 수 있다.
예제
<template lang="pug">
.sample(v-for="item in sampleData.array")
p {{item}}
</template>
<script>
export default {
name:"Example",
data(){
return {
sampleData:{}
}
},
methods:{
async sampleFetch(){
const res = await fetch("https://sample.com/api/data",{
method:"GET"
});
const {data} = await res.json();
return data
}
},
async cretaed(){
this.sampleData = await this.sampleFetch()
}
}
</script>
vue의 특징은 콧수염 기법이나 디렉티브 기법 등과 같은 방법을 사용해 javasciprt에서 생성된 값을 동적으로 전달 할 수 있다.
react에서는 hook을 사용하면 이런 점이 가능하다. 하지만 아직 둘의 차이점은 잘 모르겠다.
개인적으로 지금까지는 react hook이 더 사용하기 편리했다.
vue router는 사용하기가 너무 어려웠다. react router와 작동하는 방법은 거의 비슷하다. 그런데 vue router로 컨트롤 할 수 없는 문제들이 나를 미치게했다.
router 중첩이 내가 원하는대로 안됐다. 이게 뭔 말이냐면 vue나 react는 vitual-dom을 사용하여 페이지를 랜더링한다. 그래서 페이지를 새로고침 할 필요 없이 컴퓨터가 바뀌는 부분만 감지를 해서 그림을 새로 그려주는 식으로 동작한다. 그래서 url값이 바뀔때, 페이지 전체 데이터를 다시 req하는게 아니다.
react에서는 router를 사용하면 동일 선상에 있는 url값은 중첩을 해서 내가 원하는 정보를 동시에 내보낼 수 있었다. 그런데 vue router는 이게 왜 안되지? children으로 하면 될 줄 알았는데 그렇지도 않았다. 아마 뭔가를 잘못 설계한게 분명하다. vue router를 설계하신 분들이 이걸 모를리가 없다. 6일간 뒤지고 뒤져봤지만 찾을 수가 없었다.
혹시 이 글을 여기까지 읽으셨다면 방법 공유를 부탁드립니다...(절)
어쨌든 vue router를 이해하는 건 필수다. router를 통해 원하는 컴포넌트만 원하는 곳에 출력할 수 있기 때문이다.
<template lang="pug">
.sample(v-for="item in sampleData.array")
p {{item}}
router-view(:sampleData="sampleData")
</template>
<script>
export default {
name:"Example",
data(){
return {
sampleData:{}
}
},
methods:{
async sampleFetch(){
const res = await fetch("https://sample.com/api/data",{
method:"GET"
});
const {data} = await res.json();
return data
}
},
async cretaed(){
this.sampleData = await this.sampleFetch()
}
}
</script>
'router-view'에 원하는 정보를 내보낼 수 있다. 그럼 이런 경우가 있다. 어떤 페이지에서는 페이지를 통채로 바꿔야하고 어느 곳에서는 일부만 바꿔야하는데 router-view가 여러개면 어디에 어떻게 정보를 보낼 수 있는가?
그건 router를 설계 할 때, children을 사용해서 설계하면된다. 그러면 원하는 component에서 router-view를 사용하면 원하는 값을 출력 할 수 있다. 나는 아래 링크의 문서와 유튜브를 둘다 보면서 router를 설계했다.
만났던 몇 가지 오류를 해결한 방법을 공유하고 글을 마치는게 나을 것 같다.
예제
<template lang="pug"> .iterate p(v-for="item in sampleString.split(" ")"){{item}} </template>
위 구문은 오류를 뿜어낸다. 이것 뿐 아니라 .map을 사용하는 것도 마찬가지다. json데이터를 불러와 가공하려면 split이나 map으로 데이터를 적절하게 조작할 수 있어야한다. 그런데 데이터가 불러와지기는 하는데 TypeError가 계속 발생했다.
정확히 어떤 문제인지 이해가 완전하진 않지만 불러온 데이터가 분명 존재하는데 undefined가 되는게 원인이다. 왜 데이터가 존재하는데 undefined을 주는 건지 이해가 되지 않는다.
해결 방법 레퍼런스는 undefined를 정의해주라고 한다. (?)
<template lang="pug">
p(v-for="item in (sampleString || "").split(" ")"){{item}}
</temlplate>
이러면 문제가 해결된다. 그런데 아래 댓글에 더 좋은 방법이 있었다. 바로 computed에서 데이터를 조작해서 가지고 오는 것이다. 이러면 template에서 적어야하는 코드가 쓸데없이 길어지지 않을 수 있어 좋다.
<script>
computed(){
sampleStringArray(){
return (sampleString || "").split("")
}
}
</script>
이 방법으로 map이나 다른 기타 함수를 사용할 때 발생하는 똑같은 오류를 해결할 수 있었다. 다만 map은 array이기 때문에 빈 문자열대신 빈 배열을 값으로 넘겨야한다.
초반에 데이터가 정상적으로 bind 됐는지 확인하기 위해서 console.log()를 하려고 하는데 당최 어디서 하는지 알수가 없었다. created(){}내부에서 하면 된다. 확인하려는 props이나 data등은 this를 붙여야한다.
이미지가 있을 때는 imageUrl 값을 사용하고 그렇지 않을 경우에는 내가 가지고 있는 값을 사용하려고 하는데 당최... 작동을 하지 않았다. 삼항연산자 값이 true일 경우에는 작동을 하지만 false일 경우에는 작동은 하나 파일을 불러오지 못했다. 다행이 짧은 시간안에 해결할 수 있었다. 한시간 정도...?
<template lang="pug">
img(:src="imageUrl ? imageUrl : require('@/assets/ex.png')")
</template>
react를 내가 능동적으로 사용한 적이 거의 없었다. vue는 능동적으로 뭔가를 만들어보면서 google을 미친듯이 찾아 헤맸는데, react는 동영상 강의를 수동적으로만 시청했던 것 같다. react로 front-end를 한번 설계 해봐야겠다. 아마 수많은 에러를 만나겠지만 이렇게 성장할 수 있는 것 같다.