[React] JSX(TSX) 문법 정리

2025. 8. 20. 13:58·🖥️ Frontend/React

💡 JSX(TSX)란?

JSX는 JavaScript를 확장한 문법(JavaScript XML)입니다. 쉽게 말해, JavaScript 파일 안에서 HTML과 비슷한 코드를 작성할 수 있게 해주는 특별한 문법이죠. 우리가 보기엔 HTML 같지만, 사실 이 코드는 브라우저가 읽기 전에 바벨(Babel)이라는 도구를 통해 순수한 JavaScript 객체로 변환됩니다.

TSX도 JSX의 문법을 따릅니다.

  • React는 UI를 만들기 위한 라이브러리입니다.
  • JSX는 React에서 UI를 더 쉽고 직관적으로 표현하기 위해 사용하는 문법입니다.

예를 들어, 우리가 이렇게 JSX를 작성하면:

const element = <h1>안녕하세요, 리액트!</h1>;

바벨은 이 코드를 아래와 같은 순수 JavaScript 코드로 바꿔줍니다.

const element = React.createElement('h1', null, '안녕하세요, 리액트!');

결국 JSX는 복잡한 React.createElement 코드를 더 편하게 작성하기 위한 "문법적 설탕(Syntactic Sugar)"인 셈입니다. 이 덕분에 우리는 마치 HTML을 다루듯 익숙하게 UI 구조를 짤 수 있고, 동시에 JavaScript의 모든 강력한 기능을 활용할 수 있습니다.


🚀 JSX 핵심 문법

이제 본격적으로 JSX를 사용할 때 반드시 알아야 할 핵심 규칙을 살펴보겠습니다.

1. 모든 태그는 단 하나의 최상위 태그로 감쌀 것

JSX 표현식은 반드시 하나의 부모 요소만 반환해야 합니다. 여러 개의 태그를 병렬로 나열하면 오류가 발생합니다. 이는 컴포넌트가 반환해야 하는 결과물이 하나의 '덩어리'여야 한다는 React의 규칙 때문입니다.

// ⭕ 올바른 예시: div라는 하나의 부모 태그로 감싸기
return (
  <div>
    <h1>안녕하세요!</h1>
    <p>JSX 문법을 배우고 있습니다.</p>
  </div>
);

// ❌ 잘못된 예시: 부모 태그 없이 여러 태그를 반환
return (
  <h1>안녕하세요!</h1><p>이 코드는 오류를 발생시킵니다.</p>
);

2. JSX 내부 주석

JSX 내부의 주석은 일반적인 HTML 주석(``)이나 JavaScript 주석(//, /* */)과 다릅니다. 중괄호 {} 안에 JavaScript의 여러 줄 주석 형태를 사용해야 합니다.

VS Code에서는 주석을 달고 싶은 부분을 선택하고 Alt + Shift + A 단축키를 사용하면 바로 JSX 주석을 만들 수 있습니다.

function MyComponent() {
  return (
    <div>
      {/* 이렇게 한 줄 주석을 작성할 수 있습니다. */}
      <p>이 문장은 화면에 보입니다.</p>
      {/*
        물론,
        여러 줄에 걸쳐
        주석을 작성하는 것도 가능합니다.
      */}
    </div>
  );
}`

 3. 불필요한 <div> 대신 Fragment를 사용할 것

가끔 최상위 태그 규칙을 지키기 위해 의미 없는 <div>로 감싸야 할 때가 있습니다. 이렇게 불필요한 태그는 DOM 구조를 복잡하게 만들고 스타일링에 문제를 일으킬 수 있죠. 이럴 때 Fragment를 사용하면 좋습니다. <React.Fragment> 또는 축약형인 <>를 사용하면, 실제 DOM에는 추가되지 않는 가상의 부모 요소를 만들 수 있습니다.

import React from 'react';

function MyComponent() {
  return (
    // <div> 대신 Fragment(<>)를 사용해 깔끔한 DOM 구조를 유지합니다.
    <>
      <h1>안녕하세요!</h1>
      <p>Fragment를 사용하고 있어요.</p>
    </>
  );
}

4. JavaScript 변수를 사용하려면 중괄호 {}

JSX 내부에서 JavaScript 변수나 표현식의 결과값을 보여주고 싶을 때는 중괄호 {}로 감싸주면 됩니다.

const name = '리액트';
const studyTopic = 'JSX 문법';

return (
  <h1>{name}로 {studyTopic} 배우기</h1>
);
// 결과: <h1>리액트로 JSX 문법 배우기</h1>

5. 조건부 렌더링은 삼항 연산자를 활용하세요.

JSX 내부에서는 if 문을 직접 사용할 수 없습니다. 대신 삼항 연산자 (조건 ? 결과1 : 결과2)를 사용하여 조건에 따라 다른 UI를 렌더링하는 것이 일반적입니다.

const isLoggedIn = true;

return (
  <div>
    {isLoggedIn ? <p>환영합니다!</p> : <p>로그인이 필요합니다.</p>}
  </div>
);

6. 렌더링할 내용이 없다면 null을 사용

특정 조건에서 아무것도 화면에 그리고 싶지 않다면 null을 반환하면 됩니다. React는 null이나 false를 렌더링하지 않습니다. 하지만 undefined를 반환하면 오류가 발생할 수 있으니 주의해야 합니다.

// 렌더링할 내용이 없을 때
if (someConditionIsFalse) {
  return null; // 아무것도 렌더링하지 않음
}

// undefined 변수를 안전하게 처리하기
const value = undefined;
return <div>{value || '기본값'}</div>; // value가 undefined이면 '기본값'을 출력

7. 인라인 스타일은 객체 형태로 작성

JSX에서 HTML 요소에 직접 스타일을 적용할 때는 스타일 객체를 사용합니다. CSS 속성 이름은 하이픈(-) 대신 카멜 케이스(camelCase)로 작성해야 합니다. 예를 들어, background-color는 backgroundColor로, font-size는 fontSize로 바뀝니다.

const divStyle = {
  backgroundColor: 'navy',
  color: 'white',
  fontSize: '24px',
  padding: '1rem'
};

return <div style={divStyle}>스타일이 적용된 텍스트</div>;

8. CSS 클래스는 className을 사용

HTML에서는 class 속성을 사용해 CSS 클래스를 지정하지만, JSX에서는 class가 JavaScript의 예약어이기 때문에 **className**이라는 속성을 사용해야 합니다.

// 일반 CSS 파일에 .container 클래스가 정의되어 있다고 가정
import './App.css';

return <div className="container">컨텐츠</div>;

9. 태그는 반드시 닫기

HTML에서는 <img>나 <br>처럼 닫는 태그가 없는 태그들이 허용되지만, JSX는 XML 규칙을 따르기 때문에 모든 태그를 명시적으로 닫아야 합니다. 내용이 없는 태그는 셀프 클로징(self-closing) 형식인 <tag />로 닫아주세요.

// 일반 CSS 파일에 .container 클래스가 정의되어 있다고 가정
import './App.css';

return <div className="container">컨텐츠</div>;

// ⭕ 올바른 예시
<img src="image.jpg" alt="이미지" />
<input type="text" /><br />// ❌ 잘못된 예시 (오류 발생)
<img src="image.jpg" alt="이미지">

10. for, onclick 등 HTML 속성 이름의 차이

className과 마찬가지로, 몇몇 HTML 속성은 JavaScript 예약어와의 충돌을 피하기 위해 JSX에서 다른 이름을 사용합니다.

  • for (라벨) → htmlFor
  • onclick, onmouseover 등 이벤트 핸들러 → onClick, onMouseOver (카멜 케이스)
<>
  <label htmlFor="my-input">입력:</label><input id="my-input" type="text" />
</>

11. 이벤트 핸들링은 함수를 직접 전달

React에서 이벤트를 처리할 때는 이벤트 핸들러 속성(예: onClick)에 문자열이 아닌 함수를 직접 전달해야 합니다.

function handleClick() {
  alert('버튼이 클릭되었습니다!');
}

// 함수 자체를 전달합니다. handleClick()처럼 호출하면 안됩니다!
return <button onClick={handleClick}>클릭하세요</button>;

12. 중괄호 안에는 어떤 JavaScript 표현식이든 OK!

중괄호 {} 안에는 변수뿐만 아니라, 함수 호출, 계산 등 유효한 모든 JavaScript 표현식을 넣을 수 있습니다.

const name = 'React';

return (
  <h1>{name.toUpperCase()} 배우기</h1> // "REACT 배우기" 출력
);

13. 배열을 렌더링할 땐 key 속성이 필수

map() 함수 등을 사용해 배열의 각 항목을 컴포넌트나 엘리먼트로 변환할 때, React는 각 항목을 식별하기 위해 고유한 key 속성을 요구합니다. key는 형제 요소들 사이에서만 고유하면 되며, 주로 데이터의 id를 사용합니다. key는 React가 어떤 항목이 변경, 추가, 삭제되었는지 효율적으로 파악하는 데 매우 중요합니다.

const items = [
  { id: 1, name: '사과' },
  { id: 2, name: '바나나' },
  { id: 3, name: '오렌지' }
];

const listItems = items.map(item => (
  <li key={item.id}>{item.name}</li>
));

return <ul>{listItems}</ul>;

14. PropTypes와 defaultProps로 컴포넌트 안정성 높이기

  • PropTypes: 다른 개발자나 미래의 내가 이 컴포넌트에 어떤 props를 어떤 타입으로 전달해야 하는지 명확히 알려주는 명세서와 같습니다. 타입이 맞지 않으면 콘솔에 경고가 나타나 버그를 예방하는 데 도움이 됩니다.
  • defaultProps: props가 전달되지 않았을 경우 사용할 기본값을 설정합니다.
import PropTypes from 'prop-types';

function Greeting({ name }) {
  return <h1>안녕하세요, {name}님!</h1>;
}

// props 타입 검증
Greeting.propTypes = {
  name: PropTypes.string.isRequired // name은 반드시 문자열이어야 함
};

// props 기본값 설정
Greeting.defaultProps = {
  name: '방문자'
};

15. 사용자 정의 컴포넌트는 항상 대문자로 시작

React는 태그의 시작이 소문자이면 일반 HTML 태그 (예: <div>, <p>)로, 대문자이면 사용자 정의 컴포넌트 (예: <MyComponent>)로 인식합니다. 이 규칙을 지키지 않으면 React가 컴포넌트를 제대로 렌더링하지 못합니다.

// ⭕ 올바른 예시: 컴포넌트 이름은 대문자로 시작
function MyComponent() {
  return <div>사용자 정의 컴포넌트</div>;
}

// ❌ 잘못된 예시: 소문자로 시작하면 HTML 태그로 인식하려다 오류 발생
function myComponent() {
  return <div>잘못된 컴포넌트</div>;
}

16. JSX 스프레드 연산자로 props 한번에 전달

객체에 여러 props를 담아두고, **스프레드 연산자(...)**를 사용해 한 번에 컴포넌트로 전달할 수 있습니다. 코드를 훨씬 간결하게 만들어 줍니다.

const buttonProps = {
  className: 'btn-primary',
  disabled: false,
  onClick: () => console.log('클릭!')
};

function MyButton() {
  return <button {...buttonProps}>멋진 버튼</button>;
}

17. 간단한 조건부 렌더링은 && 연산자

true && expression은 항상 expression으로 평가되고, false && expression은 항상 false로 평가되는 JavaScript의 특징을 이용한 방법입니다. 조건이 true일 때만 특정 요소를 렌더링하고 싶을 때 유용합니다.

const isLoggedIn = true;
const messageCount = 5;

return (
  <div>
    {isLoggedIn && <p>환영합니다!</p>}
    {messageCount > 0 && <p>새 메시지가 {messageCount}개 있습니다.</p>}
  </div>
);

 


 

'🖥️ Frontend > React' 카테고리의 다른 글

React 입력값 처리 최적화: Debounce vs 클라이언트 필터링  (0) 2025.09.13
React에서 필요한 Hook 정리  (0) 2025.09.08
'🖥️ Frontend/React' 카테고리의 다른 글
  • React 입력값 처리 최적화: Debounce vs 클라이언트 필터링
  • React에서 필요한 Hook 정리
hjwjo
hjwjo
백엔드 및 풀스택 개발에 관심 있는 초보 개발자의 개발 블로그입니다.
  • hjwjo
    Jeongwoo's Devlog
    hjwjo
  • 전체
    오늘
    어제
    • Devlog N
      • 🗄️ Backend
        • Java
        • Spring
        • JPA
        • SQL
        • JSP
        • AWS
        • GCP
        • Linux
        • GitHub
        • ML
        • Security
      • 🖥️ Frontend N
        • React N
        • CSS
      • 🏅 Project
        • Hackathon
        • Team Project
      • 📊 Algorithm
        • BOJ
      • 📜 Certs
        • ADsP
        • SQLD
        • 정보처리기사
      • 📖
        • JavaScript
      • 일상
        • 면접후기
  • 블로그 메뉴

    • 홈
    • Devlog
    • 태그
    • 방명록
  • 링크

    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    스프링부트
    스프링
    java기초
    백준
    http
    SQL
    Spring
    DML
    jsp
    GCP
    쿼리
    ADsP
    java
    AWS
    springboot
    백엔드
    데이터베이스
    정처기
    자바
    정보처리기사
  • 최근 댓글

  • 최근 글

hjwjo
[React] JSX(TSX) 문법 정리
상단으로

티스토리툴바