React 란 무엇인지, 정의와 특징에 대해 간단히 정리했고 초기 셋팅 후 실행까지 해보았습니다. 다음으로 리액트의 기본적인 내용들 !! 배포하는 법부터 리액트의 핵심!! Component의 Props와 State에 대해서 자세하게 알아봅시다 🔥
제일 처음 예제로 만들었던 Hello, React !! 라는 h1 태그 하나만 들어있는 간단한 리액트 앱이 있습니다. npm start로 앱을 실행시켰을 때, 앱의 전체 용량이 1.7MB 라고 나옵니다. 기능이 하나도 없는데, 이런 용량이 나오는 것은 도저히 이해가 안됩니다.
이는 바로 리액트가 개발의 편의성을 위해서 여러가지 기능을 추가해놓은 상태이기 때문입니다. create react app 의 개발 환경은 파일의 무게가 상당히 나무겁습니다. 하지만 개발자만 사용하고 로컬에서만 사용하기 때문에 괜찮습니다. 근데 사람들이 쓸 때는 1.7MB를 쓰게하면 절대 안되겠죠!? (보안의 문제도 있을 수 있고.. 이러쿵 저러쿵...)
create react app 에서의 개발 환경을 실행시킬 때는 npm run start(npm srart)를 쎴는데, production mode 의 app 을 만들 때(빌드할 때)는 npm run build를 이용합니다. 그러면 디렉토리에 이전에는 없었던 build 라는 내부(하부) 디렉토리가 새로 생깁니다. 그 안에 보면 index.html 이 있습니다. 한번 까봅시다 ✌️
😱 공백이 하나도 없고, 아예 읽을수가 없습니다... 간혹 알아볼 수 있는 단어가 조금 보이기도...? 이는 create react app 이 실제 production 환경에서 사용되는 app을 만들기 위해서, 이미 가지고 있는 index.html 에서 불필요한 정보를 다 걸러낸 결과물이기 때문입니다. (=> 용량이 매우 작다!!!)
src 에서 작업했던 소스코드들도 전부 마찬가지 입니다.
실제로 서비스할 때는 build 안에 있는 파일들을 쓰면 됩니다. (이것들이 바로 공정 과정을 거친 알짜배기들? 이라고 이해하면 좀 쉬울까요??) 웹 서버에 도큐먼트 루트(문서를 찾는 최상위 디렉토리)에다가 build 안의 파일들을 위치시키면 됩니다!
왼쪽의 html 코드가 있습니다. 이를 Js-리액트로 다시 작성해보았습니다.
만약 왼쪽의 header, nav, article (이들을 시멘틱 코드라고 합니다.) 의 길이가
천만 라인, 1억 라인 등으로 엄청나게 길어진다면 어떻게 될까요?
이 코드들을 유지보수하고 수정하는데에 엄청난 시간을 쓰게 될 것입니다.
그렇다면 개발자는 이러한 생각을 하게 될 것입니다.
"header 라는 이름으로 가져다 쓰기만 하고 안에 내용들은 다른 데다가 정의 해두면 안될까?" 다음과 같은 생각을 구현하게 해주는 것이리액트이고,
바로 리액트의 컴포넌트 개념이라고 할 수 있습니다. 컴포넌트를 정의하는 가장 간단한 방법은 JavaScript 함수를 작성하는 것입니다. 위의 그림에서 오른쪽 !!
이렇게 리팩토링을 해줘도, 하나의 파일에 수천개의 컴포넌트가 있다면 그것 또한 보기가 혼란스럽습니다. 그래서 보통의 경우에 컴포넌트를 파일로 분리해서 주로 사용합니다⭐️
여기서 잠깐 !! React Component 선언하는 방식에는 두 가지가 있습니다. 클래스형 컴포넌트 와 함수형 컴포넌트. 현재 공부하고 있는 생활코딩에서는 클래스형 컴포넌트로 설명을 해줍니다.(아무래도 옛날 강의라서,,ㅠ)
React의 최신 문법에 따르면 함수형 컴포넌트를 사용하고 권장합니다.
그럼에도 불구하고? 클래스형 컴포넌트를 사용하는 기업들이 간혹 있습니다..!
이 둘의 차이점에 대해서 한번 알아보고 프롭스(Props)로 넘어가겠습니다 ✌️
< 함수형 컴포넌트 >
import React from 'react';
import './App.css';
function App() {
const name = 'react';
return <div className = "react">{name}</div>
}
export default App;
< 클래스형 컴포넌트 >
import React, {Component} from 'react';
class App extends Component {
render() {
const name = 'react';
return <div className="react">{name}</div>
}
}
export default App;
함수형과는 다른 클래스 컴포넌트의 핵심은 크게 3가지입니다.
일반적인 차이점으로
클래스형에서는 state, lifeCycle 관련 기능을 사용할 수 있다는 점, 메모리 자원을 함수형 컴포넌트보다 조금 더 사용한다는 점, 임의 메서드를 정의할 수 있다는 점 등이 있습니다.
함수형은 state, lifeCycle 관련 기능사용 불가능하고(Hook을 통해 해결) 메모리 자원을 함수형 컴포넌트보다 덜 사용한다, 컴포넌트 선언이 편하다. 라는 점들이 있습니다.
State 와 Props의 사용에서도 큰 차이점이 있습니다. 이는 State와 Props를 공부하면서 같이 살펴보도록 하겠습니다!
프롭스(props) 는 컴포넌트(Component)에서 사용 할 데이터 중 변동되지 않는 데이터를 다룰 때 사용됩니다. 또한 부모(parent) 컴포넌트에서 자식(child) 컴포넌트로 데이터를 전할 때, props 가 사용됩니다.
예를 들어, Content 라는 컴포넌트를 2개 만들었는데 이게 계속 같은 역할만 수행합니다. naver a태그를 이용하여 h1태그를 만든다고 가정하면 개발자는 이런 고민을 할 수 있습니다.
"동작은 똑같은데 그 안에 내용만 조금씩, 내가 원하는거로 바꿔줄 수는 없나?
전달해준 인자를 적용해줄 수는 없나?"
여기서 나온 개념이 바로 props 입니다!
클래스형으로 예제를 만들어보면 다음과 같습니다.
class MyComponent extends Component {
render() {
const {dept, id, name} = this.props;
return{
<div>
안녕하세요! 저는 {dept}, {id}, {name} 입니다.
</div>
};
}
}
function MyComponent = ({dept, id, name}) => {
return (
<div>
안녕하세요! 저는 {dept}, {id}, {name} 입니다.
</div>
)
}
함수 선언시 에로우 화살로 바로 선언 가능합니다. 요소에서 적용하기 위해서는 this를 붙여야합니다.
const 키워드 + 함수 형태로 선언 해야합니다. 요소에서 적용하기 위해서는 this가 필요없습니다.
[그림 출처] - sdc337dc.log, < 함수형과 클래스형의 차이 >
컴포넌트에서 유동적인 데이터를 다룰 때, 스테이트(State)를 사용합니다.
Props가 읽기 전용이라면 State는 컴포넌트 내부에서 바꿀 수 있는, 바뀔 수 있는 값 !!
프롭스는 사용자가 컴포넌트를 사용하는 입장에서 중요한 것이고, 스테이트는 프롭스의 값에 따라 내부 구현에 필요한 데이터라고 구분해서 이해 가능합니다!
사용자는 태그의 속성에 해당하는 프롭스를 통해 컴포넌트를 조작합니다. 사용자는 컴포넌트 내부에서 사용되는 동작, 구현 방식에 대해서는 아무것도 모릅니다. 이게 바로 스테이트 입니다.
리액트와 같은 시스템은 컴포넌트를 만들고 외부에서의 프롭스, 그리고 실제로 내부에서의 스테이트가 철저히 구분되어 있습니다. 사용하는 쪽과 구현하는 쪽이 철저히 구분되어 있는 것입니다.
클래스형으로 예제를 만들어보면 다음과 같습니다.
constructor 안에서 this.state 초기 값 설정 가능하고 state는 객체 형식입니다. 컴포넌트가 실행될 때 render 메소드보다 먼저 실행이 되면서 그 컴포넌트를 초기화 시켜주고 싶은 내용들은 constructor 안에다가 작성해줍니다.
constructor(props) {
super(props);
this.state = {
monsters : [],
userInput: "",
};
}
this.setState 함수로 state의 값을 변경할 수 있습니다.
onClick={() => {
this.setState({number:number+1});
}}
함수형 컴포넌트에서는 useState 함수로 state를 사용합니다. useState 함수를 호출하면 배열이 반환되는데 첫 번째 원소는 현재 상태, 두 번째 원소는 상태를 바꾸어 주는 함수입니다.
const [message, setMessage] = useState("");
상태를 바꿔주는 함수는 보통 set + 원소 이름(첫문자는 대문자)로 사용합니다.
가장 많이 쓰이는 개념은 상위 컴포넌트의 상태를 하위 컴포넌트로 전달하고 싶을 때 상위 컴포넌트의 스테이트 값을 하위 컴포넌트의 프롭스 값으로 전달하기! 입니다.
데이터가 바뀌어도 하위 컴포넌트에 직접 접근해서 코드를 수정하지 않아도 되게 되는 것입니다! (말이 좀 이상한가요ㅠ) 이해가 되셨으면 좋겠습니다 !!