[FrontEnd6] naver-movie-api를 이용하여 네이버 영화 검색 페이지 만들기 (router, naver-api, pagination, axios, query-string)

    SMALL

    안녕하세요~ 보라해바라기입니다!

     

    오늘은 naver 영화 검색 api를 사용하여 라우터에 따른 영화검색 페이지를 만들어보았습니다:)

     

    1. App.js

    import './App.css';
    import { Component } from 'react';
    import { BrowserRouter, Routes, Route } from 'react-router-dom';
    import Home from './components/Home.js'
    import Search from './components/Search.js'
    import InputComp from './components/InputComp.js'
    
    class App extends Component {
      constructor(props){
        super(props)
        this.state={
    
        }
      }
    
      render(){
        return (
          <div id='app'>
            <BrowserRouter>
              <InputComp/>
              <Routes>
                <Route exact path='/' element={<Home/>}/>
                <Route exact path='/search' element={<Search/>}/>
              </Routes>
            </BrowserRouter>
          </div>
        );
      }
    }
    
    export default App;

     

    2. App.css

    #app{
      width: 1100px;
      height: 1400px;
      margin: 0 auto;
      background-color: aliceblue;
    }

     

    3.Home.js

    import { Component } from 'react';
    import '../css/Home.css'
    
    class Home extends Component {
        constructor(props){
            super(props)
            this.state={
    
            }
        }
    
        render(){
            return(
                <div id='home'>
                    home
                </div>
            )
        }
    }
    
    
    export default Home;

     

    4.Home.css

    #home{
        width: 1000px;
        height: 1000px;
        background-color: thistle;
    }

     

    5.Search.js

    import { Component } from 'react';
    import '../css/Search.css'
    import axios from 'axios'
    import queryString from 'query-string'
    import MovieList from './MovieList.js'
    import Pagination from './Pagination.js';
    
    //search한 값을 pagination
    
    class Search extends Component {
        constructor(props){
            super(props)
            this.state={
               movieList:[],
               currentPage:1,
               moviePerPage:3
            }
        }
    
        componentDidMount(){
        //    console.log('Search')
        //   console.log('window.location', window.location) // host, hostname, href, pathname. port...
        //    console.log('window.location.href', window.location.href) 
            // http://localhost:3000/search?searchText=블라블라블라&display=10&country=JPN
        //    console.log('window.location.search', window.location.search)
            // ?searchText=블라블라블라&display=10&country=JPN
            const queryObj=queryString.parse(window.location.search)
        //    console.log(queryObj) // {country: 'JPN', display: '10', searchText: '스파이더맨'}
        //    console.log(queryObj.searchText) //스파이더맨
            const searchText = queryObj.searchText
            this.searchMovie(searchText)
        }
    
        searchMovie=async(searchText)=>{
            const {movieList} = this.state
            console.log(searchText)
            const axios_movies = await axios({
                method:'get',
                url:`/v1/search/movie.json?query=${searchText}`,
                dataType:'json',
                headers:{
                    "X-Naver-Client-Id": "OCTOqeR_MCymgnyep8zR",
                    "X-Naver-Client-Secret": "_UO4OJzKop"
                }
            })
            this.setState({
                movieList:axios_movies.data.items
            })
            console.log(axios_movies.data.items)
            console.log(movieList)
        }
    
        setCurrentPage=(page)=>{
            alert("페이지 설정(App.js):"+page)
            this.setState({
                currentPage:page
            })
        }
    
        currentMovieList=(movieList)=>{
            const {currentPage, moviePerPage} = this.state
            const indexFirst = (currentPage-1)*moviePerPage
            const indexLast = indexFirst+moviePerPage
            const slicedMovieList = movieList.slice(indexFirst, indexLast)
            return slicedMovieList;
        }
    
        
    
        render(){
            const {movieList, moviePerPage, currentPage} = this.state
            return(
                <div id='search'>
                    <MovieList movieList={this.currentMovieList(movieList)}/>
                    <Pagination movieListLength={movieList.length} currentPage={currentPage}
                    moviePerPage={moviePerPage} setCurrentPage={this.setCurrentPage}/>
                </div>
            )
        }
    }
    
    
    export default Search;

     

    6.Search.css

    #search{
        width: 1000px;
        height: auto;
        background-color: lightgreen;
    }

     

    7.InputComp.js

    import { Component } from 'react';
    import '../css/InputComp.css'
    
    class InputComp extends Component {
        constructor(props){
            super(props)
            this.state={
                searchText:''
            }
        }
    
        searchBook=()=>{
            alert("책 검색")
            window.location.href=`/search?searchText=${this.state.searchText}&display=10&country=JPN`
        }
    
        inputChange=(e)=>{
            this.setState({
                searchText:e.target.value
            })
        }
    
        render(){
            return(
                <div id='input-comp'>
                    <input type='text' placeholder='검색어' onChange={this.inputChange}/>
                    <button onClick={this.searchBook}>검색</button>
                </div>
            )
        }
    }
    
    
    export default InputComp;

     

    8.InputComp.css

    #input-comp{
        width: 1000px;
        height: 50px;
        margin-bottom: 10px;
        background-color: lightpink;
    }

     

    9.Movie.js

    import { Component } from 'react';
    import '../css/Movie.css';
    
    class Movie extends Component {
      constructor(props){
        super(props)
        this.state={
        
        }
      }
    
      render(){
        return (
          <div id="movie">
            <div id='left-side'>
                {this.props.image}
            </div>
            <div id='right-side'>
                <span>제목: {this.props.title} </span>
                <span>년도: {this.props.pubDate} </span>
                <span>감독: {this.props.director}</span>
                <span>배우: {this.props.actor}</span>
                <span>평점: {this.props.userRating}/10</span>
            </div>
          </div>
        );
      }
    }
    
    export default Movie;

     

    10.Movie.css

    #movie{
        width: 900px;
        height: 300px;
        background-color: yellowgreen;
        margin: 10px;
    }
    
    #movie>#left-side{
        float: left;
        width: 250px;
        height: 290px;
        background-color: lightpink;
        padding-top: 30px;
        padding-left: 40px;
        box-sizing: border-box;
    }
    
    #movie>#right-side{
        float: left;
        width: 550px;
        height: 290px;
        background-color: lightblue;
    }
    
    #movie>#right-side>span{
        display: block;
        width: 540px;
        height: 35px;
        padding-top: 10px;
        box-sizing: border-box;
    }
    
    #movie>#right-side>span:first-child{
        background-color: lightgray;
    }
    
    #movie>#right-side>span:nth-child(2){
        background-color: lightgoldenrodyellow;
    }
    
    #movie>#right-side>span:nth-child(3){
        background-color: lightcyan;
    }
    
    #movie>#right-side>span:nth-child(4){
        background-color: sandybrown;
        height: auto;
    }
    
    #movie>#right-side>span:nth-child(5){
        background-color: plum;
    }

     

    11.MovieList.js

    import { Component } from 'react';
    import '../css/MovieList.css';
    import Movie from './Movie';
    
    class MovieList extends Component {
      constructor(props){
        super(props)
        this.state={
        
        }
      }
    
      // 제목에 나오는 html태그 제거해야 함 -> (구글링: react 태그 제거 ~ replace)
    
      render(){
        const result= this.props.movieList.map(
            (data) => (<Movie key={data.id} 
            image = {<img src= {data.image}/>}
            title={data.title.replace(/(<([^>]+)>)/ig,"")} 
            pubDate={data.pubDate} director={data.director.replace(/(<([^>]+)>)/ig,"").replace(/\|/ig,",")}
            actor={data.actor.replace(/(<([^>]+)>)/ig,"").replace(/\|/ig,",")} userRating={data.userRating}/>)
        )
    
        // data.title.replace(/(<([^>]+)>)/ig,"") => 모든 태그를 제거
        // data.director.replace(/\|/ig,",") => |를 한꺼번에 바꾸기 (| 앞에 무효화할 수 있도록 \키 넣기)
    
        return (
          <div id="movie-list">
            {result}
          </div>
        );
      }
    }
    
    export default MovieList;

     

    12.MovieList.css

    #movie-list{
        width: 900px;
        height: auto;
        margin: 0 auto;
    }
    
    img{
        width: 180px;
        height: 230px;
    }

     

    13.Pagination.js

    import { Component } from 'react';
    import '../css/Pagination.css';
    
    class Pagination extends Component {
      constructor(props){
        super(props)
        this.state={
        
        }
      }
    
      setCurrentPage=(page)=>{
        alert(page+"페이지 클릭(Pagination.js)")
        this.props.setCurrentPage(page)
      }
    
      prevPage=()=>{
        alert("이전")
    
        const {currentPage, setCurrentPage} = this.props
        if (currentPage==1){
            alert("여기는 첫 페이지 입니다.")
            return
        }
        setCurrentPage(currentPage-1)
      }
    
      nextPage=()=>{
        alert("다음")
    
        const {currentPage, setCurrentPage} = this.props
        const {lastPageNum} = this.state
    
        if (currentPage+1 > lastPageNum){
            alert("여기는 마지막 페이지 입니다.")
            return
        }
        setCurrentPage(currentPage+1)
      }
    
      render(){
        const {movieListLength, moviePerPage} = this.props
    
        let pageNumbers=[];
        const lastPageNum = Math.ceil(movieListLength/moviePerPage)
        for(var i=1; i<=lastPageNum; i++){
            pageNumbers.push(i)
        }
    
        const result=pageNumbers.map(
            (data)=>(<span className='page' key={data}
            onClick={()=>this.setCurrentPage(data)}>{data}</span>)
          )
    
        return (
          <div id="pagination">
            <div>
                총 글 갯수: {movieListLength}
            </div>
            <div>
                페이지당 글 갯수: {moviePerPage}
            </div>
            <div>
                <span className='page' onClick={this.prevPage}>
                    &lt;
                </span>
                <span>{result}</span>
                <span className='page' onClick={this.nextPage}>
                    &gt;
                </span>
            </div>
          </div>
        );
      }
    }
    
    export default Pagination;

     

    14.Pagination.css

    #pagination{
        width: 900px;
        height: 100px;
        background-color: springgreen;
        position: relative;
        margin-left: 60px;
    }
    
    .page{
        display:inline-block;
        width:35px;
        height:35px;
        border:1px solid black;
        margin:5px;
        text-align: center;
        padding-top:5px;
        box-sizing: border-box;
        background-color: darkgray;
        cursor: pointer;
    }
    
    #pagination>div:nth-child(3){
        position: absolute;
        left: 240px;
    }

    15. 실행결과

    "스파이더맨"을 검색했을 때, 네이버 영화 api에서 data를 받아와 페이지네이션으로 출력

    728x90

    댓글