JavaScript in JSX with Curly Braces

김동현·2026년 3월 15일

title: JSX에서 중괄호로 자바스크립트 사용하기

안녕하세요 여러분! 오늘 배워볼 내용은 리액트의 핵심 중 하나인 JSX에서 자바스크립트를 어떻게 활용하는가에 대한 것입니다.

JSX를 사용하면 자바스크립트 파일 안에 HTML과 매우 비슷한 형태의 마크업을 작성할 수 있어요. 덕분에 화면에 무엇을 그릴지 결정하는 렌더링 로직과 실제 보여질 콘텐츠를 한 곳에 깔끔하게 유지할 수 있죠.

하지만 단순히 고정된 화면만 보여줄 건 아니잖아요? 때로는 마크업 안에 약간의 자바스크립트 로직을 더하거나, 동적으로 변하는 데이터를 속성에 연결하고 싶을 때가 생길 겁니다. 바로 이런 상황에서 여러분은 JSX 안에 중괄호({})를 사용하여 자바스크립트의 세계로 통하는 마법의 창문을 열 수 있습니다!

(👨‍🏫 강사 부연설명: 과거에는 HTML, CSS, JavaScript 파일을 각각 따로 분리해서 작업하는 것이 일반적이었죠? 하지만 리액트에서는 '컴포넌트' 단위로 생각하기 때문에, 눈에 보이는 구조(HTML)와 그걸 제어하는 로직(JS)이 한 몸처럼 움직이는 게 훨씬 효율적이고 직관적이랍니다. 오늘 이 중괄호 문법을 확실히 익혀두면, 리액트가 얼마나 유연한지 느끼게 되실 거예요!)

이 문서를 통해 여러분은 다음 내용들을 확실히 마스터하게 될 겁니다!

  • 따옴표를 사용하여 문자열 속성을 전달하는 방법
  • 중괄호를 사용하여 JSX 안에서 자바스크립트 변수를 참조하는 방법
  • 중괄호를 사용하여 JSX 안에서 자바스크립트 함수를 직접 호출하는 방법
  • 중괄호를 사용하여 JSX 안에서 자바스크립트 객체(Object)를 다루는 방법

따옴표로 문자열 전달하기 {/passing-strings-with-quotes/}

JSX 태그에 문자열 속성(attribute)을 전달하고 싶을 때는, HTML에서 하던 것과 비슷하게 작은따옴표(')나 큰따옴표(") 안에 값을 넣어주면 됩니다.

export default function Avatar() {
  return (
    <img
      className="avatar"
      src="[https://i.imgur.com/7vQD0fPs.jpg](https://i.imgur.com/7vQD0fPs.jpg)"
      alt="Gregorio Y. Zara"
    />
  );
}
.avatar { border-radius: 50%; height: 90px; }

위 코드를 보면, "https://i.imgur.com/7vQD0fPs.jpg""Gregorio Y. Zara"라는 텍스트가 순수한 문자열로 잘 전달되고 있죠.

하지만 srcalt 텍스트를 상황에 따라 동적으로 지정하고 싶다면 어떨까요? 그럴 때는 "(따옴표)를 {}(중괄호)로 교체하여 자바스크립트의 값을 바로 가져다 쓸 수 있습니다!

export default function Avatar() {
  const avatar = '[https://i.imgur.com/7vQD0fPs.jpg](https://i.imgur.com/7vQD0fPs.jpg)';
  const description = 'Gregorio Y. Zara';
  return (
    <img
      className="avatar"
      src={avatar}
      alt={description}
    />
  );
}
.avatar { border-radius: 50%; height: 90px; }

className="avatar"src={avatar}의 차이점을 잘 눈여겨보세요. 앞의 것은 이미지를 둥글게 만들어주기 위해 "avatar"라는 CSS 클래스 이름을 직접 지정한 문자열이고요, 뒤의 것은 avatar라는 이름의 자바스크립트 변수 값을 읽어오도록 지시한 것입니다.

중괄호가 있기 때문에, 여러분은 마크업 작성 중에도 언제든지 자바스크립트 기능을 끌어와서 작업할 수 있는 거랍니다!

중괄호 사용하기: 자바스크립트 세계로 통하는 창문 {/using-curly-braces-a-window-into-the-javascript-world/}

JSX는 자바스크립트를 작성하는 조금 특별한 방식일 뿐입니다. 그 말은 즉, JSX 내부에서도 언제든지 자바스크립트를 사용할 수 있다는 뜻이죠. 어떻게 하냐고요? 바로 중괄호 { }를 열고 닫으면 됩니다.

아래 예제를 볼까요? 먼저 과학자의 이름을 name이라는 변수로 선언한 다음, <h1> 태그 안에 중괄호를 사용해 그 이름을 쏙 끼워 넣고 있습니다.

export default function TodoList() {
  const name = 'Gregorio Y. Zara';
  return (
    <h1>{name}'s To Do List</h1>
  );
}

직접 코드를 만져보세요! name의 값을 'Gregorio Y. Zara'에서 'Hedy Lamarr'로 바꿔보실래요? 리스트의 제목이 즉각적으로 바뀌는 걸 확인하실 수 있을 거예요.

중괄호 안에는 변수뿐만 아니라, formatDate() 같은 함수 호출을 포함하여 값을 반환하는 모든 자바스크립트 표현식(expression)이 들어갈 수 있습니다.

const today = new Date();

function formatDate(date) {
  return new Intl.DateTimeFormat(
    'en-US',
    { weekday: 'long' }
  ).format(date);
}

export default function TodoList() {
  return (
    <h1>To Do List for {formatDate(today)}</h1>
  );
}

(👨‍🏫 강사 부연설명: 변수명, 수학 계산식(1 + 1), 함수 실행(func()), 삼항 연산자(a ? b : c) 등 자바스크립트에서 결과값을 만들어내는 것이라면 무엇이든 이 중괄호 안에 들어갈 수 있어요. 다만 if 문이나 for 문 같은 '문장(Statement)'은 값이 아니기 때문에 중괄호 안에 직접 넣을 수는 없다는 점, 꼭 기억해 두세요!)

중괄호를 사용할 수 있는 곳 {/where-to-use-curly-braces/}

JSX 안에서 중괄호는 딱 두 군데에서만 사용할 수 있습니다. 엄격한 규칙이니 잘 외워두세요!

  1. 텍스트로서 JSX 태그 안쪽에 직접 사용하기: <h1>{name}'s To Do List</h1>는 완벽하게 동작합니다. 하지만 <{tag}>Gregorio Y. Zara's To Do List</{tag}> 처럼 태그의 껍데기 자체에는 사용할 수 없습니다.
  2. 속성(Attributes)으로서 = 기호 바로 뒤에 사용하기: src={avatar}avatar 변수의 값을 읽어오지만, src="{avatar}"라고 쓰면 변수를 무시하고 그냥 "{avatar}"라는 문자 자체를 그대로 전달해 버립니다.

"이중 중괄호" 사용하기: JSX 안의 CSS와 객체 {/using-double-curlies-css-and-other-objects-in-jsx/}

문자열이나 숫자, 기타 자바스크립트 표현식 외에도, JSX 안에는 심지어 객체(Object) 자체를 전달할 수도 있습니다! 자바스크립트에서 객체는 { name: "Hedy Lamarr", inventions: 5 }처럼 생겼죠?

이걸 JSX에 전달하려면 어떻게 해야 할까요? 맞습니다. 객체 자체의 중괄호를 JSX의 중괄호로 한 번 더 감싸주어야 합니다. 바로 이렇게요! person={{ name: "Hedy Lamarr", inventions: 5 }}

실제 개발하시면서 JSX 안에 인라인 CSS 스타일을 작성할 때 이런 형태를 가장 자주 보게 될 겁니다. 리액트에서 꼭 인라인 스타일을 써야 하는 건 아니에요 (대부분의 경우는 CSS 클래스를 사용하는 것이 성능이나 유지보수 면에서 좋습니다). 하지만 인라인 스타일이 불가피하게 필요할 때는 style 속성에 반드시 객체를 전달해야 합니다.

export default function TodoList() {
  return (
    <ul style={{
      backgroundColor: 'black',
      color: 'pink'
    }}>
      <li>Improve the videophone</li>
      <li>Prepare aeronautics lectures</li>
      <li>Work on the alcohol-fuelled engine</li>
    </ul>
  );
}
body { padding: 0; margin: 0 }
ul { padding: 20px 20px 20px 40px; margin: 0; }

직접 backgroundColorcolor의 값을 다른 색상으로 수정해 보세요.

코드를 아래처럼 줄 바꿈 해서 작성해 보면, 바깥쪽 중괄호(JSX) 안에 안쪽 중괄호(자바스크립트 객체)가 들어있다는 사실이 훨씬 명확하게 보일 겁니다.

<ul style={
  {
    backgroundColor: 'black',
    color: 'pink'
  }
}>

그러니 다음에 JSX에서 {{}} 를 연달아 보게 되더라도 절대 당황하지 마세요! 이건 무슨 신비한 특수 문법이 아니라, JSX 중괄호 안에 들어있는 평범한 자바스크립트 객체일 뿐이니까요.

🚨 주의사항!
인라인 style 속성의 이름은 반드시 camelCase(카멜 케이스)로 작성해야 합니다. 예를 들어, 순수 HTML에서 <ul style="background-color: black"> 이라고 쓰던 것을 리액트 컴포넌트에서는 <ul style={{ backgroundColor: 'black' }}> 이라고 작성해야 에러가 나지 않습니다.

(👨‍🏫 강사 부연설명: 자바스크립트에서 객체의 키(Key) 이름에 하이픈(-)을 넣으려면 일일이 따옴표로 감싸줘야 해서 코드가 꽤 지저분해지거든요 ('background-color': 'black'). 그래서 리액트 개발팀은 자바스크립트 친화적인 카멜 케이스 방식으로 작성하도록 규칙을 정해두었답니다!)

자바스크립트 객체와 중괄호로 더 재미있게 놀아보기 {/more-fun-with-javascript-objects-and-curly-braces/}

변수 하나하나를 따로 넘길 필요 없이, 관련된 여러 정보들을 하나의 객체로 묶어둔 다음 JSX 안에서 참조하는 것도 아주 좋은 방법입니다.

const person = {
  name: 'Gregorio Y. Zara',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person.name}'s Todos</h1>
      <img
        className="avatar"
        src="[https://i.imgur.com/7vQD0fPs.jpg](https://i.imgur.com/7vQD0fPs.jpg)"
        alt="Gregorio Y. Zara"
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}
body { padding: 0; margin: 0 }
body > div > div { padding: 20px; }
.avatar { border-radius: 50%; height: 90px; }

이 예제에서 person이라는 자바스크립트 객체 안에는 name이라는 문자열과, theme이라는 또 다른 객체가 들어있습니다.

const person = {
  name: 'Gregorio Y. Zara',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

그러면 컴포넌트에서는 person 객체를 불러와 필요한 값들을 이렇게 쏙쏙 뽑아 쓸 수 있죠!

<div style={person.theme}>
  <h1>{person.name}'s Todos</h1>

JSX는 자체적으로 복잡한 문법을 가진 무거운 템플릿 언어가 아닙니다. 대신 여러분이 이미 알고 있는 자바스크립트를 활용해서 데이터와 로직을 자유롭게 구성할 수 있게 해주는 아주 미니멀하고 직관적인 도구랍니다.

📌 핵심 요약 및 복습

수고하셨습니다! 이제 여러분은 JSX를 다루는 데 필요한 거의 모든 지식을 갖추셨어요:

  • 따옴표 안에 작성된 JSX 속성은 단순한 고정 문자열로 전달됩니다.
  • 중괄호를 사용하면 자바스크립트의 로직과 변수를 마크업 세상 안으로 끌고 올 수 있습니다.
  • 이 중괄호는 오직 JSX 태그의 콘텐츠 영역 안이나, 속성을 할당하는 = 기호 바로 뒤에서만 작동합니다.
  • {{}} 는 어떤 대단하고 특별한 문법이 아닙니다. 단순히 JSX 중괄호 안에 자바스크립트 객체가 쏙 들어가 있는 형태일 뿐입니다.

자, 배운 내용을 토대로 아래 도전 과제들을 해결해 볼까요? 💪

1. 실수 고치기 {/fix-the-mistake/}

아래 코드는 실행하면 Objects are not valid as a React child (객체는 리액트의 자식 요소로 사용할 수 없습니다) 라는 무서운 에러와 함께 화면이 터져버립니다.

const person = {
  name: 'Gregorio Y. Zara',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person}'s Todos</h1>
      <img
        className="avatar"
        src="[https://i.imgur.com/7vQD0fPs.jpg](https://i.imgur.com/7vQD0fPs.jpg)"
        alt="Gregorio Y. Zara"
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}
body { padding: 0; margin: 0 }
body > div > div { padding: 20px; }
.avatar { border-radius: 50%; height: 90px; }

어디가 문제인지 찾으셨나요?

중괄호 안에 무엇이 들어있는지 유심히 살펴보세요. 우리가 지금 '객체'를 보여주려고 하는 건지, 아니면 '문자열'을 보여주려고 하는 건지 생각해보세요!

정답을 공개합니다!

이 에러가 발생한 이유는, 개발자가 실수로 문자열이 아니라 객체 그 자체를 화면에 렌더링하려고 시도했기 때문입니다.
<h1>{person}'s Todos</h1> 부분을 보세요. person 객체를 통째로 화면에 출력하려고 하고 있죠? 리액트는 이런 쌩짜 객체 덩어리를 화면에 어떻게 그려야 할지 모르기 때문에, 일반 객체를 텍스트로 넣으려고 하면 에러를 뿜어냅니다.

(👨‍🏫 강사 부연설명: 화면에 글자를 찍으려면, 객체 자체가 아니라 그 객체 안에 있는 '텍스트 값'에 정확히 접근해서 넘겨줘야 해요!)

문제를 해결하려면 <h1>{person}'s Todos</h1><h1>{person.name}'s Todos</h1>로 수정해 주시면 됩니다:

const person = {
  name: 'Gregorio Y. Zara',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person.name}'s Todos</h1>
      <img
        className="avatar"
        src="[https://i.imgur.com/7vQD0fPs.jpg](https://i.imgur.com/7vQD0fPs.jpg)"
        alt="Gregorio Y. Zara"
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}
body { padding: 0; margin: 0 }
body > div > div { padding: 20px; }
.avatar { border-radius: 50%; height: 90px; }

2. 객체로 정보 추출하기 {/extract-information-into-an-object/}

이번에는 <img> 태그에 하드코딩 되어있는 이미지 URL을, person 객체 안으로 빼내어 깔끔하게 정리해 보세요.

const person = {
  name: 'Gregorio Y. Zara',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person.name}'s Todos</h1>
      <img
        className="avatar"
        src="[https://i.imgur.com/7vQD0fPs.jpg](https://i.imgur.com/7vQD0fPs.jpg)"
        alt="Gregorio Y. Zara"
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}
body { padding: 0; margin: 0 }
body > div > div { padding: 20px; }
.avatar { border-radius: 50%; height: 90px; }

다 푸셨나요? 정답은 이렇습니다!

이미지 URL을 person.imageUrl 이라는 속성(Property)으로 옮긴 다음, <img> 태그의 src에서 중괄호를 사용해 해당 값을 읽어오도록 만들면 됩니다:

const person = {
  name: 'Gregorio Y. Zara',
  imageUrl: "[https://i.imgur.com/7vQD0fPs.jpg](https://i.imgur.com/7vQD0fPs.jpg)",
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person.name}'s Todos</h1>
      <img
        className="avatar"
        src={person.imageUrl}
        alt="Gregorio Y. Zara"
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}
body { padding: 0; margin: 0 }
body > div > div { padding: 20px; }
.avatar { border-radius: 50%; height: 90px; }

3. JSX 중괄호 안에 표현식 작성하기 {/write-an-expression-inside-jsx-curly-braces/}

아래 객체를 보면 전체 이미지 URL이 4개의 조각으로 쪼개져 있습니다. base URL, imageId, imageSize, 그리고 파일 확장자(file extension)죠.

우리는 이 조각들을 하나로 예쁘게 합쳐서 완성된 이미지 URL을 만들고 싶습니다.
합쳐야 할 속성들은 base URL (항상 'https://i.imgur.com/'), imageId ('7vQD0fP'), imageSize ('s'), 파일 확장자 (항상 '.jpg') 입니다.

그런데 코드를 보니 <img> 태그가 src를 지정하는 방식에 무언가 단단히 문제가 있네요! 어떻게 수정해야 할지 직접 고쳐보시겠어요?


const baseUrl = '[https://i.imgur.com/](https://i.imgur.com/)';
const person = {
  name: 'Gregorio Y. Zara',
  imageId: '7vQD0fP',
  imageSize: 's',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person.name}'s Todos</h1>
      <img
        className="avatar"
        src="{baseUrl}{person.imageId}{person.imageSize}.jpg"
        alt={person.name}
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}
body { padding: 0; margin: 0 }
body > div > div { padding: 20px; }
.avatar { border-radius: 50%; }

제대로 고치셨는지 확인하고 싶다면, imageSize의 값을 's'에서 'b'로 바꿔보세요. 문자열을 합치는 로직이 정상적이라면 이미지가 커다랗게 변할 것입니다!

아래와 같이 자바스크립트의 문자열 덧셈(+) 연산을 활용하여 src={baseUrl + person.imageId + person.imageSize + '.jpg'} 로 작성해 주시면 됩니다.

  1. { 를 통해 자바스크립트 표현식을 시작합니다.
  2. baseUrl + person.imageId + person.imageSize + '.jpg' 를 통해 변수와 문자열을 결합하여 올바른 전체 URL을 만들어 냅니다.
  3. } 로 자바스크립트 표현식을 닫아줍니다.
const baseUrl = '[https://i.imgur.com/](https://i.imgur.com/)';
const person = {
  name: 'Gregorio Y. Zara',
  imageId: '7vQD0fP',
  imageSize: 's',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person.name}'s Todos</h1>
      <img
        className="avatar"
        src={baseUrl + person.imageId + person.imageSize + '.jpg'}
        alt={person.name}
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}
body { padding: 0; margin: 0 }
body > div > div { padding: 20px; }
.avatar { border-radius: 50%; }

또 다른 좋은 방법으로는, 이 지저분한 표현식을 아예 밖으로 꺼내어 아래의 getImageUrl 처럼 별도의 독립적인 함수로 분리해 버리는 것입니다!

// src/App.js
import { getImageUrl } from './utils.js'

const person = {
  name: 'Gregorio Y. Zara',
  imageId: '7vQD0fP',
  imageSize: 's',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person.name}'s Todos</h1>
      <img
        className="avatar"
        src={getImageUrl(person)}
        alt={person.name}
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}
// src/utils.js
export function getImageUrl(person) {
  return (
    '[https://i.imgur.com/](https://i.imgur.com/)' +
    person.imageId +
    person.imageSize +
    '.jpg'
  );
}
body { padding: 0; margin: 0 }
body > div > div { padding: 20px; }
.avatar { border-radius: 50%; }

(👨‍🏫 강사 부연설명: 어때요? 로직을 함수로 분리하니까 컴포넌트 내부의 마크업이 훨씬 읽기 쉽고 깔끔해졌죠? 리액트 개발을 하다 보면 이렇게 변수와 함수를 적절히 분리하여 마크업을 단순하게 유지하는 습관이 매우 중요하답니다!)


Sitemap

모든 문서 페이지 한눈에 보기 (Overview of all docs pages)

profile
프론트에_가까운_풀스택_개발자

0개의 댓글