React 시작하기

seul_velog·2022년 3월 30일
0

React

목록 보기
1/11
post-thumbnail
post-custom-banner

React

컴포넌트 단위로 이루어진 UI(User Interface)를 만들 수 있는 라이브러리




컴포넌트 Component

버튼 하나와 같이 한 가지의 기능을 수행하는 UI단위




Webpack과 Babel

리액트 프로젝트를 만들게 되면서, 컴포넌트를 여러가지 파일로 분리해서 저장 할 것이고, 또 이 컴포넌트는 일반 자바스크립트가 아닌 JSX 라는 문법으로 작성하게 된다.

  • 여러가지의 파일을 한개로 결합하기 위해서 Webpack 이라는 도구를 사용한다.
  • JSX 를 비롯한 새로운 자바스크립트 문법들을 사용하기 위해서 Babel 이라는 도구를 사용한다.

📌 Babel
바벨은 자바스크립트의 문법을 확장해주는 도구이다.
아직 지원되지 않는 최신 문법이나, 편의상 사용하거나 실험적인 자바스크립트 문법들을 정식 자바스크립트 형태로 변환해줌으로써 구형 브라우저같은 환경에서도 제대로 실행 할 수 있게 해주는 역할을 한다.
BABEL 사용해보기




react-app

  • create-react-app 을 통해서 리액트 툴을 설치한다.
  • 페이스북에서 만든 패키지였다. 라이브러리를 이용, 프로젝트를 간편히 만들 수 있다.
  • 깃도 초기화가 되어진다.
  • 툴 안에는 BABEL, Webpack, ESLint, Jest, PostCSS 등이 들어있다.
  • 바벨, 웹 팩을 어떻게 설정하면 되는지 몰라도 공통적으로 많이 설정되는 것들이 기본적으로 설정되어진다.
    → 현업에서는 수동적으로 관리를 하기때문에 잘 사용하지 않는다고 한다. 🤔

📌 CRA 살펴보기

  • npx create-react-app [파일명]
  • node_modules: npm으로 다운받은 모든 패키지들이 저장된 폴더
    • node_modules는 용량이 크므로 git ignore에 등록되어 있는 상태 (즉, git clone 시 해당 파일을 받지 않음)
      npm install 로 설치 (npm이 dependencies 항목을 자동으로 읽어서 필요한 패키지를 다운받음)
  • package.json : 프로젝트에대한 정보들이 기입된 파일
    • script : 이 프로젝트에서 실행할 수 있는 명령어들
      → start의 경우 관습적으로 사용되므로 그냥 입력ok
      → build 등의 경우 npm run build 와 같이 실행
    • dependencies : 프로젝트에서 필요로하는 다른 패키지들에 대한 정보




import와 export

import React from 'react';
  • 리액트 컴포넌트를 만들 때는 import를 통해서 리액트를 불러온다.
export default Hello;
  • 컴포넌트를 내보내고, 다른 컴포넌트에서 불러와서 사용할 수 있다.




react-dom과 render함수

import React from 'react';
import ReactDOM from 'react-dom'; // 3)
import App from './App';

ReactDOM.render( // 1)
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root') // 2)
);
  • 1) ReactDOM.render 의 역할은 브라우저에 있는 실제 DOM 내부에 리액트 컴포넌트를 렌더링하겠다는 것을 의미한다.

  • 2) idroot 인 DOM 을 선택하고 있는데, 이 DOM은 리액트 컴포넌트가 렌더링 될 때, public/index.html 파일 내 <div id="root"></div> 내부에 렌더링 된다.

  • 즉, 사용자에게 궁극적으로 배포되어 지는 것은 index.html 이며, id=”root” 를 통해서 자바스크립트와 연결해준다.
    → 이것을 가능하게 하는 것이 3) react-dom 이다.

    • react-dom 이라는 라이브러리에서 ReactDOM 클래스를 import, 가져온다.
    • 가져온 ReactDOM 이라는 클래스에 있는 렌더 함수를 이용, document.getElementByIdroot 요소를 가지고 와서 컴포넌트를 연결시켜준다.

📌 ReactDOM.render()

  • render함수는 3개의 입력을 받는다. 첫번째 인자는 표시할 내용, 두번째 인자는 그것을 보여주는 곳을 넣는다. 세번째 인자로는 렌더 기능이 완료되었을 때 알려주는 콜백을 선택적으로 추가할 수 있다고 한다. 그동안 랜더 함수의 인자가 어떻게 표현되는지 생각을 못해봤는데 알고 보니 당연하게도 각각의 역할이 있었다. 😀
    ▼ 아래 코드는 root 안에 App 컴포넌트를 표시하기 위해 ReactDOM 모듈의 render 메소드를 사용한 것이라고 볼 수 있다.
    ReactDOM.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>,
      document.getElementById('root')
    );
  • 아래 두 코드는 브라우저에서 같은 결과로 출력된다.
// 1)
ReactDOM.render(<h1>Hello world! </h1>, document.getElementById("root"));

// 2)
const h1 = document.createElement("h1");
h1.innerHTML = "Hello world!";
document.getElementById("root").appendChild(h1);

📌 React 모듈

  • React 모듈 내부에는 Babel이 있고, babel은 JSX를 일반 JavaScript로 컴파일 하는 작업이 포함된다. 따라서 아래 코드를 지우면 제대로 동작할 수 없다. (react가 정의되지 않았으며 더이상 App컴포넌트가 렌더링 되지 않음)
import React from 'react';

+) 추가
최신 버전에서 해당 코드가 없어도 동작되는 부분이 궁금해서 참고로 찾아본 글 :)





JSX

  • JavaScript와 HTML을 합쳐놓은 듯한 형태이며, 마크업을 편리하게 작성하기 위한 문법이다.
  • 자바스크립트가 인식할 수 없는 문법이므로 Bable이라는 패키지를 이용해서 변환해 줘야한다.
  • JSX는 리액트 컴포넌트에서 XML 형식의 값을 반환해 준다.

❓ 정확히 JS소스의 어느 부분 안에서 JSX를 문법을 지켜야 하는걸까 ?
return(...) 내에 JSX 문법으로 작성한다. ( 궁금해서 이 안에서 JSX가 아닌 js 문법을 사용하니 작동이 되지 않았다. 하지만 컴포넌트 안에서도 JSX문법이 적용되는 것 같은데 이부분은 다시 확인해 보자. 🤔 )


왜 JSX를 쓸까 ?

  • React.createElement vs JSX 중 JSX의 가독성이 훨씬 좋다.
  • babel 과 같은 컴파일 과정에서 문법적 오류를 인지하기 쉽다.
  • html 태그를 그대로 사용하므로 익숙하고, html마크업과 js로직을 같이 구현할 수 있다.
  • js 문법을 이용해서 html을 생성할 수 있고, 기존의 DOM+Event 작동방식과 비교했을 때 훨씬 간편하게 UI 구성이 가능하다.

JSX 문법 특징

  • 최상위 요소가 하나여야 한다.
  • 최상위 요소 리턴시 () 로 감싸야 한다. (요즘은 절대적이지 않다고 한다. vscode prettier)
  • 자식들을 바로 렌더링할 때는 <>자식들</> 를 사용한다. (Fragment)
  • 자바스크립트 표현식을 사용하려면 {표현식} 처럼 사용한다.
  • if 문은 사용할 수 없다. 삼항 연산자나 && 를 사용한다.
  • style 을 이용해 인라인 스타일링이 가능하다.
  • camelCase Property를 이용한다.
    ex.) class 대신 className을 사용해서 class 를 적용한다.
  • 자식요소가 있으면 꼭 닫고, 자식요소가 없으면 열면서 닫아야 한다. ex.) <p>내용</p>, </br>
  • 모든 태그가 셀프클로징이 가능하다.
  • 컴포넌트 첫글자는 대문자(파스칼케이스)로 작성한다. 일반 태그와 구별이 되지 않기 때문이다.

✍️ JSX 사용하기

태그는 꼭 닫혀있어야 한다.

  • 리액트에서는 HTML에서의 input 태그와 br 태그를 사용할 때처럼 닫지 않고 사용하게 되면 에러가 발생한다.
  • 태그 사이에 내용이 들어가지 않을 때 Self Closing 태그를 사용할 수 있다.
    ex.) <br />

형제노드를 사용할 수 없다.

  • JSX는 형제노드가 있는 경우 묶어줘야한다.
    → 다수의 태그들을 리턴할 수 없다. 따라서 <> 태그와 같이 묶어줘야 한다. 즉 꼭 감싸져야 한다.
  • 렌더 메소드를 사용할 때 단일 HTML 요소만 사용할 수 있기 때문이다.
    function App() {
      return (
        <div> // 이곳에 div 태그로 묶어주지 않으면 에러
          <Hello />
          <Hello />
          <Hello />
        </div> // 
      );
    }
  • 단순히 감싸기 위해서 div 태그 남용을 방지하기 위해서 리액트에서 제공하는 Fragment 를 이용한다.
  • Fragment 는 브라우저 상에서 따로 별도의 엘리먼트로 나타나지 않는다.
    function App() {
      return (
        <React.Fragment> // <> 로 표기가능
          <Hello />
          <Hello />
          <Hello />
        </React.Fragment> // </> 로 표기가능
      );
    }
    ✍️ 감싸는 이유
    : 리액트가 사용하는 Virtual DOM 방식에서는 컴포넌트 변화를 감지할 때 효율적으로 비교하고자, 컴포넌트 내부는 하나의 DOM 트리 구조로 이루어져야 한다는 규칙이 있기 때문이라고 한다.🤔

JSX 변수 접근하기, 조건부 렌더링

  • JSX 내부에 자바스크립트 변수를 보여줘야 할 때에는 {} 으로 감싸서 보여준다.
  • 이처럼 HTML처럼 간편하게 마크업 가능 + 비즈니스로직 (js코드) 와 함께 섞어서 사용 가능하다.
function App() {
  const name = "seul";
  return (
    <>
    
      <Hello />
      {name && <h1> Hi ~ </h1>} // name이 있으므로(true) 출력된다.
  
      {["a", "b"].map((i) => (<h2>{i}</h2>))} // i를 {}안에 넣어야 한다.
  
    </>
  );
}

✍️ JSX 내부의 자바스크립트 표현식 내에서는 if 문을 사용할 수 없다. 대신 조건부 연산자(삼항 연산자)를 사용한다. ▼

function App() {
  const name = "seul";
  return <>{name === "seul" ? <h1>yes</h1> : <h1>no</h1>}</>;
}
  • 보통 삼항연산자를 사용한 조건부 렌더링은 특정 조건에 따라 보여줘야 하는 내용이 다를 때 사용한다. 단순히 특정 조건이 true 일 때 보여주고 싶다면 && 연산자를 사용해서 처리하는 것이 간단하다.

✍️ undefined 를 렌더링하지 않아야 하며, OR연산자를 이용해서 방지할 수 있다. ▼
- JSX 내부에서 undefined를 렌더링 하는 것은 에러가 나지 않는다. (JSX 에서 null, false, undefined 를 렌더링하게 된다면 아무것도 나타나지 않게 된다.)

function App() {
  const name = undefined;
  return name || "값이 undefined";
}

❓ 왜 if문은 사용할 수 없을까 🤔 ?
✍️ Expressions과 Statements

  • JavaScript는 Expressions(표현식)과 Statements(문장)을 구별한다.
  • if while for 모두 Statements이다. 이들 모두 단지 작업을 수행하고 작업을 제어하지만 값이 되지는 않는다. 여기서 if문은 표현식이 아닌 문장이기 때문에 작동하지 않는 것이라고 한다.
  • 대체할 수 있는 방법이 어떤 것들이 있는지 찾아보았다. 필요할 때 참고해보자🔥
    리액트에서 자주쓰는 if문 작성패턴 5개

style과 className

(1) 인라인 스타일

  • 객체 형태로 작성한다. 프로퍼티는 camelCase형태로 네이밍 해준다.
function App() {
  const name = "seul";
  const style = {
    backgroundColor: "gray",
    color: "aqua",
    fontSize: 24, // 기본 단위 px
    margin: "1rem", // px외 다른 단위 사용 시 문자열로 설정
  };
  return (
    <>
      <Hello />

      <div style={style}>
        {name && <h1> Hi ~ </h1>}
        {["a", "b"].map((i) => (
          <h2>{i}</h2>
        ))}
      </div>
    </>
  );
}

✍️ 혹은 아래와 같이 사용할 수 있다.

function Login() {
  return (
    <h1
      style={{
        color: 'powderblue',
      }}
    >
      Login
    </h1>
  );
}
  • JSX안에서 스타일을 부여해 줄 때는 자바스크립트 객체 형태로 부여해 줘야한다.
    즉 자바스크립트 문법을 표현해 주기 위해 {} 를 한번 넣고, 객체 형태를 부여해주기 위해 {}를 한번 더 넣는다. (자바스크립트 활용 + 객체 활용)

(2) 가져오기

  • CSS class를 설정할 때는className 으로 설정한다.
/* App.js */
import React from "react";
import Hello from "./Hello";
import "./App.css";

function App() {
  const name = "seul";
  const style = {
    backgroundColor: "gray",
    color: "aqua",
    fontSize: 24, // 기본 단위 px
    margin: "1rem", // 다른 단위 사용 시 문자열로 설정
    padding: "1rem",
  };
  return (
    <>
      <Hello />
      <div style={style}>{name}</div>
      <div className="box"></div>
    </>
  );
}

export default App;
/* App.css */
body {
  font-size: 30px;
  margin: 1rem;
}

.box {
  background-color: powderblue;
  width: 60px;
  height: 60px;
  margin-left: 1rem;
}


주석 사용하기

  • JSX 내부의 주석은 {/* 이런 형태로 */} 작성한다. {} 중괄호로 감싸지 않으면 화면에 보이게 된다.
  • 열리는 태그 내부에서는 // 이런 형태로 도 작성이 가능하다.
function App() {
  return (
    <>
      
      {/* 화면에 보이지 않는 주석1 */}
      <Hello  // 화면에 보이지 않는 주석2
      />
      
      /* 화면에 보인다 */
      // 화면에 보인다
      
    </>
  );
}



+) ✍️ 추가

React 18

리액트18버전 이후로 콘솔창에 에러가 나타나서 index.js 파일을 재설정 해주었다.
이렇게 공부하고 알아가는 도중에도 라이브러리나 프레임워크들이 계속해서 새로운 버전이 나오고 바뀌고 개선되어가면서 기술이 빠르게 발전된다는 것을 느꼈다. 😀 공식사이트에서 소식을 접했는데, 최신 트렌드와 개선된 환경 등을 바로 이해하고 공감하고 토론도 해보고 싶은 욕심이 생겼다. 계속해서 지식을 쌓고 싶다!

import ReactDOM from 'react-dom'; // 18 이전 버전
import ReactDOMClient from 'react-dom/client'; // 18 버전


ReactDOM.render(<App />, document.getElementById('root')); // 18 이전 버전
// 18 버전
 const container = document.getElementById('root');
 const root = ReactDOMClient.createRoot(container);
 root.render(<App />);
// 혹은 아래처럼
ReactDOMClient.createRoot(document.getElementById('root')).render(<App />);

📌 참고 !
React_How to Upgrade to React 18
react18 준비하기




reference)
vlpt-react
react-jsx
DreamCoding
udemy

profile
기억보단 기록을 ✨
post-custom-banner

0개의 댓글