React

노마드코더 : React(영화 웹 서비스) - 7. 라우터, 내비게이션, 영화 상세정보 만들기

식초 2020. 12. 13. 12:03

react-router-dom 설치하고 프로젝트 폴더 정리하기

가장 처음 만들 기능은 네비게이션 기능이다.

Home, About 메뉴를 추가한다.

Home은 영화 앱 화면으로 이동시켜주고, About은 개발자 자기 소개 화면으로 이동시켜준다.

'화면 이동을 시켜주는 장치'라우터이다. (URL에 맞게 이동시켜주는 장치)

라우터는 react-router-dom 패키지를 이용하면 쉽게 도입할 수 있다.

 

 

react-router-dom 설치하기

패키지 설치하기.

> npm install react-router-dom

 

 

components 폴더에 Movie 컴포넌트 옮기기

컴포넌트를 역할에 맞게 분리해서 폴더에 담아 관리한다.

src 폴더 안에 components 폴더 만든다.

Movie.jsMovie.css 를 components 에 옮긴다.

뭔가 업데이트 하겠냐고 물어보면 <No> 누른다.

 

 

routes 폴더에 라우터가 보여줄 화면 만들기

src 폴더 안에 routes 폴더 만든다. 여기에 라우터가 보여줄 화면(컴포넌트)을 만든다.

내비게이션에 Home, About 메뉴를 만드니까 Home.js , About.js 파일을 만든다.

Home.js 파일은 영화 앱 화면, About.js 파일은 개발자 소개 화면이다.

 

 

Home.js 수정하기

Home.js 파일에 작성할 코드는 App.js 파일의 코드를 그대로 복사하면 된다.

class Homeexport default Home 모두 바꾼다.

Movie 컴포넌트를 임포트하고, 스타일링을 위한 Home.css도 임포트한다.

 

 

 

Home.css 만들기

routes 폴더Home.css를 만든 다음에 아래와 같이 입력한다.

이 과정을 통해 영화 카드가 브라우저 폭에 맞게 1줄 또는 2줄로 출력된다.

 

 

 

App.js 수정하기

 

영화 앱 실행하면 다음과 같이 브라우저 폭에 맞게 영화 카드 출력된다.

 

이제 App.js가 2개의 라우터(Home.js, About.js)를 보여줄 수 있도록 만들면 된다.

 

 

 


라우터 만들어 보기

App.js를 수정해서 라우터를 만들어 볼 것이다. 

라우터사용자가 입력한 URL을 통해 특정 컴포넌트를 불러준다.

예를 들어, 사용자 localhost:3000/home 입력 → Home 컴포넌트 보여줌, 

사용자 localhost:3000/about 입력 → About 컴포넌트 보여준다.

 

react-router-dom여러 종류의 라우터를 제공하는데 HashRouterRoute 컴포넌트 사용한다.

 

 

HashRouter와 Route 컴포넌트 사용하기

HashRouter와 Route 컴포넌트 임포트한 다음,

HashRouter 컴포넌트가 Route 컴포넌트 감싸 반환하도록 App.js 수정한다.

그리고 컴포넌트를 임포트하는 코드 사용한 코드잠시 지운다.

 

 

앱이 실행되는 주소에 #/이 붙는다. HashRouter 때문이다.

Route2가지 props를 전달할 수 있다.

하나는 URL을 위한 path props이고, 다른 하나는 URL에 맞는 컴포넌트를 불러 주기 위한 component props이다.

path, component props를 통해 사용자가 접속한 URL을 보고, 그에 맞는 컴포넌트를 화면에 그릴 수 있다.

 

 

Route 컴포넌트에 path, component props 추가하기

About 컴포넌트를 임포트하고, 

path, component props에 URLAbout 컴포넌트전달하자.

 

 

 

About.js 수정하기

About.js 에는 아무것도 입력한 적 없으니 아래 입력하자.

 

HashRouter 에 Route를 넣었고, Route가 About 컴포넌트를 불러오도록 만들었다.

 

 

라우터 테스트 해보기

localhost:3000/# 에 path props로 지정했던 값 /about을 붙여서 다시 접속한다.

 

URL은 localhost:3000/#/about 이고, About 컴포넌트에 작성했던 내용이 나왔다.

Route 컴포넌트에 전달한 path props를 보 component props에 지정한 About 컴포넌트를 그려준 것이다.

Home 컴포넌트도 보여줄 수 있도록 App.js를 수정해 보자.

 

 

Home 컴포넌트를 위한 Route 컴포넌트 추가하기

App 컴포넌트에 Home 컴포넌트 임포트하고, 또다른 Route 컴포넌트 추가한다.

 

path props를 "/"로 입력한 이유는 localhost:3000에 접속하면 기본으로 보여줄 컴포넌트가 Home 컴포넌트이라서다.

 

 

라우터 테스트하고 문제 찾아보기

localhost:3000 에 접속하면 주소 뒤에 자동으로 /#/가 붙으면서 영화 앱 화면이 나타난다. 

이어서 /about 에도 접속해 보면, About 컴포넌트와 함께 Movie 컴포넌트가 출력된다.

 

./about 에 접속하면 About 컴포넌트만 보여야 하는데 Movie 컴포넌트가 같이 보이는 문제가 있다.

리액트 라우터를 제대로 활용하지 못해서 그렇다.

 

 

라우터 자세히 살펴보기

라우터의 동작을 자세히 알아보기 위해 Home, About 컴포넌트는 잠시 잊고,

아래처럼 라우터 구성한다. App.js

 

라우터가 h1 엘리먼트를 보여준다. 

주목할 부분path props이다.

공부한 대로면 아래 상황이 예상된다.

localhost:3000/#/home                           <h1>Home</h1> 출력

localhost:3000/#/home/introduction         <h1>Introduction</h1> 출력

localhost:3000/#/about                        <h1>About</h1> 출력

 

 

라우터 다시 테스트해 보기

우선 /home 에 접속해 보자.

 

별 문제가 없다.

 

/home/introduction에 접속해 보자.

 

문제가 있다. Home 과 introduction을 함께 출력하고 있다.

 

이 문제가 발생한 이유는 라우터가 URL을 찾는 방식이 아래와 같기 때문이다.

 

라우터는 사용자가 /home/introduction 에 접속하면

/  →  /home  →  /home/introduction 순서 path props가 있는지 찾는다.

그런데 path props에는 /home/home/introduction 모두 있다.

따라서 Home, Introduction 컴포넌트 모두 그려진다.

 

깉은 원리로 사용자가 /about 에 접속하면

path props가 그려지므로 Home, About 컴포넌트 모두 그려진다.

 

 

App.js 다시 원래대로 돌리기

Home, About 컴포넌트를 그려줬던 상태로 코드를 돌려 놓는다.

 

그리고나서 /about 에 다시 접속하면, 여전히 Home, About 컴포넌트 모두 그려진다.

 

 

Route 컴포넌트에 exact props 추가해보기

위 문제를 해결하려면 Route 컴포넌트에 exact props 를 추가하면 된다.

exact props는 Route 컴포넌트가 path props와 정확하게 일치하는 URL에만 반응하도록 만들어 준다.

 

path props 가 "/"인 Route 컴포넌트에 exact={true}추가해 보자.

 

이제 /about 에 접속하면 About 컴포넌트만 출력된다.

path props가 정확히 /인 경우에만 Home 컴포넌트 출력되도록 설정했기 때문이다.

이제 라우터를 제대로 활용할 수 있게 되었다.

 

 

About.css 작성하기

About 컴포넌트의 모양을 다듬기 위해 스타일을 적용한다.

routes 폴더About.css 파일 생성한 다음 아래와 같이 입력한다.

 

 

About.js 에 About.css를 임포트하고, 

임포트한 About.css를 적용할 수 있도록 JSX를 수정한다.

 

영화 앱을 실행하여 /about으로 접속하면 이렇게 꾸며져서 나온다.

 

 

 


내비게이션 만들어 보기

라우터가 준비되었으므로 내비게이션을 통해 다른 화면으로 이동하면 된다.

라우터를 이용하여 간단한 내비게이션을 만들 것이다.

 

<Home>과 <About>이라는 2개의 버튼을 만들고, 각각의 버튼을 눌렀을 때 적절한 화면을 보여주도록 코딩한다.

 

 

Navigation 컴포넌트 만들기

components 폴더Navigation.js 파일 만들고 2개의 a 엘리먼트를 반환하도록 JSX를 작성한다.

 

2개의 a 엘리먼트는 각각 URL을 / 와 /about 으로 이동시켜줄 것 같은가? 아니다.

Navigation 컴포넌트App 컴포넌트에 포함시키면 어떤 문제가 생길까?

 

 

Navigation 컴포넌트 App 컴포넌트에 포함시키기

Navigation.js 를 임포트하고, <HashRouter></HashRouter> 사이에 포함시키면 된다.

 

영화 앱 실행하면, 왼쪽 위에 Navigation 컴포넌트가 출력하는 Home, About 링크(a 엘리먼트)를 확인할 수 있다.

 

 

Home 링크 눌러 보기

겉으로 보기에는 잘 동작하는 것처럼 보인다.

그러나 링크 누를 때마다 리액트가 죽고, 새 페이지가 열리는 문제가 있다. a 엘리먼트 특징 때문이다.

a 엘리먼트의 href 속성페이지 전체를 다시 그린다.

필요한 부분만 다시 그려주는 리액트의 장점을 활용하기 힘들다!

이 문제를 해결하려면 react-router-domLink 컴포넌트를 사용하면 된다.

 

 

a 엘리먼트 Link 컴포넌트로 바꾸기

Navigation 컴포넌트에 Link 컴포넌트임포트한다.

다음 a 엘리먼트를 Link 컴포넌트로 바꾸자.

href 속성은 to로 바꾼다

영화 앱을 실행하고 Home과 About 링크 한 번씩 눌러 보자.

 

페이지 전체가 다시 새로 고침 안 된다.

내비게이션이 잘 만들어진 것이다.

Link, Router 컴포넌트는 반드시 HashRouter 안에 포함되어야 한다는 것 기억하자.

 

 

Navigation 컴포넌트 위치 다시 확인하기

Navigation 컴포넌트에서 Link 컴포넌트를 반환하므로

Navigation 컴포넌트는 HashRouter 컴포넌트 안에 있어야 한다.

 

 

Navigation 컴포넌트 스타일링하기

components 폴더에 Navigation.css 파일을 만들고 아래와 같이 입력한다.

 

 

Navigation.js 파일 안에서 Navigation 컴포넌트에 임포트 시킨다.

Navigation 컴포넌트의 JSX를 수정하자.

 

화면이 넓어지면 왼쪽에, 좁아지면 아래에 내비게이션이 놓인다.

 

 

 


영화 상세 정보 기능 만들어 보기

Home에서 볼 수 있는 정보는 아주 일부분이다.

영화 API를 통해 더 많은 정보를 받고 있으니까 이것을 활용한다.

영화 카드를 누르면 상세 정보를 보여주는 기능을 만들 것이다.

 

이 기능을 위해서는 route props를 반드시 이해해야 한다.

route props란 라우팅 대상이 되는 컴포넌트에 넘겨주는 기본 props를 말한다.

우리가 직접 넘겨주지 않아도 기본으로 넘어가는 route props라는 것이 있고,

이것을 이용해 영화 데이터상세 정보 컴포넌트에 전달할 수 있다.

 

 

route props 살펴보기

우선 console.log()를 통해 About으로 어떤 props가 넘어오는지 살펴본다.

About.js 파일

About으로 이동해서 콘솔탭을 확인하면,

이렇게 나온다.

이것이 바로 react-router-dom에서 Route 컴포넌트가 그려줄 컴포넌트에 전달할 route props이다.

 

항상 route props는 전달되고, 이 props에 마음대로 데이터를 담아 보내줄 수 있다.

 

 

route props에 데이터 담아 보내기

이를 위해서는 Navigation 컴포넌트에 있는 /about으로 보내주는 Link 컴포넌트to props의 구조를 바꿔야한다.

to props에 객체를 전달했다. 

pathnameURL을 의미하고, state는 우리가 route props에 보내줄 데이터를 의미한다.

state에 담아 보낸 객체가 About 컴포넌트로 넘어갔는지 확인해보자.

 

 

route props 다시 살펴보기

/about 으로 이동한 후, 콘솔 탭에서 [location]을 펼쳐보자.

state 키에 보내준 데이터를 확인할 수 있다.

localhost:3000에 다시 접속한 다음 /about으로 이동해야 보인다.

 

이런식으로 route props를 사용하면 된다.

 

 

Navigation 컴포넌트 정리하기

Navigation 컴포넌트를 원래대로 돌려 놓는다.

 

이제 본격적으로 영화 상세 정보 기능을 만들어 볼 것이다.

Movie 컴포넌트를 누르면 영화 상세 정보 페이지로 이동해야 하니까 Movie 컴포넌트Link 컴포넌트를 추가하면 된다.

 

 

Movie 컴포넌트에 Link 컴포넌트 추가하기

Movie 컴포넌트에 Link 컴포넌트를 임포트하고, Link 컴포넌트에 to props를 작성하면 된다.

이때 Link 컴포넌트 위치에 주의해야 한다. 안 그러면 영화 카드 모양이 이상해진다.

이제 영화 카드 누르면 /movie-detail로 이동한다. 

/movie-detail로 이동했을 때 보여줄 화면을 만들면 된다.

 

 

Detail 컴포넌트 만들기

Detail 컴포넌트routes 폴더에 추가한다.

그리고 Detail 컴포넌트에서 Movie 컴포넌트의 Link 컴포넌트가 보내준 영화 데이터(state: {year, title, summary, poster, genres})를 확인해 볼 수 있도록 console.log()도 작성한다.

아직 Detail을 출력해 주는 Route 컴포넌트를 추가하지 않았으므로 console.log(props)의 실행은 확인할 수 없다.

App.js에서 Route 컴포넌트를 마저 추가해준다.

 

 

Route 컴포넌트 추가하기

App.js를 연 다음 Detail 컴포넌트를 임포트하고, Route 컴포넌트에서 Detail 컴포넌트를 그려주도록 코드를 작성한다.

 

 

영화 카드를 눌러 /movie-detail로 이동한 다음 영화 데이터 확인하기

영화카드를 눌러 /movie-detail로 이동해 본다.

화면을 보면 Detail 컴포넌트가 출력하고 있는 hello라는 문장이 보인다.

[Console] 탭을 보면 [location → state]에 Moive 컴포넌트에서 Link 컴포넌트를 통해 보내준 데이터가 들어 있을 것이다.

localhost:3000으로 다시 이동한 다음 영화 카드를 눌러 /movie-detail로 이동해보면 console에 잘 뜬다.

 

이 내용을 Detail 컴포넌트에서 출력하기만 하면 된다.

 

 

/movie-detail로 바로 이동하기

만약 /movie-detail을 주소창에 직접 입력해서 이동하면 어떻게 될까?

Detail 컴포넌트의 hello는 잘 출력하고 있지만

[console]탭에는 영화 데이터가 없다(state가 undefined).

Detail 컴포넌트로 영화 데이터가 넘어오지 못한 것이다.

이런 경우 상대방을 강제로 Home 으로 돌려보내야 한다.

그 기능을 리다이렉트 기능이라 부른다.