<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hooks on Korobopolly's Dev Blog</title><link>https://korobopolly.github.io/tags/hooks/</link><description>Recent content in Hooks on Korobopolly's Dev Blog</description><generator>Hugo</generator><language>ko</language><lastBuildDate>Mon, 16 Feb 2026 13:15:00 +0900</lastBuildDate><atom:link href="https://korobopolly.github.io/tags/hooks/index.xml" rel="self" type="application/rss+xml"/><item><title>React Hooks 심화 - useEffect, useMemo, useReducer, 커스텀 Hook</title><link>https://korobopolly.github.io/posts/react-hooks/</link><pubDate>Mon, 16 Feb 2026 13:15:00 +0900</pubDate><guid>https://korobopolly.github.io/posts/react-hooks/</guid><description>&lt;h2 id="react-hooks란"&gt;React Hooks란?&lt;/h2&gt;
&lt;p&gt;Hooks는 함수형 컴포넌트에서 상태 관리, 사이드 이펙트 처리, 성능 최적화 등을 가능하게 하는 함수입니다. React 16.8에서 도입되어 현재 React 개발의 핵심이 되었습니다.&lt;/p&gt;
&lt;h3 id="hooks-규칙"&gt;Hooks 규칙&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;최상위에서만 호출&lt;/strong&gt;: 조건문, 반복문, 중첩 함수 내에서 호출 금지&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;React 함수 내에서만 호출&lt;/strong&gt;: 일반 JavaScript 함수에서 호출 금지&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-tsx" data-lang="tsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6c7086;font-style:italic"&gt;// 잘못된 사용
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f38ba8"&gt;function&lt;/span&gt; BadExample() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#cba6f7"&gt;if&lt;/span&gt; (someCondition) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#cba6f7"&gt;const&lt;/span&gt; [value, setValue] &lt;span style="color:#89dceb;font-weight:bold"&gt;=&lt;/span&gt; useState(&lt;span style="color:#a6e3a1"&gt;&amp;#34;&amp;#34;&lt;/span&gt;); &lt;span style="color:#6c7086;font-style:italic"&gt;// 조건문 안에서 호출 금지
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6c7086;font-style:italic"&gt;// 올바른 사용
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f38ba8"&gt;function&lt;/span&gt; GoodExample() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#cba6f7"&gt;const&lt;/span&gt; [value, setValue] &lt;span style="color:#89dceb;font-weight:bold"&gt;=&lt;/span&gt; useState(&lt;span style="color:#a6e3a1"&gt;&amp;#34;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#cba6f7"&gt;if&lt;/span&gt; (someCondition) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#6c7086;font-style:italic"&gt;// Hook이 아닌 로직은 조건문 안에서 사용 가능
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="useeffect---사이드-이펙트-처리"&gt;useEffect - 사이드 이펙트 처리&lt;/h2&gt;
&lt;h3 id="기본-사용법"&gt;기본 사용법&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-tsx" data-lang="tsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#cba6f7"&gt;import&lt;/span&gt; { useState, useEffect } &lt;span style="color:#cba6f7"&gt;from&lt;/span&gt; &lt;span style="color:#a6e3a1"&gt;&amp;#34;react&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f38ba8"&gt;function&lt;/span&gt; UserProfile({ userId }&lt;span style="color:#89dceb;font-weight:bold"&gt;:&lt;/span&gt; { userId: &lt;span style="color:#f38ba8"&gt;number&lt;/span&gt; }) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#cba6f7"&gt;const&lt;/span&gt; [user, setUser] &lt;span style="color:#89dceb;font-weight:bold"&gt;=&lt;/span&gt; useState&amp;lt;&lt;span style="color:#cba6f7"&gt;User&lt;/span&gt; &lt;span style="color:#f38ba8"&gt;|&lt;/span&gt; &lt;span style="color:#89b4fa"&gt;null&lt;/span&gt;&amp;gt;(&lt;span style="color:#fab387"&gt;null&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#cba6f7"&gt;const&lt;/span&gt; [loading, setLoading] &lt;span style="color:#89dceb;font-weight:bold"&gt;=&lt;/span&gt; useState(&lt;span style="color:#fab387"&gt;true&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; useEffect(() &lt;span style="color:#89dceb;font-weight:bold"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#6c7086;font-style:italic"&gt;// 사이드 이펙트 실행
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; setLoading(&lt;span style="color:#fab387"&gt;true&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fetch(&lt;span style="color:#a6e3a1"&gt;`/api/users/&lt;/span&gt;&lt;span style="color:#a6e3a1"&gt;${&lt;/span&gt;userId&lt;span style="color:#a6e3a1"&gt;}&lt;/span&gt;&lt;span style="color:#a6e3a1"&gt;`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .then((res) &lt;span style="color:#89dceb;font-weight:bold"&gt;=&amp;gt;&lt;/span&gt; res.json())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .then((data) &lt;span style="color:#89dceb;font-weight:bold"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; setUser(data);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; setLoading(&lt;span style="color:#fab387"&gt;false&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }, [userId]); &lt;span style="color:#6c7086;font-style:italic"&gt;// userId가 변경될 때만 실행
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#cba6f7"&gt;if&lt;/span&gt; (loading) &lt;span style="color:#cba6f7"&gt;return&lt;/span&gt; &amp;lt;&lt;span style="color:#cba6f7"&gt;p&lt;/span&gt;&amp;gt;&lt;span style="color:#f38ba8"&gt;로딩&lt;/span&gt; &lt;span style="color:#f38ba8"&gt;중&lt;/span&gt;...&amp;lt;/&lt;span style="color:#cba6f7"&gt;p&lt;/span&gt;&amp;gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#cba6f7"&gt;if&lt;/span&gt; (&lt;span style="color:#89dceb;font-weight:bold"&gt;!&lt;/span&gt;user) &lt;span style="color:#cba6f7"&gt;return&lt;/span&gt; &amp;lt;&lt;span style="color:#cba6f7"&gt;p&lt;/span&gt;&amp;gt;&lt;span style="color:#f38ba8"&gt;사용자를&lt;/span&gt; &lt;span style="color:#f38ba8"&gt;찾을&lt;/span&gt; &lt;span style="color:#f38ba8"&gt;수&lt;/span&gt; &lt;span style="color:#f38ba8"&gt;없습니다&lt;/span&gt;.&amp;lt;/&lt;span style="color:#cba6f7"&gt;p&lt;/span&gt;&amp;gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#cba6f7"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#cba6f7"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#cba6f7"&gt;h2&lt;/span&gt;&amp;gt;{user.name}&amp;lt;/&lt;span style="color:#cba6f7"&gt;h2&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#cba6f7"&gt;p&lt;/span&gt;&amp;gt;{user.email}&amp;lt;/&lt;span style="color:#cba6f7"&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#cba6f7"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="의존성-배열-패턴"&gt;의존성 배열 패턴&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-tsx" data-lang="tsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f38ba8"&gt;function&lt;/span&gt; EffectPatterns() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#cba6f7"&gt;const&lt;/span&gt; [count, setCount] &lt;span style="color:#89dceb;font-weight:bold"&gt;=&lt;/span&gt; useState(&lt;span style="color:#fab387"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#6c7086;font-style:italic"&gt;// 1. 마운트 시 1회만 실행
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; useEffect(() &lt;span style="color:#89dceb;font-weight:bold"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; console.log(&lt;span style="color:#a6e3a1"&gt;&amp;#34;컴포넌트 마운트&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }, []);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#6c7086;font-style:italic"&gt;// 2. 특정 값 변경 시 실행
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; useEffect(() &lt;span style="color:#89dceb;font-weight:bold"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; console.log(&lt;span style="color:#a6e3a1"&gt;&amp;#34;count 변경:&amp;#34;&lt;/span&gt;, count);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }, [count]);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#6c7086;font-style:italic"&gt;// 3. 매 렌더링마다 실행 (의존성 배열 생략)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; useEffect(() &lt;span style="color:#89dceb;font-weight:bold"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; console.log(&lt;span style="color:#a6e3a1"&gt;&amp;#34;렌더링됨&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#cba6f7"&gt;return&lt;/span&gt; &amp;lt;&lt;span style="color:#cba6f7"&gt;button&lt;/span&gt; &lt;span style="color:#89b4fa"&gt;onClick&lt;/span&gt;&lt;span style="color:#89dceb;font-weight:bold"&gt;=&lt;/span&gt;{() &lt;span style="color:#89dceb;font-weight:bold"&gt;=&amp;gt;&lt;/span&gt; setCount(count &lt;span style="color:#89dceb;font-weight:bold"&gt;+&lt;/span&gt; &lt;span style="color:#fab387"&gt;1&lt;/span&gt;)}&amp;gt;{count}&amp;lt;/&lt;span style="color:#cba6f7"&gt;button&lt;/span&gt;&amp;gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="클린업-함수"&gt;클린업 함수&lt;/h3&gt;
&lt;p&gt;컴포넌트 언마운트 시 또는 이펙트 재실행 전에 정리 작업을 수행합니다.&lt;/p&gt;</description></item><item><title>Claude Code Hooks - 이벤트 타입, 자동 린팅, 조건부 실행 설정</title><link>https://korobopolly.github.io/posts/claude-code-hooks-automation/</link><pubDate>Mon, 16 Feb 2026 13:03:00 +0900</pubDate><guid>https://korobopolly.github.io/posts/claude-code-hooks-automation/</guid><description>&lt;h2 id="hooks-시스템-개요"&gt;Hooks 시스템 개요&lt;/h2&gt;
&lt;p&gt;Claude Code의 Hooks는 도구 실행의 특정 시점에 자동으로 쉘 명령을 실행할 수 있는 자동화 메커니즘입니다. 파일을 편집할 때마다 자동으로 린팅을 실행하거나, 세션 시작 시 프로젝트 컨텍스트를 로딩하거나, 특정 도구 호출 후 알림을 보내는 등 다양한 자동화가 가능합니다.&lt;/p&gt;
&lt;p&gt;Hooks는 개발 워크플로우를 크게 개선할 수 있습니다. 반복적인 작업을 자동화하고, 코드 품질을 즉각적으로 검증하며, 작업 흐름을 방해하지 않으면서도 필요한 체크를 수행할 수 있습니다.&lt;/p&gt;
&lt;h2 id="hook-이벤트-타입"&gt;Hook 이벤트 타입&lt;/h2&gt;
&lt;p&gt;Claude Code는 네 가지 주요 이벤트 타입을 제공합니다.&lt;/p&gt;</description></item></channel></rss>