리액트 Summary - 0-1. JSX와 주의할 점들에 대하여-thumbnail

리액트 Summary - 0-1. JSX와 주의할 점들에 대하여

JSX and precautions
314

JSX

What's JSX and entry point

JSX란 무엇인가? Javascript에 XML을 추가한 문법이라고 보면 된다. 공식 자바스크립트 문법은 아니고, React.js에서 사용된다. 나중에 Babel을 사용하여 해당 문법을 Javascript로 변환해주는 과정을 거치게 된다. 참고한 책에 의하면 "가독성이 높고 작성하기도 쉽다"는 점이 "JSX를 사용하는 주된 이유"라고 한다. React 프로젝트의 entry point가 되는 src/index.js 파일을 보며 이를 확인해보자.

(src/index.js)

(...)

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

이런 식으로 XML 문법(<React.StrictMode><App /></React.StrictMode> 등)이 Javascript 코드(document.getElementById('root') 등)와 혼용되어 사용되고 있는 것을 알 수 있다.

ReactDOM.createRoot는 React 18부터 제공되는 메서드인데, 이전의 ReactDOM.render를 대체하는 것이라고 한다. Legacy가 된 이전 ReactDOM.render의 경우 아래와 같이 작성된다.

(...)

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

얼핏 보면 위와 아래의 차이가 거의 없어보이지만, React 18 이후 버전인 위의 경우 render를 여러 번 해주게 되었을 때 계속해서 document.getElementById('root')가 호출될 일이 없는 반면, 아래는 계속해서 document.getElementById('root')를 호출하게 된다는 차이가 있다고 한다.

<React.StrictMode> component는 현재 프로젝트를 진행할 때 legacy 기능을 사용하면 경고를 띄워서 차후 React와 호환 가능한 개발이 이루어질 수 있게 해주는 component다. legacy 기능이란 정확히 뭘 말하는 걸까?

공식 문서에는 안전하지 않은 생명주기 사용, 현재의 ref가 나오기 전 사용되던 ref APIcallback API의 사용, 역시나 ref로 해결할 수 있으나 그 전에 사용되어 왔던 findDOMNode의 사용, 오류가 발생하기 쉬운 Legacy context API의 사용 등이 그 대상이라고 나와있다. 여러 번 호출될 가능성이 있는 생명주기 메서드들을 (development 환경에서 React가) 의도적으로 여러 번 호출하였는데 그 테스트에서 잠재적인 위협이 발견된 경우나 React가 곧 도입하려고 하는 성능개선에 필수적인 state인 reusable state도 만족하는지에 대해 검사하고 이를 충족하지 못하는 경우에도 경고를 날린다고 한다.

유의할 점들 & 자주 보일 문법들

1. 감싸줄 것

function Component() {
  return (
    <>
      <div>Hello, React</div>
      <p>Written by PajaritoMoyqi</p>
    </>
  );
}

Component에서 반환되는(혹은 class 형태인 component의 render 함수에서 반환되는) 요소가 여러 개가 있다면 그 요소들은 반드시 부모 요소 하나로 감싸져야 한다. 이유는 간단한데, Virtual DOM에서 Component 변화를 효율적으로 감지하기 위해 각 Component는 단일한 DOM Tree 구조를 형성해야 하기 때문이다. 여기서는 Fragment 요소를 사용하여 전체 요소를 감쌌다.

2. undefined를 render하지 말 것

function Component() {
  const a = undefined;
  return a;
}

위와 같은 상황은 안 된다. 하지만 아래의 코드는 작동한다.

function Component() {
  const a = undefined;
  return (
    <>
      <div>{a}</div>
      <p>Wirtten by PajaritoMoyqi</p>
    </>
  );
}

조건부로 Component를 보여주고 싶을 때 return null;을 활용할 수 있는데, 이에 대한 예시는 아래 if문을 다루는 절에서 확인해보자.

3. javascript 표현식은 {} 안에

function Component() {
  const name = 'React';
  return (
    <>
      <div>Hello, {name}</div>
      <p>Written by PajaritoMoyqi</p>
    </>
  );
}

다양한 template language를 써보았다면 익숙한 모습일 것이다.

4. 연산자 활용

-1. if문을 대체하는 조건부 연산자
function Component() {
  const name = 'React';
  return (
    <>
      {name === 'React' ? (
        <div>Hello, {name}</div> 
      ) : (
        <div>Hello, Anonymous</div>
      )}
      <p>Written by PajaritoMoyqi</p>
    </>
  );
}

React에서는 if문 사용이 불가하다. 하지만 조건부로 Component를 바꿔주고 싶을 때 if문이 쓰이기도 한다.

function Component() {
  if ( true ) {
    return <p>You can see me, becuase it's true</p>;
  } else {
    return null;
  }
} 

조건부로 아예 Component를 안 보여줘야 하는 경우에는 null을 return해주면 된다.

-2. if문을 대체하는 AND 연산자
function Component() {
  const name = 'React';
  return (
    <>
      <div>Hello, {name === 'React' && <h1>React</h1>}</div> 
      <p>Written by PajaritoMoyqi</p>
    </>
  );
}

5. DOM 요소에 style을 적용할 때에는 객체로!

function Component() {
  const name = 'React';
  const style = {
    backgroundColor: 'black',
    color: 'white'
  }

  return (
    <>
      <div>Hello, {name === 'React' && <h1>React</h1>}</div> 
      <p style={style}>Written by PajaritoMoyqi</p>
    </>
  );
}

6. className

function Component() {
  const name = 'React';
  const style = {
    backgroundColor: 'black',
    color: 'white'
  }

  return (
    <>
      <div className="title-box">Hello, {name === 'React' && <h1>React</h1>}</div> 
      <p style={style}>Written by PajaritoMoyqi</p>
    </>
  );
}

class를 적극 활용하는 React에서 겹침을 방지하기 위해 HTML code 내의 class attribute는 className을 사용하여 표현한다. 역시 다양한 template language를 사용해왔다면 본 적 있는 형태일 것이다.

7. tag는 꼭 닫아주기

function Component() {
  const name = 'React';
  const style = {
    backgroundColor: 'black',
    color: 'white'
  }

  return (
    <>
      <div className="title-box">Hello, {name === 'React' && <h1>React</h1>}</div> 
      <p style={style}>Written by PajaritoMoyqi</p>
      <input type="text" />
    </>
  );
}

8. 주석

function Component() {
  const name = 'React';
  const style = {
    backgroundColor: 'black',
    color: 'white'
  }

  return (
    <>
      {/* show how it looks like */}
      <div className="title-box">Hello, {name === 'React' && <h1>React</h1>}</div> 
      <p style={style}>Written by PajaritoMoyqi</p>
      <input type="text" />
    </>
  );
}

{/**/}로 감싸서 주석을 표현해주도록 한다.


참고 서적 :
김민준, 2019, 길벗, 『리액트를 다루는 기술, 개정판』

참고 사이트 :
React Document: Strict Mode