<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Keep the Experience Natural, Easy, Light</title>
    <link>https://kenel.tistory.com/</link>
    <description>정보의 마찰 계수를 0으로 만드는 것</description>
    <language>ko</language>
    <pubDate>Wed, 10 Jun 2026 04:17:44 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>interfacer_han</managingEditor>
    <image>
      <title>Keep the Experience Natural, Easy, Light</title>
      <url>https://tistory1.daumcdn.net/tistory/6693629/attach/de10de1777bd402c8cbe314350b929a3</url>
      <link>https://kenel.tistory.com</link>
    </image>
    <item>
      <title>2023 ~ 2026년 AI 사용법의 진화</title>
      <link>https://kenel.tistory.com/401</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;#1 개요&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#1-1 What&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2022년 말 ChatGPT 출시 이후 LLM은 빠르게 대중화되었다. 개발자들은 2026년 지금까지도 현재진행형으로, LLM이 더 잘 응답하거나 행동하도록 설계하는 기법을 연구하고 있다. 가장 대표적인 기법 3가지를 &lt;b&gt;시간순으로&lt;/b&gt; 나열해본다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;#1-2 주의할 점&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 게시글의 제목에 '진화'라는 단어를 썼다. 그래서 &quot;(비교적) 오래된 기법은 혹시 도태된 것인가?&quot;라고 생각할 수도 있지만, 그렇지 않다. 모든 기법은 전부 중요하다. '진화'는 '개발자 관심사의 이동 경로'일 뿐, &lt;b&gt;모든 기법은 충실히 지켜야&lt;/b&gt; 한다 (세대교체가&amp;nbsp;아니라&amp;nbsp;&lt;b&gt;동시&amp;nbsp;병행&lt;/b&gt;).&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;#2 프롬프트 엔지니어링&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-1 WhatㆍWhy&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;어떻게 질문해야 잘 대답하는가?&quot; (입력 최적화)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력 &amp;rarr; 출력의 구조에서 &lt;b&gt;입력을 조작&lt;/b&gt;해 좋은 출력을 기대한다. &quot;가는 말이 고와야 오는 말도 곱다&quot;라는 속담은 LLM에도 적용되기 때문이다.&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;#2-2 How&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 역할 부여 (Role Prompting)&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;너는 초등학교 교사야. 초등학생이 이해하기 쉬운 방식으로 설명해.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;어떤 존재로서 답해야 하는지&lt;/b&gt;를 지정해ㆍ관점ㆍ태도ㆍ전문성 프레임을 변경한다.&lt;b&gt;&lt;br /&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;b&gt;Chain-of-Thought Prompting (CoT)&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;A, B, C의 단계별로 생각해.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델이 사고하는 순서(= &lt;b&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;b&gt;ReAct (Reason + Act)&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;생각하고, 행동하고, 관찰하고, 다시 생각해.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델이 추론과 외부 행동을 번갈아 수행하는 패턴을 설계한다. &lt;b&gt;'행동 후 피드백 기반 수정'&lt;/b&gt; 기법이라는 점에서 &lt;b&gt;현대&amp;nbsp;AI 에이전트의 원형&lt;/b&gt;이 되는 기법이기도 하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#3 컨텍스트 엔지니어링&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#3-1 WhatㆍWhy&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;어떤 정보를 떠먹여 줘야 잘 대답하는가?&quot; (정보 공급)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Context_window&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;컨텍스트 윈도우(Context window)&lt;/a&gt;는 LLM 모델이 가진 일종의 &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EB%9E%9C%EB%8D%A4_%EC%95%A1%EC%84%B8%EC%8A%A4_%EB%A9%94%EB%AA%A8%EB%A6%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;램(RAM)&lt;/a&gt;이다. 컴퓨터의 RAM과 마찬가지로 무한한 크기가 아니기 때문에, 적당한 크기의 정확한 정보를 적재적소에 제공하는 것이 필요하다.&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;이는 프롬프트 엔지니어링의 한계로 이어진다. 양질의 질문만으로는, LLM 모델의 물리적 한계(컨텍스트 윈도우 크기)를 극복할 수 없는 것이다.&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;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;질문(요청)에 담긴 정보(컨텍스트)가 커질수록 LLM의 컴퓨팅 비용과 응답이 시간 급증한다. 반면, 같은 정보를 '반복 전달'(= 2번 이상 전달)하는 경우에는 (정보가) 캐시 처리되어 비용이 거의 10분의 1로 줄어든다. AI 사용료를 아끼기 위해서라도 컨텍스트 엔지니어링은 필요하다.&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;#3-2 종류&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;System Context: 에이전트가 &lt;b&gt;항상&lt;/b&gt; 참조하는 기본 설정&lt;/li&gt;
&lt;li&gt;Conversation Context: &lt;b&gt;대화&lt;/b&gt; 과정에서 누적되는 정보&lt;/li&gt;
&lt;li&gt;Tool &amp;amp; Environment Context: 도구 실행으로 얻는 &lt;b&gt;실시간&lt;/b&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;#3-3 '다다익램'은 LLM에서도 통할까?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'다다익램'은 컴퓨터의 RAM 크기는 클수록 좋다는 의미다. LLM의 RAM인 컨텍스트 윈도우에게도 일반적으로는 통하는 말이다. 컨텍스트 윈도우가 커질수록 긴 대화를 잘 기억하고, 연속적인 작업도 잘 수행한다. 하지만 아래의 2가지 주의 사항을 고려해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://arxiv.org/abs/2307.03172&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Lost in the Middle&lt;/a&gt;: LLM이 전체 컨텍스트의 첫 부분과 끝부분은 잘 지키지만, &lt;b&gt;중간(Middle) 부분에 있는 컨텍스트일수록 무시&lt;/b&gt;할 확률이 높은 현상을 의미한다. 컨텍스트 윈도우의 크기가 커질수록 많은 정보(컨텍스트)를 넣을 수 있지만, 그에 비례해서 Lost in the Middle 현상 제어의 필요성도 커진다.&lt;/li&gt;
&lt;li&gt;작업대(컨텍스트 윈도우)에 관련 없는 &lt;b&gt;(쓰레기) 정보가 넘치면 모델의 판단이 '오염'&lt;/b&gt;되어 결과의 질이 저해된다. 무작정 많이 넣는 것만이 능사는 아니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#3-4 How&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Retrieval-Augmented Generation (RAG)&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;모르는 건 알아서 검색해.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요한 정보를 외부 저장소에서 &lt;b&gt;알아서 찾게&lt;/b&gt; 풀어준다. 웹(구글 등), DB의 특정 레코드, Notion 문서, 구글 드라이브 등 검색(접근)할 수 있는 매개체를 활용하게 만든다.&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;Context Packing&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;(LLM이 RAG 등을 활용해 가져온) 정보들을 알아서 최적화해&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨텍스트 윈도우 안에 정보 조각들을 어떤 우선순위와 압축도로 넣을지 결정한다. 이른바 &lt;b&gt;선택과 집중&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Chunking&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;검색ㆍ저장ㆍ삽입을 용이하게 하려고 정보(문서 파일 등)를 적절하게 작은 크기의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;조각(Chunk) 단위로 잘라두는 것.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;s&gt;Chunking은 RAG이나 Context Packing처럼 LLM이 동작 중(런타임)에 하는 일이 아니라 사람이 하는 일이다.&lt;/s&gt; 요즈음엔 런타임 Chunking도 많아졌다고 한다.&lt;/li&gt;
&lt;li&gt;혹은, 사람이 LLM에게 (본격적인 핵심 질문을 하기 전에) 미리 시켜둘 일이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#4 하네스 엔지니어링&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#4-1 Why&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;원하는 대답을 강요하려면 어떻게 해야 하는가?&quot; (실행 통제)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하네스 엔지니어링 전까지 LLM에게 &lt;b&gt;질문(요청)&lt;/b&gt;한다는 것은, 곧 &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;부탁&lt;/b&gt;&lt;/span&gt;하는 것과 같았다. 왜냐하면 LLM은 그 원리상, 뜬금없는 대답을 할 수도 있기 때문이다. 그럴 때의 시간 낭비를 막기 위해서, LLM이 반드시 &lt;b&gt;내가 원하는 답&lt;/b&gt;을 내놓도록 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;강제&lt;/b&gt;&lt;/span&gt;할 필요성이 생겼다. Structured Output 등 (지엽적인) 실행 통제 기법은 이미 존재했으나, 이를 좀 더 체계화하고 (전체적으로) 확장할 필요를 느낀 것이다.&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;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;'강제'&lt;/b&gt;&lt;/span&gt;라는 표현은 직관적인 설명을 위해 과장한 감이 없지 않다. 여기서 말하는 &lt;span style=&quot;color: #ee2323;&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;&quot;특정 파일 속 소스 코드 실행&quot;같이 거의 100%의 일관성을 지닌 요청&lt;/li&gt;
&lt;li&gt;여전히 &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;'부탁'&lt;/b&gt;&lt;/span&gt;처럼 보일 순 있으나, 프롬프트 엔지니어링 및 컨텍스트 엔지니어링의 패러다임 때와 비교하면 훨씬 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;더 &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EB%AA%85%EB%A0%B9%ED%98%95_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;명령적&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;(&lt;/b&gt;&lt;b&gt;&amp;harr; &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%84%A0%EC%96%B8%ED%98%95_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;선언적&lt;/a&gt;)&lt;/b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;인 요청&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;(똑똑하지만 동시에) &lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;불안정&lt;/span&gt;&lt;/b&gt;한 LLM을 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;안정적&lt;/span&gt;&lt;/b&gt;으로&amp;nbsp;일하게&amp;nbsp;만드는&amp;nbsp;기술&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1)부터 (3)까지의 모두를 포함한다.&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;#4-2 What&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;LLM을 말(Horse)로 비유하자면, 하네스 엔지니어링은 말에 마구(Harness)를 씌워 내가 원하는 행동을 하도록&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;조종(강제)&lt;/b&gt;&lt;/span&gt;하는 것이다. &lt;b&gt;구체적&lt;/b&gt;으로는 아래와 같은 절차를 설계하는 걸 하네스 엔지니어링이라 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Agent가 Context를 바탕으로 Plan을 세우고,&lt;br /&gt;Tool / MCP를 사용해 실행하고,&lt;br /&gt;Hook과 Skill로 품질을 제어하고,&lt;br /&gt;Human이 감독한다. (&lt;a href=&quot;https://www.youtube.com/watch?v=m99Vs94oHTQ&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;출처&lt;/a&gt;)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI &lt;b&gt;Agent는 알아서 판단하고 계획해서 결과&lt;/b&gt;를 내는 AI를 의미한다. 즉, AI Agent 구축엔 하네스 엔지니어링이 반드시 들어가야 한다. &lt;b&gt;실무적으로는 둘을 같다&lt;/b&gt;고 봐도 된다. 그 때문에 바로 아래에서 이어지는 #4-3에서, 하네스 엔지니어링의 기법과 AI Agent 구축 기법을 구분하지 않고 서술했다.&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;#4-3 How&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Planning &lt;/b&gt;&lt;br /&gt;사용자의 요청(질문) 즉 &lt;b&gt;복잡한 과제를 나눠서, 실행할 수 있는 &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%9B%8C%ED%81%AC%ED%94%8C%EB%A1%9C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Workflow&lt;/a&gt;로&lt;/b&gt; 바꾸는 것. 일반적으로 AI는 Workflow를 세운 뒤 사용자에게 보여주고 이대로 진행할지를 먼저 확인받는다. 저위험&amp;nbsp;과제의&amp;nbsp;경우엔&amp;nbsp;승인&amp;nbsp;없이&amp;nbsp;그냥&amp;nbsp;즉시&amp;nbsp;실행하기도&amp;nbsp;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;Sub Agent에 위임&lt;/b&gt; &lt;br /&gt;#3-3에서 말했던 Lost in the Middle 등의 이유로, &lt;b&gt;단일 에이전트에게 많은 일을 시키면 컨텍스트를 까먹는 현상&lt;/b&gt;이 발생한다. 따라서, AI Agent를 여러 Sub Agent를 나누는 구조가 나오게 되었다. Sub Agent의 역할은 프론트엔드 전문, 백엔드 전문, DB 설계 전문, 테스트 전문 등으로 다양하게 나뉠 수 있다. 또, 여러 &lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Sub Agent를 관리하는&lt;span&gt; Agent를 &lt;/span&gt;&lt;/span&gt;Orchestrator Agent&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;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Orchestrator Agent가 각 Sub Agent에 '작업을 분배'(= Fan Out)&lt;/li&gt;
&lt;li&gt;각 Sub Agent는 병렬적으로 독립적인 컨텍스트와 도구를 가지고 작업 수행 후 반환&lt;/li&gt;
&lt;li&gt;Orchestrator Agent가 반환된 결과를 통합(= Fan In)&lt;/li&gt;
&lt;/ol&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;Tool, Plugin, Model Context Protocol (MCP)&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;Tool&lt;/b&gt;: 개별 함수&lt;br /&gt;&lt;b&gt;Plugin&lt;/b&gt;: Tool 묶음&lt;br /&gt;&lt;b&gt;MCP&lt;/b&gt;: 모든 Tool과 Plugin을 어떤 AI 모델에서도 쓸 수 있게 하는 표준화된 인터페이스로 연결&lt;br /&gt;(&amp;asymp; 충전 케이블 타입을 USB-C로 통일했던 과거의 사례)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트의 &lt;b&gt;손과 발&lt;/b&gt;이 되어, 실제 세계와의 상호작용을 하는 기법들이다. 좀 더 엄밀하게 말하자면, Tool은 AI가 호출할 수 있는 기능의 단위, Plugin은 어떤 기능들을 하나의 패키지로 묶은 배포용 단위다.&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;Skill &amp;amp; Hook&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;Skill&lt;/b&gt;:&amp;nbsp;에이전트가&amp;nbsp;특정&amp;nbsp;작업을&amp;nbsp;수행할&amp;nbsp;때&amp;nbsp;참조하는&amp;nbsp;Best&amp;nbsp;Practice&amp;nbsp;문서&lt;b&gt;&lt;br /&gt;Hook&lt;/b&gt;: 특정 조건 만족 시 어떤 일을 하라고 강제&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트의 행동을 제약하는 기법들이다. Hook에는 아래와 같은 4가지 종류가 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Pre-action: 에이전트가 행동하기 전 수행&lt;/li&gt;
&lt;li&gt;Post-action: 에이전트가 행동한 후 수행&lt;/li&gt;
&lt;li&gt;Validation: 에이전트 출력의 품질 검증&lt;/li&gt;
&lt;li&gt;Notification: 특정 조건 충족 시 인간에게 알림&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;Human In The Loop (HITL)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 동작의 중간 또는 최종 단계에서, 인간 판단이 결과에 영향을 주도록 설계하는 것. 앞서 설명한 Planning에서 설명했듯, Agent가 실행할 일련의 계획을 사람에게 먼저 확인받고 진행하는 것도 HITL의 일부다. HITL은 2종류로 나뉜다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Task-level HITL: &lt;b&gt;개별 작업&lt;/b&gt; 승인/수정
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AI가&amp;nbsp;짠&amp;nbsp;Planning&amp;nbsp;검토&lt;/li&gt;
&lt;li&gt;AI 산출물의 결과 검수&lt;/li&gt;
&lt;li&gt;민감하거나 애매한 동작 수행 전 확인받기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;System-level HITL: &lt;b&gt;전체 루프&lt;/b&gt; 성능 평가/개선
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Prompt 수정&lt;/li&gt;
&lt;li&gt;제목&amp;nbsp;생성&amp;nbsp;Skill&amp;nbsp;교체&lt;/li&gt;
&lt;li&gt;검수&amp;nbsp;Rule&amp;nbsp;추가&lt;/li&gt;
&lt;li&gt;코드&amp;nbsp;생성&amp;nbsp;후&amp;nbsp;테스트&amp;nbsp;단계&amp;nbsp;추가&lt;/li&gt;
&lt;/ul&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;#4-4 실습&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가 예정 (&lt;a href=&quot;https://kenel.tistory.com/402&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;다음 게시글&lt;/a&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;#4-5 용어에 대한 논쟁&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트/배포 자동화 (CI/CD), 성능 평가 파이프라인(흐름) 등의 개념은 LLM이 대중화되기 한참 전에 나왔다. 저 개념들을 LLM을 활용해 구현했을 뿐인데, 그걸 &lt;b&gt;굳이&lt;/b&gt; &quot;하네스 엔지니어링&quot;라는 &lt;b&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;color: #409d00;&quot;&gt;&lt;b&gt;부탁&lt;/b&gt;&lt;/span&gt;&lt;b&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#5 요약&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ChatGPT 이후, 개발자들은 &lt;b&gt;'챗봇'의 잠재력을 끌어내 '에이전트'로&lt;/b&gt; 만드는 기법들을 고안해 냈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#6 출처&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ryyEm2MKwtg&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[YouTube]&amp;nbsp;AI&amp;nbsp;엔지니어링이&amp;nbsp;4년간&amp;nbsp;이렇게&amp;nbsp;변화했습니다&amp;nbsp;|&amp;nbsp;개발동생&amp;nbsp;하네스&amp;nbsp;공개&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=m99Vs94oHTQ&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[YouTube]&amp;nbsp;메타&amp;nbsp;엔지니어가&amp;nbsp;알려주는&amp;nbsp;에이전틱&amp;nbsp;엔지니어링&amp;nbsp;핵심&amp;nbsp;개념&amp;nbsp;5가지&amp;nbsp;총정리&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=6gvnDSAcZww&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[YouTube]&amp;nbsp;프롬프트&amp;nbsp;엔지니어링은&amp;nbsp;끝났습니다:&amp;nbsp;이제&amp;nbsp;'하네스'의&amp;nbsp;시대입니다&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발 일지  /AI</category>
      <author>interfacer_han</author>
      <guid isPermaLink="true">https://kenel.tistory.com/401</guid>
      <comments>https://kenel.tistory.com/401#entry401comment</comments>
      <pubDate>Fri, 1 May 2026 16:42:12 +0900</pubDate>
    </item>
    <item>
      <title>Swemo - Iteration 5: MVP 1 구현 (2/3)</title>
      <link>https://kenel.tistory.com/399</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;#1 개발 목표 (Iteration Goal)&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#1-1 이상(Ideal)과 징검다리&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Iteration 5: MVP 1 구현 (2/3)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://kenel.tistory.com/398&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Iteration 4&lt;/a&gt;의 토대 위에 기본 기능들을 구현했다. 이어지는 &lt;a href=&quot;https://kenel.tistory.com/400&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Iteration 6&lt;/a&gt;에서 추가적인 리팩토링 후 MVP를 마무리한다.&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;#1-2 개발 범위&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이번&amp;nbsp;개발&amp;nbsp;범위&amp;nbsp;(In&amp;nbsp;Scope)&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;/li&gt;
&lt;li&gt;메모 수정, 삭제 기능&lt;/li&gt;
&lt;li&gt;메모 콘텐츠(MemoContent) 제거 기능&lt;/li&gt;
&lt;li&gt;리팩토링
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;MemoViewModel가 지닐 필요가 없는 과도한 프로퍼티를 MemoUiState 쪽으로 옮김&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;MemoViewModel의 일부 이벤트들이 재사용성을 가지도록 수정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;MemoViewModel의 이벤트들에 (직관적으로 읽히도록) 주석 추가&lt;/li&gt;
&lt;li&gt;MemoScreen에 구조적으로 화면의 하나의 Dialog만 표시되도록 설계&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#2 변경 내역 (커밋 목록)&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-1 Iteration 5-1: MemoRepository에&amp;nbsp;함수&amp;nbsp;추가&amp;nbsp;및&amp;nbsp;MemoDao&amp;nbsp;가독성&amp;nbsp;업데이트&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&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;카테고리&amp;nbsp;추가,&amp;nbsp;이름&amp;nbsp;변경,&amp;nbsp;삭제&amp;nbsp;기능&lt;/li&gt;
&lt;li&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;/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;MemoRepository에 Iteration 5에서 사용할 여러 함수를 (선제적으로) 추가&lt;/li&gt;
&lt;li&gt;MemoDao 함수들의 이름을 가독성과 통일성을 고려해 변경하고 역할별로 (섹션으로 나눠) 정돈&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;/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;a href=&quot;https://github.com/Kanmanemone/swemo/commit/7e901c86b33eff18094ec5dab1faab5b609fa4a2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub] 이 작업의 Commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/CRUD&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Wikipedia] CRUD&lt;/a&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;#2-2 Iteration 5-2: MemoViewModel 리팩토링&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 MemoViewModel이 Category 인스턴스를 직접 보유하고 그걸 MemoUiState에 넘겨주고 있다. MemoViewModel이 불필요한 책임을 떠맡고 있기에, 이를 고쳐서 ViewModel은 Category.id만 조작하게 두었다. 그리고 그 Category.id에 종속되어 업데이트되는 Category 인스턴스가 MemoUiState 속에 들어가도록 변경했다.&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;/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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MemoViewModel가&amp;nbsp;지닐&amp;nbsp;필요가&amp;nbsp;없는&amp;nbsp;과도한&amp;nbsp;프로퍼티를&amp;nbsp;MemoUiState&amp;nbsp;쪽으로&amp;nbsp;옮김&lt;/li&gt;
&lt;/ul&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;/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;현재 카테고리를 직접 저장(보유)하지 않고, selectedCategoryId를 단일 진실 공급원으로 삼아 파생하도록 변경&lt;/li&gt;
&lt;li&gt;determineCategory()로 기본 선택과 유효하지 않은 선택값 복구 로직을 정리&lt;/li&gt;
&lt;li&gt;카테고리 변경이나 MemoEditor 토글이 편집 중인 Memo에 영향을 주지 않도록 수정&lt;/li&gt;
&lt;li&gt;State 관리 코드 가독성 개선&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;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1766585027758&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 기존 코드
private val selectedCategory = MutableStateFlow&amp;lt;Category?&amp;gt;(null)

---
// 변경한 코드
private val selectedCategoryId = MutableStateFlow&amp;lt;Long?&amp;gt;(null)

// 이제 selectedCategory는 selectedCategoryId로부터 파생되는 상태
// MutableStateFlow가 아니기 때문에, 임의로 조작할 수 없다 (= 책임에서 해방)
private val selectedCategory: StateFlow&amp;lt;Category?&amp;gt; = combine(
    categories,
    selectedCategoryId,
    ::determineCategory
).stateIn(
    scope = viewModelScope,
    started = SharingPolicy,
    initialValue = null
)&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;/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;a href=&quot;https://github.com/Kanmanemone/swemo/commit/18729ef21b2697d4c1e7ae32d497b597b38f36ab&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub] 이 작업의 Commit&lt;/a&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;#2-3 Iteration 5-3: Dialog&amp;nbsp;상태를&amp;nbsp;enum&amp;nbsp;형&amp;nbsp;UI&amp;nbsp;로컬&amp;nbsp;상태로&amp;nbsp;전환&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 경험을 위해서라도 한 화면에 Dialog는 하나만 떠 있어야 한다. 그리고 Dialog가 많아짐에 따라 선언적으로 관리할 필요도 느꼈다. 따라서, 'Dialog 표시'의 플래그 역할을 하는 State를 선언하고, 그 State의 변화에 맞춰 MemoScreen에 Dialog가 뜨도록 설계했다.&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;/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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MemoScreen에&amp;nbsp;구조적으로&amp;nbsp;화면의&amp;nbsp;하나의&amp;nbsp;Dialog만&amp;nbsp;표시되도록&amp;nbsp;설계&lt;/li&gt;
&lt;/ul&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;/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;앞으로 여러 종류의 Dialog를 표현해야 하므로, 복수 개의 Dialog가 화면에 중첩되는 현상 또는 가독성 저해를 대비해 'Dialog 표시 플래그 State'를 ViewModel에서 UI로 내림&lt;/li&gt;
&lt;li&gt;State를 Boolean 형이 아닌 enum 형으로 변경해 여러 다이얼로그를 표현할 수 있으면서, 오직 하나의 Dialog만을 화면에 띄우도록 구조적으로 강제&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;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1766585027758&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;internal fun MemoScreen(
    ...
    dialogState: MemoScreenDialog?, // 추가됨
    ...
) {
    ...

    when (dialogState) {
        MemoScreenDialog.CATEGORY_ADD -&amp;gt; {
            AddCategoryDialog(
                ...
            ) {
                ...
            }
        }

        MemoScreenDialog.CATEGORY_RENAME -&amp;gt; {
            ...
        }

        MemoScreenDialog.CATEGORY_DELETE -&amp;gt; {
            ...
        }

        null -&amp;gt; Unit // Dialog가 닫힌 상태 의미
    }
}&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;/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;a href=&quot;https://github.com/Kanmanemone/swemo/commit/dddbaa4f559b1fbd7360863de428134f25a6cefd&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub] 이 작업의 Commit&lt;/a&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;#2-4 Iteration 5-4: 카테고리&amp;nbsp;추가,&amp;nbsp;이름&amp;nbsp;변경,&amp;nbsp;제거&amp;nbsp;기능&amp;nbsp;추가&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Iteration 4 및 Iteration 5-1 ~ 5-3에서서 행한 밑작업 토대 위에 카테고리 조작 관련 기능을 구현했다.&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;/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;카테고리&amp;nbsp;추가,&amp;nbsp;이름&amp;nbsp;변경,&amp;nbsp;삭제&amp;nbsp;기능&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;/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;/li&gt;
&lt;li&gt;카테고리 추가, 이름 변경, 삭제를 위한 여러 Dialog 구현&lt;/li&gt;
&lt;li&gt;구현한 Dialog를 MemoScreenDialogHost에 추가&lt;/li&gt;
&lt;li&gt;CategoryDao에 정의해놓은 함수를 MemoViewModel과 MemoScreen을 거쳐 Dialog까지 전달&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;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2833&quot; data-origin-height=&quot;3808&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xFDP0/dJMcaiQx8dg/IT0NqokExxGJ1Kk989hn91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xFDP0/dJMcaiQx8dg/IT0NqokExxGJ1Kk989hn91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xFDP0/dJMcaiQx8dg/IT0NqokExxGJ1Kk989hn91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxFDP0%2FdJMcaiQx8dg%2FIT0NqokExxGJ1Kk989hn91%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;2833&quot; height=&quot;3808&quot; data-origin-width=&quot;2833&quot; data-origin-height=&quot;3808&quot;/&gt;&lt;/span&gt;&lt;/figure&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;/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;a href=&quot;https://github.com/Kanmanemone/swemo/commit/4f4c1564b1328c1aec7001340676d74f706ba476&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub] 이 작업의 Commit&lt;/a&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;#2-5 Iteration 5-5: 메모&amp;nbsp;제거&amp;nbsp;구현&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Iteration 4 및 Iteration 5-1 ~ 5-3에서서 행한 밑 작업 토대 위에 메모 제거 기능을 구현했다.&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;추가로, Iteration 5-3에서 만든 'Dialog 표시 플래그' State를 enum에서 sealed interface로 변경했다. 왜냐하면, 메모를 제거할 때 어떤 메모를 제거하는지에 대한 정보를 ViewModel에게 알려줘야 하기 때문이다. sealed interface로 묶을 '메모 제거 Dialog 플래그'가 Memo.id를 받도록 선언해야, 사용자가 '메모 제거 Dialog'에 있는 '삭제' 버튼을 클릭했을 때 발생하는 이벤트에 Memo.id 인수를 실어 (MemoViewModel로) 보낼 수 있다.&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;/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;/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;/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;MemoScreenDialog를 enum 형에서 sealed interface로 변경&lt;/li&gt;
&lt;li&gt;Memo 아이템을 길게 눌러 DeleteMemoDialog를 띄움&lt;/li&gt;
&lt;li&gt;Dialog에서 버튼을 한 번 더 눌러 해당 Memo 제거&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;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1766585027758&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 제거한 코드
enum class MemoScreenDialog {
    CATEGORY_ADD,
    CATEGORY_RENAME,
    CATEGORY_DELETE
}

---
// 추가한 코드
sealed interface MemoScreenDialog : Serializable {
    data object CategoryAdd : MemoScreenDialog {
        private fun readResolve(): Any = CategoryAdd
    }

    data object CategoryRename : MemoScreenDialog {
        private fun readResolve(): Any = CategoryRename
    }

    data object CategoryDelete : MemoScreenDialog {
        private fun readResolve(): Any = CategoryDelete
    }

    data class MemoDelete(val memoId: Long) : MemoScreenDialog
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조에서, MemoScreenDialog형 데이터가 MemoDelete로 그 값을 변경하려면 memoId도 함께 넣어주어야 한다.&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;/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;a href=&quot;https://github.com/Kanmanemone/swemo/commit/c34a534a2fff7396e6976c994065b5f017e25295&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub] 이 작업의 Commit&lt;/a&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;#2-6 Iteration 5-6: 메모&amp;nbsp;업데이트&amp;nbsp;구현&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MemoCard 클릭 시, MemoEditor에 해당 MemoCard의 Memo 정보가 MemoEditor로 복사되게 만들었다. 이 상태에서는 MemoEditor의 '전송' 버튼이 '수정' 버튼으로 변경된다. 그리고 수정 버튼을 클릭하면 Memo가 업데이트된다.&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;/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;/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;/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;/li&gt;
&lt;li&gt;에디터가 &quot;등록 모드&quot;, &quot;수정 모드&quot; 둘 중 하나가 되도록 변경&lt;/li&gt;
&lt;li&gt;에디터의 모드에 따라 메모를 추가(Insert)하거나 수정(Update)&lt;/li&gt;
&lt;li&gt;메모 삭제 시, 해당 메모를 에디터에서 수정 중이었으면 에디터 초기화&lt;/li&gt;
&lt;li&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;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2833&quot; data-origin-height=&quot;4338&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YzstH/dJMcafsMvS7/kBZYKbmI859E7ytteeekPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YzstH/dJMcafsMvS7/kBZYKbmI859E7ytteeekPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YzstH/dJMcafsMvS7/kBZYKbmI859E7ytteeekPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYzstH%2FdJMcafsMvS7%2FkBZYKbmI859E7ytteeekPk%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;2833&quot; height=&quot;4338&quot; data-origin-width=&quot;2833&quot; data-origin-height=&quot;4338&quot;/&gt;&lt;/span&gt;&lt;/figure&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;/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;a href=&quot;https://github.com/Kanmanemone/swemo/commit/126280bab71b35deab8013b853bb7e4e936ea9ce&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub] 이 작업의 Commit&lt;/a&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;#2-7 Iteration 5-7: MemoContent 제거 구현&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;-&quot; 버튼을 클릭하면 MemoContent가 한 줄씩 지워지게 만들었다.&lt;/li&gt;
&lt;li&gt;MemoContent.text가 수정될 때마다 내부적으로 전제 Memo를 갈아끼우는 식으로 데이터베이스 조작이 이뤄졌는데, 이제 MemoContent의 변화가 해당 전체 Memo를 건들이지 않고 해당 MemoContent가 저장된 장소만 업데이트하도록 개선했다.&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;/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;메모&amp;nbsp;콘텐츠(MemoContent)&amp;nbsp;제거&amp;nbsp;기능&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;/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;MemoContent 제거 버튼 및 동작 구현&lt;/li&gt;
&lt;li&gt;MemoEditor에서 Memo를 수정할 때마다 전체 Memo가 갱신되는 구조 대신, MemoContent 별로 갱신되게 만듦&lt;/li&gt;
&lt;li&gt;MemoContent가 하나도 없는 Memo는
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;(UI) Insert 및 Update 버튼을 비활성화&lt;/li&gt;
&lt;li&gt;(ViewModel) Insert 및 Update 이벤트에서도 (분기문으로) 걸러줌&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;새 MemoContent의 label 값이 MemoContent의 갯수에 기반하는 대신, 마지막 MemoContent의 label 값에 기반해 생성되게 함&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;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2833&quot; data-origin-height=&quot;3808&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKQ39K/dJMcaipwFLg/AWcx1aRteYisxN1xnALuYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKQ39K/dJMcaipwFLg/AWcx1aRteYisxN1xnALuYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKQ39K/dJMcaipwFLg/AWcx1aRteYisxN1xnALuYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKQ39K%2FdJMcaipwFLg%2FAWcx1aRteYisxN1xnALuYK%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;2833&quot; height=&quot;3808&quot; data-origin-width=&quot;2833&quot; data-origin-height=&quot;3808&quot;/&gt;&lt;/span&gt;&lt;/figure&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;/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;a href=&quot;https://github.com/Kanmanemone/swemo/commit/c85c381e4c07db533fff7ebae2daf999aefddfca&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub] 이 작업의 Commit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발 일지  /Swemo</category>
      <author>interfacer_han</author>
      <guid isPermaLink="true">https://kenel.tistory.com/399</guid>
      <comments>https://kenel.tistory.com/399#entry399comment</comments>
      <pubDate>Tue, 21 Apr 2026 18:23:25 +0900</pubDate>
    </item>
    <item>
      <title>Swemo - Iteration 4: MVP 1 구현 (1/3)</title>
      <link>https://kenel.tistory.com/398</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;#1 개발 목표 (Iteration Goal)&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#1-1 이상(Ideal)과 징검다리&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이상(Ideal)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가&amp;nbsp;직접&amp;nbsp;쓰고&amp;nbsp;싶은&amp;nbsp;앱이&amp;nbsp;아닌데,&amp;nbsp;남에게&amp;nbsp;어떻게&amp;nbsp;권유할&amp;nbsp;수&amp;nbsp;있을까?&amp;nbsp;앞으로&amp;nbsp;추가할&amp;nbsp;기능의&amp;nbsp;아이디어를&amp;nbsp;얻기&amp;nbsp;위해서든,&amp;nbsp;개발&amp;nbsp;의욕을&amp;nbsp;위해서든,&amp;nbsp;버그&amp;nbsp;발견을&amp;nbsp;위해서든&amp;nbsp;제작자의&amp;nbsp;실사용은&amp;nbsp;필수다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;지금까지의 작업 결과물을 토대로, 당장 내가 사용할 수 있는 앱을 만든다. 메모장 대용으로 사용할 수 있기만 하면 그만이므로, 완성도에는 신경 쓰지 않아야 할 것이다. CategoryㆍMemoㆍMemoContent 각각에 대한 &lt;a href=&quot;https://ko.wikipedia.org/wiki/CRUD&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CRUD&lt;/a&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;Iteration 4: MVP 1 구현 (1/3)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재까지&amp;nbsp;구현한&amp;nbsp;것을&amp;nbsp;중간&amp;nbsp;마무리하여&amp;nbsp;첫&amp;nbsp;번째&amp;nbsp;MVP를&amp;nbsp;만든다.&amp;nbsp;Iteration&amp;nbsp;4에서는&amp;nbsp;실제&amp;nbsp;데이터베이스&amp;nbsp;추가&amp;nbsp;및&amp;nbsp;해당&amp;nbsp;DB에&amp;nbsp;메모를&amp;nbsp;추가하는&amp;nbsp;기능까지만&amp;nbsp;구현한다.&amp;nbsp;이어지는&amp;nbsp;&lt;a href=&quot;https://kenel.tistory.com/399&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Iteration&amp;nbsp;5&lt;/a&gt;에서 나머지 기능들까지 구현하고 &lt;a href=&quot;https://kenel.tistory.com/400&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Iteration 6&lt;/a&gt;에서 코드 리팩토링까지 한 후에, 첫 번째 MVP를 마무리하겠다.&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;#1-2 개발 범위&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이번&amp;nbsp;개발&amp;nbsp;범위&amp;nbsp;(In&amp;nbsp;Scope)&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;실제 Database 구현&lt;/li&gt;
&lt;li&gt;메모 추가 기능&lt;/li&gt;
&lt;li&gt;MVP를 위한 UI 업데이트
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;IME에 반응하는 UI&lt;/li&gt;
&lt;li&gt;LabelChipGroup 제거
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아이디어 자체를 폐기하는 게 아니라, 당장의 MVP 구현을 위해 제거&lt;/li&gt;
&lt;li&gt;Iteration 4에서 제거 후 나중에 다시 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&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;범위&amp;nbsp;외&amp;nbsp;(Out&amp;nbsp;of&amp;nbsp;Scope)&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;/li&gt;
&lt;li&gt;메모 속 MemoContent 개별 삭제 기능&lt;/li&gt;
&lt;li&gt;메모 수정 기능&lt;/li&gt;
&lt;li&gt;카테고리 추가 기능&lt;/li&gt;
&lt;li&gt;카테고리 삭제 기능&lt;/li&gt;
&lt;li&gt;카테고리 이름 수정 기능&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#2 변경 내역 (커밋 목록)&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-1 Iteration 4-1: IME에 반응하는 UI&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실사용을 위해서, 우선 UI가 IME에 반응하지 않는 점을 수정한다.&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;/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;MVP를&amp;nbsp;위한&amp;nbsp;UI&amp;nbsp;업데이트
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IME에 반응하는 UI&lt;/li&gt;
&lt;/ul&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;/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;App의 Window가 IME에 영향받지 않도록 설정&lt;/li&gt;
&lt;li&gt;MemoEditor가 IME에 맞춰 움직이도록 구현&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kenel.tistory.com/384#2-3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Iteration 1-3&lt;/a&gt;에서 테스트용으로 뒀던 topBar 속 버튼을 제거하고, 해당 버튼이 지녔던 기능을 MemoEditor 속 &quot;Send&quot; 버튼에 할당&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;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2833&quot; data-origin-height=&quot;1948&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIeOsh/dJMcafMSO6G/OQ1uaJVBF5igXS02GYZMyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIeOsh/dJMcafMSO6G/OQ1uaJVBF5igXS02GYZMyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIeOsh/dJMcafMSO6G/OQ1uaJVBF5igXS02GYZMyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIeOsh%2FdJMcafMSO6G%2FOQ1uaJVBF5igXS02GYZMyK%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;2833&quot; height=&quot;1948&quot; data-origin-width=&quot;2833&quot; data-origin-height=&quot;1948&quot;/&gt;&lt;/span&gt;&lt;/figure&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;/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;a href=&quot;https://github.com/Kanmanemone/swemo/commit/83d43b584d3bb3b063422daa52421498712eba7c&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub] 이 작업의 Commit&lt;/a&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;#2-2 Iteration 4-2: LabelChipGroup&amp;nbsp;등&amp;nbsp;제거&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://kenel.tistory.com/392#2-5&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;LabelChipGroup&lt;/a&gt;은 일단 삭제했다. 당장 구현할 MVP에서 보이기에는 완성도가 떨어지고 시간도 없기 때문이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하지만, LabelChipGroup은 본 앱의 핵심 UI 요소이기 때문에 나중에 어떤 형태로든 다시 추가될 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kenel.tistory.com/392#2-1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이전에 구상했던 설계&lt;/a&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;/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;MVP를 위한 UI 업데이트
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LabelChipGroup 제거&lt;/li&gt;
&lt;/ul&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;/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;MemoFeed의 아이템이 아래에서 위로 올라오는 형태로 변경&lt;/li&gt;
&lt;li&gt;MemoEditor에서 &quot;-&quot; 버튼 제거&lt;/li&gt;
&lt;li&gt;LabelChipGroup 제거&lt;/li&gt;
&lt;li&gt;MemoContentTextField 디자인 살짝 다듬음&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;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2833&quot; data-origin-height=&quot;1948&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMcdl3/dJMcabRcWNb/WsmZXb04EpKC005dMEQ1y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMcdl3/dJMcabRcWNb/WsmZXb04EpKC005dMEQ1y1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMcdl3/dJMcabRcWNb/WsmZXb04EpKC005dMEQ1y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMcdl3%2FdJMcabRcWNb%2FWsmZXb04EpKC005dMEQ1y1%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;2833&quot; height=&quot;1948&quot; data-origin-width=&quot;2833&quot; data-origin-height=&quot;1948&quot;/&gt;&lt;/span&gt;&lt;/figure&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;코드 스니펫 - MemoFeed&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1766585027758&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.example.memo.components

...

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MemoFeed(
    memos: List&amp;lt;Memo&amp;gt;,
    modifier: Modifier
) {
    LazyColumn(
        modifier = modifier,
        reverseLayout = true,
    ) {
        items(memos.asReversed()) { memo -&amp;gt;
            Spacer(modifier = Modifier.height(4.dp))
            MemoCard(memo = memo)
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reverseLayout = true 로 레이아웃 컨테이너를 뒤집고, 그 뒤집힌 컨테이너에 아이템을 역순(asReversed)으로 준다. 이러면 최신 메모일수록 아래에 있고 최초 스크롤바의 위치도 맨 아래에서 시작하는, 이른바 &lt;a href=&quot;https://kenel.tistory.com/249&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;채팅 UI&lt;/a&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;/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;a href=&quot;https://github.com/Kanmanemone/swemo/commit/94e3b69c466973a5f5fbb704113042a0090f5ca4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub] 이 작업의 Commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kenel.tistory.com/249&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Tistory]&amp;nbsp;Nutri&amp;nbsp;Capture&amp;nbsp;-&amp;nbsp;채팅&amp;nbsp;UI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kenel.tistory.com/392&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Tistory] Swemo - Iteration 2: UI 디자인 방향 탐색(Exploration)&lt;/a&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;#2-3 Iteration 4-3: MemoContent&amp;nbsp;추가&amp;nbsp;버튼&amp;nbsp;구현&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MVP를 위한 UI 업데이트를 마무리한다&lt;/li&gt;
&lt;li&gt;MemoEditor를 통해 FakeMemoRepository에 메모를 추가하는 기능을 구현했다&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;/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;MVP를 위한 UI 업데이트&lt;/li&gt;
&lt;li&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;/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;MemoEditor 속에 MemoContent 추가 버튼 구현&lt;/li&gt;
&lt;li&gt;MemoEditor로 메모 입력 &amp;rarr; (FakeMemoRepository에) 메모 추가 기능 구현&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;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2833&quot; data-origin-height=&quot;1948&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zdNVD/dJMcagycJyV/KOjIfBU0bHBbZhv2Ug68F0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zdNVD/dJMcagycJyV/KOjIfBU0bHBbZhv2Ug68F0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zdNVD/dJMcagycJyV/KOjIfBU0bHBbZhv2Ug68F0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzdNVD%2FdJMcagycJyV%2FKOjIfBU0bHBbZhv2Ug68F0%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;2833&quot; height=&quot;1948&quot; data-origin-width=&quot;2833&quot; data-origin-height=&quot;1948&quot;/&gt;&lt;/span&gt;&lt;/figure&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;/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;a href=&quot;https://github.com/Kanmanemone/swemo/commit/09f3fad7d71474567416ef730a5c810880e9ba1e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub] 이 작업의 Commit&lt;/a&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;#2-4 Iteration 4-4: id&amp;nbsp;프로퍼티의&amp;nbsp;데이터형&amp;nbsp;변경&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내부&amp;nbsp;데이터베이스를&amp;nbsp;사용할&amp;nbsp;예정이므로,&amp;nbsp;id는&amp;nbsp;서버&amp;nbsp;환경처럼&amp;nbsp;String&amp;nbsp;타입으로&amp;nbsp;둘&amp;nbsp;필요가&amp;nbsp;크지&amp;nbsp;않다고&amp;nbsp;판단했다.&amp;nbsp;오히려&amp;nbsp;전통적인&amp;nbsp;방식대로&amp;nbsp;숫자형&amp;nbsp;데이터를&amp;nbsp;사용하는&amp;nbsp;편이&amp;nbsp;저장,&amp;nbsp;조회,&amp;nbsp;관리&amp;nbsp;측면에서&amp;nbsp;더&amp;nbsp;적절하다고&amp;nbsp;본다.&lt;/li&gt;
&lt;li&gt;MemoContent는 Memo에 종속된 항목이기 때문에 별도의 id 프로퍼티를 두지 않았다. 그러나 앞으로 다른 Memo로 이동시키는 기능 등이 추가될 가능성이 높다고 판단해, 선제적으로 id 프로퍼티를 추가했다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;식별자가 뒤늦게 필요해지면 데이터 구조 + 사용처 전반을 &lt;a href=&quot;https://kenel.tistory.com/375#3-2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;함께 수정&lt;/a&gt;해야 할 수 있어, 여기에서 미리 반영하는 편이 더 안정적이라고 판단했다.&lt;/li&gt;
&lt;/ul&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;/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;실제&amp;nbsp;Database&amp;nbsp;구현&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;/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;Model 클래스들의 String 형 &quot;id&quot; 프로퍼티의 데이터형을 Long 형으로 변경&lt;/li&gt;
&lt;li&gt;MemoContent에 (Long 형) &quot;id&quot; 프로퍼티 추가&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;/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;a href=&quot;https://github.com/Kanmanemone/swemo/commit/d4cca18d79b9962e452872fec3b1c8fa39eb5905&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub] 이 작업의 Commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kenel.tistory.com/375&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Tistory]&amp;nbsp;SOLID&amp;nbsp;원칙&lt;/a&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;#2-5 Iteration 4-5: database&amp;nbsp;모듈&amp;nbsp;구현&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;database&amp;nbsp;모듈을&amp;nbsp;선언&amp;nbsp;후&amp;nbsp;간단하고&amp;nbsp;정석적인&amp;nbsp;데이터베이스를&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;/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;실제&amp;nbsp;Database&amp;nbsp;구현&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;/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;database 모듈 추가 및 기본적인 데이터베이스 구현&lt;/li&gt;
&lt;li&gt;.gitignore 업데이트&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;/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;a href=&quot;https://github.com/Kanmanemone/swemo/commit/48c5b339710ab97d744c2574a446ee75beeab283&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub] 이 작업의 Commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/android/nowinandroid/tree/main/core/database&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub]&amp;nbsp;nowinandroid&amp;nbsp;의&amp;nbsp;database&amp;nbsp;모듈&lt;/a&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;#2-6 Iteration 4-6: 내부&amp;nbsp;데이터베이스와&amp;nbsp;연동&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Iteration 4-5에서 만든 데이터베이스를 사용한다.&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;/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;메모&amp;nbsp;추가&amp;nbsp;기능&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;/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;FakeMemoRepository &amp;rarr; FakeMemoRepositoryImpl로 이름 변경&lt;/li&gt;
&lt;li&gt;database 모듈을 의존하는 MemoRepositoryImpl 구현&lt;/li&gt;
&lt;li&gt;MemoViewModel에 FakeMemoRepositoryImpl 대신 MemoRepositoryImpl 주입&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;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2833&quot; data-origin-height=&quot;1948&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OssLv/dJMcadhb16r/vP69oKE4kWsPoGkwrbynVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OssLv/dJMcadhb16r/vP69oKE4kWsPoGkwrbynVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OssLv/dJMcadhb16r/vP69oKE4kWsPoGkwrbynVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOssLv%2FdJMcadhb16r%2FvP69oKE4kWsPoGkwrbynVK%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;2833&quot; height=&quot;1948&quot; data-origin-width=&quot;2833&quot; data-origin-height=&quot;1948&quot;/&gt;&lt;/span&gt;&lt;/figure&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;/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;a href=&quot;https://github.com/Kanmanemone/swemo/commit/9a4ed38ee26a5fa9ebad0a3fee866af488868915&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub] 이 작업의 Commit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발 일지  /Swemo</category>
      <author>interfacer_han</author>
      <guid isPermaLink="true">https://kenel.tistory.com/398</guid>
      <comments>https://kenel.tistory.com/398#entry398comment</comments>
      <pubDate>Wed, 1 Apr 2026 14:32:40 +0900</pubDate>
    </item>
    <item>
      <title>AI 혁신 뒤에 남는 것</title>
      <link>https://kenel.tistory.com/396</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;#1 혁신 뒤에 남는 것&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 혁신은 공통으로 하나의 일을 해왔다. 바로, &lt;b&gt;'미련한 짓'의 범위&lt;/b&gt;를 늘려온 것이다. 혁신이 일어나면 새로운 능력이 생기는 것과 동시에, 예전엔 당연했던 일부 행동이 비합리적 선택으로 변모한다. &lt;b&gt;혁신 뒤에 남는 것은, 버려야 할 과거의 잔재다.&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;엑셀 등장 이후, 수기로 장부 쓰기는 미련한 일이 되었다.&lt;/li&gt;
&lt;li&gt;검색엔진 등장 이후 백과사전을 뒤지는 행위도 마찬가지다.&lt;/li&gt;
&lt;li&gt;내비게이션 등장 이후, 종이지도를 펴는 일 역시 (특별한 경우를 제외하면) 거의 사라졌다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;따라서 중요한 질문은 이것이다: AI 혁신이 이뤄진 지금, &lt;b&gt;무엇이 미련한 짓&lt;/b&gt;인가?&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#2 AI 혁신 뒤에 남는 것은...&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-1 초안&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 어떤 분야든, 준전문가 수준의 초안을 즉시 만들어 볼 수 있다. 따라서 빈 화면에서 &lt;b&gt;모든 것을 처음부터&lt;/b&gt; 작성하려는 시도는 미련한 짓이 된다.&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-2 반복&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 프로그래밍에서 그렇다. &lt;b&gt;반복되는 패턴을 직접 타이핑&lt;/b&gt;하고, 구조를 매번 처음부터 세우고, 기계적으로 구현을 반복하는 일은 자기 학대나 다름이 없다. 그래도 개발자가 집중해야 할 것은 여전히 남아 있으며, 그중 일부는 아래와 같다.&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그램 구조 결정&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Trade-off&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;트레이드-오프&lt;/a&gt; 판단&lt;/li&gt;
&lt;li&gt;사용자(인간) 행동에 대한 통찰&lt;/li&gt;
&lt;li&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;#2-3 지식 학습&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과거에는 경험을 쌓아야만 알 수 있는 것들이 많았다. 이제는 비교, 요약, 대안 검토, 가정의 검증이 거의 즉시 가능하다. &lt;b&gt;단순 반복을 통한 축적&lt;/b&gt;은 점점 학습이라기보다 자동화로 대체될 작업에 가까워지고 있다.&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-4 직관 (암산)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI의 가장 큰 특징은 정답을 잘 맞히는 것이 아니라, 대안을 거의 무한히 만들어낼 수 있다는 점이다. 따라서 &lt;b&gt;하나의 직관만 믿고 단일한 설계를 고집하는 태도&lt;/b&gt;는 미련하다. 다른 구조는 없는지, 더 나은 설계는 없는지, 이 가정이 틀렸다면 어떻게 되는지 이 질문을 하지 않는 것이 오히려 더 큰 비용이 된다. 질문하는 (거의) 동시에 AI발 초안을 받아서 직접 보고 판단 할 수 있으니 말이다. &lt;b&gt;직관(直觀)이 아닌 직관(직접 관람)&lt;/b&gt;을 하라는 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#3 결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 내가 스스로에게 던지는 질문은 이것이다. 나는 아직 무엇을 미련하게 계속하고 있는가?&lt;br /&gt;&amp;nbsp;&lt;br /&gt;인터넷 이후 세대는 인터넷을 배우지 않았다. 그냥 썼다. 엑셀도 마찬가지다. 익히기 위해 사용한 것이 아니라, 필요해서 쓰다 보니 익숙해졌다. AI도 결국 같은 종류의 도구가 될 것이다. 나는 AI를 '이해'하려고 하지 않을 것이다. AI를 '잘' 쓰는 사람이 되려고도 하지 않을 것이다. 대신 AI 때문에 &lt;b&gt;더 이상 할 필요가 없는 일을 버리는 사람&lt;/b&gt;이 될 것이다. 아마, 혁신 뒤에 남는 차이는 결국 그것뿐일 테다.&lt;/p&gt;</description>
      <category>개발 일지  /AI</category>
      <author>interfacer_han</author>
      <guid isPermaLink="true">https://kenel.tistory.com/396</guid>
      <comments>https://kenel.tistory.com/396#entry396comment</comments>
      <pubDate>Wed, 18 Feb 2026 09:34:14 +0900</pubDate>
    </item>
    <item>
      <title>Swemo - Iteration 3: 메모 화면의 State &amp;amp; Event 체계 정리</title>
      <link>https://kenel.tistory.com/395</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;#1 개발 목표 (Iteration Goal)&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#1-1 이상(Ideal)과 징검다리&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이상(Ideal)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;Iteration 3: 메모&amp;nbsp;화면의&amp;nbsp;State&amp;nbsp;&amp;amp;&amp;nbsp;Event&amp;nbsp;체계&amp;nbsp;정리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 구현한 UI는 일종의 뼈대에 불과했다. 이 뼈대에 붙일만한 '살'이란, 사용자 행동에 의한 상호작용(Event) 그리고 상태(State)의 변화다. 앱에서 사용자에게 제공할 '직관적인 행동'이 무엇인지를 정의하고, (좋은 방향으로) 업데이트 해나가야 한다.&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;#1-2 개발 범위&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이번&amp;nbsp;개발&amp;nbsp;범위&amp;nbsp;(In&amp;nbsp;Scope)&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;State down / Event up 구조 확립
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Screen은 ViewModel을 몰라야 함&lt;/li&gt;
&lt;li&gt;ViewModel은 Compose State를 몰라야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ViewModel 구현
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ViewModel 보유할 State와 UI 단에서 보유할 State (DrawerState 등)를 구분&lt;/li&gt;
&lt;li&gt;&lt;s&gt;이벤트 발생에 따른 State 업데이트를 위한 onEvent() 함수 보유&lt;/s&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전체 코드의 평균 가독성이 저해되기에 진행하지 않음 (참조:&amp;nbsp;#2-2)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MemoUiState 클래스 구현&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ViewModel에서 관리할 모든 State를 Wrapping 한 클래스&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;s&gt;MemoEvent 클래스&amp;nbsp;구현&lt;/s&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;s&gt;Event&amp;nbsp;sealed&amp;nbsp;interface&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;전체 코드의 평균 가독성이 저해되기에 진행하지 않음 (참조:&amp;nbsp;#2-2)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MemoScreen 업데이트
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;매개변수로 State 및 Event만 받도록 업데이트&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&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;범위&amp;nbsp;외&amp;nbsp;(Out&amp;nbsp;of&amp;nbsp;Scope)&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;Data layer 관련&lt;/li&gt;
&lt;li&gt;IME, focus, scroll 관련&lt;/li&gt;
&lt;li&gt;UI 다듬기&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;애니메이션&lt;/li&gt;
&lt;li&gt;세부&amp;nbsp;레이아웃&amp;nbsp;미세조정&lt;/li&gt;
&lt;li&gt;디자인&amp;nbsp;개선&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;성능(최적화) 관련&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;derivedStateOf&amp;nbsp;최적화&lt;/li&gt;
&lt;li&gt;recomposition&amp;nbsp;분석&lt;/li&gt;
&lt;li&gt;snapshotFlow&amp;nbsp;사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#2 변경 내역 (커밋 목록)&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-1 Iteration 3-1: ViewModel 도입 및 State 정리&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Swemo의 MemoScreen에는 MemoEditor가 존재하고, 이 컴포넌트에서 (앞으로의 구현에서) 꽤 복잡한 State 및 Event가 존재할 터다.&lt;/p&gt;
&lt;pre id=&quot;code_1772173086671&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;data class MemoUiState(
    val categories: List&amp;lt;Category&amp;gt; = emptyList(),
    val selectedCategory: Category? = null,
    val memos: List&amp;lt;Memo&amp;gt; = emptyList(),
    val allLabels: Set&amp;lt;String&amp;gt; = emptySet(),
    val editorState: EditorState = EditorState()
) {
    data class EditorState(
        val isVisible: Boolean = false,
        val editingMemo: Memo? = null
    )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서, MemoUiState 속에 inner class로 EditorState를 (별도로 분리해) 선언했다.&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;의존성 관리를 위해 Hilt 등의 라이브러리들을 추가했고, 마무리로 &lt;a href=&quot;https://kenel.tistory.com/358&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이 스크립트&lt;/a&gt;를 통해서 Now in Android와 버전 카탈로그에서의 프로터피명을 맞춰주었다.&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;/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;State&amp;nbsp;down&amp;nbsp;/&amp;nbsp;Event&amp;nbsp;up&amp;nbsp;구조&amp;nbsp;확립&lt;/li&gt;
&lt;li&gt;ViewModel&amp;nbsp;구현&lt;/li&gt;
&lt;li&gt;MemoUiState&amp;nbsp;클래스&amp;nbsp;구현&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;/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;MemoViewModel&amp;nbsp;도입&amp;nbsp;(의존성&amp;nbsp;주입은&amp;nbsp;Hilt를&amp;nbsp;이용)&lt;/li&gt;
&lt;li&gt;MemoUiState로&amp;nbsp;MemoScreen의&amp;nbsp;모든&amp;nbsp;State를&amp;nbsp;객체&amp;nbsp;하나로&amp;nbsp;통합(Wrapping)&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;/b&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MemoScreen 매개변수에 들어갈 람다 함수를&amp;nbsp;&lt;a href=&quot;https://kotlinlang.org/docs/reflection.html#callable-references&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;함수 참조(Callable Reference)&lt;/a&gt;로 표기해 봤다. 가독성 면에서 훨씬 나았다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&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;/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;a href=&quot;https://github.com/Kanmanemone/swemo/commit/ec0dafa2e73482c03fe3e9172bff70abe8b5d71c&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub] 이 작업의 Commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kenel.tistory.com/373&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Tistory] Gradle, 버전 카탈로그&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kenel.tistory.com/358&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Tistory] 내 프로젝트와 Now in Android의 버전 카탈로그 속 프로퍼티명 맞추기&lt;/a&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;#2-2 Iteration 3-2: Event 관리를 위한 구조 설계&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#2-1에 맞춰, &lt;a href=&quot;https://kenel.tistory.com/192#4-2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;예전에 배운 방식&lt;/a&gt;대로 MemoEvent를 만들어서 Event 관리를 하려고 했다.&lt;/p&gt;
&lt;pre id=&quot;code_1772415264192&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 추가하려고 했던 코드

sealed interface MemoEvent {
    data class SelectCategory(val category: Category) : MemoEvent
    data class AddMemo(val memo: Memo?) : MemoEvent
    data class ChangeAddCategoryDialogVisibility(val visible: Boolean) : MemoEvent

    sealed interface MemoEditor : MemoEvent {
        data object ToggleVisibility : MemoEditor
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 Event를 sealed interface로 묶는 것이 보기에는 통합성 있어 보인다. 이후 MemoViewModel에 fun onEvent(event: MemoEvent)를 선언해서 MemoScreen으로부터 Event를 받는 방식으로 바꾸려 했다. 하지만 실제 프로젝트에 적용해 보니 문제가 발생했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1772415341959&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// in MemoScreen.kt

ModalNavigationDrawer(
    ...
    drawerContent = {
        CategorySelector(
            ...
            onAddCategoryButtonClick = {
//              onAddCategoryDialogVisibilityChange(true)
                onEvent(MemoEvent.ChangeAddCategoryDialogVisibility(true)) // 복잡해졌다
            }
        )
    }
)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주석 처리된 코드가 원래 코드인데, 그 아래 코드와 같이 가독성이 나쁜 코드로 바꿔주어야 했기 때문이다. 따라서, 나중에 Event가 정말 많이 복잡해져서 집중 관리를 해줘야 할 필요가 생기기 전까지는 (MemoEvent 등으로) Event들을 묶지 않기로 했다.&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;결론적으로 이번 커밋에선, 아직 MemoScreen에 남아있던 이벤트 선언부들을 ViewModel로 올리고 코드를 약간 다듬는 정도로 마무리했다.&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;/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;State&amp;nbsp;down&amp;nbsp;/&amp;nbsp;Event&amp;nbsp;up&amp;nbsp;구조&amp;nbsp;확립&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;/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;MemoScreen에 남아있던 이벤트 선언부들을 ViewModel로 올림&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;코드 스니펫 - MemoScreen 호출부&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1766585027758&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;MemoScreen(
    uiState = uiState,
    drawerState = drawerState,
    // events
    onCategorySelected = viewModel::selectCategory,
    onAddMemoClick = { viewModel.addMemo() },
    onMemoEditorToggleButtonClick = viewModel::toggleEditorVisibility,
    onAddCategoryDialogVisibilityChange = viewModel::changeAddCategoryDialogVisibility,
)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Event가 하나 추가될 때마다 람다 함수 매개변수가 하나씩 늘어날 것이다. MemoEvent 및 MemoViewModel.onEvent()가 있었다면, 모든 이벤트 람다 함수를 onEvent = viewModel::onEvent 로 퉁칠 수 있었을 것이다. 하지만 이런 이득보다, 다른 부분에서 발생하는 가독성적인 손실이 더 클 것이다.&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;/b&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;당연하게도, &lt;a href=&quot;https://kotlinlang.org/docs/reflection.html#callable-references&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;함수 참조(Callable Reference)&lt;/a&gt;는 매개변수가 없을 때만 쓸 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&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;/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;a href=&quot;https://github.com/Kanmanemone/swemo/commit/05fe55b9f80d37fa0e40248d3c18cb52d778638e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GitHub] 이 작업의 Commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kenel.tistory.com/192&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Tistory] [Android] Jetpack Compose - 객체 지향적 UI 레이어 설계&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#3 개발 결과 (Iteration Outcome)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MemoScreen을&amp;nbsp;State&amp;nbsp;down&amp;nbsp;/&amp;nbsp;Event&amp;nbsp;up&amp;nbsp;구조로&amp;nbsp;전환하고,&amp;nbsp;ViewModel&amp;nbsp;도입으로&amp;nbsp;UI가&amp;nbsp;ViewModel의&amp;nbsp;상태에&amp;nbsp;의존하게&amp;nbsp;만들었다.&amp;nbsp;이벤트의&amp;nbsp;추상화(MemoEvent)도&amp;nbsp;검토했지만,&amp;nbsp;가독성을&amp;nbsp;해하기에&amp;nbsp;일단&amp;nbsp;보류했다.&lt;/p&gt;</description>
      <category>개발 일지  /Swemo</category>
      <author>interfacer_han</author>
      <guid isPermaLink="true">https://kenel.tistory.com/395</guid>
      <comments>https://kenel.tistory.com/395#entry395comment</comments>
      <pubDate>Sun, 8 Feb 2026 20:01:32 +0900</pubDate>
    </item>
    <item>
      <title>최소한의 행동경제학 - 행복</title>
      <link>https://kenel.tistory.com/355</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;#1 개요&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;모든 선택에는 심리적 가격표가 붙어 있다.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;책 '&lt;/span&gt;&lt;a style=&quot;color: #3d62ce; text-align: start;&quot; href=&quot;https://kenel.tistory.com/349&quot;&gt;최소한의 행동경제학&lt;/a&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;'의 여섯 번째 장.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#2 책 요약&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-1 손실회피&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;'100%로 5만원 얻기'와 '50%로 100만원 얻고 50%로 50만원 잃기'의 이지선다가 있다. 기댓값만 보자면 '5만원 vs 25만원'이다. 하지만 대부분의 사람은 전자를 고른다. &lt;b&gt;얻게 될 때의 기쁨보다, 잃게 될 때의 고통을 더 크게 느끼기&lt;/b&gt; 때문이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-2 부킹 프라이스*&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 부킹 프라이스&lt;sup&gt;booking price&lt;/sup&gt;: 자신이 &lt;b&gt;행복을 느끼는 데 필요한 최소한의 가격 또는 가치.&lt;/b&gt; 마음의 장부에 기록(booking)해두는 가격이라는 뜻.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;환심을 사기 위해선 큰 선물보단 여러 번의 작은 선물이 좋다. 그렇다고 모래알처럼 작은 선물은 안 된다. 부킹 프라이스는 충족하는 선에서 쪼개라. 자신에게도 적용할 수 있다. '&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%86%8C%ED%99%95%ED%96%89&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;소확행&lt;/a&gt;' 아니, &lt;b&gt;'부확행'을 자주 느끼는 인생 전략&lt;/b&gt;을 짜는 것이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-3 보유 효과&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;우리 뇌는 소유한 것을 (타인에게) 넘기는 걸 손실로 여기고 회피한다. 이 때문에 사람들은 물건이나 권력, 지위 등을 한 번 손에 넣게 되면 &lt;b&gt;그걸 가지고 있지 않았을 때보다 훨씬 높게 평가&lt;/b&gt;한다. 제품의 경우 &quot;7일 이내 무조건 환불&quot;, 구독형 서비스의 경우 &quot;처음 한 달 무료&quot;와 같은 홍보 문구는 상품에 대한 판매자의 자신감을 내비침과 동시에, 소비자의 보유 효과를 이용하는 것이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-4 결제와 소비의 디커플링&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;현금결제처럼 상품을 소비하는 시점과 비용을 지불하는 시점이 동시에 이루어지는 것을 '소비와 지불이 커플링(Copling)'되어 있다고 한다. '식권 30장 미리 구매'처럼 지불을 미리 하거나, 신용카드 결제처럼 나중에 하는 경우는 '소비와 지불이 디커플링(Decoupling)'되어 있다고 한다.&lt;br /&gt;&lt;br /&gt;소비와 지불이 커플링 되어있을 때는 &lt;b&gt;지불의 고통&lt;/b&gt;이 커진다. 그래서 소비를 절제하게 되지만, 그만큼 실제 소비 시의 만족감이 떨어진다. 지불의 고통은 현금 &amp;rarr; 체크카드 &amp;rarr; 신용카드 순으로 작아진다. 즉, 이 순서는 디커플링된 정도의 순서기도 하다. 소비와 지불이 디커플링될수록 소비하는 순간의 만족감이 높아지지만, 그만큼 씀씀이가 커지는 문제도 생긴다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-5 상향 비교&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;남의 떡&lt;/b&gt;이 더 커 보인다. 가령 SNS에서 보이는 사람들의 모습을 보면, 대부분 나보다 더 잘 사는 것만 같다. 그 모습이 '최대한 부러움을 유발하려고 일부러 가공'한 이미지라는 걸 알고 봐도 그렇다. 비교는 어제의 나 및 미래의 나와 하는 것이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-6 자율성 + 유능성 + 관계성&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;자율성(Autonomy)은 &lt;b&gt;자신의 의지에 따라 행동하고자 하는 마음&lt;/b&gt;이다. 학생으로 치면, &quot;시키는 대로 시간표대로 생활하는 게 답답하다&quot;, &quot;내가 하고 싶은 공부를 할 수 없다&quot;라는 말로 흔히 표현된다.&lt;br /&gt;&lt;br /&gt;유능성(Competence)은 &lt;b&gt;능력을 발전시키고자 하는 것&lt;/b&gt;이다. 학생으로 치면, &quot;왜 문제 풀이를 반복해서 하는지 모르겠다&quot;, &quot;내 발전에 도움이 되지 않는 것 같다&quot;라는 고민이 대표적이다.&lt;br /&gt;&lt;br /&gt;관계성(Relatedness)은 &lt;b&gt;주변 사람들과 어울리고자 하는 욕구&lt;/b&gt;다. 학생으로 치면, &quot;어떤 친구와 다퉜다&quot;, &quot;선생님 때문에 힘들다&quot;하는 식이다.&lt;br /&gt;&lt;br /&gt;3가지를 고려해서 &lt;b&gt;직업&lt;/b&gt;을 선택하라. 개인의 스타일을 존중해주는 널널한 회사에 가거나, 창업을 택할 수도 있다. 내가 잘하고 좋아하는 일을 택하라. 마지막으로 좋은 사람들이 모인 곳을 택하라.&lt;/blockquote&gt;</description>
      <category>책  /최소한의 행동경제학</category>
      <author>interfacer_han</author>
      <guid isPermaLink="true">https://kenel.tistory.com/355</guid>
      <comments>https://kenel.tistory.com/355#entry355comment</comments>
      <pubDate>Fri, 6 Feb 2026 15:22:10 +0900</pubDate>
    </item>
    <item>
      <title>최소한의 행동경제학 - 돈</title>
      <link>https://kenel.tistory.com/354</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;#1 개요&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;사람들은 반드시 필요해서 물건을 사는 것이 아니라, 자신이 원하는 것을 구매한다.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;책 '&lt;/span&gt;&lt;a style=&quot;color: #3d62ce; text-align: start;&quot; href=&quot;https://kenel.tistory.com/349&quot;&gt;최소한의 행동경제학&lt;/a&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;'의 다섯 번째 장.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#2 책 요약&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-1 심적 회계&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;비상금은 쓰기 싫다. 지금 당장 비상금을 쓰고 나중에 메우는 게 합리적인 경우에도 말이다. &lt;b&gt;같은 돈인데, 같지 않다.&lt;/b&gt; 용돈과 내가 직접 번 돈의 무게가 다른 것도 같은 맥락이다. 심적 회계는 우리가 마음속에서 돈을 &lt;b&gt;여러 개의 통(식비, 문화비, 교육비, 예금 등)&lt;/b&gt;에 나눠 담는다는 의미다.&lt;br /&gt;&lt;br /&gt;심적 회계는 합리적 의사결정을 방해하지만, 잘 이용하면 합리적 의사결정을 촉진하는 도구로 쓸 수도 있다. 첫째로, 돈이 드는 목표마다 '돈통'을 만들어두고 조금씩 저축하는 것이다. 둘째로, 공돈을 심적 회계에 포함하는 것이다. 우연히 받은 용돈을 막 쓰게 되는 건 심적 회계에 없던 공돈으로 취급되기 때문인데, 이 현상을 방지할 수 있다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-2 비인지능력&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;키가 큰 사람일수록 돈을 잘 번다는 연구 결과가 있다. 정확히는, 15~16세에 또래보다 키가 컸던 사람들의 평균 소득이 높은 것이라 한다. 뒤늦게 폭발적으로 큰 사람들은 작은 사람들과 다르지 않았다. 사실, 키는 직접 요인도 아니었다. &lt;br /&gt;&lt;br /&gt;이유는 바로 키가 큰 학생일수록 육체적 자신감이 있고, 그래서 성장기에 할만한 사회 활동(학생회, 동아리, 봉사 등)을 더 적극적으로 참여하기 때문이다. 그때 길러진 사회성(&amp;sub; 비인지능력)이 죽을 때까지(!) 긍정적 영향을 준 것이다. 그러니, 키가 작다고 위축된 자녀가 있다면 응원해 주어야 한다. &lt;b&gt;중요한 건 키가 아니라 다양한 사회 경험&lt;/b&gt;이니까.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-3 프레이밍 효과&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;열쇠공 A는 1분 만에 샥하고 잠긴 문을 열었다. 열쇠공 B는 더운 여름날 2시간 동안 땀을 뻘뻘 흘리며 간신히 잠긴 문을 열었다. 어느 쪽이든 비용은 4만 원으로 같다. A 쪽 또는 B 쪽의 비용을 싸다고 느낄 수도 있고 비싸다고 느낄 수도 있다. &lt;b&gt;어느 기준ㆍ틀(프레임)인지에 따라&lt;/b&gt;서 말이다.&lt;br /&gt;&lt;br /&gt;위의 사례에 적용해 볼 수 있는 2가지 프레임&lt;br /&gt;- 일의 가치(비용)란, 상황의 신속한 해결이다.&lt;br /&gt;- 일의 가치(비용)란, 내 눈앞에서 보인 노력과 시간이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-4 사회적자본&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;식당의 &lt;b&gt;별점은 식당의 자산&lt;/b&gt;(자본)이다. 사회적으로(사람의 평가로) 형성되었기에 사회적자본이라 부른다. 자본이기에 안전성(신뢰성)도 존재하는데, 이는 주로 별점을 부여할 수 있는 플랫폼(에어비앤비, 네이버 지도, 당근마켓 등)을 얼마나 신뢰하는지에 달린다.&lt;br /&gt;&lt;br /&gt;그렇다면 이렇게 말할 수도 있다: 특정 플랫폼ㆍ&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EB%B8%8C%EB%9E%9C%EB%93%9C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;브랜드&lt;/a&gt;에 대한 &lt;b&gt;'신뢰' 그 자체 또한 회사의 자산&lt;/b&gt;(자본)이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;#2-5 인적 네트워크&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;단어 자체는 인간관계를 뜻하나, 말하고자 하는 바는 면식이 옅은 사람(느슨한 관계인 사람)의 중요성이다. &lt;b&gt;친하지 않은 사람일수록 내가 접하지 못한 정보를 가지고 있을 가능성&lt;/b&gt;이 높기 때문이다. 그 정보로 일자리를 구하거나 자신이 하는 일에 대한 도움을 받을 수 있다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-6 휴리스틱*&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 휴리스틱&lt;sup&gt;heuristic&lt;/sup&gt;: 시간이 부족하거나 정보가 불충분할 때 &lt;b&gt;합리적인 판단 대신 경험에 기반&lt;/b&gt;해 빠르고 쉽게 내리는 어림짐작(추론).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;** 편익&lt;sup&gt;benefit&lt;/sup&gt;: 어떤 선택을 함으로써 얻게 되는 이익이나 만족감.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*** 기회비용&lt;sup&gt;opportunity cost&lt;/sup&gt;: ↖ 그 선택으로 인해 포기되는 것의 가치.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;비 오는 날엔 유독 택시 잡기가 힘들다. 왜? &quot;날씨가 안 좋을수록 사람들이 택시를 많이 이용하니까&quot;라는 대답은 하수다. 정확히는 '택시 기사들이 돈을 많이 벌어서'다. 택시 기사는 본인이 정한 하루 매출 목표금액을 달성하면 퇴근하는 경우가 많다고 한다. 비가 오면 목표금액을 빨리 달성하니 퇴근 시간도 빨라지는 것이다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;익숙히 하던 대로&lt;/b&gt;(= 휴리스틱), 목표금액 달성 시 퇴근을 해버리는 전략은 돈벌이 면에서 합리적이지 않다. 비 오는 날처럼 손님이 많은 날일수록, 빠른 퇴근에 의한 편익**보다 기회비용***이 크기 때문이다.&lt;/blockquote&gt;</description>
      <category>책  /최소한의 행동경제학</category>
      <author>interfacer_han</author>
      <guid isPermaLink="true">https://kenel.tistory.com/354</guid>
      <comments>https://kenel.tistory.com/354#entry354comment</comments>
      <pubDate>Fri, 6 Feb 2026 15:17:44 +0900</pubDate>
    </item>
    <item>
      <title>최소한의 행동경제학 - 선택</title>
      <link>https://kenel.tistory.com/353</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;#1 개요&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;결정의 순간에, 사람들은 논리보다 직관에 의존한다.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;책 '&lt;/span&gt;&lt;a href=&quot;https://kenel.tistory.com/349&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;최소한의 행동경제학&lt;/a&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;'의 네 번째 장.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#2 책 요약&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-1 앵커링 효과&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;'&lt;b&gt;1만 원&lt;/b&gt;짜리 옷'과 '&lt;b&gt;2만 원&lt;/b&gt;에서 50% 할인된 1만 원짜리 옷'은 같은 가격임에도, 자아내는 분위기가 분명 다르다. 고객이 처음 접한(인식한) 숫자(1만 원 vs 2만 원)가 다르기 때문이다. 고객은 후자의 옷을 더 좋은 것으로 판단할 가능성이 높다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;처음 접한 숫자&lt;/b&gt;는 마치 우리 뇌에 내리는 배의 닻(앵커&lt;sup&gt;Anchor&lt;/sup&gt;)과 같아서, '기준'으로서 뇌리에 각인된다. 가령 음식점에서 가장 비싼 메뉴, 의류 가게에서 가장 비싼 옷은 다른 메뉴나 옷의 가격을 상대적으로 싸게 느끼게 만드는 앵커다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;셀프 앵커링 효과도 존재한다. 예를 들어 특정 브랜드의 패딩이 비싸 보여도, 그걸 한 번 사서 입고 나면 그게 기준(앵커)이 되어버린다. 나중에 패딩이 낡아 새로 패딩을 사려고 하면, 앵커를 박아놓은 (비싼) 가격대의 패딩을 다시 사게 될 확률이 높다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플 특유의 폐쇄적인 생태계는 셀프 앵커링 효과를 유발한다. Windows나 Android 등 다른 생태계에 대한 호환성이 미비한 iOS에 한 번이라도 발을 들이면 빠져나가기 힘들다.&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;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비싸다/싸다를 판단하는 기준이라는 점은 같지만, 서로 다른 효과다. 앵커링&amp;nbsp;효과가&amp;nbsp;'외부에서&amp;nbsp;주입된&amp;nbsp;숫자가&amp;nbsp;즉각적으로&amp;nbsp;판단을&amp;nbsp;왜곡하는&amp;nbsp;현상'이라면,&amp;nbsp;준거&amp;nbsp;가격(#2-6)은&amp;nbsp;'소비자에게&amp;nbsp;축적된&amp;nbsp;경험에서&amp;nbsp;형성된&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;#2-2 왝더독&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;공짜 아이스크림을 위해 비 오는 날 긴 대기 줄을 기다리는 건 합리적일까? 웩더독은 개(dog)의 꼬리가 몸통을 흔드는(wag) 현상을 말한다. 기업들은 소비자들로 하여금, &lt;b&gt;몸통은 보이지 않게 꼬리는 집중하게&lt;/b&gt; 만든다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;#2-3 매몰 비용&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;뷔페는 대부분 비싸다. 그래서 &quot;본전은 뽑아야지&quot;라는 생각으로 무심코 과식하게 된다. 이미 지불한(매몰된) 가격이 &lt;b&gt;아깝다는 이유로, 스스로 손해&lt;/b&gt;를 입는 것이다. 물이 엎질러지지 않게 주의하되, 이미 엎질러졌다면 깨끗하게 포기하자.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-4 대조 효과&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;500만 원짜리 가죽시트는 비싼 것 같지만, 1억 원짜리 차의 500만 원짜리 가죽시트 옵션은 뭔가 그럴듯하다. '의자시트 하나에 500만 원이나 하는 절대 수치'라는 기준이, '자동차 가격의 5%밖에 안 되는 상대 수치'로 옮겨갔기 때문이다. 같은 값이어도 &lt;b&gt;무슨 기준이냐에 따라 반응이 달라진다.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;거의 같은 사례로, 사치품 매장은 입구 쪽에 초고가 제품을 전시하곤 한다. 해당 초고가 제품이 아닌 제품들이 비교적 싸게 느껴지도록 만들기 위함이다. '비싼 제품'이라는 인식이 '그나마 싼 제품'으로 바뀐다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;비슷한 효과 - 미끼 효과&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대조&amp;nbsp;효과가&amp;nbsp;'비교&amp;nbsp;&lt;b&gt;기준&lt;/b&gt;의 변화'로 목표(Target)의 가치나 매력을 왜곡시키는 전략이라면, &lt;a href=&quot;https://kenel.tistory.com/351#2-3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;미끼&amp;nbsp;효과&lt;/a&gt;는&amp;nbsp;목표보다&amp;nbsp;'&lt;b&gt;열등&lt;/b&gt;한&amp;nbsp;선택지'의&amp;nbsp;추가로&amp;nbsp;목표의&amp;nbsp;상대적&amp;nbsp;우위를&amp;nbsp;높이는&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;#2-5 한정된 인지적 자원*&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 인지적 자원&lt;sup&gt;cognitive resources&lt;/sup&gt;: 사람들이 작업을 수행하고 정보를 처리하는 데 필요한 &lt;b&gt;정신적인 의미의 자원.&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;모든 '자원'이 그렇듯, 인지적 자원 또한 무한하지 않다. 우울하거나 힘들 때는 감정 관리 때문에 인지적 자원이 더 쉽게 동난다. 합리적인 사고는 (인지적 자원에 기반한) 인지적 노력의 결과인데, 이 말은 &lt;b&gt;자원이 결핍되면 합리적 사고가 줄어들어&lt;/b&gt; 충동적으로 행동하게 된다는 것이다. 이것이 우울하거나 힘들 때 과소비가 발생하는 원리다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-6 준거가격*&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 준거가격&lt;sup&gt;reference price&lt;/sup&gt;: 기준이 되는 최초의 가격 (정상가).&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;준거가격은 &lt;b&gt;이른바 '국룰' 가격&lt;/b&gt;이다. 가령 PC방 요금의 국룰은 15년 넘게 '시간 당 1000원'을 유지하고 있다. 사람들에게 형성된 국룰 가격보다 낮은 가격은, '사면 이득'이라는 심리를 불러일으킨다. 그래서 필요없는 소비가 조장된다. 이는 비합리적 소비임에도, &quot;싸게 잘 샀다&quot;라며 자기합리화하게 만든다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;반대로 준거가격에 비해 비싼 값을 소비자가 기꺼이 지불할 때도 있다. 축제 부스에 있는 음식이나 영화관에서 파는 생수의 가격을 떠올려보라. 그 장소에서 사야 의미가 있는 물건들이기에 우리는 웃돈을 주고 구매하는 것이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;붕어빵 가격의 요즘 국룰은 '1000원에 2개' 정도다 (1000원에 3개 시절은 이제 끝이 났다). 나의 경우 길을 걷다가 1000원에 3개 붕어빵을 파는 곳을 발견한다면, 배가 불러도 살 것 같다. 물건(붕어빵)이 아닌, 소비 그 자체를 위한 소비를 위해서.&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;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비싸다/싸다를&amp;nbsp;판단하는&amp;nbsp;기준이라는&amp;nbsp;점은&amp;nbsp;같지만,&amp;nbsp;서로&amp;nbsp;다른&amp;nbsp;효과다.&amp;nbsp;준거 가격이 '소비자에게 축적된 경험에서 형성된 가격'이라면, 앵커링 효과(#2-1)는 '외부에서&amp;nbsp;주입된&amp;nbsp;숫자가&amp;nbsp;즉각적으로&amp;nbsp;판단을&amp;nbsp;왜곡하는&amp;nbsp;현상'이다.&lt;/p&gt;</description>
      <category>책  /최소한의 행동경제학</category>
      <author>interfacer_han</author>
      <guid isPermaLink="true">https://kenel.tistory.com/353</guid>
      <comments>https://kenel.tistory.com/353#entry353comment</comments>
      <pubDate>Fri, 6 Feb 2026 15:05:10 +0900</pubDate>
    </item>
    <item>
      <title>최소한의 행동경제학 - 목표</title>
      <link>https://kenel.tistory.com/352</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;#1 개요&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;사람들은 선택의 자유를 좋아하지만, 너무 많은 선택은 결정을 어렵게 만든다.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;책 '&lt;/span&gt;&lt;a href=&quot;https://kenel.tistory.com/349&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;최소한의 행동경제학&lt;/a&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;'의 세 번째 장.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#2 책 요약&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-1 순서 효과&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;상대 평가를 잘하려면 표본이 많이 필요하다. 그래서 심사 위원은 먼저 나오는 사람들에게는 높은 점수를 주지 않으려는 경향이 있다. 따라서 &lt;b&gt;발표든&amp;nbsp;면접이든&amp;nbsp;순서상&amp;nbsp;나중에&amp;nbsp;하는&amp;nbsp;게&amp;nbsp;더&amp;nbsp;좋다.&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-2 자기 절제 도구&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;데드라인&lt;/b&gt;이 중요하다는 사실은 이미 유명하다. 과제의 마감 시간을 잘게 나눠라. 이때, 나누는 주체는 (타인이 아닌) 본인일 때 더 좋다. 그래야 자신의 능력에 맞게 과제와 시간을 소분할 수 있고, 계획이 틀어지더라도 수월하게 통제할 수 있기 때문이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-3 자이가르닉 효과&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;드라마ㆍ웹툰은 다음 내용이 궁금해지는 시점에서 끊음으로써, 시청자의 탄식을 자아낸다. 찜찜해진 시청자는 빨리 다음 내용이 나오길 고대한다. '미완성 효과'로도 불린다. 또, '일단 시작하라' 효과라고도 부를 수 있겠다. &lt;b&gt;시작하는 순간부터 '완성' 전까지는&lt;/b&gt; '미완성' 상태가 유지되므로.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;#2-4 상태 의존 기억&amp;nbsp;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;우리는 시험에 대비하기 위해 모의고사를 치른다. 시험과 같은 환경에서 연습하기 위함이다. 이렇듯, &lt;b&gt;학습한 환경&lt;/b&gt;은 기억에 영향을 준다. &quot;내가 뭘 하려고 했더라?&quot;라는 의문을 해결하는 가장 강력한 방법을 우린 모두 경험적으로 알고 있다. 바로 조금 전까지 있었던 장소나 행했던 행동을 다시 복기하는 것이다. 시험을 치를 장소에 미리 가보자. 내가 발표할 장소에 가서 리허설을 해보자.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-5 공개 선언 효과&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;누구나 타인에게 인정받고 싶은 욕구를 지니고 있다. 그렇다면 당연히, 지키지도 못할 말을 하는 &lt;b&gt;가벼운 사람으로도 보이기 싫을 것&lt;/b&gt;이다. 다른 사람들 앞에서 나의 목표를 공개적으로 선언해 보자. 우리는 의식ㆍ무의식적으로 해당 목표를 더 열심히 챙기게 된다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-6 부화 효과&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;창의적인 문제 해결을 원한다면, 업무 중 적절한 휴식을 취해주어야 한다. 원리는 '망각'이다. 쉬는 동안 특정 해결법에 매몰되었던 나의 의식이 초기화(망각)되고, &lt;b&gt;의식이 쉬는 동안 무의식&lt;/b&gt;은 새로운 해결법을 떠올려 내게 알려준다.&lt;/blockquote&gt;</description>
      <category>책  /최소한의 행동경제학</category>
      <author>interfacer_han</author>
      <guid isPermaLink="true">https://kenel.tistory.com/352</guid>
      <comments>https://kenel.tistory.com/352#entry352comment</comments>
      <pubDate>Fri, 6 Feb 2026 14:59:56 +0900</pubDate>
    </item>
    <item>
      <title>최소한의 행동경제학 - 대화</title>
      <link>https://kenel.tistory.com/351</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;#1 개요&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;가치는 절대적인 것이 아니라, 상대적인 기준에서 만들어진다.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;책 '&lt;/span&gt;&lt;a style=&quot;color: #3d62ce; text-align: start;&quot; href=&quot;https://kenel.tistory.com/349&quot;&gt;최소한의 행동경제학&lt;/a&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;'의 두 번째 장.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;#2 책 요약&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-1 상호성의 법칙&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;작은 선물이 동반된 부탁은 거절하기 힘들다.&lt;/b&gt; 상대방의 호의에 보답(상호)하려는 마음 때문이다. 웃긴 건, '병 주고 약 주기'도 호의로 인식한다는 점이다. 처음에는 1만원을 요구했지만, 후에 3000원 요구로 인하'해준' 상대에게, 우리는 '호의'를 느낀다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-2 사소한 칭찬의 힘&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;우리가 어린 시절에는 어른들에게 사소한 칭찬을 많이 들었다. 유년 시절이 종종 '잃어버린 천국'으로 묘사되는 이유 중 하나일 것이다. 이를 고려할 때,&lt;b&gt; 사소한 칭찬을 싫어할 사람은 없다.&lt;/b&gt; 상대방이 칭찬을 귀찮아하거나 아부를 떠는 것으로 여긴다는 인식은 오해다. 어린이들은 칭찬을 받으면 기분이 좋은 게 티가 나지만, 점점 자라면서 티를 내지 않게 된 것뿐이다. 당연하겠지만, 터무니없는 억지 칭찬은 역효과만 난다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-3 미끼 효과&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;'리그오브레전드 플래티넘 티어 플레이어'와 '오버워치 플래티넘 티어 플레이어' 둘 중 누가 더 게임을 잘하는가? 선뜻 대답하기 힘들다. 그러나 선택지에 '리그오브레전드 골드 티어 플레이어'가 추가되면, 사람들은 셋 중에서 '리그오브레전드 플래티넘 티어 플레이어'가 '오버워치 플래티넘 티어 플레이어'를 제치고 게임을 제일 잘 한다고 답한다. 상대방이 A와 B를 고민하고 있고 나는 상대방이 A를 고르길 원하는 상황이라면, A&lt;b&gt;-&lt;/b&gt;를 &lt;b&gt;추가 선택지&lt;/b&gt;로서 제시하라.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이폰 16e는 가격 대 성능비가 낮은 것으로 유명하다. 어쩌면 아이폰 16e의 포지션은, 아이폰16을 더 매력적으로 보이게 만드는 앵커가 아니었을까.&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;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미끼 효과&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;가 목표(Target)보다 '&lt;/span&gt;&lt;b&gt;열등&lt;/b&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;한 선택지'의 추가로 목표의 상대적 우위를 높이는 전략이라면, &lt;a href=&quot;https://kenel.tistory.com/353#2-4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;대조 효과&lt;/a&gt;는 '비교&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;기준&lt;/b&gt;&lt;span style=&quot;color: #222222; text-align: start;&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;#2-4 낮은 공 기법&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;배달 앱에서 식당을 고를 때, 가격이 많이 낮은 식당이 눈에 띄곤 한다. 그러나 자세히 들여다보면, 처음 봤던 가격은 갖가지 수수료가 제외된 허수아비에 불과했다는 사실을 깨닫게 된다. 사람들은 자신이 결정한 것에 일관성을 지키려는 경향이 있다. 그러니 &lt;b&gt;좋은 조건들을 먼저 제시&lt;/b&gt;해서 상대의 일관성을 만들어내는 전략은 유효하다. 단, 일회성이 짙은 전략이다. 앞서 말한 식당들이 과연 오래갈까? 나는 아니라고 본다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-5 사회적 바람직성 편향&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;어떤 질문에 대답할 때, 솔직한 자신의 선호를 숨기고 대신 &lt;b&gt;사회적으로 바람직하다고 여겨지는 쪽&lt;/b&gt;으로 답하는 경향이다. &quot;요즘 어떻게 지내냐는 친구의 말에 그랜저로 대답했습니다&quot;라는 광고 문구가 있다. 이 문구는 그랜저가 사회적으로 지니는 이미지를 '바람직(여기서는 경제적 성공)'한쪽으로 몰고 간다. 애플이 '힙'하고 '세련'된 이미지를 소비자의 뇌리에 각인하려고 기를 쓰는 것도 같은 맥락이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;#2-6 거래효용*&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 거래효용: 물건의 실제 가격과 마음속 가격의 차이에 따라 느끼는 만족감.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;실제 가치와 무관하게, &lt;b&gt;어렵게 얻었기 때문에 느껴지는 만족.&lt;/b&gt; 대기하는 줄이 긴 SNS 맛집에서 먹으면 식사의 만족도가 높아지는 이유다. 또 일부 기업들이, 판매하는 제품의 품귀 현상을 고의로 유도하는 이유다.&lt;br /&gt;&lt;br /&gt;면접관들의 단골 질문은 &quot;왜 지원했나요?&quot;다. 이때, &quot;집이랑 가까워서요.&quot;라고 대답하는 행위는 스스로 거래효용을 떨어뜨리는 것이다. 저 멀리서 힘들게 와야 하지만, 그럼에도 이 학교를 선택한 특별한 이유가 있다고 얘기하라. 이러면 면접관들의 관점에서 지원자의 거래효용이 높아져, 해당 지원자를 더 가치 있게 여기게 된다.&lt;/blockquote&gt;</description>
      <category>책  /최소한의 행동경제학</category>
      <author>interfacer_han</author>
      <guid isPermaLink="true">https://kenel.tistory.com/351</guid>
      <comments>https://kenel.tistory.com/351#entry351comment</comments>
      <pubDate>Fri, 6 Feb 2026 14:59:22 +0900</pubDate>
    </item>
  </channel>
</rss>