안녕하세요

221018 메가박스 리액트 - 영화검색(2) TMBD 검색기능 구현 본문

프론트엔드 국비교육/구현한 웹페이지

221018 메가박스 리액트 - 영화검색(2) TMBD 검색기능 구현

sakuraop 2022. 10. 19. 16:04

TMDB의 영화 데이터를 받아와 검색기능을 구현합니다.

 


 

TMDB의 search API는 url에 query로 보낸 값과 일치하는 제목의 영화들을 가져옵니다.

const { default: axios } = require("axios");

const key = "KEY_VALUE";

const instance = axios.create({
    baseURL: url,
    params: {
        api_key: key,
        language: "ko-KR",
    },
});

const category = {
    search: "search/movie?query=",
};

export { instance, category };

 


 

1. App.js 에서 get으로 데이터를 받아오기위해서 useState에 입력받을 Query를 저장시킵니다.

    const [searchList, setSearchList] = useState([]);
    const [searchQuery, setSearchQuery] = useState("");
 
 
 

2. get으로 url주소 + ?query=[searchQuery] 에서 데이터를 받아와 searchList 스테이트에 저장하도록 합니다.

 

    const getTMDBSearch = async () => {
        const res = await instance.get(category.search + searchQuery);
        console.log(res.data.results);
        const searchData = res.data.results;
        setSearchList(searchData);
    };

검색할 URL의 예시는 다음과 같습니다.

 

3. input 태그의 value를 query로 전달하도록 합니다.

매 타이핑마다 데이터를 불러오는 것을 피하기 위해서 setTimeout()을 이벤트에 주었습니다.

0.5초간 기다린 뒤에 실행하여 데이터를 불러오도록 합니다.

 

    // 검색어를 입력할 때마다 바꾸지 않고 입력하고 잠깐 기다렸다가 출력되도록 하려면 이벤트에 setTimeout을 합니다.
    const querySetTimeout = (e) => {
        setTimeout(() => {
            setSearchQuery(e.target.value);
        }, 500);
    };

 

4. useEffect를 이용하여 query의 값이 변하면 검색결과를 출력하도록 합니다.

검색어를 다 지웠을 때 검색 결과가 남지 않도록 if문을 이용하여 검색창이 비어있다면 searchList를 비우도록 합니다.

 

const SearchMovie = ({ searchVisual, TRENDINGDATA, getTMDBSearch, searchList, setSearchList, searchQuery, setSearchQuery }) => {
    useEffect(() => {
        // input이벤트는 onChange로 검색어가 변할 때마다 검색결과를 출력하도록 합니다.
        if (searchQuery !== "") {
            getTMDBSearch();
            // 검색창이 비어있다면 검색결과를 삭제합니다.
        } else if (searchQuery === "") {
            setSearchList([]);
        }
    }, [searchQuery]);

 

 

5. slice() 메서드를 이용하여 인기 영화 순으로 5개의 영화를 그리도록 합니다.

 

<h3>예매율 순위</h3>
                <div className="content">
                    <ul className="left">
                        {TRENDINGDATA.slice(0, 5).map((el, idx) => {
                            return (
 
 
 
6. onMouseEnter 이벤트를 이용해서 마우스를 타이틀에 가져다 댈 경우 이미지가 나타나도록 합니다.
 
 
 
 <li key={idx} className={`${idx === num ? "on" : ""}`}>
                                    <div className="img">
                                        <figure>
                                            <img src={"https://image.tmdb.org/t/p/w500/" + el.poster_path} alt="" />
                                        </figure>
                                    </div>
                                    <div className="txt">
                                        <p>
                                            <span>{idx + 1}</span>
                                            <strong
                                                onMouseEnter={() => {
                                                    setNum(idx);
                                                }}
                                            >

 

 

7. 검색 결과창도 동일한 방식으로 출력해줍니다.

너무 많은 결과가 나와 css를 깨지 않도록 하기 위해서 마찬가지로 slice() 메서드를 이용해 7개까지만 출력하도록 합니다.

<ul className="right">
                        <input onChange={(e) => querySetTimeout(e)} placeholder="영화이름으로 검색하세요.     ex) 토르" />
                        {searchList.slice(0, 7).map((el, idx) => {
                            return (

 

 

8. 이미지가 존재하지 않는 데이터가 있습니다. 

검색결과 품질을 높이기 위해 이미지가 존재하지 않는 경우는

상함연산자를 이용하여 해당 데이터를 검색 결과에서 제외하도록 했습니다.

 

                            return (
                                <li key={idx} className={`${idx === sNum ? "on" : ""}`}>
                                    {el.poster_path ? (
                                        <div className="autoComp">
                                            <div className="txt">
                                                <span
                                                    onMouseEnter={() => {
                                                        setSNum(idx);
                                                    }}
                                                >
                                                    {el.title}
                                                </span>
                                            </div>
                                            <div className="img">
                                                <img src={"https://image.tmdb.org/t/p/w500/" + el.poster_path} alt="" />
                                            </div>
                                        </div>
                                    ) : (
                                        ""
                                    )}
                                </li>