Skip to content

Latest commit

 

History

History
201 lines (145 loc) · 5.69 KB

File metadata and controls

201 lines (145 loc) · 5.69 KB

📖JSX의 정의

JSX는 흔히 개발자들이 알고 있는 XML과 유사한 내장형 구문이다. JSX가 포함된 구문을 아무런 처리 없이 그대로 실행하면 에러가 발생하며, 반드시 트랜스파일러를 거쳐야 비로소 자바스크립트 런타임이 이해할 수 있는 의미 있는 자바스크립트 코드로 변환된다. JSX의 설계 목적은 다양한 트랜스파일러에서 다양한 속성을 가진 트리 구조를 토큰화 해 ECMAScript로 변환하는데 초점을 두고 있다.

요약하자면 JSX는 자바스크립트 내부에서 표현하기 까다로웠던 XML 스타일의 트리 구문을 작성하는 데 많은 도움을 주는 새로운 문법이라고 볼 수 있다.

JSX는 기본적으로 JSXElementJSXAttributesJSXChildrenJSXStrings라는 4가지 컴포넌트를 기반으로 구성되어 있다.

JSXElement

JSX를 구성하는 가장 기본 요소로, HTML의 element와 비슷한 역할을 한다. JSXElement가 되기 위해서는 다음과 같은 형태 중 하나여야 한다.

  • JSXOpeningElement
    • 일반적으로 볼 수 있는 요소
    • JSXOpeningElement로 시작했다면 후술할 JSXClosingElement가 동일한 요소로 같은 단계에서 선언되어 있어야 올바른 JSX 문법으로 간주된다.
    • <JSXElemnt JSXAttributes(optional)>
  • JSXClosingElement
    • JSXOpeningElement가 종료됐음을 알리는 요소
    • 반드시 JSXOpeningElement와 쌍으로 사용되어야 한다.
  • JSXSelfClosingElement
    • 요소가 시작되고 스스로 종료되는 형태
    • 내부적으로 자식을 포함할 수 없다.
    • <JSXElement JSXAttributes(optional) />
  • JSXFragment
    • 아무런 요소가 없는 형태
    • JSXSelfClosingElement 형태를 띨 수는 없다.
    • <>JSXChildren(optional)</>

JSXElementName

JSXElement의 요소 이름으로 쓸 수 있는 것을 의미

  • JSXIdentifier
    • JSX 내부에서 사용할 수 있는 식별자
  • JSXNamespacedName
    • JSXIdentifier:JSXIdentifier의 조합
  • JSXMemberExpression
    • JSXIdentifier.JSXIdentifier의 조합

JSXAttributes

JSXElement에 부여할 수 있는 속성을 의미한다.

모든 경우에서 필수값이 아니고, 존재하지 않아도 에러가 나지 않는다.

function Example() {
	return (
    	<Component attribute="hello"></Component>
        <Component attribute=<div>hello</div>></Component>
    );
}

JSXChildren

JSXElement의 자식 값을 나타낸다.

JSXChild

JSXChildren을 이루는 기본 단위

JSXChildren은 JSXChild를 0개 이상 가질 수 있다.

function Example() {
	return (
    	<>{'{}'}</>
        <>{(() => 'foo')()}</>
    );
}

JSXStrings

HTML에서 사용 가능한 모든 문자열은 JSXStrings에서도 사용 가능하다.

자바스크립트와는 한가지 중요한 차이점이 있다.

\로 시작하는 이스케이프 문자 형태소 또한 제약없이 사용할 수 있다.

\는 자바스크립트에서 특수문자를 처리할 때 사용되므로 제약사항이 있지만, HTML에서는 아무런 제약 없이 사용할 수 있다.

💻JSX 예제

//하나의 요소로 구성된 가장 단순한 형태
const ComponentA = <A>안녕하세요</A>;

//자식이 없이 SelfClosingTag로 닫혀있는 형태
const ComponentB = <A />;

//옵션을 { }와 전개 연산자로 넣음
const ComponentC = <A {...(required: true)} />;

//속성만 넣음
const ComponentD = <A required />;

//속성과 속성값을 넣음
const ComponentE = <A required={false} />;

//문자열은 작은 따옴표와 큰 따옴표 모두 가능
const ComponentF = (
  <A>
    <B text="리액트" />
  </A>
);

//옵션의 값으로 JSXElement를 넣음
const ComponentG = (
  <A>
    <B optionalChildren={<>리액트</>} />
  </A>
);

//여러개의 자식 포함
const ComponentH = (
  <A>
    리액트
    <B text="리액트 2" />
  </A>
);

🔄JSX는 어떻게 자바스크립트에서 변환될까?

@babel/plugin-transform-react-jsx 플러그인은 JSX 구문을 자바스크립트가 이해할 수 있는 형태로 변환한다.

  • JSX 코드
const ComponentA = <A required={true}>Hello World</A>;

const ComponentB = <>Hello World</>;

const ComponentC = (
  <div>
    <span>Hello World</span>
  </div>
);
  • JSX 코드를 @babel/plugin-transform-react-jsx 로 변환한 결과
'use strict’

var ComponentA =React.createElement(
 A,
  {
    required: true,
  },
'Hello World',
)

var ComponentB = React.createElement(React.Fragment, null, ’Hello World’)

var ComponentC = React.createElement(
      ’div’,
      null,
      React.createElement(’span’, null, ’Hello World'),
)
  • 리액트 17, 바벨 7.9.0 이후 버전에서 추가된 자동 런타임으로 트랜스파일한 결과
'use strict’

var _jsxRuntime = require (’custom-jsx-library/jsx-runtime')

var ComponentA = (0, _jsxRuntime.jsx)(A,
{
  required: true,
  children : 'Hello World' ,
})

var ComponentB = (0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
  children : 'Hello World’,
})

var ComponentC = (0, _jsxRuntime.jsx)('div’, {
  children: (0, _jsxRuntime.jsx)(’span’, {
    children: ’Hello World’
  }),
})

JSX 반환값이 결국 React.createElement로 귀결된다는 사실을 활용해 리팩터링할 수 있다.

📝정리

JSX 문법에는 있지만 리액트에서 사용하지 않는 것

  • JSXNamespacedName
  • JSXMemberExpression

JSX와 React.createElement의 효율적 사용

JSX는 대부분의 경우 편리하고 간결하게 컴포넌트를 작성하는데 많은 도움을 주지만, 때에 따라서는 직접 createElement를 사용해 컴포넌트를 구성하는 편이 더 효율적일 수 있다.