05. 길고도 험난한 4주 완성 Vue.js
반갑습니다 주인장입니다. 저번보다 오랜만에 왔지요. 인스타그램 따라 만들다가 왔습니다. 이렇게 vue.js 강의가 마무리가 되었는데요, 앞으로 또 뭘 해야 하나 고민입니다.
우선 vue 강의 듣겠다고 javascript를 날림으로 배워서 es6에 맞는 문법을 간단하게 배우는 중이구요, 이건 하루 이틀이면 마무리가 되니까 이후엔 typescript를 조금 해볼까 합니다,, 개발자 구인 공고 보니까 다 어느정도 필요로 하는 것 같네요,, 근데 그 전에 인스타그램 강의 들으면서 따라 친 거 백지 상태에서 시작해서 함 해보기도 할 거구요 그럼 당장 적은 걸로만 해도 일주일 정도 걸리겠네요(보통 일주일이라고 하면 열흘로 치환하게 되죠)
또 이후엔 Vue.js로 뭐 하나 해보려고 하는데 마땅히 생각나는 게 없습니다. 서버 통신 안하고 만들만한 건 뭐 제 일기장이나 전화번호부 정도 밖에 생각이 나지 않네요. 조금 더 상세하게 말하자면 '남우현은 어떻게 개발자를 하기로 했고 뭘 하고 있는가'를 주제로 일대기를 담은 사이트나 친구들 개인 프로필을 담은 '남(우현의)친(구를)소(개합니다)'도 괜찮을 것 같습니다. 근데 이제 그것도 다 만들고 나면 그 때는,,, 그 때는,,,음 다른 사람들과 프로젝트로 뭘 좀 해보거나,,, React를 배워보지 않을까 싶습니다,,,
서론은 여기까지 하고 오늘은 며칠간 배운 인스타그램 따라 만들기를 되짚어 보려고 하는데요, 대단히 새로운 기술들을 배웠다기 보단 그간의 컴포넌트화, 데이터 바인딩들을 심화하는 게 제일 큰 비중을 차지했던 것 같습니다. 상태관리를 위한 vuex나 url 생성, axios를 활용한 ajax 요청, mitt 라이브러리 등(이렇게 써 놓으니 대단한 새로운 기술의 비중이 더 큰 것 같네요,,)도 배웠으니 한 번 가봅시다.
우선은 이런 모양새를 하고 있습니다.
App.vue라는 큰 틀에 Container.vue를 컴포넌트화 시키고 또 그 안에 Post.vue를 컴포넌트로 넣었습니다. 이후 Container.vue에는 Post.vue만 들어오는 게 아니고 게시물 업로드에 필요한 컴포넌트들이 들어오기도 합니다. 지금 생각해보면 굳이 Container.vue를 만들었어야 하나 싶기도 한데 어쩌겠습니까 하란 대로 해야지 뭐. 당장 Post.vue에서 보여줄 게시물들은
요렇게 다른 파일로 만들어서 import 해왔구요, 딱 저 3개뿐입니다. 여기서 이제 게시물을 더 가져오는 절차를 밟아보는데 여기서 ajax요청을 보냅니다.
Ajax 요청을 보낼 땐 Axios로 보내봅시다
사실 아직도 Ajax 요청을 보낸다는 게 어떤 의미인지는 잘 모르겠습니다. 하지만 여튼 간에 다른 통신들을 기다리지 않고 기다리게 하지 않고 get, post 요청을 보낸다고 대충 이해하고 있습니다. Ajax 요청을 보내기 위해선 뭐 여러 방법이 있는데 그 중에 Axios라는 라이브러리를 사용했구요 'npm install axios'라는 명령어로 라이브러리 설치 후 사용하고자 하는 컴포넌트에서
요렇게 import를 해줍니다. 사용법은 아래 코드 처럼
axios.get(요청을 보내는 URL).then((받아온 데이터)=>{데이터를 처리하는 함수})로 이루어 집니다. 그 동안 제이슨, 제이슨 하고 어디서 누군가 맨날 떠들어 대던 걸 이제야 제가 한 번 써봤습니다. url에 this.more라고 데이터 바인딩 되어있는 건 게시물을 한 번만 끌어오는 게 아니라서 함수 실행마다 1씩 커지는 변수를 넣어놓은 겁니다.
사진 업로드 페이지를 위한 UI 설계
와, 진짜 별 거 아닌 내용인데 ~~를 위한 UI 설계 라고 써놓으니까 마치 뭐 대단한 것이라도 만든 것 같은 기분이랄까요 별 거 아니고
기존 페이지에서 저기 저 플러스 버튼을 정확하게 누르면
요렇게 이미지 파일을 선택하게 되고, 선택하면
이렇게 필터를 선택하는 탭이 나오구요, 여기서 필터를 선택하고 나면
이렇게 글을 쓸 수 있는 화면이 나오구요, 위에 발행 버튼을 누르면
짠! 이렇게 새로운 게시물이 생성됩니다. 각 화면은 기존에 배웠던 UI 설계를 통해서 했구요(대충 설명을 생략하겠다는 말) 선택한 이미지의 url을 만드는 것과 화면에 필터를 나열하고 선택한 필터를 바로 바로 적용하여 이미지로 보여주는 것, 그리고 각 데이터를 저장해서 게시물로 올리는 게 보다 어려운 일이었습니다.
(잡기술) 이미지 URL 얻어보자
앞서 + 버튼을 누르면 이미지 선택 후 다음 탭으로 넘어갔는데요, + 버튼을 누르면 upload() 함수가 동작합니다. 그리고 그 업로드 함수는,,,
이렇게 생겨먹었습니다. e.target.files로 선택한 이미지를 uploadFile에 담아놓고 그걸 URL.createObjectURL() 안에 넣어주기만 하면 이미지 url생성 끝! 해당 url은 나중에 쓸 데가 있어서 imageURL이라는 변수에 담아주었습니다. url은 String이라서 애초에 imageURL : ''로 선언해놨구용
mitt을 이용한 데이터 전송
필터를 선택하는 화면입니다. 일단 필터가 아래 쭉 나열되어 있구요 그 중 하나 선택하면 위 이미지에 적용됩니다. Container.vue에 배열로 각 필터들을 쭉 저장해놨구요 배열 길이만큼 Filter 컴포넌트를 반복시켰습니다.
그리고 Container.vue에서 각 필터들을 하나씩 꺼내서 props로 Filter.vue에 쏴주었구요, cssgram이라는 뭐시기를 사용하면 저렇게 클래스에 필터 이름을 넣어주는 것만으로도 인스타 필터 효과를 줄 수 있다고 함미다. 여기는 생략하죠. Filter.vue에는 아까 만들어놓은 imageURL을 배경으로 넣어서 필터들이 여러개 나열되는 부분을 완성했습니다. 이제 여기서 필터를 하나 선택하면 그게 큰 이미지에 적용되는 것을 구현해야 하는데,,,
mitt로 커스텀 이벤트를 자유롭게 다뤄보세요
기존에 자식 컴포넌트에서 부모 컴포넌트에 데이터를 쏴주거나 수정할 땐 $emit을 사용했지요 하지만 직계 부모 자식간에만 가능한 기능이었습니다. Filter.vue에서 선택한 필터는 Container.vue만이 아니라 App.vue에도 보내야하는데 그럼 어떻게 해야할까용? 왜 App.vue까지 보내냐고? 그거야 새로운 게시물을 만들 때 필터 정보도 받아야 하니까? 못 알아듣나? 그치 당연하지 나만 알아듣지. 여튼 커스텀 이벤트를 컴포넌트 사이에서 자유롭게 사용하기 위해 mitt라는 라이브러리를 사용했습니다. 이것도 뭐 npm install mitt를 먼저해주고
main.js에 이렇게 등록을 해주고, 사용해봅시다. Filter.vue에서 필터를 하나 선택하면 sendFilter() 함수가 실행되는데 그 함수는 바로 바로
이렇게 생겼습니다. mitt 라이브러리를 사용하는 방법이죠. this.emitter.emit(커스텀 이벤트의 제목, 보낼 데이터)입니다. 그럼 이렇게 보낸 데이터를 App.vue에선
라이프 사이클 훅으로 mounted 시점에 저렇게 받아줍니다.
this.emitter.on(받을 이벤트 이름, (전송된 데이터)=>{그 데이터로 처리할 작업})
이라고 보면 되겠습니다. App.vue에는 userFilter : ''를 미리 만들어 놨답니다. 그리고 다음 화면으로 넘어가면 textarea에 글 내용을 입력하고 그것도 App.vue로 넘기는데, 이거 만든 순서가 "textarea에 적은 내용 App.vue로 보내기 -> Filter.vue만들기 -> mitt라이브러리 사용법 배우기" 여서 textarea에 적은 내용은 mitt 안 쓰고 $emit 씀. 토 달지 마셈. 뭐 어떡하라고.
자 그럼 이제 게시물을 따란~ 하고 올리면 된다
지금쯤이면 App.vue에는 온갖 데이터들이 다 모여 있을 겁니다. 업로드한 이미지, 선택한 필터, 사용자가 쓴 글 등이 말이죠. 그럼 이걸 어떻게 Object로 잘 묶어가지고 앞서 포스팅 데이터가 모여있는 곳에 추가해주면 게시물로 보인다 이 말 아닙니까?? 그래서 publish라는 버튼을 누르면 아래와 같은 일이 벌어집니다.
대충 무슨 말인지 아시겠지요? javascript를 안 다뤄봤다고 해도 대충 알 것만 같은 코드입니다. unshift는 배열 가장 첫 자리에 추가하는 거임. 여튼 이렇게 새로운 게시물이 땋 만들어졌습니다~~와~~
Vuex에 대하여
사실 vuex에 관해서 배운게 여기에 쓸 거 이외에도 actions, mapState 등 더 많은데 이게 아무래도 강의 후반부에 있다보니까 집중력이 떨어졌달까요, 그리고 만드는 사이트에 크게 적용하지도 않아서 날림으로 넘어갔습니다. 뭐 문법이나 개념의 존재를 알고 있으니 나중에 모를 때 다시 보면 되지 않을까요,,,?? 그래도 간단하게 사용한 부분을 보자면,,,
왜 그 동안은 중요한 데이터를 보통 App.vue에 넣어두지 않았습니까? 그래서 어디 필요한 곳 있으면 props로 쏴주고 다른 곳에서 변경하려고 하면 emit으로 메시지 보내고 뭐 별 거 다 했다아입니까,, 그래서 뭐랄까 데이터 집합소 같은 곳이라고 보면 좋을 것 같네요. 근데 이제 상태관리 라이브러리라고 하는 이유는 '어떤 UI가 보이는 상태' 같은 것도 데이터로 저장을 해왔기 때문에 그런 거 아닐까요 npm install 뭐시기로 또 vuex를 설치하구요
store.js라는 파일을 만듭니다. 그리고 어떤 템플릿을 박아넣구요 또 main.js에 이거 쓴다고 import도 따로 해줍니다. 그럼 vuex 사용할 준비 끝! 우리가 흔히 말하는 데이터를 vuex에선 state라고 합니다. 그래서 저기에 넣어놓은 데이터는 어떤 컴포넌트에서든 자유롭게 사용이 가능합니다. 심지어 어떤 컴포넌트에서든 자유롭게 수정이 가능한데요, 그건 불법입니다. 컴포넌트에서 store에 있는 state를 바로 바꾸면 컴퓨터가 과부하에 걸려 터져버린다고 하니 명심하시길 바랍니다. 대신 mutations에 state를 변경하는 함수를 미리 작성해두고 그 함수를 호출하는 식으로 해야합니다. mutations에 들어 있는 것들은 전부 함수고 000(state)라고 꼭 인자를 넣어두셔야 합니다. 그리고 두 번째 인자로 적힌 data는 함수를 호출하는 곳에서 전송한 데이터입니다. 이걸 이용해서 좋아요 기능을 만들긴 했는데 뭐 딱히 설명드리고 싶진 않습니다. 진짜.
아 다른 컴포넌트에서 state에 있는 변수나 함수를 호출할 땐
이렇게 호출해주시면 됩니다. 근데 호출할 때마다 $store.state 뭐시기~ $store.commit()뭐시기~쓰기 귀찮으니 mapState, mapMutation 등을 쓰는데 그건 앞서 말씀드린 대로 생략,,,
진짜 끝! 이거 외에 PWA이나 Composition API를 배우기도 했는데 너무 귀찮아요 너무. 그리고 사실 간단한 블로그 만들기 까지 배운 문법과 이런 저런 것들이 Vue.js의 90%라고 봐도 무방하답니다. 뭐랄까 이후에 배운 것들은 점점 복잡해지는 코드들을 정리하고 관리하는데 편하도록 하는 느낌이 강해요. 물론 이게 후반부에 가면 아주 중요하겠지만 아직은 집중할 부분이 아니어도 괜찮다고 봅니다. 뭐 여튼 서론에서 이것 저것 떠들었으니 그만 하겠습니다. ㅃ