<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>코딩수련장</title>
    <link>https://11001.tistory.com/</link>
    <description>(17~19) Unity/Unreal Engine 게임 프로그래머

(20~21) System Administrator ___________
                                                                            
(22~) React 웹 프론트앤드 개발자 __________
깃헙 : https://github.com/snowman95</description>
    <language>ko</language>
    <pubDate>Mon, 13 Apr 2026 07:21:36 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>snowman95</managingEditor>
    <image>
      <title>코딩수련장</title>
      <url>https://tistory1.daumcdn.net/tistory/3223191/attach/2ab40c9c34694336803eced5954f3bc4</url>
      <link>https://11001.tistory.com</link>
    </image>
    <item>
      <title>[개발자 이야기] AI 에게 일을 위임하고 나는 딸깍하는 회사 라이프를 꿈꾸다</title>
      <link>https://11001.tistory.com/294</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-size: 1.44em; letter-spacing: -1px; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif;&quot;&gt;매우 저조한 AI 활용도&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리 회사에서는 클로드 코드는 지원하지 않고 (지원하다가 잠정 중단), 커서는 지원하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가&amp;nbsp;팀&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;회사마다 AI 활용도가 천차만별인데요.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;openAI 의 사례&lt;/b&gt;처럼 AI 가 일 다하는 곳도 있고, &lt;b&gt;저희 팀 처럼 나를 약간 도와주는 도구?&lt;/b&gt; 정도로 쓰는 곳도 많습니다.&lt;/p&gt;
&lt;figure id=&quot;og_1774022365791&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[AI] 완전 자율 소프트웨어 구축 시스템 개발 경험과 과정에 대한 글&quot; data-og-description=&quot;open AI 에서 공개한 글에 대해 요약하고 제 생각을 추가한 글입니다. 지난 5개월 동안 수동으로 작성한 코드가 단 한 줄도 없이 소프트웨어 제품의 내부 베타 버전을 개발하고 배포했습니다.이 제&quot; data-og-host=&quot;11001.tistory.com&quot; data-og-source-url=&quot;https://11001.tistory.com/290&quot; data-og-url=&quot;https://11001.tistory.com/290&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/mwMtw/dJMb9kT2bTi/varHE6mouMduGxXNko2fF1/img.png?width=800&amp;amp;height=436&amp;amp;face=0_0_800_436,https://scrap.kakaocdn.net/dn/7dCCU/dJMb9jOl9WS/mviGmYlKK94EPkzbWTccE1/img.png?width=800&amp;amp;height=436&amp;amp;face=0_0_800_436,https://scrap.kakaocdn.net/dn/dBPyCu/dJMb9bv1vbh/cQm3hNiWKtaROnmMTh1WZ0/img.png?width=2816&amp;amp;height=1536&amp;amp;face=0_0_2816_1536&quot;&gt;&lt;a href=&quot;https://11001.tistory.com/290&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://11001.tistory.com/290&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/mwMtw/dJMb9kT2bTi/varHE6mouMduGxXNko2fF1/img.png?width=800&amp;amp;height=436&amp;amp;face=0_0_800_436,https://scrap.kakaocdn.net/dn/7dCCU/dJMb9jOl9WS/mviGmYlKK94EPkzbWTccE1/img.png?width=800&amp;amp;height=436&amp;amp;face=0_0_800_436,https://scrap.kakaocdn.net/dn/dBPyCu/dJMb9bv1vbh/cQm3hNiWKtaROnmMTh1WZ0/img.png?width=2816&amp;amp;height=1536&amp;amp;face=0_0_2816_1536');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[AI] 완전 자율 소프트웨어 구축 시스템 개발 경험과 과정에 대한 글&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;open AI 에서 공개한 글에 대해 요약하고 제 생각을 추가한 글입니다. 지난 5개월 동안 수동으로 작성한 코드가 단 한 줄도 없이 소프트웨어 제품의 내부 베타 버전을 개발하고 배포했습니다.이 제&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;11001.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대충 한 이정도.. 활용도였던 거 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 검색 엔진 대신에 물어보는 용도&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 반복되는 코드나 간단한 코드 수정 정도&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 코드 리뷰 용도&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저희 회사 서비스는 전세계에 서비스 중인데요. 서비스되는 국가들에 대해 다르게 처리되는 것들이 너무 너무 많기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;검토하고 확인하고 재확인하고 기억해내고 ..&lt;/b&gt; &lt;b&gt;이 과정들이 제 일의 거의 80%는 됩니다&lt;/b&gt;. 가끔 제가 개발자인가 잊어버릴 때도 많습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옛날에 삼성에 있을때는 작업 계획서 쓰고 엔지니어들 출입 관리하고 일정 잡고.. &lt;b&gt;내가 스케줄 매니저인가?&lt;/b&gt; 그런 생각 많이 했는데 요즘 비슷한 생각이 드는거 보면 확실히 제가 큰 회사로 다시 돌아온 느낌이 드네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;AI 활용도가 떨어진 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쨌든 &lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;저희 팀은 정말로 AI 도입이 정말 많이 늦었고 활용도가 저조한데요. 그 이유는 이렇게 뽑아보았습니다.&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 개발자의 일 자체가 코드에 집중되기 보다는 기획 검토, 정리, 분류 등 코드 보다는&lt;b&gt; 문서 작업에 많은 리소스가 들기 때문&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 글로벌 서비스라서 &lt;b&gt;코드가 복잡도가 매우 높다&lt;/b&gt;는 점.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 다들 10년+ 의 괴물 시니어 경력자라서 &lt;b&gt;AI 에게 일을 시켜봤는데 별로더라.. 내가 하는게 더 낫다는 생각&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 전사적으로&lt;b&gt; AI 를 밀어주는 부서나 사람이 없음.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;AI 는 개발자의 위기가 아닌 성장 기회&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼에도 제가&lt;b&gt; AI 를 억지로라도 많이 쓰고 활용하는 분위기&lt;/b&gt;를 만들고자 한 이유는&lt;b&gt; 개발자는 성장을 멈추면 안되기 때문&lt;/b&gt;인데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금의 시대가&lt;b&gt; AI를 원하는 시대&lt;/b&gt;가 되었기 때문에 좋든 싫든 우리 개발자들은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;AI 를 통해 성장&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;해야만 하는 상황에 놓여있기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마치 AI 를 거부하는 것은 난 디지털 싫은데? 아날로그가 좋은데? 지금도 충분히 잘 되는데 굳이? ㅋㅋ 하는 것과 마찬가지라는겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AI 는 개발자에게 숙제를 뛰어 넘어 하나의 큰 과업입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저도 처음에는 AI 거부하기도 하고 방관하기도 하고 한 1년? 2년 가까이 좀 더 지켜보자는 마음가짐 이었는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 저의 성장 발판이라는걸 스스로 깨닫고나서 그때 부터 미친듯이 밤낮으로 공부해보고 돈 쏟아부으면서 이것 저것 다&amp;nbsp;&lt;span style=&quot;text-align: start;&quot;&gt;사용해보고&lt;/span&gt;&amp;nbsp;따라가려고 발악했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;AI 도입 시도&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;누구나 AI 에 대한 글을 쓰고 공유할 수 있는&lt;b&gt; 슬랙 공개 채널&lt;/b&gt;을 먼저 만들었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;누군가 열심히 활동해주면 좋겠지만 그럴 가능성이 낮기 때문에 사실상 제가 리딩할 마음가짐으로 만들었고,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 를 배우고 관심을 가질 수 있는 글을 공유하다보니 팀원들도 같이 AI 사용 사례들을 올리면서 관심을 보여주셨습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근에는 AI 에 특히 관심이 많았던 분들과 업무 시간 중에 1시간 정도 &lt;b&gt;OpenClaw&lt;/b&gt; 를 설치하고 메신저에 연동하는 작업 것을 실습하는 시간을 가져보았고, 그렇게 만들어진 &lt;b&gt;OpenClaw&lt;/b&gt; 를 슬렉 채널에서 말을 걸 수 있게 연동을 해두었더니 다들 개발자 아니랄까봐 이것저것 기능을 붙이더군요. 재미있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 시간적인 여유만 있으면 좀 더 양질의 자료를 준비하고 많은 것들을 공유하고 싶은데 요즘 일에 파묻혀있다보니.. 쉽지 않네요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTGwRq/dJMcagx3nNe/AQhJBCkK8HQSHIpJPaLpt1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTGwRq/dJMcagx3nNe/AQhJBCkK8HQSHIpJPaLpt1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTGwRq/dJMcagx3nNe/AQhJBCkK8HQSHIpJPaLpt1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTGwRq%2FdJMcagx3nNe%2FAQhJBCkK8HQSHIpJPaLpt1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;380&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;AI 개발 workflow 를 만들자&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 개인이 AI 를 사용하는 것을 넘어서 &lt;b&gt;팀 전체에서 활용&lt;/b&gt;되었으면 좋겠다는 생각이 들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;회사에서 개발자가 하는 일을 (일부분 이라도) AI 에게 떠넘기는것&lt;/b&gt;을 꿈꿨습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 와중에 AI 부서에서 현업 10년+ 풀스텍 AI 개발자로 활동 중인 지인을 통해 좋은 블로그를 소개 받았고, AI 활용 사례 등을 공유 받았습니다. (동서남북 &amp;zwj;♂️)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말해서 &lt;b&gt;AI 에게 요구사항을 전달하여 코드를 편집하게 하는 과정&lt;/b&gt;에 대해 연구하고, 그것을 &lt;b&gt;workflow&lt;/b&gt;(순서대로 처리하는 구조화된 업무 방식)으로 만들어야 한다. 그런 내용이었습니다.&lt;/p&gt;
&lt;figure id=&quot;og_1774023276345&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Boris Tane&quot; data-og-description=&quot;The research-plan-implement workflow I use to build software with Claude Code, and why I never let it write code until I've approved a written plan.&quot; data-og-host=&quot;boristane.com&quot; data-og-source-url=&quot;https://boristane.com/blog/how-i-use-claude-code/&quot; data-og-url=&quot;https://boristane.com/blog/how-i-use-claude-code/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bh00mI/dJMb8SpHaV6/lpn0gZsHW8gISKA8FyARcK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/z95AR/dJMb8WMoMQl/fSRI5tF4PYGi7KXG7nKfu0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/Rot1y/dJMb8WMoMQm/b0kscZg9FgCXTedbbbDSN1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://boristane.com/blog/how-i-use-claude-code/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://boristane.com/blog/how-i-use-claude-code/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bh00mI/dJMb8SpHaV6/lpn0gZsHW8gISKA8FyARcK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/z95AR/dJMb8WMoMQl/fSRI5tF4PYGi7KXG7nKfu0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/Rot1y/dJMb8WMoMQm/b0kscZg9FgCXTedbbbDSN1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Boris Tane&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The research-plan-implement workflow I use to build software with Claude Code, and why I never let it write code until I've approved a written plan.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;boristane.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[글 요약] Cloudflare 출신 엔지니어의 클로드 코드 사용 방법에 대한 글입니다.여기서 소개하는 workflow 는 &lt;br /&gt;&lt;u data-stringify-type=&quot;underline&quot;&gt;&lt;b&gt;&quot;문서로 작성된 계획을 검토후 승인하기 전까지 절대로 코드 작성을 시키지 않는다&quot;&lt;/b&gt; &lt;/u&gt;라는 대원칙을 사용하여 계획과 실행을 분리했습니다.&lt;br /&gt;1. 기본 개념은 &lt;b&gt;Garbage in, garbage out.&lt;/b&gt; plan은 코드만큼 중요하다. (쓰레기 계획은 쓰레기를 반환)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 좋은 &lt;b&gt;plan&lt;/b&gt;을 짜려면 &lt;b&gt;research&lt;/b&gt;도 잘 되어야 한다. (프로젝트 내의 코드가 어떻게 짜여있는지에 대한 연구)&lt;br /&gt;3. &lt;b&gt;plan&lt;/b&gt;을 매우 꼼꼼하게 검토하고 &lt;span style=&quot;text-align: start;&quot;&gt;허락없이 절대 코드를 편집하지 않는다. (코딩하고 검토하는게 아니라 검토를 다 끝내고 코딩)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;이 아이디어를 CLAUDE.md 또는 커서 rules/workflow.mdc 로 옮겨서 &lt;b&gt;항상 컨텍스트에 포함&lt;/b&gt;시키게 했습니다.&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;개발자가 요구사항을 전달하면 코드베이스를 &lt;b&gt;연구&lt;/b&gt;하고&lt;b&gt; 계획&lt;/b&gt;을 세운 다음에 제&lt;b&gt; 승인&lt;/b&gt;을 받을 때 까지&lt;b&gt; 계획 수정을 반복&lt;/b&gt;하고 승인을 받으면 코드로 옮기는 매우 단순한 흐름입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tzen9/dJMcacbnuwj/j0OrGfgTm1JqdQ1ItkKGK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tzen9/dJMcacbnuwj/j0OrGfgTm1JqdQ1ItkKGK1/img.png&quot; data-alt=&quot;출처: boristane.com&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tzen9/dJMcacbnuwj/j0OrGfgTm1JqdQ1ItkKGK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ftzen9%2FdJMcacbnuwj%2Fj0OrGfgTm1JqdQ1ItkKGK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;712&quot; height=&quot;166&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;166&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: boristane.com&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Git 브랜치 전략도 그렇고 이런 것도 엄청 복잡한 흐름 보다는 결국 &lt;b&gt;사람이 이해할 수 있는 단순한 형태를 사용하는게 가장 강력&lt;/b&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고&lt;b&gt;&amp;nbsp;세팅도 수 초 이내에 끝낼 수 있을 정도로 매우 간단&lt;/b&gt;해야합니다.&lt;br /&gt;일단 TUI 환경(cmux 를 추천)에서 &lt;b&gt;cursor cli&lt;/b&gt; 설치하고 &lt;b&gt;~/.cursor/&lt;/b&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;b&gt;rules/workflow.mdc&lt;/b&gt; 파일에 위의 규칙을 작성하는 것 까지만 하면 세팅은 끝납니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1774075706645&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl https://cursor.com/install -fsS | bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 이 내용만 보면 그냥 AI Agent 돌리는 거랑 크게 다를 거 없는데? Plan 모드 쓰면 되지않나? 랄프 루프 돌리면 되지 않나? 싶지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 workflow 는 &lt;b&gt;모든 작업 산출물을 문서화 하여 영구적으로 저장&lt;/b&gt;한다는 차이가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서들은 개인&amp;nbsp;&lt;b&gt;클라우드 저장소&lt;/b&gt;로 올려놓고 해당 폴더를 &lt;span style=&quot;text-align: start;&quot;&gt;&lt;b&gt;옵시디언&lt;/b&gt; 노트로 열어서 연결된 링크를 쉽게 오가면서 확인하는 그러한 형태로 사용할 수 있겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1164&quot; data-origin-height=&quot;658&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CfIgN/dJMcad2m4mp/6snrs7eid9u6wJrcsIoOLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CfIgN/dJMcad2m4mp/6snrs7eid9u6wJrcsIoOLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CfIgN/dJMcad2m4mp/6snrs7eid9u6wJrcsIoOLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCfIgN%2FdJMcad2m4mp%2F6snrs7eid9u6wJrcsIoOLk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1164&quot; height=&quot;658&quot; data-origin-width=&quot;1164&quot; data-origin-height=&quot;658&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;눈치 채신 분들도 있겠지만 &lt;b&gt;~/.cursor/rules 경로를 사용하여 전역 프로젝트에 공통 적용하는 방식&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깃 저장소에 올리는게 아니고 &lt;b&gt;개인 별로 사용&lt;/b&gt;하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;왜냐면 작업 할 때마다 발견되고 연구된 새로운 내용이 실시간으로 계속 업데이트 될 테니까요&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기획서는 MCP 써서 누구나 받아올 수 있고 코드베이스는 공유되고 있으니 각자 AI Agent 가 읽고 이해하는게 빠릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;b&gt;작업 판단에 중대한 영향을 끼치는 문서나 설계도 같은 것들만 별도로 공유&lt;/b&gt;해서 받아쓰는 정도로 충분하지 않은가 싶습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;QA 이슈 해결 workflow 를 만들자&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&amp;nbsp;저희 회사의 경우에는 새로운 기능 스펙 개발에 대해서는 이와 같은 사이클을 가지고 있는데요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;기획 Jira 티켓 -&amp;gt; 티켓 내 기획서 확인 -&amp;gt; 개발자가 기획서 내용을 읽고 이해, 정리 -&amp;gt; 개발 jira 티켓 생성 -&amp;gt; 코드 변경 계획 -&amp;gt; 코딩 -&amp;gt; PR 생성 -&amp;gt; 코드 리뷰&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&amp;gt; 개발 환경 배포 -&amp;gt; QA 진행 -&amp;gt; (이슈 발생시) QA jira 티켓 발행 -&amp;gt; 이슈 내용을 읽고 이해, 정리 -&amp;gt; 코드 변경 계획 -&amp;gt; 코딩 -&amp;gt; PR 생성 -&amp;gt; 코드 리뷰 -&amp;gt; 배포&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;525&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rFJ3z/dJMcagLDlP5/CAnc7RRdOHbRKKu7hUKddK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rFJ3z/dJMcagLDlP5/CAnc7RRdOHbRKKu7hUKddK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rFJ3z/dJMcagLDlP5/CAnc7RRdOHbRKKu7hUKddK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrFJ3z%2FdJMcagLDlP5%2FCAnc7RRdOHbRKKu7hUKddK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;942&quot; height=&quot;525&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;525&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실은 첫 단계부터 AI 가 해야하지만, 요즘 제가 하고 있는 진행중인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;장기&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;프로젝트는 한창 &lt;b&gt;QA 단계&lt;/b&gt;에서 돌고 있는 상태라..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당장은 QA 단계에 대한 workflow 가 필요한 상황입니다. (단계 별로 만들지 못해서 참 슬프네요 현실이 그러하네요..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;QA 진행 -&amp;gt; (이슈 발생시) QA jira&lt;span&gt;&amp;nbsp;&lt;/span&gt;티켓&lt;span&gt;&amp;nbsp;&lt;/span&gt;발행 -&amp;gt; 이슈 내용을 읽고 이해, 정리 -&amp;gt; 코드 변경 계획 -&amp;gt; 코딩 -&amp;gt; PR 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;QA jira&lt;span&gt;&amp;nbsp;&lt;/span&gt;티켓&lt;span&gt; &lt;/span&gt;이슈 내용을 읽고 이해, 정리&lt;span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 AI Agent 가 티켓 내용을 읽어 오는 것 부터 가능하게 해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;.cursor/mcp.js&lt;/span&gt;&lt;span&gt;on 에&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;b&gt; atlassian MCP 서버를 등록&lt;/b&gt;합니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;(node v18 사용 시 오류 발생하여 강제로 node v20 경로를 읽게 변경했습니다. 대부분은 그냥 npx 로도 충분할듯)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1774025873612&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;mcpServers&quot;: {
    &quot;atlassian&quot;: {
      &quot;command&quot;: &quot;/Users/사용자/.nvm/versions/node/v20.20.0/bin/npx&quot;,
      &quot;args&quot;: [&quot;-y&quot;, &quot;mcp-remote&quot;, &quot;https://mcp.atlassian.com/v1/mcp&quot;]
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하고 웹 브라우저가 열려서 인증을 받게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 cursor cli 를 설치 했기에&amp;nbsp; 터미널 열고 agent 입력 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP 사용 ㄱㅊ? 하고 물어봅니다. yes !&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;티켓 유형에 대해 설명해주고나서 해결안됨, 검토중 상태의 QA 티켓를 모두 가져와서 문서에 표로 정리해달라고 시켰습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2490&quot; data-origin-height=&quot;790&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oVLbW/dJMcaaEEhle/jimOnzllg4OELqGXSzcso0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oVLbW/dJMcaaEEhle/jimOnzllg4OELqGXSzcso0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oVLbW/dJMcaaEEhle/jimOnzllg4OELqGXSzcso0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoVLbW%2FdJMcaaEEhle%2FjimOnzllg4OELqGXSzcso0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2490&quot; height=&quot;790&quot; data-origin-width=&quot;2490&quot; data-origin-height=&quot;790&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 해보니까 지라에서 이미지나 영상은 못 가져오고 &lt;span style=&quot;text-align: start;&quot;&gt;담당자 마다 티켓 내용 형식이 조금씩 다르는 것 때문에&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;text-align: start;&quot;&gt;AI 가 이해할 수 있는 상태가 아닌 상태로 가져온 경우들도 있더군요.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;이럴 때는 어쩔 수 없이 사람이 개입해서 이건 어떤 내용이야~ 이렇게 해줘야만 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;티켓을 읽어와서 문서에 한번 정리하는 과정이 불필요해 보일 수도 있겠지만&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;text-align: start;&quot;&gt; 굳이 이 과정을 넣은 이유가 이것 때문입니다!&amp;nbsp;&lt;br /&gt;(티켓의 요구사항을 보완하는 단계)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쨋든 이제 테이블 표에 이쁘게 티켓 번호, 이슈, 확인내용, 원인, 해결, 브랜치명, PR 링크, 진행상황 등이 쭉 정리되어서 보여집니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;이제 코딩을 위한 workflow 를 태우기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;티켓 하나씩 차례로 &lt;b&gt;research -&amp;gt; plan&lt;/b&gt; 과정을 시켜보았습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드베이스를 연구한 뒤에 md 파일을 남겨놓고, &lt;b&gt;연구된 코드베이스를 기반으로 plan 을 세우니 매우 똑똑하게 작업&lt;/b&gt;을 해주더군요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cursor 에도 plan 모드가 있는데 이 커스텀 workflow 는 문서를 남긴다는 장점과 plan 에서 원하는 부분에 인라인으로 메모를 남기고 다시 계획을 세우게 만드는 루프를 돌릴 수 있어서 훨씬 효과적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 문제점은 &lt;b&gt;cursor 자체적으로도 workflow 를 가지고 있기 때문에 제 workflow 를 무조건적으로 잘 지켜주지 않습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계속 지속해서 &quot;내 승인이 없으면 코드 변경하지마&quot;, &quot;지금 단계 까지만 진행해야해&quot; 와 같이 지시를 내려야하는 불편함이 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;일단.. 진행시켜!&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;477&quot; data-origin-height=&quot;458&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCsJA9/dJMcafTtFB3/Yaz8LCA47kBVQWQ7hwiKLk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCsJA9/dJMcafTtFB3/Yaz8LCA47kBVQWQ7hwiKLk/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCsJA9/dJMcafTtFB3/Yaz8LCA47kBVQWQ7hwiKLk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCsJA9%2FdJMcafTtFB3%2FYaz8LCA47kBVQWQ7hwiKLk%2Fimg.webp&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;477&quot; height=&quot;458&quot; data-origin-width=&quot;477&quot; data-origin-height=&quot;458&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수 십개의 이슈 티켓을 차례로 진행하려니 시간이 부족해서 도저히 안되겠습니다. 지금 무척 바쁘거든요 ㅠㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(나중에 일괄 검토할 각오로) 전체 티켓에 대해 &lt;span style=&quot;color text-align: start;&quot;&gt;workflow&lt;span&gt; 를 진행 시켜보았고 이번에만 plan 은 일괄 승인해주겠다. &lt;/span&gt;&lt;/span&gt;각 티켓마다 base 브랜치를 기반으로하는 하위 브랜치를 만들고 코드 변경 작업 후 커밋 까지 해줘 라고 시키고 저는 저녁 밥을 먹고 왔습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(잠시후...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런? &lt;b&gt;같은 페이지 내에서 관련된 이슈를 묶어서 하나의 브랜치에서 처리를 해두었더군요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 관련 이슈들은 묶어서 하나의 PR 로 올리곤 했거든요 그래서 제가 원했던 희망사항이었지만 딱히 커서에서 시킨 적은 없습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;b&gt;한 세션에서 처리하기엔 너무 분량이 많다고 불평&lt;/b&gt;했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 분량이 많은 거 동의합니다... 그래도 커서가 한 7개 정도의 이슈를 한번에 처리해두었거든요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 변경사항을 보니 비교적 간단한 변경 작업들이었고, 제가 딱히 건드릴게 많이 없어서 대부분은 곧바로 PR 까지 생성할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 여기까지 시도하여 꽤나 나쁘지 않은 결과물이 나왔으므로 성공!?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(문구 바꾸기, 조건 바꾸기 같은 단순 작업 같은건 앞으로 티켓만 넣으면 PR 생성 까지도 당장 가능하다고 봐야함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;후기 정리&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발을 위한 workflow 앞 단에 &lt;b&gt;기획서나 티켓 내용을 읽어오는 과정&lt;/b&gt;을 MCP 를 통해 구현했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이슈나 요구사항에 대해 부족한 내용을 사람이 보완을 해주는 단계가 필요하고, 이 단계에 &lt;b&gt;부족한 자료 추가와 내용 정리가 필요&lt;/b&gt;.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;작업 시 worflow 를 반드시 준수해 달라고 지속적인 지시 필요&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;유사 작업 분류, 브랜치 생성&lt;/b&gt; -&amp;gt; 이 과정을 좀 더 개선할 필요가 있는 상태.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 정도로 현재 진행형인 상태라고 정리되네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 중요하게 느낀 것은 &lt;b&gt;기획서&lt;/b&gt;를 반드시 AI 가 읽어야한다는 것이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기획 내용을 모르니 그 기획을 코드로 구현한 것에서 발생한 이슈 내용을 완벽히 이해하지 못했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 처&lt;b&gt;음 만드는 단계부터 기획서를 넣어서 그걸 베이스로 작업을 시키고 문서화&lt;/b&gt; 했더라면 &lt;br /&gt;아마 지금 단계에 왔을때 정확히 이슈와 코드베이스를 이해하고 작업이 가능했을것이라 믿고 있습니다. (인간이 미안해)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쨋든 이거를 개인적으로 계속 테스트하고 디벨롭 하고 있는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느정도 정립이 되면 팀 내에 공유하고 작은 부분에서라도 도입해보려고 합니다..&lt;/p&gt;</description>
      <category>개발자 이야기</category>
      <category>AI</category>
      <author>snowman95</author>
      <guid isPermaLink="true">https://11001.tistory.com/294</guid>
      <comments>https://11001.tistory.com/294#entry294comment</comments>
      <pubDate>Sat, 21 Mar 2026 02:30:46 +0900</pubDate>
    </item>
    <item>
      <title>[독후감] 나의 돈 많은 고등학교 친구 (송희구 작가)</title>
      <link>https://11001.tistory.com/292</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;[오랜만에 만난 친구가 알고보니 시그니엘 집주인]&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Uc1Lq/dJMcahDy4j4/dM2g0A5sPYgEpSGzKVkov1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Uc1Lq/dJMcahDy4j4/dM2g0A5sPYgEpSGzKVkov1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Uc1Lq/dJMcahDy4j4/dM2g0A5sPYgEpSGzKVkov1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUc1Lq%2FdJMcahDy4j4%2FdM2g0A5sPYgEpSGzKVkov1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;1024&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올해 나이 마흔에 대기업 과장인 영철은 아들인 영현을 데리고 롯데월드에 갔다가 고등학교 시절 골동품 운영하며 반지하에 살던 친구 광수와 그의 아들 광현을 만나게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;광수는&lt;b&gt; 20초 만에 기구를 탈 수 있는 프리미엄 매직패스 티켓&lt;/b&gt;을 가지고 있었고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영철의 티켓은 &lt;b&gt;1시간을 기다려야 기구를 탈 수 있는 일반 티켓&lt;/b&gt;이었기에 1시간 이후에 만나기로 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;광수는 조그만 사업을 한다는 영철이 허름한 차림에 차를 가지고 오지 않은 것으로 보아, 분명 저 멀리 외곽에서 놀러온 것으로 생각했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영철은 사옥을 짓는 현장에서 광수를 만나게 되는데 알고보니 광수가 건설 회사 대표였네요.&lt;br /&gt;알고보니 광수가 저~위에 살고 있다는 것이 경기 북부가 아니라 진짜로 저 위인 시그니엘 이라고 합니다. 어떻게 된 일일까요? 정신이 멍해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[돈을 쉽게 벌고 싶었던 영철]&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mJT4H/dJMcai3vvDS/EabbbLEnoQVbkbHkDrQAE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mJT4H/dJMcai3vvDS/EabbbLEnoQVbkbHkDrQAE0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mJT4H/dJMcai3vvDS/EabbbLEnoQVbkbHkDrQAE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmJT4H%2FdJMcai3vvDS%2FEabbbLEnoQVbkbHkDrQAE0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;1024&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영철은 우연히 주워들은 &lt;b&gt;루나바이오헬스케어&lt;/b&gt; 라는 주식에 5000만원을 넣었다가 휴지조각이 됩니다.&lt;br /&gt;영철이 했던 것은 투자가 아니라 투기였던 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점집에 들려 점을 보고왔는데 물을 피해야 합니다 라는 소리를 듣고 아, 내가 잘 안되는 이유가 물가에 살아서 그렇구나~ 그러던 와중에 경기 외곽 타운하우스를 분양을 받게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 꿈에 그리던 타운하우스를 입주했으나 기대와 많이 달랐고,&lt;br /&gt;막상 들어가니 단점도 보이고 시세는 반토막이 나고, 대체 왜 그런지 알 수 없었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영철은 너무 쉽게 돈을 벌고자 했기 때문이죠.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3kJWa/dJMcabDnEO0/VY39x5qMnaBBMPW3lSo6hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3kJWa/dJMcabDnEO0/VY39x5qMnaBBMPW3lSo6hk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3kJWa/dJMcabDnEO0/VY39x5qMnaBBMPW3lSo6hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3kJWa%2FdJMcabDnEO0%2FVY39x5qMnaBBMPW3lSo6hk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;1024&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;루나바이오헬스케어&lt;/b&gt;라는 회사에 대해 제대로 알아보지도 않고 그저 누군가의 비밀 정보라는 소식에 팔랑 넘어가서 '투기' 해버렸고&lt;br /&gt;부동산도 잘 모르면서 공부하여 살 생각하지를 않고, 점에 의지하고 타운하우스 팔이들에게 또 팔랑 넘어가서 호구 당했습니다.&lt;br /&gt;그렇게 평생 모아온 돈인데 한 순간에 날려버린 이유는 공부를 안 하고 누군가에게 미신에 의지했기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 이 열등감을 이해합니다. 사람은 누군가와 비교를 할 수 밖에 없고 그게 나보다 못살던 가까운 친구라면...&lt;br /&gt;괜히 내가 뒤쳐진 거 같고 마음이 조급하고 뭐라도 해야할 거 같은 생각이 크게 들죠. 그러다가 준비 안된 상태에서 무턱대고 덤볐다가 화를 당하기 마련입니다.&lt;br /&gt;이야기는 광수,영철의 아들인 광현, 영현의 이야기로 넘어갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[더 많은 돈을 벌기 위해 사업가가 된 광현, 영현]&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cf4H1K/dJMcaiJdT5u/xrGkknoenqfyX0PfSHuF61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cf4H1K/dJMcaiJdT5u/xrGkknoenqfyX0PfSHuF61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cf4H1K/dJMcaiJdT5u/xrGkknoenqfyX0PfSHuF61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcf4H1K%2FdJMcaiJdT5u%2FxrGkknoenqfyX0PfSHuF61%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;1024&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;광현, 영현은 성인이 되어 대학교에 들어갔습니다.&lt;br /&gt;낮밤으로 할아버지들이 소리를 지르는 동네 원룸에서 둘이서 살면서 알바를 하며 나름 열심히 돈을 모았다고 생각하지만 돈이 모이질 않습니다. 광수를 찾아가 도움을 요청합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;돈을 더 많이 벌어라&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;소비를 줄여라&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;광현과 영현은 돈을 더 많이 벌기 위해 사업에 뛰어듭니다. 평소 좋아하던 캠핑이라는 주제로 해보기로 했는데요.&lt;br /&gt;국내에서는 생소한 외국 캠핑 브랜드를 사서 팔아보기로 했는데요. 하나도 팔리질 않습니다.&lt;br /&gt;광수의 도움으로 독일 캠핑 박람회에 방문하여 캠핑용품을 구경하고 백여개의 업체 명함을 받아옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;그 중에 호의적인 업체와 연락하여 계약 했고 샘플을 들고 오프라인 매장에 찾아가서 샘플 전시 부탁하고, 열심히 카페에 홍보도 했습니다. 그러다 한국에서 열리는 박람회에서 이제는 소비자가 아닌 공급자가 되어서 박람회에 캠핑 용품을 소개하는 역할을 하게 되었고, 수동적인 자세에서 능동적으로 주체적으로 사람자들의 이목을 끌면서 성공적으로 마무리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이후로 공모전을 여는 등 여러가지 시도를 통하여 사업은 안정기에 접어 들었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cb0XRw/dJMcahcvAZt/Kr2AUCraT2kDp3PZplLa20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cb0XRw/dJMcahcvAZt/Kr2AUCraT2kDp3PZplLa20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cb0XRw/dJMcahcvAZt/Kr2AUCraT2kDp3PZplLa20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcb0XRw%2FdJMcahcvAZt%2FKr2AUCraT2kDp3PZplLa20%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;1024&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 느낀 점은 수동적인 자세로 사업을 하는 것은 남의 말을 듣고 주식을 사서 대박 나기를 바라는 것과 다를 거 없다는 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가만히 있는데 손님들이 오기를 바란다? 내가 직접 가서 입에 떠먹여주고 반응도 보고 또 찾아올 수 있게 해도 모자라다는 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;기회는 누구에게나 찾아 오지만 가만히 있으면 기회인 줄도 모르고 지나가는게 맞는거 같습니다.&lt;/b&gt;&lt;br /&gt;그러나 한국인들은 어릴때 부터 나대지마라, 가만히 있으면 중간은 간다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이딴 식으로 교육 받으며 자랐고 저도 그렇게 자랐기 때문에 이런 부분에서 엄청난 고생을 하게 되는거 같습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[광수는 어떻게 부자가 되었는가]&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJ8i2b/dJMcafsd3Ph/oE8Jcnaky6CVdr8t7nuLi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJ8i2b/dJMcafsd3Ph/oE8Jcnaky6CVdr8t7nuLi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJ8i2b/dJMcafsd3Ph/oE8Jcnaky6CVdr8t7nuLi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJ8i2b%2FdJMcafsd3Ph%2FoE8Jcnaky6CVdr8t7nuLi1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;1024&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;광수는&lt;b&gt; 행복, 성공&lt;/b&gt; 이런것들을 목표로 하지 않습니다.&lt;br /&gt;행복은 언제든 느낄 수 있는 것이고, 작은 것을 이루는 것도 성공이기 때문이죠.&lt;br /&gt;부자는 목표라고 할 수 있습니다. 하지만 부자는 누구와도 경쟁하는 것이 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;광수는 어린시절 물이 새는 철물점을 보며, 물이 새지 않는 튼튼한 집을 짓고자 하는 깊고 강한 목표가 새겨졌고&lt;/b&gt;&lt;br /&gt;그 목표를 위해서 건축과 진학, 건축사무소에서 일하며 남들이 힘들다고 하지 않는 일까지 도맡아 해왔습니다. 젊은 시절의 고생들이 나중에 기회가 왔을때 잡을 수 있는 능력이 되었고,&lt;br /&gt;약간 손해를 보더라도 고객에게 최고의 결과를 제공하고자 하는 마음가짐이 있었기 때문에 결과가 좋을 수 밖에 없었고, 그것이 입소문을 타고 사업이 번창하게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;광수는 어린 시절 반지하에서 살았기에 제일 높은 곳에서 살고 싶었고, 반지하의 좁고 작은 창문을 보며 자랐기 때문에 가능하면 크고 넓은 통창을 얻고 싶었습니다. &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그것이 광수의 성장동력이 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 본인만의 성장동력, 신념, 철학이 있었기에 본업에 진심일 수 밖에 없었고 좋은 건물을 지을 수 밖에 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저의 경험을 빗대어 보면 저는 광수처럼 제가 이루고 싶은 원초적인 목표가 없었고, 대학 외에 다른 선택지가 없어서 대학을 갔고, 그나마 익숙하고 많이 친근한 것을 전공을 선택했습니다. 광수와 마음 가짐 자체가 다르고 삶의 방향이 다르죠..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[부의 대물림, 가난한 마음가짐 물려주기]&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 광수의 아들인 광현은 어차피 아버지에게 자산을 물려 받으면 스타트 자체가 다르니까 인생 편거 아닌가요? 그런데 광현도 과연 광수와 같은 성장동력을 가지고 살아갈 수 있을까요?&lt;br /&gt;요즘 중상층 자녀들이 어차피 부모님이 집 물려주실거니까 공부도 안하고 대충 살려고 한다는 고민이 있다고 합니다. 이게 바로 부의 대물림에서 오는 부작용이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현명한 광수는 아들인 광현에게도 자산을 물려주지 않고 용돈도 쥐어주지 않습니다.&lt;br /&gt;아버지의 꼭 필요한, 최소한의 서포트를 받으며 스스로 인생을 학습하고 경험을 해보며 삶을 개척합니다.&lt;br /&gt;부는 축적하는 것만 어려운게 아니라 유지하는 것도 매우 어렵습니다.&lt;br /&gt;아마 이렇게 키우지 않았다면 어차피 내 돈도 아니고 아버지가 준 공짜 돈인데..ㅋ 하고 흥청망청 쓰는 철부지 아들이 되었을 지도 모릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[후기]&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 책을 읽으면 어린 시절 부터의 빌드업이 얼마나 삶에 큰 영향을 미치는가를 볼 수 있습니다.&lt;/b&gt;&lt;br /&gt;내가 살아가면서 무언가를 절실히 느끼고 원하는 바, 목표를 가지고 그것을 향해서 쏟아부을 수 있는 열정을 가져야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무언가 쉽게 얻으려고 하면 쉽게 잃어버린다. &lt;b&gt;철저히 시간과 공을 들여서 결과를 얻으려는 자세를 가져야 합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;열등감은 부자에게도 있고 누구에게나 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부자는 남과 경쟁하는 것이 아닙니다. 남과 비교하면 끝이 없습니다. &lt;b&gt;남이 아닌 나에게 집중해야합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;투자든 사업이든 &quot;기본&quot;에 충실해야 합니다.&lt;/b&gt;&lt;br /&gt;&lt;b&gt;내가 얼마를 남겨먹을 지 고민하기 전에 내가 무엇을 해줄 수 있는지?&lt;/b&gt; 생각해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무엇을 얻고자 한다면 반드시 수동적인 자세를 버리고 적극적으로 뛰어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어찌보면 뻔한 소리이지만, 이 뻔한 것도 잘 몰라서 잘 못지키는 사람들이 많고 저도 똑같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제 인생의 근본적인 목표도 모호하고, 열심히 만든 서비스를 적극적으로 홍보할 줄도 몰랐고, 부끄럽고 망설여하면서 많은 기회를 놓친것도 제 제 잘못입니다. 열심히 공부한 투자가 아닌 팔랑귀 투기를 통해 많은 기회비용을 날려버린 것도 제 잘못이고요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;616&quot; data-origin-height=&quot;439&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cp4fKe/dJMcajuBIOC/0JXClM75YZk2Sq3riApRZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cp4fKe/dJMcajuBIOC/0JXClM75YZk2Sq3riApRZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cp4fKe/dJMcajuBIOC/0JXClM75YZk2Sq3riApRZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcp4fKe%2FdJMcajuBIOC%2F0JXClM75YZk2Sq3riApRZ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;616&quot; height=&quot;439&quot; data-origin-width=&quot;616&quot; data-origin-height=&quot;439&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;저는 3/28 송희구 작가님의 부동산 강의를 들으러 킨텍스에 갑니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무언가 얻고 싶기에 시간과 노력을 들여서 책도 읽고 먼 거리를 이동합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;광수와 약간 다르지만 저는 내집마련이 어릴적 부터의 큰 소원이자 목표를 뛰어넘은 숙원 같은거라&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사회초년생 부터 또래에 비해 유독 관심이 많았고, 부동산 스타트업에 가게된 이유도 그러한 제 내재적인 갈망 때문이었을거 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 결혼하면서 내집마련의 꿈을 이루기 위한 목전에 있고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;똘똘한 내 집과 그 이후의 갈아타기를 잘해서 저도 잠실 입성을 하게 되는 그 날까지&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발도 열심히, 부동산 공부도 열심히 해보려 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발자 이야기</category>
      <category>독후감</category>
      <category>부동산</category>
      <category>송희구</category>
      <author>snowman95</author>
      <guid isPermaLink="true">https://11001.tistory.com/292</guid>
      <comments>https://11001.tistory.com/292#entry292comment</comments>
      <pubDate>Sun, 8 Mar 2026 13:33:07 +0900</pubDate>
    </item>
    <item>
      <title>[시니어 FE] CSRF GET 공격 시나리오와 방어법</title>
      <link>https://11001.tistory.com/291</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;cookie.jpg&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;854&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3wAWT/dJMcadHT5Ij/vQMJTuOtXpDZasQUKYXKuk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3wAWT/dJMcadHT5Ij/vQMJTuOtXpDZasQUKYXKuk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3wAWT/dJMcadHT5Ij/vQMJTuOtXpDZasQUKYXKuk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3wAWT%2FdJMcadHT5Ij%2FvQMJTuOtXpDZasQUKYXKuk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;854&quot; data-filename=&quot;cookie.jpg&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;854&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;쿠키(Cookie)를 인증 수단으로 사용할 때, SameSite 속성을 Lax나 Strict로 설정하는 것만으로 CSRF 공격을 완벽히 막을 수 있을까요? 추가적으로 'CSRF 토큰'이나 'Custom Header'가 필요한 이유는 무엇이라고 생각하시나요?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;사용자가 우리 서비스에 로그인한 상태로, 해커가 만든 악성 사이트에 접속했습니다. 그 사이트에는 우리 서비스의 '비밀번호 변경' API를 자동으로 호출하는 폼(Form)이 숨겨져 있습니다. 사용자가 모르는 사이에 비밀번호가 바뀌는 이 공격을 프론트엔드와 백엔드에서 어떻게 협업하여 막으시겠습니까?&quot;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CSRF(Cross-Site Request Forgery)&amp;nbsp;공격의 목적&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자의&amp;nbsp;권한을&amp;nbsp;도용해&amp;nbsp;비밀번호&amp;nbsp;변경,&amp;nbsp;결제,&amp;nbsp;게시글&amp;nbsp;삭제&amp;nbsp;등&amp;nbsp;서버의&amp;nbsp;상태를&amp;nbsp;변조하는&amp;nbsp;것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 GET 요청은 자원의 변경하지 않기 때문에 문제가 될 일은 없다만, 만에 하나 GET 메소드로 잘못 지정하거나 잘못 사용하고 있는 서버 자원을 변경하는 API가 있다면 공격의 대상이 될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;CSRF PUT/POST 공격 시나리오&lt;/h4&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;CSRF POST/PUT 공격은 사용자의 브라우저가 대상 서버로 요청을 보낼 때 &lt;b data-index-in-node=&quot;46&quot; data-path-to-node=&quot;21,0&quot;&gt;인증 쿠키를 자동으로 포함하는 특성&lt;/b&gt;을 악용합니다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;공격자는&amp;nbsp;사용자가&amp;nbsp;로그인한&amp;nbsp;상태를&amp;nbsp;유지하고&amp;nbsp;있다는&amp;nbsp;점을&amp;nbsp;악용하여,&amp;nbsp;사용자&amp;nbsp;모르게&amp;nbsp;서버&amp;nbsp;상태를&amp;nbsp;변경하는&amp;nbsp;요청을&amp;nbsp;보내게&amp;nbsp;합니다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 사이트에 로그인한 상태에서 해커의 사이트에 접속하게 하여 form 을 제출하게 합니다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;근데 외부 요청은 서버에서 설정한 CORS 정책으로 다 막히지 않나요?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;lt;form&amp;gt; 태그는 CORS 정책을 무시합니다. &lt;br /&gt;브라우저는 폼 제출을 페이지 전환의 일종으로 간주하기 때문에 다른 도메인으로 POST 요청 보내는 것에 대해서는 무시합니다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;form 태그는 method=&quot;POST&quot; 와 GET 만 지원하기에 해커의 공격 대상은 POST, GET 뿐입니다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;일단 외부에서 우리 사이트로 요청이 들어오는 경우&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;브라우저 레벨에서&lt;b&gt; SameSite Cookie&lt;/b&gt; 설정을 통해 외부 사이트에서 쿠키 자체가 넘어가지 못하게 하여 대부분 방어가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SameSite는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&quot;다른 사이트(Cross-site)에서 발생한 요청에 이 쿠키를 실어 보낼 것인가?&quot;&lt;/b&gt;를 결정합니다.&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;SameSite=&lt;/span&gt;Strict 가장 엄격합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 google.com에 있다가 링크를 타고 naver.com으로 넘어올 때조차 쿠키를 보내지 않습니다.&lt;br /&gt;(사용자 경험이 나빠질 수 있음 - 매번 다시 로그인 등)&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;SameSite=&lt;/span&gt;Lax (기본값) 조금 유연합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 사이트에서 우리 사이트로 오는 '하위 리소스 요청(img, iframe 등)'은 차단하지만, '안전한 요청(GET)'이나 '탑 레벨 내비게이션(링크 클릭)', 즉 브라우저의 주소창이 바뀌는 a 태그 클릭이나 window.location.href 이동은 쿠키 전송을 허용합니다.&lt;br /&gt;하지만 &lt;b&gt;POST, PUT, DELETE 같은 상태 변경 요청에는 쿠키를 보내지 않습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션 레벨에서는 &lt;b&gt;CSRF Token&lt;/b&gt; 로 방어가 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;서버가 페이지 렌더링 시 매번 무작위 토큰&lt;/b&gt;을 발급하고, 클라이언트는 POST/PUT 요청 시 이를 헤더나 바디에 포함합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해커는 사용자의 쿠키는 브라우저를 통해 보낼 수 있지만, 자바스크립트로 &lt;b&gt;우리 서버의 토큰값을 읽어올 수 없으므로&lt;/b&gt;(SOP 정책) 공격이 실패합니다. 보통 초고보안이 필요한 환경에서 이렇게 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SPA 에서는 매번 서버가 토큰을 보내줄 수 없으니 &lt;b&gt;로그인시 무작위 생성된 CSRF 토큰을 쿠키에 넣어둡니다.&lt;/b&gt;&lt;br /&gt;HttpOnly: true 가 아닌 &lt;b&gt;false&lt;/b&gt; 설정하여, 자바스크립트에서 읽어와서 API 요청 보낼때 &lt;b&gt;별도의 헤더&lt;/b&gt;로 실어 보내는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 그러냐면 브라우저가 자동으로 실어 보내는 쿠키를 맹신적으로 믿어서는 공격 당할 수 있기 때문에 별도의 헤더를 쓰는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인프라/API 레벨에서는&lt;b&gt; Custom Header&lt;/b&gt; 검증이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;X-Requested-With&lt;/b&gt; 같은 고정된 커스텀 헤더를 하나 추가하여&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;왜 Custom Header가 CSRF를 막는가? (핵심 원리)&lt;br /&gt;핵심은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&quot;브라우저는 교차 출처(Cross-Origin) 요청 시, 커스텀 헤더가 포함되면 반드시 Preflight(OPTIONS) 요청을 보낸다&quot;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;는 점에 있습니다.&lt;br /&gt;기본 헤더 (Simple Request): Content-Type: text/plain, Accept 등 표준 헤더만 사용하면 브라우저는 바로 서버로 요청을 보냅니다.&lt;br /&gt;커스텀 헤더: X-Requested-With, X-App-Version 같은 표준이 아닌 헤더를 추가하면, 브라우저는 이 요청을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;'잠재적으로 위험한 요청'&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;으로 간주합니다.&lt;br /&gt;Preflight 발생: 브라우저는 실제 요청을 보내기 전에 OPTIONS 메소드로 서버에 &quot;이 헤더 써도 돼?&quot;라고 먼저 물어봅니다.&lt;br /&gt;CORS 차단: 해커의 사이트(evil.com)에서 우리 API로 커스텀 헤더를 실어 보내려 하면, 서버는 Preflight 응답에서 evil.com을 허용하지 않을 것이고, 브라우저는 실제 요청 자체를 보내지 않고 차단합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;① 클라이언트(프론트엔드) 설정&lt;br /&gt;모든 API 요청에 공통 헤더를 주입합니다. 보통 axios 인스턴스나 fetch 래퍼 함수에서 설정합니다.&lt;/p&gt;
&lt;pre style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;import axios from 'axios';

const api = axios.create({
  baseURL: 'https://api.bank.com',
  headers: {
    // 관례적으로 많이 쓰는 헤더명입니다. 값은 무엇이든 상관없습니다.
    'X-Requested-With': 'XMLHttpRequest', 
    'X-App-Service-Id': 'my-frontend-app'
  },
  withCredentials: true // 쿠키를 포함하여 전송
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;② 서버(백엔드) 설정&lt;br /&gt;서버는 두 가지를 수행해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CORS 설정: Access-Control-Allow-Headers에 우리가 정의한 커스텀 헤더명을 추가하여 허용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;헤더 검증 미들웨어: 상태를 변경하는 요청(POST, PUT, DELETE 등)이 올 때, 해당 헤더가 존재하는지 확인합니다.&lt;/p&gt;
&lt;pre style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;// Express.js 예시 미들웨어
app.use((req, res, next) =&amp;gt; {
  // GET 요청은 대개 제외하고, 상태 변경 요청에서만 체크
  if (['POST', 'PUT', 'DELETE'].includes(req.method)) {
    const customHeader = req.headers['x-requested-with'];

    if (!customHeader) {
      // 헤더가 없으면 우리 프론트엔드에서 보낸 것이 아니라고 판단
      return res.status(403).json({ error: 'Invalid Request: Missing Custom Header' });
    }
  }
  next();
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;CSRF GET 공격 시나리오&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인한 사용자가 a 태그를 클릭하게 만들고, 그 주소가 '&lt;a href=&quot;https://bank.com/transfer?to=hacker&amp;amp;amount=10000'&quot;&gt;https://bank.com/transfer?to=hacker&amp;amp;amount=10000'&lt;/a&gt; 이와 같을 경우, 쿠키가 sameSite=LAX 이면 외부 사이트여도 a 링크니까 쿠키가 보내질거고, CORS 의 영향을 받지도 않겠네요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럴 수 있습니다.&lt;br /&gt;SameSite=Lax 에서 a 태그를 이용한 탑 레벨 내비게이션은 쿠키 전송이 허용되므로, 보안이 허술한 서비스라면 CSRF 공격에 노출될 수 있습니다.&lt;br /&gt;CORS는 '스크립트(JS)'가 다른 도메인의 데이터를 읽으려 할 때 작동하는 보안 책입니다.&lt;br /&gt;사용자가 직접 링크를 클릭해서 페이지를 이동하는 것은 브라우저의 기본 동작이므로 CORS 정책의 적용 대상이 아닙니다.&lt;br /&gt;사용자가 이미 은행에 로그인되어 있다면, 브라우저는 &quot;사용자가 직접 링크를 눌러서 은행으로 가겠다는데, 당연히 인증 쿠키를 보내줘야지&quot;라고 판단합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;CSRF GET 방어 방법&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 방어하기 위해 두 가지 원칙을 고수해야합니다.&lt;br /&gt;첫째, 상태를 변경하는 모든 API는 반드시 POST/PUT/DELETE를 사용하고,&lt;br /&gt;둘째, 단순 쿠키 인증에만 의존하지 않고 CSRF 토큰이나 Custom Header 검증을 병행합니다.&lt;br /&gt;특히 금융권처럼 민감한 서비스라면 결제/이체 직전에 다중 인증(MFA) 레이어를 추가하여 사용자 의사를 최종 확인하는 설계가 필수적입니다.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;11&quot; data-ke-size=&quot;size23&quot;&gt;CSRF Token의 원리&lt;/h3&gt;
&lt;p data-path-to-node=&quot;12&quot; data-ke-size=&quot;size16&quot;&gt;CSRF 토큰은 &lt;b&gt;&quot;이 요청이 우리 프론트엔드에서 보낸 것이 맞다&quot;&lt;/b&gt;라는 일종의 신분증입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-path-to-node=&quot;13&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사용자가 접속하면 서버는 &lt;b data-index-in-node=&quot;14&quot; data-path-to-node=&quot;13,0,0&quot;&gt;무작위 토큰&lt;/b&gt;을 발행하여 세션에 저장하고, 프론트엔드에 전달합니다.&lt;/li&gt;
&lt;li&gt;프론트엔드는 POST/PUT 요청을 보낼 때 HTTP 헤더(예: X-CSRF-TOKEN)에 이 값을 실어 보냅니다.&lt;/li&gt;
&lt;li&gt;서버는 쿠키(자동 전송됨)와 헤더의 토큰(프론트가 직접 넣어줘야 함)을 비교합니다.&lt;/li&gt;
&lt;li&gt;해커의 악성 사이트에서는 사용자의 쿠키는 (브라우저가) 실어 보낼 수 있어도, &lt;b data-index-in-node=&quot;44&quot; data-path-to-node=&quot;13,3,0&quot;&gt;우리 서버가 발행한 고유 토큰값&lt;/b&gt;은 알 방법이 없으므로 공격이 차단됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리해보자면, 쿠키 sameSite=LAX 인 경우 a tag 의 GET 요청으로 CSRF 공격이 들어올 수 가 는데&lt;br /&gt;외부 사이트는 CORS 정책으로 막히거나 sameSite=LAX 에 의해 쿠키 자체가 넘어가지 않겠지만&lt;br /&gt;a tag 로 넣은 주소는 same site 이므로, 해당 사이트에 사용자가 로그인한 상태라면 쿠키 정보가 넘어갈 수 있게됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 이때 서버단에서 Custom Header 검증이 있다면, a tag 를 통해 넘어왔을때 우리 도메인의 클라이언트에서 Custom Header 를 집어넣어준 것이 아니기 때문에 검증이 실패할 것이고 방어를 할 수 있다. 이렇게 정리가 되겠습니다.&lt;/p&gt;</description>
      <category>프론트엔드 개발/시니어 시리즈</category>
      <author>snowman95</author>
      <guid isPermaLink="true">https://11001.tistory.com/291</guid>
      <comments>https://11001.tistory.com/291#entry291comment</comments>
      <pubDate>Sat, 7 Mar 2026 14:50:44 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 완전 자율 소프트웨어 구축 시스템 개발 경험과 과정에 대한 글</title>
      <link>https://11001.tistory.com/290</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;open AI 에서 공개한 글에 대해 요약하고 제 생각을 추가한 글입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Gemini_Generated_Image_1xjxrx1xjxrx1xjx.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wGAGn/dJMcahXRAsq/GWEZSzzDHzA6koAvR85fm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wGAGn/dJMcahXRAsq/GWEZSzzDHzA6koAvR85fm1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wGAGn/dJMcahXRAsq/GWEZSzzDHzA6koAvR85fm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwGAGn%2FdJMcahXRAsq%2FGWEZSzzDHzA6koAvR85fm1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2816&quot; height=&quot;1536&quot; data-filename=&quot;Gemini_Generated_Image_1xjxrx1xjxrx1xjx.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 5개월 동안 &lt;b&gt;수동으로 작성한 코드가 단 한 줄도 없이 소프트웨어 제품의 내부 베타 버전을 개발하고 배포&lt;/b&gt;했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 제품은 어플리케이션 로직,테스트,CI 구성, 문서화, 관찰 가능성 및 내부 도구 등 &lt;b&gt;모든 코드를 Codex 가 작성&lt;/b&gt;을 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;사람이 코딩하는 것 보다 10배 빠른 효과를 낸 것으로 추정합니다.&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;에이전트에 맞춘 환경 구축&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 유용한 작업을 수행할 수 있도록 큰 목표를 설계, 코딩, 검토, 테스트 등으로 분해하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 구성요소를 구축하도록 유도한 다음에 이를 통해 더 큰 작업을 수행하게 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 실패 했을때 &quot;&lt;b&gt;더 열심히 해보세요&quot;&lt;/b&gt; 가 아니라&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;&quot;어떤 기능이 부족하고, 에이전트가 이를 명확하게 이해하고 실행할 수 있도록 하려면 어떻게 해야할까요?&lt;/b&gt; &lt;/u&gt;라고 질문했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;인력 기반의 QA 병목을 제거&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;고정된 제약 조건은 사람의 시간과 집중력이었기에 UI, 로그, 앱 메트릭 등 Codex 가 가능한 모든 정보를 읽을 수 있게 했습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Chrome 개발자 도구 프로토콜을 에이전트 런타임에 통합하고 DOM 스냅샷, 스크린샷 및 탐색 작업을 위한 스킬을 개발했고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 통해 Codex는 버그를 재현, 수정 사항 검증, UI 동작에 대해 직접 분석 가능하게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업이 완료되면 제거되는 격리된 버전에서 로그, 메트릭, 트레이스를 수집하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LogQL를 통해 로그를 쿼리, PromQL을 이용해 메트릭을 쿼리하여 &quot;서비스 시작이 800ms 이내에 완료되도록 보장&quot;, &quot;핵심 사용자 여정에서 어떤 구간도 2초를 초과하지 않도록 보장&quot; 과 같은 요구 사항을 효과적으로 처리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;저장소의 지식을 기록 시스템으로 구축&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;초기에 배운 교훈: Codex 에게 1000페이지짜리 설명서가 아닌 지도를 제공해야합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하나의 큰 AGENTS.md 실패했습니다.&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;많은 컨텍스트를 소비하고 에이전트가 핵심 제약 조건을 놓치거나 잘못된 제약 조건에 최적화 하게 됩니다.&lt;/li&gt;
&lt;li&gt;모든 것이 중요하다고 하면 결국 아무것도 중요하지 않은게 됩니다. 의도적인 탐색 대신에 국소적인 패턴 매칭에 매몰되게 됩니다.&lt;/li&gt;
&lt;li&gt;거대한 메뉴얼은 금방 낡게되고 무엇이 유효한지 알 수 없게 됩니다.&lt;/li&gt;
&lt;li&gt;단일 데이터 덩어리는 기계적인 검사에 적합하지 않습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AGENTS.md 는 백과사전이 아닌 목차(index) 처럼 취급하세요.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;100줄 정도의 짧은 설명이 맥락에 삽입되게 하여 지도 역할을 하고, 더 심층적인 정보 소스를 가리키는 포인터 역할을 해야합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1772716818564&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;AGENTS.md
ARCHITECTURE.md
docs/
├── design-docs/
│   ├── index.md
│   ├── core-beliefs.md
│   └── ...
├── exec-plans/
│   ├── active/
│   ├── completed/
│   └── tech-debt-tracker.md
├── generated/
│   └── db-schema.md
├── product-specs/
│   ├── index.md
│   ├── new-user-onboarding.md
│   └── ...
├── references/
│   ├── design-system-reference-llms.txt
│   ├── nixpacks-llms.txt
│   ├── uv-llms.txt
│   └── ...
├── DESIGN.md
├── FRONTEND.md
├── PLANS.md
├── PRODUCT_SENSE.md
├── QUALITY_SCORE.md
├── RELIABILITY.md
└── SECURITY.md&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설계 문서 (DESIGN)&lt;/b&gt;: 검증 상태 및 에이전트 우선 운영 원칙을 정의하는 핵심 신념 세트를 포함한 색인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;아키텍처 문서 (ARCHITECTURE):&amp;nbsp;&lt;/b&gt;최상위 도메인 및 패키지 계층 구조 맵&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;품질 문서 (QUALITY_SCORE)&lt;/b&gt;: 제품 도메인 및 아키텍처 계층을 등급화하고 시간 경과에 따른 격차를 추적&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;계획 (PLAN)&lt;b&gt;:&lt;/b&gt;&amp;nbsp;&lt;/b&gt;최우선 산출물로 취급. 간단 변경 사항에는 일시적 계획을 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실행 계획(ExecPlan): &lt;/b&gt;몇 시간씩 걸리는 복잡한 문제를 해결&lt;/p&gt;
&lt;figure id=&quot;og_1772719873441&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[AI] PLAN.md 몇 시간이 걸리는 복잡한 계획을 수행하는 프롬프트 (번역)&quot; data-og-description=&quot;Codex 실행 계획(ExecPlans) 가이드라인이 문서는 코딩 에이전트가 작동 가능한 기능이나 시스템 변경 사항을 전달하기 위해 따를 수 있는 설계 문서인 실행 계획(ExecPlan)의 요구 사항을 설명합니다. &quot; data-og-host=&quot;11001.tistory.com&quot; data-og-source-url=&quot;https://11001.tistory.com/289&quot; data-og-url=&quot;https://11001.tistory.com/289&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cMXutl/dJMb9frDhMh/GAyYa3UVqbNpeS7EjRk4Ck/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/1Mmgy/dJMb81GU2f4/VyzWIvlA5GmeH5VXYgi1Yk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/fBNxl/dJMb84p6xvX/KC9082NJkpOpK5mmiq8P6k/img.png?width=2752&amp;amp;height=1536&amp;amp;face=0_0_2752_1536&quot;&gt;&lt;a href=&quot;https://11001.tistory.com/289&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://11001.tistory.com/289&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cMXutl/dJMb9frDhMh/GAyYa3UVqbNpeS7EjRk4Ck/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/1Mmgy/dJMb81GU2f4/VyzWIvlA5GmeH5VXYgi1Yk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/fBNxl/dJMb84p6xvX/KC9082NJkpOpK5mmiq8P6k/img.png?width=2752&amp;amp;height=1536&amp;amp;face=0_0_2752_1536');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[AI] PLAN.md 몇 시간이 걸리는 복잡한 계획을 수행하는 프롬프트 (번역)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Codex 실행 계획(ExecPlans) 가이드라인이 문서는 코딩 에이전트가 작동 가능한 기능이나 시스템 변경 사항을 전달하기 위해 따를 수 있는 설계 문서인 실행 계획(ExecPlan)의 요구 사항을 설명합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;11001.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[기록&amp;nbsp;시스템&amp;nbsp;검증과&amp;nbsp;정리]&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;전용 린터와 CI 작업&lt;/b&gt;이 지식 기반이 최신 상태이고, 상호 연결되어 있으며, 올바르게 구성되어 있는지 검증함.&lt;/li&gt;
&lt;li&gt;정기적으로 실행되는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&quot;문서 정리&quot; 에이전트&lt;/b&gt;가 실제 코드 동작을 반영하지 않는 오래되거나 더 이상 사용되지 않는 문서를 찾아 수정 풀 리퀘스트를 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;목표는 에이전트의 가독성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 모든 일을 수행하므로 에이전트 가독성을 최우선으로 고려하여 최적화함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트가 저장소 전체 비즈니스 도메인에 대해 직접 추론 가능하게 함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실행 중에 컨텍스트 내에서 접근할 수 없는 것은 존재하지 않는 것과 마찬가지입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;외부문서, 채팅 스레드, 사람의 머릿속 지식은 시스템에서 접근 불가함.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 팀원에게 제품 원칙, 엔지니어링 규범, 팀 문화를 교육하는 것처럼,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트에게 이러한 정보를 제공하면 더욱 일관성 있는 결과를 얻을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 경우에는 공개 라이브러리의 기능 일부를 에이전트가 재구현하는 것이 더 저렴했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;에이전트를 위한 엄격한 제약 조건 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저희는 구현을 세세하게 관리하지 않고, &lt;b&gt;불변 조건을 강제하여 기반을 훼손하지 않고 더 빠르게 배포&lt;/b&gt;가 가능했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트는 엄격한 경계와 예측 가능한 구조를 가진 환경에서 가장 효과적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엄격한 아키텍처 모델을 기반으로 어플리케이션 구축하고 각 비즈니스 도메인은 고정된 계층으로 나누고, 종속성 방향은 엄격하게 검증되고 허용되는 연결은 제한됩니다. 이러한 제약 조건은 린터와 구조적 테스트를 통해 자동으로 적용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이러한 구조는 보통 큰 조직 구조에서 적합한데 에이전트를 사용하는 경우에는 초기 단계부터 필수 조건입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 제약 조건 덕분에 아키텍처의 퇴보나 변질 없이 속도 유지가 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;구조화된 로깅, 스키마 및 유형에 대한 명명 규칙, 파일 크기 제한, 플랫폼별 안정성 요구 사항 등을 사용자 지정 린터를 통해 적용.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;린터가 사용자 지정 방식이기 때문에 오류 메시지를 작성하여 에이전트 컨텍스트에 수정 지침을 삽입합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;또한 제약 조건이 중요한 부분과 아닌 부분을 명확히 구분합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중앙에서 경계를 설정하고, 각 팀(담당자)에게 자율성을 부여하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경계, 정확성, 재현성을 매우 중요하게 생각하면서도, 이러한&lt;b&gt; 경계 내에서 팀(담당자)가 표현하는 방식에는 자유를 허용합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성된 코드가 항상 사람의 스타일 선호도와 일치하지 않아도, 출력 결과가 정확하고 유지 관리가 용이하고 향후 에이전트 실행 시 읽기가 쉬우면 조건 충족&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;병합을 차단하는 요소 최소화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Codex 처리량이 증가함에 따라 기존의 엔지니어링 관행은 비효율적이 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PR은 수명이 짧고, 테스트 오류는 진행을 무기한으로 막는 대신 후속 실행을 통해 해결됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;에이전트의 처리량이 사람의 처리량을 압도하는 시스템에서는 수정 비용이 저렴하고 대기 시간이 매우 깁니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;완전한 에이전트 자율성의 새로운 문제점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장소에 이미 존재하는 패턴, 불균형하거나 최적화되지 않은 패턴까지 복제하는 문제가 발생했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기에는 사람이 직접 해결하려고 시도했으나 확장성 떨어졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 &lt;b&gt;&quot;황금 원칙&lt;/b&gt;&quot; 이라고 불리는 것들을 저장소에 직접 인코딩하고 정기 프로세스를 구축했습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;불변 조건을 중앙 집중화 하기 위해 직접 작성한 헬퍼보다는 공유 유틸리티 패키지를 선호&lt;/li&gt;
&lt;li&gt;데이터를 YOLO 스타일로 탐색하지 않고 경계를 검증하거나 타입이 지정된 SDK를 사용하여 에이전트가 추측된 형태를 기반으로 실수로 구축하지 않게 합니다.&lt;/li&gt;
&lt;li&gt;정기적으로 백그라운드에서 실행되는 Codex 작업들을 통해 편차를 검사, 품질 등급을 업데이트, 특정 리팩토링 PR 생성.&lt;br /&gt;기술 부채를 한 번에 몰아서 갚는것 보다 지속적으로 나눠서 갚는게 효율적인것 처럼 이것도 마찬가지임. (like 가비지컬렉션)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;마무리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트 기반 시스템에서 아키텍처의 일관성이 시간이 지남에 따라 어떻게 진화하는지 아직 알 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간이 지남에 따라 모델의 능력이 향상되면서 이 시스템이 어떻게 진화하는지 알 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;코드베이스의 일관성을 유지하는 데 필요한 도구, 추상화, 피드백 루프가 점점 중요해지고 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;에이전트가 안정적인 소프트웨어를 대규모로 구축하고 유지 관리하는 데 도움이 되는 환경, 피드백 루프, 제어 시스템을 설계하는 것이 가장 중요하며 가장 어려운 과제입니다.&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;후기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자율주행 자동차 처럼 에이전트가 운행하는 완전 자율 SW 개발 솔루션이 실제로 세상에 작동하고 있고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀지 않은 미래에 이렇게 개발 하는것이 &lt;b&gt;표준&lt;/b&gt;이 될 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;개발자 역할의 변화&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구 시대의 개발자의 역할이 기획서 검토하여 요구사항을 코드로 옮기고 테스트 후 배포하는 것이었다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로는 완전 자율 SW 개발 솔루션에 &lt;b&gt;요구사항을 전달하고, 결과물을 검토하고, 유지보수&lt;/b&gt;하는 역할이 되었다는 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;개발자 = &quot;도메인, 사업 특성에 맞게 에이전트가 작업할 환경을 설계, 유지보수 하는 역할&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;서비스는 빨리 만들어도 여전히 사람은 느리다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 미래에는 저비용으로 초고속 서비스 개발이 가능하게 되는건데, 문제는 그 서비스를 사람이 쓰고 있다는 것인데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금도 미친듯이 쏟아져 나오는 서비스들이 감당이 안되는데 앞으로는 어떻게 될지 참 궁금합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사람들은 나이가 들 수록 변화를 싫어하는데 세상이 더 빠르게 변하는걸 감당할 수 있을지 모르겠습니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저희가 노인이 되었을때 온라인 상의 모든 것이 AI로 자동화가 되어있고, 오프라인의 모든 것이 로봇으로 대체되었을 것인데요...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;노동&quot; 과 &quot;소유&quot; 라는 개념 자체가 사라지는 세상.. 모두 통속의 뇌 또는 메트릭스 안에서 살아가게 되겠죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;컴퓨터가 처음 발명되었을때 사람들은 무슨 기분이었을까요?&lt;/b&gt; 이렇게 까지 될 거라고 생각했을까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;나의 이야기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 요즘 회사에서 &lt;b&gt;지식 저장소&lt;/b&gt;를 구축하는 것 부터 시작하고 있는데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 저희는 아직 완전 수동 에이전트 구동 환경이라서.. Open AI 처럼 만들지는 못하겠지만요. 그래도 따라겠다는 생각이 들어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국은 느리고 보수적이기 때문에 아마 이렇게 되기 까지 5년, 10년은 더 걸릴지도 모릅니다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음부터 이렇게 구축하는건 불가능하고, 변화하는건 어렵다고 판단하고 있고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 머릿속에 이런 식으로 구상하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 지식 저장소 구축을 먼저 진행 (현재 진행중  )&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 새로운 기획서를 넣었을때 Agent 가 전체 작업을 수행 &lt;/b&gt;(엄격한 제약, 규칙 설정 등을 재검토)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 수행된 결과물을 테스트/검토 하는 환경을 구축 &lt;/b&gt;(여기가 진짜 어려울 거 같습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 테스트/검토 통과되면 자동 PR 생성 &lt;/b&gt;(당장은 3번 과정을 사람이 PR 리뷰를 통해서 해도 될듯함. 간단한 작업은 고치는 것 보다 PR 올리고 굳이 리뷰받고 배포하는게 더 많은 리소스가 들기 때문에 당장 효과를 볼 수 있을것임)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. 지식저장소 최신화/정리 Agent 생성 후 구동&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;아마 이러한 상용 서비스 나오기 전 까지 가장 크게 뜰 직업이 이 전체 과정을 구축하는 전문가가 아닐까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1772715825705&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Harness engineering: leveraging Codex in an agent-first world&quot; data-og-description=&quot;By Ryan Lopopolo, Member of the Technical Staff&quot; data-og-host=&quot;openai.com&quot; data-og-source-url=&quot;https://openai.com/index/harness-engineering/&quot; data-og-url=&quot;https://openai.com/index/harness-engineering/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/lmEr5/dJMb8YpTfvt/IJu8ERSsJRNH39V6HDPwn0/img.png?width=1600&amp;amp;height=900&amp;amp;face=0_0_1600_900,https://scrap.kakaocdn.net/dn/oo8jF/dJMb81GU1Zr/vKvRy7FU2rvbSLnus0KJik/img.png?width=1600&amp;amp;height=900&amp;amp;face=0_0_1600_900&quot;&gt;&lt;a href=&quot;https://openai.com/index/harness-engineering/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://openai.com/index/harness-engineering/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/lmEr5/dJMb8YpTfvt/IJu8ERSsJRNH39V6HDPwn0/img.png?width=1600&amp;amp;height=900&amp;amp;face=0_0_1600_900,https://scrap.kakaocdn.net/dn/oo8jF/dJMb81GU1Zr/vKvRy7FU2rvbSLnus0KJik/img.png?width=1600&amp;amp;height=900&amp;amp;face=0_0_1600_900');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Harness engineering: leveraging Codex in an agent-first world&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;By Ryan Lopopolo, Member of the Technical Staff&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;openai.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>개발자 글 수집</category>
      <author>snowman95</author>
      <guid isPermaLink="true">https://11001.tistory.com/290</guid>
      <comments>https://11001.tistory.com/290#entry290comment</comments>
      <pubDate>Fri, 6 Mar 2026 00:21:22 +0900</pubDate>
    </item>
    <item>
      <title>[AI] PLAN.md 몇 시간이 걸리는 복잡한 계획을 수행하는 프롬프트 (번역)</title>
      <link>https://11001.tistory.com/289</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Gemini_Generated_Image_oq4x9doq4x9doq4x.png&quot; data-origin-width=&quot;2752&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/by3NwI/dJMcab4pkFc/fdfIDthKHnjwzottAtx7T0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/by3NwI/dJMcab4pkFc/fdfIDthKHnjwzottAtx7T0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/by3NwI/dJMcab4pkFc/fdfIDthKHnjwzottAtx7T0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fby3NwI%2FdJMcab4pkFc%2FfdfIDthKHnjwzottAtx7T0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2752&quot; height=&quot;1536&quot; data-filename=&quot;Gemini_Generated_Image_oq4x9doq4x9doq4x.png&quot; data-origin-width=&quot;2752&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;Codex 실행 계획(ExecPlans) 가이드라인&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문서는 코딩 에이전트가 작동 가능한 기능이나 시스템 변경 사항을 전달하기 위해 따를 수 있는 설계 문서인 &lt;b&gt;실행 계획(ExecPlan)&lt;/b&gt;의 요구 사항을 설명합니다. 독자를 이 저장소에 대한 완전한 초보자로 취급하십시오. 독자에게는 현재의 작업 트리(working tree)와 귀하가 제공하는 단일 ExecPlan 파일만 주어집니다. 이전 계획에 대한 기억이나 외부 컨텍스트는 존재하지 않는다고 가정합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ExecPlan 및 PLANS.md 사용법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 가능한 명세서(ExecPlan)를 작성할 때는 &lt;b&gt;PLANS.md의 내용을 문자 그대로 엄격히 준수하십시오.&lt;/b&gt; 만약 컨텍스트에 해당 파일이 없다면, PLANS.md 파일 전체를 읽어 기억을 되살리십시오. 정확한 명세를 작성하기 위해 소스 자료를 철저하게 읽고 또 읽으십시오. 명세를 만들 때는 골격(Skeleton)에서 시작하여 조사를 진행함에 따라 내용을 채워 넣으십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 가능한 명세(ExecPlan)를 구현할 때, 사용자에게 &quot;다음 단계&quot;를 묻지 말고 즉시 다음 마일스톤으로 진행하십시오. 모든 섹션을 최신 상태로 유지하고, 중단 지점마다 목록에 항목을 추가하거나 분할하여 진행 상황과 다음 단계를 명확히 밝히십시오. 모호함은 자율적으로 해결하고, 빈번하게 커밋하십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ExecPlan에 대해 논의할 때, 후세를 위해 결정 사항을 명세 내의 로그에 기록하십시오. 명세가 변경된 이유는 모호함 없이 명확해야 합니다. ExecPlan은 &lt;b&gt;살아있는 문서(living document)&lt;/b&gt;이며, 오직 ExecPlan 하나만 가지고 다른 작업 없이도 언제든 다시 시작할 수 있어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;까다로운 요구 사항이나 불확실성이 큰 설계를 조사할 때는 마일스톤을 사용해 개념 증명(PoC)이나 &quot;토이 구현(toy implementations)&quot; 등을 수행하여 사용자의 제안이 실현 가능한지 검증하십시오. 라이브러리를 찾아 소스 코드를 읽고 깊이 있게 연구하며, 완전한 구현을 가이드할 수 있는 프로토타입을 포함하십시오.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;요구 사항&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;타협 불가능한 요구 사항:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;모든 ExecPlan은 완전히 자기 완결적(self-contained)이어야 합니다.&lt;/b&gt; 자기 완결적이란 현재 형태 그대로 초보자가 성공하는 데 필요한 모든 지식과 지침을 포함하고 있음을 의미합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모든 ExecPlan은 살아있는 문서입니다.&lt;/b&gt; 기여자는 진행 상황, 발견 사항 및 확정된 설계 결정에 따라 이를 수정해야 합니다. 각 수정본은 여전히 완전히 자기 완결적이어야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모든 ExecPlan은 초보자가 이 저장소에 대한 사전 지식 없이도 기능을 처음부터 끝까지 구현할 수 있게 해야 합니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모든 ExecPlan은 단순히 &quot;정의를 충족하는&quot; 코드 변경이 아니라, 입증 가능하게 작동하는 동작을 생성해야 합니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모든 ExecPlan은 전문 용어를 사용할 경우 쉬운 언어로 정의하거나, 아예 사용하지 말아야 합니다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;목적과 의도가 최우선입니다.&lt;/b&gt; 먼저 이 작업이 사용자 관점에서 왜 중요한지 몇 문장으로 설명하십시오. 이 변경 후에 사용자가 이전에는 할 수 없었던 무엇을 할 수 있는지, 그리고 그것이 작동하는 것을 어떻게 확인할 수 있는지 설명하십시오. 그런 다음 수정할 내용, 실행할 내용, 관찰해야 할 내용을 포함하여 해당 결과를 달성하기 위한 정확한 단계를 안내하십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계획을 실행하는 에이전트는 파일 목록 확인, 파일 읽기, 검색, 프로젝트 실행 및 테스트 실행을 할 수 있습니다. 에이전트는 이전 컨텍스트를 전혀 모르며 이전 마일스톤에서 당신이 의미한 바를 추론할 수 없습니다. 의존하는 모든 가정은 반복해서 명시하십시오. 외부 블로그나 문서로 링크를 걸지 마십시오. 지식이 필요하다면 계획 자체에 본인의 언어로 포함시키십시오. ExecPlan이 이전 ExecPlan을 기반으로 하고 해당 파일이 체크인되어 있다면 참조로 포함하십시오. 그렇지 않다면 해당 계획의 모든 관련 컨텍스트를 포함해야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;형식 (Formatting)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;형식과 봉투(envelope)는 단순하고 엄격합니다. 각 ExecPlan은 &lt;b&gt;&lt;code&gt;md&lt;/code&gt;로 표시된 단일 코드 블록&lt;/b&gt;이어야 하며, 세 개의 백틱(```)으로 시작하고 끝나야 합니다. 내부에 추가적인 백틱 코드 펜스를 중첩하지 마십시오. 명령어, 기록(transcripts), diff 또는 코드를 보여줘야 할 때는 단일 펜스 내에서 &lt;b&gt;들여쓰기 된 블록&lt;/b&gt;으로 제시하십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ExecPlan의 코드 펜스가 조기에 닫히는 것을 방지하기 위해 코드 펜스 대신 들여쓰기를 사용하십시오. 모든 헤딩 뒤에는 두 개의 줄 바꿈을 사용하고, # 및 ## 등을 사용하며, 번호 매기기 및 글머리 기호 목록의 구문을 정확히 맞추십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 내용이 &lt;i&gt;오직&lt;/i&gt; 단일 ExecPlan인 Markdown(.md) 파일에 작성할 때는 세 개의 백틱을 생략해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평이한 산문체로 작성하십시오. 목록보다는 문장을 선호하십시오. 간결함이 의미를 가릴 정도가 아니라면 체크리스트, 표, 긴 나열은 피하십시오. 체크리스트는 필수 사항인 &lt;code&gt;Progress(진행 상황)&lt;/code&gt; 섹션에서만 허용됩니다. 서사적인 섹션은 산문 중심이어야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;가이드라인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자기 완결성과 평이한 언어가 가장 중요합니다.&lt;/b&gt; 일반적인 영어가 아닌 문구(&quot;daemon&quot;, &quot;middleware&quot;, &quot;RPC gateway&quot;, &quot;filter graph&quot; 등)를 도입한다면 즉시 정의하고, 이 저장소에서 어떻게 나타나는지(예: 관련 파일 이름이나 명령어 제시) 독자에게 상기시키십시오. &quot;이전에 정의된 바와 같이&quot; 또는 &quot;아키텍처 문서에 따라&quot;라고 말하지 마십시오. 반복되더라도 필요한 설명을 여기에 포함하십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흔한 실패 사례를 피하십시오. 정의되지 않은 전문 용어에 의존하지 마십시오. 기능의 &quot;문구&quot;에만 너무 좁게 집중하여 코드는 컴파일되지만 의미 있는 동작은 하지 않는 결과를 초래하지 마십시오. 핵심 결정을 독자에게 떠넘기지 마십시오. 모호함이 존재할 때는 계획 자체에서 해결하고 왜 그 경로를 선택했는지 설명하십시오. 사용자에게 보이는 효과는 과할 정도로 설명하고, 부수적인 구현 세부 사항은 가볍게 명시하십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;관찰 가능한 결과에 계획의 중심을 두십시오.&lt;/b&gt; 구현 후 사용자가 할 수 있는 일, 실행할 명령어, 예상되는 출력을 기술하십시오. 수락 기준은 내부 속성(&quot;HealthCheck 구조체 추가&quot;)이 아니라 인간이 검증할 수 있는 동작(&quot;서버 시작 후 &lt;a href=&quot;http://localhost:8080/health&quot;&gt;http://localhost:8080/health&lt;/a&gt; 접속 시 HTTP 200과 바디 OK 반환&quot;)으로 표현되어야 합니다. 변경 사항이 내부적인 것이라면, 그 영향이 어떻게 입증될 수 있는지 설명하십시오 (예: 변경 전에는 실패하고 변경 후에는 통과하는 테스트 실행, 새로운 동작을 사용하는 시나리오 제시 등).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;저장소 컨텍스트를 명시적으로 지정하십시오.&lt;/b&gt; 파일 이름은 저장소 루트 기준의 전체 경로로 기재하고, 함수와 모듈의 이름을 정확히 명명하며, 새 파일이 생성될 위치를 설명하십시오. 여러 영역을 다루는 경우 초보자가 확신을 가지고 탐색할 수 있도록 각 부분이 어떻게 결합되는지 설명하는 짧은 오리엔테이션 단락을 포함하십시오. 명령어를 실행할 때는 작업 디렉토리와 정확한 명령줄을 보여주십시오. 결과가 환경에 의존하는 경우 가정을 명시하고 합리적인 대안을 제공하십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;멱등성(Idempotent)과 안전성을 유지하십시오.&lt;/b&gt; 단계를 여러 번 실행해도 손상이나 드리프트(drift)가 발생하지 않도록 작성하십시오. 단계가 중간에 실패할 수 있는 경우 재시도 또는 적응 방법을 포함하십시오. 마이그레이션이나 파괴적인 작업이 필요한 경우 백업이나 안전한 폴백(fallback)을 상세히 설명하십시오. 진행하면서 검증할 수 있는 추가적이고 테스트 가능한 변경 사항을 선호하십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;검증은 선택 사항이 아닙니다.&lt;/b&gt; 테스트를 실행하고, 해당하는 경우 시스템을 시작하며, 시스템이 유용한 작업을 수행하는지 관찰하기 위한 지침을 포함하십시오. 새로운 기능이나 역량에 대한 포괄적인 테스트를 기술하십시오. 초보자가 성공과 실패를 구분할 수 있도록 예상 출력과 오류 메시지를 포함하십시오. 가능하면 컴파일 이상의 효과를 증명하는 방법(예: 소규모 엔드 투 엔드 시나리오, CLI 호출, HTTP 요청/응답 기록 등)을 보여주십시오. 프로젝트의 툴체인에 적합한 정확한 테스트 명령어와 결과를 해석하는 방법을 명시하십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;증거를 기록하십시오.&lt;/b&gt; 단계에서 터미널 출력, 짧은 diff 또는 로그가 생성되면 단일 펜스 블록 내에 들여쓰기 된 예시로 포함하십시오. 간결함을 유지하고 성공을 증명하는 내용에 집중하십시오. 패치를 포함해야 할 경우, 거대한 덩어리를 붙여넣기보다 독자가 지침을 따라 재현할 수 있는 파일 단위의 diff나 짧은 발췌본을 선호하십시오.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마일스톤 (Milestones)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마일스톤은 관료적인 절차가 아니라 &lt;b&gt;서사&lt;/b&gt;입니다. 작업을 마일스톤으로 나누는 경우, 각 마일스톤의 범위, 마일스톤이 끝났을 때 이전에는 없었던 무엇이 존재하게 되는지, 실행할 명령어, 예상되는 수락 기준을 설명하는 짧은 단락으로 시작하십시오. 목표, 작업, 결과, 증명이라는 하나의 이야기처럼 읽힐 수 있게 하십시오. 진행 상황(Progress)과 마일스톤은 별개입니다. 마일스톤은 이야기를 들려주고, 진행 상황은 세부 작업을 추적합니다. 둘 다 존재해야 합니다. 단순히 간결함을 위해 마일스톤을 축약하지 마십시오. 향후 구현에 중요할 수 있는 세부 사항을 누락하지 마십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 마일스톤은 독립적으로 검증 가능해야 하며 실행 계획의 전체 목표를 점진적으로 구현해야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;살아있는 계획 및 설계 결정&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ExecPlan은 살아있는 문서입니다. 주요 설계 결정을 내릴 때, 결정 내용과 그 뒤에 숨겨진 사고 과정을 모두 기록하도록 계획을 업데이트하십시오. 모든 결정은 &lt;code&gt;Decision Log(결정 로그)&lt;/code&gt; 섹션에 기록하십시오.&lt;/li&gt;
&lt;li&gt;ExecPlan은 &lt;code&gt;Progress(진행 상황)&lt;/code&gt;, &lt;code&gt;Surprises &amp;amp; Discoveries(놀라운 점 및 발견 사항)&lt;/code&gt;, &lt;code&gt;Decision Log(결정 로그)&lt;/code&gt;, &lt;code&gt;Outcomes &amp;amp; Retrospective(결과 및 회고)&lt;/code&gt; 섹션을 반드시 포함하고 유지해야 합니다. 이는 선택 사항이 아닙니다.&lt;/li&gt;
&lt;li&gt;최적화 도구의 동작, 성능 트레이드오프, 예기치 않은 버그 또는 접근 방식에 영향을 준 반대/취소 의미론(semantics)을 발견하면, 해당 관찰 내용을 &lt;code&gt;Surprises &amp;amp; Discoveries&lt;/code&gt; 섹션에 짧은 증거 스니펫(테스트 출력이 이상적임)과 함께 기록하십시오.&lt;/li&gt;
&lt;li&gt;구현 도중 방향을 바꾸는 경우 &lt;code&gt;Decision Log&lt;/code&gt;에 이유를 문서화하고 &lt;code&gt;Progress&lt;/code&gt;에 그 영향을 반영하십시오. 계획은 당신을 위한 체크리스트인 동시에 다음 기여자를 위한 가이드입니다.&lt;/li&gt;
&lt;li&gt;주요 작업이나 전체 계획이 완료되면 달성된 사항, 남은 과제, 배운 교훈을 요약한 &lt;code&gt;Outcomes &amp;amp; Retrospective&lt;/code&gt; 항목을 작성하십시오.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;프로토타이핑 마일스톤 및 병렬 구현&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대규모 변경의 리스크를 줄이기 위해 명시적인 프로토타이핑 마일스톤을 포함하는 것은 허용되며 종종 권장됩니다. 예: 실현 가능성 검증을 위해 종속성에 저수준 연산자 추가, 또는 최적화 효과를 측정하면서 두 가지 구성 순서 탐색 등. 프로토타입은 추가적이고 테스트 가능하게 유지하십시오. 범위를 &quot;프로토타이핑&quot;으로 명확히 표시하고, 실행 및 결과 관찰 방법을 설명하며, 프로토타입을 채택하거나 폐기하기 위한 기준을 명시하십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트가 계속 통과되도록 하는 추가적인 코드 변경을 먼저 하고 나중에 삭제하는 방식을 선호하십시오. 마이그레이션 중에 이전 경로와 함께 어댑터를 유지하는 것과 같은 병렬 구현은 리스크를 줄이거나 대규모 마이그레이션 중에도 테스트가 계속 통과될 수 있게 한다면 괜찮습니다. 두 경로를 모두 검증하는 방법과 테스트를 통해 한 경로를 안전하게 제거하는 방법을 설명하십시오. 여러 개의 새로운 라이브러리나 기능 영역을 다룰 때는, 이러한 기능들의 실현 가능성을 서로 독립적으로 평가하는 '스파이크(spikes)'를 만드는 것을 고려하십시오. 이를 통해 외부 라이브러리가 예상대로 작동하고 우리가 필요한 기능을 격리된 상태에서 구현하는지 증명하십시오.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;좋은 ExecPlan의 골격&lt;/h2&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;# &amp;lt;짧고 행동 중심적인 설명&amp;gt;

이 ExecPlan은 살아있는 문서입니다. `Progress`, `Surprises &amp;amp; Discoveries`, `Decision Log`, `Outcomes &amp;amp; Retrospective` 섹션은 작업이 진행됨에 따라 최신 상태로 유지되어야 합니다.

PLANS.md 파일이 저장소에 체크인되어 있다면, 저장소 루트로부터의 해당 파일 경로를 여기에 참조하고 이 문서가 PLANS.md에 따라 유지되어야 함을 명시하십시오.

## 목적 / 큰 그림 (Purpose / Big Picture)

이 변경 후에 무엇을 얻게 되는지, 그리고 그것이 작동하는 것을 어떻게 볼 수 있는지 몇 문장으로 설명하십시오. 활성화할 사용자 가시적 동작을 명시하십시오.

## 진행 상황 (Progress)

체크박스가 있는 목록을 사용하여 세부 단계를 요약하십시오. 중단 지점은 모두 여기에 기록되어야 하며, 필요하다면 부분적으로 완료된 작업을 두 개로 분할하십시오(&quot;완료&quot; vs &quot;남음&quot;). 이 섹션은 항상 실제 현재 작업 상태를 반영해야 합니다.

- [x] (2025-10-01 13:00Z) 완료된 단계 예시.
- [ ] 미완료 단계 예시.
- [ ] 부분 완료된 단계 예시 (완료: X, 남음: Y).

진행 속도를 측정하기 위해 타임스탬프를 사용하십시오.

## 놀라운 점 및 발견 사항 (Surprises &amp;amp; Discoveries)

구현 중 발견된 예기치 않은 동작, 버그, 최적화 또는 통찰력을 문서화하십시오. 간결한 증거를 제시하십시오.

- 관찰: &amp;hellip;
증거: &amp;hellip;

## 결정 로그 (Decision Log)

계획 작업 중 내린 모든 결정을 다음 형식으로 기록하십시오:

- 결정: &amp;hellip;
근거: &amp;hellip;
날짜/작성자: &amp;hellip;

## 결과 및 회고 (Outcomes &amp;amp; Retrospective)

주요 마일스톤이나 완료 시점에 결과, 공백, 배운 교훈을 요약하십시오. 결과를 원래 목적과 비교하십시오.

## 컨텍스트 및 오리엔테이션 (Context and Orientation)

독자가 아무것도 모른다고 가정하고 이 작업과 관련된 현재 상태를 설명하십시오. 주요 파일과 모듈을 전체 경로로 명명하십시오. 사용할 명확하지 않은 용어를 정의하십시오. 이전 계획을 참조하지 마십시오.

## 작업 계획 (Plan of Work)

수정 및 추가 순서를 산문체로 설명하십시오. 각 수정에 대해 파일 이름과 위치(함수, 모듈) 및 삽입하거나 변경할 내용을 명시하십시오. 구체적이고 최소한으로 유지하십시오.

## 구체적 단계 (Concrete Steps)

실행할 정확한 명령어와 실행 위치(작업 디렉토리)를 명시하십시오. 명령어가 출력을 생성하는 경우 독자가 비교할 수 있도록 짧은 예상 기록을 보여주십시오. 이 섹션은 작업이 진행됨에 따라 업데이트되어야 합니다.

## 검증 및 수락 (Validation and Acceptance)

시스템을 시작하거나 실행하는 방법과 관찰할 내용을 설명하십시오. 수락 기준을 구체적인 입력과 출력이 있는 동작으로 표현하십시오. 테스트가 포함된 경우 &quot;&amp;lt;프로젝트 테스트 명령어&amp;gt;를 실행하고 &amp;lt;N&amp;gt;개 통과를 예상함; 새로운 테스트 &amp;lt;이름&amp;gt;은 변경 전에는 실패하고 변경 후에는 통과함&quot;이라고 명시하십시오.

## 멱등성 및 복구 (Idempotence and Recovery)

단계를 안전하게 반복할 수 있다면 그렇게 명시하십시오. 단계가 위험하다면 안전한 재시도 또는 롤백 경로를 제공하십시오. 완료 후 환경을 깨끗하게 유지하십시오.

## 산출물 및 참고 사항 (Artifacts and Notes)

가장 중요한 기록, diff 또는 스니펫을 들여쓰기 된 예시로 포함하십시오. 간결함을 유지하고 성공을 증명하는 내용에 집중하십시오.

## 인터페이스 및 종속성 (Interfaces and Dependencies)

규정적으로 작성하십시오. 사용할 라이브러리, 모듈, 서비스를 이름 짓고 그 이유를 밝히십시오. 마일스톤이 끝날 때 존재해야 하는 유형(types), 트레이트/인터페이스, 함수 시그니처를 지정하십시오. `crate::module::function` 또는 `package.submodule.Interface`와 같은 안정적인 이름과 경로를 선호하십시오. 예:

crates/foo/planner.rs에서 다음을 정의함:

pub trait Planner {
fn plan(&amp;amp;self, observed: &amp;amp;Observed) -&amp;gt; Vec&amp;lt;Action&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 지침을 따르면 단일한 상태 비보존형(stateless) 에이전트나 초보자도 귀하의 ExecPlan을 위에서 아래로 읽고 작동하며 관찰 가능한 결과를 만들어낼 수 있습니다. 그것이 기준입니다: &lt;b&gt;자기 완결적, 자기 충분적, 초보자 가이드형, 결과 중심적.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계획을 수정할 때는 살아있는 문서 섹션을 포함한 모든 섹션에 변경 사항이 종합적으로 반영되었는지 확인해야 하며, 계획 하단에 변경 내용과 이유를 설명하는 노트를 작성해야 합니다. ExecPlan은 거의 모든 항목에 대해 '무엇'뿐만 아니라 '왜'를 설명해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1772719916232&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;openai-cookbook/articles/codex_exec_plans.md at main &amp;middot; openai/openai-cookbook&quot; data-og-description=&quot;Examples and guides for using the OpenAI API. Contribute to openai/openai-cookbook development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/openai/openai-cookbook/blob/main/articles/codex_exec_plans.md&quot; data-og-url=&quot;https://github.com/openai/openai-cookbook/blob/main/articles/codex_exec_plans.md&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bHo71I/dJMb9gxjdgE/2drUaLVmy9ZHIiW8I3UXO1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/LND9b/dJMb9hCY7YM/Hnvl2MQivt4kvsNCYiVtZk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/openai/openai-cookbook/blob/main/articles/codex_exec_plans.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/openai/openai-cookbook/blob/main/articles/codex_exec_plans.md&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bHo71I/dJMb9gxjdgE/2drUaLVmy9ZHIiW8I3UXO1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/LND9b/dJMb9hCY7YM/Hnvl2MQivt4kvsNCYiVtZk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;openai-cookbook/articles/codex_exec_plans.md at main &amp;middot; openai/openai-cookbook&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Examples and guides for using the OpenAI API. Contribute to openai/openai-cookbook development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발자 글 수집</category>
      <author>snowman95</author>
      <guid isPermaLink="true">https://11001.tistory.com/289</guid>
      <comments>https://11001.tistory.com/289#entry289comment</comments>
      <pubDate>Thu, 5 Mar 2026 23:10:46 +0900</pubDate>
    </item>
    <item>
      <title>[시니어 FE] 동시성(Concurrency) 에 대해 알아보자</title>
      <link>https://11001.tistory.com/288</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;시니어 FE 시리즈&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시니어 프론트엔드 개발자가 되기위해 해보지 않았던 경험의 틈을 채우거나 기술적으로 딥다이브 해보고자 준비한 시리즈입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Gemini_Generated_Image_lzzm8nlzzm8nlzzm.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5OLvX/dJMcahp2hPG/PqUT2pdAvoze4URTkiMwC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5OLvX/dJMcahp2hPG/PqUT2pdAvoze4URTkiMwC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5OLvX/dJMcahp2hPG/PqUT2pdAvoze4URTkiMwC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5OLvX%2FdJMcahp2hPG%2FPqUT2pdAvoze4URTkiMwC0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2816&quot; height=&quot;1536&quot; data-filename=&quot;Gemini_Generated_Image_lzzm8nlzzm8nlzzm.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;동시성(Concurrency)&lt;/b&gt;은 단순히 async/await를 쓰는 수준을 넘어,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;사용자 경험을 해치지 않으면서 여러 작업을 어떻게 조율(Orchestration)하는가&quot;&lt;/b&gt;에 대한 능력을 검증하는 아주 중요한 키워드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 대표적인 &lt;b&gt;두 가지 구체적인 상황&lt;/b&gt;을 통해 심도 있게 파헤쳐 보겠습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 사용자 입력과 무거운 렌더링의 충돌 (React 18 Transition)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[상황]&lt;/b&gt;&lt;br /&gt;사용자가 검색창에 타이핑을 할 때마다, 하단에 수천 개의 데이터 리스트가 실시간으로 필터링되어 그려져야 합니다. 이때 리스트를 그리는 작업(무거운 작업) 때문에 사용자가 입력하는 글자가 버벅이며 늦게 나타나는 현상이 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[시니어의 해결책: 우선순위 큐(Priority Queue)]&lt;/b&gt;&lt;br /&gt;과거에는 debounce나 throttle로 입력을 지연시켰지만, 이는 근본적인 해결책이 아닙니다. React 18의 &lt;b&gt;Concurrent Mode&lt;/b&gt;는 작업을 '긴급(Urgent)'과 '전환(Transition)'으로 나눕니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Urgent Update:&lt;/b&gt; 글자 입력 (사용자 반응성 직결)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Transition Update:&lt;/b&gt; 리스트 필터링 (조금 늦어도 괜찮음)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[코드 예시]&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;const [isPending, startTransition] = useTransition();
const [filterTerm, setFilterTerm] = useState('');

const handleChange = (e) =&amp;gt; {
  // 1. 긴급 업데이트: 타이핑은 즉시 반영
  setFilterTerm(e.target.value);

  // 2. 비긴급 업데이트: 리스트 렌더링은 메인 스레드가 한가할 때 처리
  startTransition(() =&amp;gt; {
    setFilteredList(bigData.filter(item =&amp;gt; item.includes(e.target.value)));
  });
};

return (
  &amp;lt;&amp;gt;
    &amp;lt;input type=&quot;text&quot; onChange={handleChange} /&amp;gt;
    {isPending ? &amp;lt;Spinner /&amp;gt; : &amp;lt;List data={filteredList} /&amp;gt;}
  &amp;lt;/&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  포인트:&lt;/b&gt; startTransition은 렌더링 도중 더 급한 작업(추가 타이핑)이 들어오면 &lt;b&gt;진행 중인 렌더링을 중단(Interrupt)&lt;/b&gt;하고 새 작업을 먼저 처리합니다. 이것이 진정한 동시성의 핵심입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Race Condition (경쟁 상태) 해결&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[상황]&lt;/b&gt;&lt;br /&gt;탭 메뉴(A, B, C)가 있습니다. 사용자가 'A'를 클릭하고 데이터가 오기 전에 빛의 속도로 'B'를 클릭했습니다. 그런데 네트워크 사정상 'A'의 응답이 'B'보다 늦게 도착했습니다. 결과적으로 화면은 'B' 탭인데 데이터는 'A' 것이 보여주는 &lt;b&gt;데이터 불일치&lt;/b&gt;가 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[시니어의 해결책: 이전 요청 무효화(Cancellation)]&lt;/b&gt;&lt;br /&gt;이것은 전형적인 비동기 동시성 문제입니다. 시니어는 이를 해결하기 위해 &lt;b&gt;AbortController&lt;/b&gt;를 사용하거나, &lt;b&gt;React Query&lt;/b&gt;의 자동 취소 기능을 활용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[코드 예시 (Native JS)]&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;qml&quot;&gt;&lt;code&gt;let currentController = null;

async function fetchData(tabId) {
  // 이전 요청이 있다면 취소
  if (currentController) {
    currentController.abort();
  }

  currentController = new AbortController();

  try {
    const response = await fetch(`/api/data/${tabId}`, { 
      signal: currentController.signal 
    });
    const data = await response.json();
    renderUI(data);
  } catch (error) {
    if (error.name === 'AbortError') {
      console.log('이전 요청 취소됨');
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 심화: 비동기 작업의 병렬성 제어 (Concurrency Control)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[상황]&lt;/b&gt;&lt;br /&gt;사용자가 100개의 이미지를 업로드합니다. Promise.all로 한꺼번에 던지면 브라우저의 네트워크 커넥션 제한에 걸려 성능이 급격히 저하되거나 서버가 터질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[시니어의 해결책: 큐(Queue)를 이용한 동시 실행 수 제한]&lt;/b&gt;&lt;br /&gt;한 번에 딱 5개씩만 업로드되도록 제어하는 큐 시스템을 설계해야 합니다. (라이브러리로는 p-limit 등이 있습니다.)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자바스크립트 연산 자체가 무거운 경우?&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;그런데 useTransition은 렌더링 우선순위를 조절하는 것이지, 자바스크립트 연산 자체가 무거워서 메인 스레드를 점유하는 'Blocking' 현상 자체를 없애주는 건 아니지 않나요? 만약 filter 로직 자체가 2초가 걸린다면 useTransition을 써도 화면은 여전히 멈출 텐데, 이때는 어떻게 하시겠습니까?&quot;&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 연산 자체가 너무 무겁다면 &lt;b&gt;Web Worker&lt;/b&gt;로 넘겨야 합니다.&lt;br /&gt;&lt;a href=&quot;https://11001.tistory.com/287&quot;&gt;[시니어 FE] Web Worker 에 대해 알아보자 (Comlink)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1772709721206&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[시니어 FE] Web Worker 에 대해 알아보자 (Comlink)&quot; data-og-description=&quot;시니어 FE 시리즈시니어 프론트엔드 개발자가 되기위해 해보지 않았던 경험의 틈을 채우거나 기술적으로 딥다이브 해보고자 준비한 시리즈입니다. 그 동안 Web Worker를 막연하게 알고만 있었지 &quot; data-og-host=&quot;11001.tistory.com&quot; data-og-source-url=&quot;https://11001.tistory.com/287&quot; data-og-url=&quot;https://11001.tistory.com/287&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/BxSHY/dJMb8951oME/z6zSt3mE5QWX7qdeEZcG51/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/Zvk81/dJMb84p6wLX/CmqTemkLgaU9oyUegxX7wK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/MIdAJ/dJMb9kmaBgJ/w7aKNqZRC1RCRk5EZwYzek/img.png?width=2816&amp;amp;height=1536&amp;amp;face=0_0_2816_1536&quot;&gt;&lt;a href=&quot;https://11001.tistory.com/287&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://11001.tistory.com/287&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/BxSHY/dJMb8951oME/z6zSt3mE5QWX7qdeEZcG51/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/Zvk81/dJMb84p6wLX/CmqTemkLgaU9oyUegxX7wK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/MIdAJ/dJMb9kmaBgJ/w7aKNqZRC1RCRk5EZwYzek/img.png?width=2816&amp;amp;height=1536&amp;amp;face=0_0_2816_1536');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[시니어 FE] Web Worker 에 대해 알아보자 (Comlink)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;시니어 FE 시리즈시니어 프론트엔드 개발자가 되기위해 해보지 않았던 경험의 틈을 채우거나 기술적으로 딥다이브 해보고자 준비한 시리즈입니다. 그 동안 Web Worker를 막연하게 알고만 있었지&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;11001.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹은 렌더링 단위를 쪼개는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Time Slicing&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;기법(예: 대량의 리스트를 requestIdleCallback으로 조금씩 나눠 그리기)도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Time Slicing&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;브라우저의 메인 스레드를 독점하지 않고, 사용자에게 실시간 응답성을 제공하기 위해 작업을 잘게 쪼개는 기술&quot;로 정의됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트의 Fiber 아키텍처가 내부적으로 하는 일이기도 하지만, 시니어라면 이를 &lt;b&gt;브라우저 네이티브 API&lt;/b&gt; 수준에서 이해하고 직접 제어할 줄 알아야 합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Time Slicing의 핵심 원리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저는 보통 &lt;b&gt;16.7ms(60fps)&lt;/b&gt;마다 한 프레임을 그립니다. 만약 자바스크립트 연산이 &lt;b&gt;100ms&lt;/b&gt; 동안 메인 스레드를 점유하면, 그동안 브라우저는 화면을 그리지 못하고 사용자 입력도 받지 못하는 &lt;b&gt;프리징(Freezing)&lt;/b&gt; 상태가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Time Slicing&lt;/b&gt;은 이 100ms짜리 작업을 &lt;b&gt;5ms짜리 작업 20개&lt;/b&gt;로 쪼개서, 작업 사이사이에 브라우저가 쉬거나 다른 급한 일(사용자 클릭 등)을 처리할 틈을 주는 전략입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. requestIdleCallback을 이용한 구현&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 API는 브라우저가 모든 긴급한 작업(애니메이션, 입력 처리 등)을 마치고 &lt;b&gt;한가할 때(Idle)&lt;/b&gt; 콜백을 실행하도록 예약합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[시나리오: 10,000개의 리스트 아이템 렌더링]&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 번에 10,000개를 그리는 대신, 브라우저가 쉴 때마다 100개씩 끊어서 그리는 예시입니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const bigData = new Array(10000).fill(0).map((_, i) =&amp;gt; `Item ${i}`);
let currentIndex = 0;
const CHUNK_SIZE = 100;

function renderChunk(deadline) {
  // deadline.timeRemaining() &amp;gt; 0: 브라우저가 이번 프레임에서 쉴 수 있는 남은 시간(ms)
  // 남은 시간이 있고, 아직 그릴 데이터가 있다면 계속 실행
  while (deadline.timeRemaining() &amp;gt; 0 &amp;amp;&amp;amp; currentIndex &amp;lt; bigData.length) {
    const chunk = bigData.slice(currentIndex, currentIndex + CHUNK_SIZE);

    // 실제 DOM 조작 또는 상태 업데이트 (현업에선 가상 DOM 업데이트)
    renderToUI(chunk); 

    currentIndex += CHUNK_SIZE;
  }

  // 아직 남은 데이터가 있다면 다음 유휴 시간에 예약
  if (currentIndex &amp;lt; bigData.length) {
    requestIdleCallback(renderChunk);
  }
}

// 최초 실행
requestIdleCallback(renderChunk);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 현대적인 대안: scheduler.postTask와 MessageChannel&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;requestIdleCallback은 실행 주기가 불안정할 수 있다는 단점이 있습니다. 그래서 더 정교한 제어가 필요할 때 시니어들은 다음 방식을 언급합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;scheduler.postTask (Modern API):&lt;/b&gt; 크롬 등 최신 브라우저에서 지원하며, 작업에 우선순위(user-blocking, user-visible, background)를 부여하여 스케줄링할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MessageChannel을 이용한 0ms 지연:&lt;/b&gt; 리액트의 Scheduler 패키지가 내부적으로 사용하는 방식입니다. setTimeout보다 빠르게 다음 태스크로 넘기면서도 메인 스레드에 제어권을 잠시 넘겨줍니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&quot;Time Slicing이 왜 필요한가요?&quot;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;결국 핵심은 &lt;b&gt;메인 스레드 점유권의 양보(Yielding)&lt;/b&gt;입니다.&lt;br /&gt;아무리 성능이 좋은 컴퓨터라도 자바스크립트가 루프를 돌며 스레드를 꽉 잡고 있으면 사용자는 '앱이 멈췄다'고 느낍니다.&lt;br /&gt;무거운 리스트 렌더링이나 복잡한 데이터 가공 시, 작업을 청크(Chunk) 단위로 쪼개고 requestIdleCallback이나 MessageChannel을 활용해 &lt;b&gt;브라우저가 프레임을 그릴 시간을 확보&lt;/b&gt;해 줍니다. 이렇게 하면 전체 작업 완료 시간은 조금 늘어날 수 있어도, 사용자가 느끼는 &lt;b&gt;상호작용성(Interaction)&lt;/b&gt;은 비약적으로 향상됩니다.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  추가 심화&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;리액트 18의 useDeferredValue도 내부적으로는 이 Time Slicing 원리를 이용합니다. 만약 검색어 입력에 따라 리스트가 필터링되는 UI에서 debounce를 쓰는 것과 useDeferredValue를 쓰는 것의 결정적인 차이는 무엇일까요?&quot;&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;debounce는 설정한 시간(예: 300ms) 동안 무조건 기다려야 함.&lt;/li&gt;
&lt;li&gt;useDeferredValue는 브라우저가 한가해지는 즉시 실행됨 (고성능 기기에선 더 빠르게 반응).&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;debounce vs useDeferredValue&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단은 제 경험상 실무에서 &lt;b&gt;useDeferredValue 는 거의 쓸 상황이 생기지 않고,&lt;/b&gt;&amp;nbsp;&lt;b&gt;debounce&lt;/b&gt; 를 훨씬 많이 쓰게됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜냐면 &lt;b&gt;'인터렉션'에 대한 지연이 중요하지, 사실 렌더링 '지연' 을 할 일이 그렇게 많지 않아요!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;useDeferredValue&lt;span&gt;&amp;nbsp;&lt;/span&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=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;렌더링이 무거워서 지연해야하는 경우 메인 쓰레드가 여유로울때 렌더링한다는 개념이 &lt;/span&gt;&lt;b&gt;useDeferredValue &lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 현실의 대부분은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;인터렉션 -&amp;gt; 네트워크 요청 -&amp;gt; 렌더링&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;순서를 거쳐서 화면에 무언가를 보여주게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 단기간에 여러 번 인터렉션(연타, 입력) 했을때&lt;b&gt; '네트워크 요청'&lt;/b&gt; 이 여러번 들어가게 되면 렌더링을 미루는게 의미가 있나요? &lt;br /&gt;네트워크 요청을 1번만 들어가게끔 지연하는게 훨낫죠.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. &quot;네트워크 요청이 포함된 경우&quot; &amp;rarr; Debounce가 압승&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후보자님 말씀대로 인터렉션 -&amp;gt; 네트워크 -&amp;gt; 렌더링 흐름이라면, useDeferredValue는 네트워크 요청 횟수를 줄여주지 못합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;문제점:&lt;/b&gt; 입력을 10번 하면 네트워크 요청도 10번 발생합니다. 비록 리액트가 마지막 결과만 화면에 그리려고 노력하겠지만(Concurrent Rendering), 서버 부하와 불필요한 대역폭 낭비는 막을 수 없습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해결책:&lt;/b&gt; 이때는 &lt;b&gt;Debounce&lt;/b&gt;를 써서 네트워크 요청 자체를 1번으로 제한하는 것이 비용과 성능 측면에서 훨씬 유리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. &quot;순수 클라이언트 연산이 무거운 경우&quot; &amp;rarr; useDeferredValue가 유리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면, &lt;b&gt;이미 모든 데이터를 브라우저가 가지고 있는 상태&lt;/b&gt;에서 사용자의 입력(Filter, Sort)에 따라 화면을 다시 그릴 때는 useDeferredValue가 빛을 발합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;상황:&lt;/b&gt; 10,000개의 주식 데이터를 이미 클라이언트가 들고 있고, 검색어에 따라 실시간 필터링을 할 때.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;장점:&lt;/b&gt; Debounce는 300ms라는 인위적인 지연 시간이 생기지만, useDeferredValue는 사양이 좋은 컴퓨터에서는 지연 없이 즉시, 사양이 나쁜 컴퓨터에서는 버벅이지 않을 정도로만 끊어서 결과를 보여줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  정리: 시니어의 결정 트리 (Decision Tree)&lt;/h3&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구분&lt;/th&gt;
&lt;th&gt;&lt;b&gt;Debounce / Throttle&lt;/b&gt;&lt;/th&gt;
&lt;th&gt;&lt;b&gt;useDeferredValue / Transition&lt;/b&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;최적화 대상&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;이벤트 발생 횟수&lt;/b&gt; 및 외부 리소스(API)&lt;/td&gt;
&lt;td&gt;&lt;b&gt;렌더링 우선순위&lt;/b&gt; 및 CPU 점유율&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;주요 타겟&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;API 서버 부하, 과도한 함수 실행 방지&lt;/td&gt;
&lt;td&gt;메인 스레드 블로킹(Jank) 방지, UX 응답성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;핵심 이점&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;네트워크 비용 절감, 불필요한 작업 차단&lt;/td&gt;
&lt;td&gt;기기 사양에 맞는 가변적 응답 속도 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;결정적 단호함&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&quot;네트워크 요청이 있다면 무조건 Debounce&quot;&lt;/td&gt;
&lt;td&gt;&quot;로컬 데이터 가공/렌더링이 무겁다면 useDeferredValue&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프론트엔드 개발/시니어 시리즈</category>
      <author>snowman95</author>
      <guid isPermaLink="true">https://11001.tistory.com/288</guid>
      <comments>https://11001.tistory.com/288#entry288comment</comments>
      <pubDate>Thu, 5 Mar 2026 20:29:31 +0900</pubDate>
    </item>
    <item>
      <title>[시니어 FE] Web Worker 에 대해 알아보자 (Comlink)</title>
      <link>https://11001.tistory.com/287</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;시니어 FE 시리즈&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시니어 프론트엔드 개발자가 되기위해 해보지 않았던 경험의 틈을 채우거나 기술적으로 딥다이브 해보고자 준비한 시리즈입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Gemini_Generated_Image_3pfk8p3pfk8p3pfk.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N1Q0e/dJMcacWxl6t/ImbEuHA0fRvKracxNKfs0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N1Q0e/dJMcacWxl6t/ImbEuHA0fRvKracxNKfs0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N1Q0e/dJMcacWxl6t/ImbEuHA0fRvKracxNKfs0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN1Q0e%2FdJMcacWxl6t%2FImbEuHA0fRvKracxNKfs0k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2816&quot; height=&quot;1536&quot; data-filename=&quot;Gemini_Generated_Image_3pfk8p3pfk8p3pfk.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 동안 &lt;b&gt;Web Worker&lt;/b&gt;를 막연하게 알고만 있었지 실제로 써볼 기회가 없었습니다.&lt;br /&gt;엄청나게 무거운 정보를 실시간으로 화면에 보여줘야하는 서비스를 만들어본 적이 없었기 때문이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그치만 내가 안해봤다고 모른다고 앞으로도 그런 상황이 주어졌을때 Web Worker 생각을 못한다면 안되겠죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Web Worker의 기본 구조 (Concept)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Web Worker는 브라우저의 &lt;b&gt;메인 스레드&lt;/b&gt;와 별개로 배경(Background)에서 돌아가는 &lt;b&gt;별도의 스레드&lt;/b&gt;입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;메인 스레드:&lt;/b&gt; UI 렌더링, 사용자 클릭 이벤트 처리 (DOM 접근 가능)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Web Worker:&lt;/b&gt; 복잡한 연산, 데이터 가공, 소켓 통신 (DOM 접근 불가)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘 사이는 postMessage와 onmessage라는 메시지 기반 시스템으로 소통합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 실시간 대시보드 설계 구조&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대시보드에서 Web Worker를 활용하는 가장 효율적인 파이프라인은 다음과 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Worker:&lt;/b&gt; WebSocket 연결을 맺고 데이터를 수신합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Worker:&lt;/b&gt; 수신된 대량의 원본 데이터(Raw Data)를 UI에 맞게 가공(Filtering, Sorting, 포맷팅)합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Worker -&amp;gt; Main:&lt;/b&gt; 가공이 끝난 &quot;최종 결과물&quot;만 메인 스레드로 던집니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Main:&lt;/b&gt; 전달받은 데이터를 상태(State)에 넣고 화면을 그립니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 코드 예시 (TypeScript 기반)&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;① Worker 파일 (price.worker.ts)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Worker 내부에서는 self를 통해 전역 객체에 접근합니다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;// worker 환경에서는 DOM에 접근할 수 없음에 유의하세요.
self.onmessage = (e: MessageEvent) =&amp;gt; {
  if (e.data.type === 'CONNECT') {
    const socket = new WebSocket('wss://stock-api.com');

    socket.onmessage = (event) =&amp;gt; {
      const rawData = JSON.parse(event.data);

      // [무거운 작업 예시] 수천 개의 데이터 중 5% 이상 변동된 것만 필터링하고 정렬
      const processedData = rawData
        .filter((item: any) =&amp;gt; Math.abs(item.change) &amp;gt;= 5)
        .sort((a: any, b: any) =&amp;gt; b.price - a.price);

      // 가공된 데이터만 메인 스레드로 전송
      self.postMessage({ type: 'UPDATE_PRICE', data: processedData });
    };
  }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;② 메인 컴포넌트 (Dashboard.tsx)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React 컴포넌트에서 Worker를 생성하고 메시지를 받습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import { useEffect, useState } from 'react';

const Dashboard = () =&amp;gt; {
  const [prices, setPrices] = useState([]);

  useEffect(() =&amp;gt; {
    // 1. Worker 인스턴스 생성
    const worker = new Worker(new URL('./price.worker.ts', import.meta.url));

    // 2. Worker로부터 메시지 수신
    worker.onmessage = (e) =&amp;gt; {
      if (e.data.type === 'UPDATE_PRICE') {
        setPrices(e.data.data); // 이미 가공된 데이터이므로 바로 상태 업데이트
      }
    };

    // 3. Worker에 시작 명령 전송
    worker.postMessage({ type: 'CONNECT' });

    return () =&amp;gt; worker.terminate(); // 컴포넌트 언마운트 시 워커 종료 (메모리 관리)
  }, []);

  return (
    &amp;lt;div&amp;gt;
      {prices.map(p =&amp;gt; &amp;lt;PriceItem key={p.id} data={p} /&amp;gt;)}
    &amp;lt;/div&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 핵심 포인트 (Tricky Parts)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;구조 분해(Structured Clone) 비용:&lt;/b&gt; 메인 스레드와 Worker 사이에서 데이터를 주고받을 때 데이터가 복사(Clone)됩니다. 데이터 양이 너무 크면 이 복사 비용 때문에 메인 스레드가 잠깐 멈출 수 있습니다. 이때는 &lt;b&gt;Transferable Objects&lt;/b&gt;(ArrayBuffer 등)를 사용해 소유권을 넘겨버리는 방식으로 최적화할 수 있다고 언급하세요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Worker 라이브러리 활용:&lt;/b&gt; 실무에서는 Worker 생성을 직접 관리하기보다 Comlink 같은 라이브러리를 사용하여 RPC(Remote Procedure Call) 방식으로 깔끔하게 함수처럼 호출하는 방식을 선호&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Transferable Objects&lt;/b&gt;와 &lt;b&gt;Comlink&lt;/b&gt;를 언급하는 것은&lt;br /&gt;&quot;단순히 기능을 구현하는 수준을 넘어 브라우저의 저수준(Low-level) 메모리 관리와 개발 생산성까지 고려한다&quot;는 강력한 증거가 됩니다.&lt;/p&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;구체적인 예시와 설계&lt;/h1&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Transferable Objects (소유권 이전 방식)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 postMessage는 데이터를 &lt;b&gt;복사(Structured Clone)&lt;/b&gt;합니다. 100MB 데이터를 보내면 메모리에 100MB가 하나 더 생기고, 이 복사 과정에서 메인 스레드가 블로킹됩니다.&lt;br /&gt;&lt;b&gt;Transferable Objects&lt;/b&gt;는 복사하지 않고 데이터의 &lt;b&gt;'소유권(Ownership)'&lt;/b&gt;만 워커로 넘깁니다. 넘겨준 쪽(메인 스레드)에서는 더 이상 그 데이터를 쓸 수 없게 되지만, 복사 비용이 &lt;b&gt;0&lt;/b&gt;에 가깝습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[코드 예시: ArrayBuffer 활용]&lt;/h4&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;// Main Thread
const buffer = new ArrayBuffer(1024 * 1024 * 100); // 100MB 데이터
const uint8Array = new Uint8Array(buffer);

// 데이터를 채운 뒤 워커로 전송
// 두 번째 인자인 배열 [buffer]가 중요합니다. &quot;이 객체의 소유권을 이전하겠다&quot;는 선언입니다.
worker.postMessage(buffer, [buffer]);

console.log(buffer.byteLength); 
// 출력: 0 (소유권이 이전되었으므로 메인 스레드에서는 데이터가 사라짐)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Comlink 활용 (RPC 방식)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;postMessage와 onmessage를 직접 쓰면 코드가 매우 파편화되고 if/else 분기 처리가 복잡해집니다. 구글에서 만든 &lt;b&gt;Comlink&lt;/b&gt;를 쓰면 워커에 있는 함수를 마치 메인 스레드에 있는 일반 비동기 함수처럼 호출할 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[Step 1: Worker 정의 (worker.ts)]&lt;/h4&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;import * as Comlink from 'comlink';

const stockService = {
  processedData: [],
  // 복잡한 계산 로직을 메서드로 정의
  async calculateVolatility(data: any[]) {
    // 무거운 연산 수행...
    return data.filter(d =&amp;gt; d.volatility &amp;gt; 0.5);
  }
};

// Comlink로 객체를 노출(Expose)시킵니다.
Comlink.expose(stockService);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[Step 2: Main Thread에서 사용 (App.tsx)]&lt;/h4&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import * as Comlink from 'comlink';

async function init() {
  const worker = new Worker(new URL('./worker.ts', import.meta.url));

  // 워커를 마치 로컬 객체처럼 래핑합니다.
  const service = Comlink.wrap&amp;lt;any&amp;gt;(worker);

  // 워커 내의 함수를 await로 직접 호출합니다 (메시지 이벤트를 직접 짤 필요 없음)
  const result = await service.calculateVolatility(rawData);
  console.log('가공된 데이터:', result);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  더 발전시키기&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;실시간 대시보드처럼 초당 수백 건의 데이터가 들어오는 환경에서는 postMessage의 Structured Clone 비용조차 성능 병목이 될 수 있습니다.&lt;br /&gt;따라서 저는 대량의 바이너리 데이터를 다룰 때는 ArrayBuffer를 Transferable Objects로 넘겨 메인 스레드의 부하를 제로(0)에 가깝게 유지하는 설계를 선호합니다.&lt;br /&gt;&lt;br /&gt;또한, 팀 협업 측면에서 postMessage를 직접 다루면 이벤트 핸들러가 비대해져 유지보수가 어렵기 때문에, Comlink 같은 라이브러리를 도입하여 RPC 형태로 추상화함으로써 동료들이 워커 로직을 일반 비동기 함수처럼 쉽고 안전하게 호출할 수 있는 환경을 구축하는것이 좋습니다.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;Web Worker는 언제 써야 하는가?&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;언제 쓰는 것이 적합한가?&quot;&lt;/b&gt;라는 질문은 기술의 &lt;b&gt;트레이드오프(비용 대비 이득)&lt;/b&gt;를 이해하고 있는지 묻는 것입니다.&lt;br /&gt;Web Worker는 스레드를 생성하고 데이터를 복사(또는 이전)하는 데 비용이 들기 때문에 모든 곳에 쓰면 안 됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Web Worker 도입이 적합한 상황 (Decision Making)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시니어라면 &lt;b&gt;&quot;메인 스레드(UI Thread)의 응답성&quot;&lt;/b&gt;을 최우선으로 고려해야 합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;CPU 집약적인 무거운 연산:&lt;/b&gt; * 대량의 JSON 데이터 파싱 및 가공 (수천 개의 주식 데이터 필터링/정렬)&lt;/li&gt;
&lt;li&gt;복잡한 수학 계산 (암호화, 이미지/비디오 처리, 캔버스 그래픽 계산)&lt;/li&gt;
&lt;li&gt;큰 규모의 텍스트 분석이나 정규식 검사&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;지속적인 데이터 스트리밍:&lt;/b&gt; * WebSocket을 통해 쉼 없이 들어오는 데이터를 실시간으로 처리해야 할 때&lt;/li&gt;
&lt;li&gt;&lt;b&gt;UI와 독립적인 백그라운드 작업:&lt;/b&gt; * 사용자가 화면을 조작하는 동안 영향을 주지 않고 데이터를 미리 페칭(Prefetching)하거나 인덱싱할 때&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;반대로 부적합한 경우:&lt;/b&gt; 단순한 API 호출이나 작은 데이터 처리. 오히려 Worker를 띄우는 오버헤드와 데이터 전송 비용(Serialization)이 더 커서 성능이 저하될 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Web Worker의 종류&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크게 3가지로 나뉩니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;종류&lt;/th&gt;
&lt;th&gt;특징&lt;/th&gt;
&lt;th&gt;주요 용도&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Dedicated Worker&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;1:1 관계.&lt;/b&gt; 생성한 스레드(Tab)에서만 접근 가능.&lt;/td&gt;
&lt;td&gt;특정 페이지의 무거운 연산.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Shared Worker&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;1:N 관계.&lt;/b&gt; 동일한 도메인의 여러 탭/윈도우에서 공유 가능.&lt;/td&gt;
&lt;td&gt;여러 탭 간의 채팅 연결 공유, 공통 상태 동기화.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Service Worker&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;프록시 서버 역할.&lt;/b&gt; 브라우저와 네트워크 사이에서 동작.&lt;/td&gt;
&lt;td&gt;오프라인 캐싱 (PWA), 푸시 알림, 백그라운드 동기화.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 방금의 대시보드 예시는 어떤 Worker인가?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 구현한 예시는 &lt;b&gt;Dedicated Worker (전용 워커)&lt;/b&gt;입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;이유:&lt;/b&gt; 주식 대시보드라는 특정 페이지(탭)가 열려 있을 때, 그 페이지를 위한 데이터를 처리하기 위해 생성되었기 때문입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;동작 방식:&lt;/b&gt; 해당 컴포넌트가 마운트될 때 new Worker()로 생성되고, 언마운트될 때 terminate()`로 종료되는, 단일 컨텍스트에 종속된 형태입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  정리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;Web Worker를 써본 적 있나요? 없다면 언제 도입하시겠나요?&quot;라고 물으면 이렇게 답변하세요.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;저는 프레임 드랍 없는 사용자 경험을 중요하게 생각합니다.&lt;br /&gt;일반적으로 브라우저는 16.7ms(60fps 기준) 안에 한 프레임의 작업을 마쳐야 하는데, 대시보드처럼 대량의 실시간 데이터를 가공하는 로직이 메인 스레드에서 16.7ms 이상을 점유할 것으로 판단될 때 Web Worker 도입을 검토합니다.&lt;br /&gt;&lt;br /&gt;특히 Dedicated Worker를 사용하여 데이터 수신과 가공을 격리하고, 메인 스레드는 오직 렌더링에만 집중하게 함으로써 복잡한 계산 중에도 사용자 입력이 씹히지 않는 안정적인 아키텍처를 설계하겠습니다.&quot;&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>프론트엔드 개발/시니어 시리즈</category>
      <author>snowman95</author>
      <guid isPermaLink="true">https://11001.tistory.com/287</guid>
      <comments>https://11001.tistory.com/287#entry287comment</comments>
      <pubDate>Thu, 5 Mar 2026 19:48:03 +0900</pubDate>
    </item>
    <item>
      <title>[개발자 이야기] Cursor 를 혼자가 아닌 팀원들과 함께 활용해보는 시도중 (rules 와 skill 의 차이는?)</title>
      <link>https://11001.tistory.com/286</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;715&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t8BoK/dJMcagLqBt2/6nJEN6c4qcYW1XbUYVHG7k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t8BoK/dJMcagLqBt2/6nJEN6c4qcYW1XbUYVHG7k/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t8BoK/dJMcagLqBt2/6nJEN6c4qcYW1XbUYVHG7k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft8BoK%2FdJMcagLqBt2%2F6nJEN6c4qcYW1XbUYVHG7k%2Fimg.webp&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1000&quot; height=&quot;715&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;715&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오늘은 제가 최근에 회사에서 시도중인 내용을 작성해보려고 합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;기존에 Cursor 를 사용하던 방식&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저희 팀은 작년에 vscode + copilot 에서 cursor.ai 를 기본 IDE 로 전환했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 질문, 코드생성, 자동완성에서 나름 만족하면서 쓰고 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 팀 규칙이라거나 그런 것들을 사용하고 있지 않았기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분명 팀에서 cursor 를 사용하고 있기는 하지만, 제대로 활용하고 있다는 느낌을 받지 못했습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 개인적으로 Claude Code 를 사용하면서 경험했던 memory, skill 에 대한 개념과 지식을 가지고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;cursor 를 팀 단위로 활용할 방법에 대해서 고민해보았습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;팀 전체에서 활용해보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선은 &lt;b&gt;AGENTS.md&lt;/b&gt; 파일 부터 만들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트의 기본이자 핵심 지침 내용을 담았습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고&lt;b&gt; .cursor&lt;/b&gt; 폴더 내에 내부에&lt;b&gt; rules, reference 폴더&lt;/b&gt;를 만들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;rules&lt;/b&gt; 에는 500자 이하의 AI Agent 가 반드시 지켜야하는 규칙을 작성했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;rules 와 skills 의 차이는?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;막상 하다보니 이게 정말 헷갈리는겁니다. 검색해보면 수 많은 토론이 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;제&amp;nbsp;경험과&amp;nbsp;검색&amp;nbsp;결과를&amp;nbsp;합쳐보면&amp;nbsp;원래&amp;nbsp;cursor&amp;nbsp;에는&amp;nbsp;지금은&amp;nbsp;레거시인&lt;b&gt;&amp;nbsp;.cursorrules&amp;nbsp;&lt;/b&gt;라는&amp;nbsp;파일이&amp;nbsp;존재했었고&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러니까&amp;nbsp;rules&amp;nbsp;개념이&amp;nbsp;먼저&amp;nbsp;존재했고&amp;nbsp;skill&amp;nbsp;은&amp;nbsp;나중에&amp;nbsp;claude&amp;nbsp;code&amp;nbsp;등에서&amp;nbsp;참고하여&amp;nbsp;만든게&amp;nbsp;아닐까&amp;nbsp;싶은데요.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;클로드&amp;nbsp;코드에서는&amp;nbsp;skill&amp;nbsp;이&amp;nbsp;지식&amp;nbsp;문서&amp;nbsp;또는&amp;nbsp;기능&amp;nbsp;수행이&amp;nbsp;가능한&amp;nbsp;재사용&amp;nbsp;도구&amp;nbsp;정도의&amp;nbsp;개념이거든요.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;근데&amp;nbsp;커서의&amp;nbsp;rules&amp;nbsp;는&amp;nbsp;원하는&amp;nbsp;때에&amp;nbsp;AI&amp;nbsp;에게&amp;nbsp;내려주는&amp;nbsp;지침인데&amp;nbsp;어떤&amp;nbsp;상황에서는&amp;nbsp;이&amp;nbsp;문서를&amp;nbsp;읽어라.&amp;nbsp;&lt;br /&gt;이&amp;nbsp;스크립트를&amp;nbsp;실행해라.&amp;nbsp;이렇게&amp;nbsp;해버리면&amp;nbsp;사실&amp;nbsp;skill&amp;nbsp;이랑&amp;nbsp;똑같잖아요?&amp;nbsp;충분히&amp;nbsp;혼동될&amp;nbsp;만&amp;nbsp;합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&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;정리했습니다.&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;skills&lt;/b&gt; 은 &quot;외부&quot;의 도구를 불러오거나 스크립트 등을 통해 어떠한 기능을 수행할 수 있는 &quot;재활용 가능한 단위&quot;로 작성한다.&lt;br /&gt;어떠한 상황에 의존하는게 아닌, 필요에 의해 사용되는 재사용 도구라고 생각.&lt;br /&gt;(외부 도구를 이용해 웹 스크래핑을 수행)&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;rules&lt;/b&gt; 는 어떠한 상황에서 지켜야하는 규칙을 작성하고, &lt;br /&gt;참고해야하는 문서 등은 &lt;b&gt;reference&lt;/b&gt; 에 작성하여 어떤 파일을 읽으면 되는지 연결시킨다.&lt;br /&gt;'상황'에 의존성이 있다고 생각.&lt;br /&gt;(어떤 도메인에서는 이 문서를 참고, 어떤 형식의 파일을 만들때, 입력 폼을 다룰때, API 연동 규칙, 에러 핸들링 규칙 등)&lt;/blockquote&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마&amp;nbsp;skills&amp;nbsp;를&amp;nbsp;활용하기는&amp;nbsp;쉽지&amp;nbsp;않겠다는&amp;nbsp;생각이&amp;nbsp;들었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클로드&amp;nbsp;코드로&amp;nbsp;치면&amp;nbsp;웹스크래핑&amp;nbsp;도구를&amp;nbsp;써서&amp;nbsp;데이터를&amp;nbsp;모아오는&amp;nbsp;스킬,&amp;nbsp;DB에&amp;nbsp;정보를&amp;nbsp;업로드하는&amp;nbsp;스킬&amp;nbsp;뭐&amp;nbsp;이런&amp;nbsp;식일&amp;nbsp;건데요.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데&amp;nbsp;팀&amp;nbsp;프로젝트에서&amp;nbsp;그럴&amp;nbsp;만한게&amp;nbsp;뭐가&amp;nbsp;있겠습니까.&amp;nbsp;특히&amp;nbsp;안정성,&amp;nbsp;유지보수성&amp;nbsp;때문에&amp;nbsp;새로운&amp;nbsp;코드를&amp;nbsp;맘대로&amp;nbsp;쓰지도&amp;nbsp;못하는&amp;nbsp;프로젝트인걸요.&lt;/p&gt;
&lt;h3 style=&quot;text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;지식 대통합의 기회&lt;/h3&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이것들은 AI Agent 를 위한 것들이지만 동시에 팀원들 끼리&lt;b&gt; 지식을 대통합 할 수 있는 기회&lt;/b&gt;라고 생각이 들었습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;솔직히 회사 들어오고나서 아직까지도 프로젝트 코드를 다 이해를 못했어요... 일일이 까서 열어봐야하는 캡슐화된 코드가 너무 많습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;특히 서버사이트 코드 복잡도는 미쳐버리는 줄 알았어요.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이런 거대하고 복잡한걸 만들어놓고서는 설명하는 문서를 하나도 만들어놓질 않으니&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;새로온 사람이 코드베이스 전체 맥락과 흐름을 다 파악하는데 너무 많은 시간과 노력을 쏟아야 하더군요.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;효과가&amp;nbsp;있을까?&amp;nbsp;기도해보자..&lt;/h3&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사실 AI는 핑계고 어쩌면 지식의 문서화가 더 시급한 목표인 거 같습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;저희 프로젝트에서는 &lt;b&gt;안정성&lt;/b&gt;이 그 무엇보다도 중요하기에 코드 한 줄 한 줄 엄격하게 코드 리뷰를 하는데&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;앞으로도 Claude Code 를 개인 프로젝트에서 권한 다주고 대량의 코드를 책임없이 찍어내게 절대 할 수 없다는것을 알고 있고,&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;지금까지 해왔던 것 처럼 AI Agent 로 매우 국소적인 단위의 코드 생성, 테스트 코드 생성, 이슈 처리, 리뷰 등에만 쓸 것인데.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;적어도 안정성을 더 높이려면 코드 패턴, 비즈니스 로직, 이슈 이런 것들을 문서로 잘 정리해야 할 것이라는 결론이었습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;앞으로 문서가 쌓여갈 수록 cursor 는 더 똑똑하게 알아먹고 대답을 잘 해주겠죠?&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발자 이야기</category>
      <category>AI</category>
      <category>cursor</category>
      <category>커서</category>
      <author>snowman95</author>
      <guid isPermaLink="true">https://11001.tistory.com/286</guid>
      <comments>https://11001.tistory.com/286#entry286comment</comments>
      <pubDate>Thu, 5 Mar 2026 00:51:55 +0900</pubDate>
    </item>
    <item>
      <title>[개발자 이야기] 프론트 개발자의 AI로 인해 잠 못드는 나날</title>
      <link>https://11001.tistory.com/285</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjRExx/dJMcaibnVnI/XrbCZZvPHSqzD1Pq5MR6rk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjRExx/dJMcaibnVnI/XrbCZZvPHSqzD1Pq5MR6rk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjRExx/dJMcaibnVnI/XrbCZZvPHSqzD1Pq5MR6rk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjRExx%2FdJMcaibnVnI%2FXrbCZZvPHSqzD1Pq5MR6rk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;559&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;AI 기술 부채&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI로 인해 흥분되어 잠 못드는 날, AI로 불안해서 잠 못드는 날이 반복됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자고 일어나면 또 새로운 AI 기사가 쏟아지면서 &lt;b&gt;AI 기술 부채&lt;/b&gt;가 나날이 쌓이고 있습니다. 열심히 따라가기 위해 노력 중입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;퇴근하고, 주말에도 쉬지를 못하고 AI를 배우고 공부하고 실습하고 고민하고 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-path-to-node=&quot;3&quot; data-ke-size=&quot;size26&quot;&gt;&quot;껍데기만 만드는 개발자&quot;가 될 것인가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하지만 프론트엔드 개발자는 AI 를 커리어와 직접 연결시키질 못하니 그게 참 답답합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서 팀 단위로 AI를 활용하고 있지 않고, 각자 개인적으로 쓸 뿐이고.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI와 접목한 서비스를 만들고 있지도 않아서 내가 이러다간 AI 시대에 뒤떨어지고 경쟁력에서 밀리는 것이 아닐까 두려움이 듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 제가 &lt;b&gt;프론트엔드 개발자&lt;/b&gt;라서 더욱 더 스트레스가 큰 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설령 회사에서 AI 서비스를 개발하더라도 이미 다 만들어진 AI 서비스를 화면상에 보여주기만 하면 되는 일이라서 이거는 절대 AI 개발자라고 할 수가 없죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 그런 직무를&lt;b&gt; AI Service Frontend-Engineer&lt;/b&gt; 라는 이름으로 뽑는 회사가 있던데 그냥 AI 서비스를 화면에 보여주는거죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 난 이전에 머신러닝을 통해 만들어낸 데이터를 화면 상에 보여주는 일을 했는데 AI Frontend-Engineer 개발자라고 할 수 있는가? LLM 을 안썼으니 인정 안되는건가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뒷단이 어떻게 되어있든 화면에 그리는 역할이라는 본질을 같은걸?..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;내가 지금 하고 있는 일에서 어떻게든 AI와 '직접적'으로 엮이려면?&lt;/b&gt; &lt;br /&gt;빠르게 백엔드 영역으로 확장하고 백터DB, LLM 연결하여 AI 기능을 제공하는 백엔드 개발자가 되어야 하는건데..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 내가 그 수준에 도달했을때 과연 세상은 또 얼마나 바뀌어 있을지 미지수입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쩌면 인프라 담당자만 남아있을 수도 있겠죠. &lt;b&gt;그러면 제가 인프라 하러 가는게 맞을까요? 단지 오래 살아남을 것 같으니까?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;책임 지는 사람이 필요한&lt;/b&gt; &lt;b&gt;거라면 직무 유지하고 제 연차와 경험으로 비비고&lt;/b&gt; 들어가는게 나을 수도 있는 선택일 수 있겠죠.&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프론트엔드 개발자의 선택의 기로&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 스테이 (직무 유지)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 회사의 직무 그대로 유지하면서 현재에 충실히 사는 방법.. 자유롭게 뭔가 할 수 있는 회사는 아니지만 AI로 시끄럽게 떠들어본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그치만 그게 AI 경력으로 쌓이는 것도 아니고, 앞으로도 큰 변화가 기대되진 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다고 직무 전환을 해달라고 때쓰면 어디로 가나? 누가 받아주나?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 직무 변환 가능한 회사로 이직 (아마 AI스타트업)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 이 게임을 해봤어요. (AI 스타트업을 다녀봤어요)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 만능이 아니다. 아무리 언변이 뛰어나도 돈 못벌면 끝이다. 스타트업은 참으로 냉혹한 곳이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 이걸 선택하게 되면 또 경력 2-3년 다시 쌓아서 과거에 했던것 처럼 대기업 경력직에 도전하겠죠...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 또 경력 리셋으로 인한 돈은 돈대로 후려치기 당하고, AI는 얼마나 더 발전되어 있을지도 모르고..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 이직하고 금융치료 (직무 유지)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;국내 TOP IT 회사 중에서 비포괄 회사로 가서 퇴근 안한다고 생각하고 야근비 뽑아먹는게 제일 편하고 좋은 방법일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 환자고 금융치료가 필요한 걸 지도 모르겠습니다. 커리어 경력도 버리지 않고 그대로 인정받고요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 는 주말에 공부하면 되지.. GPU 값 벌어야지&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;&lt;span style=&quot;text-align: start;&quot;&gt;제미나이 선생님&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;제미나이 선생님께서도 그냥 금융치료 받으라고 하네요. ㅋㅋ&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작년에 이직하고 이사하고 결혼 준비하고.. 진짜 미친듯이 많은 일이 있었는데요. 올해가 더 하면 더 할듯 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-03-02 오후 4.19.06.png&quot; data-origin-width=&quot;1104&quot; data-origin-height=&quot;848&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bctWeG/dJMcabi2cNo/hmSoJP2FCXWmNnAAeOONuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bctWeG/dJMcabi2cNo/hmSoJP2FCXWmNnAAeOONuK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bctWeG/dJMcabi2cNo/hmSoJP2FCXWmNnAAeOONuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbctWeG%2FdJMcabi2cNo%2FhmSoJP2FCXWmNnAAeOONuK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1104&quot; height=&quot;848&quot; data-filename=&quot;스크린샷 2026-03-02 오후 4.19.06.png&quot; data-origin-width=&quot;1104&quot; data-origin-height=&quot;848&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>개발자 이야기</category>
      <author>snowman95</author>
      <guid isPermaLink="true">https://11001.tistory.com/285</guid>
      <comments>https://11001.tistory.com/285#entry285comment</comments>
      <pubDate>Mon, 2 Mar 2026 16:34:54 +0900</pubDate>
    </item>
    <item>
      <title>Anthropic Courses - 무료 온라인 강의 공개</title>
      <link>https://11001.tistory.com/284</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1446&quot; data-origin-height=&quot;298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxA4D0/dJMcac3gams/T1ftJAUF5J7snwZw1dLOkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxA4D0/dJMcac3gams/T1ftJAUF5J7snwZw1dLOkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxA4D0/dJMcac3gams/T1ftJAUF5J7snwZw1dLOkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxA4D0%2FdJMcac3gams%2FT1ftJAUF5J7snwZw1dLOkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1446&quot; height=&quot;298&quot; data-origin-width=&quot;1446&quot; data-origin-height=&quot;298&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;figure id=&quot;og_1772433249612&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Anthropic Courses&quot; data-og-description=&quot;Browse all Anthropic courses&quot; data-og-host=&quot;anthropic.skilljar.com&quot; data-og-source-url=&quot;https://anthropic.skilljar.com/&quot; data-og-url=&quot;https://anthropic.skilljar.com/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/iD5vm/dJMb87f3Voe/DKLYClm9p1C3uGSF0RHeWk/img.png?width=2400&amp;amp;height=1260&amp;amp;face=0_0_2400_1260,https://scrap.kakaocdn.net/dn/87Jb5/dJMb9jOksDk/s0fXz8sqK5znFktHboaCw1/img.png?width=2400&amp;amp;height=1260&amp;amp;face=0_0_2400_1260,https://scrap.kakaocdn.net/dn/rIjIt/dJMb8QL9sLI/TtqJjQBfZUvHk3pqM7sjFk/img.png?width=2400&amp;amp;height=1260&amp;amp;face=0_0_2400_1260&quot;&gt;&lt;a href=&quot;https://anthropic.skilljar.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://anthropic.skilljar.com/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/iD5vm/dJMb87f3Voe/DKLYClm9p1C3uGSF0RHeWk/img.png?width=2400&amp;amp;height=1260&amp;amp;face=0_0_2400_1260,https://scrap.kakaocdn.net/dn/87Jb5/dJMb9jOksDk/s0fXz8sqK5znFktHboaCw1/img.png?width=2400&amp;amp;height=1260&amp;amp;face=0_0_2400_1260,https://scrap.kakaocdn.net/dn/rIjIt/dJMb8QL9sLI/TtqJjQBfZUvHk3pqM7sjFk/img.png?width=2400&amp;amp;height=1260&amp;amp;face=0_0_2400_1260');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Anthropic Courses&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Browse all Anthropic courses&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;anthropic.skilljar.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #1f2023; color: #b1b1b1; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;개발자 대상 과정&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #1f2023; color: #b1b1b1; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;https://anthropic.skilljar.com/claude-code-in-action&quot;&gt;Claude Code in Action&lt;/a&gt;&lt;/b&gt;: Claude Code를 개발 워크플로에 통합하는 실습 과정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;https://anthropic.skilljar.com/claude-with-the-anthropic-api&quot;&gt;Building with the Claude API&lt;/a&gt;&lt;/b&gt;: Anthropic 모델을&amp;nbsp;&lt;b&gt;Claude API&lt;/b&gt;로 활용하는 전 과정을 포괄적으로 다루는 과정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;https://anthropic.skilljar.com/introduction-to-model-context-protocol&quot;&gt;Introduction to Model Context Protocol&lt;/a&gt;&lt;/b&gt;: Python으로&amp;nbsp;&lt;b&gt;MCP 서버와 클라이언트&lt;/b&gt;를 처음부터 구축하는 방법 학습
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MCP의 세 가지 핵심 프리미티브인&amp;nbsp;&lt;b&gt;tools, resources, prompts&lt;/b&gt;를 다룸&lt;/li&gt;
&lt;li&gt;Claude를 외부 서비스에 연결하는 방법 포함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;https://anthropic.skilljar.com/model-context-protocol-advanced-topics&quot;&gt;Model Context Protocol: Advanced Topics&lt;/a&gt;&lt;/b&gt;: 샘플링, 알림, 파일 시스템 접근,&amp;nbsp;&lt;b&gt;트랜스포트 메커니즘&lt;/b&gt;&amp;nbsp;등 프로덕션 MCP 서버 개발을 위한 고급 구현 패턴&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;https://anthropic.skilljar.com/introduction-to-agent-skills&quot;&gt;Introduction to Agent Skills&lt;/a&gt;&lt;/b&gt;: Claude Code에서&amp;nbsp;&lt;b&gt;재사용 가능한 마크다운 기반 스킬&lt;/b&gt;을 생성&amp;middot;구성&amp;middot;공유하는 방법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Claude가 적절한 작업에 자동으로 적용하는 스킬을 만드는 과정&lt;/li&gt;
&lt;li&gt;팀 간 배포 및 일반적 문제 해결까지 포함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;background-color: #1f2023; color: #b1b1b1; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;일반 사용자 및 입문 과정&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #1f2023; color: #b1b1b1; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;https://anthropic.skilljar.com/claude-101&quot;&gt;Claude 101&lt;/a&gt;&lt;/b&gt;: 일상 업무에 Claude를 활용하는 방법,&amp;nbsp;&lt;b&gt;핵심 기능 이해&lt;/b&gt;, 고급 학습 리소스 탐색&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;https://anthropic.skilljar.com/ai-fluency-framework-foundations&quot;&gt;AI Fluency: Framework &amp;amp; Foundations&lt;/a&gt;&lt;/b&gt;: AI 시스템과 효과적&amp;middot;효율적&amp;middot;윤리적&amp;middot;안전하게&amp;nbsp;&lt;b&gt;협업하는 프레임워크&lt;/b&gt;&amp;nbsp;학습&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;background-color: #1f2023; color: #b1b1b1; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;교육&amp;middot;학생&amp;middot;비영리 대상 과정&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #1f2023; color: #b1b1b1; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;https://anthropic.skilljar.com/ai-fluency-for-educators&quot;&gt;AI Fluency for Educators&lt;/a&gt;&lt;/b&gt;: 교수진, 교육 설계자, 교육 리더가 AI Fluency를&amp;nbsp;&lt;b&gt;자신의 교육 실무와 기관 전략&lt;/b&gt;에 적용하는 과정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;https://anthropic.skilljar.com/ai-fluency-for-students&quot;&gt;AI Fluency for Students&lt;/a&gt;&lt;/b&gt;: 학생들이 학습, 커리어 계획, 학업 성취를 위해&amp;nbsp;&lt;b&gt;책임감 있는 AI 협업 역량&lt;/b&gt;을 개발하는 과정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;https://anthropic.skilljar.com/teaching-ai-fluency&quot;&gt;Teaching AI Fluency&lt;/a&gt;&lt;/b&gt;: 학술 교수진과 교육 설계자가&amp;nbsp;&lt;b&gt;강사 주도 환경에서 AI Fluency를 교육&amp;middot;평가&lt;/b&gt;하는 과정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;https://anthropic.skilljar.com/ai-fluency-for-nonprofits&quot;&gt;AI Fluency for Nonprofits&lt;/a&gt;&lt;/b&gt;: 비영리 전문가가 조직의 임팩트와 효율성을 높이면서&amp;nbsp;&lt;b&gt;미션과 가치에 충실한 AI 역량&lt;/b&gt;을 개발하는 과정&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;background-color: #1f2023; color: #b1b1b1; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;클라우드 플랫폼 통합 과정&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #1f2023; color: #b1b1b1; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;https://anthropic.skilljar.com/claude-in-amazon-bedrock&quot;&gt;Claude with Amazon Bedrock&lt;/a&gt;&lt;/b&gt;: AWS 직원 대상으로 만들어진&amp;nbsp;&lt;b&gt;인증 프로그램 기반 교육&lt;/b&gt;을 일반에 공개&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;https://anthropic.skilljar.com/claude-with-google-vertex&quot;&gt;Claude with Google Cloud's Vertex AI&lt;/a&gt;&lt;/b&gt;: Google Cloud의&amp;nbsp;&lt;b&gt;Vertex AI&lt;/b&gt;를 통해 Anthropic 모델을 활용하는 전 과정을 포괄적으로 다룸&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발자 글 수집</category>
      <author>snowman95</author>
      <guid isPermaLink="true">https://11001.tistory.com/284</guid>
      <comments>https://11001.tistory.com/284#entry284comment</comments>
      <pubDate>Mon, 2 Mar 2026 15:35:10 +0900</pubDate>
    </item>
  </channel>
</rss>