florent의 개발 적응기
이 글의 주요 내용
[선언적 프로그래밍 vs 명령적 프로그래밍 (Declarative vs Imperative Programming)]
[React.js]
[JSX(JavaScript XML)]
[React.js 스타일링(styling)]
[React.js 컴포넌트(Component)]
[조건부 렌더링]
[훅(Hook)]
[useState]
[구조 분해 할당 (Destructuring Assignment)]
[React.js 이벤트 핸들링]
[전개 연산자 (Spread Operator)]
[컴포넌트 트리 관리]
React는 선언적 프로그래밍 방식을 채택 ⇒ "무엇"을 할지 설명하는 방식으로, 명령적 프로그래밍이 "어떻게" 할지를 설명하는 것과 대조
(1) 명령적 프로그래밍 (Imperative Programming): "어떻게" 할 지를 단계별로 지시하는 것으로, 프로그램의 상태를 변경하는 명령문들의 순서를 나열
DOM을 직접 조작
각 단계를 명시적으로 프로그래머가 지정
상태 변경의 과정을 직접 관리
(2) 선언적 프로그래밍 (Declarative Programming): "무엇"을 원하는지 설명하는 것으로, 원하는 결과를 묘사하고, 시스템이 그 결과를 얻는 방법을 결정하게 함
상태에 따라 UI가 어떻게 보여야 할지 설명
React가 실제 DOM 업데이트를 처리
컴포넌트는 주어진 props에 따라 어떻게 렌더링될지만 정의
[리액트(React.js)란?]
React.js는 사용자 인터페이스(User Interface, UI)를 구축하기 위한 자바스크립트 라이브러리로, 프론트엔드 프레임워크로 여겨지기도 함
Facebook(현 Meta)에서 개발했으며, 컴포넌트 기반 아키텍처를 사용하여 재사용 가능하고 모듈화된 UI 요소를 만들 수 있음
[React.js의 주요 특징]
컴포넌트 기반 아키텍처 (Component-based Architecture)
가상 DOM (Virtual DOM)
JSX (JavaScript XML)
단방향 데이터 흐름 (One-way Data Flow)
선언적 프로그래밍 (Declarative Programming)
[컴포넌트 (Components)]
컴포넌트란, UI를 구성하는 독립적이고 재사용 가능한 조각을 의미
각 컴포넌트는 자체적인 로직, 구조, 스타일을 가질 수 있음
[JSX (JavaScript XML)]
JSX는 JavaScript 내에서 HTML과 유사한 구문을 사용할 수 있게 해주는 React의 문법 확장
[가상 DOM (Virtual DOM)]
가상 DOM은 실제 DOM의 가벼운 복사본으로, React는 가상 DOM을 사용하여 실제 DOM 업데이트를 최적화
[상태 관리 (State Management)]
React 컴포넌트는 자체 상태를 가질 수 있으며, 이를 통해 동적인 UI를 구현 가능
[프로퍼티 (Props)]
Props는 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하는 방법
[생명주기 메서드 (Lifecycle Methods)]
클래스 컴포넌트에서는 생명주기 메서드를 통해 컴포넌트의 다양한 단계에서 코드를 실행 가능
함수형 컴포넌트에서는 useEffect 훅을 사용하여 비슷한 기능을 구현
[Diffing (차이점 비교)]
React는 효율적인 UI 업데이트를 위해 가상 DOM을 사용하여 변경 사항을 비교하고 실제 DOM에 최소한의 변경만을 적용 ⇒ 이 과정을 "재조정(Reconciliation)"이라고도 함
이러한 특징들을 통해 React는 효율적이고 유지보수가 쉬운 웹 애플리케이션을 구축 가능
컴포넌트 기반 구조는 코드의 재사용성을 높이고, 가상 DOM과 효율적인 렌더링 메커니즘은 애플리케이션의 성능을 향상
[JSX란?]
JSX는 JavaScript XML의 약자로, JavaScript 내에서 HTML과 유사한 구문을 사용하여 React 컴포넌트를 작성할 수 있게 해주는 문법
JSX는 React 요소를 생성하기 위해 사용되며, JavaScript 코드와 HTML 코드를 결합할 수 있게 해줌
JSX를 사용하는 이유는 UI를 더 직관적이고 읽기 쉽게 작성할 수 있기 때문
[JSX 문법]
(1) HTML 태그 사용: JavaScript 코드 안에 HTML 태그를 직접 작성 가능
(2) JavaScript 표현식 사용: JSX 내부에서는 중괄호 {}를 사용하여 JavaScript 표현식을 사용
(3) JSX 안에서의 스타일링: JSX에서 스타일을 적용할 때는 객체를 사용하여 인라인 스타일을 정의
(4) 클래스 속성: HTML의 class 속성은 JSX에서 className으로 작성해야함 ⇒ JavaScript의 class 예약어와의 충돌을 피하기 위함
(5) 조건부 렌더링: JSX에서 조건부 렌더링을 할 때는 JavaScript의 삼항 연산자를 사용 가능
(6) JSX에서 리스트를 렌더링할 때는 map() 함수를 사용하고 각 요소에 고유한 key를 지정
(7) 컴포넌트 혼합 사용: JSX에서는 다른 컴포넌트를 포함하여 재사용 가능한 UI 요소를 만들 수 있음
(8) 이벤트 핸들링: JSX에서 이벤트를 처리할 때는 JavaScript 함수와 이벤트 핸들러를 사용
이벤트 유형 및 JSX 속성
(9) JSX 내부에서 주석을 작성할 때는 중괄호와 슬래시를 사용
[이미지 사용]
React에서 이미지를 사용할 때는 항상 닫는 태그를 사용해야 하며, src 속성에 동적 값을 할당 가능
[인라인 스타일링]
React에서 인라인 스타일은 객체로 전달되며, 속성명은 camelCase를 사용
[CSS 모듈 사용]
React에서는 CSS 모듈을 사용하여 스타일의 범위를 컴포넌트로 제한할 수 있음
[조건부 스타일링]
React에서는 조건에 따라 동적으로 스타일을 적용할 수 있음
[컴포넌트란]
React 컴포넌트는 UI의 재사용 가능한 부분을 나타냄
일반적으로 컴포넌트 이름은 파스칼 케이스(PascalCase)로 작성
함수형 컴포넌트와 클래스형 컴포넌트 두 가지 방식으로 생성
(1) 함수형 컴포넌트
함수형 컴포넌트는 JavaScript 함수로 정의되며, props를 인자로 받아 JSX를 반환
간단하고 읽기 쉬운 구조를 가짐
React 16.8 이후로 Hooks를 사용하여 상태와 생명주기 기능을 사용할 수 있음
성능상 이점이 있으며, 최근 React 개발에서 권장되는 방식
(2) 클래스형 컴포넌트
클래스형 컴포넌트는 React.Component를 상속받아 정의되며, render() 메서드를 통해 JSX를 반환
this 키워드를 사용하여 props와 state에 접근
생명주기 메서드(예: componentDidMount, componentDidUpdate)를 사용할 수 있음
복잡한 UI 로직을 구현할 때 유용할 수 있음
[컴포넌트의 Import와 Export]
컴포넌트는 모듈 시스템을 사용하여 컴포넌트를 내보내고 불러올 수 있음
내보내기 (Export)
불러오기 (Import)
[Props(속성)]
Props는 주로 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하는 데 사용 ⇒ Props는 부모 컴포넌트에서 자식 컴포넌트로 전달되는 데이터
Props는 읽기 전용이므로 자식 컴포넌트는 props를 직접 수정할 수 없음
function으로 임의의 파라미터를 설정하여 props 함수를 정의한 후, 해당 속성을 사용할 곳에서 태그 형태로 props 함수 사용
Props를 활용하여 컴포넌트간 데이터 전달 예시
[데이터 매핑 (Data Mapping)]
배열 데이터를 컴포넌트로 변환할 때 map 함수를 사용
[조건부 렌더링 (Conditional Rendering)]
조건부 렌더링은 특정 조건에 따라 다른 컴포넌트나 요소를 렌더링하는 기법
(1) 삼항 연산자 (Ternary Operator) 활용
(2) React.js의 && 연산자 활용
falsy 값 (0, empty string 등)을 사용할 때 주의해야 함 (의도치 않게 렌더링 실패가 될 수 있음)
[훅 (Hooks)]
훅은 React 16.8에서 도입된 기능으로, 함수형 컴포넌트에서 상태(state)와 생명주기(lifecycle) 기능을 사용할 수 있게 해줌
클래스 컴포넌트 없이 상태 관리 가능
로직의 재사용성 향상
복잡한 컴포넌트를 쉽게 이해하고 관리 가능
[주요 훅]
useState: 상태 관리
useEffect: 부수 효과 처리
useContext: 컨텍스트 사용
useReducer: 복잡한 상태 로직 처리
useCallback, useMemo: 성능 최적화
useRef: DOM 요소 참조 또는 변경 가능한 값 저장
[상태 관리 (State Management)]
상태 관리는 React 애플리케이션에서 동적 데이터를 다루는 핵심 개념으로, 함수형 컴포넌트에서는 useState 훅을 사용하여 상태를 관리
컴포넌트별 로컬 상태 관리
상태 변경 시 자동으로 리렌더링 트리거
불변성(Immutability) 유지 중요
[생명주기 메서드 (Lifecycle Methods)]
생명주기 메서드는 컴포넌트의 다양한 단계(마운트, 업데이트, 언마운트)에서 실행되는 특별한 메서드로, 함수형 컴포넌트에서는 useEffect 훅을 사용하여 유사한 기능을 구현
[useState란?]
useState는 React의 Hook 중 하나로, 함수형 컴포넌트에서 상태(state)를 관리할 수 있게 해줌
[useState의 특징]
상태 초기화: 초기 상태 값을 설정할 수 있습니다.
상태 읽기: 현재 상태 값을 읽을 수 있습니다.
상태 업데이트: 상태를 변경할 수 있는 함수를 제공합니다.
[useState의 구조]
컴포넌트가 처음 렌더링될 때 useState가 호출되며, 초기 상태가 설정
이후 렌더링에서는 최신 상태 값을 반환
setState 함수를 호출하면 상태가 업데이트되고 컴포넌트가 다시 렌더링됨
사용 예시
[제어된 컴포넌트(Controlled Component)]
제어된 컴포넌트는 React에서 폼 요소의 상태를 관리하는 방식으로, HTML에서 <input>, <textarea>, <select> 등의 폼 요소는 자체적으로 상태를 관리하지만, React에서는 이러한 상태를 컴포넌트의 state로 관리
단일 진실의 원천(Single Source of Truth): 컴포넌트의 state가 폼 데이터의 유일한 출처가 됨
즉각적인 유효성 검사: 사용자 입력에 대해 즉시 반응하고 유효성을 검사
조건부 렌더링: 입력값에 따라 UI를 동적으로 변경
다중 입력 처리: 여러 입력 필드를 가진 폼의 경우, 각 필드에 대해 별도의 핸들러를 만드는 대신 하나의 핸들러로 여러 입력을 관리 가능
[제어된 컴포넌트의 이점]
데이터 일관성: React state와 폼 입력값이 항상 동기화
즉각적인 필드 유효성 검사: 사용자가 입력하는 대로 유효성을 검사할 수 있음
조건부 렌더링: 특정 입력값에 따라 다른 UI 요소를 보여줄 수 있음
폼 데이터 조작: 제출 전에 입력된 데이터를 쉽게 수정하거나 포매팅
[구조 분해 할당 (Destructuring Assignment)]
구조 분해 할당은 ES6에서 도입된 JavaScript 문법으로, 배열이나 객체의 속성을 쉽게 추출하여 별도의 변수에 할당할 수 있게 해줌
객체와 배열 모두에 적용 가능하며, 중첩된 객체나 배열에도 사용 가능
기본값 설정 가능, 변수 이름 변경 가능 (객체 구조 분해에서)
나머지 요소 할당 가능 (Rest 패턴)
일반적인 변수 할당(’변수 = 객체’)과는 반대 순서로 작성해야 함: ‘부분 객체 = 변수’
React.js에서의 이벤트 핸들링 방식
(1) 이벤트 핸들러 정의: 함수형 컴포넌트 내부에 이벤트 처리 함수를 정의
(2) 이벤트 리스너 연결: JSX에서 해당 요소에 이벤트 리스너를 연결
(3) 이벤트 객체 처리: 필요한 경우 이벤트 객체를 활용
즉각적인 필드 유효성 검사: 사용자가 입력하는 대로 유효성을 검사
조건부 렌더링: 특정 입력값에 따라 다른 UI 요소를 보여줄 수 있음
폼 데이터 조작: 제출 전에 입력된 데이터를 쉽게 수정하거나 포매팅
전개 연산자(...)는 ES6에서 도입된 기능으로, 배열이나 객체의 요소를 펼치는 데 사용 ⇒ React에서 상태를 업데이트할 때 매우 유용
(1) 배열에 사용된 전개 연산자
(2) 객체에 사용된 전개 연산자
(3) React.js 내 전개 연산자 사용 예시
[컴포넌트 트리 관리 (Component Tree Management)]
React 애플리케이션은 일반적으로 여러 컴포넌트로 구성되며, 이들은 트리 구조를 형성
상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달하고, 하위 컴포넌트에서 상위 컴포넌트의 상태를 변경하는 방법을 이해하는 것이 중요
[컴포넌트 트리의 주요 개념]
Props (속성): 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하는 방법
Lifting State Up (상태 끌어올리기): 여러 컴포넌트가 공유하는 상태를 공통 조상 컴포넌트로 이동시키는 기법
Callback 함수: 자식 컴포넌트에서 부모 컴포넌트의 상태를 변경할 수 있게 하는 방법
[컴포넌트 트리 관리의 이점]
데이터 흐름이 명확해집니다 (항상 위에서 아래로)
상태 관리가 중앙화되어 유지보수가 쉬워짐
컴포넌트 간 결합도가 낮아져 재사용성이 높아짐
[컴포넌트 트리 구성시 주의할 점]
컴포넌트 트리가 깊어질수록 props를 전달하는 과정이 복잡해질 수 있음 ⇒ 이런 경우 Context API나 상태 관리 라이브러리(예: Redux)를 고려할 수 있음
각 컴포넌트의 책임을 명확히 하고, 가능한 작고 집중된 컴포넌트를 만들어야 함