data life

[React] React 기초 본문

Front-end/React

[React] React 기초

주술회전목마 2022. 12. 17. 13:33


React란?

SPA (Single Page Application)
일반적으로는 최초에 서버로부터 HTML을 받고 페이지의 변경이 필요하다면 다시 서버에 요청하여 HTML을 전달받음
이 과정에서 페이지를 처음부터 다시 불러옴(reload)

반대로 SPA의 경우, 최초 서버로부터 HTML을 받고 페이지의 변경이 필요하다면 변경이 필요한 부분만 JSON으로 전달받음
이 과정에서 페이지에서 변경된 부분만 계산하여 다시 그리게 됨!


이를 위해서, React가 쓰이는데

사용자 인터페이스(UI)를 만들기 위한 JavaScript 라이브러리이다.
이때, JavaScript 내에서 UI를 작성하기 위해 개발자에게 익숙한 환경을 제공하는 JSX가 있다.
이는 HTML과 유사하여 개발자들에게 유용하다!
또한, UI를 구성하기 위해 '컴포넌트' 단위로 개발을 진행한다 (like 레고)
==> 코드의 재사용성을 늘릴 수 있게 됨

 

 

과연 얼마나 중요한가?

페이스북에서 개발한 후, 다시 자체 웹사이트를 React JS로 갈아엎음,,
지금까지도 React JS로 작업하고 있고 개선을 위해 자금을 투자 중임
이 말인 즉슨 안정성이 크다는 뜻!
또한 자바스크립트와 연관이 있고 아주 가까운 사이이기 때문에 작업 시 용이할 수 있음 (커뮤니티가 뛰어남)
더 나은 자바스크립트 개발자가 되기 위해선 React JS를 배우고 작업하는 것을 추천한다.

많은 대기업들이 사용하고 있고 (특히, 페이스북) 생태계가 늘어남에 있어서 많은 거대한 웹사이트들이 React JS를 사용하고 있다. 오늘날 React JS를 배우는 것은 좋은 선택이라고 본다!

단순 웹 어플리케이션 개발 뿐만 아니라 React-Native에 적용하여 안드로이드/iOS 어플리케이션도 개발이 가능하다.

1. 설치하기

먼저 node.js의 npm을 이용하기 때문에 먼저 node.js가 설치되어있지 않다면, 설치하길 바란다!
설치가 완료되었다면 react 설치는 다음과 같다.

npx create-react-app <디렉토리명>
cd <디렉토리명>
npm start
이때, npm이 아닌 npx는 npm package를 1회성으로 내려 받아 실행할 때 사용하는 명령어이다.
cd로 원하는 디렉토리로 이동한 다음,
npm start로 현재 디렉토리에서 프로젝트를 실행할 수 있다.


설치가 완료되면 설치 파일들이 나타나면서 리액트가 실행되는 것을 확인할 수 있다.
디렉토리 구조를 살펴보면 다음과 같다.

  • node_modules : npm을 이용하여 설치한 패키지들 모음
  • public : 정적인 파일들 모음
  • src : 리액트 개발을 위한 파일들 모음
  • .gitignore : git을 이용할 경우 불필요한 파일을 무시하도록 설정할 파일들 모음
  • package.json : 프로젝트에 관한 정보와 사용하는 패키지들을 명세하는 파일
  • README.md : 프로젝트에 관한 설명 파일 (마크다운 형식)

 

2. 설치한 라이브러리를 프로젝트 내 불러오기

import "패키지명"
// css 불러오기
import "./App.css";

import name from "패키지명"

import { a, b } from "패키지명"  // 패키지 내 일부 매소드나 변수만 가져올 때

import * as name from "패키지명" // 패키지에 default로 export되는 객체가 존재하지 않을 때

 

3. 자바스크립트와 jsx 비교

js

<!DOCTYPE html>
<html>
	<header>
		<h1>Website</h1>
	</header>
    <nav>
    	<ul>
        	<li>html</li>
            <li>css</li>
            <li>js</li>
        </ul>
    </nav>
    <article>
    	<h2>Welcome</h2>
        React world!
    </article>
</html>

jsx

import "./App.css";
// arrow function 이용
const Header = (props) => {
	return (
		<header>
			<h1>
				<a href="index.html">{props.title}</a>
			</h1>
		</header>
	);
};
function Nav() {
	return (
		<nav>
			<ul>
				<li>
					html
				</li>
				<li>
					css
				</li>
				<li>
					js
				</li>
			</ul>
		</nav>
	);
}
// 구조분해할당법 이용
const Article = ({title, body}) => {
	return (
		<article>
			<h2>{title}</h2>
			{body}
		</article>
	);
};
function App() {
	return (
		<div className="App">
			<HeaderTag title="웹" />
			<Nav />
			<Article title="어서오세요" body="웹의 세계로 초대합니다." />
		</div>
	);
}

export default App;

 

JSX

함수 호출과 객체 생성을 위한 문법적 편의를 제공하는 javascript의 확장
위의 React 형식보다는 html 내에 필요한 데이터를 한 공간에 사용할 수 있어서 개발이 용이하고 읽기도 쉽다,,
그러나 브라우저는 JSX를 이해하지 못하기 때문에 코드를 변환시켜주는 Babel을 이용해 줄 것임!

 

html과의 차이점이 있다면?

1. html tag 내에 javascript 연산이 가능하다.
2. class명 입력 시, class => className 입력
3. 스타일은 object로 표현 큰따옴표("")가 아닌 중괄호({})로 입력
+ Inline style은 camelCase로 명명 ex> background-color => backgroundColor
4. 닫는 태그 필수! <br /> <img /> <input />
5. 최상단 element는 반드시 한 개만 작성 가능
<> </> 이용

 

 

컴포넌트

React에서 페이지를 구성하는 최소 단위로, 독립적이고 재사용이 가능한 코드 조각임
항상 이름의 첫 글자는 대문자로!!!
arrow function을 이용하여 <Title /> <Button /> 이용
이때, arrow function 이란?

화살표 함수로 기존 함수 표현보다 구문이 짧은 함수 표현
function이라는 키워드를 생략하고 매개변수를 받은 뒤 '=>'를 써주는 형태
중괄호({})를 열어서 로직을 작성하고 return 값만 존재하는 짧은 함수의 경우 중괄호와 return을 생략하고 바로 return할 값을 입력할 수도 있다.
const c = (x,y) => {
	console.log(x,y);
};

const d = (x,y) => console.log(x,y);
const TopElement = (props) => {
	const {user, color, children} = props
    
    return (
    	<div style={{color}}>
            <span>{user.name}님의 하위 요소는</span>
            {children}
        </div>
    )
 }
  • 컴포넌트끼리 데이터를 주고 받을 땐 props
  • 컴포넌트 내에서 데이터를 관리할 땐 state
  • 데이터는 부모에서 자식으로만 전달

 

컴포넌트 종류

- class component VS function component

// class component
class Hello extends Component {
	render() {
    	const {name} = this.props
        return <div>{name}님, hello!</div>
    }
}
// function component
const Hello = (props) => {
	const {name} = props
    return <div>{name}님, hello!</div>

 

Props 란?
>> 컴포넌트에 원하는 값을 넘겨줄 때 사용하며 재사용이 용이하다
단, 변경을 원한다면 새로운 변수를 생성하여 복제한 다음 변경해줌!

const Hello = (props) => {
	return <h1>Hello, {props.name}</h1>;
}
const App = () => {
	return (
    	<>
            <Hello name="길동" />
            <Hello name="철수" />
            <Hello name="영희" />
        </>;
    )
}

State
먼저 react 패키지로 useState를 import해줌

import { useState } from "react";

 

다음과 같이 state 선언

const [value, setValue] = useState(초기값);

//State 변경
const [value, setValue] = useState("");
setValue("변경값");

>> 컴포넌트 내에서 데이터를 유동적으로 관리함
>>state가 변경될 때마다 컴포넌트가 다시 렌더링(rendering)
단, state 값을 직접 변경하게 되면 렌더링할 타이밍을 알아차리지 못해 에러 발생
1. setState에 변경할 값을 직접 넣기
2. setState에 함수 넣기
>>object의 경우, 기존 내용을 새로운 object에 넣고 변경 {...}

import React from 'react';
import { useState } from 'react';

function App() {
  const [value, setValue] = useState(0);
  return (
    <div className="App">
      <span>{value}회 클릭하였습니다.</span>
      <button
        onClick={() => {
          setValue(current => {
            return current + 1;
          });
        }}
      >
        클릭
      </button>
    </div>
  );
}

state VS props

props는 컴포넌트에 전달되어 사용되고 (함수의 매개변수)
state는 컴포넌트 안에서 관리된다. (함수 내 선언된 변수)

값이 매번 변하는 상황일때 state를 사용하는 것이 좋다.
props는 읽기 전용이라 수정이 불가능하고 state는 수정이 가능하기 때문!

함수 컴포넌트는 state를 가질 수 없어서 클래스 컴포넌트로 변환시켜줘야 한다.

1. class 함수명 extends React.Component {} 생성
2. render() {} 추가
3. props => this.props

state를 이용하기 위해선 클래스 컴포넌트에 constructor() 선언해야함

1. class 내에 constructor(props){} 생성
2. constructor 내에 super(props) 호출
3. this.state로 초기화

 

 

DOM


DOM element의 속성
기본적으로 camel case로 작성
예외> 'data-' , 'aria-' 로 시작

HTML 속성과 다른 이름을 가짐

  • class -> className
  • for -> htmlFor

HTML 속성과 다른 동작을 가짐

  • checked -> DefaultChecked
  • value -> defaultValue)
  • style

React에만 쓰이는 속성

  • key : element에 고유성을 부여해서 React가 어떤 항목을 변경/추가/삭제할지 식별하는 것을 도와줌
  • dangerouslySetInnerHTML
const className = () => {
	const students = [
    	{key:'1', name:'길동'},
        {key:'2', name:'철수'},
        {key:'3', name:'영희'),
    ]
    return (
    	<>
        	{name.map((item) => {
            	<li key={item.key}>{item.name}</li>
                ))}
        </>
    )
}

 

Event

>> HTML element에 대한 사건 발생을 자바스크립트를 이용해 대응
>> 다양한 이벤트들이 존재하며 'eventHandler 함수'를 이용하여 다양한 로직을 처리할 수도 있음

DOM element의 경우 핸들링 함수에 event object를 매개변수로 전달한다.

const APP = () => {
	const handler = (event) => {
    	console.log(event.target.value + "검색하기");
    }
    return (
    	<>
           <input onChange={handler} />
        </>
    );
};
  • onClick : 클릭 시
  • onDoubleClick : 더블 클릭 시
  • onSubmit : submit 시
  • onChange : element 내용 변경 시
  • onKeyDown/Up/Press : 키보드 입력 시
  • onBlur : element가 focus를 잃었을 시
  • onFocus : element가 focus되었을 시

 

React의 Life Cycle

>> 컴포넌트가 이벤트를 다룰 수 있는 시점
원하는 시점에 맞춰 컴포넌트가 다른 동작을 수행하길 원한다면 생명주기에 대해 알 필요가 있다.

종류
- 마운트 : 컴포넌트가 실제 DOM에 삽입
- 업데이트 : 컴포넌트 변경
- 언마운트 : 컴포넌트가 DOM에서 제거

메소드

  • constructor() : State 데이터 초기화
  • render() : 클래스 컴포넌트에서 필수 구현
  • componentDidMount() : 컴포넌트가 마운트된 직후 호출
  • componentDidUpdate() : 업데이트가 진행된 직후 호출
  • componentWillUnmount() : 컴포넌트가 마운트 해제되어 제거되기 직전 호출

 

Hook

컴포넌트 내에서 state와 life cycle을 관리하기 위해 반드시 클래스 컴포넌트를 사용한다고 설명했지만,
다소 복잡하기 때문에 이를 보완하고 함수 컴포넌트에서도 클래스 컴포넌트 기능을 구현시키기 위해 등장하게 됨

Hook의 이름은 'use'로 시작해야 한다.
ex> useState
최상위에서만 호출이 가능하다.
ex> if문, for문 안쪽, 콜백함수 내에서는 불가능

Hook을 왜 사용하는가?
>> 일반적으로 리액트 컴포넌트가 함수 컴포넌트로 시작하게 되는 경우, 클래스 컴포넌트로 변경하기 위해서는 꽤나 복잡해지게 되는데 이때, hook을 사용하게 되면 구성 요소로만 상태관리가 가능해지므로 리팩토링을 최소화할 수 있다
>> 분리가 쉬워지게 됨으로써 코드의 재사용도 줄이고 가독성 또한 좋아진다.
>> 일부 컴포넌트 안에서 hook을 사용하므로써 기존 코드를 다시 작성하게 되는 번거로움을 줄여준다.
>> 컴포넌트 개개적으로 테스트가 가능하다. 따라서 상테 관련 로직 추상화가 가능해진다.



useState Hook

const App = () => {
	const [state명, setState명] = useState(초기값)
}


state 변경을 위해 setState에 변경할 값을 직접 입력하거나
현재 값을 매개변수로 받는 콜백함수를 이용한다.

 

useEffect Hook
함수 컴포넌트 내에서 side effect를 실행할 수 있게 도와줌.

const App = () => {
	useEffect(EffectCallback, Deps[])
}

- EffectCallback : Deps에 지정된 변수가 변경될 때 실행할 함수
- Deps : 변경을 감지할 변수들의 집합([])

정리

클래스 컴포넌트에서 unmounting 시, componentWillUnmont 를 이용하여 더 이상 사용하지 않는 컴포넌트를 해제하는 것

- 정리가 필요없는경우
: 컴포넌트가 실행되고 나서 추가로 실행해야할 코드가 없을 때
- 정리가 필요한 경우
: 컴포넌트가 실행되고 나서 추가로 실행해야할 코드가 있을 때

 

useMemo Hook
지정 state나 props가 변경될 경우 해당 값을 활용하여 계산된 값을 memoization => 재렌더링 시 불필요한 연산을 줄여줌

useCallback Hook
함수를 memoization => 재렌더링 시 불필요한 함수 생성을 방지

useRef Hook

컴포넌트 life cycle 내에 유지할 ref 객체를 반환하며 일반적으로 React에서 DOM element에 접근할 때 사용한다.





'Front-end > React' 카테고리의 다른 글

[React] State 끌어올리기  (0) 2023.03.29
[React] State의 비동기적 업데이트  (0) 2023.03.29
[React] State  (0) 2023.03.29
[React] 라이브러리 vs 프레임워크  (0) 2023.03.24
[Project] React로 단위변환기 만들기  (0) 2022.12.25