article thumbnail

 

인프런의 '실무 중심! FE 입문자를 위한 React' 을 들으면서 기록으로 남겨두면 좋을 React의 특징들을 남겨두었습니다.

강의에서는 React의 기본, 기초적인 설명들을 해주지만, 해당 내용들은 이 포스트에서 제외하였습니다.

 

1일차 (25.02.27)

Chapter 04 LifeCycle과 Hooks

4-1. Hooks 종류

React에 기본으로 내장되어 있는 Hooks는 10가지이지만, 실제적으로 사용하는 것은 3가지 정도이다.

  • useState
  • useEffect
  • useCallback

Hooks가 위에서부터 아래의 순서대로 관리다.

 

4-2. React 랜더링 과정

✨ Rerendering

컴포넌트의 상태, 즉 State 또는 Props가 변경되면서 해당 컴포넌트를 다시 실행하여 화면을 다시 그리는 것

 

✨ React의 라이프 사이클

  • 처음 컴포넌트가 실행될 때, 상태변화에 의해 다시 실행될 때, 또는 어떤 상태가 변했는지 등에 따라 동작 방식이 달라지는 것을 React의 라이프 사이클이라고 한다.
  • 💡 함수형 컴포넌트의 라이프 사이클
    • 마운트 → 바로 자기 자신 실행 →반환된 JSX 값을 DOM에 반영 → useEffect (Hook) 실행
    • 업데이트 → 함수 실행 → JSX 값을 DOM에 반영 → useEffect 실행
    • 언마운트 → useEffect만 실행
  • React의 라이프 사이클은 useEffect가 핵심


 

2일차 (25.02.28)

Chapter 05 이벤트 핸들링

5-1. 이벤트 연결하기

  • React의 이벤트는 JavaScript의 이벤트와는 다른, 합성 이벤트이며, JavaScript의 확장 이벤트이다.
합성 이벤트 (SyntheticEvent)
- React에서 이벤트가 발생할 때, 이벤트 핸들러의 인자로 합성 이벤트 객체가 전달된다.
- 이 합성 이벤트는 JavaScript에서 전달받는 이벤트 객체를 확장(래핑)한 객체
- 거의 동일한 인터페이스를 가지고 있다.
- 원본 이벤트 객체(native event)는 syntheticEvent.nativeEvent에 존재한다.

 

4-2에서 배운 React의 라이프 사이클을 고려했을 때 이벤트 핸들러 함수는 아래와 같이 작성하는 것을 추천한다.

React의 이벤트 핸들러 함수 작성 고려사항
- 컴포넌트가 리랜더링 되면 컴포넌트 내에서 단순 정의한 함수가 새로운 함수로 만들어진다.
  👉 불필요한 작업으로 성능 문제를 야기할 수 있다.
- 때문에, 함수의 정의를 최대한 컴포넌트 밖으로 빼거나, useCallback으로 감싸서 매 랜더링 마다 함수가 새로 만들어지지 않도록 할 필요가 있다.

 

5-3. Form

Controlled Component (제어 컴포넌트)

  • 장점
    • 컴포넌트의 state와 input value가 완전히 동일한 값을 갖는다. (신뢰 가능한 단일 출처)
    • 다른 컴포넌트에 input value를 전달하거나 다른 이벤트 핸들러에서 값을 재설정 할 수 있다.
  • 단점
    • 값이 변경되는 매 순간 랜더링이 된다.
    • 즉, 해당 컴포넌트의 영향 범위가 클 수록 성능이 저하된다.
  • ↔ Uncontrolled Component: React에 의해 입력 요소의 값이 제어되는 컴포넌트

 

✨ useRef
- React의 Hook 중 하나
- 특정 DOM 요소의 레퍼런스를 직접 가져올 때 사용

 

Chapter 06 React 환경 설정

6-4. eslint, prettier 설정

✨ eslint

  • 문법 및 코드 스타일을 검사해주는 도구
  • 문법적인 오류를 사전에 발견할 수 있다.
  • 협업에서 통일된 코드 스타일을 유지할 수 있도록 도와준다.
  • CRA에는 자체 내장되어 있다. (package.json의 eslintConfig)

💡 pacakge.json의 eslintConfig를 다른 파일에 설정하기

일반적으로 eslint는 package.json에 설정되어 있지만, 설정을 다른 파일로 따로 빼 설정할 수 있다.

package.json 파일의 eslint 설정을 찾고, .eslintrc.json 파일을 생성하여 코드를 옮긴다.

// pacakge.json
"eslintConfig": {
    "extend": {
    	"react-app",
        "react-app/jest"
    }
}
// .eslintrc.json
{
    "extends": {
    	"react-app",
        "react-app/jsest"
    },
    // 다른 설정을 추가할 때 아래로 이어 작성하면 된다.
    "rules": {
    	// console 사용을 못하도록 설정
    	"no-console": "error"
    }
}

 

✨ prettier

  • 자동으로 코드를 정해진 규칙에 맞게 고쳐주는 툴
  • .prettierrc.json에서 규칙 정의
// .prettierrc.json
{
    "singleOuote": true, // "" → ''
    "semi": true,
    "tabWidth": 2,
    "trailingComma": "all" // 마지막까지 ','를 찍도록 설정
}

 


 

3일차 (25.03.04)

Chapter 07. React 메모장 만들기

7-5. 메모 삭제 기능 구현

// MemoItem.js
function MemoItem({ children, onClickItem, onClickDelete, isSelected }) {
  return (
    <div
      onClick={
        onClickItem
      }
      className={'MemoItem' + (isSelected ? ' selected' : '')}
    >
      {children}
      <button className="MemoItem_delete-button" onClick={onClickDelete}>
        x
      </button>
    </div>
  );
}

export default MemoItem;

button 요소가 div 요소 안에 존재하기 때문에 button을 클릭했을 때(onClickDelete 실행) div의 클릭 이벤트도 함께 실행된다. (onClickItem 실행) 

 

// MemoList.js
function MemoList({
  memos,
  setSelectedMemoIndex,
  deleteMemo,
  selectedMemoIndex,
}) {
  return (
    <div className="SideBar">
      {memos.map((memo, index) => (
        <MemoItem
          key={index}
          onClickItem={() => {
            setSelectedMemoIndex(index);
          }}
          onClickDelete={(e) => {
            deleteMemo(index);
            e.preventDefault(); // ★ 중요 포인트
            e.stopPropagation(); // ★ 중요 포인트
          }}
          isSelected={index === selectedMemoIndex}
        >
          {memo.title}
        </MemoItem>
      ))}
    </div>
  );
}

export default MemoList;

이로 인해 상위 js 파일에서는 onClickDelete가 실행되면서 선택한 메모가 삭제되고

원하는 메모의 index로 설정되는 것이 아니라 (현재 이 프로젝트에서는 메모가 삭제된 후 첫 번째 메모로 index를 설정하도록 하였다.)

onClickItem에 의해 삭제한 메모에 대한 index로 재설정되기 때문에 error가 발생한다.

 

하지만 이벤트(event) 메서드를 사용하여 이를 방지할 수 있다.

e.preventDefault()

  • 어떤 이벤트를 명시적으로 처리하지 않은 경우, 해당 이벤트에 대한 사용자 에이전트의 기본 동작을 실행하지 않도록 지정
  • 특정 기능이 그 의도로 사용되지 않을 때 생기는 불편함을 방지
  • html에서 표준으로 제공하는 태그의 기본 이벤트 발생 방지 베서

 

✨ e.stopPropagation()

  • e.preventDefault()와 함께 사용하는 경우가 많음
  • e.preventDefault()와의 차이점은 이벤트 버블링을 중단시킬 수 있다는 점
이벤트 버블링(Event Bubbling)
- 특정 화면 요소에서 이벤트가 발생했을 때 해당 이벤트가 더 상위의 화면 요소들로 전달되어 가는 특성
- 이러한 이벤트가 발생하는 이유는 브러우저가 이벤트를 감지하는 방식 때문
- 브라우저는 특정 화면 요소에서 이벤트가 발생했을 때, 그 이벤트를 최상위에 있는 화면 요소까지 이벤트를 전파시킨다. 이와 같은 하위에서 상위 요소로의 이벤트 전파 방식을 이벤트 버블링이라 함

 

✨ 디렉토리의 구조

📂 src

    📂 components

         📂 MemoContainer

              📂 index.js (이전 파일 명: MemoContainer.js)

// App.js
import MemoContainer from './components/MemoContainer'

function App() {
	// (내용 생략)
};

export default App;

다음과 같이 디렉토리를 설정한 후 import를 하게 될 경우, 자동으로 MemoContainer 디렉토리에서 index.js 파일을 찾아 import를 하게 된다.

MemoContainer와 관련된 컴포넌트, 소스 등을 해당 디렉토리로 지정하고 핵심적인 요소는 index.js로 관리할 수 있다.

 


[ 참고 자료 ]