◼ FrontEnd/ReactJS

[ReactJS] JSX와 컴포넌트 (Component)

SangYoonLee (SYL) 2023. 1. 22. 18:38
반응형

JSX

  • JSX JavaScript의 문법을 확장한 React만의 문법으로, JavaScript 내에서 HTML 마크업을 사용할 수 있도록 한 것이다.
  • 마크업과 자바스크립트 로직이 서로 연결되어 있다고 판단하여 이를 한 번에 작성할 수 있는 방법을 고민한 결과 생겨난 문법이다.
  • JavaScript 내에서 마크업을 작성할 수 있고, JS 로직도 함께 작성할 수 있다.

 

  • JavaScript 정식 문법은 아니기 때문에 브라우저에서 이를 해석할 수 없다.
  • 따라서 Babel 변역기로 이를 React.createElement() 함수로 변환하는 과정이 반드시 필요하다.

 


JSX의 특징

JSX는 자바스크립트의 값이다.

  • 특정한 변수에 이 값을 담을 수 있고, 함수의 인자로 전달하거나 함수의 리턴값으로 사용할 수 있다.
function App() {
  return <h1>Hello 이코딩</h1>;
}

const hello = App();

 

 

JSX는 JavaScript 값을 포함할 수 있다.

  • 중괄호를 이용해서 자바스크립트의 값을 감싸주면 된다.
  • 함수의 반환 값도 값이므로, (반환값이 있는) 함수를 중괄호로 감싸 JSX 내부에서 사용할 수 있다.
function App() {
  return <h1>Hello {() => "이코딩"}</h1>;
}
function App() {
  const name = "이코딩";

  return <h1>Hello {name}</h1>;
}

 

 

JSX 안에서 태그의 속성(Attribute)을 정의할 수 있다.

  • 문자열로 줄 수도 있고 중괄호를 사용하여 JS 값으로 줄 수도 있다.
function App() {
  const class = "title";

  return <h1 className={class}>Hello 이코딩</h1>;
}

 

 

JSX에서 요소에 inline 방식으로 이벤트 라스너를 등록할 수 있다.

  • 태그를 작성할 때 on 뒤에 이벤트 명을 작성하는 방식으로 바로 이벤트 리스너를 부착할 수 있다.
const introduce = () => alert("Hello World");

function App() {
  return <h1 onClick={introduce}>Hello 이코딩</h1>;
}

 

 

JSX에서 요소에 JavaScript 객체 형태로 inline style을 줄 수 있다.

  • key-value 형태로 작성한 객체의 이름을 style 속성의 속성값으로 요소에 주면 된다.
const style = {
  color: "red";,
  backgroundColor: "yellow",
};

function App() {
  return <h1 style={style}>Hello 이코딩</h1>;
}

 

  • JSX 내부에서 바로 스타일 객체를 선언하고 싶은 경우, 아래처럼 태그의 style 속성값에 객체를 작성하면 된다.
function App() {
  return <h1 style={{
    color: "red";,
    backgroundColor: "yellow",
  }}
  >
    Hello 이코딩
  </h1>;
}

 

 

JSX 요소는 반환값 전체가 하나의 부모 태그로만 감싸져 있어야 한다.

  • React.Fragment 태그를 활용하자. (실제로 이 태그는 브라우저에 표시되지 않는다)
function App() {
  return (
    <React.Fragment>
      <h1>Hello 이코딩</h1>
      <p>
        Who is 이코딩? For the blind, He is vision. For the hungry, He is
        the chef. For the thirsty, He is water. If 이코딩 thinks, I agree.
        If 이코딩 speaks, I’m listening. If 이코딩 has one fan, it is me. If
        이코딩 has no fans, I do not exist.
      </p>
    </React.Fragment>
  );
}

 

  • <>, </> 로 단축해서 쓸 수도 있다.
function App() {
  return (
    <>
      <h1>Hello 이코딩</h1>
      <p>
        Who is 이코딩? For the blind, He is vision. For the hungry, He is
        the chef. For the thirsty, He is water. If 이코딩 thinks, I agree.
        If 이코딩 speaks, I’m listening. If 이코딩 has one fan, it is me. If
        이코딩 has no fans, I do not exist.
      </p>
    </>
  );
}

 

 

  • 그 외 JSX의 특징 및 규칙
    • JSX 태그는 확실하게 닫아주어야 한다.

 


createElement vs JSX

createElement로 작성된 코드와 JSX 문법으로 작성된 코드를 서로 비교해보면 JSX 문법의 강력함을 알 수 있다.

 

< 예시 1 >

  • createElement
const title = React.createElement(
  "h3",
  {
    id: "title",
    onMouseEnter: () => console.log("mouse enter"),
  },
  "Hello. I'm a title."
);

 

  • JSX
const title = (
  <h3 id="title" onMouseEnter={() => console.log("mouse enter")}>
    Hello I'm a title
  </h3>
);

 

 

< 예시 2 >

  • createElement
const btn = React.createElement(
  "button",
  {
    onClick: () => console.log("i clicked"),
    style: {
      backgroundColor: "tomato",
    },
  },
  "Click Me"
);

 

  • JSX
const btn = (
  <button
    style={{
      backgroundColor: "tomato",
    }}
    onClick={() => console.log("i clicked")}
  >
    Click Me
  </button>
);

 

 

  • JSX 문법은 HTML과 유사하나 다른 점도 존재함을 기억해야 한다.
    • class나 for같은 키워드는 React JS에서 제대로 동작하지 않을 수 있다.
    • (class => className, for => htmlFor을 써야 한다.)

 

  • (위에서 언급했지만) JSX 문법으로 작성한 코드는 브라우저가 바로 이해할 수 없기 때문에, 브라우저가 이해할 수 있는 형태로 변환해주는 장치가 필요하다. 그 장치가 바로 Babel인 것이다.

 


Babel

Babel이란?

  • 브라우저마다 사용하는 언어가 달라 발생하는 크로스브라우징 이슈를 해결하기 위해, 스크립트를 모든 브라우저에서 동작할 수 있는 코드로 '트랜스파일'해주는 장치
    • 트랜스파일 : 추상화 수준이 같은 코드로 변환해주는 것 (vs 빌드)
  • ECMAScript2015 이상의 코드를 적당한 하위 버전으로 변환
  • TypeScript나 JSX도 Babel의 변환 대상이다.
  • Babel 홈페이지 바로가기

 

 

Babel standalone를 이용하여 변환기 설치하기

  • HTML에 다음을 삽입한다.
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  • 그리고 JS 코드를 작성할 때 script 태그의 속성(property)에 type="text/babel"를 부여해준다.
<script type="text/babel">
  // JS 코드를 작성하는 곳
</script>

 

  • 다만, 이 방식은 느리기 때문에 혼자할 때는 절대 이렇게 할 일이 없을 것이다. 이보다 더 나은 방식이 있다.

 

 

Node.js를 통해 설치하기

  • 설치 명령어
    • npm i -D babel-loader : Webpack에서 Babel을 쓸 수 있도록 도와줌
    • npm i -D @babel/core
    • npm i -D @babel/preset-env @babel/preset-react
  • config 설정
// webpack.config.js
module.exports = {
  mode: "development",
  module: {
    rules: [
      {
        test: /\.(js|jsx)?$/,
        loader: "babel-loader",
        options: {
          presets: ["@babel/preset-env", "@babel/preset-react"],
        },
      },
    ],
  },
  resolve: { extensions: [".js", ".jsx"] },
};
// babel.config.js
module.exports = {
  presets: [
    [
      "@babel/preset-env",
      {
        targets: {
          node: "current",
          chrome: "79",
        },
      },
    ],
    "@babel/preset-react",
  ],
};

 


컴포넌트 생성 & 컴포넌트를 다른 컴포넌트에 넣기

컴포넌트 (Component) 란?

  • 컴퓨터 과학에서 컴포넌트란?
    • 독립적이고, 재사용할 수 있는 소프트웨어 구성

 

  • 프론트엔드에서 컴포넌트란?
    • 독립적이고, 재사용할 수 있는 UI 단위
    • 로고 블록을 조립해서 큰 성을 만들듯이, 작은 UI를 조합해서 큰 UI를 구성할 수 있다.

 

  • 컴포넌트란 JSX를 반환하는 함수이다. (함수형 컴포넌트)
  • 임의의 입력값(props)을 받아 화면에 어떻게 표시할 지를 기술하는 React 엘리먼트(element)를 반환한다.
  • 일반 element를 함수형으로 바꾸면 컴포넌트(사용자 정의 태그)로 인식된다.

 

  •  직접 만든 컴포넌트를 렌더링해서 다른 곳에 사용할 때는 이름이 항상 대문자로 시작되어야 한다.
  •  컴포넌트를 리렌더링 시, 전체를 전부 재생산하지 않고 전과 달리진 부분만 새로 생성한다.

 


클래스 컴포넌트 vs 함수 컴포넌트

클래스 컴포넌트

  • state, lifeCycle 등의 기능을 이용할 수 있어 초항기에 많이 사용된 방식이다.
  • 하지만, Class 문법과 동작이 복잡하다는 단점이 존재한다.
class Component {
  render() {
    <section>
      <h1>Hello World</h1>
    </section>;
  }
}

 

함수 컴포넌트

const Component = () => (
  <section>
    <h1>Hello World</h1>
  </section>
);
  • 클래스에 비해 직관적이고 사용하기 쉽지만, state, lifeCycle 등의 기능을 이용할 순 없었다.
  • 하지만 React 16.8 버전에서 Hook이란 개념의 등장으로 위 기능들을 함수 컴포넌트에서도 사용할 수 있게 되었다.
  • 그로 인해 현재 React 생태계에서는 함수 컴포넌트를 가장 많이 사용한다.
function Component() {
  return (
    <section>
      <h1>Hello World</h1>
    </section>
  );
}

 


컴포넌트 생성 & 컴포넌트를 다른 컴포넌트에 넣기

const root = document.getElementById("root");

// Title 컴포넌트
const Title = () => (
  <h3 id="title" onMouseEnter={() => console.log("mouse enter")}>
    Hello I'm a title
  </h3>
);

// Btn 컴포넌트
const Btn = () => (
  <button
    style={{
      backgroundColor: "tomato",
    }}
    onClick={() => console.log("i clicked")}
  >
    Click Me
  </button>
);

// Title, Btn, Container와 같이 이름이 대문자로 시작해야 컴포넌트로 바르게 인식된다.
const Container = () => (
  <>
    <Title />
    <Btn />
  </>
);

ReactDOM.render(<Container />, root);

 

반응형