JSX 란?

Date
Created
Apr 28, 2024 08:05 AM
Tags
2장

JSX

JSX는 XML과 유사한 내장형 구문, 리액트에 종속하지 않는 독자적인 문법으로 보는 것이 옳다.
JSX는 ECMAScript 표준이 아니기에 브라우저나 v8, deno에서 실행되도록 만들어진 구문이 아님.
그렇기에 트랜스파일러를 거쳐야 자바스크립트 런타임이 이해할 수 있는 코드로 변환이 됨.
 
JSX는 HTML이나 XML을 자바스크립트 내부에 표현하는 것이 유일한 목적이 아님.
JSX의 설계 목적은 다양한 트랜스파일러에서 다양한 속성을 가진 트리 구조를 토큰화해 ECMAScript로 변환하는데 초점을 두고 있음.
즉 JSX 내부에 트리 구조로 표현하고 싶은 다양한 것들을 작성해 두고, 이 JSX를 트랜스파일 과정을 거쳐 자바스크립트가 이해할 수 있는 코드로 변환하는것.
JSX는 주로 리액트 내부에서 반환하는 HTML과 XML 외에도 다른 구문으로 확장될 수 있게끔 고려되어있다.

JSX의 정의

JSX는 4가지 컴포넌트를 기반으로 구성되어 있음

JSXElement

JSX를 구성하는 가장 기본 요소. HTML의 요소와 비슷한 역할을 함.
JSXElement이 되기 위해선 다음과 같은 형태 중 하나여야만 함.
  • JSXOpeningElement: 일반적으로 볼 수 있는 요소. JSXOpeningElement로 시작했다면 후술할 JSXClosingElement가 동일한 요소로 같은 단계에서 선언돼 있어야 올바른 JSX 문법으로 간주됨.
    • <JSXElement JSXAttributes(optional)>
  • JSXClosingElement: JSXOpeningElement가 종료되었음을 알리는 요소, 반드시 JSXOpeningElement와 쌍으로 사용되어야 함.
    • <JSXElement />
  • JSXSelfClosingElement: 요소가 시작되고, 스스로 종료되는 형태를 의미. <script />와 동일한 모습을 띠고 있다. 내부적으로 자식을 포함할 . 수없음. <JSXElement JSXAttributes(optional) />
  • JSXFragment: 아무 요소가 없는 형태 JSXSelfClosingElement 형태를 띌 수는 없다.
    • <>JSXChildren(optional)</>
리액트에서 HTML 구문 이외에 사용자 컴포넌트는 반드시 대문자로 써야하는데 이는 HTML 태그명과 사용자 컴포넌트를 구별하기 위해. HTML를 딱 지정해서 필터링 하지 않은 이유는 추후 추가될 HTML 태그의 확장성을 고려한듯.

JSXElementName

JSXElement의 요소 이름으로 쓸 수 있는 것.
  • JSXIdentifier: JSX 내부에서 사용할 수 있는 식별자를 의미함. 자바스크립트 식별자 규칙과 동일함. <$></$> <_></_>도 가능하지만 이외에 숫자로 시작하거나 다른 특수문자는 안된다.
  • JSXNamespacedName: JSXIdentifier: JSXIdentifier 의 조합 : 을 사용해 서로 다른 식별자를 이어주는 것도 하나의 식별자로 취급됨. 1개만 가능하고 두개 이상은 올바른 식별자로 취급하지 않음.
  • JSXMemberExpression: JSXIdentifier.JSXIdentifier의 조합 . 을 통해 서로 다른 식별자를 이어주는 것. JSXNamespacedName과 다르게 .을 여러개 이어서 하는게 가능하지만 JSXNamespacedName과는 함께 사용 불가능

JSXAttributes

JSXElement에 부여할 수 있는 속성을 의미함. 필수값은 아니다.
  • JSXSpreadAttributes: 자바스크립트의 전개 연산자와 동일한 역할.\
    • {…AssignmentExpression} : 단순히 객체뿐만 아니라 자바스크립트에서 AssignmentExpression 로 취급되는 모든 표현식이 존재할 수 있다.(조건문, 표현식 함수 등)
  • JSXAttribute: 속성을 나타내는 키와 값으로 짝을 이루어 표현 키는 JSXAttributeName, 값은 JSXAttributeValue로 불림.
    • JSXAttributeName: JSXIdentifier와 JSXNamespacedName 이름이 가능
    • JSXAttributeValue:
      • 문자열
      • {…AssignmentExpression} : 자바스크립트에서 값을 할당할 떄 쓰는 표현식 변수에 값을 넣을 수 있는 표현식은 JSX 속성의 값으로도 가능함.
      • JSXElement: 값으로 다른 JSX 요소가 가능함.

JSXChildern

JSXElement의 자식 값을 나타냄. JSX는 속성을 가진 트리 구조를 나타내기 위해 만들어 졌기 때문에 JSX로 부모와 자식 관계를 나타낼 수 있으며, 그 자식을 JSXChildren이라고 함.
  • JSXChild: JSXChildern을 이루는 기본 단위 JSXChildern은 JSXChild를 0개 이상 가질 수 있다.
    • JSXText: {, <, >, } 을 제외한 문자열 이걸 표현하고 싶으면 문자열로 표현하기 ‘{’
    • JSXElement: 값으로 다른 JSX 요소가 가능
    • JSXFragment: 값으로 빈 JSX 요소가 가능 <></>
    • {JSXChildExpression}: AssignmentExpression 을 의미함.
    • export default function App (){ return <>{(() => 'foo')()}</>

JSXString

JSXText와 JSXAttributeValue는 HTML과 JSX 사이에 복사와 붙여넣기를 쉽게 할 수 있게 되어있음.
HTML에서 사용 가능한 문자열은 JSXString에서도 가능함.

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

리액트에서 JSX를 변환할 때 @babel/plugin-transform-react-jsx 를 사용함.

꿀팁

JSX가 변환되는 특성을 활용하면 간결히 처리할 수 있음
props 여부에 따라 children 요소만 달라지는 경우 내용을 삼항 연산으로 처리할 필요가 없음.
function TextOrHeading({ isHeading, children, }: PropsWithChildren<{isHeading: boolean}>{ return isHeading ? ( <h1 className='txt'>{children}</h1> ):( <span className='txt'>{children}</span> ) } // 리펙토링 import {createElement} from 'react'; function TextOrHeading({ isHeading, children, }: PropsWithChildren<{isHeading: boolean}>{ return createElement( isHeading ? 'h1' : 'span', {className: 'text' }, children ) }

마무리

JSX 문법에 있지만 React가 사용하지 않는 것은JSXNamespacedName, JSXMemberExpression이 있음.
리액트에서는 사용하지 않지만 preact, solidjs 등등 이런 JSX 문법을 사용할 수도 있으니 알아두자.
때에 따라 createElement로 직접 컴포넌트를 구성하는게 효율적일 수 있다.
그리나 JSX를 잘 알아야 한다.