Front-end/React

[React] JSX(JavaScript and XML)

늘이 2023. 5. 7. 17:16

 

1.  JSX(JavaScript and XML)

- 자바스크립트와 XML/HTML을 함께 사용할 수 있는 자바스크립트의 확장 문법

// HTML의 <h1>태그를 사용한 Hello, world!라는 문자열을 값으로 가지고있는 것을 const형의 element 변수에 대입
const element = <h1>Hello, world!</h1>;

 

- 내부적으로 XML/HTML 코드를 자바스크립트로 변환하는 과정을 거침

- 리액트의 createElement() 함수는 JSX코드를 자바스크립트 코드로 변환해주는 역할을 함

-> JSX코드를 작성해도 최종적으로 자바스크립트 코드가 나옴

 

 

2.  JSX의 역할

 

1) JSX로 작성된 코드는 모두 자바스크립트 코드로 변환

 

JSX로 작성한 코드와 순수 자바스크립트로 작성한 코드 비교

- JSX로 작성한 코드

// Hello라는 이름을 가진 리액트 컴포넌트, 컴포넌트 내부에서 자바스크립트 코드와 HTML 코드가 결합된 JSX사용
class Hello extends React.Component {
	render() {
    	return <div>Hello {this.props.toWhat}</div>;
	}
}

// 위에서 만들어진 컴포넌트를 ReactDOM의 render()함수를 사용해서 실제 화면에 렌더링
ReactDOM.render(
    <Hello towhat="World" />,
    document.getElementById('root')
);

 

- 순수 자바스크립트로 작성한 코드

class Hello extends React.Component {
    render() {
    // JSX를 사용했던 부분이 React.createElement()라는 함수로 대체
    return React.createElement('div', null, 'Hello ${this.props.toWhat}');
    }
}


ReactDOM.render(
    React.createElement(Hello, {towhat:'World'}, null),
    document.getElementById('root')
);

 

-> JSX를 사용했을 때 코드가 더욱 간결해지고 생산성과 가독성이 올라가기 때문에 JSX 사용을 권장

 

cf) ReactDOM.render

더보기

ReactDOM.render 코드는 컴포넌트를 페이지에 렌더링하는 역할을 하며 react-dom 모듈을 불러와 사용할 수 있다.

이 함수의 첫 번째 파라미터에는 페이지에 렌더링할 내용을 JSX 형태로 작성하고, 두 번째 파라미터에는 해당 JSX를 렌더링할 document 내부 요소를 설정한다.

위에서는 id가 root인 요소 안에 렌더링을 하도록 설정한 코드이다.

이 요소는 public/index.html 파일을 열어보면 확인할 수 있다.

 

2) JSX를 사용한 코드는 내부적으로 createElement()함수를 사용하도록 변환되기 때문에 자바스크립트 객체가 나오게 됨

// JSX를 사용한 코드
const element = (	
    <h1 className="greeting">
    Hello, world! 
    </h1>
)


// JSX를 사용하지 않은 코드
const element = React.createElement(
    'h1',
    { className: 'greeting' },
    'Hello, world!'
)

 

리액트에서는 createElement() 함수의 결과인 자바스크립트 객체를 엘리먼트라고 부름

(createElement는  element를 생성해서 리턴)

 

element() 함수

const element = {
    type: 'h1',
    props: {
	className: 'greeting',
	children: 'Hello, world!'
    }
}

 

element()함수의 파라미터

React.createElement (
    type, // 엘리먼트 유형(type): <div>, <span> 같은 HTML 태그, 리액트 컴포넌트가 들어갈 수 있음
    [props], // 속성 
    [...children] // children: 현재 엘리먼트가 포함하고 있는 자식 엘리먼트
)

 

 

3. JSX의 장점

 

1) 코드가 간결해짐

// JSX 사용함
<div>Hello, {name}</div>

// JSX사용안함
React.createElement ('div', null, 'Hello, ${name}');

 

 

2) 가독성 향상

 

3) Injection Attack 이라 불리는 해킹 방법을 방어함으로써 보안성 상승

Injection Attack: 입력창에 문자나 숫자 같은 일반적인 값이 아닌 소스코드를 입력하여 해당 코드가 실행되도록 만드는 해킹 방법

// title이라는 변수에 잠재적으로 보안 위험의 가능성이 있는 코드가 삽입되어 있음
const title = response. potentiallyMaliciousInput;

 // 괄호를 사용해서 title 변수를 임베딩(삽입)
const element = <h1›{title}</h1>;

 

기본적으로 ReactDOM은 렌더링 전에 임베딩 값을 모두 문자열로 변환함

-> 명시적으로 선언되지 않은 값은 괄호 사이에 들어갈 수 없음

-> XSS(cross-site-scripting attacks)를 방어할 수 있음

 

 

4. JSX 사용법

 

1) 기본적으로 모든 자바 스크립트 문법 지원

2) 자바스크립트에 XML과 HTML 섞어서 사용

3) 중괄호를 사용하여 자바 스크립트 코드 삽입 -> 데이터 바인딩

const name = 'sky';
/* 엘리먼트 선언, HTML과 자바스크립트가 섞인 형태로 코드 작성
* XML/HTML 코드를 사용하다가 중간에 자바스크립트 코드 사용할 부분에 중괄호 '{}' 로 묶어주면 됨
*/
const element = <h1>안녕, {name}</h1>;

ReactDOM.render(
	element,
	document.getElementById('root') 
);

 

4) 인라인 스타일링

<h1 style={{color : 'red', fontSize : '16px'}}>제목</h1>

 

5) 감싸인 요소

컴포넌트에 여러 요소가 있다면 반드시 부모 요소 하나로 감싸야 함

이유: Virtual DOM에서 컴포넌트 변화를 감지해 낼 때 효율적으로 비교할 수 있도록 컴포넌트 내부는 하나의 DOM 트리 구조로 이루어져야 한다는 규칙이 있기 때문

// 컴파일 에러 발생, 요소 여러 개가 부모 요소 하나에 감싸져 있지 않음
import React from 'react';
 
function App() {
  return (
    <h1>리액트 안녕!</h1>
    <h2>잘 작동하니?</h2>
  )
}
 
export default App;


// 규칙이 적용된 코드, <div> 태그 사용
import React from 'react';
 
function App() {
  return (
    <div>
      <h1>리액트 안녕!</h1>
      <h2>잘 작동하니?</h2>
    </div>
  );
}
 
export default App;


// 규칙이 적용된 코드, <Fragment> 사용( '<>'로 간략하게 표현 가능)
import React, { Fragment } from 'react';
 
function App() {
  return (
    <Fragment>
      <h1>리액트 안녕!</h1>
      <h2>잘 작동하니?</h2>
    </Fragment>
  );
}
 
export default App;

 

 

6) If문 대신 조건부 연산자(삼항 연산자)사용

JSX 내부의 자바스크립트 표현식에서 if문은 사용할 수 없지만 조건에 따라 다른 내용을 렌더링해야 할 때는 JSX 밖에서 if문을 사용하여 사전에 값을 설정하거나, { } 안에 조건부 연산자를 사용하면 됨

import React from 'react';
 
function App() {
  const name = '리액트';
  return (
    <div>
      {name === '리액트' ? (
        <h1>리액트입니다.</h1>
      ) : (
        <h2>리액트가 아닙니다.</h2>
      )}
    </div>
  );
}
 
export default App;

 

7) AND 연산자(&&)을 사용한 조건부 렌더링

& 연산자로 조건부 렌더링 할 수 있는 이유는 리액트에서 flase를 렌더링할 때는 null과 마찬가지로 아무것도 나타나지 않기 때문임

import React from 'react';
 
function App() {
  const name = '리액트';
  return <div>{name === '리액트' && <h1>리액트입니다.</h1>}</div>;
}
 
export default App;

 

한 가지 주의해야할 점은 falsy한 값인 0은 예외적으로 화면에 나타남

const number = 0;
return number && <div>내용</div>

 

 

4. JSX 주의사항

1) undefined를 렌더링하지 않기

// App(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
// 에러 발생
import React from 'react';
import './App.css';
 
function App() {
  const name = undefined;
  return name;
}
 
export default App;

 

에러 발생을 막기 위해서 OR(||) 연산자 이용

어떤 값이 undefined일 수 있다면 사용할 값을 지정할 수 있음

import React from 'react';
import './App.css';
 
function App() {
const name = undefined;
return name || '값이 undefined입니다.';
}
 
export default App;

 

JSX 내부에서 undefined를 렌더링하는 것은 가능