본문 바로가기

모카 스터디/React

ReactJS로 영화 웹 서비스 만들기

#2  THE BASICS OF REACT

React Js는 UI를 interactive하게 만들어 준다.

우선 바닐라js로 간단한 어플리케이션을 만들어 보려한다.

첫번쨰로  html를 만들고

두번쨰로 js에서 button을 가져왔다.

세번쨰로 button.addEventListener로 두고 

click event를 감지하게 하였다.

그리고 click에 대응하는 함수를 만들어 줬다.

 

 

 

 

 

 

 

왼쪽은 clickㄹ르 해도 콘솔에 직접 counter 변수를 확인하지 않으면 수가 증가되는 것을 알수가 없지만

오른쪽은 span을 가져와서 연결하면 htlm에서도 바로 변경된것을 확인할 수 있다.

 

 

종합적으로 

1.html을 만들기

2.js에서 가져와서

3.event를 감지

4.데이터를 업데이트 한다.(counter=counter+1)

5.html업데이

 

 

이제 위의 번거로운 과정을 줄여주는 React를 사용해 보려한다.

 

React를 설치하기 위해서는  두 개의 javascprit 코들르 import해야한다.

react와 react-dom이다.

두개 모두 import하면 콘솔에서 react가 코드내에 있는지 확인 할 수있다.

 

 

첫번쨰로 react js element를 어떻게 생성하는지에 대해 알아보자.

 

react의 규칙중 하나는 html을 이 페이지에 직접 작성하지 않고 js를 이용하는것이다.

즉 element를 js와 react를 사용해서 작성할것이다. 직접 html을 작성하지 않고.

 

우선 이번 방법은 다른 사람들도 사용하지 않고 앞으로도 사용하지 않을 것이다.

하지만 이런 어려운 방법을 통해 react를 더 잘 이해하기 위해 사용하려한다.

" " 사이의 초록색은

html의 태그 이름과 같아야한다.

 

 

그렇다면 body안에 react element를 가져다 둘 수 있을까 ?

 

react-dom은 libray혹은 package이며  react element들을 html body에 둘수 있도록 해준다.

reactjs는 엔진이며 interactive한 UI를 만들 수 있게 한다.

 

render == 사용자에게 보여준다.

처음 span이 어디에 두어야하는지 dom이

모르기 때문에 span의 위치를 잡기 위해

div에 id를 하나 달아 주어 연결.

 

 

 

 

 

 

 

두번쨰 인자로는 property로서  class name이 될수 있고 id가 될 수 있다.  세번째 인자로는 span의 내용이다.

 

즉  한줄로 span을 만들고 id와 content를 줄수 있다. 

 

이렇게  유독 비효율적이고 긴 예제를 본 이유는 react는 우리가 해왔던 방식을 꺼꾸로 하고 있는걸 확인하기 위함이다.

js에서는 html을 먼저 만들고 js로 가져와서 html을 수정하는 식이었지만

react에서는 모든것이 js로 시작한다 그리고 그것들이 html로 변한다.

 

즉 reactjs는 유저에게 보여질 내용을 컨트롤 할 수있

 

 

이제는 버튼에서 일어나는 event를 어떻게 감지하는지 알아 보고자 한다.

 


button.addEventListener가 대체될 거고

button=document.getElement~~ 여기도 대체될 거야

 

id도 대체할 거야. id가 필요없거든

 

 

 

 

 

자, 버튼을 생성해보자 constant의 이름은 HTML의 태그 이름과 반드시 일치할 필요가 없어

React.createElement() 그리고 이 괄호 안에는 HTML 태그의 이름이 들어가야 하지 그래서 여기에 span 말고, button

그 다음으로는 button을 render해야해

 

그런데, 여기 두 가지를 모두 render하고 싶다면 어떨까? span과 button 말이야

 

property에다가 event listener를 등록할 수 있어 그러니까 button.addEventListener 대신에

여기다 onClick이라고 적으면 돼  그럼 button이 클릭될 때마다 호출될 function을 여기에 작성할 수 있지.

 

 

 event를 적는 방식이 좀 다르지?

바닐라 JS에서는 "click", React JS에서는 on

그렇게 해야 React JS에게 우리가 event listener를 생성한다고 알려줄 수 있어

 

 

 

React JS는 바로 interactivity를 위하여  제작된거야 React JS 팀은 알고 있는거야

interactive한 어플리케이션에서 하는 작업들 모두가 event들을 감지하는 일이란 것을 말이야.

addEventListener를 반복하는 것 대신에 property에서 event를 등록할 수 있게 된 거야

알겠지? 하지만 명심해, 우리는 이런 방식으로 오래 끌고 가지 않을거야

 

예를 들어 여기에서 style을 두고 backgroundColor: "tomato"로 할 수 있지

 

 

 

 

 

 

 

 

이번 강의에서는 이제까지 한 것을 모두 복습해볼거야 알겠지? 첫 번째

React JS와 ReactDOM 코드를 import했지 React JS는 반드시 필요해

React JS가 element를 생성하고 event listener를 더하는 것을 도와주기 때문이지 

또한 우리는 ReactDOM도 import했지 React element들을 가져다가 HTML로 바꿔야 했기 때문이야

가장 먼저, body에 비어있는 div를 생성했어 이 비어있는 div는 ReactDOM이 React element들을 가져다놓을 곳이야

그래서 그 root div를 가져온 후에, 그 다음 ReactDOM.render를 했지

이 코드의 의미는 React element들을 root div 안에서 보여주라는 뜻이야

React 개발자로서, createElement를 쓸 일은 없을거야

하지만 이게 핵심이야. 이게 React JS의 기초라고. 그리고 어려운 방법이지

하지만 보면 알겠지만, 어려운 방식인데도 이해하기 정말 쉬워


ReactDOM은 container element를 root div 안에 render할거야 알겠지? 여기 container element는 div야

아무런 property도 없어 property는 이제까지 봤듯이 id나 class, event listener가 될 수 있지

그리고 이 div의 content들은 h3와 btn이야

알겠지? h3로 가보자 h3은 그냥 단순한 h3야. header 3로, HTML element이지 property가 좀 있고, content도 있어

 첫 번째 argument는 root에 들어갈 HTML 태그야 두 번째 argument는 props가 포함된 object이고 세 번째는 content지. 


처음은 "button" 그 다음은 props, 세 번째는 content

이제 props를 살펴보자고 이전에 살펴봤듯이 props에서 id나 class를 바꿀 수 있었어

색도 바꿀 수 있었고 일반적인 HTML tag의 property로부터 무엇이든지 바꿀 수 있었지

예를 들어, 여러분이 input을 가지고 있다고 해보자 그러면 이 props에서 placeholder 등 무엇이든 바꿀 수 있을거야

중요한건 여기에 있어! event listener에 말이야 

React 팀은 개발자들이 element에 event listener를 달아야 한다는 걸 알았지


여기 보면 property object에 이런 식으로 event listener를 등록할 수 있어


우리는 addEventListener를 할 필요가 없어. 이렇게 안해도 돼


알겠지? 여기까지가 우리가 해본 것들이야

element를 어떻게 생성하는지 배웠고 props object의 파워에 대해서도 배웠어

그리고 props object에서 일부는 HTML로 가는 것도 보았지

 


예를 들면 여기에서 우리가 작성한 style을 찾아볼 수 있지 그런 것을 배웠는데, 또한 React JS는 스마트하기 때문에

어떤 것은 HTML로 가야 하는데, 가끔 event listener와 같은 것들 on으로 시작하는 이거 말이야

그리고 여기엔 유효한 event가 있어야 하지



우리는 일종의, 거의 interactive한 React JS 어플리케이션을 만들었어

마지막 하나가 남았는데, 데이터를 업데이트하는 거야

이걸 다음 강의에서 하지는 않을거야

다음 강의에서는 React element를 생성하는 더 편리한 방식을 배워볼거야


자 다시, 복습해보자. 우리는 React JS와 ReactDOM을 먼저 설치했어

React JS는 interactivity의 원동력이야 ReactDOM은 React element를 가져다가 HTML로 바꾸는 역할을 하지

그 다음 우리는 세 개의 element를 생성했어 첫 번째는 div인데, 아무런 property를 가지지 않아

h3와 button 두 개의 element를 render하고 있지 h3는 h3 HTML element야

몇몇의 property와 content를 가지고 있지 button 역시 button element이고 마찬가지로 몇몇의 property와 content를 가지고 있지

여기서 중요한 것은!

props 안에서 event listener를 등록할 수 있었지. 이건 아주 파워풀한 거야

그리고 다시, React JS는 스마트하기 때문에 이건 event listener인 것을 알고

이 id는 마지막으로 생성된  HTML에 있어야 한다는 것도 알지

 

1.5 JSX

createElement를 대체할 수 있는 방법에 대해 다뤄볼 거야

그 편리한 녀석은 JSX라는 녀석이야 JSX는 JavaScript를 확장한 문법이야

 여기서 한 것처럼 React 요소를 만들 수 있게 해주는데 우리가 HTML에서 사용한 문법과 흡사한 문법을 사용해서 말이야

생긴 게 HTML이랑 비슷해서, JSX로 React 요소를 만드는 게 개발자들 입장에서는 굉장히 편해

 새로고침해주면 에러가 발생할 거야 왜냐면 브라우저가 온전히 JSX를 이해하는 것은 아니라서 에러가 발생하는 거야

그래서 브라우저가 JSX를 이해할 수 있게 뭔가를 설치해줘야 돼 한 번 변환해줘야 하지

이걸 하는 데에 Babel을 사용하려고 해 Babel은 코드를 변환해주는 녀석인데

여러분들이 JSX로 적은 코드를 브라우저가 이해할 수 있는 형태로 바꿔주는 거지 브라우저는 JSX를 모르니까 말이야

자, 이제 이 변환기를 설치해줄 건데 Babel standalone을 이용해서 다운받을 거야



혼자할 때는 절대 이렇게 할 일이 없을 거야, 이 방식은 느리거든 더 나은 방식들이 있어

지금은 이렇게 하겠지만, 항상 이렇게 할 필요는 없어 이 코스에서만 이렇게 진행하는 거야

이제 새로고침하면 아직 잘 동작하지 않지 왜냐면 여기 type을 안적어줬거든

 



type="text/babel" 입력

이벤트리스너들도 전부 똑같이 동작하고 말이야 우리가 어려운 방식을 먼저 해보길 잘한 거 같아

덕분에 이제 React.js를 무서워하지 않게 됐잖아


여기 까지가 JSX 소개 시간이었고 JSX에 대해 알아야 할 다른 것들은 다음 강의에서 다뤄볼 거야

createElement를 그만 사용하고 이런 방식으로 하고 싶어 좀 더 cool한 방식으로 하면 좋잖아 JSX를 이용해서 말이야

 

1.6JSXpart Two

 


Container라고 적어주고 div 태그를 담아줄게, 이렇게 말이야 그리고 내부에 Button과 Title을 렌더링해줄 거야

그리고 새로고침 해주면 에러가 발생할 거야 실제로 에러는 아니지만 텍스트가 나타나버렸지

이 모든 요소들은 하나도 포함시키고 있지 않지 예를 들어, Title이나 Button을 포함시키기 위해서 우리가 해야할 건 첫째로

이 녀석들을 함수로 만들어줘야 돼

그래서 이런 식으로 함수로 만들어주면 돼, 굉장히 간단하지


나는 이 녀석들을 여기에 포함시키고 싶어

이제 우리가 하려는 건, 이것들이 마치 일반적인 HTML 태그인 것처럼 포함시켜줄 거야

예를 들어, Title을 렌더링하고 싶으면 우린 이렇게 대문자로 Title이라 적어줄 거야  Button도 같은 방식으로 해줄 거야

우린 지금 여러 컴포넌트들이 합쳐진 구성을 만들고 있는 거야


div 태그를 렌더링하고 있는 컴포넌트가 하나 있는데, Title에 관련된 코드를 포함시키고 있는 거지

 

 


기억해야 될 게 컴포넌트의 첫 글자는 반드시 대문자여야 한다는 거야

만약 소문자면 React랑 JSX는 이게 HTML button 태그라고 생각할 거야

여러분들이 직접 만든 요소는 전부 대문자로 시작해야 돼

이건 HTML button 태그고
이 대문자 Button은 여러분들이 생성한 Button이야

보다시피, JSX는 어플리케이션을 여러 가지 작은 요소로 나누어 관리할 수 있게 해줘, 정말 멋지지

 

 



여러 요소로 잘게 쪼개서 만들어서 합쳐 주기만 하면 되는 거지

한 쪽에서 Title을 만들어 주고, 다른한 쪽에서는  Button을 만들어 주고

이렇게 보기 쉽게 코드를 분리한 뒤에 함께 렌더링하는 거지

 

 


#3 STATE

3.0 Understanding State 

좋아 모두들, 이번 강의에서는 React.js의 state에 대해 배워볼 거야 state는 기본적으로 데이터가 저장되는 곳이야

우리가 지금 바닐라 JS로 진행중인 예제를 완성하려면 우린 지금 counter를 증가시키고, 그걸 UI에 디스플레이하고 있잖아

그걸 state로 만들 수 있어, counter 말이야 바뀌는 데이터들 말이야 지금부터 배워볼 부분이야

어떻게 하면 React.js 어플에 값이 바뀔 데이터를 담아줄수 있을까 

이제 이 텍스트를 전에 적었던 텍스트로 바꿔줄거야

 

 

 

 

 

 

 

 

 

 

 

 


이제 이 React.js 코드 내에서 카운트를 셀 수 있게 만들어 보려 하는데

 먼저 별로 좋지않은 방식으로 해보고 우리한테 어떤게 필요하고, 어떤걸 해야되는지 이해하고 나서

프로페셔널한 React.js 방식을 보여줄게 그러면 여러분들이 왜 그런방식으로 하는건지 이해할수 있겠지



그럼 먼저 let counter를 만들어주고 초기값으로 0을 줘볼게

이제 내가 여러분들께 보여주고 싶은건, 이런 변수들을 JSX에 전달하는 방법이야

바닐라 JS로 진행할 때는 이렇게 했었지 span.innerText를 이용해서 span의 텍스트를 바꿔줬었어

React.js에서는 이 방식을 사용하지 않아도 돼 단지 중괄호를 열어주고 변수 이름을 담아주면 끝이야


그래서 countUp이라는 함수를 만들어 주고 counter = counter + 1 입력
우린 이미 React.js에서 이벤트리스너를 추가하는 방법을 알고있지

button으로 가서, 전에 써봤던 onClick prop을 만들어주면 돼 이제 onClick에 countUp을 담아줄게



UI가 업데이트 되지 않아서 일어나는 문제야 하지만 확실한건 이렇게 클릭할때, 카운트는 증가하고 있다는거야
그럼 카운트를 console.log 해보자 봐봐, 지금 counter가 53이지 이 말인 즉, 이벤트리스너가 동작하고 있다는 거야
그저 UI가 업데이트되질 않는거지

 


왜냐면 지금 우리 프로그램이 동작하는 원리를 생각해보면 우리는 컴포넌트를 단 한번만 렌더링하고 있잖아


우리가 어플리케이션을 시작했을때 counter는 0이지 우리가 페이지를 로드했을때 바로 말이야

그래서 이 코드가 실행되면 Container 컴포넌트가 렌더링될텐데

그 말인 즉, 이 코드가 React Element가 될거란 뜻이야 이게 실행될때는 counter는 0이야

우리가 Container를 렌더링하고 root에 담는데 이렇게 렌더링한 Container는 counter 값으로 0을 가져

왜냐면 이제 막 페이지가 로드됐으니까 말이야


리렌더링하고 있지않아, 그게 우리가 원하는건데 말이야 Container를 리렌더링해서 다시 보여줘야지

새로운 버전의 Container를 말이야 한마디로 우리가 countUp을 호출할 때마다 여기 이 라인을 다시 호출하고 싶은 거야

counter가 1이 증가하고 그리고 나서 Container를 리렌더링해주면  이번에 그려질때는 counter는 1이겠지

 

 

 

 

 

 

 

 

 

 

 

 

 

 

다시 말하는데, 이건 우리의 목표를 달성하는 최고의 방법은 아니야
왜냐면 여길보면 우리가 값을 바꿀때마다, 다시 렌더링하는걸 잊어서는 안되거든 그렇게 좋은방법은 아니야

 

 

React.js는 UI에서 바뀐부분만 업데이트해주고 있지
보다시피 React.js는 이전에 렌더링된 컴포넌트는 어떤거였는지 확인하고 있어 그리고 다음에 렌더링될 컴포넌트는 어떤지를 보고 React.js는 다른 부분만 파악하지

다시 Total clicks를 생성할 필요 없고 button도 다시 생성할 필요도없고 오로지 바뀐 부분만 업데이트 해주면 돼
여러분이 여러가지 요소들을 리렌더링하려고 해도, 전부다 새로 생성되진 않을거야 오로지 바뀐부분만 생성될거야

#3.1 setState part One


 지금까지 진행한 부분을 전부 삭제하고 React.js 어플 내에서 데이터를 보관하고
자동으로 리렌더링을 일으킬수 있는 최고의 방법을 배워보려해

React.js가 여러분이 원하는 리렌더링을 어떻게 도와주는지 알아볼거야  그 이유는

우리가 만약 사용자에게 업데이트된걸 보여주고싶으면 새로운 정보를 가지고 컴포넌트를 리렌더링해줘야 하기 때문이야

리렌더링을 유발시키기 위해서 React.js 가진 기능을 배워볼거야
자, 이제 여기로 와보면 이벤트리스너가 사라져서 아무것도 바뀌지 않아



이제 여러분에게 React 어플리케이션을 다룰때, 어디에 데이터를 담으면 되는지 알려주고 싶어

왜냐면 그 전에는 counter 같은 변수에 담았었잖아 이렇게 하면 안된다는건 아니야

하지만 React.js는 여러분들을 도와줄 기능들을 가지고 있지

만약 그런 기능들을 사용하고 싶으면 React.js가 제시하는 룰을 따라야겠지

data를 만들고 함수 내에서 return문 전에 상수를 하나 만들어 주는 거야 그리고 React.useState()를 사용할 거야
React.js가 이 라인의 코드를 가지고 우리가 이전 강의에서 했던 많은것들을 제공해주고있어

그래서 이 라인의 코드를 통해 우리가 얻게 되는 건 보다시피 undefined와 함수 하나야

여러분들이 알아야 되는건 이 녀석이 바로 data고 여기 이 함수는 data를 바꿀때 사용하는 함수인거야
React.useState() 함수는 초기값을 설정할 수도 있어 초기값으로 0을 줘볼게
초기값인 0과 이 data의 값을 바꿀수있는 함수가 들어있는 배열을 얻었어

여기 이 두 요소가 만나서 우리가 전에 만들었던 함수의 역할을 대신하고 있어 바로 countUp 함수야
data 값을 바꿔주는 녀석이었고 data였던 counter 역시 0이었지


하지만 배열상태 그대로 사용하는건 보기 불편하잖아
왜냐면 내가 만약 h3에서 첫번째 요소를 사용하려고 한다면 그러면 data[0] 같은 방식으로 접근해야겠지
어떻게 하면 배열에서 요소들을 꺼내서 이름을 부여할 수 있을까?

여거로 와서 상수 counter에 data[0]를 할당해주자
그리고 modifier를 만들어 줄 건데

말 그대로 값을 modify해줄 녀석이라 이렇게 이름붙이는거야  이 녀석은 data[1]이 되겠지

구려(질색)

 



더 나은 방식이 이미 존재하고 있어

첫 번째 아이템은 counter가 될거고 이 이름은 변경가능해 두번째 녀석은 modifier야

이게 state의 첫 번째 부분이야 이제 우리가 배워볼건 어떻게 modifier를 이용해서 counter의 값을 바꿔줄지
그리고 왜 modifier가 필요한지 배워볼거야

#3.2 setState part Two 


const로 바꿔주고  counter를 업데이트하는데 modifier 함수를 쓰려고해

modifier 함수는 값을 하나 받아 어떤 값을 부여하던 modifier 함수는 그 값으로 업데이트하고 리렌더링을 일으킬 거야


이젠 단순히 이 한줄 코드로 React.useState 함수는 counter 같은 데이터를 숫자형 데이터로 건네줄거고

그 데이터 값을 바꿀 함수도 함께 줄거야 그리고 그 함수를 이용해서 데이터를 바꿨을때, 데이터 값이 바뀌고

컴포넌트도 동시에 리렌더링될 거야

그래서 보통 사람들이 하는 방식은, 데이터를 이름 붙일때 counter처럼 원하는대로 붙이고
modifier는 modifier가 아니라, set 뒤에 데이터이름을 붙여주는거야 이 경우에는 setCounter가 되겠지

 

그리고 물론 React.js는 오로지 바뀐 부분만을 업데이트해주고있어
React는 업데이트 사이사이마다, 정확히 어떤것이 업데이트됐는지 파악해서 HTML에서 그 부분만 고치는거야

 

#3.3 Recap 

우리가 기억해야 할 건 modifier 함수를 사용해 state, 즉 어플리케이션의 데이터를 바꿀때
modifier 함수로 state를 바꿀때, 컴포넌트 전체가 재생성될 거야 새로운 값을 가지고 말이지


이게 우리가 알아둬야 할 전부야 마지막으로 한 번만 더
modifier 함수를 이용해서 state를 바꾸면, 이 컴포넌트가 재생성되고  코드가 다시 한번 실행될거야
그리고 이 return도 한번더 실행되지만, 이번에는 새로운 값을 가지고 실행될거야


가장 중요한건 state가 바뀌면 리렌더링이 일어난다는거야

보다시피, 바닐라js를 완전히 대체했어
HTML 요소를 생성하거나 찾을 필요도 없고 이벤트리스너를 더해줄 필요도 UI를 업데이트해줄 필요도 없지
바로 HTML을 만들어버렸고 여기에 곧바로 이벤트리스너를 더해줬고 그리고 UI를 업데이트하면 자동으로 리렌더링되지

#3.4 State Functions 

 

 

 

 

 



setCounter를 쓰긴 할건데, setCounter에는 함수를 넣을수도 있어 이 함수의 첫 번째 argument는 현재 값이야.
그리고 이 함수의 return값이 새로운 state가 되는거지.
둘 다 현재의 state을 가지고 새로운 값을 계산해내지. 하지만 아래쪽이 더 안전해.

 

여러분이 현재 state를 기반으로 계산을하고 싶다면, 함수를 이용하는 거야.

그래서 다음 state의 값이 현재 값을 바탕으로 나올수 있도록. 알겠지?


state를 세팅해주는 데에는 2가지 방법이 있다
1. 이렇게 직접 값을 설정해주는 것.  예를 들면 이렇게 원하는 숫자 입력해주기.
2. 함수를 전달하기. 

#3.5 Inputs and State 

먼저 분을 시간 단위로 바꾸는 것부터 시작해보자.
Minutes라고 되어있는 placeholder 부분에 분을 쓰면,  시 단위가 갱신될거고,
Hours라고 되어있는 placeholder 부분에 시간을 쓰면,  분 단위가 갱신될거야


좋아, 이제 JSX 에 대해 새로운 걸 알려줄게.

이거 사실 틀렸어.  React JS의 세계에서는 말이지. JSX에서는 다르게 표현해줘야 해.
기억해, 우린 지금 HTML을 사용하는 게 아니야. 우린 JSX를 사용하고 있지. 좀 달라.

문제1. class 를 사용한 것. 우린 class 를 사용하면 안돼.     className이라고 써줘야 해.
문제2. for 을 사용한 것. for 도 사용하면 안돼.       htmlFor이라고 써줘야 해.

이제부터 중요한 거야. miniutes에 필요한 state를 만들거거든.
react code로 miniutes에 어떤 숫자를 적었는지 추척할 수 있어
이 input은 uncontrolled이라고 알려져있어.

그래서 이제 state를 만들어 줄거야.

React.useState

기억해. useState는 array를 제공해. 

첫 번째 element가 현재의 값이 되지 minutes라고 하자
두 번째 element엔 minutes를 수정해주는 modifier 함수가 들어가.setMinutes 라고 적어줄게.

그리고 이제 value를 input에게 줄 수 있어. value= minutes
자 이제 minute의 값을 넣어주는 input이 있고, 그리고 그 값은 minutes가 될거야. 그리고 minutes은 state에 있지.


좋아, 이제 내가 하고 싶은 건... 사용자가 다른 값을 입력할 때마다 이 value를 업뎃시키는거야.
여기 value를 업데이트 하고 싶어. 사용자가 Input에 새로운 값을 입력할 때마다 이 state를 업데이트 하고싶어.

우리가 찾고있는 그 이벤트는 바로 "change"야 onChange를 써주고.. 여기에서  value를 얻게될거야.

onChange라는 함수도 만들도록 하자.


좋아, 이제 input에 변화가 생길때마다 그 변화를 리스닝 하고싶어
여기서 변화란, 사용자가 input에 뭔가를 입력하는 걸 말해.
좋아, 이제 onChange라는 event를 리스닝할거야.

 


전에 버튼에서 onClick을 리스닝한것처럼 이제 우린 onChange를 리스닝하고있어.
이제 input에 변화가 생기면, onChange  함수를 실행해줄거야.

 

 

 

 

 



여기 event, 이거 우리 바닐라 JS 할 때 하곤 했잖아? 그니까 여기서도 event 해줄거야.
event.target.value 순서로 적어주면 되겠다.

그러니까 document.getelement 어쩌구 저쩌구 해 줄 필요 없단 말이지.

좋아, 이제 value를 가지고 있으니 이걸 minutes에 넣어줄거야.
기억하지? 데이터를 업데이트하는 방법은 setState 함수를 사용하는 거야.
setMinutes(event.target.value)

 

 

 

 

#4 [2021 UPDATE] PROPS

#4.0 Props 


그럼 이제, 우리는 Props에 대해서 배울 거야.
Props는 일종의 방식이야. 부모 컴포넌트로부터 자식 컴포넌트에 데이터를 보낼 수 있게 해주는 방법.


이제부터 우리가 할 것은, 한 예시를 만들 거야.  부모 컴포넌트로부터 자식 컴포넌트로 데이타를 보내는 거지




Props를 이해하기 위해서,  왜 필요한지를 보기 위해 우리는 Props로 해결이 가능하게 될 문제들을 일단 먼저 겪어봐야해


고로 한번 가정을 해보자. 우리가 회사에서 어플리케이션을 만들고 있다고.
물론 이 어플리케이션은 버튼을 갖고 있겠지. 꽤 많은 다양한 버튼들 말이야.
그런데 대부분의 회사들은 이 모든 버튼들이 같은 모습이야. 

그들은 모든 버튼들을 똑같이 보이게끔 만들어. 하지만 우린 아직 몰라.
어떻게 리액트 컴포넌트를 재사용할 수 있게 만드는지. 만드는 방법을 모르기 때문에, 
우리는 우리가 아는 방법으로 해볼 거야. 각각 버튼마다 컴포넌트를 만드는 거지.

 

 



그래서 우리는 function(함수)를 만들어 볼 거야. SaveBtn이라는 새로운 컴포넌트를 만들 거야.
그리고 내가 component(컴포넌트)라고 하는건, 보고 있는 대로 단지 function(함수)일 뿐이야 이게 바로 컴포넌트야.
그래서 컴포넌트는 단지 함수야. 어떤 JSX를 반환하는.

 

 

그러므로 우리는 SaveBtn을 사용할 수 있겠지. 
이건 ConfirmBtn이라고 하자.

그리고 우리는 Render할 거야, 

 

 

 

 

<div>사이를 JSX 내부라고 부른다.

 



 

 

 

그래서 지금부터 뭘 할 거냐면, button의 style property(속성)을 사용할 거야. 
 button Tag(태그) 내의 style을 변경하는 거야

 

 

 

 

 

 

우리에게는 총 두 개의 버튼이 있어. 하나는 ‘확인 (버튼)’ 하나는 ‘저장 (버튼)’.
그래서 뭘 해야 하냐면, 이걸 복사해서, 여기에 붙여넣기할 거야.
그럼 지금 얘네 둘은 다 똑같게 보이지. 

Style을 그저 복붙하는 것 대신에,  보다 좀 더 설정이 가능한 컴포넌트
 이 모종의 설정들을 넘겨 줄 수 있는 button 컴포넌트가 있다면 말이야
왜냐하면, 잘 생각해 봐. 이 컴포넌트에서 보면 단지 이 text만 다르잖아.
이런 Style들을 모두 갖는 단 한 가지의 컴포넌트만 만들 수 있다면 얼마나 좋을까?
다만 text만 변경되는 거지.

 

그리고 여기 이름을 바꿔 줄 거야. SaveBtn을 Btn으로.

그리고 여기에 Render해 줄 거야. 두 Btn을.
첫 번째 Btn, 그리고 두 번째 Btn. 

좋아. 이제 그럼. 여기 새로고침하고, 보이지, 둘 다 똑같아.

 

 

 

떠올려봐. 우리가 HTML에서 input을 어떻게 설정했지? HTML에서 우리는 input이라고 썼지, 그치?
그리고 type. 이렇게 썼지. text
맞지, 또는 button을 어떻게 설정했더라. 그리고 onClick, 우리가 배운 대로.
그치만 이건 무척 새로운 거야 이건 JSX야.
이게 우리가 EventListener를 붙여주는 방법이었지.

 이미지는 img라고 쓰고, 여기 img 그리고 src, 맞지? 우린 매우 자주 이 syntax(구문)을 사용해 왔지
그래서 이 syntax를, 우리의 커스텀 컴포넌트에 똑같이 적용해 볼 수 있어.
이게 바로 우리가 얘네들에게 데이타를 전달시킬 수 있는 방법이 되겠어.

그래서 동일한 syntax를 사용하면서, 예를 들면 이 img 태그에 정보를 전송하는 것과 같이
이제 우리는 "새로운" 정보를 이 Btn 컴포넌트에 전송할 거야.
알았지, 그리고 그건 "text"가 될 거야. 이렇게.

 

 

 

 





그리고 이쪽으로 와서, 새로고침하면. 보시다시피. 당연히 아무것도 변한 게 없지.
우리는 banana를 Btn에게 보냈는데, 이 Btn은 banana를 사용하고 있지 않거든.


이번에 배워볼 건, 네가 만들고 사용하는 모든 컴포넌트들은
여기 "()" 괄호로 argument(인자)를 받는다는 거야. 리액트가 넣어주는 거지.
여기 첫 번째 argument의 이름은 마음대로 지어줄 수 있어.


사람들은 이 인자 이름을 props라고 부르지. Btn으로부터 전달 받는 properties인거지

결국 Btn() 함수를 불러서 banana라는 인자를 이런식으로 보내는 것과 같은거야


왜냐하면 “Btn”은 함수니까

Btn은 function이지.

 

 


그래서 어떤 prop이든 네가 Btn 컴포넌트에 보내면 그것들은 Btn 함수의 첫 번째 argument(인자) 속으로 들어갈 거야.
props를 한 번 console.log로 찍어보자.

두개의 Object가 나온다.

하나는 banana: “Save Changes” 또 하나는 banana: “Continue”

 왜냐하면 Btn을 “두 번” rendering했거든.
하나는 Save Changes 또 하나는 Continue.

 



그러므로, 우리가 여기서 하고 있는 것은, Btn이라는 이름의 function(함수)를 부르고 있는 것뿐이야
그리고 정보를 이 함수에 전송하고 있는 거지. 그리고  React.js가 이 부분에서 실제로 하는 작업은 Btn() 이렇게 함수를 호출해서 우리가 넣어둔 모든 것들을 첫 번째 인자로서 넣어줄 거야.

Btn({banana: "Save Changes"}) 이런식이지


즉,  ReactJS는 자동으로 네가 이곳에 넣는 모든 property(prop)들을 모조리 이 오브젝트 안으로 집어넣을 거야.
그리고 이 오브젝트는 네 컴포넌트의 첫 번째 인자로 주어지는거지 두 번째 인자는 없어.
알았지, props는 첫 번째이자 유일한 인자야. 이 Btn이 전달 받는 유일한 인자.
그리고 props는 오브젝트지. 우리가 이쪽에서 보낸 모든 것들을 갖는 오브젝트.
그래서 우리가 원한다면 이렇게 x={false} 그리고 여기는 y={7} 이라고 할 수 있겠고, 뭐든 간에.
그리고 console.log 해보면

보이지, 첫 번째 Btn의 props는 이렇게 우리가 넣은 모든 것을 갖는 오브젝트가 됐지.
"Save Changes", 그리고 false  "Continue", 그리고 y

 


그럼 이제 뭘 할 거냐면, banana를 이곳에 사용해볼 거야.
우리가 오브젝트를 받고 있다는 걸 알기 때문에 가능하지.
이 오브젝트는 banana라는 이름의 key를 갖고 있어.

그래서 이쪽으로 와서, props.banana
좋아, 그럼 이쪽으로 와서 새로고침하고.

 

우리는 여기서 같은 Btn 컴포넌트를 사용하지만,  이 버튼들은 App 컴포넌트에 의해 설정되고 있어

단 하나의 Btn 컴포넌트가 있지만
보다시피 UI는 다르지. 알았지.

재사용 가능하게 만들고 있어.


한 가지, 너는 이것(props)들을 자주 보지 않을 거야.  대신에 사람들은 shortcut(지름길)을 자주 쓰지. 그게 뭐냐면,
네가 원한다면 이렇게 props.banana 이런 식으로 쓸 필요는 없어.
대신에, props는 오브젝트이기 때문에 우리는 "{}" 중괄호를 열어
이렇게. {}. 그리고 오브젝트로부터 banana를 받을 수 있어.

고로 이곳에서도 banana라고 적기만 하면 되지.

그래서 이건 단지 shortcut이야. property를 오브젝트로부터 꺼내는 거지. 왜냐하면 props는 오브젝트이기 때문이야
우리는 props 안에 banana가 있다는 사실을 알고 그래서 그냥 이렇게 할 수 있는 거지.

 

 

#4.1 Memo 

 props에 뭘 또 넣어볼 수 있는지를 볼 거야. 보았다시피, true나 false는 보낼 수 있었지. string도 보낼 수 있었고
또한, 네가 원한다면 우린 function도 보내볼 수 있어.

알았지, 그리고 Btn을 렌더링하는 컴포넌트가 어떻게 되는지도 알아보자고.
예를 들어 이 부모 컴포넌트. 부모 컴포넌트가 state(상태)를 변경할 때 어떤 일이 일어나는지도 좀보자고

그래서 뭘 할 거냐면. 내 Btn들에 onClick function을 달아주고 싶어.
이 onClick function은 내 App 컴포넌트에 있는 뭔가의 state를 바꾸게 될 거야.

 

 

 

 

 

 

 

state의 기본값 로 “Save Changes”를 넣어 보자고. 알겠지. 그리고 우리는 Btn의 “text”를 state에 연결할 거야.
그러니까 value, setValue 적어 주고  보내는 string을 다른 걸로 바꿨을 뿐이야.
그냥 string을 전달하고 있지. 그래, state로부터 말이야.
알겠지, 그럼 이제 function을 만들어 보자. 이름은, “changeValue”.

 

 

 

 

 

 

 

 

changeValue는 “setValue”를 부를거고, 이건 Revert Changes로 값을 재설정할 거야

이 함수를! 이 Btn의 onClick으로서 말이지.

난 이걸 onClick이라고 이름 붙일 거야. 하지만 무척이나 중요한 건데, 이것들은 Btn으로 들어가는 prop이야.
실제 EventListener(이벤트리스너)가 아니고. 이것들은 지금 prop 이름일 뿐이고, 지금 Btn 안으로 전달되고 있는 거지.

 

 

 


나는 여기에 style을 달 수 없어. color가 green이고 뭐고.  전혀 작동하지 않을 거지.


고로 동일한 이유에서, 내가 만약 이 첫 번째 Btn을 클릭한다면, 보겠지만, 어디에도 등록된 onClick 이벤트는 없는 거야.
알겠지, 왜냐하면 다시, 이건 button으로 들어가는 무언가가 아니야.
이건 Btn 컴포넌트로 들어가는 무언가지. 이건 button 태그를 위한 이벤트리스너가 아니야.

 

 

내가 직접적으로 손수 해줘야 하지. 이쪽으로 와서,

onClick을 전달 받아와서,  onClick을 설정해줘야만 해.

 

 

 

 

 

 

 

그래서, 이걸 좀 더 이해하기 쉽게끔 하기 위해서.



난 이걸 changeValue 라고 이름 지어 볼게. 

 

그렇다는 말은, changeValue라는 prop을 갖게 되는 거고,
button은  changeValue라는 onClick 리스너를 갖게 되는 거지.

 

 

이렇게 해보고 싶었어. 왜냐하면  네가 커스텀 컴포넌트의 prop으로 원하는 뭐든지 사용할 수 있다는걸 보여주고 싶었거든.
prop들은 물론 직접적으로 return문 안으로 들어가지 않지만 말이야. 네가 prop들을 넣어야 하는 거야.

 

 





부모 컴포넌트는 state(상태) 변경을 겪잖아. 그리고 상태가 변경될 때 여기 있는 모든 게 새로 그려지지.
그치? 매우 명심하고 명심해야만 해. 알겠지?

보다시피 우린 부모의 상태를 바꾸는 함수를 만들었고,   이놈이 이 함수를 실행하는데, 그건 자식이 실행시키지. 미쳤어.

 

ReactJS가 네 어플리케이션을 최적화시키는 많은 것들을 갖고 있다는 거야.
어떤 부분이 Btn Continue를 다시 그리는 걸까? 딱히 뭐 없잖아. 그러니까 이건 다시 그려서는 안 되겠지.

알겠지. 첫 번째 놈은 다시 그려야만 해. 왜냐하면 이건 Save Changes이지만, 
Revert Changes가 되었거든. 고로 새로운 버튼인 거야.

하지만 두 번째 놈은, 다시 그릴 필요가 전혀 없잖아.
그치? 하지만, ReactJS의 규칙에 의해서 우리는 만약 컴포넌트가 상태를 바꾼다면 다시 render하리란 것을 알고 있잖아.
알겠지, 이 케이스에서는 보다시피, 부모가 state를 변경하고 있고
그럼 여기 있는 모든 게 다시 그려지잖아. 이 Btn과 여기 Continue 모두가 말이야. 그치?
그래서 우리가 뭘 할 수 있냐면, 바로 React Memo 라고 불리는 걸 할 수 있어.

마치 memorize(기억)하는 것처럼. 알겠지? 우린 리액트에게 말해줄 수 있어.

우리는 이 컴포넌트가 다시 그려지는 것을 원치 않는다고 말이야 만약 props가 변경되지 않는다고 하면.

그래서, MemorizedBtn은 바로 memorized version의 Btn이 될 거야.
알겠지, 그럼 이제 이 Btn을 MemorizedBtn으로 교체해볼게.

알겠지, 그럼 너는 차이점을 보게 될 거야.
그리고 알다시피 내가 Save Changes를 누르면, changeValue 함수가 실행될 거고
changeValue는 state를 바꿀 거고, 그건 re-render를 발생시켜야만 해.
하지만 지금 내가 Save Changes를 클릭하면,  보이지, Continue는 다시 그려지지 않았어.
단지 새로운 버튼만 그려졌지.

 

 

 

만약 아빠(부모)가 어떤 state라도 변경이 있다?  모든 자식들은 다시 그려질(re-render) 거야.
그리고 이게 추후에 네 어플리케이션이 느려지는 원인이 될 수도 있어.

왜냐하면 상상해봐, 만약 네가 하나의 컴포넌트를 갖는데, 그 컴포넌트가 천 개의 컴포넌트를 그리고 있다고 말이야.
그리고 네가 부모 컴포넌트의 state를 변경했다고 해보면,  그 말은 넌 천 개의 컴포넌트들을 다시 그리게 될 것이란 말이지.

이 prop이 변했다는 말은, state가 변했었다는 말이고. 그리고 이 state는 이 prop에 연결되어 있었지.

#4.2 Prop Types (08:14)



그럼 이제 뭘할 거냐면, “Props Types”에 대해서 이야기 할 거야.
왜냐하면 컴포넌트를 다룰 때 우리가 알아야만 하는 놈들 중 마지막 놈이기 때문이지.


원하는 어떤 prop이든 보낼 수 있게 해주지, 우리가 하고 있는 뭐든 가능하게 해주지,
정말 멋지지. 다 컴포넌트의 환경을 우리가 원하는 만큼 설정할 수가 있기 때문이야.
text를 보낼 수 있지, boolean 타입도 보낼 수 있지, 뭐든 원하는 건 다 보낼 수 있잖아.


문제는 네가 컴포넌트들을 갖고 있는데, 그것들이 매우 많은 props를 가질 때 생기지.
때때로 넌 실수를 할지도 몰라. 또는 뭐 네 팀원이 실수를 저지를지도 모르고.  잘못된 prop을 전달한다든가 말이야

 

그래서 한 가지 예시를 들어볼게. 
우리 Btn에 한 가지 더 configuration(설정)을  해 보자고. user(사용자)가 prop으로 fontSize를 전달할 수 있도록 해볼 거야.
여기 fontSize 적고, 18이라고 하자. 알겠지, 그럼 이제 여기로 fontSize를 받아 올 거야.


근데 상상해봐, 만약 네가 협업하고 있고. 팀원이 꼼꼼히 읽지 않거나 뭐 실수를 한다고 말이야
뭐 어쩌면 (prop에)전송하지 말아야 할 것들을 전송한다든가. 어쩌면 text prop에 string 타입을 보내는 대신에,
숫자를 넘겨줄 수도 있지 그치? 그리고 fontSize에는 text를 보내는 실수를 할 수도 있어.

보다시피 이건 error야 코드 상에서는 에러가 아니지. 틀린 code는 아니야.syntax(구문)은 괜찮아.
규칙에 어긋난 문자는 없잖아.  근데 우리가 사용하고 있는 컴포넌트 방식 내에서는 에러잖아.


리액트가 우리한테 너는 실수를 하고 있다라고 말해준다면 말이지.

문제는 리액트는 모른다는 거야. 우리가 text에 무엇을 받고 싶어하는지를.
우리는 text가 string이 되길 원해. 그리고 fontSize는 number가 되길 원하고. 하지만 ReactJS는 이걸 몰라.
하지만 감사하게도, 이거 또한 리액트 팀으로부터 나왔는데, PropTypes라는 이름의 한 패키지가 있어.
PropType은 네가 어떤 타입의 prop을 받고 있는지를 체크해준단 말이지.


왜냐면 ReactJS는 모르기 때문이지. 하지만 우리가 PropType을 설치함으로써
현재 뭘 할 수 있냐면, 우리의 컴포넌트 이름을 가져와서,

그럼 이제 props의 타입이 뭐고 어떤 모양이어야 하는지를

우리가 설명해줄 수 있다는 거지.

 

 


그럼 다시 와서, 새로고침 해보면, 봐봐. 우린 최소한 경고 문구를 볼 수가 있어.

'='text는 number였지만, Btn은 string을 원한다.'

 

좋은 소식은 이렇게 이런 warning을 콘솔로 받을 수 있다는 거지.

 

#5 [2021 UPDATE] CREATE REACT APP

#5.0 Introduction 

좋았어, 모두들. 이번 비디오에서, 아니면 이번 섹션에서, 우리는 Create React App에 대해서 친해져 볼 거야.

create-react-app은... 리액트 어플리케이션을 만드는 최고의 방식이야.
봤다시피 우리가 이전에 만든 리액트 어플리케이션은 스크립트를 import함으로써 만들어졌지.
create-react-app을 사용한다면, ReactJS 어플리케이션을 만듦에 있어 훨씬 쉬워질 거야.
이유는, create-react-app은 엄청나게 많은 스크립트들과 많은 사전설정들을 너를 위해서 준비해주기 때문이지.


예를 들면, 네가 create-react-app을 이용해서 작업을 할 때, 즉 create-react-app을 사용해서 어플리케이션을 만들면
개발 서버에 접근or자동으로 새로고침or  즉각적으로 어플리케이션 안에 CSS를 포함시켜 준다든가 하는 기능들이 있어

그리고, 우리가 웹사이트를 publish할 준비가 되면 create-react-app은 publish하는 명령어를 갖고 있단 말이지.
코드를 압축하고, 좀 더 빠르게 만들고.


그래서 지금부터 뭘 할 거냐면, [ppx create-react-app my-app]
이 한 줄의 코드를 실행하기 위해 뭘 해야만 하는지 살펴볼 거야

 

 

 


내가 npx create-react-app 그리고 내 프로젝트 이름을 넣어서 실행시키면, 한 폴더(=프로젝트 이름)를 만들 거야.
==>npx create-react-app react-for-beginners

그럼 이제 package.json을 볼 거야. 여기 보면 실행시킬 수 있는 script들이 있는 걸 확인할 수 있어.
npm run start 아니면 뭐 그냥 npm start 그럼 development server(개발용 서버)를 만들게 될 거야.


우린 아주 멋진 페이지를 얻었지.


그래서, 이게 바로 네가 create-react-app을 사용해서 어플리케이션을 만들었을 때 초기 버전이야.

그럼 이제 src(폴더명)을 볼 수 있을 거야.

src 폴더는 네 모든 파일들을 넣을 폴더야.
중요한 건 바로 index.js야.

그리고 index.js에서는, 아주 익숙한 것들을 볼 수 있지.
ReactDOM도 있고, document.getElementById도 보이네.

 


create-react-app은 우리 어플리케이션을 가지고 여기 index.html 안에 넣어주도록
설정되어 있어. index.html은 만들어져 있지.

 

 

그리고 create-react-app을 이용하면 얻을 수 있는 장점 한 가지는  또한 Auto-Reload(자동 재실행)이야.
그래서 만약 app.js에 와서 이걸 “Hello”로 바꾸고 저장해본다면 보이지? 새로고침해보고, 그럼 여기에 “Hello”라고 뜨지.

 

#5.1 Tour of CRA 

 create-react-app하고 친해져볼 거야. 컴포넌트도 만들 거고,  props도 좀 넣어볼 거고, PropTypes도 좀 확인해볼 거야.
이전에 배웠던 것과 똑같이 할 수 있어. 하지만 create-react-app으로 하면 더 낫지.
그래서 뭘 할 거냐면, 우리는 새로운 파일을 여기에 만들 거야.
이걸 Button이라고 하자. 저번이랑 같아. Button.js    이건 function이 될 거야. 


그래서! 이제 뭘 하고 싶면, 난 PropTypes를 checking하고 싶어.
고로 우린 PropTypes를 install할 거야. 새 콘솔 창을 열고,  ==> npm i prop-types
그리고 설치되면, 우린 PropTypes를 import할 거야

 



create-react-app으로 작업할 때  우린 CSS에 관한 두 가지 선택지를 가질 수 있어.
한 가지 옵션은, 한 개의 css파일을 만드는 건데, 이건 styles.css라고 부를 거야. 
우리가 해야 할 건 말이지. index로 가서 import를 해. 알겠지.

 


css파일을 index.js에 import시키지 않아도 돼.
바로 CSS modules라는거야




Button.module.css 내에서 우린 btn이라는 클래스를 만들어 볼 거야.
알겠지. 그리고 우린 Button.module.css를 우리 index.js에 import 하지 않을 거야.
우린 그러지 않을 거야. 대신에m 이 스타일을 Button.js에 import시켜줄 거야.


이유는, 이제 내가 class이름을 내 버튼에 추가할 수 있는데
하지만 난 className을 btn 이런 식으로 쓰지 않을 거야.
CSS 코드를 작성하고 있어. 하지만 create-react-app은 이 CSS코드를 javascript 오브젝트로 변환시켜줘.
그리고 이 javascript 오브젝트는 btn을 안에 갖고 있는 거지
그래서 우리 브라우저로 다시 가보면 create-react-app은 무작위적인 랜덤 class를 갖는다는 걸.


이건 진짜 최고야. 내 생각이지만, create-react-app으로 작업 할 때 이 부분이 최고인 것 같아
심지어 네 style들도 modular가 될 수 있다는 거야. 고 동일한 class이름을, btn을, 다른 파일 내에서도 사용할 수 있어.

하지만 create-react-app은 랜덤하게 보이는 클래스 이름을 만들어낼 거지.
그리고 우리 어플리케이션을 위한 다른 CSS module도 만들어볼 수 있는데,
애플리케이션을 위한 거니까 App.module.css이라고 해볼게. 이름은 중요하지 않아.  .module.css만 붙인다면.

 


이건 훨씬 더 좋은 거야. 내내 다른 클래스 이름들을 사용하기 위해 기억하고 있어야만 하는 것보다.
이제는 다른 클래스 이름들을 기억할 필요가 없어.

왜냐면 create-react-app이 그것들을 다 랜덤하게(각기 다르게) 바꿔줄 거니까 말이지.

이제 너는 컴포넌트를 분리해서 만들 수 있고, 그 컴포넌트를 위한 CSS를 만들 수 있고,
그건 비눗방울 처럼 독립적인 형태가 될거야

다시, 만약 우리가 어떤 이유에서 같은 class이름을 사용한다면,

App.module.css에서는 title 클래스이름을 사용한다고 해보자.
그리고 또 Button.module에서도 클래스이름 title을 사용한다고 해보자.
심지어 같은 클래스이름을 사용한다고 해도, 전혀 문제 될 게 없어.


보다시피, 심지어 같은 클래스이름이라고 해도 내 HTML 내에서는, 랜덤 방식으로 생성되는 거지. 
create-react-app으로 작업하는게 얼마나 멋진 건지 보여주고 싶었어
컴포넌트들이나 스타일들을 독립적이게 유지시켜주고있지

 

#6 [2021 UPDATE] EFFECTS

 

#6.0 Introduction 



우린 useState가 반환값으로 array를 줄 거라는 걸 알아
그 array는 여기있는 value와, 두번째로  써준 modifier function이 되겠지
이번에는 state의 초기값으로 0을 줘볼게.
그러면 시작할 때 count의 값이 0가 될거야.
그리고 이게 counter를 modify하는 function이 되겠지.

자 이번에는 onClick function을 만들어보자.

이렇게 setValue를 써주면,이전 counter에 1이 더해져서 return 될거야.
onClick을 해주고, 방금 만든 function을 보내줄게.


자 이번에는 component가 render될 때 console.log를 찍어보도록 할게.
component가 처음으로 render될 때 console에 render가 찍히네.
이번에는 component의 state가 변화하고, 보다시피 다시 render가 됐어. 이건 정말 일반적이야.


우리는 계속 state를 change해 왔고, 그럴 때 마다 이 모든 것이 다시 실행되는 것에 익숙했어.
counter에 0이 아니라 새로운 값이 들어가는 것만 빼고는 똑같이 function이 다시 실행되는 거지

 

가끔은, 계속 다시 render될 때 마다 반복실행되어도 괜찮은 코드가 있을 수 있어.
component가 처음 render될 때만 코드가 실행되길 원할 수 있어.

예를들어, 네가 API를 통해 데이터를 가져올 떄 첫번째 component render에서 API를 call하고,
이후에 state가 변화할 때, 그 API에서 데이터를 또다시 가져오고 싶진 않겠지?

state가 변화할 때 너의 모든 component는 다시 실행되고, 모든 code들도 다시 실행될거야.

 

 

 

#6.1 useEffect 



그치, 우리는 코드를 딱 한번만 실행하고, 다시는 실행하지 않을 거야.
useEffect라고 불리는 function이야. useEffect는 두 개의 argument를 가지는 function이야.
첫 번째 argument는 우리가 딱 한번만 실행하고 싶은 코드가 될 거야.
두 번째 argument는 정말 마법같은 친구인데, 일단은 나를 믿고 나중에 다시 이야기 해보도록 하자.


여기에 익명의 function을 만들어 볼게 그리고 여기에 console.log로 CALL THE API라고 쓸게
여기에서 한번 CALL THE API를 하고, 계속 refresh해도 그건 반복되지 않고 있어.



#6.2 Deps 

 

좋아, 이 function은 우리의 input에 event listener로 들어갈 거야.
우리는 onChange가 발생하면 여기서 그 event를 받을거고
이 event가 text를 가지고 있겠지. 그래서 setKeyword를 다음과 같이 만들거야.   event.target.value

이제는 이 input에 value를 줘서 state와 연결될 수 있게 하자.


우리가 한 건 그냥 input을 만들고 event listener를 연결했고, 이 function이 작동할 때 argument로 event를 받을거야.
그리고 event를 발생시킨 input에서 value를 받아서, 그 value를 여기 있는 'keyword' state에 넣어줬지.
그리고 그 keyword를 가져와서, input의 value로 사용하면 우리가 원할 때 이 input를 조작할 수 있겠어.

우리가 타이핑할 때 마다 state를 modify하고 있어 왜냐면 여기에서 Keyword를 set 해주었기 때문이야.
그치? useEffect를 써야 하는 또 다른 이유를 찾았네.
만약에 누군가 글자를 타이핑할 때 마다 API를 새로 호출한다고 생각해봐. 완전 별로지.
다행히도 우리는 useEffect가 있으니까 API를 한번 만 호출할 수 있어.

그런데 이번에 하고 싶은 건, 검색이야  내가 이 검색창에 무언가를 썼을 때, 검색API를 이용하는거지.
그런데, 그렇다고 이 state를 클릭할때 마저 검색API를 호출하고싶지는 않아.


그치? 나는 search keyword에 변화가 있을 때 만! marvel영화를 검색하고 싶은거잖아.
나는 counter가 변화할 때에도 marvel 영화를 검색하고 싶지는 않아.
그런데 지금은 counter 변화시에도 검색이 되고있잖아? 이걸 원하지는 않는다구.
keyword가 변화할 때만 marvel을 검색하도록 할 거야.

 


user가 입력하는 것들은 바로 여기 들어있을거고 다시 한번, 이게 계속 반복되는 이유는 우리가 state를 변화시킬 떄마다
이 줄과, 이 줄 모두 다 실행되기 때문이야.

 네가 keyword가 변화할 때 코드를 실행하고 싶다면,  이 자리에 'keyword'라고 써줘.
여기서 하는 건, 이 'keyword'가 변화할 때 코드를 실행할 거라고 react.js에게 알려주는 거야.

 

자 이번엔, counter가 변화할 때에는 이 코드가 실행되지 않을거야.
이 코드는 keyword가 변화할 때 만 실행될거야.


이게 바로 우리가 여기에 빈 array를 써 주었을 때 코드가 단 한번만 실행되는 이유야.
여기에서는 react가 지켜볼 게 아무것도 없으니까 처음 한번만 실행되겠지

 

 

keyword가 빈 값이 아니라면, 그 때 keyword를 검색하자. 여기에 keyword.length가 5보다 길 때 라는 조건도 추가해주자.

 

 

그리고 여기에다 keyword와 counter를 같이 적어줄거야.

 

#6.4 Clean up

 



자바스크립트 쓸 때 중괄호 쓰는거 기억해야해!

 

또 보여주고 싶은건, react.js가 할 수 있는 건데 component가 destroy될 때도 코드를 실행할 수 있는거야.


우리가 create할 때는,  useEffect를 사용해. 자 이번에는 우리가 destroy할 때도 function을 하나 작동시켜보고 싶어.

이번에는, console.log에 destroyed라고도 찍어보고 싶어. 우리가 이 component를 destroy할 때 말이야.
그러기 위해서 우리가 할 것은 function을 return해주는 건데 이 function은 useEffect에서 오게 돼.

 

#7 RACTICE MOVIE APP

#7.0 To Do List part One (13:00)


자, 그럼 우선 아주 매우 엄청 간단한 to-do list를 만드는 걸로 시작해보자. 알겠지?


이제 이 버튼을 클릭했을 때 form의 submit 이벤트를 발생시키도록 할 거야
여기 form을 만들어 뒀는데, 그 form 안에 button이 하나만 있다면 그 button이 클릭 됐을 때 form을 submit 하도록 만들게.

나는 우리가 갖고 있는 이 array(toDos)를 가져가서 한가지를 더 넣고 싶어
일반적인 자바스크립트에서라면 toDos.push를 했을 거야  이건 array이니까. 맞지?
하지만 우리는 State를 직접적으로 수정할 수 없다는 걸 기억해야 해


절대 State를 직접적으로 수정하지 않아 우리는 항상 수정하는 함수를 사용하는 거지

결국 요점은 우리는 State를 직접적으로 수정하지 않는 다는 거야

 

 


우린 toDo와 toDos를 직접 수정하지 않아 우린 이런 식으로 코드를 작성하지 않을 거야
만약 네가 toDos array를 수정하고 싶다면 수정하는 함수를 사용해야만 해. 오케이?


비어있는 array야 이제 array에 element를 추가하는 방법을 보여주고 싶어


우린 element들을 가져오길 원하지 그래서 앞에 점점점을 찍어준 거야, 알겠지?
이렇게 여기도 점 세개를 찍어서 currentArray를 가져올게


이제 일어나는 일을 살펴보면
어플리케이션이 시작될 때는 비어있는 array를 가지게 될거야
우리가 첫번째 to-do를 입력할 때 여기에서 우선 비어 있는 currentArray를 받아올 텐데

이건 결국 새로운 toDos 가 input을 통해 작성한 toDo와
아무것도 들어있지 않은 비어있는 array의 element가 더해진 게 된다는 거야

 

#7.1 To Do List part Two (11:30)

 

수정하는 함수를 사용할 때 두가지 옵션이 있다는 것을 꼭 기억해야해
하나는 값을 보낼 때 이런 식으로 보낼 수 있다는거야
다른 하나는 함수를 보내는 방법이야

함수를 보낼 때 react.js는 함수의 첫번째 argument로 현재 State로 보내


그러면 우리는 이 현재 State를 계산하거나 새로운 State를 만드는데 사용할 수 있게 되지
우리가 여기서 하고 있는 건 결국 현재 toDos를 받아와서 새로운 toDo의 array로 return하고 있는거야

이 toDo는 State로부터 만들어진거고 이 toDo, 그냥 text 지. 이거에 현재 State에 들어있는 모든 요소들을 더해서
새로운 State를 계산할 수 있는거지 여기까지가 우리가 한 일이야

 

 

 

map은 하나의 array에 있는 item을 내가 원하는 무엇이든지로 바꿔주는 역할을 하고
그건 결국 새로운 array로 return 해줘

여기서 문제는 이게 좀 쓸모 없다는 거야
보다시피 기존의 item으로 접근할 수 없게 되었어

좋은 소식은 map은 함수의 첫번째 argument로 현재의 item을 가져올 수 있다는 거야

map이 6번 동작할 때 첫번째로 우리는 there을 얻을거고 두번째로는 are을 얻고 세번째로 you, 그다음 are, how, hello 


이렇게 하는 방법은 여기에 item이나 원하는 어떠한 변수명을 여기에 넣고 어떤 변수명이든 상관없이 넣을 수 있어
포인트는 map의 함수의 첫번째 argument가 진행되고 있는 순서에 맞는 item이라는거야
그리고 우리가 return하는 어떤 값이던지 간에 그 값이 새로운 array에 들어가게 되는거지
그 말은 나는 item 자체를 return할 수도 있다는 거지

 

#7.2 Coin Tracker 


이 프로젝트는 단순히 그냥 암호화폐들과 그 가격을 나열하게 될거야

이렇게 만들기 위해서 useEffect라는 것을 연습해볼 건데
내가 원하는 건, 페이지나 앱을 들어왔을 때 로딩 메세지가 보이고 코인들이 나열되면
로딩 메세지를 숨기고 코인들을 멋진 리스트로 보여주는 거야


우린 두가지 State를 만들게 될 건데 하나는 로딩을 위한 거고 또 다른 건 코인 리스트를 잠시 갖고 있기 위한 거야
우선 이건 loading이라 setLoading으로 설정해두고  useState를 사용할 건데, 기본 값으로 loading은 true일거야

 

이제 API를 가져오고 싶어 API는 coinpaprika라고 불리고
api.coinpaprika.com/v1/tickers에서 어어엄청 많은 코인을 넘겨주고 있어
그래서 component가 가장 처음으로 render되었을 때 이 함수를 즉시 실행시키고 싶어

 

useEffect를 넣어줄 거야

그러니 이제 이 URL을 fetch시켜보자

 

 

 

 

콘솔에 들어가서 네트워크에 들어가면 우린 그럼 어딘가에서 tickers를 request했다는 것을 확인할 수 있어

여기 보이는 것처럼 request가 일어났지 그리고 우리는 큰 response를 받았어
그래서 request가 일어나면 request를 받아서 우리는 200을 받았고 그렇게 우리는 response를 받았어!


이제 나는 response로 부터 이 json을 추출해내고 싶어 그래서 우리가 fetch에 추가로 해야할 것은
then을 쓰고 response를 받아서 response.json을 return해주자
그리고 then을 써서 그 json을 가지고 console.log()를 해보자

 

 

그 data를 우리의 component에서 어떻게 보여줄 수 있지?
어떻게 해야하지? 맞았어!
이 data를 State에 넣으면 되지 자 그럼 useState를 해보자

기본 값으로는 비어있는 array가 되어야 할거고data의 이름은 coins라고 하자 그리고 setCoins 이렇게
그럼 우리가 json 즉 coins를 얻었을 때 json의 값을 setCoins 해줄 거야

하지만 이와 동시에 coins 얻기를 끝냈다면 loading을 false로 바꿔줘야 해

보다시피 다른 함수를 사용해서 data를 바꿀 수 있다는건 정말 멋져

하나의 함수에서는 loading의 state를 변환하고 또 다른 하나에서 coins의 state를 바꿔줬지

 

 

 

우린 map을 사용할거야 이전에 배운 것들을 연습해볼거야 그래서 우리는 ul을 만들고
중괄호를 열고 coins.map()이라고 하자

map은 함수가 필요한데, 그 함수는 첫번째 argument로 차례에 따른 값을 가지고 그 다음에는 index, 
자 이제 값을 받아오자 우린 이걸 coin이라고 부르자, 이건 뭐라고 이름 지어도 상관 없어


그럼 이제 우리 여기에 li를 해주자 이제 우린 coin에 접근할 수 있게 되었으니
생각해봐야해 우리가 보여주고 싶은 건 뭘까?

자 첫번째로 나는 name을 보여주고 싶어그럼 여기에 coin.name을 해주자 그리고 그 뒤에 symbol을 보여줄 수 있겠지
그럼 이제 괄호를 열고 여기에 coin.symbol을 해주자 그리고 자바스크립트를 쓸 때 여기에 괄호 쳐주는 것을 잊지마
만약 변수를 사용하고 싶다면 괄호를 꼭 쳐줘야 해 만약 괄호를 안쳐준다면 이건 그냥 string이야
자 이제 우리는 symbol도 있고, 그 다음엔 price 를 말해주고 싶어 그 price 는 quotes라는 object의 USD 야
그러니까 coin


coin이라는 변수는 이 경우에서 coins array안에 있는 각각의 coin을 의미한다는 걸 기억해


여기로 와서 새로고침을 하면


이렇게 나오네!


보다시피 우리가 새로고침을 하면 로딩 중이기 때문에 코인이 0개이지만
그리고 이제 다 로딩 됐어 우린 처음에 기본값으로 비어있는 array를 넘겨주기 때문에 coin이 처음에는 0개야



우린 select를 만들어서 li가 option이 되는거지 그래서 아마 이렇게 하면..


이거 엄청 많네.. 대박이야. 미쳤어 그래 그래 음.. 너무 많다

 

 

#7.3 Movie App part One (16:13)

이 프로젝트는 영화를 보여주고 그 영화들에 대한 정보들도 조금 보여주고
거기에 링크를 넣어서 그 영화에 대해 더 많은 것을 찾아볼 수 있도록 앱에서 다른 곳으로 연결도 시켜줄거야
사용자는 클릭해서 선택한 영화에 대한 더 많은 정보를 볼 수 있는거지


알겠지? 그래서 우리는 앱 안에서 페이지를 전환하는 방법을 배울거야
지금까지는 하나의 상호작용이 있는 스크린은 만들 수 있었지만 어떻게 페이지를 전환하는지는 몰랐어


그런데 가장 첫번째로 해야할 것은 그 영화들을 다 보여주는 거야

그렇게 하기 위해서 많은 영화 정보들을 받을 수 있는 API를 가지고 왔어
나는 별점이 8.5점 이상인 영화들만 원한다고 했어 그리고 나는 연도별로 정렬하고 싶어




나는 내 component가 시작할 때만 어떠한 코드를 딱 한 번 실행시키고 싶어
그래서 useEffect를 사용할 거야

만약 웹사이트에 올라가 있는 우리 강의를 순서대로 따라오고 있다면 'then' 이라는 것을 사용하지 않았을거야
보통 요즘 좀 더 보편적으로 사용하는 게 있는데 이거 대신 async-await 를 사용해
그래서 async-await를 사용하기 위해서 여기에 getMovies라는 함수를 만들거야

이건 async 함수가 될거고 useEffect를 이용해서 getMovies를 호출할 거야 그리고 then() 을 사용하는 대신에



 React.js 앱에서 페이지를 전환하는 방법을 배워볼거야 보다시피 지금은 모든 것이 같은 스크린에서 동작하고 있잖아
어딘가로 넘어갈 수 없지 그렇지만 여기를 누르면 어딘가로 갔으면 좋겠어

 



난 여기서 React.js의 장점을 좀 활용해도 된다고 생각해 그게 뭐냐면, 바로 component를 사용할 수 있다는 거야

자 그럼 우리 Movie라는 첫번째 component를 만들어보자 이게 Movie component가 될거야
Movie component는 그냥 Movie라고 불리는 함수일 뿐이었어 그리고 우리는 export default Movie를 할거야


Movie는 기본적으로 이 모든 것들이었잖아 그래서 나는 이걸 여기서 잘라서

여기에 (route폴더 안에 있는movie)붙여 넣을거야



자 이제 우리는 React Router에 대해 배울거야
React Router가 하는 것은 내가 이전에 말한 것처럼 페이지를 전환하는 거야
여기 보이는 것처럼 우린 지금 home에 있어


예를 들어서 movies/movie.id가 붙은 페이지로 갈 수 있었으면 좋겠어
이게 내가 원하는 거야. 아주 쉽지만 우린 어떻게 해야할지 모르지
React Router를 사용해서 해볼거야  일단 npm install react-router-dom을 할건데

여기로 넘어와서 npm install react-router-dom을 해줘
자 이제 우리의 코드를 바꾸거나 이동시켜야하는데 이제 우리는 스크린 단위로 생각해야하기 때문이야
우리는 route별로 생각해봐야해  예를 들어서 하나의 route는 home, 홈스크린, 홈페이지 등등
스크린이나 페이지나 route나 부르고 싶은대로 불러도 되는데 우리는 Route별로 생각해봐야해

우리는 home route를 두고 이 곳에서 모든 영화를 보여줄거고 Movie route를 두고
그 곳에서는 영화 하나만 보여줄 예정이야 이렇게 하기 위해서 여기에 새로운 폴더를 만들건데
이 폴더를 routes라고 할게 그리고 여기에 또 다른 components라는 새 폴더를 만들어도 좋을 것 같아

자 이제 우리는 components안에 Movie를 집어넣어야 해

이제 routes안에서 Home route를 만들어 줄거야 여기에는 home이라는 함수가 있을거고
이 Home route는 기본적으로 우리의 App component 전체를 가지고 있게 될 거야
왜냐면 이제 App component는 매우매우 달라지게 될거고 바로 곧 볼 수 있을거야
App component에서 null을 return하면 페이지에서 아무것도 보지 않는다는 것을 의미하기 때문에 안 보이는게 맞고

이렇게 하는건 이제 모든 App component 코드가 Home component로 옮겨오기 때문이야


나는 그저 App.js에서 코드를 복사해서, 아니 잘라서 routes 폴더의 Home.js로 그 코드를 옮겨온 것 뿐이야
코드는 그대로 똑같아 코드에서 바뀐 점은 없고 바뀐 것은 그저 component 이름과 위치 뿐이야

이제 나는 새로운 route를 만들고 싶은데 이걸 route라고 불러도 되고 screen이라고 불러도 되고
page라고 불러도 되고, 원하는대로 부르면 돼 이건 Detail.js 를 가지고 있게 될거야
그러니 여기에 Detail이라는 함수를 만들어주자 그리고 이렇게 Detail을 return하고 싶어
그러고 나서 export defult Detail;을 해주면 돼

조금 다른 점은 여기 App.js에 있는데 App.js는 더 이상 영화들을 보여주지 않고 대신에 App.js는 router를 render해
router는 URL을 보고있는 component고 우리가 여기 있다면router는 우리에게 Home component를 보여주게 될거야
그리고 만약 우리가 이걸 movies/123 이런 식으로 바꾼다면 router는 우리에게 Detail component를 보여주게 될거야



그래서 App.js는 이제 새로운 component를 render하게 될텐데 이건 다음 영상에서 소개할게
그리고 이 새로운 component는 URL을 보고 있는거고 URL에 따라서
우리는 Home을 보여주거나 Detail을 보여주거나 할거야



 

 

#7.5 React Router (11:29)



이번 영상에서는 react-router-dom 사용법에 대해 배울거야

알겠지? react-router-dom을 사용하기 위해서는 우선 몇가지를 import 해야 해 튜토리얼에서 요것들을 복사해서

BrowserRouter를 import 해 올거야

라우터에는 두 가지 종류가 있는데
하나는 Hash Router고  다른 하나는 Browser Router야



여기에 Router 컴포넌트를 만들어줄게
그 다음에는 Switch를 사용해 Switch가 하는 일은 Route를 찾는건데 Route는 여기 이 URL을 의미해
알겠지? 그리고 Route를 찾으면 컴포넌트를 렌더링해

Route를 써줘 알겠지? 그리고 여기 Route 안에다가 컴포넌트를 써줄거야
오케이? 예를 들어서, 우리는 2개의 Route를 만들건데
하나는 유저가 홈화면으로 갈때 사용할 Route야

그럼 우리는 path="/"라고 해주면
유저가 이 경로에 있으면, 우리는 Home Route를 렌더링 해줄거야
이 Home 함수를 import 하기만 하면, 끝이야!
여기에 Home이라고 적어주고

 




우리는 여기서 Router를 만들고 그리고 그 안에 Route를 만들어줬어
그리고 누군가 우리 웹사이트의 "/" url에 있다면 우리는 Home 컴포넌트를 보여줄거야


이제 우리는 React.js 에게 url 마다 정확히 우리가 원하는걸 보여달라고 말할 수 있어


여기로 와서 Route를 열고 좋아. Route를 닫아주고
그리고 여기에 Detail을 import 해오자 h1 하나만 들어있는 이거 말이야
path는 "/movie"라고 써주자
여기로 오면, 우리는 Home 화면에 있고 Home 화면에는 Home 컴포넌트를 렌더링 하고 있어
loading이랑 기타등등을 포함하지 이제 "/movie"로 가보면 보이지? Detail이 나왔어!


우리는 알맞은 컴포넌트를 잘 import 하기만 하면 돼. 그럼 된거야!

Brower Router랑 다른 하나의 차이점에 대해 궁금할텐데 차이점은 URL의 생김새에 있어
Browser Router에서 URL은 여러분이 예상하는 대로 생겼어. 보통의 웹사이트처럼 말이야

만약 다른 Router 종류인, HashRouter를 사용한다면 여기 보이는 것처럼 조금 다르게 생겼을거야
여기 뒤에 뭔가를 덧붙여 그 다음에 /movie가 붙는거지


대부분은 Browser Router를 사용해. 뒤에 이 #를 붙이고 싶지 않으니까 말야

 


전체적으로 빠르게 복습해볼까
우리는 react-router-dom을 설치했지 react-router-dom은 아주아주 쿨한 컴포넌트들의 모음집이야

첫번째 컴포넌트는 Router였어 Router를 먼저 렌더링 해주고
그 안에 들어가는건 우리가 유저에게 보여주고 싶은 것들이야
유저가 있는 url에 따라서 말이야

여기에 Swtich 컴포넌트를 넣어준 이유는 한 번에 하나의 Route만 렌더링 하기 위해서야
알겠지? React Router에서는 네가 원한다면 두개의 Route를 한번에 렌더링할 수 있거든
우리는 한 번에 Route 하나만 렌더링 되기를 원해. 그렇지?
우리가 Switch 컴포넌트를 사용하는 이유야


그리고 나머지 여기에 있는 것들은
공식 문서의 튜토리얼을 따라했어. 아주 쉽거든

 

우리의 경우에는 url이 두 개지
하나는 home url 이고, Home 컴포넌트를 보여줘

Home 컴포넌트는 loading이랑 movies 등을 포함해서 만들었던 컴포넌트고.
그리고 누군가 /movie로 간다면 Detail 화면을 보여주지


 

 

현재는 Switch가 routes로 변경되어서 이후  코드는 실습시 변경 수정행함 !


이제 보여주고 싶은 건 한 Route에서 다른 Route로 이동하는 방법이야
유저가 영화 제목을 클릭하면 Detail 스크린으로 가게 하고 싶거든

아마 이렇게 생각하고 있을 수도 있는데
Movie.js로 가서 h2 안에다가 a 태그를 넣어서 link를 만들면 될거라고 말이야
단순 HTML이었다면 이렇게 했을거야 "/movie"로 간다고 해보자
우리가 아주 잘 알고 있는거지여기를 클릭하면 이동하게 되는거 말이야

문제는, 이게 되긴 하지만 페이지 전체가 다시 실행 된다는거야
영화 제목을 클릭하면, 화면 전체가 재실행 되는걸 볼 수 있어
우린 React.js를 사용하고 있고, 재실행하는 걸 피하고 싶어


희소식은, 정확히 이걸 위해 존재하는 컴포넌트가 있다는거야
그리고 그 컴포넌트는 Link라고 해
Link는 브라우저 새로고침 없이도 유저를 다른 페이지로 이동시켜주는 컴포넌트야
Link는 네가 원하는 곳 어디에든 사용할 수 있어
우리는 movie 컴포넌트 안에서 사용할거야
react-router-dom에서 Link를 import 해오고 a href=""를 사용하는 대신에 
Link to=""를 사용할거야


이렇게

이제 여기로 와보면 보다시피 링크가 생겼고
이걸 클릭하면 Detail 화면으로 넘어가지만

브라우저가 새로고침되지는 않아 다시 한 번 해보자
다시 보여줄게 영화 제목을 클릭하면 이동은 했는데, 새로고침 되지 안 않았어

아주아주 멋져. 이러면 되게 빠르게 반응하는 것처럼 보이거든

 


방금 한 걸 빠르게 다시 복습해보자
이전에는 App 컴포넌트가 모든 걸 다 하고 있었어
그 다음에는 App 컴포넌트에 만들었던 모든 로직을 별개의 장소로 옮겼어
Home이라는 별개의 컴포넌트로 옮겼지
Home에는 기존에 만들었던걸 복붙했어. 그렇지?

그리고 Detail 컴포넌트를 만들었지. 일단 자리를 좀 차지하고 있으라고
그리고 App.js에 있던 모든 걸 삭제하고 이걸로 대신 채워넣었어

이제 여기서 우리는 react-router-dom의 컴포넌트를 가져다 쓰고 있어
이 컴포넌트들이 하는 일은 여기 url을 바라보고 있는거야
url이 바뀌면 어떤 걸 보여줄지 결정해


제공된 Route 컴포넌트를 사용해서 유저가 "/movie" path에 있다면 Detail 컴포넌트를 보여주라고 하기만 하면 됐지
유저가 "/"(home) path에 있다면 Home 컴포넌트를 보여주라 하고 말이야


/movie 경로에 오니까 Detail 컴포넌트를 보여주고 있어
"Detail"만 딱 있지 그리고 movie로 다시 가보면, 아니 미안. home으로 가보면


home 경로로 돌아가면 Home 컴포넌트가 실행돼 Home은 모든 영화를 보여주는 컴포넌트였어



React.js가 작동하는 방식이랑 컴포넌트가 생긴 모습 때문에 Route를 만들면 그 안에 넣어준게 렌더링 되는거야

다른 Route를 만들 수도 있지 예를 들어, 여기에 Route 그리고 path="/hello"를 해줘
당연히 여기서 Route 를 닫아줘야 하고  여기에는 h1 안에 Hello를 넣어줘
이제 여러분은 이건 유저가 "/hello" 경로에 올때에만 렌더링 될거라는 걸 알지

해보자

url에 /hello라고 쓰면 이거 봐봐. Hello Route 안에 컴포넌트를 넣어주기만 하면 돼
그럼 React Router가 해당 경로일때에 그 컴포넌트를 보여줄거야



다음 영상에서는

다이나믹(동적) url을 어떻게 만드는지 알아볼거야
왜냐면 여기 이 "movie"는 아무런 정보도 넘겨주고 있지 않거든
그 대신 난 movie로 가면 movie id를 얻고 싶어 다음 영상에서 만나, 바이바이

 

#7.6 Parameters (11:54)


React Router는 다이나믹(동적) url을 지원해주기도 해 다이나믹하다는 건 url에 변수를 넣을 수 있다는 의미야


유저가 "/movie "경로로 와서 여기에 id를 적으면  Detail 을 보여주도록 할거야

유저를 "/movie/변수"의 경로로 보낼 수 있기 때문이야



자, 이렇게 해주자고. 짜잔

오케이. 이렇게 되면, Movie 컴포넌트에 id가 필요하게 되지

이렇게, 그렇지?

근데 Movie 컴포넌트에서는 props로 id를 받고 있지 않아 그 말은 Movie 컴포넌트의 부모 요소를 살펴봐야 한다는 건데
그건 바로 여기 있는 Home 이지 Home이 바로 Movie 컴포넌트를 렌더링하는 녀석이고 Home이 id를 넘겨주고 있지 않아


(위와 같이 작성)

자 이제 Movie가 prop 으로 id를 받고 있어 그렇다면 여기서 id을 넘겨받을 수 있지 그렇지? propTypes를 설정해주자


(위와 같이 작성)

이건 number 일거고 필수(required)야 이건 전부 object 였어. 기억나?

컴포넌트를 렌더링 한다는 건 실질적으로는 함수를 불러오는거였지

여기보면

우리는 Movie 함수를 호출해서

그 안에 이런 식으로 object 들을 전부 넘겨주고 있는 거야

props는 object 일 뿐이고, 우리는 그걸 열어서 item을 꺼내 쓰는 거라는 걸 기억해
이렇게 되면 url을 더 좋게 만들 수 있지


(위와 같이 작성)


자 이제 우리가 배울건 여기에 오는 id 값이 뭔지 알아내는 거야
여기에 어떤 id가 오는지 알면 이 url에 요청을 보낼 수 있기 때문이야 이 url은 id값을 요구하거든

 


그치?

그러니까 우리는 여기 오는 id가 뭔지 알아야 해

알겠지? 우린 여기에 id를 위한 자리를 마련해줬어
React Router한테 여기 오는 id값이 뭔지 알고 싶다고 말하고 있는 거야
url의 이 부분에 오는 값이 뭔지 확인하는 건 사실 아주 아주 쉬워

예를 들어서, 여기 Home으로 가보면 useState 함수를 이렇게 사용하고 있어
또 React Router에서 제공하는 함수가 있어 url에 있는 값을 반환해주는 함수야
특히, 변경되는 값을 말이야url에 있는 변수값. 아주 쉬워

우리는 useParams라는 함수를 불러오기만 하면 돼

(위와 같이 작성) 이제 이 useParams이라는 함수를 써보자
(위와 같이 작성)  뭘 반환해주는지 확인해보자

빠밤! 여기 봐봐! id를 받아왔어

다시 한번 해보자. Home으로 와서 홈 화면에서 첫번째 영화제목을 눌러볼게  뾰로롱
url에는 34015이 있고 콘솔에도 똑같은 번호가 있어

그리고 React Router는 내가 Route에 써둔 변수명을 그대로 사용하고 있어

그래서 만약 내가 여기에 chillitomato라고 쓰면 이게 바로 내가 받게 될 변수의 이름이 되는거야
그래서 여기 Detail.js에서  console.log(x)를 하면 콘솔에 parameters가 찍히고, 그게 chillitomato 지

아주 아주 간단해

우리는 React Router에 이 url이 변수를 받을거라고 말해주기만 하면 돼 그 다음엔 Detail 화면에서
useParams 라는 함수를 사용하는 거야 이 함수를 사용하면 React Router는 바로 이 변수의 값을 넘겨줘

여기에 id라고 했던걸 기억한다면 중괄호 안에 id라고 해주면 돼

API에 요청을 보내는 것만 남은 것 같아
그리고 이게 바로 우리가 공략해야 할 url 이야

앞에 이런 url이 있고, 그 담에는 movie_id, 그리고 id값이 와
그리고 useEffect를 써줄거야 (위와 같이 작성) 이 url을 공략할거고 id 부분을 이렇게 수정해줘 (위와 같이 작성)

근데 await는 async 함수 내부에 있지 않으면 사용할 수 없어
그래서 이걸 옮겨줄건데 이걸 getMovie 함수라고 해두고 여기에 function 혹은 const getMovie를 만들어주자
그리고 이걸 async 함수로 만들어줘

그럼 끝이야. 다음으로 넘어가자
이제 이걸 console.log 해보자
여기를 클릭하면 Detail 화면으로 넘어가고

여기 id가 있으니까 이 url을 공략할 수 있고
그렇다면 이 데이터는 Gintama 영화에 대한 거겠지

이거야 여기 title 이 있어, 봐봐
완벽해 실행되고 있어!

영화들이 렌더링 됐고 제목을 클릭하면 id가 있는 페이지로 가게 돼
React Router는 아주 똑똑한 녀석이라 여기서 id값을 찾아올 수 있었어
id을 알고 있으니까 API로부터 정보를 fetch 해올 수 있었지

이제 더 많은 영화 정보를 보여줄 수 있게 되었어

 


다음 영상은 우리가 만든 이 아름다운 결과물을 어떻게 github pages에 올리는지에 대한 작은 보너스 영상이 될거야
Command 하나로 말이지 다음 영상에서 만나, 바이바이

 

 

#7.7 Publishing (07:42)

이제 이 아름다운 결과물을 github pages에 deploy 할거야 이제 gh-pages라는 아주 나이스한 툴을 설치할건데

이렇게 npm i gh-pages를 해줘

알겠지? gh-pages란

결과물을 github pages에 업로드 할 수 있게 해주는 나이스한 패키지야
github pages는 github 에서 제공하는 무료 서비스인데 네가 html, css, javascript를 올리면
그걸 웹사이트로 만들어서 전세계에 무료로 배포해줘 좋은 도메인도 가지게 되고 말이야. 알겠지?

가장 먼저 해야 할건 package.json에 있는 scripts를 확인하는거야
package.json에는 build라는 script가 있어
이 script를 실행하면 우리 웹사이트의 production ready code를 생성하게 돼

"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },

production ready란 코드가 압축되고 모든게 최적화 된다는 의미야
이렇게 build를 실행시키면, npm run build 시간이 좀 걸릴거야

압축하고, 최적화하는 등 모든걸 해야 하니까 말이야
이게 실행이 되고 나면 여기 "build" 라는 폴더가 생겨. 그렇지?

아주 요상한 javascript로 가득하지
이게 바로 build 명령어를 실행하면 나오는 결과야

 


이제 이건 끝났어. 좋아

이제 이걸 GitHub Pages에 push 해야해 push 하기 전에 네가 해야할 건 package.json으로 가서
여기 마지막으로 온 다음 ,(콤마)를 먼저 찍어주고
"homepage" 라고 적어줘 그 다음에는 내가 하는 걸 따라하면 돼

"https"를 써준 다음에 첫번째로는 네 GitHub username을 써줘
그 다음에는 github.io라고 쓰는거야그리고 나서는 코드가 들어있는 github repository를 써줘

 


첫번째 단계였고 두번째 단계는
다른 script를 하나 만들어줄건데

deploy라는 거야  deploy가 하는 일은 우리가 방금 설치한 gh-pages를 실행시키고 "build"라는 디렉토리를 가져가는거야

"depoly":"gh-pages -d build",
    "predeploy": "npm run build"

여기에 "build"라고 적어줘 근데 나는 먼저 build를 하고 난 다음에 deploy를 해야 한다는걸 기억하고 싶지 않기 때문에
predeploy command 를 만들어 줄거야 그럼 내가 deploy를 실행시키면 predeploy가 자동으로 먼저 실행이 되고
predeploy는 npm run build를 실행시켜

 

이전에 만든 build폴더를 삭제하고 


그 다음에 deploy 를 실행할거야
deploy를 실행하면 Node.js가 predeploy를 먼저 실행시킬거야

그럼 한번 npm run deploy를 해보자 여기 보이는 것처럼, 먼저 predeploy가 실행되고
predeploy는 npm run build를 실행시키고 npm run build는 react-scripts build를 실행시키고

그럼 이게 아주 최적화된 것들을 만들어낼거고 그게 끝이 나면 gh-pages -d build가 실행돼

이게 하는 일은 gh-pages가 build 폴더를 여기에(  "homepage": "https://softmoca.github.io/react-for-beginners.")적어놓은 이 웹사이트에 업로드하도록 하는거야

이제 이 url(  "homepage": "https://softmoca.github.io/react-for-beginners.")을 클릭하고

조금 기다려야 해 왜냐면 이게 빨리 되진 않거든조금 걸려
웹사이트가 업데이트 된걸 보려면 5분정도 걸려. 알겠지?
그러니까 웹사이트가 보이지 않더라도 걱정하지마
조금만 기다리면 돼
알겠지? url도 아주 쉽게 생겼어


이제 우리 웹사이트를 deploy까지 했어
우리가 한건 homepage를 적어주고, script 두개를 만들어준 것 뿐이야
deploy랑 predeploy
다음에 네가 뭔가를 수정하고 업데이트를 하고 싶다면
npm run deploy만 하면 돼
그럼 자동으로 프로젝트가 build 되고
이전에 봤던 이상한 것들이 만들어지면서
그 폴더가 GitHub Pages에 push 될거야
오케이? 만약 변화가 바로 반영이 되지 않더라도
걱정하지마. Github pages 는 무료라서
업데이트하는데 시간이 좀 걸리곤 해

 

https://softmoca.github.io/react-for-beginners/

 

 

 

현재 route하는 법이 바뀌어서 위의 url로 접속해도 빈화면이 뜨지만 차차 공부하며 수정해 보고자 한다.