[리액트] 2. JSX(리액트 사용 언어)

김태훈·2022년 9월 12일
0

1. 코드 이해하기

import logo from './logo.svg'; 
import './App.css';
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

이 코드에는 없지만 이전 버전에서는

import React from 'react';

의 코드가 존재했다.
이 코드는 리액트를 불러와서 사용할 수 있게 해준다. ( 다시 한 번, 말하지만 리액트는 프레임워크가 아닌 라이브러리이다.)
리액트 프로젝트를 만들 때 node_modules라는 디렉터리도 생성되는데, 프로젝트 생성 과정에서 node_modules 디렉터리에 react 모듈이 생성된다. 그 후에, 이렇게 import를 통해 리액트를 불러와서 사용하는 것이다.
여기서 한 가지 더 알아두어야 할 점은, 이렇게 모듈을 불러와서 사용하는 것은 사실 원래 브라우저 에는 없었던 기능이었다. 브라우저가 아닌 환경에서 자바스크립트를 실행할 수 있게 해주는 환경인 Node.js에서 이 기능일 지원한다.
이러한 기능(모듈을 브라우저 밖 환경에서 묶는 것)을 브라우저에서 사용하기 위해 bundler를 사용한다. 번들(bundle)은 묶는다는 뜻으로, 파일을 묶듯이 연결하는 것이다.

대표적인 번들러 : 웹팩, Parcel, browserify가 있고, 각 도구마다 특성이 다른데, 리액트에서는 웹팩을 사용하는 추세이다. 번들러 도구를 사용하면 import로 모듈을 불러왔을 때 불러온 모듈을 모두 합쳐서 하나의 파일을 생성한다.

코드블럭 1

import logo from './logo.svg';
import './App.css';

웹팩을 사용하면 SVG파일과 CSS파일도 불러와서 사용할 수 있다. 이렇게 파일들을 불러오는 것은 웹팩의 로더(loader)가 담당한다.
CSS는 css-loader가 담당하고, file-loader는 웹 폰트나 미디어 파일 등을 불러올 수 있게 해준다.
그리고 babel-loader는 자바스크립트 파일들을 불러오면서 최신 자바스크립트 문법으로 작성된 코드를 바벨이라는 도구를 사용하여 ES5 문법(이전 버전의 자바스크립트, 이렇게 해줘야 구버전 웹브라우저에서 실행이 가능해진다)으로 변환해준다.
이 때 원래는, 웹팩의 로더는 직접 설치하고 설정해야 하지만, 리액트 프로젝트를 만들 때 사용했던 create-react-app이 이러한 번거로운 작업을 대신해주었고, 별도의 설정을 할 필요가 없어졌다.

2. JSX란?

JSX는 자바스크립트의 확장 문법이다. XML과 매우 비슷하게 생김. 이러한 형식으로 작성한 코드는 브라우저에서 실행되기 전에 코드가 번들링되는 과정에서 바벨을 사용하여 일반 자바스크립트 형태의 코드로 변환된다.

function App() {
	return (
		<div>
			Hello <b>react</b>
		</div>
	);
}

이렇게 작성된 코드는 다음과 같이 변형된다.

function App() {
	return React.createElement("div",null,"Hello ", React.createElement("b",null,"react"));

3. JSX의 장점

1) 보기 쉽고 익숙하다.

첫 번째 게시글에서도 설명했지만, 일반 자바스크립트로 웹을 구현하는 것은 매우 빡세다. JSX를 쓰면 결국 HTML코드를 작성하는 것과 비슷해지기 때문에 매우 보기 쉽고 익숙하다!

2) 더욱 높은 활용도

JSX에서는 우리가 알고있는 div 나 span 같은 HTML 태그를 사용할 수 있을 뿐 아니라, 앞으로 만들 컴포넌트도 JSX안에서 작성할 수 있다.
App.js 에서는 App 컴포넌트가 만들어졌지만, src/index.js 파일을 열어보면, 이 App 컴포넌트를 마치 HTML태그 쓰듯이 그냥 작성한다.
다음 코드를 보자.

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
	//원래는 document.getElementById('root'); 가 존재했음
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals(); //serviceWorker.unregister(); 가 존재했음
  • ReactDOM.render는 무엇인가?
    이 코드는 컴포넌트를 페이지에 렌더링하는 역할을 하며, react-dom 모듈을 불러와 사용할 수 있다. 이 함수의 첫 번째 파라미터에는 페이지에 렌더링할 내용을 JSX 형태로 작성하고, 두 번째 파라미터에는 해당 JSX를 렌더링할 document 내부 요소를 설정한다. 여기서는 id가 root인 요소 안에 렌더링하도록 설정했다. (주석부분)document.getElementById('root'); 이 요소는 public/index.html을 열어 보면 있다.
  • React.StrictMode는 무엇인가?
    React.StrictMode는 리액트 프로젝트에서 리액트의 레거시 기능들을 사용하지 못하게 하는 기능이다. 이를 사용하면 문자열 ref, componentWillMount 등 나중에는 완전히 사라지게 될 옛날 기능을 사용했을 때 경고를 출력한다. 앞으로 이 책에 나타날 index.js에 React.StrictMode가 적용되어 있지 않으니 참고할것.

4. JSX 문법

import React from 'react'; 할 때, 뭔가 이상하면 다음 주석을 넣을 것.

import React from 'react'; // eslint-disable-line no-unused-vars

1) 감싸인 요소

컴포넌트에 여러 요소가 있다면 반드시 부모 요소 하나로 감싸야 한다.

import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <h1>리액트 안녕!</h1>
		<h2>잘 작동하니?</h2>
  );
}

export default App;

❌컴포넌트 여러개 요소가 안 감싸져 있어서 오류❌

import logo from './logo.svg';
import './App.css';

function App() {
  return (
		<div> 
	    	<h1>리액트 안녕!</h1>
			<h2>잘 작동하니?</h2>
		</div> 
	);
}

export default App;

⭕잘 감싸져 있습니다. ⭕

왜 꼭 리액트 컴포넌트에서 여러 요소를 쓸거면 부모요소로 묶어야 할까?
그 이유는 이미 우리가 배웠다. 바로 리렌더링시, 성능의 최적화를 위해 DOM 요소의 변화를 쉽게 감지하기 위해서이다. DOM은 트리구조로 이루어져 있다는 사실을 잊지 말자.

2) 자바스크립트 표현

JSX가 단순히 DOM 요소를 렌더링하는 기능만 있지 않다. JSX안에서 자바스크립트 표현식을 쓸 수 있다. 자바스크립트 표현식을 작성하려면 JSX 내부에서 코드를 { } 로 감싸면 된다.

function App() {
  const name = '리액트';
  return (
    <>
      <h1>{name} 안녕!</h1>
      <h2>잘 작동하니?</h2>
    </>
  );
}
export default App;
  • <ES6 의 const 와 let>
    const 는 ES6에서 새로이 도입, 한번 지정하면 변경 불가능한 상수. let은 동적인 값을 담을 수 있는 변수를 선언할 때 사용하는 키워드
    function myFunction(){
    	var a = "hello";
    	if(true){
    		var a = "bye";
    		console.log(a); //bye
    	}
    	console.log(a); //bye
    }
    myFunction();
    ES6 이전에 var 키워드는 scope(해당 값을 사용할 수 있는 코드 영역)이 함수 단위이다.
    if문 밖에서 var 값을 hello로 선언하고, if문 내부에서 bye로 설정, if 문 내부에서 새로선언했음에도, if문 밖에서 a를 조회하면 변경된 값이 나타난다.
    이런 결점을 해결해주는 것이 바로 let 과 const입니다.
    function myFunction() {
    	let a = 1;
    	if(true) {
    		let a = 2;
    		console.log(a) //2
    	}
    	console.log(a); //1
    }
    myFunction();
    let 과 const는 scope 가 함수 단위가 아닌 블록단위여서 if문 내부에서 선언한 a 값은 if문 밖의 a값을 변경하지 않는다.
    단, let 과 const를 사용할때 같은 블록 내부에서 중복선언이 불가능하다.
    let a = 1;
    let a = 2; //이렇게 불가능하다는 뜻이다.
    그리고 const 는 한번 선언하면 재설정할 수 없습니다.
    const b = 1;
    b = 2;
    편하게 생각하면 기본적으로 const를 사용하고, 해당 값을 바꾸어야 할 때는 let을 사용하면된다.

3) if문 대신 조건 연산자

JSX 내부의 자바스크립트 표현식에서 IF문을 사용할 수는 없다.
조건에 따른 내용을 렌더링하려면 JSX 밖에서 if문을 사용하여 사전에 값을 설정하거나, { }안에 조건부 연산자를 사용하면 된다. 자바 스크립트 표현식을 작성하기 위해 이렇게 했죠?

//import React from 'react';
function App() {
  const name = '리액트';
  return (
    <div>
      {name ==='리액트' ?(
        <h1>리액트입니다.</h1>
      ):(
        <h2>리액트가 아닙니다.</h2>
      )}
    </div>
  );
}
export default App;

4) AND 연산자(&&)을 사용한 조건부 렌더링

function App() {
  const name = '뤼액트';
  return <div>{name === '리액트' ? <h1>리액트입니다.</h1>:null}</div>; //null 로 렌더링하면 아무것도 안보여줌.
}
export default App;

이 코드를 AND 연산자를 활용하면 간단하게 코드를 작성할 수 있다.

function App() {
  const name = '리액트';
  return <div> {name === '리액트' && <h1>리액트입니다.</h1>}</div>;
}
export default App;

&&연산자로 조건부 렌더링을 할 수 있는 이유는 리액트에서 false를 렌더링할 떄는 null과 마찬가지로 아무것도 나타나지 않기 때문이다.
null == false와 같은 취급이다. 하지만, falsy한 값인 0 은 예외적으로 화면에 나타남!!

5) undefined 렌더링하지 않기

리액트 컴포넌트에서는 함수에서 undefined만 반환하여 렌더링하는 상황을 만들면 안된다.
예시의 코드를 보자.

import React from 'react';
import './App.css';

function App() {
	const name = undefined;
	return name;
}
export default App;

이를 서버 브라우저에서 실행해보면, 오류가 나옴. (하지만 이제는 JSX 내부에서 undefined를 렌더링하는 것이 가능하다고는 합니다.)
name 값이 undefined 일 때 보여주고 싶은 문구가 있다면 다음과 같이 코드를 작성할 것.

import React from 'react';
import './App.css';

function App() {
	const name = undefined;
	return <div>{name||'리액트'}</div>;
}
export default App;

6) 인라인 스타일링

리액트에서 DOM 요소에 스타일을 적용할 떄는 문자열 형태로 넣는 것이 아닌, 객체 형태로 넣어주어야 한다.
스타일 이름중에서 background-color 처럼 -문자가 포함된 이름이 있는데, 이러한 이름은 - 문자를 빼고, 카멜표기법으로 작성해야한다.

  • style 객체를 미리 선언하고 div의 style 값으로 지정한 코드
import React from 'react'  // eslint-disable-line no-unused-vars

function App() {
  const name = '리액트';
  const style = {
    backgroundColor : 'black',
    color : 'aqua',
    fontSize : '48px',
    fontWeight : 'bold',
    padding : 16 //단위 생략시 px로 지정
  };
    return <div style = {style}>{name} </div>;
}
export default App;
  • style 객체를 미리 선언하지 않고, 바로 style을 지정한 코드
import React from 'react'  // eslint-disable-line no-unused-vars

function App() {
  const name = '리액트';
  return (
    <div
    style = {{
      backgroundColor : 'black',
      color : 'aqua',
      fontSize : '48px',
      fontWeight : 'bold',
      padding : 16
    }}
    >{name}</div>
  );
}
export default App;

7) class 대신 className

일반 HTML에서 CSS클래스 사용시,

<div class = "myClass"> </div> // 이런식으로 class의 속성을 지정했다.

하지만, JSX에서는 class가 아닌 className으로 설정해주어야 한다.
먼저 App.css 파일에 .reaaact 라는 클래스에 해당하는 style을 지정한다. (임의로 지정한 클래스명)이다.

.reaaact{
  background : aqua;
  color : black;
  font-size : 48px;
  font-weight : bold;
  padding : 16px;
}

그 후, App.js 에서 App.css를 불러온 뒤, div 요소에 className을 reaaact로 지정한후 다음과 같이 작성한다.

import React from 'react'  // eslint-disable-line no-unused-vars
import './App.css';

function App() {
  const name = '리액트';
  return <div className = 'reaaact'>{name}</div>;
}
export default App;

8) 반드시 닫아야 하는 태그

HTML 코드를 작성할 때 가끔 태그를 닫지 않은 상태로 코드를 작성하기도 한다.
예를들면 input HTML요소는 <input></input>이라 입력하지 않고, <input>이라고 해도 작동한다.
HTML에서는 다음의 코드는 정상적으로 작동한다.

  • 태그를 닫지 않은 HTML코드
<form>: <br>
	<input><br>
	이름 : <br>
	<input>
</form>

위 코드에서, br과 input태그는 열기만 할 뿐 닫지 않았다.
하지만 JSX 에서는 위와 같은 코드가 제대로 작동하지 않는다. 무조건 닫아야함.
다음과 같이 App.js 에 작성해보아라.

import React from 'react'  // eslint-disable-line no-unused-vars
import './App.css';

function App() {
  const name = '리액트';
  return (
    <>
    <div className = 'reaaact'>{name}</div>
    <input>  
    </>
    
  );
}
export default App;

빨간줄 투성이가 될것이다. 무조건 input태그를 열었다면 닫아야 함.
반면, 태그 사이에 별도의 내용이 들어가지 않는 경우에는 다음과 같이 작성할 수도 있다.
이러한 태그를 self-closing 태그라고 한다.

import React from 'react'  // eslint-disable-line no-unused-vars
import './App.css';

function App() {
  const name = '리액트';
  return (
    <>
    <div className = 'reaaact'>{name}</div>
    <input/>
    </>
    
  );
}
export default App;

9) 주석

JSX 안에서 주석을 작성하는 방법은 일반 자바스크립트와 조금 다르다.

import React from 'react'  // eslint-disable-line no-unused-vars
import './App.css';

function App() {
  const name = '리액트';
  return (
    <>
    {/*주석은 이렇게 작성합니다. */}
    <div
      className = "reaaact" //시작 태그를 여러줄로 작성하게 된다면, 여기에 주석을 작성할 수 있다.
    >
      {name}
    </div>
    //하지만 이런 주석이나
    /* 이런 주석은 페이지에 그대로 나타나게 됩니다. */
    <input />
    </>
  );
}
export default App;

profile
기록하고, 공유합시다

0개의 댓글