본문 바로가기

카테고리 없음

[2024 여름방학 React.js 스터디] 정채은 #3주차

반응형

3주차 

[1강 - 1]

DOM (문서 객체 모델)이란?

 

문서 객체 모델, 즉 DOM은 웹 페이지(HTML이나 XML 문서)의 콘텐츠 및 구조, 그리고 스타일 요소를 구조화 시켜 표현하여 프로그래밍 언어가 해당 문서에 접근하여 읽고 조작할 수 있도록 API를 제공하는 일종의 인터페이스

 

프레임워크

자바스크립트의 특정 값이 바뀌면 특정 DOM의 속성이 바뀌도록 연결을 해주어서, 업데이트 하는 작업을 간소화해주는 방식으로 웹개발의 어려움을 해결

 

Virtual DOM

메모리에 가상으로 존재하는 DOM 으로 그냥 JavaScript 객체

 

Virtual DOM의 작동방식

1. 리액트는 상태가 업데이트된 후, 업데이트가 필요한 곳의 UI( 사용자 인터페이스 또는 유저 인터페이스(영어: user interface, UI)는 사람(사용자)과 사물 또는 시스템, 기계, 컴퓨터 프로그램 등 사이에서 의사소통을 할 수 있도록 일시적 또는 영구적인 접근을 목적으로 만들어진 물리적, 가상적 매개체)를 Virtual DOM 을 통해서 렌더링( 웹사이트 코드를 사용자가 웹 사이트를 방문할 때 보게 되는 대화형 페이지로 바꾸는 웹 개발에 사용되는 절차)( 서버로부터 HTML 파일을 받아 브라우저에 뿌려주는 과정)

2. 리액트 개발팀이 만든 매우 효율적인 비교 알고리즘을 통하여 실제 브라우저에 보여지고 있는 DOM 과 비교

3. 차이가 있는 곳을 감지하여 이를 실제 DOM 에 패치(일반적으로 이미 발표된 소프트웨어 제품에서 발견된 사소한 기능 개선 또는 버그나 오류 등을 수정하기 위해 개발자가 내놓는 업데이트 프로그램)

 

[1강 - 2]

설치 하기 !

 

[1강 - 3]

리액트 컴포넌트를 만들 땐 다음 문장 이용해 리액트를 불러와야함

컴포넌트란?

프로그래밍에 있어 재사용이 가능한 각각의 독립된 모듈

import React from 'react';

리액트 컴포넌트 함수형태 or 클래스형태 작성 가능

먼저 함수작성 방법

리액트 컴포넌트에서는 XML 형식의 값을 반환해줄 수 있는데 이를 JSX

export default Hello;

--->  Hello 라는 컴포넌트를 내보내겠다는 의미

 

ReactDOM.render 의 역할?

브라우저에 있는 실제 DOM 내부에 리액트 컴포넌트를 렌더링

 

<<<리액트 컴포넌트가 렌더링 될 때에는, 렌더링된 결과물이 위 div 내부에 렌더링되는 것>>>

 

[1강 - 4]

JSX?

리액트에서 생김새를 정의할 때, 사용하는 문법

 

리액트 컴포넌트 파일에서 XML 형태로 코드를 작성하면 babel 이 JSX 를 JavaScript 로 변환 해줌

{Babel : 자바스크립트의 문법을 확장해주는 도구

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

 

<<<JSX 가 JavaScript 로 제대로 변환이 되려면 지켜주어야 하는 몇가지 규칙>>>

1. 꼭 닫혀야 하는 태그

HTML 에서는 input 또는 br 태그를 사용 할 때 닫지 않고 사용하기도 함

but!! 리액트에서는 그렇게 하면 안됨!

 

태그와 태그 사이에 내용이 들어가지 않을 때에는, Self Closing 태그 라는 것을 사용해야 함

열리고, 바로 닫히는 태그를 의미

 

2.꼭 감싸져야하는 태그

두가지 이상의 태그는 무조건 하나의 태그로 감싸져있어야 함

 

but! 이렇게 단순히 감싸기 위하여 불필요한 div 로 감싸는게 별로 좋지 않은 상황일 때, 예를 들어서 스타일 관련 설정을 하다가 복잡해지게 되는 상황도 올 수 있고, table 관련 태그를 작성 할 때에도 내용을 div 같은걸로 감싸기엔 애매함.

 

그 때! 리액트의 Fragment 라는 것을 사용!!

 

태그를 작성 할 때 이름 없이 작성을 하게 되면 Fragment 가 만들어지는데, Fragment 는 브라우저 상에서 따로 별도의 엘리먼트로 나타나지 않음

 

3.JSX 안에 자바스크립트 값 사용하기

JSX 내부에 자바스크립트 변수를 보여줘야 할 때에는 {} 으로 감싸서 보여줌.

 

4.style 과 className

JSX 에서 태그에 style 과 CSS class 를 설정하는 방법?

우선, 인라인 스타일은 객체 형태로 작성을 해야 하며, background-color 처럼 - 로 구분되어 있는 이름들은 backgroundColor 처럼 camelCase 형태로 네이밍

그리고, CSS class 를 설정 할 때에는 class= 가 아닌 className= 으로 설정

 

5.주석

JSX 내부의 주석은 {/*주석입니다*/} 작성

additionally! ,  열리는 태그 내부에서는 // 이런 형태로도 주석 작성이 가능

[1강 - 5] props 를 통해 컴포넌트에게 값 전달하기

props 는 properties 의 줄임말. 우리가 어떠한 값을 컴포넌트에게 전달해줘야 할 때, props 를 사용

 

props 의 기본 사용법

전달App 컴포넌트에서 Hello 컴포넌트를 사용 할 때 name 이라는 값을 전달해주고 싶다고 가정, look 다음의 코드

import React from 'react';
import Hello from './Hello';

function App() {
  return (
    <Hello name="react" />
  );
}

export default App;

사용 : Hello 컴포넌트에서 name 값을 사용 하고 싶을 땐 어떻게 하면 되는지 알아볼까요?

import React from 'react';

function Hello(props) {
  return <div>안녕하세요 {props.name}</div>
}

export default Hello;

컴포넌트에게 전달되는 props 는 파라미터를 통하여 조회 가능

props 는 객체 형태로 전달되며, 만약 name 값을 조회하고 싶다면 props.name 을 조회

 

 

여러개의 props, 비구조화 할당

Hello 컴포넌트에 또 다른 props 를 전달 ㄱㄱ , color 라는 값을 설정

import React from 'react';
import Hello from './Hello';

function App() {
  return (
    <Hello name="react" color="red"/>
  );
}

export default App;

 

그 다음에는, Hello 컴포넌트에서 color 값을 조회해서 폰트의 색상으로 설정 ㄱㄱ

import React from 'react';

function Hello(props) {
  return <div style={{ color: props.color }}>안녕하세요 {props.name}</div>
}

export default Hello;

props 내부의 값을 조회 할 때마다 props. 를 입력하고 있음

함수의 파라미터에서 비구조화 할당(구조 분해)문법을 사용하면 조금 더 코드를 간결하게 작성가능

import React from 'react';

function Hello({ color, name }) {
  return <div style={{ color }}>안녕하세요 {name}</div>
}

export default Hello;

 

 

defaultProps 로 기본값 설정

컴포넌트에 props 를 지정하지 않았을 때 기본적으로 사용 할 값을 설정하고 싶다면 컴포넌트에 defaultProps 라는 값을 설정

 

props.children

컴포넌트 태그 사이에 넣은 값을 조회하고 싶을 땐, props.children 을 조회

이번에, props.children 을 사용하는 새로운 컴포넌트를 만들겨

Wrapper.js 를 src 디렉터리에 만들어보자.

import React from 'react';

function Wrapper() {
  const style = {
    border: '2px solid black',
    padding: '16px',
  };
  return (
    <div style={style}>

    </div>
  )
}

export default Wrapper;

이 컴포넌트를 App 에서 사용 ㄱㄱ

import React from 'react';
import Hello from './Hello';
import Wrapper from './Wrapper';

function App() {
  return (
    <Wrapper>
      <Hello name="react" color="red"/>
      <Hello color="pink"/>
    </Wrapper>
  );
}

export default App;

이렇게 Wrapper 태그 내부에 Hello 컴포넌트 두개를 넣었음.  브라우저를 확인하면 다음과 같이 Hello 컴포넌트들은 보여지지 않을 것

<내부의 내용이 보여지게 하기 위해서는 Wrapper 에서 props.children 을 렌더링>

 

[1강 - 6]

조건부 렌더링?

특정 조건에 따라 다른 결과물을 렌더링 하는 것

 

자바스크립트 값은 중괄호로 감싸주기

 

삼항연산자

(참고로 JSX 에서 null, false, undefined 를 렌더링하게 된다면 아무것도 나타나지 않게 됨)

 

보통 삼항연산자를 사용한 조건부 렌더링을 주로 특정 조건에 따라 보여줘야 하는 내용이 다를 때 사용

 

단순히 특정 조건이 true 이면 보여주고, 그렇지 않다면 숨겨주고 있는 이러한 상황에서는 && 연산자를 사용해서 처리하는 것이 더 간편

 

props 값 설정을 생략하면 ={true}

컴포넌트의 props 값을 설정하게 될 때 만약 props 이름만 작성하고 값 설정을 생략한다면, 이를 true 로 설정한 것으로 간주

[1강 - 7] useState 를 통해 컴포넌트에서 바뀌는 값 관리하기

지금까지 우리가 리액트 컴포넌트를 만들 때는, 동적인 부분이 하나도 없었다. 값이 바뀌는 일이 없었던것.

컴포넌트에서 보여줘야 하는 내용이 사용자 인터랙션에 따라 바뀌어야 할 때 어떻게 구현할 수 있는지 알아보자.

 

이벤트 설정

 Counter 에서 버튼이 클릭되는 이벤트가 발생 했을 때, 특정 함수가 호출되도록 설정

import React from 'react';

function Counter() {
  const onIncrease = () => {
    console.log('+1')
  }
  const onDecrease = () => {
    console.log('-1');
  }
  return (
    <div>
      <h1>0</h1>
      <button onClick={onIncrease}>+1</button>
      <button onClick={onDecrease}>-1</button>
    </div>
  );
}

export default Counter;

여기서 onIncrease  onDecrease 는 화살표 함수를 사용하여 구현

함수를 만들고, button 의 onClick 으로 각 함수를 연결

리액트에서 엘리먼트(요소)에 이벤트를 설정해줄때에는 on이벤트이름={실행하고싶은함수} 형태로 설정 해야함.

<<주의>> 함수형태를 넣어주어야 하지, 함수를 다음과 같이 실행하면 안된다!!!!

onClick={onIncrease()}

이렇게 하면 렌더링되는 시점에서 함수가 호출됨. 이벤트를 설정할때에는 함수타입의 값을 넣어주어야 한다!!!

 

 

동적인 값 끼얹기, useState

상태(state)?

컴포넌트에서 동적인 값

리액트에 useState 라는 함수 존재. 이것을 사용하면 컴포넌트에서 상태를 관리할수 있

import React, { useState } from 'react';

이 코드는 리액트 패키지에서 useState 라는 함수를 불러와 줌

const [number, setNumber] = useState(0);

useState 를 사용 할 때에는 상태의 기본값을 파라미터로 넣어서 호출

이 함수를 호출해주면 배열이 반환됨. 여기서 첫번째 원소는 현재 상태, 두번째 원소는 Setter 함수

 

원래는 다음과 같이 해야하지만,

const numberState = useState(0);
const number = numberState[0];
const setNumber = numberState[1];

배열 비구조화 할당을 통하여 각 원소를 추출해준것

 const onIncrease = () => {
    setNumber(number + 1);
  }

  const onDecrease = () => {
    setNumber(number - 1);
  

Setter 함수는 파라미터로 전달 받은 값을 최신 상태로 설정해줌

    <h1>{number}</h1>

h1 태그에서는 이제 0 이 아닌 {number} 값을 보여주어야 함.

 

 

함수형 업데이트

지금은 Setter 함수를 사용 할 때, 업데이트 하고 싶은 새로운 값을 파라미터로 넣어주고 있음.

그 대신에 기존 값을 어떻게 업데이트 할 지에 대한 함수를 등록하는 방식으로도 값을 업데이트 할 수 있다!

 

함수형 업데이트는 주로 나중에 컴포넌트를 최적화를 하게 될 때 사용하게 됨.지금 당장은 함수형 업데이트란게 있는 것 정도만 이해해두면 충분하다고 하십니다 흐흐

 

 

[1강 - 8]input 상태 관리하기

먼저,  src 디렉터리에 InputSample.js 라는 파일 생성

 

다음, 이 컴포넌트를 App 에서 렌더링

 

import React from 'react';
import InputSample from './InputSample';

function App() {
  return (
    <InputSample />
  );
}

export default App;

 그 뒤 input 에 입력하는 값이 하단에 나타나게 하고, 초기화 버튼을 누르면 input 이 값이 비워지도록 구현

 

이번에도, useState 를 사용, 이번에는 input 의 onChange 라는 이벤트를 사용,

이벤트에 등록하는 함수에서는 이벤트 객체 e 를 파라미터로 받아와서 사용 할 수 있는데 이 객체의 e.target 은 이벤트가 발생한 DOM 인 input DOM 을 가르키게 됨.

이 DOM 의 value 값, 즉 e.target.value 를 조회하면 현재 input 에 입력한 값이 무엇인지 알 수 있음.

이 값을 useState 를 통해서 관리

 

input 의 상태를 관리할 때에는 input 태그의 value 값도 설정해주는 것이 중요함 !!!

그렇게 해야, 상태가 바뀌었을때 input 의 내용도 업데이트 됨

 

 

[1강 - 9] 여러개의 input 상태 관리하기

8장에서는 input 상태를 관리하는 방법이었고 9장에서는 input 이 여러개일때는 어떻게 관리해야 하는지 알아보기

 

저번에 만든 InputSample 에서 새로운 input 을 제시

이번에 input 이 비어져있을 때 인풋에 대한 설명을 보여주는 placeholder 값도 설정

기존에 만들었던 상태는 지우고, onChange  onReset 함수는 비우기

import React, { useState } from 'react';

function InputSample() {
  const onChange = (e) => {
  };

  const onReset = () => {
  };


  return (
    <div>
      <input placeholder="이름" />
      <input placeholder="닉네임" />
      <button onClick={onReset}>초기화</button>
      <div>
        <b>값: </b>
        이름 (닉네임)
      </div>
    </div>
  );
}

export default InputSample;

 

input 의 개수가 여러개가 됐을때는, 단순히 useState 를 여러번 사용하고 onChange 도 여러개 만들어서 구현 할 수 있지만더 좋은 방법은, input 에 name 을 설정하고 이벤트가 발생했을 때 이 값을 참조하는 것!!

그리고, useState 에서는 문자열이 아니라 객체 형태의 상태를 관리해야함.

한번 InputSample 컴포넌트를 다음과 같이 수정해보장

import React, { useState } from 'react';

function InputSample() {
  const [inputs, setInputs] = useState({
    name: '',
    nickname: ''
  });

  const { name, nickname } = inputs; // 비구조화 할당을 통해 값 추출

  const onChange = (e) => {
    const { value, name } = e.target; // 우선 e.target 에서 name 과 value 를 추출
    setInputs({
      ...inputs, // 기존의 input 객체를 복사한 뒤
      [name]: value // name 키를 가진 값을 value 로 설정
    });
  };

  const onReset = () => {
    setInputs({
      name: '',
      nickname: '',
    })
  };


  return (
    <div>
      <input name="name" placeholder="이름" onChange={onChange} value={name} />
      <input name="nickname" placeholder="닉네임" onChange={onChange} value={nickname}/>
      <button onClick={onReset}>초기화</button>
      <div>
        <b>값: </b>
        {name} ({nickname})
      </div>
    </div>
  );
}

export default InputSample;

 

리액트 상태에서 객체를 수정해야 할 때에는!!!!

inputs[name] = value;

이런식으로 직접 수정하면 안됨 !!!!!

 

그 대신, 새로운 객체를 만들어서 새로운 객체에 변화를 주고, 이를 상태로 사용해주어야 함.

setInputs({
  ...inputs,
  [name]: value
});

 

여기서 사용한 ... 문법은 spread 문법, 객체의 내용을 모두 "펼쳐서" 기존 객체를 복사ㄱㄱ

 

이러한 작업을, "불변성을 지킨다" 라는 작업이라 함.

불변성을 지켜주어야만 리액트 컴포넌트에서 상태가 업데이트가 됐음을 감지 할 수 있고 이에 따라 필요한 리렌더링이 진행됨.

만약에 inputs[name] = value 이런식으로 기존 상태를 직접 수정하게 되면, 값을 바꿔도 리렌더링 안됨.

추가적으로, 리액트에서는 불변성을 지켜주어야만 컴포넌트 업데이트 성능 최적화를 제대로 할 수 있음.

컴포넌트 최적화에 대해서는 나중에 더 자세히 알아보도록 한다고 하심.

 

 

지금까지 기억해야 할건 리액트에서 객체를 업데이트하게 될 때에는 기존 객체를 직접 수정하면 안되고, 새로운 객체를 만들어서, 새 객체에 변화를 주어야 됨!!!!!

반응형