본문 바로가기
FE/React

[React Official Document] #1 Quick Start

by aeyong-dev 2023. 9. 25.

리액트의 공식문서는 꽤나 잘 구성되어 있다. 

오죽하면 '공식문서로 공부해라' 라는 의견이 있을 정도일까.

이 문서는 리액트의 작동 원리에 대해 자세하게 이해할 수 있도록 잘 작성되어있다고 한다.

리액트를 공부하는 학생으로써 공식문서를 읽어보지 않을 수 없다. 

당연하게도 영어로 작성되었지만, 굳이 번역기를 쓰지는 않았다.

개발을 공부하는 이상 앞으로 리액트 뿐 아니라 다양한 공식문서들을 읽을 것이다.

출시된지 얼마 지나지 않은 최신 기술, 내가 꼭 써야하지만 사용자가 적어 공식문서 외에는 정보를 얻기 힘든 기술들을 마주할 것이다.

그럴 때 마다 다른것이 아닌 영어가 내 발목을 잡는다면... 분명히 좋은 꼴은 못 볼 것이다.

모르는 단어가 나오거나 한글로 바로 떠올리지 못하는 문장들은 chatGPT를 통해 이해하였다.

'아직 이해가 잘 안되는데, 다른 예시 코드를 보여줘' 같은 대화를 입력하며 더 효율적인 공부도 될 수 있었다.

앞으로 작성할 [React Official Document] 포스팅에서는 필자 본인의 기준(리액트 초심자)에서 새롭게 배우게 된 내용들, 어느정도 알고는 있었지만 확실하게 설명하지는 못했던 것들을 위주로 작성할 것이다(기초적인 내용을 아예 다루지 않는 것은 아니다).  

리액트에 대한 모든 것들을 설명하지는 않기에 아예 처음 접하는 사람들에게는 이 글을 추천하지 않는다.

https://react.dev/learn

 

Quick Start – React

The library for web and native user interfaces

react.dev


 Quick Start는 Learn 버튼을 누르면 가장 먼저 나오는 페이지다.

제목이 Quick Start인 만큼, 리액트를 사용하기 위한 기본적인 지식들을 안내하고 있다.

컴포넌트의 생성과 중첩, 스타일 적용, 데이터 출력, 간단한 상태 관리에 대해 알 수 있다. 

 

컴포넌트란? 

컴포넌트란 UI, 즉 사용자가 보는 화면에서의 한 조각을 말한다. 

컴포넌트들은 각자만의 로직과 모양을 갖고있다. 

이런 컴포넌트들이 모여서 하나의 리액트 앱을 완성하는 것이다. 

비유하자면 컴포넌트라는 퍼즐 조각들이 모여 완성한 그림이 리액트 앱이라고 할 수 있을 것 같다.

컴포넌트의 이름을 지을 때는 특별한 규칙을 지켜야 하는데, 반드시 대문자로 시작해야 한다는 것이다. 

  • HTML: <input />
  • Component: <MyComponent />

반면에 HTML 태그는 항상 소문자로 시작한다. 

이 차이점을 기억하면 이해하기 쉬울 것이다. 

HTML 태그는 항상 소문자, 컴포넌트는 항상 대문자.

 

export default에 대해

아래는 예시 코드이다. 

const HelloComponent = () => {
	return (
    	<div>
        	<h1>Hello Component!!</h1>
        </div>
    );
};

export default const MyComponent = () => {
	return (
    	<div>
        	<HelloComponent />
        </div>
    );
};

두 개의 컴포넌트를 하나의 파일에서 정의하고 있다. 

MyComponent에서는 export default 라는 키워드가 덧붙여졌다. 

export default는 '이 파일의 대표 컴포넌트는 ~입니다' 라는 뜻이다. 

즉, 이 파일을 import하게되면 MyComponent가 오는 것이다. 

 

컴포넌트의 스타일 적용

컴포넌트를 사용할 때 style 속성을 부여함으로써 사용할 수 있다. 

<h1 style={{color: 'red'}}> ...

그런데 중괄호가 두번이나 사용되었다.

JSX에서 JS코드를 삽입할 때는 중괄호를 사용하여야 한다. 

바깥의 중괄호가 그 역할을 한다. 

안쪽의 중괄호는 특별한 문법이 아니라 객체를 나타내는 중괄호이다. 

그러니까, {color: 'red'} 라는 객체를 사용한 것이다. 

 

조건에 따른 렌더링

상태에 따라 컴포넌트를 보이지 않게 하거나 다른 컴포넌트를 보여주고 싶을 때가 있다. 

그럴때는 다음과 같은 코드를 사용하면 된다. 

아래의 두 코드는 같은 의미를 가진다. 

if(isLoggedIn) {
	content = <AdminPannel />
} else {
	content = <LoginForm />
}
{isLoggedIn ? <AdminPannel /> : <LoginForm>}

isLoggedIn이 true 라면 <AdminPannel /> 컴포넌트를 보여주고, false라면 <LoginForm />을 보여준다. 

위의 조건문에서는 content에 컴포넌트를 할당하여 content를 return해줄 것이다. 

아래의 코드에서는 삼항연산자를 이용한 코드이다. 

isLoggedIn이 true라면 <AdminPannel />을, false라면<LoginForm />을 렌더링하게 될 것이다. 

코드 길이가 짧아지고 가독성이 좋다는 면에서 아래의 코드가 더 효율적이라 생각한다. 

{isLoggedIn && <AdminPannel />}

반면의 이 코드는 AND연산자를 사용하였다. 

AND 연산자는 양쪽이 모두 true일때만 true를 return한다. 

이 경우 isLoggedIn이 true라면 <AdminPannel />을 렌더링해줄 것이다. 

만약 isLoggedIn이 false라면 아무것도 표시되지 않을 것이다. 

 

리스트의 렌더링

for문이나 map() 함수를 사용하여 리스트를 렌더링할 수 있다. 

이때 주의해야 할 점은 리스트의 각 항목에 대해 반드시 문자열이나 숫자인 key값을 전달해줘야 한다는 것이다. 

그래야만 나중에 리스트에 항목을 추가, 삭제, 재정렬 하는 등의 수정이 있을 경우 리액트가 상황을 파악할 수 있다. 

보통 key값으로 데이터 고유의 ID를 사용한다. 

아래는 리스트를 렌더링하는 예시이다. 

const listItems = books.map(book => {
	<li key = {book.ISBN}>
    	{book.title}
    </li>
}

 

특정 이벤트에 반응 요소 추가하기

이벤트 핸들러 함수(event handler function)를 통해 이벤트에 대해 원하는 반응을 추가할 수 있다. 

예를 들어, 버튼을 눌렀을 때 콘솔에 로그를 찍고싶다면 다음과 같이 작성할 수 있다. 

const ClickButton = () => {
	const handleClick = () => {
    	console.log("You clicked me!");
    }
	return (
		<div>
        	<button onClick={handleClick}> Click me! </button>
        </div>
    )
}

 

상태관리, useState

만약 useState로 상태를 정의한 컴포넌트를 여러번 사용하게 된다면 상태관리는 어떻게 될까? 

각자의 컴포넌트들은 서로 독립된 상태를 갖게된다. 

아래와 같은 컴포넌트가 있다고 가정해보자. 

import { useState } from 'react';

const Counter = () => {

	const [count, setCount] = useState(0);

	const onClickHandler = () => {
		setCount(count+1);
    };
    
    return (
    	<div>
        	<button onClick={onClickHandler}>
            	{count}
            </button>
        </div>
    );
};

export default const CountersBox = () => {
	return (
    	<div>
    		<Counter />
            <Counter />
            <Counter />
        </div>
    );
};

CountersBox 컴포넌트에서는 여러개의 Counter 컴포넌트들이 있는데, 이들은 각자의 count를 가진다. 

만약 모든 Counter가 같은 상태를 공유하여 버튼 세개 중 하나만 눌러도 모든 숫자가 바뀌는 것을 원한다면 어떻게 할까? 

Counter 컴포넌트들을 감싸고 있는 부모 컴포넌트에서 상태를 props로 전달하여 구현할 수 있다. 

state = {count} setState = {setCount} 와 같은 식으로 말이다. 

이렇게 해서 여러 컴포넌트가 하나의 상태를 공유할 수 있다.