심화 프로젝트 주제로 전통시장을 홍보하는 웹사이트를 구현하기로 했다. 원래는 공공데이터포털에 '전통시장표준데이터규격' api를 사용하려고 했는데 계속해서 SERVICE KEY IS NOT REGISTERED ERROR 이라는 오류가 떴다. 인증키를 재발급 받아보기도하고, 인코딩된 키값을 넣어 호출하면 해당 키값이 한번더 인코딩되어 온다고해서 decodeURIComponent() 메서드를 사용해서 디코딩 작업을 했는데도 오류가 사라지지 않았다.. 공공데이터 키값으로 해당 에러를 경험한 사람이 많아서 우선은 구글에 나오는 방법들로 시도해봤지만 에러가 고쳐지지 않아 공공데이터포털에 문의를 넣은 상태이다. 키 값의 문제가 아니라고 하면 에러 이유에 대해서 더 알아봐야할 것 같다.
그렇게 돌고 돌아 다른 api 를 찾다가 원래 가지고 오려는 api보다 더 많은 정보가 있는 '전통시장현황' api를 발견했다.
2. 버튼으로 슬라이드 동작 구현하기 (swipe-button-next / swipe-button-prev)
3. tmdb 데이터 가져와서 뿌리기
html
<!-- 슬라이드 영역 -->
<div id="main-banner" class="swiper-container banner">
<div class="main01-nav">
<!-- prev, next -->
<button class="swiper-button-next"></button>
<button class="swiper-button-prev"></button>
</div>
<div id="wrapper" class="swiper-wrapper-banner">
</div>
</div>
<!-- 슬라이드 영역 -->
tmdb 데이터를 받아와서 dom을 생성해줄거라서 html에 원래 만들어놓은 코드는 빼고 시작! 전 코드보다 아주 많이 간결해졌다.
css는 건드린게 없어서 생략하고 바로 js 파일 수정을 해보자.
Javascript
//tmdb api
const options = {
method: "GET",
headers: {
accept: "application/json",
Authorization:
"Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI5ZDE3MGZlMGJlM2UwZDE3NzkyMGE3MDQxZmQ1NGM4NiIsInN1YiI6IjY2MjVkYTMzMjIxYmE2MDE3YzE1NDQ1ZSIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.tRZNYVownPtQj6yIFrodZCqJZfvFyuPxHjF_kH8JMyI",
},
};
// 영화 장르 ID 정보
fetch("https://api.themoviedb.org/3/movie/popular?language=ko-KR&page=1", options)
.then((response) => response.json())
.then((data) => {
let movieList = data['results'];
initSlider(movieList);
});
패치를 가져와서 정보를 movieList에 저장해주고, movieList 데이터를 인자로 받아 아래 만든 캐러셀 함수를 호출해준다. 패치 데이터 저장하는게 제일 쉽다 진짜.. 이것만 하고싶다..
function initSlider(movieList) {
const wrapper = document.querySelector('.swiper-wrapper-banner')
const prevBtn = document.querySelector(".swiper-button-prev");
const nextBtn = document.querySelector(".swiper-button-next");
movieList.forEach(a => {
let slideimage = 'https://image.tmdb.org/t/p/w500' + a['poster_path'];
let slidetitle = a['title'];
let ogtitle = a['original_title'];
let movieid = a['id'];
}
movieList 데이터를 순회해서 각 변수에 데이터 값을 할당해준다. 배너에 필요한 데이터는 이미지와 타이틀, 영문 타이틀이고, movieid는 배너를 눌렀을 때 id가 동일한 상세페이지로 이동해야하기 때문에 같이 선언해준다. 맨 위 wrapper, prevBtn, nextBtn은 따로 dom을 만들지 않고 이미 html에 있는 요소이므로 querySelector를 사용해서 가져왔다.
배너 위에 올라가는 텍스트들은 slide-txt 안에 h1, p태그가 있는 구조인데 위처럼 엘리먼트만 생성해주면 slide_txt안에 h1, p태그가 생기는게 아니라 다 따로 생성되기 때문에 slide_txt.append(titleEl, ogtitleEl); 이걸 해줘야 slide_txt 안에 태그들이 들어간다.
이렇게 생긴다고 보면된다! 그래서 slide-txt에 css 를 주면 h1, p 태그 모두 적용이 가능하다. 배너 위에 올라가서 position : absolute; 를 주어야하는데 h1, p 태그 따로 주고싶지 않아서 append 했다.
배너를 클릭했을 때 id값이 동일한 상세페이지로 이동하게 해주고 html에 위에서 만든 dom을 뿌려주면 우선 영화 데이터 가져오기는 끝!
const slideCount = 20; //array(20)
//슬라이드 0번째에 있는 컨텐츠의 크기를 확인 => 이미지 사이즈 : 1250px / margin : 0 10px
const size = 1270
//currentIndex = 1로 초기값 슬라이드[1]
let currentIndex = 1;
function updateSliderPosition() {
wrapper.style.transform = `translateX(${-size * currentIndex + 70}px)`; //-1270 * 1 + 70
}
다음은 슬라이드가 움직이도록 만들어보자. 우선 내가 가져온 영화의 수는 20개라서 slideCount도 동일하게 값을 주었다. 사이즈는 배너의 크기를 저장하는 변수로 이미지 사이즈 1250px에 margin 사이드 10px씩 더하면 메인 화면에 보이는 사이즈는 1270px 이다.
아래 +70은 메인 배너 사이드로 보이는 다음 배너와 이전배너가 조금씩 보여야하기 때문에 준 값이다.
데이터를 불러오기 전과 다른 점은 변수만 달라졌다는 것! 데이터가 할당된 변수로만 바꿔줬다.
🔥 완성
흠이라면.. tmdb에서 제공하는 이미지의 화질이 좋지 않다는 것 .. img를 100% 채웠더니 다 깨진다 .. 영화진흥위원회 API를 사용해도된다고 했었는데 여긴 이미지 자체를 제공하지 않아서 기존에 작업하던 tmdb로 작업하라고 했다. 새로운 api를 사용할 수 있는 기회였는데 아쉽지만 차라리 잘됐다(?) 처음부터 시작하는 것보다 내가 원래 하던걸 제대로 마무리 하는게 나으니께 후후 "오늘도 나는 성장했다" 재훈이가 맨날 ㅋㅋㅋㅋ 오류 해결하고 하는 말인데 왠지 모르게 웃기면서도 뭔가 진짜 성장하는 것 같은 느낌이 든다..! 앞으로 나도 자주 써야할 듯~ㅋㅋ
-카드에는 title(제목), overview(내용 요약), poster_path(포스터 이미지 경로), vote_average(평점) 이렇게 4가지 정보가 필수
-카드 클릭 시에는 클릭한 영화 id 를 나타내는 alert 창을 띄우기
4. 영화 검색 UI 구현
5. Javascript 문법 요소를 이용하여 구현
-const와 let만을 이용한 변수 선언 필수
-화살표 함수
-배열 메소드 : 하기 예시 중 2개 이상 사용
forEach
map
filter
reduce
find
-DOM 제어하기 : 아래 api 목록 중 2개 이상 사용하기
document.createElement(tagName) //새로운 HTML 요소를 생성합니다.
document.getElementById(id) //id 속성을 기준으로 요소를 선택합니다.
document.getElementsByTagName(name) //태그 이름을 기준으로 요소를 선택합니다.
document.getElementsByClassName(name) //클래스 이름을 기준으로 요소를 선택합니다.
document.querySelector(selector) //CSS 선택자를 이용하여 요소를 선택합니다.
document.querySelectorAll(selector) //CSS 선택자를 이용하여 모든 요소를 선택합니다.
element.innerHTML //해당 요소 내부의 HTML 코드를 변경합니다.
element.textContent //해당 요소 내부의 텍스트를 변경합니다.
element.setAttribute(attr, value) //해당 요소의 속성 값을 변경합니다.
element.getAttribute(attr) //해당 요소의 속성 값을 가져옵니다.
element.style.property //해당 요소의 스타일 값을 변경합니다.
element.appendChild(child) //해당 요소의 하위 요소로 child를 추가합니다.
element.removeChild(child) //해당 요소의 하위 요소 중 child를 삭제합니다.
element.classList.add(class) //해당 요소의 클래스에 새로운 클래스를 추가합니다.
element.classList.remove(class) //해당 요소의 클래스 중에서 특정 클래스를 제거합니다.
element.classList.toggle(class) //해당 요소의 클래스 중에서 특정 클래스를 추가 또는 제거합니다.
element.addEventListener(type, listener) //해당 요소에서 이벤트가 발생했을 때 호출할 함수를 등록합니다.
element.removeEventListener(type, listener) //해당 요소에서 등록된 함수를 제거합니다.
event.preventDefault() //이벤트가 발생했을 때 기본 동작을 취소합니다.
event.stopPropagation() //이벤트의 버블링을 방지하기 위해 이벤트 전파를 중지합니다.
window.location.href //현재 페이지의 URL을 가져옵니다.
window.alert(message) //경고 메시지를 출력합니다.
window.confirm(message) //확인 메시지를 출력하고 사용자의 답변에 따라 Boolean 값을 반환합니다.
🔥 완성
각 영화 카드를 눌렀을 때 고유 id가 alert 뜨기도 했고, 영화 제목을 검색했을 때 해당 영화만 뜨도록 구현도 완료했다!
순수 바닐라는 너무 오랜만이고 실무에서도 제이쿼리만 쓰다보니 너무 헷갈리고 메서드도 잘 기억이 안난다
그래서 요즘은 알고리즘 문제들만 주구장창 푸는 중이다. 풀다보니 메서드 기억이 새록새록 올라와서 요즘 꽤 재미 붙이고있다.
사용자가 검색한 영화 제목이 포함되어있지 않은 카드들은 display:none; 하는 코드를 짜봤다. 우선, dom요소들을 가져오고 각 변수에 선언해준다. 검색 기능이 아예 감도 안잡힐 때 🧑🏻🦱은채 튜터님한테 물어봤는데 querySelector로 html 요소들을 가지고와서 작업하면 편리하다고 말씀해주셨다. 전에는 주구장창 getElementById만 써서 특정 아이디가 아니면 동작을 안해서 골머리를 썼는데..
function searchHandle(e){
e.preventDefault();
let userInput = searchInput.value;
movieCard.forEach((el) => {
el.classList.remove('hidden');
let movieTitle = el.getElementsByTagName('h2')[0].innerText;
if (!movieTitle.toLowerCase().includes(userInput)) {
el.classList.add("hidden");
}
})
}
let userInput = searchInput.value;
우선 검색 버튼을 눌렀을 때 실행하는 이벤트 핸들러를 만들어주고 userInput 변수에 사용자가 입력한 값을 할당해준다.
movieCard.forEach((el) => {}
forEach문으로 이미 만들어진 무비 카드들에서 사용자가 입력한 값과 영화 제목이 일치하면 일치한 영화는 제외하고 나머지 카드들은 hidden 클래스는 add하면 된다.
let movieTitle = el.getElementsByTagName('h2')[0].innerText;
-카드에는 title(제목), overview(내용 요약), poster_path(포스터 이미지 경로), vote_average(평점) 이렇게 4가지 정보가 필수
-카드 클릭 시에는 클릭한 영화 id 를 나타내는 alert 창을 띄우기
4. 영화 검색 UI 구현
5. Javascript 문법 요소를 이용하여 구현
- const와 let만을 이용한 변수 선언 필수
- 화살표 함수
- 배열 메소드 : 하기 예시 중 2개 이상 사용
forEach
map
filter
reduce
find
-DOM 제어하기 : 아래 api 목록 중 2개 이상 사용하기
document.createElement(tagName) //새로운 HTML 요소를 생성합니다.
document.getElementById(id) //id 속성을 기준으로 요소를 선택합니다.
document.getElementsByTagName(name) //태그 이름을 기준으로 요소를 선택합니다.
document.getElementsByClassName(name) //클래스 이름을 기준으로 요소를 선택합니다.
document.querySelector(selector) //CSS 선택자를 이용하여 요소를 선택합니다.
document.querySelectorAll(selector) //CSS 선택자를 이용하여 모든 요소를 선택합니다.
element.innerHTML //해당 요소 내부의 HTML 코드를 변경합니다.
element.textContent //해당 요소 내부의 텍스트를 변경합니다.
element.setAttribute(attr, value) //해당 요소의 속성 값을 변경합니다.
element.getAttribute(attr) //해당 요소의 속성 값을 가져옵니다.
element.style.property //해당 요소의 스타일 값을 변경합니다.
element.appendChild(child) //해당 요소의 하위 요소로 child를 추가합니다.
element.removeChild(child) //해당 요소의 하위 요소 중 child를 삭제합니다.
element.classList.add(class) //해당 요소의 클래스에 새로운 클래스를 추가합니다.
element.classList.remove(class) //해당 요소의 클래스 중에서 특정 클래스를 제거합니다.
element.classList.toggle(class) //해당 요소의 클래스 중에서 특정 클래스를 추가 또는 제거합니다.
element.addEventListener(type, listener) //해당 요소에서 이벤트가 발생했을 때 호출할 함수를 등록합니다.
element.removeEventListener(type, listener) //해당 요소에서 등록된 함수를 제거합니다.
event.preventDefault() //이벤트가 발생했을 때 기본 동작을 취소합니다.
event.stopPropagation() //이벤트의 버블링을 방지하기 위해 이벤트 전파를 중지합니다.
window.location.href //현재 페이지의 URL을 가져옵니다.
window.alert(message) //경고 메시지를 출력합니다.
window.confirm(message) //확인 메시지를 출력하고 사용자의 답변에 따라 Boolean 값을 반환합니다.
🦴 와이어 프레임
와이어 프레임으로 기획부터 하고 대충 어디에 뭘 가져다 놓을껀지 정해봤다
웨이브를 레퍼로 삼아서 했는데 결과물은 깔끔하게 나온 것 같다
TMDB api 페이지에 뿌리기
1. api 가져오기
패치를 실행했을 때 console창에서 results에 데이터가 저장되어있는지 확인할 수 있다.
- 카드에는 title(제목), overview(내용 요약), poster_path(포스터 이미지 경로), vote_average(평점) 이렇게 4가지 정보가 필수
- 카드 클릭 시에는 클릭한 영화 id 를 나타내는 alert 창을 띄우기
4. 영화 검색 UI 구현
5. Javascript 문법 요소를 이용하여 구현
- const와 let만을 이용한 변수 선언 필수
- 화살표 함수
- 배열 메소드 : 하기 예시 중 2개 이상 사용
forEach
map
filter
reduce
find
- DOM 제어하기 : 아래 api 목록 중 2개 이상 사용하기
document.createElement(tagName) //새로운 HTML 요소를 생성합니다.
document.getElementById(id) //id 속성을 기준으로 요소를 선택합니다.
document.getElementsByTagName(name) //태그 이름을 기준으로 요소를 선택합니다.
document.getElementsByClassName(name) //클래스 이름을 기준으로 요소를 선택합니다.
document.querySelector(selector) //CSS 선택자를 이용하여 요소를 선택합니다.
document.querySelectorAll(selector) //CSS 선택자를 이용하여 모든 요소를 선택합니다.
element.innerHTML //해당 요소 내부의 HTML 코드를 변경합니다.
element.textContent //해당 요소 내부의 텍스트를 변경합니다.
element.setAttribute(attr, value) //해당 요소의 속성 값을 변경합니다.
element.getAttribute(attr) //해당 요소의 속성 값을 가져옵니다.
element.style.property //해당 요소의 스타일 값을 변경합니다.
element.appendChild(child) //해당 요소의 하위 요소로 child를 추가합니다.
element.removeChild(child) //해당 요소의 하위 요소 중 child를 삭제합니다.
element.classList.add(class) //해당 요소의 클래스에 새로운 클래스를 추가합니다.
element.classList.remove(class) //해당 요소의 클래스 중에서 특정 클래스를 제거합니다.
element.classList.toggle(class) //해당 요소의 클래스 중에서 특정 클래스를 추가 또는 제거합니다.
element.addEventListener(type, listener) //해당 요소에서 이벤트가 발생했을 때 호출할 함수를 등록합니다.
element.removeEventListener(type, listener) //해당 요소에서 등록된 함수를 제거합니다.
event.preventDefault() //이벤트가 발생했을 때 기본 동작을 취소합니다.
event.stopPropagation() //이벤트의 버블링을 방지하기 위해 이벤트 전파를 중지합니다.
window.location.href //현재 페이지의 URL을 가져옵니다.
window.alert(message) //경고 메시지를 출력합니다.
window.confirm(message) //확인 메시지를 출력하고 사용자의 답변에 따라 Boolean 값을 반환합니다.
TMDB api key 생성
2. pick a language 에서 javascript 선택 후 토큰 입력하기
3. 코드에 내 토큰을 적용하고 Try it! (꼭 Success 를 확인하고 내 코드로 옮겨주세요!)