진짜 이제 리액트 시작 !
우리가 웹으로 유튜브를 보고 있다고 생각해보자. 이런 저런 영상들을 볼 때마다 영상과 그 영상의 설명들은 바뀌어도 최상단에 로고와 검색창이 있는 header부분과 최하단 foooter부분은 바뀌지 않는다. 근데 만약 유튜브 로고의 img가 바뀌었다고 한다면? 연결되는 모든 html파일 하나하나를 다 찾아가서 header부분 코드를 수정해야하는 상황이 생긴다.
그리고 그런 상황을 '산탄총 수술'이라고 한다.이러한 번거로움 없이 아래 사진과 같이 코드를 짜놓는다면?
모든 페이지에 중복으로 적용되는 코드 부분을 각각 하나의 컴포넌트로 만들어놓는 방법이다.
이런 방법을 "컴포넌트화 방식"이라고 하자.
절차를 하나하나 다 나열 해야하는 명령형 프로그래밍보다는
그냥 목적을 바로 말해서 쓸 수 있는 선언형 프로그래밍이 더 편리하기 때문이다.
(명령형 : jQuery)
(선언형 : React)
가상DOM을 사용해서 기존 js가 3번 업데이트 할 거를 한 번에 가능하게 해준다.
즉, 낭비되는 메모리를 효율적으로 굴릴 수 있게 해줌.
rendering과정을 생략 할 수 있음 !
그냥 리액트를 깔았다고 바로 사용할 수 있는 것이 아니라 Webpack, Babel 등등의 각종 라이브러리들을 하나하나 설치하고 세팅을 해줘야한다. 근데 이렇게까지 하는건 개오바잖아? 그래서 우리에겐 "Boiler Plate"라고 하는 패키지가 있고 이걸 사용할거다. 보일러 플레이트는 우리가 하나하나 세팅해야할 패키지들을 패키지화 시켜서 미리 틀을 다 준비해놓은 거다 !
실습을 위해 새로운 폴더를 만들고 VScode로 실행한 다음 터미널에서 명령어를 통해 새로운 리액트앱을 생성하려고 했는데 오류가 떴다 !! 시작부터 열받게 왜이럴까 싶어서 한참 쳐다보는데 멍청하게 create를 creat이라고 해놨다 ^_^
정신 차리고 다시 해보자 ㅎㅎ
이렇게 현재 열심히 설치 되고 있다. 환경에 따라 3~4분 정도 소요될 수 있다고 하니 텁텁한데 양치나 하고와야지..
자 설치가 잘 됐고, App.js에서 header태그 부분을 지운 뒤에 h2태그 하나 넣었더니 localhost:3000 (리액트앱)에서 이렇게 바로바로 잘 나타나는 걸 확인할 수 있었다.
참고로 node_modules라는 저 맨 위에 있는 폴더는 겁나 많은 양의 패키지들을 다 가지고 있다. 그래서 내가 작업한 코드들을 깃허브에 push하거나 메일로 보내거나 할 때는 빼고 보내야한다. 용량이 너무 크기에 ...
function App() {
return (
<div className="App">
<header className="App-header">
<h2>안녕 리액트</h2>
</header>
</div>
);
}
App.js 파일에서 App( )이라는 함수에 html코드를 작성하면 잘 동작한다. js랑 html이 짬뽕돼있는건데 이렇게 js 안에서 html을 쓸 수 있게 해주는게 JSX이다. 이제 JSX에대해서 좀 더 알아보자.
JSX가 결국 아까 공부했던 '컴포넌트화'방식을 가능하게 해주는 녀석이다. App( )이라는 js함수를 다른 파일에서 불러다 쓸 수 있으니까 그 안에 들어있는 html내용들을 모든 페이지 하나하나에 수정하지 않고도 App( )하나만 수정해서 다른 파일들에서 다 불러다가 쓸 수 있으니깐!
여는 태그가 있으면 닫는 태그도 반드시 있어야 함.
div나 p같은 태그들이야 html에서도 당연히 닫아줬어야 하는거지만 JSX에서 특별히 닫힌 규칙을 설명하는 이유는 img태그나 br태그 같은 애들도 그냥 쓰면 안되고 반드시 닫아줘야한다는 조금 더 엄격한 규칙이 있기 때문.
<br />
<img />
번거롭다면 이렇게 />를 바로 붙이는 self-closing tag를 사용하면 된다 .
function App() {
return (
<div className="App">
<MyHeader />
<header className="App-header">
<h2>안녕 리액트</h2>
</header>
</div>
);
}
위에서 봤던 코드를 다시 보자. 여기서 현재 최상위 태그가 되는 애는 (div className="App") 이 태그이다. 만약 이 태그가 없어지면 에러가 뜬다. JSX표현식은 반드시 하나의 부모 태그를 가져야 한다는 규칙이 있기 때문이다. 즉, JSX로 컴포넌트를 만들어서 return하려면 반드시 하나의 최상위 태그로 다른 모든 태그들을 묶어줘야 한다. 하지만 이 역시 귀찮으면 그냥 <> ~ </>이렇게 비어있는 태그로 묶어줘도 괜찮다.
가장 먼저 외우고 있어야 하는 것은 기존에 html에서 css 스타일링을 위해서 class를 만들 때는
<div class = "lion">
이렇게 썼지만 JSX에서 class는 js의 예약어라서 사용이 불가능하다. 따라서
<div className = "lion">
이렇게 사용해야 한다 !!
자그러면 해보장
.App {
background-color: black;
}
h2{
color: red;
}
#bold_text {
color: green;
}
App.css파일에 이렇게 코드를 짜면
이렇게 잘 적용되는 것을 알 수 있다.
하지만 인라인 스타일 방법을 쓸 수도 있다!
이렇게 js안에다가 짤 수 있는데 새내기 때 배운 리액트 개념 중 유일하게 기억나는 카멜표기법이 여기서 나온다 !!! 대쉬를 쓰지 않고 단어들을 붙여쓰되 대문자로 바꿔서 땡겨붙여야 함 !
< 매우 중요한 강의 >
자 숫자를 띄워놓고 +버튼을 누르면 1이 올라가고 -를 누르면 1이 내려가게 하는 기능을 구현해보자.
먼저 아래와 같이 Counter.js라는 새로운 파일을 src폴더 안에다가 만들어준다.
const Counter = () => {
return (
<div>
<h2>0</h2>
<button>+</button>
<button>-</button>
</div>
);
};
export default Counter;
return이 없으면 에러 뜨니까 return도 만들어줬고 최상위 태그가 있어야 하니까 div로 묶어주는 것 까지 잘 해줬다.
App.js에서
import React from "react";
import "./App.css";
import MyHeader from "./MyHeader";
import Counter from "./Counter";
function App() {
return (
<div>
<MyHeader />
<Counter />
</div>
);
}
export default App;
이렇게 수정해주면
여기까지는 만들어진다. 근데 +랑 - 버튼에 아무 기능을 구현하지 않았기 때문에 눌러도 변화가 없다. 이제 하나씩 만들어보자.
여기서 상태가 되는 부분은 어디일까? 바로 h2태그 속 숫자 0이다. 즉, 우리가 리액트로 만들어야하는 상태는 "0에서 출발해서 1씩 증가하고 1씩 감소하는 count 상태"라고 정의할 수 있다.
import React, { useState } from "react";
//0에서 출발
//1씩 증가하고
//1씩 감소하는
//count 상태
const Counter = () => {
const [count, setCount] = useState(0);
const onIncrease = () => {
setCount(count + 1);
};
const onDecrease = () => {
setCount(count - 1);
};
return (
<div>
<h2>{count}</h2>
<button onClick={onIncrease}>+</button>
<button onClick={onDecrease}>-</button>
</div>
);
};
export default Counter;
새로 만들었던 Count.js를 위와 같이 코드를 추가했다.
음... 대충 보면 이해할 수 있지만 신경써야 하는 부분은 onClick 이런거 카멜표기법으로 써야해서 C가 대문자라는거, onClick= 다음에 중괄호를 써서 함수를 불러온다는 거 정도가 있겠다. 리액트의 문법이다 ! 어쨌든 이렇게 코드를 구현하면
+를 누르면 1이 증가하고 -를 누르면 1이 감소하는 기능이 구현된다.
추가로 위 코드에서 만들어놓은 상태인 const[count, setCount] = useState(0) 이거를 하나의 컴포넌트로, 여러개로 사용할 수도 있다. 그래서 위에꺼는 1씩 증감, 다른거는 뭐 2씩 증감, 2배씩 증감 등등 다 구현할 수 있다. 단, 변수명이 중복되지 않게만 조절해주면 된다.
이번에는 Props라는 강의도 상태와 더불어 리액트에서 가장 중요한 개념 중 하나니까 꼼꼼히...
function App() {
return (
<div>
<MyHeader />
<Counter />
</div>
);
}
자 위에 만들었던 App.js에서 App( )함수의 코드이다. 이걸 토대로 Count.js를 구현해서 0에서부터 1씩 증감하는 기능을 만들었었는데 만약 출발이 0이 아니라 App.js로부터 지정받은 다른 값에서 출발하게 설정하려면 어떡해야할까? 여기서 쓸 수 있는 개념이 Props개념이다.
위 코드를 살짝 수정해보자
function App() {
return (
<div>
<MyHeader />
<Counter initialValue={5} />
</div>
);
}
이렇게 수정하면, 부모 컴포넌트인 App()이 자식 컴포넌트인 Counter에게 특정 이름을 붙여서 전송하는 방식이 바로 prop이다. 이게 여러개면 props가 되는 것!
근데 저렇게 코드 수정해서 전달만 한다고 초기값이 5로 바뀌지는 않는다. App.js에서 const Counter = (props) => 여기게 props를 인자로 받아와서 사용할 수 있게끔 같이 수정해줘야 된다.
이번에는 컴포넌트를 다른 컴포넌트의 prob으로 넘겨주는 연습을 해보자.
const Container = ({ children }) => {
return (
<div style={{ margin: 20, padding: 20, border: "1px solid gray" }}>
{children}
</div>
);
};
export default Container;
이 코드들을 src폴더 안에 새로운 Container.js파일을 만들어서 작성해준다. 그리고 다시 App.js로 돌아와서
import Container from "./Container";
//import해주는거 까먹지 말고
function App() {
return (
<Container>
<div>
<MyHeader />
<Counter />
</div>
</Container>
);
}
//이렇게 Container을 최상위 태그로 내용들을 감싸주면
이렇게 스타일을 입힐 수 있다.
Container태그의 자식으로 있는 저 html 즉, JSX들은 Conatiner컴포넌트에 children이라는 이름으로 prob되는 것 ! 그래서 저 children을 값처럼 활용해서 스타일을 입힐 수 있는 것이다. 와 생각보다 어려운데?
이렇게 일단 이론 강의는 다 끝 !
JS응용 부분에서 비동기식에서 한 번 어지러웠고
리액트에서 JSX로 html, css 이래저래 만지는 거에서 또 어지러웠지만
크게 빵꾸내지 않고 어느정도 이해하면서 따라오기는 했다.
다음 강의부터는 일기장 만들어보기 프로젝트 시작이니깐 실습하면서 다시 정리한 내용들 참고하면 충분히 소화할 수 있을 것 같기도... 분명 이번 섹션4,5의 강의시간은 2시간 30분도 안되는데 들으면서 블로그 정리하는데는 6시간은 걸린 것 같다.. 근데 대강대강 듣고 넘어가지 않는 이상 이거보다 빠르게는 못 할 것 같다.
아무튼 아자아자