react 기본 익히기 -JSX에 대하여-

1. JSX

 

A syntax extension to JavaScript

 

"자바스크립트의 확장 문법"

 

자바스크립트의 문법을 확장시킨 것

 

JavaScript와 XML/HTML을 합친 것

 

JSX의 X는 extension의 X로 볼 수도 있지만 실제로는 JavaScript and XML의 앞 글자를 따서 JSX라고 부르는 것

 

 

1-1) 예시

 

다음은 간단한 JSX 코드

 

대입연산자 =의 오른쪽에 특이하게 HTML코드가 나온다

 

HTML의 <h1> 태그를 사용해 Hello, world!라는 문자열을 값으로 갖고 있다

 

const element = <h1>Hello, world!</h1>;

 

결과적으로 자바스크립트 코드와 HTML 코드가 결합되어 있는 JSX 코드가 된다.

 

이 코드가 하는 역할은 <h1> 태그로 둘러싸인 문자열을 element라는 변수에 저장하는 것이다

 

 

2. JSX 역할

 

JSX는 내부적으로 XML/HTML 코드를 자바스크립트로 변환하는 과정을 거치게 된다.

 

실제로 JSX로 코드를 작성하더라도, 최종적으로는 자바스크립트 코드가 나온다.

 

여기서 JSX 코드를 자바스크립트 코드로 변환하는 역할을 하는 것이 리액트의 createElement()라는 함수이다.

 

class Hello extends React.Component {
    render() {
        return <div>Hello {this.props.toWhat}</div>;
    }
}

ReactDOM.render(
    <Hello toWhat="World" />,
    document.getElementById('root')
);

 

위 코드는 Hello라는 이름을 가진 리액트 컴포넌트가 나오고

 

컴포넌트 내부에서 자바스크립트 코드와 HTML 코드가 결합된 JSX를 사용하고 있는 것을 볼 수 있습니다.

 

이렇게 만든 Hello 컴포넌트를 ReactDOM의 render()함수로 실제 화면에 렌더링하고 있습니다.

 

class Hello extends React.Component {
    render() {
        return React.createElement('div', null, `Hello ${this.props.toWhat}`);
    }
}

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

 

 위 코드는 JSX를 사용하지 않고 순수한 자바스크립트 코드만을 사용해서 위에서 사용한 JSX 코드와 완전히 동일한 역할을 하도록 만든 코드이다.

 

달라진 점은 Hello 컴포넌트 내부에서 JSX를 사용했던 부분이 React.createElement()라는 함수로 대체된 것이다.

 

//JSX
class Hello extends React.Component {
    render() {
        return <div>Hello {this.props.toWhat}</div>;
    }
}

//JS
class Hello extends React.Component {
    render() {
        return React.createElement('div', null, `Hello ${this.props.toWhat}`);
    }
}

 

결국 JSX를 사용한 부분이 React.createElement()라는 함수로 대체된다는 것을 알 수 있다.

 

그래서 createElement() 함수를 호출해서 자바스크립트 객체가 나온다.

 

const element = (
    <h1 className = "greeting">
        Hello, world!
    </h1>
)

const element = React.createElement(
    'h1',
    {className: 'greeting'},
    'Hello, world!'
)

 

역시 위 코드는 JSX를 사용한 코드와 사용하지 않은 코드이며, 모두 동일한 역할을 한다.

 

JSX를 사용한 코드도 내부적으로는 createElement() 함수를 사용하도록 변환되기 때문이다.

 

함수 호출하면 아래와 같은 자바스크립트 객체가 나오게 된다.

 

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

 

3. createElement()함수

 

함수의 파라미터는 다음과 같다

 

 

첫번째 파라미터는 element의 유형

 

이 유형은 <div>나 <span>같은 HTML태그, 다른 리액트 컴포넌트가 들어갈 수도 있다.

 

두번째 파라미터는 props가 들어간다. 지금은 속성이라고만 생각해두면 되겠다.

 

세번째 파라미터는 children이 들어가는데 여기서 children이란 현재 element가 포함하고 있는 자식 element

 

react는 이런식으로 JSX 코드를 모두 createElement()함수를 사용하는 코드로 변환한다

 

그렇기 때문에 리액트에서 JSX를 사용하는 것은 필수는 아니지만, 코드가 더욱 간결해지고 생산성과 가독성이 올라가기 때문에 사용하는 것을 권장한다.

 

 

4. injection attack

 

injection attack이라 불리는 해킹 방법을 방어함으로써 보안성이 올라간다

 

injection attack은 쉽게 말해서 입력창에 문자나 숫자같은 일반적인 값이 아닌 소스코드를 입력해서 해당 코드가 실행되도록 만드는 해킹 방법

 

const title = response.potentiallyMaliciousInput;

//이 코드는 안전
const element = <h1>{title}</h1>;

 

title이라는 코드에 보안 위험 가능성이 있는 코드가 삽입되어 있다고 함

 

JSX 코드에는 괄호를 사용해서 title 변수를 임베딩함

 

ReactDOM은 렌더링하기 전에 임베딩된 값을 모두 문자열로 변환

 

명시적으로 선언되지 않은 값은 괄호 사이에 들어갈 수 없다고 함

 

그래서 XSS라 불리는 cross-site-scripting attacks를 방어하게 된다

 

 

5. JSX 사용법

 

JSX는 기본적으로 자바스크립트 문법을 확장했으며 모든 자바스크립트 문법을 지원한다

 

여기에 추가로 XML과 HTML을 섞어 쓰면 된다

 

 

5-1)

 

const name = '대혁';
const element = <h1>안녕, {name}</h1>;

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

 

위 코드에서 element 선언하는 부분처럼 HTML과 자바스크립트를 섞어서 작성한다

 

XML/HTML 코드를 사용하다가 중간에 자바스크립트 코드를 쓰고 싶다면 중괄호를 써서 묶어준다

 

{name}이라는 부분이 name이라는 자바스크립트 변수를 참조하기 위해 괄호를 사용한 것이다.

 

 

5-2)

 

function formatName(user) {
    return user.firstName + ' ' + user.lastName;
}

const user = {
    firstName: 'Inje',
    lastName: 'Lee',
}

const element = (
    <h1>
        Hello, {formatUser(user)}
    </h1>
)

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

 

위 코드에서 HTML 코드 사이에 괄호 { } 를 사용해서 변수가 아닌 formatUser()라는 자바스크립트 함수를 호출하고 있다.

 

function getGreeting(user){
    if (user) {
        return <h1>Hello, {formatName(user)}!</h1>
    }

    return <h1>Hello, Stranger.</h1>
}

 

위 코드는 JSX를 사용해서 사용자 이름에 따라 다른 인사말을 표시하도록 만든 함수이다.

 

사용자가 존재하면 formatName()이라는 함수를 써서 formatting된 이름을 출력

 

그렇지 않으면 Stranger에게 하는 인사말을 출력

 

 

5-3) 태그 속성에 값을 넣기

 

큰따옴표 사이에 문자열을 넣거나, 중괄호 사이에 자바스크립트 코드를 넣는다.

 

"JSX에서는 중괄호를 사용하면 무조건 자바스크립트 코드가 들어간다"

 

//큰 따옴표 사이에 문자열을 넣거나
const element = <div tabIndex="0"></div>;

//중괄호 사이에 자바스크립트 코드를 넣는다
const element = <img src={user.avatarUrl}></img>;

 

5-4) children 정의

 

HTML을 사용하듯이 상위 태그가 하위 태그를 둘러싸도록 하면 자연스럽게 children 정의

 

const element = (
    <div>
        <h1>안녕하세요</h1>
        <h2>열심히 리액트를 공부해 봅시다!</h2>
    </div>
)

 

6. 실습 따라해보면서 익히기

 

$ npx create-react-app my-app으로 리액트 앱 생성

 

 

 

위와 같이 src/chapter_03/Book.jsx를 생성

 

import React from 'react';

function Book(props) {
    return (
        <div>
            <h1>{`이 책의 이름은 ${props.name}입니다.`}</h1>
            <h2>{`이 책은 총 ${props.numOfPage}페이지로 이뤄져 있습니다.`}</h2>
        </div>
    )
}

export default Book;

 

Book 컴포넌트는 props로 name과 numOfPage를 받아서 이를 출력하는 컴포넌트이다.

 

그냥 대충 봐도 어느 정도 이해할 수 있는 가독성이 높고 직관적인 코드이다..??

 

JSX를 사용하지 않고 작성하면 다음과 같다..

 

import React from 'react';

function Book(props) {
    return React.createElement(
        'div',
        null,
        [
            React.createElement(
                'h1',
                null,
                `이 책의 이름은 ${props.name}입니다.`
            ),
            React.createElement(
                'h2',
                null,
                `이 책은 총 ${props.numOfPage}페이지로 이뤄져 있습니다.`
            )
        ]
    )
}

export default Book;

 

코드가 상당히 길어지기때문에 웬만하면 jsx를 사용하는 것을 권장함

 

 

Library.jsx도 생성하고 다음과 같이 코드 작성

 

import React from 'react';
import Book from './Book';

function Library(props) {
    return (
        <div>
            <Book name="처음 만난 파이썬" numOfPage={300} />
            <Book name="처음 만난 AWS" numOfPage={400} />
            <Book name="처음 만난 리액트" numOfPage={500} />
        </div>
    );
}

export default Library;

 

Library 컴포넌트는 총 3개의 Book 컴포넌트를 렌더링한다.

 

이렇게 작성한 컴포넌트를 화면에 렌더링할려면 index.js를 수정해야한다.

 

 

 

Library 컴포넌트를 import하고, root.render 부분에 

 

<React.StrictMode><App /></React.StrictMode>

 

라고 적혀있는데, 실제 화면에 렌더링하기 위해 <App />을 지우고, 

 

<React.StrictMode>

<Library />

</React.StrictMode>로 작성

 

그리고 npm start로 수행하면 다음과 같다..

 

 

 

TAGS.

Comments