프로젝트/영화 목록 (Netflix) 앱

영화목록 (netflix) 앱 2 - 라우터 구현하기

syleemomo 2021. 11. 22. 22:43
728x90

 

* 프로젝트 폴더 생성하기

npx create-react-app netflix

 

* 리액트 라우터 설치하기 

cd netflix
npm install react-router-dom

 

리액트 라우터 URL 주소 이동하기

 

how to use history instance while using react routers v6?

I'm using react-router v6 and I have to use history instance. I've installed it using yarn add history react-router-dom@next One way of using history instance I guess it must be with v5 is to use

stackoverflow.com

 

 

* 라우터 기능 추가하기

import React from "react"
import ReactDOM from "react-dom"
import { BrowserRouter } from "react-router-dom"

const App = () => {
  return (
    <div>Hello React !</div>
  );
};
  
ReactDOM.render(<BrowserRouter>
                  <App />
                </BrowserRouter>, 
                document.getElementById("root"));

index.js 파일을 위와 같이 수정하자! 

import { BrowserRouter } from "react-router-dom"

라우터 기능을 추가하기 위하여 react-router-dom 라이브러리에서 BrowserRouter 컴포넌트를 임포트한다. 

ReactDOM.render(<BrowserRouter>
                  <App />
                </BrowserRouter>, 
                document.getElementById("root"));

App 컴포넌트를 BrowserRouter 컴포넌트로 감싸준다. 

 

* 페이지 생성하기 - 사용자 등록 페이지, 사용자 로그인 페이지, 홈페이지

src 폴더 하위에 pages 폴더를 생성한다. pages 폴더 하위에 아래와 같은 파일들을 생성하고 코드를 구현하자!

import React from 'react'

const Register = () => {
    return (
        <div>Register</div>
    )
}

export default Register

Register.js 파일을 생성하고 위와 같이 작성하자!

import React from 'react'

const Login = () => {
    return (
        <div>Login</div>
    )
}

export default Login

Login.js 파일을 생성하고 위와 같이 작성하자!

import React from 'react'

const Home = () => {
    return (
        <div>Home</div>
    )
}

export default Home

Home.js 파일을 생성하고 위와 같이 작성하자!

export { default as Register } from './Register'
export { default as Login } from './Login'
export { default as Home } from './Home'

index.js 파일을 생성하고 위와 같이 작성하자!

 

* 페이지 라우팅하기

import React from "react"
import ReactDOM from "react-dom"
import { BrowserRouter, Route, Routes } from "react-router-dom"
import { Register, Login, Home } from './pages'


const App = () => {
  return (
    <div>
      <Routes>
          <Route path='/' element={<Register/>}/>
          <Route path="/login" element={<Login/>}/>
          <Route path="/home" element={<Home/>}/>
      </Routes>
    </div>
  );
};
  
ReactDOM.render(<BrowserRouter>
                  <App />
                </BrowserRouter>, 
                document.getElementById("root"));

index.js 파일을 위와 같이 수정하자!

import { BrowserRouter, Route, Routes } from "react-router-dom"

페이지 라우팅 기능을 적용하기 위하여 react-router-dom 라이브러리에서 BrowserRouter, Route, Routes 컴포넌트를 임포트한다. 

import { Register, Login, Home } from './pages'

pages 폴더 내부의 페이지 컴포넌트들을 임포트한다. 

<div>
    <Routes>
        <Route path='/' element={<Register/>}/>
        <Route path="/login" element={<Login/>}/>
        <Route path="/home" element={<Home/>}/>
    </Routes>
  </div>

Routes, Route 컴포넌트를 사용하여 URL 경로에 따라 해당 페이지를 보여줄 수 있도록 설정한다. 웹서비스가 시작하면 사용자 등록을 위한 페이지가 처음으로 보여진다. /login 경로에 접속하면 로그인 화면을 보여준다. /home 경로에 접속하면 홈 화면을 보여준다.

 

* Input 컴포넌트 만들기

src 폴더 하위에 components 폴더를 생성한다.  components 폴더 하위에 아래와 같은 파일들을 생성하고 코드를 구현하자!

import React from 'react'

const Input = ({ name, type, placeholder, value, onChange}) => {
    return (
        <input name={name} type={type} placeholder={placeholder} value={value} onChange={onChange}/>
    )
}

export default Input

Input.js 파일을 위와 같이 생성하자!

export { default as Input } from './Input'

index.js 파일을 위와 같이 생성하자!

 

* Register 페이지에서 Input 사용하기 

import React, { useState } from 'react'

import { Input } from '../components'

const Register = () => {
    const [id, setId] = useState('')
    const [password, setPassword] = useState('')

    const handleChange = (e) => {
        const { name, value } = e.target
        name === 'id' ? setId(value) : setPassword(value)
        console.log(name, value)
    }
    return (
        <div>
            <Input name='id' type='text' placeholder='Type ID ...' value={id} onChange={handleChange}/><br/>
            <Input name='password' type='password' placeholder='Type PASSWORD ...' value={password} onChange={handleChange}/>
        </div>
    )
}

export default Register

Register.js 파일을 위와 같이 수정하자!

사용자 등록을 위한 Input 컴포넌트를 임포트하고 사용한다. 리액트 훅 (state hook) 을 사용하여 사용자 입력을 처리한다. 

 

* 사용자 정보의 유무에 따라 다른 페이지 보여주기 - Register 페이지

import React, { useState } from 'react'
import { useNavigate } from "react-router-dom"

import { Input } from '../components'

const Register = () => {
    const [id, setId] = useState('')
    const [password, setPassword] = useState('')
    const navigate = useNavigate()

    const handleChange = (e) => {
        const { name, value } = e.target
        name === 'id' ? setId(value) : setPassword(value)
        console.log(name, value)
    }
    const handleRegister = () => {
        if(JSON.parse(sessionStorage.getItem('user'))){
            navigate('/login')
        }else{
            sessionStorage.setItem('user', JSON.stringify({ id, password }))
            navigate('/home')
        } 
    }
    return (
        <div>
            <Input name='id' type='text' placeholder='Type ID ...' value={id} onChange={handleChange}/><br/>
            <Input name='password' type='password' placeholder='Type PASSWORD ...' value={password} onChange={handleChange}/><br/>
            <button onClick={handleRegister}>Register</button>
        </div>
    )
}

export default Register

Register.js 파일을 위와 같이 수정하자!

import { useNavigate } from "react-router-dom"

특정 페이지로 이동 (redirect) 하기 위하여 react-router-dom 라이브러리에서 useNavigate 함수를 임포트한다. 

const navigate = useNavigate()

useNavigate 함수를 실행하면 navigate 함수를 반환한다. 해당 함수는 다른 URL 경로로 이동할 수 있는 기능을 제공한다.

const handleRegister = () => {
      if(JSON.parse(sessionStorage.getItem('user'))){ // 사용자 정보가 있는 경우
          navigate('/login')
      }else{
          sessionStorage.setItem('user', JSON.stringify({ id, password })) // 사용자 정보 등록
          navigate('/home')
      } 
  }

사용자가 등록 정보를 입력하고 버튼을 클릭하면 해당 함수가 실행된다. 사용자 정보가 이미 등록되어 있으면 로그인 화면으로 안내한다. 그렇지 않으면 사용자 정보를 등록하고 홈화면으로 이동한다. navigate 의 인자로 이동하고자 하는 URL 경로를 설정하면 해당 경로로 이동한다. 

브라우저 API 인 세션 스토리지를 사용하여 사용자 정보를 조회하고 등록한다. 

 

* 로그인 기능 구현하기 - Login 페이지 

import React, { useState } from 'react'
import { useNavigate } from "react-router-dom"

import { Input } from '../components'

const Login = () => {
    const [id, setId] = useState('')
    const [password, setPassword] = useState('')
    const navigate = useNavigate()

    const handleChange = (e) => {
        const { name, value } = e.target
        name === 'id' ? setId(value) : setPassword(value)
        console.log(name, value)
    }
    const handleLogin = () => {
        const user = JSON.parse(sessionStorage.getItem('user'))
        if(id === user.id && password === user.password){
            navigate('/home')
        }else{
            alert('You gaved wrong id or password !')
        } 
    }
    return (
        <div>
            <Input name='id' type='text' placeholder='Type ID ...' value={id} onChange={handleChange}/><br/>
            <Input name='password' type='password' placeholder='Type PASSWORD ...' value={password} onChange={handleChange}/><br/>
            <button onClick={handleLogin}>Login</button>
        </div>
    )
}

export default Login

Login.js 파일을 위와 같이 작성하자!

const handleLogin = () => {
      const user = JSON.parse(sessionStorage.getItem('user'))
      if(id === user.id && password === user.password){
          navigate('/home')
      }else{
          alert('You gaved wrong id or password !')
      } 
  }

Register 화면과 사용자 입력 처리 부분은 동일하다. 사용자가 로그인 정보를 입력하고 버튼을 클릭했을때 실제 사용자 정보와 입력한 정보가 일치하면 /home 경로로 이동한다. 그렇지 않으면 경고창을 띄워서 사용자에게 다시 한번 로그인 정보를 입력하도록 안내한다. 

 

* 홈화면에 영화목록 보여주기

components 폴더에 다음 파일을 추가한다. 

import React from 'react'

const Movie = ({ title, genres, cover, summary }) => {
    return (
        <div>
            <img src={cover} alt={title}></img>
            <h3>{title}</h3>
            <h4>{genres.join(" ")}</h4>
            <p>{summary}</p>
        </div>
    )
}

export default Movie

Movie.js 파일을 위와 같이 생성하자!

export { default as Input } from './Input'
export { default as Movie } from './Movie'

index.js 파일을 위와 같이 수정하자!

import React, { useState, useEffect } from 'react'
import { Movie } from '../components'

const Home = () => {
    const [loading, setLoading] = useState(true)
    const [movies, setMovies] = useState([])

    useEffect( () => {
        fetch('https://yts.mx/api/v2/list_movies.json?limit=12')
        .then( res => res.json())
        .then( result => {
            const {data: {movies}} = result
            console.log(movies)
            setLoading(false)
            setMovies(movies)
        })
    }, [])

    const homeUI = movies.map(movie => <Movie 
                                        key={movie.id} 
                                        title={movie.title} 
                                        genres={movie.genres} 
                                        cover={movie.medium_cover_image} 
                                        summary={movie.summary}/>
                                    )

    return (
        <div>
            {loading? 'Loading ...': homeUI}
        </div>
    )
}

export default Home

Home.js 파일을 위와 같이 수정하자! 

리액트 훅 (state hook, effect hook) 을 사용하여 OPEN API 서버에서 무비 데이터를 가져와서 홈화면에 디스플레이한다.

 

* 로딩화면 구현하기

먼저 src 폴더 하위에 assets 폴더를 생성한다. assets 폴더 하위에 images 폴더를 생성한다. images 폴더에 loading.gif 를 추가한다. 

components 폴더에 다음 파일을 추가한다. 

import React from 'react'
import loadingImg from '../assets/images/loading.gif'

const Loading = () => {
    return (
        <div>
            <img src={loadingImg} alt='loading-img'></img>
        </div>
    )
}

export default Loading

Loading.js 파일을 위와 같이 생성하자!

export { default as Input } from './Input'
export { default as Movie } from './Movie'
export { default as Loading } from './Loading'

index.js 파일을 위와 같이 수정하자!

import React, { useState, useEffect } from 'react'
import { Movie, Loading } from '../components'

const Home = () => {
    const [loading, setLoading] = useState(true)
    const [movies, setMovies] = useState([])

    useEffect( () => {
        fetch('https://yts.mx/api/v2/list_movies.json?limit=12')
        .then( res => res.json())
        .then( result => {
            const {data: {movies}} = result
            console.log(movies)
            setLoading(false)
            setMovies(movies)
        })
    }, [])

    const homeUI = movies.map(movie => <Movie 
                                        key={movie.id} 
                                        title={movie.title} 
                                        genres={movie.genres} 
                                        cover={movie.medium_cover_image} 
                                        summary={movie.summary}
                                       />
                                    )

    return (
        <div>
            {loading? <Loading/>: homeUI}
        </div>
    )
}

export default Home

 

Home.js 파일을 위와 같이 수정하자! 

import { Movie, Loading } from '../components'

Loading 컴포넌트를 임포트한다. 

<div>
    {loading? <Loading/>: homeUI}
</div>

Loading 컴포넌트를 사용해서 로딩화면을 디스플레이한다. 

 

728x90