React TIL (2)

기멜·2021년 11월 14일
0

React

목록 보기
2/24

오늘도 리액트 공부 해보겠다. 이곳저곳에서 강의를 듣고 정리해보는

라이브러리란?

간략 설명: 프로그램 제작 시 필요한 기능
비교 설명: 자동차 바퀴, 자동차 헤드라이트, 자동차 에어백 등

재사용이 필요한 기능으로 반복적인 코드 작성을 없애기 위해 언제든지필요한 곳에서 호출하여 사용할 수 있도록 Class나 Function으로 만들어진 것입니다. 사용여부는 코드 작성자 선택 사랑이며 새로운 라이브러리 제작 시에도 엄격한 규칙이 존재하지 않습니다. 제작 의도에 맞게 작성하면 됩니다.

라이브러리 예시

  • 가장 유명한 자바스크립트 라이브러리는 jQuery입니다.
  • 그래픽 사용자 인터페이스 (GUI)에서 재사용하기 쉽게 버튼, 테이블 같은 구성 요소를 호출해서 쓸 수 있도록 분리해두었다면 라이브러리입니다.
  • window에서 간론 보았을 dll 확장자는 동적 링크 라이브러리 (DLL)의 약자로 라이브러리라고 할 수 있습니다.
  • 객체 지향 프로그래밍 (OPP)은 기본적으로 각 기능마다 함수화 하는 것으로 클래스 라이브러리라고 할 수도 있습니다.

프레임워크란?

간략설명: 프로그램 기본 구조(뼈대)
비교 설명: 자동차 프레임

원하는 기능 구현에만 집중하여 빠르게 개발 할 수 있도록 기본적으로 필요한 기능을 갖추고 있는 것으로 위에서 설명한 라이브러리가 포함되어 있습니다.
프레임워크만으로는 실행되지 않으며 기능 추가를 해야 되고 프레임워크에 의존하여 개발해야 되며 프레임워크가 정의한 규칙을 준수해야 합니다.
겉보기에는 비슷하지만 많은 프레임워크가 존재하는 이유는 아래에서 설명하게 될 아키텍처가 다른 것이며 규칙을 준수해야 되는 이유기도 합니다.

프레임워크 예시

  • JavaScript 개발자라면 Angularjs!

출처: 개발자스럽다 blog

이제 React를 본격적으로 다뤄보겠습니다.

const hi = <p>Hi</p>;

위 코드는 자바스크립트인가요 HTML인가요? 둘 다 아닙니다.
JSX라고 불리는 자바스크립트 확장버전입니다. javascript syntax extension 라고 합니다. HTML과 아주 비슷하게 생겼고 JavaScript 파일 내에서 작성할 수 있습니다.

JSX는 원래의 자바스크립트 문법이 아니기 때문에, .js파일 내에 JSX문법이 있으면 브라우저에서 해석하지 못합니다. 문법 오류가 납니다.

React.js를 사용하기 위해 JSX 문법이 포함되어 있으면, 해당 파일을 정규 javascript 문법으로 변환시키는 컴파일 과정이 필요합니다.

JSX element

HTML문법을 JavaScript 코드 내부에 써주면 그것이 바로 JSX입니다. .js 파일 어디에서나 필요한 곳에 작성해주세요. 변수에 저장할 수도 있고, 함수의 인자로 넘길 수도 있습니다.

const hi = <p>Hi</p>;

const myFavorite = {
    food: <li>샐러드</li>,
    animal: <li>dog</li>,
    hobby: <li>programming</li>};

JSX attribute

태그에 attribute(속성)을 주고 싶을 때는 항상 "" 쌍따옴표로 감싸주세요. attribute를 추가하고 싶을 때는 실제 HTML에서 쓰는 attribute name(속성명)과 다를 수 있으니 react 공식문서를 참고해주세요.

예를 들어, class를 주고 싶을 때 원래 속성명은 class이지만 JSX에서는 className을 사용해야 합니다.

const hi = <input readOnly={true} />;

const myFavorite = {
    food: <li>샐러드</li>,
    animal: <li>dog</li>,
    hobby: <li className="list-item">programming</li>};

Self-Closing Tag

그리고 JSX에서는 어떤 태그라도 self closing tag가 항상 가능합니다. <input\>과 같이 하나의 태그가 요소인 경우에는  <input /\>와 같이 항상 /으로 끝내줘야 합니다.<div />와 <div></div>는 같은 표현입니다.

Nested JSX

  1. (필수) 소괄호로 감싸기

    const good = (
    <div>
        <p>hi</p>
    </div>);

    중첩된 요소를 만들려면 () 소괄호로 감싸주세요!

  2. (필수) 항상 하나의 태그로 시작

    const wrong = (
    <p>list1</p><p>list2</p>);

    위와 같이 제일 처음 요소가 sibling이면 안됩니다. 무조건 하나의 태그로 감싸져야 합니다. 아래의 코드처럼 첫 요소는 하나의 태그로 감싸주세요.

    const right = (
      <div>
        <p>list1</p>
        <p>list2</p>
      </div>
    );

Rendering

html 요소(element), 또는 React 요소 등의 코드가 눈으로 볼 수 있도록 그려지는 것을 렌더링(rendering) 이라고 말합니다.

React 요소가 DOM node에 추가되어 화면에 렌더되려면 ReactDOM.render 함수를 사용합니다. 첫 번째 인자에는 JSX로 React 요소를 인자로 넘기고, 두 번째 인자는 해당 요소를 렌더하고 싶은 container(부모요소)를 전달합니다.

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('root')
);

Component

프론트앤드 개발에서 Component라는 단어를 많이 사용합니다. 컴포넌트란 재사용이 가능한 UI 단위입니다.
회원가입 페이지를 만들 때 input태그가 여러개 필요했을겁니다. 만약 '내정보수정'이라는 페이지가 추가되어 password input이 필요하다면, 또 똑같은 html, css를 작성해주어야합니다. 이럴 때 동일 코드가 반복되는 부분을 하나의 component로 만들어서 같은 디자인의 input이 필요한 곳마다 재사용할 수가 있습니다.

컴포넌트를 하나만 만들고 여기저기서 재사용하면, input 디자인이 바꼈을 때 css 한줄만 수정하면 로그인, 회원가입, 내정보수정 페이지에 바뀐 디자인이 모두 반영이 됩니다.

컴포넌트는 독립적으로, 재사용가능한 코드로 관리할 수 있습니다. 하나의 컴포넌트에 필요한 html,css,js를 모두 합쳐서 만들 수 있습니다.

컴포넌트는 함수랑 비슷합니다. 함수도 기능이 독립적이고 한번 선언해두면 필요할 때 마다 호출하면서 재사용할 수 있습니다. 컴포넌트도 함수처럼 input을 받아서 return 할 수 있습니다.

React 컴포넌트에서는 input을 props라고 말하고 return은 화면에 보여져야할 React요소가 return 됩니다.

Component 만들기

React는 Component를 만들고 관리하기 정말 좋은 라이브러리 입니다. React에서는 컴포넌트를 class나 함수로 만들 수 있습니다. 어떤 때에는 함수로 만들면 좋고, 어떤 때에는 class로 만들어야만 합니다. 일단은 컴포넌트를 어떻게 만들 수 있는지 알아봅시다 :)

함수로 Welcome 컴포넌트 구현하기

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

class로 Welcome 컴포넌트 구현하기

class로 컴포넌트를 만드려면 React.Component 를 extends해서 생성합니다. 컴포넌트를 생성할 때 render() 메서드는 무조건 정의해야하고, return도 해주어야 합니다. render() 메서드는 무조건 정의해야한다는 말은, component를 만들 때 필요한 메서드가 원래 더 있다는 말입니다. 그런데 그 중에서 render() 만 필수입니다.

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

Component 사용

위처럼 정의한 컴포넌트는 함수 이름 or class 이름으로 사용할 수 있습니다. 태그처럼 <Welcome /> 으로 작성합니다.

우리가 정의한 컴포넌트를 사용할 때, 원하는 property를 얼마든지 추가할 수 있습니다. 그러면 Welcome 컴포넌트(함수)에서 parameter로 해당 property를 받아서 사용할 수 있습니다. 이것을 props라고 말합니다. props는 property의 줄임말입니다. .(dot)으로 속성명에 접근가능하고, props.속성명 으로 속성 값을 가져올 수 있죠.

// 1. Welcome 컴포넌트 정의
function Welcome(props) {
  return <h1>Hello, {props.name}!</h1>;
}

// 2. App 컴포넌트 정의
function App() {
  return (
    <div>
      <Welcome name="wecoder" />
      <Welcome name="John" />
      <Welcome name="Sara" />
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));
  1. Welcome 컴포넌트: Welcome 컴포넌트를 사용한 측(부모)에서 name이라는 property를 부여했나봅니다. props.name의 값을 사용하네요.
  2. App 컴포넌트를 보니 div로 감싸져있고, <Welcome /> 컴포넌트를 세번 사용했습니다. name이라는 property를 부여해주었네요.
  3. ReactDOM.render 함수로 React 요소를 그려줍니다. root라는 id를 찾아 <App /> 컴포넌트를 그려주네요.

내가 이해한 것 Welcome 함수의 속성이 props 라는 것 여기서 props의 이름을 바꿔도 작동은 하긴하는데 그냥 props로 하기.(왜냐면 props가 자동완성이 되기때문에)

더 작은 Component로 분리하기

아래는 Comment라는 컴포넌트입니다.컴포넌트는 재사용 가능한 코드 단위라고 했죠. Comment 컴포넌트 내에도 더 재사용할 수 있는 요소들이 보이네요.

.avatar 요소를 컴포넌트로 만들겠습니다. avatar 컴포넌트는 분명 댓글창 이외에도 사용자정보 등 여기저기 많이 쓰일 것 같습니다.

function Comment(props) {
  return (
    <div className="comment">
      <div className="user-info">
        <img className="avatar"src={props.author.avatarUrl}alt={props.author.name}/>
        <div className="user-info-name">
          {props.author.name}
        </div>
      </div>
      <div className="comment-text">
        {props.text}
      </div>
      <div className="comment-date">
        {formatDate(props.date)}
      </div>
    </div>);
}

.avatar 부분을 그대로 떼와서 Avatar라는 이름으로 컴포넌트를 만들어줍니다. Comment 컴포넌트에서는 props.author로 접근해서 avatarUrl과 name을 가져왔는데, Avatar 컴포넌트에서는 좀 더 직관적으로 사용할 수 있도록 user 라는 이름으로 받아오겠습니다.

props.user 에서 avatarUrl, name 값을 가져오도록 하겠습니다. <Avatar />를 사용하는 측에서 user라는 attribute를 추가해야겠네요.

function Avatar(props) {
  return (
    <img className="avatar"src={props.user.avatarUrl}alt={props.user.name}/>);
}

Avatar 컴포넌트에서 user의 avatarUrl과 name이 필요하므로, Comment 컴포넌트에서 props.author 정보를 user라는 attribute로 넘겨주었습니다. props.author의 avatarUrl, name 값이 user를 통해 전달되었습니다.

function Comment(props) {
  return (
    <div className="comment">
      <div className="user-info">
        <Avatar user={props.author} />
        <div className="user-info-name">
          {props.author.name}
        </div>
      </div>
      <div className="comment-text">
        {props.text}
      </div>
      <div className="comment-date">
        {formatDate(props.date)}
      </div>
    </div>);
}

한 번만 더 분리해보겠습니다! 이제는 .user-info 부분을 컴포넌트로 만들어볼까요. 재사용할 가능성이 조금이라도 있다면 컴포넌트로 만들어주는 것이 좋습니다. .user-info 부분을 그대로 떼어다가 UserInfo 라는 컴포넌트로 만들었습니다.

function UserInfo(props) {
  return (
    <div className="user-info">
      <Avatar user={props.user} />
      <div className="user-info-name">
        {props.user.name}
      </div>
    </div>);
}

Comment 컴포넌트는 아래처럼 확 간결해졌습니다!!

function Comment(props) {
  return (
    <div className="comment">
      <UserInfo user={props.author} />
      <div className="comment-text">
        {props.text}
      </div>
      <div className="comment-date">
        {formatDate(props.date)}
      </div>
    </div>);
}

state

state란 말 그대로 컴포넌트의 상태 값입니다.

state와 props는 둘 다 object 이고, 화면에 보여줄 정보(상태)를 가지고 있다는 점에서 서로 비슷한 역할을 합니다. props는 컴포넌트를 사용하는 부모쪽에서 전달해야만 사용할 수 있고(함수의 parameter 처럼) 읽기전용입니다. state는 컴포넌트 내에서 정의하고 사용하며 업데이트 할 수 있습니다.

아래의 코드는 버튼을 눌렀을 때, state를 변화시켜서 보여줘야할 텍스트를 바꾸는 코드입니다. 예제코드에서는 isClicked라는 하나의 state만 있지만, 여러 개의 state를 추가할 수 있습니다. 그리고 state의 이름은 원하는대로 지을 수 있습니다.

코드는 여기에서 확인할 수 있습니다.

import { useState } from "react";
import ReactDOM from "react-dom";

function Button(props) {
  const [isClicked, setIsClicked] = useState(false);

  return (
    <button className="btn" onClick={() => setIsClicked(!isClicked)}>
      {isClicked ? "좋아요" : "싫어요"}
    </button>
  );
}

ReactDOM.render(<Button />, document.getElementById("root"));

div 태그의 onClick 내부에 있는 ()=>{}이 어색하면 여기에서 꼭 공부하고 넘어가주세요. 함수의 ES6 표현입니다. arrow function 이라고 부릅니다.

onClick는 event 시간에 배울 예정입니다. 지금은 <button />를 클릭하면 onClick에 넘긴 함수를 실행한다고만 알아주세요.

<button className="btn" onClick={() => setIsClicked(!isClicked)}>
      {isClicked ? "좋아요" : "싫어요"}
</button>

코드 해석

아래의 코드 설명이 처음에는 이해가 잘 되지 않을수도 있습니다. state를 다루는 전체적인 흐름을 파악하는 식으로 학습해주세요 자세한 내용은 추후 세션시간에 다룰 예정입니다.

1. const [isClicked, setIsClicked] = useState(false)

:: tl;dr;

  • useState를 통해서 isClicked라는 state와, setIsClicked라는 state를 업데이트 할 수 있는 함수를 선언했습니다.
  • useState의 인자로 false를 전달하여서 isClicked의 초기값이 false가 되도록 설정하였습니다.

:: 설명

  • isClicked라는 state를 선언하는 코드입니다.
  • 함수형 컴포넌트에서 state를 만들때는 useState라는 함수를 이용합니다.
  • useState의 인자로 전달된 값은 선언된 state의 초기값으로 할당됩니다.
  • useState의 실행 결과는 좌측에 [state, state를 갱신할 수 있는 함수] 배열 형태로 리턴됩니다.
  • useState의 리턴값을 배열 구조 분해 할당문법을 이용해서 각각 isClicked와 setIsClicked라는 이름으로 선언했습니다.

2. onClick={() => setIsClicked(!isClicked)}

:: tl;dr;

  • onClick이 달려있는 <button />를 클릭할 때마다, isClicked 상태가 true나, false로 업데이트 됩니다.

:: 설명

  • click하면 isClicked 이라는 state를 수정합니다. setIsClicked 함수로 state를 업데이트할 수 있습니다.
  • setIsClicked함수의 인자로 전달된 값으로 isClicked값이 업데이트 됩니다.
  • !isClicked 으로 인자로 전달해 업데이트 한다는 말은, 현재 isClicked 의 반대로(true면 false로, false면 true로) 저장한다는 말입니다.
  • 위 코드로 인해 button에 click event가 발생할 때 마다 isClicked state가 업데이트 됩니다.

props와 state

이번에는 앞에서 배웠던 props도 넣어보겠습니다. <Button /> 에 type을 추가했고, Button 컴포넌트에서 props로 받을 수 있습니다.

코드는 여기에서 확인할 수 있습니다.

import { useState } from "react";
import ReactDOM from "react-dom";
import "./index.css";

function Button(props) {
  const [isClicked, setIsClicked] = useState(false);

  return (
    <button
      className={`btn ${props.type === "like" ? "like" : ""}`}
      onClick={() => setIsClicked(!isClicked)}>
      {isClicked ? "좋아요" : "싫어요"}
    </button>
  );
}

ReactDOM.render(<Button type="like" />, document.getElementById("root"));

props.type이 ‘like’이면 like-btn 이라는 class 속성이 추가됩니다. 미리 .like-btn 에 배경색이 나오도록 css는 추가해 두었습니다. 코드를 잘 이해하고 넘어갑시다 :)

profile
프론트엔드 개발자를 꿈꾸는 도화지 위를 달리는 여자

0개의 댓글