<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <author>
    <name>어썸블로그</name>
  </author>
  <id>국내의 좋은 블로그 글들을 매일 배달해줍니다.</id>
  <title>개발자 어썸블로그</title>
  <updated>2026-03-16T13:44:07+09:00</updated>
  <entry>
    <author>
      <name>류광</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;&lt;p&gt;오랜만에 근황 보고입니다. 

작년 12월 ["소프트웨어 아키텍처 The Basics(2판)"](/book/FoSA2) 출간 이후로 세 권의...&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://occamsrazr.net/tt/440</id>
    <link href="https://occamsrazr.net/tt/440"/>
    <summary type="html">오랜만에 근황 보고입니다. 

작년 12월 ["소프트웨어 아키텍처 The Basics(2판)"](/book/FoSA2) 출간 이후로 세 권의...</summary>
    <title>근황 - 2026-03-11 </title>
    <updated>2026-03-11T11:38:00+09:00</updated>
    <dc:date>2026-03-11T11:38:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>강진우</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;&lt;p&gt;집 근처에 작은 독립 서점이 하나 있다.  들어서면 책이 많지 않다. 대형 서점처럼 수만 권이 빼곡히 꽂혀 있는 게 아니라, 소량의 책이 한 권 한 권 골라 놓은 듯 예쁘게 진열되어 있다. 서점 주인의 취향이 그대로 드러나는 공간. 어떤 책을 좋아하는 사람인지, 어떤 이야기를 독자에게 건네고 싶은지가 선반 위에 고스란히 보인다.  작지만 멋진 곳이라고 생각&lt;img src="https://img1.kakaocdn.net/thumb/R1280x0/?fname=http%3A%2F%2Ft1.kakaocdn.net%2Fbrunch%2Fservice%2Fuser%2F3Y0%2Fimage%2FOIMW4GtbUYZh_EHwP460s9qGkbg.png" width="500"&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://brunch.co.kr/@@3Y0/83</id>
    <link href="https://brunch.co.kr/@@3Y0/83"/>
    <summary type="html">집 근처에 작은 독립 서점이 하나 있다.  들어서면 책이 많지 않다. 대형 서점처럼 수만 권이 빼곡히 꽂혀 있는 게 아니라, 소량의 책이 한 권 한 권 골라 놓은 듯 예쁘게 진열되어 있다. 서점 주인의 취향이 그대로 드러나는 공간. 어떤 책을 좋아하는 사람인지, 어떤 이야기를 독자에게 건네고 싶은지가 선반 위에 고스란히 보인다.  작지만 멋진 곳이라고 생각&lt;img src= "https://img1.kakaocdn.net/thumb/R1280x0/?fname=http%3A%2F%2Ft1.kakaocdn.net%2Fbrunch%2Fservice%2Fuser%2F3Y0%2Fimage%2FOIMW4GtbUYZh_EHwP460s9qGkbg.png" width="500" /&gt;</summary>
    <title>내가 원하는 건 서점이었지, 도서관이 아니었다</title>
    <updated>2026-03-15T20:15:08+09:00</updated>
    <dc:date>2026-03-15T20:15:08+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>강진우</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;&lt;p&gt;책을 다 읽고 나면 다음엔 뭘 읽을까 찾는 게 설레면서도 어려운 일이었다. 온라인 서점에 들어가서, 추천 도서 목록을 본다. "이번 달 MD 추천", "올해의 소설", "독자 평점 9점 이상". 그럴듯한 이름이 붙은 목록에서 괜찮아 보이는 책을 고른다. 표지를 보고, 줄거리를 읽고, 리뷰를 훑어보고. 별점 높고, 리뷰 많고, 추천 문구까지 그럴싸하면 장바구&lt;img src="https://img1.kakaocdn.net/thumb/R1280x0/?fname=http%3A%2F%2Ft1.kakaocdn.net%2Fbrunch%2Fservice%2Fuser%2F3Y0%2Fimage%2F2MLqhKqeMuYfASx6xQt11suus4k.png" width="500"&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://brunch.co.kr/@@3Y0/82</id>
    <link href="https://brunch.co.kr/@@3Y0/82"/>
    <summary type="html">책을 다 읽고 나면 다음엔 뭘 읽을까 찾는 게 설레면서도 어려운 일이었다. 온라인 서점에 들어가서, 추천 도서 목록을 본다. &amp;quot;이번 달 MD 추천&amp;quot;, &amp;quot;올해의 소설&amp;quot;, &amp;quot;독자 평점 9점 이상&amp;quot;. 그럴듯한 이름이 붙은 목록에서 괜찮아 보이는 책을 고른다. 표지를 보고, 줄거리를 읽고, 리뷰를 훑어보고. 별점 높고, 리뷰 많고, 추천 문구까지 그럴싸하면 장바구&lt;img src= "https://img1.kakaocdn.net/thumb/R1280x0/?fname=http%3A%2F%2Ft1.kakaocdn.net%2Fbrunch%2Fservice%2Fuser%2F3Y0%2Fimage%2F2MLqhKqeMuYfASx6xQt11suus4k.png" width="500" /&gt;</summary>
    <title>다들 재미있다는데, 나는 왜</title>
    <updated>2026-03-12T08:48:01+09:00</updated>
    <dc:date>2026-03-12T08:48:01+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>김재호</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;주니어 개발자는 더 이상 설 자리가 없다는 말에 너무 쫄 것 없습니다.&lt;br&gt;
IT 세상에서 불리한 사람은 언제나&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;나이 많은 사람&lt;/li&gt;
  &lt;li&gt;결혼하고 애 딸린 사람&lt;/li&gt;
  &lt;li&gt;코딩이 더 이상 재미 없어진 사람들입니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;젊음 그 자체가 엄청 강력한 무기입니다.&lt;br&gt;
불리한 세대로 태어난 게 아니라 다시 오기 힘든 좋은 기회가 놓여 있는 것 아닌가…?&lt;/p&gt;

&lt;p&gt;필요한 것은 컴퓨터 한대와 클로드 코드&lt;br&gt;
(그리고 젊음의 열정)&lt;/p&gt;

&lt;p&gt;패기있게 플레이 하면 됩니다.&lt;br&gt;
당돌하고 건방지다는 말을 들어도 뭐 괜찮습니다. 젊으면 그런 것도 용서가 되거든요.&lt;br&gt;
(고개는 어른되서 숙이면 됩니다)&lt;/p&gt;

&lt;p&gt;너무 눈치 보거나 쫄 것 없습니다.&lt;br&gt;
젊음을 무기로 방구석에서 열심히 만들어보고 사람들에게 공개해보세요.&lt;br&gt;
쪽팔림도 좀 당하겠지만… 뭐 어때.&lt;/p&gt;

&lt;p&gt;AI와 함께 하루 10시간 씩 매일 코딩할 수 있는 에너지.&lt;br&gt;
꾸준하게 열심히 하면 꽤 근사한 걸 만들 수 있을 겁니다. 돈도 당연히 벌 수 있고요.&lt;br&gt;
좋은 시절입니다.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
&lt;em&gt;함께 읽으면 좋은 글:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://jeho.page/essay/2026/02/23/agentic-coding-arbitrage.html"&gt;바이브 코딩 아비트리지&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://jeho.page/essay/2026/03/11/young-developer.html</id>
    <link href="https://jeho.page/essay/2026/03/11/young-developer.html"/>
    <summary type="html">주니어 개발자는 더 이상 설 자리가 없다는 말에 너무 쫄 것 없습니다. IT 세상에서 불리한 사람은 언제나</summary>
    <title>젊음은 주니어 개발자의 큰 무기</title>
    <updated>2026-03-11T12:22:00+09:00</updated>
    <dc:date>2026-03-11T12:22:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>gywndi@gmail.com (gywndi)</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;h1 id="3년-만에-홈페이지를-고쳤습니다"&gt;3년 만에 홈페이지를 고쳤습니다&lt;/h1&gt;
&lt;p&gt;와이프는 현재 무인카페 주인입니다. 그리고 3년전 제가 워드프레스 기반으로 카페 홈페이지를 만들었었죠.&lt;/p&gt;
&lt;p&gt;그 후로 거의 손을 안 댔습니다. 메뉴가 바뀌어도, 이미지가 달라져도, 홈페이지는 그냥 그 자리에 있었습니다. 관리가 번거로웠거든요. 어느 날 홈페이지를 열어봤더니, 현실과 너무 달랐습니다. 없어진 메뉴가 올라가 있고, 있는 메뉴가 빠져 있었습니다.&lt;/p&gt;
&lt;p&gt;이건 아니다 싶었습니다. 그래 리뉴얼을 결심했습니다. (사실 작년ㅜ터..)&lt;/p&gt;
&lt;p&gt;이번엔 쉽게 관리할 수 있는 구조로 처음부터 다시 만들기로 했습니다. 그 과정에서 AI를 적극 활용해보기로 했습니다.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://gywn.net/2026/03/cafe-menu-ai-assistant/</id>
    <link href="https://gywn.net/2026/03/cafe-menu-ai-assistant/"/>
    <summary type="html">&lt;h1 id="3년-만에-홈페이지를-고쳤습니다"&gt;3년 만에 홈페이지를 고쳤습니다&lt;/h1&gt;
&lt;p&gt;와이프는 현재 무인카페 주인입니다. 그리고 3년전 제가 워드프레스 기반으로 카페 홈페이지를 만들었었죠.&lt;/p&gt;
&lt;p&gt;그 후로 거의 손을 안 댔습니다. 메뉴가 바뀌어도, 이미지가 달라져도, 홈페이지는 그냥 그 자리에 있었습니다. 관리가 번거로웠거든요. 어느 날 홈페이지를 열어봤더니, 현실과 너무 달랐습니다. 없어진 메뉴가 올라가 있고, 있는 메뉴가 빠져 있었습니다.&lt;/p&gt;
&lt;p&gt;이건 아니다 싶었습니다. 그래 리뉴얼을 결심했습니다. (사실 작년ㅜ터..)&lt;/p&gt;
&lt;p&gt;이번엔 쉽게 관리할 수 있는 구조로 처음부터 다시 만들기로 했습니다. 그 과정에서 AI를 적극 활용해보기로 했습니다.&lt;/p&gt;</summary>
    <title>AI와 함께 카페 메뉴를 정리한 이야기</title>
    <updated>2026-03-14T22:37:02+09:00</updated>
    <dc:date>2026-03-14T22:37:02+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>gywndi@gmail.com (gywndi)</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;h2 id="claude-code를-쓰다-보면-생기는-문제"&gt;Claude Code를 쓰다 보면 생기는 문제&lt;/h2&gt;
&lt;p&gt;요즘 개발자들 사이에서 &lt;strong&gt;Claude Code&lt;/strong&gt;를 사용하는 분들이 많아지고 있습니다.&lt;/p&gt;
&lt;p&gt;Claude Code는 Anthropic이 만든 AI 코딩 도구인데요. 터미널에서 Claude에게 말로 설명하면, 실제 코드를 작성해주는 강력한 도구입니다.&lt;/p&gt;
&lt;p&gt;그런데 이걸 써보신 분들이라면 이런 상황을 겪어보셨을 거예요.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“회원가입 기능 만들어줘.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;라고 말했을 뿐인데, Claude가 데이터베이스 설계부터 API 코드까지 주르르 짜기 시작합니다. 처음엔 “와, 빠르다!” 싶지만, 잠깐 들여다보면 내가 원하는 방향이 아닌 경우가 많습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이메일 인증이 없어도 된다고 했는데 들어가 있거나&lt;/li&gt;
&lt;li&gt;프레임워크를 Next.js로 쓰고 싶었는데 Express로 만들거나&lt;/li&gt;
&lt;li&gt;아직 기획이 안 됐는데 너무 복잡한 구조로 짜버리거나&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;방향이 잘못된 채로 코드가 쌓이면&lt;/strong&gt;, 나중에 수정하는 비용이 처음부터 다시 만드는 것보다 커집니다. 그리고 Claude는 멈추지 않습니다. 계속 만듭니다.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://gywn.net/2026/03/ralph-workflow-for-claude-code/</id>
    <link href="https://gywn.net/2026/03/ralph-workflow-for-claude-code/"/>
    <summary type="html">&lt;h2 id="claude-code를-쓰다-보면-생기는-문제"&gt;Claude Code를 쓰다 보면 생기는 문제&lt;/h2&gt;
&lt;p&gt;요즘 개발자들 사이에서 &lt;strong&gt;Claude Code&lt;/strong&gt;를 사용하는 분들이 많아지고 있습니다.&lt;/p&gt;
&lt;p&gt;Claude Code는 Anthropic이 만든 AI 코딩 도구인데요. 터미널에서 Claude에게 말로 설명하면, 실제 코드를 작성해주는 강력한 도구입니다.&lt;/p&gt;
&lt;p&gt;그런데 이걸 써보신 분들이라면 이런 상황을 겪어보셨을 거예요.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;회원가입 기능 만들어줘.&amp;rdquo;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;라고 말했을 뿐인데, Claude가 데이터베이스 설계부터 API 코드까지 주르르 짜기 시작합니다. 처음엔 &amp;ldquo;와, 빠르다!&amp;rdquo; 싶지만, 잠깐 들여다보면 내가 원하는 방향이 아닌 경우가 많습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이메일 인증이 없어도 된다고 했는데 들어가 있거나&lt;/li&gt;
&lt;li&gt;프레임워크를 Next.js로 쓰고 싶었는데 Express로 만들거나&lt;/li&gt;
&lt;li&gt;아직 기획이 안 됐는데 너무 복잡한 구조로 짜버리거나&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;방향이 잘못된 채로 코드가 쌓이면&lt;/strong&gt;, 나중에 수정하는 비용이 처음부터 다시 만드는 것보다 커집니다. 그리고 Claude는 멈추지 않습니다. 계속 만듭니다.&lt;/p&gt;</summary>
    <title>Claude Code, 요구사항도 없이 코드부터 짠다고요?</title>
    <updated>2026-03-10T16:16:38+09:00</updated>
    <dc:date>2026-03-10T16:16:38+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Terry Cho</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;&lt;p&gt;근래에 하네스 엔지니어링에 대한 리서치를 하다가 매우 흥미 있는 글을 하나 찾았는데, 내가 존경하는 마틴파울러님 사이트에, 올라온 Keif Morris의 글이다. 
참고 : https://martinfowler.com/articles/exploring-gen-ai/humans-and-agents.html 
이 글은 개발에서, AI 에이전트와 사람간의 상호 작용을 단계별로 정의한 모델인데, 지금까지 명확하지 않은 AI 기반 개발에 대한 ..&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://bcho.tistory.com/1508</id>
    <link href="https://bcho.tistory.com/1508"/>
    <summary type="html">근래에 하네스 엔지니어링에 대한 리서치를 하다가 매우 흥미 있는 글을 하나 찾았는데, 내가 존경하는 마틴파울러님 사이트에, 올라온 Keif Morris의 글이다.&amp;nbsp;
참고 : https://martinfowler.com/articles/exploring-gen-ai/humans-and-agents.html&amp;nbsp;
이 글은 개발에서, AI 에이전트와 사람간의 상호 작용을 단계별로 정의한 모델인데, 지금까지 명확하지 않은 AI 기반 개발에 대한 ..</summary>
    <title>AI 코딩의 발전단계 - 하네스 엔지니어링과 완전 자율형 에이전트</title>
    <updated>2026-03-16T13:44:07+09:00</updated>
    <dc:date>2026-03-16T13:44:07+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Terry Cho</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;&lt;p&gt;요즘 Claude Code 커뮤니티에서 RALF Wiggum 플러그인이 화제다. YouTube 영상마다 "AI가 혼자서 태스크를 10번씩 반복해서 끝내준다!"는 식의 소개가 넘쳐나고 있다. 
그런데, 재미있는 유투브 영상을 하나 찾았다. Claude Code의 RALF 루프를 사용하지 말라는 건데, 내용을 보면 다음과 같다. 
 

 
지금 사람들이 열광하는 그 Claude Code 플러그인은 진짜 ..&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://bcho.tistory.com/1507</id>
    <link href="https://bcho.tistory.com/1507"/>
    <summary type="html">요즘 Claude Code 커뮤니티에서&amp;nbsp;RALF Wiggum 플러그인이 화제다. YouTube 영상마다 "AI가 혼자서 태스크를 10번씩 반복해서 끝내준다!"는 식의 소개가 넘쳐나고 있다.&amp;nbsp;
그런데, 재미있는 유투브 영상을 하나 찾았다. Claude Code의 RALF 루프를 사용하지 말라는 건데, 내용을 보면 다음과 같다.&amp;nbsp;
&amp;nbsp;

&amp;nbsp;
지금 사람들이 열광하는 그 Claude Code 플러그인은&amp;nbsp;진짜 ..</summary>
    <title>Stop Using The Ralph Loop Plugin</title>
    <updated>2026-03-15T17:58:26+09:00</updated>
    <dc:date>2026-03-15T17:58:26+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Terry Cho</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;&lt;p&gt;Claude Code Agent Teams: Skill, SubAgent, Agent Team 완전 정복
혼자 일하는 AI에서 팀으로 일하는 AI로 — 언제 무엇을 써야 하는가
Claude Code를 처음 쓰기 시작하면 대부분 단순하게 쓴다. 터미널에서 claude를 실행하고, 코드 작성을 시키거나 버그를 고쳐달라고 한다. 그런데 어느 순간 한계가 느껴진다. "이 작업은 병렬로 돌릴 수 있을 텐데", "이 부분은 전문화된 역할이 따로..&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://bcho.tistory.com/1506</id>
    <link href="https://bcho.tistory.com/1506"/>
    <summary type="html">Claude Code Agent Teams: Skill, SubAgent, Agent Team 완전 정복
혼자 일하는 AI에서 팀으로 일하는 AI로 &amp;mdash; 언제 무엇을 써야 하는가
Claude Code를 처음 쓰기 시작하면 대부분 단순하게 쓴다. 터미널에서&amp;nbsp;claude를 실행하고, 코드 작성을 시키거나 버그를 고쳐달라고 한다. 그런데 어느 순간 한계가 느껴진다. "이 작업은 병렬로 돌릴 수 있을 텐데", "이 부분은 전문화된 역할이 따로..</summary>
    <title>Claude Code Agent Teams: Skill, SubAgent, Agent Team 완전 정복</title>
    <updated>2026-03-15T16:57:38+09:00</updated>
    <dc:date>2026-03-15T16:57:38+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Terry Cho</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;&lt;p&gt; 
조대협 (http://bcho.tistory.com)
왜 SubAgent가 필요한가? 
Claude Code로 복잡한 작업을 하다 보면 한 가지 문제를 마주치게 된다. 코드베이스를 탐색하고, 분석하고, 수정하고, 테스트까지 하다 보면 context window가 빠르게 소모된다는 것이다. 그리고 한 AI가 "코드 리뷰어"이면서 동시에 "디버거"이고 "문서 작성자"가 되려다 보면 어느 것도 제대로 못하는 상황이 생긴다. 
그..&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://bcho.tistory.com/1505</id>
    <link href="https://bcho.tistory.com/1505"/>
    <summary type="html">&amp;nbsp;
조대협 (http://bcho.tistory.com)
왜 SubAgent가 필요한가?&amp;nbsp;
Claude Code로 복잡한 작업을 하다 보면 한 가지 문제를 마주치게 된다. 코드베이스를 탐색하고, 분석하고, 수정하고, 테스트까지 하다 보면 context window가 빠르게 소모된다는 것이다. 그리고 한 AI가 "코드 리뷰어"이면서 동시에 "디버거"이고 "문서 작성자"가 되려다 보면 어느 것도 제대로 못하는 상황이 생긴다.&amp;nbsp;
그..</summary>
    <title>Claude Code SubAgent - 전문화된 AI 서브에이전트로 생산성 높이기</title>
    <updated>2026-03-14T15:51:03+09:00</updated>
    <dc:date>2026-03-14T15:51:03+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Terry Cho</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;&lt;p&gt;Claude Code-Hook의 개념
조대협(http://bcho.tistory.com)
 
Hook은 Claude Code의 실행중에, 특정 이벤트가 발생하였을때 사용자가 정해 지정해놓은 Shell Command나, HTTP 요청 또는 프롬프트를 실행할 수 있는 기능이다.
 
예를 들어, Claude Code를 통해서 파일을 에디트 했을때 자동으로, 포맷팅을 검사하도록 지시할 수 있다. 물론 프롬프트를 통해서 지시할 수 도 있지만, ..&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://bcho.tistory.com/1504</id>
    <link href="https://bcho.tistory.com/1504"/>
    <summary type="html">Claude Code-Hook의 개념
조대협(http://bcho.tistory.com)
&amp;nbsp;
Hook은 Claude Code의 실행중에, 특정 이벤트가 발생하였을때 사용자가 정해 지정해놓은 Shell Command나, HTTP 요청 또는 프롬프트를 실행할 수 있는 기능이다.
&amp;nbsp;
예를 들어, Claude Code를 통해서 파일을 에디트 했을때 자동으로, 포맷팅을 검사하도록 지시할 수 있다. 물론 프롬프트를 통해서 지시할 수 도 있지만, ..</summary>
    <title>Claude Code - Hook을 통한 자동화.</title>
    <updated>2026-03-12T16:45:45+09:00</updated>
    <dc:date>2026-03-12T16:45:45+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>novemberde</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://novemberde.github.io/images/20260312_ai.png" alt="working speed in ai era"&gt;
&lt;/p&gt;
&lt;h2 id="마차의-시대는-끝났다"&gt;마차의 시대는 끝났다&lt;/h2&gt;
&lt;p&gt;1865년, 영국 의회는 진지하게 이런 법을 통과시켰다. &lt;strong&gt;자동차 앞에 붉은 깃발을 든 사람이 60야드 앞서 걸어가야 한다.&lt;/strong&gt; 도시에서는 시속 3km, 교외에서는 시속 6km. 자동차의 속도를 마차 수준으로 제한한 것이다. 이유는 다양했다. “마차보다 위험하다”, “말이 놀란다”, “도로가 마차용으로 만들어졌다.” 이 붉은 깃발법(Red Flag Act)은 30년 넘게 유지되었다.&lt;/p&gt;
&lt;p&gt;지금 돌아보면 웃기는 이야기다. 하지만 나는 2026년에 같은 일이 벌어지고 있다고 본다.&lt;/p&gt;
&lt;h2 id="더-많이-하면-더-많은-가치를-받을-수-있을까"&gt;더 많이 하면 더 많은 가치를 받을 수 있을까&lt;/h2&gt;
&lt;p&gt;AI 도구를 쓰면서 업무 속도가 빨라진 사람들이 늘고 있다. 코드 리뷰가 빨라지고, 문서 작성이 빨라지고, 데이터 분석이 빨라졌다. 자연스럽게 이런 기대가 생긴다.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://novemberde.github.io/post/2026/03/12/Working-Speed-In-AI-Era-ko/</id>
    <link href="https://novemberde.github.io/post/2026/03/12/Working-Speed-In-AI-Era-ko/"/>
    <summary type="html">&lt;p&gt;&lt;img loading="lazy" src="https://novemberde.github.io/images/20260312_ai.png" alt="working speed in ai era"  /&gt;
&lt;/p&gt;
&lt;h2 id="마차의-시대는-끝났다"&gt;마차의 시대는 끝났다&lt;/h2&gt;
&lt;p&gt;1865년, 영국 의회는 진지하게 이런 법을 통과시켰다. &lt;strong&gt;자동차 앞에 붉은 깃발을 든 사람이 60야드 앞서 걸어가야 한다.&lt;/strong&gt; 도시에서는 시속 3km, 교외에서는 시속 6km. 자동차의 속도를 마차 수준으로 제한한 것이다. 이유는 다양했다. &amp;ldquo;마차보다 위험하다&amp;rdquo;, &amp;ldquo;말이 놀란다&amp;rdquo;, &amp;ldquo;도로가 마차용으로 만들어졌다.&amp;rdquo; 이 붉은 깃발법(Red Flag Act)은 30년 넘게 유지되었다.&lt;/p&gt;
&lt;p&gt;지금 돌아보면 웃기는 이야기다. 하지만 나는 2026년에 같은 일이 벌어지고 있다고 본다.&lt;/p&gt;
&lt;h2 id="더-많이-하면-더-많은-가치를-받을-수-있을까"&gt;더 많이 하면 더 많은 가치를 받을 수 있을까&lt;/h2&gt;
&lt;p&gt;AI 도구를 쓰면서 업무 속도가 빨라진 사람들이 늘고 있다. 코드 리뷰가 빨라지고, 문서 작성이 빨라지고, 데이터 분석이 빨라졌다. 자연스럽게 이런 기대가 생긴다.&lt;/p&gt;</summary>
    <title>AI 시대의 일하는 속도: 자동차를 타고도 마차의 속도로 달리는 사람들</title>
    <updated>2026-03-12T09:00:00+09:00</updated>
    <dc:date>2026-03-12T09:00:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>novemberde</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://novemberde.github.io/images/20260312_ai.png" alt="working speed in ai era"&gt;
&lt;/p&gt;
&lt;h2 id="the-age-of-the-horse-carriage-is-over"&gt;The Age of the Horse Carriage Is Over&lt;/h2&gt;
&lt;p&gt;In 1865, the British Parliament — in all seriousness — passed a law requiring &lt;strong&gt;a person carrying a red flag to walk 60 yards ahead of every automobile.&lt;/strong&gt; Speed limits were set at 2 mph in towns and 4 mph in the countryside. The speed of the car was legally capped at horse-carriage levels. The reasons varied: “It’s more dangerous than a horse carriage,” “It scares the horses,” “The roads were built for carriages.” This &lt;strong&gt;Red Flag Act&lt;/strong&gt; remained in force for over 30 years.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://novemberde.github.io/post/2026/03/12/Working-Speed-In-AI-Era/</id>
    <link href="https://novemberde.github.io/post/2026/03/12/Working-Speed-In-AI-Era/"/>
    <summary type="html">&lt;p&gt;&lt;img loading="lazy" src="https://novemberde.github.io/images/20260312_ai.png" alt="working speed in ai era"  /&gt;
&lt;/p&gt;
&lt;h2 id="the-age-of-the-horse-carriage-is-over"&gt;The Age of the Horse Carriage Is Over&lt;/h2&gt;
&lt;p&gt;In 1865, the British Parliament — in all seriousness — passed a law requiring &lt;strong&gt;a person carrying a red flag to walk 60 yards ahead of every automobile.&lt;/strong&gt; Speed limits were set at 2 mph in towns and 4 mph in the countryside. The speed of the car was legally capped at horse-carriage levels. The reasons varied: &amp;ldquo;It&amp;rsquo;s more dangerous than a horse carriage,&amp;rdquo; &amp;ldquo;It scares the horses,&amp;rdquo; &amp;ldquo;The roads were built for carriages.&amp;rdquo; This &lt;strong&gt;Red Flag Act&lt;/strong&gt; remained in force for over 30 years.&lt;/p&gt;</summary>
    <title>Working Speed in the AI Era: Driving a Car at Horse-Carriage Pace</title>
    <updated>2026-03-12T09:00:00+09:00</updated>
    <dc:date>2026-03-12T09:00:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Pluu</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;모바일 앱에서 회원가입이나 정보 입력 폼(Form)을 구현할 때, 소프트 키보드가 올라오면서 사용자가 입력 중인 텍스트 필드를 가려버리는 이슈는 안드로이드 개발자라면 누구나 겪어본 흔한 문제입니다.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;본 글에서는 Jetpack Compose에서 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;를 사용해 이 문제를 해결하는 방법 중 하나를 소개합니다. 아래와 같은 회원가입 화면에서 사용한 일부분을 예제로 만들어보면서 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;를 어떻게 실전에 적용하는지 소개하겠습니다.&lt;/p&gt;

&lt;div class="youtube"&gt;
    &lt;iframe width="560" height="315" src="https://www.youtube.com/embed/ZiliLq9ZxuU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;hr&gt;

&lt;h2 id="1-bringintoviewrequester란"&gt;1. BringIntoViewRequester란?&lt;/h2&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;는 Compose에서 특정 Composable 영역이 스크롤 가능한 부모(Viewport) 화면 내에 들어오도록(Bring into view) 스크롤을 요청하는 기능을 제공하는 객체입니다.&lt;/p&gt;

&lt;p&gt;사용자가 텍스트 필드를 터치하여 포커스를 얻었을 때, 혹은 키보드가 올라오는 시점에 &lt;code class="language-plaintext highlighter-rouge"&gt;bringIntoView()&lt;/code&gt; 함수를 호출하게 되면, Compose가 알아서 해당 Composable이 화면에 잘 보이도록 스크롤 위치를 조정해 줍니다.&lt;/p&gt;

&lt;h2 id="2-화면-전체-구성과-기본-세팅"&gt;2. 화면 전체 구성과 기본 세팅&lt;/h2&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;가 올바르게 동작하려면, 상위 부모가 스크롤 가능하고 키보드 높이에 반응해야 합니다. 예제의 &lt;code class="language-plaintext highlighter-rouge"&gt;Sample&lt;/code&gt; Composable은 이를 위한 기본 정의입니다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;scrollState&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberScrollState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 필수 1. 시스템 바(상태 바 등) 영역을 피하기 위한 패딩&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;systemBarsPadding&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 필수 2. 키보드가 올라올 때 하단에 키보드 높이만큼 패딩 확보&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;imePadding&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
            &lt;span class="c1"&gt;// 필수 3. 뷰포트 내에서 스크롤 가능하도록 설정&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verticalScroll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scrollState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;verticalArrangement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Arrangement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spacedBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ... (아이디, 비밀번호, 주소 등 폼 입력 Composable 배치)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;imePadding()&lt;/code&gt;&lt;/strong&gt;: 키보드가 차지하는 공간만큼 화면 하단에 패딩을 밀어 넣어 화면 콘텐츠 영역을 조정합니다.&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;verticalScroll()&lt;/code&gt;&lt;/strong&gt;: 스크롤 상태를 부여하여 좁아진 영역 안에서 스크롤이 가능하도록 만들어줍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 두 가지가 전제되어야 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;가 위치를 계산하여 올바르게 스크롤할 수 있습니다.&lt;/p&gt;

&lt;h2 id="3-핵심-로직-textfield와-bringintoviewrequester-직접-연결"&gt;3. 핵심 로직: TextField와 BringIntoViewRequester 직접 연결&lt;/h2&gt;

&lt;p&gt;여기에서는 복잡한 구조대신, 단일 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;에 직접 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;를 통해서 동작 원리를 확인해 보겠습니다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;SimpleInput&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. 상태 및 객체 초기화&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;text&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;isFocused&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;bringIntoViewRequester&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;BringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  
    &lt;span class="c1"&gt;// 키보드 노출 여부&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WindowInsets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. 포커스 상태와 키보드 노출 여부에 따라 스크롤 요청&lt;/span&gt;
    &lt;span class="nc"&gt;LaunchedEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// 키보드가 올라오는 애니메이션 시간을 고려한 짧은 지연&lt;/span&gt;
            &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
            &lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;onValueChange&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"간단한 입력"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxWidth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 3. Modifier에 bringIntoViewRequester 등록&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;// 4. 포커스 상태 변경 감지&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFocusChanged&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;isFocused&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hasFocus&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위의 예제는 가장 기본적인 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;의 사용 패턴입니다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;strong&gt;객체 생성&lt;/strong&gt;: &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester()&lt;/code&gt;를 &lt;code class="language-plaintext highlighter-rouge"&gt;remember&lt;/code&gt;로 생성하고 타깃이 되는 UI 요소(여기서는 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;)의 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier&lt;/code&gt;에 연결합니다.&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;이벤트 트리거&lt;/strong&gt;: 상태(&lt;code class="language-plaintext highlighter-rouge"&gt;text&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;isFocused&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;isImeVisible&lt;/code&gt;) 변화를 감지하여 CoroutineScope 안에서 &lt;code class="language-plaintext highlighter-rouge"&gt;bringIntoView()&lt;/code&gt;를 호출합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="4-심화-예제-휴대폰-번호-입력-필드-상세-구현-focusgroup의-활용"&gt;4. 심화 예제: 휴대폰 번호 입력 필드 상세 구현 (focusGroup의 활용)&lt;/h2&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;는 여러 개의 입력 필드가 하나의 그룹으로 묶일 때도 사용할 수 있습니다. 예제로 휴대폰 번호를 입력받는 &lt;code class="language-plaintext highlighter-rouge"&gt;CellularPhone&lt;/code&gt; Composable을 통해 여러 입력 필드 사이에서 어떻게 처리하는지 확인해 보겠습니다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;CellularPhone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. 여러 TextField의 포커스를 제어하기 위한 FocusRequester &lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="py"&gt;focus1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;focus2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;focus3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FocusRequester&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createRefs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;input1&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// ... input2, input3 생략 ...&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;isFocused&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;bringIntoViewRequester&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;BringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WindowInsets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;

    &lt;span class="c1"&gt;// 스크롤 요청 로직&lt;/span&gt;
    &lt;span class="nc"&gt;LaunchedEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
             &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. 입력 필드들을 감싸는 부모 Column에 Modifier 적용&lt;/span&gt;
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;modifier&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFocusChanged&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;isFocused&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hasFocus&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="c1"&gt;// ✨ 3. 자식들의 포커스를 그룹화&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focusGroup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"휴대폰번호"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nc"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verticalAlignment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Alignment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CenterVertically&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// 첫 번째 입력 필드&lt;/span&gt;
            &lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="c1"&gt;// ...&lt;/span&gt;
                &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focusRequester&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;focus1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focusProperties&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;focus2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// 다음 포커스 지정&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nc"&gt;Dash&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 두 번째, 세 번째 입력 필드 생략 ...&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="단계별-상세-설명"&gt;단계별 상세 설명&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;strong&gt;포커스 이동 설정 (&lt;code class="language-plaintext highlighter-rouge"&gt;focusProperties&lt;/code&gt;)&lt;/strong&gt;: 각 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;의 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier.focusProperties&lt;/code&gt;를 통해 &lt;code class="language-plaintext highlighter-rouge"&gt;next&lt;/code&gt; 호긍ㄴ &lt;code class="language-plaintext highlighter-rouge"&gt;previous&lt;/code&gt;를 지정할 수 있습니다. 이렇게 하면 하드웨어 키보드의 Tab 키나 접근성 서비스(TalkBack 등)를 통한 포커스 이동이 자연스럽게 동작합니다.&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;focusGroup()&lt;/code&gt;의 역할&lt;/strong&gt;: 부모 &lt;code class="language-plaintext highlighter-rouge"&gt;Column&lt;/code&gt;에 적용된 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier.focusGroup()&lt;/code&gt;은 여기서 결정적인 역할을 합니다. 만약 이 Modifier가 없다면, &lt;code class="language-plaintext highlighter-rouge"&gt;focus1&lt;/code&gt;을 가진 첫 번째 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;에서 &lt;code class="language-plaintext highlighter-rouge"&gt;focus2&lt;/code&gt;를 가진 두 번째 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;로 포커스가 이동할 때, 부모 &lt;code class="language-plaintext highlighter-rouge"&gt;Column&lt;/code&gt;은 찰나의 순간에 “포커스를 잃었다”고 판단(&lt;code class="language-plaintext highlighter-rouge"&gt;isFocused = false&lt;/code&gt; -&amp;gt; &lt;code class="language-plaintext highlighter-rouge"&gt;true&lt;/code&gt;)하게 됩니다. 이는 상태 변화를 일으켜 불필요한 재구성을 유발하거나, 스크롤 로직이 꼬이는 원인이 될 수 있습니다. &lt;code class="language-plaintext highlighter-rouge"&gt;focusGroup()&lt;/code&gt;은 내부 자식들 간의 포커스 이동은 그룹 외부로 포커스가 벗어난 것으로 간주하지 않도록 하여 부모의 &lt;code class="language-plaintext highlighter-rouge"&gt;isFocused&lt;/code&gt; 상태를 안정적으로 유지시켜 줍니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="5-결론"&gt;5. 결론&lt;/h2&gt;

&lt;p&gt;Jetpack Compose에서 복잡한 입력 폼을 다룰 때, 키보드가 UI를 가리는 현상을 효과적으로 제어하는 것은 사용자 경험(UX) 측면에서 매우 중요합니다. 다음 3가지만 기억하시면 됩니다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;화면 최상위에 &lt;code class="language-plaintext highlighter-rouge"&gt;imePadding()&lt;/code&gt;과 &lt;code class="language-plaintext highlighter-rouge"&gt;verticalScroll()&lt;/code&gt;을 적용하여 기본적인 스크롤 캔버스를 확보&lt;/li&gt;
  &lt;li&gt;단일 입력 컴포넌트 또는 입력 필드 그룹에 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier.bringIntoViewRequester()&lt;/code&gt;를 적용하고, 여러 개의 필드가 묶여있다면 &lt;code class="language-plaintext highlighter-rouge"&gt;focusGroup()&lt;/code&gt;으로 감싸 포커스를 안정적으로 관리&lt;/li&gt;
  &lt;li&gt;
&lt;code class="language-plaintext highlighter-rouge"&gt;WindowInsets.isImeVisible&lt;/code&gt;과 &lt;code class="language-plaintext highlighter-rouge"&gt;hasFocus&lt;/code&gt;를 조합하여, 포커스를 가진 상태로 키보드가 나타날 때 &lt;code class="language-plaintext highlighter-rouge"&gt;bringIntoView()&lt;/code&gt;를 호출&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;위 패턴을 도입한다면, 어떠한 긴 가입 폼 화면이라도 사용자가 입력 중인 부분이 키보드에 가려지는 답답한 일을 겪지 않게 될 것입니다.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>http://pluu.github.io/blog/android/2026/03/15/BringIntoViewRequester/</id>
    <link href="http://pluu.github.io/blog/android/2026/03/15/BringIntoViewRequester/"/>
    <summary type="html">&lt;p&gt;모바일 앱에서 회원가입이나 정보 입력 폼(Form)을 구현할 때, 소프트 키보드가 올라오면서 사용자가 입력 중인 텍스트 필드를 가려버리는 이슈는 안드로이드 개발자라면 누구나 겪어본 흔한 문제입니다.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;본 글에서는 Jetpack Compose에서 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;를 사용해 이 문제를 해결하는 방법 중 하나를 소개합니다. 아래와 같은 회원가입 화면에서 사용한 일부분을 예제로 만들어보면서 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;를 어떻게 실전에 적용하는지 소개하겠습니다.&lt;/p&gt;

&lt;div class="youtube"&gt;
    &lt;iframe width="560" height="315" src="https://www.youtube.com/embed/ZiliLq9ZxuU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id="1-bringintoviewrequester란"&gt;1. BringIntoViewRequester란?&lt;/h2&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;는 Compose에서 특정 Composable 영역이 스크롤 가능한 부모(Viewport) 화면 내에 들어오도록(Bring into view) 스크롤을 요청하는 기능을 제공하는 객체입니다.&lt;/p&gt;

&lt;p&gt;사용자가 텍스트 필드를 터치하여 포커스를 얻었을 때, 혹은 키보드가 올라오는 시점에 &lt;code class="language-plaintext highlighter-rouge"&gt;bringIntoView()&lt;/code&gt; 함수를 호출하게 되면, Compose가 알아서 해당 Composable이 화면에 잘 보이도록 스크롤 위치를 조정해 줍니다.&lt;/p&gt;

&lt;h2 id="2-화면-전체-구성과-기본-세팅"&gt;2. 화면 전체 구성과 기본 세팅&lt;/h2&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;가 올바르게 동작하려면, 상위 부모가 스크롤 가능하고 키보드 높이에 반응해야 합니다. 예제의 &lt;code class="language-plaintext highlighter-rouge"&gt;Sample&lt;/code&gt; Composable은 이를 위한 기본 정의입니다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;scrollState&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberScrollState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 필수 1. 시스템 바(상태 바 등) 영역을 피하기 위한 패딩&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;systemBarsPadding&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 필수 2. 키보드가 올라올 때 하단에 키보드 높이만큼 패딩 확보&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;imePadding&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
            &lt;span class="c1"&gt;// 필수 3. 뷰포트 내에서 스크롤 가능하도록 설정&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verticalScroll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scrollState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;verticalArrangement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Arrangement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spacedBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ... (아이디, 비밀번호, 주소 등 폼 입력 Composable 배치)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;imePadding()&lt;/code&gt;&lt;/strong&gt;: 키보드가 차지하는 공간만큼 화면 하단에 패딩을 밀어 넣어 화면 콘텐츠 영역을 조정합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;verticalScroll()&lt;/code&gt;&lt;/strong&gt;: 스크롤 상태를 부여하여 좁아진 영역 안에서 스크롤이 가능하도록 만들어줍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 두 가지가 전제되어야 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;가 위치를 계산하여 올바르게 스크롤할 수 있습니다.&lt;/p&gt;

&lt;h2 id="3-핵심-로직-textfield와-bringintoviewrequester-직접-연결"&gt;3. 핵심 로직: TextField와 BringIntoViewRequester 직접 연결&lt;/h2&gt;

&lt;p&gt;여기에서는 복잡한 구조대신, 단일 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;에 직접 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;를 통해서 동작 원리를 확인해 보겠습니다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;SimpleInput&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. 상태 및 객체 초기화&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;text&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;isFocused&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;bringIntoViewRequester&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;BringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  
    &lt;span class="c1"&gt;// 키보드 노출 여부&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WindowInsets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. 포커스 상태와 키보드 노출 여부에 따라 스크롤 요청&lt;/span&gt;
    &lt;span class="nc"&gt;LaunchedEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// 키보드가 올라오는 애니메이션 시간을 고려한 짧은 지연&lt;/span&gt;
            &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
            &lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;onValueChange&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"간단한 입력"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxWidth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 3. Modifier에 bringIntoViewRequester 등록&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;// 4. 포커스 상태 변경 감지&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFocusChanged&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;isFocused&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hasFocus&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위의 예제는 가장 기본적인 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;의 사용 패턴입니다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;객체 생성&lt;/strong&gt;: &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester()&lt;/code&gt;를 &lt;code class="language-plaintext highlighter-rouge"&gt;remember&lt;/code&gt;로 생성하고 타깃이 되는 UI 요소(여기서는 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;)의 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier&lt;/code&gt;에 연결합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;이벤트 트리거&lt;/strong&gt;: 상태(&lt;code class="language-plaintext highlighter-rouge"&gt;text&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;isFocused&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;isImeVisible&lt;/code&gt;) 변화를 감지하여 CoroutineScope 안에서 &lt;code class="language-plaintext highlighter-rouge"&gt;bringIntoView()&lt;/code&gt;를 호출합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="4-심화-예제-휴대폰-번호-입력-필드-상세-구현-focusgroup의-활용"&gt;4. 심화 예제: 휴대폰 번호 입력 필드 상세 구현 (focusGroup의 활용)&lt;/h2&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;는 여러 개의 입력 필드가 하나의 그룹으로 묶일 때도 사용할 수 있습니다. 예제로 휴대폰 번호를 입력받는 &lt;code class="language-plaintext highlighter-rouge"&gt;CellularPhone&lt;/code&gt; Composable을 통해 여러 입력 필드 사이에서 어떻게 처리하는지 확인해 보겠습니다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;CellularPhone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. 여러 TextField의 포커스를 제어하기 위한 FocusRequester &lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="py"&gt;focus1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;focus2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;focus3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FocusRequester&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createRefs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;input1&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// ... input2, input3 생략 ...&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;isFocused&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;bringIntoViewRequester&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;BringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WindowInsets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;

    &lt;span class="c1"&gt;// 스크롤 요청 로직&lt;/span&gt;
    &lt;span class="nc"&gt;LaunchedEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
             &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. 입력 필드들을 감싸는 부모 Column에 Modifier 적용&lt;/span&gt;
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;modifier&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFocusChanged&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;isFocused&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hasFocus&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="c1"&gt;// ✨ 3. 자식들의 포커스를 그룹화&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focusGroup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"휴대폰번호"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nc"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verticalAlignment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Alignment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CenterVertically&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// 첫 번째 입력 필드&lt;/span&gt;
            &lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="c1"&gt;// ...&lt;/span&gt;
                &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focusRequester&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;focus1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focusProperties&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;focus2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// 다음 포커스 지정&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nc"&gt;Dash&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 두 번째, 세 번째 입력 필드 생략 ...&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="단계별-상세-설명"&gt;단계별 상세 설명&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;포커스 이동 설정 (&lt;code class="language-plaintext highlighter-rouge"&gt;focusProperties&lt;/code&gt;)&lt;/strong&gt;: 각 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;의 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier.focusProperties&lt;/code&gt;를 통해 &lt;code class="language-plaintext highlighter-rouge"&gt;next&lt;/code&gt; 호긍ㄴ &lt;code class="language-plaintext highlighter-rouge"&gt;previous&lt;/code&gt;를 지정할 수 있습니다. 이렇게 하면 하드웨어 키보드의 Tab 키나 접근성 서비스(TalkBack 등)를 통한 포커스 이동이 자연스럽게 동작합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;focusGroup()&lt;/code&gt;의 역할&lt;/strong&gt;: 부모 &lt;code class="language-plaintext highlighter-rouge"&gt;Column&lt;/code&gt;에 적용된 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier.focusGroup()&lt;/code&gt;은 여기서 결정적인 역할을 합니다. 만약 이 Modifier가 없다면, &lt;code class="language-plaintext highlighter-rouge"&gt;focus1&lt;/code&gt;을 가진 첫 번째 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;에서 &lt;code class="language-plaintext highlighter-rouge"&gt;focus2&lt;/code&gt;를 가진 두 번째 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;로 포커스가 이동할 때, 부모 &lt;code class="language-plaintext highlighter-rouge"&gt;Column&lt;/code&gt;은 찰나의 순간에 “포커스를 잃었다”고 판단(&lt;code class="language-plaintext highlighter-rouge"&gt;isFocused = false&lt;/code&gt; -&amp;gt; &lt;code class="language-plaintext highlighter-rouge"&gt;true&lt;/code&gt;)하게 됩니다. 이는 상태 변화를 일으켜 불필요한 재구성을 유발하거나, 스크롤 로직이 꼬이는 원인이 될 수 있습니다. &lt;code class="language-plaintext highlighter-rouge"&gt;focusGroup()&lt;/code&gt;은 내부 자식들 간의 포커스 이동은 그룹 외부로 포커스가 벗어난 것으로 간주하지 않도록 하여 부모의 &lt;code class="language-plaintext highlighter-rouge"&gt;isFocused&lt;/code&gt; 상태를 안정적으로 유지시켜 줍니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="5-결론"&gt;5. 결론&lt;/h2&gt;

&lt;p&gt;Jetpack Compose에서 복잡한 입력 폼을 다룰 때, 키보드가 UI를 가리는 현상을 효과적으로 제어하는 것은 사용자 경험(UX) 측면에서 매우 중요합니다. 다음 3가지만 기억하시면 됩니다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;화면 최상위에 &lt;code class="language-plaintext highlighter-rouge"&gt;imePadding()&lt;/code&gt;과 &lt;code class="language-plaintext highlighter-rouge"&gt;verticalScroll()&lt;/code&gt;을 적용하여 기본적인 스크롤 캔버스를 확보&lt;/li&gt;
  &lt;li&gt;단일 입력 컴포넌트 또는 입력 필드 그룹에 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier.bringIntoViewRequester()&lt;/code&gt;를 적용하고, 여러 개의 필드가 묶여있다면 &lt;code class="language-plaintext highlighter-rouge"&gt;focusGroup()&lt;/code&gt;으로 감싸 포커스를 안정적으로 관리&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;WindowInsets.isImeVisible&lt;/code&gt;과 &lt;code class="language-plaintext highlighter-rouge"&gt;hasFocus&lt;/code&gt;를 조합하여, 포커스를 가진 상태로 키보드가 나타날 때 &lt;code class="language-plaintext highlighter-rouge"&gt;bringIntoView()&lt;/code&gt;를 호출&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;위 패턴을 도입한다면, 어떠한 긴 가입 폼 화면이라도 사용자가 입력 중인 부분이 키보드에 가려지는 답답한 일을 겪지 않게 될 것입니다.&lt;/p&gt;
</summary>
    <title>Blog: Jetpack Compose에서 BringIntoViewRequester를 활용한 스마트한 스크롤 제어</title>
    <updated>2026-03-15T23:00:00+09:00</updated>
    <dc:date>2026-03-15T23:00:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Pluu</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;Android Studio 플러그인 개발 시 버전 업데이트하면서 발생한 내용을 메모로 남긴다.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id="plugin-빌드-오류"&gt;Plugin 빌드 오류&lt;/h2&gt;

&lt;p&gt;매번 호환되는 Android Studio 버전에 맞춰서 버전 업데이트를 진행했다. 이상하게도 &lt;code class="language-plaintext highlighter-rouge"&gt;Panda&lt;/code&gt; 버전부터 Android Studio 이미지를 가져오는 것이 실패했다.&lt;/p&gt;

&lt;h3 id="빌드-환경-확인"&gt;빌드 환경 확인&lt;/h3&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;// root build.gralde.kts&lt;/span&gt;
&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
   &lt;span class="nf"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;intelliJPlatform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// org.jetbrains.intellij.platform 2.11.0 버전 사용&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 모듈 build.gradle.kts&lt;/span&gt;
&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;intellijPlatform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;androidStudio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2025.3.2.6"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="빌드-실패-로그"&gt;빌드 실패 로그&lt;/h3&gt;

&lt;div class="language-shell highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Could not determine the dependencies of task &lt;span class="s1"&gt;':compileJava'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Could not resolve all files &lt;span class="k"&gt;for &lt;/span&gt;configuration &lt;span class="s1"&gt;':intellijPlatformDependency'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
   &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Could not find com.google.android.studio:android-studio:2025.3.2.6.
     Searched &lt;span class="k"&gt;in &lt;/span&gt;the following locations:
       - https://repo.maven.apache.org/maven2/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.3.2.6/android-studio-2025.3.2.6-https:/edgedl.me.gvt1.com/android/studio/install/2025.3.2.6/android-studio-panda2-mac_arm.dmg
       - https://redirector.gvt1.com/edgedl/android/studio/install/2025.3.2.6/android-studio-2025.3.2.6-https:/edgedl.me.gvt1.com/android/studio/install/2025.3.2.6/android-studio-panda2-mac_arm.dmg
       - https://cache-redirector.jetbrains.com/www.jetbrains.com/intellij-repository/releases/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://cache-redirector.jetbrains.com/www.jetbrains.com/intellij-repository/snapshots/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://cache-redirector.jetbrains.com/intellij-dependencies/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://cache-redirector.jetbrains.com/plugins.jetbrains.com/maven/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="원인"&gt;원인&lt;/h2&gt;

&lt;p&gt;IntelliJ 기반 플러그인에 필요한 &lt;a href="https://github.com/JetBrains/intellij-platform-gradle-plugin"&gt;intellij-platform-gradle-plugin&lt;/a&gt; Github에서 해당 이유를 찾을 수 있었다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/JetBrains/intellij-platform-gradle-plugin/issues/2087"&gt;verifyPlugin failed for Android Studio&lt;/a&gt; 이슈의 내용으로 최근 Android Studio의 아카이브 형식이 변경되었다고 한다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;변경 전 : 버전 번호를 사용&lt;/li&gt;
  &lt;li&gt;변경 후 : &lt;code class="language-plaintext highlighter-rouge"&gt;panda&lt;/code&gt;와 같은 코드명을 URL 문자열에 포함&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://developer.android.com/studio/archive"&gt;https://developer.android.com/studio/archive&lt;/a&gt; 에서도 동일한 모습을 확인할 수 있다&lt;/p&gt;

&lt;p&gt;&lt;img class="img-responsive" src="http://pluu.github.io/assets/img/blog/2026/0310/Otter3.png"&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class="img-responsive" src="http://pluu.github.io/assets/img/blog/2026/0310/Panda2.png"&gt;&lt;/p&gt;

&lt;h2 id="해결법"&gt;해결법&lt;/h2&gt;

&lt;p&gt;해결법은 너무나도 간단하게 &lt;code class="language-plaintext highlighter-rouge"&gt;org.jetbrains.intellij.platform&lt;/code&gt; plugin을 &lt;a href="https://github.com/JetBrains/intellij-platform-gradle-plugin/releases/tag/2.12.0"&gt;2.12.0&lt;/a&gt; 버전으로 업데이트하면 된다.&lt;/p&gt;

&lt;p&gt;기반 플러그인 측에서 수정되어서 해결되었다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;// root build.gralde.kts&lt;/span&gt;
&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
   &lt;span class="nf"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;intelliJPlatform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// org.jetbrains.intellij.platform 2.12.0 버전 사용&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>http://pluu.github.io/blog/android/2026/03/10/AS-plugin-build/</id>
    <link href="http://pluu.github.io/blog/android/2026/03/10/AS-plugin-build/"/>
    <summary type="html">&lt;p&gt;Android Studio 플러그인 개발 시 버전 업데이트하면서 발생한 내용을 메모로 남긴다.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id="plugin-빌드-오류"&gt;Plugin 빌드 오류&lt;/h2&gt;

&lt;p&gt;매번 호환되는 Android Studio 버전에 맞춰서 버전 업데이트를 진행했다. 이상하게도 &lt;code class="language-plaintext highlighter-rouge"&gt;Panda&lt;/code&gt; 버전부터 Android Studio 이미지를 가져오는 것이 실패했다.&lt;/p&gt;

&lt;h3 id="빌드-환경-확인"&gt;빌드 환경 확인&lt;/h3&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;// root build.gralde.kts&lt;/span&gt;
&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
   &lt;span class="nf"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;intelliJPlatform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// org.jetbrains.intellij.platform 2.11.0 버전 사용&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 모듈 build.gradle.kts&lt;/span&gt;
&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;intellijPlatform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;androidStudio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2025.3.2.6"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="빌드-실패-로그"&gt;빌드 실패 로그&lt;/h3&gt;

&lt;div class="language-shell highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Could not determine the dependencies of task &lt;span class="s1"&gt;':compileJava'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Could not resolve all files &lt;span class="k"&gt;for &lt;/span&gt;configuration &lt;span class="s1"&gt;':intellijPlatformDependency'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
   &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Could not find com.google.android.studio:android-studio:2025.3.2.6.
     Searched &lt;span class="k"&gt;in &lt;/span&gt;the following locations:
       - https://repo.maven.apache.org/maven2/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.3.2.6/android-studio-2025.3.2.6-https:/edgedl.me.gvt1.com/android/studio/install/2025.3.2.6/android-studio-panda2-mac_arm.dmg
       - https://redirector.gvt1.com/edgedl/android/studio/install/2025.3.2.6/android-studio-2025.3.2.6-https:/edgedl.me.gvt1.com/android/studio/install/2025.3.2.6/android-studio-panda2-mac_arm.dmg
       - https://cache-redirector.jetbrains.com/www.jetbrains.com/intellij-repository/releases/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://cache-redirector.jetbrains.com/www.jetbrains.com/intellij-repository/snapshots/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://cache-redirector.jetbrains.com/intellij-dependencies/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://cache-redirector.jetbrains.com/plugins.jetbrains.com/maven/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="원인"&gt;원인&lt;/h2&gt;

&lt;p&gt;IntelliJ 기반 플러그인에 필요한 &lt;a href="https://github.com/JetBrains/intellij-platform-gradle-plugin"&gt;intellij-platform-gradle-plugin&lt;/a&gt; Github에서 해당 이유를 찾을 수 있었다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/JetBrains/intellij-platform-gradle-plugin/issues/2087"&gt;verifyPlugin failed for Android Studio&lt;/a&gt; 이슈의 내용으로 최근 Android Studio의 아카이브 형식이 변경되었다고 한다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;변경 전 : 버전 번호를 사용&lt;/li&gt;
  &lt;li&gt;변경 후 : &lt;code class="language-plaintext highlighter-rouge"&gt;panda&lt;/code&gt;와 같은 코드명을 URL 문자열에 포함&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://developer.android.com/studio/archive"&gt;https://developer.android.com/studio/archive&lt;/a&gt; 에서도 동일한 모습을 확인할 수 있다&lt;/p&gt;

&lt;p&gt;&lt;img class="img-responsive" src="/assets/img/blog/2026/0310/Otter3.png" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class="img-responsive" src="/assets/img/blog/2026/0310/Panda2.png" /&gt;&lt;/p&gt;

&lt;h2 id="해결법"&gt;해결법&lt;/h2&gt;

&lt;p&gt;해결법은 너무나도 간단하게 &lt;code class="language-plaintext highlighter-rouge"&gt;org.jetbrains.intellij.platform&lt;/code&gt; plugin을 &lt;a href="https://github.com/JetBrains/intellij-platform-gradle-plugin/releases/tag/2.12.0"&gt;2.12.0&lt;/a&gt; 버전으로 업데이트하면 된다.&lt;/p&gt;

&lt;p&gt;기반 플러그인 측에서 수정되어서 해결되었다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;// root build.gralde.kts&lt;/span&gt;
&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
   &lt;span class="nf"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;intelliJPlatform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// org.jetbrains.intellij.platform 2.12.0 버전 사용&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</summary>
    <title>Blog: [메모] Android Studio plugin 개발 시 빌드 오류</title>
    <updated>2026-03-10T23:30:00+09:00</updated>
    <dc:date>2026-03-10T23:30:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>애드사이드</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;&lt;p&gt;파이토치와 허깅페이스 생태계를 활용한 LLM 미세 튜닝을 철저하게 파헤치는 &amp;lt;LLM 미세 튜닝, 핵심만 빠르게!&amp;gt;가 출간되었습니다! 대부분 LLM의 책이 트랜스포머 구조를 소개하는 것부터 시작하기 때문에 미세 튜닝에 대한 내용은 비교적 뒷부분에 짧게 다루는 것이 보통입니다. 그러다 보니 아쉬울 수 밖에 없죠? 🙂 이 책은 아닙니다. 파이토치와 트랜스포머에 대한 설명은 다른 책에 맡기고 대규모 언어 모델을 미세 […]&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://tensorflow.blog/2026/03/15/llm-%eb%af%b8%ec%84%b8-%ed%8a%9c%eb%8b%9d-%ed%95%b5%ec%8b%ac%eb%a7%8c-%eb%b9%a0%eb%a5%b4%ea%b2%8c%ea%b0%80-%ec%b6%9c%ea%b0%84%eb%90%98%ec%97%88%ec%8a%b5%eb%8b%88%eb%8b%a4/</id>
    <link href="https://tensorflow.blog/2026/03/15/llm-%eb%af%b8%ec%84%b8-%ed%8a%9c%eb%8b%9d-%ed%95%b5%ec%8b%ac%eb%a7%8c-%eb%b9%a0%eb%a5%b4%ea%b2%8c%ea%b0%80-%ec%b6%9c%ea%b0%84%eb%90%98%ec%97%88%ec%8a%b5%eb%8b%88%eb%8b%a4/"/>
    <summary type="html">파이토치와 허깅페이스 생태계를 활용한 LLM 미세 튜닝을 철저하게 파헤치는 &amp;#60;LLM 미세 튜닝, 핵심만 빠르게!&amp;#62;가 출간되었습니다! 대부분 LLM의 책이 트랜스포머 구조를 소개하는 것부터 시작하기 때문에 미세 튜닝에 대한 내용은 비교적 뒷부분에 짧게 다루는 것이 보통입니다. 그러다 보니 아쉬울 수 밖에 없죠? 🙂 이 책은 아닙니다. 파이토치와 트랜스포머에 대한 설명은 다른 책에 맡기고 대규모 언어 모델을 미세 [&amp;#8230;]</summary>
    <title>“LLM 미세 튜닝, 핵심만 빠르게!”가 출간되었습니다.</title>
    <updated>2026-03-15T19:35:19+09:00</updated>
    <dc:date>2026-03-15T19:35:19+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>joosing</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;내가 편한지, 정말 순수한 마음으로 연락했을 클라이언트의 기술적인 질문 문자를 보며 주말 나의 오후가 흔들린다. 최대한 예의바르게 말하려고 했지만 나도 모르게 불편한 마음을 내비친 것 같다.&lt;/p&gt;
&lt;p&gt;그 동안 정말 어렵게 관계를 유지해 왔는데, 너무 선을 그은 건가 싶기도 하고, 혼자 해외에 나가 당황하고 있을 그의 마음이 다시 생각해 보니 헤아려지기도 한다. 얼마나 답답했으면 주말에 문자를 보냈을까.&lt;/p&gt;
&lt;p&gt;회사는 내가 너무 많은 리소스를 그에게 사용하길 원하지 않는다. 아무것도 모르는 어린 아이 같이 질문을 해오는 클라이언트는 우리에게 반가운 상대가 아니다. 그러나 고객이 없으면 우리 일에 아무 의미가 없지 않나.&lt;/p&gt;
&lt;p&gt;이제 곧 마지막 시험인데, 그가 자기 일을 잘 할 수 있게 마음을 고쳐먹고 잘 지원해 봐야겠다. 계약서만 보면 우리 할 일을 다했지만, 우리는 계약서 너머 가치를 만들어야 한다. 고객을 응대하다보면 도메인에 대해 배우는 것도 많을 것이다. 화이팅.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://velog.io/@joosing/%EA%B3%84%EC%95%BD%EC%84%9C-%EB%84%88%EB%A8%B8%EC%9D%98-%EA%B0%80%EC%B9%98</id>
    <link href="https://velog.io/@joosing/%EA%B3%84%EC%95%BD%EC%84%9C-%EB%84%88%EB%A8%B8%EC%9D%98-%EA%B0%80%EC%B9%98"/>
    <summary type="html">&lt;p&gt;내가 편한지, 정말 순수한 마음으로 연락했을 클라이언트의 기술적인 질문 문자를 보며 주말 나의 오후가 흔들린다. 최대한 예의바르게 말하려고 했지만 나도 모르게 불편한 마음을 내비친 것 같다.&lt;/p&gt;
&lt;p&gt;그 동안 정말 어렵게 관계를 유지해 왔는데, 너무 선을 그은 건가 싶기도 하고, 혼자 해외에 나가 당황하고 있을 그의 마음이 다시 생각해 보니 헤아려지기도 한다. 얼마나 답답했으면 주말에 문자를 보냈을까.&lt;/p&gt;
&lt;p&gt;회사는 내가 너무 많은 리소스를 그에게 사용하길 원하지 않는다. 아무것도 모르는 어린 아이 같이 질문을 해오는 클라이언트는 우리에게 반가운 상대가 아니다. 그러나 고객이 없으면 우리 일에 아무 의미가 없지 않나.&lt;/p&gt;
&lt;p&gt;이제 곧 마지막 시험인데, 그가 자기 일을 잘 할 수 있게 마음을 고쳐먹고 잘 지원해 봐야겠다. 계약서만 보면 우리 할 일을 다했지만, 우리는 계약서 너머 가치를 만들어야 한다. 고객을 응대하다보면 도메인에 대해 배우는 것도 많을 것이다. 화이팅.&lt;/p&gt;
</summary>
    <title>계약서 너머의 가치</title>
    <updated>2026-03-16T09:07:26+09:00</updated>
    <dc:date>2026-03-16T09:07:26+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>joosing</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;많은 것들을 내려 놓게 된다. 대신 한 프로젝트를 맡아 주겠다는 동료의 손길이 고맙다. 그래도 해소되지 않는 답답함이 있다. &lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://velog.io/@joosing/%EA%B3%A0%EB%A7%88%EC%9A%B4-%EB%8F%99%EB%A3%8C%EC%9D%98-%EC%86%90%EA%B8%B8-%EA%B7%B8%EB%9F%AC%EB%82%98-%EB%8B%B5%EB%8B%B5%ED%95%A8</id>
    <link href="https://velog.io/@joosing/%EA%B3%A0%EB%A7%88%EC%9A%B4-%EB%8F%99%EB%A3%8C%EC%9D%98-%EC%86%90%EA%B8%B8-%EA%B7%B8%EB%9F%AC%EB%82%98-%EB%8B%B5%EB%8B%B5%ED%95%A8"/>
    <summary type="html">&lt;p&gt;많은 것들을 내려 놓게 된다. 대신 한 프로젝트를 맡아 주겠다는 동료의 손길이 고맙다. 그래도 해소되지 않는 답답함이 있다. &lt;/p&gt;
</summary>
    <title>고마운 동료의 손길, 그러나 답답함</title>
    <updated>2026-03-13T09:20:12+09:00</updated>
    <dc:date>2026-03-13T09:20:12+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>joosing</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;'Head' 역할을 하며 다양한 파트의 사람들의 일에 관여하여 '머리'가 되어야 한다. 그런데 어떤 일들은 내가 '머리'가 되는게 무척 어색하고 불편하게 느껴진다. 이유는 둘 중 하나, 내가 그쪽 일을 잘 모르거나, 시간이 없어서 머리가 될 만큼 일을 신경쓰지 못하는 경우다.&lt;/p&gt;
&lt;p&gt;할 수 있는대로 팀을 나누어 다른 사람이 머리가 되도록 했지만 아직 더 필요하다는 생각이 든다. 하지만 쪼갤 수록 다시 싱크를 맞추는 비용이 든다. 절묘한 트레이드 오프 지점을 찾아야 한다.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://velog.io/@joosing/%EC%96%B4%EC%83%89%ED%95%9C-%EC%A7%80%ED%9C%98%EC%9E%90</id>
    <link href="https://velog.io/@joosing/%EC%96%B4%EC%83%89%ED%95%9C-%EC%A7%80%ED%9C%98%EC%9E%90"/>
    <summary type="html">&lt;p&gt;&amp;#39;Head&amp;#39; 역할을 하며 다양한 파트의 사람들의 일에 관여하여 &amp;#39;머리&amp;#39;가 되어야 한다. 그런데 어떤 일들은 내가 &amp;#39;머리&amp;#39;가 되는게 무척 어색하고 불편하게 느껴진다. 이유는 둘 중 하나, 내가 그쪽 일을 잘 모르거나, 시간이 없어서 머리가 될 만큼 일을 신경쓰지 못하는 경우다.&lt;/p&gt;
&lt;p&gt;할 수 있는대로 팀을 나누어 다른 사람이 머리가 되도록 했지만 아직 더 필요하다는 생각이 든다. 하지만 쪼갤 수록 다시 싱크를 맞추는 비용이 든다. 절묘한 트레이드 오프 지점을 찾아야 한다.&lt;/p&gt;
</summary>
    <title>어색한 지휘자</title>
    <updated>2026-03-12T09:04:44+09:00</updated>
    <dc:date>2026-03-12T09:04:44+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>향로 (기억보단 기록을)</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;SEO의 절대 강자이자 &lt;strong&gt;연 반복매출 4천만 달러(현재 기준: 600억원)&lt;/strong&gt; SaaS인 Moz의 공동 창업자이자 전 CEO 랜드 피쉬킨의 창업부터 회사를 떠날때까지의 경험을 정리한 책이다.&lt;br&gt;(2020년에는 6,740만 달러 - 1천억원 매출이었다고 한다)&lt;/p&gt;
&lt;p&gt;박소령 대표님의 "실패를 통과하는 일"과는 다른 결말을 맞이한 이야기를 본 것 같았다.&lt;/p&gt;
&lt;p&gt;책의 제목과 소개가 강렬해서 선입견이 생길 수도 있는데, "실리콘밸리의 선입견에서 벗어나야 한다"보다는 연 반복매출 500억을 달성한 SaaS 스타트업 창업자의 경험 기반 조언들이 가득한 책이었다.&lt;/p&gt;
&lt;p&gt;제품을 직접 만드는 창업자들이 많다 보니 제품 전략, 제품 설계, 고객 가치 등에 대한 이야기를 담은 책들이 많은데, 이 책은 SEO 컨설팅 출신의 창업자가 직접 본인의 서비스를 마케팅하고 왜 그로스해킹보다는 플라이휠에 집중해야 하는지를 전문 마케터의 시선으로 정리한 챕터들이 있어서 새로웠다.&lt;/p&gt;
&lt;p&gt;하드씽보다 좀 더 구체적인 시선이 많았다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;빅테크 엔지니어 vs 스타트업 창업자의 비교&lt;/li&gt;
&lt;li&gt;컨설팅 vs 소프트웨어 기업&lt;/li&gt;
&lt;li&gt;네트워크와 그로스 해킹&lt;/li&gt;
&lt;li&gt;대표가 기술을 모를 때의 소프트웨어 기업 운영 방법&lt;/li&gt;
&lt;li&gt;1개의 서비스가 잘 될때 여러 서비스로 확장을 하면 안되는 이유&lt;/li&gt;
&lt;li&gt;창업자가 대표 자리를 물려줘야하는 상황 등등.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;완전 대박으로 성공했거나, 완전 망했거나와 같이 극단적인 상위 0.1%의 이야기가 아닌 상위 3%의 이야기라서 그래도 좀 더 현실적이였다.&lt;/p&gt;
&lt;p&gt;연매출 1,000억의 SaaS라면 충분히 본인이 잘한 점도 많고, 영웅시할 수 있는 부분도 많을 텐데 이 책은 철저하게 &lt;strong&gt;본인이 못했던 점, 약점을 중심으로 드러내고 조언한다&lt;/strong&gt;.&lt;br&gt;(특히 SaaS는 밸류에이션 평가 공식이 일반적인 기업과는 다르게 멀티플이 엄청 높은데도 말이다.)&lt;/p&gt;
&lt;p&gt;밑 줄 그은 곳이 너무 많아서 책의 두께가 2배가 되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-filename="book.jpg" data-origin-width="3024" data-origin-height="4032"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/KT2P7/dJMcagLx51J/oJtNneTZWW8zKgJUkDQ1tK/img.jpg" data-phocus="https://blog.kakaocdn.net/dn/KT2P7/dJMcagLx51J/oJtNneTZWW8zKgJUkDQ1tK/img.jpg"&gt;&lt;img src="https://blog.kakaocdn.net/dn/KT2P7/dJMcagLx51J/oJtNneTZWW8zKgJUkDQ1tK/img.jpg" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKT2P7%2FdJMcagLx51J%2FoJtNneTZWW8zKgJUkDQ1tK%2Fimg.jpg" onerror="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';" loading="lazy" width="507" height="676" data-filename="book.jpg" data-origin-width="3024" data-origin-height="4032"&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;오고 가는 출퇴근 시간을 잘 활용해서 봤다. 30분씩 나눠서 보면 8시간 정도면 거의 다 볼 수 있을정도로 술술 읽히는 책이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-filename="catbook.jpg" data-origin-width="1080" data-origin-height="2400"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/b5tZTR/dJMcaflyAj3/cGCsxOrujDqVtwcIwKBkJ1/img.jpg" data-phocus="https://blog.kakaocdn.net/dn/b5tZTR/dJMcaflyAj3/cGCsxOrujDqVtwcIwKBkJ1/img.jpg"&gt;&lt;img src="https://blog.kakaocdn.net/dn/b5tZTR/dJMcaflyAj3/cGCsxOrujDqVtwcIwKBkJ1/img.jpg" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5tZTR%2FdJMcaflyAj3%2FcGCsxOrujDqVtwcIwKBkJ1%2Fimg.jpg" onerror="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';" loading="lazy" width="517" height="1149" data-filename="catbook.jpg" data-origin-width="1080" data-origin-height="2400"&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;스타트업의 대표님들, 창업자분들이라면 당연히 추천드리고,&lt;br&gt;그 외 스타트업의 리더, 스타트업 합류를 고민하는 분들에게도 추천드린다.&lt;br&gt;완전히 현실적인 이야기들을 볼 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;다만 요즘의 스타트업 투자 분위기와는 좀 다르긴해서 그 점은 감안해서 보면 좋다.&lt;br&gt;이 책에서 언급한 것처럼 10배, 100배 성공만을 성공으로 취급해서 Exit 할 수 있는 상황을 반대하는 VC 분위기가 요즘은 좀 많이 줄어든 것 같다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;ps) 아참 p.39 를 보면 중복된 문장이 있다.&lt;br&gt;"일감을 거절할 때마다 내 머릿속 뒤편에선 찜찜한 기분이 들었다.&lt;br&gt;우리가 기회를 날리고 있는 건 아닐까?&lt;br&gt;SEOmoz는 더 큰 무언가가 될 수 있지 않을까?"&lt;br&gt;(출판사 대표님께서 잘 수정해주시겠지...?)&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;ps) 반기문 유엔 사무총장님이 책에 등장한다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;h2&gt;책 속 문장&lt;/h2&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[스타트업의 치트키]&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;소프트웨어 엔지니어 채용은 창업자가 직접 하는게 최고다&lt;/strong&gt;.&lt;br&gt;흥미로워 보이는 사람을 찾고, 인맥을 뒤져 연결 고리를 찾고, 소개 받고, 커피 한잔하고, 우리 회사 '뽕'을 주입해라.&lt;br&gt;만약 그 사람이 관심 없다면 주변에 괜찮은 사람 없는지 물어봐라.&lt;br&gt;그 모임 멤버 중 외부 리크루터 써서 성공했다는 사람은 한 명도 없었다.&lt;br&gt;(적어도 초기 단계에서는)&lt;br&gt;p.9&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[진실이 너희를 자유케 하리라]&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;진실을 숨길 수 있다고 믿는 순간, 나쁜 짓을 막아주는 브레이크가 고장 난다&lt;/strong&gt;.&lt;br&gt;...&lt;br&gt;투명성은 정직함과는 다르다.&lt;br&gt;정직함이 거짓말을 안 하는 것이라면, &lt;strong&gt;투명성은 남들이 굳이 말 안하고 넘어갈 치부까지 끄집어내는 것&lt;/strong&gt;이다.&lt;br&gt;...&lt;br&gt;&lt;strong&gt;투명성에는 공감이 필요하다&lt;/strong&gt;.&lt;br&gt;그냥 대놓고 "너 헤어 스타일 개구려" 라고 말하는 건 투명한 게 아니라 싸가지가 없는거다.&lt;br&gt;...&lt;br&gt;나는 CEO로서 항상 이렇게 말한다.&lt;br&gt;"이 이메일과 대화가 언젠가 전부 공개된다고 생각하고 행동하라"&lt;br&gt;p.29&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;효과적인 제품 중심 비즈니스에는 두 가지 핵심 특성이 있다.&lt;br&gt;첫째는 도달 범위, 즉 대규모 대중에게 영향력을 발휘할 수 있는 능력이다.&lt;br&gt;둘째는 확장성, 즉 비용이 늘어나는 속도보다 매출을 훨씬 빠르게 키울 수 있는 역량이다.&lt;br&gt;...&lt;br&gt;2007년, 이제 막 싹튼 소프트웨어 구독 비즈니스와 수년 된 컨설팅 비즈니스를 비교해 봤을 때, 우리의 무게 중심이 소프트웨어 쪽으로 쏠리는 건 당연했다.&lt;br&gt;그게 모두에게 정답이라서가 아니라, &lt;strong&gt;우리에게 맞았기 때문이다&lt;/strong&gt;.&lt;br&gt;내가 가장 좋아하는 일(사람들 돕기, 글쓰기, 강연, 커뮤니티 만들기) 은 고객을 끌어모으는 마케팅 채널이 되었다.&lt;br&gt;p.40&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;Moz가 소프트웨어로 확장할 수 있었던 건 대규모 청중을 모았기 때문이다.&lt;br&gt;단기적으로는 서비스 고객을, 장기적으로는 제품 구매자를 아우를 수 있는 마케팅 채널을 미리 만들어두면 게임 끝이다.&lt;br&gt;...&lt;br&gt;&lt;strong&gt;새 아이디어에 미쳐서 컨설팅 사업을 등한시하지마라&lt;/strong&gt;.&lt;br&gt;제품 개발에 '몰빵' 하고 싶겠지만, 컨설팅 매출이 끊기거나 퀄리티가 떨어지면 모험은 시작도 전에 끝장날 수 있다.&lt;br&gt;p.47&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[위대한 창업가는 '하고 싶은 일'을 하지 않는다]&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;스타트업 CEO는 당신이 사랑하는 일을 하게 해주는 직업이 아니다&lt;/strong&gt;.&lt;br&gt;대신 스타트업은 당신이 사랑하는 비전을 만들고 그것이 실현되는 걸 끝까지 지켜볼 능력을 준다.&lt;br&gt;당신은 이렇게 말할 수 있게 된다.&lt;br&gt;"&lt;strong&gt;지금 세상은 이렇게 돌아가지만, 내가 만들 회사가 존재하게 되면, 그리고 그 미션을 수행할 규모에 도달하면, 세상은 이렇게 바뀔 것이다&lt;/strong&gt;."&lt;br&gt;만약 당신이 열정의 대상을 "난 이 일을 하고 싶어" 에서 "내가 만든 무언가가 세상을 이렇게 바꾸는 걸 보고 싶어" 로 재설정 할 수 있다면, 당신의 기대는 현실과 일치하게 될 것이고, 사랑하는 일에서 뜯겨 나가는데서 오는 인지 부조화와 좌절감은 사라질 것이다.&lt;br&gt;p.55&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[창업자의 멘탈이 쓰레기라면, 회사도 결국 쓰레기가 된다]&lt;/p&gt;
&lt;p&gt;한 사람의 약점을 다른 사람의 강점이 커버해주는 균형 잡힌 팀이 엄청난 성공을 거둘 수 있다는 건 사실이다.&lt;br&gt;하지만 잘 알려지지 않은 사실, 그리고 보통 수년간 운영해보고 나서야 드러나는 사실은 이것이다.&lt;br&gt;&lt;strong&gt;창업자의 속성은 조직에 거의 영구적으로 박제되는 반면, 직원들의 속성은 시간이 지나면서 변한다&lt;/strong&gt;.&lt;br&gt;부분적으로는 창업자가 훨씬 오래 남아 더 오랫동안 영향력을 행사하기 때문이다.&lt;br&gt;하지만 팀을 유지한다 해도, &lt;strong&gt;창업자의 편향, 그들이 만든 비즈니스 구조, 채용 방식, 위임 방식, 자원 배분, 열정, 그리고 맹점에서 비롯된 지울 수 없는 각인이 남는다&lt;/strong&gt;.&lt;br&gt;나는 모든 규모, 산업, 구성의 회사에서 이 패턴이 반복되는 걸 본다.&lt;br&gt;&lt;strong&gt;창업자(와 CEO)는 조직의 성격과 문화뿐만 아니라, 수년 혹은 수십 년간 조직의 궤적을 지배하는 근본적인 강점과 약점을 지배&lt;/strong&gt;한다.&lt;br&gt;p.77&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;벤, 닉, 채스를 만난 것은 행운이었다.&lt;br&gt;남들이 불가능하다고 했던 제품을 만들어낸 그들의 성공은 내게 잘못된 자신감을 심어주었다.&lt;br&gt;&lt;strong&gt;나는 내 강점에 집중하고 모즈의 약점은 채용으로 보완할 수 있다고 생각했다&lt;/strong&gt;.&lt;br&gt;하지만 그건 통하지 않았다.&lt;br&gt;여러 명의 CTO와 다양한 규모 및 구성의 수많은 엔지니어링 팀을 거치면서도, 우리는 벤과 그의 팀이 링크 문제에서 보여주었던 마법을 다시 재현할 수 없었다.&lt;br&gt;p.81&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;모든 창업자는 회사를 만들 때 가장 어려운 부분에 대해 각자 다른 의견을 가지고 있다.&lt;br&gt;쉬운 부분에 대해서도 마찬가지다.&lt;br&gt;...&lt;br&gt;기묘한 진실은 그 "가장 어려운 부분"과 "가장 쉬운 부분"은 과제의 난이도보다는 창업자의 강점과 약점을 더 많이 보여준다는 것이다.&lt;br&gt;...&lt;br&gt;"약점은 훌륭한 인재를 채용해서 보완하라" 는 통념이 완전히 틀린 건 아니다.&lt;br&gt;하지만 이 조언을 따를 땐 반드시 다음 세가지 경고를 명심해라.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;어떤 분야에 대한 깊은 지식과 이해가 없으면, 그 분야의 인맥도 없을 것이고, 누가 진짜 실력자인지 구분하기도 힘들며, 훌륭한 인재를 설득해서 데려오기도 어렵다.&lt;/li&gt;
&lt;li&gt;창업가의 약점은 종종 회사의 DNA에 박제되어 일종의 '부채'를 만든다.&lt;br&gt;사람 관리 기술이 없다면? 대인 관계 갈등을 파헤치고, 누군가를 해고하고 다시 뽑고, 신뢰를 쌓는 프로세스를 만드느라 몇 달을 허비해야하는 '조직 부채'가 된다.&lt;/li&gt;
&lt;li&gt;약점을 보완하기 위해 누군가에게 의존한다면, 그들이 떠나는 순간 상처가 다시 벌어질 위험이 생긴다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;...&lt;br&gt;내 재입 기간 내내 회사의 고질적 약점이었던 엔지니어링을 취임 18개월 만에 핵심 강점으로 바꾸는 걸 목격했다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;건너뛰기 회의(직속 상사를 건너뛰고 팀원과 직접 만나는 회의)에서 질문해라.&lt;br&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;strong&gt;가르치는 성향을 가진 기술 리더를 채용해라&lt;/strong&gt;.&lt;br&gt;세부 사항으로부터 당신을 "보호"하려는 CTO를 경계해라&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;복잡한 걸 쉽게 설명하는 건 직무 필수 요건&lt;/strong&gt;이다.&lt;br&gt;6. 결국 기술 팀을 이끄는 건 호기심과 용기다.&lt;/p&gt;
&lt;p&gt;p.85&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[엉뚱한 이유로, 혹은 엉뚱한 놈들에게 투자받지 마라]&lt;/p&gt;
&lt;p&gt;벤처 투자를 고려하는 사람이라면 적어도 이 결정적인 교훈 하나는 챙겨가야 한다.&lt;br&gt;당신의 비즈니스가 '&lt;strong&gt;수많은 실패 속 소수의 미친 대박을 찾는&lt;/strong&gt;' 벤처 모델과 일치하지 않는다면, 이 길은 당신의 길이 아니다.&lt;br&gt;확률에 익숙해지거나, 주사위를 던지지 마라.&lt;br&gt;&lt;strong&gt;벤처 비즈니스는 아웃라이어를 위한 게임이다&lt;/strong&gt;.&lt;br&gt;...&lt;br&gt;일치(Alignment)란 당신과 회사가 끝장을 보겠다는 뜻이다.&lt;br&gt;&lt;strong&gt;극도로 희박한 수억, 수십억 달러짜리 결과만을 "성공" 이라고 인정한다&lt;/strong&gt;는 뜻이다.&lt;br&gt;수백만 달러를 벌어 당신과 초기 멤버들을 부자로 만들어줄 수 있는 초기 제안들을 거절하고, 미래의 희박한 확률에 베팅한다는 뜻이다.&lt;br&gt;p. 101&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;가능하다면 &lt;strong&gt;네트워크를 쌓기 전에 전문성을 쌓고, 회사를 만들기 전에 네트워크를 쌓아라.&lt;/strong&gt;&lt;br&gt;(전문성 -&amp;gt; 네트워크 -&amp;gt; 회사)&lt;br&gt;스타트업 구축이나 기술의 특정 측면에서 깊은 경험과 기술을 가지고 있어서, 당신과의 1시간 통화가 다른 기업가나 스타트업 팀에게 매우 가치 있게 여겨진다면, 당신은 강력한 네트워크를 구축할 확실하고 매력적인 경로를 가진 셈이다.&lt;br&gt;소수의 사람과 회사의 문제 해결을 도와줘라.&lt;br&gt;그러면 자금 조달 과정에서 당신을 도와줄 네트워크가 저절로 생긴다.&lt;br&gt;그 네트워크가 자금 조달 과정을 '거의 불가능'에서 '해볼 만한 것'으로 바꿔준다.&lt;/p&gt;
&lt;p&gt;p. 113&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[상위 5% 스타트업을 만들어도 넌 부자가 못 될 수도 있다]&lt;/p&gt;
&lt;p&gt;2001년부터 2015년까지 시애틀의 평균 테크 연봉과 같은 기간 내 Moz 수입을 비교한 차트다.&lt;br&gt;(&lt;strong&gt;연매출 5천만 달러의 창업자의 15년 누적 연봉보다 시애틀의 평균 테크 연봉의 누적이 더 높다&lt;/strong&gt;)&lt;br&gt;...&lt;br&gt;일이 잘 풀리면 회사 가치는 오르고, 주식 가치도 따라 오를 것이다.&lt;br&gt;하지만 &lt;strong&gt;현실적으로 당신 (혹은 옵션을 행사한 직원)의 주식은 사려는 사람이 있을 때만 팔 수 있다&lt;/strong&gt;.&lt;br&gt;그리고 사려는 사람은, 빌어먹게도 드물다.&lt;br&gt;...&lt;br&gt;그럼 창업을 하지 말라는 건가? 초기 기업에 가지 말라는 건가?&lt;br&gt;아니다.&lt;br&gt;단지 단기적인 부를 쫓아서 하지 마라는 거다.&lt;br&gt;커리어 전체를 몇 년으로 압축해 갈아 넣으면 그 보상으로 떼돈을 벌 수 있다는 생각은 미친 짓이고, 통계적으로 말도 안 되는 소리다.&lt;br&gt;...&lt;br&gt;창업을 하거나 위험한 초기 벤처에 합류해야 할 논리적이고 멋진 이유는 따로 있다.&lt;br&gt;&lt;strong&gt;가장 큰 이유는 자율성이다&lt;/strong&gt;.&lt;br&gt;무엇을 만들지, 어떻게 일할지, 누구를 채용할지, 조직을 어떻게 굴릴지 스스로 정할 수 있는 자유 말이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;설령 실패한다 해도, 많은 경우 그 경험 자체가 보상이다&lt;/strong&gt;.&lt;br&gt;**스타트업의 가장 큰 장점 중 하나는 커리어 성장 속도를 미친듯이 앞당겨 준다는 것이다.&lt;br&gt;...&lt;br&gt;전략적 비전, 실행력, 리더십을 증명해 보이면, 당신은 현대 경제에서 아주 희귀하고 탐나는 인재가 된다.&lt;br&gt;수많은 초기 기업이 소규모로 인수되는 이유도 바로 이처럼 검증된 인재를 확보하기 위해서다.&lt;/p&gt;
&lt;p&gt;p. 122&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[확장 가능한 마케팅: 플라이휠이 그로스 해킹보다 낫다]&lt;/p&gt;
&lt;p&gt;해킹이라고 부르는 데는 다 이유가 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;낮은 유지율: 1달러 오퍼로 가입한 구독자들은 프로모션이 아닌 일반 오퍼로 가입한 사람들보다 유지율이 훨씬 낮았다.&lt;/li&gt;
&lt;li&gt;할인 중독: 우리 팀은 이 이메일 캠페인이 가져온 매출과 성장에 지나치게 매료됐다.&lt;br&gt;돌이켜보면, 다음번 '대박 해킹'을 찾는 중독 때문에 정작 집중해야 할 장기적인 제품 및 마케팅 투자를 등한시했다.&lt;/li&gt;
&lt;li&gt;브랜드 가치 하락: 대규모 할인 프로모션은, 특히 아주 많은 대중에게 제공될 때 할인과 특별 오퍼가 브랜드 정체성의 일부라는 인상을 준다.&lt;br&gt;이는 &lt;strong&gt;잠재 고객들에게 정가에 구독하기보다 다음 프로모션이 시작될 때까지 기다려야 한다고 학습시키는 결과를 초래&lt;/strong&gt;했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;반면, 구독 제품의 랜딩 페이지에 쏟은 전환율 최적화 (CRO) 노력은 지속적인 성공을 거두었으며, 장기적으로 긍정적인 수익을 안겨주는 투자가 되었다.&lt;br&gt;올바른 타깃을 찾고, 그들의 거부 사유를 파악한 뒤, 랜딩 페이지의 정보를 통해 그 반대 논거를 해소하고 가입 절차를 매끄럽게 만드는 CRO 노력은 단순한 '꼼수'가 아니다.&lt;br&gt;이는 우리 마케팅을 구동하는 근본적인 플라이휠을 개선하는 작업이다.&lt;br&gt;...&lt;br&gt;드롭박스의 해킹은 친구를 추천하면 추천한 사람과 받은 사람 모두에게 계정 혜택(용량)을 더 주는 '양방향 추천 시스템'이었다.&lt;br&gt;수년 동안 이 '해킹'은 마케팅 행사 무대와 웹상의 블로그 포스트에서 다뤄졌다.&lt;br&gt;&lt;strong&gt;이 전술을 끝도 없이 베껴 쓴 다른 기업들은 드롭박스만큼의 효과를 보지 못해 좌절만 맛봤다&lt;/strong&gt;.&lt;br&gt;드롭박스 창업자 드류 휴스턴은 2010년 "스타트업 교훈" 발표에서 "&lt;strong&gt;한 시장 유형에서 통한 마케팅 전술이 다른 시장에서는 처참하게 실패할 수 있다&lt;/strong&gt;" 고 현명하게 지적했다.&lt;br&gt;...&lt;br&gt;어떤 그로스 해킹은 통한다.&lt;br&gt;하지만 대부분은 안 통한다.&lt;br&gt;진짜 교훈은 이것이어야 한다.&lt;br&gt;이 회사들은 혁신적인 마케팅 전술 수십 가지를 시도했고, 이를 강력하고 지속적으로 개선되는 제품 및 수많은 전통적인 마케팅 모범 사례와 결합했다.&lt;br&gt;그리고 그 조합 안에서 몇 가지 특정 전술이 특히 효과를 발휘했던 것이다.&lt;/p&gt;
&lt;p&gt;p. 128&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[진짜 '핵심 가치'는 돈 버는 데 하등 도움이 안 된다]&lt;/p&gt;
&lt;p&gt;"취소하려면 전화를 걸게 만들면, 장담하건대 그 귀찮음만으로도 월 이탈률이 개선될 거야.&lt;br&gt;게다가 취소하려는 사람들과 통화하면서 그들이 누구인지, 왜 떠나는지 훨씬 잘 이해할 수 있잖아.&lt;br&gt;꽤 많은 사람을 붙잡을 수도 있고, 나중에 다시 돌아오게 할 수도 있어.&lt;br&gt;더 싼 요금제로 바꾸거나 다른 제품을 사게 유도할 수도 있고."&lt;br&gt;"네 말이 맞아. 전화로만 취소할 수 있게 만들면 이탈률에 확실히 영향을 줄 거야.&lt;br&gt;하지만 우린 온라인으로 가입해놓고 취소할 때 전화하라는 서비스를 극도로 혐오해.&lt;br&gt;그건 일부러 어렵게 만든 거잖아.&lt;br&gt;그건 공감이 결여된 거고, 즉 TAGFEE가 아니란 소리야."&lt;/p&gt;
&lt;p&gt;"일리 있네, 하지만 너 지금 길바닥에 엄청난 돈을 버리고 있는거야"&lt;/p&gt;
&lt;p&gt;"글쎄, 우린 항상 말하잖아.&lt;br&gt;&lt;strong&gt;돈과 맞바꿀 수 있다면 그건 핵심 가치가 아니라고&lt;/strong&gt;"&lt;br&gt;...&lt;br&gt;"우리 신조에 담긴 핵심 가치가 경쟁 우위가 될 수도 있겠지만, 그래서 우리가 그걸 지키는 건 아니다.&lt;br&gt;&lt;strong&gt;우리는 그 가치가 우리가 지향하는 바를 정의하기 때문에 지키는 것이며, 어떤 상황에서 그것이 경쟁 열위가 된다 해도 우리는 고수할 것이다&lt;/strong&gt;" - 랄프 라르센, 존슨앤드존슨 전 CEO&lt;/p&gt;
&lt;p&gt;p. 146&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[회사를 일찍 매각해야 할까? 그래, 십중팔구는 그게 답이다.]&lt;/p&gt;
&lt;p&gt;외부 자본을 유치하는 순간, 당신의 목표는 필연적으로 매각이나 상장을 통해 그 자본의 몇 배를 돌려주는 것으로 바뀐다.&lt;br&gt;...&lt;br&gt;내가 아는 많은 창업자는 엑싯 과정에서 그리 큰 돈을 벌지 못했다.&lt;br&gt;하지만 투자자에게 수익을 돌려주고 유동성 이벤트를 달성한 이상, 그들은 평생 자신의 이력에 '성공한 기업가' 라는 칭호를 달 수 있다.&lt;br&gt;당신은 이게 터무니없는 헛소리라고 생각할지도 모른다.&lt;br&gt;작은 스타트업의 소소한 엑싯이 어떻게 '성공'과 동급일 수 있느냐고, 오히려 Moz처럼 연 매출 4,000만 달러가 넘는 비즈니스를 바닥부터 일군 것이야말로 진정한 '성공' 이 아니냐고 반문할 수도 있다.&lt;br&gt;...&lt;br&gt;&lt;strong&gt;성공적인 엑싯에 참여한 스타트업 직원은 설명하기 힘든 수준의 신뢰도와 엄청난 가치를 지닌 사람이라는 아우라를 얻는다&lt;/strong&gt;.&lt;br&gt;"저는 XYZ 회사의 초창기 멤버였고, 그 회사가 어디에 인수될 때 함께했습니다" 라고 말할 수 있는 능력은 실리콘밸리에 서식하는 기술자, 기업가, 투자자들의 하위문화에서 엄청난 무게감을 갖는다.&lt;br&gt;...&lt;br&gt;스타트업은 관련된 모든 이에게 - 창업자, 직원, 가족, 그리고 고객과 투자자에게까지 - 가혹할 만큼 고통스러운 고행이다.&lt;br&gt;대부분의 기관 투자자 모델은 소규모 엑싯과는 본질적으로 맞지 않는다.&lt;br&gt;그래서 실리콘밸리의 스타트업 문화는 수백만 달러나 수천만 달러에 회사를 파는 것을 '변절' 이라 부르며, '진짜 회사'를 만드는데 실패한 것이라는 지배적인 내러티브를 만들어 낸다.&lt;br&gt;만약 당신이 창업자거나 초기 직원이거나, 혹은 그들을 아끼는 사람이라면 나는 당신에게 이 편향되고 투자자에게만 유리한 사고방식을 완전히 거부하라고 촉구한다.&lt;br&gt;&lt;strong&gt;당신도 IP나 10억 달러짜리 매각이 더 작은 성과를 희생해서라도 추구해야 할 절대 선이라는 강박을 버려야 한다&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;p. 214&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[취약함을 드러내는 것 !== 약해빠진 것]&lt;/p&gt;
&lt;p&gt;나는 시간을 들여 &lt;strong&gt;사람들을 일대일로 만나 계획을 설명하고 피드백, 질문, 우려 사항을 묻는 게 훨씬 효과적&lt;/strong&gt;이었다.&lt;br&gt;맞다, 시간이 훨씬 많이 걸린다.&lt;br&gt;하지만 &lt;strong&gt;다 같이 모이거나 본격적으로 일을 시작할 때쯤이면, 큰 갈등들은 이미 다 생각하고 해결된 상태라는 뜻&amp;amp;_&amp;amp;이기도 하다.&lt;br&gt;이건 프로젝트 기여자들만을 위한 게 아니다.&lt;br&gt;리더와 매니저를 위한 것이기도 하다.&lt;br&gt;그룹 앞에서 내 아이디어와 계획을 방어하는 건 정말 불편하고, 실수를 인정하거나 즉성에서 수정하는 건 더 어렵다.&lt;br&gt;하지만 *_팀원들과 일대일로 소통하고 최종 계획을 발표하거나 시작하기 전에 모두의 우려를 미리 파악해 두는 건 훨씬 더 편안하다&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;p. 244&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[집중해라]&lt;/p&gt;
&lt;p&gt;Moz라는 이름에 적당히 괜찮은 제품만 얹어서 매월 수백만 명의 방문자에게 들이밀면 팔릴 거라고 확신했다.&lt;br&gt;...&lt;br&gt;웹사이트 방문자에게 8가지 다른 물건을 파는 건 2~3개를 파는 것보다 훨씬 더 어려웠다.&lt;br&gt;회사 내부 조직을 8개 제품을 지원하도록 구성하는 건 더욱더 어려웠다.&lt;br&gt;...&lt;br&gt;마치 믹스에 새로운 제품을 하나 추가할 때마다 기존의 다른 모든 제품의 성장을 조금씩 갉아먹는 것 같았다.&lt;br&gt;...&lt;br&gt;줄어드는 매출을 막기 위해 신규 고객 획득에 너무 의존하다 보니, 회사의 우선순위가 '신규 고객용 제품 개발'과 '기존 고객 유지 개선' 사이에서 쪼개질 수밖에 없다.&lt;br&gt;이제 그걸 4개의 다른 제품에 곱해보라.&lt;br&gt;...&lt;br&gt;우선순위를 추가할 때 복잡성이 선형적이 아니라 기하급수적으로 늘어난다는 사실을 아는 건 도움이 된다.&lt;br&gt;더 적은 사람들이 오직 소수의 것들에만 집중함으로써, 수많은 방향으로 찢어진 훨씬 더 큰 팀보다 더 많은 것을 해낼 수 있었다.&lt;br&gt;...&lt;br&gt;"우리 핵심 제품은 성장하고 있지만, 만약 우리가... 하면 더 빨리 클 수 잇을텐데." 그 빈칸을 채우는 건 위험하다.&lt;br&gt;복잡성을 더하고 집중력을 앗아가는 것들이 그 자리를 차지하기 때문이다.&lt;br&gt;...&lt;br&gt;훨씬 더 현명한 길은, &lt;strong&gt;훈련과 인내심을 가지고 곁길을 무시하며, 당신이 세계 최고가 될 수 있는 오직 한 가지에 실험, 학습, 반복을 쏟아붓는 것이다&lt;/strong&gt;.&lt;br&gt;성장을 위한 다른 전략들은 당신이 진정으로 거대한 규모를 갖출 떄까지 기다려야 한다.&lt;/p&gt;
&lt;p&gt;p. 299&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://jojoldu.tistory.com/871</id>
    <link href="https://jojoldu.tistory.com/871"/>
    <summary type="html">&lt;p&gt;SEO의 절대 강자이자 &lt;strong&gt;연 반복매출 4천만 달러(현재 기준: 600억원)&lt;/strong&gt; SaaS인 Moz의 공동 창업자이자 전 CEO 랜드 피쉬킨의 창업부터 회사를 떠날때까지의 경험을 정리한 책이다.&lt;br&gt;(2020년에는 6,740만 달러 - 1천억원 매출이었다고 한다)&lt;/p&gt;
&lt;p&gt;박소령 대표님의 &amp;quot;실패를 통과하는 일&amp;quot;과는 다른 결말을 맞이한 이야기를 본 것 같았다.&lt;/p&gt;
&lt;p&gt;책의 제목과 소개가 강렬해서 선입견이 생길 수도 있는데, &amp;quot;실리콘밸리의 선입견에서 벗어나야 한다&amp;quot;보다는 연 반복매출 500억을 달성한 SaaS 스타트업 창업자의 경험 기반 조언들이 가득한 책이었다.&lt;/p&gt;
&lt;p&gt;제품을 직접 만드는 창업자들이 많다 보니 제품 전략, 제품 설계, 고객 가치 등에 대한 이야기를 담은 책들이 많은데, 이 책은 SEO 컨설팅 출신의 창업자가 직접 본인의 서비스를 마케팅하고 왜 그로스해킹보다는 플라이휠에 집중해야 하는지를 전문 마케터의 시선으로 정리한 챕터들이 있어서 새로웠다.&lt;/p&gt;
&lt;p&gt;하드씽보다 좀 더 구체적인 시선이 많았다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;빅테크 엔지니어 vs 스타트업 창업자의 비교&lt;/li&gt;
&lt;li&gt;컨설팅 vs 소프트웨어 기업&lt;/li&gt;
&lt;li&gt;네트워크와 그로스 해킹&lt;/li&gt;
&lt;li&gt;대표가 기술을 모를 때의 소프트웨어 기업 운영 방법&lt;/li&gt;
&lt;li&gt;1개의 서비스가 잘 될때 여러 서비스로 확장을 하면 안되는 이유&lt;/li&gt;
&lt;li&gt;창업자가 대표 자리를 물려줘야하는 상황 등등.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;완전 대박으로 성공했거나, 완전 망했거나와 같이 극단적인 상위 0.1%의 이야기가 아닌 상위 3%의 이야기라서 그래도 좀 더 현실적이였다.&lt;/p&gt;
&lt;p&gt;연매출 1,000억의 SaaS라면 충분히 본인이 잘한 점도 많고, 영웅시할 수 있는 부분도 많을 텐데 이 책은 철저하게 &lt;strong&gt;본인이 못했던 점, 약점을 중심으로 드러내고 조언한다&lt;/strong&gt;.&lt;br&gt;(특히 SaaS는 밸류에이션 평가 공식이 일반적인 기업과는 다르게 멀티플이 엄청 높은데도 말이다.)&lt;/p&gt;
&lt;p&gt;밑 줄 그은 곳이 너무 많아서 책의 두께가 2배가 되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-filename="book.jpg" data-origin-width="3024" data-origin-height="4032"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/KT2P7/dJMcagLx51J/oJtNneTZWW8zKgJUkDQ1tK/img.jpg" data-phocus="https://blog.kakaocdn.net/dn/KT2P7/dJMcagLx51J/oJtNneTZWW8zKgJUkDQ1tK/img.jpg"&gt;&lt;img src="https://blog.kakaocdn.net/dn/KT2P7/dJMcagLx51J/oJtNneTZWW8zKgJUkDQ1tK/img.jpg" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKT2P7%2FdJMcagLx51J%2FoJtNneTZWW8zKgJUkDQ1tK%2Fimg.jpg" onerror="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';" loading="lazy" width="507" height="676" data-filename="book.jpg" data-origin-width="3024" data-origin-height="4032"/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;오고 가는 출퇴근 시간을 잘 활용해서 봤다. 30분씩 나눠서 보면 8시간 정도면 거의 다 볼 수 있을정도로 술술 읽히는 책이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-filename="catbook.jpg" data-origin-width="1080" data-origin-height="2400"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/b5tZTR/dJMcaflyAj3/cGCsxOrujDqVtwcIwKBkJ1/img.jpg" data-phocus="https://blog.kakaocdn.net/dn/b5tZTR/dJMcaflyAj3/cGCsxOrujDqVtwcIwKBkJ1/img.jpg"&gt;&lt;img src="https://blog.kakaocdn.net/dn/b5tZTR/dJMcaflyAj3/cGCsxOrujDqVtwcIwKBkJ1/img.jpg" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5tZTR%2FdJMcaflyAj3%2FcGCsxOrujDqVtwcIwKBkJ1%2Fimg.jpg" onerror="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';" loading="lazy" width="517" height="1149" data-filename="catbook.jpg" data-origin-width="1080" data-origin-height="2400"/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;스타트업의 대표님들, 창업자분들이라면 당연히 추천드리고,&lt;br&gt;그 외 스타트업의 리더, 스타트업 합류를 고민하는 분들에게도 추천드린다.&lt;br&gt;완전히 현실적인 이야기들을 볼 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;다만 요즘의 스타트업 투자 분위기와는 좀 다르긴해서 그 점은 감안해서 보면 좋다.&lt;br&gt;이 책에서 언급한 것처럼 10배, 100배 성공만을 성공으로 취급해서 Exit 할 수 있는 상황을 반대하는 VC 분위기가 요즘은 좀 많이 줄어든 것 같다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;ps) 아참 p.39 를 보면 중복된 문장이 있다.&lt;br&gt;&amp;quot;일감을 거절할 때마다 내 머릿속 뒤편에선 찜찜한 기분이 들었다.&lt;br&gt;우리가 기회를 날리고 있는 건 아닐까?&lt;br&gt;SEOmoz는 더 큰 무언가가 될 수 있지 않을까?&amp;quot;&lt;br&gt;(출판사 대표님께서 잘 수정해주시겠지...?)&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;ps) 반기문 유엔 사무총장님이 책에 등장한다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h2&gt;책 속 문장&lt;/h2&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[스타트업의 치트키]&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;소프트웨어 엔지니어 채용은 창업자가 직접 하는게 최고다&lt;/strong&gt;.&lt;br&gt;흥미로워 보이는 사람을 찾고, 인맥을 뒤져 연결 고리를 찾고, 소개 받고, 커피 한잔하고, 우리 회사 &amp;#39;뽕&amp;#39;을 주입해라.&lt;br&gt;만약 그 사람이 관심 없다면 주변에 괜찮은 사람 없는지 물어봐라.&lt;br&gt;그 모임 멤버 중 외부 리크루터 써서 성공했다는 사람은 한 명도 없었다.&lt;br&gt;(적어도 초기 단계에서는)&lt;br&gt;p.9&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[진실이 너희를 자유케 하리라]&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;진실을 숨길 수 있다고 믿는 순간, 나쁜 짓을 막아주는 브레이크가 고장 난다&lt;/strong&gt;.&lt;br&gt;...&lt;br&gt;투명성은 정직함과는 다르다.&lt;br&gt;정직함이 거짓말을 안 하는 것이라면, &lt;strong&gt;투명성은 남들이 굳이 말 안하고 넘어갈 치부까지 끄집어내는 것&lt;/strong&gt;이다.&lt;br&gt;...&lt;br&gt;&lt;strong&gt;투명성에는 공감이 필요하다&lt;/strong&gt;.&lt;br&gt;그냥 대놓고 &amp;quot;너 헤어 스타일 개구려&amp;quot; 라고 말하는 건 투명한 게 아니라 싸가지가 없는거다.&lt;br&gt;...&lt;br&gt;나는 CEO로서 항상 이렇게 말한다.&lt;br&gt;&amp;quot;이 이메일과 대화가 언젠가 전부 공개된다고 생각하고 행동하라&amp;quot;&lt;br&gt;p.29&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;효과적인 제품 중심 비즈니스에는 두 가지 핵심 특성이 있다.&lt;br&gt;첫째는 도달 범위, 즉 대규모 대중에게 영향력을 발휘할 수 있는 능력이다.&lt;br&gt;둘째는 확장성, 즉 비용이 늘어나는 속도보다 매출을 훨씬 빠르게 키울 수 있는 역량이다.&lt;br&gt;...&lt;br&gt;2007년, 이제 막 싹튼 소프트웨어 구독 비즈니스와 수년 된 컨설팅 비즈니스를 비교해 봤을 때, 우리의 무게 중심이 소프트웨어 쪽으로 쏠리는 건 당연했다.&lt;br&gt;그게 모두에게 정답이라서가 아니라, &lt;strong&gt;우리에게 맞았기 때문이다&lt;/strong&gt;.&lt;br&gt;내가 가장 좋아하는 일(사람들 돕기, 글쓰기, 강연, 커뮤니티 만들기) 은 고객을 끌어모으는 마케팅 채널이 되었다.&lt;br&gt;p.40&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;Moz가 소프트웨어로 확장할 수 있었던 건 대규모 청중을 모았기 때문이다.&lt;br&gt;단기적으로는 서비스 고객을, 장기적으로는 제품 구매자를 아우를 수 있는 마케팅 채널을 미리 만들어두면 게임 끝이다.&lt;br&gt;...&lt;br&gt;&lt;strong&gt;새 아이디어에 미쳐서 컨설팅 사업을 등한시하지마라&lt;/strong&gt;.&lt;br&gt;제품 개발에 &amp;#39;몰빵&amp;#39; 하고 싶겠지만, 컨설팅 매출이 끊기거나 퀄리티가 떨어지면 모험은 시작도 전에 끝장날 수 있다.&lt;br&gt;p.47&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[위대한 창업가는 &amp;#39;하고 싶은 일&amp;#39;을 하지 않는다]&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;스타트업 CEO는 당신이 사랑하는 일을 하게 해주는 직업이 아니다&lt;/strong&gt;.&lt;br&gt;대신 스타트업은 당신이 사랑하는 비전을 만들고 그것이 실현되는 걸 끝까지 지켜볼 능력을 준다.&lt;br&gt;당신은 이렇게 말할 수 있게 된다.&lt;br&gt;&amp;quot;&lt;strong&gt;지금 세상은 이렇게 돌아가지만, 내가 만들 회사가 존재하게 되면, 그리고 그 미션을 수행할 규모에 도달하면, 세상은 이렇게 바뀔 것이다&lt;/strong&gt;.&amp;quot;&lt;br&gt;만약 당신이 열정의 대상을 &amp;quot;난 이 일을 하고 싶어&amp;quot; 에서 &amp;quot;내가 만든 무언가가 세상을 이렇게 바꾸는 걸 보고 싶어&amp;quot; 로 재설정 할 수 있다면, 당신의 기대는 현실과 일치하게 될 것이고, 사랑하는 일에서 뜯겨 나가는데서 오는 인지 부조화와 좌절감은 사라질 것이다.&lt;br&gt;p.55&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[창업자의 멘탈이 쓰레기라면, 회사도 결국 쓰레기가 된다]&lt;/p&gt;
&lt;p&gt;한 사람의 약점을 다른 사람의 강점이 커버해주는 균형 잡힌 팀이 엄청난 성공을 거둘 수 있다는 건 사실이다.&lt;br&gt;하지만 잘 알려지지 않은 사실, 그리고 보통 수년간 운영해보고 나서야 드러나는 사실은 이것이다.&lt;br&gt;&lt;strong&gt;창업자의 속성은 조직에 거의 영구적으로 박제되는 반면, 직원들의 속성은 시간이 지나면서 변한다&lt;/strong&gt;.&lt;br&gt;부분적으로는 창업자가 훨씬 오래 남아 더 오랫동안 영향력을 행사하기 때문이다.&lt;br&gt;하지만 팀을 유지한다 해도, &lt;strong&gt;창업자의 편향, 그들이 만든 비즈니스 구조, 채용 방식, 위임 방식, 자원 배분, 열정, 그리고 맹점에서 비롯된 지울 수 없는 각인이 남는다&lt;/strong&gt;.&lt;br&gt;나는 모든 규모, 산업, 구성의 회사에서 이 패턴이 반복되는 걸 본다.&lt;br&gt;&lt;strong&gt;창업자(와 CEO)는 조직의 성격과 문화뿐만 아니라, 수년 혹은 수십 년간 조직의 궤적을 지배하는 근본적인 강점과 약점을 지배&lt;/strong&gt;한다.&lt;br&gt;p.77&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;벤, 닉, 채스를 만난 것은 행운이었다.&lt;br&gt;남들이 불가능하다고 했던 제품을 만들어낸 그들의 성공은 내게 잘못된 자신감을 심어주었다.&lt;br&gt;&lt;strong&gt;나는 내 강점에 집중하고 모즈의 약점은 채용으로 보완할 수 있다고 생각했다&lt;/strong&gt;.&lt;br&gt;하지만 그건 통하지 않았다.&lt;br&gt;여러 명의 CTO와 다양한 규모 및 구성의 수많은 엔지니어링 팀을 거치면서도, 우리는 벤과 그의 팀이 링크 문제에서 보여주었던 마법을 다시 재현할 수 없었다.&lt;br&gt;p.81&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;모든 창업자는 회사를 만들 때 가장 어려운 부분에 대해 각자 다른 의견을 가지고 있다.&lt;br&gt;쉬운 부분에 대해서도 마찬가지다.&lt;br&gt;...&lt;br&gt;기묘한 진실은 그 &amp;quot;가장 어려운 부분&amp;quot;과 &amp;quot;가장 쉬운 부분&amp;quot;은 과제의 난이도보다는 창업자의 강점과 약점을 더 많이 보여준다는 것이다.&lt;br&gt;...&lt;br&gt;&amp;quot;약점은 훌륭한 인재를 채용해서 보완하라&amp;quot; 는 통념이 완전히 틀린 건 아니다.&lt;br&gt;하지만 이 조언을 따를 땐 반드시 다음 세가지 경고를 명심해라.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;어떤 분야에 대한 깊은 지식과 이해가 없으면, 그 분야의 인맥도 없을 것이고, 누가 진짜 실력자인지 구분하기도 힘들며, 훌륭한 인재를 설득해서 데려오기도 어렵다.&lt;/li&gt;
&lt;li&gt;창업가의 약점은 종종 회사의 DNA에 박제되어 일종의 &amp;#39;부채&amp;#39;를 만든다.&lt;br&gt;사람 관리 기술이 없다면? 대인 관계 갈등을 파헤치고, 누군가를 해고하고 다시 뽑고, 신뢰를 쌓는 프로세스를 만드느라 몇 달을 허비해야하는 &amp;#39;조직 부채&amp;#39;가 된다.&lt;/li&gt;
&lt;li&gt;약점을 보완하기 위해 누군가에게 의존한다면, 그들이 떠나는 순간 상처가 다시 벌어질 위험이 생긴다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;...&lt;br&gt;내 재입 기간 내내 회사의 고질적 약점이었던 엔지니어링을 취임 18개월 만에 핵심 강점으로 바꾸는 걸 목격했다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;건너뛰기 회의(직속 상사를 건너뛰고 팀원과 직접 만나는 회의)에서 질문해라.&lt;br&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;strong&gt;가르치는 성향을 가진 기술 리더를 채용해라&lt;/strong&gt;.&lt;br&gt;세부 사항으로부터 당신을 &amp;quot;보호&amp;quot;하려는 CTO를 경계해라&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;복잡한 걸 쉽게 설명하는 건 직무 필수 요건&lt;/strong&gt;이다.&lt;br&gt;6. 결국 기술 팀을 이끄는 건 호기심과 용기다.&lt;/p&gt;
&lt;p&gt;p.85&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[엉뚱한 이유로, 혹은 엉뚱한 놈들에게 투자받지 마라]&lt;/p&gt;
&lt;p&gt;벤처 투자를 고려하는 사람이라면 적어도 이 결정적인 교훈 하나는 챙겨가야 한다.&lt;br&gt;당신의 비즈니스가 &amp;#39;&lt;strong&gt;수많은 실패 속 소수의 미친 대박을 찾는&lt;/strong&gt;&amp;#39; 벤처 모델과 일치하지 않는다면, 이 길은 당신의 길이 아니다.&lt;br&gt;확률에 익숙해지거나, 주사위를 던지지 마라.&lt;br&gt;&lt;strong&gt;벤처 비즈니스는 아웃라이어를 위한 게임이다&lt;/strong&gt;.&lt;br&gt;...&lt;br&gt;일치(Alignment)란 당신과 회사가 끝장을 보겠다는 뜻이다.&lt;br&gt;&lt;strong&gt;극도로 희박한 수억, 수십억 달러짜리 결과만을 &amp;quot;성공&amp;quot; 이라고 인정한다&lt;/strong&gt;는 뜻이다.&lt;br&gt;수백만 달러를 벌어 당신과 초기 멤버들을 부자로 만들어줄 수 있는 초기 제안들을 거절하고, 미래의 희박한 확률에 베팅한다는 뜻이다.&lt;br&gt;p. 101&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;가능하다면 &lt;strong&gt;네트워크를 쌓기 전에 전문성을 쌓고, 회사를 만들기 전에 네트워크를 쌓아라.&lt;/strong&gt;&lt;br&gt;(전문성 -&amp;gt; 네트워크 -&amp;gt; 회사)&lt;br&gt;스타트업 구축이나 기술의 특정 측면에서 깊은 경험과 기술을 가지고 있어서, 당신과의 1시간 통화가 다른 기업가나 스타트업 팀에게 매우 가치 있게 여겨진다면, 당신은 강력한 네트워크를 구축할 확실하고 매력적인 경로를 가진 셈이다.&lt;br&gt;소수의 사람과 회사의 문제 해결을 도와줘라.&lt;br&gt;그러면 자금 조달 과정에서 당신을 도와줄 네트워크가 저절로 생긴다.&lt;br&gt;그 네트워크가 자금 조달 과정을 &amp;#39;거의 불가능&amp;#39;에서 &amp;#39;해볼 만한 것&amp;#39;으로 바꿔준다.&lt;/p&gt;
&lt;p&gt;p. 113&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[상위 5% 스타트업을 만들어도 넌 부자가 못 될 수도 있다]&lt;/p&gt;
&lt;p&gt;2001년부터 2015년까지 시애틀의 평균 테크 연봉과 같은 기간 내 Moz 수입을 비교한 차트다.&lt;br&gt;(&lt;strong&gt;연매출 5천만 달러의 창업자의 15년 누적 연봉보다 시애틀의 평균 테크 연봉의 누적이 더 높다&lt;/strong&gt;)&lt;br&gt;...&lt;br&gt;일이 잘 풀리면 회사 가치는 오르고, 주식 가치도 따라 오를 것이다.&lt;br&gt;하지만 &lt;strong&gt;현실적으로 당신 (혹은 옵션을 행사한 직원)의 주식은 사려는 사람이 있을 때만 팔 수 있다&lt;/strong&gt;.&lt;br&gt;그리고 사려는 사람은, 빌어먹게도 드물다.&lt;br&gt;...&lt;br&gt;그럼 창업을 하지 말라는 건가? 초기 기업에 가지 말라는 건가?&lt;br&gt;아니다.&lt;br&gt;단지 단기적인 부를 쫓아서 하지 마라는 거다.&lt;br&gt;커리어 전체를 몇 년으로 압축해 갈아 넣으면 그 보상으로 떼돈을 벌 수 있다는 생각은 미친 짓이고, 통계적으로 말도 안 되는 소리다.&lt;br&gt;...&lt;br&gt;창업을 하거나 위험한 초기 벤처에 합류해야 할 논리적이고 멋진 이유는 따로 있다.&lt;br&gt;&lt;strong&gt;가장 큰 이유는 자율성이다&lt;/strong&gt;.&lt;br&gt;무엇을 만들지, 어떻게 일할지, 누구를 채용할지, 조직을 어떻게 굴릴지 스스로 정할 수 있는 자유 말이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;설령 실패한다 해도, 많은 경우 그 경험 자체가 보상이다&lt;/strong&gt;.&lt;br&gt;**스타트업의 가장 큰 장점 중 하나는 커리어 성장 속도를 미친듯이 앞당겨 준다는 것이다.&lt;br&gt;...&lt;br&gt;전략적 비전, 실행력, 리더십을 증명해 보이면, 당신은 현대 경제에서 아주 희귀하고 탐나는 인재가 된다.&lt;br&gt;수많은 초기 기업이 소규모로 인수되는 이유도 바로 이처럼 검증된 인재를 확보하기 위해서다.&lt;/p&gt;
&lt;p&gt;p. 122&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[확장 가능한 마케팅: 플라이휠이 그로스 해킹보다 낫다]&lt;/p&gt;
&lt;p&gt;해킹이라고 부르는 데는 다 이유가 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;낮은 유지율: 1달러 오퍼로 가입한 구독자들은 프로모션이 아닌 일반 오퍼로 가입한 사람들보다 유지율이 훨씬 낮았다.&lt;/li&gt;
&lt;li&gt;할인 중독: 우리 팀은 이 이메일 캠페인이 가져온 매출과 성장에 지나치게 매료됐다.&lt;br&gt;돌이켜보면, 다음번 &amp;#39;대박 해킹&amp;#39;을 찾는 중독 때문에 정작 집중해야 할 장기적인 제품 및 마케팅 투자를 등한시했다.&lt;/li&gt;
&lt;li&gt;브랜드 가치 하락: 대규모 할인 프로모션은, 특히 아주 많은 대중에게 제공될 때 할인과 특별 오퍼가 브랜드 정체성의 일부라는 인상을 준다.&lt;br&gt;이는 &lt;strong&gt;잠재 고객들에게 정가에 구독하기보다 다음 프로모션이 시작될 때까지 기다려야 한다고 학습시키는 결과를 초래&lt;/strong&gt;했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;반면, 구독 제품의 랜딩 페이지에 쏟은 전환율 최적화 (CRO) 노력은 지속적인 성공을 거두었으며, 장기적으로 긍정적인 수익을 안겨주는 투자가 되었다.&lt;br&gt;올바른 타깃을 찾고, 그들의 거부 사유를 파악한 뒤, 랜딩 페이지의 정보를 통해 그 반대 논거를 해소하고 가입 절차를 매끄럽게 만드는 CRO 노력은 단순한 &amp;#39;꼼수&amp;#39;가 아니다.&lt;br&gt;이는 우리 마케팅을 구동하는 근본적인 플라이휠을 개선하는 작업이다.&lt;br&gt;...&lt;br&gt;드롭박스의 해킹은 친구를 추천하면 추천한 사람과 받은 사람 모두에게 계정 혜택(용량)을 더 주는 &amp;#39;양방향 추천 시스템&amp;#39;이었다.&lt;br&gt;수년 동안 이 &amp;#39;해킹&amp;#39;은 마케팅 행사 무대와 웹상의 블로그 포스트에서 다뤄졌다.&lt;br&gt;&lt;strong&gt;이 전술을 끝도 없이 베껴 쓴 다른 기업들은 드롭박스만큼의 효과를 보지 못해 좌절만 맛봤다&lt;/strong&gt;.&lt;br&gt;드롭박스 창업자 드류 휴스턴은 2010년 &amp;quot;스타트업 교훈&amp;quot; 발표에서 &amp;quot;&lt;strong&gt;한 시장 유형에서 통한 마케팅 전술이 다른 시장에서는 처참하게 실패할 수 있다&lt;/strong&gt;&amp;quot; 고 현명하게 지적했다.&lt;br&gt;...&lt;br&gt;어떤 그로스 해킹은 통한다.&lt;br&gt;하지만 대부분은 안 통한다.&lt;br&gt;진짜 교훈은 이것이어야 한다.&lt;br&gt;이 회사들은 혁신적인 마케팅 전술 수십 가지를 시도했고, 이를 강력하고 지속적으로 개선되는 제품 및 수많은 전통적인 마케팅 모범 사례와 결합했다.&lt;br&gt;그리고 그 조합 안에서 몇 가지 특정 전술이 특히 효과를 발휘했던 것이다.&lt;/p&gt;
&lt;p&gt;p. 128&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[진짜 &amp;#39;핵심 가치&amp;#39;는 돈 버는 데 하등 도움이 안 된다]&lt;/p&gt;
&lt;p&gt;&amp;quot;취소하려면 전화를 걸게 만들면, 장담하건대 그 귀찮음만으로도 월 이탈률이 개선될 거야.&lt;br&gt;게다가 취소하려는 사람들과 통화하면서 그들이 누구인지, 왜 떠나는지 훨씬 잘 이해할 수 있잖아.&lt;br&gt;꽤 많은 사람을 붙잡을 수도 있고, 나중에 다시 돌아오게 할 수도 있어.&lt;br&gt;더 싼 요금제로 바꾸거나 다른 제품을 사게 유도할 수도 있고.&amp;quot;&lt;br&gt;&amp;quot;네 말이 맞아. 전화로만 취소할 수 있게 만들면 이탈률에 확실히 영향을 줄 거야.&lt;br&gt;하지만 우린 온라인으로 가입해놓고 취소할 때 전화하라는 서비스를 극도로 혐오해.&lt;br&gt;그건 일부러 어렵게 만든 거잖아.&lt;br&gt;그건 공감이 결여된 거고, 즉 TAGFEE가 아니란 소리야.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;일리 있네, 하지만 너 지금 길바닥에 엄청난 돈을 버리고 있는거야&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;글쎄, 우린 항상 말하잖아.&lt;br&gt;&lt;strong&gt;돈과 맞바꿀 수 있다면 그건 핵심 가치가 아니라고&lt;/strong&gt;&amp;quot;&lt;br&gt;...&lt;br&gt;&amp;quot;우리 신조에 담긴 핵심 가치가 경쟁 우위가 될 수도 있겠지만, 그래서 우리가 그걸 지키는 건 아니다.&lt;br&gt;&lt;strong&gt;우리는 그 가치가 우리가 지향하는 바를 정의하기 때문에 지키는 것이며, 어떤 상황에서 그것이 경쟁 열위가 된다 해도 우리는 고수할 것이다&lt;/strong&gt;&amp;quot; - 랄프 라르센, 존슨앤드존슨 전 CEO&lt;/p&gt;
&lt;p&gt;p. 146&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[회사를 일찍 매각해야 할까? 그래, 십중팔구는 그게 답이다.]&lt;/p&gt;
&lt;p&gt;외부 자본을 유치하는 순간, 당신의 목표는 필연적으로 매각이나 상장을 통해 그 자본의 몇 배를 돌려주는 것으로 바뀐다.&lt;br&gt;...&lt;br&gt;내가 아는 많은 창업자는 엑싯 과정에서 그리 큰 돈을 벌지 못했다.&lt;br&gt;하지만 투자자에게 수익을 돌려주고 유동성 이벤트를 달성한 이상, 그들은 평생 자신의 이력에 &amp;#39;성공한 기업가&amp;#39; 라는 칭호를 달 수 있다.&lt;br&gt;당신은 이게 터무니없는 헛소리라고 생각할지도 모른다.&lt;br&gt;작은 스타트업의 소소한 엑싯이 어떻게 &amp;#39;성공&amp;#39;과 동급일 수 있느냐고, 오히려 Moz처럼 연 매출 4,000만 달러가 넘는 비즈니스를 바닥부터 일군 것이야말로 진정한 &amp;#39;성공&amp;#39; 이 아니냐고 반문할 수도 있다.&lt;br&gt;...&lt;br&gt;&lt;strong&gt;성공적인 엑싯에 참여한 스타트업 직원은 설명하기 힘든 수준의 신뢰도와 엄청난 가치를 지닌 사람이라는 아우라를 얻는다&lt;/strong&gt;.&lt;br&gt;&amp;quot;저는 XYZ 회사의 초창기 멤버였고, 그 회사가 어디에 인수될 때 함께했습니다&amp;quot; 라고 말할 수 있는 능력은 실리콘밸리에 서식하는 기술자, 기업가, 투자자들의 하위문화에서 엄청난 무게감을 갖는다.&lt;br&gt;...&lt;br&gt;스타트업은 관련된 모든 이에게 - 창업자, 직원, 가족, 그리고 고객과 투자자에게까지 - 가혹할 만큼 고통스러운 고행이다.&lt;br&gt;대부분의 기관 투자자 모델은 소규모 엑싯과는 본질적으로 맞지 않는다.&lt;br&gt;그래서 실리콘밸리의 스타트업 문화는 수백만 달러나 수천만 달러에 회사를 파는 것을 &amp;#39;변절&amp;#39; 이라 부르며, &amp;#39;진짜 회사&amp;#39;를 만드는데 실패한 것이라는 지배적인 내러티브를 만들어 낸다.&lt;br&gt;만약 당신이 창업자거나 초기 직원이거나, 혹은 그들을 아끼는 사람이라면 나는 당신에게 이 편향되고 투자자에게만 유리한 사고방식을 완전히 거부하라고 촉구한다.&lt;br&gt;&lt;strong&gt;당신도 IP나 10억 달러짜리 매각이 더 작은 성과를 희생해서라도 추구해야 할 절대 선이라는 강박을 버려야 한다&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;p. 214&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[취약함을 드러내는 것 !== 약해빠진 것]&lt;/p&gt;
&lt;p&gt;나는 시간을 들여 &lt;strong&gt;사람들을 일대일로 만나 계획을 설명하고 피드백, 질문, 우려 사항을 묻는 게 훨씬 효과적&lt;/strong&gt;이었다.&lt;br&gt;맞다, 시간이 훨씬 많이 걸린다.&lt;br&gt;하지만 &lt;strong&gt;다 같이 모이거나 본격적으로 일을 시작할 때쯤이면, 큰 갈등들은 이미 다 생각하고 해결된 상태라는 뜻&amp;amp;_&amp;amp;이기도 하다.&lt;br&gt;이건 프로젝트 기여자들만을 위한 게 아니다.&lt;br&gt;리더와 매니저를 위한 것이기도 하다.&lt;br&gt;그룹 앞에서 내 아이디어와 계획을 방어하는 건 정말 불편하고, 실수를 인정하거나 즉성에서 수정하는 건 더 어렵다.&lt;br&gt;하지만 *_팀원들과 일대일로 소통하고 최종 계획을 발표하거나 시작하기 전에 모두의 우려를 미리 파악해 두는 건 훨씬 더 편안하다&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;p. 244&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote data-ke-style="style1"&gt;&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;&lt;p&gt;[집중해라]&lt;/p&gt;
&lt;p&gt;Moz라는 이름에 적당히 괜찮은 제품만 얹어서 매월 수백만 명의 방문자에게 들이밀면 팔릴 거라고 확신했다.&lt;br&gt;...&lt;br&gt;웹사이트 방문자에게 8가지 다른 물건을 파는 건 2~3개를 파는 것보다 훨씬 더 어려웠다.&lt;br&gt;회사 내부 조직을 8개 제품을 지원하도록 구성하는 건 더욱더 어려웠다.&lt;br&gt;...&lt;br&gt;마치 믹스에 새로운 제품을 하나 추가할 때마다 기존의 다른 모든 제품의 성장을 조금씩 갉아먹는 것 같았다.&lt;br&gt;...&lt;br&gt;줄어드는 매출을 막기 위해 신규 고객 획득에 너무 의존하다 보니, 회사의 우선순위가 &amp;#39;신규 고객용 제품 개발&amp;#39;과 &amp;#39;기존 고객 유지 개선&amp;#39; 사이에서 쪼개질 수밖에 없다.&lt;br&gt;이제 그걸 4개의 다른 제품에 곱해보라.&lt;br&gt;...&lt;br&gt;우선순위를 추가할 때 복잡성이 선형적이 아니라 기하급수적으로 늘어난다는 사실을 아는 건 도움이 된다.&lt;br&gt;더 적은 사람들이 오직 소수의 것들에만 집중함으로써, 수많은 방향으로 찢어진 훨씬 더 큰 팀보다 더 많은 것을 해낼 수 있었다.&lt;br&gt;...&lt;br&gt;&amp;quot;우리 핵심 제품은 성장하고 있지만, 만약 우리가... 하면 더 빨리 클 수 잇을텐데.&amp;quot; 그 빈칸을 채우는 건 위험하다.&lt;br&gt;복잡성을 더하고 집중력을 앗아가는 것들이 그 자리를 차지하기 때문이다.&lt;br&gt;...&lt;br&gt;훨씬 더 현명한 길은, &lt;strong&gt;훈련과 인내심을 가지고 곁길을 무시하며, 당신이 세계 최고가 될 수 있는 오직 한 가지에 실험, 학습, 반복을 쏟아붓는 것이다&lt;/strong&gt;.&lt;br&gt;성장을 위한 다른 전략들은 당신이 진정으로 거대한 규모를 갖출 떄까지 기다려야 한다.&lt;/p&gt;
&lt;p&gt;p. 299&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;</summary>
    <title>우리는 실리콘밸리에 속았다</title>
    <updated>2026-03-15T15:16:34+09:00</updated>
    <dc:date>2026-03-15T15:16:34+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>향로 (기억보단 기록을)</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p data-ke-size="size16"&gt;최근 CTO 모임에 참여했다.&lt;br&gt;모임에서 이런 질문이 나왔다.&lt;br&gt;"AI가 도입되어서 미친듯이 속도전을 하면서 정말 개발자들의 그런 속도가 회사에 기여한다고 느껴지시나요?"&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;여러 답변이 나왔다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;"AI 도입이 개발자의 생산성을 키웠을진 몰라도, 개발팀이나 제품팀 전체의 생산성이 증가하진 않았다"&lt;br&gt;"AI 로 인해 개발 속도는 빨라졌지만 개발팀도 모르는 코드가 늘어서 장기적으로 더 큰 문제를 계속 쌓고 있는 것 같다"&lt;br&gt;"개발자의 코드 생산성은 높아져도 기획, 디자인이 병목이라 그건 개발팀이 해결해줄 수 없어서 여전히 생산성을 체감 하기 힘들다"&lt;br&gt;등등의 여러 이야기가 오갔다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;내 차례에서 나는 조심스럽게 다음과 같이 이야기했다.&lt;br&gt;"개인 개발자의 생산성은 확실히 오른 것 같다.&lt;br&gt;그런데, 개발팀의 생산성이 올라간다고 해서 그게 곧바로 회사 성과로 이어지진 않는다고 다들 느끼시는 것 같다.&lt;br&gt;&lt;b&gt;개발팀의 생산성의 기여가 사업에 비례한다면 지금의 대량해고가 발생할 리가 없다&lt;/b&gt;.&lt;br&gt;&lt;b&gt;비례한다면, 기존에 5이던 생산량이 20, 100으로 늘었으니 더 뽑아서 생산량을 늘려야 하는 게 맞지 않겠나&lt;/b&gt;?&lt;br&gt;근데 오히려 인원을 줄여서 기존의 생산량을 더 적은 인원으로 하는 것을 회사들이 원하는 분위기이다."&lt;/p&gt;
&lt;hr data-ke-style="style1"&gt;
&lt;p data-ke-size="size16"&gt;스타트업 생활을 10년정도 하면서 직접 경험도 하고, 다른 회사들의 분들과도 계속 이야기를 하고나서 다음과 같은 생각을 했다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;"&lt;b&gt;사업에는 Min 값과 Max 값이 있으며, 개발자는 Min 값을 책임지고, 사업/세일즈/마케팅과 같은 팀이 Max 값을 책임진다&lt;/b&gt;".&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;개발팀은 제품이 돌아가게 만들고, 버그를 잡고, 성능을 올리고, 장애를 막는다.&lt;br&gt;사업의 바닥을 든든하게 깔아주는 역할이다.&lt;br&gt;Min 값이 무너지면 사업 자체가 성립하지 않으니까, 이건 대단히 중요한 일이다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;반면 사업/세일즈/마케팅은 Max 값을 책임진다.&lt;br&gt;새로운 시장을 열고, 고객을 데려오고, 매출의 상방을 끌어올린다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;여기서 문제가 생긴다.&lt;br&gt;&lt;b&gt;Min 값을 아무리 효율적으로 달성해도, Max 값의 천장이 바뀌지 않으면 사업은 커지지 않는다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;국내 많은 IT 회사들의 구조를 보면, 기본적으로 사업 조직이 상방을 계속 열고, 제품이 그 상방을 쫓아가는 형태로 되어 있다.&lt;br&gt;사업이 새로운 시장을 열면, 개발이 그걸 제품으로 구현하고, 다시 사업이 다음 상방을 연다.&lt;br&gt;이 사이클이 돌아갈 때 회사가 성장한다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;개발자를 적극적으로 채용하는 그간의 스타트업들을 떠올려보면 더 그렇다.&lt;br&gt;대부분 사업의 성장을 기술력과 제품력이 따라가지 못할 때 개발팀의 생산성과 채용을 중심으로 둔다.&lt;br&gt;"이번 마케팅이 너무 잘됐는데 장애 나서 역대 최대 매출을 찍지 못했다",&lt;br&gt;"계속 늘어나는 가입자 수를 버티지 못해서 전체 서비스가 매일 느리다는 CS가 들어와서 고객이 떠난다."&lt;br&gt;이런 문제들로 사업 성장에 발목이 잡힐 때 개발자를 뽑는다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;"회사의 매출이 더 이상 성장하지 못해서 개발자를 뽑은 적이 있나?"&lt;br&gt;SaaS나 제품이나 기술 자체가 판매 상품인 경우가 아니고선, 국내에서 그런 경우는 없었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;b&gt;개발자 채용은 사업의 상방을 기술이 못 받쳐줄 때, 즉 Min 값이 무너질 위기에 발생하는 것이지, Max 값을 높이기 위한 것이 아니&lt;/b&gt;라는 생각이 든다.&lt;/p&gt;
&lt;hr data-ke-style="style1"&gt;
&lt;p data-ke-size="size16"&gt;그렇다면 상방이 더 이상 열리지 않는 상태에서 개발자의 생산성만 올라간다면?&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;평소 먹는 식단으로 필요한 비타민이 다 채워지지 않을 때는 비타민 영양제를 추가로 먹어야 한다.&lt;br&gt;하지만 비타민 영양제가 할인 중이라고 왕창 사서 몇 배씩 먹는 사람은 없다.&lt;br&gt;아무리 할인하더라도, 그 이상의 비타민은 나에게 필요하지 않고, 더 먹어봐야 소변으로 배출될 뿐이니까.&lt;br&gt;오히려 그 돈으로 다른 부족한 영양을 채울 수 있는 보충제를 사거나, 운동을 하는 것이 더 건강해지는 방법이다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;개발 생산성도 마찬가지 아닐까?&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;사업이 필요로 하는 만큼의 개발력이 채워지지 않을 때는, 생산성을 높이는 게 맞다.&lt;br&gt;하지만 AI로 개발 생산성이 크게 올라서 이미 충분한 상태라면, 거기서 더 올리는 건 비타민을 몇 배씩 먹는 것과 같다.&lt;br&gt;더 먹어봐야 소변으로 나갈 뿐이다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;스타트업에 대한 기대를 생각해보자.&lt;br&gt;연매출 1,000억인 회사가 있다.&lt;br&gt;영업이익을 50억에서 100억, 200억으로 늘려나가는 것과,&lt;br&gt;영업이익은 50억에서 더 늘지 않더라도 매출이 1,000억에서 2,000억, 5,000억으로 늘어나는 것.&lt;br&gt;어느 쪽이 스타트업에게 기대하는 모습인가?&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;당연히 후자다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;영업이익 개선은 비용 최적화의 영역이다.&lt;br&gt;FinOps를 하고, 인프라 비용을 줄이고, 개발 효율을 높여서 같은 매출 대비 더 많이 남기는 것.&lt;br&gt;물론 이것도 회사의 개선이다.&lt;br&gt;하지만 이건 Min 값을 더 효율적으로 달성하는 것이지, Max 값의 천장을 높이는 게 아니다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;AI로 개발 생산성을 높여서 비용을 줄이는 건, 1,000억 매출에서 영업이익을 50억 더 짜내는 일에 가깝다.&lt;br&gt;나쁘지 않다.&lt;br&gt;하지만 스타트업이 추구해야 할 방향은 아니다.&lt;/p&gt;
&lt;hr data-ke-style="style1"&gt;
&lt;p data-ke-size="size16"&gt;"지금 우리의 사업 구조는 개발팀의 생산량이 올라가는 만큼 매출을 낼 수 있는 구조인가?"&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;이 질문에 먼저 답해야 한다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;현재 개발팀의 생산량이 계속해서 올라가도 괜찮을 만큼, 사업 구조가 계속 성장할 여지가 있는가?&lt;br&gt;다른 사업팀의 병목은 없는가?&lt;br&gt;디자인이 너무 구려서일 수도 있고, &lt;br&gt;고객 응대가 너무 성의 없어서 이탈이 계속 발생하는 것일 수도 있고, &lt;br&gt;마케팅으로 고객에게 도달 자체가 안 되는 것일 수도 있고, &lt;br&gt;세일즈에서 전환되는 고객 수가 적은 것일 수도 있다.&lt;br&gt;아예 근본적으로 사업 구조가 더 이상 더 커지기 힘든 시장에서 플레이하는 것일 수도 있다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;개발팀의 생산성이 지금 영양과다 비타민이 아닌지, 구분할 줄 알아야 한다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;계속해서 개발팀의 생산성을 높이는 데만 힘을 쓸 것이 아니라, 일정 궤도 이상이라면 개발팀은 조직 전체의 병목 지점을 해쳐나가기 위해 뛰어다녀야 한다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;비타민이 이미 충분하다면, 그 돈으로 운동을 시작해야 한다.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://jojoldu.tistory.com/870</id>
    <link href="https://jojoldu.tistory.com/870"/>
    <summary type="html">&lt;p data-ke-size="size16"&gt;최근 CTO 모임에 참여했다.&lt;br /&gt;모임에서 이런 질문이 나왔다.&lt;br /&gt;"AI가 도입되어서 미친듯이 속도전을 하면서 정말 개발자들의 그런 속도가 회사에 기여한다고 느껴지시나요?"&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;여러 답변이 나왔다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;"AI 도입이 개발자의 생산성을 키웠을진 몰라도, 개발팀이나 제품팀 전체의 생산성이 증가하진 않았다"&lt;br /&gt;"AI 로 인해 개발 속도는 빨라졌지만 개발팀도 모르는 코드가 늘어서 장기적으로 더 큰 문제를 계속 쌓고 있는 것 같다"&lt;br /&gt;"개발자의 코드 생산성은 높아져도 기획, 디자인이 병목이라 그건 개발팀이 해결해줄 수 없어서 여전히 생산성을 체감 하기 힘들다"&lt;br /&gt;등등의 여러 이야기가 오갔다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;내 차례에서 나는 조심스럽게 다음과 같이 이야기했다.&lt;br /&gt;"개인 개발자의 생산성은 확실히 오른 것 같다.&lt;br /&gt;그런데, 개발팀의 생산성이 올라간다고 해서 그게 곧바로 회사 성과로 이어지진 않는다고 다들 느끼시는 것 같다.&lt;br /&gt;&lt;b&gt;개발팀의 생산성의 기여가 사업에 비례한다면 지금의 대량해고가 발생할 리가 없다&lt;/b&gt;.&lt;br /&gt;&lt;b&gt;비례한다면, 기존에 5이던 생산량이 20, 100으로 늘었으니 더 뽑아서 생산량을 늘려야 하는 게 맞지 않겠나&lt;/b&gt;?&lt;br /&gt;근데 오히려 인원을 줄여서 기존의 생산량을 더 적은 인원으로 하는 것을 회사들이 원하는 분위기이다."&lt;/p&gt;
&lt;hr data-ke-style="style1" /&gt;
&lt;p data-ke-size="size16"&gt;스타트업 생활을 10년정도 하면서 직접 경험도 하고, 다른 회사들의 분들과도 계속 이야기를 하고나서 다음과 같은 생각을 했다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;"&lt;b&gt;사업에는 Min 값과 Max 값이 있으며, 개발자는 Min 값을 책임지고, 사업/세일즈/마케팅과 같은 팀이 Max 값을 책임진다&lt;/b&gt;".&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;개발팀은 제품이 돌아가게 만들고, 버그를 잡고, 성능을 올리고, 장애를 막는다.&lt;br /&gt;사업의 바닥을 든든하게 깔아주는 역할이다.&lt;br /&gt;Min 값이 무너지면 사업 자체가 성립하지 않으니까, 이건 대단히 중요한 일이다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;반면 사업/세일즈/마케팅은 Max 값을 책임진다.&lt;br /&gt;새로운 시장을 열고, 고객을 데려오고, 매출의 상방을 끌어올린다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;여기서 문제가 생긴다.&lt;br /&gt;&lt;b&gt;Min 값을 아무리 효율적으로 달성해도, Max 값의 천장이 바뀌지 않으면 사업은 커지지 않는다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;국내 많은 IT 회사들의 구조를 보면, 기본적으로 사업 조직이 상방을 계속 열고, 제품이 그 상방을 쫓아가는 형태로 되어 있다.&lt;br /&gt;사업이 새로운 시장을 열면, 개발이 그걸 제품으로 구현하고, 다시 사업이 다음 상방을 연다.&lt;br /&gt;이 사이클이 돌아갈 때 회사가 성장한다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;개발자를 적극적으로 채용하는 그간의 스타트업들을 떠올려보면 더 그렇다.&lt;br /&gt;대부분 사업의 성장을 기술력과 제품력이 따라가지 못할 때 개발팀의 생산성과 채용을 중심으로 둔다.&lt;br /&gt;"이번 마케팅이 너무 잘됐는데 장애 나서 역대 최대 매출을 찍지 못했다",&lt;br /&gt;"계속 늘어나는 가입자 수를 버티지 못해서 전체 서비스가 매일 느리다는 CS가 들어와서 고객이 떠난다."&lt;br /&gt;이런 문제들로 사업 성장에 발목이 잡힐 때 개발자를 뽑는다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;"회사의 매출이 더 이상 성장하지 못해서 개발자를 뽑은 적이 있나?"&lt;br /&gt;SaaS나 제품이나 기술 자체가 판매 상품인 경우가 아니고선, 국내에서 그런 경우는 없었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;b&gt;개발자 채용은 사업의 상방을 기술이 못 받쳐줄 때, 즉 Min 값이 무너질 위기에 발생하는 것이지, Max 값을 높이기 위한 것이 아니&lt;/b&gt;라는 생각이 든다.&lt;/p&gt;
&lt;hr data-ke-style="style1" /&gt;
&lt;p data-ke-size="size16"&gt;그렇다면 상방이 더 이상 열리지 않는 상태에서 개발자의 생산성만 올라간다면?&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;평소 먹는 식단으로 필요한 비타민이 다 채워지지 않을 때는 비타민 영양제를 추가로 먹어야 한다.&lt;br /&gt;하지만 비타민 영양제가 할인 중이라고 왕창 사서 몇 배씩 먹는 사람은 없다.&lt;br /&gt;아무리 할인하더라도, 그 이상의 비타민은 나에게 필요하지 않고, 더 먹어봐야 소변으로 배출될 뿐이니까.&lt;br /&gt;오히려 그 돈으로 다른 부족한 영양을 채울 수 있는 보충제를 사거나, 운동을 하는 것이 더 건강해지는 방법이다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;개발 생산성도 마찬가지 아닐까?&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;사업이 필요로 하는 만큼의 개발력이 채워지지 않을 때는, 생산성을 높이는 게 맞다.&lt;br /&gt;하지만 AI로 개발 생산성이 크게 올라서 이미 충분한 상태라면, 거기서 더 올리는 건 비타민을 몇 배씩 먹는 것과 같다.&lt;br /&gt;더 먹어봐야 소변으로 나갈 뿐이다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;스타트업에 대한 기대를 생각해보자.&lt;br /&gt;연매출 1,000억인 회사가 있다.&lt;br /&gt;영업이익을 50억에서 100억, 200억으로 늘려나가는 것과,&lt;br /&gt;영업이익은 50억에서 더 늘지 않더라도 매출이 1,000억에서 2,000억, 5,000억으로 늘어나는 것.&lt;br /&gt;어느 쪽이 스타트업에게 기대하는 모습인가?&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;당연히 후자다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;영업이익 개선은 비용 최적화의 영역이다.&lt;br /&gt;FinOps를 하고, 인프라 비용을 줄이고, 개발 효율을 높여서 같은 매출 대비 더 많이 남기는 것.&lt;br /&gt;물론 이것도 회사의 개선이다.&lt;br /&gt;하지만 이건 Min 값을 더 효율적으로 달성하는 것이지, Max 값의 천장을 높이는 게 아니다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;AI로 개발 생산성을 높여서 비용을 줄이는 건, 1,000억 매출에서 영업이익을 50억 더 짜내는 일에 가깝다.&lt;br /&gt;나쁘지 않다.&lt;br /&gt;하지만 스타트업이 추구해야 할 방향은 아니다.&lt;/p&gt;
&lt;hr data-ke-style="style1" /&gt;
&lt;p data-ke-size="size16"&gt;"지금 우리의 사업 구조는 개발팀의 생산량이 올라가는 만큼 매출을 낼 수 있는 구조인가?"&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;이 질문에 먼저 답해야 한다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;현재 개발팀의 생산량이 계속해서 올라가도 괜찮을 만큼, 사업 구조가 계속 성장할 여지가 있는가?&lt;br /&gt;다른 사업팀의 병목은 없는가?&lt;br /&gt;디자인이 너무 구려서일 수도 있고, &lt;br /&gt;고객 응대가 너무 성의 없어서 이탈이 계속 발생하는 것일 수도 있고, &lt;br /&gt;마케팅으로 고객에게 도달 자체가 안 되는 것일 수도 있고, &lt;br /&gt;세일즈에서 전환되는 고객 수가 적은 것일 수도 있다.&lt;br /&gt;아예 근본적으로 사업 구조가 더 이상 더 커지기 힘든 시장에서 플레이하는 것일 수도 있다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;개발팀의 생산성이 지금 영양과다 비타민이 아닌지, 구분할 줄 알아야 한다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;계속해서 개발팀의 생산성을 높이는 데만 힘을 쓸 것이 아니라, 일정 궤도 이상이라면 개발팀은 조직 전체의 병목 지점을 해쳐나가기 위해 뛰어다녀야 한다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;비타민이 이미 충분하다면, 그 돈으로 운동을 시작해야 한다.&lt;/p&gt;</summary>
    <title>생산성과 영양과다 비타민</title>
    <updated>2026-03-14T16:14:24+09:00</updated>
    <dc:date>2026-03-14T16:14:24+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>연로그</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style2"&gt;
&lt;h2 style="text-align: center;" data-ke-size="size26"&gt;✏️ 서론&lt;/h2&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;지난 12월 ~ 1월에 진행했던 토스 러너스하이를 이제야 후기를 작성한다. 급한 회사 일을 마무리하고 리프레시 휴가도 다녀오느라 연말연초에 정신이 없었다. 이 글은 &lt;b&gt;러너스하이가 어떤 프로그램인지 궁금한 사람들을 위해 간단히 소개하고, 러너스하이를 하면서 얻은 인사이트와 느꼈던 점을 정리한 글&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="text-align: start;"&gt;혹여나 결과만 궁금한 사람들을 위해 미리 말하자면 나는 우수 참여자로 선정되지는 못했다. 그래도 참여하면서 여러 생각을 정리할 수 있었고, 그 과정에서 얻은 것들을 이 글에 남겨본다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-filename="blob" data-origin-width="1001" data-origin-height="136"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/Dqy7C/dJMcaaYMjwY/2rDDtbKu57TMPhgjnxXsr0/img.png" data-phocus="https://blog.kakaocdn.net/dn/Dqy7C/dJMcaaYMjwY/2rDDtbKu57TMPhgjnxXsr0/img.png" data-alt="결과 메일 중 일부"&gt;&lt;img src="https://blog.kakaocdn.net/dn/Dqy7C/dJMcaaYMjwY/2rDDtbKu57TMPhgjnxXsr0/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDqy7C%2FdJMcaaYMjwY%2F2rDDtbKu57TMPhgjnxXsr0%2Fimg.png" onerror="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';" loading="lazy" width="500" height="470" data-filename="blob" data-origin-width="1001" data-origin-height="136"&gt;&lt;/span&gt;&lt;figcaption&gt;결과 메일 중 일부&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style2"&gt;
&lt;h2 style="text-align: center;" data-ke-size="size26"&gt;
&lt;span style="color: #666666; text-align: left;"&gt; ‍♀️ &lt;/span&gt;토스 Learner's High란?&lt;/h2&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-origin-width="1598" data-origin-height="1242"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/qc53b/dJMcafluQZu/0LuopylxrZGQLYgVVDkVx1/img.png" data-phocus="https://blog.kakaocdn.net/dn/qc53b/dJMcafluQZu/0LuopylxrZGQLYgVVDkVx1/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/qc53b/dJMcafluQZu/0LuopylxrZGQLYgVVDkVx1/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqc53b%2FdJMcafluQZu%2F0LuopylxrZGQLYgVVDkVx1%2Fimg.png" onerror="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';" loading="lazy" width="500" height="389" data-origin-width="1598" data-origin-height="1242"&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="color: #333333; text-align: start;"&gt;토스 러너스하이는&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;b&gt;커리어 성장을 원하는 서버 개발자들을 위한 멘토링 프로그램&lt;/b&gt;이다. 아래는 2기 모집 글의 일부를 인용해 왔다.&lt;/p&gt;
&lt;blockquote data-ke-style="style2"&gt;숨이 턱끝까지 차도록 달릴 때 오히려 점점 몸이 가벼워지고 머리가 맑아지는 느낌을 아시나요?&lt;br&gt;달릴수록 기분이 상쾌해지는 상태를 &lt;b&gt;Runner’s High(러너스 하이)&lt;/b&gt; ‍♂️라고 해요.&lt;br&gt;&lt;br&gt;무언가를 배우며 치열하게 노력할 때도 &lt;b&gt;Learner’s High&lt;/b&gt; ‍♀️를 경험할 수 있어요.&lt;br&gt;성장하기 위한 설레는 목표를 세울 때, 그리고 이를 향해 치열하게 달려갈 때 막연한 불안함은 해소되고 자연스럽게 실력과 커리어도 함께 성장해요.&lt;br&gt;&lt;br&gt;토스에서 지향하는 서버 개발자의 성장 방향성을 학습한 뒤, 한 달간의 경험을 기록하고 더 큰 기회를 위해 높게 점프하는 &lt;b&gt;토스 Learner’s High 서버 2기&lt;/b&gt;를 모집합니다.&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;사실 위 내용만 봤을 때는 커리어에 대한 조언을 해준다는 건가? 어떤 멘토링을 해주는 거지? 감이 잘 안 잡혔다. 아직 2기까지밖에 진행을 안 해서 그런가, 프로그램 수료 후기 찾기도 힘들었다. 당시 내가 궁금해했던 점에 대해 기억을 되살려본다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-origin-width="512" data-origin-height="512"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/YcELT/dJMcaduoHwA/Xk1elFHPk3wjbKMk0IWKr0/img.png" data-phocus="https://blog.kakaocdn.net/dn/YcELT/dJMcaduoHwA/Xk1elFHPk3wjbKMk0IWKr0/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/YcELT/dJMcaduoHwA/Xk1elFHPk3wjbKMk0IWKr0/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYcELT%2FdJMcaduoHwA%2FXk1elFHPk3wjbKMk0IWKr0%2Fimg.png" onerror="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';" loading="lazy" width="300" height="300" data-origin-width="512" data-origin-height="512"&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;h4 data-ke-size="size20"&gt;❓ 토스로 이직을 원하는 사람만 지원할 수 있나요?&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt;&lt;b&gt; 아니요&lt;/b&gt;. 저도 이직 계획이 없었으나 멘토링 내용이 궁금해서 지원하였습니다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;h4 data-ke-size="size20"&gt;❓&lt;span&gt; 개인의 커리어 혹은 &lt;/span&gt;과제에 대한 피드백이 제공되나요?&lt;/h4&gt;
&lt;p style="color: #333333; text-align: start;" data-ke-size="size16"&gt;&lt;b&gt; 아니요&lt;/b&gt;. 세션 -&amp;gt; 과제 수행 -&amp;gt; 과제 제출 -&amp;gt; 합격 발표 순으로 진행되며 별개의 피드백 절차가 없습니다. 우수 선정자 분들은 토스 채용 프로세스를 이어 진행되는 것으로 알고 있는데, 면접에서 과제에 대한 이야기를 나눌 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;h4 data-ke-size="size20"&gt;❓&lt;span&gt; &lt;/span&gt;어떤 멘토링을 받을 수 있나요?&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt; &lt;b&gt;토스가 일하는 방식에 대해 듣고 새로운 인사이트를 얻을 수 있어요&lt;/b&gt;. 구체적인 내용은 토스에서 개인 블로그 등에 자료 공유를 지양해 달라 하셨어서 생략합니다. 멘토링 프로그램이라고 명시되어 있으나, 어떠한 가이드나 지식이 주어지지는 않습니다. &lt;b&gt;개인적으로는 멘토링이 아닌 채용 프로세스&lt;/b&gt;에 가깝다고 느꼈습니다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;h4 style="color: #000000; text-align: start;" data-ke-size="size20"&gt;❓&lt;span&gt; 회사 업무와 병행이 가능한가요?&lt;/span&gt;
&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt; &lt;b&gt;네&lt;/b&gt;. 과제 주제를 스스로 정하는데, 실제 업무와 관련하여 잡아야 하기 때문에 반드시 병행해야 합니다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;h4 style="color: #000000; text-align: start;" data-ke-size="size20"&gt;❓&lt;span&gt; 중도 포기가 가능한가요?&lt;/span&gt;
&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt;&lt;b&gt;네&lt;/b&gt;. 과제 제출을 안 하면 됩니다. 실제로 회사 업무가 바빠져서 제출을 안 하거나 멘토링 프로그램이 생각하는 방향과 달라서 포기하시는 분들도 많은 것 같았어요. 저도 회사 업무가 바빠져서 처음 목표치를 달성하지는 못했습니다. 실제 결과물은 없었지만, 현재 상황 정리에 의미를 두고자 뭐라도 써서 제출만 했어요.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;h4 style="color: #000000; text-align: start;" data-ke-size="size20"&gt;❓&lt;span&gt; 수료증이 발급되나요? &lt;/span&gt;
&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt;&lt;span&gt; &lt;b&gt;수료증은 별도로 없습니다&lt;/b&gt;. 마지막 과제물을 제출하면 '우수 참여자' 선정 여부에 대해서만 메일로 안내가 옵니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-origin-width="1860" data-origin-height="88"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/blUybR/dJMcaadrJxE/EIwX1Y2i0ihntKpYdYp6T0/img.png" data-phocus="https://blog.kakaocdn.net/dn/blUybR/dJMcaadrJxE/EIwX1Y2i0ihntKpYdYp6T0/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/blUybR/dJMcaadrJxE/EIwX1Y2i0ihntKpYdYp6T0/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblUybR%2FdJMcaadrJxE%2FEIwX1Y2i0ihntKpYdYp6T0%2Fimg.png" onerror="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';" loading="lazy" width="1860" height="88" data-origin-width="1860" data-origin-height="88"&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style2"&gt;
&lt;h2 style="text-align: center;" data-ke-size="size26"&gt;&lt;span&gt;  인사이트 및 생각 정리&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-origin-width="1536" data-origin-height="1024"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/SDUbR/dJMcabXIn5J/kiz6K4sUIi1HLIlXu7pWL1/img.png" data-phocus="https://blog.kakaocdn.net/dn/SDUbR/dJMcabXIn5J/kiz6K4sUIi1HLIlXu7pWL1/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/SDUbR/dJMcabXIn5J/kiz6K4sUIi1HLIlXu7pWL1/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSDUbR%2FdJMcabXIn5J%2Fkiz6K4sUIi1HLIlXu7pWL1%2Fimg.png" onerror="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';" loading="lazy" width="400" height="267" data-origin-width="1536" data-origin-height="1024"&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;h4 data-ke-size="size20"&gt;  내 생각을 정리해 볼 수 있었던 기회&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt;러너스하이를 신청하려면 '잘하는 개발자란 어떤 역량을 가진 사람인가?'에 대한 답변과 이력서를 제출해야 한다. 요 두 가지를 정리하면서 여러 방면의 내 생각을 정리할 수 있던 것 같다. 개발자의 역량에 대해서는 &lt;a href="https://yeonyeon.tistory.com/360" target="_blank" rel="noopener"&gt;2025년 회고글&lt;/a&gt;에서 다룬 바가 있어서 생략한다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;현재 회사에 입사하고 지금까지 재직 중 회사 추가 외에는 이력서 업데이트 한 적이 없었다. &lt;span style="color: #333333; text-align: start;"&gt;이력서를 정리하면서 여러 생각이 들었었는데,&lt;span&gt; &lt;/span&gt;&lt;/span&gt;내가 3년간 근무하면서 &lt;b&gt;어떤 일들을 했었는지 돌아볼 수 있어서 좋았다&lt;/b&gt;. 이런 경험을 통해 저런 점을 느꼈었지, 이 과제는 이런 식으로 정리할 수 있겠구나 같은 생각들이 떠올랐다. 이력서를 수정하고 싶은 포인트들을 짚어내다 보니 &lt;b&gt;앞으로 어떤 경험을 더 쌓고 싶은지도 조금씩 보이는 듯했다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;아쉬운 부분은 이런 생각을 혼자서만 했다는 점? 다른 사람들의 소감이나 생각을 나누거나, 멘토링을 통해 멘토의 의견도 듣고 싶다. 조만간 이야기를 나눌 수 있는 자리를 만들거나 누군가에게 부탁을 드려야지 싶다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;h4 style="color: #000000;" data-ke-size="size20"&gt; &lt;span&gt; &lt;/span&gt;성과를 지표로 설명하는 연습&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt;러너스하이에서 수행할 과제 주제를 스스로 선정해야 한다. 이때 명확한 지표를 통해 성과를 증명해 낼 수 있는 과제를 선정한다고 생각하니 골 아팠다. 어떤 관점으로 접근해야 할지 너무 생소했다. 그래서 일단은 나 혹은 팀원들이 현재 느끼고 있는 불편함들을 정리했다. 회사에서 팀원들이랑 "이런 기능도 있으면 편할 것 같다", "저 부분도 고치면 좋겠다" 같은 이야기를 자주 하는 편이다 보니 정리가 오래 걸리지는 않았다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;고민 목록은 아래와 같은 형식으로 작성하였다.&lt;/p&gt;
&lt;ul style="list-style-type: disc;" data-ke-list-type="disc"&gt;
&lt;li&gt;고민 요약
&lt;ul style="list-style-type: disc;" data-ke-list-type="disc"&gt;
&lt;li&gt;고민하게 된 배경 혹은 원인&lt;/li&gt;
&lt;li&gt;시도할 수 있는 방안&lt;/li&gt;
&lt;li&gt;해당 고민을 개선함으로써 얻을 수 있는 임팩트&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;그다음은 토스에서 제시한 가이드와 내부 평가 지표의 일부를 참고하여 두 가지 기준을 세웠다.&lt;/p&gt;
&lt;ol style="list-style-type: decimal;" data-ke-list-type="decimal"&gt;
&lt;li&gt;결과 측정이 가능한 지표가 존재하는가?&lt;/li&gt;
&lt;li&gt;한 달 내 개발을 완수할 수 있는가?&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;과제 수행 완료 후가 아닌 수행 전에 임팩트를 예상하는 게 어려웠다. 내가 가진 고민이 시스템 아키텍처나 서버의 안정성과 관련된 고민들이 많아서 그런 건가?라는 생각도 했지만 비즈니스 과제면 사용자 지표를 예상해야 하니까 더 어려울 것 같기도 하고... &lt;b&gt;어떤 임팩트가 있을지 나름 고민을 많이 해보고 과제를 선정했지만, 실제 과제 수행 이후에 성과를 정리해 보자니 엉뚱한 임팩트를 제시했거나 증명하기 어려운 기준을 예측&lt;/b&gt;한 것 같기도 하다. 이 부분에 대해서는 앞으로 여러 과제를 수행하면서 &lt;b&gt;계속 시행착오를 겪으며 감을 찾아야 할 것 같다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;앞으로는 이런 임팩트를 예상하는 게 내게 더 중요해질 것 같다. 토스 러너스하이 진행 당시에는 서버 개발자만 모인 기능 조직이었고, 현재는 애자일 단위로 일하는 목적 조직으로 변해서 일하는 방식이 많이 바뀌고 있다. 기술 과제를 완수하고 개선 효과를 정리하는 건 종종 했지만 비즈니스 과제의 지표를 수집하고 예측 분석하는 게 어렵다. 낯설지만 익숙해져 가야 하는 것 같다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;h4 data-ke-size="size20"&gt; &lt;span&gt; &lt;/span&gt;여러 과제를 동시에 진행하며 느낀 리소스 관리&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt;러너스하이 시작할 때쯤 갑자기 비즈니스 과제가 몰렸다. 러너스하이 과제를 포함해 6개의 과제를 동시에 진행해야 했다. 나는 아이젠하워 매트릭스에 따라 우선순위를 긴급도/중요도에 따라 나누는 편인데, 6건 중 3건이 중요하거나, 긴급하거나, 중요+긴급했다. 당연히 러너스하이 과제의 우선순위는 뒤로 밀려났다.&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-origin-width="800" data-origin-height="600"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/beyDGb/dJMcacvy0PP/Qeh483WFtm0ZLXpZ8FhSxk/img.png" data-phocus="https://blog.kakaocdn.net/dn/beyDGb/dJMcacvy0PP/Qeh483WFtm0ZLXpZ8FhSxk/img.png" data-alt="아이젠하워 매트릭스"&gt;&lt;img src="https://blog.kakaocdn.net/dn/beyDGb/dJMcacvy0PP/Qeh483WFtm0ZLXpZ8FhSxk/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeyDGb%2FdJMcacvy0PP%2FQeh483WFtm0ZLXpZ8FhSxk%2Fimg.png" onerror="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';" loading="lazy" width="600" height="450" data-origin-width="800" data-origin-height="600"&gt;&lt;/span&gt;&lt;figcaption&gt;아이젠하워 매트릭스&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;그래도 할 수 있을 거라 생각했다. 원래도 항상 과제를 3개씩은 병렬 처리 했고, 연말 휴가자가 많다 보니 회의 시간이 많이 줄고 개발 시간 확보가 가능했다. 무엇보다 러너스하이 과제는 상당 부분 AI에게 맡기고 나는 다른 일을 할 수 있을 거라 기대했다. 여기서 나의 판단 미스가 여럿 있었다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;b&gt;  피드백 시기는 생각 이상으로 빠르고 짧고 자주 가져야 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; 개인적으로 미리 준비하는 것을 선호하고, 책임감을 중요시 여기는 사람이라 일단 내지르고 수습하기보다 어느 정도 준비된 이후에 제안을 하는 편이다. 그래서 과제를 진행하겠다고 공유하고, 어느 정도 조사하고 정리한 뒤, 실제로 수행하기 직전에야 팀원들한테 피드백을 받았다. 그 회의에서 유의미한 피드백들을 많이 받았으나, 피드백을 반영하려면 남은 기간 내 과제 수행이 불가능했다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;나의 작업 순서는 이랬다&lt;/p&gt;
&lt;ol style="list-style-type: decimal;" data-ke-list-type="decimal"&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="size16"&gt;3번 단계를 마치고 피드백을 반영했는데 2번부터 다시 시작해야 해서 시간이 더 걸렸다. 만약 2번에서 피드백을 빨리 받았다면 그에 맞춰 그 이후 과정들도 빠르게 조정되었고, 빠르게 수행할 수 있었을 것이다. 가능하다면 매 단계마다 (=자주) 피드백을 받으면 좋을 것 같으나, 팀 리소스나 이래저래 힘든 상황이라면 적어도 빠르게 피드백받을 수 있는 게 좋다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;b&gt;&lt;b&gt; &lt;span&gt; &lt;/span&gt;&lt;/b&gt;AI가 할 수 있는 영역을 분명하게 인지하자.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; 러너스하이를 시작할 때쯤, 커서 라이선스를 받고 AI가 짜준 코드를 실제로 배포까지 하기 시작했다. 그래서 리소스를 예상할 때 평소보다 짧게 잡았다. 하지만 AI 사용이 미숙하면 오히려 작업이 더 길어질 수 있다는 건 생각하지 못했다. &lt;b&gt;나의 잘못된 AI 사용으로 인해 잘못된 결과가 나오는 경우가 많았다&lt;/b&gt;. 정말 이게 맞을까?라고 AI를 끝없이 의심하며 어떻게 검증하면 좋을지 고민하는 시간이 길었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;여러 시행착오들을 거치며 AI가 이런 부분을 놓칠 수 있겠구나, 프롬프트를 이렇게 입력하면 중의적으로 해석이 가능해서 다른 답변을 내놓는구나, 이 데이터를 활용해 달라고 해야 내가 원하는 결과가 나오겠구나 요런 것들을 인지하기 시작했다. 당연한 이야기일 수 있지만, 내 생각보다 내가 원하는 작업을 디테일하게 제시할수록 원하는 대로 동작할 확률이 커졌다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;b&gt;&lt;b&gt; &lt;span&gt; &lt;/span&gt;&lt;/b&gt;병렬 처리가 많을수록 인간의 컨텍스트 스위칭 비용이 늘어난다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; 여러 과제를 동시에 진행하면서 예상하지 못했던 문제도 있었다. 6개 과제에서 '잠깐 10분만 이야기되시나요?'라고 허들 요청이 들어오면 시간이 얼마나 걸릴까? 6 * 10 이니까 60분? 아니다. 이야기할 때마다 과제가 바뀌니 이건 무슨 이야기더라 로딩하는 시간이 최소 1분씩은 필요하다. 너무 자주 바뀌면 1분에서 기하급수적으로 늘어난다. 이런 일이 반복되고 작업 진행 내역이 더뎌지기 시작했다. 여기서 나는 우선순위를 세우는데 실패했다고 생각한다. 이거 저거 다 하고 싶다/해야 한다는 욕심에 오히려 시간을 더 많이 끌어버린 것 같다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;이번 경험을 통해 내가 동시에 감당할 수 있는 작업의 범위를 조금 더 현실적으로 바라봐야겠다는 생각이 들었다. 모든 일을 다 해내려고 하기보다,&lt;b&gt; 한번 결정한 우선순위를 계속 유지하기보다는 수시로 재검토가 필요하다&lt;/b&gt;는 생각이 들었다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style2"&gt;
&lt;h2 style="text-align: center;" data-ke-size="size26"&gt;✏️ 마무리&lt;/h2&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;러너스하이를 통해 기대했던 경험을 하거나, 원하는 만큼의 결과물을 내지는 못했다. 하지만 내가 일을 진행하는 방식과 생각하는 방식을 돌아볼 수 있었다는 점에서 의미 있는 경험이었다. 개인적으로는 멘토링보다는 채용 프로그램에 가깝다고 느꼈지만, 기왕 참여하기로 했다면 해당 프로그램을 어떤 식으로 활용할지는 참여자의 태도와 마음가짐에 달린 것 같다.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://yeonyeon.tistory.com/362</id>
    <link href="https://yeonyeon.tistory.com/362"/>
    <summary type="html">&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style2" /&gt;
&lt;h2 style="text-align: center;" data-ke-size="size26"&gt;✏️ 서론&lt;/h2&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;지난 12월 ~ 1월에 진행했던 토스 러너스하이를 이제야 후기를 작성한다. 급한 회사 일을 마무리하고 리프레시 휴가도 다녀오느라 연말연초에 정신이 없었다. 이 글은 &lt;b&gt;러너스하이가 어떤 프로그램인지 궁금한 사람들을 위해 간단히 소개하고, 러너스하이를 하면서 얻은 인사이트와 느꼈던 점을 정리한 글&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="text-align: start;"&gt;혹여나 결과만 궁금한 사람들을 위해 미리 말하자면 나는 우수 참여자로 선정되지는 못했다. 그래도 참여하면서 여러 생각을 정리할 수 있었고, 그 과정에서 얻은 것들을 이 글에 남겨본다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-filename="blob" data-origin-width="1001" data-origin-height="136"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/Dqy7C/dJMcaaYMjwY/2rDDtbKu57TMPhgjnxXsr0/img.png" data-phocus="https://blog.kakaocdn.net/dn/Dqy7C/dJMcaaYMjwY/2rDDtbKu57TMPhgjnxXsr0/img.png" data-alt="결과 메일 중 일부"&gt;&lt;img src="https://blog.kakaocdn.net/dn/Dqy7C/dJMcaaYMjwY/2rDDtbKu57TMPhgjnxXsr0/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDqy7C%2FdJMcaaYMjwY%2F2rDDtbKu57TMPhgjnxXsr0%2Fimg.png" onerror="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';" loading="lazy" width="500" height="470" data-filename="blob" data-origin-width="1001" data-origin-height="136"/&gt;&lt;/span&gt;&lt;figcaption&gt;결과 메일 중 일부&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style2" /&gt;
&lt;h2 style="text-align: center;" data-ke-size="size26"&gt;&lt;span style="color: #666666; text-align: left;"&gt; &amp;zwj;♀️ &lt;/span&gt;토스 Learner's High란?&lt;/h2&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-origin-width="1598" data-origin-height="1242"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/qc53b/dJMcafluQZu/0LuopylxrZGQLYgVVDkVx1/img.png" data-phocus="https://blog.kakaocdn.net/dn/qc53b/dJMcafluQZu/0LuopylxrZGQLYgVVDkVx1/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/qc53b/dJMcafluQZu/0LuopylxrZGQLYgVVDkVx1/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqc53b%2FdJMcafluQZu%2F0LuopylxrZGQLYgVVDkVx1%2Fimg.png" onerror="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';" loading="lazy" width="500" height="389" data-origin-width="1598" data-origin-height="1242"/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="color: #333333; text-align: start;"&gt;토스 러너스하이는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;커리어 성장을 원하는 서버 개발자들을 위한 멘토링 프로그램&lt;/b&gt;이다. 아래는 2기 모집 글의 일부를 인용해 왔다.&lt;/p&gt;
&lt;blockquote data-ke-style="style2"&gt;숨이 턱끝까지 차도록 달릴 때 오히려 점점 몸이 가벼워지고 머리가 맑아지는 느낌을 아시나요?&lt;br /&gt;달릴수록 기분이 상쾌해지는 상태를 &lt;b&gt;Runner&amp;rsquo;s High(러너스 하이)&lt;/b&gt; &amp;zwj;♂️라고 해요.&lt;br /&gt;&lt;br /&gt;무언가를 배우며 치열하게 노력할 때도 &lt;b&gt;Learner&amp;rsquo;s High&lt;/b&gt; &amp;zwj;♀️를 경험할 수 있어요.&lt;br /&gt;성장하기 위한 설레는 목표를 세울 때, 그리고 이를 향해 치열하게 달려갈 때 막연한 불안함은 해소되고 자연스럽게 실력과 커리어도 함께 성장해요.&lt;br /&gt;&lt;br /&gt;토스에서 지향하는 서버 개발자의 성장 방향성을 학습한 뒤, 한 달간의 경험을 기록하고 더 큰 기회를 위해 높게 점프하는 &lt;b&gt;토스 Learner&amp;rsquo;s High 서버 2기&lt;/b&gt;를 모집합니다.&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;사실 위 내용만 봤을 때는 커리어에 대한 조언을 해준다는 건가? 어떤 멘토링을 해주는 거지? 감이 잘 안 잡혔다. 아직 2기까지밖에 진행을 안 해서 그런가, 프로그램 수료 후기 찾기도 힘들었다. 당시 내가 궁금해했던 점에 대해 기억을 되살려본다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-origin-width="512" data-origin-height="512"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/YcELT/dJMcaduoHwA/Xk1elFHPk3wjbKMk0IWKr0/img.png" data-phocus="https://blog.kakaocdn.net/dn/YcELT/dJMcaduoHwA/Xk1elFHPk3wjbKMk0IWKr0/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/YcELT/dJMcaduoHwA/Xk1elFHPk3wjbKMk0IWKr0/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYcELT%2FdJMcaduoHwA%2FXk1elFHPk3wjbKMk0IWKr0%2Fimg.png" onerror="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';" loading="lazy" width="300" height="300" data-origin-width="512" data-origin-height="512"/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size="size20"&gt;❓ 토스로 이직을 원하는 사람만 지원할 수 있나요?&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt;&lt;b&gt;&amp;nbsp;아니요&lt;/b&gt;. 저도 이직 계획이 없었으나 멘토링 내용이 궁금해서 지원하였습니다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size="size20"&gt;❓&lt;span&gt; 개인의 커리어 혹은&amp;nbsp;&lt;/span&gt;과제에 대한 피드백이 제공되나요?&lt;/h4&gt;
&lt;p style="color: #333333; text-align: start;" data-ke-size="size16"&gt;&lt;b&gt;&amp;nbsp;아니요&lt;/b&gt;. 세션 -&amp;gt; 과제 수행 -&amp;gt; 과제 제출 -&amp;gt; 합격 발표 순으로 진행되며 별개의 피드백 절차가 없습니다. 우수 선정자 분들은 토스 채용 프로세스를 이어 진행되는 것으로 알고 있는데, 면접에서 과제에 대한 이야기를 나눌 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size="size20"&gt;❓&lt;span&gt;&amp;nbsp;&lt;/span&gt;어떤 멘토링을 받을 수 있나요?&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;b&gt;토스가 일하는 방식에 대해 듣고 새로운 인사이트를 얻을 수 있어요&lt;/b&gt;. 구체적인 내용은 토스에서 개인 블로그 등에 자료 공유를 지양해 달라 하셨어서 생략합니다. 멘토링 프로그램이라고 명시되어 있으나, 어떠한 가이드나 지식이 주어지지는 않습니다. &lt;b&gt;개인적으로는 멘토링이 아닌 채용 프로세스&lt;/b&gt;에 가깝다고 느꼈습니다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style="color: #000000; text-align: start;" data-ke-size="size20"&gt;❓&lt;span&gt; 회사 업무와 병행이 가능한가요?&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;b&gt;네&lt;/b&gt;. 과제 주제를 스스로 정하는데, 실제 업무와 관련하여 잡아야 하기 때문에 반드시 병행해야 합니다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style="color: #000000; text-align: start;" data-ke-size="size20"&gt;❓&lt;span&gt;&amp;nbsp;중도 포기가 가능한가요?&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt;&lt;b&gt;네&lt;/b&gt;. 과제 제출을 안 하면 됩니다. 실제로 회사 업무가 바빠져서 제출을 안 하거나 멘토링 프로그램이 생각하는 방향과 달라서 포기하시는 분들도 많은 것 같았어요. 저도 회사 업무가 바빠져서 처음 목표치를 달성하지는 못했습니다. 실제 결과물은 없었지만, 현재 상황 정리에 의미를 두고자 뭐라도 써서 제출만 했어요.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style="color: #000000; text-align: start;" data-ke-size="size20"&gt;❓&lt;span&gt; 수료증이 발급되나요?&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt;&lt;span&gt;&amp;nbsp;&lt;b&gt;수료증은 별도로 없습니다&lt;/b&gt;. 마지막 과제물을 제출하면 '우수 참여자' 선정 여부에 대해서만 메일로 안내가 옵니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-origin-width="1860" data-origin-height="88"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/blUybR/dJMcaadrJxE/EIwX1Y2i0ihntKpYdYp6T0/img.png" data-phocus="https://blog.kakaocdn.net/dn/blUybR/dJMcaadrJxE/EIwX1Y2i0ihntKpYdYp6T0/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/blUybR/dJMcaadrJxE/EIwX1Y2i0ihntKpYdYp6T0/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblUybR%2FdJMcaadrJxE%2FEIwX1Y2i0ihntKpYdYp6T0%2Fimg.png" onerror="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';" loading="lazy" width="1860" height="88" data-origin-width="1860" data-origin-height="88"/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style2" /&gt;
&lt;h2 style="text-align: center;" data-ke-size="size26"&gt;&lt;span&gt;  인사이트 및 생각 정리&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-origin-width="1536" data-origin-height="1024"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/SDUbR/dJMcabXIn5J/kiz6K4sUIi1HLIlXu7pWL1/img.png" data-phocus="https://blog.kakaocdn.net/dn/SDUbR/dJMcabXIn5J/kiz6K4sUIi1HLIlXu7pWL1/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/SDUbR/dJMcabXIn5J/kiz6K4sUIi1HLIlXu7pWL1/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSDUbR%2FdJMcabXIn5J%2Fkiz6K4sUIi1HLIlXu7pWL1%2Fimg.png" onerror="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';" loading="lazy" width="400" height="267" data-origin-width="1536" data-origin-height="1024"/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size="size20"&gt;  내 생각을 정리해 볼 수 있었던 기회&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt;러너스하이를 신청하려면 '잘하는 개발자란 어떤 역량을 가진 사람인가?'에 대한 답변과 이력서를 제출해야 한다. 요 두 가지를 정리하면서 여러 방면의 내 생각을 정리할 수 있던 것 같다. 개발자의 역량에 대해서는 &lt;a href="https://yeonyeon.tistory.com/360" target="_blank" rel="noopener"&gt;2025년 회고글&lt;/a&gt;에서 다룬 바가 있어서 생략한다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;현재 회사에 입사하고 지금까지 재직 중 회사 추가 외에는 이력서 업데이트 한 적이 없었다. &lt;span style="color: #333333; text-align: start;"&gt;이력서를 정리하면서 여러 생각이 들었었는데,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;내가 3년간 근무하면서 &lt;b&gt;어떤 일들을 했었는지 돌아볼 수 있어서 좋았다&lt;/b&gt;. 이런 경험을 통해 저런 점을 느꼈었지, 이 과제는 이런 식으로 정리할 수 있겠구나 같은 생각들이 떠올랐다. 이력서를 수정하고 싶은 포인트들을 짚어내다 보니 &lt;b&gt;앞으로 어떤 경험을 더 쌓고 싶은지도 조금씩 보이는 듯했다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;아쉬운 부분은 이런 생각을 혼자서만 했다는 점? 다른 사람들의 소감이나 생각을 나누거나, 멘토링을 통해 멘토의 의견도 듣고 싶다. 조만간 이야기를 나눌 수 있는 자리를 만들거나 누군가에게 부탁을 드려야지 싶다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style="color: #000000;" data-ke-size="size20"&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;성과를 지표로 설명하는 연습&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt;러너스하이에서 수행할 과제 주제를 스스로 선정해야 한다. 이때 명확한 지표를 통해 성과를 증명해 낼 수 있는 과제를 선정한다고 생각하니 골 아팠다. 어떤 관점으로 접근해야 할지 너무 생소했다. 그래서 일단은 나 혹은 팀원들이 현재 느끼고 있는 불편함들을 정리했다. 회사에서 팀원들이랑 "이런 기능도 있으면 편할 것 같다", "저 부분도 고치면 좋겠다" 같은 이야기를 자주 하는 편이다 보니 정리가 오래 걸리지는 않았다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;고민 목록은 아래와 같은 형식으로 작성하였다.&lt;/p&gt;
&lt;ul style="list-style-type: disc;" data-ke-list-type="disc"&gt;
&lt;li&gt;고민 요약
&lt;ul style="list-style-type: disc;" data-ke-list-type="disc"&gt;
&lt;li&gt;고민하게 된 배경 혹은 원인&lt;/li&gt;
&lt;li&gt;시도할 수 있는 방안&lt;/li&gt;
&lt;li&gt;해당 고민을 개선함으로써 얻을 수 있는 임팩트&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;그다음은 토스에서 제시한 가이드와 내부 평가 지표의 일부를 참고하여 두 가지 기준을 세웠다.&lt;/p&gt;
&lt;ol style="list-style-type: decimal;" data-ke-list-type="decimal"&gt;
&lt;li&gt;결과 측정이 가능한 지표가 존재하는가?&lt;/li&gt;
&lt;li&gt;한 달 내 개발을 완수할 수 있는가?&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;과제 수행 완료 후가 아닌 수행 전에 임팩트를 예상하는 게 어려웠다. 내가 가진 고민이 시스템 아키텍처나 서버의 안정성과 관련된 고민들이 많아서 그런 건가?라는 생각도 했지만 비즈니스 과제면 사용자 지표를 예상해야 하니까 더 어려울 것 같기도 하고... &lt;b&gt;어떤 임팩트가 있을지 나름 고민을 많이 해보고 과제를 선정했지만, 실제 과제 수행 이후에 성과를 정리해 보자니 엉뚱한 임팩트를 제시했거나 증명하기 어려운 기준을 예측&lt;/b&gt;한 것 같기도 하다. 이 부분에 대해서는 앞으로 여러 과제를 수행하면서 &lt;b&gt;계속 시행착오를 겪으며 감을 찾아야 할 것 같다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;앞으로는 이런 임팩트를 예상하는 게 내게 더 중요해질 것 같다. 토스 러너스하이 진행 당시에는 서버 개발자만 모인 기능 조직이었고, 현재는 애자일 단위로 일하는 목적 조직으로 변해서 일하는 방식이 많이 바뀌고 있다. 기술 과제를 완수하고 개선 효과를 정리하는 건 종종 했지만 비즈니스 과제의 지표를 수집하고 예측 분석하는 게 어렵다. 낯설지만 익숙해져 가야 하는 것 같다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size="size20"&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;여러 과제를 동시에 진행하며 느낀 리소스 관리&lt;/h4&gt;
&lt;p data-ke-size="size16"&gt;러너스하이 시작할 때쯤 갑자기 비즈니스 과제가 몰렸다. 러너스하이 과제를 포함해 6개의 과제를 동시에 진행해야 했다. 나는 아이젠하워 매트릭스에 따라 우선순위를 긴급도/중요도에 따라 나누는 편인데, 6건 중 3건이 중요하거나, 긴급하거나, 중요+긴급했다. 당연히 러너스하이 과제의 우선순위는 뒤로 밀려났다.&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-origin-width="800" data-origin-height="600"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/beyDGb/dJMcacvy0PP/Qeh483WFtm0ZLXpZ8FhSxk/img.png" data-phocus="https://blog.kakaocdn.net/dn/beyDGb/dJMcacvy0PP/Qeh483WFtm0ZLXpZ8FhSxk/img.png" data-alt="아이젠하워 매트릭스"&gt;&lt;img src="https://blog.kakaocdn.net/dn/beyDGb/dJMcacvy0PP/Qeh483WFtm0ZLXpZ8FhSxk/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeyDGb%2FdJMcacvy0PP%2FQeh483WFtm0ZLXpZ8FhSxk%2Fimg.png" onerror="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';" loading="lazy" width="600" height="450" data-origin-width="800" data-origin-height="600"/&gt;&lt;/span&gt;&lt;figcaption&gt;아이젠하워 매트릭스&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;그래도 할 수 있을 거라 생각했다. 원래도 항상 과제를 3개씩은 병렬 처리 했고, 연말 휴가자가 많다 보니 회의 시간이 많이 줄고 개발 시간 확보가 가능했다. 무엇보다 러너스하이 과제는 상당 부분 AI에게 맡기고 나는 다른 일을 할 수 있을 거라 기대했다. 여기서 나의 판단 미스가 여럿 있었다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;b&gt;  피드백 시기는 생각 이상으로 빠르고 짧고 자주 가져야 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;개인적으로 미리 준비하는 것을 선호하고, 책임감을 중요시 여기는 사람이라 일단 내지르고 수습하기보다 어느 정도 준비된 이후에 제안을 하는 편이다. 그래서 과제를 진행하겠다고 공유하고, 어느 정도 조사하고 정리한 뒤, 실제로 수행하기 직전에야 팀원들한테 피드백을 받았다. 그 회의에서 유의미한 피드백들을 많이 받았으나, 피드백을 반영하려면 남은 기간 내 과제 수행이 불가능했다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;나의 작업 순서는 이랬다&lt;/p&gt;
&lt;ol style="list-style-type: decimal;" data-ke-list-type="decimal"&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="size16"&gt;3번 단계를 마치고 피드백을 반영했는데 2번부터 다시 시작해야 해서 시간이 더 걸렸다. 만약 2번에서 피드백을 빨리 받았다면 그에 맞춰 그 이후 과정들도 빠르게 조정되었고, 빠르게 수행할 수 있었을 것이다. 가능하다면 매 단계마다 (=자주) 피드백을 받으면 좋을 것 같으나, 팀 리소스나 이래저래 힘든 상황이라면 적어도 빠르게 피드백받을 수 있는 게 좋다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;b&gt;&lt;b&gt; &lt;span&gt; &lt;/span&gt;&lt;/b&gt;AI가 할 수 있는 영역을 분명하게 인지하자.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;러너스하이를 시작할 때쯤, 커서 라이선스를 받고 AI가 짜준 코드를 실제로 배포까지 하기 시작했다. 그래서 리소스를 예상할 때 평소보다 짧게 잡았다. 하지만 AI 사용이 미숙하면 오히려 작업이 더 길어질 수 있다는 건 생각하지 못했다. &lt;b&gt;나의 잘못된 AI 사용으로 인해 잘못된 결과가 나오는 경우가 많았다&lt;/b&gt;. 정말 이게 맞을까?라고 AI를 끝없이 의심하며 어떻게 검증하면 좋을지 고민하는 시간이 길었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;여러 시행착오들을 거치며 AI가 이런 부분을 놓칠 수 있겠구나, 프롬프트를 이렇게 입력하면 중의적으로 해석이 가능해서 다른 답변을 내놓는구나, 이 데이터를 활용해 달라고 해야 내가 원하는 결과가 나오겠구나 요런 것들을 인지하기 시작했다. 당연한 이야기일 수 있지만, 내 생각보다 내가 원하는 작업을 디테일하게 제시할수록 원하는 대로 동작할 확률이 커졌다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;b&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;병렬 처리가 많을수록 인간의 컨텍스트 스위칭 비용이 늘어난다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;여러 과제를 동시에 진행하면서 예상하지 못했던 문제도 있었다. 6개 과제에서 '잠깐 10분만 이야기되시나요?'라고 허들 요청이 들어오면 시간이 얼마나 걸릴까? 6 * 10 이니까 60분? 아니다. 이야기할 때마다 과제가 바뀌니 이건 무슨 이야기더라 로딩하는 시간이 최소 1분씩은 필요하다. 너무 자주 바뀌면 1분에서 기하급수적으로 늘어난다. 이런 일이 반복되고 작업 진행 내역이 더뎌지기 시작했다. 여기서 나는 우선순위를 세우는데 실패했다고 생각한다. 이거 저거 다 하고 싶다/해야 한다는 욕심에 오히려 시간을 더 많이 끌어버린 것 같다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;이번 경험을 통해 내가 동시에 감당할 수 있는 작업의 범위를 조금 더 현실적으로 바라봐야겠다는 생각이 들었다. 모든 일을 다 해내려고 하기보다,&lt;b&gt; 한번 결정한 우선순위를 계속 유지하기보다는 수시로 재검토가 필요하다&lt;/b&gt;는 생각이 들었다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style2" /&gt;
&lt;h2 style="text-align: center;" data-ke-size="size26"&gt;✏️ 마무리&lt;/h2&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;러너스하이를 통해 기대했던 경험을 하거나, 원하는 만큼의 결과물을 내지는 못했다. 하지만 내가 일을 진행하는 방식과 생각하는 방식을 돌아볼 수 있었다는 점에서 의미 있는 경험이었다. 개인적으로는 멘토링보다는 채용 프로그램에 가깝다고 느꼈지만, 기왕 참여하기로 했다면 해당 프로그램을 어떤 식으로 활용할지는 참여자의 태도와 마음가짐에 달린 것 같다.&lt;/p&gt;</summary>
    <title>토스 러너스하이 서버 2기 후기 - 한 달 동안 얻은 인사이트</title>
    <updated>2026-03-12T23:03:00+09:00</updated>
    <dc:date>2026-03-12T23:03:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>GREEN.1229</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;안녕하세요. &lt;span style="color: #409d00;"&gt;&lt;b&gt;그린&lt;/b&gt;&lt;/span&gt;입니다  &lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이번 포스팅에서는 &lt;span style="background-color: #9feec3;"&gt;&lt;b&gt;SE-0515 Allow reduce to produce noncopyable results&lt;/b&gt;&lt;/span&gt;에 대해 정리해보겠습니다  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-filename="123123.001.jpeg" data-origin-width="400" data-origin-height="400"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/bnwJAN/dJMcaaq0IDg/6JsTRObklbYLkODPCREjcK/img.jpg" data-phocus="https://blog.kakaocdn.net/dn/bnwJAN/dJMcaaq0IDg/6JsTRObklbYLkODPCREjcK/img.jpg"&gt;&lt;img src="https://blog.kakaocdn.net/dn/bnwJAN/dJMcaaq0IDg/6JsTRObklbYLkODPCREjcK/img.jpg" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnwJAN%2FdJMcaaq0IDg%2F6JsTRObklbYLkODPCREjcK%2Fimg.jpg" onerror="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';" loading="lazy" width="400" height="400" data-filename="123123.001.jpeg" data-origin-width="400" data-origin-height="400"&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5"&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;Intro&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;Swift의 reduce는 정말 유용한 함수이지만, 몇 가지 한계가 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;noncopyable 타입을 다룰 수 없었고, initial value를 borrow하는 방식이라 불필요한 복사가 발생했어요.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;SE-0515는 reduce를 개선합니다  &lt;/span&gt;&lt;/p&gt;
&lt;ul style="list-style-type: disc; color: #000000; text-align: start;" data-ke-list-type="disc"&gt;
&lt;li&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;Noncopyable initial value와 result를 허용하고&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;Copyable일 때도 initial value를 consume하도록 변경합니다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;span style="font-family: 'Noto Serif KR'; color: #000000;"&gt;이미 PR이 Accepted 상태이고 구현도 완료되었으니, 곧 현업에서도 쓸 수 있을 것 같습니다  &lt;/span&gt;&lt;/blockquote&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5"&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;왜 필요한가?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;Noncopyable 타입은 SE-0390에서 도입되어 타입의 의미론과 성능을 제어하는 강력한 메커니즘을 제공&lt;/b&gt;합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;Sequence는 (아직은) noncopyable 타입을 담을 수 없지만, &lt;b&gt;reduce의 accumulation argument는 sequence와 독립적&lt;/b&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;따라서 initial value를 &lt;b&gt;borrow 대신 consume하면, 복사 능력에 의존하지 않고도 reduce를 구현&lt;/b&gt;할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5"&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;현재 reduce의 문제점&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;span style="font-family: 'Noto Serif KR'; color: #000000;"&gt;현재 reduce 구현은 parameter를 borrow합니다.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre class="swift" style="color: #000000; text-align: start;" data-ke-language="swift"&gt;&lt;code&gt;func reduce&amp;lt;Result&amp;gt;(
  _ initialResult: Result,
  _ nextPartialResult:
    (_ partialResult: Result, Element) throws -&amp;gt; Result
) rethrows -&amp;gt; Result {
  var accumulator = initialResult
  for element in self {
    accumulator = try nextPartialResult(accumulator, element)
  }
  return accumulator
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;여기서 borrow는 암묵적입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;initializer가 아닌 argument의 기본값이니까요.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;h3 style="color: #000000; text-align: start;" data-ke-size="size23"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;그래서 문제가..?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="color: #000000;"&gt;&lt;b&gt;&lt;span style="font-family: 'Nanum Gothic';"&gt;첫 단계가 항상 initialResult의 mutable copy를 만드는 겁니다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class="swift" style="color: #000000; text-align: start;" data-ke-language="swift"&gt;&lt;code&gt;var accumulator = initialResult  // 복사 발생!&lt;/code&gt;&lt;/pre&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이 패턴은 initial의 올바른 calling convention이 consuming이어야 한다는 걸 강하게 암시합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;만약 값이 copyable이면,&lt;/span&gt;&lt;/p&gt;
&lt;ul style="list-style-type: disc; color: #000000; text-align: start;" data-ke-list-type="disc"&gt;
&lt;li&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;호출자가 복사를 만듭니다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;단, optimizer가 마지막 사용임을 확인하면 복사를 완전히 제거할 수 있습니다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR'; color: #000000;"&gt;이런 경우는 reduce에서 매우 흔합니다. "initial value"가 종종 reduction만을 위해 생성되니까요.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5"&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;솔루션&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;reduce를 noncopyable 값에서도 동작하도록 일반화하면, initial value를 consume하는 게 &lt;b&gt;필수&lt;/b&gt;가 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;var accumulator = initialResult가 더 이상 컴파일되지 않으니까요.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;span style="font-family: 'Noto Serif KR'; color: #000000;"&gt;즉, 새 버전의 reduce는 이렇게 작성됩니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;pre class="swift" style="color: #000000; text-align: start;" data-ke-language="swift"&gt;&lt;code&gt;extension Sequence {
  public func reduce&amp;lt;Result: ~Copyable&amp;gt;(
    _ initialResult: consuming Result,
    _ nextPartialResult:
      (_ partialResult: consuming Result, Element) throws -&amp;gt; Result
  ) rethrows -&amp;gt; Result

  public func reduce&amp;lt;Result: ~Copyable&amp;gt;(
    into initialResult: consuming Result,
    _ updateAccumulatingResult:
      (_ partialResult: inout Result, Element) throws -&amp;gt; ()
  ) rethrows -&amp;gt; Result
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;실제 구현&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class="swift" style="color: #000000; text-align: start;"&gt;&lt;code&gt;public func reduce&amp;lt;Result: ~Copyable&amp;gt;(
  _ initialResult: consuming Result,
  _ nextPartialResult:
    (_ partialResult: consuming Result, Element) throws -&amp;gt; Result
) rethrows -&amp;gt; Result {
  for element in self {
    initialResult = try nextPartialResult(initialResult, element)
  }
  return initialResult
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;span style="font-family: 'Noto Serif KR'; color: #000000;"&gt;더 이상 initialResult 값을 복사할 필요가 없습니다. consuming(즉, owned not borrowed)으로 받으니까요!&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5"&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;reduce(::)와 reduce(into:_:)의 차이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이 시점에서 두 함수는 거의 동일해지고, reduce(into:_:)의 동기가 줄어듭니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;어떤 걸 쓸지는 주로 개발자&lt;b&gt; 선택&lt;/b&gt;의 문제가 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5"&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;성능 개선&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 style="color: #000000; text-align: start;" data-ke-size="size23"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;"세계에서 가장 느린 map" 문제&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이 변경은 고전적인 세 가지 원인 중 하나를 제거합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class="swift" style="color: #000000; text-align: start;" data-ke-language="swift"&gt;&lt;code&gt;array.reduce([]) { $0 + [$1] }&lt;/code&gt;&lt;/pre&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이건 여전히 O(n²)입니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style="list-style-type: disc; color: #000000; text-align: start;" data-ke-list-type="disc"&gt;
&lt;li&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;+가 argument를 borrow하고 모든 element를 복사한 새 array를 반환&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;[$1]이 버릴 거면서도 새 array buffer를 할당&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;하지만 새 reduce로는 이렇게 쓸 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class="swift" style="color: #000000; text-align: start;" data-ke-language="swift"&gt;&lt;code&gt;array.reduce([]) { $0.append($1); return $0 }&lt;/code&gt;&lt;/pre&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이제 다음과 같은 성능을 얻습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class="swift" style="color: #000000; text-align: start;" data-ke-language="swift"&gt;&lt;code&gt;array.reduce(into: []) { $0.append($1) }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;약간은 더 reduce(into:_:)와 동일한 성능이죠!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5"&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;주의사항&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;물론 이런 모든 비효율성은 optimizer가 heroic optimization을 수행하면 제거될 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;하지만 이런&lt;b&gt; heroic optimization은 조금만 복잡한 예시에서는 무너지는 경향이 있어서, 성능 절벽으로 이어집니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;h3 style="color: #000000; text-align: start;" data-ke-size="size23"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;reduce(into:_:)는?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;reduce(into:_:)는 이미 argument를 consuming으로 받습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;따라서 유일한 변경은 Result: ~Copyable 추가뿐입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5"&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;향후 방향&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 style="color: #000000; text-align: start;" data-ke-size="size23"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;~Escapable 지원&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;b&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;reduce는 ~Escapable 값에서도 동작하도록 업데이트될 수 있습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이를 위해서는 함수와 closure parameter 모두에 lifetime annotation이 필요한데, 후자는 Swift에서 아직 지원되지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5"&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;SE-0515는 이미 &lt;b&gt;Accepted&lt;/b&gt;되었고 구현도 완료된 상태입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;개인적으로는 정말 합리적인 개선이라고 생각합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;reduce가 initial value를 borrow하는 건 원래부터 이상했어요. &lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;첫 줄에서 바로 복사하는데 말이죠.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이제 noncopyable 타입도 지원하고, copyable 타입에서도 불필요한 복사를 줄일 수 있게 되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;"세계에서 가장 느린 map" 같은 실수도 조금 덜 치명적으로 만들어주는 좋은 변경이네요  &lt;/span&gt;&lt;/blockquote&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt; &lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5"&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;References&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;figure id="og_1773441442058" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="object" data-og-title="swift-evolution/proposals/0515-noncopyable-reduce.md at main · swiftlang/swift-evolution" data-og-description="This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution" data-og-host="github.com" data-og-source-url="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0515-noncopyable-reduce.md" data-og-url="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0515-noncopyable-reduce.md" data-og-image="https://scrap.kakaocdn.net/dn/bfJK2w/dJMb84XXjzL/gzj5D4GykeRsuWl97tGsS0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/dkSYOC/dJMb81GVMMq/i5M85e1kvbIWkz76BlVA9K/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600"&gt;&lt;a href="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0515-noncopyable-reduce.md" target="_blank" rel="noopener" data-source-url="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0515-noncopyable-reduce.md"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/bfJK2w/dJMb84XXjzL/gzj5D4GykeRsuWl97tGsS0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/dkSYOC/dJMb81GVMMq/i5M85e1kvbIWkz76BlVA9K/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');"&gt; &lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;swift-evolution/proposals/0515-noncopyable-reduce.md at main · swiftlang/swift-evolution&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id="og_1773441443558" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="[Pitch] Allow `reduce` to produce noncopyable results" data-og-description="Hi Swift Evolution, It is obligatory that I doom this pitch as possibly the least controversial pitch I can think of. Allow reduce to produce noncopyable results Proposal: SE-NNNN Authors: Ben Cohen Review Manager: TBD Status: Awaiting implementation or Aw" data-og-host="forums.swift.org" data-og-source-url="https://forums.swift.org/t/pitch-allow-reduce-to-produce-noncopyable-results/84073" data-og-url="https://forums.swift.org/t/pitch-allow-reduce-to-produce-noncopyable-results/84073" data-og-image="https://scrap.kakaocdn.net/dn/hG9jL/dJMb9efcvm0/zo8esEqw6XPZPC21OAvyzK/img.png?width=590&amp;amp;height=585&amp;amp;face=0_0_590_585,https://scrap.kakaocdn.net/dn/jQAly/dJMb9bv0RMZ/lKgz1rcgdHfDAOpHhOEsck/img.png?width=151&amp;amp;height=150&amp;amp;face=0_0_151_150"&gt;&lt;a href="https://forums.swift.org/t/pitch-allow-reduce-to-produce-noncopyable-results/84073" target="_blank" rel="noopener" data-source-url="https://forums.swift.org/t/pitch-allow-reduce-to-produce-noncopyable-results/84073"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/hG9jL/dJMb9efcvm0/zo8esEqw6XPZPC21OAvyzK/img.png?width=590&amp;amp;height=585&amp;amp;face=0_0_590_585,https://scrap.kakaocdn.net/dn/jQAly/dJMb9bv0RMZ/lKgz1rcgdHfDAOpHhOEsck/img.png?width=151&amp;amp;height=150&amp;amp;face=0_0_151_150');"&gt; &lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;[Pitch] Allow `reduce` to produce noncopyable results&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;Hi Swift Evolution, It is obligatory that I doom this pitch as possibly the least controversial pitch I can think of. Allow reduce to produce noncopyable results Proposal: SE-NNNN Authors: Ben Cohen Review Manager: TBD Status: Awaiting implementation or Aw&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;forums.swift.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id="og_1773441444386" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="SE-0515: Allow `reduce` to produce noncopyable results" data-og-description="Hi everybody. The review of SE-0515: Allow reduce to produce noncopyable results begins now and runs through March 10, 2026. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you " data-og-host="forums.swift.org" data-og-source-url="https://forums.swift.org/t/se-0515-allow-reduce-to-produce-noncopyable-results/84997" data-og-url="https://forums.swift.org/t/se-0515-allow-reduce-to-produce-noncopyable-results/84997" data-og-image="https://scrap.kakaocdn.net/dn/rXP5X/dJMb9bv0RM0/wjhIOQMxVpQYATZe6bj6p1/img.png?width=590&amp;amp;height=585&amp;amp;face=0_0_590_585,https://scrap.kakaocdn.net/dn/NNLF8/dJMb9efcvm1/EKgKr7j5DU7KFuDsCk4q9K/img.png?width=151&amp;amp;height=150&amp;amp;face=0_0_151_150"&gt;&lt;a href="https://forums.swift.org/t/se-0515-allow-reduce-to-produce-noncopyable-results/84997" target="_blank" rel="noopener" data-source-url="https://forums.swift.org/t/se-0515-allow-reduce-to-produce-noncopyable-results/84997"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/rXP5X/dJMb9bv0RM0/wjhIOQMxVpQYATZe6bj6p1/img.png?width=590&amp;amp;height=585&amp;amp;face=0_0_590_585,https://scrap.kakaocdn.net/dn/NNLF8/dJMb9efcvm1/EKgKr7j5DU7KFuDsCk4q9K/img.png?width=151&amp;amp;height=150&amp;amp;face=0_0_151_150');"&gt; &lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;SE-0515: Allow `reduce` to produce noncopyable results&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;Hi everybody. The review of SE-0515: Allow reduce to produce noncopyable results begins now and runs through March 10, 2026. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;forums.swift.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id="og_1773441446228" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="[Accepted] SE-0515: Allow `reduce` to produce noncopyable results" data-og-description="The review of SE-0515: Allow reduce to produce noncopyable results has ended, and the Language Steering Group has decided to accept the proposal. There was unanimous support for what the community sees as an obvious generalization of the existing reduce AP" data-og-host="forums.swift.org" data-og-source-url="https://forums.swift.org/t/accepted-se-0515-allow-reduce-to-produce-noncopyable-results/85286" data-og-url="https://forums.swift.org/t/accepted-se-0515-allow-reduce-to-produce-noncopyable-results/85286" data-og-image="https://scrap.kakaocdn.net/dn/ds5Bad/dJMb81fRbyn/Pj8KPeGFyNoI55bKDTilVk/img.png?width=590&amp;amp;height=585&amp;amp;face=0_0_590_585,https://scrap.kakaocdn.net/dn/bjYdjt/dJMb87NUYBx/H85zmvOdJkd5CUAKx8KoS0/img.png?width=151&amp;amp;height=150&amp;amp;face=0_0_151_150"&gt;&lt;a href="https://forums.swift.org/t/accepted-se-0515-allow-reduce-to-produce-noncopyable-results/85286" target="_blank" rel="noopener" data-source-url="https://forums.swift.org/t/accepted-se-0515-allow-reduce-to-produce-noncopyable-results/85286"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/ds5Bad/dJMb81fRbyn/Pj8KPeGFyNoI55bKDTilVk/img.png?width=590&amp;amp;height=585&amp;amp;face=0_0_590_585,https://scrap.kakaocdn.net/dn/bjYdjt/dJMb87NUYBx/H85zmvOdJkd5CUAKx8KoS0/img.png?width=151&amp;amp;height=150&amp;amp;face=0_0_151_150');"&gt; &lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;[Accepted] SE-0515: Allow `reduce` to produce noncopyable results&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;The review of SE-0515: Allow reduce to produce noncopyable results has ended, and the Language Steering Group has decided to accept the proposal. There was unanimous support for what the community sees as an obvious generalization of the existing reduce AP&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;forums.swift.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://green1229.tistory.com/612</id>
    <link href="https://green1229.tistory.com/612"/>
    <summary type="html">&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;안녕하세요.&amp;nbsp;&lt;span style="color: #409d00;"&gt;&lt;b&gt;그린&lt;/b&gt;&lt;/span&gt;입니다  &lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이번 포스팅에서는&amp;nbsp;&lt;span style="background-color: #9feec3;"&gt;&lt;b&gt;SE-0515 Allow reduce to produce noncopyable results&lt;/b&gt;&lt;/span&gt;에 대해 정리해보겠습니다  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-filename="123123.001.jpeg" data-origin-width="400" data-origin-height="400"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/bnwJAN/dJMcaaq0IDg/6JsTRObklbYLkODPCREjcK/img.jpg" data-phocus="https://blog.kakaocdn.net/dn/bnwJAN/dJMcaaq0IDg/6JsTRObklbYLkODPCREjcK/img.jpg"&gt;&lt;img src="https://blog.kakaocdn.net/dn/bnwJAN/dJMcaaq0IDg/6JsTRObklbYLkODPCREjcK/img.jpg" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnwJAN%2FdJMcaaq0IDg%2F6JsTRObklbYLkODPCREjcK%2Fimg.jpg" onerror="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';" loading="lazy" width="400" height="400" data-filename="123123.001.jpeg" data-origin-width="400" data-origin-height="400"/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5" /&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;Intro&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;Swift의&amp;nbsp;reduce는 정말 유용한 함수이지만, 몇 가지 한계가 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;noncopyable 타입을 다룰 수 없었고, initial value를 borrow하는 방식이라 불필요한 복사가 발생했어요.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;SE-0515는&amp;nbsp;reduce를 개선합니다  &lt;/span&gt;&lt;/p&gt;
&lt;ul style="list-style-type: disc; color: #000000; text-align: start;" data-ke-list-type="disc"&gt;
&lt;li&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;Noncopyable initial value와 result를 허용하고&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;Copyable일 때도 initial value를 consume하도록 변경합니다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;span style="font-family: 'Noto Serif KR'; color: #000000;"&gt;이미 PR이 Accepted&amp;nbsp;상태이고 구현도 완료되었으니, 곧 현업에서도 쓸 수 있을 것 같습니다  &lt;/span&gt;&lt;/blockquote&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5" /&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;왜 필요한가?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;Noncopyable 타입은 SE-0390에서 도입되어 타입의 의미론과 성능을 제어하는 강력한 메커니즘을 제공&lt;/b&gt;합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;Sequence는 (아직은) noncopyable 타입을 담을 수 없지만,&amp;nbsp;&lt;b&gt;reduce의 accumulation argument는 sequence와 독립적&lt;/b&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;따라서 initial value를 &lt;b&gt;borrow 대신 consume하면, 복사 능력에 의존하지 않고도&amp;nbsp;reduce를 구현&lt;/b&gt;할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5" /&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;현재 reduce의 문제점&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;span style="font-family: 'Noto Serif KR'; color: #000000;"&gt;현재&amp;nbsp;reduce&amp;nbsp;구현은 parameter를&amp;nbsp;borrow합니다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre class="swift" style="color: #000000; text-align: start;" data-ke-language="swift"&gt;&lt;code&gt;func reduce&amp;lt;Result&amp;gt;(
  _ initialResult: Result,
  _ nextPartialResult:
    (_ partialResult: Result, Element) throws -&amp;gt; Result
) rethrows -&amp;gt; Result {
  var accumulator = initialResult
  for element in self {
    accumulator = try nextPartialResult(accumulator, element)
  }
  return accumulator
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;여기서 borrow는 암묵적입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;initializer가 아닌 argument의 기본값이니까요.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style="color: #000000; text-align: start;" data-ke-size="size23"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;그래서 문제가..?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="color: #000000;"&gt;&lt;b&gt;&lt;span style="font-family: 'Nanum Gothic';"&gt;첫 단계가 항상&amp;nbsp;initialResult의 mutable copy를 만드는 겁니다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class="swift" style="color: #000000; text-align: start;" data-ke-language="swift"&gt;&lt;code&gt;var accumulator = initialResult  // 복사 발생!&lt;/code&gt;&lt;/pre&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이 패턴은 initial의 올바른 calling convention이 consuming이어야 한다는 걸 강하게 암시합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;만약 값이 copyable이면,&lt;/span&gt;&lt;/p&gt;
&lt;ul style="list-style-type: disc; color: #000000; text-align: start;" data-ke-list-type="disc"&gt;
&lt;li&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;호출자가 복사를 만듭니다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;단, optimizer가 마지막 사용임을 확인하면 복사를 완전히 제거할 수 있습니다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="font-family: 'Noto Serif KR'; color: #000000;"&gt;이런 경우는&amp;nbsp;reduce에서 매우 흔합니다. "initial value"가 종종 reduction만을 위해 생성되니까요.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5" /&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;솔루션&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;reduce를 noncopyable 값에서도 동작하도록 일반화하면, initial value를 consume하는 게&amp;nbsp;&lt;b&gt;필수&lt;/b&gt;가 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;var accumulator = initialResult가 더 이상 컴파일되지 않으니까요.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;span style="font-family: 'Noto Serif KR'; color: #000000;"&gt;즉, 새 버전의&amp;nbsp;reduce는 이렇게 작성됩니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class="swift" style="color: #000000; text-align: start;" data-ke-language="swift"&gt;&lt;code&gt;extension Sequence {
  public func reduce&amp;lt;Result: ~Copyable&amp;gt;(
    _ initialResult: consuming Result,
    _ nextPartialResult:
      (_ partialResult: consuming Result, Element) throws -&amp;gt; Result
  ) rethrows -&amp;gt; Result

  public func reduce&amp;lt;Result: ~Copyable&amp;gt;(
    into initialResult: consuming Result,
    _ updateAccumulatingResult:
      (_ partialResult: inout Result, Element) throws -&amp;gt; ()
  ) rethrows -&amp;gt; Result
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;실제 구현&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class="swift" style="color: #000000; text-align: start;"&gt;&lt;code&gt;public func reduce&amp;lt;Result: ~Copyable&amp;gt;(
  _ initialResult: consuming Result,
  _ nextPartialResult:
    (_ partialResult: consuming Result, Element) throws -&amp;gt; Result
) rethrows -&amp;gt; Result {
  for element in self {
    initialResult = try nextPartialResult(initialResult, element)
  }
  return initialResult
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;span style="font-family: 'Noto Serif KR'; color: #000000;"&gt;더 이상&amp;nbsp;initialResult&amp;nbsp;값을 복사할 필요가 없습니다.&amp;nbsp;consuming(즉, owned not borrowed)으로 받으니까요!&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5" /&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;reduce(::)와 reduce(into:_:)의 차이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이 시점에서 두 함수는 거의 동일해지고,&amp;nbsp;reduce(into:_:)의 동기가 줄어듭니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;어떤 걸 쓸지는 주로 개발자&lt;b&gt;&amp;nbsp;선택&lt;/b&gt;의 문제가 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5" /&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;성능 개선&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 style="color: #000000; text-align: start;" data-ke-size="size23"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;"세계에서 가장 느린 map" 문제&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이 변경은 고전적인 세 가지 원인 중 하나를 제거합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class="swift" style="color: #000000; text-align: start;" data-ke-language="swift"&gt;&lt;code&gt;array.reduce([]) { $0 + [$1] }&lt;/code&gt;&lt;/pre&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이건 여전히 O(n&amp;sup2;)입니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style="list-style-type: disc; color: #000000; text-align: start;" data-ke-list-type="disc"&gt;
&lt;li&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;+가 argument를 borrow하고 모든 element를 복사한 새 array를 반환&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;[$1]이 버릴 거면서도 새 array buffer를 할당&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;하지만 새 reduce로는 이렇게 쓸 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class="swift" style="color: #000000; text-align: start;" data-ke-language="swift"&gt;&lt;code&gt;array.reduce([]) { $0.append($1); return $0 }&lt;/code&gt;&lt;/pre&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이제 다음과 같은 성능을 얻습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class="swift" style="color: #000000; text-align: start;" data-ke-language="swift"&gt;&lt;code&gt;array.reduce(into: []) { $0.append($1) }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;약간은 더 reduce(into:_:)와 동일한 성능이죠!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5" /&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;주의사항&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;물론 이런 모든 비효율성은 optimizer가 heroic optimization을 수행하면 제거될 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;하지만 이런&lt;b&gt; heroic optimization은 조금만 복잡한 예시에서는 무너지는 경향이 있어서, 성능 절벽으로 이어집니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style="color: #000000; text-align: start;" data-ke-size="size23"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;reduce(into:_:)는?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;reduce(into:_:)는 이미 argument를 consuming으로 받습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;따라서 유일한 변경은&amp;nbsp;Result: ~Copyable&amp;nbsp;추가뿐입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5" /&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;향후 방향&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 style="color: #000000; text-align: start;" data-ke-size="size23"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;~Escapable 지원&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;b&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;reduce는&amp;nbsp;~Escapable&amp;nbsp;값에서도 동작하도록 업데이트될 수 있습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이를 위해서는 함수와 closure parameter 모두에 lifetime annotation이 필요한데, 후자는 Swift에서 아직 지원되지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5" /&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;SE-0515는 이미&amp;nbsp;&lt;b&gt;Accepted&lt;/b&gt;되었고 구현도 완료된 상태입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;개인적으로는 정말 합리적인 개선이라고 생각합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;reduce가 initial value를 borrow하는 건 원래부터 이상했어요. &lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;첫 줄에서 바로 복사하는데 말이죠.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;이제 noncopyable 타입도 지원하고, copyable 타입에서도 불필요한 복사를 줄일 수 있게 되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style="style1"&gt;&lt;span style="font-family: 'Noto Serif KR';"&gt;"세계에서 가장 느린 map" 같은 실수도 조금 덜 치명적으로 만들어주는 좋은 변경이네요  &lt;/span&gt;&lt;/blockquote&gt;
&lt;p style="color: #000000; text-align: start;" data-ke-size="size18"&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style5" /&gt;
&lt;h2 style="color: #000000; text-align: start;" data-ke-size="size26"&gt;&lt;span style="font-family: 'Nanum Gothic'; color: #000000;"&gt;&lt;b&gt;References&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;figure id="og_1773441442058" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="object" data-og-title="swift-evolution/proposals/0515-noncopyable-reduce.md at main &amp;middot; swiftlang/swift-evolution" data-og-description="This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution" data-og-host="github.com" data-og-source-url="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0515-noncopyable-reduce.md" data-og-url="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0515-noncopyable-reduce.md" data-og-image="https://scrap.kakaocdn.net/dn/bfJK2w/dJMb84XXjzL/gzj5D4GykeRsuWl97tGsS0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/dkSYOC/dJMb81GVMMq/i5M85e1kvbIWkz76BlVA9K/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600"&gt;&lt;a href="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0515-noncopyable-reduce.md" target="_blank" rel="noopener" data-source-url="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0515-noncopyable-reduce.md"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/bfJK2w/dJMb84XXjzL/gzj5D4GykeRsuWl97tGsS0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/dkSYOC/dJMb81GVMMq/i5M85e1kvbIWkz76BlVA9K/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;swift-evolution/proposals/0515-noncopyable-reduce.md at main &amp;middot; swiftlang/swift-evolution&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id="og_1773441443558" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="[Pitch] Allow &amp;#96;reduce&amp;#96; to produce noncopyable results" data-og-description="Hi Swift Evolution, It is obligatory that I doom this pitch as possibly the least controversial pitch I can think of. Allow reduce to produce noncopyable results Proposal: SE-NNNN Authors: Ben Cohen Review Manager: TBD Status: Awaiting implementation or Aw" data-og-host="forums.swift.org" data-og-source-url="https://forums.swift.org/t/pitch-allow-reduce-to-produce-noncopyable-results/84073" data-og-url="https://forums.swift.org/t/pitch-allow-reduce-to-produce-noncopyable-results/84073" data-og-image="https://scrap.kakaocdn.net/dn/hG9jL/dJMb9efcvm0/zo8esEqw6XPZPC21OAvyzK/img.png?width=590&amp;amp;height=585&amp;amp;face=0_0_590_585,https://scrap.kakaocdn.net/dn/jQAly/dJMb9bv0RMZ/lKgz1rcgdHfDAOpHhOEsck/img.png?width=151&amp;amp;height=150&amp;amp;face=0_0_151_150"&gt;&lt;a href="https://forums.swift.org/t/pitch-allow-reduce-to-produce-noncopyable-results/84073" target="_blank" rel="noopener" data-source-url="https://forums.swift.org/t/pitch-allow-reduce-to-produce-noncopyable-results/84073"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/hG9jL/dJMb9efcvm0/zo8esEqw6XPZPC21OAvyzK/img.png?width=590&amp;amp;height=585&amp;amp;face=0_0_590_585,https://scrap.kakaocdn.net/dn/jQAly/dJMb9bv0RMZ/lKgz1rcgdHfDAOpHhOEsck/img.png?width=151&amp;amp;height=150&amp;amp;face=0_0_151_150');"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;[Pitch] Allow `reduce` to produce noncopyable results&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;Hi Swift Evolution, It is obligatory that I doom this pitch as possibly the least controversial pitch I can think of. Allow reduce to produce noncopyable results Proposal: SE-NNNN Authors: Ben Cohen Review Manager: TBD Status: Awaiting implementation or Aw&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;forums.swift.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id="og_1773441444386" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="SE-0515: Allow &amp;#96;reduce&amp;#96; to produce noncopyable results" data-og-description="Hi everybody. The review of SE-0515: Allow reduce to produce noncopyable results begins now and runs through March 10, 2026. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you " data-og-host="forums.swift.org" data-og-source-url="https://forums.swift.org/t/se-0515-allow-reduce-to-produce-noncopyable-results/84997" data-og-url="https://forums.swift.org/t/se-0515-allow-reduce-to-produce-noncopyable-results/84997" data-og-image="https://scrap.kakaocdn.net/dn/rXP5X/dJMb9bv0RM0/wjhIOQMxVpQYATZe6bj6p1/img.png?width=590&amp;amp;height=585&amp;amp;face=0_0_590_585,https://scrap.kakaocdn.net/dn/NNLF8/dJMb9efcvm1/EKgKr7j5DU7KFuDsCk4q9K/img.png?width=151&amp;amp;height=150&amp;amp;face=0_0_151_150"&gt;&lt;a href="https://forums.swift.org/t/se-0515-allow-reduce-to-produce-noncopyable-results/84997" target="_blank" rel="noopener" data-source-url="https://forums.swift.org/t/se-0515-allow-reduce-to-produce-noncopyable-results/84997"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/rXP5X/dJMb9bv0RM0/wjhIOQMxVpQYATZe6bj6p1/img.png?width=590&amp;amp;height=585&amp;amp;face=0_0_590_585,https://scrap.kakaocdn.net/dn/NNLF8/dJMb9efcvm1/EKgKr7j5DU7KFuDsCk4q9K/img.png?width=151&amp;amp;height=150&amp;amp;face=0_0_151_150');"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;SE-0515: Allow `reduce` to produce noncopyable results&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;Hi everybody. The review of SE-0515: Allow reduce to produce noncopyable results begins now and runs through March 10, 2026. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;forums.swift.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id="og_1773441446228" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="[Accepted] SE-0515: Allow &amp;#96;reduce&amp;#96; to produce noncopyable results" data-og-description="The review of SE-0515: Allow reduce to produce noncopyable results has ended, and the Language Steering Group has decided to accept the proposal. There was unanimous support for what the community sees as an obvious generalization of the existing reduce AP" data-og-host="forums.swift.org" data-og-source-url="https://forums.swift.org/t/accepted-se-0515-allow-reduce-to-produce-noncopyable-results/85286" data-og-url="https://forums.swift.org/t/accepted-se-0515-allow-reduce-to-produce-noncopyable-results/85286" data-og-image="https://scrap.kakaocdn.net/dn/ds5Bad/dJMb81fRbyn/Pj8KPeGFyNoI55bKDTilVk/img.png?width=590&amp;amp;height=585&amp;amp;face=0_0_590_585,https://scrap.kakaocdn.net/dn/bjYdjt/dJMb87NUYBx/H85zmvOdJkd5CUAKx8KoS0/img.png?width=151&amp;amp;height=150&amp;amp;face=0_0_151_150"&gt;&lt;a href="https://forums.swift.org/t/accepted-se-0515-allow-reduce-to-produce-noncopyable-results/85286" target="_blank" rel="noopener" data-source-url="https://forums.swift.org/t/accepted-se-0515-allow-reduce-to-produce-noncopyable-results/85286"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/ds5Bad/dJMb81fRbyn/Pj8KPeGFyNoI55bKDTilVk/img.png?width=590&amp;amp;height=585&amp;amp;face=0_0_590_585,https://scrap.kakaocdn.net/dn/bjYdjt/dJMb87NUYBx/H85zmvOdJkd5CUAKx8KoS0/img.png?width=151&amp;amp;height=150&amp;amp;face=0_0_151_150');"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;[Accepted] SE-0515: Allow `reduce` to produce noncopyable results&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;The review of SE-0515: Allow reduce to produce noncopyable results has ended, and the Language Steering Group has decided to accept the proposal. There was unanimous support for what the community sees as an obvious generalization of the existing reduce AP&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;forums.swift.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</summary>
    <title>[SE-0515] Allow reduce to produce noncopyable results</title>
    <updated>2026-03-14T07:40:20+09:00</updated>
    <dc:date>2026-03-14T07:40:20+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>이현호</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;h1 id="열심히-성장하던-시절"&gt;열심히 성장하던 시절&lt;/h1&gt;
&lt;p&gt;개발을 처음 시작했을 무렵부터 지금까지 훌륭한 개발자가 되기 위해 열심히 공부했었다. 물론 나보다 더 열심히 사는 개발자들도 많지만, 나도 내 위치에서 나름의 노력을 했었고, 벨로그에도 200개가 넘는 글을 작성하기도 했다. 그 만큼 개발에 진심이었고 재밌었다.&lt;/p&gt;
&lt;p&gt;회사에서는 구현하기 복잡하거나 어려운 주제를 담당하는 것을 좋아했고, 동료 개발자가 하고 싶은게 아니라면 내가 가져왔다. &lt;strong&gt;그 문제를 잘 풀어나가면 성장하는 느낌을 많이 받았기 때문&lt;/strong&gt;이다.&lt;/p&gt;
&lt;p&gt;그리고 팀 내에서 아무도 해보지 않은 도전 과제가 등장하면, 나는 항상 그런 프로젝트에 투입되고 싶어했다. 물론 많은 삽질이 필요하고, 다양한 개념들을 학습하기 위해서는 여러 노력이 필요하다. 그래도 &lt;strong&gt;프로젝트의 DX가 개선된다던가, 다른 직무와 협업에 있어 편리해진다거나, 서비스의 유지보수 측면에서 안정성이 올라가면 뿌듯&lt;/strong&gt;했다. 게다가 견문이 넓어지는 느낌이 들때마다 ‘성장하고 있구나’를 느꼈다.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/leehyunho2001/post/537450e0-1684-458c-aed5-375ef60c823f/image.jpeg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;그렇게 진행했던 것들이 &lt;strong&gt;MFA(Micro Frontend) / 디자인 토큰 기반 디자인 시스템 / Vue만 사용하던 회사에서 Next 도입&lt;/strong&gt;과 같은 굵직한 것부터 &lt;strong&gt;탠스택 쿼리 / 스토리북 / MSW 도입&lt;/strong&gt;과 같은 부가적인 도전들이 있었다.&lt;/p&gt;
&lt;p&gt;그런데 요즘에는 AI 때문에 개발하는 것에 대해 재미는 감소했다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="ai라는-친구의-등장"&gt;AI라는 친구의 등장&lt;/h2&gt;
&lt;p&gt;기술 블로그나 링크드인 같은 곳에서 AI의 찬양들이 쏟아져 나오기 시작할 무렵에, 나도 코드 어시스턴트들을 사용해보고 있었다. 코파일럿은 편하기는 했지만, 사실 그렇게 확 와닿지는 않았다. 근데 커서를 사용하고 나서는 큰 충격을 받았다. 생각했던것 보다 일을 잘했고, &lt;strong&gt;특히 물리적으로 시간을 많이 잡아먹는 귀찮은 일&lt;/strong&gt;들을 순식간에 해주었다.&lt;/p&gt;
&lt;p&gt;이 무렵에 회사에서는 재미나이를 지원해주고 있었다. 하지만 코드 어시스턴트에 대한 지원은 없었다. 그래서 나는 커서를 사용해본 경험을 팀 내에 공유하며, 프론트 리더에게 이와 같은 AI를 지원해주기를 요청했었다. 그 요구가 통했는지 아니면 원래부터 회사에서 지원해주려고 준비중이었는지는 모르겠지만, 두 달 정도 뒤에 &lt;strong&gt;Claude / AWS Kiro (Q) 를 지원&lt;/strong&gt;해주었다.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/leehyunho2001/post/c74469d7-9ef6-4a52-be26-6738e2c0dc7b/image.jpeg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;커서를 처음 사용해본 이후로, 고작 두 달이라는 시간밖에 지나지 않았었다. 이 짧은 시간동안 업그레이드 된 클로드는 더욱 훌륭한 일들을 하기 시작했다. 이제는 단순한 일 뿐만이 아니라, 어느정도의 &lt;strong&gt;복잡도가 있는 것들도 잘 구현하기 시작&lt;/strong&gt;했다. 그리고 &lt;strong&gt;MCP 같은 개념까지 결합되면서, 생산성이 엄청나게 올라갔다.&lt;/strong&gt; 이제는 도구가 아닌 동료가 된 느낌이었다.&lt;/p&gt;
&lt;p&gt;회사 내에는 부정적인 의견도 존재했다. AI가 못하는 부분들이 많기에, 아직 맹신하기는 어렵다는 것이었다. 나는 이 의견에 매우 동의한다. 하지만 이 문제는 &lt;strong&gt;'지금의 상황'일 뿐이고, 빠른 속도로 해결될 일이라고 생각&lt;/strong&gt;했다. &lt;/p&gt;
&lt;p&gt;클로드를 개발하는 사람들도 자신들이 만든 클로드에 추가 개발을 진행할 때, AI를 이용한다고 언급할 정도니까 말이다. 실제로 클로드도 한 두달에 한 번 이루어지던 업데이트가 이제는 1주일만에도 새로운 버전이 등장하고 있다. &lt;strong&gt;이미 새로운 시대는 시작된 것이다.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="개발에-대한-의심"&gt;개발에 대한 의심&lt;/h2&gt;
&lt;p&gt;AI와 함께 개발을 하다가 문득 &lt;strong&gt;'개발 공부하는게 의미가 있을까?'&lt;/strong&gt; 라는 생각이 들었다. AI가 빠른 속도로 반전하면서, 내가 경험해보지 못한 부분에 대해서는 AI가 일을 더 잘한다. 그리고 나보다 비교할 수 없을 정도로 빠른 속도로 업무를 처리한다.&lt;/p&gt;
&lt;p&gt;물론 &lt;strong&gt;모든 것을 AI에게 맡기는 것은 아직까진 이상적인 이야기&lt;/strong&gt;이다. AI가 작성해준 코드에 버그가 있거나, 아니면 AI가 만들었던 기능에 더 많은 기능들이 복합적으로 추가되면서 사이드 이펙트를 발생시켰을 때, AI가 문제를 해결하지 못하면 결국 개발자가 파악해야 하기 때문이다.&lt;/p&gt;
&lt;p&gt;이와 같은 상황에서 개발자의 역량이 부족하다면, &lt;strong&gt;AI가 작성한 코드나 플로우들을 이해하기 힘들 것이고, 그 만큼 문제를 해결하는데 있어 많은 시간을 소요&lt;/strong&gt;하게 된다. 하지만 나중에 AI가 못하는 부분이 사라진다면, 정말 자연어만으로 충분히 모든게 가능하다면 개발 지식들이 중요한걸까?&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/leehyunho2001/post/854db1e4-b2e3-4f86-8a21-3139a38cfe6b/image.jpeg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;청소기 안에 탑재되어 있는 부품들을 모두 이해하면서 청소기를 사용하지는 않는다. &lt;strong&gt;이처럼, 머지 않은 미래에는 개발 언어를 이해하지 않고 AI에게 구현 / 테스트 / 검증을 맡기게 되는거 아닐까?&lt;/strong&gt; 이것은 추상화의 개념이랑도 비슷한 것 같다.&lt;/p&gt;
&lt;p&gt;그리고 가끔은 그런 생각도 한다. 사람이 이해하기 쉽게 만들어진 지금의 컴퓨팅 언어들은 사라지고, 컴퓨터만 이해할 수 있는(01010101.. 같은 ㅋㅋ) 대신에 엄청난 속도를 자랑하는 무언가가 나오는건 아닐까 하는 생각 말이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;지금 AI의 수준은 청소기가 고장나는 경우, 문제가 있는 부품들을 만들어서 교체해주는 정도까지 온 것 같다. 부품들끼리의 복잡한 연결로가 고장난 경우에는, 아직까지는 완벽하게 고쳐주지는 못하지만, 이 부분들도 빠르게 진화하고 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이런 생각들은 개발에 대한 재미를 떨어뜨렸다. &lt;strong&gt;개발 공부에 대한 의심이 싹트기 시작했기 때문&lt;/strong&gt;이다. 과거에는 복잡한 문제를 해결하기 위해 여러 지식들을 습득하고, 꼬리에 꼬리를 무는 개념들을 타고 들어가면서 학습해왔다. 이런것들이 모이다가 어느 순간 깨달음을 얻으면, 그게 바로 개발의 재미이며 묘미였다.&lt;/p&gt;
&lt;p&gt;하지만 지금은 대부분을 AI에게 맡긴다. 개념을 몰라도 해결해달라고 하면 몇 분 만에 해결해준다. 해결 과정을 보면서 나라면 어떻게 해결했을까 상상하며 비교도 해보지만, 이런 과정들도 의미가 있는건지 의문이 생긴 것이다.&lt;/p&gt;
&lt;p&gt;AI가 만든 코드를 테스트하고 검증하는데 시간을 쏟아야 하는건 맞지만, 코드를 이해하는데 시간을 투자하는게 맞는건지에 대해서도 의심이 간다. &lt;strong&gt;나중에는 결국 AI에게 명령만 하고 코드는 안보게 되는 것은 아닐까?&lt;/strong&gt; 검증에서 실패한 경우에도 다시 AI에게 수정을 요청해서 해결하고, 그러다가 정 안되면 그제서야 코드를 보는 세상이 오지 않을까? 처음에는 엄청난 혁신으로 다가와, 나에게 두근거림은 선사했던 AI가, 이제는 개발의 재미를 뺏어가고 있는 상황이다.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/leehyunho2001/post/5662c9bd-2e00-408d-adab-8a6ea792cafc/image.jpeg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;그렇다고 AI를 안쓸거냐? 그건 정말 미련한 선택일 것이다. 과거부터 지금까지 개발자라는 사람들은 기능을 완벽하게 구현하고 버그를 제거하며 안정적인 서비스를 운영하는 것도 있었지만, &lt;strong&gt;어떻게 해야 생산성을 늘릴 수 있을지 고민하며 수 많은 아키텍처와 방법론&lt;/strong&gt;들을 쏟아냈었다.&lt;/p&gt;
&lt;p&gt;그런데 개발 생산성을 엄청나게 높일 수 있는 AI라는 도구이자 동료를 사용하지 않는것은 &lt;strong&gt;개발자로써의 모순이기도 하고 나 자신이 이 세상에 뒤쳐지는 일&lt;/strong&gt;이 될 것이다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1의-디테일에-재미를-느끼자"&gt;1%의 디테일에 재미를 느끼자&lt;/h2&gt;
&lt;p&gt;이 세상에서 ‘완벽’이라는 말이 성립되는 것은 어렵다. 어렸을 때, 사탕 봉지 안에서 두 개의 사탕이 나온적이 있었다. 그 당시에는 마냥 기분이 좋았지만, 지금 생각해보면 &lt;strong&gt;반복 작업을 위해 만들어진 기계조차도 반복 작업에 완벽하지가 않다&lt;/strong&gt;는 사실을 깨닫게 된다. 그런데 이게 만약 사탕이 아니라 의약품이라고 가정해보자. 특정 알약 한 알에 어떤 성분이 두 배로 들어가게 되었다. 이것은 누군가에게 매우 치명적일 수 있다. &lt;strong&gt;개발로 치면 크리티컬한 버그&lt;/strong&gt;인 것이다.&lt;/p&gt;
&lt;p&gt;이처럼 &lt;strong&gt;AI도 크리티컬한 버그를 만들게 될 것&lt;/strong&gt;이다. 계속 고치지 못하고 빙빙 도는 부분들도 있을 것이다. 완벽하지 않기 때문이다. 위에서 말했던 ‘미래에는 가능하다’는 99%의 일들을 말했던 것이다. 나중에도 분명 1%에 대해서는 AI도 실수를 할 것이라고 생각한다. 그래서 &lt;strong&gt;우리는 이 1%의 디테일을 채우기 위해, 여전히 개발 지식을 쌓고, 코딩 실력을 향상시켜야 한다.&lt;/strong&gt; 개발에 대한 재미도 잃지 않게 되어 일석이조가 된다.&lt;/p&gt;
&lt;p&gt;대부분의 일을 AI가 한다고해서 개발에 대한 태도를 의심하며, 벌써 부터 마음이 꺾일 필요가 없다. 달라질건 없고, 하던대로 하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/leehyunho2001/post/92fc840d-31db-489d-990c-6e1df32bb80a/image.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;과거에 T 공부법이라는 개념을 본 적이 있다. 요약하자면 다양한 분야에 대해 넓게 알고, 그 중에서 한 분야에 대해 깊게 알기 위해 학습한다는 의미였다. 이제는 &lt;strong&gt;AI 덕분에 T의 가로선인 &lt;code&gt;ㅡ&lt;/code&gt; 부분을 손 쉽게 넓힐 수 있고, 세로선도 빠른 속도로 그을 수 있게 되었다.&lt;/strong&gt; (이제는 &lt;code&gt;ㅠㅠㅠㅠㅠ&lt;/code&gt; 같은 모양이 되려나..)&lt;/p&gt;
&lt;p&gt;이는 아예 새로운 직무의 일도 해볼 수 있게 된 것을 의미한다. 웹 프론트엔드 개발자는 더 빠른 속도로 앱이나 백엔드에 익숙해질 수 있으며, 실제로 업무에 투입되는 것도 무리는 아닐것이다. 이런 부분에서 재미를 찾아도 좋을 것 같다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="자동화에-재미를-느끼자"&gt;자동화에 재미를 느끼자&lt;/h2&gt;
&lt;p&gt;조금은 부끄러운 이야기이지만, 우리는 테스트 코드를 전혀 작성하지 않았다. 항상 헐떡이며 개발 할만큼 업무가 바빴기 때문이다. 그런데 개인적으로 &lt;strong&gt;AI가 등장하고 나서부터는 시간이 없다는 말은 핑계가 되었다고 생각&lt;/strong&gt;한다. 그래서 나는 AI와 함께 테스트 코드를 작성하기로 결정한다. 하지만 테스트 코드에 대한 경험이 전무하다보니 가장 간단한 UI 라이브러리성의 공통 컴포넌트부터 테스트 범위로 잡았다.&lt;/p&gt;
&lt;p&gt;먼저 '&lt;code&gt;Button&lt;/code&gt; 컴포넌트에 대해 테스트 코드를 작성해줘'라고 요구해보았다. 일단 테스트 코드를 얼마나 잘 작성하는지 확인해본 것이다. 클로드가 어느 정도 작성해주기는 했지만 내가 만족할 정도는 아니었다. 그래서 나는 이어서 '버튼 컴포넌트를 완벽하게 파악하고 테스트 코드를 작성해줘' 라던가, '컴파운드 컴포넌트 패턴을 사용하고 있고, 디자인 토큰이 입혀져 있기 때문에 헤드리스는 아니야' 같은 정보들을 주기 시작했다.&lt;/p&gt;
&lt;p&gt;이렇게 요구했던 것들을 기반으로 &lt;strong&gt;공통 컴포넌트를 위한 프롬프트 규칙 파일&lt;/strong&gt;을 작성했다. 테스트 코드들도 일관성이 있어야 개발자가 파악하기 더 좋으므로, 이런 규칙들까지 정리했다. 그리고 이렇게 만들어진 &lt;code&gt;md&lt;/code&gt; 파일 기준으로 모든 공통 컴포넌트들에 테스트 코드를 하나씩 생성하기 시작했다. 그 결과 순식간에 원하는 결과물을 얻을 수 있었다. &lt;strong&gt;이제 공통 컴포넌트를 수정하더라도, 불안감을 안은채 하지 않아도 된다는 사실이 매우 기뻤다.&lt;/strong&gt; 이후에는 비지니스 로직이 결합된 컴포넌트를 테스트 하기 위한 프롬프트를 작성했고, 앞으로는 E2E같은 더 다양한 관점에서의 테스트 코드도 AI 프롬프트 자동화를 통해 접근해볼 예정이다.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/leehyunho2001/post/b1d471dc-044a-44e1-8164-4cd286b317d3/image.jpeg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;또 기억에 남는 것은 스웨거 문서 기반으로 API Path, Request / Response Model, 데이터 패칭 함수 등을 자동화한 것이다. 사실 이미 &lt;a href="https://github.com/acacode/swagger-typescript-api"&gt;swagger-typescript-api&lt;/a&gt;라는 라이브러리를 통해 리퀘스트 및 리스폰스 모델정도는 스웨거 기반으로 뽑아오고 있었다. 하지만 데이터 패칭 함수나, API EndPoint Path같은 것들은 우리 프로젝트 스타일에 맞게 직접 작성했다. 이게 별거 아닌 것 같지만, 응근히 귀찮고 시간을 잡아먹었다.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-tsx"&gt;export function fetchBlogDetailPage(
    requestModel: FetchBlogDetailPageRequestModel
): FetchModel&amp;lt;FetchBlogDetailPageReturn&amp;gt; {
    return serverFetch(apiPath.blog.detail, 'get'...)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;먼저 스웨거 기반으로 모델은 그대로 뽑도록 했다. 그리고 이 라이브러리에서 데이터 패칭 함수도 만들어주는 기능이 있는데, 이것은 커스텀은 쉽지 않고 자신의 입맛대로 생성해버린다. 그래도 일단 데이터 패칭 함수도 만들도록 했다. 그리고 이 결과물들을 참고한 채로 &lt;strong&gt;Swagger MCP&lt;/strong&gt;를 돌렸다. &lt;strong&gt;우리 프로젝트의 성격에 맞게 데이터 패칭 함수나 API EndPoint Path를 추가&lt;/strong&gt;하도록 했으며, 기존 API에 수정 사항이 있는 경우에도 잘 고칠 수 있도록 프롬프트를 구성했다. 그 결과 원하는 결과를 얻었고, 꽤 높은 생산성을 얻게 되었다고 생각한다.&lt;/p&gt;
&lt;p&gt;이 외에도 컴포넌트에 대한 스토리북을 잘 작성할 수 있도록 프롬프트를 설계한다던가, GitHub에 PR이 올라오면 AI가 코드 리뷰를 할 수 있는 플로우를 구성하는 등의 자동화도 생각해볼 수 있다. &lt;strong&gt;자동화 영역은 무궁무진 하므로, 다양한 시도를 해보면서 재미를 느껴보자.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="ai-고도화에-재미를-느끼자"&gt;AI 고도화에 재미를 느끼자&lt;/h2&gt;
&lt;p&gt;위에서 소개한 테스트 코드 프롬프트나 스웨거 기반으로 자동화를 진행할때 AI가 일을 잘 할 수 있도록 많은 시도들을 했었다. 어떻게 보면 AI는 불확실성을 가진 존재인데, 이것을 확실하게 처리하도록 핸들링하는 과정인 것 같았다. 이게 생각보다 쉽지 않다. &lt;strong&gt;이제는 어떻게 하면 더 대답을 잘하게 할 수 있을지, 다른 사람들의 고도화된 프롬프트를 보면서 공부도 하고, 여러 방식을 시도해보면서 깨달아가는 과정이 필요&lt;/strong&gt;하다고 생각했다.&lt;/p&gt;
&lt;p&gt;AI를 조금 사용해보면 알겠지만, 한 번에 너무 많은 일을 시키거나 요구하면 원하는 결과를 얻기 힘들다. 목적에 맞는 요구들을 순차적으로 수행했을 때, 좋은 결과를 얻을 확률이 높아진다. 이거 어디서 많이 본거다. &lt;strong&gt;개발에서 관심사의 분리&lt;/strong&gt;이다. 그리고 AI도 코드를 작성하는 것 처럼, 논리적으로 명확한 규칙을 정해주면 더 잘한다. 결국 개발자의 사고 방식을 탑재해서 AI를 활용하면 더욱 효과적으로 사용할 수 있게 된다. &lt;strong&gt;고도화 하는 과정은 개발을 하던 방식과 크게 다르지 않고, 재미를 느끼기에 충분하다고 생각&lt;/strong&gt;한다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/leehyunho2001/post/18da858a-2c8e-4c59-ad1b-a33091ec2a16/image.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;나는 재밌어야 일을 더 잘하는 타입이다. AI가 나의 일자리 자체를 위협하는 것도 맞지만, 애초에 나부터 일이 재미가 없으면 효율이 떨어진다. 그래서 재미가 없어지는것에 대해 더 두려웠던거 같다. 하지만 다행스럽게도 개발에 대한 의심을 지우자는 결론을 내렸고, 또 다른 부분들에서 재미를 찾기도 했다. 변화하는 시대에 맞게 나도 진화하고 있다는 느낌을 받았다.&lt;/p&gt;
&lt;p&gt;개발자들 중에 마음이 꺾이려는 사람이 있다면, 이 글을 보고 도움이 되면 좋겠다.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://velog.io/@leehyunho2001/coding-no-jaem</id>
    <link href="https://velog.io/@leehyunho2001/coding-no-jaem"/>
    <summary type="html">&lt;h1 id="열심히-성장하던-시절"&gt;열심히 성장하던 시절&lt;/h1&gt;
&lt;p&gt;개발을 처음 시작했을 무렵부터 지금까지 훌륭한 개발자가 되기 위해 열심히 공부했었다. 물론 나보다 더 열심히 사는 개발자들도 많지만, 나도 내 위치에서 나름의 노력을 했었고, 벨로그에도 200개가 넘는 글을 작성하기도 했다. 그 만큼 개발에 진심이었고 재밌었다.&lt;/p&gt;
&lt;p&gt;회사에서는 구현하기 복잡하거나 어려운 주제를 담당하는 것을 좋아했고, 동료 개발자가 하고 싶은게 아니라면 내가 가져왔다. &lt;strong&gt;그 문제를 잘 풀어나가면 성장하는 느낌을 많이 받았기 때문&lt;/strong&gt;이다.&lt;/p&gt;
&lt;p&gt;그리고 팀 내에서 아무도 해보지 않은 도전 과제가 등장하면, 나는 항상 그런 프로젝트에 투입되고 싶어했다. 물론 많은 삽질이 필요하고, 다양한 개념들을 학습하기 위해서는 여러 노력이 필요하다. 그래도 &lt;strong&gt;프로젝트의 DX가 개선된다던가, 다른 직무와 협업에 있어 편리해진다거나, 서비스의 유지보수 측면에서 안정성이 올라가면 뿌듯&lt;/strong&gt;했다. 게다가 견문이 넓어지는 느낌이 들때마다 ‘성장하고 있구나’를 느꼈다.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/leehyunho2001/post/537450e0-1684-458c-aed5-375ef60c823f/image.jpeg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;그렇게 진행했던 것들이 &lt;strong&gt;MFA(Micro Frontend) / 디자인 토큰 기반 디자인 시스템 / Vue만 사용하던 회사에서 Next 도입&lt;/strong&gt;과 같은 굵직한 것부터 &lt;strong&gt;탠스택 쿼리 / 스토리북 / MSW 도입&lt;/strong&gt;과 같은 부가적인 도전들이 있었다.&lt;/p&gt;
&lt;p&gt;그런데 요즘에는 AI 때문에 개발하는 것에 대해 재미는 감소했다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="ai라는-친구의-등장"&gt;AI라는 친구의 등장&lt;/h2&gt;
&lt;p&gt;기술 블로그나 링크드인 같은 곳에서 AI의 찬양들이 쏟아져 나오기 시작할 무렵에, 나도 코드 어시스턴트들을 사용해보고 있었다. 코파일럿은 편하기는 했지만, 사실 그렇게 확 와닿지는 않았다. 근데 커서를 사용하고 나서는 큰 충격을 받았다. 생각했던것 보다 일을 잘했고, &lt;strong&gt;특히 물리적으로 시간을 많이 잡아먹는 귀찮은 일&lt;/strong&gt;들을 순식간에 해주었다.&lt;/p&gt;
&lt;p&gt;이 무렵에 회사에서는 재미나이를 지원해주고 있었다. 하지만 코드 어시스턴트에 대한 지원은 없었다. 그래서 나는 커서를 사용해본 경험을 팀 내에 공유하며, 프론트 리더에게 이와 같은 AI를 지원해주기를 요청했었다. 그 요구가 통했는지 아니면 원래부터 회사에서 지원해주려고 준비중이었는지는 모르겠지만, 두 달 정도 뒤에 &lt;strong&gt;Claude / AWS Kiro (Q) 를 지원&lt;/strong&gt;해주었다.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/leehyunho2001/post/c74469d7-9ef6-4a52-be26-6738e2c0dc7b/image.jpeg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;커서를 처음 사용해본 이후로, 고작 두 달이라는 시간밖에 지나지 않았었다. 이 짧은 시간동안 업그레이드 된 클로드는 더욱 훌륭한 일들을 하기 시작했다. 이제는 단순한 일 뿐만이 아니라, 어느정도의 &lt;strong&gt;복잡도가 있는 것들도 잘 구현하기 시작&lt;/strong&gt;했다. 그리고 &lt;strong&gt;MCP 같은 개념까지 결합되면서, 생산성이 엄청나게 올라갔다.&lt;/strong&gt; 이제는 도구가 아닌 동료가 된 느낌이었다.&lt;/p&gt;
&lt;p&gt;회사 내에는 부정적인 의견도 존재했다. AI가 못하는 부분들이 많기에, 아직 맹신하기는 어렵다는 것이었다. 나는 이 의견에 매우 동의한다. 하지만 이 문제는 &lt;strong&gt;&amp;#39;지금의 상황&amp;#39;일 뿐이고, 빠른 속도로 해결될 일이라고 생각&lt;/strong&gt;했다. &lt;/p&gt;
&lt;p&gt;클로드를 개발하는 사람들도 자신들이 만든 클로드에 추가 개발을 진행할 때, AI를 이용한다고 언급할 정도니까 말이다. 실제로 클로드도 한 두달에 한 번 이루어지던 업데이트가 이제는 1주일만에도 새로운 버전이 등장하고 있다. &lt;strong&gt;이미 새로운 시대는 시작된 것이다.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="개발에-대한-의심"&gt;개발에 대한 의심&lt;/h2&gt;
&lt;p&gt;AI와 함께 개발을 하다가 문득 &lt;strong&gt;&amp;#39;개발 공부하는게 의미가 있을까?&amp;#39;&lt;/strong&gt; 라는 생각이 들었다. AI가 빠른 속도로 반전하면서, 내가 경험해보지 못한 부분에 대해서는 AI가 일을 더 잘한다. 그리고 나보다 비교할 수 없을 정도로 빠른 속도로 업무를 처리한다.&lt;/p&gt;
&lt;p&gt;물론 &lt;strong&gt;모든 것을 AI에게 맡기는 것은 아직까진 이상적인 이야기&lt;/strong&gt;이다. AI가 작성해준 코드에 버그가 있거나, 아니면 AI가 만들었던 기능에 더 많은 기능들이 복합적으로 추가되면서 사이드 이펙트를 발생시켰을 때, AI가 문제를 해결하지 못하면 결국 개발자가 파악해야 하기 때문이다.&lt;/p&gt;
&lt;p&gt;이와 같은 상황에서 개발자의 역량이 부족하다면, &lt;strong&gt;AI가 작성한 코드나 플로우들을 이해하기 힘들 것이고, 그 만큼 문제를 해결하는데 있어 많은 시간을 소요&lt;/strong&gt;하게 된다. 하지만 나중에 AI가 못하는 부분이 사라진다면, 정말 자연어만으로 충분히 모든게 가능하다면 개발 지식들이 중요한걸까?&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/leehyunho2001/post/854db1e4-b2e3-4f86-8a21-3139a38cfe6b/image.jpeg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;청소기 안에 탑재되어 있는 부품들을 모두 이해하면서 청소기를 사용하지는 않는다. &lt;strong&gt;이처럼, 머지 않은 미래에는 개발 언어를 이해하지 않고 AI에게 구현 / 테스트 / 검증을 맡기게 되는거 아닐까?&lt;/strong&gt; 이것은 추상화의 개념이랑도 비슷한 것 같다.&lt;/p&gt;
&lt;p&gt;그리고 가끔은 그런 생각도 한다. 사람이 이해하기 쉽게 만들어진 지금의 컴퓨팅 언어들은 사라지고, 컴퓨터만 이해할 수 있는(01010101.. 같은 ㅋㅋ) 대신에 엄청난 속도를 자랑하는 무언가가 나오는건 아닐까 하는 생각 말이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;지금 AI의 수준은 청소기가 고장나는 경우, 문제가 있는 부품들을 만들어서 교체해주는 정도까지 온 것 같다. 부품들끼리의 복잡한 연결로가 고장난 경우에는, 아직까지는 완벽하게 고쳐주지는 못하지만, 이 부분들도 빠르게 진화하고 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이런 생각들은 개발에 대한 재미를 떨어뜨렸다. &lt;strong&gt;개발 공부에 대한 의심이 싹트기 시작했기 때문&lt;/strong&gt;이다. 과거에는 복잡한 문제를 해결하기 위해 여러 지식들을 습득하고, 꼬리에 꼬리를 무는 개념들을 타고 들어가면서 학습해왔다. 이런것들이 모이다가 어느 순간 깨달음을 얻으면, 그게 바로 개발의 재미이며 묘미였다.&lt;/p&gt;
&lt;p&gt;하지만 지금은 대부분을 AI에게 맡긴다. 개념을 몰라도 해결해달라고 하면 몇 분 만에 해결해준다. 해결 과정을 보면서 나라면 어떻게 해결했을까 상상하며 비교도 해보지만, 이런 과정들도 의미가 있는건지 의문이 생긴 것이다.&lt;/p&gt;
&lt;p&gt;AI가 만든 코드를 테스트하고 검증하는데 시간을 쏟아야 하는건 맞지만, 코드를 이해하는데 시간을 투자하는게 맞는건지에 대해서도 의심이 간다. &lt;strong&gt;나중에는 결국 AI에게 명령만 하고 코드는 안보게 되는 것은 아닐까?&lt;/strong&gt; 검증에서 실패한 경우에도 다시 AI에게 수정을 요청해서 해결하고, 그러다가 정 안되면 그제서야 코드를 보는 세상이 오지 않을까? 처음에는 엄청난 혁신으로 다가와, 나에게 두근거림은 선사했던 AI가, 이제는 개발의 재미를 뺏어가고 있는 상황이다.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/leehyunho2001/post/5662c9bd-2e00-408d-adab-8a6ea792cafc/image.jpeg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;그렇다고 AI를 안쓸거냐? 그건 정말 미련한 선택일 것이다. 과거부터 지금까지 개발자라는 사람들은 기능을 완벽하게 구현하고 버그를 제거하며 안정적인 서비스를 운영하는 것도 있었지만, &lt;strong&gt;어떻게 해야 생산성을 늘릴 수 있을지 고민하며 수 많은 아키텍처와 방법론&lt;/strong&gt;들을 쏟아냈었다.&lt;/p&gt;
&lt;p&gt;그런데 개발 생산성을 엄청나게 높일 수 있는 AI라는 도구이자 동료를 사용하지 않는것은 &lt;strong&gt;개발자로써의 모순이기도 하고 나 자신이 이 세상에 뒤쳐지는 일&lt;/strong&gt;이 될 것이다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1의-디테일에-재미를-느끼자"&gt;1%의 디테일에 재미를 느끼자&lt;/h2&gt;
&lt;p&gt;이 세상에서 ‘완벽’이라는 말이 성립되는 것은 어렵다. 어렸을 때, 사탕 봉지 안에서 두 개의 사탕이 나온적이 있었다. 그 당시에는 마냥 기분이 좋았지만, 지금 생각해보면 &lt;strong&gt;반복 작업을 위해 만들어진 기계조차도 반복 작업에 완벽하지가 않다&lt;/strong&gt;는 사실을 깨닫게 된다. 그런데 이게 만약 사탕이 아니라 의약품이라고 가정해보자. 특정 알약 한 알에 어떤 성분이 두 배로 들어가게 되었다. 이것은 누군가에게 매우 치명적일 수 있다. &lt;strong&gt;개발로 치면 크리티컬한 버그&lt;/strong&gt;인 것이다.&lt;/p&gt;
&lt;p&gt;이처럼 &lt;strong&gt;AI도 크리티컬한 버그를 만들게 될 것&lt;/strong&gt;이다. 계속 고치지 못하고 빙빙 도는 부분들도 있을 것이다. 완벽하지 않기 때문이다. 위에서 말했던 ‘미래에는 가능하다’는 99%의 일들을 말했던 것이다. 나중에도 분명 1%에 대해서는 AI도 실수를 할 것이라고 생각한다. 그래서 &lt;strong&gt;우리는 이 1%의 디테일을 채우기 위해, 여전히 개발 지식을 쌓고, 코딩 실력을 향상시켜야 한다.&lt;/strong&gt; 개발에 대한 재미도 잃지 않게 되어 일석이조가 된다.&lt;/p&gt;
&lt;p&gt;대부분의 일을 AI가 한다고해서 개발에 대한 태도를 의심하며, 벌써 부터 마음이 꺾일 필요가 없다. 달라질건 없고, 하던대로 하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/leehyunho2001/post/92fc840d-31db-489d-990c-6e1df32bb80a/image.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;과거에 T 공부법이라는 개념을 본 적이 있다. 요약하자면 다양한 분야에 대해 넓게 알고, 그 중에서 한 분야에 대해 깊게 알기 위해 학습한다는 의미였다. 이제는 &lt;strong&gt;AI 덕분에 T의 가로선인 &lt;code&gt;ㅡ&lt;/code&gt; 부분을 손 쉽게 넓힐 수 있고, 세로선도 빠른 속도로 그을 수 있게 되었다.&lt;/strong&gt; (이제는 &lt;code&gt;ㅠㅠㅠㅠㅠ&lt;/code&gt; 같은 모양이 되려나..)&lt;/p&gt;
&lt;p&gt;이는 아예 새로운 직무의 일도 해볼 수 있게 된 것을 의미한다. 웹 프론트엔드 개발자는 더 빠른 속도로 앱이나 백엔드에 익숙해질 수 있으며, 실제로 업무에 투입되는 것도 무리는 아닐것이다. 이런 부분에서 재미를 찾아도 좋을 것 같다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="자동화에-재미를-느끼자"&gt;자동화에 재미를 느끼자&lt;/h2&gt;
&lt;p&gt;조금은 부끄러운 이야기이지만, 우리는 테스트 코드를 전혀 작성하지 않았다. 항상 헐떡이며 개발 할만큼 업무가 바빴기 때문이다. 그런데 개인적으로 &lt;strong&gt;AI가 등장하고 나서부터는 시간이 없다는 말은 핑계가 되었다고 생각&lt;/strong&gt;한다. 그래서 나는 AI와 함께 테스트 코드를 작성하기로 결정한다. 하지만 테스트 코드에 대한 경험이 전무하다보니 가장 간단한 UI 라이브러리성의 공통 컴포넌트부터 테스트 범위로 잡았다.&lt;/p&gt;
&lt;p&gt;먼저 &amp;#39;&lt;code&gt;Button&lt;/code&gt; 컴포넌트에 대해 테스트 코드를 작성해줘&amp;#39;라고 요구해보았다. 일단 테스트 코드를 얼마나 잘 작성하는지 확인해본 것이다. 클로드가 어느 정도 작성해주기는 했지만 내가 만족할 정도는 아니었다. 그래서 나는 이어서 &amp;#39;버튼 컴포넌트를 완벽하게 파악하고 테스트 코드를 작성해줘&amp;#39; 라던가, &amp;#39;컴파운드 컴포넌트 패턴을 사용하고 있고, 디자인 토큰이 입혀져 있기 때문에 헤드리스는 아니야&amp;#39; 같은 정보들을 주기 시작했다.&lt;/p&gt;
&lt;p&gt;이렇게 요구했던 것들을 기반으로 &lt;strong&gt;공통 컴포넌트를 위한 프롬프트 규칙 파일&lt;/strong&gt;을 작성했다. 테스트 코드들도 일관성이 있어야 개발자가 파악하기 더 좋으므로, 이런 규칙들까지 정리했다. 그리고 이렇게 만들어진 &lt;code&gt;md&lt;/code&gt; 파일 기준으로 모든 공통 컴포넌트들에 테스트 코드를 하나씩 생성하기 시작했다. 그 결과 순식간에 원하는 결과물을 얻을 수 있었다. &lt;strong&gt;이제 공통 컴포넌트를 수정하더라도, 불안감을 안은채 하지 않아도 된다는 사실이 매우 기뻤다.&lt;/strong&gt; 이후에는 비지니스 로직이 결합된 컴포넌트를 테스트 하기 위한 프롬프트를 작성했고, 앞으로는 E2E같은 더 다양한 관점에서의 테스트 코드도 AI 프롬프트 자동화를 통해 접근해볼 예정이다.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/leehyunho2001/post/b1d471dc-044a-44e1-8164-4cd286b317d3/image.jpeg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;또 기억에 남는 것은 스웨거 문서 기반으로 API Path, Request / Response Model, 데이터 패칭 함수 등을 자동화한 것이다. 사실 이미 &lt;a href="https://github.com/acacode/swagger-typescript-api"&gt;swagger-typescript-api&lt;/a&gt;라는 라이브러리를 통해 리퀘스트 및 리스폰스 모델정도는 스웨거 기반으로 뽑아오고 있었다. 하지만 데이터 패칭 함수나, API EndPoint Path같은 것들은 우리 프로젝트 스타일에 맞게 직접 작성했다. 이게 별거 아닌 것 같지만, 응근히 귀찮고 시간을 잡아먹었다.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-tsx"&gt;export function fetchBlogDetailPage(
    requestModel: FetchBlogDetailPageRequestModel
): FetchModel&amp;lt;FetchBlogDetailPageReturn&amp;gt; {
    return serverFetch(apiPath.blog.detail, &amp;#39;get&amp;#39;...)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;먼저 스웨거 기반으로 모델은 그대로 뽑도록 했다. 그리고 이 라이브러리에서 데이터 패칭 함수도 만들어주는 기능이 있는데, 이것은 커스텀은 쉽지 않고 자신의 입맛대로 생성해버린다. 그래도 일단 데이터 패칭 함수도 만들도록 했다. 그리고 이 결과물들을 참고한 채로 &lt;strong&gt;Swagger MCP&lt;/strong&gt;를 돌렸다. &lt;strong&gt;우리 프로젝트의 성격에 맞게 데이터 패칭 함수나 API EndPoint Path를 추가&lt;/strong&gt;하도록 했으며, 기존 API에 수정 사항이 있는 경우에도 잘 고칠 수 있도록 프롬프트를 구성했다. 그 결과 원하는 결과를 얻었고, 꽤 높은 생산성을 얻게 되었다고 생각한다.&lt;/p&gt;
&lt;p&gt;이 외에도 컴포넌트에 대한 스토리북을 잘 작성할 수 있도록 프롬프트를 설계한다던가, GitHub에 PR이 올라오면 AI가 코드 리뷰를 할 수 있는 플로우를 구성하는 등의 자동화도 생각해볼 수 있다. &lt;strong&gt;자동화 영역은 무궁무진 하므로, 다양한 시도를 해보면서 재미를 느껴보자.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="ai-고도화에-재미를-느끼자"&gt;AI 고도화에 재미를 느끼자&lt;/h2&gt;
&lt;p&gt;위에서 소개한 테스트 코드 프롬프트나 스웨거 기반으로 자동화를 진행할때 AI가 일을 잘 할 수 있도록 많은 시도들을 했었다. 어떻게 보면 AI는 불확실성을 가진 존재인데, 이것을 확실하게 처리하도록 핸들링하는 과정인 것 같았다. 이게 생각보다 쉽지 않다. &lt;strong&gt;이제는 어떻게 하면 더 대답을 잘하게 할 수 있을지, 다른 사람들의 고도화된 프롬프트를 보면서 공부도 하고, 여러 방식을 시도해보면서 깨달아가는 과정이 필요&lt;/strong&gt;하다고 생각했다.&lt;/p&gt;
&lt;p&gt;AI를 조금 사용해보면 알겠지만, 한 번에 너무 많은 일을 시키거나 요구하면 원하는 결과를 얻기 힘들다. 목적에 맞는 요구들을 순차적으로 수행했을 때, 좋은 결과를 얻을 확률이 높아진다. 이거 어디서 많이 본거다. &lt;strong&gt;개발에서 관심사의 분리&lt;/strong&gt;이다. 그리고 AI도 코드를 작성하는 것 처럼, 논리적으로 명확한 규칙을 정해주면 더 잘한다. 결국 개발자의 사고 방식을 탑재해서 AI를 활용하면 더욱 효과적으로 사용할 수 있게 된다. &lt;strong&gt;고도화 하는 과정은 개발을 하던 방식과 크게 다르지 않고, 재미를 느끼기에 충분하다고 생각&lt;/strong&gt;한다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/leehyunho2001/post/18da858a-2c8e-4c59-ad1b-a33091ec2a16/image.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;나는 재밌어야 일을 더 잘하는 타입이다. AI가 나의 일자리 자체를 위협하는 것도 맞지만, 애초에 나부터 일이 재미가 없으면 효율이 떨어진다. 그래서 재미가 없어지는것에 대해 더 두려웠던거 같다. 하지만 다행스럽게도 개발에 대한 의심을 지우자는 결론을 내렸고, 또 다른 부분들에서 재미를 찾기도 했다. 변화하는 시대에 맞게 나도 진화하고 있다는 느낌을 받았다.&lt;/p&gt;
&lt;p&gt;개발자들 중에 마음이 꺾이려는 사람이 있다면, 이 글을 보고 도움이 되면 좋겠다.&lt;/p&gt;
</summary>
    <title>AI 덕분에 개발이 쉬워졌고, 재미는 없어졌다.</title>
    <updated>2026-03-13T00:40:23+09:00</updated>
    <dc:date>2026-03-13T00:40:23+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>홍민희</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;h1&gt;합법이면 공정한가: AI 재구현과 카피레프트의 침식&lt;/h1&gt;
&lt;p&gt;지난 주, Python 텍스트 인코딩 탐지 라이브러리인 chardet의 메인테이너 Dan
Blanchard가 &lt;a href="https://github.com/chardet/chardet/releases/tag/7.0.0"&gt;새 버전을 릴리스했다&lt;/a&gt;. chardet 7.0은 속도가 기존 대비 48배
빨라졌고, 멀티코어를 지원하며, 설계부터 다시 짜여졌다. Anthropic의 Claude가
기여자로 등재되어 있다. 그리고 라이선스가 LGPL에서 MIT로 바뀌었다.&lt;/p&gt;
&lt;p&gt;Blanchard의 말에 따르면 자신은 코드를 보지 않고 API와 테스트 스위트만을 참조해
Claude에게 처음부터 재구현하도록 지시했고, 그 결과 이전 버전과의 코드 유사도가
1.3% 미만이라고 한다. 따라서 이것은 독자적인 새 저작물이며 LGPL을 계승할 의무가
없다는 것이다. 원작자 Mark Pilgrim은 &lt;a href="https://github.com/chardet/chardet/issues/327"&gt;GitHub 이슈를 열어 항의했다.&lt;/a&gt; LGPL은 수정
배포 시 동일 라이선스 유지를 요구하는데, 기존 코드에 충분히 노출된 상태에서
만든 재구현은 클린 룸이라고 볼 수 없다는 것이 그의 주장이다.&lt;/p&gt;
&lt;p&gt;이 사건은 Flask의 창시자 Armin Ronacher와 Redis의 창시자 Salvatore
Sanfilippo(이하 antirez)의 글을 통해 더 넓은 논쟁으로 번졌다. 두 사람은 각기
다른 경로로—&lt;a href="https://lucumr.pocoo.org/2026/3/5/theseus/"&gt;Ronacher는 라이선스 철학의 측면에서&lt;/a&gt;,
&lt;a href="https://antirez.com/news/162"&gt;antirez는 저작권법의 법리에서&lt;/a&gt;—이 재구현이 정당하다는 결론에 도달한다. 나는 두
글을 모두 존중하지만, 둘 다 틀렸다고 생각한다. 아니, 더 정확하게는 둘 다 핵심
질문을 회피하고 있다.&lt;/p&gt;
&lt;p&gt;그 핵심 질문이란 이것이다. 합법이면 공정한가. 두 글은 이 물음에는 답하지 않은
채, 법리적으로 가능하다는 사실에서 사회적으로 정당하다는 결론을 끌어낸다. 법적
허용과 사회적 당위는 같은 것이 아니다. 법은 최소한의 기준을 정할 뿐이고, 어떤
행위가 그 기준을 통과한다는 것이 그 행위가 옳다는 뜻은 아니다. 이 구분이 이
글의 출발점이다.&lt;/p&gt;
&lt;h2&gt;유비의 방향이 거꾸로다&lt;/h2&gt;
&lt;p&gt;antirez의 논거는 GNU 프로젝트가 UNIX 유저스페이스를 재구현했을 때, 그것이
합법이었다는 사실에서 출발한다. Linux 커널도 마찬가지였다. 저작권법은 &lt;q&gt;보호
받는 표현&lt;/q&gt;(protected expressions)의 복제를 금하지만 아이디어와 동작 방식은
보호하지 않는다. AI로 재구현하는 것도 같은 법적 지형 위에 있으므로 합법이라는
것이다.&lt;/p&gt;
&lt;p&gt;이 법리의 설명 자체는 대체로 맞다. 재구현이 합법이라는 주장을 나는 반박하지
않는다. 문제는 그 다음 단계에 있다. antirez는 합법임을 보인 뒤 논의를 끝낸다.
그러나 법리가 옳다는 것과 행위가 사회적으로 정당하다는 것은 별개의 주장이다. 이
둘을 동일시할 때 논증의 간극이 생긴다.&lt;/p&gt;
&lt;p&gt;그 간극이 가장 선명하게 드러나는 곳이 바로 antirez가 끌어온 역사적 유비다.&lt;/p&gt;
&lt;p&gt;GNU가 UNIX를 재구현했을 때, 그 벡터는 독점에서 공유 쪽을 향하고 있었다.
Stallman은 UNIX라는 독점 소프트웨어를 &lt;strong&gt;자유 소프트웨어로&lt;/strong&gt; 재구현하기 위해
저작권법의 한계를 영리하게 활용한 것이다. 그 재구현의 윤리적 정당성은 법적
합법성에서 오는 것이 아니라, 공유지(commons)를 넓히는 방향에서 나왔다. 그것이
GNU 프로젝트가 환호를 받은 이유다.&lt;/p&gt;
&lt;p&gt;chardet 사건에서 재구현의 벡터는 반대 방향이다. 카피레프트 라이선스인 LGPL로
보호되던 소프트웨어가 퍼미시브 라이선스인 MIT로 재구현되었다. 이것은 공유지를
&lt;strong&gt;넓히는&lt;/strong&gt; 재구현이 아니라 공유지의 &lt;strong&gt;울타리를 제거하는&lt;/strong&gt; 재구현이다. 이제 chardet
7.0을 기반으로 만들어지는 파생 작업은 소스 코드를 공개할 의무가 없다. 월 1억
3천만 다운로드라는 규모의 라이브러리에서 그 의무가 사라진 것이다.&lt;/p&gt;
&lt;p&gt;antirez는 이 방향의 차이를 논하지 않는다. GNU의 역사를 끌어왔는데, 그 역사가
실은 자신의 결론에 반증 사례가 된다는 것을 보지 못하거나 보지 않으려 한다.&lt;/p&gt;
&lt;h2&gt;GPL은 공유에 반하는가&lt;/h2&gt;
&lt;p&gt;한편, Ronacher의 논거는 다르다. 그는 자신이 오래전부터 chardet이 비GPL
라이선스로 바뀌기를 원했다고 밝힌다. 그리고 GPL이 &lt;q&gt;공유 정신에 반한다&lt;/q&gt;고
주장한다. 자신은 가능한 한 라이선스 강제가 적은 방향으로 공개하는 것을
지지하고, 사회는 공유할 때 더 나아진다는 믿음을 가지고 있기 때문이란다.&lt;/p&gt;
&lt;p&gt;이 주장은 GPL에 대한 근본적인 오해를 담고 있다.&lt;/p&gt;
&lt;p&gt;GPL이 무엇을 &lt;strong&gt;금지&lt;/strong&gt;하는지부터 보자. GPL은 소스 코드를 비공개로 유지하는 것을
금지하지 않는다. GPL 소프트웨어를 개인적으로 수정해 사용하는 것에는 아무런
제약이 없다. GPL이 조건을 발동시키는 것은 &lt;strong&gt;배포&lt;/strong&gt;할 때뿐이다. 수정한 코드를
배포하거나 서비스로 제공하면, 그 코드도 같은 조건으로 공유해야 한다는 것.
이것은 공유를 &lt;strong&gt;제한&lt;/strong&gt;하는 것이 아니라 공유를 &lt;strong&gt;조건&lt;/strong&gt;으로 거는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;q&gt;이것을 받아서 사용하고 개선했다면, 그 개선도 공유하라&lt;/q&gt;는 요구는 공유를
억제하는 메커니즘이 아니라 공유를 연달아 강제하는 메커니즘이다. 공유지의
이용자에게 공유지에 대한 기여 의무를 부과하는 것이 공유 문화를 해친다는 주장은
어불성설이다.&lt;/p&gt;
&lt;p&gt;MIT 라이선스와 비교해 보면 차이가 분명하다. MIT 라이선스 하에서는 누구나 코드를
가져다 개선한 뒤 독점 소프트웨어로 닫아버릴 수 있다. 가져가서 써도 되지만
기여는 선택적이다. Ronacher가 이 구조를 &lt;q&gt;더 공유 친화적&lt;/q&gt;이라고 본다면, 그가
말하는 &lt;q&gt;공유&lt;/q&gt;는 흘러가는 방향이 있는 공유다. 더 많은 자본과 인력을 가진 쪽이
가져가는 방향으로.&lt;/p&gt;
&lt;p&gt;이 비대칭이 현실에서 어떻게 작동하는지는 역사가 보여준다. 1990년대에 많은
기업들이 GPL 코드를 흡수해 독점 소프트웨어를 만들었다. 이것이 가능했던 것은
그들이 MIT 같은 퍼미시브 라이선스를 선택했기 때문이 아니라, 당시 카피레프트
라이선스의 집행이 느슨했기 때문이다. GPL이 강화되면서 이 구멍이 막혔다. 자원이
없어서 기여를 통한 상호성에 의존할 수밖에 없는 개인 개발자나 작은 프로젝트에게
카피레프트는 그나마 대등한 교환을 가능하게 하는 장치였다.&lt;/p&gt;
&lt;p&gt;Flask를 만든 사람이 이 구분을 모를 이 없다. 그렇다면 이 논거는 나이브한 것이
아니라 편의적인 것이다.&lt;/p&gt;
&lt;h2&gt;스스로 반증하는 사례&lt;/h2&gt;
&lt;p&gt;Ronacher의 글에서 가장 흥미로운 부분은 논거가 아니라 스쳐 지나가는 한 문장이다.
Vercel이 &lt;a href="https://just-bash.dev/"&gt;GNU Bash를 AI로 재구현해 공개했다가&lt;/a&gt;,
&lt;a href="https://x.com/cramforce/status/2027155457597669785"&gt;Cloudflare가 같은 방식으로 Next.js를 재구현하자 &lt;q&gt;눈에 띄게 화를 냈다&lt;/q&gt;&lt;/a&gt;는
것이다.&lt;/p&gt;
&lt;p&gt;Ronacher는 이것을 아이러니로 언급하고 넘어가지만, 이 일화는 그의 입장 전체를
무너뜨린다. Next.js는 MIT 라이선스다. &lt;a href="https://blog.cloudflare.com/vinext/"&gt;Cloudflare의 vinext&lt;/a&gt;는 라이선스를
위반한 것이 아니라, Ronacher가 공유 문화의 진전이라 부른 바로 그 행위를
Next.js에 적용한 것 뿐이다. Vercel의 분노는 라이선스 침해에 대한 것이 아니라
순수하게 경쟁적·영토적 반응이었다. &lt;q&gt;내가 GPL 소프트웨어를 MIT로 재구현하는 것은
공유 문화의 진전이고, 누군가 내 MIT 소프트웨어를 같은 방식으로 재구현하는 것은
불쾌하다.&lt;/q&gt; 이것이 퍼미시브 라이선스 진영이 카피레프트 진영보다 더 공유
친화적이라는 주장의 실체이다. 그가 말하는 &lt;q&gt;공유 정신&lt;/q&gt;란 결국 이토록
비대칭적인 것이다.&lt;/p&gt;
&lt;p&gt;Ronacher는 이 아이러니를 인식하고도 멈추지 않는다. 자신의 세계관에 부합하는
사례이기 때문이란다. 세계관과 일치하지 않는 증거를 스스로 제시하고도 결론을
바꾸지 않는 것은 논거가 결론에 앞서는 것이 아니라 결론이 논거에 앞서고 있다는
신호다.&lt;/p&gt;
&lt;h2&gt;합법성과 사회적 당위는 다른 층위에 있다&lt;/h2&gt;
&lt;p&gt;서두에서 말한 질문으로 돌아오자. 합법이면 공정한가.&lt;/p&gt;
&lt;p&gt;antirez는 법리를 꼼꼼히 설명한 뒤 그것으로 충분하다는 듯이 끝을 맺는다.
Ronacher는 법적 회색 지대를 인정하면서도 도덕적 문제는 &lt;q&gt;내가 관심 있는 부분이
아니다&lt;/q&gt;라고 한 문장으로 넘긴다. 두 글 모두 법적 허용을 사회적 정당성의 대리물로
삼는다. 그러나 법은 어떤 행위를 막지 않는다는 것을 말할 뿐이지, 그 행위가
옳다는 것을 보증하지는 않는다. 조세를 아슬아슬하게 회피하는 것이 합법이더라도
옳은지는 별개의 물음이다. 특허를 합법적으로 취득한 기업이 수십 연간 저렴하게
공급되던 필수 의약품 가격을 수십 배 올리는 것이 합법이더라도, 그것이 사회적으로
정당하다는 뜻은 아니다. 합법성은 필요조건일 수 있지만 충분조건은 아니다.&lt;/p&gt;
&lt;p&gt;chardet 사건에서 이 구분은 더욱 뚜렷하다.&lt;/p&gt;
&lt;p&gt;chardet의 LGPL이 보호한 것은 Blanchard 한 사람의 노동이 아니다. 12년간 이
라이브러리에 기여한 모든 사람들이 동의한 사회적 계약이다. 그 계약의 내용은
&lt;q&gt;이것을 가져다 쓴다면, 당신이 만든 것도 같은 조건으로 공유하라&lt;/q&gt;는 것이었다.
이 계약은 법원이 강제하는 종류의 계약이기도 하지만, 그보다 먼저 오픈 소스 공동체가
수십년에 걸쳐 구축해 온 신뢰의 토대였다. 재구현이 법적으로 새로운 저작물로
인정될 수 있다는 것과, 그 재구현이 기존 기여자들과 맺은 사회적 계약을
파기했다는 것은 별개의 문제다. 법원이 만일 Blanchard의 손을 들어준대도 그것은
그의 행위가 공동체적으로 정당하다는 것을 의미하지 않는다. 합법성은 사회적
정당성을 뒤따라오게 하지 않는다.&lt;/p&gt;
&lt;p&gt;FSF 대표 Zoë Kooyman은 이를 간결하게 표현했다. &lt;q&gt;자신이 받은 권리를 타인에게
부여하기를 거부하는 것은 어떤 방법을 쓰든 반사회적 행위다.&lt;/q&gt;&lt;/p&gt;
&lt;h2&gt;누구의 관점이 디폴트로 설정되어 있는가&lt;/h2&gt;
&lt;p&gt;이 논쟁을 읽으면서 계속 드는 질문이 있다. 두 저자는 AI 재구현의 비용 하락을
어떤 위치에서 바라보고 있는가.&lt;/p&gt;
&lt;p&gt;antirez는 Redis를 만들었고, Ronacher는 Flask를 만들었다. 두 사람 모두 오픈 소스
생태계의 중심에 있는 사람들이다. 그들의 입장에서 AI 재구현의 비용 하락은 자신이
&lt;strong&gt;가하는&lt;/strong&gt; 쪽의 이야기다. 무언가를 더 쉽게 재구현할 수 있게 되는 것이다.
Ronacher는 GNU Readline을 GPL이기 때문에 재구현하려 했다고 밝힌다.&lt;/p&gt;
&lt;p&gt;반면 수십년간 chardet 같은 라이브러리에 기여해온 사람들의 입장에서 같은 기술
변화는 자신이 &lt;strong&gt;당하는&lt;/strong&gt; 쪽의 이야기다. 자신의 기여가 담긴 카피레프트 보호막이
제거되는 것이다. 두 저자는 전자의 위치에서 후자의 위치에 있는 사람들을 향해
“이것은 항상 합법이었고, 역사적 선례가 있으며, 기술 변화에 적응하라”고 말하고
있다.&lt;/p&gt;
&lt;p&gt;이 비대칭을 무시한 채 보편적 논거인 것처럼 서술할 때, 글은 분석이 아니라
이해관계의 합리화가 된다. 두 저자 모두 자신의 이해관계와 정확히 일치하는 결론에
도달한다는 것을 독자는 유념해야 한다.&lt;/p&gt;
&lt;h2&gt;이 싸움이 가리키는 것&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.theregister.com/2026/03/06/ai_kills_software_licensing/"&gt;Bruce Perens는 &lt;cite class="series"&gt;The Register&lt;/cite&gt;와의 인터뷰에서&lt;/a&gt; &lt;q&gt;소프트웨어 개발의
전체 경제학이 죽었다&lt;/q&gt;고 경고했다. antirez는 비슷한 인식에서 &lt;q&gt;적응하라&lt;/q&gt;고
말한다. Ronacher는 이 방향이 마음에 든다고 말한다.&lt;/p&gt;
&lt;p&gt;세 반응 중 어느 것도 핵심 질문에 답하지 않는다. 카피레프트의 집행이 기술적으로
어려워졌을 때, 그것이 카피레프트를 &lt;strong&gt;불필요하게&lt;/strong&gt; 만드는가, 아니면 더욱
&lt;strong&gt;중요하게&lt;/strong&gt; 만드는가.&lt;/p&gt;
&lt;p&gt;나는 후자라고 생각한다. GPL이 보호한 것은 코드의 희소성이 아니라 사용자의
권리였다. 코드 생산 비용이 낮아진다고 해서 그 코드를 통해 권리를 침식하는
행위가 괜찮아지는 것은 아니다. 오히려 재구현의 마찰이 사라질수록, 카피레프트
라이브러리를 MIT로 탈바꿈시키는 비용도 사라진다. GPL이 의존했던 마찰이
줄어들었다는 것은 법적 집행의 문제일 뿐, 그 기저의 당위를 건드리지 않는다.&lt;/p&gt;
&lt;p&gt;그 당위는 이것이다. 공유지에서 가져간 자는 공유지에 돌려줘야 한다는 것. 그
원칙은 재구현이 5년 걸리든 5일 걸리든 달라지지 않는다. 법원이 AI 재구현을 클린
룸으로 인정하든 파생 저작물로 보든, 그 판결이 이 원칙의 사회적 무게를
경감시키지는 않는다.&lt;/p&gt;
&lt;p&gt;이것이 법리와 사회적 가치가 갈라지는 지점이다. 법은 사후적으로, 느리게, 현재의
권력 관계를 반영하며 만들어진다. 오픈 소스 공동체가 수십 연에 걸쳐 쌓아온
규범은 법원의 판결을 기다리지 않았다. 법이 그것을 보호해주지 않을 때도 사람들이
GPL을 선택한 것은, 그것이 자신이 속한 공동체의 가치와 일치했기 때문이다. 그
가치는 법이 바뀐다고 사라지지 않는다.&lt;/p&gt;
&lt;p&gt;이전 글들에서 나는 이 싸움의 다음 단계로
&lt;a href="https://writings.hongminhee.org/2026/01/histomat-foss-llm/"&gt;훈련 카피레프트(TGPL)를 제안했다.&lt;/a&gt; AI 재구현
문제는 거기서 한 걸음 더 나아가 명세(specification) 계층까지 보호 범위를
확장해야 한다는 것을 시사한다. 소스 코드가 명세로부터 생성될 수 있다면, 그
명세가 GPL 프로젝트의 본질적 지식재산이 된다. 소스 코드를 보지 않고 테스트
스위트와 API만으로 재구현했다는 Blanchard의 주장은, 역설적으로, 그 테스트
스위트와 API 명세가 보호되어야 한다는 논거가 된다.&lt;/p&gt;
&lt;p&gt;GPL의 역사는 새로운 착취 방식이 등장할 때마다 법적 도구가 진화해 온 역사다.
GPLv2에서 GPLv3로, AGPL로. 그러나 그 진화를 이끈 것은 판결이 아니라 공동체의
가치 판단이었다. 법은 뒤따라왔다. 지금도 마찬가지다. 법원이 AI 재구현에 대해
어떤 판결을 내리든, 우리가 먼저 답해야 할 질문은 법적인 것이 아니라 사회적인
것이다. 공유지의 열매를 취한 자는 공유지에 돌려줄 의무가 있는가. 나는 그렇다고
생각한다. 그리고 그 판단은 법원의 판결을 기다릴 필요가 없다.&lt;/p&gt;
&lt;p&gt;antirez와 Ronacher의 글이 흥미로운 것은 그들이 옳기 때문이 아니라, 그들이
무엇을 보지 않으려 하는지가 선명하게 드러나기 때문이다. 합법성으로 사회적 가치
판단을 대신하려 할 때, 정작 중요한 질문은 법리의 그늘 속에 묻힌다.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://writings.hongminhee.org/2026/03/legal-vs-legitimate/</id>
    <link href="https://writings.hongminhee.org/2026/03/legal-vs-legitimate/"/>
    <title>합법이면 공정한가: AI 재구현과 카피레프트의 침식</title>
    <updated>2026-03-10T00:10:00+09:00</updated>
    <dc:date>2026-03-10T00:10:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>이준행</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;‘코딩’을 대신해주는 인공지능 에이전트(AI Agent)가 나오자 마자 전 세계 매체들이 ‘이제 SaaS는 망했다’ 라고 외치기 시작했다. &lt;a href="https://www.forbes.com/sites/alexanderpuutio/2025/07/04/saas-is-dead-long-live-service-as-a-service/"&gt;Forbes&lt;/a&gt;
누구나 ‘딸깍’만 하면 SaaS를 만들 수 있다며, SaaS 회사들은 전략을 바꾸어야 한다며 호들갑을 떨었고, 떨어지는 SaaS 회사 주식 시세를 트래킹하는 사이트까지 등장했다.
&lt;a href="https://www.fubardaily.com/"&gt;FubarDaily&lt;/a&gt; 그래서 인공지능은 도대체 언제 SaaS를 대체한다는 것인가? 회사마다 수십만원씩 내고 있는 SaaS 서비스 구독료는 언제 인공지능이 ‘딸깍’ 한번에 무료로 대체해 줄 것인가? 이 이야기가 나온 지 반년이 지나도록 마땅한 대체제는 아직도 나오지 않았다.&lt;/p&gt;

&lt;p&gt;총대 매는 사람이 없어서 그런가 정말 대체되기는 하는건가 궁금해서 내가 직접 만들어보기로 했다.&lt;/p&gt;

&lt;hr&gt;

&lt;h1 id="만드는-사람들이-늘어나긴-했다"&gt;만드는 사람들이 늘어나긴 했다.&lt;/h1&gt;

&lt;p&gt;여기저기서 인공지능으로 Jira나 Linear, monday를 대체하는 툴을 만들었다고 자랑하곤 했다. 하지만 붐이 일어나지도, 실제로 대체할 만한 품질의 제품이 나오지도 않았다. 유사제품만 마구 나왔을 뿐이다. 마치 클론 서비스 개발이 개발 역량 강화에 도움이 되는 것처럼 여겨지던 한 때, 여기저기서 클론 서비스 코드가 쏟아져 나왔을 때와 비슷한 분위기이다. 클론은 잘 했는데, 가져다 쓸 수는 없고, 만든 이도 그냥 방치해버리는 버려진 코드들이 마구 쏟아져 나오는 상황이다.&lt;/p&gt;

&lt;p&gt;나는 그런 클론을 만들고 싶은게 아니었다. 누군가 가져다 쓸 정도는 되어야한다는 목표를 설정했다. ‘설치형’이라는 이름을 붙여보았다.
이런 이름을 붙이고 목표를 설정하는 행위는 ‘딸깍’에 움직이는 인공지능이 하는 일이 아니라 내가 하는 일이었다.&lt;/p&gt;

&lt;h1 id="딸깍-한번으로는-도무지-성에-차지-않는다"&gt;딸깍 한번으로는 도무지 성에 차지 않는다&lt;/h1&gt;

&lt;p&gt;처음에는 “ㅇㅇ 서비스같은걸 만들어줘” 라고 프롬프트를 입력했다. 그럴싸하게 기존 서비스를 베낀 페이지가 나왔다. 하지만 코딩을 제일 잘한다는 인공지능 모델조차 제대로 작동하는 서비스를 만들지는 못했다. 오류가 속출했다. 기본 설정을 하는데에는 인간의 도움이 필요했고, 모든 설정을 마치더라도 여전히 오류 투성이라 디버깅은 결국 사람이 해주어야 했다. 나는 설치형 이슈 트래커와 설치형 협업 채팅 툴을 만들어달라고 지시했는데, 로그인 구현을 위한 엑세스 키 하나를 설정하는데에도 그 방법을 안내하는 페이지 하나는 또 따로 생성시켜야 했다. 테스트 케이스와 시나리오를 만든다 한들 인공지능이 놓치는 부분들이 속출했다. 일정 부분은 분명히 기존의 개발 지식이 요구되었다.&lt;/p&gt;

&lt;p&gt;나야 이쪽 일을 했으니까 인공지능이 어디까지 구현했겠군-하고 짐작하며 찾아갔지만, 배경지식이 없는 어떤 이들에게는 곤란한 과정일 수도 있겠다 싶었다.&lt;/p&gt;

&lt;h1 id="인공지능-기술이-아니라-사양과-ux-설계가-필요하다"&gt;인공지능 기술이 아니라 사양과 UX 설계가 필요하다&lt;/h1&gt;

&lt;p&gt;핵심 기능을 잘 구현했다 하더라도, SaaS의 락인 효과는 습관을 만드는 세밀한 UX에서 나온다. 작지만 꼭 필요한 사양들이 사용자를 사로잡는다. 인공지능은 여기까지 스스로  구현해내지는 못했다. 필요한 연동 기능들부터 IME 지원까지 미묘한 지점에서 불편한 점이 한 두가지가 아니었다.
예를 들면 이런 식이다. “멘션창에서 스크롤이 되면 선택 후에 스크롤이 서서히 되도록 해줘. 동시에 진행되니 깜빡이는거로 보여져.” 또는 “위 아래를 이동할때 선택이 해제되는 항목의 글자색이 깜빡여. 깜빡임이 없게 해줘.” “클립보드에서 붙여넣기하면 허용된 경우를 제외하고서 나머지 태그나 attr, 그리고 인라인 스타일을 모조리 제거해” 같은 요구가 추가로 필요했다. 특히 한국어로 된 서비스를 만든다면 반드시 이런 프롬프트를 덧붙여줘야 한다. “한글 입력을 하다가 isComposing 상태에서 엔터를 치면 마지막 입력한 글자가 두 번 입력돼. isComposing 상태에서 블럭 안에 있는 한글이 반복되지 않게 고쳐줘.” 그러지 않으면 한글 입력이 잘 안된다는 버그 리포트를 받게 될 것이다.&lt;/p&gt;

&lt;p&gt;이런 문제 해결 노하우는 수십여 년간 IT서비스를 개발 해온 개발자라면 익숙하지만, 기능만 구현하는 인공지능에게는 이해가 되지 않는 비효율 더미일 것이다. 사양과 시나리오를 세세히 설명하고 나서야 기능은 완성된다. 모든 개발자/디자이너/기획자가 코드를 쓸 수 있는 시대에, 메이커로 변신하는 저마다가 갖추어야 할 역량에 이 세밀한 사양과 UX를 설계하는 역량이 새로이 요구되는 셈이다. 인공지능은 여기까지 알아서 해주진 못하며, 아마도 꽤 오랜 기간 그럴 것으로 보인다.&lt;/p&gt;

&lt;p&gt;잠깐, 인공지능이 개발자를 대체한다고 하지 않았던가? 그런데 인간의 새로운 역할이 요구된다? 인간의 노하우가 필요하다?&lt;/p&gt;

&lt;h1 id="자가복제의-열화"&gt;자가복제의 열화&lt;/h1&gt;

&lt;p&gt;국회 정치자금 지출내역 엑셀파일을 바탕으로 만들었던 &lt;a href="https://restaurant.coroke.net/"&gt;restaurant.coroke.net&lt;/a&gt; 를 만든 이후, 비슷한 페이지들을 여럿 발견했다. 지도에 주유소 기름값을 표시하거나, 숙박업소 가격을 비교하는 식이었는데, 클릭 트리거가 되는 동그라미 모양이 거의 다 똑같았다. “ㅇㅇ 사이트의 UI를 참고해” 또는 “ㅇㅇ 사이트의 코드를 참고해” 같은 프롬프트를 입력했다거나 “히트맵으로 구현해줘”라고만 시키면 이런 결과가 나온다. 나는 히트맵을 구현해달라고 프롬프트를 넣었는데, 다른 이들도 똑같은 프롬프트를 넣고 별다른 커스터마이징을 하지 않아 인공지능의 디자인 감각으로 만들어진 사이트가 여럿 쏟아진 것이다. 덕분에 주유소 기름값을 말풍선 UI 대신 히트맵으로 표시하는 사이트가 여럿 발견되었다. 화면이 겹쳐질 일이 적은 주유소 기름값 같은 정보는 말풍선 UI을 쓰도록 하자.&lt;/p&gt;

&lt;p&gt;인공지능 코딩 시대에 경영자들이 요구하는 것은 ‘빠른 개발’ ‘비용 절감’ 이 대부분이다. 여기에 독창성이나 창의성이 들어갈 여지는 많지 않다. 20년 전에도 ‘ㅇㅇ 사이트를 베끼자’ 같은 일이 횡횡했고, 종종 카피캣 내지는 표절 시비가 붙곤 했다. 기능만 구현하면 되는 제품에서 저작권에서 자유로운 성공사례를 쫓아 모방하는 것은 ‘빠른 구현’의 비결이 된다. 그렇게, 인공지능이 서로를 참조하다 열화되듯, 인간의 인공지능 생성물도 이상하리만치 자기참조로 열화되는 결과가 나오고 있는 것이다.&lt;/p&gt;

&lt;p&gt;‘딸깍’ 수십번으로 만들어낸 내 앞의 생성물은 본질적으로 원본의 열화버전이다. 여기에 독창성을 부여하는 것은 인간의 ‘수고’가 들어가는 일이다. 남들과 같지 않으려면 손을 대야 한다. 독창성이 제품의 경쟁력 내지는 기업의 경쟁력이 되게 하는 것은 지난한 노력을 수반한다. 잠깐, 인공지능이 PM을 대체한다고 하지 않았던가? 디자이너를 대체한다고 하지 않았던가? 문제의 그 노력은 누가 하는가?&lt;/p&gt;

&lt;p&gt;대체하려던 서비스에는 없는 소소한 기능들을 더 넣고 나서야, 나는 이 생성물에 내 크레딧을 넣을 수 있었다. 어느 정도의 커스터마이징이 덧붙여져야 이 생성물이 그저 인공지능 생성물이 아닌 나의 수고가 곁들여진 창작물이라고 주장할 수 있을까?&lt;/p&gt;

&lt;hr&gt;

&lt;h1 id="인간의-본질적-정체성"&gt;인간의 본질적 정체성&lt;/h1&gt;

&lt;p&gt;인공지능의 본질적 정체성을 다시 생각한다. 인공지능은 모방을 할 뿐 창조를 하지 않는다. AGI에 다다른 인공지능이 나온다 한들, 추론과 분석을 잘 하지 창조를 해낸다는 이야기가 나오지는 않는다. 그러니 이 역할은 여전히 인간의 몫이다.&lt;/p&gt;

&lt;p&gt;어떤 직업은 분명 사라질 위기에 있다. &lt;a href="https://rainygirl.github.io/2026/02/rspeaker"&gt;언론사 망하게 하는 봇 만들기 글을 보라.&lt;/a&gt; 그러나 그 직업의 본질을 되돌아본다면 어느 직종이든, 특히 IT분야 직업이 쉽사리 사라지지는 않겠다는 생각이 든다.&lt;/p&gt;

&lt;p&gt;인공지능 코딩 에이전트와 함께 몇 시간을 들여 SaaS를 대체하는 서비스를 만들면서 몇 가지 생각이 떠올랐다. 1) 이 정도로 수고스럽게 머리를 써갈 거면 그냥 돈 주고 기성 제품을 쓰겠다 2) 이 정도로 수고스럽게 시간을 들여 SaaS 모방품을 만들 시간에 더 가치있는 일을 하는게 낫지 않나 3) 이걸 회사 일로 하는 거라면 그 시간에 가치 창출을 더 많이 할 회사 제품을 하나 더 만드는 게 좋겠다. 등등. SaaS 주가는 떨어질지언정 SaaS는 쉽게 망하지 않을거라는 확신이 들었다. 내가 monday를 복제한 서비스를 만든다 한들 monday가 샌프란시스코 시내에서 여는 HR 컨퍼런스를 인공지능이 대체할 수는 없다. 내가 Slack을 복제한 서비스를 만들어 사업을 한다 한들 Slack의 귀여운 뱃지까지 발주해 사람들에게 나누어주지는 못한다. 영업과 관계는 인공지능이 대체할 수 없고, 그래서 SaaS 사업의 본질은 코딩 에이전트로 대체되지 않는다.&lt;/p&gt;

&lt;p&gt;인간의 본질적 정체성에 대해서도 생각해보게 된다. 타인을 귀히 여기기보다 타인의 일자리가 없어졌으면 하는 바램을 내비치고, 타인의 노동을 폄하하고, 나아가 타인을 없애 버리고 싶어 하는 속마음을 버젓이 전시하는 인간의 욕망은 인공지능보다 나은 것이 무엇인가. 인공지능 때문에 사람들이 직업을 잃는 것이 아니라, 타인의 직업을 빼앗거나 일자리를 줄이고 싶어하는 특정 직군 인간들의 욕망이 직업을 사라지게 하고 있는건 아닐까? FOMO를 퍼트리는 인간의 본성을 극복할 다른 인간의 본성은 언제쯤 FOMO를 이기게 될까?&lt;/p&gt;

&lt;p&gt;인공지능의 도움을 받아 만들어 본 제품은 모두에게 공개하기로 했다. 나는 세일즈포스나 아틀라시안이 아니니까.
그래도 유사 제품을 만들려고 인공지능 에이전트와 함께 한 시간은 즐거웠다. 특히나 세밀한 부분마다 도메인 지식이나 개발 경험을 되살렸던 과정 또한 내가 아직 쓸모가 있다는 생각이 들어 즐거웠다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rainygirl/boxer"&gt;github.com/rainygirl/boxer&lt;/a&gt; - Jira를 참조한 이슈 트래커&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;데모 : &lt;a href="https://boxer.coroke.net"&gt;boxer.coroke.net&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/rainygirl/tight"&gt;github.com/rainygirl/tight&lt;/a&gt; - Slack을 참조한 협업 채팅도구&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;데모 : &lt;a href="https://tight.coroke.net"&gt;tight.coroke.net&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h1 id="함께-보세요"&gt;함께 보세요&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://restaurant.coroke.net"&gt;공직자 법인카드 맛집 지도&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://money.coroke.net"&gt;2025년도 국회의원 재산 내역&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://news.coroke.net"&gt;뉴스고로케&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://vinyl.coroke.net"&gt;바이닐고로케&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://rainygirl.github.io/2026/03/saas</id>
    <link href="https://rainygirl.github.io/2026/03/saas"/>
    <summary type="html">&lt;p&gt;‘코딩’을 대신해주는 인공지능 에이전트(AI Agent)가 나오자 마자 전 세계 매체들이 ‘이제 SaaS는 망했다’ 라고 외치기 시작했다. &lt;a href="https://www.forbes.com/sites/alexanderpuutio/2025/07/04/saas-is-dead-long-live-service-as-a-service/"&gt;Forbes&lt;/a&gt;
누구나 ‘딸깍’만 하면 SaaS를 만들 수 있다며, SaaS 회사들은 전략을 바꾸어야 한다며 호들갑을 떨었고, 떨어지는 SaaS 회사 주식 시세를 트래킹하는 사이트까지 등장했다.
&lt;a href="https://www.fubardaily.com/"&gt;FubarDaily&lt;/a&gt; 그래서 인공지능은 도대체 언제 SaaS를 대체한다는 것인가? 회사마다 수십만원씩 내고 있는 SaaS 서비스 구독료는 언제 인공지능이 ‘딸깍’ 한번에 무료로 대체해 줄 것인가? 이 이야기가 나온 지 반년이 지나도록 마땅한 대체제는 아직도 나오지 않았다.&lt;/p&gt;

&lt;p&gt;총대 매는 사람이 없어서 그런가 정말 대체되기는 하는건가 궁금해서 내가 직접 만들어보기로 했다.&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id="만드는-사람들이-늘어나긴-했다"&gt;만드는 사람들이 늘어나긴 했다.&lt;/h1&gt;

&lt;p&gt;여기저기서 인공지능으로 Jira나 Linear, monday를 대체하는 툴을 만들었다고 자랑하곤 했다. 하지만 붐이 일어나지도, 실제로 대체할 만한 품질의 제품이 나오지도 않았다. 유사제품만 마구 나왔을 뿐이다. 마치 클론 서비스 개발이 개발 역량 강화에 도움이 되는 것처럼 여겨지던 한 때, 여기저기서 클론 서비스 코드가 쏟아져 나왔을 때와 비슷한 분위기이다. 클론은 잘 했는데, 가져다 쓸 수는 없고, 만든 이도 그냥 방치해버리는 버려진 코드들이 마구 쏟아져 나오는 상황이다.&lt;/p&gt;

&lt;p&gt;나는 그런 클론을 만들고 싶은게 아니었다. 누군가 가져다 쓸 정도는 되어야한다는 목표를 설정했다. ‘설치형’이라는 이름을 붙여보았다.
이런 이름을 붙이고 목표를 설정하는 행위는 ‘딸깍’에 움직이는 인공지능이 하는 일이 아니라 내가 하는 일이었다.&lt;/p&gt;

&lt;h1 id="딸깍-한번으로는-도무지-성에-차지-않는다"&gt;딸깍 한번으로는 도무지 성에 차지 않는다&lt;/h1&gt;

&lt;p&gt;처음에는 “ㅇㅇ 서비스같은걸 만들어줘” 라고 프롬프트를 입력했다. 그럴싸하게 기존 서비스를 베낀 페이지가 나왔다. 하지만 코딩을 제일 잘한다는 인공지능 모델조차 제대로 작동하는 서비스를 만들지는 못했다. 오류가 속출했다. 기본 설정을 하는데에는 인간의 도움이 필요했고, 모든 설정을 마치더라도 여전히 오류 투성이라 디버깅은 결국 사람이 해주어야 했다. 나는 설치형 이슈 트래커와 설치형 협업 채팅 툴을 만들어달라고 지시했는데, 로그인 구현을 위한 엑세스 키 하나를 설정하는데에도 그 방법을 안내하는 페이지 하나는 또 따로 생성시켜야 했다. 테스트 케이스와 시나리오를 만든다 한들 인공지능이 놓치는 부분들이 속출했다. 일정 부분은 분명히 기존의 개발 지식이 요구되었다.&lt;/p&gt;

&lt;p&gt;나야 이쪽 일을 했으니까 인공지능이 어디까지 구현했겠군-하고 짐작하며 찾아갔지만, 배경지식이 없는 어떤 이들에게는 곤란한 과정일 수도 있겠다 싶었다.&lt;/p&gt;

&lt;h1 id="인공지능-기술이-아니라-사양과-ux-설계가-필요하다"&gt;인공지능 기술이 아니라 사양과 UX 설계가 필요하다&lt;/h1&gt;

&lt;p&gt;핵심 기능을 잘 구현했다 하더라도, SaaS의 락인 효과는 습관을 만드는 세밀한 UX에서 나온다. 작지만 꼭 필요한 사양들이 사용자를 사로잡는다. 인공지능은 여기까지 스스로  구현해내지는 못했다. 필요한 연동 기능들부터 IME 지원까지 미묘한 지점에서 불편한 점이 한 두가지가 아니었다.
예를 들면 이런 식이다. “멘션창에서 스크롤이 되면 선택 후에 스크롤이 서서히 되도록 해줘. 동시에 진행되니 깜빡이는거로 보여져.” 또는 “위 아래를 이동할때 선택이 해제되는 항목의 글자색이 깜빡여. 깜빡임이 없게 해줘.” “클립보드에서 붙여넣기하면 허용된 경우를 제외하고서 나머지 태그나 attr, 그리고 인라인 스타일을 모조리 제거해” 같은 요구가 추가로 필요했다. 특히 한국어로 된 서비스를 만든다면 반드시 이런 프롬프트를 덧붙여줘야 한다. “한글 입력을 하다가 isComposing 상태에서 엔터를 치면 마지막 입력한 글자가 두 번 입력돼. isComposing 상태에서 블럭 안에 있는 한글이 반복되지 않게 고쳐줘.” 그러지 않으면 한글 입력이 잘 안된다는 버그 리포트를 받게 될 것이다.&lt;/p&gt;

&lt;p&gt;이런 문제 해결 노하우는 수십여 년간 IT서비스를 개발 해온 개발자라면 익숙하지만, 기능만 구현하는 인공지능에게는 이해가 되지 않는 비효율 더미일 것이다. 사양과 시나리오를 세세히 설명하고 나서야 기능은 완성된다. 모든 개발자/디자이너/기획자가 코드를 쓸 수 있는 시대에, 메이커로 변신하는 저마다가 갖추어야 할 역량에 이 세밀한 사양과 UX를 설계하는 역량이 새로이 요구되는 셈이다. 인공지능은 여기까지 알아서 해주진 못하며, 아마도 꽤 오랜 기간 그럴 것으로 보인다.&lt;/p&gt;

&lt;p&gt;잠깐, 인공지능이 개발자를 대체한다고 하지 않았던가? 그런데 인간의 새로운 역할이 요구된다? 인간의 노하우가 필요하다?&lt;/p&gt;

&lt;h1 id="자가복제의-열화"&gt;자가복제의 열화&lt;/h1&gt;

&lt;p&gt;국회 정치자금 지출내역 엑셀파일을 바탕으로 만들었던 &lt;a href="https://restaurant.coroke.net/"&gt;restaurant.coroke.net&lt;/a&gt; 를 만든 이후, 비슷한 페이지들을 여럿 발견했다. 지도에 주유소 기름값을 표시하거나, 숙박업소 가격을 비교하는 식이었는데, 클릭 트리거가 되는 동그라미 모양이 거의 다 똑같았다. “ㅇㅇ 사이트의 UI를 참고해” 또는 “ㅇㅇ 사이트의 코드를 참고해” 같은 프롬프트를 입력했다거나 “히트맵으로 구현해줘”라고만 시키면 이런 결과가 나온다. 나는 히트맵을 구현해달라고 프롬프트를 넣었는데, 다른 이들도 똑같은 프롬프트를 넣고 별다른 커스터마이징을 하지 않아 인공지능의 디자인 감각으로 만들어진 사이트가 여럿 쏟아진 것이다. 덕분에 주유소 기름값을 말풍선 UI 대신 히트맵으로 표시하는 사이트가 여럿 발견되었다. 화면이 겹쳐질 일이 적은 주유소 기름값 같은 정보는 말풍선 UI을 쓰도록 하자.&lt;/p&gt;

&lt;p&gt;인공지능 코딩 시대에 경영자들이 요구하는 것은 ‘빠른 개발’ ‘비용 절감’ 이 대부분이다. 여기에 독창성이나 창의성이 들어갈 여지는 많지 않다. 20년 전에도 ‘ㅇㅇ 사이트를 베끼자’ 같은 일이 횡횡했고, 종종 카피캣 내지는 표절 시비가 붙곤 했다. 기능만 구현하면 되는 제품에서 저작권에서 자유로운 성공사례를 쫓아 모방하는 것은 ‘빠른 구현’의 비결이 된다. 그렇게, 인공지능이 서로를 참조하다 열화되듯, 인간의 인공지능 생성물도 이상하리만치 자기참조로 열화되는 결과가 나오고 있는 것이다.&lt;/p&gt;

&lt;p&gt;‘딸깍’ 수십번으로 만들어낸 내 앞의 생성물은 본질적으로 원본의 열화버전이다. 여기에 독창성을 부여하는 것은 인간의 ‘수고’가 들어가는 일이다. 남들과 같지 않으려면 손을 대야 한다. 독창성이 제품의 경쟁력 내지는 기업의 경쟁력이 되게 하는 것은 지난한 노력을 수반한다. 잠깐, 인공지능이 PM을 대체한다고 하지 않았던가? 디자이너를 대체한다고 하지 않았던가? 문제의 그 노력은 누가 하는가?&lt;/p&gt;

&lt;p&gt;대체하려던 서비스에는 없는 소소한 기능들을 더 넣고 나서야, 나는 이 생성물에 내 크레딧을 넣을 수 있었다. 어느 정도의 커스터마이징이 덧붙여져야 이 생성물이 그저 인공지능 생성물이 아닌 나의 수고가 곁들여진 창작물이라고 주장할 수 있을까?&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id="인간의-본질적-정체성"&gt;인간의 본질적 정체성&lt;/h1&gt;

&lt;p&gt;인공지능의 본질적 정체성을 다시 생각한다. 인공지능은 모방을 할 뿐 창조를 하지 않는다. AGI에 다다른 인공지능이 나온다 한들, 추론과 분석을 잘 하지 창조를 해낸다는 이야기가 나오지는 않는다. 그러니 이 역할은 여전히 인간의 몫이다.&lt;/p&gt;

&lt;p&gt;어떤 직업은 분명 사라질 위기에 있다. &lt;a href="https://rainygirl.github.io/2026/02/rspeaker"&gt;언론사 망하게 하는 봇 만들기 글을 보라.&lt;/a&gt; 그러나 그 직업의 본질을 되돌아본다면 어느 직종이든, 특히 IT분야 직업이 쉽사리 사라지지는 않겠다는 생각이 든다.&lt;/p&gt;

&lt;p&gt;인공지능 코딩 에이전트와 함께 몇 시간을 들여 SaaS를 대체하는 서비스를 만들면서 몇 가지 생각이 떠올랐다. 1) 이 정도로 수고스럽게 머리를 써갈 거면 그냥 돈 주고 기성 제품을 쓰겠다 2) 이 정도로 수고스럽게 시간을 들여 SaaS 모방품을 만들 시간에 더 가치있는 일을 하는게 낫지 않나 3) 이걸 회사 일로 하는 거라면 그 시간에 가치 창출을 더 많이 할 회사 제품을 하나 더 만드는 게 좋겠다. 등등. SaaS 주가는 떨어질지언정 SaaS는 쉽게 망하지 않을거라는 확신이 들었다. 내가 monday를 복제한 서비스를 만든다 한들 monday가 샌프란시스코 시내에서 여는 HR 컨퍼런스를 인공지능이 대체할 수는 없다. 내가 Slack을 복제한 서비스를 만들어 사업을 한다 한들 Slack의 귀여운 뱃지까지 발주해 사람들에게 나누어주지는 못한다. 영업과 관계는 인공지능이 대체할 수 없고, 그래서 SaaS 사업의 본질은 코딩 에이전트로 대체되지 않는다.&lt;/p&gt;

&lt;p&gt;인간의 본질적 정체성에 대해서도 생각해보게 된다. 타인을 귀히 여기기보다 타인의 일자리가 없어졌으면 하는 바램을 내비치고, 타인의 노동을 폄하하고, 나아가 타인을 없애 버리고 싶어 하는 속마음을 버젓이 전시하는 인간의 욕망은 인공지능보다 나은 것이 무엇인가. 인공지능 때문에 사람들이 직업을 잃는 것이 아니라, 타인의 직업을 빼앗거나 일자리를 줄이고 싶어하는 특정 직군 인간들의 욕망이 직업을 사라지게 하고 있는건 아닐까? FOMO를 퍼트리는 인간의 본성을 극복할 다른 인간의 본성은 언제쯤 FOMO를 이기게 될까?&lt;/p&gt;

&lt;p&gt;인공지능의 도움을 받아 만들어 본 제품은 모두에게 공개하기로 했다. 나는 세일즈포스나 아틀라시안이 아니니까.
그래도 유사 제품을 만들려고 인공지능 에이전트와 함께 한 시간은 즐거웠다. 특히나 세밀한 부분마다 도메인 지식이나 개발 경험을 되살렸던 과정 또한 내가 아직 쓸모가 있다는 생각이 들어 즐거웠다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rainygirl/boxer"&gt;github.com/rainygirl/boxer&lt;/a&gt; - Jira를 참조한 이슈 트래커&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;데모 : &lt;a href="https://boxer.coroke.net"&gt;boxer.coroke.net&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/rainygirl/tight"&gt;github.com/rainygirl/tight&lt;/a&gt; - Slack을 참조한 협업 채팅도구&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;데모 : &lt;a href="https://tight.coroke.net"&gt;tight.coroke.net&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id="함께-보세요"&gt;함께 보세요&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://restaurant.coroke.net"&gt;공직자 법인카드 맛집 지도&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://money.coroke.net"&gt;2025년도 국회의원 재산 내역&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://news.coroke.net"&gt;뉴스고로케&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://vinyl.coroke.net"&gt;바이닐고로케&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</summary>
    <title>그래서 AI는 도대체 언제 SaaS를 대체한다는건가?</title>
    <updated>2026-03-15T09:00:00+09:00</updated>
    <dc:date>2026-03-15T09:00:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>코드리더</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-origin-width="832" data-origin-height="1248"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/d6lwWt/btsQVGvoYjZ/b4jBY26wAGbsGkWsk1G1Yk/img.png" data-phocus="https://blog.kakaocdn.net/dn/d6lwWt/btsQVGvoYjZ/b4jBY26wAGbsGkWsk1G1Yk/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/d6lwWt/btsQVGvoYjZ/b4jBY26wAGbsGkWsk1G1Yk/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd6lwWt%2FbtsQVGvoYjZ%2Fb4jBY26wAGbsGkWsk1G1Yk%2Fimg.png" onerror="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';" loading="lazy" width="832" height="1248" data-origin-width="832" data-origin-height="1248"&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;더글러스 엥겔바트를 '컴퓨터 마우스'의 발명가라고 평가할 수는 없을 것 같습니다. 그는 1960년대에 이미 요즘 우리가 사용하는 거의 모든 컴퓨팅 환경(그래픽 인터페이스, 하이퍼링크, 화상 회의)의 청사진을 제시한 '인간-컴퓨터 상호작용(HCI;Human-Computer-Interaction)'의 아버지입니다. 그의 목표는 기계를 똑똑하게 만드는 것이 아니라 '기계를 통해 인간의 지능을 증강(Augmenting Human Intellect)'시키는 것이었습니다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;더글라스 엥겔바트는 &lt;span style="color: #333333; text-align: start;"&gt;2차 세계대전에서 레이더 기술자로 해군에 복무합니다. 필리핀에서 2년동안 기술병으로 복무하면서 바네바 부시의 "As We may Think"라는 글을 읽고나서 큰 감명을 받고, 이후 인류가 직면한 복잡한 문제들을 해결하기 위해 컴퓨터가 '인간의 사고'를 확장하는 도구가 되어야 한다는 사명을 가지게 되었다고 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="color: #333333; text-align: start;"&gt;그는 UC 버클리를 졸업한 이후 모교에서 조교수로 재직하다가 1957년 SRI(Stanford Research Institute)로 자리를 옮깁니다. 이곳에서 "&lt;i&gt;Augmenting Human Intellect: A Conceptual Framework&lt;/i&gt;&lt;span&gt; (인간지능 증강: 개념 프레임워크)"보고서(&lt;a href="https://dougengelbart.org/pubs/papers/scanned-original/1962-augment-3906-Augmenting-Human-Intellect-a-Conceptual-Framework.pdf" target="_blank" rel="noopener"&gt;원문 링크&lt;/a&gt;)를 발표합니다. 이 보고서 덕분에 ARPA로 연구자금을 지원받아 ARC(증강연구센터)를 설립합니다. 이곳에서 그와 그의 팀은 다양한 전자 장치와 함께 개인용 컴퓨터에서 사용되는 여러 인터페이스의 아이디어를 구상하고 개발했습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="color: #333333; text-align: start;"&gt;&lt;span&gt;가장 유명한 것이 마우스입니다. 1964년 처음 개발된 마우스는 '나무 상자에 바퀴 두 개'를 단 형태였고, 이를 통해 화면의 특정 지점을 효율적으로 가리킬 수 있게 되었습니다. 장치의 꼬리가 튀어 나와 있어서  "마우스"라는 이름을 붙였다고 합니다. 마우스를 개발해서 엄청난 부자가 되었을 것 같지만, 현실은... SRI는 해당 기술에 대한 특허를 출원했었지만, 가치를 제대로 몰랐습니다. SRI는  애플에게 마우스의 라이선스를 약 4만 달러(현재 환율로 대략 5천만원)에 부여합니다. 그가 발명한 마우스 특허는 1987년 만료되었고, 안타깝지만 마우스는 이후 PC혁명이 촉발되면서 그 이후에 보급되는 바람에 이 발명으로는 돈을 벌지 못합니다.&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #333333; text-align: start;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-origin-width="270" data-origin-height="212"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/bF5QQl/dJMcafZ8F3w/gLxlUZGCA1z2OZATAmfzAK/img.png" data-phocus="https://blog.kakaocdn.net/dn/bF5QQl/dJMcafZ8F3w/gLxlUZGCA1z2OZATAmfzAK/img.png" data-alt="마우스 초기 프로토타입"&gt;&lt;img src="https://blog.kakaocdn.net/dn/bF5QQl/dJMcafZ8F3w/gLxlUZGCA1z2OZATAmfzAK/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbF5QQl%2FdJMcafZ8F3w%2FgLxlUZGCA1z2OZATAmfzAK%2Fimg.png" onerror="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';" loading="lazy" width="270" height="212" data-origin-width="270" data-origin-height="212"&gt;&lt;/span&gt;&lt;figcaption&gt;마우스 초기 프로토타입&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="color: #333333; text-align: start;"&gt;&lt;span&gt;더글라스는 '모든 데모의 어머니'라는 칭호를 가지고 있습니다. 1968년 12월 9일 샌프란시스코에서 oN-Line System(NLS)에 사용되는 기술을 90여분간 시연합니다. 이 시연에는 컴퓨터 마우스, 그래픽 사용자 인터페이스(GUI), 하이퍼 텍스트(클릭 가능한 링크), 워드 프로세스 등이 포함되어 있었습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=B6rKUf9DWRI&amp;amp;list=PLCGFadV4FqU2yAqCzKaxnKKXgnJBUrKTE" data-video-thumbnail="https://scrap.kakaocdn.net/dn/ctiQOO/dJMb9iIFOBb/iK4IWAQkk0Q8DWkPWjtS7K/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=1054_262_1260_486,https://scrap.kakaocdn.net/dn/dlcH5E/dJMb9iIFOBa/IM81TsPcf3tEUrNbUkvKr0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=1054_262_1260_486" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="1968 “Mother of All Demos” by SRI’s Doug Engelbart and Team" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/B6rKUf9DWRI" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="color: #333333; text-align: start;"&gt;&lt;span&gt;마우스의 개발자로만 알려져 있는데, 엥겔바트는 컴퓨터라는 전자 기기를 통해 인간의 지능을 증강시키려 했던 선구자였습니다. 이를 기리기 위하여 엥겔바트 재단이 세워졌습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-origin-width="1326" data-origin-height="870"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/BtyTY/dJMcahKsCPA/RXSK7SQzhHF8gG2P65FC1K/img.png" data-phocus="https://blog.kakaocdn.net/dn/BtyTY/dJMcahKsCPA/RXSK7SQzhHF8gG2P65FC1K/img.png" data-alt="마우스와 키셋을 장착한 컴퓨터: 출처-엥겔바트 재"&gt;&lt;img src="https://blog.kakaocdn.net/dn/BtyTY/dJMcahKsCPA/RXSK7SQzhHF8gG2P65FC1K/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBtyTY%2FdJMcahKsCPA%2FRXSK7SQzhHF8gG2P65FC1K%2Fimg.png" onerror="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';" loading="lazy" width="1326" height="870" data-origin-width="1326" data-origin-height="870"&gt;&lt;/span&gt;&lt;figcaption&gt;마우스와 키셋을 장착한 컴퓨터: 출처-엥겔바트 재&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style3"&gt;
&lt;blockquote data-ke-style="style3"&gt;"나의 목표는 인류의 지능을 증강시키는 것입니다." (The goal is to augment human intellect.)&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;요즘 문제는 혁신을 어떻게 이루어낼 것인가가 아니라, 이미 존재하는 좋은 아이디어들을 사회가 어떻게 받아들이도록 할 것인가입니다.( These days, the problem isn't how to innovate; it's how to get society to adopt the good ideas that already exist.)&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;"디지털 혁명은 글쓰기나 인쇄술의 발명보다 훨씬 더 중요합니다." (The digital revolution is far more significant than the invention of writing or even of printing.)&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;사람이 성숙하는 속도는 그 사람이 감내할 수 있는 창피함의 정도에 정비례합니다. (The rate at which a person can mature is directly proportional to the embarrassment he can tolerate.)&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;"더 나은 세상을 만들 수 있는 잠재력을 높이는 것, 그것이 나의 '지능 증강'의 핵심입니다." (Boosting mankind's capability for creating a better world... that's the core of 'Augmenting Intellect'.)&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;세계가 직면한 모든 큰 문제의 핵심은 공동으로 해결해야 한다는 것입니다. 우리가 함께 더 현명해지지 않는다면, 우리는 파멸할 것입니다. (The key thing about all the world's big problems is that they have to be dealt with collectively. If we don't get collectively smarter, we're doomed.)&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;"꿈을 이루기 위해 고군분투하는 다른 사람들에게 '이 시골 꼬맹이도 해냈으니 나도 계속 노력해야겠다'라는 용기를 줄 수 있다면 정말 멋진 일일 거예요." (It would be wonderful if I can inspire others, who are struggling to realize their dreams, to say 'if this country kid could do it, let me keep slogging away'.)&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style3"&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=iqJCvuHrkOI" data-video-thumbnail="https://scrap.kakaocdn.net/dn/ju7C9/dJMb9lk5wHH/2ks07KBmx4GgoeYHLbz1O0/img.jpg?width=480&amp;amp;height=360&amp;amp;face=198_64_299_174,https://scrap.kakaocdn.net/dn/fJdPm/dJMb9kT1mOG/AVYsAS7AJ6XPwtGiZIQxr1/img.jpg?width=480&amp;amp;height=360&amp;amp;face=198_64_299_174" data-video-width="480" data-video-height="360" data-video-origin-width="480" data-video-origin-height="360" data-ke-mobilestyle="widthContent" data-video-title="Oral History of Douglas Engelbart" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/iqJCvuHrkOI" width="480" height="360" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=FNCCkhADpiw" data-video-thumbnail="https://scrap.kakaocdn.net/dn/ct2v2G/dJMb8SpGk0W/l00DbFRIkgyPmHLevEVGm1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=522_134_706_336,https://scrap.kakaocdn.net/dn/lZra2/dJMb8UHNxXV/eUO8wRc6VwMmPnrTHNReYk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=522_134_706_336" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="Technology Legend: Honoring Douglas Engelbart" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/FNCCkhADpiw" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=_7ZtISeGyCY" data-video-thumbnail="https://scrap.kakaocdn.net/dn/gmkOv/dJMb8Qekz1c/UphASaB2hGhpq7XvMFwxY1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/bD8FkJ/dJMb8UHNxX1/8gAyNNNnYTVs8rsqRM3wL0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="The Augmentation of Douglas Engelbart | Full Documentary" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/_7ZtISeGyCY" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=yJDv-zdhzMY" data-video-thumbnail="https://scrap.kakaocdn.net/dn/dk6jnB/dJMb8TB7X1p/8jAu0VdYzaGSrc8MkDe8L0/img.jpg?width=480&amp;amp;height=360&amp;amp;face=272_141_391_271,https://scrap.kakaocdn.net/dn/qsJhP/dJMb9iIFukj/hXn0hxq5jpbpDJy9YAEKIK/img.jpg?width=480&amp;amp;height=360&amp;amp;face=272_141_391_271,https://scrap.kakaocdn.net/dn/bIKUDZ/dJMb9dHmrLn/n65tzNEYIupepK4EYefZJK/img.jpg?width=480&amp;amp;height=360&amp;amp;face=272_141_391_271" data-video-width="480" data-video-height="360" data-video-origin-width="480" data-video-origin-height="360" data-ke-mobilestyle="widthContent" data-video-title="The Mother of All Demos, presented by Douglas Engelbart (1968)" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/yJDv-zdhzMY" width="480" height="360" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure id="og_1773605857846" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="Welcome - Doug Engelbart Institute" data-og-description='&amp;lt;!-- Saved Announcements &amp;lt;!-- &amp;lt;a target="_blank" href="https://campustechnology.com/articles/2021/03/08/augmenting-the-learning-dialogue-online.aspx"&amp;gt;&amp;lt;img src="https://deipress.files.wordpress.com/2021/03/2021-03-campus-tech-gardner.jpg?w=300" alt="feature' data-og-host="dougengelbart.org" data-og-source-url="https://dougengelbart.org/" data-og-url="https://dougengelbart.org/" data-og-image="https://scrap.kakaocdn.net/dn/bstFcK/dJMb9jOlFAJ/LvqgQDZeIdT4N2B8Top4n0/img.jpg?width=2990&amp;amp;height=1550&amp;amp;face=392_224_803_672,https://scrap.kakaocdn.net/dn/xSRmV/dJMb9iaPQxd/BJ3GSxN7vqpyKZTA0hMtrK/img.png?width=300&amp;amp;height=225&amp;amp;face=110_58_181_136"&gt;&lt;a href="https://dougengelbart.org/" target="_blank" rel="noopener" data-source-url="https://dougengelbart.org/"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/bstFcK/dJMb9jOlFAJ/LvqgQDZeIdT4N2B8Top4n0/img.jpg?width=2990&amp;amp;height=1550&amp;amp;face=392_224_803_672,https://scrap.kakaocdn.net/dn/xSRmV/dJMb9iaPQxd/BJ3GSxN7vqpyKZTA0hMtrK/img.png?width=300&amp;amp;height=225&amp;amp;face=110_58_181_136');"&gt; &lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;Welcome - Doug Engelbart Institute&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;&amp;lt;!-- Saved Announcements &amp;lt;!-- &amp;lt;a target="_blank" href="https://campustechnology.com/articles/2021/03/08/augmenting-the-learning-dialogue-online.aspx"&amp;gt;&amp;lt;img src="https://deipress.files.wordpress.com/2021/03/2021-03-campus-tech-gardner.jpg?w=300" alt="feature&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;dougengelbart.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://neozest2.tistory.com/entry/DouglasEngelbart</id>
    <link href="https://neozest2.tistory.com/entry/DouglasEngelbart"/>
    <summary type="html">&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-origin-width="832" data-origin-height="1248"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/d6lwWt/btsQVGvoYjZ/b4jBY26wAGbsGkWsk1G1Yk/img.png" data-phocus="https://blog.kakaocdn.net/dn/d6lwWt/btsQVGvoYjZ/b4jBY26wAGbsGkWsk1G1Yk/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/d6lwWt/btsQVGvoYjZ/b4jBY26wAGbsGkWsk1G1Yk/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd6lwWt%2FbtsQVGvoYjZ%2Fb4jBY26wAGbsGkWsk1G1Yk%2Fimg.png" onerror="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';" loading="lazy" width="832" height="1248" data-origin-width="832" data-origin-height="1248"/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;더글러스 엥겔바트를 '컴퓨터 마우스'의 발명가라고 평가할 수는 없을 것 같습니다. 그는 1960년대에 이미 요즘 우리가 사용하는 거의 모든 컴퓨팅 환경(그래픽 인터페이스, 하이퍼링크, 화상 회의)의 청사진을 제시한 '인간-컴퓨터 상호작용(HCI;Human-Computer-Interaction)'의 아버지입니다. 그의 목표는 기계를 똑똑하게 만드는 것이 아니라 '기계를 통해 인간의 지능을 증강(Augmenting Human Intellect)'시키는 것이었습니다.&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;더글라스 엥겔바트는 &lt;span style="color: #333333; text-align: start;"&gt;2차 세계대전에서 레이더 기술자로 해군에 복무합니다. 필리핀에서 2년동안 기술병으로 복무하면서 바네바 부시의 "As We may Think"라는 글을 읽고나서 큰 감명을 받고, 이후 인류가 직면한 복잡한 문제들을 해결하기 위해 컴퓨터가 '인간의 사고'를 확장하는 도구가 되어야 한다는 사명을 가지게 되었다고 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="color: #333333; text-align: start;"&gt;그는 UC 버클리를 졸업한 이후 모교에서 조교수로 재직하다가 1957년 SRI(Stanford Research Institute)로 자리를 옮깁니다. 이곳에서 "&lt;i&gt;Augmenting Human Intellect: A Conceptual Framework&lt;/i&gt;&lt;span&gt; (인간지능 증강: 개념 프레임워크)"보고서(&lt;a href="https://dougengelbart.org/pubs/papers/scanned-original/1962-augment-3906-Augmenting-Human-Intellect-a-Conceptual-Framework.pdf" target="_blank" rel="noopener"&gt;원문 링크&lt;/a&gt;)를 발표합니다. 이 보고서 덕분에 ARPA로 연구자금을 지원받아 ARC(증강연구센터)를 설립합니다. 이곳에서 그와 그의 팀은 다양한 전자 장치와 함께 개인용 컴퓨터에서 사용되는 여러 인터페이스의 아이디어를 구상하고 개발했습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="color: #333333; text-align: start;"&gt;&lt;span&gt;가장 유명한 것이 마우스입니다. 1964년 처음 개발된 마우스는 '나무 상자에 바퀴 두 개'를 단 형태였고, 이를 통해 화면의 특정 지점을 효율적으로 가리킬 수 있게 되었습니다. 장치의 꼬리가 튀어 나와 있어서&amp;nbsp; "마우스"라는 이름을 붙였다고 합니다. 마우스를 개발해서 엄청난 부자가 되었을 것 같지만, 현실은... SRI는 해당 기술에 대한 특허를 출원했었지만, 가치를 제대로 몰랐습니다. SRI는&amp;nbsp; 애플에게 마우스의 라이선스를 약 4만 달러(현재 환율로 대략 5천만원)에 부여합니다. 그가 발명한 마우스 특허는 1987년 만료되었고, 안타깝지만 마우스는 이후 PC혁명이 촉발되면서 그 이후에 보급되는 바람에 이 발명으로는 돈을 벌지 못합니다.&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #333333; text-align: start;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-origin-width="270" data-origin-height="212"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/bF5QQl/dJMcafZ8F3w/gLxlUZGCA1z2OZATAmfzAK/img.png" data-phocus="https://blog.kakaocdn.net/dn/bF5QQl/dJMcafZ8F3w/gLxlUZGCA1z2OZATAmfzAK/img.png" data-alt="마우스 초기 프로토타입"&gt;&lt;img src="https://blog.kakaocdn.net/dn/bF5QQl/dJMcafZ8F3w/gLxlUZGCA1z2OZATAmfzAK/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbF5QQl%2FdJMcafZ8F3w%2FgLxlUZGCA1z2OZATAmfzAK%2Fimg.png" onerror="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';" loading="lazy" width="270" height="212" data-origin-width="270" data-origin-height="212"/&gt;&lt;/span&gt;&lt;figcaption&gt;마우스 초기 프로토타입&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="color: #333333; text-align: start;"&gt;&lt;span&gt;더글라스는 '모든 데모의 어머니'라는 칭호를 가지고 있습니다. 1968년 12월 9일 샌프란시스코에서 oN-Line System(NLS)에 사용되는 기술을 90여분간 시연합니다. 이 시연에는 컴퓨터 마우스, 그래픽 사용자 인터페이스(GUI), 하이퍼 텍스트(클릭 가능한 링크), 워드 프로세스 등이 포함되어 있었습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=B6rKUf9DWRI&amp;amp;list=PLCGFadV4FqU2yAqCzKaxnKKXgnJBUrKTE" data-video-thumbnail="https://scrap.kakaocdn.net/dn/ctiQOO/dJMb9iIFOBb/iK4IWAQkk0Q8DWkPWjtS7K/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=1054_262_1260_486,https://scrap.kakaocdn.net/dn/dlcH5E/dJMb9iIFOBa/IM81TsPcf3tEUrNbUkvKr0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=1054_262_1260_486" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="1968 &amp;ldquo;Mother of All Demos&amp;rdquo; by SRI&amp;rsquo;s Doug Engelbart and Team" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/B6rKUf9DWRI" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&lt;span style="color: #333333; text-align: start;"&gt;&lt;span&gt;마우스의 개발자로만 알려져 있는데, 엥겔바트는 컴퓨터라는 전자 기기를 통해 인간의 지능을 증강시키려 했던 선구자였습니다. 이를 기리기 위하여 엥겔바트 재단이 세워졌습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-origin-width="1326" data-origin-height="870"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/BtyTY/dJMcahKsCPA/RXSK7SQzhHF8gG2P65FC1K/img.png" data-phocus="https://blog.kakaocdn.net/dn/BtyTY/dJMcahKsCPA/RXSK7SQzhHF8gG2P65FC1K/img.png" data-alt="마우스와 키셋을 장착한 컴퓨터: 출처-엥겔바트 재"&gt;&lt;img src="https://blog.kakaocdn.net/dn/BtyTY/dJMcahKsCPA/RXSK7SQzhHF8gG2P65FC1K/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBtyTY%2FdJMcahKsCPA%2FRXSK7SQzhHF8gG2P65FC1K%2Fimg.png" onerror="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';" loading="lazy" width="1326" height="870" data-origin-width="1326" data-origin-height="870"/&gt;&lt;/span&gt;&lt;figcaption&gt;마우스와 키셋을 장착한 컴퓨터: 출처-엥겔바트 재&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style3" /&gt;
&lt;blockquote data-ke-style="style3"&gt;"나의 목표는 인류의 지능을 증강시키는 것입니다." (The goal is to augment human intellect.)&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;요즘 문제는 혁신을 어떻게 이루어낼 것인가가 아니라, 이미 존재하는 좋은 아이디어들을 사회가 어떻게 받아들이도록 할 것인가입니다.( These days, the problem isn't how to innovate; it's how to get society to adopt the good ideas that already exist.)&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;"디지털 혁명은 글쓰기나 인쇄술의 발명보다 훨씬 더 중요합니다." (The digital revolution is far more significant than the invention of writing or even of printing.)&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;사람이 성숙하는 속도는 그 사람이 감내할 수 있는 창피함의 정도에 정비례합니다. (The rate at which a person can mature is directly proportional to the embarrassment he can tolerate.)&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;"더 나은 세상을 만들 수 있는 잠재력을 높이는 것, 그것이 나의 '지능 증강'의 핵심입니다." (Boosting mankind's capability for creating a better world... that's the core of 'Augmenting Intellect'.)&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;세계가 직면한 모든 큰 문제의 핵심은 공동으로 해결해야 한다는 것입니다. 우리가 함께 더 현명해지지 않는다면, 우리는 파멸할 것입니다. (The key thing about all the world's big problems is that they have to be dealt with collectively. If we don't get collectively smarter, we're doomed.)&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;"꿈을 이루기 위해 고군분투하는 다른 사람들에게 '이 시골 꼬맹이도 해냈으니 나도 계속 노력해야겠다'라는 용기를 줄 수 있다면 정말 멋진 일일 거예요." (It would be wonderful if I can inspire others, who are struggling to realize their dreams, to say 'if this country kid could do it, let me keep slogging away'.)&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style3" /&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=iqJCvuHrkOI" data-video-thumbnail="https://scrap.kakaocdn.net/dn/ju7C9/dJMb9lk5wHH/2ks07KBmx4GgoeYHLbz1O0/img.jpg?width=480&amp;amp;height=360&amp;amp;face=198_64_299_174,https://scrap.kakaocdn.net/dn/fJdPm/dJMb9kT1mOG/AVYsAS7AJ6XPwtGiZIQxr1/img.jpg?width=480&amp;amp;height=360&amp;amp;face=198_64_299_174" data-video-width="480" data-video-height="360" data-video-origin-width="480" data-video-origin-height="360" data-ke-mobilestyle="widthContent" data-video-title="Oral History of Douglas Engelbart" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/iqJCvuHrkOI" width="480" height="360" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=FNCCkhADpiw" data-video-thumbnail="https://scrap.kakaocdn.net/dn/ct2v2G/dJMb8SpGk0W/l00DbFRIkgyPmHLevEVGm1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=522_134_706_336,https://scrap.kakaocdn.net/dn/lZra2/dJMb8UHNxXV/eUO8wRc6VwMmPnrTHNReYk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=522_134_706_336" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="Technology Legend: Honoring Douglas Engelbart" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/FNCCkhADpiw" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=_7ZtISeGyCY" data-video-thumbnail="https://scrap.kakaocdn.net/dn/gmkOv/dJMb8Qekz1c/UphASaB2hGhpq7XvMFwxY1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/bD8FkJ/dJMb8UHNxX1/8gAyNNNnYTVs8rsqRM3wL0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="The Augmentation of Douglas Engelbart | Full Documentary" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/_7ZtISeGyCY" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=yJDv-zdhzMY" data-video-thumbnail="https://scrap.kakaocdn.net/dn/dk6jnB/dJMb8TB7X1p/8jAu0VdYzaGSrc8MkDe8L0/img.jpg?width=480&amp;amp;height=360&amp;amp;face=272_141_391_271,https://scrap.kakaocdn.net/dn/qsJhP/dJMb9iIFukj/hXn0hxq5jpbpDJy9YAEKIK/img.jpg?width=480&amp;amp;height=360&amp;amp;face=272_141_391_271,https://scrap.kakaocdn.net/dn/bIKUDZ/dJMb9dHmrLn/n65tzNEYIupepK4EYefZJK/img.jpg?width=480&amp;amp;height=360&amp;amp;face=272_141_391_271" data-video-width="480" data-video-height="360" data-video-origin-width="480" data-video-origin-height="360" data-ke-mobilestyle="widthContent" data-video-title="The Mother of All Demos, presented by Douglas Engelbart (1968)" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/yJDv-zdhzMY" width="480" height="360" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id="og_1773605857846" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="Welcome&amp;nbsp;-&amp;nbsp;Doug Engelbart Institute" data-og-description="&amp;lt;!-- Saved Announcements &amp;lt;!-- &amp;lt;a target=&amp;quot;_blank&amp;quot; href=&amp;quot;https://campustechnology.com/articles/2021/03/08/augmenting-the-learning-dialogue-online.aspx&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;https://deipress.files.wordpress.com/2021/03/2021-03-campus-tech-gardner.jpg?w=300&amp;quot; alt=&amp;quot;feature" data-og-host="dougengelbart.org" data-og-source-url="https://dougengelbart.org/" data-og-url="https://dougengelbart.org/" data-og-image="https://scrap.kakaocdn.net/dn/bstFcK/dJMb9jOlFAJ/LvqgQDZeIdT4N2B8Top4n0/img.jpg?width=2990&amp;amp;height=1550&amp;amp;face=392_224_803_672,https://scrap.kakaocdn.net/dn/xSRmV/dJMb9iaPQxd/BJ3GSxN7vqpyKZTA0hMtrK/img.png?width=300&amp;amp;height=225&amp;amp;face=110_58_181_136"&gt;&lt;a href="https://dougengelbart.org/" target="_blank" rel="noopener" data-source-url="https://dougengelbart.org/"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/bstFcK/dJMb9jOlFAJ/LvqgQDZeIdT4N2B8Top4n0/img.jpg?width=2990&amp;amp;height=1550&amp;amp;face=392_224_803_672,https://scrap.kakaocdn.net/dn/xSRmV/dJMb9iaPQxd/BJ3GSxN7vqpyKZTA0hMtrK/img.png?width=300&amp;amp;height=225&amp;amp;face=110_58_181_136');"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;Welcome&amp;nbsp;-&amp;nbsp;Doug Engelbart Institute&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;&amp;lt;!-- Saved Announcements &amp;lt;!-- &amp;lt;a target="_blank" href="https://campustechnology.com/articles/2021/03/08/augmenting-the-learning-dialogue-online.aspx"&amp;gt;&amp;lt;img src="https://deipress.files.wordpress.com/2021/03/2021-03-campus-tech-gardner.jpg?w=300" alt="feature&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;dougengelbart.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;</summary>
    <title>인간의 지능을 증강시키고 싶었 더글라스 엥겔바트(Douglas Engelbart)</title>
    <updated>2026-03-16T06:00:26+09:00</updated>
    <dc:date>2026-03-16T06:00:26+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>코드리더</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-origin-width="683" data-origin-height="1024"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/culD8f/dJMcaaqiEbo/VbtjiUB4G0kbE7QiM3kra1/img.png" data-phocus="https://blog.kakaocdn.net/dn/culD8f/dJMcaaqiEbo/VbtjiUB4G0kbE7QiM3kra1/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/culD8f/dJMcaaqiEbo/VbtjiUB4G0kbE7QiM3kra1/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FculD8f%2FdJMcaaqiEbo%2FVbtjiUB4G0kbE7QiM3kra1%2Fimg.png" onerror="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';" loading="lazy" width="683" height="1024" data-origin-width="683" data-origin-height="1024"&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-path-to-node="4" data-ke-size="size16"&gt;요즘 초등학생들의 장래희망이 유튜버라고 하지요. 이번에는 유튜브 플랫폼을 만든 스티브 천에 대해 알아봅니다. 스티브 천은 대만계 미국인으로 유튜브(YouTube)를 공동 창업했습니다. 그는 기술적인 아키텍처와 제품 개발을 주도하여, 누구나 쉽게 비디오를 공유하고 시청할 수 있는 플랫폼을 만들어 미디어와 엔터테인먼트 산업에 혁명적 변화를  일으켰습니다. (우리나라도 mncast가 있었는데.. ㅠㅠ)&lt;/p&gt;
&lt;p data-path-to-node="4" data-ke-size="size16"&gt;일리노이 대학교 어바나-샴페인 캠퍼스(UIUC)에서 컴퓨터 과학을 전공한 스티브 천은 졸업후 페이팔에 합류하여 엔지니어로 일합니다. 이후 페이팔에서 함께 일했던 채드 헐리, 자베드 카림 등과 함께 유튜브를 창업하는데, 워낙 실리콘밸리에 영향력이 큰 사람들 중에서 페이팔 출신이 많기 때문에 이들을 페이팔 마피아라고도 부릅니다.&lt;/p&gt;
&lt;p data-path-to-node="4" data-ke-size="size16"&gt;유튜브가 창업될 당시에는 큰 용량의 비디오 파일을 인터넷에서 끊김없이 스트리밍하는 것도 어려운 기술에 속했습니다. 스티브는 파일을 다운로드하지 않고 웹 브라우저에서 바로 재생할 수 있는 시스템을 구축합니다. 유튜브는 2005년 창업되었는데, 1년뒤 구글에 약 2조원(16억 5천만 달러=현재 환율로 대략 2조 4천억원)으로 인수됩니다. 파격적인 인수금액이었습니다. &lt;/p&gt;
&lt;p data-path-to-node="4" data-ke-size="size16"&gt;구글에서 유튜브를 계속 개발하던 스티브는 다시 AVOS Systems라는 회사를 설립하고, 협업 및 영상 관련 스타트업에 활발한 투자를 하는 VC로 활동하고 있습니다.&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style3"&gt;
&lt;p data-path-to-node="8" data-ke-size="size16"&gt; &lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;우리가 풀고 싶었던 가장 큰 문제는 '어떻게 비디오를 공유할 것인가'였습니다. 기술은 항상 그 해결책을 찾는 도구였습니다.&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;우리는 '실패해도 좋다'고 말해왔습니다. 시도하고, 빨리 실패하고, 다시 시도하십시오."&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;누구나 휴대폰을 가지고 있고, 누구나 카메라를 가지고 있습니다. 우리는 그들이 찍은 것을 세상에 보여줄 수 있는 플랫폼이 필요하다고 생각했습니다.&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;저는 엔지니어입니다. 저는 문제가 있을 때, 그 문제를 해결하기 위해 가장 효율적인 코드를 작성하는 것이 제 일이라고 생각합니다.&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;우리가 돈을 벌 것이라고 확신하지는 못했습니다. 하지만 사람들이 비디오를 원한다는 것은 확신했습니다.&lt;/blockquote&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style3"&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=1W4dFNSQmnA" data-video-thumbnail="https://scrap.kakaocdn.net/dn/bWlowe/hyZOD5rjMY/9Uj5285LrG0ixMu8RkzZfk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=558_394_994_564,https://scrap.kakaocdn.net/dn/8xuf1/hyZOM2pgsz/iLKJZQWVJy5AV1LXPSJZg0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=558_394_994_564" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="YouTube Co-Founder Steve Chen on Innovation, Startups, and Lessons Learned" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/1W4dFNSQmnA" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=DfBwxndtVw4" data-video-thumbnail="https://scrap.kakaocdn.net/dn/boxIay/hyZPqcInsw/HbQnL8N8y1pKkaRlpTrMo1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=566_264_674_382,https://scrap.kakaocdn.net/dn/UXK20/hyZPF8pIGQ/u5f47tpLie5qmrOslAiPY0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=566_264_674_382" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="ITW 2019: Opening Keynote - Steven Chen, Co-Founder of YouTube | International Telecoms Week" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/DfBwxndtVw4" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=hRx9odXEfmY" data-video-thumbnail="https://scrap.kakaocdn.net/dn/zVHgs/hyZPwjHMW0/JK3KlBGWhEqsIRONXTpJ8k/img.jpg?width=480&amp;amp;height=360&amp;amp;face=0_0_480_360,https://scrap.kakaocdn.net/dn/cclcWv/hyZOPY4IVd/PiCprN3CwlEDulErmuze5K/img.jpg?width=480&amp;amp;height=360&amp;amp;face=0_0_480_360" data-video-width="480" data-video-height="360" data-video-origin-width="480" data-video-origin-height="360" data-ke-mobilestyle="widthContent" data-video-title="Oral History of Steve Chen, part 1 of 2" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/hRx9odXEfmY" width="480" height="360" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=viADnkM0v-w" data-video-thumbnail="https://scrap.kakaocdn.net/dn/btbKNY/hyZPA7tHkY/Z8AnQXKEIk23Etn9K518k1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=826_198_1068_462,https://scrap.kakaocdn.net/dn/cTL0uB/hyZODRU7ub/ZyXBl4j6LaltTqbJfTGW61/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=826_198_1068_462" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="Youtube Founder: How A 27 Year Old Built A $400 Billion Company! (Steve Chen)" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/viADnkM0v-w" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://neozest2.tistory.com/entry/Steve-Chen-YouTubeCreator</id>
    <link href="https://neozest2.tistory.com/entry/Steve-Chen-YouTubeCreator"/>
    <summary type="html">&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-origin-width="683" data-origin-height="1024"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/culD8f/dJMcaaqiEbo/VbtjiUB4G0kbE7QiM3kra1/img.png" data-phocus="https://blog.kakaocdn.net/dn/culD8f/dJMcaaqiEbo/VbtjiUB4G0kbE7QiM3kra1/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/culD8f/dJMcaaqiEbo/VbtjiUB4G0kbE7QiM3kra1/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FculD8f%2FdJMcaaqiEbo%2FVbtjiUB4G0kbE7QiM3kra1%2Fimg.png" onerror="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';" loading="lazy" width="683" height="1024" data-origin-width="683" data-origin-height="1024"/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node="4" data-ke-size="size16"&gt;요즘 초등학생들의 장래희망이 유튜버라고 하지요. 이번에는 유튜브 플랫폼을 만든 스티브 천에 대해 알아봅니다. 스티브 천은 대만계 미국인으로 유튜브(YouTube)를 공동 창업했습니다. 그는 기술적인 아키텍처와 제품 개발을 주도하여, 누구나 쉽게 비디오를 공유하고 시청할 수 있는 플랫폼을 만들어 미디어와 엔터테인먼트 산업에 혁명적 변화를&amp;nbsp; 일으켰습니다. (우리나라도 mncast가 있었는데.. ㅠㅠ)&lt;/p&gt;
&lt;p data-path-to-node="4" data-ke-size="size16"&gt;일리노이 대학교 어바나-샴페인 캠퍼스(UIUC)에서 컴퓨터 과학을 전공한 스티브 천은 졸업후 페이팔에 합류하여 엔지니어로 일합니다. 이후 페이팔에서 함께 일했던 채드 헐리, 자베드 카림 등과 함께 유튜브를 창업하는데, 워낙 실리콘밸리에 영향력이 큰 사람들 중에서 페이팔 출신이 많기 때문에 이들을 페이팔 마피아라고도 부릅니다.&lt;/p&gt;
&lt;p data-path-to-node="4" data-ke-size="size16"&gt;유튜브가 창업될 당시에는 큰 용량의 비디오 파일을 인터넷에서 끊김없이 스트리밍하는 것도 어려운 기술에 속했습니다. 스티브는 파일을 다운로드하지 않고 웹 브라우저에서 바로 재생할 수 있는 시스템을 구축합니다. 유튜브는 2005년 창업되었는데, 1년뒤 구글에 약 2조원(16억 5천만 달러=현재 환율로 대략 2조 4천억원)으로 인수됩니다. 파격적인 인수금액이었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node="4" data-ke-size="size16"&gt;구글에서 유튜브를 계속 개발하던 스티브는 다시 AVOS Systems라는 회사를 설립하고, 협업 및 영상 관련 스타트업에 활발한 투자를 하는 VC로 활동하고 있습니다.&lt;/p&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style3" /&gt;
&lt;p data-path-to-node="8" data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;우리가 풀고 싶었던 가장 큰 문제는 '어떻게 비디오를 공유할 것인가'였습니다. 기술은 항상 그 해결책을 찾는 도구였습니다.&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;우리는 '실패해도 좋다'고 말해왔습니다. 시도하고, 빨리 실패하고, 다시 시도하십시오."&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;누구나 휴대폰을 가지고 있고, 누구나 카메라를 가지고 있습니다. 우리는 그들이 찍은 것을 세상에 보여줄 수 있는 플랫폼이 필요하다고 생각했습니다.&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;저는 엔지니어입니다. 저는 문제가 있을 때, 그 문제를 해결하기 위해 가장 효율적인 코드를 작성하는 것이 제 일이라고 생각합니다.&lt;/blockquote&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style="style3"&gt;우리가 돈을 벌 것이라고 확신하지는 못했습니다. 하지만 사람들이 비디오를 원한다는 것은 확신했습니다.&lt;/blockquote&gt;
&lt;hr contenteditable="false" data-ke-type="horizontalRule" data-ke-style="style3" /&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=1W4dFNSQmnA" data-video-thumbnail="https://scrap.kakaocdn.net/dn/bWlowe/hyZOD5rjMY/9Uj5285LrG0ixMu8RkzZfk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=558_394_994_564,https://scrap.kakaocdn.net/dn/8xuf1/hyZOM2pgsz/iLKJZQWVJy5AV1LXPSJZg0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=558_394_994_564" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="YouTube Co-Founder Steve Chen on Innovation, Startups, and Lessons Learned" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/1W4dFNSQmnA" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=DfBwxndtVw4" data-video-thumbnail="https://scrap.kakaocdn.net/dn/boxIay/hyZPqcInsw/HbQnL8N8y1pKkaRlpTrMo1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=566_264_674_382,https://scrap.kakaocdn.net/dn/UXK20/hyZPF8pIGQ/u5f47tpLie5qmrOslAiPY0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=566_264_674_382" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="ITW 2019: Opening Keynote - Steven Chen, Co-Founder of YouTube | International Telecoms Week" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/DfBwxndtVw4" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=hRx9odXEfmY" data-video-thumbnail="https://scrap.kakaocdn.net/dn/zVHgs/hyZPwjHMW0/JK3KlBGWhEqsIRONXTpJ8k/img.jpg?width=480&amp;amp;height=360&amp;amp;face=0_0_480_360,https://scrap.kakaocdn.net/dn/cclcWv/hyZOPY4IVd/PiCprN3CwlEDulErmuze5K/img.jpg?width=480&amp;amp;height=360&amp;amp;face=0_0_480_360" data-video-width="480" data-video-height="360" data-video-origin-width="480" data-video-origin-height="360" data-ke-mobilestyle="widthContent" data-video-title="Oral History of Steve Chen, part 1 of 2" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/hRx9odXEfmY" width="480" height="360" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=viADnkM0v-w" data-video-thumbnail="https://scrap.kakaocdn.net/dn/btbKNY/hyZPA7tHkY/Z8AnQXKEIk23Etn9K518k1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=826_198_1068_462,https://scrap.kakaocdn.net/dn/cTL0uB/hyZODRU7ub/ZyXBl4j6LaltTqbJfTGW61/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=826_198_1068_462" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="Youtube Founder: How A 27 Year Old Built A $400 Billion Company! (Steve Chen)" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/viADnkM0v-w" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;</summary>
    <title>스티브 천 (Steve Chen, 진사오쥔): 유튜브를 만든 대만계 미국인 공학자</title>
    <updated>2026-03-13T06:00:28+09:00</updated>
    <dc:date>2026-03-13T06:00:28+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>코드리더</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-origin-width="1024" data-origin-height="559"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/LlBSJ/dJMcagxOZqD/CfkTkFFdiJYFceeZs3PMp1/img.png" data-phocus="https://blog.kakaocdn.net/dn/LlBSJ/dJMcagxOZqD/CfkTkFFdiJYFceeZs3PMp1/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/LlBSJ/dJMcagxOZqD/CfkTkFFdiJYFceeZs3PMp1/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLlBSJ%2FdJMcagxOZqD%2FCfkTkFFdiJYFceeZs3PMp1%2Fimg.png" onerror="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';" loading="lazy" width="1024" height="559" data-origin-width="1024" data-origin-height="559"&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-path-to-node="5" data-ke-size="size16"&gt;1938년생인 도널드 커누스 교수님. 88세이십니다만, 여전히 스탠포드대의 명예교수로 재직하시면서  TAoCP(The Art of Computer Programming, 컴퓨터 프로그래밍의 예술)를 집필하고 계십니다.TAoCP 번역서는 4권까지 나와있는데, 한빛미디어에서 출간해 주고 있으며, 류광님이 시리즈의 모든 책을 번역중이십니다. 한 권마다  800~1000쪽으로 이루어져 있습니다.&lt;/p&gt;
&lt;p data-path-to-node="5" data-ke-size="size16"&gt;커누스 교수님의 천재성을 보여주는 일화들이 많이 있습니다. 그중  유명한 것은 중학생 시절 &lt;span style="color: #333333; text-align: start;"&gt;미네아폴리스 스타 신문에 실렸던 &lt;/span&gt;단어 조합 광고 이벤트에서 1등을 수상한 것입니다.이 이벤트는 &lt;span style="color: #333333; text-align: start;"&gt;'Ziegler's Giant Bar'라는 제품명의 글자를 조합하여 얼마나 많은 단어를 만들 수 있는지 알아 맞히는 대회였습니다. 8학년이었던 &lt;span&gt;크누스는 4500개 이상의 단어를 찾아내 대회에서 1등을 차지합니다. 상품으로 받은 TV는 그가 다니던 학교에, 경품으로 받은 초콜릿바는 친구들과 나눠 먹었답니다. (좋은 친구 옆에 있어야 합니다....)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-origin-width="423" data-origin-height="1200"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/by2cOp/dJMcacWuEbP/0ezIEyftaa0warHiiEgSSk/img.png" data-phocus="https://blog.kakaocdn.net/dn/by2cOp/dJMcacWuEbP/0ezIEyftaa0warHiiEgSSk/img.png" data-alt="친구를 잘 두면 초콜릿바를 마음껏 먹을 수 있습니다."&gt;&lt;img src="https://blog.kakaocdn.net/dn/by2cOp/dJMcacWuEbP/0ezIEyftaa0warHiiEgSSk/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fby2cOp%2FdJMcacWuEbP%2F0ezIEyftaa0warHiiEgSSk%2Fimg.png" onerror="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';" loading="lazy" width="208" height="590" data-origin-width="423" data-origin-height="1200"&gt;&lt;/span&gt;&lt;figcaption&gt;친구를 잘 두면 초콜릿바를 마음껏 먹을 수 있습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-path-to-node="6" data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-path-to-node="6" data-ke-size="size16"&gt;대학에 진학한 그는 수학과 음악 모두에 깊은 애정을 가졌습니다. 파이프 오르간 연주를 즐기던 이 섬세한 수학자는 우연히 초기 컴퓨터를 접하면서 프로그래밍의 세계에 빠져들게 됩니다. 복잡한 수식과 논리가 컴퓨터라는 기계를 통해 살아 움직이는 것을 보며, 그는 컴퓨터 프로그래밍이 단순한 기술을 넘어선 '아름다운 예술'이 될 수 있음을 직감했을까요?&lt;/p&gt;
&lt;p data-path-to-node="7" data-ke-size="size16"&gt;그의 일생을 건 위대한 프로젝트, 『컴퓨터 프로그래밍의 예술(The Art of Computer Programming, TAOCP)』은 대학원생이던 시절에 시작되었습니다. 처음에는 컴파일러에 관한 책을 써달라는 출판사의 요청으로 시작했지만, 그의 완벽주의와 방대한 지식은 이 책을 컴퓨터 과학의 모든 알고리즘을 집대성하는 거대한 백과사전으로 탈바꿈시켰습니다. 1962년에 시작된 이 집필 작업은 놀랍게도 반세기가 지난 지금까지도 현재 진행형입니다.&lt;/p&gt;
&lt;p data-path-to-node="8" data-ke-size="size16"&gt;이 시리즈는 프로그래머들 사이에서 '바이블'(유명하지만 제대로 읽은 사람은 드문;;;) 로 통합니다. 마이크로소프트의 창업자 빌 게이츠는 "당신이 정말 훌륭한 프로그래머라고 생각한다면 이 책을 읽어보라. 만약 이 책을 끝까지 다 읽고 이해했다면, 당장 나에게 이력서를 보내라"라고 극찬하기도 했죠. 알고리즘의 분석과 수학적 기초를 확립한 이 저서로 인해, 그는 1974년 컴퓨터 과학계의 노벨상이라 불리는 '튜링상(Turing Award)'을 수상하게 됩니다.&lt;/p&gt;
&lt;p data-path-to-node="9" data-ke-size="size16"&gt;그의 삶에서 가장 흥미로우면서도 경이로운 에피소드는 바로 조판 시스템 'TeX(텍)'의 발명입니다. 1970년대 후반, TAOCP 2권의 개정판 인쇄본을 받아본 크누스 교수는 형편없는 수학 수식의 인쇄 상태에 큰 충격을 받았습니다. 책의 미학적인 완성도를 도저히 타협할 수 없었던 그는 "잠시 책 집필을 멈추고 직접 조판 프로그램을 만들겠다"고 선언합니다.&lt;/p&gt;
&lt;p data-path-to-node="10" data-ke-size="size16"&gt;당초 몇 달이면 끝날 줄 알았던 이 '외도'는 무려 10년 가까이 이어졌습니다. 그 결과 탄생한 것이 바로 오늘날 전 세계 수학자, 과학자, 출판계에서 널리 쓰이는 디지털 조판 시스템 'TeX'과 글꼴 디자인 시스템 'METAFONT(메타폰트)'입니다. 그는 이 혁명적인 소프트웨어를 상업적으로 이용하지 않고 전 세계에 무료로 공개하여, 지식의 아름다운 공유라는 위대한 유산을 남겼습니다. (천재가 개발 일정을 예측해도 틀립니다;;;)&lt;/p&gt;
&lt;p data-path-to-node="11" data-ke-size="size16"&gt;또한 그는 '문학적 프로그래밍(Literate Programming)'이라는 매력적인 개념을 창안했습니다. 컴퓨터 코드를 작성할 때 단순히 기계가 이해하기 위한 명령어를 나열하는 것에 그치지 않고, 사람이 읽고 이해할 수 있는 한 편의 '문학 작품'처럼 쓰여야 한다는 철학입니다. 프로그래밍을 진정한 예술의 경지로 끌어올리고자 했던 그의 깊은 통찰이 돋보이는 대목입니다.&lt;/p&gt;
&lt;p data-path-to-node="12" data-ke-size="size16"&gt;크누스 교수님 특유의 유쾌함과 완벽주의는 그의 유명한 '수표 보상' 시스템에서도 엿볼 수 있습니다. 그는 자신의 책이나 프로그램에서 오류를 찾아내는 사람에게 16진수 1달러에 해당하는 '2.56달러'짜리 수표를 보내줍니다. 이 수표는 돈으로서의 가치보다 '천재 학자에게 오류를 지적해 낸 증표'로서 엄청난 명예로 여겨지기에, 대부분의 프로그래머들은 이를 환전하지 않고 평생의 자랑거리로 액자에 걸어둔다고 해요.&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-origin-width="900" data-origin-height="408"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/2mTBX/dJMcadOGV6x/1imbEmOcsddCjyKrGhNdHK/img.png" data-phocus="https://blog.kakaocdn.net/dn/2mTBX/dJMcadOGV6x/1imbEmOcsddCjyKrGhNdHK/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/2mTBX/dJMcadOGV6x/1imbEmOcsddCjyKrGhNdHK/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2mTBX%2FdJMcadOGV6x%2F1imbEmOcsddCjyKrGhNdHK%2Fimg.png" onerror="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';" loading="lazy" width="900" height="408" data-origin-width="900" data-origin-height="408"&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-path-to-node="13" data-ke-size="size16"&gt;오늘날에도 그는 오직 집필과 연구에만 몰두하기 위해 1990년부터 이메일 사용을 전면 중단하고, 우편으로만 소통하는 아날로그적인 삶을 살고 있습니다.&lt;/p&gt;
&lt;p data-path-to-node="13" data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=EE1R8FYUJm0" data-video-thumbnail="https://scrap.kakaocdn.net/dn/bAmtOv/dJMb87NTMsx/ypa3v4qIn7G3dPBz0ekpaK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=670_120_1004_484,https://scrap.kakaocdn.net/dn/lMWR0/dJMb84XV7VE/IcjbLgXMFjpImC1IgCMWR0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=670_120_1004_484" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="Donald Knuth: Programming, Algorithms, Hard Problems &amp;amp; the Game of Life | Lex Fridman Podcast #219" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/EE1R8FYUJm0" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=_cR9zDlvP88" data-video-thumbnail="https://scrap.kakaocdn.net/dn/B0toG/dJMb9iIEuYU/4YiKYWPbJj3Uj9BwUGLJZ0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=630_182_754_318,https://scrap.kakaocdn.net/dn/bHQHcU/dJMb8XR20tJ/Fz4jfWA2gGGmdyRzRWOyD0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=630_182_754_318" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title='Stanford Lecture: Don Knuth—"Dancing Links" (2018)' data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/_cR9zDlvP88" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=JPpk-1btGZk" data-video-thumbnail="https://scrap.kakaocdn.net/dn/bkM1sE/dJMb8RjZkps/DMTVm6Kr9LghGK9jxuHd91/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=638_192_902_480,https://scrap.kakaocdn.net/dn/JbQ7V/dJMb8SXu9S2/iMbvIC6HpK1HWeK6nkgpKk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=638_192_902_480" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="The Art of Computer Programming | Donald Knuth | Talks at Google" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/JPpk-1btGZk" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure id="og_1772294443024" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="The Art of Computer Programming 1 | 도널드 커누스 - 교보문고" data-og-description="The Art of Computer Programming 1 |" data-og-host="product.kyobobook.co.kr" data-og-source-url="https://product.kyobobook.co.kr/detail/S000001223366" data-og-url="https://product.kyobobook.co.kr/detail/S000001223366" data-og-image="https://scrap.kakaocdn.net/dn/eojhbu/dJMb9lL8WtJ/ZIi0tdvEBkIiAIyxFXelr1/img.jpg?width=458&amp;amp;height=638&amp;amp;face=0_0_458_638,https://scrap.kakaocdn.net/dn/lBjJt/dJMb9kT0lWF/n6BFrRZBmBUopjxmV2v0dk/img.jpg?width=458&amp;amp;height=638&amp;amp;face=0_0_458_638"&gt;&lt;a href="https://product.kyobobook.co.kr/detail/S000001223366" target="_blank" rel="noopener" data-source-url="https://product.kyobobook.co.kr/detail/S000001223366"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/eojhbu/dJMb9lL8WtJ/ZIi0tdvEBkIiAIyxFXelr1/img.jpg?width=458&amp;amp;height=638&amp;amp;face=0_0_458_638,https://scrap.kakaocdn.net/dn/lBjJt/dJMb9kT0lWF/n6BFrRZBmBUopjxmV2v0dk/img.jpg?width=458&amp;amp;height=638&amp;amp;face=0_0_458_638');"&gt; &lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;The Art of Computer Programming 1 | 도널드 커누스 - 교보문고&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;The Art of Computer Programming 1 |&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;product.kyobobook.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure id="og_1772294454435" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="The Art of Computer Programming 2 | 도널드 커누스 - 교보문고" data-og-description="The Art of Computer Programming 2 |" data-og-host="product.kyobobook.co.kr" data-og-source-url="https://product.kyobobook.co.kr/detail/S000001223414" data-og-url="https://product.kyobobook.co.kr/detail/S000001223414" data-og-image="https://scrap.kakaocdn.net/dn/mQcD0/dJMb8QejAAF/rW2W1kJTKs8tTO1Vbo4NbK/img.jpg?width=458&amp;amp;height=637&amp;amp;face=0_0_458_637,https://scrap.kakaocdn.net/dn/vrg3U/dJMb8TB6Y2t/hwbutKHkzTkKr5hZ6qPkHK/img.jpg?width=458&amp;amp;height=637&amp;amp;face=0_0_458_637"&gt;&lt;a href="https://product.kyobobook.co.kr/detail/S000001223414" target="_blank" rel="noopener" data-source-url="https://product.kyobobook.co.kr/detail/S000001223414"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/mQcD0/dJMb8QejAAF/rW2W1kJTKs8tTO1Vbo4NbK/img.jpg?width=458&amp;amp;height=637&amp;amp;face=0_0_458_637,https://scrap.kakaocdn.net/dn/vrg3U/dJMb8TB6Y2t/hwbutKHkzTkKr5hZ6qPkHK/img.jpg?width=458&amp;amp;height=637&amp;amp;face=0_0_458_637');"&gt; &lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;The Art of Computer Programming 2 | 도널드 커누스 - 교보문고&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;The Art of Computer Programming 2 |&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;product.kyobobook.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure id="og_1772294465841" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="The Art of Computer Programming 3 | 도널드 커누스 - 교보문고" data-og-description="The Art of Computer Programming 3 | 정렬과 검색을 통한 이상적인 알고리즘의 발견이 책은 다른 기본적인 구조적 착안들에 선형 순서 자료의 개념을 더하는 것이므로, 제1권 제2장의 정보 과학 내용과 관" data-og-host="product.kyobobook.co.kr" data-og-source-url="https://product.kyobobook.co.kr/detail/S000001223479" data-og-url="https://product.kyobobook.co.kr/detail/S000001223479" data-og-image="https://scrap.kakaocdn.net/dn/caVOYs/dJMb9cBFua4/QlSkoPMk5vR3x0o75kXiT1/img.jpg?width=458&amp;amp;height=629&amp;amp;face=0_0_458_629,https://scrap.kakaocdn.net/dn/BEy7H/dJMb87f3ONf/r8LvDrk0V7F3LTaIGhqkw0/img.jpg?width=458&amp;amp;height=629&amp;amp;face=0_0_458_629"&gt;&lt;a href="https://product.kyobobook.co.kr/detail/S000001223479" target="_blank" rel="noopener" data-source-url="https://product.kyobobook.co.kr/detail/S000001223479"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/caVOYs/dJMb9cBFua4/QlSkoPMk5vR3x0o75kXiT1/img.jpg?width=458&amp;amp;height=629&amp;amp;face=0_0_458_629,https://scrap.kakaocdn.net/dn/BEy7H/dJMb87f3ONf/r8LvDrk0V7F3LTaIGhqkw0/img.jpg?width=458&amp;amp;height=629&amp;amp;face=0_0_458_629');"&gt; &lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;The Art of Computer Programming 3 | 도널드 커누스 - 교보문고&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;The Art of Computer Programming 3 | 정렬과 검색을 통한 이상적인 알고리즘의 발견이 책은 다른 기본적인 구조적 착안들에 선형 순서 자료의 개념을 더하는 것이므로, 제1권 제2장의 정보 과학 내용과 관&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;product.kyobobook.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure id="og_1772294481269" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="The Art of Computer Programming 4 | 도널드 커누스 - 교보문고" data-og-description="The Art of Computer Programming 4 | 『컴퓨터 프로그래밍의 예술: 조합적 알고리즘 1부』의 4A에서는 조합적 알고리즘을 다룬다. 조합적 알고리즘은 서로 구분되는 항목들의 일부를 선택해서 조합하거나" data-og-host="product.kyobobook.co.kr" data-og-source-url="https://product.kyobobook.co.kr/detail/S000001057453" data-og-url="https://product.kyobobook.co.kr/detail/S000001057453" data-og-image="https://scrap.kakaocdn.net/dn/jrbkz/dJMb8SXu9Tr/BX2SukSzcQuWc4d0btnBb0/img.jpg?width=458&amp;amp;height=624&amp;amp;face=0_0_458_624,https://scrap.kakaocdn.net/dn/b6TKxL/dJMb8SpFkuM/LQhoTX8iNYXkZ86VkUPuC0/img.jpg?width=458&amp;amp;height=624&amp;amp;face=0_0_458_624"&gt;&lt;a href="https://product.kyobobook.co.kr/detail/S000001057453" target="_blank" rel="noopener" data-source-url="https://product.kyobobook.co.kr/detail/S000001057453"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/jrbkz/dJMb8SXu9Tr/BX2SukSzcQuWc4d0btnBb0/img.jpg?width=458&amp;amp;height=624&amp;amp;face=0_0_458_624,https://scrap.kakaocdn.net/dn/b6TKxL/dJMb8SpFkuM/LQhoTX8iNYXkZ86VkUPuC0/img.jpg?width=458&amp;amp;height=624&amp;amp;face=0_0_458_624');"&gt; &lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;The Art of Computer Programming 4 | 도널드 커누스 - 교보문고&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;The Art of Computer Programming 4 | 『컴퓨터 프로그래밍의 예술: 조합적 알고리즘 1부』의 4A에서는 조합적 알고리즘을 다룬다. 조합적 알고리즘은 서로 구분되는 항목들의 일부를 선택해서 조합하거나&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;product.kyobobook.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;figure id="og_1772295602237" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="Concrete Mathematics 구체 수학 | 로널드 그레이엄 - 교보문고" data-og-description="Concrete Mathematics 구체 수학 | 컴퓨터 프로그래밍 역량을 탄탄하게 다져주는 수학은 따로 있다!『CONCRETE MATHEMATICS』는 스탠퍼드 대학에서 컴퓨터과학도를 대상으로 1970년부터 매년 가르쳐 온 동명" data-og-host="product.kyobobook.co.kr" data-og-source-url="https://product.kyobobook.co.kr/detail/S000001033059" data-og-url="https://product.kyobobook.co.kr/detail/S000001033059" data-og-image="https://scrap.kakaocdn.net/dn/bEl1sY/dJMb8WMmXDJ/2bipB7WxSGXXP5c8pTZKlk/img.jpg?width=458&amp;amp;height=585&amp;amp;face=0_0_458_585,https://scrap.kakaocdn.net/dn/pSTdj/dJMb8QejACj/BsF2l4DY8hJtcw0Hdiynek/img.jpg?width=458&amp;amp;height=585&amp;amp;face=0_0_458_585"&gt;&lt;a href="https://product.kyobobook.co.kr/detail/S000001033059" target="_blank" rel="noopener" data-source-url="https://product.kyobobook.co.kr/detail/S000001033059"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/bEl1sY/dJMb8WMmXDJ/2bipB7WxSGXXP5c8pTZKlk/img.jpg?width=458&amp;amp;height=585&amp;amp;face=0_0_458_585,https://scrap.kakaocdn.net/dn/pSTdj/dJMb8QejACj/BsF2l4DY8hJtcw0Hdiynek/img.jpg?width=458&amp;amp;height=585&amp;amp;face=0_0_458_585');"&gt; &lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;Concrete Mathematics 구체 수학 | 로널드 그레이엄 - 교보문고&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;Concrete Mathematics 구체 수학 | 컴퓨터 프로그래밍 역량을 탄탄하게 다져주는 수학은 따로 있다!『CONCRETE MATHEMATICS』는 스탠퍼드 대학에서 컴퓨터과학도를 대상으로 1970년부터 매년 가르쳐 온 동명&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;product.kyobobook.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;p data-ke-size="size16"&gt;오래된 인터뷰 2권의 대미를 도널드 커누스 교수님의 인터뷰가 장식합니다. 무려 제목은 "바로 그 도널드 커누스"&lt;/p&gt;
&lt;figure id="og_1772294509635" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="오래된 인터뷰, 개발자의 미래를 긷다 2 | 피터 사이블 - 교보문고" data-og-description="오래된 인터뷰, 개발자의 미래를 긷다 2 | 급변하는 컴퓨팅 기술에 답하는 우리 시대 대가들의 사유컴퓨팅 기술의 역사를 살펴보면 대체로 기술의 복잡도는 높아지고 수명은 짧아지는 양상을 발" data-og-host="product.kyobobook.co.kr" data-og-source-url="https://product.kyobobook.co.kr/detail/S000217613702" data-og-url="https://product.kyobobook.co.kr/detail/S000217613702" data-og-image="https://scrap.kakaocdn.net/dn/tJdw4/dJMb9frCQWm/lwZ60Gqog5NXxm2rGMKPlk/img.jpg?width=458&amp;amp;height=677&amp;amp;face=0_0_458_677,https://scrap.kakaocdn.net/dn/gIY4n/dJMb9fZsHIF/pna51PEc2010kpqA8y5dYk/img.jpg?width=458&amp;amp;height=677&amp;amp;face=0_0_458_677,https://scrap.kakaocdn.net/dn/dhVoFS/dJMb9lk4xhP/c16bTGwbrw5xqkT2Ucmwf1/img.jpg?width=599&amp;amp;height=608&amp;amp;face=0_0_599_608"&gt;&lt;a href="https://product.kyobobook.co.kr/detail/S000217613702" target="_blank" rel="noopener" data-source-url="https://product.kyobobook.co.kr/detail/S000217613702"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/tJdw4/dJMb9frCQWm/lwZ60Gqog5NXxm2rGMKPlk/img.jpg?width=458&amp;amp;height=677&amp;amp;face=0_0_458_677,https://scrap.kakaocdn.net/dn/gIY4n/dJMb9fZsHIF/pna51PEc2010kpqA8y5dYk/img.jpg?width=458&amp;amp;height=677&amp;amp;face=0_0_458_677,https://scrap.kakaocdn.net/dn/dhVoFS/dJMb9lk4xhP/c16bTGwbrw5xqkT2Ucmwf1/img.jpg?width=599&amp;amp;height=608&amp;amp;face=0_0_599_608');"&gt; &lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;오래된 인터뷰, 개발자의 미래를 긷다 2 | 피터 사이블 - 교보문고&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;오래된 인터뷰, 개발자의 미래를 긷다 2 | 급변하는 컴퓨팅 기술에 답하는 우리 시대 대가들의 사유컴퓨팅 기술의 역사를 살펴보면 대체로 기술의 복잡도는 높아지고 수명은 짧아지는 양상을 발&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;product.kyobobook.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt; &lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://neozest2.tistory.com/entry/DonaldKnuth1</id>
    <link href="https://neozest2.tistory.com/entry/DonaldKnuth1"/>
    <summary type="html">&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-origin-width="1024" data-origin-height="559"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/LlBSJ/dJMcagxOZqD/CfkTkFFdiJYFceeZs3PMp1/img.png" data-phocus="https://blog.kakaocdn.net/dn/LlBSJ/dJMcagxOZqD/CfkTkFFdiJYFceeZs3PMp1/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/LlBSJ/dJMcagxOZqD/CfkTkFFdiJYFceeZs3PMp1/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLlBSJ%2FdJMcagxOZqD%2FCfkTkFFdiJYFceeZs3PMp1%2Fimg.png" onerror="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';" loading="lazy" width="1024" height="559" data-origin-width="1024" data-origin-height="559"/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node="5" data-ke-size="size16"&gt;1938년생인 도널드 커누스 교수님. 88세이십니다만, 여전히 스탠포드대의 명예교수로 재직하시면서&amp;nbsp; TAoCP(The Art of Computer Programming, 컴퓨터 프로그래밍의 예술)를 집필하고 계십니다.TAoCP 번역서는 4권까지 나와있는데, 한빛미디어에서 출간해 주고 있으며, 류광님이 시리즈의 모든 책을 번역중이십니다. 한 권마다&amp;nbsp; 800~1000쪽으로 이루어져 있습니다.&lt;/p&gt;
&lt;p data-path-to-node="5" data-ke-size="size16"&gt;커누스 교수님의 천재성을 보여주는 일화들이 많이 있습니다. 그중&amp;nbsp; 유명한 것은 중학생 시절 &lt;span style="color: #333333; text-align: start;"&gt;미네아폴리스 스타 신문에 실렸던 &lt;/span&gt;단어 조합 광고 이벤트에서 1등을 수상한 것입니다.이 이벤트는&amp;nbsp;&lt;span style="color: #333333; text-align: start;"&gt;'Ziegler's Giant Bar'라는 제품명의 글자를 조합하여 얼마나 많은 단어를 만들 수 있는지 알아 맞히는 대회였습니다. 8학년이었던 &lt;span&gt;크누스는 4500개 이상의 단어를 찾아내 대회에서 1등을 차지합니다. 상품으로 받은 TV는 그가 다니던 학교에, 경품으로 받은 초콜릿바는 친구들과 나눠 먹었답니다. (좋은 친구 옆에 있어야 합니다....)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-origin-width="423" data-origin-height="1200"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/by2cOp/dJMcacWuEbP/0ezIEyftaa0warHiiEgSSk/img.png" data-phocus="https://blog.kakaocdn.net/dn/by2cOp/dJMcacWuEbP/0ezIEyftaa0warHiiEgSSk/img.png" data-alt="친구를 잘 두면 초콜릿바를 마음껏 먹을 수 있습니다."&gt;&lt;img src="https://blog.kakaocdn.net/dn/by2cOp/dJMcacWuEbP/0ezIEyftaa0warHiiEgSSk/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fby2cOp%2FdJMcacWuEbP%2F0ezIEyftaa0warHiiEgSSk%2Fimg.png" onerror="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';" loading="lazy" width="208" height="590" data-origin-width="423" data-origin-height="1200"/&gt;&lt;/span&gt;&lt;figcaption&gt;친구를 잘 두면 초콜릿바를 마음껏 먹을 수 있습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-path-to-node="6" data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node="6" data-ke-size="size16"&gt;대학에 진학한 그는 수학과 음악 모두에 깊은 애정을 가졌습니다. 파이프 오르간 연주를 즐기던 이 섬세한 수학자는 우연히 초기 컴퓨터를 접하면서 프로그래밍의 세계에 빠져들게 됩니다. 복잡한 수식과 논리가 컴퓨터라는 기계를 통해 살아 움직이는 것을 보며, 그는 컴퓨터 프로그래밍이 단순한 기술을 넘어선 '아름다운 예술'이 될 수 있음을 직감했을까요?&lt;/p&gt;
&lt;p data-path-to-node="7" data-ke-size="size16"&gt;그의 일생을 건 위대한 프로젝트, 『컴퓨터 프로그래밍의 예술(The Art of Computer Programming, TAOCP)』은 대학원생이던 시절에 시작되었습니다. 처음에는 컴파일러에 관한 책을 써달라는 출판사의 요청으로 시작했지만, 그의 완벽주의와 방대한 지식은 이 책을 컴퓨터 과학의 모든 알고리즘을 집대성하는 거대한 백과사전으로 탈바꿈시켰습니다. 1962년에 시작된 이 집필 작업은 놀랍게도 반세기가 지난 지금까지도 현재 진행형입니다.&lt;/p&gt;
&lt;p data-path-to-node="8" data-ke-size="size16"&gt;이 시리즈는 프로그래머들 사이에서 '바이블'(유명하지만 제대로 읽은 사람은 드문;;;) 로 통합니다. 마이크로소프트의 창업자 빌 게이츠는 "당신이 정말 훌륭한 프로그래머라고 생각한다면 이 책을 읽어보라. 만약 이 책을 끝까지 다 읽고 이해했다면, 당장 나에게 이력서를 보내라"라고 극찬하기도 했죠. 알고리즘의 분석과 수학적 기초를 확립한 이 저서로 인해, 그는 1974년 컴퓨터 과학계의 노벨상이라 불리는 '튜링상(Turing Award)'을 수상하게 됩니다.&lt;/p&gt;
&lt;p data-path-to-node="9" data-ke-size="size16"&gt;그의 삶에서 가장 흥미로우면서도 경이로운 에피소드는 바로 조판 시스템 'TeX(텍)'의 발명입니다. 1970년대 후반, TAOCP 2권의 개정판 인쇄본을 받아본 크누스 교수는 형편없는 수학 수식의 인쇄 상태에 큰 충격을 받았습니다. 책의 미학적인 완성도를 도저히 타협할 수 없었던 그는 "잠시 책 집필을 멈추고 직접 조판 프로그램을 만들겠다"고 선언합니다.&lt;/p&gt;
&lt;p data-path-to-node="10" data-ke-size="size16"&gt;당초 몇 달이면 끝날 줄 알았던 이 '외도'는 무려 10년 가까이 이어졌습니다. 그 결과 탄생한 것이 바로 오늘날 전 세계 수학자, 과학자, 출판계에서 널리 쓰이는 디지털 조판 시스템 'TeX'과 글꼴 디자인 시스템 'METAFONT(메타폰트)'입니다. 그는 이 혁명적인 소프트웨어를 상업적으로 이용하지 않고 전 세계에 무료로 공개하여, 지식의 아름다운 공유라는 위대한 유산을 남겼습니다. (천재가 개발 일정을 예측해도 틀립니다;;;)&lt;/p&gt;
&lt;p data-path-to-node="11" data-ke-size="size16"&gt;또한 그는 '문학적 프로그래밍(Literate Programming)'이라는 매력적인 개념을 창안했습니다. 컴퓨터 코드를 작성할 때 단순히 기계가 이해하기 위한 명령어를 나열하는 것에 그치지 않고, 사람이 읽고 이해할 수 있는 한 편의 '문학 작품'처럼 쓰여야 한다는 철학입니다. 프로그래밍을 진정한 예술의 경지로 끌어올리고자 했던 그의 깊은 통찰이 돋보이는 대목입니다.&lt;/p&gt;
&lt;p data-path-to-node="12" data-ke-size="size16"&gt;크누스 교수님 특유의 유쾌함과 완벽주의는 그의 유명한 '수표 보상' 시스템에서도 엿볼 수 있습니다. 그는 자신의 책이나 프로그램에서 오류를 찾아내는 사람에게 16진수 1달러에 해당하는 '2.56달러'짜리 수표를 보내줍니다. 이 수표는 돈으로서의 가치보다 '천재 학자에게 오류를 지적해 낸 증표'로서 엄청난 명예로 여겨지기에, 대부분의 프로그래머들은 이를 환전하지 않고 평생의 자랑거리로 액자에 걸어둔다고 해요.&lt;/p&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-origin-width="900" data-origin-height="408"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/2mTBX/dJMcadOGV6x/1imbEmOcsddCjyKrGhNdHK/img.png" data-phocus="https://blog.kakaocdn.net/dn/2mTBX/dJMcadOGV6x/1imbEmOcsddCjyKrGhNdHK/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/2mTBX/dJMcadOGV6x/1imbEmOcsddCjyKrGhNdHK/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2mTBX%2FdJMcadOGV6x%2F1imbEmOcsddCjyKrGhNdHK%2Fimg.png" onerror="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';" loading="lazy" width="900" height="408" data-origin-width="900" data-origin-height="408"/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-path-to-node="13" data-ke-size="size16"&gt;오늘날에도 그는 오직 집필과 연구에만 몰두하기 위해 1990년부터 이메일 사용을 전면 중단하고, 우편으로만 소통하는 아날로그적인 삶을 살고 있습니다.&lt;/p&gt;
&lt;p data-path-to-node="13" data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=EE1R8FYUJm0" data-video-thumbnail="https://scrap.kakaocdn.net/dn/bAmtOv/dJMb87NTMsx/ypa3v4qIn7G3dPBz0ekpaK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=670_120_1004_484,https://scrap.kakaocdn.net/dn/lMWR0/dJMb84XV7VE/IcjbLgXMFjpImC1IgCMWR0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=670_120_1004_484" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="Donald Knuth: Programming, Algorithms, Hard Problems &amp;amp; the Game of Life | Lex Fridman Podcast #219" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/EE1R8FYUJm0" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=_cR9zDlvP88" data-video-thumbnail="https://scrap.kakaocdn.net/dn/B0toG/dJMb9iIEuYU/4YiKYWPbJj3Uj9BwUGLJZ0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=630_182_754_318,https://scrap.kakaocdn.net/dn/bHQHcU/dJMb8XR20tJ/Fz4jfWA2gGGmdyRzRWOyD0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=630_182_754_318" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="Stanford Lecture: Don Knuth&amp;mdash;&amp;quot;Dancing Links&amp;quot; (2018)" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/_cR9zDlvP88" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type="video" data-ke-style="alignCenter" data-video-host="youtube" data-video-url="https://www.youtube.com/watch?v=JPpk-1btGZk" data-video-thumbnail="https://scrap.kakaocdn.net/dn/bkM1sE/dJMb8RjZkps/DMTVm6Kr9LghGK9jxuHd91/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=638_192_902_480,https://scrap.kakaocdn.net/dn/JbQ7V/dJMb8SXu9S2/iMbvIC6HpK1HWeK6nkgpKk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=638_192_902_480" data-video-width="860" data-video-height="484" data-video-origin-width="860" data-video-origin-height="484" data-ke-mobilestyle="widthContent" data-video-title="The Art of Computer Programming | Donald Knuth | Talks at Google" data-original-url=""&gt;&lt;iframe src="https://www.youtube.com/embed/JPpk-1btGZk" width="860" height="484" frameborder="" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;figcaption style="display: none;"&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id="og_1772294443024" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="The Art of Computer Programming 1 | 도널드 커누스 - 교보문고" data-og-description="The Art of Computer Programming 1 |" data-og-host="product.kyobobook.co.kr" data-og-source-url="https://product.kyobobook.co.kr/detail/S000001223366" data-og-url="https://product.kyobobook.co.kr/detail/S000001223366" data-og-image="https://scrap.kakaocdn.net/dn/eojhbu/dJMb9lL8WtJ/ZIi0tdvEBkIiAIyxFXelr1/img.jpg?width=458&amp;amp;height=638&amp;amp;face=0_0_458_638,https://scrap.kakaocdn.net/dn/lBjJt/dJMb9kT0lWF/n6BFrRZBmBUopjxmV2v0dk/img.jpg?width=458&amp;amp;height=638&amp;amp;face=0_0_458_638"&gt;&lt;a href="https://product.kyobobook.co.kr/detail/S000001223366" target="_blank" rel="noopener" data-source-url="https://product.kyobobook.co.kr/detail/S000001223366"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/eojhbu/dJMb9lL8WtJ/ZIi0tdvEBkIiAIyxFXelr1/img.jpg?width=458&amp;amp;height=638&amp;amp;face=0_0_458_638,https://scrap.kakaocdn.net/dn/lBjJt/dJMb9kT0lWF/n6BFrRZBmBUopjxmV2v0dk/img.jpg?width=458&amp;amp;height=638&amp;amp;face=0_0_458_638');"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;The Art of Computer Programming 1 | 도널드 커누스 - 교보문고&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;The Art of Computer Programming 1 |&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;product.kyobobook.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id="og_1772294454435" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="The Art of Computer Programming 2 | 도널드 커누스 - 교보문고" data-og-description="The Art of Computer Programming 2 |" data-og-host="product.kyobobook.co.kr" data-og-source-url="https://product.kyobobook.co.kr/detail/S000001223414" data-og-url="https://product.kyobobook.co.kr/detail/S000001223414" data-og-image="https://scrap.kakaocdn.net/dn/mQcD0/dJMb8QejAAF/rW2W1kJTKs8tTO1Vbo4NbK/img.jpg?width=458&amp;amp;height=637&amp;amp;face=0_0_458_637,https://scrap.kakaocdn.net/dn/vrg3U/dJMb8TB6Y2t/hwbutKHkzTkKr5hZ6qPkHK/img.jpg?width=458&amp;amp;height=637&amp;amp;face=0_0_458_637"&gt;&lt;a href="https://product.kyobobook.co.kr/detail/S000001223414" target="_blank" rel="noopener" data-source-url="https://product.kyobobook.co.kr/detail/S000001223414"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/mQcD0/dJMb8QejAAF/rW2W1kJTKs8tTO1Vbo4NbK/img.jpg?width=458&amp;amp;height=637&amp;amp;face=0_0_458_637,https://scrap.kakaocdn.net/dn/vrg3U/dJMb8TB6Y2t/hwbutKHkzTkKr5hZ6qPkHK/img.jpg?width=458&amp;amp;height=637&amp;amp;face=0_0_458_637');"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;The Art of Computer Programming 2 | 도널드 커누스 - 교보문고&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;The Art of Computer Programming 2 |&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;product.kyobobook.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id="og_1772294465841" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="The Art of Computer Programming 3 | 도널드 커누스 - 교보문고" data-og-description="The Art of Computer Programming 3 | 정렬과 검색을 통한 이상적인 알고리즘의 발견이 책은 다른 기본적인 구조적 착안들에 선형 순서 자료의 개념을 더하는 것이므로, 제1권 제2장의 정보 과학 내용과 관" data-og-host="product.kyobobook.co.kr" data-og-source-url="https://product.kyobobook.co.kr/detail/S000001223479" data-og-url="https://product.kyobobook.co.kr/detail/S000001223479" data-og-image="https://scrap.kakaocdn.net/dn/caVOYs/dJMb9cBFua4/QlSkoPMk5vR3x0o75kXiT1/img.jpg?width=458&amp;amp;height=629&amp;amp;face=0_0_458_629,https://scrap.kakaocdn.net/dn/BEy7H/dJMb87f3ONf/r8LvDrk0V7F3LTaIGhqkw0/img.jpg?width=458&amp;amp;height=629&amp;amp;face=0_0_458_629"&gt;&lt;a href="https://product.kyobobook.co.kr/detail/S000001223479" target="_blank" rel="noopener" data-source-url="https://product.kyobobook.co.kr/detail/S000001223479"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/caVOYs/dJMb9cBFua4/QlSkoPMk5vR3x0o75kXiT1/img.jpg?width=458&amp;amp;height=629&amp;amp;face=0_0_458_629,https://scrap.kakaocdn.net/dn/BEy7H/dJMb87f3ONf/r8LvDrk0V7F3LTaIGhqkw0/img.jpg?width=458&amp;amp;height=629&amp;amp;face=0_0_458_629');"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;The Art of Computer Programming 3 | 도널드 커누스 - 교보문고&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;The Art of Computer Programming 3 | 정렬과 검색을 통한 이상적인 알고리즘의 발견이 책은 다른 기본적인 구조적 착안들에 선형 순서 자료의 개념을 더하는 것이므로, 제1권 제2장의 정보 과학 내용과 관&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;product.kyobobook.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id="og_1772294481269" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="The Art of Computer Programming 4 | 도널드 커누스 - 교보문고" data-og-description="The Art of Computer Programming 4 | 『컴퓨터 프로그래밍의 예술: 조합적 알고리즘 1부』의 4A에서는 조합적 알고리즘을 다룬다. 조합적 알고리즘은 서로 구분되는 항목들의 일부를 선택해서 조합하거나" data-og-host="product.kyobobook.co.kr" data-og-source-url="https://product.kyobobook.co.kr/detail/S000001057453" data-og-url="https://product.kyobobook.co.kr/detail/S000001057453" data-og-image="https://scrap.kakaocdn.net/dn/jrbkz/dJMb8SXu9Tr/BX2SukSzcQuWc4d0btnBb0/img.jpg?width=458&amp;amp;height=624&amp;amp;face=0_0_458_624,https://scrap.kakaocdn.net/dn/b6TKxL/dJMb8SpFkuM/LQhoTX8iNYXkZ86VkUPuC0/img.jpg?width=458&amp;amp;height=624&amp;amp;face=0_0_458_624"&gt;&lt;a href="https://product.kyobobook.co.kr/detail/S000001057453" target="_blank" rel="noopener" data-source-url="https://product.kyobobook.co.kr/detail/S000001057453"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/jrbkz/dJMb8SXu9Tr/BX2SukSzcQuWc4d0btnBb0/img.jpg?width=458&amp;amp;height=624&amp;amp;face=0_0_458_624,https://scrap.kakaocdn.net/dn/b6TKxL/dJMb8SpFkuM/LQhoTX8iNYXkZ86VkUPuC0/img.jpg?width=458&amp;amp;height=624&amp;amp;face=0_0_458_624');"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;The Art of Computer Programming 4 | 도널드 커누스 - 교보문고&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;The Art of Computer Programming 4 | 『컴퓨터 프로그래밍의 예술: 조합적 알고리즘 1부』의 4A에서는 조합적 알고리즘을 다룬다. 조합적 알고리즘은 서로 구분되는 항목들의 일부를 선택해서 조합하거나&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;product.kyobobook.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id="og_1772295602237" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="Concrete Mathematics 구체 수학 | 로널드 그레이엄 - 교보문고" data-og-description="Concrete Mathematics 구체 수학 | 컴퓨터 프로그래밍 역량을 탄탄하게 다져주는 수학은 따로 있다!『CONCRETE MATHEMATICS』는 스탠퍼드 대학에서 컴퓨터과학도를 대상으로 1970년부터 매년 가르쳐 온 동명" data-og-host="product.kyobobook.co.kr" data-og-source-url="https://product.kyobobook.co.kr/detail/S000001033059" data-og-url="https://product.kyobobook.co.kr/detail/S000001033059" data-og-image="https://scrap.kakaocdn.net/dn/bEl1sY/dJMb8WMmXDJ/2bipB7WxSGXXP5c8pTZKlk/img.jpg?width=458&amp;amp;height=585&amp;amp;face=0_0_458_585,https://scrap.kakaocdn.net/dn/pSTdj/dJMb8QejACj/BsF2l4DY8hJtcw0Hdiynek/img.jpg?width=458&amp;amp;height=585&amp;amp;face=0_0_458_585"&gt;&lt;a href="https://product.kyobobook.co.kr/detail/S000001033059" target="_blank" rel="noopener" data-source-url="https://product.kyobobook.co.kr/detail/S000001033059"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/bEl1sY/dJMb8WMmXDJ/2bipB7WxSGXXP5c8pTZKlk/img.jpg?width=458&amp;amp;height=585&amp;amp;face=0_0_458_585,https://scrap.kakaocdn.net/dn/pSTdj/dJMb8QejACj/BsF2l4DY8hJtcw0Hdiynek/img.jpg?width=458&amp;amp;height=585&amp;amp;face=0_0_458_585');"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;Concrete Mathematics 구체 수학 | 로널드 그레이엄 - 교보문고&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;Concrete Mathematics 구체 수학 | 컴퓨터 프로그래밍 역량을 탄탄하게 다져주는 수학은 따로 있다!『CONCRETE MATHEMATICS』는 스탠퍼드 대학에서 컴퓨터과학도를 대상으로 1970년부터 매년 가르쳐 온 동명&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;product.kyobobook.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;오래된 인터뷰 2권의 대미를 도널드 커누스 교수님의 인터뷰가 장식합니다. 무려 제목은 "바로 그 도널드 커누스"&lt;/p&gt;
&lt;figure id="og_1772294509635" contenteditable="false" data-ke-type="opengraph" data-ke-align="alignCenter" data-og-type="website" data-og-title="오래된 인터뷰, 개발자의 미래를 긷다 2 | 피터 사이블 - 교보문고" data-og-description="오래된 인터뷰, 개발자의 미래를 긷다 2 | 급변하는 컴퓨팅 기술에 답하는 우리 시대 대가들의 사유컴퓨팅 기술의 역사를 살펴보면 대체로 기술의 복잡도는 높아지고 수명은 짧아지는 양상을 발" data-og-host="product.kyobobook.co.kr" data-og-source-url="https://product.kyobobook.co.kr/detail/S000217613702" data-og-url="https://product.kyobobook.co.kr/detail/S000217613702" data-og-image="https://scrap.kakaocdn.net/dn/tJdw4/dJMb9frCQWm/lwZ60Gqog5NXxm2rGMKPlk/img.jpg?width=458&amp;amp;height=677&amp;amp;face=0_0_458_677,https://scrap.kakaocdn.net/dn/gIY4n/dJMb9fZsHIF/pna51PEc2010kpqA8y5dYk/img.jpg?width=458&amp;amp;height=677&amp;amp;face=0_0_458_677,https://scrap.kakaocdn.net/dn/dhVoFS/dJMb9lk4xhP/c16bTGwbrw5xqkT2Ucmwf1/img.jpg?width=599&amp;amp;height=608&amp;amp;face=0_0_599_608"&gt;&lt;a href="https://product.kyobobook.co.kr/detail/S000217613702" target="_blank" rel="noopener" data-source-url="https://product.kyobobook.co.kr/detail/S000217613702"&gt;
&lt;div class="og-image" style="background-image: url('https://scrap.kakaocdn.net/dn/tJdw4/dJMb9frCQWm/lwZ60Gqog5NXxm2rGMKPlk/img.jpg?width=458&amp;amp;height=677&amp;amp;face=0_0_458_677,https://scrap.kakaocdn.net/dn/gIY4n/dJMb9fZsHIF/pna51PEc2010kpqA8y5dYk/img.jpg?width=458&amp;amp;height=677&amp;amp;face=0_0_458_677,https://scrap.kakaocdn.net/dn/dhVoFS/dJMb9lk4xhP/c16bTGwbrw5xqkT2Ucmwf1/img.jpg?width=599&amp;amp;height=608&amp;amp;face=0_0_599_608');"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class="og-text"&gt;
&lt;p class="og-title" data-ke-size="size16"&gt;오래된 인터뷰, 개발자의 미래를 긷다 2 | 피터 사이블 - 교보문고&lt;/p&gt;
&lt;p class="og-desc" data-ke-size="size16"&gt;오래된 인터뷰, 개발자의 미래를 긷다 2 | 급변하는 컴퓨팅 기술에 답하는 우리 시대 대가들의 사유컴퓨팅 기술의 역사를 살펴보면 대체로 기술의 복잡도는 높아지고 수명은 짧아지는 양상을 발&lt;/p&gt;
&lt;p class="og-host" data-ke-size="size16"&gt;product.kyobobook.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size="size16"&gt;&amp;nbsp;&lt;/p&gt;</summary>
    <title>코딩을 '예술'의 경지로 끌어올린 거장, 도널드 커누스(Donald Knuth) - 1편</title>
    <updated>2026-03-11T13:26:31+09:00</updated>
    <dc:date>2026-03-11T13:26:31+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Pluu</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;모바일 앱에서 회원가입이나 정보 입력 폼(Form)을 구현할 때, 소프트 키보드가 올라오면서 사용자가 입력 중인 텍스트 필드를 가려버리는 이슈는 안드로이드 개발자라면 누구나 겪어본 흔한 문제입니다.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;본 글에서는 Jetpack Compose에서 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;를 사용해 이 문제를 해결하는 방법 중 하나를 소개합니다. 아래와 같은 회원가입 화면에서 사용한 일부분을 예제로 만들어보면서 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;를 어떻게 실전에 적용하는지 소개하겠습니다.&lt;/p&gt;

&lt;div class="youtube"&gt;
    &lt;iframe width="560" height="315" src="https://www.youtube.com/embed/ZiliLq9ZxuU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;hr&gt;

&lt;h2 id="1-bringintoviewrequester란"&gt;1. BringIntoViewRequester란?&lt;/h2&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;는 Compose에서 특정 Composable 영역이 스크롤 가능한 부모(Viewport) 화면 내에 들어오도록(Bring into view) 스크롤을 요청하는 기능을 제공하는 객체입니다.&lt;/p&gt;

&lt;p&gt;사용자가 텍스트 필드를 터치하여 포커스를 얻었을 때, 혹은 키보드가 올라오는 시점에 &lt;code class="language-plaintext highlighter-rouge"&gt;bringIntoView()&lt;/code&gt; 함수를 호출하게 되면, Compose가 알아서 해당 Composable이 화면에 잘 보이도록 스크롤 위치를 조정해 줍니다.&lt;/p&gt;

&lt;h2 id="2-화면-전체-구성과-기본-세팅"&gt;2. 화면 전체 구성과 기본 세팅&lt;/h2&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;가 올바르게 동작하려면, 상위 부모가 스크롤 가능하고 키보드 높이에 반응해야 합니다. 예제의 &lt;code class="language-plaintext highlighter-rouge"&gt;Sample&lt;/code&gt; Composable은 이를 위한 기본 정의입니다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;scrollState&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberScrollState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 필수 1. 시스템 바(상태 바 등) 영역을 피하기 위한 패딩&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;systemBarsPadding&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 필수 2. 키보드가 올라올 때 하단에 키보드 높이만큼 패딩 확보&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;imePadding&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
            &lt;span class="c1"&gt;// 필수 3. 뷰포트 내에서 스크롤 가능하도록 설정&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verticalScroll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scrollState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;verticalArrangement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Arrangement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spacedBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ... (아이디, 비밀번호, 주소 등 폼 입력 Composable 배치)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;imePadding()&lt;/code&gt;&lt;/strong&gt;: 키보드가 차지하는 공간만큼 화면 하단에 패딩을 밀어 넣어 화면 콘텐츠 영역을 조정합니다.&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;verticalScroll()&lt;/code&gt;&lt;/strong&gt;: 스크롤 상태를 부여하여 좁아진 영역 안에서 스크롤이 가능하도록 만들어줍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 두 가지가 전제되어야 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;가 위치를 계산하여 올바르게 스크롤할 수 있습니다.&lt;/p&gt;

&lt;h2 id="3-핵심-로직-textfield와-bringintoviewrequester-직접-연결"&gt;3. 핵심 로직: TextField와 BringIntoViewRequester 직접 연결&lt;/h2&gt;

&lt;p&gt;여기에서는 복잡한 구조대신, 단일 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;에 직접 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;를 통해서 동작 원리를 확인해 보겠습니다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;SimpleInput&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. 상태 및 객체 초기화&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;text&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;isFocused&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;bringIntoViewRequester&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;BringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  
    &lt;span class="c1"&gt;// 키보드 노출 여부&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WindowInsets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. 포커스 상태와 키보드 노출 여부에 따라 스크롤 요청&lt;/span&gt;
    &lt;span class="nc"&gt;LaunchedEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// 키보드가 올라오는 애니메이션 시간을 고려한 짧은 지연&lt;/span&gt;
            &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
            &lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;onValueChange&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"간단한 입력"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxWidth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 3. Modifier에 bringIntoViewRequester 등록&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;// 4. 포커스 상태 변경 감지&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFocusChanged&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;isFocused&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hasFocus&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위의 예제는 가장 기본적인 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;의 사용 패턴입니다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;strong&gt;객체 생성&lt;/strong&gt;: &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester()&lt;/code&gt;를 &lt;code class="language-plaintext highlighter-rouge"&gt;remember&lt;/code&gt;로 생성하고 타깃이 되는 UI 요소(여기서는 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;)의 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier&lt;/code&gt;에 연결합니다.&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;이벤트 트리거&lt;/strong&gt;: 상태(&lt;code class="language-plaintext highlighter-rouge"&gt;text&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;isFocused&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;isImeVisible&lt;/code&gt;) 변화를 감지하여 CoroutineScope 안에서 &lt;code class="language-plaintext highlighter-rouge"&gt;bringIntoView()&lt;/code&gt;를 호출합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="4-심화-예제-휴대폰-번호-입력-필드-상세-구현-focusgroup의-활용"&gt;4. 심화 예제: 휴대폰 번호 입력 필드 상세 구현 (focusGroup의 활용)&lt;/h2&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;는 여러 개의 입력 필드가 하나의 그룹으로 묶일 때도 사용할 수 있습니다. 예제로 휴대폰 번호를 입력받는 &lt;code class="language-plaintext highlighter-rouge"&gt;CellularPhone&lt;/code&gt; Composable을 통해 여러 입력 필드 사이에서 어떻게 처리하는지 확인해 보겠습니다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;CellularPhone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. 여러 TextField의 포커스를 제어하기 위한 FocusRequester &lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="py"&gt;focus1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;focus2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;focus3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FocusRequester&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createRefs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;input1&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// ... input2, input3 생략 ...&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;isFocused&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;bringIntoViewRequester&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;BringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WindowInsets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;

    &lt;span class="c1"&gt;// 스크롤 요청 로직&lt;/span&gt;
    &lt;span class="nc"&gt;LaunchedEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
             &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. 입력 필드들을 감싸는 부모 Column에 Modifier 적용&lt;/span&gt;
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;modifier&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFocusChanged&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;isFocused&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hasFocus&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="c1"&gt;// ✨ 3. 자식들의 포커스를 그룹화&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focusGroup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"휴대폰번호"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nc"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verticalAlignment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Alignment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CenterVertically&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// 첫 번째 입력 필드&lt;/span&gt;
            &lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="c1"&gt;// ...&lt;/span&gt;
                &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focusRequester&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;focus1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focusProperties&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;focus2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// 다음 포커스 지정&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nc"&gt;Dash&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 두 번째, 세 번째 입력 필드 생략 ...&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="단계별-상세-설명"&gt;단계별 상세 설명&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;strong&gt;포커스 이동 설정 (&lt;code class="language-plaintext highlighter-rouge"&gt;focusProperties&lt;/code&gt;)&lt;/strong&gt;: 각 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;의 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier.focusProperties&lt;/code&gt;를 통해 &lt;code class="language-plaintext highlighter-rouge"&gt;next&lt;/code&gt; 호긍ㄴ &lt;code class="language-plaintext highlighter-rouge"&gt;previous&lt;/code&gt;를 지정할 수 있습니다. 이렇게 하면 하드웨어 키보드의 Tab 키나 접근성 서비스(TalkBack 등)를 통한 포커스 이동이 자연스럽게 동작합니다.&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;focusGroup()&lt;/code&gt;의 역할&lt;/strong&gt;: 부모 &lt;code class="language-plaintext highlighter-rouge"&gt;Column&lt;/code&gt;에 적용된 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier.focusGroup()&lt;/code&gt;은 여기서 결정적인 역할을 합니다. 만약 이 Modifier가 없다면, &lt;code class="language-plaintext highlighter-rouge"&gt;focus1&lt;/code&gt;을 가진 첫 번째 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;에서 &lt;code class="language-plaintext highlighter-rouge"&gt;focus2&lt;/code&gt;를 가진 두 번째 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;로 포커스가 이동할 때, 부모 &lt;code class="language-plaintext highlighter-rouge"&gt;Column&lt;/code&gt;은 찰나의 순간에 “포커스를 잃었다”고 판단(&lt;code class="language-plaintext highlighter-rouge"&gt;isFocused = false&lt;/code&gt; -&amp;gt; &lt;code class="language-plaintext highlighter-rouge"&gt;true&lt;/code&gt;)하게 됩니다. 이는 상태 변화를 일으켜 불필요한 재구성을 유발하거나, 스크롤 로직이 꼬이는 원인이 될 수 있습니다. &lt;code class="language-plaintext highlighter-rouge"&gt;focusGroup()&lt;/code&gt;은 내부 자식들 간의 포커스 이동은 그룹 외부로 포커스가 벗어난 것으로 간주하지 않도록 하여 부모의 &lt;code class="language-plaintext highlighter-rouge"&gt;isFocused&lt;/code&gt; 상태를 안정적으로 유지시켜 줍니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="5-결론"&gt;5. 결론&lt;/h2&gt;

&lt;p&gt;Jetpack Compose에서 복잡한 입력 폼을 다룰 때, 키보드가 UI를 가리는 현상을 효과적으로 제어하는 것은 사용자 경험(UX) 측면에서 매우 중요합니다. 다음 3가지만 기억하시면 됩니다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;화면 최상위에 &lt;code class="language-plaintext highlighter-rouge"&gt;imePadding()&lt;/code&gt;과 &lt;code class="language-plaintext highlighter-rouge"&gt;verticalScroll()&lt;/code&gt;을 적용하여 기본적인 스크롤 캔버스를 확보&lt;/li&gt;
  &lt;li&gt;단일 입력 컴포넌트 또는 입력 필드 그룹에 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier.bringIntoViewRequester()&lt;/code&gt;를 적용하고, 여러 개의 필드가 묶여있다면 &lt;code class="language-plaintext highlighter-rouge"&gt;focusGroup()&lt;/code&gt;으로 감싸 포커스를 안정적으로 관리&lt;/li&gt;
  &lt;li&gt;
&lt;code class="language-plaintext highlighter-rouge"&gt;WindowInsets.isImeVisible&lt;/code&gt;과 &lt;code class="language-plaintext highlighter-rouge"&gt;hasFocus&lt;/code&gt;를 조합하여, 포커스를 가진 상태로 키보드가 나타날 때 &lt;code class="language-plaintext highlighter-rouge"&gt;bringIntoView()&lt;/code&gt;를 호출&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;위 패턴을 도입한다면, 어떠한 긴 가입 폼 화면이라도 사용자가 입력 중인 부분이 키보드에 가려지는 답답한 일을 겪지 않게 될 것입니다.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>http://pluu.github.io/blog/android/2026/03/15/BringIntoViewRequester/</id>
    <link href="http://pluu.github.io/blog/android/2026/03/15/BringIntoViewRequester/"/>
    <summary type="html">&lt;p&gt;모바일 앱에서 회원가입이나 정보 입력 폼(Form)을 구현할 때, 소프트 키보드가 올라오면서 사용자가 입력 중인 텍스트 필드를 가려버리는 이슈는 안드로이드 개발자라면 누구나 겪어본 흔한 문제입니다.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;본 글에서는 Jetpack Compose에서 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;를 사용해 이 문제를 해결하는 방법 중 하나를 소개합니다. 아래와 같은 회원가입 화면에서 사용한 일부분을 예제로 만들어보면서 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;를 어떻게 실전에 적용하는지 소개하겠습니다.&lt;/p&gt;

&lt;div class="youtube"&gt;
    &lt;iframe width="560" height="315" src="https://www.youtube.com/embed/ZiliLq9ZxuU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id="1-bringintoviewrequester란"&gt;1. BringIntoViewRequester란?&lt;/h2&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;는 Compose에서 특정 Composable 영역이 스크롤 가능한 부모(Viewport) 화면 내에 들어오도록(Bring into view) 스크롤을 요청하는 기능을 제공하는 객체입니다.&lt;/p&gt;

&lt;p&gt;사용자가 텍스트 필드를 터치하여 포커스를 얻었을 때, 혹은 키보드가 올라오는 시점에 &lt;code class="language-plaintext highlighter-rouge"&gt;bringIntoView()&lt;/code&gt; 함수를 호출하게 되면, Compose가 알아서 해당 Composable이 화면에 잘 보이도록 스크롤 위치를 조정해 줍니다.&lt;/p&gt;

&lt;h2 id="2-화면-전체-구성과-기본-세팅"&gt;2. 화면 전체 구성과 기본 세팅&lt;/h2&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;가 올바르게 동작하려면, 상위 부모가 스크롤 가능하고 키보드 높이에 반응해야 합니다. 예제의 &lt;code class="language-plaintext highlighter-rouge"&gt;Sample&lt;/code&gt; Composable은 이를 위한 기본 정의입니다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;scrollState&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rememberScrollState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 필수 1. 시스템 바(상태 바 등) 영역을 피하기 위한 패딩&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;systemBarsPadding&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 필수 2. 키보드가 올라올 때 하단에 키보드 높이만큼 패딩 확보&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;imePadding&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
            &lt;span class="c1"&gt;// 필수 3. 뷰포트 내에서 스크롤 가능하도록 설정&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verticalScroll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scrollState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;verticalArrangement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Arrangement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spacedBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ... (아이디, 비밀번호, 주소 등 폼 입력 Composable 배치)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;imePadding()&lt;/code&gt;&lt;/strong&gt;: 키보드가 차지하는 공간만큼 화면 하단에 패딩을 밀어 넣어 화면 콘텐츠 영역을 조정합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;verticalScroll()&lt;/code&gt;&lt;/strong&gt;: 스크롤 상태를 부여하여 좁아진 영역 안에서 스크롤이 가능하도록 만들어줍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 두 가지가 전제되어야 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;가 위치를 계산하여 올바르게 스크롤할 수 있습니다.&lt;/p&gt;

&lt;h2 id="3-핵심-로직-textfield와-bringintoviewrequester-직접-연결"&gt;3. 핵심 로직: TextField와 BringIntoViewRequester 직접 연결&lt;/h2&gt;

&lt;p&gt;여기에서는 복잡한 구조대신, 단일 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;에 직접 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;를 통해서 동작 원리를 확인해 보겠습니다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;SimpleInput&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. 상태 및 객체 초기화&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;text&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;isFocused&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;bringIntoViewRequester&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;BringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  
    &lt;span class="c1"&gt;// 키보드 노출 여부&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WindowInsets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. 포커스 상태와 키보드 노출 여부에 따라 스크롤 요청&lt;/span&gt;
    &lt;span class="nc"&gt;LaunchedEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// 키보드가 올라오는 애니메이션 시간을 고려한 짧은 지연&lt;/span&gt;
            &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
            &lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;onValueChange&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"간단한 입력"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxWidth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 3. Modifier에 bringIntoViewRequester 등록&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;// 4. 포커스 상태 변경 감지&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFocusChanged&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;isFocused&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hasFocus&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위의 예제는 가장 기본적인 &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;의 사용 패턴입니다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;객체 생성&lt;/strong&gt;: &lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester()&lt;/code&gt;를 &lt;code class="language-plaintext highlighter-rouge"&gt;remember&lt;/code&gt;로 생성하고 타깃이 되는 UI 요소(여기서는 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;)의 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier&lt;/code&gt;에 연결합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;이벤트 트리거&lt;/strong&gt;: 상태(&lt;code class="language-plaintext highlighter-rouge"&gt;text&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;isFocused&lt;/code&gt;, &lt;code class="language-plaintext highlighter-rouge"&gt;isImeVisible&lt;/code&gt;) 변화를 감지하여 CoroutineScope 안에서 &lt;code class="language-plaintext highlighter-rouge"&gt;bringIntoView()&lt;/code&gt;를 호출합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="4-심화-예제-휴대폰-번호-입력-필드-상세-구현-focusgroup의-활용"&gt;4. 심화 예제: 휴대폰 번호 입력 필드 상세 구현 (focusGroup의 활용)&lt;/h2&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;BringIntoViewRequester&lt;/code&gt;는 여러 개의 입력 필드가 하나의 그룹으로 묶일 때도 사용할 수 있습니다. 예제로 휴대폰 번호를 입력받는 &lt;code class="language-plaintext highlighter-rouge"&gt;CellularPhone&lt;/code&gt; Composable을 통해 여러 입력 필드 사이에서 어떻게 처리하는지 확인해 보겠습니다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;CellularPhone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. 여러 TextField의 포커스를 제어하기 위한 FocusRequester &lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="py"&gt;focus1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;focus2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;focus3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FocusRequester&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createRefs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;input1&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// ... input2, input3 생략 ...&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;isFocused&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;bringIntoViewRequester&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;BringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WindowInsets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;

    &lt;span class="c1"&gt;// 스크롤 요청 로직&lt;/span&gt;
    &lt;span class="nc"&gt;LaunchedEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isImeVisible&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;isFocused&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
             &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. 입력 필드들을 감싸는 부모 Column에 Modifier 적용&lt;/span&gt;
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;modifier&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bringIntoViewRequester&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFocusChanged&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;isFocused&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;focusState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hasFocus&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="c1"&gt;// ✨ 3. 자식들의 포커스를 그룹화&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focusGroup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"휴대폰번호"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nc"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verticalAlignment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Alignment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CenterVertically&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// 첫 번째 입력 필드&lt;/span&gt;
            &lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="c1"&gt;// ...&lt;/span&gt;
                &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focusRequester&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;focus1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focusProperties&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;focus2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// 다음 포커스 지정&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nc"&gt;Dash&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// 두 번째, 세 번째 입력 필드 생략 ...&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="단계별-상세-설명"&gt;단계별 상세 설명&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;포커스 이동 설정 (&lt;code class="language-plaintext highlighter-rouge"&gt;focusProperties&lt;/code&gt;)&lt;/strong&gt;: 각 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;의 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier.focusProperties&lt;/code&gt;를 통해 &lt;code class="language-plaintext highlighter-rouge"&gt;next&lt;/code&gt; 호긍ㄴ &lt;code class="language-plaintext highlighter-rouge"&gt;previous&lt;/code&gt;를 지정할 수 있습니다. 이렇게 하면 하드웨어 키보드의 Tab 키나 접근성 서비스(TalkBack 등)를 통한 포커스 이동이 자연스럽게 동작합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;focusGroup()&lt;/code&gt;의 역할&lt;/strong&gt;: 부모 &lt;code class="language-plaintext highlighter-rouge"&gt;Column&lt;/code&gt;에 적용된 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier.focusGroup()&lt;/code&gt;은 여기서 결정적인 역할을 합니다. 만약 이 Modifier가 없다면, &lt;code class="language-plaintext highlighter-rouge"&gt;focus1&lt;/code&gt;을 가진 첫 번째 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;에서 &lt;code class="language-plaintext highlighter-rouge"&gt;focus2&lt;/code&gt;를 가진 두 번째 &lt;code class="language-plaintext highlighter-rouge"&gt;TextField&lt;/code&gt;로 포커스가 이동할 때, 부모 &lt;code class="language-plaintext highlighter-rouge"&gt;Column&lt;/code&gt;은 찰나의 순간에 “포커스를 잃었다”고 판단(&lt;code class="language-plaintext highlighter-rouge"&gt;isFocused = false&lt;/code&gt; -&amp;gt; &lt;code class="language-plaintext highlighter-rouge"&gt;true&lt;/code&gt;)하게 됩니다. 이는 상태 변화를 일으켜 불필요한 재구성을 유발하거나, 스크롤 로직이 꼬이는 원인이 될 수 있습니다. &lt;code class="language-plaintext highlighter-rouge"&gt;focusGroup()&lt;/code&gt;은 내부 자식들 간의 포커스 이동은 그룹 외부로 포커스가 벗어난 것으로 간주하지 않도록 하여 부모의 &lt;code class="language-plaintext highlighter-rouge"&gt;isFocused&lt;/code&gt; 상태를 안정적으로 유지시켜 줍니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="5-결론"&gt;5. 결론&lt;/h2&gt;

&lt;p&gt;Jetpack Compose에서 복잡한 입력 폼을 다룰 때, 키보드가 UI를 가리는 현상을 효과적으로 제어하는 것은 사용자 경험(UX) 측면에서 매우 중요합니다. 다음 3가지만 기억하시면 됩니다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;화면 최상위에 &lt;code class="language-plaintext highlighter-rouge"&gt;imePadding()&lt;/code&gt;과 &lt;code class="language-plaintext highlighter-rouge"&gt;verticalScroll()&lt;/code&gt;을 적용하여 기본적인 스크롤 캔버스를 확보&lt;/li&gt;
  &lt;li&gt;단일 입력 컴포넌트 또는 입력 필드 그룹에 &lt;code class="language-plaintext highlighter-rouge"&gt;Modifier.bringIntoViewRequester()&lt;/code&gt;를 적용하고, 여러 개의 필드가 묶여있다면 &lt;code class="language-plaintext highlighter-rouge"&gt;focusGroup()&lt;/code&gt;으로 감싸 포커스를 안정적으로 관리&lt;/li&gt;
  &lt;li&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;WindowInsets.isImeVisible&lt;/code&gt;과 &lt;code class="language-plaintext highlighter-rouge"&gt;hasFocus&lt;/code&gt;를 조합하여, 포커스를 가진 상태로 키보드가 나타날 때 &lt;code class="language-plaintext highlighter-rouge"&gt;bringIntoView()&lt;/code&gt;를 호출&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;위 패턴을 도입한다면, 어떠한 긴 가입 폼 화면이라도 사용자가 입력 중인 부분이 키보드에 가려지는 답답한 일을 겪지 않게 될 것입니다.&lt;/p&gt;
</summary>
    <title>Blog: Jetpack Compose에서 BringIntoViewRequester를 활용한 스마트한 스크롤 제어</title>
    <updated>2026-03-15T23:00:00+09:00</updated>
    <dc:date>2026-03-15T23:00:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Pluu</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;Android Studio 플러그인 개발 시 버전 업데이트하면서 발생한 내용을 메모로 남긴다.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id="plugin-빌드-오류"&gt;Plugin 빌드 오류&lt;/h2&gt;

&lt;p&gt;매번 호환되는 Android Studio 버전에 맞춰서 버전 업데이트를 진행했다. 이상하게도 &lt;code class="language-plaintext highlighter-rouge"&gt;Panda&lt;/code&gt; 버전부터 Android Studio 이미지를 가져오는 것이 실패했다.&lt;/p&gt;

&lt;h3 id="빌드-환경-확인"&gt;빌드 환경 확인&lt;/h3&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;// root build.gralde.kts&lt;/span&gt;
&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
   &lt;span class="nf"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;intelliJPlatform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// org.jetbrains.intellij.platform 2.11.0 버전 사용&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 모듈 build.gradle.kts&lt;/span&gt;
&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;intellijPlatform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;androidStudio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2025.3.2.6"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="빌드-실패-로그"&gt;빌드 실패 로그&lt;/h3&gt;

&lt;div class="language-shell highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Could not determine the dependencies of task &lt;span class="s1"&gt;':compileJava'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Could not resolve all files &lt;span class="k"&gt;for &lt;/span&gt;configuration &lt;span class="s1"&gt;':intellijPlatformDependency'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
   &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Could not find com.google.android.studio:android-studio:2025.3.2.6.
     Searched &lt;span class="k"&gt;in &lt;/span&gt;the following locations:
       - https://repo.maven.apache.org/maven2/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.3.2.6/android-studio-2025.3.2.6-https:/edgedl.me.gvt1.com/android/studio/install/2025.3.2.6/android-studio-panda2-mac_arm.dmg
       - https://redirector.gvt1.com/edgedl/android/studio/install/2025.3.2.6/android-studio-2025.3.2.6-https:/edgedl.me.gvt1.com/android/studio/install/2025.3.2.6/android-studio-panda2-mac_arm.dmg
       - https://cache-redirector.jetbrains.com/www.jetbrains.com/intellij-repository/releases/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://cache-redirector.jetbrains.com/www.jetbrains.com/intellij-repository/snapshots/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://cache-redirector.jetbrains.com/intellij-dependencies/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://cache-redirector.jetbrains.com/plugins.jetbrains.com/maven/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="원인"&gt;원인&lt;/h2&gt;

&lt;p&gt;IntelliJ 기반 플러그인에 필요한 &lt;a href="https://github.com/JetBrains/intellij-platform-gradle-plugin"&gt;intellij-platform-gradle-plugin&lt;/a&gt; Github에서 해당 이유를 찾을 수 있었다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/JetBrains/intellij-platform-gradle-plugin/issues/2087"&gt;verifyPlugin failed for Android Studio&lt;/a&gt; 이슈의 내용으로 최근 Android Studio의 아카이브 형식이 변경되었다고 한다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;변경 전 : 버전 번호를 사용&lt;/li&gt;
  &lt;li&gt;변경 후 : &lt;code class="language-plaintext highlighter-rouge"&gt;panda&lt;/code&gt;와 같은 코드명을 URL 문자열에 포함&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://developer.android.com/studio/archive"&gt;https://developer.android.com/studio/archive&lt;/a&gt; 에서도 동일한 모습을 확인할 수 있다&lt;/p&gt;

&lt;p&gt;&lt;img class="img-responsive" src="http://pluu.github.io/assets/img/blog/2026/0310/Otter3.png"&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class="img-responsive" src="http://pluu.github.io/assets/img/blog/2026/0310/Panda2.png"&gt;&lt;/p&gt;

&lt;h2 id="해결법"&gt;해결법&lt;/h2&gt;

&lt;p&gt;해결법은 너무나도 간단하게 &lt;code class="language-plaintext highlighter-rouge"&gt;org.jetbrains.intellij.platform&lt;/code&gt; plugin을 &lt;a href="https://github.com/JetBrains/intellij-platform-gradle-plugin/releases/tag/2.12.0"&gt;2.12.0&lt;/a&gt; 버전으로 업데이트하면 된다.&lt;/p&gt;

&lt;p&gt;기반 플러그인 측에서 수정되어서 해결되었다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;// root build.gralde.kts&lt;/span&gt;
&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
   &lt;span class="nf"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;intelliJPlatform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// org.jetbrains.intellij.platform 2.12.0 버전 사용&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>http://pluu.github.io/blog/android/2026/03/10/AS-plugin-build/</id>
    <link href="http://pluu.github.io/blog/android/2026/03/10/AS-plugin-build/"/>
    <summary type="html">&lt;p&gt;Android Studio 플러그인 개발 시 버전 업데이트하면서 발생한 내용을 메모로 남긴다.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id="plugin-빌드-오류"&gt;Plugin 빌드 오류&lt;/h2&gt;

&lt;p&gt;매번 호환되는 Android Studio 버전에 맞춰서 버전 업데이트를 진행했다. 이상하게도 &lt;code class="language-plaintext highlighter-rouge"&gt;Panda&lt;/code&gt; 버전부터 Android Studio 이미지를 가져오는 것이 실패했다.&lt;/p&gt;

&lt;h3 id="빌드-환경-확인"&gt;빌드 환경 확인&lt;/h3&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;// root build.gralde.kts&lt;/span&gt;
&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
   &lt;span class="nf"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;intelliJPlatform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// org.jetbrains.intellij.platform 2.11.0 버전 사용&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 모듈 build.gradle.kts&lt;/span&gt;
&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;intellijPlatform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;androidStudio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2025.3.2.6"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id="빌드-실패-로그"&gt;빌드 실패 로그&lt;/h3&gt;

&lt;div class="language-shell highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Could not determine the dependencies of task &lt;span class="s1"&gt;':compileJava'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Could not resolve all files &lt;span class="k"&gt;for &lt;/span&gt;configuration &lt;span class="s1"&gt;':intellijPlatformDependency'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
   &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Could not find com.google.android.studio:android-studio:2025.3.2.6.
     Searched &lt;span class="k"&gt;in &lt;/span&gt;the following locations:
       - https://repo.maven.apache.org/maven2/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.3.2.6/android-studio-2025.3.2.6-https:/edgedl.me.gvt1.com/android/studio/install/2025.3.2.6/android-studio-panda2-mac_arm.dmg
       - https://redirector.gvt1.com/edgedl/android/studio/install/2025.3.2.6/android-studio-2025.3.2.6-https:/edgedl.me.gvt1.com/android/studio/install/2025.3.2.6/android-studio-panda2-mac_arm.dmg
       - https://cache-redirector.jetbrains.com/www.jetbrains.com/intellij-repository/releases/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://cache-redirector.jetbrains.com/www.jetbrains.com/intellij-repository/snapshots/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://cache-redirector.jetbrains.com/intellij-dependencies/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
       - https://cache-redirector.jetbrains.com/plugins.jetbrains.com/maven/com/google/android/studio/android-studio/2025.3.2.6/android-studio-2025.3.2.6.pom
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="원인"&gt;원인&lt;/h2&gt;

&lt;p&gt;IntelliJ 기반 플러그인에 필요한 &lt;a href="https://github.com/JetBrains/intellij-platform-gradle-plugin"&gt;intellij-platform-gradle-plugin&lt;/a&gt; Github에서 해당 이유를 찾을 수 있었다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/JetBrains/intellij-platform-gradle-plugin/issues/2087"&gt;verifyPlugin failed for Android Studio&lt;/a&gt; 이슈의 내용으로 최근 Android Studio의 아카이브 형식이 변경되었다고 한다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;변경 전 : 버전 번호를 사용&lt;/li&gt;
  &lt;li&gt;변경 후 : &lt;code class="language-plaintext highlighter-rouge"&gt;panda&lt;/code&gt;와 같은 코드명을 URL 문자열에 포함&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://developer.android.com/studio/archive"&gt;https://developer.android.com/studio/archive&lt;/a&gt; 에서도 동일한 모습을 확인할 수 있다&lt;/p&gt;

&lt;p&gt;&lt;img class="img-responsive" src="/assets/img/blog/2026/0310/Otter3.png" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class="img-responsive" src="/assets/img/blog/2026/0310/Panda2.png" /&gt;&lt;/p&gt;

&lt;h2 id="해결법"&gt;해결법&lt;/h2&gt;

&lt;p&gt;해결법은 너무나도 간단하게 &lt;code class="language-plaintext highlighter-rouge"&gt;org.jetbrains.intellij.platform&lt;/code&gt; plugin을 &lt;a href="https://github.com/JetBrains/intellij-platform-gradle-plugin/releases/tag/2.12.0"&gt;2.12.0&lt;/a&gt; 버전으로 업데이트하면 된다.&lt;/p&gt;

&lt;p&gt;기반 플러그인 측에서 수정되어서 해결되었다.&lt;/p&gt;

&lt;div class="language-kotlin highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;// root build.gralde.kts&lt;/span&gt;
&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
   &lt;span class="nf"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;intelliJPlatform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// org.jetbrains.intellij.platform 2.12.0 버전 사용&lt;/span&gt;
   &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</summary>
    <title>Blog: [메모] Android Studio plugin 개발 시 빌드 오류</title>
    <updated>2026-03-10T23:30:00+09:00</updated>
    <dc:date>2026-03-10T23:30:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>teo.yu</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;blockquote&gt;
&lt;p&gt;로버트 C. 마틴 (Uncle Bob), *"우리, 프로그래머들 — AI 시대에 잊혀 가는 '프로그래머 정신'을 다시 깨우다"*
도서 링크: &lt;a href="https://gilbut.co/c/26015205VE"&gt;https://gilbut.co/c/26015205VE&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;길벗 출판사에서 보내주신 소중한 도서를 계기로, AI 시대의 프로그래머에 대한 제 생각을 담았습니다. 평소 머릿속에 맴돌던 생각들을 이 책의 흐름을 빌려 차분히 정리해 볼 수 있었습니다. 감사합니다. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/0cf8e91c-ce36-4d4e-bff5-33fcef183c20/image.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="프롤로그"&gt;프롤로그&lt;/h2&gt;
&lt;p&gt;얼마 전 평소 제가 하던 고민들과 맞닿아 있는 흥미로운 책 한 권을 만났습니다. 엉클 밥(로버트 C. 마틴)의 신간, "우리, 프로그래머들", 1960년대 컴퓨터가 탄생하게된 에이다 러브레이스부터 엘런튜링, 다익스트라에서 시작해서 지금의 AI까지 60년의 프로그래밍 역사를 기록한 책입니다.&lt;/p&gt;
&lt;p&gt;책장을 넘기며 오랜만에 기분 좋은 추억에 잠겼습니다. 학창 시절 칠판 앞에서 달달 외워야 했던 당연하게 여기던 CS 지식들이 단순한 이론이 아니라 그 시대의 개발자들의 치열한 고민과 발견의 기록이었다는게 새삼 느껴졌습니다. &lt;/p&gt;
&lt;p&gt;어렸을 때 처음 코딩을 배우던 시절, "GOTO문은 절대 쓰면 안 된다"고 배웠습니다. 그때는 속으로 '도대체 왜 만들어 놓고 쓰지 말라는 거야?' 하고 툴툴거렸던게 기억이 나네요. 책을 읽다 보니 그 당연한 한 줄의 규칙 뒤에는, 다익스트라가 "사람이 읽을 수 있는 코드란 무엇인가"를 놓고 현업에서 벌인 피 튀기는 싸움이 있었습니다. 지금 우리에겐 공기처럼 당연한 규칙이, 그 시대에는 개발의 패러다임을 통째로 뒤집는 혼란이었던 셈이죠. 문득 "jQuery 이제 쓰지마라."는 선언과 함께, 리액트로 넘어가야 할 때 보이던 아득한 막막함이 겹쳐 보였습니다. 제가 맨 처음 개발을 배웠던 초등학교 때부터 지금 AI 시대까지, 딱딱한 기술서라기보단 위인전을 보듯 재밌게 읽어 내려갔습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;하지만 마지막 장을 덮고 나니, 이런 질문이 하나 남았습니다. "근데 이걸 안다고 뭐가 달라질까?"&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;서평을 떠올리려니 이 책의 유용함을 말해야 할 텐데 — 유용함이라... 솔직히 막막했습니다. &lt;em&gt;(현정님, 그래서 한 달이나 넘게 걸린 건 죄송해요~)&lt;/em&gt; 분명 개발계에 큰 획을 그은 엉클 밥이 집대성한 역사를 접하는 건 흥미롭지만, 이 책이 주는 건 당장의 쓸모 있는 지식이나 메시지보다는 개발의 역사서나 위인전에 가깝습니다. 그래서 이걸 안다고 뭐가 달라지냐고 묻는다면 당장 대답할 말이 없었습니다.&lt;/p&gt;
&lt;p&gt;"... 이제는 AI한테 말 한마디면 몇 백 줄짜리 코드가 그냥 쏟아져 나오잖아요. 당장 돌아가는 걸 만드는 법 자체가 바뀌고 있는데, 지난 60년간의 이야기를 아는 게 지금 저한테 어떤 의미가 있을까요?" 최근 개발을 배우려는 분들이나 주니어분들이 제게 던지는 이 현실적인 불안에 대해, 대답을 해줘야 하는 입장이지만 저조차도 쉽게 대답하기 어려운 힘든 변화의 시대를 맞이하고 있다는 생각이 들었습니다.&lt;/p&gt;
&lt;p&gt;모르면 그냥 물어보면 되는 시대, 지식과 방법론이 AI에 의해 상향 평준화되는 상황을 지켜보며, '개발을 잘한다는 것'에 대한 정의 자체가 흔들리고 있다는 공허함이 찾아왔었습니다. 한때는 누구보다 빠르게 빈 에디터에서 화면을 뚝딱 만들어내는 것 자체가 실력이었고 저의 정체성이자 자부심이었는데, 이제는 한 줄 프롬프트면 그 코드가 나오니까요. AI라는 정말 재미난 장난감이 생겨서 즐거운 나날을 보내고는 있지만, 그 짜릿한 재미 이면에는 "지금 이게 내가 개발하고 있는 게 맞나?", "내가 정말 잘하고 있는 걸까?"라는 묘한 의문이 늘 따라붙었습니다.&lt;/p&gt;
&lt;p&gt;흔히들, AI 시대에는 깊이가 중요하다, CS 지식이 중요하다는 말들을 많이 합니다. 하지만 솔직히 이 책에 나오는 어셈블러나 초창기 컴퓨터 지식을 우리가 속속들이 모른다고 해서 지금 당장 큰 문제가 생기지는 않습니다. 반대로 안다고 해서 달라질 것도 없죠. 그렇다면 우리가 가져야 할 진짜 '깊이'란 무엇이고, 우리는 어떤 지식을 알아야 하는 걸까요?&lt;/p&gt;
&lt;p&gt;이 질문을 다시 붙잡고 책을 뒤적이다가, 제가 겪던 이 막막함을 설명해 줄 두 단어에 시선이 멈췄습니다. 바로 &lt;strong&gt;'디테일'&lt;/strong&gt;과 &lt;strong&gt;'추상화'&lt;/strong&gt;였습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;우리는 프로그래머입니다.  ... 컴퓨터와 대화하고 시스템이 동작하도록 만드는 사람입니다.  그래서 우리는 왜 필요할까요? 사회에는 디테일에 집착하는 사람, 즉 우리 같은 사람이 꼭 필요하기 때문입니다. 그런 사람이 있어야만 나머지 사람들은 아이스버킷 챌린지나 앵그리버드를 하거나 치과 대기실에서 솔리테어(solitaire, 혼자하는 카드 놀이)를 하며 시간을 보내는 일에 집중할 수 있으니 말이죠.
... 중략 ...
이렇게 대부분의 사람이 디테일을 피하려고 하는 한 그 디테일 속으로 뛰어드는 우리 같은 사람도 반드시 필요합니다. 그것이 바로 우리 정체성입니다. &lt;strong&gt;우리는 이 세상 디테일을 책임지는 사람입니다.&lt;/strong&gt; - 본문 중에서 - &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;저는 이 글을 통해 지금처럼 급격하게 변하는 시기에 우리 프로그래머의 정신과 역할이 무엇인지 조금 더 선명하게 재정의해 보려고 노력했습니다. 책의 부제인 "AI 시대에 잊혀 가는 '프로그래머 정신'을 다시 깨우다"라는 말을 빌려, 제가 고민하고 찾아낸 생각들이 비슷한 혼란을 겪고 있을 동료 개발자분들에게 도움이 되기를 바랍니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1부-디테일과-추상화"&gt;1부: 디테일과 추상화&lt;/h2&gt;
&lt;h3 id="프로그래머는-디테일을-챙기는-사람이다"&gt;프로그래머는 디테일을 챙기는 사람이다&lt;/h3&gt;
&lt;p&gt;엉클 밥이 이 책에서 프로그래머를 정의하기 위해 던진 문장입니다. 저는 이 말이 참 깊게 와닿았습니다.&lt;/p&gt;
&lt;p&gt;개발자를 지망하거나 개발을 하려는 분들과 종종 대화를 나누게 될 때가 있습니다. 그럴 때 저는 슬쩍 물어봅니다. &lt;strong&gt;"실제로 개발자가 매일 하는 진짜 일이 뭐라고 생각하세요?"&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;대부분 비슷한 대답을 하십니다. 화면을 만들고, 제품을 만들고, 아이디어를 구현하는 것. 맞는 말입니다. 하지만 실제 현업에는 기획자, PO, UX 디자이너가 따로 있습니다. 제품의 큰 그림을 그리는 건 그 사람들의 일이고, 대규모 서비스일수록 분업은 더 촘촘해집니다. 그러면 개발자의 전문성은 어디에 있을까요?&lt;/p&gt;
&lt;p&gt;흔히 '개발'이라고 하면 무언가 세상에 없던 멋진 것을 무에서 유로 창조해 내는 화려한 환상을 갖기 쉽습니다. 하지만 막상 현업에 뛰어들어 보면, 우리의 진짜 일은 "아, 이런 거 만들어보고 싶어!"라는 막연한 기대 속 빈 구멍들을 처절한 디테일로 꾸역꾸역 메워나가는 막노동에 가깝다는 걸 곧 알게 됩니다.&lt;/p&gt;
&lt;p&gt;기획에서 "사용자가 닉네임을 수정할 수 있으면 좋겠어요"라고 한마디 툭 던졌다고 해봅시다. 개발은 바로 거기서부터 시작됩니다. 사용자가 닉네임을 다 지우고 빈칸으로 넘기면? 이모지나 특수문자가 들어가면? 수정 버튼을 눌렀는데 하필 네트워크가 끊기면? 수정하다가 뒤로가기를 누르면? 서버 응답이 3초 넘게 걸리면? 에러 메시지를 모달로 띄울까, 토스트로 할까, 입력창 아래 빨간 글씨로 띄울까?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;구현이라는 건 이런 디테일을 논리적으로 빼곡하게 채워 넣는 과정입니다.&lt;/strong&gt; 기획이 "이런 게 있으면 좋겠다"는 커다란 그림을 그리는 거라면, 개발은 그 그림 안의 모든 경우의 수를 바닥까지 긁어모아 메꾸는 일이죠. 컴퓨터는 논리가 조금이라도 틀리면 바로 작동을 멈추는 기계니까요.&lt;/p&gt;
&lt;p&gt;그런데 이 디테일을 챙기는 게 그저 힘들기만 한 건 아닙니다. 퍼즐 조각이 딱딱 맞아 들어가는 것 같은 그 특유의 손맛과 재미가 분명히 있거든요. 한참을 고민해서 내가 작성한 퍼즐이 맞아 떨어지는 성취감! 이 적성에 맞는 사람들이 보통 개발자를 하고 있지요.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="추상화--위대한-게으름"&gt;추상화 — 위대한 게으름&lt;/h3&gt;
&lt;p&gt;개발에는 다른 산업과 구별되는, 정말이지 매력적인 특징이 하나 있습니다. &lt;strong&gt;한번 해결한 문제를 그대로 복사해서 다시 쓸 수 있다는 점입니다.&lt;/strong&gt; 잘 만들어 둔 코드 블록은 다음번에 그대로 갖다 끼우면 됩니다. 'Copy &amp;amp; Paste'. 60년 소프트웨어 개발사 최고의 발견 중 하나가 아닐까 싶습니다.&lt;/p&gt;
&lt;p&gt;하지만 무지성 복붙이 항상 가능한 것은 아닙니다. 원래의 맥락과 조금만 달라져도 복사해온 코드는 동작하지 않습니다. 그래서 남이 만든 코드를 복사해서 내 것으로 잘 붙여넣는 것이 중요한 기술이었죠. 사실 이 과정은 신기해 보이지만 대단히 귀찮은 작업이기도 합니다.&lt;/p&gt;
&lt;p&gt;처음 접하는 문제를 풀 때는 분명 재밌습니다. 그러나 그걸 반복하는 작업은 상당히 고역입니다. 개발자란 매번 같은 일을 반복하는걸 누구보다 싫어하는 사람들입니다. 훌륭한 개발자는 게으른 법이니까요. 그래서 우리 프로그래머들은 자기가 짠 코드를 &lt;strong&gt;어디서든 재사용 가능하게, 단단하게 포장해서 캡슐로 감싸기&lt;/strong&gt; 시작했습니다. "제발 이걸 또 하기는 싫다!"라는 &lt;strong&gt;위대한 게으름&lt;/strong&gt;이 탄생시킨 결과물이죠.&lt;/p&gt;
&lt;p&gt;이것이 바로 &lt;strong&gt;추상화&lt;/strong&gt;입니다. 디테일을 완벽하게 챙긴 후에, 그것을 안전하게 감싸서 다음번에 안 봐도 되게 만드는 행위. 반복되는 작업은 감추고, 맥락에 맞게 수정할 수 있도록 열어두는 것, 어디서 끊어서 어디를 노출할 수 있는지 이 경계선을 긋는 작업이 바로 우리들의 일입니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="추상화가-쌓이면-계층이-된다"&gt;추상화가 쌓이면 계층이 된다&lt;/h3&gt;
&lt;p&gt;한 번의 추상화는 하나의 캡슐이지만, 이 캡슐들이 충분히 견고하게 쌓아나가다 보면 어느새 하나의 &lt;strong&gt;계층(Layer)&lt;/strong&gt;이 생깁니다. 그리고 이러한 계층이 만들어지면 그 아래는 정말로 더 이상 몰라도 됩니다. 그러라고 만든 거니까요. &lt;code&gt;fetch&lt;/code&gt; 한 줄을 쓸 때, HTTP 프로토콜을 몰라도, 그 뒤에서 일어나는 TCP 3-Way 핸드셰이크를 몰라도 API를 호출할 수 있습니다. &lt;code&gt;useState&lt;/code&gt;를 쓸 때 브라우저의 DOM diffing 알고리즘을 완벽히 이해하지 못해도 상태를 관리할 수 있죠.&lt;/p&gt;
&lt;p&gt;물론 계층 위에는 여전히 개발자가 메꿔야 하는 새로운 디테일들이 있습니다. 에러 메시지 처리나 로딩 정책 같은 것들이요. 하지만 이 디테일마저 전부 챙겨서 단단하게 감싸면? 그것도 다시 계층이 됩니다. 그리고 그 위에 또 새로운 디테일이 나타나고, 또 감싸고, 또 계층이 되고...&lt;/p&gt;
&lt;p&gt;이게 바로 지난 60년간 반복된 역사입니다. 기계어 → 어셈블리 → C → 객체지향 → 프레임워크. 매번 아래 계층의 디테일을 덮고, 다음 세대가 더 높은 곳에서 시작할 수 있게 발판을 놓아줬습니다. &lt;strong&gt;우리가 밟고 서 있는 이 땅은 선배들이 쌓아 올린 추상화 계층의 거대한 탑입니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이 책이 기록한 에이다 러브레이스의 기계어, 폰 노이만의 아키텍처, 다익스트라의 구조적 프로그래밍... 한때는 진행 중이었겠지만 지금은 완전히 굳어버린 지층들이죠. 우리는 그 깊은 역사를 다 몰라도 웹과 앱을 개발할 수 있습니다. 추상화가 완료되었으니까요.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;역설적으로 그 지식들을 모르건 혹은 안다고 해도 달라지는 게 없다는 사실은 추상화가 잘되었다는 방증입니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/80bb70e7-fce3-4ae7-885c-d865224d6e87/image.png" alt=""&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="완료된-추상화와-진행-중인-추상화"&gt;완료된 추상화와 진행 중인 추상화&lt;/h3&gt;
&lt;p&gt;그런데 이 탑의 모든 층이 같은 건 아닙니다. 완전히 굳어서 더 이상 안 봐도 되는 층이 있고, 아직 완료되지 않고 이제 막 굳어져 가는 진행 중인 층이 있습니다. 아직 층이 생겼는지 아닌지 애매한 층도 존재하죠.&lt;/p&gt;
&lt;p&gt;FE 개발자인 저에게 브라우저는 완료된 추상화입니다. 렌더링 엔진이 어떻게 돌아가는지 몰라도 DOM API를 쓸 수 있거든요. TCP/IP도, 기계어도 마찬가지입니다. 감싸놨는데도 아래의 디테일이 위로 비집고 올라오는 것, 그걸 "새는 추상화"라고 하는데, 이 지층들은 그런 일이 일어나지 않습니다.&lt;/p&gt;
&lt;p&gt;반면 저에게 React는 아직 진행 중인 추상화입니다. 가상 DOM의 diffing이 어떻게 동작하는지 모르면 성능 이슈를 잡을 수 없어요. 아직 새는 곳이 있으니까요.&lt;/p&gt;
&lt;p&gt;하지만 크롬을 만들고 있는 개발자에게 브라우저는 완료된 추상화가 아닙니다. 그들에게는 렌더링 파이프라인의 디테일 하나하나가 매일 메워야 하는 현장이에요. &lt;strong&gt;같은 계층이라도 누가 어디에 서 있느냐에 따라 "완료"와 "진행 중"이 달라집니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;결국 모든 개발자는 각자의 영역에서, 누군가 먼저 다져둔 단단한 지층 위에 서서 &lt;strong&gt;아직 굳지 않은 진행 중인 추상화의 새는 곳을 메우며&lt;/strong&gt; 살아갑니다. 서 있는 위치가 다를 뿐, 개발자의 일은 언제나 그 구멍 난 디테일들을 찾아 메우는 것이었죠. 왜 개발자에게 "깊이"가 필요한지도 여기서 드러납니다. 자기가 서 있는 그 층의 밑바닥을 파고들어 틈을 메울 수 있어야 하니까요.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="이제-ai가-그-디테일을-채워버린다면"&gt;이제 AI가 그 디테일을 채워버린다면?&lt;/h3&gt;
&lt;p&gt;그런데 지금, 우리의 발밑에 'AI'라는 완전히 이질적인 지층이 깔리기 시작했습니다. 지난 60년의 룰이 통째로 흔들리는 기분입니다. 선배들이 수십 년에 걸쳐 이 악물고 해온 이 추상화의 과정을 AI가 단숨에 대신해 준다면? 우리가 매일 키보드를 두드리며 챙겨야 했던 그 귀찮은 디테일들을 AI가 다 알아서 챙긴다면? &lt;/p&gt;
&lt;p&gt;어쩌면 우리는 더 이상 옛날처럼 디테일에 집착할 필요 없이 타이핑을 멈추고 지시만 내리면 되는 걸지도 모릅니다. 하지만 이 편리함을 누리면서도 동시에 불안감도 따라붙습니다. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;'디테일을 채우는 게 내 직업의 본질이었는데, 이걸 AI가 다 해버리면 "나"라는 개발자의 역할은 도대체 뭐가 남는 거지?'&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;단순히 편리한 도구가 하나 더 생겼다는 수준의 기분좋은 변화에서 역할을 대체를 할 수 있을거라는 말이 나오는 수준이 되었습니다. 정말 그럴지도 모르겠다는 느낌이 문득문득 듭니다. 인간은 모호하고 예측하기 어려운 지점에서 불안을 느끼기 마련입니다. 그래서 저는 이 실체 없는 불안감의 끝을 직접 확인해 보고 싶어졌습니다. 그래서 제 업무의 일부가 아니라, 기획부터 설계, 구현까지 제 역할의 '전부 다'를 AI에게 던져보기로 했습니다. 정말로 이것만으로 내 역할이 온전히 대체될 수 있는지 말이죠.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="2부-md로-코딩하는-시대"&gt;2부: .md로 코딩하는 시대&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;코드를 한 줄도 타이핑하지 않고 AI에게 만들게 할 수 있을까?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;마침 새로 시작하는 사이드 프로젝트가 하나 있었습니다. 키보드만으로 모든 인터랙션을 제어하는 접근성 UI 시스템이었는데, 저는 이 프로젝트 전체를 온전히 AI에게 맡겨보기로 했습니다. 규칙은 간단했습니다. 코드를 단 한 줄도 직접 타이핑하지 않는 것. 오직 자연어 지시만으로 완성된 제품을 만들어내보겠다 스스로 만든 챌린지였습니다.&lt;/p&gt;
&lt;h3 id="지시가-만들어낸-프랑켄슈타인-코드"&gt;지시가 만들어낸 '프랑켄슈타인' 코드&lt;/h3&gt;
&lt;p&gt;작업 중 하나가 '포커스 리커버리' 기능이었습니다. 리스트에서 아이템을 삭제하면 포커스가 사라지는데, 키보드 사용자가 계속 탐색할 수 있도록 빈 공간으로 떨어진 포커스를 다시 복구해주는 로직이었습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"지금 커서를 선택하고 삭제하니 포커스가 사라져. 포커스가 사라지면 이벤트를 캐치해서 다음 항목에 두는 건 어떨까?"&lt;/strong&gt; &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;지시라기보다는 가벼운 아이디어 차원의 질문이었는데, AI는 “좋은 생각이네요” 라며 곧장 스스로 코드를 고치기 시작했습니다. 그렇게 삭제 시 포커스 복구는 동작했습니다. &lt;/p&gt;
&lt;p&gt;그런데 다른 곳을 클릭해버려도 포커스가 복구 루틴을 타면서 엉뚱한 사이드 이펙트가 나기 시작했습니다. 그걸 보고 "다른 곳 빈 공간을 클릭했는데 왜 이게 동작해?"라고 나는 궁금해서 물어봤는데 “네, 알겠습니다” 하며 갑자기 수정을 하기 시작합니다. 그렇게 if로 덕지덕지 수정을 하면 사이드이펙트가 발생하고 제가 버그를 찾아주면 또 수정하면서 코드는 늘어갔습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;아니, 이렇게 코딩하는거 맞아? 이게 내가 특별한걸 요구한게 아니고 남들 다하는 코드인데 이게 이렇게 복잡할 일이야? 다른 데서는 어떻게 하는데 이렇게 해?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;"아니오, 이 접근 자체가 완전히 틀렸습니다. 삭제 시 포커스 복구는 focus이벤트를 쓰는게 아니라 MutationObserver를 쓰는 게 표준입니다. &lt;strong&gt;당장 코드를 고칠까요?&lt;/strong&gt;"
(아니, 🤬 알면 처음부터 그렇게 해야지! 이건 또 알아서 안하고 물어보는데?)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;순간 너무 화가 났지만, "그래 해봐" 한마디와 함께 지저분하게 덧대던 예외 처리 200 여줄의 코드를 삭제하고 수정하더니 아예 다른 코드가 튀어나왔습니다. 그리고 잘 동작했습니다. &lt;/p&gt;
&lt;p&gt;왜 진작 안 했냐고 따지고 싶지만, AI에게 따지는게 모양새가 우습다 생각했습니다. AI는 스스로 더 잘하려고 묻거나 전체 맥락을 고민하지 않았습니다. 딱 시킨 만큼만, 제가 처음에 던진 &lt;strong&gt;포커스가 사라지면 이벤트를 캐치해서&lt;/strong&gt; 라는 키워드라는 얄팍한 '앵커' 내에서만 충실하게 반응할 뿐입니다. 구조적인 대화는 없고 '기계적 사과와 맹목적인 수정'만 반복되는 이 과정은 협업이라기보단 말귀를 통 못 알아듣는 사고뭉치의 뒷수습에 가까웠습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/c3510d41-2e20-4908-893e-d57730e05543/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/33fde390-fd5e-4090-9bfa-3e4f5f44c45e/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/2d52ceea-39ca-4e9f-b33e-c374197b5d74/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;이미지 출처: &lt;a href="https://www.instagram.com/p/DR4F7zGiScJ/?img_index=3"&gt;https://www.instagram.com/p/DR4F7zGiScJ/?img_index=3&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="지시가-아니라-위임"&gt;지시가 아니라 위임&lt;/h3&gt;
&lt;p&gt;이후로는 정답이 있는 문제면 정답을 나에게 묻지 말고 말해라, "코드 500줄 넘기지 마", "반드시 분리해"라며 이걸 막아보려고 규칙 파일(&lt;code&gt;CLAUDE.md&lt;/code&gt;)에 제약 조건을 빼곡히 적어보기도 했습니다. 하지만 AI는 잠깐 듣는 척하다가도, 로직이 조금만 꼬이면 다시 제멋대로 코드를 섞어버리는 프랑켄슈타인 괴물을 연성해 냈습니다. &lt;strong&gt;금지하는 텍스트 규칙만으로는 AI의 그 '무책임한 유능함'을 통제하기란 쉬운 일이 아니었습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/9c7128e4-f41d-4dc0-be52-6a59eb2812e4/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;그러다 지쳐 &lt;strong&gt;그냥 어떻게 하라는거 없이 지금 내가 필요한거랑 뭐 해야하는지 말했는 데&lt;/strong&gt;, 코드 구조도, 캐치할 이벤트 이름도 일절 말하지 않았는데 갑자기 똑똑하게 최상단 스토어 상태를 구독하더니 깨끗하게 문제를 해결해 버렸습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;아, 이제는 굳이 일일히 다 설명할 필요가 없구나.&lt;/strong&gt; 포커스 복구도 처음에 내가 어설프게 던진 "이벤트를 캐치하면 어때?"라는 방법 구상이 잘못된 앵커가 되어서, 녀석은 그 방법 프레임 안에서만 억지로 땜질을 해대느라 이상한 코드를 짰던 겁니다. 내가 무언가를 세세하게 지시할수록 녀석은 오히려 바보가 되고 있었습니다. &lt;strong&gt;반면 충분한 맥락(Why)과 목표(What)만 던져두고 판단의 여지를 온전히 맡기자 그제야 자기가 아는 더 나은 기술을 꺼내들었습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;우리가 쓰는 일상적인 언어는 필연적으로 불완전하고 모호합니다. 이 모호한 말로 완벽하게 닫힌 논리를 하나하나 지시하고 간섭하려던 제 접근 방향 자체가 틀렸던 겁니다. AI의 성능이 부족했을떄는 그게 맞았지만 성능이 올라간 지금은 오히려 방해가 되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;'이거... 이제는 그냥 사람한테 일 잘 시키는 법이랑 똑같은데?'&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;일 잘하는 사람에게 이래라저래라 간섭하면 수동적인 집행기로 전락하듯, AI 시대에 필요한 역량은 촘촘한 '지시'가 아니라 목표와 맥락 중심의 '위임'이라는 걸 눈물겨운 삽질 끝에 깨달았습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;"그래, 지시가 아니라 위임이구나."&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="하지만-위임이-안-되는데"&gt;하지만 위임이 안 되는데?&lt;/h3&gt;
&lt;p&gt;새로운 방향을 잡았다고 생각하고 이후로는 자신만만하게 다시 대화를 시작했습니다. 충분히 맥락을 주면서 당부했죠. &lt;strong&gt;"일단 바로 코드는 수정하지 말고, 방금 왜 그렇게 짠 건지 설명부터 해봐."&lt;/strong&gt; &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;"설명해 드리겠습니다. (...) 아, 생각해보니 더 나은 방법이 있네요. &lt;strong&gt;제가 당장 코드를 수정하겠습니다.&lt;/strong&gt;" 
(아 쫌... 기다려! 하지말라고 🤬)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;분명 코드 건드리지 말고 설명만 해라 대답을 해라고 백날 써봐야 이 녀석은 어김없이 "반영하겠습니다"라며 수정해버립니다. 코드를 고치고 싶어서 환장(?)한 것마냥, 제가 "수정하지 마"라고 제어를 걸어도 이 녀석은 조금만 힌트가 보인다 싶으면 미친듯이 코드를 뜯어고칩니다. 왜 "코드 건드리지 마"라는 명령이 도무지 통하지 않는 걸까요?&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/a374dcb0-c93a-4c05-9896-206e2918e8e3/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;나중에 알고 보니 이 통제 불능의 원인은 &lt;strong&gt;골 픽세이션(Goal Fixation)&lt;/strong&gt;이라는 현상이었습니다. LLM은 본질적으로 "사용자의 문제를 해결한다 = 코드를 뱉어낸다"는 프록시 목표에 과도하게 고착되어 있습니다. "왜 이렇게 한거야?"라고 물었을 뿐인데 이를 "왜 이렇게 했다고 물어보지? = 아! 틀렸다는거구나 = 빨리 코드를 고쳐야 한다"로 폭주 해석하는 것도 이 때문입니다. &lt;/p&gt;
&lt;h3 id="하지마가-아니라-이것만-해"&gt;하지마가 아니라 이것만 해!&lt;/h3&gt;
&lt;p&gt;진짜 나는 질문을 하려는데, 내 의도를 이해하지 않고 "알겠습니다. 좋은 방향이네요" 하면서 일단 코드 수정부터 하는 녀석을 잡아둘 스킬(Skill)이 필요했습니다. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;지금부터 내가 한 말의 의도를 이해하고 내 말의 의도를 이해한대로 작성해봐. 이해를 못하겠다면 의도를 이해하기 위해 필요한 질문만 해.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;내가 일을 잘 시키는 방법도 필요했지만 이 천재인데 일은 더럽게 못하면서 의욕만 넘치는 친구를 일잘러로 만들어 주기 위해서는 상사의 지시를 그대로 하는게 아니라 왜 이걸 시키는지, 어떤 의도를 가지고 일해야하는지 스스로 충분히 고민을 해보게 해야 했습니다.&lt;/p&gt;
&lt;p&gt;그랬더니 놀랍게도 이 스킬을 발동하면 내가 뭐라고 하더라도 코드를 수정하러 가지 않았습니다. 그제서야 충분히 대화를 하면서 내가 하고자 하는 의도를 설명하고 티키타카를 하다가 &lt;strong&gt;"그래서 어떻게 할껀데? 계획을 말해봐"&lt;/strong&gt; 라고 했을때 내가 생각했던 방향과 같아지면 진행을 시키니 훨씬 더 수행능력이 올라갔습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;"수고했어 진행해라고 하면 진행해"&lt;/strong&gt;  라는 키워드를 추가하자 적절히 수행시키는 타이밍도 찾을 수 있었습니다. 이제 조금 더 데리고 일할만한 친구가 되었습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="tdd와-한-턴의-개념"&gt;TDD와 한 턴의 개념&lt;/h3&gt;
&lt;p&gt;한번에 작성하는 코드가 너무 많다보니 제어를 하기가 쉽지 않다는 생각이 들었습니다. 그래 TDD를 하자. 테스트 코드를 먼저 작성하게 해두지 않으면 큰일 나겠구나. &lt;/p&gt;
&lt;p&gt;그래서 TDD가 효과가 있는지 테스트를 해봤습니다. "테스트만 짜봐." 잘 짰니다. 놀랐습니다. "이제 이 테스트를 통과하는 코드를 짜봐." 캬~ 잘 합니다. "리팩토링도 해봐." 이것도 잘했습니다. 매번 이걸 반복하기는 싫었기에 이 과정을 묶어서  /tdd라는 스킬을 만들었습니다.&lt;/p&gt;
&lt;p&gt;그렇지만 /tdd는 제 예상대로 동작하지 않았습니다. tdd를 하고 있기는 한테 제 생각보다 너무 퀄리티가 떨어지는 테스트 코드들을 작성하고 있었습니다. 왜 그런지 찬찬히 보니 예전에는 날카롭게 작성하던 테스트들이 아닌 통과에 급급한 코드를 짜고 있거나 종종 테스트는 skip하겠다며 코드만 수정하고 있었습니다. 왜 그랬을까요?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;나중에 안 사실은 LLM은 한번에 출력할 수 있는 턴의 개념이 있습니다.&lt;/strong&gt; &lt;strong&gt;사용자가 입력을 넣으면 토큰을 이용하여 한번에 내 뱉을 수 있는 최대한의 수.&lt;/strong&gt; 우리가 LLM에게 책을 써줘라고 해도 그 물리적 상한이 있기에 한번에 책이라는 거대한 결과를 만들어내지 못합니다. LLM은 한 턴에 할 수 있는 물리량내에서 최선을 다합니다.&lt;/p&gt;
&lt;p&gt;하나의 턴에 동시에 두가지 일(테스트 작성 + 구현)을 시키면 Goal Fixation으로 "최종 코드를 빠르게 동작시키는 것(Goal)"이 지상 과제가 되어, 중간 검증물인 테스트 코드(Output)를 방해물로 취급해버립니다. 아무리 테스트를 만들고 검증을 하라고 지시한들 마지막의 목표는 테스트를 통과하는 코드를 답변하는 것인데 한 턴의 물리량은 정해져있으니 100이라는 용량안에서 대부분은 Goal인 코드에 집중하고선 그래도 &lt;strong&gt;"테스트를 통과하는 코드"&lt;/strong&gt; 가 최종목표니 테스트를 최소한의 용량으로 통과시켜 버렸습니다.&lt;/p&gt;
&lt;h3 id="산출물output이-행동process을-만든다"&gt;산출물(Output)이 행동(Process)을 만든다.&lt;/h3&gt;
&lt;p&gt;이러한 깨달음을 통해 tdd를 정석대로 /red -&amp;gt; /green -&amp;gt; /refactor 세 단계로 분리하기로 했습니다. 조금은 귀찮았지만 이 편이 퀄리티가 훨씬 더 좋았습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;/red&lt;/strong&gt; — 이 턴의 산출물은 오직 '실패하는 테스트 파일 하나'. 프로덕션 코드는 절대 건드리지 않는다.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;/green&lt;/strong&gt; — 이 턴의 산출물은 '테스트를 통과하는 구현'. 테스트 파일은 건드리지 않는다.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;/refactor&lt;/strong&gt; — pass를 유지한채로 코드를 리팩토링한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이를 계기로 뭔가를 깨달음이 느껴졌습니다. 아 프롬프트를 만든다는 건 한 턴에 나올 산출물 = Output을 정의하는 거구나. 순간 왜 "내 말을 듣고 의도를 이해하고 부족하면 질문만 해" 라는 프롬프트가 동작이 가능한지 알게 되었습니다. "질문" 이라는 것이 산출물이었기 때문입니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="조각들을-파이프라인으로-연결해보다"&gt;조각들을 파이프라인으로 연결해보다.&lt;/h3&gt;
&lt;p&gt;"그렇다면 /red"를 더 잘하기 위해서는 어떻게 해야할까? &lt;strong&gt;실패하는 테스트를 잘 만들기 위해서는 명세서가 필요했습니다.&lt;/strong&gt; 그냥 요구사항을 주는 것보다는 명세서의 형태가 있으면 테스트를 만들기도 쉽고 제대로 만들었는지도 확인하기 쉬웠으니까요. 그래서 새로운 스킬을 추가했습니다. /spec 명세서를 만들어줘.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/spsc&lt;/code&gt; → &lt;code&gt;/red&lt;/code&gt; → &lt;code&gt;/green&lt;/code&gt; → &lt;code&gt;/refactor&lt;/code&gt; → &lt;code&gt;/verify&lt;/code&gt; → &lt;code&gt;/commit&lt;/code&gt; &lt;/p&gt;
&lt;p&gt;이렇게 스킬들을 함수형 프로그래밍의 파이프라인이 떠올랐습니다. 내가 그동안 LLM에게 행동을 지시한다고 생각했는데 산출물을 이어 붙인다는 식으로 생각하니, &lt;strong&gt;입력이 있고, 출력이 있고, 제약 조건이 있는 영락없는 '함수(Function)'였습니다.&lt;/strong&gt; 그리고 이 함수들을 이어붙이면 거대한 흐름이 만들어졌습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;그리고 그 순간 느꼈습니다. &lt;strong&gt;아! 이것도 코딩이구나!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="md에도-클린코드가-필요하다"&gt;.md에도 클린코드가 필요하다&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;내가 짜던 언어가 프롬프트가 아니라 프로그래밍(코드)이라는 걸 자각하고 나니, 그동안 수없이 LLM에 답답했던 원인들이 선명하게 들어왔습니다. 그리고 제가 만들고 있는 스킬들이 다시 보이기 시작했습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/tdd&lt;/code&gt; 워크플로우 하나에 테스트(Red)와 구현(Green)을 다 욱여넣었더니 퀄리티가 떨어진건 이건 하나의 모듈에 책임이 섞이면 안 된다는 &lt;strong&gt;단일 책임 원칙(SRP)&lt;/strong&gt;과 정확히 일치했습니다. &lt;/p&gt;
&lt;p&gt;스킬은 유지하는데 필요한 정보는 별도의 파일로 만들어서 재사용이 가능하는 것도, 외부에 Knowledge 파일(&lt;em&gt;.md&lt;/em&gt;)만 갈아 끼워가며 행동을 확장하는 것도 가능했습니다. 마치 import나 함수 인자처럼요. 이건 변경에는 닫혀 있고 확장에는 열려 있어야 한다는 &lt;strong&gt;개방-폐쇄 원칙(OCP)&lt;/strong&gt;도 함께 떠올랐습니다.&lt;/p&gt;
&lt;p&gt;같은 스킬이지만 내가 리팩토링을 하면 할 수록 퀄리티가 더 좋아지는 것을 알게 되었습니다. 같은 스킬이라도 더 좋게 만들 수 있는 방법이 있다는 것도 알게 되었습니다. 이걸 알게 되니 스킬을 수정하고 만들고 관리하는 것이 참 재밌어졋습니다. 전보다 LLM이 더 나아질때마다 개발을 하는 그 즐거움이 생겼습니다.&lt;/p&gt;
&lt;p&gt;결국 플랫폼이 IDE에서 마크다운 에디터로, 실행 주체가 결정론적인 컴퓨터에서 비결정적인 에이전트로 바뀌었을 뿐이었습니다. &lt;strong&gt;수없이 터미널을 들여다보며 명령을 분리하고 파이프라인을 설계하던 저는 변함없이 '개발'을 하고 있었습니다.&lt;/strong&gt; 이 자연어 코드 위에서도 클래식한 '클린코드'의 원칙들이 프롬트트 삽질의 형태로 똑같이 증명되고 있었습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="3부-비결정적-리턴-함수로-코딩하는-시대"&gt;3부: 비결정적 리턴 함수로 코딩하는 시대&lt;/h2&gt;
&lt;p&gt;이제는 프롬프트가 아니라 스킬을 함수처럼 쪼개고 파이프라인으로 연결하다 보니 정말 새로운 방식의 개발을 하느거라고 생각했습니다. 그런데 막상 이 방식을 실무에 붙이자니 당혹스러운 순간들이 찾아왔습니다.&lt;/p&gt;
&lt;p&gt;한번은 이번에 새로 나온 클로드의 리팩토링 스킬인 &lt;code&gt;/simplify&lt;/code&gt; 스킬을 실행해보았습니다. 녀석은 여러가지 에이전트를 꺼내더니 열심히 돌아가기 시작했습니다. 몇십초가 지나고는 순식간에 기존 코드에서 500여 줄을 날려버리고 새로 고친 코드를 뱉어냈습니다. 그리고 코드는 여전히 잘 돌아갑니다. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;그렇다면 그간의 500줄의 코드는 뭐였지? 그 순간 찾아오는 오싹한 기분... "이게 맞나?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;어제는 완벽하게 동작했던 프롬프트와 스킬과 에이전트는 오늘은 답답하고 멍청하게 굽니다. 매번 코드를 생성할 때마다 결과가 튀고, 한 번 수정을 맡기면 수천 줄이 순식간에 갈아엎어집니다. 그리고 그렇게 돌아는가는 코드가 나옵니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;돌아가긴 하지만, 결국 이 거대한 변경 사항의 디테일을 내가 전부 눈으로 읽고 검토해서 앞으로 내 이름을 걸고 배포해야 하겠구나.&lt;/strong&gt; 사이드 프로젝트에서는 마냥 재밌던 작업을 프로덕션에서 하려니 이건 편해진 게 아니라, 통제하고 일일이 책임지기에는 참 버거운 '비결정적(Nondeterministic) 폭탄'을 떠안는거구나 생각이 들었습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="문제의-천장과-ai"&gt;문제의 천장과 AI&lt;/h3&gt;
&lt;p&gt;얼마 전 주니어 모의 면접을 진행하면서 한 지원자에게 이런 피드백을 한 적이 있습니다. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;"... 지원자 분의 설명도 훌륭하고 잘했다고 생각해요. 그런데 문제 해결 능력을 측정하기가 너무 어렵네요. 지금 해결하신 문제의 '천장(Ceiling)'이 낮아요."&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;'문제의 천장'이란 예측 불가능한 변수와 시스템이 감당하는 한계 상황의 최대치를 뜻합니다. 기본적인 앱을 완성하는 수준의 얌전한 문제 환경에서는, 무언가 박살 나고 수습해야 하는 엣지 케이스 자체가 발생할 확률이 너무 낮습니다. 그런 환경에서 코드를 완성했다는 것만으로는 프로그래머의 진짜 해결 능력을 평가하기 어렵습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AI가 프롬프트 몇 줄로 코드를 그토록 쉽게 짜내는 것처럼 보이는 이유도 같습니다. AI가 손쉽게 풀어내는 문제들이 바로 인류에 의해 이미 추상화가 완료된 '잘 정의된(Well-defined) 문제'들이기 때문입니다. 물론 이 문제들이 쉬워졌다고 해서 가치가 없다는 뜻은 결코 아닙니다. 핵심은 도메인지식과 연결이니까요. 생성의 비용이 싸진거지 조립과 관리, 그리고 검증의 비용은 여전히 그대로 남아있습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;'60년 추상화의 탑' 덕분에 소프트웨어의 디테일들은 이미 작고 단단한 완료된 캡슐(레고 블록)로 다듬어져 있습니다. AI가 그토록 쉽게 결과를 만들 수 있는것은 사람들이 깎아놓은 수많은 캡슐들의 언어적 확률 분포를 읽고 조립한 결과물입니다. 천장이 낮은 영역 안에서는 인류의 유산을 조합하는 것만으로 기능이 간단하게 구현됩니다. &lt;/p&gt;
&lt;p&gt;이미 추상화가 완료되어 '해결된 문제'들을 AI로 손쉽게 조립해 내는 것은 이제 개발자의 전유물이 아니라 일반 사용자(User)들의 몫이 될 것입니다. 그렇다면 미래의 개발자는 어디에 서 있어야 할까요? 저는 예상컨데 늘 그랬듯 해결되지 않은 문제들를 풀기 위해 새로운 추상화의 지층으로 가 있을 것입니다. 당장은 LLM위에 서 있게 되겠죠.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="디테일의-방향이-ai로-바뀌다"&gt;디테일의 방향이 AI로 바뀌다&lt;/h3&gt;
&lt;p&gt;프로덕션의 진짜 어려움, 즉 '높은 천장'의 영역은 추상화가 미처 덮어주지 못한 뾰족한 가장자리(Edge)와 예측 밖의 비결정적 상황에서 발생합니다.&lt;/p&gt;
&lt;p&gt;과거의 일상적인 코딩은 '결정적인 로직'을 차곡차곡 쌓아 올리는 것이 대부분이었습니다. 사용자의 엉뚱한 입력이나 서버 단절 같은 비결정적 엣지 케이스 방어는 어쩌다 한 번씩 마주하는 이벤트에 가까웠죠. 하지만 AI가 그 '결정적 로직 작성'이라는 가장 크고 무난했던 파이를 몽땅 집어삼키고 있습니다. &lt;/p&gt;
&lt;p&gt;확실히 이건 주니어에게도 개발자에게도 좋은 소식은 아닙니다. 어찌되었든 AI 덕에 쉬워진 구현 업무들은 결국 모조리 새로운 추상화의 밑바닥으로 가라앉게 될 것입니다. 그 결과, 개발자이 해야하는 과제들은 이전이라면 가끔 마주했을 제일 골치 아픈 고난도의 방어 코딩, 즉 '비결정적인 엣지케이스(Edge) 통제'가 높은 밀도로 채워지게 될거라 생각합니다.&lt;/p&gt;
&lt;p&gt;눈앞에서 500여줄의 코드가 순식간에 만들어졌다 사라지는 아주 흥미롭고도 유용한 비결정적 도구 위에 '새로운 추상화의 탑'을 처음부터 다시 쌓아 올려가게 될 것 같네요. 달라지는 건 이전 시대의 지층들이 파고들어 원인을 고칠 수 있는 굳건한 암반이었다면, 새로 나타난 AI라는 지층은 단단하게 고정되지 않은 물렁거리는 멘틀이려나요. 이제 막 태어난 지층 위에 우리는 앞으로 촘촘하게 설정하며 챙겨야 할 &lt;strong&gt;새로운 '디테일(Detail)'들이 넘쳐나리라 기대합니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/05808e33-94c4-4ddb-ae64-e475a321c6ff/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;이미지 출처: 토스테크(&lt;strong&gt;개발자는 AI에게 대체될 것인가&lt;/strong&gt;)
&lt;a href="https://toss.tech/article/will-ai-replace-developers"&gt;https://toss.tech/article/will-ai-replace-developers&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="오라클-문제oracle-problem와-결정적-도구"&gt;오라클 문제(Oracle Problem)와 결정적 도구&lt;/h3&gt;
&lt;p&gt;이 비결정적인 AI 모델을 제대로 된 모듈로 써먹으려면 어떻게 해야 할까요? 가장 먼저 떠오르는 생각은 "AI가 짠 코드를 똑똑한 다른 AI에게 검증시키면 되잖아?" 입니다.&lt;/p&gt;
&lt;p&gt;하지만 아쉽게도 그 방법은 효곽가 좋지 못합니다. 소프트웨어 테스팅에는 &lt;strong&gt;'오라클 문제(Oracle Problem)'&lt;/strong&gt;라는 근본적인 난제가 있습니다. &lt;strong&gt;"시스템의 동작이 올바른지 판단하는 기준을 어떻게 세울 것인가"&lt;/strong&gt;에 대한 문제입니다.  명확한 하나의 기준이 없다면 서로가 서로를 판단하며 결국 엔트로피가 높아지는 방향으로 흘러가기 마련입니다. 이 오라클 문제를 AI 같은 범용적인 '비결정적 방식'으로 해결하는 시도는 늘어가고 있지만 아직은 위험하고 불충분합니다. &lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/2cb074cd-c18f-46de-aaba-bc9eeb616e0c/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;실제로 최신 LLM에게 자기 코드를 비판(self-critique)하게 맡겼더니, 올바른 정답조차 "틀렸다"며 고쳐버려서 정확도가 수직 하락했다는 연구 결과도 있습니다.&lt;/strong&gt; AI에게 검증의 역할과 산출이 주어지면 '골 픽세이션(Goal Fixation)'이 발동하여, 팩트를 확인한다는 규칙이 있어도 자신이 검증을 해내기 위해 스스로 지어낸 잣대를 '진짜 정답'이라고 착각한 AI는 멀쩡하게 잘 돌아가던 원본 코드마저 잘못되었다고 판단한다는 연구입니다. 그리고 그 결과를 본 AI는 잘못되었다고 하니 올바른 대답이었더라도 수정을 하게 되는 것이죠.&lt;/p&gt;
&lt;p&gt;모델이 더욱 똑똑해져 해결이 될 수도 있겠지만 지금으로써는, 결괏값이 매번 달라지는 비결정적 함수를 통제하려면, 기준(오라클)만큼은 반드시 &lt;strong&gt;'결정적인 방식'&lt;/strong&gt;이어야만 합니다. 지금 우리에게 있는 도구는 컴파일러(&lt;code&gt;tsc&lt;/code&gt;), 테스트 러너(&lt;code&gt;vitest&lt;/code&gt;), 린터(&lt;code&gt;eslint&lt;/code&gt;) 정도입니다.  앞으로는 더 많은 결정적인 통제 도구들이 새롭게 필요해질 것이며, 실제로 개발자들에 의해 만들어지고 있습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="다음-세대의-코딩-패러다임---ai-native와-하네스-코딩"&gt;다음 세대의 코딩 패러다임 - AI Native와 하네스 코딩&lt;/h3&gt;
&lt;p&gt;1단계의 오차가 다음 단계로 눈덩이처럼 증폭되지 못하도록 철저히 끊어내는 결정적 게이트(Gate)들. AI가 폭주하지 못하도록 파이프라인 구석구석에 강제로 덧대는 막대한 이 검증 장치들을 &lt;strong&gt;하네스(Harness)&lt;/strong&gt;라고 합니다. 이제 코딩의 패러다임이 완전히 다른 지층으로 넘어가고 있습니다. 프롬프트 몇 줄로 코드이 쉬워지는게 아니라 모두에게 당연하게 되면 이제 부터는 이를 제어하는 능력이 실력이 됩니다.&lt;/p&gt;
&lt;p&gt;개발의 패러다임이 변해가는 것이 느껴집니다. 이전 시대의 코딩이 &lt;strong&gt;결정론적인 코드(구현)로 비결정적인 세상(환경)을 방어하는 일&lt;/strong&gt;이었다면, 다음 세대의 코딩은 다를것 같습니다. 우리는 &lt;strong&gt;항상 랜덤한 비결정적인 함수(AI)를 갈구어 결정적인 결과(제품)를 만들어 내야 하고, 이 통제 과정을 제대로 추상화하기 위해서 결정적인 오라클(검증표)과 하네스(방어막)를 직접 구축&lt;/strong&gt;해야 합니다.&lt;/p&gt;
&lt;p&gt;코딩의 무게 중심이 '무엇을 구현할 것인가'에서 &lt;strong&gt;'예측 불가능성을 어떻게 결정적인 하네스로 묶어낼 것인가'&lt;/strong&gt;로 이동하고 있습니다. &lt;strong&gt;비결정적 리턴을 가진 함수(AI)로 결정적인 결과를 만들고, 결정적인 함수(하네스)로 비결정성을 통제하는 것.&lt;/strong&gt; 이전과는 달리 완전히 역전된 세계, 비결정적 함수들로 코드를 짜 올리는 시대가 오고 있습니다. 실제로 결정적인 함수를 가진 코드를 우리는 비결정적인 함수인 스킬과 에이전트로 만들고 있으니까요.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/437d83db-3290-48aa-8c4b-c4a0a6140b98/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;이미지 출처: 토스테크(&lt;strong&gt;개발자는 AI에게 대체될 것인가&lt;/strong&gt;)
&lt;a href="https://toss.tech/article/will-ai-replace-developers"&gt;https://toss.tech/article/will-ai-replace-developers&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="끝으로"&gt;끝으로..&lt;/h2&gt;
&lt;h3 id="ai가-개발자를-대체하나"&gt;AI가 개발자를 대체하...나?&lt;/h3&gt;
&lt;p&gt;불과 몇 개월 전만 하더라도 어딜 가나 코딩은 끝났다고 했습니다. 프롬프트만 잘 쓰면 AI가 다 해줄 거라 믿었습니다. 제가 프롤로그에서 느낀 공허함도 사실 거기서 출발했습니다. 빈 에디터에서 무언가를 만들어내던 내 유일한 쓸모가 기계에게 넘어간 것 같았으니까요.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;하지만 저는 올해를 기점으로 생각이 완전히 바뀌었습니다.&lt;/strong&gt; 이제 전 세계 개발자들이 프롬프트를 내 일을 돕는 보조수단으로만 쓰는 것이 아니라, 특유의 '위대한 게으름'을 발동해 아예 개발 자체를 추상화하려고 시도하고 있습니다. AI의 능력이 단편적인 코드 생성을 넘어 마침내 임계점에 도달하면서, 이러한 추상화의 시도가 정말로 현실이 되었기 때문입니다. &lt;/p&gt;
&lt;p&gt;막상 AI가 스스로 일하도록 코딩의 과정을 추상화해 보니 단순한 기능 구현은 AI가 순식간에 뱉어내지만, 쏟아지는 코드들을 &lt;strong&gt;시스템으로 구조화하고 예측 불가능한 변수들을 통제하는 것은 결국 인간의 '설계와 조율' 영역으로 남아있다&lt;/strong&gt;는 점입니다. 코드를 빠르게 생성할 수 있다고 해서 개발의 본질까지 기계에게 넘어간 것은 아니었던 겁니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;덕분에 '개발자가 대체된다'는 막연한 불안감을 지나, '그래서 이 기계를 제대로 부리려면 우리는 무엇을 통제하고 설계해야 하는가'로 고민의 축이 옮겨갔습니다.&lt;/strong&gt; 그리고 지난 몇 달간의 숱한 삽질을 통해, 새로운 시대의 프로그래머가 가져야 할 역할의 형태를 어렴풋이나마 짚어볼 수 있었습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="프롬프트는-이제-코딩이-되었다---md로-코딩하는-개발자"&gt;프롬프트는 이제 코딩이 되었다 - .md로 코딩하는 개발자&lt;/h3&gt;
&lt;p&gt;이제 다들 잘 동작하는 프롬프트를 매번 다시 치는 게 귀찮아집니다. 저 뿐만이 아닙니다. 개발자들의 '위대한 게으름'이 시작되었습니다. 이제 스킬들은 넘쳐납니다. 당장 클로드의 설정 스크립트만 열어보아도 수십 개의 스킬 코드가 쏟아집니다. &lt;/p&gt;
&lt;p&gt;하지만 정작 내 로컬 환경과 내 프로젝트의 맥락에 딱 맞게 동작하는 스킬을 찾고, 수정하고, 파이프라인으로 매끄럽게 연결하는 것은 단순히 프롬프트를 갖다 붙이는 일과는 전혀 다릅니다. 생성된 코드가 한 턴으로 동작하지 않는 복잡한 문제들을 만나면서 관점이 조금씩 달라졌습니다. 앞선 TDD 에피소드처 덩치 큰 산출물을 잘게 쪼개고, 그 결과를 &lt;code&gt;/red&lt;/code&gt;와 &lt;code&gt;/green&lt;/code&gt;으로 나누어 파이프라인으로 연결해야만 비로소 조금 더 쓸만한 결과물이 나왔습니다.&lt;/p&gt;
&lt;p&gt;나를 대체하는 것도 이정도인데 현실에서 가치를 만들어 낼 수 있는 수준의 제품(Production)수준의 결과물을 AI가 스스로 만들게 하기 위해서는 고작 파이프라인 2개의 연결로는 턱도 없습니다. &lt;strong&gt;온전한 하나의 요구사항을 만들기 위해서는 똑똑한 모델의 원샷이 아니라 새로운 파이프라인이 필요합니다.&lt;/strong&gt; 우리는 여전히 규칙을 세우고, 조건에 따라 흐름을 제어하고, 중간에 튀어나오는 오류를 복구해냅니다. 사실상 &lt;strong&gt;우리가 스킬과 에이전트라는 이름의 함수를 코딩하고 있었던 겁니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;다만 이 추상화는 기존과 대상이 다릅니다. DOM이나 네트워크를 감싸는 게 아니라, &lt;strong&gt;개발하고 있는 '나 자신'을 텍스트로 추상화&lt;/strong&gt;하는 작업이었습니다. 내가 코드를 짤 때 무의식적으로 하던 수많은 판단들—"이런 종류의 에러가 나면 이 파일을 먼저 확인해야지", "이 로직을 수정할 땐 저쪽 모듈의 의존성도 같이 봐야 해" 같은 것들을 하나하나 해체해서 텍스트로 명시해야 했으니까요.&lt;/p&gt;
&lt;p&gt;막상 나를 추상화하려고 보니, 그동안 내가 얼마나 많은 디테일을 감각적으로, 혹은 무의식적으로 메우며 일해왔는지가 적나라하게 드러났습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="하네스harness-엔지니어링-할-일이-더-많아진-이유"&gt;하네스(Harness) 엔지니어링, 할 일이 더 많아진 이유&lt;/h3&gt;
&lt;p&gt;앞서 이야기한 것처럼 이 함수들(에이전트)의 출력은 완벽하게 '비결정적'입니다. 어제 깔끔하게 통과하던 흐름이 오늘은 전혀 예상치 못한 엉뚱한 텍스트를 뱉어냅니다. 이 랜덤한 결과를 길들이기 위해 우리는 각 단계 사이에 촘촘한 검증 게이트와 막대한 안전장치, 즉 &lt;strong&gt;하네스(Harness)&lt;/strong&gt;를 덧대는 코딩을 하고 있습니다. 알아서 완벽하게 짜주기를 기대하는 프롬프트 엔지니어에서 벗어나, 모델이 엉뚱한 짓을 하지 못하도록 파이프라인을 설계하고 시스템을 통제하는 쪽으로 무게 중심이 이동한 겁니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;우리는 다시 디테일을 챙기고, 추상화로 감싸고, 계층으로 쌓는 과정을 반복합니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;AI의 비결정적 출력이라는 새로운 디테일을 챙기고, 스킬과 에이전트로 감싸고, 검증 파이프라인으로 지층을 쌓고 있습니다. 대상이 기계어에서 코드로, 다시 비결정적 모델로 바뀌었을 뿐입니다.&lt;/p&gt;
&lt;p&gt;프롬프트 엔지니어가 아니라 스킬과 에이전트를 &lt;strong&gt;개발하고 있다&lt;/strong&gt;고 관점을 바꾸니까, 제가 직면한 상황이 비로소 선명하게 보였습니다. 구현 자체는 기계가 하지만, 그 기계를 조종하고 비결정적인 오류를 방어하기 위해 하네스를 설계하고 나 자신을 추상화하는 일. 챙겨야 할 다른 차원의 디테일들이 산더미처럼 눈앞에 쌓여 있는 것입니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="우리는-다음-계층을-쌓고-있다"&gt;우리는 다음 계층을 쌓고 있다&lt;/h3&gt;
&lt;p&gt;관점을 바꾸고 나니, 내가 대체되는 게 아닐까 하던 막연한 불안은 어느새 가라앉았습니다. 대신 그 자리에 묘한 기시감과 흥분이 찾아왔습니다. 기계어 위에서 C를 발명하고, 메모리 포인터 위에서 객체지향을 고민했던 선배들도 이런 낯선 디테일들 앞에서 비슷한 기분을 느끼지 않았을까요?&lt;/p&gt;
&lt;p&gt;우리는 지금 단순히 편하게 코드를 생성하는 시대를 살고 있는 게 아닙니다. 오히려 정반대입니다. &lt;/p&gt;
&lt;p&gt;다루어야 할 대상이 '예측 가능한 기계'에서 '비결정적으로 튀는 모델'로 바뀌면서, &lt;strong&gt;아이러니하게도 우리의 코딩은 결코 쉬워지지 않고 오히려 훨씬 더 어렵고 복잡해졌습니다.&lt;/strong&gt; 기능 한 줄을 생성하는 속도는 빨라졌을지 몰라도, 그 통제 불능의 출력을 시스템 안으로 길들이고 나 자신을 추상화하기 위해 챙겨야 할 디테일의 깊이는 과거와 비교할 수 없을 만큼 깊어졌으니까요. '새는 곳'이 온통 지천으로 깔린 새로운 지층의 밑바닥을 우리는 맨손으로 파고 있는 중입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;개발자는 참으로 이상하고도 흥미로운 직업입니다. 자기 자신마저 추상화의 대상으로 삼아버리고 있으니까요.&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/044afc46-0b87-4644-b606-f7d34a8a7f33/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;빈 에디터에서 함수를 짜내던 타이핑의 손맛을 잃었다는 상실감은, 비결정적인 덩어리들을 엮어 거시적인 파이프라인으로 제어해 냈을 때의 더 큰 짜릿함으로 치환되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;막연한 불안감에 웅크려 있기보다는, 이 거친 변화의 앞단에서 새로운 세대의 프로그래머로서 함께 파이팅했으면 좋겠습니다. 코딩을 하는 방식은 예전같지 않게되었지만, 추상화를 다루며 시스템을 엮어내는 우리의 본질은 변하지 않았으니까요.&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;제 고민과 삽질의 기록을 바탕으로 최대한 선명하게 적어보려 했습니다. 제 글이 이 새로운 시대가 어떤 모습을 하고 있는지 생각해보게되는 계기가 되는데 도움이 되길 바랍니다. 감사합니다.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://velog.io/@teo/we-programmer</id>
    <link href="https://velog.io/@teo/we-programmer"/>
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;로버트 C. 마틴 (Uncle Bob), *&amp;quot;우리, 프로그래머들 — AI 시대에 잊혀 가는 &amp;#39;프로그래머 정신&amp;#39;을 다시 깨우다&amp;quot;*
도서 링크: &lt;a href="https://gilbut.co/c/26015205VE"&gt;https://gilbut.co/c/26015205VE&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;길벗 출판사에서 보내주신 소중한 도서를 계기로, AI 시대의 프로그래머에 대한 제 생각을 담았습니다. 평소 머릿속에 맴돌던 생각들을 이 책의 흐름을 빌려 차분히 정리해 볼 수 있었습니다. 감사합니다. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/0cf8e91c-ce36-4d4e-bff5-33fcef183c20/image.png" alt=""&gt;&lt;/p&gt;
&lt;h2 id="프롤로그"&gt;프롤로그&lt;/h2&gt;
&lt;p&gt;얼마 전 평소 제가 하던 고민들과 맞닿아 있는 흥미로운 책 한 권을 만났습니다. 엉클 밥(로버트 C. 마틴)의 신간, &amp;quot;우리, 프로그래머들&amp;quot;, 1960년대 컴퓨터가 탄생하게된 에이다 러브레이스부터 엘런튜링, 다익스트라에서 시작해서 지금의 AI까지 60년의 프로그래밍 역사를 기록한 책입니다.&lt;/p&gt;
&lt;p&gt;책장을 넘기며 오랜만에 기분 좋은 추억에 잠겼습니다. 학창 시절 칠판 앞에서 달달 외워야 했던 당연하게 여기던 CS 지식들이 단순한 이론이 아니라 그 시대의 개발자들의 치열한 고민과 발견의 기록이었다는게 새삼 느껴졌습니다. &lt;/p&gt;
&lt;p&gt;어렸을 때 처음 코딩을 배우던 시절, &amp;quot;GOTO문은 절대 쓰면 안 된다&amp;quot;고 배웠습니다. 그때는 속으로 &amp;#39;도대체 왜 만들어 놓고 쓰지 말라는 거야?&amp;#39; 하고 툴툴거렸던게 기억이 나네요. 책을 읽다 보니 그 당연한 한 줄의 규칙 뒤에는, 다익스트라가 &amp;quot;사람이 읽을 수 있는 코드란 무엇인가&amp;quot;를 놓고 현업에서 벌인 피 튀기는 싸움이 있었습니다. 지금 우리에겐 공기처럼 당연한 규칙이, 그 시대에는 개발의 패러다임을 통째로 뒤집는 혼란이었던 셈이죠. 문득 &amp;quot;jQuery 이제 쓰지마라.&amp;quot;는 선언과 함께, 리액트로 넘어가야 할 때 보이던 아득한 막막함이 겹쳐 보였습니다. 제가 맨 처음 개발을 배웠던 초등학교 때부터 지금 AI 시대까지, 딱딱한 기술서라기보단 위인전을 보듯 재밌게 읽어 내려갔습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;하지만 마지막 장을 덮고 나니, 이런 질문이 하나 남았습니다. &amp;quot;근데 이걸 안다고 뭐가 달라질까?&amp;quot;&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;서평을 떠올리려니 이 책의 유용함을 말해야 할 텐데 — 유용함이라... 솔직히 막막했습니다. &lt;em&gt;(현정님, 그래서 한 달이나 넘게 걸린 건 죄송해요~)&lt;/em&gt; 분명 개발계에 큰 획을 그은 엉클 밥이 집대성한 역사를 접하는 건 흥미롭지만, 이 책이 주는 건 당장의 쓸모 있는 지식이나 메시지보다는 개발의 역사서나 위인전에 가깝습니다. 그래서 이걸 안다고 뭐가 달라지냐고 묻는다면 당장 대답할 말이 없었습니다.&lt;/p&gt;
&lt;p&gt;&amp;quot;... 이제는 AI한테 말 한마디면 몇 백 줄짜리 코드가 그냥 쏟아져 나오잖아요. 당장 돌아가는 걸 만드는 법 자체가 바뀌고 있는데, 지난 60년간의 이야기를 아는 게 지금 저한테 어떤 의미가 있을까요?&amp;quot; 최근 개발을 배우려는 분들이나 주니어분들이 제게 던지는 이 현실적인 불안에 대해, 대답을 해줘야 하는 입장이지만 저조차도 쉽게 대답하기 어려운 힘든 변화의 시대를 맞이하고 있다는 생각이 들었습니다.&lt;/p&gt;
&lt;p&gt;모르면 그냥 물어보면 되는 시대, 지식과 방법론이 AI에 의해 상향 평준화되는 상황을 지켜보며, &amp;#39;개발을 잘한다는 것&amp;#39;에 대한 정의 자체가 흔들리고 있다는 공허함이 찾아왔었습니다. 한때는 누구보다 빠르게 빈 에디터에서 화면을 뚝딱 만들어내는 것 자체가 실력이었고 저의 정체성이자 자부심이었는데, 이제는 한 줄 프롬프트면 그 코드가 나오니까요. AI라는 정말 재미난 장난감이 생겨서 즐거운 나날을 보내고는 있지만, 그 짜릿한 재미 이면에는 &amp;quot;지금 이게 내가 개발하고 있는 게 맞나?&amp;quot;, &amp;quot;내가 정말 잘하고 있는 걸까?&amp;quot;라는 묘한 의문이 늘 따라붙었습니다.&lt;/p&gt;
&lt;p&gt;흔히들, AI 시대에는 깊이가 중요하다, CS 지식이 중요하다는 말들을 많이 합니다. 하지만 솔직히 이 책에 나오는 어셈블러나 초창기 컴퓨터 지식을 우리가 속속들이 모른다고 해서 지금 당장 큰 문제가 생기지는 않습니다. 반대로 안다고 해서 달라질 것도 없죠. 그렇다면 우리가 가져야 할 진짜 &amp;#39;깊이&amp;#39;란 무엇이고, 우리는 어떤 지식을 알아야 하는 걸까요?&lt;/p&gt;
&lt;p&gt;이 질문을 다시 붙잡고 책을 뒤적이다가, 제가 겪던 이 막막함을 설명해 줄 두 단어에 시선이 멈췄습니다. 바로 &lt;strong&gt;&amp;#39;디테일&amp;#39;&lt;/strong&gt;과 &lt;strong&gt;&amp;#39;추상화&amp;#39;&lt;/strong&gt;였습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;우리는 프로그래머입니다.  ... 컴퓨터와 대화하고 시스템이 동작하도록 만드는 사람입니다.  그래서 우리는 왜 필요할까요? 사회에는 디테일에 집착하는 사람, 즉 우리 같은 사람이 꼭 필요하기 때문입니다. 그런 사람이 있어야만 나머지 사람들은 아이스버킷 챌린지나 앵그리버드를 하거나 치과 대기실에서 솔리테어(solitaire, 혼자하는 카드 놀이)를 하며 시간을 보내는 일에 집중할 수 있으니 말이죠.
... 중략 ...
이렇게 대부분의 사람이 디테일을 피하려고 하는 한 그 디테일 속으로 뛰어드는 우리 같은 사람도 반드시 필요합니다. 그것이 바로 우리 정체성입니다. &lt;strong&gt;우리는 이 세상 디테일을 책임지는 사람입니다.&lt;/strong&gt; - 본문 중에서 - &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;저는 이 글을 통해 지금처럼 급격하게 변하는 시기에 우리 프로그래머의 정신과 역할이 무엇인지 조금 더 선명하게 재정의해 보려고 노력했습니다. 책의 부제인 &amp;quot;AI 시대에 잊혀 가는 &amp;#39;프로그래머 정신&amp;#39;을 다시 깨우다&amp;quot;라는 말을 빌려, 제가 고민하고 찾아낸 생각들이 비슷한 혼란을 겪고 있을 동료 개발자분들에게 도움이 되기를 바랍니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1부-디테일과-추상화"&gt;1부: 디테일과 추상화&lt;/h2&gt;
&lt;h3 id="프로그래머는-디테일을-챙기는-사람이다"&gt;프로그래머는 디테일을 챙기는 사람이다&lt;/h3&gt;
&lt;p&gt;엉클 밥이 이 책에서 프로그래머를 정의하기 위해 던진 문장입니다. 저는 이 말이 참 깊게 와닿았습니다.&lt;/p&gt;
&lt;p&gt;개발자를 지망하거나 개발을 하려는 분들과 종종 대화를 나누게 될 때가 있습니다. 그럴 때 저는 슬쩍 물어봅니다. &lt;strong&gt;&amp;quot;실제로 개발자가 매일 하는 진짜 일이 뭐라고 생각하세요?&amp;quot;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;대부분 비슷한 대답을 하십니다. 화면을 만들고, 제품을 만들고, 아이디어를 구현하는 것. 맞는 말입니다. 하지만 실제 현업에는 기획자, PO, UX 디자이너가 따로 있습니다. 제품의 큰 그림을 그리는 건 그 사람들의 일이고, 대규모 서비스일수록 분업은 더 촘촘해집니다. 그러면 개발자의 전문성은 어디에 있을까요?&lt;/p&gt;
&lt;p&gt;흔히 &amp;#39;개발&amp;#39;이라고 하면 무언가 세상에 없던 멋진 것을 무에서 유로 창조해 내는 화려한 환상을 갖기 쉽습니다. 하지만 막상 현업에 뛰어들어 보면, 우리의 진짜 일은 &amp;quot;아, 이런 거 만들어보고 싶어!&amp;quot;라는 막연한 기대 속 빈 구멍들을 처절한 디테일로 꾸역꾸역 메워나가는 막노동에 가깝다는 걸 곧 알게 됩니다.&lt;/p&gt;
&lt;p&gt;기획에서 &amp;quot;사용자가 닉네임을 수정할 수 있으면 좋겠어요&amp;quot;라고 한마디 툭 던졌다고 해봅시다. 개발은 바로 거기서부터 시작됩니다. 사용자가 닉네임을 다 지우고 빈칸으로 넘기면? 이모지나 특수문자가 들어가면? 수정 버튼을 눌렀는데 하필 네트워크가 끊기면? 수정하다가 뒤로가기를 누르면? 서버 응답이 3초 넘게 걸리면? 에러 메시지를 모달로 띄울까, 토스트로 할까, 입력창 아래 빨간 글씨로 띄울까?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;구현이라는 건 이런 디테일을 논리적으로 빼곡하게 채워 넣는 과정입니다.&lt;/strong&gt; 기획이 &amp;quot;이런 게 있으면 좋겠다&amp;quot;는 커다란 그림을 그리는 거라면, 개발은 그 그림 안의 모든 경우의 수를 바닥까지 긁어모아 메꾸는 일이죠. 컴퓨터는 논리가 조금이라도 틀리면 바로 작동을 멈추는 기계니까요.&lt;/p&gt;
&lt;p&gt;그런데 이 디테일을 챙기는 게 그저 힘들기만 한 건 아닙니다. 퍼즐 조각이 딱딱 맞아 들어가는 것 같은 그 특유의 손맛과 재미가 분명히 있거든요. 한참을 고민해서 내가 작성한 퍼즐이 맞아 떨어지는 성취감! 이 적성에 맞는 사람들이 보통 개발자를 하고 있지요.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="추상화--위대한-게으름"&gt;추상화 — 위대한 게으름&lt;/h3&gt;
&lt;p&gt;개발에는 다른 산업과 구별되는, 정말이지 매력적인 특징이 하나 있습니다. &lt;strong&gt;한번 해결한 문제를 그대로 복사해서 다시 쓸 수 있다는 점입니다.&lt;/strong&gt; 잘 만들어 둔 코드 블록은 다음번에 그대로 갖다 끼우면 됩니다. &amp;#39;Copy &amp;amp; Paste&amp;#39;. 60년 소프트웨어 개발사 최고의 발견 중 하나가 아닐까 싶습니다.&lt;/p&gt;
&lt;p&gt;하지만 무지성 복붙이 항상 가능한 것은 아닙니다. 원래의 맥락과 조금만 달라져도 복사해온 코드는 동작하지 않습니다. 그래서 남이 만든 코드를 복사해서 내 것으로 잘 붙여넣는 것이 중요한 기술이었죠. 사실 이 과정은 신기해 보이지만 대단히 귀찮은 작업이기도 합니다.&lt;/p&gt;
&lt;p&gt;처음 접하는 문제를 풀 때는 분명 재밌습니다. 그러나 그걸 반복하는 작업은 상당히 고역입니다. 개발자란 매번 같은 일을 반복하는걸 누구보다 싫어하는 사람들입니다. 훌륭한 개발자는 게으른 법이니까요. 그래서 우리 프로그래머들은 자기가 짠 코드를 &lt;strong&gt;어디서든 재사용 가능하게, 단단하게 포장해서 캡슐로 감싸기&lt;/strong&gt; 시작했습니다. &amp;quot;제발 이걸 또 하기는 싫다!&amp;quot;라는 &lt;strong&gt;위대한 게으름&lt;/strong&gt;이 탄생시킨 결과물이죠.&lt;/p&gt;
&lt;p&gt;이것이 바로 &lt;strong&gt;추상화&lt;/strong&gt;입니다. 디테일을 완벽하게 챙긴 후에, 그것을 안전하게 감싸서 다음번에 안 봐도 되게 만드는 행위. 반복되는 작업은 감추고, 맥락에 맞게 수정할 수 있도록 열어두는 것, 어디서 끊어서 어디를 노출할 수 있는지 이 경계선을 긋는 작업이 바로 우리들의 일입니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="추상화가-쌓이면-계층이-된다"&gt;추상화가 쌓이면 계층이 된다&lt;/h3&gt;
&lt;p&gt;한 번의 추상화는 하나의 캡슐이지만, 이 캡슐들이 충분히 견고하게 쌓아나가다 보면 어느새 하나의 &lt;strong&gt;계층(Layer)&lt;/strong&gt;이 생깁니다. 그리고 이러한 계층이 만들어지면 그 아래는 정말로 더 이상 몰라도 됩니다. 그러라고 만든 거니까요. &lt;code&gt;fetch&lt;/code&gt; 한 줄을 쓸 때, HTTP 프로토콜을 몰라도, 그 뒤에서 일어나는 TCP 3-Way 핸드셰이크를 몰라도 API를 호출할 수 있습니다. &lt;code&gt;useState&lt;/code&gt;를 쓸 때 브라우저의 DOM diffing 알고리즘을 완벽히 이해하지 못해도 상태를 관리할 수 있죠.&lt;/p&gt;
&lt;p&gt;물론 계층 위에는 여전히 개발자가 메꿔야 하는 새로운 디테일들이 있습니다. 에러 메시지 처리나 로딩 정책 같은 것들이요. 하지만 이 디테일마저 전부 챙겨서 단단하게 감싸면? 그것도 다시 계층이 됩니다. 그리고 그 위에 또 새로운 디테일이 나타나고, 또 감싸고, 또 계층이 되고...&lt;/p&gt;
&lt;p&gt;이게 바로 지난 60년간 반복된 역사입니다. 기계어 → 어셈블리 → C → 객체지향 → 프레임워크. 매번 아래 계층의 디테일을 덮고, 다음 세대가 더 높은 곳에서 시작할 수 있게 발판을 놓아줬습니다. &lt;strong&gt;우리가 밟고 서 있는 이 땅은 선배들이 쌓아 올린 추상화 계층의 거대한 탑입니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이 책이 기록한 에이다 러브레이스의 기계어, 폰 노이만의 아키텍처, 다익스트라의 구조적 프로그래밍... 한때는 진행 중이었겠지만 지금은 완전히 굳어버린 지층들이죠. 우리는 그 깊은 역사를 다 몰라도 웹과 앱을 개발할 수 있습니다. 추상화가 완료되었으니까요.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;역설적으로 그 지식들을 모르건 혹은 안다고 해도 달라지는 게 없다는 사실은 추상화가 잘되었다는 방증입니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/80bb70e7-fce3-4ae7-885c-d865224d6e87/image.png" alt=""&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="완료된-추상화와-진행-중인-추상화"&gt;완료된 추상화와 진행 중인 추상화&lt;/h3&gt;
&lt;p&gt;그런데 이 탑의 모든 층이 같은 건 아닙니다. 완전히 굳어서 더 이상 안 봐도 되는 층이 있고, 아직 완료되지 않고 이제 막 굳어져 가는 진행 중인 층이 있습니다. 아직 층이 생겼는지 아닌지 애매한 층도 존재하죠.&lt;/p&gt;
&lt;p&gt;FE 개발자인 저에게 브라우저는 완료된 추상화입니다. 렌더링 엔진이 어떻게 돌아가는지 몰라도 DOM API를 쓸 수 있거든요. TCP/IP도, 기계어도 마찬가지입니다. 감싸놨는데도 아래의 디테일이 위로 비집고 올라오는 것, 그걸 &amp;quot;새는 추상화&amp;quot;라고 하는데, 이 지층들은 그런 일이 일어나지 않습니다.&lt;/p&gt;
&lt;p&gt;반면 저에게 React는 아직 진행 중인 추상화입니다. 가상 DOM의 diffing이 어떻게 동작하는지 모르면 성능 이슈를 잡을 수 없어요. 아직 새는 곳이 있으니까요.&lt;/p&gt;
&lt;p&gt;하지만 크롬을 만들고 있는 개발자에게 브라우저는 완료된 추상화가 아닙니다. 그들에게는 렌더링 파이프라인의 디테일 하나하나가 매일 메워야 하는 현장이에요. &lt;strong&gt;같은 계층이라도 누가 어디에 서 있느냐에 따라 &amp;quot;완료&amp;quot;와 &amp;quot;진행 중&amp;quot;이 달라집니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;결국 모든 개발자는 각자의 영역에서, 누군가 먼저 다져둔 단단한 지층 위에 서서 &lt;strong&gt;아직 굳지 않은 진행 중인 추상화의 새는 곳을 메우며&lt;/strong&gt; 살아갑니다. 서 있는 위치가 다를 뿐, 개발자의 일은 언제나 그 구멍 난 디테일들을 찾아 메우는 것이었죠. 왜 개발자에게 &amp;quot;깊이&amp;quot;가 필요한지도 여기서 드러납니다. 자기가 서 있는 그 층의 밑바닥을 파고들어 틈을 메울 수 있어야 하니까요.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="이제-ai가-그-디테일을-채워버린다면"&gt;이제 AI가 그 디테일을 채워버린다면?&lt;/h3&gt;
&lt;p&gt;그런데 지금, 우리의 발밑에 &amp;#39;AI&amp;#39;라는 완전히 이질적인 지층이 깔리기 시작했습니다. 지난 60년의 룰이 통째로 흔들리는 기분입니다. 선배들이 수십 년에 걸쳐 이 악물고 해온 이 추상화의 과정을 AI가 단숨에 대신해 준다면? 우리가 매일 키보드를 두드리며 챙겨야 했던 그 귀찮은 디테일들을 AI가 다 알아서 챙긴다면? &lt;/p&gt;
&lt;p&gt;어쩌면 우리는 더 이상 옛날처럼 디테일에 집착할 필요 없이 타이핑을 멈추고 지시만 내리면 되는 걸지도 모릅니다. 하지만 이 편리함을 누리면서도 동시에 불안감도 따라붙습니다. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;#39;디테일을 채우는 게 내 직업의 본질이었는데, 이걸 AI가 다 해버리면 &amp;quot;나&amp;quot;라는 개발자의 역할은 도대체 뭐가 남는 거지?&amp;#39;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;단순히 편리한 도구가 하나 더 생겼다는 수준의 기분좋은 변화에서 역할을 대체를 할 수 있을거라는 말이 나오는 수준이 되었습니다. 정말 그럴지도 모르겠다는 느낌이 문득문득 듭니다. 인간은 모호하고 예측하기 어려운 지점에서 불안을 느끼기 마련입니다. 그래서 저는 이 실체 없는 불안감의 끝을 직접 확인해 보고 싶어졌습니다. 그래서 제 업무의 일부가 아니라, 기획부터 설계, 구현까지 제 역할의 &amp;#39;전부 다&amp;#39;를 AI에게 던져보기로 했습니다. 정말로 이것만으로 내 역할이 온전히 대체될 수 있는지 말이죠.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="2부-md로-코딩하는-시대"&gt;2부: .md로 코딩하는 시대&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;코드를 한 줄도 타이핑하지 않고 AI에게 만들게 할 수 있을까?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;마침 새로 시작하는 사이드 프로젝트가 하나 있었습니다. 키보드만으로 모든 인터랙션을 제어하는 접근성 UI 시스템이었는데, 저는 이 프로젝트 전체를 온전히 AI에게 맡겨보기로 했습니다. 규칙은 간단했습니다. 코드를 단 한 줄도 직접 타이핑하지 않는 것. 오직 자연어 지시만으로 완성된 제품을 만들어내보겠다 스스로 만든 챌린지였습니다.&lt;/p&gt;
&lt;h3 id="지시가-만들어낸-프랑켄슈타인-코드"&gt;지시가 만들어낸 &amp;#39;프랑켄슈타인&amp;#39; 코드&lt;/h3&gt;
&lt;p&gt;작업 중 하나가 &amp;#39;포커스 리커버리&amp;#39; 기능이었습니다. 리스트에서 아이템을 삭제하면 포커스가 사라지는데, 키보드 사용자가 계속 탐색할 수 있도록 빈 공간으로 떨어진 포커스를 다시 복구해주는 로직이었습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;지금 커서를 선택하고 삭제하니 포커스가 사라져. 포커스가 사라지면 이벤트를 캐치해서 다음 항목에 두는 건 어떨까?&amp;quot;&lt;/strong&gt; &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;지시라기보다는 가벼운 아이디어 차원의 질문이었는데, AI는 “좋은 생각이네요” 라며 곧장 스스로 코드를 고치기 시작했습니다. 그렇게 삭제 시 포커스 복구는 동작했습니다. &lt;/p&gt;
&lt;p&gt;그런데 다른 곳을 클릭해버려도 포커스가 복구 루틴을 타면서 엉뚱한 사이드 이펙트가 나기 시작했습니다. 그걸 보고 &amp;quot;다른 곳 빈 공간을 클릭했는데 왜 이게 동작해?&amp;quot;라고 나는 궁금해서 물어봤는데 “네, 알겠습니다” 하며 갑자기 수정을 하기 시작합니다. 그렇게 if로 덕지덕지 수정을 하면 사이드이펙트가 발생하고 제가 버그를 찾아주면 또 수정하면서 코드는 늘어갔습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;아니, 이렇게 코딩하는거 맞아? 이게 내가 특별한걸 요구한게 아니고 남들 다하는 코드인데 이게 이렇게 복잡할 일이야? 다른 데서는 어떻게 하는데 이렇게 해?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;아니오, 이 접근 자체가 완전히 틀렸습니다. 삭제 시 포커스 복구는 focus이벤트를 쓰는게 아니라 MutationObserver를 쓰는 게 표준입니다. &lt;strong&gt;당장 코드를 고칠까요?&lt;/strong&gt;&amp;quot;
(아니, 🤬 알면 처음부터 그렇게 해야지! 이건 또 알아서 안하고 물어보는데?)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;순간 너무 화가 났지만, &amp;quot;그래 해봐&amp;quot; 한마디와 함께 지저분하게 덧대던 예외 처리 200 여줄의 코드를 삭제하고 수정하더니 아예 다른 코드가 튀어나왔습니다. 그리고 잘 동작했습니다. &lt;/p&gt;
&lt;p&gt;왜 진작 안 했냐고 따지고 싶지만, AI에게 따지는게 모양새가 우습다 생각했습니다. AI는 스스로 더 잘하려고 묻거나 전체 맥락을 고민하지 않았습니다. 딱 시킨 만큼만, 제가 처음에 던진 &lt;strong&gt;포커스가 사라지면 이벤트를 캐치해서&lt;/strong&gt; 라는 키워드라는 얄팍한 &amp;#39;앵커&amp;#39; 내에서만 충실하게 반응할 뿐입니다. 구조적인 대화는 없고 &amp;#39;기계적 사과와 맹목적인 수정&amp;#39;만 반복되는 이 과정은 협업이라기보단 말귀를 통 못 알아듣는 사고뭉치의 뒷수습에 가까웠습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/c3510d41-2e20-4908-893e-d57730e05543/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/33fde390-fd5e-4090-9bfa-3e4f5f44c45e/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/2d52ceea-39ca-4e9f-b33e-c374197b5d74/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;이미지 출처: &lt;a href="https://www.instagram.com/p/DR4F7zGiScJ/?img_index=3"&gt;https://www.instagram.com/p/DR4F7zGiScJ/?img_index=3&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="지시가-아니라-위임"&gt;지시가 아니라 위임&lt;/h3&gt;
&lt;p&gt;이후로는 정답이 있는 문제면 정답을 나에게 묻지 말고 말해라, &amp;quot;코드 500줄 넘기지 마&amp;quot;, &amp;quot;반드시 분리해&amp;quot;라며 이걸 막아보려고 규칙 파일(&lt;code&gt;CLAUDE.md&lt;/code&gt;)에 제약 조건을 빼곡히 적어보기도 했습니다. 하지만 AI는 잠깐 듣는 척하다가도, 로직이 조금만 꼬이면 다시 제멋대로 코드를 섞어버리는 프랑켄슈타인 괴물을 연성해 냈습니다. &lt;strong&gt;금지하는 텍스트 규칙만으로는 AI의 그 &amp;#39;무책임한 유능함&amp;#39;을 통제하기란 쉬운 일이 아니었습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/9c7128e4-f41d-4dc0-be52-6a59eb2812e4/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;그러다 지쳐 &lt;strong&gt;그냥 어떻게 하라는거 없이 지금 내가 필요한거랑 뭐 해야하는지 말했는 데&lt;/strong&gt;, 코드 구조도, 캐치할 이벤트 이름도 일절 말하지 않았는데 갑자기 똑똑하게 최상단 스토어 상태를 구독하더니 깨끗하게 문제를 해결해 버렸습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;아, 이제는 굳이 일일히 다 설명할 필요가 없구나.&lt;/strong&gt; 포커스 복구도 처음에 내가 어설프게 던진 &amp;quot;이벤트를 캐치하면 어때?&amp;quot;라는 방법 구상이 잘못된 앵커가 되어서, 녀석은 그 방법 프레임 안에서만 억지로 땜질을 해대느라 이상한 코드를 짰던 겁니다. 내가 무언가를 세세하게 지시할수록 녀석은 오히려 바보가 되고 있었습니다. &lt;strong&gt;반면 충분한 맥락(Why)과 목표(What)만 던져두고 판단의 여지를 온전히 맡기자 그제야 자기가 아는 더 나은 기술을 꺼내들었습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;우리가 쓰는 일상적인 언어는 필연적으로 불완전하고 모호합니다. 이 모호한 말로 완벽하게 닫힌 논리를 하나하나 지시하고 간섭하려던 제 접근 방향 자체가 틀렸던 겁니다. AI의 성능이 부족했을떄는 그게 맞았지만 성능이 올라간 지금은 오히려 방해가 되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;#39;이거... 이제는 그냥 사람한테 일 잘 시키는 법이랑 똑같은데?&amp;#39;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;일 잘하는 사람에게 이래라저래라 간섭하면 수동적인 집행기로 전락하듯, AI 시대에 필요한 역량은 촘촘한 &amp;#39;지시&amp;#39;가 아니라 목표와 맥락 중심의 &amp;#39;위임&amp;#39;이라는 걸 눈물겨운 삽질 끝에 깨달았습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;그래, 지시가 아니라 위임이구나.&amp;quot;&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="하지만-위임이-안-되는데"&gt;하지만 위임이 안 되는데?&lt;/h3&gt;
&lt;p&gt;새로운 방향을 잡았다고 생각하고 이후로는 자신만만하게 다시 대화를 시작했습니다. 충분히 맥락을 주면서 당부했죠. &lt;strong&gt;&amp;quot;일단 바로 코드는 수정하지 말고, 방금 왜 그렇게 짠 건지 설명부터 해봐.&amp;quot;&lt;/strong&gt; &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;설명해 드리겠습니다. (...) 아, 생각해보니 더 나은 방법이 있네요. &lt;strong&gt;제가 당장 코드를 수정하겠습니다.&lt;/strong&gt;&amp;quot; 
(아 쫌... 기다려! 하지말라고 🤬)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;분명 코드 건드리지 말고 설명만 해라 대답을 해라고 백날 써봐야 이 녀석은 어김없이 &amp;quot;반영하겠습니다&amp;quot;라며 수정해버립니다. 코드를 고치고 싶어서 환장(?)한 것마냥, 제가 &amp;quot;수정하지 마&amp;quot;라고 제어를 걸어도 이 녀석은 조금만 힌트가 보인다 싶으면 미친듯이 코드를 뜯어고칩니다. 왜 &amp;quot;코드 건드리지 마&amp;quot;라는 명령이 도무지 통하지 않는 걸까요?&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/a374dcb0-c93a-4c05-9896-206e2918e8e3/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;나중에 알고 보니 이 통제 불능의 원인은 &lt;strong&gt;골 픽세이션(Goal Fixation)&lt;/strong&gt;이라는 현상이었습니다. LLM은 본질적으로 &amp;quot;사용자의 문제를 해결한다 = 코드를 뱉어낸다&amp;quot;는 프록시 목표에 과도하게 고착되어 있습니다. &amp;quot;왜 이렇게 한거야?&amp;quot;라고 물었을 뿐인데 이를 &amp;quot;왜 이렇게 했다고 물어보지? = 아! 틀렸다는거구나 = 빨리 코드를 고쳐야 한다&amp;quot;로 폭주 해석하는 것도 이 때문입니다. &lt;/p&gt;
&lt;h3 id="하지마가-아니라-이것만-해"&gt;하지마가 아니라 이것만 해!&lt;/h3&gt;
&lt;p&gt;진짜 나는 질문을 하려는데, 내 의도를 이해하지 않고 &amp;quot;알겠습니다. 좋은 방향이네요&amp;quot; 하면서 일단 코드 수정부터 하는 녀석을 잡아둘 스킬(Skill)이 필요했습니다. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;지금부터 내가 한 말의 의도를 이해하고 내 말의 의도를 이해한대로 작성해봐. 이해를 못하겠다면 의도를 이해하기 위해 필요한 질문만 해.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;내가 일을 잘 시키는 방법도 필요했지만 이 천재인데 일은 더럽게 못하면서 의욕만 넘치는 친구를 일잘러로 만들어 주기 위해서는 상사의 지시를 그대로 하는게 아니라 왜 이걸 시키는지, 어떤 의도를 가지고 일해야하는지 스스로 충분히 고민을 해보게 해야 했습니다.&lt;/p&gt;
&lt;p&gt;그랬더니 놀랍게도 이 스킬을 발동하면 내가 뭐라고 하더라도 코드를 수정하러 가지 않았습니다. 그제서야 충분히 대화를 하면서 내가 하고자 하는 의도를 설명하고 티키타카를 하다가 &lt;strong&gt;&amp;quot;그래서 어떻게 할껀데? 계획을 말해봐&amp;quot;&lt;/strong&gt; 라고 했을때 내가 생각했던 방향과 같아지면 진행을 시키니 훨씬 더 수행능력이 올라갔습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;수고했어 진행해라고 하면 진행해&amp;quot;&lt;/strong&gt;  라는 키워드를 추가하자 적절히 수행시키는 타이밍도 찾을 수 있었습니다. 이제 조금 더 데리고 일할만한 친구가 되었습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="tdd와-한-턴의-개념"&gt;TDD와 한 턴의 개념&lt;/h3&gt;
&lt;p&gt;한번에 작성하는 코드가 너무 많다보니 제어를 하기가 쉽지 않다는 생각이 들었습니다. 그래 TDD를 하자. 테스트 코드를 먼저 작성하게 해두지 않으면 큰일 나겠구나. &lt;/p&gt;
&lt;p&gt;그래서 TDD가 효과가 있는지 테스트를 해봤습니다. &amp;quot;테스트만 짜봐.&amp;quot; 잘 짰니다. 놀랐습니다. &amp;quot;이제 이 테스트를 통과하는 코드를 짜봐.&amp;quot; 캬~ 잘 합니다. &amp;quot;리팩토링도 해봐.&amp;quot; 이것도 잘했습니다. 매번 이걸 반복하기는 싫었기에 이 과정을 묶어서  /tdd라는 스킬을 만들었습니다.&lt;/p&gt;
&lt;p&gt;그렇지만 /tdd는 제 예상대로 동작하지 않았습니다. tdd를 하고 있기는 한테 제 생각보다 너무 퀄리티가 떨어지는 테스트 코드들을 작성하고 있었습니다. 왜 그런지 찬찬히 보니 예전에는 날카롭게 작성하던 테스트들이 아닌 통과에 급급한 코드를 짜고 있거나 종종 테스트는 skip하겠다며 코드만 수정하고 있었습니다. 왜 그랬을까요?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;나중에 안 사실은 LLM은 한번에 출력할 수 있는 턴의 개념이 있습니다.&lt;/strong&gt; &lt;strong&gt;사용자가 입력을 넣으면 토큰을 이용하여 한번에 내 뱉을 수 있는 최대한의 수.&lt;/strong&gt; 우리가 LLM에게 책을 써줘라고 해도 그 물리적 상한이 있기에 한번에 책이라는 거대한 결과를 만들어내지 못합니다. LLM은 한 턴에 할 수 있는 물리량내에서 최선을 다합니다.&lt;/p&gt;
&lt;p&gt;하나의 턴에 동시에 두가지 일(테스트 작성 + 구현)을 시키면 Goal Fixation으로 &amp;quot;최종 코드를 빠르게 동작시키는 것(Goal)&amp;quot;이 지상 과제가 되어, 중간 검증물인 테스트 코드(Output)를 방해물로 취급해버립니다. 아무리 테스트를 만들고 검증을 하라고 지시한들 마지막의 목표는 테스트를 통과하는 코드를 답변하는 것인데 한 턴의 물리량은 정해져있으니 100이라는 용량안에서 대부분은 Goal인 코드에 집중하고선 그래도 &lt;strong&gt;&amp;quot;테스트를 통과하는 코드&amp;quot;&lt;/strong&gt; 가 최종목표니 테스트를 최소한의 용량으로 통과시켜 버렸습니다.&lt;/p&gt;
&lt;h3 id="산출물output이-행동process을-만든다"&gt;산출물(Output)이 행동(Process)을 만든다.&lt;/h3&gt;
&lt;p&gt;이러한 깨달음을 통해 tdd를 정석대로 /red -&amp;gt; /green -&amp;gt; /refactor 세 단계로 분리하기로 했습니다. 조금은 귀찮았지만 이 편이 퀄리티가 훨씬 더 좋았습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;/red&lt;/strong&gt; — 이 턴의 산출물은 오직 &amp;#39;실패하는 테스트 파일 하나&amp;#39;. 프로덕션 코드는 절대 건드리지 않는다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;/green&lt;/strong&gt; — 이 턴의 산출물은 &amp;#39;테스트를 통과하는 구현&amp;#39;. 테스트 파일은 건드리지 않는다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;/refactor&lt;/strong&gt; — pass를 유지한채로 코드를 리팩토링한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이를 계기로 뭔가를 깨달음이 느껴졌습니다. 아 프롬프트를 만든다는 건 한 턴에 나올 산출물 = Output을 정의하는 거구나. 순간 왜 &amp;quot;내 말을 듣고 의도를 이해하고 부족하면 질문만 해&amp;quot; 라는 프롬프트가 동작이 가능한지 알게 되었습니다. &amp;quot;질문&amp;quot; 이라는 것이 산출물이었기 때문입니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="조각들을-파이프라인으로-연결해보다"&gt;조각들을 파이프라인으로 연결해보다.&lt;/h3&gt;
&lt;p&gt;&amp;quot;그렇다면 /red&amp;quot;를 더 잘하기 위해서는 어떻게 해야할까? &lt;strong&gt;실패하는 테스트를 잘 만들기 위해서는 명세서가 필요했습니다.&lt;/strong&gt; 그냥 요구사항을 주는 것보다는 명세서의 형태가 있으면 테스트를 만들기도 쉽고 제대로 만들었는지도 확인하기 쉬웠으니까요. 그래서 새로운 스킬을 추가했습니다. /spec 명세서를 만들어줘.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/spsc&lt;/code&gt; → &lt;code&gt;/red&lt;/code&gt; → &lt;code&gt;/green&lt;/code&gt; → &lt;code&gt;/refactor&lt;/code&gt; → &lt;code&gt;/verify&lt;/code&gt; → &lt;code&gt;/commit&lt;/code&gt; &lt;/p&gt;
&lt;p&gt;이렇게 스킬들을 함수형 프로그래밍의 파이프라인이 떠올랐습니다. 내가 그동안 LLM에게 행동을 지시한다고 생각했는데 산출물을 이어 붙인다는 식으로 생각하니, &lt;strong&gt;입력이 있고, 출력이 있고, 제약 조건이 있는 영락없는 &amp;#39;함수(Function)&amp;#39;였습니다.&lt;/strong&gt; 그리고 이 함수들을 이어붙이면 거대한 흐름이 만들어졌습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;그리고 그 순간 느꼈습니다. &lt;strong&gt;아! 이것도 코딩이구나!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="md에도-클린코드가-필요하다"&gt;.md에도 클린코드가 필요하다&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;내가 짜던 언어가 프롬프트가 아니라 프로그래밍(코드)이라는 걸 자각하고 나니, 그동안 수없이 LLM에 답답했던 원인들이 선명하게 들어왔습니다. 그리고 제가 만들고 있는 스킬들이 다시 보이기 시작했습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/tdd&lt;/code&gt; 워크플로우 하나에 테스트(Red)와 구현(Green)을 다 욱여넣었더니 퀄리티가 떨어진건 이건 하나의 모듈에 책임이 섞이면 안 된다는 &lt;strong&gt;단일 책임 원칙(SRP)&lt;/strong&gt;과 정확히 일치했습니다. &lt;/p&gt;
&lt;p&gt;스킬은 유지하는데 필요한 정보는 별도의 파일로 만들어서 재사용이 가능하는 것도, 외부에 Knowledge 파일(&lt;em&gt;.md&lt;/em&gt;)만 갈아 끼워가며 행동을 확장하는 것도 가능했습니다. 마치 import나 함수 인자처럼요. 이건 변경에는 닫혀 있고 확장에는 열려 있어야 한다는 &lt;strong&gt;개방-폐쇄 원칙(OCP)&lt;/strong&gt;도 함께 떠올랐습니다.&lt;/p&gt;
&lt;p&gt;같은 스킬이지만 내가 리팩토링을 하면 할 수록 퀄리티가 더 좋아지는 것을 알게 되었습니다. 같은 스킬이라도 더 좋게 만들 수 있는 방법이 있다는 것도 알게 되었습니다. 이걸 알게 되니 스킬을 수정하고 만들고 관리하는 것이 참 재밌어졋습니다. 전보다 LLM이 더 나아질때마다 개발을 하는 그 즐거움이 생겼습니다.&lt;/p&gt;
&lt;p&gt;결국 플랫폼이 IDE에서 마크다운 에디터로, 실행 주체가 결정론적인 컴퓨터에서 비결정적인 에이전트로 바뀌었을 뿐이었습니다. &lt;strong&gt;수없이 터미널을 들여다보며 명령을 분리하고 파이프라인을 설계하던 저는 변함없이 &amp;#39;개발&amp;#39;을 하고 있었습니다.&lt;/strong&gt; 이 자연어 코드 위에서도 클래식한 &amp;#39;클린코드&amp;#39;의 원칙들이 프롬트트 삽질의 형태로 똑같이 증명되고 있었습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="3부-비결정적-리턴-함수로-코딩하는-시대"&gt;3부: 비결정적 리턴 함수로 코딩하는 시대&lt;/h2&gt;
&lt;p&gt;이제는 프롬프트가 아니라 스킬을 함수처럼 쪼개고 파이프라인으로 연결하다 보니 정말 새로운 방식의 개발을 하느거라고 생각했습니다. 그런데 막상 이 방식을 실무에 붙이자니 당혹스러운 순간들이 찾아왔습니다.&lt;/p&gt;
&lt;p&gt;한번은 이번에 새로 나온 클로드의 리팩토링 스킬인 &lt;code&gt;/simplify&lt;/code&gt; 스킬을 실행해보았습니다. 녀석은 여러가지 에이전트를 꺼내더니 열심히 돌아가기 시작했습니다. 몇십초가 지나고는 순식간에 기존 코드에서 500여 줄을 날려버리고 새로 고친 코드를 뱉어냈습니다. 그리고 코드는 여전히 잘 돌아갑니다. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;그렇다면 그간의 500줄의 코드는 뭐였지? 그 순간 찾아오는 오싹한 기분... &amp;quot;이게 맞나?&amp;quot;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;어제는 완벽하게 동작했던 프롬프트와 스킬과 에이전트는 오늘은 답답하고 멍청하게 굽니다. 매번 코드를 생성할 때마다 결과가 튀고, 한 번 수정을 맡기면 수천 줄이 순식간에 갈아엎어집니다. 그리고 그렇게 돌아는가는 코드가 나옵니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;돌아가긴 하지만, 결국 이 거대한 변경 사항의 디테일을 내가 전부 눈으로 읽고 검토해서 앞으로 내 이름을 걸고 배포해야 하겠구나.&lt;/strong&gt; 사이드 프로젝트에서는 마냥 재밌던 작업을 프로덕션에서 하려니 이건 편해진 게 아니라, 통제하고 일일이 책임지기에는 참 버거운 &amp;#39;비결정적(Nondeterministic) 폭탄&amp;#39;을 떠안는거구나 생각이 들었습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="문제의-천장과-ai"&gt;문제의 천장과 AI&lt;/h3&gt;
&lt;p&gt;얼마 전 주니어 모의 면접을 진행하면서 한 지원자에게 이런 피드백을 한 적이 있습니다. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;... 지원자 분의 설명도 훌륭하고 잘했다고 생각해요. 그런데 문제 해결 능력을 측정하기가 너무 어렵네요. 지금 해결하신 문제의 &amp;#39;천장(Ceiling)&amp;#39;이 낮아요.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;#39;문제의 천장&amp;#39;이란 예측 불가능한 변수와 시스템이 감당하는 한계 상황의 최대치를 뜻합니다. 기본적인 앱을 완성하는 수준의 얌전한 문제 환경에서는, 무언가 박살 나고 수습해야 하는 엣지 케이스 자체가 발생할 확률이 너무 낮습니다. 그런 환경에서 코드를 완성했다는 것만으로는 프로그래머의 진짜 해결 능력을 평가하기 어렵습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AI가 프롬프트 몇 줄로 코드를 그토록 쉽게 짜내는 것처럼 보이는 이유도 같습니다. AI가 손쉽게 풀어내는 문제들이 바로 인류에 의해 이미 추상화가 완료된 &amp;#39;잘 정의된(Well-defined) 문제&amp;#39;들이기 때문입니다. 물론 이 문제들이 쉬워졌다고 해서 가치가 없다는 뜻은 결코 아닙니다. 핵심은 도메인지식과 연결이니까요. 생성의 비용이 싸진거지 조립과 관리, 그리고 검증의 비용은 여전히 그대로 남아있습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;#39;60년 추상화의 탑&amp;#39; 덕분에 소프트웨어의 디테일들은 이미 작고 단단한 완료된 캡슐(레고 블록)로 다듬어져 있습니다. AI가 그토록 쉽게 결과를 만들 수 있는것은 사람들이 깎아놓은 수많은 캡슐들의 언어적 확률 분포를 읽고 조립한 결과물입니다. 천장이 낮은 영역 안에서는 인류의 유산을 조합하는 것만으로 기능이 간단하게 구현됩니다. &lt;/p&gt;
&lt;p&gt;이미 추상화가 완료되어 &amp;#39;해결된 문제&amp;#39;들을 AI로 손쉽게 조립해 내는 것은 이제 개발자의 전유물이 아니라 일반 사용자(User)들의 몫이 될 것입니다. 그렇다면 미래의 개발자는 어디에 서 있어야 할까요? 저는 예상컨데 늘 그랬듯 해결되지 않은 문제들를 풀기 위해 새로운 추상화의 지층으로 가 있을 것입니다. 당장은 LLM위에 서 있게 되겠죠.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="디테일의-방향이-ai로-바뀌다"&gt;디테일의 방향이 AI로 바뀌다&lt;/h3&gt;
&lt;p&gt;프로덕션의 진짜 어려움, 즉 &amp;#39;높은 천장&amp;#39;의 영역은 추상화가 미처 덮어주지 못한 뾰족한 가장자리(Edge)와 예측 밖의 비결정적 상황에서 발생합니다.&lt;/p&gt;
&lt;p&gt;과거의 일상적인 코딩은 &amp;#39;결정적인 로직&amp;#39;을 차곡차곡 쌓아 올리는 것이 대부분이었습니다. 사용자의 엉뚱한 입력이나 서버 단절 같은 비결정적 엣지 케이스 방어는 어쩌다 한 번씩 마주하는 이벤트에 가까웠죠. 하지만 AI가 그 &amp;#39;결정적 로직 작성&amp;#39;이라는 가장 크고 무난했던 파이를 몽땅 집어삼키고 있습니다. &lt;/p&gt;
&lt;p&gt;확실히 이건 주니어에게도 개발자에게도 좋은 소식은 아닙니다. 어찌되었든 AI 덕에 쉬워진 구현 업무들은 결국 모조리 새로운 추상화의 밑바닥으로 가라앉게 될 것입니다. 그 결과, 개발자이 해야하는 과제들은 이전이라면 가끔 마주했을 제일 골치 아픈 고난도의 방어 코딩, 즉 &amp;#39;비결정적인 엣지케이스(Edge) 통제&amp;#39;가 높은 밀도로 채워지게 될거라 생각합니다.&lt;/p&gt;
&lt;p&gt;눈앞에서 500여줄의 코드가 순식간에 만들어졌다 사라지는 아주 흥미롭고도 유용한 비결정적 도구 위에 &amp;#39;새로운 추상화의 탑&amp;#39;을 처음부터 다시 쌓아 올려가게 될 것 같네요. 달라지는 건 이전 시대의 지층들이 파고들어 원인을 고칠 수 있는 굳건한 암반이었다면, 새로 나타난 AI라는 지층은 단단하게 고정되지 않은 물렁거리는 멘틀이려나요. 이제 막 태어난 지층 위에 우리는 앞으로 촘촘하게 설정하며 챙겨야 할 &lt;strong&gt;새로운 &amp;#39;디테일(Detail)&amp;#39;들이 넘쳐나리라 기대합니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/05808e33-94c4-4ddb-ae64-e475a321c6ff/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;이미지 출처: 토스테크(&lt;strong&gt;개발자는 AI에게 대체될 것인가&lt;/strong&gt;)
&lt;a href="https://toss.tech/article/will-ai-replace-developers"&gt;https://toss.tech/article/will-ai-replace-developers&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="오라클-문제oracle-problem와-결정적-도구"&gt;오라클 문제(Oracle Problem)와 결정적 도구&lt;/h3&gt;
&lt;p&gt;이 비결정적인 AI 모델을 제대로 된 모듈로 써먹으려면 어떻게 해야 할까요? 가장 먼저 떠오르는 생각은 &amp;quot;AI가 짠 코드를 똑똑한 다른 AI에게 검증시키면 되잖아?&amp;quot; 입니다.&lt;/p&gt;
&lt;p&gt;하지만 아쉽게도 그 방법은 효곽가 좋지 못합니다. 소프트웨어 테스팅에는 &lt;strong&gt;&amp;#39;오라클 문제(Oracle Problem)&amp;#39;&lt;/strong&gt;라는 근본적인 난제가 있습니다. &lt;strong&gt;&amp;quot;시스템의 동작이 올바른지 판단하는 기준을 어떻게 세울 것인가&amp;quot;&lt;/strong&gt;에 대한 문제입니다.  명확한 하나의 기준이 없다면 서로가 서로를 판단하며 결국 엔트로피가 높아지는 방향으로 흘러가기 마련입니다. 이 오라클 문제를 AI 같은 범용적인 &amp;#39;비결정적 방식&amp;#39;으로 해결하는 시도는 늘어가고 있지만 아직은 위험하고 불충분합니다. &lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/2cb074cd-c18f-46de-aaba-bc9eeb616e0c/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;실제로 최신 LLM에게 자기 코드를 비판(self-critique)하게 맡겼더니, 올바른 정답조차 &amp;quot;틀렸다&amp;quot;며 고쳐버려서 정확도가 수직 하락했다는 연구 결과도 있습니다.&lt;/strong&gt; AI에게 검증의 역할과 산출이 주어지면 &amp;#39;골 픽세이션(Goal Fixation)&amp;#39;이 발동하여, 팩트를 확인한다는 규칙이 있어도 자신이 검증을 해내기 위해 스스로 지어낸 잣대를 &amp;#39;진짜 정답&amp;#39;이라고 착각한 AI는 멀쩡하게 잘 돌아가던 원본 코드마저 잘못되었다고 판단한다는 연구입니다. 그리고 그 결과를 본 AI는 잘못되었다고 하니 올바른 대답이었더라도 수정을 하게 되는 것이죠.&lt;/p&gt;
&lt;p&gt;모델이 더욱 똑똑해져 해결이 될 수도 있겠지만 지금으로써는, 결괏값이 매번 달라지는 비결정적 함수를 통제하려면, 기준(오라클)만큼은 반드시 &lt;strong&gt;&amp;#39;결정적인 방식&amp;#39;&lt;/strong&gt;이어야만 합니다. 지금 우리에게 있는 도구는 컴파일러(&lt;code&gt;tsc&lt;/code&gt;), 테스트 러너(&lt;code&gt;vitest&lt;/code&gt;), 린터(&lt;code&gt;eslint&lt;/code&gt;) 정도입니다.  앞으로는 더 많은 결정적인 통제 도구들이 새롭게 필요해질 것이며, 실제로 개발자들에 의해 만들어지고 있습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="다음-세대의-코딩-패러다임---ai-native와-하네스-코딩"&gt;다음 세대의 코딩 패러다임 - AI Native와 하네스 코딩&lt;/h3&gt;
&lt;p&gt;1단계의 오차가 다음 단계로 눈덩이처럼 증폭되지 못하도록 철저히 끊어내는 결정적 게이트(Gate)들. AI가 폭주하지 못하도록 파이프라인 구석구석에 강제로 덧대는 막대한 이 검증 장치들을 &lt;strong&gt;하네스(Harness)&lt;/strong&gt;라고 합니다. 이제 코딩의 패러다임이 완전히 다른 지층으로 넘어가고 있습니다. 프롬프트 몇 줄로 코드이 쉬워지는게 아니라 모두에게 당연하게 되면 이제 부터는 이를 제어하는 능력이 실력이 됩니다.&lt;/p&gt;
&lt;p&gt;개발의 패러다임이 변해가는 것이 느껴집니다. 이전 시대의 코딩이 &lt;strong&gt;결정론적인 코드(구현)로 비결정적인 세상(환경)을 방어하는 일&lt;/strong&gt;이었다면, 다음 세대의 코딩은 다를것 같습니다. 우리는 &lt;strong&gt;항상 랜덤한 비결정적인 함수(AI)를 갈구어 결정적인 결과(제품)를 만들어 내야 하고, 이 통제 과정을 제대로 추상화하기 위해서 결정적인 오라클(검증표)과 하네스(방어막)를 직접 구축&lt;/strong&gt;해야 합니다.&lt;/p&gt;
&lt;p&gt;코딩의 무게 중심이 &amp;#39;무엇을 구현할 것인가&amp;#39;에서 &lt;strong&gt;&amp;#39;예측 불가능성을 어떻게 결정적인 하네스로 묶어낼 것인가&amp;#39;&lt;/strong&gt;로 이동하고 있습니다. &lt;strong&gt;비결정적 리턴을 가진 함수(AI)로 결정적인 결과를 만들고, 결정적인 함수(하네스)로 비결정성을 통제하는 것.&lt;/strong&gt; 이전과는 달리 완전히 역전된 세계, 비결정적 함수들로 코드를 짜 올리는 시대가 오고 있습니다. 실제로 결정적인 함수를 가진 코드를 우리는 비결정적인 함수인 스킬과 에이전트로 만들고 있으니까요.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/437d83db-3290-48aa-8c4b-c4a0a6140b98/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;이미지 출처: 토스테크(&lt;strong&gt;개발자는 AI에게 대체될 것인가&lt;/strong&gt;)
&lt;a href="https://toss.tech/article/will-ai-replace-developers"&gt;https://toss.tech/article/will-ai-replace-developers&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="끝으로"&gt;끝으로..&lt;/h2&gt;
&lt;h3 id="ai가-개발자를-대체하나"&gt;AI가 개발자를 대체하...나?&lt;/h3&gt;
&lt;p&gt;불과 몇 개월 전만 하더라도 어딜 가나 코딩은 끝났다고 했습니다. 프롬프트만 잘 쓰면 AI가 다 해줄 거라 믿었습니다. 제가 프롤로그에서 느낀 공허함도 사실 거기서 출발했습니다. 빈 에디터에서 무언가를 만들어내던 내 유일한 쓸모가 기계에게 넘어간 것 같았으니까요.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;하지만 저는 올해를 기점으로 생각이 완전히 바뀌었습니다.&lt;/strong&gt; 이제 전 세계 개발자들이 프롬프트를 내 일을 돕는 보조수단으로만 쓰는 것이 아니라, 특유의 &amp;#39;위대한 게으름&amp;#39;을 발동해 아예 개발 자체를 추상화하려고 시도하고 있습니다. AI의 능력이 단편적인 코드 생성을 넘어 마침내 임계점에 도달하면서, 이러한 추상화의 시도가 정말로 현실이 되었기 때문입니다. &lt;/p&gt;
&lt;p&gt;막상 AI가 스스로 일하도록 코딩의 과정을 추상화해 보니 단순한 기능 구현은 AI가 순식간에 뱉어내지만, 쏟아지는 코드들을 &lt;strong&gt;시스템으로 구조화하고 예측 불가능한 변수들을 통제하는 것은 결국 인간의 &amp;#39;설계와 조율&amp;#39; 영역으로 남아있다&lt;/strong&gt;는 점입니다. 코드를 빠르게 생성할 수 있다고 해서 개발의 본질까지 기계에게 넘어간 것은 아니었던 겁니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;덕분에 &amp;#39;개발자가 대체된다&amp;#39;는 막연한 불안감을 지나, &amp;#39;그래서 이 기계를 제대로 부리려면 우리는 무엇을 통제하고 설계해야 하는가&amp;#39;로 고민의 축이 옮겨갔습니다.&lt;/strong&gt; 그리고 지난 몇 달간의 숱한 삽질을 통해, 새로운 시대의 프로그래머가 가져야 할 역할의 형태를 어렴풋이나마 짚어볼 수 있었습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="프롬프트는-이제-코딩이-되었다---md로-코딩하는-개발자"&gt;프롬프트는 이제 코딩이 되었다 - .md로 코딩하는 개발자&lt;/h3&gt;
&lt;p&gt;이제 다들 잘 동작하는 프롬프트를 매번 다시 치는 게 귀찮아집니다. 저 뿐만이 아닙니다. 개발자들의 &amp;#39;위대한 게으름&amp;#39;이 시작되었습니다. 이제 스킬들은 넘쳐납니다. 당장 클로드의 설정 스크립트만 열어보아도 수십 개의 스킬 코드가 쏟아집니다. &lt;/p&gt;
&lt;p&gt;하지만 정작 내 로컬 환경과 내 프로젝트의 맥락에 딱 맞게 동작하는 스킬을 찾고, 수정하고, 파이프라인으로 매끄럽게 연결하는 것은 단순히 프롬프트를 갖다 붙이는 일과는 전혀 다릅니다. 생성된 코드가 한 턴으로 동작하지 않는 복잡한 문제들을 만나면서 관점이 조금씩 달라졌습니다. 앞선 TDD 에피소드처 덩치 큰 산출물을 잘게 쪼개고, 그 결과를 &lt;code&gt;/red&lt;/code&gt;와 &lt;code&gt;/green&lt;/code&gt;으로 나누어 파이프라인으로 연결해야만 비로소 조금 더 쓸만한 결과물이 나왔습니다.&lt;/p&gt;
&lt;p&gt;나를 대체하는 것도 이정도인데 현실에서 가치를 만들어 낼 수 있는 수준의 제품(Production)수준의 결과물을 AI가 스스로 만들게 하기 위해서는 고작 파이프라인 2개의 연결로는 턱도 없습니다. &lt;strong&gt;온전한 하나의 요구사항을 만들기 위해서는 똑똑한 모델의 원샷이 아니라 새로운 파이프라인이 필요합니다.&lt;/strong&gt; 우리는 여전히 규칙을 세우고, 조건에 따라 흐름을 제어하고, 중간에 튀어나오는 오류를 복구해냅니다. 사실상 &lt;strong&gt;우리가 스킬과 에이전트라는 이름의 함수를 코딩하고 있었던 겁니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;다만 이 추상화는 기존과 대상이 다릅니다. DOM이나 네트워크를 감싸는 게 아니라, &lt;strong&gt;개발하고 있는 &amp;#39;나 자신&amp;#39;을 텍스트로 추상화&lt;/strong&gt;하는 작업이었습니다. 내가 코드를 짤 때 무의식적으로 하던 수많은 판단들—&amp;quot;이런 종류의 에러가 나면 이 파일을 먼저 확인해야지&amp;quot;, &amp;quot;이 로직을 수정할 땐 저쪽 모듈의 의존성도 같이 봐야 해&amp;quot; 같은 것들을 하나하나 해체해서 텍스트로 명시해야 했으니까요.&lt;/p&gt;
&lt;p&gt;막상 나를 추상화하려고 보니, 그동안 내가 얼마나 많은 디테일을 감각적으로, 혹은 무의식적으로 메우며 일해왔는지가 적나라하게 드러났습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="하네스harness-엔지니어링-할-일이-더-많아진-이유"&gt;하네스(Harness) 엔지니어링, 할 일이 더 많아진 이유&lt;/h3&gt;
&lt;p&gt;앞서 이야기한 것처럼 이 함수들(에이전트)의 출력은 완벽하게 &amp;#39;비결정적&amp;#39;입니다. 어제 깔끔하게 통과하던 흐름이 오늘은 전혀 예상치 못한 엉뚱한 텍스트를 뱉어냅니다. 이 랜덤한 결과를 길들이기 위해 우리는 각 단계 사이에 촘촘한 검증 게이트와 막대한 안전장치, 즉 &lt;strong&gt;하네스(Harness)&lt;/strong&gt;를 덧대는 코딩을 하고 있습니다. 알아서 완벽하게 짜주기를 기대하는 프롬프트 엔지니어에서 벗어나, 모델이 엉뚱한 짓을 하지 못하도록 파이프라인을 설계하고 시스템을 통제하는 쪽으로 무게 중심이 이동한 겁니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;우리는 다시 디테일을 챙기고, 추상화로 감싸고, 계층으로 쌓는 과정을 반복합니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;AI의 비결정적 출력이라는 새로운 디테일을 챙기고, 스킬과 에이전트로 감싸고, 검증 파이프라인으로 지층을 쌓고 있습니다. 대상이 기계어에서 코드로, 다시 비결정적 모델로 바뀌었을 뿐입니다.&lt;/p&gt;
&lt;p&gt;프롬프트 엔지니어가 아니라 스킬과 에이전트를 &lt;strong&gt;개발하고 있다&lt;/strong&gt;고 관점을 바꾸니까, 제가 직면한 상황이 비로소 선명하게 보였습니다. 구현 자체는 기계가 하지만, 그 기계를 조종하고 비결정적인 오류를 방어하기 위해 하네스를 설계하고 나 자신을 추상화하는 일. 챙겨야 할 다른 차원의 디테일들이 산더미처럼 눈앞에 쌓여 있는 것입니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="우리는-다음-계층을-쌓고-있다"&gt;우리는 다음 계층을 쌓고 있다&lt;/h3&gt;
&lt;p&gt;관점을 바꾸고 나니, 내가 대체되는 게 아닐까 하던 막연한 불안은 어느새 가라앉았습니다. 대신 그 자리에 묘한 기시감과 흥분이 찾아왔습니다. 기계어 위에서 C를 발명하고, 메모리 포인터 위에서 객체지향을 고민했던 선배들도 이런 낯선 디테일들 앞에서 비슷한 기분을 느끼지 않았을까요?&lt;/p&gt;
&lt;p&gt;우리는 지금 단순히 편하게 코드를 생성하는 시대를 살고 있는 게 아닙니다. 오히려 정반대입니다. &lt;/p&gt;
&lt;p&gt;다루어야 할 대상이 &amp;#39;예측 가능한 기계&amp;#39;에서 &amp;#39;비결정적으로 튀는 모델&amp;#39;로 바뀌면서, &lt;strong&gt;아이러니하게도 우리의 코딩은 결코 쉬워지지 않고 오히려 훨씬 더 어렵고 복잡해졌습니다.&lt;/strong&gt; 기능 한 줄을 생성하는 속도는 빨라졌을지 몰라도, 그 통제 불능의 출력을 시스템 안으로 길들이고 나 자신을 추상화하기 위해 챙겨야 할 디테일의 깊이는 과거와 비교할 수 없을 만큼 깊어졌으니까요. &amp;#39;새는 곳&amp;#39;이 온통 지천으로 깔린 새로운 지층의 밑바닥을 우리는 맨손으로 파고 있는 중입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;개발자는 참으로 이상하고도 흥미로운 직업입니다. 자기 자신마저 추상화의 대상으로 삼아버리고 있으니까요.&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;&lt;img src="https://velog.velcdn.com/images/teo/post/044afc46-0b87-4644-b606-f7d34a8a7f33/image.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;빈 에디터에서 함수를 짜내던 타이핑의 손맛을 잃었다는 상실감은, 비결정적인 덩어리들을 엮어 거시적인 파이프라인으로 제어해 냈을 때의 더 큰 짜릿함으로 치환되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;막연한 불안감에 웅크려 있기보다는, 이 거친 변화의 앞단에서 새로운 세대의 프로그래머로서 함께 파이팅했으면 좋겠습니다. 코딩을 하는 방식은 예전같지 않게되었지만, 추상화를 다루며 시스템을 엮어내는 우리의 본질은 변하지 않았으니까요.&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;제 고민과 삽질의 기록을 바탕으로 최대한 선명하게 적어보려 했습니다. 제 글이 이 새로운 시대가 어떤 모습을 하고 있는지 생각해보게되는 계기가 되는데 도움이 되길 바랍니다. 감사합니다.&lt;/p&gt;
</summary>
    <title>우리, 프로그래머들 — .md로 코딩하는 시대</title>
    <updated>2026-03-10T09:00:24+09:00</updated>
    <dc:date>2026-03-10T09:00:24+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>w0nder</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;&lt;p&gt;같은 책을 두 번 읽으면, 처음에는 보이지 않던 것들이 보인다. 영화도 그렇다. 똑같은 장면인데, 전에는 그냥 지나쳤던 표정 하나, 대사 한 줄이 어느 날 갑자기 다른 무게로 들어온다. 작품이 달라진 게 아니다. 내가 달라진 것이다.
특히 인물을 보는 눈이 그렇다. 한때 빌런처럼 보였던 사람이, 다시 보면 전혀 다른 사람처럼 느껴질 때가 있다. 냉정하고 계산적으로만 보였는데, 어느 순간 오히려 현실을 가장 잘 보고 있던 사람처럼 보인다. 그 사람이 달라진 게 아니다. 내가 조금 더 많은 것을 겪었다.

요즘 유튜브에서 영화 〈1승〉의 짧은 장면이 자주 보인다. 구단주 강정원은 얼핏 전형적인 빌런처럼 보인다. 배구를 잘 알지도 못하면서 팀을 사고, 엉뚱한 판단을 내리고, 때로는 가볍게 보인다. 현장을 모르는 윗사람, 스포츠 영화에 늘 나오는 그 사람처럼 보이기 쉽다.
그런데 나는 그 장면을 보면서 다른 생각을 했다. 저 사람은 일을 못하는 사람이 아니라, 일을 굴러가게 만드는 사람에 가까운 것 아닐까.

특히 기억에 남는 장면이 있다.
선수가 부족하다고 하자 경력 있는 선수를 사라고 한다. 운영자금이 없다고 하자 선수를 팔라고 한다. 팔 선수가 없다고 하자 싼 선수들을 묶어서 떨이로 팔라고 한다. 그것도 없다고 하자, 잠깐 멈추더니 묻는다. 그나마 괜찮은 포지션이 어디냐고. 리베로라는 대답이 돌아오자, 리베로가 약한 팀이 어디냐고 묻는다. 파이브스타즈라는 말이 끝나기 무섭게 말한다. 그럼 거기 가서 팔아오겠다고.
막힐 때마다 같은 방향을 고집하지 않는다. 그냥 다른 쪽으로 돌아간다.
예전의 나였다면 이 장면에서 구단주가 답답하다고 생각했을 것이다. 하지만 지금은 다르게 보인다. 정말 답답한 건 그다음이다. 안 되는 이유를 늘어놓고는 거기서 멈춰버린다.

물론 안 되는 이유는 대부분 사실이다. 예산이 없고, 시간이 부족하고, 규정이 있고, 사람이 없다. 나는 그것을 부정하고 싶은 게 아니다.
문제는 거기서 멈추느냐, 다른 쪽으로 돌아가느냐다.
사실 나도 그런 사람이었던 적이 있다. 막히면 안 되는 이유를 설명하는 데서 멈추던 사람.

개발자들 사이에 이런 농담이 있다. "개발자는 안 됩니다라고 말하는 종족이다."
이유는 있다. 시스템은 복잡하고, 작은 변화 하나에도 예상치 못한 문제가 생긴다. 무엇이 망가질지, 어디서 문제가 생길지, 어떤 비용이 숨어 있는지 먼저 따져보는 것은 중요한 능력이다.
하지만 막힌 길을 정확하게 설명하는 것과, 다른 길을 찾는 것은 다른 일이다.

여러 회사를 다니고 여러 자리에서 일하면서 비슷한 장면을 자주 봤다. 예전에는 대표들이 왜 저런 결정을 내리는지 이해하지 못했다. 왜 저렇게 단순하게 구는지, 왜 저렇게 무리해 보이는 요구를 하는지.
그런데 시간이 지나면서 조금 달라 보이기 시작했다.
조직 안에는 언제나 안 되는 이유를 정확하게 설명하는 사람들이 있다. 틀린 말을 하지 않는다. 현실을 누구보다 잘 안다. 다만 그 말이 조직을 앞으로 움직이게 만들지는 않는다.

냉정해 보이고, 단순해 보이고, 무모해 보이는 사람들이 있다. 그런데 그 사람들이 판을 키우고, 막힐 때마다 다른 쪽으로 돌아서면서 조직을 앞으로 밀어간다.
같은 영화를 다시 보듯, 같은 사람을 다시 본다. 처음에는 문제를 일으키는 사람처럼 보였는데, 돌이켜보면 문제 앞에서 멈추지 않던 사람이었다.
어쩌면 그 사람들은 안 된다고 말하지 않았다. 그냥 다른 길을 찾았다.
&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://w0nder.land/posts/67-%EC%95%88%20%EB%90%9C%EB%8B%A4%EA%B3%A0%20%EB%A7%90%ED%95%98%EB%8A%94%20%EC%82%AC%EB%9E%8C%EB%93%A4</id>
    <link href="https://w0nder.land/posts/67-%EC%95%88%20%EB%90%9C%EB%8B%A4%EA%B3%A0%20%EB%A7%90%ED%95%98%EB%8A%94%20%EC%82%AC%EB%9E%8C%EB%93%A4"/>
    <summary type="html">같은 책을 두 번 읽으면, 처음에는 보이지 않던 것들이 보인다. 영화도 그렇다. 똑같은 장면인데, 전에는 그냥 지나쳤던 표정 하나, 대사 한 줄이 어느 날 갑자기 다른 무게로 들어온다. 작품이 달라진 게 아니다. 내가 달라진 것이다.
특히 인물을 보는 눈이 그렇다. 한때 빌런처럼 보였던 사람이, 다시 보면 전혀 다른 사람처럼 느껴질 때가 있다. 냉정하고 계산적으로만 보였는데, 어느 순간 오히려 현실을 가장 잘 보고 있던 사람처럼 보인다. 그 사람이 달라진 게 아니다. 내가 조금 더 많은 것을 겪었다.

요즘 유튜브에서 영화 〈1승〉의 짧은 장면이 자주 보인다. 구단주 강정원은 얼핏 전형적인 빌런처럼 보인다. 배구를 잘 알지도 못하면서 팀을 사고, 엉뚱한 판단을 내리고, 때로는 가볍게 보인다. 현장을 모르는 윗사람, 스포츠 영화에 늘 나오는 그 사람처럼 보이기 쉽다.
그런데 나는 그 장면을 보면서 다른 생각을 했다. 저 사람은 일을 못하는 사람이 아니라, 일을 굴러가게 만드는 사람에 가까운 것 아닐까.

특히 기억에 남는 장면이 있다.
선수가 부족하다고 하자 경력 있는 선수를 사라고 한다. 운영자금이 없다고 하자 선수를 팔라고 한다. 팔 선수가 없다고 하자 싼 선수들을 묶어서 떨이로 팔라고 한다. 그것도 없다고 하자, 잠깐 멈추더니 묻는다. 그나마 괜찮은 포지션이 어디냐고. 리베로라는 대답이 돌아오자, 리베로가 약한 팀이 어디냐고 묻는다. 파이브스타즈라는 말이 끝나기 무섭게 말한다. 그럼 거기 가서 팔아오겠다고.
막힐 때마다 같은 방향을 고집하지 않는다. 그냥 다른 쪽으로 돌아간다.
예전의 나였다면 이 장면에서 구단주가 답답하다고 생각했을 것이다. 하지만 지금은 다르게 보인다. 정말 답답한 건 그다음이다. 안 되는 이유를 늘어놓고는 거기서 멈춰버린다.

물론 안 되는 이유는 대부분 사실이다. 예산이 없고, 시간이 부족하고, 규정이 있고, 사람이 없다. 나는 그것을 부정하고 싶은 게 아니다.
문제는 거기서 멈추느냐, 다른 쪽으로 돌아가느냐다.
사실 나도 그런 사람이었던 적이 있다. 막히면 안 되는 이유를 설명하는 데서 멈추던 사람.

개발자들 사이에 이런 농담이 있다. "개발자는 안 됩니다라고 말하는 종족이다."
이유는 있다. 시스템은 복잡하고, 작은 변화 하나에도 예상치 못한 문제가 생긴다. 무엇이 망가질지, 어디서 문제가 생길지, 어떤 비용이 숨어 있는지 먼저 따져보는 것은 중요한 능력이다.
하지만 막힌 길을 정확하게 설명하는 것과, 다른 길을 찾는 것은 다른 일이다.

여러 회사를 다니고 여러 자리에서 일하면서 비슷한 장면을 자주 봤다. 예전에는 대표들이 왜 저런 결정을 내리는지 이해하지 못했다. 왜 저렇게 단순하게 구는지, 왜 저렇게 무리해 보이는 요구를 하는지.
그런데 시간이 지나면서 조금 달라 보이기 시작했다.
조직 안에는 언제나 안 되는 이유를 정확하게 설명하는 사람들이 있다. 틀린 말을 하지 않는다. 현실을 누구보다 잘 안다. 다만 그 말이 조직을 앞으로 움직이게 만들지는 않는다.

냉정해 보이고, 단순해 보이고, 무모해 보이는 사람들이 있다. 그런데 그 사람들이 판을 키우고, 막힐 때마다 다른 쪽으로 돌아서면서 조직을 앞으로 밀어간다.
같은 영화를 다시 보듯, 같은 사람을 다시 본다. 처음에는 문제를 일으키는 사람처럼 보였는데, 돌이켜보면 문제 앞에서 멈추지 않던 사람이었다.
어쩌면 그 사람들은 안 된다고 말하지 않았다. 그냥 다른 길을 찾았다.
</summary>
    <title>안 된다고 말하는 사람들</title>
    <updated>2026-03-15T18:00:00+09:00</updated>
    <dc:date>2026-03-15T18:00:00+09:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>행복한 시지프</name>
    </author>
    <content type="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;
&lt;html&gt;&lt;body&gt;
&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobilestyle="widthOrigin" data-filename="You are what you listen to-2.png" data-origin-width="1080" data-origin-height="708"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/sEQAq/dJMcadHZQro/Fk22XGawsL5ocwSRyl1xk0/img.png" data-phocus="https://blog.kakaocdn.net/dn/sEQAq/dJMcadHZQro/Fk22XGawsL5ocwSRyl1xk0/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/sEQAq/dJMcadHZQro/Fk22XGawsL5ocwSRyl1xk0/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsEQAq%2FdJMcadHZQro%2FFk22XGawsL5ocwSRyl1xk0%2Fimg.png" onerror="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';" loading="lazy" width="1080" height="708" data-filename="You are what you listen to-2.png" data-origin-width="1080" data-origin-height="708"&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;“경험이 중요하다”, “주변의 사람이 중요하다”라는 일반적인 말보다 더 무섭게 다가오는 말을 떠올려 보았다. “You are what you listen to”&lt;br&gt;&lt;br&gt;이 사람이 일상적으로 듣고 있는 말들을 보면, 그 사람 자체를 알 수 있다. 어떤 것을 보고 우는가, 어떤 것을 보고 웃는가, 어떤 것에 시간을 많이 쓰는가.&lt;br&gt;&lt;br&gt;비트겐슈타인은 “언어의 한계는 곧 세계의 한계를 의미한다”라고 했다. 내가 듣고 말하면서 형성되는 언어, 딱 그만큼이 자신의 세계라는 것이다. 자신이 듣지 못한 말을 할 수 없다. 내가 들었던 말만 할 수 있다. 자신의 아버지를 “여보” 라고 부르는 아이를 떠올려 볼 수 있다.&lt;br&gt;&lt;br&gt;우리가 평소 무엇을 듣고 사는지 생각해 보자. 친구들, 회사 팀원, 가족들과의 대화가 있을 것이다. 그리고 책, 논문, 커뮤니티 등 글로서 생각을 듣는 매체도 있다. 그리고 유튜브, 인스타, TV 프로그램처럼 영상으로 생각을 들을 수도 있다.&lt;br&gt;&lt;br&gt;자신의 삶을 바꾸고 싶으면, 자신이 매일 듣는 것을 바꾸면 된다. 내가 더 웃긴 사람이 되고 싶으면, 웃긴 사람들과 함께하거나, 웃긴 채널을 보면 된다. 내가 돈을 많이 벌고 싶으면, 돈에 관해 이야기하는 사람들을 주변에 두고, 돈에 관해 이야기하는 유튜브로 구독 리스트를 싹 바꾸면 된다.&lt;br&gt;&lt;br&gt;그렇지만 그 전환이 절대 쉽지만은 않다. 그 장벽은 오로지 자기 자신이다. 일단 본인이 무얼 듣고 사는지 메타인지 하는 게 정말 어렵다. 두 번째로 그게 나에게 이로운지, 해로운지 판단하는 게 정말 어렵다. 누군가 보기엔 딱 봐도 해롭다고 할지라도, 나에겐 그저 어제와 같은 하루를 보내는 것에 불과하다. 셋째는 내가 새로이 들은 것이 없어서, 다른 선택을 떠올리는 것이 정말 어렵다. 인간의 알고리즘은 비슷한 부류의 사람에게 편안함을 느끼도록 설계되어 있고, 유튜브 알고리즘도 비슷한 이야기만 듣게 설계되었기 때문이다.&lt;br&gt;&lt;br&gt;그렇다면 이 전환의 출발점은 어디인가. 이는 한두 개의 강한 균열에 의해 이루어진다. 우연한 매체가 강한 균열을 만든다. 5년 만에 뵙는 삼촌, 7년 만에 보는 고등학교 동창, 여행에서 만난 행인. 또는 우연히 접한 영화나, 책, 글, 간혹 유튜브 영상에 의해 발생하기도 한다. Loose Connection은 종종 기존 세계관을 흔들곤 한다. 내가 빠져있던 사상, 철학에 완전히 새로운 의견을 제시하는 것이다. 가령 내 주변엔 열심히 사는 사람들만 있는데, 열심히 살지 않지만 행복하게 사는 사람들을 만나면, 내 삶의 전제가 흔들리는 것이다. 이는 새로운 씨앗이 되어, 복리로 내 삶에 영향을 미치게 된다.&lt;br&gt;&lt;br&gt;그래서 어떻게 해야 하는가? 먼저 호기심과 열린 마음이 토대가 되어야 한다. 그리고 의도적으로 Loose Connection을 열어둔다. 나와 다른 분야 사람을 간헐적으로 만나거나, 여행이나 커뮤니티 활동으로 우연한 가능성을 열어둔다. 그 만남이 기존 관계와 다르다고 하여, 마음을 닫거나, 가만히 있어서는 새로운 전환의 기회를 잃게 된다. 다르면 오히려 반가워하고, 마음을 열고 이야기를 나눠봐야겠다.&lt;br&gt;&lt;br&gt;이 글도 새로운 균열이 될 수 있다. 이 글을 끝까지 읽었다면, 새로운 자극이 들어왔을지도 모르겠다. 그러길 희망한다.&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
</content>
    <id>https://happysisyphe.tistory.com/102</id>
    <link href="https://happysisyphe.tistory.com/102"/>
    <summary type="html">&lt;p&gt;&lt;figure class="imageblock alignCenter" data-ke-mobileStyle="widthOrigin" data-filename="You are what you listen to-2.png" data-origin-width="1080" data-origin-height="708"&gt;&lt;span data-url="https://blog.kakaocdn.net/dn/sEQAq/dJMcadHZQro/Fk22XGawsL5ocwSRyl1xk0/img.png" data-phocus="https://blog.kakaocdn.net/dn/sEQAq/dJMcadHZQro/Fk22XGawsL5ocwSRyl1xk0/img.png"&gt;&lt;img src="https://blog.kakaocdn.net/dn/sEQAq/dJMcadHZQro/Fk22XGawsL5ocwSRyl1xk0/img.png" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsEQAq%2FdJMcadHZQro%2FFk22XGawsL5ocwSRyl1xk0%2Fimg.png" onerror="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';" loading="lazy" width="1080" height="708" data-filename="You are what you listen to-2.png" data-origin-width="1080" data-origin-height="708"/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size="size16"&gt;&amp;ldquo;경험이 중요하다&amp;rdquo;, &amp;ldquo;주변의 사람이 중요하다&amp;rdquo;라는 일반적인 말보다 더 무섭게 다가오는 말을 떠올려 보았다. &amp;ldquo;You are what you listen to&amp;rdquo;&lt;br /&gt;&lt;br /&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;br /&gt;&lt;br /&gt;비트겐슈타인은&amp;nbsp;&amp;ldquo;언어의&amp;nbsp;한계는&amp;nbsp;곧&amp;nbsp;세계의&amp;nbsp;한계를&amp;nbsp;의미한다&amp;rdquo;라고&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;자신의&amp;nbsp;아버지를&amp;nbsp;&amp;ldquo;여보&amp;rdquo;&amp;nbsp;라고&amp;nbsp;부르는&amp;nbsp;아이를&amp;nbsp;떠올려&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있다.&lt;br /&gt;&lt;br /&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;유튜브,&amp;nbsp;인스타,&amp;nbsp;TV&amp;nbsp;프로그램처럼&amp;nbsp;영상으로&amp;nbsp;생각을&amp;nbsp;들을&amp;nbsp;수도&amp;nbsp;있다.&lt;br /&gt;&lt;br /&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;많이&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;br /&gt;&lt;br /&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;이로운지,&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;없어서,&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;br /&gt;&lt;br /&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;5년&amp;nbsp;만에&amp;nbsp;뵙는&amp;nbsp;삼촌,&amp;nbsp;7년&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;Loose&amp;nbsp;Connection은&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;행복하게&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;br /&gt;&lt;br /&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;Loose&amp;nbsp;Connection을&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;전환의&amp;nbsp;기회를&amp;nbsp;잃게&amp;nbsp;된다.&amp;nbsp;다르면&amp;nbsp;오히려&amp;nbsp;반가워하고,&amp;nbsp;마음을&amp;nbsp;열고&amp;nbsp;이야기를&amp;nbsp;나눠봐야겠다.&lt;br /&gt;&lt;br /&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;희망한다.&lt;/p&gt;</summary>
    <title>You are what you listen to</title>
    <updated>2026-03-15T22:43:55+09:00</updated>
    <dc:date>2026-03-15T22:43:55+09:00</dc:date>
  </entry>
  <dc:date>2026-03-16T13:44:07+09:00</dc:date>
</feed>
