React μ€λ₯ κ²½κ³ λ΄μμ μ€λ₯λ₯Ό ν¨κ³Όμ μΌλ‘ λΆλ₯νκ³ μ²λ¦¬νμ¬ μ ν리μΌμ΄μ μμ μ±κ³Ό μ¬μ©μ κ²½νμ κ°μ νλ λ°©λ²μ μμ보μΈμ.
React μ€λ₯ κ²½κ³(Error Boundary) μ€λ₯ λΆλ₯: μ’ ν© κ°μ΄λ
μ€λ₯ μ²λ¦¬λ κ²¬κ³ νκ³ μ μ§λ³΄μ κ°λ₯ν React μ ν리μΌμ΄μ μ ꡬμΆνλ λ° μμ΄ μ€μν μΈ‘λ©΄μ λλ€. Reactμ μ€λ₯ κ²½κ³(Error Boundary)λ λ λλ§ μ€μ λ°μνλ μ€λ₯λ₯Ό μ μμ μΌλ‘ μ²λ¦¬νλ λ©μ»€λμ¦μ μ 곡νμ§λ§, λ€μν μ€λ₯ μ νμ μ΄λ»κ² λΆλ₯νκ³ λμν μ§ μ΄ν΄νλ κ²μ μ§μ μΌλ‘ νλ ₯μ μΈ μ ν리μΌμ΄μ μ λ§λλ λ° λ§€μ° μ€μν©λλ€. μ΄ κ°μ΄λμμλ μ€λ₯ κ²½κ³ λ΄μμ μ€λ₯λ₯Ό λΆλ₯νλ λ€μν μ κ·Ό λ°©μμ νμνκ³ , μ€λ₯ κ΄λ¦¬ μ λ΅μ κ°μ νκΈ° μν μ€μ©μ μΈ μμ μ μ€ν κ°λ₯ν ν΅μ°°λ ₯μ μ 곡ν©λλ€.
React μ€λ₯ κ²½κ³(Error Boundary)λ 무μμΈκ°μ?
React 16μ λμ
λ μ€λ₯ κ²½κ³(Error Boundary)λ μμ μ»΄ν¬λνΈ νΈλ¦¬ μ΄λμμλ JavaScript μ€λ₯λ₯Ό ν¬μ°©νκ³ , ν΄λΉ μ€λ₯λ₯Ό κΈ°λ‘νλ©°, μ 체 μ»΄ν¬λνΈ νΈλ¦¬κ° μΆ©λνλ λμ λ체 UIλ₯Ό νμνλ React μ»΄ν¬λνΈμ
λλ€. μ΄λ μ»΄ν¬λνΈλ₯Ό μν try...catch λΈλ‘κ³Ό μ μ¬νκ² μλν©λλ€.
μ€λ₯ κ²½κ³μ μ£Όμ νΉμ§:
- μ»΄ν¬λνΈ μμ€ μ€λ₯ μ²λ¦¬: νΉμ μ»΄ν¬λνΈ νμ νΈλ¦¬ λ΄μ μ€λ₯λ₯Ό 격리ν©λλ€.
- μ μ§μ κΈ°λ₯ μ ν(Graceful Degradation): λ¨μΌ μ»΄ν¬λνΈ μ€λ₯λ‘ μΈν΄ μ 체 μ ν리μΌμ΄μ μ΄ μ€λ¨λλ κ²μ λ°©μ§ν©λλ€.
- μ μ΄λ λ체 UI: μ€λ₯ λ°μ μ μ¬μ©μ μΉνμ μΈ λ©μμ§λ λ체 μ½ν μΈ λ₯Ό νμν©λλ€.
- μ€λ₯ λ‘κΉ : μ€λ₯ μ 보λ₯Ό κΈ°λ‘νμ¬ μ€λ₯ μΆμ λ° λλ²κΉ μ μ©μ΄νκ² ν©λλ€.
μ€λ₯ κ²½κ³μμ μ€λ₯λ₯Ό λΆλ₯ν΄μΌ νλ μ΄μ λ 무μμΈκ°μ?
λ¨μν μ€λ₯λ₯Ό ν¬μ°©νλ κ²λ§μΌλ‘λ μΆ©λΆνμ§ μμ΅λλ€. ν¨κ³Όμ μΈ μ€λ₯ μ²λ¦¬λ 무μμ΄ μλͺ»λμλμ§ μ΄ν΄νκ³ κ·Έμ λ°λΌ λμνλ κ²μ μꡬν©λλ€. μ€λ₯ κ²½κ³ λ΄μμ μ€λ₯λ₯Ό λΆλ₯νλ©΄ λ€μκ³Ό κ°μ μ¬λ¬ μ΄μ μ΄ μμ΅λλ€:
- λͺ©ν μ§ν₯μ μ€λ₯ μ²λ¦¬: μ€λ₯ μ νμ λ°λΌ λ€λ₯Έ μλ΅μ΄ νμν μ μμ΅λλ€. μλ₯Ό λ€μ΄, λ€νΈμν¬ μ€λ₯λ μ¬μλ λ©μ»€λμ¦μ΄ νμν μ μλ λ°λ©΄, λ°μ΄ν° μ ν¨μ± κ²μ¬ μ€λ₯λ μ¬μ©μ μ λ ₯ μμ μ΄ νμν μ μμ΅λλ€.
- μ¬μ©μ κ²½ν κ°μ : μ€λ₯ μ νμ λ°λΌ λ μ μ΅ν μ€λ₯ λ©μμ§λ₯Ό νμν©λλ€. μΌλ°μ μΈ "λ¬Έμ κ° λ°μνμ΅λλ€"λΌλ λ©μμ§λ λ€νΈμν¬ λ¬Έμ λ μλͺ»λ μ λ ₯μ λνλ΄λ νΉμ λ©μμ§λ³΄λ€ λμμ΄ λ λ©λλ€.
- λλ²κΉ κ°ν: μ€λ₯λ₯Ό λΆλ₯νλ©΄ λλ²κΉ λ° λ¬Έμ μ κ·Όλ³Έ μμΈμ μλ³νλ λ° μ μ©ν 컨ν μ€νΈλ₯Ό μ 곡ν©λλ€.
- μ¬μ λͺ¨λν°λ§: λ€μν μ€λ₯ μ νμ λ°μ λΉλλ₯Ό μΆμ νμ¬ λ°λ³΅λλ λ¬Έμ λ₯Ό μλ³νκ³ μμ μ°μ μμλ₯Ό μ ν©λλ€.
- μ λ΅μ λ체 UI: μ€λ₯μ λ°λΌ λ€λ₯Έ λ체 UIλ₯Ό νμνμ¬ μ¬μ©μμκ² λ κ΄λ ¨μ± μλ μ 보λ μ‘°μΉλ₯Ό μ 곡ν©λλ€.
μ€λ₯ λΆλ₯ μ κ·Ό λ°©μ
React μ€λ₯ κ²½κ³ λ΄μμ μ€λ₯λ₯Ό λΆλ₯νλ λ° μ¬μ©ν μ μλ λͺ κ°μ§ κΈ°λ²μ΄ μμ΅λλ€:
1. instanceof μ¬μ©νκΈ°
instanceof μ°μ°μλ κ°μ²΄κ° νΉμ ν΄λμ€μ μΈμ€ν΄μ€μΈμ§ νμΈν©λλ€. μ΄λ λ΄μ₯ μ€λ₯ μ νμ΄λ μ¬μ©μ μ μ μ€λ₯ μ νμ λ°λΌ μ€λ₯λ₯Ό λΆλ₯νλ λ° μ μ©ν©λλ€.
μμ :
class NetworkError extends Error {
constructor(message) {
super(message);
this.name = "NetworkError";
}
}
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
class MyErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null, errorInfo: null };
}
static getDerivedStateFromError(error) {
// λ€μ λ λλ§μμ λ체 UIλ₯Ό νμνλλ‘ stateλ₯Ό μ
λ°μ΄νΈν©λλ€.
return { hasError: true, error: error };
}
componentDidCatch(error, errorInfo) {
// μ€λ₯λ₯Ό μ€λ₯ λ³΄κ³ μλΉμ€μ κΈ°λ‘ν μλ μμ΅λλ€.
console.error("Caught error:", error, errorInfo);
this.setState({errorInfo: errorInfo});
}
render() {
if (this.state.hasError) {
// μνλ 컀μ€ν
λ체 UIλ₯Ό λ λλ§ν μ μμ΅λλ€.
let errorMessage = "λ¬Έμ κ° λ°μνμ΅λλ€.";
if (this.state.error instanceof NetworkError) {
errorMessage = "λ€νΈμν¬ μ€λ₯κ° λ°μνμ΅λλ€. μ°κ²°μ νμΈνκ³ λ€μ μλν΄μ£ΌμΈμ.";
} else if (this.state.error instanceof ValidationError) {
errorMessage = "μ ν¨μ± κ²μ¬ μ€λ₯κ° λ°μνμ΅λλ€. μ
λ ₯ λ΄μ©μ κ²ν ν΄μ£ΌμΈμ.";
}
return (
<div>
<h2>μ€λ₯!</h2>
<p>{errorMessage}</p>
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state.error && this.state.error.toString()}<br />
{this.state.errorInfo.componentStack}
</details>
</div>
);
}
return this.props.children;
}
}
μ€λͺ :
- λ΄μ₯λ
Errorν΄λμ€λ₯Ό νμ₯νλ 컀μ€ν NetworkErrorλ°ValidationErrorν΄λμ€λ₯Ό μ μν©λλ€. MyErrorBoundaryμ»΄ν¬λνΈμrenderλ©μλμμinstanceofμ°μ°μλ₯Ό μ¬μ©νμ¬ ν¬μ°©λ μ€λ₯μ μ νμ νμΈν©λλ€.- μ€λ₯ μ νμ λ°λΌ λ체 UIμ νΉμ μ€λ₯ λ©μμ§κ° νμλ©λλ€.
2. μ€λ₯ μ½λ λλ μμ± μ¬μ©νκΈ°
λ λ€λ₯Έ μ κ·Ό λ°©μμ μ€λ₯ κ°μ²΄ μ체μ μ€λ₯ μ½λλ μμ±μ ν¬ν¨νλ κ²μ λλ€. μ΄λ₯Ό ν΅ν΄ νΉμ μ€λ₯ μλ리μ€μ λ°λΌ λ μΈλΆνλ λΆλ₯κ° κ°λ₯ν©λλ€.
μμ :
function fetchData(url) {
return new Promise((resolve, reject) => {
fetch(url)
.then(response => {
if (!response.ok) {
const error = new Error("Network request failed");
error.code = response.status; // 컀μ€ν
μ€λ₯ μ½λλ₯Ό μΆκ°ν©λλ€.
reject(error);
}
return response.json();
})
.then(data => resolve(data))
.catch(error => reject(error));
});
}
class MyErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null, errorInfo: null };
}
static getDerivedStateFromError(error) {
// λ€μ λ λλ§μμ λ체 UIλ₯Ό νμνλλ‘ stateλ₯Ό μ
λ°μ΄νΈν©λλ€.
return { hasError: true, error: error };
}
componentDidCatch(error, errorInfo) {
// μ€λ₯λ₯Ό μ€λ₯ λ³΄κ³ μλΉμ€μ κΈ°λ‘ν μλ μμ΅λλ€.
console.error("Caught error:", error, errorInfo);
this.setState({errorInfo: errorInfo});
}
render() {
if (this.state.hasError) {
let errorMessage = "λ¬Έμ κ° λ°μνμ΅λλ€.";
if (this.state.error.code === 404) {
errorMessage = "리μμ€λ₯Ό μ°Ύμ μ μμ΅λλ€.";
} else if (this.state.error.code >= 500) {
errorMessage = "μλ² μ€λ₯μ
λλ€. λμ€μ λ€μ μλν΄μ£ΌμΈμ.";
}
return (
<div>
<h2>μ€λ₯!</h2>
<p>{errorMessage}</p>
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state.error && this.state.error.toString()}<br />
{this.state.errorInfo.componentStack}
</details>
</div>
);
}
return this.props.children;
}
}
μ€λͺ :
fetchDataν¨μλ HTTP μν μ½λλ₯Ό λνλ΄λcodeμμ±μ μ€λ₯ κ°μ²΄μ μΆκ°ν©λλ€.MyErrorBoundaryμ»΄ν¬λνΈλcodeμμ±μ νμΈνμ¬ νΉμ μ€λ₯ μλ리μ€λ₯Ό κ²°μ ν©λλ€.- μ€λ₯ μ½λμ λ°λΌ λ€λ₯Έ μ€λ₯ λ©μμ§κ° νμλ©λλ€.
3. μ€μ μ§μ€μ μ€λ₯ λ§€ν μ¬μ©νκΈ°
볡μ‘ν μ ν리μΌμ΄μ μ κ²½μ°, μ€μ μ§μ€μ μ€λ₯ λ§€νμ μ μ§νλ©΄ μ½λ κ΅¬μ± λ° μ μ§λ³΄μμ±μ ν₯μμν¬ μ μμ΅λλ€. μ΄λ μ€λ₯ μ νμ΄λ μ½λλ₯Ό νΉμ μ€λ₯ λ©μμ§ λ° μ²λ¦¬ λ‘μ§μ λ§€ννλ λμ λ리λ κ°μ²΄λ₯Ό λ§λλ κ²μ ν¬ν¨ν©λλ€.
μμ :
const errorMap = {
"NETWORK_ERROR": {
message: "λ€νΈμν¬ μ€λ₯κ° λ°μνμ΅λλ€. μ°κ²°μ νμΈν΄μ£ΌμΈμ.",
retry: true,
},
"INVALID_INPUT": {
message: "μλͺ»λ μ
λ ₯μ
λλ€. λ°μ΄ν°λ₯Ό κ²ν ν΄μ£ΌμΈμ.",
retry: false,
},
404: {
message: "리μμ€λ₯Ό μ°Ύμ μ μμ΅λλ€.",
retry: false,
},
500: {
message: "μλ² μ€λ₯μ
λλ€. λμ€μ λ€μ μλν΄μ£ΌμΈμ.",
retry: true,
},
"DEFAULT": {
message: "λ¬Έμ κ° λ°μνμ΅λλ€.",
retry: false,
},
};
function handleCustomError(errorType) {
const errorDetails = errorMap[errorType] || errorMap["DEFAULT"];
return errorDetails;
}
class MyErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, errorDetails: null, errorInfo: null };
}
static getDerivedStateFromError(error) {
// λ€μ λ λλ§μμ λ체 UIλ₯Ό νμνλλ‘ stateλ₯Ό μ
λ°μ΄νΈν©λλ€.
const errorDetails = handleCustomError(error.message);
return { hasError: true, errorDetails: errorDetails };
}
componentDidCatch(error, errorInfo) {
// μ€λ₯λ₯Ό μ€λ₯ λ³΄κ³ μλΉμ€μ κΈ°λ‘ν μλ μμ΅λλ€.
console.error("Caught error:", error, errorInfo);
this.setState({errorInfo: errorInfo});
}
render() {
if (this.state.hasError) {
const { message } = this.state.errorDetails;
return (
<div>
<h2>μ€λ₯!</h2>
<p>{message}</p>
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state.errorDetails.message}<br />
{this.state.errorInfo.componentStack}
</details>
</div>
);
}
return this.props.children;
}
}
function MyComponent(){
const [data, setData] = React.useState(null);
React.useEffect(() => {
try {
throw new Error("NETWORK_ERROR");
} catch (e) {
throw e;
}
}, []);
return <div></div>;
}
μ€λͺ :
errorMapκ°μ²΄λ μ€λ₯ μ νμ΄λ μ½λμ λ°λΌ λ©μμ§ λ° μ¬μλ νλκ·Έλ₯Ό ν¬ν¨ν μ€λ₯ μ 보λ₯Ό μ μ₯ν©λλ€.handleCustomErrorν¨μλ μ€λ₯ λ©μμ§λ₯Ό κΈ°λ°μΌλ‘errorMapμμ μ€λ₯ μΈλΆ μ 보λ₯Ό κ²μνκ³ νΉμ μ½λλ₯Ό μ°Ύμ μ μλ κ²½μ° κΈ°λ³Έκ°μ λ°νν©λλ€.MyErrorBoundaryμ»΄ν¬λνΈλhandleCustomErrorλ₯Ό μ¬μ©νμ¬errorMapμμ μ μ ν μ€λ₯ λ©μμ§λ₯Ό κ°μ Έμ΅λλ€.
μ€λ₯ λΆλ₯λ₯Ό μν λͺ¨λ² μ¬λ‘
- λͺ νν μ€λ₯ μ ν μ μ: μ ν리μΌμ΄μ μ λν μΌκ΄λ μ€λ₯ μ ν λλ μ½λ μ§ν©μ μ€μ ν©λλ€.
- λ¬Έλ§₯ μ 보 μ 곡: λλ²κΉ μ μ©μ΄νκ² νκΈ° μν΄ μ€λ₯ κ°μ²΄μ κ΄λ ¨ μΈλΆ μ 보λ₯Ό ν¬ν¨ν©λλ€.
- μ€λ₯ μ²λ¦¬ λ‘μ§ μ€μν: μ€μ μ§μ€μ μ€λ₯ λ§€ν λλ μ νΈλ¦¬ν° ν¨μλ₯Ό μ¬μ©νμ¬ μ€λ₯ μ²λ¦¬λ₯Ό μΌκ΄λκ² κ΄λ¦¬ν©λλ€.
- ν¨κ³Όμ μΈ μ€λ₯ λ‘κΉ : μ€λ₯ λ³΄κ³ μλΉμ€μ ν΅ν©νμ¬ νλ‘λμ νκ²½μ μ€λ₯λ₯Ό μΆμ νκ³ λΆμν©λλ€. μΈκΈ° μλ μλΉμ€λ‘λ Sentry, Rollbar, Bugsnag λ±μ΄ μμ΅λλ€.
- μ€λ₯ μ²λ¦¬ ν μ€νΈ: λ¨μ ν μ€νΈλ₯Ό μμ±νμ¬ μ€λ₯ κ²½κ³κ° λ€μν μ€λ₯ μ νμ μ¬λ°λ₯΄κ² μ²λ¦¬νλμ§ νμΈν©λλ€.
- μ¬μ©μ κ²½ν κ³ λ €: μ¬μ©μκ° ν΄κ²° λ°©λ²μ μ°Ύλλ‘ μλ΄νλ μ μ΅νκ³ μ¬μ©μ μΉνμ μΈ μ€λ₯ λ©μμ§λ₯Ό νμν©λλ€. κΈ°μ μ μΈ μ λ¬Έ μ©μ΄ μ¬μ©μ νΌν©λλ€.
- μ€λ₯ λ°μλ₯ λͺ¨λν°λ§: λ€μν μ€λ₯ μ νμ λ°μ λΉλλ₯Ό μΆμ νμ¬ λ°λ³΅λλ λ¬Έμ λ₯Ό μλ³νκ³ μμ μ°μ μμλ₯Ό μ ν©λλ€.
- κ΅μ ν(i18n): μ¬μ©μμκ² μ€λ₯ λ©μμ§λ₯Ό νμν λ, λ©μμ§κ° λ€μν μΈμ΄μ λ¬Ένλ₯Ό μ§μνλλ‘ μ μ ν κ΅μ νλμλμ§ νμΈν©λλ€.
i18nextμ κ°μ λΌμ΄λΈλ¬λ¦¬λ Reactμ Context APIλ₯Ό μ¬μ©νμ¬ λ²μμ κ΄λ¦¬ν©λλ€. - μ κ·Όμ±(a11y): μ€λ₯ λ©μμ§κ° μ₯μ λ₯Ό κ°μ§ μ¬μ©μμκ²λ μ κ·Ό κ°λ₯νλλ‘ ν΄μΌ ν©λλ€. ARIA μμ±μ μ¬μ©νμ¬ μ€ν¬λ¦° 리λμ μΆκ°μ μΈ λ¬Έλ§₯μ μ 곡ν©λλ€.
- 보μ: νΉν νλ‘λμ νκ²½μμ μ€λ₯ λ©μμ§μ μ΄λ€ μ 보λ₯Ό νμν μ§ μ£Όμν΄μΌ ν©λλ€. 곡격μμκ² μ μ©λ μ μλ λ―Όκ°ν λ°μ΄ν°λ₯Ό λ ΈμΆνμ§ λ§μμμ€. μλ₯Ό λ€μ΄, μ΅μ’ μ¬μ©μμκ² μμ μ€ν νΈλ μ΄μ€λ₯Ό νμνμ§ λ§μμμ€.
μμ μλ리μ€: μ μ μκ±°λ μ ν리μΌμ΄μ μμ API μ€λ₯ μ²λ¦¬νκΈ°
APIμμ μν μ 보λ₯Ό κ°μ Έμ€λ μ μ μκ±°λ μ ν리μΌμ΄μ μ μκ°ν΄ λ΄ μλ€. λ°μ κ°λ₯ν μ€λ₯ μλ리μ€λ λ€μκ³Ό κ°μ΅λλ€:
- λ€νΈμν¬ μ€λ₯: API μλ²λ₯Ό μ¬μ©ν μ μκ±°λ μ¬μ©μμ μΈν°λ· μ°κ²°μ΄ μ€λ¨λ κ²½μ°.
- μΈμ¦ μ€λ₯: μ¬μ©μμ μΈμ¦ ν ν°μ΄ μ ν¨νμ§ μκ±°λ λ§λ£λ κ²½μ°.
- 리μμ€λ₯Ό μ°Ύμ μ μμ μ€λ₯: μμ²ν μνμ΄ μ‘΄μ¬νμ§ μλ κ²½μ°.
- μλ² μ€λ₯: API μλ²μμ λ΄λΆ μ€λ₯κ° λ°μν κ²½μ°.
μ€λ₯ κ²½κ³μ μ€λ₯ λΆλ₯λ₯Ό μ¬μ©νμ¬ μ ν리μΌμ΄μ μ μ΄λ¬ν μλ리μ€λ₯Ό μ μμ μΌλ‘ μ²λ¦¬ν μ μμ΅λλ€:
// μμ (κ°μνλ¨)
async function fetchProduct(productId) {
try {
const response = await fetch(`/api/products/${productId}`);
if (!response.ok) {
if (response.status === 404) {
throw new Error("PRODUCT_NOT_FOUND");
} else if (response.status === 401 || response.status === 403) {
throw new Error("AUTHENTICATION_ERROR");
} else {
throw new Error("SERVER_ERROR");
}
}
return await response.json();
} catch (error) {
if (error instanceof TypeError && error.message === "Failed to fetch") {
throw new Error("NETWORK_ERROR");
}
throw error;
}
}
class ProductErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, errorDetails: null, errorInfo: null };
}
static getDerivedStateFromError(error) {
const errorDetails = handleCustomError(error.message); // μ΄μ μ 보μ¬μ€ errorMap μ¬μ©
return { hasError: true, errorDetails: errorDetails };
}
componentDidCatch(error, errorInfo) {
console.error("Caught error:", error, errorInfo);
this.setState({errorInfo: errorInfo});
}
render() {
if (this.state.hasError) {
const { message, retry } = this.state.errorDetails;
return (
<div>
<h2>μ€λ₯!</h2>
<p>{message}</p>
{retry && <button onClick={() => window.location.reload()}>μ¬μλ</button>}
</div>
);
}
return this.props.children;
}
}
μ€λͺ :
fetchProductν¨μλ API μλ΅ μν μ½λλ₯Ό νμΈνκ³ μνμ λ°λΌ νΉμ μ€λ₯ μ νμ λ°μμν΅λλ€.ProductErrorBoundaryμ»΄ν¬λνΈλ μ΄λ¬ν μ€λ₯λ₯Ό ν¬μ°©νκ³ μ μ ν μ€λ₯ λ©μμ§λ₯Ό νμν©λλ€.- λ€νΈμν¬ μ€λ₯ λ° μλ² μ€λ₯μ κ²½μ° "μ¬μλ" λ²νΌμ΄ νμλμ΄ μ¬μ©μκ° λ€μ μμ²μ μλν μ μμ΅λλ€.
- μΈμ¦ μ€λ₯μ κ²½μ° μ¬μ©μλ λ‘κ·ΈμΈ νμ΄μ§λ‘ 리λλ μ λ μ μμ΅λλ€.
- 리μμ€λ₯Ό μ°Ύμ μ μμ μ€λ₯μ κ²½μ° μνμ΄ μ‘΄μ¬νμ§ μμμ λνλ΄λ λ©μμ§κ° νμλ©λλ€.
κ²°λ‘
React μ€λ₯ κ²½κ³ λ΄μμ μ€λ₯λ₯Ό λΆλ₯νλ κ²μ νλ ₯μ μ΄κ³ μ¬μ©μ μΉνμ μΈ μ ν리μΌμ΄μ
μ ꡬμΆνλ λ° νμμ μ
λλ€. instanceof νμΈ, μ€λ₯ μ½λ, μ€μ μ§μ€μ μ€λ₯ λ§€νκ³Ό κ°μ κΈ°λ²μ μ¬μ©νλ©΄ λ€μν μ€λ₯ μλ리μ€λ₯Ό ν¨κ³Όμ μΌλ‘ μ²λ¦¬νκ³ λ λμ μ¬μ©μ κ²½νμ μ 곡ν μ μμ΅λλ€. μ ν리μΌμ΄μ
μ΄ μκΈ°μΉ μμ μν©μ μ μμ μΌλ‘ μ²λ¦¬ν μ μλλ‘ μ€λ₯ μ²λ¦¬, λ‘κΉ
λ° ν
μ€νΈμ λν λͺ¨λ² μ¬λ‘λ₯Ό λ°λ₯΄λ κ²μ μμ§ λ§μμμ€.
μ΄λ¬ν μ λ΅μ ꡬνν¨μΌλ‘μ¨ React μ ν리μΌμ΄μ μ μμ μ±κ³Ό μ μ§λ³΄μμ±μ ν¬κ² ν₯μμμΌ μ¬μ©μμ μμΉλ λ°°κ²½μ κ΄κ³μμ΄ λ λΆλλ½κ³ μ λ’°ν μ μλ κ²½νμ μ 곡ν μ μμ΅λλ€.
μΆκ° μλ£: