React 컀μ€ν ν μ νμ©ν λΉλκΈ° 리μμ€ μλΉ κ΄λ¦¬λ²μ μ¬μΈ΅ λΆμν©λλ€. λͺ¨λ² μ¬λ‘, μ€λ₯ μ²λ¦¬, κΈλ‘λ² μ±μ μν μ±λ₯ μ΅μ ν νμ νμΈνμΈμ.
React use Hook: λΉλκΈ° 리μμ€ μλΉ λ§μ€ν°νκΈ°
React ν
μ ν¨μν μ»΄ν¬λνΈμμ μνμ μ¬μ΄λ μ΄ννΈλ₯Ό κ΄λ¦¬νλ λ°©μμ νλͺ
μ μΌμΌμΌ°μ΅λλ€. κ°μ₯ κ°λ ₯ν μ‘°ν© μ€ νλλ useEffectμ useStateλ₯Ό μ¬μ©νμ¬ APIμμ λ°μ΄ν°λ₯Ό κ°μ Έμ€λ κ²κ³Ό κ°μ λΉλκΈ° 리μμ€ μλΉλ₯Ό μ²λ¦¬νλ κ²μ
λλ€. μ΄ κΈμμλ ν
μ μ¬μ©ν λΉλκΈ° μμ
μ 볡μ‘μ±μ κΉμ΄ νκ³ λ€μ΄, κ²¬κ³ νκ³ μ μΈκ³μ μΌλ‘ μ κ·Ό κ°λ₯ν React μ ν리μΌμ΄μ
μ ꡬμΆνκΈ° μν λͺ¨λ² μ¬λ‘, μ€λ₯ μ²λ¦¬ λ° μ±λ₯ μ΅μ νλ₯Ό λ€λ£Ήλλ€.
κΈ°λ³Έ μ¬ν μ΄ν΄νκΈ°: useEffectμ useState
λ 볡μ‘ν μλ리μ€μ λ€μ΄κ°κΈ° μ μ, κ΄λ ¨λ κΈ°λ³Έ ν λ€μ λ€μ μ΄ν΄λ³΄κ² μ΅λλ€:
- useEffect: μ΄ ν μ μ¬μ©νλ©΄ ν¨μν μ»΄ν¬λνΈμμ μ¬μ΄λ μ΄ννΈλ₯Ό μνν μ μμ΅λλ€. μ¬μ΄λ μ΄ννΈμλ λ°μ΄ν° κ°μ Έμ€κΈ°, ꡬλ λλ DOM μ§μ μ‘°μ λ±μ΄ ν¬ν¨λ μ μμ΅λλ€.
- useState: μ΄ ν μ μ¬μ©νλ©΄ ν¨μν μ»΄ν¬λνΈμ μνλ₯Ό μΆκ°ν μ μμ΅λλ€. μνλ λ‘λ© μνλ APIμμ κ°μ Έμ¨ λ°μ΄ν°μ κ°μ΄ μκ°μ λ°λΌ λ³νλ λ°μ΄ν°λ₯Ό κ΄λ¦¬νλ λ° νμμ μ λλ€.
λ°μ΄ν°λ₯Ό κ°μ Έμ€λ μΌλ°μ μΈ ν¨ν΄μ λΉλκΈ° μμ²μ μμνκΈ° μν΄ useEffectλ₯Ό μ¬μ©νκ³ , λ°μ΄ν°, λ‘λ© μν λ° μ μ¬μ μ€λ₯λ₯Ό μ μ₯νκΈ° μν΄ useStateλ₯Ό μ¬μ©νλ κ²μ
λλ€.
κ°λ¨ν λ°μ΄ν° κ°μ Έμ€κΈ° μμ
κ°μμ APIμμ μ¬μ©μ λ°μ΄ν°λ₯Ό κ°μ Έμ€λ κΈ°λ³Έ μμ λΆν° μμνκ² μ΅λλ€:
μμ : μ¬μ©μ λ°μ΄ν° κ°μ Έμ€κΈ°
```javascript import React, { useState, useEffect } from 'react'; function UserProfile({ userId }) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { setLoading(true); setError(null); try { const response = await fetch(`https://api.example.com/users/${userId}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); setUser(data); } catch (error) { setError(error); } finally { setLoading(false); } }; fetchData(); }, [userId]); if (loading) { return
Loading user data...
; } if (error) { returnError: {error.message}
; } if (!user) { returnNo user data available.
; } return ({user.name}
Email: {user.email}
Location: {user.location}
μ΄ μμ μμ useEffectλ userId propμ΄ λ³κ²½λ λλ§λ€ μ¬μ©μ λ°μ΄ν°λ₯Ό κ°μ Έμ΅λλ€. fetch APIμ λΉλκΈ°μ νΉμ±μ μ²λ¦¬νκΈ° μν΄ async ν¨μλ₯Ό μ¬μ©ν©λλ€. λν μ»΄ν¬λνΈλ λ λμ μ¬μ©μ κ²½νμ μ 곡νκΈ° μν΄ λ‘λ© λ° μ€λ₯ μνλ₯Ό κ΄λ¦¬ν©λλ€.
λ‘λ© λ° μ€λ₯ μν μ²λ¦¬νκΈ°
λ‘λ© μ€μ μκ°μ νΌλλ°±μ μ 곡νκ³ μ€λ₯λ₯Ό μ μμ μΌλ‘ μ²λ¦¬νλ κ²μ μ’μ μ¬μ©μ κ²½νμ μν΄ λ§€μ° μ€μν©λλ€. μ΄μ μμ λ μ΄λ―Έ κΈ°λ³Έμ μΈ λ‘λ© λ° μ€λ₯ μ²λ¦¬λ₯Ό 보μ¬μ£Όμμ΅λλ€. μ΄λ¬ν κ°λ μ νμ₯ν΄ λ³΄κ² μ΅λλ€.
λ‘λ© μν
λ‘λ© μνλ λ°μ΄ν°κ° λ‘λλκ³ μμμ λͺ ννκ² λνλ΄μΌ ν©λλ€. μ΄λ κ°λ¨ν λ‘λ© λ©μμ§λ λ μ κ΅ν λ‘λ© μ€νΌλλ₯Ό μ¬μ©νμ¬ λ¬μ±ν μ μμ΅λλ€.
μμ : λ‘λ© μ€νΌλ μ¬μ©νκΈ°
κ°λ¨ν ν μ€νΈ λ©μμ§ λμ λ‘λ© μ€νΌλ μ»΄ν¬λνΈλ₯Ό μ¬μ©ν μ μμ΅λλ€:
```javascript // LoadingSpinner.js import React from 'react'; function LoadingSpinner() { return
; // μ€μ μ€νΌλ μ»΄ν¬λνΈλ‘ κ΅μ²΄νμΈμ } export default LoadingSpinner; ``````javascript
// UserProfile.js (μμ λ¨)
import React, { useState, useEffect } from 'react';
import LoadingSpinner from './LoadingSpinner';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => { ... }, [userId]); // μ΄μ κ³Ό λμΌν useEffect
if (loading) {
return
Error: {error.message}
; } if (!user) { returnNo user data available.
; } return ( ... ); // μ΄μ κ³Ό λμΌν return } export default UserProfile; ```μ€λ₯ μ²λ¦¬
μ€λ₯ μ²λ¦¬λ μ¬μ©μμκ² μ μ©ν μ 보λ₯Ό μ 곡νκ³ μ μ¬μ μΌλ‘ μ€λ₯μμ 볡ꡬν μ μλ λ°©λ²μ μ 곡ν΄μΌ ν©λλ€. μ΄λ μμ²μ μ¬μλνκ±°λ μ§μμ μν μ°λ½μ² μ 보λ₯Ό μ 곡νλ κ²μ ν¬ν¨ν μ μμ΅λλ€.
μμ : μ¬μ©μ μΉνμ μΈ μ€λ₯ λ©μμ§ νμνκΈ°
```javascript // UserProfile.js (μμ λ¨) import React, { useState, useEffect } from 'react'; function UserProfile({ userId }) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { ... }, [userId]); // μ΄μ κ³Ό λμΌν useEffect if (loading) { return
Loading user data...
; } if (error) { return (μ¬μ©μ λ°μ΄ν°λ₯Ό κ°μ Έμ€λ μ€ μ€λ₯κ° λ°μνμ΅λλ€:
{error.message}
No user data available.
; } return ( ... ); // μ΄μ κ³Ό λμΌν return } export default UserProfile; ```μ¬μ¬μ©μ±μ μν 컀μ€ν ν λ§λ€κΈ°
μ¬λ¬ μ»΄ν¬λνΈμμ λμΌν λ°μ΄ν° κ°μ Έμ€κΈ° λ‘μ§μ λ°λ³΅νκ³ μλ€λ©΄, 컀μ€ν ν μ λ§λ€ λμ λλ€. 컀μ€ν ν μ μ½λ μ¬μ¬μ©μ±κ³Ό μ μ§λ³΄μμ±μ ν₯μμν΅λλ€.
μμ : useFetch ν
λ°μ΄ν° κ°μ Έμ€κΈ° λ‘μ§μ μΊ‘μννλ useFetch ν
μ λ§λ€μ΄ λ΄
μλ€:
```javascript // useFetch.js import { useState, useEffect } from 'react'; function useFetch(url) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { setLoading(true); setError(null); try { const response = await fetch(url); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const jsonData = await response.json(); setData(jsonData); } catch (error) { setError(error); } finally { setLoading(false); } }; fetchData(); }, [url]); return { data, loading, error }; } export default useFetch; ```
μ΄μ μ»΄ν¬λνΈμμ useFetch ν
μ μ¬μ©ν μ μμ΅λλ€:
```javascript // UserProfile.js (μμ λ¨) import React from 'react'; import useFetch from './useFetch'; function UserProfile({ userId }) { const { data: user, loading, error } = useFetch(`https://api.example.com/users/${userId}`); if (loading) { return
Loading user data...
; } if (error) { returnError: {error.message}
; } if (!user) { returnNo user data available.
; } return ({user.name}
Email: {user.email}
Location: {user.location}
useFetch ν
μ μ»΄ν¬λνΈ λ‘μ§μ ν¬κ² λ¨μννκ³ μ ν리μΌμ΄μ
μ λ€λ₯Έ λΆλΆμμ λ°μ΄ν° κ°μ Έμ€κΈ° κΈ°λ₯μ λ μ½κ² μ¬μ¬μ©ν μ μκ² ν©λλ€. μ΄λ μλ§μ λ°μ΄ν° μ’
μμ±μ κ°μ§ 볡μ‘ν μ ν리μΌμ΄μ
μ νΉν μ μ©ν©λλ€.
μ±λ₯ μ΅μ ν
λΉλκΈ° 리μμ€ μλΉλ μ ν리μΌμ΄μ μ±λ₯μ μν₯μ λ―ΈμΉ μ μμ΅λλ€. ν μ μ¬μ©ν λ μ±λ₯μ μ΅μ ννκΈ° μν λͺ κ°μ§ μ λ΅μ λ€μκ³Ό κ°μ΅λλ€:
1. λλ°μ΄μ±κ³Ό μ€λ‘νλ§
κ²μ μ λ ₯κ³Ό κ°μ΄ μμ£Ό λ³κ²½λλ κ°μ λ€λ£° λ, λλ°μ΄μ±κ³Ό μ€λ‘νλ§μ κ³Όλν API νΈμΆμ λ°©μ§ν μ μμ΅λλ€. λλ°μ΄μ±μ νΉμ μ§μ° μκ° νμ ν¨μκ° νΈμΆλλλ‘ λ³΄μ₯νλ λ°λ©΄, μ€λ‘νλ§μ ν¨μκ° νΈμΆλ μ μλ μλλ₯Ό μ νν©λλ€.
μμ : κ²μ μ λ ₯ λλ°μ΄μ±νκΈ°```javascript import React, { useState, useEffect } from 'react'; import useFetch from './useFetch'; function SearchComponent() { const [searchTerm, setSearchTerm] = useState(''); const [debouncedSearchTerm, setDebouncedSearchTerm] = useState(''); useEffect(() => { const timerId = setTimeout(() => { setDebouncedSearchTerm(searchTerm); }, 500); // 500ms μ§μ° return () => { clearTimeout(timerId); }; }, [searchTerm]); const { data: results, loading, error } = useFetch(`https://api.example.com/search?q=${debouncedSearchTerm}`); const handleInputChange = (event) => { setSearchTerm(event.target.value); }; return (
Loading...
} {error &&Error: {error.message}
} {results && (-
{results.map((result) => (
- {result.title} ))}
μ΄ μμ μμ debouncedSearchTermμ μ¬μ©μκ° 500ms λμ νμ΄νμ λ©μΆ νμλ§ μ
λ°μ΄νΈλλ―λ‘, λͺ¨λ ν€ μ
λ ₯λ§λ€ λΆνμν API νΈμΆμ λ°©μ§ν©λλ€. μ΄λ μ±λ₯μ ν₯μμν€κ³ μλ² λΆνλ₯Ό μ€μ
λλ€.
2. μΊμ±
κ°μ Έμ¨ λ°μ΄ν°λ₯Ό μΊμ±νλ©΄ API νΈμΆ μλ₯Ό ν¬κ² μ€μΌ μ μμ΅λλ€. λ€μκ³Ό κ°μ μ¬λ¬ μμ€μμ μΊμ±μ ꡬνν μ μμ΅λλ€:
- λΈλΌμ°μ μΊμ: APIκ° μ μ ν HTTP μΊμ± ν€λλ₯Ό μ¬μ©νλλ‘ κ΅¬μ±ν©λλ€.
- μΈλ©λͺ¨λ¦¬ μΊμ: μ ν리μΌμ΄μ λ΄μμ κ°μ Έμ¨ λ°μ΄ν°λ₯Ό μ μ₯νκΈ° μν΄ κ°λ¨ν κ°μ²΄λ₯Ό μ¬μ©ν©λλ€.
- μꡬ μ μ₯μ: μ₯κΈ° μΊμ±μ μν΄
localStorageλλsessionStorageλ₯Ό μ¬μ©ν©λλ€.
μμ : useFetchμ κ°λ¨ν μΈλ©λͺ¨λ¦¬ μΊμ ꡬννκΈ°
```javascript // useFetch.js (μμ λ¨) import { useState, useEffect } from 'react'; const cache = {}; function useFetch(url) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { setLoading(true); setError(null); if (cache[url]) { setData(cache[url]); setLoading(false); return; } try { const response = await fetch(url); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const jsonData = await response.json(); cache[url] = jsonData; setData(jsonData); } catch (error) { setError(error); } finally { setLoading(false); } }; fetchData(); }, [url]); return { data, loading, error }; } export default useFetch; ```
μ΄ μμ λ κ°λ¨ν μΈλ©λͺ¨λ¦¬ μΊμλ₯Ό μΆκ°ν©λλ€. νΉμ URLμ λν λ°μ΄ν°κ° μ΄λ―Έ μΊμμ μλ κ²½μ°, μλ‘μ΄ API νΈμΆμ νλ λμ μΊμμμ μ§μ λ°μ΄ν°λ₯Ό κ°μ Έμ΅λλ€. μ΄λ μμ£Ό μ‘μΈμ€νλ λ°μ΄ν°μ μ±λ₯μ κ·Ήμ μΌλ‘ ν₯μμν¬ μ μμ΅λλ€.
3. λ©λͺ¨μ΄μ μ΄μ
Reactμ useMemo ν
μ κ°μ Έμ¨ λ°μ΄ν°μ μμ‘΄νλ λΉμ©μ΄ λ§μ΄ λλ κ³μ°μ λ©λͺ¨μ΄μ¦νλ λ° μ¬μ©ν μ μμ΅λλ€. μ΄λ λ°μ΄ν°κ° λ³κ²½λμ§ μμμ λ λΆνμν μ¬λ λλ§μ λ°©μ§ν©λλ€.
μμ : νμ κ° λ©λͺ¨μ΄μ¦νκΈ°
```javascript import React, { useMemo } from 'react'; import useFetch from './useFetch'; function UserProfile({ userId }) { const { data: user, loading, error } = useFetch(`https://api.example.com/users/${userId}`); const formattedName = useMemo(() => { if (!user) return ''; return `${user.firstName} ${user.lastName}`; }, [user]); if (loading) { return
Loading user data...
; } if (error) { returnError: {error.message}
; } if (!user) { returnNo user data available.
; } return ({formattedName}
Email: {user.email}
Location: {user.location}
μ΄ μμ μμ formattedNameμ user κ°μ²΄κ° λ³κ²½λ λλ§ λ€μ κ³μ°λ©λλ€. user κ°μ²΄κ° λμΌνκ² μ μ§λλ©΄ λ©λͺ¨μ΄μ¦λ κ°μ΄ λ°νλμ΄ λΆνμν κ³μ°κ³Ό μ¬λ λλ§μ λ°©μ§ν©λλ€.
4. μ½λ μ€ν리ν
μ½λ μ€ν리ν μ μ¬μ©νλ©΄ μ ν리μΌμ΄μ μ λ μμ μ²ν¬λ‘ λΆν νμ¬ νμν λ λ‘λν μ μμ΅λλ€. μ΄λ νΉν λ§μ μ’ μμ±μ κ°μ§ λκ·λͺ¨ μ ν리μΌμ΄μ μ μ΄κΈ° λ‘λ μκ°μ κ°μ ν μ μμ΅λλ€.
μμ : μ»΄ν¬λνΈ μ§μ° λ‘λ©νκΈ°
```javascript
import React, { lazy, Suspense } from 'react';
const UserProfile = lazy(() => import('./UserProfile'));
function App() {
return (
μ΄ μμ μμ UserProfile μ»΄ν¬λνΈλ νμν λλ§ λ‘λλ©λλ€. Suspense μ»΄ν¬λνΈλ μ»΄ν¬λνΈκ° λ‘λλλ λμ λ체 UIλ₯Ό μ 곡ν©λλ€.
κ²½μ μν μ²λ¦¬νκΈ°
κ²½μ μνλ λμΌν useEffect ν
μμ μ¬λ¬ λΉλκΈ° μμ
μ΄ μμλ λ λ°μν μ μμ΅λλ€. λͺ¨λ μμ
μ΄ μλ£λκΈ° μ μ μ»΄ν¬λνΈκ° λ§μ΄νΈ ν΄μ λλ©΄ μ€λ₯λ μκΈ°μΉ μμ λμμ΄ λ°μν μ μμ΅λλ€. μ»΄ν¬λνΈκ° λ§μ΄νΈ ν΄μ λ λ μ΄λ¬ν μμ
μ μ 리νλ κ²μ΄ μ€μν©λλ€.
μμ : μ 리 ν¨μλ‘ κ²½μ μν λ°©μ§νκΈ°
```javascript import React, { useState, useEffect } from 'react'; function UserProfile({ userId }) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { let isMounted = true; // μ»΄ν¬λνΈ λ§μ΄νΈ μνλ₯Ό μΆμ νκΈ° μν νλκ·Έ μΆκ° const fetchData = async () => { setLoading(true); setError(null); try { const response = await fetch(`https://api.example.com/users/${userId}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); if (isMounted) { // μ»΄ν¬λνΈκ° μ¬μ ν λ§μ΄νΈλ κ²½μ°μλ§ μν μ λ°μ΄νΈ setUser(data); } } catch (error) { if (isMounted) { // μ»΄ν¬λνΈκ° μ¬μ ν λ§μ΄νΈλ κ²½μ°μλ§ μν μ λ°μ΄νΈ setError(error); } } finally { if (isMounted) { // μ»΄ν¬λνΈκ° μ¬μ ν λ§μ΄νΈλ κ²½μ°μλ§ μν μ λ°μ΄νΈ setLoading(false); } } }; fetchData(); return () => { isMounted = false; // μ»΄ν¬λνΈκ° λ§μ΄νΈ ν΄μ λ λ νλκ·Έλ₯Ό falseλ‘ μ€μ }; }, [userId]); if (loading) { return
Loading user data...
; } if (error) { returnError: {error.message}
; } if (!user) { returnNo user data available.
; } return ({user.name}
Email: {user.email}
Location: {user.location}
μ΄ μμ μμλ isMounted νλκ·Έλ₯Ό μ¬μ©νμ¬ μ»΄ν¬λνΈκ° μ¬μ ν λ§μ΄νΈλμ΄ μλμ§ μΆμ ν©λλ€. μνλ μ»΄ν¬λνΈκ° μ¬μ ν λ§μ΄νΈλ κ²½μ°μλ§ μ
λ°μ΄νΈλ©λλ€. μ 리 ν¨μλ μ»΄ν¬λνΈκ° λ§μ΄νΈ ν΄μ λ λ νλκ·Έλ₯Ό falseλ‘ μ€μ νμ¬ κ²½μ μνμ λ©λͺ¨λ¦¬ λμλ₯Ό λ°©μ§ν©λλ€. λμμ μΈ μ κ·Ό λ°©μμ νΉν λμ©λ λ€μ΄λ‘λλ μ₯κΈ° μ€ν μμ
μμ μ€μν AbortController APIλ₯Ό μ¬μ©νμ¬ fetch μμ²μ μ·¨μνλ κ²μ
λλ€.
λΉλκΈ° 리μμ€ μλΉμ λν μ μμ κ³ λ € μ¬ν
μ μΈκ³ μ¬μ©μλ₯Ό λμμΌλ‘ React μ ν리μΌμ΄μ μ ꡬμΆν λλ λ€μ μμλ₯Ό κ³ λ €νμμμ€:
- λ€νΈμν¬ μ§μ° μκ°: μΈκ³ κ°μ§μ μ¬μ©μλ λ€μν λ€νΈμν¬ μ§μ° μκ°μ κ²½νν μ μμ΅λλ€. API μλν¬μΈνΈμ μλλ₯Ό μ΅μ ννκ³ μΊμ± λ° μ½λ μ€ν리ν κ³Ό κ°μ κΈ°μ μ μ¬μ©νμ¬ μ§μ° μκ°μ μν₯μ μ΅μννμμμ€. CDN(μ½ν μΈ μ μ‘ λ€νΈμν¬)μ μ¬μ©νμ¬ μ¬μ©μμκ² λ κ°κΉμ΄ μλ²μμ μ μ μμ°μ μ 곡νλ κ²μ κ³ λ €νμμμ€. μλ₯Ό λ€μ΄, APIκ° λ―Έκ΅μμ νΈμ€ν λλ κ²½μ° μμμ μ¬μ©μλ μλΉν μ§μ°μ κ²½νν μ μμ΅λλ€. CDNμ λ€μν μμΉμ API μλ΅μ μΊμνμ¬ λ°μ΄ν°κ° μ΄λν΄μΌ νλ 거리λ₯Ό μ€μΌ μ μμ΅λλ€.
- λ°μ΄ν° νμ§ν: μ¬μ©μμ μμΉμ λ°λΌ λ μ§, ν΅ν, μ«μμ κ°μ λ°μ΄ν°λ₯Ό νμ§νν νμμ±μ κ³ λ €νμμμ€.
react-intlκ³Ό κ°μ κ΅μ ν(i18n) λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ λ°μ΄ν° μμμ μ²λ¦¬νμμμ€. - μ κ·Όμ±: μ ν리μΌμ΄μ μ΄ μ₯μ κ° μλ μ¬μ©μλ μ κ·Όν μ μλλ‘ νμμμ€. ARIA μμ±μ μ¬μ©νκ³ μ κ·Όμ± λͺ¨λ² μ¬λ‘λ₯Ό λ°λ₯΄μμμ€. μλ₯Ό λ€μ΄, μ΄λ―Έμ§μ λ체 ν μ€νΈλ₯Ό μ 곡νκ³ ν€λ³΄λλ₯Ό μ¬μ©νμ¬ μ ν리μΌμ΄μ μ νμν μ μλλ‘ νμμμ€.
- μκ°λ: λ μ§μ μκ°μ νμν λ μκ°λλ₯Ό μΌλμ λμμμ€.
moment-timezoneκ³Ό κ°μ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ μκ°λ λ³νμ μ²λ¦¬νμμμ€. μλ₯Ό λ€μ΄, μ ν리μΌμ΄μ μ΄ μ΄λ²€νΈ μκ°μ νμνλ κ²½μ° μ¬μ©μμ νμ§ μκ°λλ‘ λ³νν΄μΌ ν©λλ€. - λ¬Ένμ λ―Όκ°μ±: λ°μ΄ν°λ₯Ό νμνκ³ μ¬μ©μ μΈν°νμ΄μ€λ₯Ό λμμΈν λ λ¬Ένμ μ°¨μ΄λ₯Ό μΈμνμμμ€. νΉμ λ¬ΈνκΆμμ λΆμΎκ°μ μ€ μ μλ μ΄λ―Έμ§λ κΈ°νΈλ₯Ό μ¬μ©νμ§ λ§μμμ€. νμ§ μ λ¬Έκ°μ μμνμ¬ μ ν리μΌμ΄μ μ΄ λ¬Ένμ μΌλ‘ μ μ νμ§ νμΈνμμμ€.
κ²°λ‘
Reactμμ ν
μ μ¬μ©νμ¬ λΉλκΈ° 리μμ€ μλΉλ₯Ό λ§μ€ν°νλ κ²μ κ²¬κ³ νκ³ μ±λ₯μ΄ λ°μ΄λ μ ν리μΌμ΄μ
μ ꡬμΆνλ λ° νμμ μ
λλ€. useEffectμ useStateμ κΈ°λ³Έ μ¬νμ μ΄ν΄νκ³ , μ¬μ¬μ©μ±μ μν΄ μ»€μ€ν
ν
μ λ§λ€κ³ , λλ°μ΄μ±, μΊμ±, λ©λͺ¨μ΄μ μ΄μ
κ³Ό κ°μ κΈ°μ λ‘ μ±λ₯μ μ΅μ ννκ³ , κ²½μ μνλ₯Ό μ²λ¦¬ν¨μΌλ‘μ¨ μ μΈκ³ μ¬μ©μμκ² νλ₯ν μ¬μ©μ κ²½νμ μ 곡νλ μ ν리μΌμ΄μ
μ λ§λ€ μ μμ΅λλ€. μ μΈκ³ μ¬μ©μλ₯Ό μν μ ν리μΌμ΄μ
μ κ°λ°ν λλ νμ λ€νΈμν¬ μ§μ° μκ°, λ°μ΄ν° νμ§ν, λ¬Ένμ λ―Όκ°μ±κ³Ό κ°μ μ μμ μμλ₯Ό κ³ λ €νλ κ²μ μμ§ λ§μμμ€.