<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>눌엉2 개발 블로그</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Wed, 08 Apr 2026 07:46:53 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>눌엉2 개발 블로그</title>
            <url>https://velog.velcdn.com/images/null_ong2/profile/aac71dd4-8c39-4166-8420-3499d8bbc181/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. 눌엉2 개발 블로그. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/null_ong2" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[UTILS] VScode 에서 TimeStamp 찍기]]></title>
            <link>https://velog.io/@null_ong2/UTILS-VScode-%EC%97%90%EC%84%9C-TimeStamp-%EC%B0%8D%EA%B8%B0</link>
            <guid>https://velog.io/@null_ong2/UTILS-VScode-%EC%97%90%EC%84%9C-TimeStamp-%EC%B0%8D%EA%B8%B0</guid>
            <pubDate>Wed, 08 Apr 2026 07:46:53 GMT</pubDate>
            <description><![CDATA[<h3 id="1-프로필-파일-생성">1. 프로필 파일 생성</h3>
<p>New-Item -Path $PROFILE -ItemType File -Force</p>
<h3 id="2-프로필-열기">2. 프로필 열기</h3>
<p>notepad $PROFILE</p>
<h3 id="3-아래-함수-붙여넣기">3. 아래 함수 붙여넣기</h3>
<pre><code>function prompt {
    &quot;$(Get-Date -Format &#39;HH:mm:ss&#39;) PS $($executionContext.SessionState.Path.CurrentLocation)&gt; &quot;
}</code></pre><h3 id="4-vscode-터미널-재시작">4. VSCode 터미널 재시작</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[[번역] Custom Hooks와 React Query로 로직과 UI 분리하기]]></title>
            <link>https://velog.io/@null_ong2/%EB%B2%88%EC%97%AD-Custom-Hooks%EC%99%80-React-Query%EB%A1%9C-%EB%A1%9C%EC%A7%81%EA%B3%BC-UI-%EB%B6%84%EB%A6%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@null_ong2/%EB%B2%88%EC%97%AD-Custom-Hooks%EC%99%80-React-Query%EB%A1%9C-%EB%A1%9C%EC%A7%81%EA%B3%BC-UI-%EB%B6%84%EB%A6%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 26 Mar 2026 03:30:58 GMT</pubDate>
            <description><![CDATA[<p><a href="https://medium.com/@echilaka/clean-react-architecture-separating-logic-from-presentation-with-custom-hooks-and-react-query-1904e9cc1eb0">원문</a></p>
<h3 id="📌-introduction">📌 Introduction</h3>
<p>많은 React 애플리케이션에서 흔히 발생하는 문제는 데이터 fetching, 상태 관리, 비즈니스 로직을 컴포넌트 안에 모두 넣어버리는 것이다.</p>
<p>다음과 같은 코드를 본 적 있을 것이다:</p>
<pre><code>function UserProfile({ username }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() =&gt; {
    setLoading(true);
    fetch(`/api/users/${username}`)
      .then(res =&gt; res.json())
      .then(data =&gt; {
        setUser(data);
        setLoading(false);
      })
      .catch(err =&gt; {
        setError(err.message);
        setLoading(false);
      });
  }, [username]);

  if (loading) return &lt;div&gt;Loading...&lt;/div&gt;;
  if (error) return &lt;div&gt;Error: {error}&lt;/div&gt;;
  if (!user) return null;

  return (
    &lt;div&gt;
      &lt;h1&gt;{user.name}&lt;/h1&gt;
      &lt;p&gt;{user.bio}&lt;/p&gt;
    &lt;/div&gt;
  );
}</code></pre><p>이 방식은 다음 문제를 만든다:</p>
<ul>
<li>데이터 fetching</li>
<li>상태 관리</li>
<li>에러 처리</li>
<li>로딩 상태 처리</li>
<li>UI 렌더링</li>
</ul>
<h4 id="→-모든-책임이-컴포넌트에-몰림">→ 모든 책임이 컴포넌트에 몰림</h4>
<h3 id="🚨-problem-관심사-혼합-mixed-concerns">🚨 Problem: 관심사 혼합 (Mixed Concerns)</h3>
<p>이 구조의 문제:</p>
<ul>
<li>테스트 어려움</li>
<li>재사용성 낮음</li>
<li>유지보수 어려움</li>
<li>캐싱 없음</li>
<li>상태 관리 복잡</li>
</ul>
<h4 id="→-✅-solution-custom-hooks--react-query">→ ✅ Solution: Custom Hooks + React Query</h4>
<h4 id="해결-방법">해결 방법:</h4>
<p>로직 → Custom Hook으로 분리
UI → 순수 컴포넌트로 유지</p>
<p>장점:</p>
<ul>
<li>관심사 분리</li>
<li>자동 캐싱</li>
<li>테스트 용이</li>
<li>재사용성 증가</li>
</ul>
<h3 id="🏗-architecture-구조">🏗 Architecture 구조</h3>
<h4 id="-presentation-layer-">[ Presentation Layer ]</h4>
<ul>
<li>UI만 담당</li>
<li>props 기반</li>
</ul>
<h4 id="-logic-layer-">[ Logic Layer ]</h4>
<ul>
<li>Custom Hooks</li>
<li>상태 관리</li>
<li>데이터 fetching</li>
<li>비즈니스 로직</li>
</ul>
<h3 id="1️⃣-순수-ui-컴포넌트-만들기">1️⃣ 순수 UI 컴포넌트 만들기</h3>
<pre><code>// src/components/UserCard.tsx
import type { User, UserSearchItem } from &quot;../types/User&quot;;

interface UserCardProps {
  user: User | UserSearchItem;
  onClick: () =&gt; void;
}

export const UserCard = ({ user, onClick }: UserCardProps) =&gt; {
  return (
    &lt;div onClick={onClick}&gt;
      &lt;img src={user.avatar_url} /&gt;
      &lt;h3&gt;{&quot;name&quot; in user ? user.name : user.login}&lt;/h3&gt;
      &lt;p&gt;@{user.login}&lt;/p&gt;
    &lt;/div&gt;
  );
};</code></pre><p>핵심:</p>
<ul>
<li>상태 없음</li>
<li>side effect 없음</li>
<li>props → JSX</li>
</ul>
<h3 id="2️⃣-custom-hook으로-로직-분리">2️⃣ Custom Hook으로 로직 분리</h3>
<pre><code>// src/hooks/useSearchUsers.ts
import { useQuery } from &quot;@tanstack/react-query&quot;;
import { githubApi } from &quot;../services/githubApi&quot;;

export const useSearchUsers = (query: string) =&gt; {
  const { data, isLoading, error, refetch } = useQuery({
    queryKey: [&quot;users&quot;, query],
    queryFn: async () =&gt; {
      const response = await githubApi.get(
        `/search/users?q=${encodeURIComponent(query)}`
      );

      // 비즈니스 로직 (정렬)
      return response.data.items.sort((a, b) =&gt; b.score - a.score);
    },
    enabled: query.length &gt; 2,
    staleTime: 5 * 60 * 1000,
  });

  return {
    users: data || [],
    isLoading,
    error,
    refetch,
  };
};
</code></pre><p>핵심:</p>
<ul>
<li>API 호출</li>
<li>캐싱</li>
<li>정렬 로직</li>
</ul>
<p>→ 모두 Hook 내부</p>
<h3 id="3️⃣-페이지-로직-조합-composition">3️⃣ 페이지 로직 조합 (Composition)</h3>
<pre><code>// src/hooks/useHomePage.ts
import { useState } from &quot;react&quot;;
import { useNavigate } from &quot;react-router-dom&quot;;
import { useSearchUsers } from &quot;./useSearchUsers&quot;;

export const useHomePage = () =&gt; {
  const [searchQuery, setSearchQuery] = useState(&quot;&quot;);
  const { users, isLoading, error } = useSearchUsers(searchQuery);
  const navigate = useNavigate();

  const handleSelectUser = (username: string) =&gt; {
    navigate(`/user/${username}`);
  };

  return {
    searchQuery,
    setSearchQuery,
    users,
    isLoading,
    error,
    handleSelectUser,
  };
};</code></pre><h3 id="4️⃣-페이지-컴포넌트-완전-단순화">4️⃣ 페이지 컴포넌트 (완전 단순화)</h3>
<pre><code>// src/pages/HomePage.tsx
import { useHomePage } from &quot;../hooks/useHomePage&quot;;

export const HomePage = () =&gt; {
  const {
    searchQuery,
    setSearchQuery,
    users,
    isLoading,
    error,
    handleSelectUser,
  } = useHomePage();

  return (
    &lt;div&gt;
      &lt;input onChange={(e) =&gt; setSearchQuery(e.target.value)} /&gt;

      {isLoading &amp;&amp; &lt;div&gt;Loading...&lt;/div&gt;}
      {error &amp;&amp; &lt;div&gt;Error&lt;/div&gt;}

      {users.map(user =&gt; (
        &lt;div key={user.login} onClick={() =&gt; handleSelectUser(user.login)}&gt;
          {user.login}
        &lt;/div&gt;
      ))}
    &lt;/div&gt;
  );
};</code></pre><h3 id="⚙️-advanced-repo-정렬-hook">⚙️ Advanced: Repo 정렬 Hook</h3>
<pre><code>// src/hooks/useFetchRepos.ts
import { useState } from &quot;react&quot;;
import { useQuery } from &quot;@tanstack/react-query&quot;;

export const useFetchRepos = (username: string) =&gt; {
  const [sortCriteria, setSortCriteria] = useState(&quot;stars&quot;);

  const { data, isLoading, error } = useQuery({
    queryKey: [&quot;repos&quot;, username],
    queryFn: async () =&gt; {
      const response = await fetch(`/users/${username}/repos`);
      return response.json();
    },
    enabled: !!username,
  });

  const sortedRepos = data
    ? [...data].sort((a, b) =&gt; {
        if (sortCriteria === &quot;stars&quot;) {
          return b.stargazers_count - a.stargazers_count;
        }
        return a.name.localeCompare(b.name);
      })
    : [];

  return {
    repos: data || [],
    sortedRepos,
    isLoading,
    error,
    sortBy: setSortCriteria,
  };
};</code></pre><h3 id="🧪-테스트-예시">🧪 테스트 예시</h3>
<p>Hook 테스트</p>
<pre><code>import { renderHook } from &quot;@testing-library/react&quot;;

test(&quot;useSearchUsers works&quot;, async () =&gt; {
  const { result } = renderHook(() =&gt; useSearchUsers(&quot;react&quot;));
});
컴포넌트 테스트
test(&quot;UserCard renders&quot;, () =&gt; {
  render(&lt;UserCard user={{ login: &quot;test&quot; }} onClick={() =&gt; {}} /&gt;);
});</code></pre><h3 id="🔄-마이그레이션-전략">🔄 마이그레이션 전략</h3>
<pre><code>Before
function UserProfile({ id }) {
  useEffect(() =&gt; {
    fetchUser(id);
  }, []);
}

After
function useUser(id) {
  return useQuery({
    queryKey: [&quot;user&quot;, id],
    queryFn: () =&gt; fetchUser(id),
  });
}</code></pre><h3 id="🎯-결론">🎯 결론</h3>
<p>→ 컴포넌트 = UI 전용
→ Hook = 로직 전용</p>
<h3 id="결과">결과:</h3>
<ul>
<li>유지보수 ↑</li>
<li>테스트 ↑</li>
<li>재사용 ↑</li>
<li>코드 가독성 ↑</li>
<li>📌 핵심 요약</li>
<li>❌ 컴포넌트에 로직 넣지 말 것</li>
<li>✅ Custom Hook으로 분리</li>
<li>✅ React Query 활용</li>
<li>✅ UI는 pure하게 유지</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[번역] 클린 코드의 심리학: 우리는 왜 지저분한 코드를 작성하는가?]]></title>
            <link>https://velog.io/@null_ong2/%EB%B2%88%EC%97%AD-%ED%81%B4%EB%A6%B0-%EC%BD%94%EB%93%9C%EC%9D%98-%EC%8B%AC%EB%A6%AC%ED%95%99-%EC%9A%B0%EB%A6%AC%EB%8A%94-%EC%99%9C-%EC%A7%80%EC%A0%80%EB%B6%84%ED%95%9C-%EC%BD%94%EB%93%9C%EB%A5%BC-%EC%9E%91%EC%84%B1%ED%95%98%EB%8A%94%EA%B0%80</link>
            <guid>https://velog.io/@null_ong2/%EB%B2%88%EC%97%AD-%ED%81%B4%EB%A6%B0-%EC%BD%94%EB%93%9C%EC%9D%98-%EC%8B%AC%EB%A6%AC%ED%95%99-%EC%9A%B0%EB%A6%AC%EB%8A%94-%EC%99%9C-%EC%A7%80%EC%A0%80%EB%B6%84%ED%95%9C-%EC%BD%94%EB%93%9C%EB%A5%BC-%EC%9E%91%EC%84%B1%ED%95%98%EB%8A%94%EA%B0%80</guid>
            <pubDate>Thu, 26 Feb 2026 01:51:58 GMT</pubDate>
            <description><![CDATA[<p>원문: <a href="https://cekrem.github.io/posts/psychology-of-clean-code/">https://cekrem.github.io/posts/psychology-of-clean-code/</a></p>
<h1 id="클린-코드의-심리학-우리는-왜-지저분한-코드를-작성하는가">클린 코드의 심리학: 우리는 왜 지저분한 코드를 작성하는가</h1>
<p>우리는 모두 클린 코드의 중요성을 알고 있다.
단일 책임 원칙, 명확한 네이밍, 적절한 추상화, 테스트 가능성.</p>
<p>그럼에도 불구하고 실제 프로젝트에서는 점점 비대해지는 컴포넌트, 복잡한 조건문, 분리되지 않은 상태 관리 코드가 만들어진다.</p>
<p>이 문제는 기술 부족 때문만은 아니다.
대부분은 인간의 인지 구조와 심리적 편향에서 비롯된다.</p>
<p>이 글에서는 우리가 왜 지저분한 코드를 작성하게 되는지, 그리고 이를 어떻게 구조적으로 개선할 수 있는지를 정리한다.</p>
<hr>
<h2 id="1-계획-오류-planning-fallacy">1. 계획 오류 (Planning Fallacy)</h2>
<h3 id="왜-발생하는가">왜 발생하는가</h3>
<p>우리는 작업에 필요한 시간을 항상 과소평가한다.(혹은 초기 기획이 변경되면서) 그리고 마감이 다가오면 구조 개선이나 리팩토링은 가장 먼저 포기된다.</p>
<p>그 결과:</p>
<ul>
<li>임시 구현이 영구 코드가 되고</li>
<li>리팩토링은 “다음에”로 미뤄지며</li>
<li>구조는 점점 복잡해진다</li>
</ul>
<h3 id="해결-방안">해결 방안</h3>
<ul>
<li><p><strong>리팩토링 시간을 명시적으로 포함한다</strong>
기능 구현 시간과 별도로 구조 정리 시간을 계획에 포함한다.</p>
</li>
<li><p><strong>작업 단위를 더 작게 나눈다</strong>
“완성된 기능”이 아니라 “리뷰 가능한 최소 단위”로 쪼갠다.</p>
</li>
<li><p><strong>초기 구현은 단순하게 제한한다</strong>
첫 버전은 단일 책임만 만족하도록 설계하고, 확장은 이후에 진행한다.</p>
</li>
<li><p><strong>PR 크기를 제한한다</strong>
변경 범위가 과도해지면 구조를 다시 점검한다.</p>
</li>
</ul>
<hr>
<h2 id="2-매몰비용-오류-sunk-cost-fallacy">2. 매몰비용 오류 (Sunk Cost Fallacy)</h2>
<h3 id="왜-발생하는가-1">왜 발생하는가</h3>
<p>이미 많은 시간을 들여 작성한 코드일수록 수정하기 어려워진다.
“여기까지 만들었는데 다시 하긴 아깝다”는 생각이 작동한다.</p>
<p>하지만 유지보수 비용은 과거의 투입 시간이 아니라 미래의 복잡성에 의해 결정된다.</p>
<h3 id="해결-방안-1">해결 방안</h3>
<ul>
<li><p><strong>코드를 결과물이 아니라 실험으로 인식한다</strong>
코드는 언제든 교체 가능한 산출물이다.</p>
</li>
<li><p><strong>삭제를 전제로 리팩토링을 검토한다</strong>
고치는 것이 아니라 다시 작성하는 것이 더 나은지 항상 비교한다.</p>
</li>
<li><p><strong>변경 전후를 객관적으로 비교한다</strong>
가독성, 테스트 용이성, 책임 분리 정도를 기준으로 평가한다.</p>
</li>
<li><p><strong>리팩토링 체크리스트를 만든다</strong></p>
<ul>
<li>중복이 제거되었는가?</li>
<li>책임이 분리되었는가?</li>
<li>테스트가 더 쉬워졌는가?</li>
</ul>
</li>
</ul>
<hr>
<h2 id="3-복잡성-편향-complexity-bias">3. 복잡성 편향 (Complexity Bias)</h2>
<h3 id="왜-발생하는가-2">왜 발생하는가</h3>
<p>우리는 단순한 해결책보다 복잡한 설계를 더 “미래지향적”이라고 착각한다.</p>
<ul>
<li>확장성을 과대평가하고</li>
<li>아직 존재하지 않는 요구사항을 대비하며</li>
<li>불필요한 추상화 계층을 만든다</li>
</ul>
<p>그 결과, 실제 요구사항보다 훨씬 복잡한 구조가 만들어진다.</p>
<h3 id="해결-방안-2">해결 방안</h3>
<ul>
<li><p><strong>YAGNI 원칙을 적용한다</strong>
지금 필요하지 않다면 구현하지 않는다.</p>
</li>
<li><p><strong>구체 구현 후 추상화한다</strong>
최소 2~3개의 실제 사용 사례가 생긴 뒤 공통화를 고려한다.</p>
</li>
<li><p><strong>질문을 고정한다</strong></p>
<ul>
<li>이 기능은 현재 요구사항에 포함되는가?</li>
<li>확장 가능성에 대한 명확한 근거가 있는가?</li>
</ul>
</li>
<li><p><strong>컴포넌트 역할을 명확히 분리한다</strong></p>
<ul>
<li>UI 전용</li>
<li>상태 관리 전용</li>
<li>도메인 로직 전용</li>
</ul>
</li>
</ul>
<hr>
<h2 id="4-결정-피로와-인지-부하-decision-fatigue--cognitive-load">4. 결정 피로와 인지 부하 (Decision Fatigue &amp; Cognitive Load)</h2>
<h3 id="왜-발생하는가-3">왜 발생하는가</h3>
<p>작업 시간이 길어질수록 판단의 질은 떨어진다.
상태가 많아질수록, 분기가 깊어질수록, 머릿속에서 동시에 추적해야 할 정보가 증가한다.</p>
<p>인간의 작업 기억은 제한적이다.
그 한계를 초과하면 코드 품질은 급격히 저하된다.</p>
<h3 id="해결-방안-3">해결 방안</h3>
<ul>
<li><p><strong>상태 개수 제한 규칙을 둔다</strong>
한 컴포넌트에 상태가 과도해지면 분리를 검토한다.</p>
</li>
<li><p><strong>조건문 깊이를 제한한다</strong>
중첩이 깊어지면 함수를 분리한다.</p>
</li>
<li><p><strong>세션 단위로 작업한다</strong>
일정 시간마다 구조를 다시 검토한다.</p>
</li>
<li><p><strong>패턴을 표준화한다</strong>
팀 내 상태 관리 방식과 구조 패턴을 통일한다.</p>
</li>
<li><p><strong>구조 점검 질문을 활용한다</strong></p>
<ul>
<li>이 컴포넌트의 책임을 한 문장으로 설명할 수 있는가?</li>
<li>테스트 시 mocking 범위가 과도하지 않은가?</li>
</ul>
</li>
</ul>
<hr>
<h2 id="핵심-정리">핵심 정리</h2>
<table>
<thead>
<tr>
<th>원인</th>
<th>본질적인 문제</th>
<th>구조적 대응</th>
</tr>
</thead>
<tbody><tr>
<td>계획 오류</td>
<td>시간 과소평가</td>
<td>리팩토링 시간 확보</td>
</tr>
<tr>
<td>매몰비용 오류</td>
<td>기존 코드 집착</td>
<td>삭제 가능성 전제</td>
</tr>
<tr>
<td>복잡성 편향</td>
<td>과잉 설계</td>
<td>실제 요구 중심 설계</td>
</tr>
<tr>
<td>인지 부하</td>
<td>상태·분기 과다</td>
<td>책임 분리 및 구조 제한</td>
</tr>
</tbody></table>
<hr>
<h1 id="🛠-어떻게-개선할-수-있는가">🛠 어떻게 개선할 수 있는가?</h1>
<h2 id="1-시작은-작게-점진적으로-확장하기">1. 시작은 작게, 점진적으로 확장하기</h2>
<p>처음부터 모든 기능을 하나의 거대한 컴포넌트에 담지 않는다.
현재 요구사항을 충족하는 <strong>최소 단위 구현</strong>부터 시작하고, 필요할 때 확장한다.</p>
<h3 id="예시">예시</h3>
<pre><code class="language-jsx">const UserDashboard = () =&gt; {
  const { users, loading, error } = useUsers();

  if (loading) return &lt;LoadingSpinner /&gt;;
  if (error) return &lt;ErrorMessage error={error} /&gt;;

  return &lt;UserList users={users} /&gt;;
};</code></pre>
<p>이 구조의 특징은 다음과 같다:</p>
<ul>
<li>데이터 패칭은 <code>useUsers</code> 훅에 위임</li>
<li>로딩과 에러 처리는 명확하게 분리</li>
<li>UI 렌더링은 <code>UserList</code>에 위임</li>
<li>각 책임이 한눈에 보임</li>
</ul>
<p>핵심은 <strong>처음부터 확장성을 설계하지 않는 것</strong>이다.
필요가 생길 때, 실제 사용 사례를 기반으로 확장한다.</p>
<hr>
<h2 id="2-팀-및-심리적-환경-정비">2. 팀 및 심리적 환경 정비</h2>
<p>클린 코드는 개인의 의지로만 유지되지 않는다.
구조를 유지할 수 있는 환경이 필요하다.</p>
<h3 id="반드시-필요한-요소">반드시 필요한 요소</h3>
<ul>
<li><p><strong>리팩토링 시간 확보</strong>
기능 개발과 동일한 수준으로 구조 개선 시간을 인정한다.</p>
</li>
<li><p><strong>실수를 인정할 수 있는 문화</strong>
“처음에 잘못 설계했다”는 말을 할 수 있어야 구조 개선이 가능하다.</p>
</li>
<li><p><strong>코드 리뷰 활성화</strong>
단순 동작 확인이 아니라 구조, 책임 분리, 확장성 관점에서 리뷰한다.</p>
</li>
<li><p><strong>클린 코드 사례 공유</strong>
좋은 사례를 반복적으로 노출시키면 팀 기준이 정립된다.</p>
</li>
</ul>
<hr>
<h2 id="3-작은-습관이-구조를-만든다">3. 작은 습관이 구조를 만든다</h2>
<p>거대한 리팩토링보다 더 중요한 것은 반복 가능한 습관이다.</p>
<h3 id="①-5분-규칙">① 5분 규칙</h3>
<p>구현 전에 5분 동안
“가장 단순한 해결책은 무엇인가?”를 먼저 고민한다.</p>
<p>대부분의 과도한 추상화는 이 5분을 생략하면서 시작된다.</p>
<hr>
<h3 id="②-코드-리뷰-체크-질문">② 코드 리뷰 체크 질문</h3>
<ul>
<li>이 코드를 다른 사람에게 자신 있게 설명할 수 있는가?</li>
<li>리뷰어에게 보여주기 꺼려지는 부분은 없는가?</li>
</ul>
<p>감정적 기준이지만, 구조적 문제를 빠르게 드러낸다.</p>
<hr>
<h3 id="③-미래의-나-테스트">③ 미래의 나 테스트</h3>
<ul>
<li>6개월 후에 이 코드를 쉽게 이해할 수 있는가?</li>
<li>변경이 생겼을 때 어디를 수정해야 할지 명확한가?</li>
</ul>
<p>클린 코드는 현재의 동작이 아니라
<strong>미래 변경 비용을 낮추는 설계</strong>다.</p>
<hr>
<h1 id="결론">결론</h1>
<p>클린 코드는 기술적 테크닉의 문제가 아니다.
그것은 다음을 관리하는 문제에 가깝다.</p>
<ul>
<li>시간 압박</li>
<li>인지적 한계</li>
<li>심리적 편향</li>
</ul>
<p>시작은 작게.
구조는 명확하게.
확장은 필요할 때만.</p>
<p>이 원칙을 반복적으로 적용할 때
비로소 지저분해지지 않는 코드가 만들어진다.</p>
<p>지저분한 코드는 기술이 부족해서 생기는 문제가 아니다.
대부분은 인간의 인지적 한계와 심리적 편향에서 비롯된다.</p>
<p>클린 코드는 “더 잘 짜는 능력”의 문제가 아니라,
<strong>구조적 제약을 설계하고 편향을 통제하는 습관</strong>의 문제에 가깝다.</p>
<p>좋은 코드는 의지로 유지되지 않는다.
환경과 규칙이 그것을 가능하게 만든다.</p>
]]></description>
        </item>
    </channel>
</rss>