리액트란? 페이스북에서 만든 UI를 그리기 위한 자바스크립트 라이브러리
특징
1.선언적이다.
2.가상돔을 이용해서 ui를 바꾸는 기술을 사용한다.
컴포넌트 = 재사용가능하고 독립적으로 움직일 수 있는 하나의 모듈
이렇게 말하면 범위가 너무 광범위하니 프론트 엔드에서는 재사용가능한 ui단위라고 인식하면 된다.
JSX(자바스크립트 확장문법)
자바스크립안에서 html을 쓸 수 있도록 하기 위해서 쓰는 것
프레임워크 라이브러리 차이
공통점: 남이 만들어놓은 코드
프레임워크: 남이 만들어놓은 것이 완벽히 틀(프레임)이 잡히있는 것. 작업자가 거기에 들어가서
거기에 짜진 프레임대로 거기서 제공해주는 도구대로 쓰는게 프레임워크
라이브러리: 조금더 가벼운 애. 하나의 도구정도로 보면 된다. 내가 가져다가 쓸 수 있는 것. 내가 내 프로그램을 만들건데 애를 가져와서 쓸거야 라는 것이다.
라면을 끓인다고 했을 때 프레임워크는 신라면 한 봉지 주고 주방까지 다 제공 칼,후라이팬,냄비,도마,가스레인지 다 제공
그 주방안에 들어가서 걔네가 제공해주는 도구대로 라면을 끓이는 것.
근데 그렇게하면 걔네가 제공해주는 칼, 가스레인지만 써야하기 때문에 다른걸로 바꿀 수 없다.
걔네가 제공해주는 가스레인지의 사용법도 알아야하니까 배우는 난이도가 더 높다.
라이브러리는 그냥 신라면 한 봉지 주는 것(그냥 도구 하나 주는 것)이다.
그러면 가스레인지를 쓸 수도 있고 버너를 쓸 수도 있고
칼도 쓰고 싶은거 쓸 수 있다.
라면하나만 가져오고 나머지는 내가 선택해서 쓸 수 있는 것.
프레임워크는 그 틀 안에서만 움직여야 함
리액트는 ui그리는 것만 제공해주는 라이브러리이다.
그외 나머지 기능들은 내가 원하는 또다른 라이브러리들을 긁어와서 내가 만들 수 있다.
"지속적으로 데이터가 변화하는 대규모 애플리케이션을 구축하는 것"
-> 페이스북을 보면 좋아요도 계속 누르고, 팔로우도 계속 늘고 지속적으로 유저에 대한 데이터가가 변하고 있고 페이스북에서
관리하는 데이터도 변하고 있다. 그걸 실시간으로 ui에 반영을 해줘야 한다. 그걸 목표로 해서 만든 라이브러리가 리액트
앵귤러나 뷰같은 경우는 MVC가 들어있다. 데이터 그리고 그걸 컨트롤하고 그리고 그걸 화면에 보여주는 이런 기능이 프레임워크 안에 들어가 있다. 반면에 리액트는 화면에 보이는 view만 담당한다.
그럼, 뷰가 제일 쉽다고 했는데 왜 리액트를 쓰냐? 그 이유는 4번째 줄에 있다.
리액트는 웹개발 리액트 네이티브는 스마트폰 앱개발을 위해 쓰인다.
첫번째 줄 -> 선언적. 대칭되는 개념으로 절차적 절차들을 쭉 나열해서 코드로 쓰는 것(바닐라 js) 이런걸 절차적 프로그래밍이라고 한다.
리액트는 그 중간과정은 리액트가 알아서 해줄테니까 댓글이 추가됐을 때 어떻게 생겼는지 선언만 해놔라 그러면 중간과정은 내가 알아서
해줄께 라는 것이다.
비유적으로 설명하자면
냉장고는 문을 열때 불켜지고 닫을 때 불 꺼진다.
절차적으로 하면 문을 열었을 때 전기가 들어와서 형광등을 찾아가고 전기를 형광등에 흘려보내고 형광등 필라멘트에서
전기를 받아서 불이 켜진다. 라는 모든과정을 우리가 프로그래밍 해야 되는 것이다.
선언적으로 하면 문을 열었을 때는 불이 켜진모습을 보여준다. 문을 닫았을 떄는 불이 꺼진 모습을 보여준다.
이걸로 끝이다. 우리는 불이 켜진모습 꺼진모습 두가지만 묘사하면 되는 것이다.
절차적으로 햇을 때 단점
1. 문제가 생겼을 때 원인을 찾기가 어렵다.
선언적일 땐 바뀌었을 때 모습이 아니면 그러면 우리가 선언한 그 형태가 잘못됐나 그부분만 확인하면 된다.
리액트는 가상돔을 이용한다.
가상돔이란? 가상의 돔을 리액트에서 하나 더 관리하고 있는 것이다. 그래서 그걸 메모리에 유지해
놓는 것이다.
시각화하면 다음과 같은 모습이다.
위가 버츄얼 돔이고 아래가 실제 돔이다.
버츄얼 돔을 리액트에서 관리하고 있다.
무슨 일이 일어나냐면 우리가 변화를 일으킬 때 매번 직접적으로 돔에 접근해서 계속 변화를 일으킨다.
그러면 변화들을 이제 매번 새로 그려야 하고 한 번 그릴 떄마다 돔은 그리는데 좀 필요한 연산이 많다.
그래서 댓글하나를 추가한다고 하면 그 연산을 다 해줘야 하는 것이다.
근데 우리가 ui를 지속적으로 변화시킨다면 매번 다시 돔을 그리고 돔을 그리고 그러다보면 당연히 비효율적이고
무거워서 브라우저가 늦어질 수 밖에 없다.
근데 가상돔이라는걸 이용하게 되냐면 리액트에서 계산하고 있는 것이다.
우리는 가상돔을 가지고 있어 그리고나서 개발자가 우리 이렇게 바꿀거야라고 하면 가상돔이랑 먼저 비교하는 것이다.
스테이지에 들어가서 가상돔이랑 비교해서 실제로 변한게 빨간색 애밖에 없구나
그럼 자식들도 다같이 변했을 것이다.
실제 돔이랑 비교했을 때 이 두 개 밖에 안 변했어라고 파악해놓고 실제 돔한테는 이 두개만 바꾸라고 한 번에 전송해주는 것이다.
이런 과정을 통해서 효율적으로 연산이 가능해지는것이다.
우리가 일일히 매번 돔을 새로 그리지 않고 뭉쳐서 배치해서 작업을 한다.
우리가 기존에 자바스크립트를 실행하려면
html을 만들고 스크립트 태그로 html을 연결한 다음 그거를 브라우저에서 띄어 써야 했다.
자바스크립트가 돌아가는건 브라우저 뿐이니까.
그런데 노드가 나오고 나서 '탈 웹'
이제 자바스크립트가 쓰이는 환경이 브라우저에 국한되지 않고 외부환경에서도 돌아 갈수 있게 해주는
실행환경이다.
노드가 나오고나서부터 원래대로라면 전에는 ui그리는 프론트엔드 안에서 밖에 쓸 수 없었는데
이제 브라우저 밖에서도 돌릴 수 있으니까 서버쪽에서도 자바스크립트를 이용해서 노드를 이용해서 서버를 돌릴 수도 있게됐다.
그리고 우리가 이걸 써야하는 가장 큰 이유는 리액트는 뷰만 그리는 ui라이브러리인데 리액트를 동작시키기 위해서
실제 웹까지 만들어서 동작시키기 위해서는 리액트 뿐만아니라 수많은 다른 도구들도 필요하다.
ex) cra,babel,webpack
이런 도구들이 다 자바스크립트로 되어 있는 도구인데 근데 우리가 브라우저를 띄워서 그때 돌릴 수가 없다.
우리가 웹 만들때 써야하는 것이기 때문에...
(cra를 써야할 때 브라우저에서 cra를 돌릴 수는 없다. 로컬 환경에서 cra를 돌려서 우리가 웹 개발할 때 쓰는거다.)
그래서 노드라는걸 설치해서 우리 로컬 환경에서도 바벨 웹팩같은걸 돋릴 수 있게 하기 위해서 노드를 쓰는 것이다.
그렇다면 npm은 뭘까? 패키지는 뭘까? 패키지는 다른 사람이 만들어 놓은 코드다. 배포할 수 있게 딱 하나의 완성본이 되어있는 코드들이다.
바벨같은 경우 코드를 변환시켜주는 기능이 있는 하나의 프로그램이다. 그런 프로그램 하나하나를 패키지라고 부른다.
자바스크립트로 되어있는 패키지를 노드를 이용해서 다운로드 받아야하는데 이런걸 다운로드 받을 수 있게 해주는게 npm이다.
npm을 통해서 노드에 올라와 있는 여러가지 패키지를 다운로드 받고 설치하고 적용할 수 있다.
노드가 스마트폰이고 앱스토어가 npm이고 거기서 여러가지 패키지를 다운받는거라고 생각하면 편하다.
cra는 뭘까? 리액트말고도 실제 웹을 만들기 위해선 여러가지가 필요한데 ex)바벨, 웹팩 이거 뿐만아니라 다른 것들도
엄청 많이 필요하다. 물론, 우리가 필요한 것을 직접선택해서 최고효율을 낼 수 있게 조율해서 쓰면 그게 최고겠지만
지금은 그렇게 못한다.
이제 그런 도구들을 모아 놓은 것이다. create react app을 하면 프로젝트를 시작하는데 필요한 도구들이 쭈욱 다운로드
받아지는 것이다.(toolchain)
3번쨰 줄을 해석해보면 싱글페이지 어플리케이션을 구축하거나 리액트를 처음으로 배우기 시작할 때 제일 적합한 툴체인이다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
npx create-react-app westagram-react로 프로젝트 폴더를 만든다.
create-react-app을 하면 자동으로 git init도 되어있다.
node_modules는 패키지들의 실제 소스코드가 다 들어가 있는 폴더이다.
package.json은 뭐하는 파일일까? 우리가 만든 cra로 만든 프로그램도 어떻게 보면 하나의 패키지 라고 볼 수 있다.
만들어서 배포도 할 거니까 우리 westagram-react라는 패키지에 대한 정보가 여기 package.json안에 들어가 있는 것이다.
안의 script는 명령어에 대한 단축키라고 보면 된다.
"script": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test".
"eject": "react-scripts eject"
}
ex) npm start 쳤을 때 실제로 돌아가는 명령어는 start가 아니라 react-scripts start가 돌아가는 것이다.
이거는 우리가 추가할 수도 있다.
우리가 다른사람들의 패키지를 다운 받았을 때 무슨 명령어가 있는지 확인하려면 script를 확인하면 된다.
"dependencies": {
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"web-vitals": "^1.1.2"
}
dependencies(의존성)라는 것이 있다.
말그대로 이 패키지가 의존하고 있는 아이들이라는 뜻이다.
이 패키지가 의존하고 있는 다른 패키지들에 대한 걸 여기 적어 놓는 것이다.
이 패키지를 실행하기 위해서는 dependencies안의 내용이 반드시 필요로 하는 것
dependencies랑 node_modules는 연결되어 있다.
<.gitignore>
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.gitignore는 git에서 무시할 애들을 적어놓는 것이다.
node.modules가 적혀있다. 여기에 적혀있는 애들은 다 깃으로 관리를 안한다.
우리가 git add ,commit ,push를 해도 깃허브에 안올라간다.
node_modules에 우리가 필요한 패키지가 다 들어가는데 왜 git에 안올리는 걸까?
용량이 너무 크기떄문에 무거워서 그렇다.
근데 얘네가 없으면 안돌아가기 때문에 필요하긴 필요하다. 그래서 우리가 package.json의 dependencies에 집어넣었다.
node_modules를 안올려도 되는 이유는 dependencies에 다 명시가 되어 있으면 명령어 하나면 여기에 있는 애들이 다
다운로드 받아져 node_modules를 채워진다.
npm install을 치면 패키지 안의 dependencies에 있는 정보를 다 읽는다. 그걸 다 읽고 거기에 있을걸 npm에서 다 다운로드 받아준다.
그래서 dependencies는 잘 관리해야한다. 내가 잘못해서 정보를 지우면 다른 사람이 내 패키지를 쓸 때 실행이 안되는 일이 일어난다.
우리가 개발하면서 새로운 패키지들을 쓸 수도 있는데
그때도 꼭 dependencies에 꼭 넣어줘야한다. npm으로 install 하면 뒤에 --save하고 적어 놓으면 dependencies에 자동으로 추가가 된다.
import React from "react";
import ReactDOM form "react-dom";
import "./index.css";
import App from "./App";
ReactDOM.render(<App />, document.getElementById('root'));
3,4번째는 상대경로가 붙어 있는데 1,2번째는 그냥 string에 바로 적혀있다.
이런 애들은 node_modules에서 바로 끌고 오는 것이다.
node_modules에서 끌고올 때는 바로 스트링으로 적는다.
node_modules안의 react라는 폴더에서 가져오는 것이다. react-dom라는 폴더에서 가져오는 것이다.
밑에서 ReactDom을 쓰고있는데 이건 뭘까? ReactDom하고 .하고 render가 들어갔다 이렇게 생긴애를 객체(object)라고 한다.
객체에 있는 어떤 것들을 접근하기 위해서 .을 써서 들어간다.
ReactDom 다른사람들이 만들어 놓은 객체이다.
ReactDom객체 안의 render라는 프로퍼티(속성)안에 들어갔다. 그리고 괄호가 열리고 닫혔다. 괄호가 열리고 닫히는건 함수를 호출하는 표시다.
리액트돔안에 랜더라는 함수(메소드)가 있고 이걸 호출해서 인자를 두개 넣어주고 있는 것이다.
첫번째 인자로 뭘 랜더 시킬 것인지.
두번째 인자로 어디 안에 랜더 시킬 것인지.
해당 페이지가 어떻게 구성되어 있는지 파악 용이
- 예시
컴포넌트는 하나의 레고 블럭이라고 이해하면 된다.
차가 두개 있는데 위에는 레고블럭 컴포넌트 단위로 개발한 자동차이다.
아래는 하나의 통으로 찍혀져 있다. 중간에 레고처럼 나뉘어져 있지 않다.
코드의 재활용이 증가된다는 말은 바퀴는 똑같이 생겼는데 네 개 들어가는 것이다.
왼쪽 오른쪽만 살짝 바꿔 주면 된다.
그런데 그걸 판으로 찍으면 네개다 만들어야 한다.
컴포넌트를 쓰면 이런 바퀴의 틀 하나 잡아놓고 네 개를 만들어서 쓰면 끝나는 문제다.
그러니 코드의 재활용이 증가되고 유지보수가 용이하다는 말은 여기 밑에 있는 자동차에서
문의 색을 바꾸고 창문을 늘리고 싶다.
그러면 통으로 찍혀있으니까 문만 바꿀 수는 없으니 처음부터 새로 만들어야 한다.
위에 같은 경우에는 블록단위로 만들어져 있다. 문도 블록단위이니 색을 바꾸고 싶으면 문의 블록만
바꿔끼우면 된다.
이런면에서 코드의 유지보수가 용이하다는 것이다.
그리고 해당페이지가 어떻게 구성되어있는지 파악이 용이하다는 것은
아래는 뚜껑이 어디까지인지 말하기 애매하다.
위에는 한 부품이 뚜껑이다. 본넷이다. 문이다 말할 수 있다. 해당페이지가 뭘로 구성되어있는지 파악하기 쉽다.
컴포넌트의 또 다른 특징은 컴포넌트는 또 다른 컴포넌트를 포함 할 수 있다.
부모자식 컴포넌트로 표현한다.
문안의 손잡이도 컴포넌트로 만들 수 있는데 문이라는 컴포넌트에 속하게 만들 수 있다.
작은 컴포넌트 -> 중간 컴포넌트 -> 큰 컴포넌트 이런식으로 개발하는게 컴포넌트 단위개발이라고 한다.
에전에는 함수로는 상태관리가 안돼서 class형태로 주로 사용했지만 지금은 함수에 hook이라는 새로운 기술이 나오면서
요즘에는 다 함수형으로 사용한다.
ui와 자바스크립트 로직은 뗄레야 뗄 수 없는 사이인데 이것을 계속 따로 쓰다보니까 너무 불편해서
그러면 그냥 자바스크립 파일 안에서 이런 마크업까지 다 같이 해버리자 라는 컨셉으로 나온게 jsx이다.
얘는 말그대로 확장문법이기 때문에 실제로 웹 브라우저가 읽어서 해석하지를 못한다.
그래서 그 중간에 많은 패키지 중에서 babel이란 번역을 해주는 패키지가 있는데 이게 계속 jsx를 읽고html을 만드는 과정을 해준다.
그래서 얘가 컴파일에서 나간다라고 보면 된다.
jsx의 특징 4가지
1.형제구조로 이루어질 수 없다. 최상위로 하나가 감싸져서 하나의 단일 태그가 되어야 한다.
import React from "react";
class Login extends React.Component { //에러!
render(){
return(
<div>Hello</div>
<div>world</div>
)
}
}
class Login extends React.Component { //성공!
render(){
return(
<div>
<div>Hello</div>
<div>world</div>
</div>
)
}
}
class Login extends React.Component { //성공!
render(){
return(
<>
<div>Hello</div>
<div>world</div>
</>
)
}
}
export default Login;
//부모가 하나로 감싸기는 해야하는데 실질적으로 얘한테 스타일링을 줄 것도 아니고 실제로 쓰는 애가 아니다라고 하면은
//프레그먼트(fragment) <> </> 라는걸 쓸 수 있다.
fragment를 썼을 때 랜더 결과
2.class = "" 가 아니라 className=""으로 써야한다.
3.jsx는 자바스크립트 안에서 쓰는 html이다. 그러므로 이 안에 자바스크립트를 넣어줄 수도 있다. jsx안에서 자바스크립트를 쓸 땐 중괄호를 써줘야한다.
4.addeventlistener같은걸 안써도 바로 태그안에서 이벤트를 붙일 수 있다.
import React from "react";
class Login extends React.Component {
render(){
return(
<>
<div className="title" onClick = {() => alert("Function trigger")}
style={{color: "red"}}>
{"Hell" + "O"}
</div>
</>
)
}
}
export default Login;
//{"Hell" + O} => 자바스크립트 연산이 돼서 HellO라고 나옴
//onClik이 됐을 때 {}안의 자바스크립트 함수를 실행시켜라
//인라인 스타일도 줄 수 있다. 인라인 스타일은 객체형태로 들어가야한다. 객체는? 자바스크립트다. 그래서
//중괄호 한 번 열고 그안에 객체가 들어가니까 중괄호를 한 번 더 넣어야한다. 즉, 두번 중첩된 형태로 나온다.
import React from "react";
class Login extends React.Component {
render(){
const str = "Hello";
return(
<>
<div className="title" onClick = {() => alert("Function trigger")}
style={{color: "red"}}>
{"Hell" + "O"}
</div>
</>
)
}
}
export default Login;
jsx안에서 변수를 선언할 일은 거의 없고 그 밖에서 선언한다 jsx에서는 대부분 만들어놓은 변수를 쓰는 일만 있다. render밑에서 변수를 선언하는건 jsx안에서 변수를 선언하는건 아니기 때문에 일반적인 자바스크립트 문법을 따라주면 된다.
'React > Today I learned' 카테고리의 다른 글
Router (0) | 2021.06.29 |
---|---|
[React] 비동기, 동기 (0) | 2021.06.27 |
[React] key값을 써야하는 이유 (0) | 2021.06.26 |
Class 컴포넌트 Constructor에서 super(props)를 써야하는 이유 (0) | 2021.06.23 |
생활코딩 React 11. 컴포넌트 만들기 (0) | 2021.06.22 |