[React]리액트 기초 - 기본문법과 JSX

Inung_92·2023년 1월 26일
1

React

목록 보기
1/15

리액트란?

📖사용자 인터페이스를 구축하기 위한 선언적이고 효율적이며 유연한 JavaScript 라이브러리

리액트는 "컴포넌트"라고 불리는 작고 고립된 코드의 파편을 이용하여 복잡한 UI를 구성하도록 돕는다. 자칫 리액트를 프레임워크로 착각할 수도 있지만 엄연히 리액트는 JavaScript 라이브러리이다.

특징

  • React는 선언형
  • 컴포넌트 기반으로 재사용성이 뛰어남
  • Virtual DOM(가상돔) 기반으로 가벼움
  • stateprops를 가짐

위 특징들은 리액트를 대표하는 키워드이다. 선언형(Declarative), 컴포넌트(Component), 재사용성(Reusable), Virtual DOM(가상돔)를 통해서 리액트의 본질을 설명할 수 있을 것이다.

⚡️선언형(Declarative)

컴포넌트를 얻기위해 JSX문법을 통해 구현한다. 여기서 JSX문법에 대해서는 자세히 설명하지 않고, 아래에서 설명하겠다. 다시 설명해서 JSX를 얻기 위한 알고리즘에 대한 구현을 하지는 않는다.
이 말은 리액트는 특정 요소 또는 특정 컴포넌트의 변경사항을 체크하는 알고리즘이나 리-렌더링 여부 등에 대한 로직을 구현하지 않는다는 것이다. 리액트의 용도는 위에서도 보았겠지만 '사용자 인터페이스를 구축'에 초점을 맞추고 있기 때문에 다른 부분에 대한 고민을 최소화하여 높은 생산성을 보장해주는 것이다. 간단하게 명령형과 선언형 코드를 비교해보자.

🖥️ 명령형 코드 : 결과물을 얻기 위한 과정에 집중

const numbers = [1, 2, 3, 4, 5]; //배열 선언
let sum; // 배열의 합을 담을 변수 선언

sum = 0;
for(let i = 0; i < numbers.length; i++){ //배열의 길이만큼 반복문 수행
	if(i%2 === 0){
	    //2의 배수일 경우 sum에 누적하여 연산
    	sum += numbers[i] * 2;
    }
}

🖥️ 선언형 코드 : 결과물에만 집중

const numbers = [1, 2, 3, 4, 5]; //배열 선언
let sum; // 배열의 합을 담을 변수 선언

sum = numbers
	.filter(i => i % 2)
	.map( i => i * 2)
	.reduce((acc, next) => acc + next);

선언형 프로그래밍의 특징은 다음과 같다.

  • 결과물에만 집중하며 복잡한 과정은 추상화하여 신경쓰지 않음
  • 명령형의 경우 한 줄씩 읽으며 다음에 일어날 상황에 대하여 추측해야한다. 반면에 선언형은 자세한 방법을 모르더라도 코드만 보고도 어떤 일이 발생할지 예측이 가능
  • 가독성이 좋으며 예측이 용이함

⚡️컴포넌트 기반(Component Based)

컴포넌트는 독립적인 단위의 소프트웨어 모듈을 의미한다. 즉, 독립적으로 동작할 수 있는 소규모 소프트웨어를 만들어내는 방법이라 할 수 있다. 리액트는 이러한 컴포넌트 기반의 프로그래밍을 통해 기존 UI를 다른 화면 또는 다른 프로젝트에서 사용하여 높은 재사용성을 보장한다.
리액트가 지원하는 컴포넌트의 종류는 다음과 같다.

  • 함수형 컴포넌트(Stateless Functional Component)
import React from 'react';

function TestComponent(props){ //여기서 props는 properties를 의미한다. 
	return( //함수형은 반환을 명시해주어야함
    	<div>hello, {props.name}</div> //JSX문법은 아래에서 알아보자.
    )
}
  • 클래스형 컴포넌트(Class Component)
import React from 'react';

class TestComponent extends React.Component {
	constructor(props) { // 생성자 메서드
		super(props);
	}
	
	componentDidMount() { // 상속받은 생명주기 메서드
	}
	
	render() { // 상속받은 화면 출력 메서드, 클래스형 컴포넌트는 render() 필수
		return <div>Hello, {this.props.name}</div>;
	}
}

export default TestComponent; //다른 JS에서 Import 하도록 내보내주기

⚡️가상DOM(Virtual DOM)

📖DOM?
Document Object Model로 문서 객체 모델을 의미하며, html 태그들을 javascript가 이용할 수 있도록 해주는 객체 모델을 의미

위 설명을 따르면 DOM은 HTML과 JavaScript를 서로 이어주는 역할을 하며, 트리구조로 만들어진 객체 모델을 의미하는 것이다. 아래 트리구조의 그림을 보면 이해가 될 것이다.

리액트를 사용하지 않고 특정 태그에 대한 스타일을 변경한다고 가정했을 때 DOM의 접근 메서드를 사용할 것이다.

document.getElementById("해당태그의 아이디");

이 경우 해당 접근메서드를 사용할 때 마다 위 그림에서 보이는 것처럼 트리구조를 타고 하나하나 확인을하며 접근을 할 것이다. 또한, 스타일이 변경되면 모든 태그와 CSS다시 연산하고 레이아웃을 구성하여 웹페이지 전체를 렌더링하고 나서야 다시 클라이언트에게 보여줄 것이다. 이러한 작업이 반복적 또는 동시에 대량의 작업이 들어온다면? 말하지 않아도 속도가 저하되는 것을 알고 있을 것이다. 이러한 메모리 누수속도 저하를 방지하기 위하여 가상돔을 사용하는 것이다.

가상돔은 실제 돔에 접근하여 조작을 하는 기존 방식 대신 추상화시킨 javascript 객체를 이용한다. 그렇다면 어떻게 리액트가 가상돔을 반영하는지 간단하게 절차를 알아보자.

  • 특정 페이지에 변화가 일어남
  • 데이터가 업데이트 되면 전체 UI가상돔에 리-렌더링
  • 기존의 가상돔최신 가상돔을 비교
  • 비교를 통해 가상돔 내에서 바뀐 부분만 실제 돔에 적용
  • 레이아웃 계산은 한 번만 이행

이렇게해서 리액트의 개념과 특징들에 대해 살펴보았다. 다음은 리액트를 어떻게 사용해야하는지 아주 기본적인 문법에 대해서 알아보자.


리액트 기본문법

JSX를 사용하기 전에 어떻게 리액트가 요소를 생성하는지 알아보고 넘어가자.

const div = React.createElement('div', {className: 'test'}, ....attribute 지정);

위와 같이 React DOM을 통해 createElement() 내부의 파라미터를 입력함으로서 요소를 생성할 수 있다. 하지만 이러한 방법을 이용하면 코드량도 많아지고 가독성이 떨어지기 때문에 많은 개발자들이 JSX문법을 사용하는 것이다. 그렇다면 본격적으로 JSX문법을 알아보자.

JSX

📖JavaScript XML로 JavaScript에 XML을 추가하여 확장한 문법

리액트에서는 본질적으로 렌더링 로직이 UI로직과 연결된다는 사실을 받아들이기 위해 JSX를 사용한다. 이 말은 이벤트가 처리되고, 시간에 따라 상태가 변하며, 화면에 표시하기 위해 데이터가 준비되는 방식등을 이야기하는 것이다. JSX가 필수는 아니지만 대부분의 개발자들이 JavaScript 코드 안에서 UI 관련 작업을 할 때 시각적으로 도움을 주기 때문에 가독성이 좋다.

⚡️ JSX 기본문법

//표현식 사용하기
const name = 'Mr.Hwang';

const TestElement = () => {
  return (
  	<h1>Hello, {name}</h1>}
  );
};

위 코드는 name이라는 변수를 선언하고 JSX내에서 표현하기 위하여 중괄호{}를 이용하여 사용한 것이다. 이렇게 JavaScript 영역에서 html태그 안에 선언된 변수를 표현할 수 있다.

const TestComponent = () => {
  return (
	<div>
  		<TestElement /> // 사용자가 정의한 컴포넌트 호출
  	</div>
  );
};

또는 위와 같이 자식을 정의하여 사용할 수도 있다. 당연히 자식에게도 변수를 표현할 수 있다.

⚡️ 컴포넌트 정의(함수형)

이번에는 컴포넌트를 정의하고 JSX안에서 Event를 연결하는 문법에 대해서 알아보자. 위에서 설명한 함수형과 클래스형 중에 함수형을 다뤄보겠다.

//함수형 컴포넌트 선언
function App(){
  	//카운트 변수 선언
  	let conut = 0;
  	//카운트 증가 함수 선언
  	const setCount = function(){
    	count++;
    }
  	//return 영역 내에 JSX 작성
	return(
    	<div>
      		//태그 내 변수 표현
      		<h1>Click count : {count}</h1>
			//이벤트 기능 구현
			<button onClick={setCount}>cilck</button>
      	</div>
    )
}

컴포넌트를 정의할 때 중요한 부분은 우선 컴포넌트 명의 첫글자는 대문자를 사용하는 것이다. 그리고 return은 하나의 JSX만 반환할 경우 대괄호()가 필요없으나 여러 JSX를 반환할 경우에는 대괄호()로 묶어주어야한다. 변수는 위에 설명한 것처럼 중괄호{}로 감싸주며, 함수도 마찬가지이다. Event를 지정할 때에는 카멜기법을 정확히 준수하여 정의해주어야한다.(예 : onClick -> onclick으로 하면 오류가 난다.)

⚡️ 태그 속성

이번에는 태그에 속성을 부여할 때 주의해야하는 부분에 대해서 다뤄보자.

//일반적으로 태그에 속성을 부여하는 형태
function APP(){
	return(
    	<div class="container">
      		<label for="test">label</label>
      	</div>
    )
}


//JSX문법으로 속성 부여
function APP(){
	return(
    	<div className="container">
      		<label htmlFor="test">label</label>
      	</div>
    )
}

위 코드를 보면 일반적으로 HTML 태그에 속성을 주는 것 처럼 정의하면 리액트에서는 인식을 하지 못한다. 이러한 이유는 html의 속성을 구분해줘야하기 때문이다. 리액트에도 클래스형 컴포넌트가 있으니 class라고만 정의하면 인식에 장애가 발생하는 것이다.

기본적인 문법에 대해서는 알아보았다. 그렇다면 이렇게 선언된 컴포넌트는 어떻게 호출하는지 알아보자.

⚡️컴포넌트 호출

//....생략
<body>
  <div>
    <App /> <!-- 컴포넌트명을 태그로 감싸서 호출 -->
  </div>
</body>

같은 html 문서내에 script영역이 위치한다면 원하는 위치에 호출해주면 된다. 별도로 js 파일로 유지하는 경우 import를 하고 기타 등등 절차가 필요하니 해당 부분은 차후에 설명하겠다.


마무리

이렇게해서 리액트의 아주 기초적인 부분을 같이 알아보았다. JavaScript만 이용했을때는 UI를 제어하고 통제하는게 여간 힘든 일이 아니었다.(그렇다고 리액트를 써서 드라마틱하게 변한 건 아니지만...) 꾸준히 리액트를 익히고 더 많은 정보들을 접하다 보면 사용자 인터페이스를 재사용성 높고 독립적이게 구성하는 날이 오지 않을까 생각해본다.

정리를 해본다면 리액트는 선언형으로 복잡한 과정은 신경쓰지 않고 추상화된 메서드를 통해 예측이 간편하며, 컴포넌트 기반으로 재사용성이 높다. 또한, 가상돔을 사용하여 페이지 전체에 대한 변경이 아닌 UI의 변경된 데이터만 수정하여 주기 때문에 메모리의 누수가 없으며 속도가 상대적으로 빠르다.

profile
서핑하는 개발자🏄🏽

0개의 댓글