영화 검색 SPA with Vue
Vue와 영화 검색이 가능한 API를 활용하여 간단한 영화 검색 웹페이지를 구현하는 과제로 실제 배포까지 진행되어야 했기에 serverless function에 이해도를 가져야 했던 과제였습니다.
프리뷰
구현 방법
router를 활용하여 페이지를 분리하는 방법도 있었지만 규모가 크지 않았던 만큼 정말 SPA로 구현하고자 하였고 검색된 영화를 클릭하면 모달로 상세페이지를 표시하는 방식을 사용하였습니다. 스타일링을 위해서 부트스트랩과 약간의 Sass를 이용하였습니다. 상태 관리를 위해 props 넘겨주는 방식으로도 어렵지 않게 구현이 가능했지만 Vuex를 활용해보고 싶었기에 이를 적용하였습니다.
Vuex 상태관리
본인이 사용하기 위해 정리한 상태값은 아래와 같다.
state() {
return {
isLoading: false,
searchTerm: null,
searchedMovies: {},
selectedMovieId: null,
selectedMovieDetail: [],
defaultPhoto:
'https://upload.wikimedia.org/wikipedia/commons/thumb/6/65/No-Image-Placeholder.svg/1665px-No-Image-Placeholder.svg.png',
}
}
충분히 props로 관리할 수 있을 정도의 내용들이지만 이번 기회에 Vuex의 기회비용을 생각할 수 있었다.
여기서 언급한 기회비용은 역시 Vuex를 사용하기 위한 세팅에 들어가는 시간이었다. 많은 시간이 필요한 것은 아니지만 props drilling이 일어나는 상황이 아니라면 굳이 사용할 필요는 없을 것 같았다. store에 따로 mutation과 action을 정리하고 이를 또 해당 컴포넌트로 가져와 사용해야 했기 때문이다.
장점으로는 어디서든 상태값에 접근할 수 있기에 넘겨주고 다시 올리는 방식을 고민하지 않아도 괜찮았다. 이 과제에서는 관리하는 상태값이 많지 않아서 복잡해 보이지 않았으나 복잡한 경우에는 오히려 더 헷갈릴 수 도 있을 것 같다는 생각이 들었다. 다행이었던 점은 store를 여러 개로 쪼개서 정리할 수 있다는 점이었다. 정리를 잘해놓는다면 쉽게 사용할 수 있을 것 같았다. (물론 이걸 잘하기 위해서는 실력이 좋아야...)
소소한 사용성 개선을 위한 내용들
과제를 진행하며 더 적절한 v-model의 기능이나 간편화를 적용하지 못해 아쉬운 마음이 들지만 잘 적용했다고 느낀 부분도 있다.
첫번째로 v-model.lazy를 활용해서 인풋값이 모두 작성되었을 때 상태를 변경하게 하였다. 이 lazy는 포커스 아웃이나 엔터를 눌렀을 때 상태를 변경하기에 불필요한 상태변경을 줄일 수 있었고 무엇보다 한글을 입력할 때에는 한 글자가 모두 입력되어야 상태가 제대로 변경되는 문제를 해결하기에 적절했다고 생각했다.
두 번째로는 모달을 이용해서 불필요한 페이지 이동을 줄인 점이다. 물론 SPA로 동작하여 페이지를 이동한다고 느껴지진 않지만 이번 프로젝트에 적합한 방법이었다고 생각한다. 모달 바깥 부분이나 x버튼을 클릭하거나 esc키를 입력하면 모달 창이 닫히도록 하였다. 여기서는 상태값 selectedMovieDetail이 빈값이 아닐 때 모달을 보여주고 닫을 때는 이를 비우는 방식을 사용한다.
마지막으로는 간혹 API에 포스터가 없는 영화들이 있기에 사진이 없을때 준비해 둔 기본사진을 보여주는 방식으로 처리하였다.
methods: {
defaultPhoto(url) {
if (url === 'N/A') {
return this.$store.state.movie.defaultPhoto
}
return url
}
}
Serverless Function.
이번 과제를 진행하며 가장 헤멘 부분인 것 같다. API키를 숨겨줘야 했기 때문이었는데 vercel을 통해 배포할 때 환경변수를 적용하면 빌드 후 제대로 배포가 되지 않는 문제가 발생했고 이를 해결하기 위해 같이 vercel을 사용하는 팀원과 많은 시간을 투자하였다. 전 팀 멘토님께서 어느 정도 언급을 해주셨기 때문에 뭐가 문제였는지 금방 찾을 수 있었으나 역시 적용 방법은 어려웠다.
Vercel은 serverless function을 지원하는데 이는 로컬이 아닌 지정된 해당 서버에서 이 함수를 사용하는 것으로 중간 단계에서 진행되기 때문에 환경변수를 적용한 작업을 쉽게 처리할 수 있다. 아래 request와 같은 handler 함수를 작성하고 해당 내용을 가져와야 한다. 이를 적용한다면 개발자 도구에서 네트워크 탭에 접근하더라도 키값을 숨길 수 있다.
import fetch from 'node-fetch';
const API_END_POINT = process.env.API_END_POINT;
const API_KEY = process.env.API_KEY;
export default async function request(request, response) {
try {
const { id, plot } = request.query;
const params = new URLSearchParams({ apikey: API_KEY, i: id, plot });
const res = await fetch(`${API_END_POINT}?${params}`);
const data = await res.json();
return response.status(200).json(data);
} catch (e) {
console.error(e + ': api 통신 중 에러가 발생하였습니다.');
}
}
리팩토링을 진행한 부분
- "Getter, setter 이용한 searchTerm 변경 개선" - searchTerm을 변경하기 위해 watch를 사용하여 변경될때 메서드를 적용하여 상태값을 바꾸는 방식을 사용하였으나 getter와 setter로 이를 간략하고 가독성이 좋게 정리하였습니다.
- "default photo 상태 변수로 변경" - 한 곳에 정리후 이를 가져와 활용하는 방식을 사용하였습니다.
- "onClick 이벤트 id 파라미터로 직접 전달" - DOM에 접근하여 id를 가져오는 방식을 사용하였으나 불필요한 부분이었고 이를 파라미터로 함수에 넘겨 처리하였습니다.
- "node js에서의 에러 표시 방법 수정" - serverless function에서의 에러처리는 프론트엔드 단에서는 보이지 않는다는 문제점이 있기에 alert에서 console.error로 수정하였습니다.
- "prettier 적용, inset으로 변경, 컨벤션 유지를 위한 코드 수정"
과제를 마치고...
Vue를 활용하여 프로젝트를 진행한 경험은 처음이였으나 좋은 강의를 통해 요구된 구현 사항들을 처리할 수 있었습니다. 추가 구현 사항으로 로딩 애니메이션과 이미지 해상도를 다르게 요청하고 open graph를 적용하는 등 다양한 부가 사항들도 공부해 볼 수 있었습니다. 기회가 된다면 Nuxt.js로 Vue SSR을 구현해보고 싶다고 느꼈습니다. vue를 사용하며 러닝 커브가 높다고 느꼈고 왜 인기 있는지 경험해 볼 수 있었습니다.
실시간으로 이미지 크기를 다르게 요청할 수 있는 원리에 대해 참고한 자료
https://heropy.blog/2019/07/21/resizing-images-cloudfrount-lambda/
'프로그래머스 데브코스 > 회고' 카테고리의 다른 글
프로그래머스 데브코스 - 5YES 팀 프로젝트 WuMo 회고 (6) | 2023.03.31 |
---|---|
프로그래머스 데브코스 - 팀 프로젝트 디그디그딥 (0) | 2023.01.31 |
프로그래머스 데브코스 - FE#7 CSS 과제 회고 (0) | 2023.01.25 |
프로그래머스 데브코스 - FE#6 Vanilla JS_2 과제 회고 (0) | 2022.12.25 |
프로그래머스 데브코스 - FE#4 노션 클론 과제 회고 (0) | 2022.12.16 |