<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>어들의 세상, 세상의 어들</title>
    <link>https://urdle.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 20 Jul 2026 13:09:19 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Urdle</managingEditor>
    <image>
      <title>어들의 세상, 세상의 어들</title>
      <url>https://tistory1.daumcdn.net/tistory/4545828/attach/cc215bf5ac6e4c82a4d86039118cf8d5</url>
      <link>https://urdle.tistory.com</link>
    </image>
    <item>
      <title>AX에서 '무엇을 만들 것인가'보다 중요한 것은 '무엇을 안 만들 것인가'</title>
      <link>https://urdle.tistory.com/301</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;AX에 대한 관심이 뜨겁다. 어느 한 쪽에선 열정을 다해 모든 것을 AX하고 있는 모양새고, 어느 한 쪽에서는 굉장한 회의감을 느끼는 모양새다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;얼마 전 친구와 친친(친구의 친구분)을 포함해 개발자 3명과 커피챗을 가졌다. 프론트엔드 엔지니어 2명, 백엔드 엔지니어 1명이었는데 다들 AX의 생산성과 효율성에 대해 말하면서도 회의감을 가지고 있었다. 모두가,&amp;nbsp;&lt;b&gt;굳이 만들 필요 없는 것을 만드느라 리소스만 낭비한 경험, 이미 좋은 서비스가 있음에도 AX를 하고 동료에게 적응을 강요해서 오히려 생산성과 팀워크가 저해된 경험&lt;/b&gt;, 그로 인한 &lt;b&gt;수습을 누군가가 해야만 했던 경험&lt;/b&gt; 등 AX의 폐해를 보거나 들은 적이 있다고 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아빠와도 요즘 AX에 대한 대화를 많이 하고 있는데, 아빠 또한 비슷한 얘기를 한다. &lt;span style=&quot;color: #9d9d9d;&quot;&gt;(아빠는 &lt;span style=&quot;text-align: start;&quot;&gt;고등학교 시절 집에서 손코딩한 종이를 들고 세운상가의 컴퓨터 가게를 오가며 코드를 돌려보다가 결국 전산학과(...)에 진학해 지금은 AI 기술 PO로 일하고 있는 진성 개발자다) &lt;/span&gt;&lt;/span&gt;물론 아빠는 AX를 적극적으로 하는 주체의 입장이다보니 살짝 다른 관점이었다. &lt;b&gt;'[만들 수 있으니까 만드는 거]는 집에서&lt;/b&gt; 하면 되고, &lt;b&gt;회사에서는 [만들어야 해서 만드는 거]를 해야&lt;/b&gt; 한다'(...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 주변 개발자들의 이런 이야기들을 계속 접하다 보니 기획자로서는 상당히 생각이 깊어질 수밖에 없는 와중, 마침 오늘 또 한 스타트업의 전사적 AX 사례를 인상깊게 읽은 후 이에 대한 개발자의 신랄한 비판글까지 보게 되어 메모 겸 정리해 본다. 글 링크는 첨부하지 않고 따로 메모해두었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AX를 할 때 고려해야 할 것&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;What 이전에 Why&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;비판글은 사례에 '무엇을 했는지'는 있는데 '왜 그렇게 했는지'가 없다고 지적했다.&lt;/b&gt;AI로 며칠 만에 인증 프록시를 제작했고 몇 시간 만에 에디터 동기화 플러그인을 제작했다고 적혀 있었는데, &lt;b&gt;기존에 잘 만들어진 검증된 오픈소스나 솔루션을 충분히 비교한 뒤에 커스텀을 결정한 것인지&lt;/b&gt;&amp;nbsp;궁금하다고 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;제작 비용이 낮아지면&lt;span&gt;&amp;nbsp;&lt;/span&gt;대안 탐색이 상대적으로 비싼 일처럼 느껴진다. &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;&quot;AI로 금방 만들 수 있는데 왜 찾아봐?&quot;가 되는 순간, 검색 30분이면 끝났을 일에 며칠의 시간과 토큰을 태우게 된다는 것이다. &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;blockquote data-ke-style=&quot;style3&quot;&gt;- 디자인 툴의 무료 기본 플러그인으로 해결되는 기능을 워크플로우 설계도 없이 며칠간 토큰 십만 원어치를 소모해서 애매한 품질로 재구현함.&lt;br /&gt;- 이 AI slop이 내놓은 산출물들의 뒤처리는 담당 디자이너가 부담함.&lt;br /&gt;- 그런데 그 디자이너는 &quot;AI를 못 쓴다&quot;는 타박을 들음.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&amp;nbsp;대안 탐색 시간은 아무리 AI가 바로 서비스를 만들어줄 수 있다고 해도 절대 줄이면 안 되는 고정 비용이고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;'만들 수 있다'는 '만들어야 한다'의 근거가 될 수 없다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ROI를 계산할 것&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사례 글은 업무 시간을 몇십 퍼센트 절감했고, 계획 대비 몇십 퍼센트나 적은 리소스를 사용한 것이 성과라고 적고있었다. 이에 대해, 비판글을 작성하신 분은 '그래서 토큰당 ROI는 계산했는지' 궁금해했다. 분자 즉 절감량만 있고 분모(총비용)이 없는데, 어떻게 이게 덮어놓고 성과가 될 수 있느냐는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소모한 토큰 비용&lt;/li&gt;
&lt;li&gt;산출물을 사람이 수정&amp;middot;뒤처리한 시간&lt;/li&gt;
&lt;li&gt;자체 제작 도구의 유지보수 비용 (만든 순간부터 부채)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총비용에는 위의 것들도 포함되어야 하고, 그것에 '대비'해서 계산해야 성과인 것이지,&amp;nbsp;&quot;하루 N분 절약&quot;은 그 자체로 성과가 될 수 없다고 했다. &lt;b&gt;무엇을 얼마에 주고 샀는지도 파악하라는 얘기...&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;왜 꼭 그 스택이어야만 했는지 설명할 수 있을 것&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 지식이라 내가 이해를 못한 부분이지만&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사내 앱 배포에 Kubernetes &amp;mdash; 그 규모에 필요한 부하인가? 람다 같은 가벼운 스크립트 실행으로 만족할 사용자도 많지 않았을까?&lt;/li&gt;
&lt;li&gt;온프레미스인지 클라우드인지조차 글에서 불명확&lt;/li&gt;
&lt;li&gt;특정 IDE 선택 &amp;mdash; 이미 평판이 갈리는 도구인데, 다른 GUI 대안(예: Windows용 Claude 데스크톱류)은 검토했는가? WSL 세팅은 해준 것인가?&lt;/li&gt;
&lt;li&gt;Windows/macOS 환경 차이는 고려했는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요지는 &quot;그 선택이 틀렸다&quot;는 아니었고 독자 입장에서 정보가 너무 없다는 거였다.&amp;nbsp;&lt;b&gt;선택의 근거가 서술되지 않으면 독자는 합리적 선택인지 과잉 설계인지 판단할 수 없고, 그 사례는 재현 불가능한 정보가 된다&lt;/b&gt;는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자가 아니라서 스택에 대한 이해도가 낮으면 적어도 AI와 함께 스택이 왜 꼭 그것이어야만 할지에 대한 검토를 진행한 후에 작업에 들어가야겠다는 교훈을 얻었음. 추가로, 해당 글에서 배운 것: 기술 선택 기록의 최소 구성&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;span style=&quot;color: #333333; text-align: start;&quot;&gt;ADR(&lt;/span&gt;Architectural Decision Records) 필요.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;근데 이 부분은 &amp;nbsp;내가 의도치 않게 개인 플랜을 사용하면서 습관화된 것 같은 게, 무언가 AI를 가지고 만들 때 내가 해당 스펙을 전혀 모르는 것에 대한 공포와 그로 인한 토큰 낭비에 대한 공포도 커서 무언가를 시작하기 전에 항상 &lt;b&gt;스펙적으로 '꼭 그거여야 하는지'를 집요하게 묻는 버릇&lt;/b&gt;을 갖게 됐다. 그리고 이걸 &lt;b&gt;나중에 이관하거나 스펙을 변경할 때 비용과 리스크는 어떨지, 유지보수는 어떨지&lt;/b&gt;도 꼭 확인한다.&lt;/blockquote&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;갱신 주기와 폐기 규칙이라는 가드레일이 없는 축적은, 나중에 AI 오답의 원료가 된다.&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;필요한 관리 과제:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;SSOT&lt;/b&gt;: 같은 사실이 여러 문서에 흩어질 때 무엇이 원본인가&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Stale&lt;/b&gt;: 낡은 문서가 남으면 AI가 확신을 갖고 틀린 답을 생성&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Drift&lt;/b&gt;: 문서와 실제 시스템이 시간이 지나며 조용히 어긋남&lt;/li&gt;
&lt;li&gt;&lt;b&gt;검색 계층&lt;/b&gt;: 문서 수천 개 규모에서 그래프 시각화는 감상용. 임베딩/RAG 기반 검색이 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;검증까지 넣어야 자동화&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;종료 조건&lt;/b&gt;: 에이전트 파이프라인에 &quot;제대로 됐는지 검증&quot;의 기준이 명시되지 않으면, 에이전트는 무한 대기하거나 무비판 통과시킴&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자기 개선 루프&lt;/b&gt;: 만든 자동화가 실제로 효율적인지 측정하고 개선하는 순환이 필요함. 버전 관리 역시 필요함.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보안 운영&lt;/b&gt;: 시크릿 유출 스캐닝은? Node 버전&amp;middot;패키지 매니저 관리 주체는? npm 공급망 공격이 터지면?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 자동화 설계 시 &lt;b&gt;성공 판정 기준과 중단 조건을 먼저 정의&lt;/b&gt;한다. 이게 없으면 자동화가 아니라 방치다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;도구 사용을 하게 하는 것도 리소스&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사례 글에서는 터미널 미경험자에게 CLI 교육이 장애물이어서 GUI로 진입장벽을 낮춘 뒤 단계를 이전했다고 하는데 비판글은 이 문제의식과 해결은 좋았다고 했다. 그러면서 반대 사례의 에피소드를 들었는데 워크플로우 설계 없이 AI만 강요하는 바람에 도구 미숙이 &lt;b&gt;개인 역량 문제로 전가&lt;/b&gt;되고, 산출물 뒤처리는 강요당한 쪽이 부담했다는 거였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 기획자한테는 좀 다른 의미로 다가왔다. AX라는 게 내부인을 대상으로 하니까 내부인한테 강요까지 가능한 거지, AI로 뭔가를 쉽게 만들 수 있다는 이유로 대충 퉁 만들었다고 해도 고객이 안 쓰면 그만이니까.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 도입 성공 지표는 &quot;몇 명이 쓰는가&quot;가 아니라 &lt;b&gt;&quot;쓰는 사람의 총 작업시간이 줄었는가&quot;&lt;/b&gt;&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;p data-ke-size=&quot;size16&quot;&gt;그러니까 정리하면, &quot;무엇을 만들지&quot;도 중요하지만 그보다 더 중요한 것은&amp;nbsp;&lt;b&gt;&quot;애초에 만들지 않을지&quot;&lt;/b&gt; 에 대한 의사결정이라는 것이다. hype에 올라타 &quot;다 되네, 다 해보자&quot;로 가는 건 빠르지만, 그 대가로 비용과 복잡도를 감내해야 할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 예전에 TIL 탐색에 소모됐던 시간을 아끼는 자동화 슬랙봇을 만들면서, 우연찮게 &quot;어떻게 TIL을 편하게 볼까&quot;가 아니라 &quot;왜 우리는 매일 1시간씩 쓰면서도 효율적인 공유와 공부는 못 했는가&quot;가 진짜 문제였다는 것을 깨달았었다. AX도 같을 것이다. &quot;어떻게 AI를 더 쓸까&quot;가 아니라 &lt;b&gt;&quot;왜 이 일에 AI가 필요한가&quot;&lt;/b&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;제작 전: 기존 대안 후보 3개 + 탈락 사유 기록&lt;/li&gt;
&lt;li&gt;기술 선택 시: 제약조건 / 되돌리는 비용 기록&lt;/li&gt;
&lt;li&gt;자동화 설계 시: 성공 판정 기준 / 중단 조건 정의&lt;/li&gt;
&lt;li&gt;문서 축적 시: 갱신 주기 / 폐기 규칙 설정&lt;/li&gt;
&lt;li&gt;도입 시: 사용자 학습 비용을 총비용에 포함, 워크플로우까지 설계&lt;/li&gt;
&lt;li&gt;도입 후: 절감 시간 + 총비용(토큰 + 유지보수 + 뒤처리) 동시 산정&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;용어 정리&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ADR (Architecture Decision Record)&lt;/td&gt;
&lt;td&gt;기술 의사결정을 배경&amp;middot;후보&amp;middot;선택 이유&amp;middot;결과로 남긴 문서. &quot;왜 이걸 골랐는가&quot;를 추적하기 위한 기록&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI slop&lt;/td&gt;
&lt;td&gt;AI가 대량 생성한 저품질 산출물. 겉보기엔 그럴듯하나 사람이 재작업해야 하는 결과물&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;하네스(harness)&lt;/td&gt;
&lt;td&gt;에이전트를 실행&amp;middot;감시&amp;middot;평가하는 바깥 틀. 검증과 중단 로직을 담당&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RAG&lt;/td&gt;
&lt;td&gt;질문과 관련된 문서를 먼저 검색해 AI에게 근거로 제공하는 방식. 문서가 많을 때 필수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;임베딩&lt;/td&gt;
&lt;td&gt;문서를 의미 기반으로 검색 가능하게 수치화한 것. RAG의 기반&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSOT (Single Source of Truth)&lt;/td&gt;
&lt;td&gt;하나의 사실은 한 곳에서만 관리한다는 원칙. 사본이 흩어지면 신뢰도 붕괴&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stale (데이터)&lt;/td&gt;
&lt;td&gt;갱신되지 않아 낡은 상태의 정보&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Drift&lt;/td&gt;
&lt;td&gt;문서와 실제 시스템이 시간이 지나며 서로 어긋나는 현상&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단일 진실 공급원은 알고 있었는데 그걸 SSOT로 줄여 말하는 것은 처음 알았다...&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;인프라&amp;middot;배포&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Kubernetes (K8s)&lt;/td&gt;
&lt;td&gt;여러 서버에 걸쳐 앱을 자동 배치&amp;middot;확장&amp;middot;복구하는 관리 시스템. 규모가 작으면 과잉일 수 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;람다(Lambda)류 서버리스&lt;/td&gt;
&lt;td&gt;서버 관리 없이 함수(스크립트) 단위로만 실행하는 방식. 소규모 자동화에 적합한 경량 대안&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CI/CD&lt;/td&gt;
&lt;td&gt;코드 변경을 자동으로 검사&amp;middot;빌드&amp;middot;배포하는 파이프라인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;온프레미스&lt;/td&gt;
&lt;td&gt;외부 클라우드가 아닌 자사 보유 서버에서 직접 운영하는 방식&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;리버스 프록시&lt;/td&gt;
&lt;td&gt;요청을 앱보다 먼저 받아 인증&amp;middot;차단&amp;middot;기록을 수행하는 중간 계층&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;감사 로그&lt;/td&gt;
&lt;td&gt;누가 언제 무엇에 접근했는지 남기는 기록&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;시크릿 / 시크릿 스캐닝&lt;/td&gt;
&lt;td&gt;API 키&amp;middot;비밀번호 등 유출 금지 정보 / 코드에 실수로 포함됐는지 자동 검사하는 도구&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;공급망 공격&lt;/td&gt;
&lt;td&gt;외부 패키지&amp;middot;라이브러리를 경유해 침투하는 공격 방식&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;패키지 매니저&lt;/td&gt;
&lt;td&gt;외부 라이브러리를 설치&amp;middot;버전 관리하는 도구 (npm, pip 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WSL&lt;/td&gt;
&lt;td&gt;Windows에서 리눅스 환경을 사용하게 해주는 기능&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <category>프로덕트에 관한 고민들/Engineering</category>
      <author>Urdle</author>
      <guid isPermaLink="true">https://urdle.tistory.com/301</guid>
      <comments>https://urdle.tistory.com/301#entry301comment</comments>
      <pubDate>Sun, 19 Jul 2026 23:42:38 +0900</pubDate>
    </item>
    <item>
      <title>인용박스 디자인 테스트</title>
      <link>https://urdle.tistory.com/300</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;따옴표 인용&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;바 인용&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;박스 인용&lt;/blockquote&gt;</description>
      <author>Urdle</author>
      <guid isPermaLink="true">https://urdle.tistory.com/300</guid>
      <comments>https://urdle.tistory.com/300#entry300comment</comments>
      <pubDate>Sat, 18 Jul 2026 13:09:31 +0900</pubDate>
    </item>
    <item>
      <title>공고 스크랩 기능을 고도화했다.</title>
      <link>https://urdle.tistory.com/298</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;기존에는 깃헙 워크플로로 노션에 보냈음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제: 노션은 AI가 fetch할 때 너무 무거움.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1차 솔루션: 노션으로 수집된 공고 내가 대충 훑어 중요 공고 필터링하고 공고 내용들을 md로 로컬 및 깃 레포에 저장 + tracker.md 만들어서 공고 지원 트래킹.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제: 시간이 너무 많이 듦. 안 보게 됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2차 솔루션: 공고는 노션 대신 에어테이블로 보내서 원천리소스로 사용하고, 내 경험 및 경력 문서들이나 공고 내용 같은 것들은 md로 로컬 및 깃 레포에 저장하여 DB화.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1628&quot; data-origin-height=&quot;976&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z1zb3/dJMcadij8Zh/H0c21HEG2HkpyZaYz2xuBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z1zb3/dJMcadij8Zh/H0c21HEG2HkpyZaYz2xuBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z1zb3/dJMcadij8Zh/H0c21HEG2HkpyZaYz2xuBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz1zb3%2FdJMcadij8Zh%2FH0c21HEG2HkpyZaYz2xuBK%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;1628&quot; height=&quot;976&quot; data-origin-width=&quot;1628&quot; data-origin-height=&quot;976&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1796&quot; data-origin-height=&quot;592&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k0Wrz/dJMcahLKhKq/A4n12XcnJDLkbDs89T3OFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k0Wrz/dJMcahLKhKq/A4n12XcnJDLkbDs89T3OFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k0Wrz/dJMcahLKhKq/A4n12XcnJDLkbDs89T3OFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk0Wrz%2FdJMcahLKhKq%2FA4n12XcnJDLkbDs89T3OFK%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;1796&quot; height=&quot;592&quot; data-origin-width=&quot;1796&quot; data-origin-height=&quot;592&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Today I Did</category>
      <author>Urdle</author>
      <guid isPermaLink="true">https://urdle.tistory.com/298</guid>
      <comments>https://urdle.tistory.com/298#entry298comment</comments>
      <pubDate>Thu, 2 Jul 2026 02:45:25 +0900</pubDate>
    </item>
    <item>
      <title>클로드 코드는 너무 자립적이다...</title>
      <link>https://urdle.tistory.com/297</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;아니 아니지 대부분의 AI가 그렇지.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘의 소소한 레슨런: 뭔가 이상하게 돌아갈 때는 내용을 까 보고 바로 조치를 취해야 토큰을 아낄 수 있다.&lt;br /&gt;종종 AI의 기본 페르소나(?)가 개였으면 좋겠다는 생각을 한다. 개는 조금만 뭐가 안 돼도 인간에게 도움을 요청하잖아.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1264&quot; data-origin-height=&quot;1026&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ocdRb/dJMcaalioJD/piFy4svKISL7u1qe34NpTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ocdRb/dJMcaalioJD/piFy4svKISL7u1qe34NpTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ocdRb/dJMcaalioJD/piFy4svKISL7u1qe34NpTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FocdRb%2FdJMcaalioJD%2FpiFy4svKISL7u1qe34NpTk%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;1264&quot; height=&quot;1026&quot; data-origin-width=&quot;1264&quot; data-origin-height=&quot;1026&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7.18 오늘도 비슷한 일이 일어남..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1658&quot; data-origin-height=&quot;470&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lSSsP/dJMcacRlP2p/m9pz1L4OFlXh7aEhMcmWC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lSSsP/dJMcacRlP2p/m9pz1L4OFlXh7aEhMcmWC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lSSsP/dJMcacRlP2p/m9pz1L4OFlXh7aEhMcmWC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlSSsP%2FdJMcacRlP2p%2Fm9pz1L4OFlXh7aEhMcmWC1%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;1658&quot; height=&quot;470&quot; data-origin-width=&quot;1658&quot; data-origin-height=&quot;470&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1640&quot; data-origin-height=&quot;906&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBO4Gn/dJMcag0vPPe/zk2dwKUAq9bY5WhYb1K2N1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBO4Gn/dJMcag0vPPe/zk2dwKUAq9bY5WhYb1K2N1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBO4Gn/dJMcag0vPPe/zk2dwKUAq9bY5WhYb1K2N1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBO4Gn%2FdJMcag0vPPe%2Fzk2dwKUAq9bY5WhYb1K2N1%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;1640&quot; height=&quot;906&quot; data-origin-width=&quot;1640&quot; data-origin-height=&quot;906&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Today I Learned/개발&amp;middot;데이터</category>
      <author>Urdle</author>
      <guid isPermaLink="true">https://urdle.tistory.com/297</guid>
      <comments>https://urdle.tistory.com/297#entry297comment</comments>
      <pubDate>Fri, 12 Jun 2026 18:17:03 +0900</pubDate>
    </item>
    <item>
      <title>팀 탐색작업 자동화: 깃허브 액션 - 슬랙 - 노션으로 하루 1시간 아끼고 인사이트 공유 촉진한 후기</title>
      <link>https://urdle.tistory.com/295</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;작은 조직에서 내부 도구를 만들다 보면 깨닫는 게 있다. 당장의 구성원 편의를 위한 제품은 굳이 혁신적일 필요까진 없다는 것이다. 제1목표는 신속성과 편의성이고, 그걸 달성하는 데 드는 비용이 적을수록 좋다. 그 비용에는 내 시간뿐 아니라 구성원이 새 도구를 익히는 데 써야 하는 리소스까지 포함된다. 실험이 성공하거나 실패하면 그때 가서 내용을 피벗하여 더 투자하면 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그런 맥락에서 만들게 된, 부트캠프 TIL 알림 파이프라인을 회고해본다.&lt;/p&gt;
&lt;h2 style=&quot;text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;왜 만들었나&lt;/h2&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;네트워킹을 건의해봤지만 국비 교육 특성상 시간과 예산이 제한돼 있었고, 밍글링 한 번 외엔 타팀 사람들과 만날 기회가 없었다. 원온원 만남들도 진행해보았지만 얻고자 하는 내용을 얻는 데엔 한계까 있었다. 그래서 선택한 방법이 매일 모든 훈련생의 TIL을 직접 확인하는 것이었다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;효과는 있었다. '아, 이렇게도 문제를 정의할 수 있구나' 같은 인사이트가 꽤 많았고, 팀 내에 공유하자 팀원들도 자극을 받아 적극적으로 참고하기 시작했다. 문제는 그 과정이 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;너무나도 귀찮다&lt;/span&gt;&lt;/b&gt;는 거였다.&lt;/p&gt;
&lt;h2 style=&quot;text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;당시 TIL 탐색 플로우는 이랬다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사전 작업 (1회)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;부트캠프 노션에서 훈련생 개인 블로그 주소를 일일이 수집&lt;/li&gt;
&lt;li&gt;브라우저에 북마크로 저장하고 이름을 훈련생 이름으로 변경&lt;/li&gt;
&lt;/ul&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 링크를 일일이 클릭해서 새 글 여부 확인&lt;/li&gt;
&lt;li&gt;제목만으론 내용을 알기 어려워 글 본문까지 클릭&lt;/li&gt;
&lt;li&gt;&lt;u&gt;&lt;b&gt;원하는 내용이 없으면 그냥 슬퍼함&lt;/b&gt;&lt;/u&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;718&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ergpEe/dJMcaic4pPU/wwdB3Y879iVhbgEef9ekV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ergpEe/dJMcaic4pPU/wwdB3Y879iVhbgEef9ekV1/img.png&quot; data-alt=&quot;매일 작성하시는 분과 간헐적으로 작성하시는 분이 섞여 있어 자의적으로 활성 TIL과 비활성 TIL을 나누어 조금이라도 시간을 아껴보고자 했지만 역부족이었다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ergpEe/dJMcaic4pPU/wwdB3Y879iVhbgEef9ekV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FergpEe%2FdJMcaic4pPU%2FwwdB3Y879iVhbgEef9ekV1%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;400&quot; height=&quot;718&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;718&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;매일 작성하시는 분과 간헐적으로 작성하시는 분이 섞여 있어 자의적으로 활성 TIL과 비활성 TIL을 나누어 조금이라도 시간을 아껴보고자 했지만 역부족이었다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;인당 30분 이상. 새 글이 올라왔는지 궁금해서 수시로 확인하는 시간까지 합치면 하루 1시간은 가볍게 넘었다. 확인하는 시간이야 뭐 든다고 쳐도, 확인을 했는데 허탕일 때가 가장 문제였다. 급기야 팀원끼리 zep 음성을 켜고 &quot;OOO님 TIL 올라왔어요!&quot; 하고 외치는 지경에 이르렀다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;RSS 피드만 해도 40개에 달했다. 자동화가 필요했다.&lt;/p&gt;
&lt;h2 style=&quot;text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;해결 방법을 찾기까지&lt;/h2&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;처음엔 Make로 RSS를 감지해서 슬랙에 바로 보내는 구조를 생각했다. 하지만 복병이 있었다. 부트캠프 슬랙 워크스페이스는 무료 플랜이라 외부 앱 연동이 10개로 제한돼 있었고, 이미 꽉 찬 상태였다는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;대안을 여럿 검토했다. Make에서 구글 스프레드시트 연동, 노션 DB 연동 등. 하지만 무엇보다 RSS 40개를 외부 자동화 서비스에 의존하는 구조가 마음에 걸렸다. 훈련생이 블로그를 이전하는 경우도 종종 있었고, 이 파이프라인을 추후에 채용공고나 기술 아티클 수집 등에 재사용할 수 있게 만들고 싶었다. 유지보수가 쉬운 구조여야 했다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러다 클로드와 머리를 모아 찾아낸 건&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;깃허브 액션&lt;/b&gt;이었다. 코드 저장소로만 알고 있었는데, 스케줄 기반 자동화가 가능하다는 걸 처음 알았다.&lt;/p&gt;
&lt;h2 style=&quot;text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;파이프라인 구조&lt;/h2&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 파이프라인을 구축하는 이틀 간 우여곡절이 아주 많았다. 깃헙 액션 자체를 처음 사용해봤고 RSS의 작동 구조 이해도 필요했다. 오전 9시부터 오후 9시까지 이어지는 부트캠프 일정과도 병행해야 해서 체력적으로 아주 후달렸다. 어쨌거나 여러 실패를 거쳐 최종적으로 설계한 흐름은 다음과 같다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;깃허브 액션 (2시간마다 실행, 주로 TIL이 업로드되는 오후 6-10시에는 30분마다 실행)
&amp;rarr; RSS 피드 수집 및 신규 글 감지
&amp;rarr; 노션 DB에 제목 / 작성자 / 작성일시 / 링크 저장
&amp;rarr; 노션 자동화: 새 페이지 등록 감지 시 슬랙 채널에 알림 발송
&lt;/code&gt;&lt;/pre&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;결과는 성공적이었다. 슬랙에 2시간마다 새 글 알림이 왔고, URL 미리보기로 글 초입부까지 바로 확인할 수 있었다. 쓰다 만 글도 즉각 탐지됐다. 나중에 특정 내용이나 작성자를 찾고 싶으면 노션 DB를 검색하면 됐다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1712&quot; data-origin-height=&quot;1226&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWRRQf/dJMcadivjWv/bnpd3fKxk0V4lPwEpP0kj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWRRQf/dJMcadivjWv/bnpd3fKxk0V4lPwEpP0kj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWRRQf/dJMcadivjWv/bnpd3fKxk0V4lPwEpP0kj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWRRQf%2FdJMcadivjWv%2Fbnpd3fKxk0V4lPwEpP0kj1%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;1712&quot; height=&quot;1226&quot; data-origin-width=&quot;1712&quot; data-origin-height=&quot;1226&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;477&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HLnak/dJMcabdMX0G/es2q9mv6r7G6vukKTFbfOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HLnak/dJMcabdMX0G/es2q9mv6r7G6vukKTFbfOk/img.png&quot; data-alt=&quot;업로드 1주일 이상 경과한 글은 회색으로 dimmed 처리되고, '주목' 버튼을 누르면 '이슈' 속성에 느낌표가 선택된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HLnak/dJMcabdMX0G/es2q9mv6r7G6vukKTFbfOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHLnak%2FdJMcabdMX0G%2Fes2q9mv6r7G6vukKTFbfOk%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;1000&quot; height=&quot;477&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;477&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;업로드 1주일 이상 경과한 글은 회색으로 dimmed 처리되고, '주목' 버튼을 누르면 '이슈' 속성에 느낌표가 선택된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;결과&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 직접적인 변화는 시간이었다. 인당 30~60분씩 5명이 매일 쓰던 시간이 슬랙 알림을 훑는 3초로 줄었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 더 크게 느껴진 건 시간보다 인지적 소모의 제거였다. 팀 작업을 하면서 &quot;타팀은 지금 어디쯤 왔을까&quot;, &quot;오늘 TIL 올라왔나&quot; 하며 신경을 쓰지 않게 되었다. 능동적으로 확인하러 가지 않아도 됐으니까.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노션 DB가 생기면서 예상 못했던 효과도 있었다. 별도로 스크랩할 필요가 없어졌고, 시계열로 쌓인 데이터 덕분에 타팀의 스프린트 사이클을 한눈에 파악할 수 있었다. 노션 안에서 논의할 때 TIL 스크랩 페이지를 바로 검색하고 멘션할 수 있었던 것도 예상 밖의 수확이었다. 직업훈련이라는 부트캠프 본래 목적에 더 충실하게 배움을 이어나갈 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역설적으로, 자동화 이후에 TIL 확인이 오히려 더 활발해졌다. 좋은 글이 슬랙에 올라오면 모두가 슬랙 알림을 받았기에 자연스럽게 이야기가 시작됐고, 잘 쓰는 훈련생의 글을 보며 함께 논의하는 시간이 늘었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;돌이켜보면 이 파이프라인을 만들면서 직접적으로 배운 건 자동화 기술이었지만, 문제를 다르게 정의하는 방식이야말로 진짜 수확이었던 것 같다.&amp;nbsp;처음엔 &quot;어떻게 하면 TIL을 빠르고 편하게 볼 수 있을까&quot;를 고민했는데, 실제로 풀어야 했던 문제는 &quot;왜 우리는 매일 1시간을 쓰면서도 문서화와 논의는 충분히 하지 못했는가&quot;였다. 그리고 구성원들이 새로운 툴을 배울 필요 없이 문제를 해결할 수 있게 된 것도 큰 수확이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드도 재사용할 수 있었다. 간단하게는 RSS 피드 주소만 바꾸면 됐기 때문에, 비슷한 워크플로우로 채용공고 스크랩 에어테이블과 기술 블로그 아티클 수집 노션 DB, 개인 블로그 아티클 수집 사이트까지 이어서 만들었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1810&quot; data-origin-height=&quot;1356&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXbOQn/dJMcaa0jQJh/cT00g2y1C6lKhoZO5cRjGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXbOQn/dJMcaa0jQJh/cT00g2y1C6lKhoZO5cRjGK/img.png&quot; data-alt=&quot;기술블로그 스크랩 노션 DB&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXbOQn/dJMcaa0jQJh/cT00g2y1C6lKhoZO5cRjGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXbOQn%2FdJMcaa0jQJh%2FcT00g2y1C6lKhoZO5cRjGK%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;1810&quot; height=&quot;1356&quot; data-origin-width=&quot;1810&quot; data-origin-height=&quot;1356&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;기술블로그 스크랩 노션 DB&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2210&quot; data-origin-height=&quot;1794&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cyuvxC/dJMcaijLGiI/aGmhkkP2QXYNVkH00tbQa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyuvxC/dJMcaijLGiI/aGmhkkP2QXYNVkH00tbQa1/img.png&quot; data-alt=&quot;IT 개인소셜채널 아티클 트래커 V2 (V1은 프레이머, V2는 vercel로 만들었다)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyuvxC/dJMcaijLGiI/aGmhkkP2QXYNVkH00tbQa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcyuvxC%2FdJMcaijLGiI%2FaGmhkkP2QXYNVkH00tbQa1%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;2210&quot; height=&quot;1794&quot; data-origin-width=&quot;2210&quot; data-origin-height=&quot;1794&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;IT 개인소셜채널 아티클 트래커 V2 (V1은 프레이머, V2는 vercel로 만들었다)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;border: 1px solid lightseagreen33; border-radius: 10px; padding: 20px; background-color: #1a1a2e; font-family: 'Noto Sans KR',sans-serif; margin: 20px 0;&quot;&gt;
&lt;div style=&quot;display: flex; align-items: center; margin-bottom: 15px;&quot;&gt;&lt;span style=&quot;background-color: lightseagreen; color: #222; padding: 3px 8px; border-radius: 4px; font-size: 12px; font-weight: bold; margin-right: 10px;&quot;&gt;SERIES&lt;/span&gt;
&lt;h3 style=&quot;margin: 0; font-size: 18px; color: lightseagreen;&quot; data-ke-size=&quot;size23&quot;&gt;조직 생산성 향상을 위한 작은 시도들&lt;/h3&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style: none; padding: 0; margin: 0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;padding: 8px 0; border-bottom: 1px dashed #333; display: flex; justify-content: space-between; align-items: center;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: #aaa; font-size: 14px; font-weight: normal;&quot; href=&quot;https://urdle.tistory.com/217&quot;&gt;1. 약간의 노력으로 자리비움 보고체계 만들기&lt;/a&gt;&lt;span style=&quot;font-size: 11px; color: #666;&quot;&gt;완료&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;padding: 8px 0; display: flex; justify-content: space-between; align-items: center;&quot;&gt;&lt;a style=&quot;text-decoration: none; color: #fff; font-size: 14px; font-weight: bold;&quot; href=&quot;https://urdle.tistory.com/295&quot;&gt;2. 팀 탐색작업 자동화&lt;/a&gt;&lt;span style=&quot;font-size: 11px; color: lightseagreen;&quot;&gt;현재 글&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description>
      <category>Try-Catch</category>
      <author>Urdle</author>
      <guid isPermaLink="true">https://urdle.tistory.com/295</guid>
      <comments>https://urdle.tistory.com/295#entry295comment</comments>
      <pubDate>Thu, 23 Apr 2026 22:51:33 +0900</pubDate>
    </item>
    <item>
      <title>포트폴리오 웹사이트 유지보수/운영관리를 위한 백오피스 개발 (w. 클로드 코드, vercel, GitHub)</title>
      <link>https://urdle.tistory.com/294</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1806&quot; data-origin-height=&quot;794&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cF1HFR/dJMcagrIQYo/HQ8S6EkssAxwV1ipcprb2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cF1HFR/dJMcagrIQYo/HQ8S6EkssAxwV1ipcprb2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cF1HFR/dJMcagrIQYo/HQ8S6EkssAxwV1ipcprb2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcF1HFR%2FdJMcagrIQYo%2FHQ8S6EkssAxwV1ipcprb2K%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;1806&quot; height=&quot;794&quot; data-origin-width=&quot;1806&quot; data-origin-height=&quot;794&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;구조 설계 및 제작&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CMS 없이 콘텐츠를 관리하는 구조 설계&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;b&gt;피벗:&lt;/b&gt; DB나 CMS 없이 &lt;code&gt;data/content.json&lt;/code&gt; 하나를 DB로 삼는 구조로 설계. JS가 fetch로 JSON을 불러와 렌더링하고, 실패 시 &lt;code&gt;main.js&lt;/code&gt; 안의 fallback 데이터로 대체. 콘텐츠 수정 = JSON 수정만 하면 됨.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;커스텀 편집 페이지(CMS) 직접 제작&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;니즈:&lt;/b&gt; JSON을 직접 편집하기 불편하고, 비개발자 친화적인 관리 인터페이스가 필요했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;피벗:&lt;/b&gt; 별도 백엔드 없이 순수 HTML + JS로 편집 페이지 제작. URL을 추측하기 어렵게 랜덤 해시로 네이밍해 간단히 보호. 페이지가 로드될 때 &lt;code&gt;content.json&lt;/code&gt;을 fetch해 폼에 바인딩하고, 변경 시 &lt;code&gt;data-path&lt;/code&gt; 속성 기반으로 중첩 객체를 직접 업데이트하는 방식(&lt;code&gt;setPath&lt;/code&gt;/&lt;code&gt;getPath&lt;/code&gt;).&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;편집 페이지 &amp;rarr; GitHub 직접 저장&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;니즈:&lt;/b&gt; 브라우저에서 내용을 편집하면 &lt;code&gt;content.json&lt;/code&gt;이 자동으로 업데이트되길 원했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;피벗:&lt;/b&gt; 서버 없이 정적 사이트라 파일 직접 수정 불가 &amp;rarr; GitHub Contents API(&lt;code&gt;PUT /repos/.../contents/...&lt;/code&gt;)로 해결. 브라우저에서 base64로 인코딩해 커밋하면 Vercel이 자동 재배포. PAT는 &lt;code&gt;Contents: Read and write&lt;/code&gt;만 있으면 충분 (fine-grained token + 단일 레포).&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;세부 구현&lt;/h2&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;b&gt;피벗:&lt;/b&gt; 프레임워크 없이 바닐라 JS로 구현. 탭 클릭 시 &lt;code&gt;data-group&lt;/code&gt; 어트리뷰트 기반으로 카드 on/off 토글, &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; 태그로 아코디언 처리. 렌더링 함수를 섹션별로 분리(&lt;code&gt;rBasic&lt;/code&gt;, &lt;code&gt;rSkills&lt;/code&gt;, &lt;code&gt;rWork&lt;/code&gt; 등)해 유지보수성 확보.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Vercel 비밀번호 보호&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;b&gt;피벗:&lt;/b&gt; Vercel Pro 전용 기능이라 무료로 직접 구현. Edge Middleware(&lt;code&gt;middleware.js&lt;/code&gt;) + 쿠키 인증 방식으로 처리. 단, &lt;code&gt;next/server&lt;/code&gt;의 &lt;code&gt;NextResponse&lt;/code&gt;는 Next.js 없이 사용 불가 &amp;rarr; 표준 Web API(&lt;code&gt;Response.redirect&lt;/code&gt;, &lt;code&gt;request.headers.get('cookie')&lt;/code&gt;)로 재작성.&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;b&gt;피벗:&lt;/b&gt; &lt;code&gt;blogs&lt;/code&gt; 배열 항목에 &lt;code&gt;url&lt;/code&gt; 필드 추가. 렌더링 시 URL이 있으면 &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; 태그로 감싸고 없으면 일반 div. 기존 구조를 유지하면서 선택적으로 적용.&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;b&gt;피벗:&lt;/b&gt; &lt;code&gt;miniProjects&lt;/code&gt; 배열을 &lt;code&gt;projectDetails&lt;/code&gt;와 동일한 구조로 설계 (id, title, description, stack, notionUrl, images). 포트폴리오에는 갤러리 카드 형태로 렌더링.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로젝트 이미지 라이트박스 + Notion 링크&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;니즈:&lt;/b&gt; 프로젝트 카드에서 이미지를 16:9 슬라이드로 보고 싶고, Notion 문서로도 연결하고 싶었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;피벗:&lt;/b&gt; 이미지는 GitHub API로 직접 업로드 (&lt;code&gt;assets/projects/{id}/&lt;/code&gt;) &amp;rarr; &lt;code&gt;content.json&lt;/code&gt;의 &lt;code&gt;images&lt;/code&gt; 배열에 경로 저장 &amp;rarr; 카드 클릭 시 커스텀 라이트박스 오버레이 표시 (16:9 컨테이너, 좌우 화살표 페이지네이션, ESC 닫기). Notion 버튼은 카드 내 별도 &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; 태그로 분리해 카드 클릭 이벤트와 충돌하지 않게 &lt;code&gt;stopPropagation&lt;/code&gt; 처리.&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; 쓸 줄은 알지만 메인에 노출하고 싶지 않은 스킬도 있고, 프로젝트 스택 입력 시 매번 아이콘 URL을 찾는 게 번거로웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;피벗:&lt;/b&gt; &lt;code&gt;skillPool&lt;/code&gt;(전체 보유 스킬)과 &lt;code&gt;skills&lt;/code&gt;(메인 노출 스킬)을 분리. 편집 페이지에서 스택 입력 시 &quot;풀에서 선택&quot; 버튼 &amp;rarr; 팝업에서 클릭하면 이름 + 아이콘 URL이 자동 입력.&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;b&gt;피벗:&lt;/b&gt; SortableJS 라이브러리(CDN) 사용. 렌더링 후 &lt;code&gt;[data-sortable]&lt;/code&gt; 속성이 붙은 모든 컨테이너에 자동으로 Sortable 적용. &lt;code&gt;onEnd&lt;/code&gt; 콜백에서 배열의 &lt;code&gt;splice&lt;/code&gt;로 순서 재정렬 후 re-render. 스크롤 위치는 render 전후로 &lt;code&gt;window.scrollY&lt;/code&gt; 저장/복원. 드래그 핸들(⠿)을 별도 요소로 분리해 입력 필드 조작 중에는 드래그가 시작되지 않도록 처리.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;버그픽스, 이슈트래킹&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Git + VSCode 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;니즈:&lt;/b&gt; VSCode로 푸시하려 했더니 상위 프로젝트 폴더 전체가 스테이징됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;피벗:&lt;/b&gt; 포트폴리오 폴더 안에 &lt;code&gt;.git&lt;/code&gt;이 없었던 것. &lt;code&gt;git init&lt;/code&gt; &amp;rarr; &lt;code&gt;git remote add&lt;/code&gt; &amp;rarr; &lt;code&gt;git reset --hard origin/main&lt;/code&gt;으로 로컬 레포 연결. VSCode는 &lt;b&gt;해당 폴더만&lt;/b&gt; Open Folder로 열어야 Source Control이 분리됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커밋 메시지 입력이 안 되는 문제 &amp;rarr; VSCode UI 버그. 터미널에서 &lt;code&gt;git commit -m &quot;...&quot;&lt;/code&gt; 으로 우회.&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; content.json을 fetch했는데 fallback 데이터가 표시됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;피벗:&lt;/b&gt; 미들웨어가 &lt;code&gt;/data/content.json&lt;/code&gt; 요청도 로그인 페이지로 리다이렉트 &amp;rarr; JS가 HTML을 받아 JSON 파싱 실패 &amp;rarr; fallback. &lt;code&gt;PUBLIC_PATHS&lt;/code&gt;에 &lt;code&gt;/data/&lt;/code&gt; 추가해서 해결. &lt;b&gt;정적 데이터 파일 경로는 명시적으로 허용해야 함.&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;remote 앞서 있을 때 push 거절&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;니즈:&lt;/b&gt; 편집 페이지에서 GitHub API로 직접 커밋 후, 로컬에서도 푸시하려 했더니 rejected.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;피벗:&lt;/b&gt; 두 곳(편집 페이지 API, 로컬 터미널)에서 같은 브랜치에 커밋하면 발생하는 일반적인 충돌. &lt;code&gt;git pull origin main --rebase&lt;/code&gt; 후 push. 편집 페이지로 저장한 이후에는 로컬 작업 전 항상 pull 먼저.&lt;/p&gt;</description>
      <category>사이드프로젝트</category>
      <author>Urdle</author>
      <guid isPermaLink="true">https://urdle.tistory.com/294</guid>
      <comments>https://urdle.tistory.com/294#entry294comment</comments>
      <pubDate>Thu, 23 Apr 2026 20:09:56 +0900</pubDate>
    </item>
    <item>
      <title>[스크랩] 시니어 사용자가 어려워하는 UX 5가지 (토스)</title>
      <link>https://urdle.tistory.com/291</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;진짜 좋은 아티클을 발견해서 일단 스크랩. 인사이트 정리는 시간 날때 하자.&lt;/p&gt;
&lt;figure id=&quot;og_1784306774751&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;시니어 사용자가 어려워하는 UX 5가지&quot; data-og-description=&quot;시니어 UX 설계 가이드라인을 만들기 위해, 리서치로 시니어 사용자들의 공통된 사용성 패턴을 찾는 과정을 들려드릴게요.&quot; data-og-host=&quot;toss.tech&quot; data-og-source-url=&quot;https://toss.tech/article/senior-usability-research&quot; data-og-url=&quot;https://toss.tech/article/senior-usability-research&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bPvp8M/dJMb8Xksc7k/aqeYhV0NkOj1pkvyRwJDjK/img.png?width=3001&amp;amp;height=1535&amp;amp;face=0_0_3001_1535,https://scrap.kakaocdn.net/dn/IwSjK/dJMb8RR4CBG/p5NhKpi15hb327lrlRCHr1/img.png?width=3001&amp;amp;height=1535&amp;amp;face=0_0_3001_1535,https://scrap.kakaocdn.net/dn/DB9i8/dJMb8YXYtaw/9C44jYhiEZRC78feWIGsdk/img.png?width=2294&amp;amp;height=1432&amp;amp;face=0_0_2294_1432&quot;&gt;&lt;a href=&quot;https://toss.tech/article/senior-usability-research&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://toss.tech/article/senior-usability-research&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bPvp8M/dJMb8Xksc7k/aqeYhV0NkOj1pkvyRwJDjK/img.png?width=3001&amp;amp;height=1535&amp;amp;face=0_0_3001_1535,https://scrap.kakaocdn.net/dn/IwSjK/dJMb8RR4CBG/p5NhKpi15hb327lrlRCHr1/img.png?width=3001&amp;amp;height=1535&amp;amp;face=0_0_3001_1535,https://scrap.kakaocdn.net/dn/DB9i8/dJMb8YXYtaw/9C44jYhiEZRC78feWIGsdk/img.png?width=2294&amp;amp;height=1432&amp;amp;face=0_0_2294_1432');&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;시니어 사용자가 어려워하는 UX 5가지&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;시니어 UX 설계 가이드라인을 만들기 위해, 리서치로 시니어 사용자들의 공통된 사용성 패턴을 찾는 과정을 들려드릴게요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;toss.tech&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>발견과 토막글</category>
      <author>Urdle</author>
      <guid isPermaLink="true">https://urdle.tistory.com/291</guid>
      <comments>https://urdle.tistory.com/291#entry291comment</comments>
      <pubDate>Tue, 14 Apr 2026 21:24:25 +0900</pubDate>
    </item>
    <item>
      <title>Figma Sites라는 게 생김...</title>
      <link>https://urdle.tistory.com/289</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;프레이머보다 인터페이스 편해 보임...&lt;/p&gt;</description>
      <category>발견과 토막글</category>
      <author>Urdle</author>
      <guid isPermaLink="true">https://urdle.tistory.com/289</guid>
      <comments>https://urdle.tistory.com/289#entry289comment</comments>
      <pubDate>Sat, 11 Apr 2026 23:31:40 +0900</pubDate>
    </item>
    <item>
      <title>GA4 트래킹 계획 수립, UT 배포</title>
      <link>https://urdle.tistory.com/285</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;오늘 한 일&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;나&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;트래킹 계획 최종 검토 후 튜터님께 전달&lt;/li&gt;
&lt;li&gt;트래킹 계획 피드백 받음&lt;/li&gt;
&lt;li&gt;GA4 트래킹 되지 않는 이슈 확인, 튜터님께 문의. framer 를 통해 타 서비스를 받아오는 경우 framer에서의 경험이 수집되지 않는다는 점 팀에 전달.&lt;/li&gt;
&lt;li&gt;유즈베리 무료 플랜은 csv export가 되지 않는 점 확인, 수기로 옮기기 위해 구글 스프레드시트로 틀 만들어 팀에 공유&lt;/li&gt;
&lt;li&gt;팀원들과 함께 유즈베리 답변을 구글 시트에 테라포밍&lt;/li&gt;
&lt;li&gt;브로셔용 표지 제작&lt;/li&gt;
&lt;li&gt;브로셔 내용 피드백&lt;/li&gt;
&lt;li&gt;계정이 모자라서, 내 유즈베리 계정으로 동일한 UT 하나 제작함&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;팀&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UT 마지막 점검&lt;/li&gt;
&lt;li&gt;UT 배포&lt;/li&gt;
&lt;li&gt;들어온 응답들을 구글 스프레드시트에 테라포밍&lt;/li&gt;
&lt;li&gt;간략하게 UT 중간 인사이트 이야기 나눔&lt;/li&gt;
&lt;li&gt;브로셔: 팀내 피드백 진행, 튜터님 피드백 진행 (담당하시는 팀원 분께서 1:1로 다녀오심)&lt;/li&gt;
&lt;li&gt;발표자료: 팀내 피드백 진행, 디자인 구조 변경&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;오늘의 인사이트&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만들어진 '댓글 슬쩍 보기' 기능에 대해, 스포일러에 대한 우려가 크며, 로맨스판타지에서 두드러짐. 이 점 때문에 기능에 대해서 복합적.&lt;/li&gt;
&lt;li&gt;판타지 장르 유저들은 이탈률이 매우 높음 50%에 육박. 그러나 스포일러 고민은 없는 편이고 기능에 대해서도 긍정적.&lt;/li&gt;
&lt;li&gt;GA4 트래킹의 진정한 의미는 핵심 지표를 잘 설명하는 것, 그리고 핵심 데이터를 '보충'하는 것. 데이터가 많다고 좋은 것이 아님.&lt;/li&gt;
&lt;li&gt;vercel 로 만들어진 서비스를 framer를 통해 배포했을 때, 프레이머에서의 이벤트는 GA4에 집계가 되지 않음.&lt;/li&gt;
&lt;li&gt;유즈베리에는 오디언스를 그룹화하여 별도로 링크를 생성할 수 있는 기능이 있음.&lt;/li&gt;
&lt;li&gt;어떤 요소에 대해 기술적인 이해도에 차이가 있을 때, 더블체크는 구두로만 하는 게 아니라 직접 확인해야함.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;GA4 트래킹 계획 수립&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리팀이 UT 앱에 대한 숙지가 잘 안되어있다고 판단해서 GA4 태깅에서 욕심을 많이 냈기도 하고,&lt;br /&gt;(팀원들이 처음 보는 앱, 강의에 없었음, maze보다 인지도 떨어짐, 영어 서비스)&lt;br /&gt;급해서 다른 튜터님들께 보여드리지 못한 채로 기술 튜터님께 트래킹 계획을 아침에 전달드렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 티가 너무너무 잘 나서 반성함...!!&lt;br /&gt;기술 튜터님께서 정말 꼼꼼히 피드백 해주셨다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실무에선 어차피 중요 데이터는 수집이 되기 때문에(커머스를 예로 들면 판매량, 구매횟수, 구매액 등) GA4에 의존할 일이 많지 않음, GA4는 정말 보조적 수단&lt;/li&gt;
&lt;li&gt;데이터가 많다고 해서 좋은 게 아니다. (이전에 개인과제 해결방안 제시했을 때 ㅈㅇ 튜터님께도 비슷하게 피드백 받았던 부분)&lt;/li&gt;
&lt;li&gt;'튜터님께서 이벤트 세팅은 다 해주셨지만, 세팅해주신 모든 이벤트를 전부 사용하는 게 아니라, 정말 핵심적인 지표를 뒷받침하는 데이터를 중심으로 분석하면 된다고 이해하면 될지' 여쭈어보니.&lt;/li&gt;
&lt;li&gt;튜터님께서 맞다고, 많은 데이터 중에서 정말 핵심적이고 필요한 데이터를 걸러내보는 경험, 그게 잘 안되어 스스로 피드백하는 경험을 해보는 것도 중요하기 때문에 계획대로 태그를 전부 해주셨다고 하심.&lt;/li&gt;
&lt;li&gt;그래서 데이터 분석하는 분에게 이 부분 잘 갈무리해 전달드리겠다고 말씀드림.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/J3F9o/dJMcaadOmXk/3yB8xKEdaEnoHKPKtwe280/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/J3F9o/dJMcaadOmXk/3yB8xKEdaEnoHKPKtwe280/img.png&quot; data-origin-width=&quot;1850&quot; data-origin-height=&quot;762&quot; data-filename=&quot;blob&quot; data-is-animation=&quot;false&quot; style=&quot;width: 56.148%; margin-right: 10px;&quot; data-widthpercent=&quot;56.81&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/J3F9o/dJMcaadOmXk/3yB8xKEdaEnoHKPKtwe280/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJ3F9o%2FdJMcaadOmXk%2F3yB8xKEdaEnoHKPKtwe280%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;1850&quot; height=&quot;762&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SPHG5/dJMcaaky2mZ/2tlGKZKooLTNjEZ4Yk92UK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SPHG5/dJMcaaky2mZ/2tlGKZKooLTNjEZ4Yk92UK/img.png&quot; width=&quot;659&quot; height=&quot;357&quot; data-origin-width=&quot;982&quot; data-origin-height=&quot;532&quot; data-filename=&quot;blob&quot; data-is-animation=&quot;false&quot; style=&quot;width: 42.6892%;&quot; data-widthpercent=&quot;43.19&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SPHG5/dJMcaaky2mZ/2tlGKZKooLTNjEZ4Yk92UK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSPHG5%2FdJMcaaky2mZ%2F2tlGKZKooLTNjEZ4Yk92UK%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;982&quot; height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 데이터 들어오는 거 24시간 지나서 살펴보고, 나도 분석에 투입이 되어서 봐야겠다고 생각함.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;UT진행, 배포&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;계정이 모자라서 내걸로도 하나 팠는데, 파다가 유즈베리에서 오디언스 바꿔서 링크별로 따로 배포하는 기능이 있다는 걸 찾음.&lt;br /&gt;근데 적용하기엔 늦어서 오늘의 배움으로만 가지고 가기로...&lt;/li&gt;
&lt;li&gt;GA4집계 안되는 건에 대하여 기술튜터님께 문의 후, framer 링크가 아니라 원 서비스 링크로 유즈베리에 임베드해야 한다는 점을 알게 되어 팀에 전달, 팀 공지 채널에 공유. 확인 표시 확인, 더블체크도 계속 진행. 그런데 이미 배포와 응답이 완료된 UT에서 framer 링크로 배포되어 있는 것을 확인하고 멘붕. 진정하고 이전까지 응답해준 응답자는 어쩔 수 없이 GA4 패스했다고 치고 새로 UT를 파서 배포. 소통이 잘 된 것 같다고 느껴도 정말 같은 곳을 보고 있는게 맞는지 확인해야 한다는 걸 느낌. 특히, 담당마다 이해도가 판이하게 다른 요소에 대해.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;스포일러 우려에 대한 인사이트&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스포일러는 팀에서 처음 기획 시에 가장 우려했던 부분. 이 때문에 '어떤 기준을 따르는 회차의 댓글을, 어떤 기준에 따라, 얼마나, 어디에, 어떻게 보여줄 것인가'에 대해 며칠 동안 논의 했었고, 댓글 노출 로직을 고민하다 스포일러 팝업을 기획했었음.&lt;/li&gt;
&lt;li&gt;진행이 빠르지 않은 만큼, 볼륨을 줄이고 가설 검증에 집중해야 한다는 피드백을 수용해 과감하게 스포일러 관련된 모든 사항을 기획에서 제거, 일단 해피패스로 제작.&lt;/li&gt;
&lt;li&gt;첫 세트의 응답에서 70%의 응답자가 스포일러를 우려하여 마지막 열람회차의 다음 회차 댓글 슬쩍보기 기능 자체를 체험하지 않으려 했다거나 기능이 우려된다거나 실수로 클릭한 후 스포일러를 당한 기분이라고 주관식 응답. 스포일러가 제거된 댓글임을 알려준다거나 경고 문구 같은 것들이 필요할 것 같다고 응답.&lt;/li&gt;
&lt;li&gt;우리의 스포일러 우려는 적중했지만, 오히려 스포일러를 가설에서 배제했기 때문에 명확하게 스포일러 필터링 로직이나 온보딩이 필요하다는 점을 인식할 수 있었음. 가능한 한 최대한 빠르게 UT를 진행해서 일단 데이터부터 수집하는 게 낫다는 피드백이 어떤 의미인지 깨달음. 다만, 스포일러 때문에 기능을 제대로 체험하지 않은 응답자들이 있는 만큼, 이미 논의했던 부분들을 어설프게라도 반영해서 배포했다면 좀더 구체적인 스포일러 관련 피드백을 받을 수 있지 않았었을까 하는 아쉬움은 남음.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;내일 해야 하는 일&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;팀&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;카카오페이지 웹툰 사용 경험이 없는 사람에게서도 피드백을 받기로 하였음(슬랙 스레드로), 그런데 이 경우 데이터가 오염될 수 있으니 GA4 안 잡히는 framer 링크로 공유할지, GA4 잡히도록 원 링크를 공유할지 논의해야 함.&lt;/li&gt;
&lt;li&gt;UT 들어오는 상태 확인하고,&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;나&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내 부담당인 발표자료에 대해 구성 및 디자인 레퍼런스 찾고 구성 점검하기&lt;/li&gt;
&lt;li&gt;시연 영상에 어떤 점이 들어가면 좋을지 브로셔 팀원분과 이야기 나눠보기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>PM부트캠프/7.  ️ 최종 프로젝트</category>
      <author>Urdle</author>
      <guid isPermaLink="true">https://urdle.tistory.com/285</guid>
      <comments>https://urdle.tistory.com/285#entry285comment</comments>
      <pubDate>Wed, 8 Apr 2026 16:44:23 +0900</pubDate>
    </item>
    <item>
      <title>BeautifulSoup으로 네이버 기사(제목, 언론사, 발췌문) 수집하기</title>
      <link>https://urdle.tistory.com/281</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;방송통신대학교 과제 중...&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;첫 시도: 개수로 쪼개서 수집&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이버 뉴스 검색 링크는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1775362507703&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;https://search.naver.com/search.naver?where=news&amp;amp;query=검색어&amp;amp;start=페이지넘버&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이버 뉴스는 무한스크롤 형태의 페이지네이션을 취하고 있지만 크롤링할 때는 저렇게 페이징으로 가져올 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제목은 a[data-heatmap-target=&quot;.tit&quot;, 언론사는 a[data-heatmap-target=&quot;.prof&quot;, 발췌문은 a[data-heatmap-target=&quot;.body&quot;에 해당한다. 키워드별 각 30건 이상씩 수집하므로 min조건을 걸었다.&lt;/p&gt;
&lt;pre id=&quot;code_1775361713526&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import requests
from bs4 import BeautifulSoup
import pandas as pd
import time

HEADERS = {
    'User-Agent': (
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
        'AppleWebKit/537.36 (KHTML, like Gecko) '
        'Chrome/120.0.0.0 Safari/537.36'
    )
}

def crawl_naver_news(keyword, min_articles=30):
    articles = []
    page = 1

    print(f&quot;\n[수집 시작] 키워드: '{keyword}'&quot;)
    print(&quot;-&quot; * 50)

    while len(articles) &amp;lt; min_articles:
        start = (page - 1) * 10 + 1
        url = f'https://search.naver.com/search.naver?where=news&amp;amp;query={keyword}&amp;amp;start={start}'

        response = requests.get(url, headers=HEADERS, timeout=10)
        soup = BeautifulSoup(response.text, 'html.parser')

        title_tags   = soup.select('a[data-heatmap-target=&quot;.tit&quot;] span')
        press_tags   = soup.select('a[data-heatmap-target=&quot;.prof&quot;] span')
        summary_tags = soup.select('a[data-heatmap-target=&quot;.body&quot;] span')

        if not title_tags:
            print(f&quot;  페이지 {page}: 기사 없음, 수집 종료&quot;)
            break

        for i in range(len(title_tags)):
            articles.append({
                'title'  : title_tags[i].get_text(strip=True)   if i &amp;lt; len(title_tags)   else None,
                'press'  : press_tags[i].get_text(strip=True)   if i &amp;lt; len(press_tags)   else None,
                'summary': summary_tags[i].get_text(strip=True) if i &amp;lt; len(summary_tags) else None,
                'keyword': keyword
            })

        print(f&quot;  페이지 {page} 완료 &amp;rarr; 누적 {len(articles)}건&quot;)

        if len(articles) &amp;gt;= min_articles:
            break

        page += 1
        time.sleep(1)

    df = pd.DataFrame(articles)
    print(f&quot;  최종 수집: {len(df)}건&quot;)
    return df


# ── 실행 ──

keyword = '티스토리'
df_keyword = crawl_naver_news(keyword, min_articles=30)&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;문제: 짝이 안 맞음&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이버 뉴스는 관련 기사들을 다음과 같이 묶어서 보여주며, 딸린 기사의 발췌문들은 제거한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1334&quot; data-origin-height=&quot;582&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqrFMm/dJMcad2y4mv/4TKC2v3wScY1nM4KSiFwn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqrFMm/dJMcad2y4mv/4TKC2v3wScY1nM4KSiFwn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqrFMm/dJMcad2y4mv/4TKC2v3wScY1nM4KSiFwn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdqrFMm%2FdJMcad2y4mv%2F4TKC2v3wScY1nM4KSiFwn0%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;1334&quot; height=&quot;582&quot; data-origin-width=&quot;1334&quot; data-origin-height=&quot;582&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 부분들 때문에 제목&amp;amp;언론사와 요약문 인덱스가 어긋나 꼬이고 있었다. 사실 맘같아선 관련기사는 전부 빼고 머리가 되는 기사들만 가져오고 싶었는데, 요약문이 없는 데이터의 결측치를 처리하는 게 2번 문항이어서 굳이여도 살리는 게 맞다고 보았다.(근데 애초부터 결측치 없이 받으면 되는데 결측치 찾아내는 문제 때문에 굳이 결측치 넣는 게 현타옴...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제가 또 있었는데 네이버 관련기사의 경우 언론사 태그가 다르다는 것 + 네이버는 관련기사를 제외하고 전부 요약문을 제공한다는 것이다. 그렇다는건 요약문이 결측치인 경우는 별도의 태그로 다 가져와야 한다는건데...&lt;/p&gt;
&lt;pre id=&quot;code_1775362738392&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 메인기사 언론사 태그
a[data-heatmap-target=&quot;.prof&quot;] span

# 관련기사 언론사 태그
sds-comps-profile-info-title-text span&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 애초에 요약문이 결측치인 애들을 별도의 태그로 가져올거면 결측치 탐지는 뭐하러 하며, 결측치 탐지과정을 뭐라고 적는지...? 아무리 생각해도 이해가 안되고... 그냥 다음기사로 하기로 했다. 과제 의도에 네이버기사가 애초에 안맞는데 왜 낸걸까...&lt;/p&gt;</description>
      <category>Today I Did</category>
      <author>Urdle</author>
      <guid isPermaLink="true">https://urdle.tistory.com/281</guid>
      <comments>https://urdle.tistory.com/281#entry281comment</comments>
      <pubDate>Sun, 5 Apr 2026 13:03:40 +0900</pubDate>
    </item>
  </channel>
</rss>