1. State Pracitce (2)
const App = () => {
const [amount, setAmount] = React.useState();
const [flipped, setFlipped] = React.useState(false);
const onChange = (event) => {
setAmount(event.target.value);
};
const reset = () => setAmount("");
const onFlip = () => {
reset();
setFlipped((current) => !current);
};
return (
<div>
<div>
<h1>Super Converter</h1>
<label htmlFor="minutes">Minutes</label>
<input
type="number"
id="minutes"
value={flipped ? amount * 60 : amount}
onChange={onChange}
disabled={flipped}
/>
</div>
<div>
<label htmlFor="hours">Hours</label>
<input
type="number"
id="hours"
value={flipped ? amount : Math.round(amount / 60)}
onChange={onChange}
disabled={!flipped}
/>
</div>
<button onClick={reset}>Reset</button>
<button onClick={onFlip}>Flipped</button>
</div>
);
};
이번 강의에선,
단위 변환을 뒤집어보는 함수(flip function)을 만들어 볼게.
알겠지? 클릭하면 Hours를 enabled(입력 가능)하게 해주고,
반대로 Minutes 은 disabled(불가능)하게 해줄거야.
그리고 다시 한 번 클릭하면
Hours 를 disabled 해주고, Minutes 를 enabled 하게 해주는 거지.
완전 뒤집어(flip) 주는거지.
자, 그럼 또 다른 버튼을 만들어보자. 이름은 Fliped.
완벽해.
그리고 만약 이 버튼을 누른다면..onFlip 이 실행되는거지.
이해가지?
이렇게. 그런데 이 함수는 아직 만들어지지 않았어.
그러니 여기에 만들어 줄게.
(위와 같이 작성)
자, 이제 뭘 해 줄 거냐 하면, 새로운 State를 조작해줄거야.
아직 우리는 하나의 state만 가지고 있는데, 이 minute지
또 다른 하나도 만들어 줘야 해
자, 그러니 만들어 봅시다.
React.useState 를 이용해줄건데,
default 값은 false 로 설정해주고,
그리고 알다시피, state 의 결과 값은 array지.
이 array 의 첫번째 item 은 fliped 이라고 해줄게.
그리고 두 번째 item은... 데이터를 수정해주는 함수였지.
그러니 setFlipped 라고 지어줄게.
좋아.
그래서 만약 이 onFlip효과를 가진 이 버튼을 누르면
이 flipped 값을 반전시키는거지
그 말은 만약 flipped이 true상태라면, false를 반환하는거야
그리고 만약 flipped가 false상태라면, true를 반환하는거고
알겠지? 이제 setFlipped 함수를 설정해줘야해.
그리고 현재 값(flipped)의 정반대를 입력해 주면 되겠지.
이렇게.
알겠지?
자, 우리가 하고 있는 건 현재 state 를 바탕으로 새로운 state 를 계산해내는 거야.
알겠지?
만약 여기 flipped이 true라면 부정명제(!flipped)는 false 가 되겠지.
만약 flipped가 false라면, !flipped는 true가 될 거고.
하지만 전에 봤듯이.. 다음 state 의 계산을 이부분을 바탕으로 하는 건 영 좋지 못해...
대신 여기 function 을 어떻게 설정해주나면,
현재 state 값을 넣어주고, 결과는 그 반대를 도출하라고 명령해주는 거지.
몇 시간 전 강의에서 배웠는데 이렇게 써먹어보는 거야.
좋아. 이제 잘 작동하나 확인해볼게.
어이쿠, flipped 가 아니라 flip 으로 고쳐줄게.
좋아, 완벽해.
작동할거야.
console 에 뜨는 에러는 없지만 결과는 볼 수없으니...
왜냐하면 말그대로 우린 아무것도 안하고 있거든.
말 그대로 여기 state(flipped) 로 아무것도 안하고 있다구.
좋아, 이제 뭘 보여줄거냐면...
이 disabled값은, 이렇게 true값을 명시적으로 쓸수도 있어
이렇게 해주면 disabled(입력 안됨) 됐지.
아니면 false로 설정해줄 수도 있겠지.
그럼 보다시피, enabled(입력 가능) 상태가 되지.
이거 진짜 반가운 사실이야.
왜냐하면 이제 state 값으로 input 을 enabled 할지, disabled 할지를 결정할 수 있거든
예를 들어, flipped의 기본값은 false 야.
그 말은 즉, flipped 가 false 이면, 내 Hours 는 disabled되어야 한다는거지.
다시 말하면, flipped가 false라면, disabled는 true가 되어야 하는거야.
알다시피 이런걸 JSX 에서 하는 건 처음인데, 이건 일반적인 JavaScript 조건문이야.
좋아, 어디까지 했나.
방금 아주 작은 comparison 을 만들었어.
true 가 될 수 도 있고 false 가 될 수 도 있어.
그리고 JSX 의 힘 덕분에, 우린 JS 코드를 이렇게 저렇게 이용할 수 있지.
좋아.
자, 그래서 이 부분이 의미하는 건 Hours 가 disabled 된단 거야.
만약 flipped 가 false 라면. 알겠지?
그리고 (Minutes) input 도 마찬가지.
(Minutes) input 도 disabled 될거야.
만약 input 이 true 라면 말이지.
좋아, 만약 우리가 flip 버튼을 누른다면, 그 말은 즉,
이제 우린 Hours 를 사용한단 얘기가 되는거지.
그 말인 즉, Minutes 는 disabled 해준다는 거고.
자 다시 한 번,
flipped는 단순히 true 혹은 false인 변수야.
우리가 flip버튼을 누르면, onFlip 함수가 실행되는데
onFlip 함수는 현재 값을 받아서 그 반대의 값을 내놓는다는 거지.
좋아, 그게 다야.
즉, 만약 현재값이 true 면 결과로 false 를 내놓을 거고,
현재값이 false 면 결과로 true 를 내놓겠지.
이제 이 state 를 여기 가지고 있는데
우리 input 을 disabled 할 건지 enabled 할 건지 결정할 수 있어.
여기선 Hours가 disabled 된다는 걸 알 수 있지. 만약 flipped 값이 false라면.
그리고 Minutes는 disabled 될거야. 만약 flipped 값이 true라면.
알겠지?
좋아, 이제 한 번 새로고침하고 뭐가 disabled 되나 보자.
보다시피, Hours 가 disabled 되고 Minutes 가 enabled 되어 있네.
하지만 Flip 버튼을 누른다면? 뿜.
보다시피
Hours가 enabled되고, Minutes가 disabled 됐네.
아주 잘 작동하네.
멋지지 않아?
완전 멋진데?
나만 그래?
자, 이런식으로 prop을 전달하는건 처음봤지.
하지만 사실 이건 true냐 false냐로 평가하는 일반적인 JS 코드야.
만약 좀 더 짧게 쓰고 싶다면,
그냥 여긴 이렇게 flipped값과 똑같이 하면 되고
여긴 반대로 주면 되겠지
좋아, 여기도 마찬가지.
같은 방식으로 작동하지만, 더 짧지.
자, 앱에 state 두개를 쓴 건 이번이 처음이었어.
하지만 보다시피 꽤 멋져. 그리고 이해하기도 쉽지.
그냥 state 만 좀 바꿔주면 돼.
그럼 React JS 가 알아서 수정된 속성들을 불러올거야.
그래서 여기 코드를 보면...
input 확인.
완벽.
만약 flip 버튼을 누르면, 보다시피 disabled 라고 뜨고, Hours엔 아무것도 없어.
하지만 만약 다시 한 번 누르면?
보다시피, 알아서 바뀐다고.
멋지지 않아?
완전 멋지다고. 이게 React JS 가 하는 일이야.
이제 뭘 할 거냐면,
우리 Hours input의 change event를 리스닝할 거야. 알겠지?
왜냐하면 flip을 하고 enabled 된 Hours에 뭔가를 쓰려고 하잖아?
보다시피 안 써져.
알겠지?
자 그래서 뭘 해 줄 거냐면,
여기 Minutes input 에서 onChange event 를 복사해와.
그리고 Hours input 에다 붙여넣기 해.
그리고 새로고침하면 적어도 아주 조금은 고칠 수 있지.
아주 조금.
문제가 뭐냐면,
내가 Hours input 에 뭐라고 써넣든,
value는 계속 이런식으로 계산될거야.
그리고 이건 내가 원하는 게 아냐.
내가 원하는 건 변환 없이 그냥 내가 쓴 value를 보여주고 싶은거지.
이런 변환 공식은 내가 Minutes 에 썼을 때만 일어나야 해.
내가 Minutes 에 썼을 때는 단위 변환이 일어나야 해.
하지만 Hours 에 값을 입력할 때는,
그냥 입력한 값 그대로 보여줬으면 좋겠어.
Minutes input 에는 단위변환 된 값으로 보여주면서 말이지.
알겠지?
좋은 소식은 이미 공식을 가지고 있단거야.
그리고 우리에겐 flipped값도 있으니까
현재 flipped상태인지도 알수있지
그래서 이 부분을 삼항연산자(ternary operator)로 바꿔줄 건데,
if문을 인라인 형태로 작성한거라고 보면 되
뭐라고 말해줄거냐면,
만약! 우리가 flipped 상태라면(true),
이렇게 flipped...
단위 변환을 보여주지 말라고 명령하는 거야.
현재 flipped가 true라면
그냥 현재 값만 보여주라고 하는 거지.
이런식으로
만약 flipped 상태라면 state에 있는 값을 그대로 보여주는거야
만약 flipped 상태가 아니라면 변환된 값을 보여주고 말야.
근데, minutes라는 이름을 사용하고 있기 때문에 약간 헷갈리는거같애.
그래서 여기 state 를 약간 손 봐줄건데,
값 이름을 그냥 amount 라고 해줄게.
그리고 이 amount 값을 Minutes뿐 아니라 Hours에도 적용해주기 때문에
여기 함수 이름도 setMinutes가 아니라 setAmount로 바꿔줄게.
여기도 마찬가지. amount.
엇 이거말고
amount
여기도, 여기도. (위와 같이 작성)
알겠지? 이제 minutes input에도 똑같이 적용해줄게.
좋아, 만약 flipped 상태라면 (true 라면)
시를 분으로 바꾸는 공식을 적용하고 싶어.
만약 flipped 상태가 아니라면 (false 라면)
amount 를 보여주고 싶어.
좋아, 그리고 공식은 아주 쉬워.
시간 곱하기 60
그럼 다 됐어.
좋아.
보다시피, 지금 같은 장소에서 두 가지 state를 조합해서 쓰고있어
좋아, 걱정하지 마.
다음 강의에서 다 복습할 거니까.
일단 잘 작동하나 보자구.
좋아, 일단 아직 flip 되지 않은 상태고.
좋아, 이제 분에 60을 입력하면(60분) 시에는 1이 뜨지(1시간)
완벽해.
자, 이제 flip 을 해볼게.
뿜.
그리고 이제 Hours 로 와서 이만큼의 시간을 적는다면...
이게 이 시간을 분 단위로 변환했을 때의 값이야.
완벽해. 1시간에 60분.
좋아, 이제 다시 한 번 flip 해서 보면... 60분에 1시간. 완벽하네.
하지만 보다시피 문제가 하나 있는데, flip을 할 때마다 변환된 값이 바뀐다는거야.
이상함
그래서 뭘 할거냐면... onFlip 함수에다가
setFlipped 말고도 reset 함수도 실행해줄거야.
자, 여기 와서 reset 도 해줄게...
(위와 같이 작성)
좋아, 이제 다했어.
이제 Minutes 에다가 (120 입력)
그건 2시간이지.
뷰티풀.
그리고 flip을 해줄게.
뿜. 완벽해.
좋아, 이제 Hours에도 입력해 줄게. 2시간...이제 flip 해주면,
완벽해. 이제 다시 Minutes도 써주면
그리고 flip!
완벽하네. 이제 다시 Hours 에 24.
완벽해.
좋아, 이제 다 한 것 같네.
다 끝났어.
멋지지 않니? 진짜 멋져. 아냐?
좋아, 이제 다음 시간에 볼게. 다음 강의에선 지금까지 배운 걸 전부 복습할 거야.
그리고 한 가지만 더 단위 변환에 추가할 건데, 그럼 끝이야.
이제 킬로미터에서 마일로 (그리고 그 반대로) 선택할 수 있도록 해볼거야.
좋아, 예를 들어.
아니면 킬로그램에서 파운드로 단위를 바꾸던가.
좋아.
그럼 다음 강의에서 보자.
복습해보자구. 안녕~
const TimeChanger = () => {
const [time, setTime] = React.useState(0);
const [swip, setSwip] = React.useState(true);
const changeTime = (event) => {
setTime(event.target.value);
};
const flip = () => {
reset();
setSwip((current) => !current);
};
const reset = () => setTime(0);
return (
<>
<label htmlFor="hours">시</label>
<input
type="number"
id="hours"
value={swip ? time : time / 60}
onChange={changeTime}
disabled={!swip}
/>
<br />
<label htmlFor="minutes">분</label>
<input
type="number"
id="minutes"
value={swip ? time * 60 : time}
onChange={changeTime}
disabled={swip}
/>
<br />
<button onClick={reset}>초기화</button>
<button onClick={flip}>시분변경</button>
</>
);
};
const WeightChanger = () => {
const [time, setTime] = React.useState(0);
const [swip, setSwip] = React.useState(true);
const changeTime = (event) => {
setTime(event.target.value);
};
const flip = () => {
reset();
setSwip((current) => !current);
};
const reset = () => setTime(0);
return (
<>
<label htmlFor="hours">KG</label>
<input
type="number"
id="hours"
value={swip ? time : time / 60}
onChange={changeTime}
disabled={!swip}
/>
<br />
<label htmlFor="minutes">G</label>
<input
type="number"
id="minutes"
value={swip ? time * 60 : time}
onChange={changeTime}
disabled={swip}
/>
<br />
<button onClick={reset}>초기화</button>
<button onClick={flip}>시분변경</button>
</>
);
};
const App = () => {
const [optionValue, setOptionValue] = React.useState();
const changeValue = (event) => {
setOptionValue(event.target.value);
};
return (
<>
<select value={optionValue} onChange={changeValue}>
<option value="0">선택</option>
<option value="1">시간변환</option>
<option value="2">몸무게변환</option>
</select>
<br />
{optionValue === "0" ? <></> : null}
{optionValue === "1" ? <TimeChanger /> : null}
{optionValue === "2" ? <WeightChanger /> : null}
</>
);
};
const container = document.getElementById("container");
ReactDOM.render(<App />, container);
2. Props
좋아, 모두들. 이전 비디오에서,
많은 설명은 하지 않았지만 아무튼 정말 멋진 것들을 우리는 만들었어.
뭘 만들었냐면,
눈치 챘는지 모르겠지만, 우리는 이 모든 logic(논리)들을 가지고
이전에 만들었던 MunitesToHours 로직 말이지.
이 로직에 isolation과 encapsulation을 적용시켜서
이 모든 JSX를 말그대로 분리된 컴포넌트로 만들었어.
그리고 이건 굉장히 멋진 거야.
이걸 이용하면 우린 “분할”해서 “정복”할 수 있거든
이건 우리가 로직을 갖는 컴포넌트를 만들게 해주고,
많은 ui들, button들과 input 등 뭐든 갖는 컴포넌트를 만들도록 허가해주거든.
그리고 우린 이 컴포넌트를 가지고 우리는 원하는 만큼 얼마든지 이놈들을 재사용할 수도 있단 말이야.
알겠지, 정확히 이게 우리가 한 거야.
알겠지, 이게 우리를 “분할”해서 “정복”할 수 있도록 해줘.
알겠지, 잘 생각해봐. 이 index 로직, 그리고 MinutesToHours, 또 KmToMiles 로직들
이 모든게 모두 한 파일에 있다고 말이야.
과하다고 생각하지 그치?
그래서 대신에, 뭘하냐면
우리는 이 로직을 고립시켜서 분리된 컴포넌트로 만든단 말이지.
그리고 리액트로 어플리케이션을 만들어가면서 이런 식으로 컴포넌트로 만들 수 있다는 걸 계속 배우게 될 거야.
무엇이 컴포넌트가 돼야 하는지, header가 컴포넌트가 되어야 하는지 등 알게 될 거야.
footer가 컴포넌트가 되어야 하는지, 어쩌면 notification bar가 컴포넌트가 되어야 하는지.
그리고 우리는 시간이 흐름에 따라 배우게 될 거야. 이 각각의 로직들을 각각의 조각들로 분리시켜서,
다시 한번 말하지만, ReactJS의 능력으로 말이야.
그리고 이렇게 할 수 있어. 다른 자식 컴포넌트를 Rendering하는 큰 부모 컴포넌트를 가질 수 있지.
심지어 부모 컴포넌트보다 훨씬 큰 로직을 자식 컴포넌트가 갖고 있다고 하더라도 말이야.
보이지? 부모 컴포넌트는 App이야.
오직 이 로직만 갖는… HTML도 많이 갖고 있지 않아. 봐봐, 아주 적지.
하지만 MinutesToHours의 로직을 보면, HTML랑 JSX를 합쳐서, 커!
말그대로 우리는 캡슐화했어. 그리고 그건 굉장히 멋지지.
그럼 이제, 우리는 Props에 대해서 배울 거야.
Props는 일종의 방식이야. 부모 컴포넌트로부터 자식 컴포넌트에 데이터를 보낼 수 있게 해주는 방법.
현재 이 예제에서 보자면 자식 컴포넌트인 MinutesToHours 또는 KmToMiles
현재 이 예시에서, 이 두 컴포넌트들은
그다지 부모 컴포넌트(App)의 데이터를 필요로 하지 않아.
그렇지, 이 둘은 독립적으로 존재할 수 있지.
이제부터 우리가 할 것은, 한 예시를 만들 거야. 부모 컴포넌트로부터 자식 컴포넌트로 데이타를 보내는 거지
알겠지?
그래서 지금부터 할 거야.
우리는 이 모든 MinutesToHours, KmToMiles를 지울 거야. 잘 가.
오케이, 이 state도 지울 거야. 왜냐하면 새로운 걸 만들 거거든.
알겠지, 이것도 다 지우고, 마찬가지로.
완벽해.
이 부분도 지울게
좋았어, 그럼 이제 계속 해보자.
Props를 이해하기 위해서, 그리고 진정으로 이게 왜 필요한지를 보기 위해
우리는 Props로 해결이 가능하게 될 문제들을 일단 먼저 겪어봐야해
알겠지.
고로 한번 가정을 해보자. 우리가 회사에서 어플리케이션을 만들고 있다고.
물론 이 어플리케이션은 버튼을 갖고 있겠지. 꽤 많은 다양한 버튼들 말이야.
변경 사항 저장 버튼이라든가, 취소 버튼이라든가, 로그인 버튼
확인 버튼 등 뭐든 간에.
알겠지, 그런데 대부분의 회사들은 이 모든 버튼들이 같은 모습이야.
왜냐하면 그게 회사의 디자이너들이 하는 일이거든.
그들은 모든 버튼들을 똑같이 보이게끔 만들어.
하지만 우린 아직 몰라.
어떻게 리액트 컴포넌트를 재사용할 수 있게 만드는지.
만드는 방법을 모르기 때문에,
우리는 우리가 아는 방법으로 해볼 거야. 각각 버튼마다 컴포넌트를 만드는 거지.
알겠지?
그래서 우리는 function(함수)를 만들어 볼 거야. SaveBtn이라는 새로운 컴포넌트를 만들 거야.
그리고 내가 component(컴포넌트)라고 하는건, 보고 있는 대로 단지 function(함수)일 뿐이야
이게 바로 컴포넌트야.
알겠지?
그래서 컴포넌트는 단지 함수야. 어떤 JSX를 반환하는.
그뿐이야.
그게 컴포넌트야.
알겠지?
그래서 여기 버튼을 return(리턴)할 거야.
그리고 버튼, 여기에는 Save Changes라고 적자.
알겠지.
그러므로 우리는 SaveBtn을 사용할 수 있겠지. 여기로 와서, SaveBtn. 좋아.
좋았어. 그럼 이제 우린 또다른 버튼이 필요하겠지? 이건, confirm(확인) 버튼이라고 하자.
이건 ConfirmBtn이라고 하자.
그리고 다시 button을 리턴하고,
confirm.
좋아. button, 완벽해.
그리고 우리는 Render할 거야, ConfirmBtn,
Boom.
알겠지,
명심해. 우리가 하고 있는 것은 단지 이 함수들을 불러내는 거야.
이게 바로 함수를 부르는 방식이야.
좋아, 여기. 이걸 바로 함수형 컴포넌트라고 부르는 거야.
이게 컴포넌트고, 그리고 이건 JSX의 내부라고 부르는 거야.
알겠지?
그럼 이제 이쪽으로 와서, 새로고침 해보고.
두 버튼이 있지, 변경 사항 저장과 확인.
좋아, 다 좋아.
하지만 이제 디자이너가 말하겠지. 이 버튼들 진짜 구리다고.
그래서 우리가 해야 할 일은 모종의 스타일을 넣어주는 거겠지.
알겠지.
그래서 지금부터 뭘 할 거냐면, button의 style property(속성)을 사용할 거야.
그리고 ReactJS에서 만일 styles를 바꾸고 싶다 한다면, 많은 방법들이 있어.
CSS를 사용하는 방법이 있겠고, 다른 여러 라이브러리들을 사용할 수도 있겠고, 하지만
가장 기본적으로 네가 할 수 있는 방법은 그저 이 button Tag(태그) 내의 style을 변경하는 거야
알겠지, 그리고 여기에 작성할 거야. 평범한 자바스크립트 object 형식으로 쓰면 돼
(위와 같이 작성)
좋아, 그럼 이걸 최대한 예쁘게 만들어보자.
(위와 같이 작성)
테두리는 다 지워주자. 못생겼거든.
이제 내 생각에 정말 예뻐졌을 것 같은데?
Boom.
여기 내 버튼 있다.
이 아름다움을 봐봐.
오케이, 하지만 지금 보면, 문제가 좀 있어.
우리에게는 총 두 개의 버튼이 있어. 하나는 ‘확인 (버튼)’ 하나는 ‘저장 (버튼)’.
그래서 뭘 해야 하냐면, 이걸 복사해서, 여기에 붙여넣기할 거야.
그럼 지금 얘네 둘은 다 똑같게 보이지. 하지만 물론! 이건 이걸 다루는 최적의 방법이 아니야.
이러면 얼마나 멋질까?
Style을 그저 복붙하는 것 대신에, 보다 좀 더 설정이 가능한 컴포넌트
이 모종의 설정들을 넘겨 줄 수 있는 button 컴포넌트가 있다면 말이야
왜냐하면, 잘 생각해 봐. 이 컴포넌트에서 보면 단지 이 text만 다르잖아.
이런 Style들을 모두 갖는 단 한 가지의 컴포넌트만 만들 수 있다면 얼마나 좋을까?
다만 text만 변경되는 거지.
그래서 두 번이나 복붙할 필요가 없어지는 거지.
또는 세 번이나.. 만약 네가 더 많은 버튼들을 필요로 한다면 몇 번이고 복붙해야겠지.
그리고 상상해봐. 만일 누군가가 이 디자인을 변경한다면 너는 다시 되돌아가서 이 모든 버튼들을 변경해야겠지.
예를 들어서 배경색이라든가. 물론, 이건 좋은 해결법이 아니야.
우리가 해야 할 일은 우리들의 컴포넌트들을 좀 더 설정 가능하게끔 만드는 것이야.
그래서 이제부터 뭘 하냐면, 여기 컴포넌트를 지워줄 거고,
그리고 여기 이름을 바꿔 줄 거야. SaveBtn을
Btn으로.
그리고 여기에 Render해 줄 거야. 두 Btn을.
첫 번째 Btn, 그리고 두 번째 Btn.
좋아. 이제 그럼. 여기 새로고침하고, 보이지, 둘 다 똑같아.
내가 원하는 건, text(텍스트)를 설정할 수 있게 하는 거야.
이 모든 Style들을 재사용하고 싶어. 하지만 이 텍스트를 설정하고 변경하고 싶기도 하지.
알겠지.
그래서, 뭘 하냐면, 우리가 할 일은...
떠올려봐. 우리가 HTML에서 input을 어떻게 설정했지?
HTML에서 우리는 input이라고 썼지, 그치?
그리고 type. 이렇게 썼지. text
맞지, 또는 button을 어떻게 설정했더라.
button 이렇게.
그리고 onClick, 우리가 배운 대로.
그치만 이건 무척 새로운 거야
이건 JSX야.
이게 우리가 EventListener를 붙여주는 방법이었지.
오케이, 그리고 이미지.
img라고 쓰고, 여기 img 그리고 src, 맞지?
우린 매우 자주 이 syntax(구문)을 사용해 왔지
그래서 이 syntax를, 우리의 커스텀 컴포넌트에 똑같이 적용해 볼 수 있어.
이게 바로 우리가 얘네들에게 데이타를 전달시킬 수 있는 방법이 되겠어.
이게 바로 얘네들을 설정하고 또 재사용할 수 있는 방법이 되겠어.
그래서 동일한 syntax를 사용하면서, 예를 들면 이 img 태그에 정보를 전송하는 것과 같이
이제 우리는 "새로운" 정보를 이 Btn 컴포넌트에 전송할 거야.
알았지, 그리고 그건 "text"가 될 거야. 이렇게.
마음대로 이름 지어도 돼.
여긴 네 왕국이야.
이건 네 컴포넌트야.
넌 정할 수 있어.
난 "text"라는 이름을 정했어.
너는 "potato"라고 지어도 돼.
알았어?
난 "banana"라고 지을래.
알았지, 그리고 첫 번째 버튼의 banana의 value(값)은 “Save Changes”
그리고 두 번째 버튼의 banana의 value는 “Countinue”
그리고 이쪽으로 와서, 새로고침하면.
보시다시피. 당연히 아무것도 변한 게 없지.
우리는 banana를 Btn에게 보냈는데, 이 Btn은 banana를 사용하고 있지 않거든.
이번에 배워볼 건, 네가 만들고 사용하는 모든 컴포넌트들은
여기 "()" 괄호로 argument(인자)를 받는다는 거야. 리액트가 넣어주는 거지.
여기 첫 번째 argument의 이름은 마음대로 지어줄 수 있어.
사람들은 이 인자 이름을 props라고 부르지. Btn으로부터 전달 받는 properties인거지
알았지?
그러니까 여기서 이렇게 쓰는건,
결국 Btn() 함수를 불러서 banana라는 인자를 이런식으로 보내는 것과 같은거야
왜냐하면 “Btn”은 함수니까
Btn은 function이지.
알았지?
그래서 어떤 prop이든 네가 Btn 컴포넌트에 보내면
그것들은 Btn 함수의 첫 번째 argument(인자) 속으로 들어갈 거야.
props를 한 번 console.log로 찍어보자.
console.log(props)
새로고침하고, inspect(검사)를 눌러보면, 콘솔에 뜰 거야. 음.
두개의 Object가 말야
하나는 banana: “Save Changes” 또 하나는 banana: “Continue”
우리는 두 개의 console.log를 볼 수 있어. 왜냐하면 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가 있다는 사실을 알고
그래서 그냥 이렇게 할 수 있는 거지.
즉 우리의 Btn 함수 컴포넌트의 첫 번째 인자인
이 오브젝트로부터 banana를 받아내고 있는 거야.
알았지, 이걸 text로 변경해볼 수도 있고, 만일 네가 이 prop의 이름을 변경한다면
동시에 컴포넌트의 이름도 바꿔야 해. 당연하게도.
내 컴포넌트는 banana라는 이름의 prop을 기다리고 있지.
여기엔 없어. text만 있지.
그래서 우리는 banana를 text로 변경하는 걸 명심해야 해.
그럼 모든 게 잘 동작하겠지.
그리고 prop을 더 많은곳에 사용할 수도 있어.
예를 들면, 여기다가도 prop을 만들 수 있지. big이라고 적고
이런 식으로, true
좋아, 그럼 이곳에서 big
알겠지.
그럼 첫 번째 Btn의 big은 true가 될 거고, 두 번째 Btn의 big은 undefined가 되겠지.
(확인 중)
하나는 true일 거고, 다른 하나는 undefined일 거야. 나는 이걸로 좋아
네가 원한다면 big={false}라고 할 수도 있어.
그럼 이 둘은 같은 개수의 인자(또는 prop)을 갖고 있지만 그 내용은 다르지.
좋아.
그럼 이제 다른 걸 해볼 수도 있어.
예를 들면, fontSize
만약에 big이 존재한다면, fontSize는 18 아니면 16
그럼 됐어.
봐봐.
style 안에서 if else를 사용할 수 있지. prop 기반으로 말이야.
얼마나 멋져.
그럼 새로고침하고, 그럼 우리는 big 버튼하고 그냥 일반 버튼을 갖는 거지.
얼마나 멋져.
그치?
그럼 다음에 보자.
바이 바이.
3. Memo
이제 뭘 해볼 거냐면, props에 뭘 또 넣어볼 수 있는지를 볼 거야.
보았다시피, true나 false는 보낼 수 있었지.
string도 보낼 수 있었고
또한, 네가 원한다면 우린 function도 보내볼 수 있어.
알았지, 그리고 Btn을 렌더링하는 컴포넌트가 어떻게 되는지도 알아보자고.
예를 들어 이 부모 컴포넌트. 부모 컴포넌트가 state(상태)를 변경할 때 어떤 일이 일어나는지도 좀보자고
알았지. 다른 컴포넌트들에는 어떤 일이 일어날까?
아주, 아주 흥미롭지.
그래서 이 big 녀석들 좀 지워 보고.
이제 더 이상 신경 쓸 필요 없는 놈들이고, 좋아. 그리고 이 녀석들도. 바이바이.
알았지. 그리고 16이 돼야 할 거야. 아니면 뭐 노멀 사이즈.
완벽해.
그래서 뭘 할 거냐면. 내 Btn들에 onClick function을 달아주고 싶어.
알겠지.
이 onClick function은 내 App 컴포넌트에 있는 뭔가의 state를 바꾸게 될 거야.
알겠지.
좋았어.
그럼 해보자.
먼저, 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 안으로 전달되고 있는 거지.
만약 내가 onClick을 여기에다 넣는다면, 여기 HTML 요소에다가 말이지,
만일 이렇게.
이게 바로 이벤트리스너인 거지.
내가 만약 onClick을 여기 내 커스텀 컴포넌트에다가 넣는다면.
이건 이벤트리스너가 아니야.
이건 단지 하나의 prop이지.
알겠지. 이건 전혀 같지 않아. 이름이야 같을지도 모르겠지만,
실질적으로 React가 절대 이벤트리스너를 추가시키는게 아니라구
난 이곳에 이벤트를 달아야만 해.
알겠지, 이건 단지 prop의 이름일 뿐이야.
요게 그저 prop의 이름인 것 처럼 말이야
알겠지. 둘이 전혀 같지 않아.
예를 들면
나는 여기에 style을 달 수 없어. color가 green이고 뭐고.
전혀 작동하지 않을 거지.
보이지, 초록색이 없잖아.
알겠지. 왜냐, 이 상황에서 style은 결코 직접적으로 button에 달리지 않기 때문이야.
내가 prop들을 가져와서 적용을 시켜야만 하지.
알겠지.
고로 동일한 이유에서, 내가 만약 이 첫 번째 Btn을 클릭한다면,
보겠지만, 어디에도 등록된 onClick 이벤트는 없는 거야.
알겠지, 왜냐하면 다시, 이건 button으로 들어가는 무언가가 아니야.
이건 Btn 컴포넌트로 들어가는 무언가지.
이건 button 태그를 위한 이벤트리스너가 아니야.
내가 직접적으로 손수 해줘야 하지. 이쪽으로 와서, onClick을 전달 받아와서,
onClick을 설정해줘야만 해.
여기에도 onClick 이렇게.
알겠지.
그래서, 다시 한번. 네가 여기에 뭘 넣든지간에, 그것들은 단지 prop이 될 거야.
이것들은 결코 실제 HTML 태그 안에 들어가지 않을 거야.
직접 손수 해야만 하지.
알겠지.
그래서, 이걸 좀 더 이해하기 쉽게끔 하기 위해서.
난 이걸 changeValue 라고 이름 지어 볼게.
그렇다는 말은, changeValue라는 prop을 갖게 되는 거고,
button은
changeValue라는 onClick 리스너를 갖게 되는 거지.
이렇게 해보고 싶었어. 왜냐하면 난 네가
커스텀 컴포넌트의 prop으로 원하는 뭐든지 사용할 수 있다는걸 보여주고 싶었거든.
prop들은 물론 직접적으로 return문 안으로 들어가지 않지만 말이야.
네가 prop들을 넣어야 하는 거야.
알겠지?
좋아.
그럼 이제 이건 작동할 거야. 이걸 클릭해보면
보이지, “River Changes”.
굉장히 달달하지?
좋아, 멋지고.
text나 boolean 타입 말고도 더 보낼 수 있는거야.
function들도 보낼 수 있는거지.
굉장히 멋지지.
강조하는데, 이건 굉장히 명심해야 해.
뭐든 여기에 prop으로서 넣는다고 하면,
그건 절대 자동적으로 너의 return 안으로 들어가지 않을 거야
항상 여기에 있을 거야. 네가 써야만 하지.
알겠지.
그러니까 내가 만약 여기 prop 이름을 바꾼다고 한다면, onClick으로,
알겠지, 그럼 여기로 onClick으로 받고, 여기에도 onClick이라고 적고,
그렇다면 이건 당연히 작동하겠지.
왜냐하면 나는 onClick이라는 이름의 prop을 사용하고 있으니까.
또한 그 prop을 button 태그가 갖고 있는 onClick 이벤트리스너로서 사용하고 있으니까.
하지만 만약 이걸 지워 버린다면,
ReactJS는 결코 매지컬하게 이 onClick을 button에 붙여주지 않을 거야.
만약 네가 더 많은 버튼들을 갖고 있다면 어떠겠어.
div나 span을 갖는다면?
예를 들어 보면, 음, 우리에게 button이 없다고 해보자.
div가 있고 그 안에 button이 있고, 예를 들면 말이야.
그럼 onClick은 어디로 가야하겠어?
이래서 ReactJS가 너를 위해 그 어떤 결정도 하지 않는거야
너는 prop들을 네가 원하는 곳에 직접 넣어야만 하는 거지.
알겠지?
그런 고로 onClick이라고 불리는, 이벤트리스너와 완전히 동일한 이름일지라도,
이건 prop일 뿐이야.
알겠지.
좋았어. 그럼 여기에 onClick 써주고.
Here.
그럼 당연하지만 작동하겠지.
새로고침해주고,
좋았어. 작동하는군. 좋아.
한 가지 너한테 보여주고 싶은 게 있어.
그다지 중요한 건 아닌데, 하지만 알아두면 좋거든.
왜냐면 정확히 ReactJS가 뭘 하는지 우리에게 상기시켜주니까.
알겠지, 그럼 이제 뭘 할 거냐면, 이 div 좀 지우고,
좋아, 너한테 console.log를 보여줄 거야.
언제 버튼이 다시 그려지는지(render) 말이야.
그래서 여기에 text 넣어주고, “was rendered”
좋아, 새로고침 하고.
좋아, 그리고 봐봐, Save Changes was rendered, 그리고
Continue was rendered. 멋지군.
그럼 이제 이 버튼을 클릭할 건데, 어떤 일이 일어날지 이미 알잖아.
이 버튼을 클릭할 때,
이 function onClick이 불러와질(function call) 거야.
내 어플리케이션으로부터 온 onClick 함수 말이지.
이 onClick 함수가 call될 때, 이 value가 재설정되겠지. 그리고 value가 바뀔 때,
우리는 re-render를 볼건데,
알다시피 데이타를 수정하는 함수가 불려질 때 다시 그려질(re-render)될 테니까
그럼 보시다시피, 내가 여길 클릭하면, 붐. 보이지, Revert Changes was rendered.
그리고 Continue was rendered.
왜냐하면 다시, 보다시피
부모 컴포넌트는 state(상태) 변경을 겪잖아. 그리고 상태가 변경될 때
여기 있는 모든 게 새로 그려지지.
그치? 매우 명심하고 명심해야만 해. 알겠지?
사실상 우리가 방금 한 건 진짜 멋진 거야.
보다시피 우린 부모의 상태를 바꾸는 함수를 만들었고,
이놈이 이 함수를 실행하는데, 그건 자식이 실행시키지. 미쳤어.
좋아, 하지만 너한테 보여줄 게 있어.
ReactJS가 네 어플리케이션을 최적화시키는 많은 것들을 갖고 있다는 거야.
이건 기억하지 않아도 되는 거지만,
난 너한테 보여주고 싶어.
알겠지. 왜냐하면 잘 생각해보면
어떤 부분이 Btn Continue를 다시 그리는 걸까? 딱히 뭐 없잖아.
그치?
내 말은, 한 번은 이렇게 그렸잖아. 퍼펙트.
그리고 여길 클릭해보면, 보이지, 여기, was rendered. 다시 그려졌지.
왜냐면 보다시피, 이건 새로운 버튼이잖아.
Revert Changes, 새로운 버튼, 하지만 Continue는 그대로야.
그러니까 이건 다시 그려서는 안 되겠지.
알겠지. 첫 번째 놈은 다시 그려야만 해. 왜냐하면 이건 Save Changes이지만, 붐
Revert Changes가 되었거든. 고로 새로운 버튼인 거야.
하지만 두 번째 놈은, 다시 그릴 필요가 전혀 없잖아.
그치? 하지만, ReactJS의 규칙에 의해서
우리는 만약 컴포넌트가 상태를 바꾼다면 다시 render하리란 것을 알고 있잖아.
알겠지, 이 케이스에서는 보다시피, 부모가 state를 변경하고 있고
그럼 여기 있는 모든 게 다시 그려지잖아. 이 Btn과 여기 Continue 모두가 말이야. 그치?
그래서 우리가 뭘 할 수 있냐면, 바로 React Memo 라고 불리는 걸 할 수 있어.
마치 memorize(기억)하는 것처럼. 알겠지? 우린 리액트에게 말해줄 수 있어.
우리는 이 컴포넌트가 다시 그려지는 것을 원치 않는다고 말이야.
만약 props가 변경되지 않는다고 하면.
다시 한 번 말할게.
우리는 결정할 수 있어. 이 컴포넌트를 다시 그릴지 어떨지를 말이야.
prop이 변경되지 않는 한에서.
알겠지, 첫 번째 버튼의 props는 바뀔 거야.
왜냐면 첫 번째 버튼의 props는 state와 연결되어 있기 때문이지. 보다시피.
그러니까, state가 변경된다면, 물론 이것들도 변경되어야만 해.
왜냐하면 props는 바뀌고 있기 때문이지.
value가 Save Changes로부터 Revert Changes로. 매우 중요해.
하지만 이 props는, 여기는 절대 바뀌지 않아.
그래서 우리는 React에게 이렇게 말할 수 있어.
부탁이니 이 Btn의 re-render를 멈춰 달라고.
이 prop들이 바뀌지 않는다면 말이야. (첫 번째 Btn은 바뀌지만 두 번째는 바뀌지 않는다)
이 props는 바뀌지 않아.
고로 우리는 다시 그릴 필요가 없는 거지.
이걸 위해서 React Memo라고 걸 사용할 거야.
알겠지.
그럼 이제 뭘 할 거냐면, 여기있는걸로 Btn 컴포넌트를 만들 거야.
그리고, (위와 같이 작성)
MemorizedBtn = React.memo()
네가 이것들을 기억할 필요는 없어.
이걸 기억하지 않아도 돼.
나는 단지 이런 feature가 리액트에 존재한다는 걸 보여주는 거야.
알겠지.
그래서, MemorizedBtn은 바로 memorized version의 Btn이 될 거야.
알겠지, 그럼 이제 이 Btn을 MemorizedBtn으로 교체해볼게.
알겠지, 그럼 너는 차이점을 보게 될 거야.
보다시피, Save Changed was rendered.
퍼펙트.
Continuous rendered.
옙.
우리가 첫 페이지를 열 때 실행되는 거지.
하지만 이제 난 버튼을 누를 거야.
Save changes.
그리고 알다시피 내가 Save Changes를 누르면, changeValue 함수가 실행될 거고
changeValue는 state를 바꿀 거고, 그건 re-render를 발생시켜야만 해.
하지만 지금 내가 Save Changes를 클릭하면, 붐.
보이지, Continue는 다시 그려지지 않았어.
단지 새로운 버튼만 그려졌지.
알겠지, 이건 네가 차후에 사용할지 아무튼 모르는 건데
하지만 보여주고 싶었어. 왜냐하면 이건, 이걸 기억하는 건 매우 중요한 거니까, 그러니까,
만약 아빠(부모)가
어떤 state라도 변경이 있다?
모든 자식들은 다시 그려질(re-render) 거야.
그리고 이게 추후에 네 어플리케이션이 느려지는 원인이 될 수도 있어.
왜냐하면 상상해봐, 만약 네가 하나의 컴포넌트를 갖는데,
그 컴포넌트가 천 개의 컴포넌트를 그리고 있다고 말이야.
그리고 네가 아버지 컴포넌트의 state를 변경했다고 해보면,
그 말은 넌 천 개의 컴포넌트들을 다시 그리게 될 것이란 말이지.
알겠지.
이건 뭐 작은 보너스야. 우리의 컴포넌트들이 다시 그려질 때 우리가 컨트롤 할 수 있다는 걸 보여준 거.
다시.
나는 네가 조만간에 이걸 사용해야만 할 것이라고는 생각하지 않아.
하지만 나는 이걸 보여주고 싶었어. 왜냐하면 ReactJS가 어떻게 동작하는지를 보는 건 꽤나 흥미롭거든.
알겠지?
그래서 다시. 우리가 한 건 다만, ReactJS에게 제발,
만약 이 props가 변경되지 않는다면 다시 그릴 필요가 없다는 것을 말해줬을 뿐이야.
만약 props가 변한다면, 뭐, 제발 우리 Btn을 다시 그려주세요, 하고 말하고.
알겠지.
이게 내가 Save Changes를 클릭했을 때 단 한 번만 re-render되는 이유인 거야.
이 prop은 변경되었거든.
이 prop이 변했다는 말은, state가 변했었다는 말이고.
그리고 이 state는 이 prop에 연결되어 있었지.
알겠지?
좋아 모두들.
현재로서는 끝이야.
다음에 보자고.
4. Prop Types
props에 관해 이야기하는 걸 끝마칠 거야.
왜냐하면 그게 끝이니까.
더는 배울 게 없어.
이제부터 연습뿐이 있는 거야.
state에 대해서 알지, props에 대해서 알지,
이제 다음 섹션까지 쭉 갈 거야.
우린 리액트 프로젝트를 만들거고, 그건 우리가 할 수 있는 최고의 방식일 거고,
그리고 다만 계속 연습 연습 연습만 할 거야.
알겠지?
좋아.
그럼 이제 뭘할 거냐면, “Props Types”에 대해서 이야기 할 거야.
왜냐하면 컴포넌트를 다룰 때 우리가 알아야만 하는 놈들 중 마지막 놈이기 때문이지.
알다시피 props는 정말 멋진 놈이지.
맞지?
원하는 어떤 prop이든 보낼 수 있게 해주지, 우리가 하고 있는 뭐든 가능하게 해주지,
정말 멋지지. 다 컴포넌트의 환경을 우리가 원하는 만큼 설정할 수가 있기 때문이야.
text를 보낼 수 있지, boolean 타입도 보낼 수 있지, 뭐든 원하는 건 다 보낼 수 있잖아.
그치, 매우 멋져.
문제는 네가 컴포넌트들을 갖고 있는데, 그것들이 매우 많은 props를 가질 때 생기지.
때때로 넌 실수를 할지도 몰라. 또는 뭐 네 팀원이 실수를 저지를지도 모르고.
잘못된 prop을 전달한다든가 말이야
그래서 한 가지 예시를 들어볼게.
우리 Btn에 한 가지 더 configuration(설정)을 해 보자고.
알겠지, 뭘 할 거냐면, user(사용자)가 prop으로 fontSize를 전달할 수 있도록 해볼 거야.
여기 fontSize 적고, 18이라고 하자.
알겠지, 그럼 이제 여기로 fontSize를 받아 올 거야.
그리고 style에 fontSize는 fontSize라고 해줄게.
그뿐이야.
얘네는 이름이 같기 때문에, 우린 그냥 이렇게 할 수 있지.
그럼 동작할 거야.
고로 이 케이스에서는, 만약 새로고침해본다면
작동하지? 완벽해.
그러니까 우린 이 컴포넌트를 사용하고 있고, 아주아주 잘 작동하고 있지.
근데 상상해봐, 만약 네가 협업하고 있고. 팀원이 꼼꼼히 읽지 않거나 뭐 실수를 한다고 말이야
뭐 어쩌면 (prop에)전송하지 말아야 할 것들을 전송한다든가.
어쩌면 text prop에 string 타입을 보내는 대신에,
숫자를 넘겨줄 수도 있지. 이렇게.
그치? 그리고 fontSize에는 text를 보내는 실수를 할 수도 있어.
“Continue”를 보낸다든가. 이렇게.
보다시피 이건 error야.
코드 상에서는 에러가 아니지. 틀린 code는 아니야.
syntax(구문)은 괜찮아.
규칙에 어긋난 문자는 없잖아.
근데 우리가 사용하고 있는 컴포넌트 방식 내에서는 에러잖아.
그치?
그런데 만약 이런다면 굉장히 멋질 거야.
리액트가 우리한테 너는 실수를 하고 있다라고 말해준다면 말이지.
문제는 리액트는 모른다는 거야. 우리가 text에 무엇을 받고 싶어하는지를.
우리는 text가 string이 되길 원해. 그리고 fontSize는 number가 되길 원하고.
하지만 ReactJS는 이걸 몰라.
하지만 감사하게도, 이거 또한 리액트 팀으로부터 나왔는데, PropTypes라는 이름의 한 패키지가 있어.
PropType은 네가 어떤 타입의 prop을 받고 있는지를 체크해준단 말이지.
정말로 유용해. 고로 이 URL을 복사해볼게. 그리고 여기에 설치.
script:src라고 적고, 여기에 붙여넣어 볼게.
그럼 뭘 할 거냐면, 바로 ReactJS에게 우리의 prop들의 타입이 무엇인지를 알려줄 거야.
왜냐면 ReactJS는 모르기 때문이지.
하지만 우리가 PropType을 설치함으로써
현재 뭘 할 수 있냐면, 우리의 컴포넌트 이름을 가져와서, 이렇게 Btn.
여기에 넣어주고, (위와 같이 작성)
이렇게. protoType이 아니야, propTypes야.
그럼 이제 props의 타입이 뭐고 어떤 모양이어야 하는지를 우리가 설명해줄 수 있다는 거지.
알았지. 그래서 여기에 적어볼게.
text가 있었지
이걸 하기 전에, 우리가 방금 뭘 install(설치)했는지를 보여줄게.
그럼 여기 다시 시작할 거고, 새로고침.
좋아, 우리가 방금 이걸 여기에 설치했기 때문에
우린 PropTypes라고 불리는 오브젝트에 접근해볼 수 있어.
그리고 PropTypes는 각기 다른 타입들을 검사하는 게 가능해.
알겠지.
그래서 하는 방법은 내가 방금 한 것과 같아.
prop 이름과, 그 type을 쓰면 돼.
이렇게 PropTypes 그리고 .
이 상황에선 우린 이 text가 string 타입이 되기를 바라지.
그러니까 string이라고 적지.
좋아, 그럼 fontSize도 똑같이 할 거야.
prop 이름을 복사해서, 이렇게 PropTypes. 그리고 number이어야만 하지. 이렇게.
알았지.
그럼 다시 와서, 새로고침 해보면, 봐봐. 우린 최소한 경고 문구를 볼 수가 있어.
'='text는 number였지만, Btn은 string을 원한다.'
얼마나 멋져.
다시 한번 말하지만, ReactJS는 어떤 에러도 보여주고 있지 않아. 여기. ui 내에서.
왜냐하면 이 코드는 유효하니까.
알겠지, 하지만 지금 우리가 여기서 하고 있는 것은, React에게 설명하고 있는 거야.
prop들의 type이 어떻게 되는지
알겠지. 그리고 우리는 여기서 우리가 실수를 하고 있다고 깨닫는 거지.
그래서 이것들을 바꿀 수 있는 거지. 이걸 text로 바꾸고, 이건 fontSize로 바꾸고.
그럼 이제 아무 문제도 없을 거야. 이제 준비가 된 거지.
알겠지. 완벽해.
사실 우린 많은 걸 갖고 있어.
테스트를 위한 거 말이지.
여기 볼 수 있는 모든 게 우리가 테스트 할 수 있는 것들이야.
array 타입이라면, boolean이라면, function이라면, number, object, 모든 것들.
element도 테스트할 수 있고, node일 수도 있고?
컴포넌트 클래스의 instance인지도 확인해볼 수 있고,
둘 중 하나, ‘News’인지 ‘Photos’인지도 확인해볼 수 있고,
그래서 딱 이거나 저거여야지만 유효한거야, string 타입인지가 아니라 딱 이 문자나 저 문자여야지만.
보다시피 우리가 테스트할 수 있는 것들이 굉장히 많아.
그리고 봐봐, 여기 또, 문서에 보면
여기 optional이라고 적혀 있지. 기본적으로 이런 식으로 prop type을 검사할 때, 예를 들면,
이거, PropTypes.string
이건 optional(있어도 되고 없어도 됨) string이야.
만약 required(필수적)인 걸로 만들고 싶다면
이를 위한 이런 것도 있어. 여기 required.
현재 우리가 코드가, 만약 어떤 연유에서, 우리가 fontSize를 이렇게 전달하고 있지 않다면.
여기로 와서 새로고침해보면,
보다시피 아무것도 일어나지 않아.
알았지, 하지만, 만약 네가 확실히하고싶다면
정말 정말 확실히 하고싶다면
이 컴포넌트가 이 두 prop들만을 정확히 갖고 render될 것이라는 걸 확실히하고 싶다면
그럼 넌 .isRequired를 하면 돼.
그래서 지금, 언제든지 누군가가 이 Btn 컴포넌트를 render한다면
text랑 fontSize는 반드시 존재하겠지.
그래서 여기 새로고침해보면, 보이지.
'fontSize는 required(필수)라고 표시되었다 하지만 실제 값은 undefined이다.'
그래서, 잘 봤지? 아주 잘 작동해.
그래, 그래서 내 상황에서는, 예를 들면 말이야,
나는 여기 text를 required로 설정할 거야. fontSize는 아니고.
그럼 이제 준비가 된 거지.
알겠지, 그럼 이제 새로고침해보고. 끝이야.
다 좋아.
text는 필수고,
fontSize는 있든 없든 상관없어. 아주 좋아.
알겠지.
좋아. 그리고 뭘 할 수 있냐면, 우리가 원한다면
우린 어떤 default value(기본값)을 설정할 수도 있어. 이건 뭐 React로 인한 건 아니고,
환상적인 Javascript 덕분인 거지.
우리는 기본값을 설정할 수 있어.
여기로 와서 이렇게,
기본적으로 만약 fontSize가 존재하지 않는다면(undefined) 값을 주는 거야 14
예를 들면 말이지. 그럼 여기, 아무것도 변하지 않아야겠지. 왜냐면 (애초에) 14는 기본값이거든.
그치. 그럼 16
바뀌었지.
그치?
그래서 이건 단지 두 번째 Btn에만 발생할 거야. 왜냐면
fontSize가 (prop으로서) 설정되지 않았기 때문이야.
그리고 이건 React에 관한 게 아니야,
이건 단지 Javascript 문법인 거지.
이곳에서 정의되지 않은 변수에 관한 기본값을 줄 수 있어.
알겠지.
좋았어, 끝이야.
그래서, 우리가 만약 fontSize를 Continue 버튼에 전달해주지 않는다고 한다면,
기본값으로 12가 될 거야.
아니면 여기에 설정해줄 수 있겠지. 이유는, fontSize는 required(필수)가 아니기 때문이야.
만약 우리가 text를 보내지 않는다면, 버튼은 당연하지만 망가질 거야.
하지만 좋은 소식은 이렇게 이런 warning을 콘솔로 받을 수 있다는 거지.
5. Create-React-App
우리는 Create React App에 대해서 친해져 볼 거야.
create-react-app은... 리액트 어플리케이션을 만드는 최고의 방식이야.
봤다시피 우리가 이전에 만든 리액트 어플리케이션은 스크립트를 import함으로써 만들어졌지.
그리고 기본적으로 우리가 모든 걸 해야 했어. 그치?
create-react-app을 사용한다면, ReactJS 어플리케이션을 만듦에 있어 훨씬 쉬워질 거야.
이유는, create-react-app은 엄청나게 많은 스크립트들과
많은 사전설정들을 너를 위해서 준비해주기 때문이지.
앞으로 알아볼건데
예를 들면, 네가 create-react-app을 이용해서 작업을 할 때,
즉 create-react-app을 사용해서 어플리케이션을 만들면
개발 서버에 접근한다든가, 자동으로 새로고침을 시켜준다든가,
즉각적으로 어플리케이션 안에 CSS를 포함시켜 준다든가 하는 기능들이 있어
진짜, 진짜 멋지지.
create-react-app으로 뭘 할 지 너한테 보여주고 싶어 미치겠어!
알겠지.
그리고, 우리가 웹사이트를 publish할 준비가 되면
create-react-app은 publish하는 명령어를 갖고 있단 말이지.
코드를 압축하고, 좀 더 빠르게 만들고.
그냥 진짜 멋진 녀석이야
다들 리액트 어플리케이션을 만들어야 할 때 이걸 사용한단 말이지.
그래서 지금부터 뭘 할 거냐면,
이 한 줄의 코드를 실행하기 위해 뭘 해야만 하는지 살펴볼 거야.
네가 해야 할 것은, nodejs를 설치해놓는 것이지.
그래서 nodejs.org에 가보면
대부분의 사용자들을 위한 추천 버전에서 네 os에 맞는 nodejs를 다운받아야 할 거야.
설치하고, 그 후에 콘솔을 확인 해봐.
node -v 커맨드가 있는지
만약 네 콘솔에서 이게 된다면, 그럼 준비가 된 거야.
알겠지, nodejs를 다운로드하고, nodejs를 설치하고, 그리고 이 커맨드를 네 콘솔창에 실행해봐.
만약 아무런 문제 없이 작동한다면.
그럼 계속 진행할 수 있어.
그리고 또한 nodejs를 설치한 다음에, 이게 되는지도 확인해야만 해.
npx install
알겠지. 만약 이 npx 커맨드를 작동시킬 수 있다면, 그럼 준비가 된 거야.
알겠지. 난 npx 커맨드를 작동시킬 수 있어.
그러므로 난 준비가 된 거야.
네가 node -v 그리고 npx 커맨드를 실행시킬 수 있는지 확실히 확인해봐.
그래서, 현재 우리의 Documents 폴더에서, 또는 네가 원하는 아무 폴더에서
우린 새로운 프로젝트를 만들 거야.
이전에 만들었던 폴더랑 같은 이름의 프로젝트가 될 것이기 때문에
지금까지 만들었던 모든 걸 다 지워야만 했어.
react-for-beginners 폴더는 지웠어. 사라졌지.
내가 npx create-react-app 그리고 내 프로젝트 이름을 넣어서 실행시키면,
한 폴더(=프로젝트 이름)를 만들 거야.
고로 확실히 해. 네가 만들 폴더가 존재하지 않게 말이야.
알겠지.
좋았어.
그래서, npx create-react-app 그런 다음에 네 어플리케이션 이름을 적을 거야.
내 거랑 같은 필요는 없어.
네가 원하는 아무거나 적어도 돼.
내 입장에서는, react-for-beginners라고 할 거야.
알겠지? 엔터.
지금, 보다시피, load가 될 거고, 이것저것 install할 거고
그럼 우리가 해야 할 건 그저 끝나기를 기다리는 거지.
거의 끝나가네.
그럼 끝났을 때, 우린 새로 만들어진 폴더를 열 거야. vscode에서 말이지.
그럼 지금 이게 끝나면, vscode를 열고
우린 package.json을 확인할 거야.
네가 nodejs가 뭔지 안다면
package.json 안에서 모든 스크립트들을 찾아낼 수 있다는 것을 알 거야.
nodejs가 뭔지 모른다고 해도 괜찮아. 걱정 마.
그저 내 손가락만 따라 와. 그럼 계속 진행할 수 있을거야. 알겠지.
그럼 react-for-beginners를 열어보자
(code react-for-beginners 입력)
알겠지?
우리 vscode에서 말이지.
완벽해.
이 파일은 지울 거고.
넌 이 파일이 없을 수도 있어.
걱정하지 말고.
그럼 이제 package.json을 볼 거야.
여기 보면 실행시킬 수 있는 script들이 있는 걸 확인할 수 있어.
알겠지. 다시. 이것들은 create-react-app 팀에 의해 만들어진 것들이야.
알겠지. 우린, 여기 start 스크립트를 실행해볼 거야.
좋아, 실행해보자. 여기로 와서,
npm run start 아니면 뭐 그냥 npm start
알겠지?
그럼 development server(개발용 서버)를 만들게 될 거야.
보고 있다 시피, 자동적으로 브라우저가 열리고 있지? 난 아무것도 하지 않았어.
그리고, 봐봐.
붐.
우린 아주 멋진 페이지를 얻었지.
알겠지?
이 얼마나 멋져.
그래서, 이게 바로 네가 create-react-app을 사용해서 어플리케이션을 만들었을 때 초기 버전이야.
그럼 이제 src(폴더명)을 볼 수 있을 거야.
src 폴더는 네 모든 파일들을 넣을 폴더야.
알겠지, 모든 게 다 src 폴더 안에 있어야 해.
src 폴더는 많은 것들을 갖고 있어.
하지만 무엇보다도 중요한 건 바로 index.js야.
그리고 index.js에서는, 아주 익숙한 것들을 볼 수 있지.
ReactDOM도 있고, document.getElementById도 보이네.
create-react-app은 우리 어플리케이션을 가지고 여기 index.html 안에 넣어주도록
설정되어 있어. index.html은 만들어져 있지.
그리고 여기 보이지,
root가 있어. 우리가 저번에 했었던 거잖아.
얼마나 멋져?
이번엔 우리가 손수 할 필요가 없어. 이제는 이미 설정되어 있는 거지.
src 안에 있는 우리 코드를 가져다가 이 페이지의 어딘가로 넣어줄 거란 말이야.
알겠지, 고로 직접하지 않아도 돼.
얘네가 자동으로 해주는 거지. 쩔어.
알겠지.
예를들어, 여기 코드를 살펴보자. inspect 탭을 봐봐.
우리가 봤던 것들에 플러스로,
보이지, 어떤 코드들, static/js.. 들이 추가됐어.
볼 수 있다시피 얘네 셋은 실제로 여기 index.html 내에 존재하지 않아.
그치?
우리를 위해서 넣어진 것들이야. 참 달달하지.
그리고 create-react-app을 이용하면 얻을 수 있는 장점 한 가지는
또한 Auto-Reload(자동 재실행)이야.
그래서 예를 들면, 만약 우리 app.js로 가본다면, 보다시피 여기,
이 코드 한 줄이 있잖아.
그래서 만약 app.js에 와서 이걸 “Hello”로 바꾸고 저장해본다면
보이지? 새로고침해보고, 그럼 여기에 “Hello”라고 뜨지.
봤지? 이건 진짜, 진짜 유용한 기능이야.
알겠지.
우리가 모르는 것들은 제쳐두고, 예를 들면, 이거. 차후에 얘기해볼 거고,
대부분의 것들은 다 거기서 거기야.
여기 보다시피, ReactDOM을 import하고, render.
이게 ReactDOM을 import하는 방법이야, 여기. 그리고 .render
그리고 이전에 했던 거 똑같이 해주고 있고.
컴포넌트를 하나, getElementById 안에 렌더링해주고 있고.
그래서 거기서 거기지.
그리고 이제 App 안을 본다면,
보이지, 여기. App은 단지 함수 컴포넌트야. 간단하지?
그리고 약간의 jsx가 이 안에 있어.
그뿐이야. 끝.
알겠지, 그렇게 이상한 거 하나 없어. 뭐, 우리가 지워야 할 몇몇 기본 코드들만 있을 뿐이야.
보다시피 이건 설정된 CSS나 뭐 기타 등등으로부터 온 거야. 우린 다 지울 거야.
바닥부터 새롭게 시작하고 싶거든.
그리고 감당할 수 없는 것들, 테스팅이라든가, 그런 건 하고 싶지 않아.
그래서 필요 없는 것들을 지워 줄 거야.
알겠지.
난 다 지울 거야, 여기 index.js에서. 이것만 남을 때까지.
그래서 네 index.js에서 뭘 보든 간에 다 지워 줘.
우리가 원하는 건 이 세 import들과 ReactDOM.render야.
알겠지.
난 우리가 이전에 더 힘든 방식을 먼저 해봤다는게 정말 좋아
왜냐면 이제는 이게 뭔지 이해할 수 있잖아. 알겠지.
그리고 App.js에서도 필요없는걸 지워볼게
App.js에서
CSS를 지울 거야, 그리고 logo도 지우고, 완벽해.
그리고 div를 반환할 거야. 안에, h1 넣어주고.
(위와 같이 작성)
보이지? 이건 단지 컴포넌트야. 하지만 지금, 네가 nodejs로 작업하고 있기 때문에
파일들을 각각 분리시키는 게 가능하고,
좀 더 조직적으로 구성할 수 있게 됐지.
우리는 한 파일당 한 컴포넌트를 가지고있고, index.js에서 그 컴포넌트를 import시켰어
즉, 차후에 버튼과 같은 다른 컴포넌트도 한개의 파일로 이루어질거라는 걸 의미하지.
그래서 보다시피 create-react-app은 꽤 많은 기본 파일들이 딸려 있어.
그래서 우린 얘네들을 지워줄 거야. 이거 지울 거고, 이것도....
App.test.js, App.css, index.css, logo.svg
reportWebVitals.js, setupTests.js
그래서 이것들 다, 지워버릴거야
index.js랑 App.js만 남길게
그게 다야.
좋아, 그래서 이거 다 지울 거고.
옙, 휴지통으로.
뿜!
결국 우린 깔끔한 create-react-app의 설치판을 얻었어.
여기 우리 리액트 어플리케이션을 랜더링해줄 뿐인 index랑
Welcome back!을 랜더링해줄 뿐인 우리의 App.
우리가 create-react-app을 사용하고 있기 때문에
나는 예상하는데, 새로고침해보면
보이지, Welcome back. 좋아.
만약 여기를 이렇게 바꾸면.
얍.
완벽하게 잘 작동하는구만.
좋아. 그럼 우린 끝냈어.
우린 React App을 만들었어.
봤지. 엄청, 엄청 사용하기 편해.
우리가 해야 할 일은, 어플리케이션을 만들고 npm start를 실행하는 거야.
build는 나중에 살펴볼 거야.
알겠지?
지금은, npm start를 실행하기만 하고, 어플리케이션을 깔끔하게 정리해.
알겠지. 네 App 컴포넌트를 이렇게 만들고
index.js도 이렇게 만들고.
6. Tour of CRA
우린 create-react-app하고 친해져볼 거야. 컴포넌트도 만들 거고,
props도 좀 넣어볼 거고, PropTypes도 좀 확인해볼 거야.
이전에 배웠던 것과 똑같이 할 수 있어. 하지만 create-react-app으로 하면 더 낫지.
그래서 뭘 할 거냐면, 우리는 새로운 파일을 여기에 만들 거야.
이걸 Button이라고 하자. 저번이랑 같아.
Button.js
알겠지.
이건 function이 될 거야. 여기.
function Button, 이전과 같이. 그래서 여기 Button,
좋아, 어떤 props를 가질 거야. 알지, text가 될 거야.
좋아, 그리고 button을 여기에 반환할 거야. text랑 같이 이렇게.
아주 쉽지.
이전에 다 했던 거야.
이제, export default button을 해줄 거야.
왜냐면 우리의 App.js에서 Button을 가져올 수 있게 하고 싶거든.
고로 여기 App.js에서 import를 할 거야.
(위와 같이 작성)
알겠지?
이제 Button을 사용할 거야. 여기로 와서,
그런데 사용하기 전에,
우리 콘솔을 살펴 보면 말이야. npm start를 실행시키면 어떤 경고문이 뜰거야.
보다시피, “Button은 정의되었지만 그러나 전혀 사용되지 않았다.”
이건 create-react-app이 주는 일종의 도움이야.
Create-react-app은 우리에게 이런 것들을 이야기해 줄 거야.
아주 좋지. 왜냐면 우리의 코드를 좀 더 낫게 해주거든.
알겠지, 어쨌든 우린 Button을 사용해볼게
이, 이 경고는 우리가 Button을 import했지만 사용하지 않았기 때문에 발생한 거야, 물론.
알겠지. 고로 해야 할 건, 여기로 와서.
Button 이렇게, 그럼 다 된 거지.
보다시피! React 동작 방식에서 그 무엇도 다를 게 없어.
알겠지.
단지 설치 할 때만 달랐지.
알겠지.
그 외에는 다 같아.
이건 컴포넌트를 렌더링하는 법이고.
이건 props를 사용하는 법, 전부 다 같아.
하지만 보면 말이지, 이제 우린 여러 파일들을 가질 수 있게 됐어.
우리의 코드를 좀 더, "답답해", 하지 않게 만들어주는.
좋아. 그럼 text를 prop으로서 전달해보자. 알겠지만, vscode에는 이런 기능이 있지
여기 보이지.
우리에게 필요할 것 같은 prop을 확인할 수 있게 해줘.
다시, create-react-app으로 작업함에 있어 전반적인 요점은
보다시피, 개발 환경이 훠얼씬 낫다는 거야. 만약 이렇게 마우스를 Button 위에 올려놓는다면
Button은 text prop을 필요로 한다는 것을 알 수 있지.
다시 강조하지만 이건 매우매우 유용한 기능이야
알겠지?
고로 여기에 text를 넣을 거야, I'm a Button... 아니면 그냥 "Continue" 끝.
그리고 보다시피 이미 새로고침돼 있지,
썩 잘 작동하지?
그래서! 이제 뭘 하고 싶면, 난 PropTypes를 checking하고 싶어.
알겠지.
고로 우린 PropTypes를 install할 거야. 새 콘솔 창을 열고,
(위와 같이 작성)
우린 install이 다 될 때까지 기다릴 거야. 오래 걸리진 않을 거야.
그리고 설치되면, 우린 PropTypes를 import할 거야. prop-types로부터.
(위와 같이 작성)
알겠지, 그럼 끝이야.
그럼 이제 해야 할 건, PropTypes를 사용하는 거야.
이전에 했던 것과 동일하게 Button.propTypes
Button에는 text가 필요하다고 할게
보다시피 전에 했던 것과 같은 코드야. 단지 setup(설치 및 초기 설정) 때만 다르지.
(위와 같이 작성)
그리고 string. 보이지?
vscode가 우리를 돕고 있어.
우리가 여기에 PropTypes를 쓸 수 있어서
모든 옵션들을 볼 수 있지. function, 또는 array가 될 수 도 있고. boolean,
많은 옵션들이 있어.
알겠지. 이건 우리를 돕고 있지. 이전보다 확연히 더!
고로 여기에 string을 적고, isRequired를 넣 수 있어. 아주 나이스한 자동완성기능으로 말이야.
알겠지, 이게 전체적인, create-react-app으로 작업할 때의 중요 포인트야.
코드는 같고, PropType도 같고.
그리고 props를 받아내는 방법도 똑같아. 하지만 이번엔
서로 다른 파일들로 코드를 분할하는 등의 작업도 할 수 있게됐어
알겠지, 그리고 또한. 내가 보여주고 싶은 건.
특정 컴포넌트를 위한 CSS파일을 만들 수 있는 기능을 얻었다는 거야.
굉장히 좋은 일이야
create-react-app으로 작업할 때
우린 CSS에 관한 두 가지 선택지를 가질 수 있어.
한 가지 옵션은, 한 개의 css파일을 만드는 건데,
이건 styles.css라고 부를 거야.
좋아, 그래서 이 styles.css에서는
음 button을 넣을 거야. 이렇게.
(위와 같이 작성)
그래. 이건 평범한 CSS야.
알겠지. 만약 네가 이 CSS를 사용하고 싶다면,
우리가 해야 할 건 말이지. index로 가서 import를 해. 알겠지.
(위와 같이 작성)
그뿐이야.
알겠지, 그래서 내가 styles.css를 import했을 때.
새로고침하고. 보다시피.
이제 버튼은 토마토색이 됐지?
알겠지, 이것도 괜찮아.
내 말은, 보다시피 이 방법은 이미 아주 편해.
진짜 간단하지.
보다시피, 우리가 해야 할 건 단지 CSS를 작성하는 것뿐이고
그걸 import해서, CSS가 작동해야 할 것들을 작동시키는 거지.
모든 버튼들은 토마토색 배경을 갖게될거야
하지만 또한, 우리가 만약 원한다면.
css파일을 index.js에 import시키지 않아도 돼.
왜냐면 만약에, 예를 들면 말이지.
여기 또 다른 버튼을 추가할 수도 있을거야
그리고 이 새로운 버튼의 배경색으로는 tomato를 원하지 않는 거지.
알겠지?
버튼이 페이지 안에 있어도
파란색으로 설정 할 수도 있고, 어찌됐든 간에.
고로 우린 styles.css 를 사용하지 않을 거야.
왜냐면 봤다시피 styles.css는 모든 버튼들의 배경색을 토마토색으로 만들어버릴 거거든.
고로 styles.css는 삭제해버릴 거고.
다른 옵션으로 우리가 이전에 시도해봤던 또다른 방식이 있지
style prop을 사용했던 거 말이야.
한 번 더 말하지만, 우리가 create-react-app 내에 있기 때문에
나이스한 자동완성기능을 가질 수 있지.
이렇게 background라고 치면, 보일 거야, 우리가 전부 입력하기도 전에
모든 옵션이 이렇게 보여
오타를 낼 수도 있지만 우린 자동완성기능을 쓰지.
BackgroundColor: “tomato” 그리고 color: “white”. 이렇게.
하지만 보다시피, 우린 CSS의 힘을 잃었어.
이건 아주 좋아.
우린 잃었어. 그리고 돌아가야 하지. javascript 코드를 작성해야해.
HTML을 본다면 그건 여기에 있을 거야.
style은 여기에 있지. 알겠지?
그래서 뭘 할 수 있냐면, 만약 우리가 global(전역적인) CSS style을 원하지 않는다면
왜냐하면 생각해봐. 엄청나게 많은 코드가 있을 거야.
네 어플리케이션을 위한 엄청나게 많은 CSS가 단 한 파일에 있겠지
미친 거지
그래서 우린 그런 짓은 하지 않을 거야.
하지만 이렇게 style을 직접적으로 넣고 싶지도 않아.
우린 CSS를 쓸 수 있었으면 하지.
하지만 CSS를 import할 때,
CSS 파일이 적용하려는 파일의 모~든 부분에 import되는 걸 원하지는 않아
알겠지. 여기서는 그게 발생하고 있잖아.
만약 index.js에 CSS를 import한다면
이 CSS파일은 페이지의 모든 것들에 적용되고 말 거야.
알겠지? create-react-app으로 작업할 때의 포인트는 “분할하고” “정복하는” 거야.
이게 우리가 create-react-app을 배울 때 진짜 멋진 점인데,
바로 CSS modules라는거야
그래서 이제 뭘 할 거냐면, styles의 이름을 바꿔 볼 거고, 이 이름은 Button이야.
Button.module.css 이렇게.
Button.module.css 내에서 우린 btn이라는 클래스를 만들어 볼 거야.
알겠지. 그리고 우린 Button.module.css를 우리 index.js에 import 하지 않을 거야.
우린 그러지 않을 거야. 대신에
이 스타일을 Button.js에 import시켜줄 거야.
고로 이건 지워버릴 거야. 이렇게.
그리고 스타일들을 import시킬 건데 이렇게,
(위와 같이 작성)
이건 진짜 멋진 거야.
이유는, 이제 내가 class이름을 내 버튼에 추가할 수 있는데
하지만 난 className을 btn 이런 식으로 쓰지 않을 거야.
절대.
나는 styles
styles.
그리고 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이라고 해볼게. 이름은 중요하지 않아.
App이 될 수도 있고
xx가 될 수도 있어.
뭐든 될 수 있어. .module.css만 붙인다면.
알겠지.
고로 이제 우린 class이름을 만들 건데, 여기 타이틀을 위한 거지.
알겠지, 그래서 여기 .title
font-family를 추가하고, 그리고... 이걸로 하자. 평범한 거.
완벽해. 그리고 font-size는, 18px
보다시피 우린 지금 css코드를 작성하고 있는 거야.
css를 Javascript 오브젝트 형식으로 쓰는 것보다 훨씬 낫지
그리고 App.js에 이전에 했던 걸 그대로 해줄 거야.
import 해주고. (위와 같이 작성)
App.module.css
그리고 여기에 우리가 h1에 style을 입히고 싶을 때, className을 적어주면 돼.
(위와 같이 작성)
그리고 같은 이름. title.
알겠지. 여기에 넣어.
아름다워.
그럼 여기로 와서, 새로고침하고.
h1을 봐보자. 보이지, h1은 현재 자기만의 스타일을 갖고 있어. 그리고 class name을 가지지.
보다시피
이건 훨씬 더 좋은 거야. 내내 다른 클래스 이름들을 사용하기 위해 기억하고 있어야만 하는 것보다.
이제는 다른 클래스 이름들을 기억할 필요가 없어.
왜냐면 create-react-app이 그것들을 다 랜덤하게(각기 다르게) 바꿔줄 거니까 말이지.
진짜 멋지지.
이제 너는 컴포넌트를 분리해서 만들 수 있고,
그 컴포넌트를 위한 CSS를 만들 수 있고,
그건 비눗방울 처럼 독립적인 형태가 될거야
진짜, 진짜 멋지지.
다시, 만약 우리가 어떤 이유에서 같은 class이름을 사용한다면,
App.module.css에서는 title 클래스이름을 사용한다고 해보자.
그리고 또 Button.module에서도 클래스이름 title을 사용한다고 해보자.
심지어 같은 클래스이름을 사용한다고 해도, 전혀 문제 될 게 없어.
알겠지.
여기에 사용해보자. title.
이건 랜덤하게 될 거야.
보다시피, 심지어 같은 클래스이름이라고 해도
내 HTML 내에서는, 랜덤 방식으로 생성되는 거지. 진짜 진짜 미쳤어.
알겠지.
좋았어. 이번 영상은 이걸로 끝이고
create-react-app으로 작업하는게 얼마나 멋진 건지 보여주고 싶었어
보다시피 이건 개발자들에게 있어서 정말 큰, 커다란 도움을 주고있어
컴포넌트들이나 스타일들을 독립적이게 유지시켜주고있지
네게 create-react-app을 보여줄 수 있어서 정말 좋아.
너도 좋아했길 바래
이제 create-react-app에 대해서 말하는 건 그만두고
이 코스의 다음 섹션으로 넘어가서,
약속할게, ReactJS의 마지막 커다란 컨셉 하나를 배울 거야.
알겠지.
마지막 한 놈. 우린 연습할 거야.
우린 암호화폐 어플리케이션을 만들 거야.
암호화폐 가격을 가져와서 사람들에게 보여줄 거야.
그러려면, 컴포넌트의 마지막 한 조각을 배워야만 해.
우린 state를
어떻게 사용하는지 알지,
props도 알고. 다음 영상에서
우린 effect에 대해서 알아볼 거야.
https://github.com/Daniel-Jeon/for-react/commit/fabaa0924d2919c32fe5af7900bec662fa3e7333