본문 바로가기
개발 기록/front - react

[React] 함수형 컴포넌트

by jeong11 2024. 11. 27.
반응형

※체크 리스트

① 함수형 컴포넌트의 개념과 특징, 이해

② 함수형 컴포넌트를 사용해 React  애플리케이션을 작성하기

③ useState와 useEffect를 활용해 동적인 UI 구현하기 

 

1. React의 함수형 컴포넌트

1-1. 정의

JavaScript 함수로 정의되는 React 컴포넌트
클래스형 컴포넌트와 달리 React의 Component를 상속받지 않으며 단순한 함수로 동작한다  

 

1-2. 특징

간결함 : 구조가 간단하고 코드 작성이 쉽다 

무상태(Stateless) : 초기에는 상태를 관리하지 않았으나, React Hooks 도입 이후 상태와 생명주기를 관리할 수 있게 됬다

성능 최적화 : 클래스형 컴포넌트보다 메모리 사용량이 적고 렌더링 속도가 빠르다 

 

1-3. 함수형 컴포넌트와 클래스형 컴포넌트 비교

  함수형 컴포넌트 클래스형 컴포넌트
작성 방식 JavaScript 함수 React.Component를 상속받는 클래스
상태 관리 useState Hook 사용 this.state 사용
라이프사이클 관리 useEffect Hook 사용 라이프사이클 메소드 사용 
코드 가독성 간결하고 직관적 상대적으로 복잡 

 

2. 함수형 컴포넌트 작성 

1, 2, 3 단계로 진행하며 프로젝트를 만들어 설명하려 한다

1) React 프로젝트 생성

npx create-react-app functional-component-app

 

2) 프로젝트 만들 구조 

src/
├── components/
│   ├── Greeting.js   // 1단계, 2단계 코드
│   ├── Counter.js    // 3단계 코드
├── App.js            // 컴포넌트들을 연결하는 메인 파일
├── index.js          // 기본 엔트리 포인트

 

3) 1단계 : 기본 함수형 컴포넌트 작성 

① React 함수형 컴포넌트는 단순한 함수를 반환한다 

> Greeting.js

// src/components/Greeting.js

// 1단계 기본함수형 컴포넌트
function Greeting() {
	return <h1>Hello, React!</h1>;
}

export default Greeting;

 

② Greeting 컴포넌트를 App 컴포넌트에서 사용

> App.js

// src/App.js
import React from 'react';
import Greeting from './components/Greeting';

// 1단계 기본 함수형 컴포넌트
function App() {
	return (
    	<div>
        	<Greeting />
        </div>
    );
}

export default App;

 

③ 실행 

npm start

결과

 

 

 

4) 2단계 : Props 사용

① > Greeting.js

// src/components/Greeting.js

// 1단계 기본 함수형 컴포넌트
/*
function Greeting() {
	return <h1>Hello, React!</h1>
}
*/

// 2단계 Props 사용
function Greeting(props) {
	return <h1>Hello, {props.name}!</h1>;
}

export default Greeting;

 

② > App.js

// src/App.js
import React from 'react';
import Greeting from './components/Greeting';

// 1단계 기본 함수형 컴포넌트 
/*
function App() {
	return (
    	<div>
        	<Greeting />
        </div>
    )
}
*/

//2단계 Props 사용 
function App() {
	return <Greeting name="React!" />;
}

export default App;

 

③ 실행 결과 

2단계 실행 화면

 

 

5) 3단계 : State 사용(React Hooks)

useState Hook을 사용해 상태를 관리합니다 

① > Counter.js 생성

// src/components/Counter.js
import React, { useState } from 'react';

function Counter() {
	const [count, setCount] = useState(0);
    
    return (
    	<div>
        	<p>현재 카운트 : {count}</p>
            <button onClick={() => setCount(count+1)}>증가</button>
        </div>
    );
}

export default Counter;

 

② > App.js

// src/App.js
import React from 'react';
import Greeting from './components/Greeting';
import Counter from './components/Counter';

// 1단계 기본 함수형 컴포넌트
/*
function App() {
	return (
    	<div> 
        	<Greeting />
        </div>
    )
}
*/

// 2단계 Props 사용
/*
function App() {
	return <Greeting name="React!" />;
}
*/

// 3단계 React Hook 사용 - useState
function App() {
	return(
    	<div>
        	<Greeting name="React!" />
            <Counter />
        </div>
    );
}

export default App;

 

③ 실행 

카운터를 추가했다
증가 버튼을 누르면 카운트 숫자 증가

 

 

3. 함수형 컴포넌트에서 생명주기 관리 

☞ React 함수형 컴포넌트에서 useEffect를 사용하는 3가지 주요 시점 

3-1. 컴포넌트가 마운트될 때 실행

1) 코드 작성

// src/App.js
import React, { useEffect } from 'react';

function App() {
	useEffect(() => {
    	console.log("컴포넌트가 마운트되었습니다.")
    }, []);
    
    return <h1>Hello, React!</h1>;
}

export default App;

 

2) 설명

● useEffect의 두번째 인자에 빈 배열([ ])을 전달하면 이 useEffect는 컴포넌트가 마운트될 때 한번만 실행된다 

● 주로 초기화 작업(데이터 fetch, 이벤트 리스터 등록 등)에 사용된다

 

3-2. 상태(State) 변경시 실행

1) 코드 작성

// src/components/Counter.js
import React, { useState, useEffect } from 'react';

function Counter() {
	const [count, setCount] = useState(0);
    
    useEffect(() => {
    	console.log('카운트가 ${count}로 변경되었습니다.');
    }, [count]);	// count 상태가 변경될 때마다 실행
    
    return(
    	<div>
        	<p>현재 카운트 : {count}</p>
            <button onClick={() => setCount(count+1)}>증가</button>
        </div>
    );
}

export default Counter;

 

2) 설명

● useEffect의 두번째 인자로 배열( [count] )를 전달하면 배열 안에 있는 값이 변경될 때마다 useEffect가 실행된다

● 이 코드에서는 count 상태가 변경될 때마다 console.log로 새로운 값이 출력된다 

● 주로 상태가 변경될 때 부수적인 작업 (예 : DOM 업데이트, API 호출, 로그 기록 등)에 사용된다

 

3-3. 컴포넌트가 언마운트될 때 실행

1) 코드 작성

useEffect(() => {
	const interval = setInterval(() => {
    	console.log("타이머 동작 중");
    }, 1000);	// 1초마다 "타이머 동작 중" 로그 출력 
    
    return () => {
    	clearInterval(interval);	// 언마운트 시 타이머 제거
        console.log("컴포넌트가 언마운트되었습니다.");
    };
}, []);	// 빈 배열 : 마운트와 언마운트 시점에서만 실행

 

2) 설명

● useEffect 안에서 return문에 함수를 작성하면 해당 함수는 컴포넌트가 언마운트될 때 실행된다 

● 위 코드에서 타이머(setInterval)를 설정하고 컴포넌트가 언마운트될 때 이를 제거(clearInterval)하며 로그를 출력한다

● 주로 정리(clean-up) 작업(이벤트 리스너 제거, 타이머 정리, 비동기 작업 취소 등)에 사용된다 

 

▷ 정리

React의 함수형 컴포넌트에서 useEffect는 3가지 주요 시점에서 동작한다 

① 마운트 : 빈 배열 [ ] → 한 번만 실행(초기화 작업)  

② 상태/props 변경 : 배열에 의존성 전달 [state/props] → 해당 값 변경 시 실행

③ 언마운트 : return 안의 함수 → 정리(clean-up) 작업

 

4. 실습 

▷ 사용자 입력을 받아 "안녕하세요, [사용자 이름]" 메시지를 표시하는 함수형 컴포넌트를 작성하세요

▷ 버튼 클릭 시 카운트를 증가시키고 10이상이 되면 "최대 카운트 도달" 메시지를 표시하세요

 

1) 구현 

▷프로젝트 구조 

Greeting.js : 사용자 입력 및 환영 메시지 표시

Counter.js : 버튼 클릭 시 카운트 증가 및 조건에 따른 메시지 표시

App.js : 두 가지 컴포넌트를 통합하여 화면에 표시 

 

▷ 프로젝트 생성

npx create-react-app functional-component-practice

 

▷코드

① 사용자 입력을 받아 "안녕하세요, [사용자 이름]"을 표시하는 함수형 컴포넌트 만들기 

> components/Greeting.js

// src/components/Greeting.js
import React, { useState } from 'react';

function Greeting() {
	const [name, setName] = useState('');
	
    return(
    	<div>
	    <input
            	type="text"
                placeholder="이름을 입력하세요"
                value={name}
                onChange={(e) => setName(e.target.value)}
            />
            <h1>안녕하세요, {name}!</h1>
        </div>
    );
}

export default Greeting;

 

● useState를 사용해 name를 생성해 입력값(input)과 동기화한다 

초기값 : 빈 문자열(' ')

상태 업데이트 함수 : setName

● <input> 태그로 사용자 입력을 받아, 입력값이 변경되면 onChange 이벤트를 통해 setName을 호출하여 name 상태를 업데이트 한다 

 

사용자가 입력 창에 값을 입력하면 onChange 이벤트 발생 → name 상태 업데이트 → <h1> 태그 안의 내용 변경

 

 

 

② 증가 버튼 클릭 시 카운트를 증가시키고, 숫자가 10 이상이 되면 "최대 카운트 도달"을 표시하기 

> src/components/Counter.js

// src/components/Counter.js
import React, { useState } from 'react';

function Counter() {
	const [count, setCount] = useState(0);
	
    return (
    	<div>
	    <p>현재 카운트 : {count}</p>
            <button onClick={() => setCount(count + 1)}>증가</button>
            {count >= 10 && <p style={{ color:'red' }}>최대 카운트 도달</p>}
        </div>
    );
}

export default Counter;

● useState 사용 : count 상태를 생성하여 버튼 클릭으로 증가시키는 카운트 값을 관리한다 

● 조건부 렌더링 (&&) : count >= 10 조건이 참일때만 <p> 태그를 렌더링해 "최대 카운트 도달" 메시지 표시

 

버튼 클릭 → onClick 이벤트 발생 → count 값 증가 → 화면에 새로운 카운트 값과 조건부 메시지 업데이트

 

 

③ App.js에 컴포넌트 두개를 통합해 화면에 표시

> src/App.js

// src/App.js
import React from 'react';
import Greeting from './components/Greeting';
import Counter from './components/Counter';

function App() {
	return (
    	<div style={{ padding: '20px', fontFamily: 'Arial, sans-serif' }}>
	    <Greeting />
            <hr />
            <Counter />
        </div>
    );
}

export default App;

● Greeting 컴포넌트 렌더링 : 사용자가 이름을 입력하고 환영 메시지를 표시

● Counter 컴포넌트 렌더링 : 버튼 클릭으로 카운트를 증가시키고 메시지를 표시 

 

App 컴포넌트가 렌더링 → Greeting과 Counter 컴포넌트를 각각 렌더링 → 사용자의 입력/버튼 클릭에 따라 각 컴포넌트가 독립적으로 작동 

 

 

2) 실행

코드 실행한 결과
이름 입력과 최대 카운트 도달

 

 


※ 정리

① 함수형 컴포넌트와 클래스형 컴포넌트 중 어떤 것을 사용해야 할까요? 

→ React의 최신 동향을 고려했을 때 함수형 컴포넌트를 사용하는게 일반적으로 더 권장된다 

→ class를 사용할 필요가 없으므로 코드가 간결하고 읽기 쉬운 장점이 있다 

→ useState, useEffect 등 React Hook을 사용해 복잡한 로직을 깔끔하게 구현할 수 있다 

 

② useEffect의 의존성 배열은 어떻게 작동하나요? 

→ 의존성 배열 : useEffect에서 두 번째 인자로 전달되는 배열이며 효과가 실행되는 조건을 결정한다 

→ [ ] 빈 배열 : useEffect가 마운트될 때 한 번만 실행된다 

useEffect(() => {
	console.log("컴포넌트가 마운트되었습니다.");
}, []);	// 빈 배열 : 마운트 시점에만 실행

 

→ [value] 값이 포함된 배열 : 배열에 명시된 값이 변경될 때마다 useEffect가 실행된다 

useEffect(() => {
	console.log('값이 변경되었습니다: ${count}');
}, [count]);	//count가 변경될 때만 실행

 

→  의존성 배열이 없는 경우 : useEffect가 모든 렌더링마다 실행되서 의도치 않은 성능 문제를 유발할 수 있으니 주의가 필요하다 

useEffect(() => {
	console.log("매 렌더링마다 실행됩니다");
});	// 의존성 배열 없음

 

반응형