[새싹x코딩온] 풀스텍 웹 개발자 과정 No. 31 회고록 | React(Component, JSX, Props)

NARDY·2023년 11월 28일
post-thumbnail

1. 이상해씨, 이상해풀이 되었나?🤔


2주 동안 진짜 눈뜨고 자기 전까지 코딩만 들여다보는 생활을 하면서 수업을 듣는 평온한 일상을 아주 그리워했었는데 드디어 그 평온한 일상을 만끽할 수 있었다! 2주 동안 프로젝트에 전념하고 나서 그래두 수업만 듣던 전보단 조금은 성장한 것 같다. 약간 감(?)같은게 살포시 생겼다. 이상해풀 진화까진 아 니여도 이상해씨에서 풀이 조금씩 자란 것 같달까..ㅋ
프론트엔드에게 중요한 React 첫 수업이 시작되었다. 역시 첫수업은 어느정도 따라잡을만한데 점점 어려워지겠찌.. 이번 12월 동안은 복습을 진짜 빡세게 해야겠다.


2. 프론트엔드 3대장

1) Angular JS

구글에서 만든 JS 기반 오픈 소스 프레임워크, 양방향 데이터 바인딩으로 양방향 웹 애플리케이션에 적합하다.
ex) 유튜브, 페이팔, 구글, 텔레그램 등

2) React JS

동적 사용자 인터페이스를 만들기 위해 페이스북에서 만든 오픈 소스 JS 라이브러리, 데이터 변경이 잦은 복잡하고 규모가 큰 라이브러리에 적합하다.
ex) 페이스북, 인스타그램, 넷플릭스, 야후, 드롭박스 등

3) Vue.js

중국어 기반인 JS 프레임 워크, Angular와 React의 장점을 수용한 것이 특징이다.
ex) 샤오미, 알리바바, 깃랩, 어도비 등


3. React JS

1) 정의

화면을 만들기 위한 JS 라이브러리며, 현재 프론트엔드 개발 환경에서 가장 많이 활용되는 라이브러리이다.
사용자와 상호 작용이 가능한 동적 UI를 제작할 수 있다.

2) 특징

① Data Flow

단반향 데이터 흐름이 특징이다. (양방향X) 즉, 부모 컴포넌트에서 자식 컴포넌트로만 이동한다.
Angular JS처럼 양방향 데이터 바인딩은 규모가 커질 수록 데이터의 흐름을 추적하기 힘들고 복잡해지는 경향이 있다.

② Component 기반 구조

React는 UI(View)를 여러 Component로 만들고 이를 합쳐서 화면을 구성한다.

💡 Component?
독립적인 단위의 소프트웨어 모듈로 소프트웨어를 독립적인 하나의 부품으로 만드는 방법이다.

Component 단위로 쪼개져 있기 때문에 전체 코드를 파악하기 쉽다. 즉, 기능/UI 단위로 캡슐화시켜 코드를 관리하므로 재사용성이 높다.
또한 코드 반복 없이 Component만 import해서 사용할 수 있어 간편하며, 애플리케이션이 복잡해져도 코드이 유지보수, 관리가 용이하다.
ex) header, footer 같은 구조를 Component로 제작 → 이를 조합해 Root Component(최상위 Component)로 만든다.

③ Virtual Dom

React는 DOM Tree구조와 같은 구조를 Virtual DOM으로 가지고 있다.
이벤트가 발생할 때마다 Virtual DOM를 만들고 실제 DOM과 전후 상태를 비교하여 전체를 변경하는게 아닌 변경사항이 있는 부분만 랜더하므로 앱의 효율성과 속도가 개선된다.

④ Props and State

  • Props
    부모 Component에서 자식 Component로 전달해주는 데이터다.
    자식에서는 Props 변경이 불가능하며, Props를 전달한 최상위에서만 변경이 가능하다.

  • State
    Component 내부에 선언되고 내부에서 값을 변경하며, 각각 state는 독립적이다.
    클래스형 Component에서만 기본제공이 되고, 함수형 Component에선 기본제공이 되지 않는다.

⑤ JSX

React에서 JSX 사용이 필수는 아니나, 편의성을 위해 대부분 프로젝트에서 JSX를 사용한다.
JSX는 JS + XML(HTML 같은 마크업 언어)라 생각하면 된다. JS를 확장한 문법으로 React Element를 생성한다.

3) 패키지

JS 런타임인 Node.js 기반으로 만들어진 Webpack과 Babel 같은 도구을 자주 사용한다.

① Babel

옛날엔 큰 기능을 하지 않는 JS 컴파일러(해석기)였으나, React에서는 중요한 역할은 한다.
최신 JS문법을 이전 버전의 JS문법으로 변환하여 다양한 브라우저에서 호환성에 문제 없이 코드를 실행할 수 있다.

② Webpack

JS 모듈 번들러로, 여러 개의 파일과 모듈을 하나의 파일로 합쳐준다. 코드 변경 사항이 발생하면 바로 반영되는 기능을 갖고 있다.

4) 프로젝트 생성

① React 프로젝트 생성

  • React 프로젝트 생성 명령어

    npx create-react-app 프로젝트명
  • React 프로젝트 이름 규칙

    • 대문자 사용 불가
    • 여러 개의 단어 사용시 하이픈 기호(-)로 구분
  • npx : npm의 자식 명령어로 npm보다 가볍게 패키지를 구성한다.

    • npm 버전이 5.2 이상일 때, node 버전이 14이상일 때 사용 가능하다.

② React 프로젝트 실행

  • React 프로젝트 실행 명령어
    npm start
    정상적으로 React 프로젝트 실행되면 아래와 같은 메시지가 뜬다.

③ React 프로젝트 구조

React 프로젝트 실행하고 나서 폴더들을 보면서 필요없는 파일들을 제거한 후 프로젝트를 시작한다.

  • /node_modules : npm을 시작하면 생기는 폴더로, 내부에 모듈과 관련된 정보가 들어있다.
  • /public : index.html & favicon.ioc → 가상 DOM을 위한 html 파일이 들어있으며, 이미지 파일 등 정적인 파일들을 넣는 폴더이다.
  • /src : 실제 React 코드(Component)를 작성하는 폴더이며, 화면을 랜더링하기 위한 코드들을 넣는 폴더이다.

5) 디버깅

기존 JavaScript는 console창으로 에러를 확인하지만, React는 치명적인 버그일 경우 화면에 바로 띄워준다.
JS의 문제점을 보완하고자 strict mode 강제하였다.


4. Component

React의 꽃이자, React의 핵심으로, 화면을 구성하는 하나의 부분을 의미한다.
내부의 데이터만 변경해서 전체적인 틀(UI)을 재사용할 수 있다. 즉, UI를 재사용 가능한 개별적인 여러 조각으로 나누고, 각 조각을 개별적으로 나누어 분리가 가능하다.

1) Component 트리 구조

2) Reac Component 종류

① 클래스형 컴포넌트(Class Component)

  • render 함수를 반드시 사용해야 한다.
  • lifecycle 기능
  • component를 만들 때 기존 components 클래스에서 상속받아서 사용한다.

② 함수형 컴포넌트(Functional Component)

  • 짧고 직관적이며, 사용방법이 더 간단하다.
  • 메모리 사용에 이점이 있다.
  • 현재는 클래스형보단 함수형 컴포넌트를 주로 사용한다.

③ 공통사항

component명에 PascalCase를 사용한다.

3) Component 생성

① 클래스형 컴포넌트(Class Component)

// 파일명 : ClassComponent.js

<script>
// 클래스형 컴포넌트 작성법

import { Component } from "react";

class ClassComponent extends Component {
  render() {
    return <h1>Class Component 입니다!</h1>;
  }
}
export default ClassComponent;

</script>

② 함수형 컴포넌트(Functional Component)

// 파일명 : FuncComponent.js

<script>
// 함수형 컴포넌트 작성법 1
export default FuncComponent = () => {
  return
  <div>Function Component 입니다!</div>;
};

// 함수형 컴포넌트 작성법 2
function FuncComponent() {	
    return(
   <div>Function Component 입니다!</div>
);
}
export default FuncComponent;
</script>

③ App.js

// 파일명 : App.js

<script>
import "./App.css";
import ClassComponent from "./components/ClassComponent";
import FuncComponent from "./components/FuncComponent";

function App() {
  return (
    <div className="App">
      <ClassComponent />
      <FuncComponent />
      <FuncComponent></FuncComponent>
      
    </div>
  );
}

export default App;
</script>

5. JSX

JSX는 JavaScript + XML 라 생각하면 된다. 자바스크립트 확장 문법으로 XML 과 유사하며, 바벨을 이용해 일반 자바스크립트 코드로 변환한다.

1) 특징

① 반드시 하나의 부모 요소가 전체 요소를 감싸는 형태

html 태그는 항상 return 이후에, 반드시 하나의 부모 요소가 전체 요소를 감싸는 형태로 있어야하며,
딱 하나의 태그만 return할 때는 ( )가 필요 없지만 여러 개의 태그가 있다면 return (~) 괄호 내부에 작성해야 한다.
부모 요소를 아래와 같이 할 수도 있다.

<>
<div>안녕!</div>
<div>죠르디:)</div>
</>

② html with JS

html를 작성하다가 중간에 js 문법을 사용하고 싶을 때는 `{ }' 로 감싸야 한다.
삼항연산자(간단한 것만 가능)만 사용할 수 있으며, if문/for문은 작성이 불가하다.

<h4>{name == "jordy" ? "안녕하니니!" : "죠르디를 불러줘니니!!"}</h4>
  • 복잡한 조건을 써야 한다면 return 상위에 함수로 만들고 return ( )안에서 불러오면 된다.

    <script>
    function FuncComponent() {
       const ifRenderTest = () => {
       if (name === "naraka") {
         return "안녕하세요!";
       } else if (name === "richard") {
         return "반가워요!";
       } else {
         return "누구세요?";
       }
     };
    
     return (
     <>
         {/* 2-1. 복잡한 조건을 이용하고 싶다면 위에서 변수로 만들고 밑에서 불러오면 된다. */}
         <h4>{ifRenderTest()} </h4>    
     </>
    ); 
    </script>
  • 조건에 따른 렌더링(논리연산자 : &&)

     <script>
       return (
       <>
         {/* && : 앞의 내용이 참이면 거짓값이 아예 안나오므로 거짓일 때 값을 설정할 필요가 없음!*/}
         
         <h5>{name === "jordy" && "죠르디를 불러와!"}</h5>
       </>
     );
    </script>

③ 인라인 style 적용

CSS를 인라인 형태로 적용할 때는 {object} 형태로 입력해야 한다.
CSS 속성은 dash-case를 camelCase로 바꿔서 작성하며, return 위에 object를 변수에 담아놓고 사용할 수 있다.

<script>
 const style = { fontSize: "20px", color: "red" };

  return (
    <>
      {/* 3. inline style 적용 방법 -> style 속성 값으로 객체{} 전달 */}
      <div style={{ fontSize: "30px", color: "red" }}>안녕하니니!</div>
      
      {/* 3-1. inline style 적용 방법 -> return 위에 object를 변수에 담아놓고 사용 */}
      <div style={style}>반갑니니!</div>
    </>
   ); 
</script>

CSS 이름이 겹칠 확률이 높아지기 때문에 BEM 네이밍 규칙 등을 사용해 이름이 중복될 확률을 줄인다.

💡 BEM 네이밍 규칙?
Block, Element, Modifier으로 이 3가지를 이용하여 이름을 짓는 방식이다.
참고 : https://nykim.work/15

④ class와 onclick

class 대신 className, onclick대신 onClick 을 사용한다.
클래스 이름도 따로 선언해서 className={class-name}처럼 사용할 수 있다.

<script>
  return (
    <>
      {/* 4. class와 onclick을 jsx에서 사용하기 */}
      {/* <div class="" > -> 원래 html에서 사용하는 방식 */}
      <div className="test-css">jsx에서 css사용하기(className)</div>

      {/* html에서는 onclick안에 함수를 '호출'해서 사용함, jsx에서는 함수를 '선언'해서 사용한다. */}
      <button
        onClick={() => {
          console.log("hello");
        }}
      >
        버튼
      </button>
    </>
   );
</script>

가상돔과 실제돔을 비교하면서 리랜더링 하면서 바뀐 부분을 계속 랜더하는데, 호출하는 경우 랜더할 때마다 매번 실행되므로 함수를 호출하지 않고 선언해서 매번 함수가 자동실행되지 않도록 ‘선언’해서 사용한다.

⑤ closing tag

opening tag(빈태그)도 closing tag가 필요하다.
ex) <br />

⑥ 주석 사용

{/* ~ */} 로 주석을 작성한다.


6. Props

properties를 줄인 표현으로 컴포넌트 속성을 설정할 때 사용하는 요소다.
컴포넌트끼리 값을 전달하는 수단이며, 상위 컴포넌트에서 하위 컴포넌트로 전달한다. (단방향 데이터 흐름)

  • defaultProps : 부모 컴포넌트에서 props가 전달되지 않았을 때 기본값으로 보여줄 props를 설정한다.

  • props.children : 부모 컴포넌트에서 자식 컴포넌트를 호출할 때 태그 사이에 작성한 문자열이다.

    // Section.js
    <script>
    import PropTypes from "prop-types";
    
    function Section({ title, children }) {
     return (
       <>
         <div className="Section__section">
           <h3 className="Section__title">{title}</h3>
           <div>{children}</div>
         </div>
       </>
     );
    }
    
    Section.prototypes = {
     title: PropTypes.string,
     children: PropTypes.node,
    };
    
    export default Section;
    
    </script>
    // App.js
    <script>
    import "./App.css";
    import Section from "./components/Section";
    
    function App() {
     return (
       <div className="App">
         <Section title="NINIZ 영역">
           <div>NINIZ 영역의 content다니니</div>
         </Section>
         <Section title="Jordy 영역">
           <h5>Jordy 영역의 content다니니</h5>
         </Section>
       </div>
     );
    }
    export default App;
    </script>
  • propTypes : 컴포넌트의 필수 props를 지정하거나 props의 타입을 지정할 때 사용g한다.
    JavaScript의 “유연한 특성” 을 해결하기 위해 권장되는 기능이다.
    정해진 타입이 아닌 다른 타입으로 정보가 전달될 시, 제대로 동작은 하지만 console에 오류가 나온다.

1) Props 종류

① 함수형 컴포넌트 props

부모 component에서 전달한 props는 함수형 컴포넌트에서 함수의 파라미터로 전달받으며, JSX 내부에서 { } 기호로 감싸서 사용한다.

// FuncPropsEx.js
<script>
// 1. props 매개변수 (기본적인 사용법)
function FuncPropsEx(props) {
  props = {
      title: "SeSAC"
      content : "hello world"
  };

  return (
    <>
      <div>함수형 컴포넌트를 이용( Props )</div>
      <div>
        여기는 {props.title}, 외쳐요 {props.content}!!
      </div>
    </>
  );
}

// 2. 매개변수로 props를 받아올 때 부터 구조분해를 사용해서 입력하는 방법
function FuncPropsEx({ title, content }) {
  return (
    <>
      <div>함수형 컴포넌트를 이용( Props )</div>
      <div>
        여기는 {title}, 외쳐요 {content}!!
      </div>
    </>
  );
}

// 3. 컴포넌트 안에서 구조분해를 하는 방법
function FuncPropsEx(props) {
  const { title, content } = props;
  return (
    <>
      <div>함수형 컴포넌트를 이용( Props )</div>
      <div>
        여기는 {title}, 외쳐요 {content}!!
      </div>
    </>
  );
}

// 4. porptype을 이용하여 어떤 props가 넘어올지 명시하는 방법
// 유연한 JS의 특징으로 인해 예기치 못한 오류가 발생할 수 있기 때문에 정확하게 명시하여 오류 발생을 예방.
// JS가 알아서 제대로 동작하게 하나, 개발자는 어디서 오류가 발생했는 지 알 수가 없게되므로 위 방법대로 진행함.
import PropTypes from "prop-types";
function FuncPropsEx({ title, content, number }) {
  return (
    <>
      <div>함수형 컴포넌트를 이용( Props )</div>
      <div>
        여기는 {title}, 외쳐요 {content}!! {number}
      </div>
    </>
  );
}
// 입력해둔 props가 안넘어갈 때 대신 채워줄 default값을 입력하면 대신 채워준다!
FuncPropsEx.defaultProps = {
  title: "SeSAC용산",
};

FuncPropsEx.propTypes = {
  title: PropTypes.string,
  content: PropTypes.string.isRequired,
  number: PropTypes.number,
};

export default FuncPropsEx;

</script>
// App.js
<script>
import "./App.css";
import FuncPropsEx from "./components/FuncPropsEx";

function App() {
  return (
    <div className="App">
      {/* props에 title과 content가 객체로 들어간다. */}
      <FuncPropsEx title="SeSAC" content="hello world" number={231128} /> 
    </div>
  );
}

export default App;
</script>

② 클래스형 컴포넌트 props

// ClassPropsEx.js
<script>
import { Component } from "react";
import PropTypes from "prop-types";

// 1. 클래스 밖에서 proptypes를 적는 방법
class ClassPropsEx extends Component {
  render() {
    return (
      <>
        <div>클래스형 컴포넌트를 이용 ( Props )</div>
        <div>
          여기는 {this.props.title}, 외쳐요 {this.props.content}!! 오늘 날짜는{" "}
          {this.props.number}
        </div>
      </>
    );
  }
}
ClassPropsEx.defaultProps = {
  title: "SeSAC용산",
};
ClassPropsEx.propTypes = {
  title: PropTypes.string,
  content: PropTypes.string.isRequired,
  number: PropTypes.number,
};

// 2. static을 이용해  proptypes를 클래스 내에 적는 방법.
class ClassPropsEx extends Component {
  render() {
    return (
      <>
        <div>클래스형 컴포넌트를 이용 ( Props )</div>
        <div>
          여기는 {this.props.title}, 외쳐요 {this.props.content}!! 오늘 날짜는{" "}
          {this.props.number}
        </div>
      </>
    );
  }
  static defaultProps = {
    title: "SeSAC용산",
  };

  static propTypes = {
    title: PropTypes.string,
    content: PropTypes.string.isRequired,
    number: PropTypes.number,
  };
}

export default ClassPropsEx;
</script>
// App.js
<script>
import "./App.css";
import ClassPropsEx from "./components/ClassPropsEx";

function App() {
  return (
    <div className="App">
      {/* props에 title과 content가 객체로 들어간다. */}
      <ClassPropsEx title="SeSAC" content="hello world" number={231128} /> 
    </div>
  );
}

export default App;
</script>

7. 마치며

간만에 벨로그로 정리하니 정리하는 방법을 그 새 까먹었는데 하나하나 정리하면서 얼른 감을 되찾아야겠다.

💻 본 글은 새싹X코딩온 풀스텍 웹 개발자 과정 수업과 수업자료를 참조하여 작성하였습니다.

profile
새싹 개발자

0개의 댓글