<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>xxlayer 님의 블로그</title>
    <link>https://xxlayer.tistory.com/</link>
    <description>xxlayer 님의 블로그 입니다.</description>
    <language>ko</language>
    <pubDate>Fri, 12 Jun 2026 23:41:40 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>xxlayer</managingEditor>
    <item>
      <title>Prometheus Alert와 AI를 연계해 장애 원인 1차 분석 자동화하기</title>
      <link>https://xxlayer.tistory.com/8</link>
      <description>&lt;h1&gt;Prometheus Alert와 AI를 연계해 장애 원인 1차 분석 자동화하기&lt;/h1&gt;
&lt;p&gt;Kubernetes 환경에서 운영을 하다 보면 Prometheus Alert는 이미 기본 인프라처럼 자리 잡고 있습니다. CPU 사용률 급증, 메모리 부족, Pod 재시작 반복, 응답 지연 증가 등 다양한 조건을 기준으로 알림이 발생합니다. 문제는 알림이 발생한 이후입니다. 알림은 알려주지만, 원인을 바로 설명해주지는 않습니다.&lt;/p&gt;
&lt;p&gt;실제 운영 상황에서는 Alert가 발생하면 다음과 같은 과정을 반복하게 됩니다.&lt;/p&gt;
&lt;ul&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;p&gt;이 과정이 익숙해지면 빠르게 처리할 수 있지만, 알림이 동시에 여러 개 발생하거나 야간 온콜 상황이라면 부담이 커집니다. 이때 Prometheus Alert와 AI를 연결해 1차 원인 후보를 자동으로 정리해주는 구조를 만들면 대응 속도를 안정적으로 줄일 수 있습니다.&lt;/p&gt;
&lt;h2&gt;왜 Alert만으로는 부족할까&lt;/h2&gt;
&lt;p&gt;Prometheus Alert는 &amp;quot;조건이 충족되었다&amp;quot;는 사실만 알려줍니다. 예를 들어 다음과 같은 메시지가 올 수 있습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;High CPU usage detected&lt;/li&gt;
&lt;li&gt;Pod restart count increased&lt;/li&gt;
&lt;li&gt;5xx error rate above threshold&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;하지만 이 메시지만으로는 원인을 알 수 없습니다. CPU가 높아진 이유가 트래픽 급증인지, 무한 루프인지, GC 문제인지 알 수 없고, 재시작이 OOM 때문인지 설정 오류 때문인지도 바로 판단하기 어렵습니다. 결국 사람은 로그와 상태 정보를 다시 모아서 해석해야 합니다.&lt;/p&gt;
&lt;p&gt;AI를 활용하는 지점은 바로 여기입니다. Alert 자체를 분석하는 것이 아니라, Alert를 트리거로 관련 정보를 자동 수집하고 그 내용을 기반으로 1차 분석 리포트를 생성하는 것입니다.&lt;/p&gt;
&lt;h2&gt;기본 구조는 단순하다&lt;/h2&gt;
&lt;p&gt;실무에서 적용하기 좋은 구조는 생각보다 복잡하지 않습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Prometheus Alert 발생&lt;/li&gt;
&lt;li&gt;Alertmanager가 Webhook 호출&lt;/li&gt;
&lt;li&gt;관련 파드 로그 및 상태 정보 자동 수집&lt;/li&gt;
&lt;li&gt;수집된 정보와 함께 AI에 전달&lt;/li&gt;
&lt;li&gt;구조화된 분석 리포트를 Slack으로 전송&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;핵심은 AI에게 &amp;quot;무엇이 발생했는지&amp;quot;가 아니라 &amp;quot;어떤 맥락에서 발생했는지&amp;quot;를 함께 주는 것입니다. Alert 이름, 발생 시각, 파드 상태, 최근 로그 일부, 재시작 횟수, 최근 배포 여부까지 포함하면 분석 결과의 질이 눈에 띄게 달라집니다.&lt;/p&gt;
&lt;h2&gt;실제로 도움이 되는 분석 유형&lt;/h2&gt;
&lt;h3&gt;1. CPU 사용률 급증 Alert&lt;/h3&gt;
&lt;p&gt;CPU Alert만 보면 단순 과부하처럼 보일 수 있습니다. 하지만 로그와 함께 보면 다음과 같은 가능성을 구분할 수 있습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;특정 요청 패턴 증가&lt;/li&gt;
&lt;li&gt;외부 API 지연으로 인한 대기 증가&lt;/li&gt;
&lt;li&gt;무한 루프 또는 버그&lt;/li&gt;
&lt;li&gt;GC 과다 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI가 원인을 확정해주는 것은 아니지만, &amp;quot;확인해야 할 후보 목록&amp;quot;을 먼저 제시해주는 것만으로도 대응 속도가 달라집니다.&lt;/p&gt;
&lt;h3&gt;2. Pod 재시작 증가 Alert&lt;/h3&gt;
&lt;p&gt;재시작이 반복되면 흔히 CrashLoopBackOff를 의심합니다. 하지만 실제로는 다양한 원인이 있습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OOMKilled&lt;/li&gt;
&lt;li&gt;readiness probe 실패&lt;/li&gt;
&lt;li&gt;환경 변수 누락&lt;/li&gt;
&lt;li&gt;ConfigMap 변경 후 설정 오류&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI 분석 결과에 종료 코드, 최근 에러 로그, 리소스 제한 정보가 함께 정리되어 있으면 운영자는 해당 포인트만 집중적으로 확인하면 됩니다.&lt;/p&gt;
&lt;h3&gt;3. 5xx 비율 증가 Alert&lt;/h3&gt;
&lt;p&gt;이 경우 단순히 &amp;quot;에러 증가&amp;quot;가 아니라 다음 흐름을 같이 보는 것이 중요합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ingress 레벨 오류인지&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;Alert만으로는 구분이 어렵지만, 관련 로그와 상태를 묶어서 분석하면 원인 후보를 상당히 좁힐 수 있습니다.&lt;/p&gt;
&lt;h2&gt;적용할 때 주의할 점&lt;/h2&gt;
&lt;p&gt;AI 분석을 자동 복구 로직과 바로 연결하는 것은 위험합니다. 특히 프로덕션 환경에서는 잘못된 판단이 더 큰 장애로 이어질 수 있습니다. 현실적인 접근은 다음과 같습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI는 1차 분석 리포트만 생성&lt;/li&gt;
&lt;li&gt;운영자가 최종 판단&lt;/li&gt;
&lt;li&gt;반복 장애 패턴은 별도 저장해 통계화&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;또한 로그를 무제한으로 전달하면 비용이 급증할 수 있으므로, 시간 범위를 제한하고 중복 로그를 줄이는 전처리 과정이 필요합니다.&lt;/p&gt;
&lt;h2&gt;운영 측면에서의 체감 효과&lt;/h2&gt;
&lt;p&gt;이 구조를 적용하면 가장 크게 느껴지는 변화는 &amp;quot;정리된 상태로 문제를 시작할 수 있다&amp;quot;는 점입니다. 기존에는 Alert → 로그 탐색 → 가설 설정 순서였다면, 이제는 Alert → 가설 후보 확인 → 검증 순서로 바뀝니다.&lt;/p&gt;
&lt;p&gt;특히 다음과 같은 상황에서 효과가 큽니다.&lt;/p&gt;
&lt;ul&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;Prometheus Alert와 AI를 연결한다고 해서 운영이 완전히 자동화되지는 않습니다. 하지만 반복되는 분석 과정을 줄여주고, 문제를 구조적으로 바라보게 해주는 도구로는 충분히 가치가 있습니다.&lt;/p&gt;
&lt;h2&gt;마무리&lt;/h2&gt;
&lt;p&gt;Alert는 신호이고, 로그는 데이터입니다. AI는 그 사이를 연결해주는 역할을 할 수 있습니다. 완전한 자동화보다는, 운영자의 판단을 빠르게 만들어주는 보조 장치로 접근하는 것이 가장 현실적인 도입 방식입니다.&lt;/p&gt;
&lt;p&gt;운영 환경이 복잡해질수록, 문제를 빠르게 구조화하는 능력이 중요해집니다. 그 과정에서 AI는 충분히 실용적인 도구가 될 수 있습니다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>xxlayer</author>
      <guid isPermaLink="true">https://xxlayer.tistory.com/8</guid>
      <comments>https://xxlayer.tistory.com/8#entry8comment</comments>
      <pubDate>Fri, 20 Feb 2026 20:59:53 +0900</pubDate>
    </item>
    <item>
      <title>Kubernetes 로그를 AI로 분석해 장애 원인 자동 추적하기</title>
      <link>https://xxlayer.tistory.com/7</link>
      <description>&lt;h1&gt;Kubernetes 로그를 AI로 분석해 장애 원인 추적 시간을 줄이는 방법&lt;/h1&gt;
&lt;p&gt;Kubernetes 환경에서 장애가 발생하면 가장 먼저 하는 일은&lt;br&gt;kubectl logs, kubectl describe, kubectl get events를 확인하는 것입니다.&lt;/p&gt;
&lt;p&gt;문제는 로그가 너무 많다는 점입니다.&lt;br&gt;특히 운영 중인 서비스가 여러 개이고, 파드가 수십 개 이상일 경우&lt;br&gt;어디서부터 봐야 할지 감이 잘 오지 않습니다.&lt;/p&gt;
&lt;p&gt;실제로 다음과 같은 상황에서는 로그 분석이 병목이 됩니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;여러 파드에서 동시에 에러가 발생하는 경우&lt;/li&gt;
&lt;li&gt;롤링 업데이트 이후 특정 시점부터 오류가 나는 경우&lt;/li&gt;
&lt;li&gt;특정 노드에서만 트래픽이 실패하는 경우&lt;/li&gt;
&lt;li&gt;외부 API 연동 이후 간헐적인 타임아웃이 발생하는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이럴 때 AI를 단순 요약 도구가 아니라&lt;br&gt;&amp;quot;원인 후보를 좁혀주는 보조 도구&amp;quot;로 활용하면 생각보다 도움이 됩니다.&lt;/p&gt;
&lt;h2&gt;단순 키워드 검색의 한계&lt;/h2&gt;
&lt;p&gt;운영자가 흔히 하는 방식은 비슷합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;error, exception, timeout 같은 키워드 검색&lt;/li&gt;
&lt;li&gt;최근 10~30분 로그만 확인&lt;/li&gt;
&lt;li&gt;의심되는 파드 재기동 후 경과 관찰&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 방식이 틀린 것은 아니지만,&lt;br&gt;문제는 실제 장애가 단일 원인으로 발생하지 않는다는 점입니다.&lt;/p&gt;
&lt;p&gt;예를 들면 이런 식입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;readiness probe 실패 → 트래픽 유입 차단&lt;/li&gt;
&lt;li&gt;DB 커넥션 풀 고갈 → 응답 지연 → 타임아웃 증가&lt;/li&gt;
&lt;li&gt;OOMKilled → 재시작 → 캐시 초기화 → 순간 트래픽 급증&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;로그 한 줄만 봐서는 전체 흐름이 잘 보이지 않습니다.&lt;br&gt;여러 컴포넌트 로그를 시간 순서대로 연결해야 원인이 드러납니다.&lt;/p&gt;
&lt;h2&gt;AI 로그 분석을 제대로 쓰는 방법&lt;/h2&gt;
&lt;p&gt;AI에 로그를 그대로 붙여 넣는다고 해서&lt;br&gt;자동으로 정확한 원인이 나오는 것은 아닙니다.&lt;/p&gt;
&lt;p&gt;핵심은 &amp;quot;맥락을 같이 주는 것&amp;quot;입니다.&lt;/p&gt;
&lt;h3&gt;1. 시간 범위를 줄이기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;장애 발생 시점 기준 ±5~10분&lt;/li&gt;
&lt;li&gt;배포 직후라면 배포 시점 기준으로 묶기&lt;/li&gt;
&lt;li&gt;과거 로그는 과감히 제외&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;불필요한 로그가 줄어들수록 분석 정확도는 오히려 올라갑니다.&lt;/p&gt;
&lt;h3&gt;2. 파드 단위로 정리하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;동일 deployment의 파드별 로그 분리&lt;/li&gt;
&lt;li&gt;재시작 횟수 함께 포함&lt;/li&gt;
&lt;li&gt;CrashLoopBackOff 여부 포함&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;단순 로그보다 상태 정보가 훨씬 중요합니다.&lt;/p&gt;
&lt;h3&gt;3. 메타 정보 함께 제공하기&lt;/h3&gt;
&lt;p&gt;다음 정보가 있으면 분석 결과가 훨씬 현실적입니다.&lt;/p&gt;
&lt;ul&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;HPA 스케일 변화 여부&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI는 로그만 보는 것이 아니라&lt;br&gt;&amp;quot;상황 전체&amp;quot;를 이해할 때 정확도가 올라갑니다.&lt;/p&gt;
&lt;h2&gt;실무에서 도움이 되었던 사례&lt;/h2&gt;
&lt;h3&gt;CrashLoopBackOff 반복 발생&lt;/h3&gt;
&lt;p&gt;마지막 종료 코드와 최근 로그, 리소스 설정을 함께 분석했더니&lt;br&gt;OOM 가능성과 환경변수 설정 오류를 동시에 지적해줬습니다.&lt;/p&gt;
&lt;p&gt;직접 로그를 하나씩 보는 것보다&lt;br&gt;확인해야 할 포인트가 먼저 정리된다는 점이 가장 큰 장점이었습니다.&lt;/p&gt;
&lt;h3&gt;502 / 504 오류가 갑자기 늘어난 경우&lt;/h3&gt;
&lt;p&gt;Ingress 로그와 서비스 파드 로그를 함께 분석했더니&lt;br&gt;readiness probe 실패가 시작점이라는 것을 빠르게 찾을 수 있었습니다.&lt;/p&gt;
&lt;p&gt;단순히 &amp;quot;502 발생&amp;quot;이 아니라&lt;br&gt;Ingress → Service → Pod 흐름으로 원인 후보를 좁혀주는 방식이 유용했습니다.&lt;/p&gt;
&lt;h2&gt;운영에 적용할 때 고려할 점&lt;/h2&gt;
&lt;p&gt;AI 분석 결과를 바로 자동 복구로 연결하는 것은 권장하지 않습니다.&lt;/p&gt;
&lt;p&gt;현실적인 구조는 다음과 같습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Alert 발생&lt;/li&gt;
&lt;li&gt;관련 파드 로그 자동 수집&lt;/li&gt;
&lt;li&gt;AI로 1차 원인 후보 정리&lt;/li&gt;
&lt;li&gt;운영자가 최종 판단&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;AI는 결정자가 아니라 보조자 역할로 두는 것이 안정적입니다.&lt;/p&gt;
&lt;h2&gt;실제로 체감되는 변화&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;1차 원인 파악 시간이 줄어듦&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;Kubernetes는 레이어가 많기 때문에&lt;br&gt;단순 로그 나열만으로는 흐름을 파악하기 어렵습니다.&lt;/p&gt;
&lt;p&gt;AI를 잘 활용하면&lt;br&gt;로그를 대신 읽어주는 도구라기보다&lt;br&gt;원인 후보를 정리해주는 도구로 사용할 수 있습니다.&lt;/p&gt;
&lt;h2&gt;마무리&lt;/h2&gt;
&lt;p&gt;로그는 이미 충분히 쌓여 있습니다.&lt;br&gt;문제는 얼마나 빨리 맥락을 파악하느냐입니다.&lt;/p&gt;
&lt;p&gt;AI를 완전 자동 복구 시스템으로 보기보다는&lt;br&gt;운영자의 판단 속도를 높여주는 도구로 접근하는 것이&lt;br&gt;현실적인 활용 방법이라고 생각합니다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>xxlayer</author>
      <guid isPermaLink="true">https://xxlayer.tistory.com/7</guid>
      <comments>https://xxlayer.tistory.com/7#entry7comment</comments>
      <pubDate>Fri, 20 Feb 2026 20:57:29 +0900</pubDate>
    </item>
    <item>
      <title>Cloudflare + AI로 내부 개발 환경 자동 관리하는 방법 (실무 코드 포함)</title>
      <link>https://xxlayer.tistory.com/6</link>
      <description>&lt;h1&gt;Cloudflare + AI로 내부 개발 환경 자동 관리하는 방법 (실무 코드 포함)&lt;/h1&gt; &lt;p&gt;내부 개발 환경을 운영하다 보면 접속 경로 관리와 장애 대응에 많은 시간이 소요됩니다. Cloudflare Tunnel을 사용하면 서버 인바운드 포트를 열지 않고도 내부 서비스를 안전하게 외부에 노출할 수 있습니다. 여기에 AI 기반 장애 분석을 붙이면 단순 모니터링을 넘어 “원인 분석 + 조치 가이드 자동 생성”까지 가능합니다.&lt;/p&gt; &lt;hr&gt; &lt;h2&gt;1. Cloudflare Tunnel 설정&lt;/h2&gt; &lt;p&gt;예시 환경&lt;/p&gt; &lt;ul&gt; &lt;li&gt;code-server: localhost:8080&lt;/li&gt; &lt;li&gt;grafana: localhost:3000&lt;/li&gt; &lt;/ul&gt; &lt;pre style=&quot;white-space:pre;&quot;&gt; # /etc/cloudflared/config.yml&amp;#10; tunnel: dev-tools-tunnel&amp;#10; credentials-file: /etc/cloudflared/dev-tools-tunnel.json&amp;#10; &amp;#10; ingress:&amp;#10; - hostname: code.example.com&amp;#10; service: http://localhost:8080&amp;#10; &amp;#10; - hostname: grafana.example.com&amp;#10; service: http://localhost:3000&amp;#10; &amp;#10; - service: http_status:404&amp;#10; &lt;/pre&gt; &lt;p&gt;서비스 등록&lt;/p&gt; &lt;pre style=&quot;white-space:pre;&quot;&gt; sudo systemctl daemon-reload&amp;#10; sudo systemctl enable --now cloudflared&amp;#10; sudo systemctl status cloudflared&amp;#10; &lt;/pre&gt; &lt;hr&gt; &lt;h2&gt;2. 외부 URL 기준 헬스체크&lt;/h2&gt; &lt;p&gt;사용자가 실제로 접근하는 URL 기준으로 상태를 점검해야 의미가 있습니다.&lt;/p&gt; &lt;pre style=&quot;white-space:pre;&quot;&gt; import requests&amp;#10; from datetime import datetime&amp;#10; &amp;#10; URLS = [&amp;#10; &quot;https://code.example.com/healthz&quot;,&amp;#10; &quot;https://grafana.example.com/api/health&quot;,&amp;#10; ]&amp;#10; &amp;#10; def healthcheck():&amp;#10; results = []&amp;#10; for url in URLS:&amp;#10; try:&amp;#10; r = requests.get(url, timeout=5)&amp;#10; ok = 200 &amp;lt;= r.status_code &amp;lt; 300&amp;#10; results.append({&amp;#10; &quot;url&quot;: url,&amp;#10; &quot;ok&quot;: ok,&amp;#10; &quot;status&quot;: r.status_code,&amp;#10; &quot;time&quot;: datetime.utcnow().isoformat()&amp;#10; })&amp;#10; except Exception as e:&amp;#10; results.append({&amp;#10; &quot;url&quot;: url,&amp;#10; &quot;ok&quot;: False,&amp;#10; &quot;status&quot;: None,&amp;#10; &quot;error&quot;: str(e),&amp;#10; &quot;time&quot;: datetime.utcnow().isoformat()&amp;#10; })&amp;#10; return results&amp;#10; &lt;/pre&gt; &lt;hr&gt; &lt;h2&gt;3. cloudflared 로그 수집&lt;/h2&gt; &lt;pre style=&quot;white-space:pre;&quot;&gt; import subprocess&amp;#10; &amp;#10; def tail_cloudflared_logs(lines=200):&amp;#10; cmd = [&quot;journalctl&quot;, &quot;-u&quot;, &quot;cloudflared&quot;, &quot;-n&quot;, str(lines), &quot;--no-pager&quot;]&amp;#10; r = subprocess.run(cmd, capture_output=True, text=True)&amp;#10; return r.stdout[-20000:]&amp;#10; &lt;/pre&gt; &lt;hr&gt; &lt;h2&gt;4. OpenAI 기반 장애 분석&lt;/h2&gt; &lt;pre style=&quot;white-space:pre;&quot;&gt; from openai import OpenAI&amp;#10; &amp;#10; client = OpenAI()&amp;#10; &amp;#10; def ai_triage(health_results, log_tail):&amp;#10; prompt = f&quot;&quot;&quot;&amp;#10; 너는 SRE다.&amp;#10; 다음 정보를 기반으로 장애 원인과 조치 가이드를 작성하라.&amp;#10; &amp;#10; 출력 형식:&amp;#10; 1. 상황 요약&amp;#10; 2. 의심 원인 Top 3&amp;#10; 3. 확인 절차&amp;#10; 4. 즉시 조치&amp;#10; 5. 재발 방지&amp;#10; &amp;#10; 헬스체크 결과:&amp;#10; {health_results}&amp;#10; &amp;#10; 로그:&amp;#10; {log_tail}&amp;#10; &quot;&quot;&quot;&amp;#10; &amp;#10; resp = client.chat.completions.create(&amp;#10; model=&quot;gpt-4o-mini&quot;,&amp;#10; messages=[{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: prompt}],&amp;#10; temperature=0.2&amp;#10; )&amp;#10; &amp;#10; return resp.choices[0].message.content&amp;#10; &lt;/pre&gt; &lt;hr&gt; &lt;h2&gt;5. Slack 알림 전송&lt;/h2&gt; &lt;pre style=&quot;white-space:pre;&quot;&gt; import os&amp;#10; import requests&amp;#10; &amp;#10; SLACK_WEBHOOK = os.getenv(&quot;SLACK_WEBHOOK&quot;)&amp;#10; &amp;#10; def send_slack(message):&amp;#10; if not SLACK_WEBHOOK:&amp;#10; return&amp;#10; payload = {&quot;text&quot;: message}&amp;#10; requests.post(SLACK_WEBHOOK, json=payload)&amp;#10; &lt;/pre&gt; &lt;hr&gt; &lt;h2&gt;6. 전체 실행 흐름&lt;/h2&gt; &lt;pre style=&quot;white-space:pre;&quot;&gt; def main():&amp;#10; results = healthcheck()&amp;#10; failed = [r for r in results if not r.get(&quot;ok&quot;)]&amp;#10; &amp;#10; if not failed:&amp;#10; return&amp;#10; &amp;#10; logs = tail_cloudflared_logs()&amp;#10; report = ai_triage(results, logs)&amp;#10; send_slack(report)&amp;#10; &amp;#10; if __name__ == &quot;__main__&quot;:&amp;#10; main()&amp;#10; &lt;/pre&gt; &lt;hr&gt; &lt;h2&gt;7. cron 등록&lt;/h2&gt; &lt;pre style=&quot;white-space:pre;&quot;&gt; */10 * * * * /usr/bin/python3 /opt/devops/devtools_monitor.py&amp;#10; &lt;/pre&gt; &lt;hr&gt; &lt;h2&gt;실무 효과&lt;/h2&gt; &lt;ul&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;/p&gt;</description>
      <category>AI</category>
      <author>xxlayer</author>
      <guid isPermaLink="true">https://xxlayer.tistory.com/6</guid>
      <comments>https://xxlayer.tistory.com/6#entry6comment</comments>
      <pubDate>Fri, 20 Feb 2026 20:48:17 +0900</pubDate>
    </item>
    <item>
      <title>AI로 회의록 자동 정리하고 Jira 티켓까지 생성하는 워크플로우 (실무 코드 포함)</title>
      <link>https://xxlayer.tistory.com/5</link>
      <description>&lt;p data-end=&quot;307&quot; data-start=&quot;243&quot; data-ke-size=&quot;size16&quot;&gt;회의가 끝나고 나면 항상 남는 일이 있다.&lt;br /&gt;회의록 정리, 액션 아이템 정리, 그리고 Jira 티켓 생성이다.&lt;/p&gt;
&lt;p data-end=&quot;374&quot; data-start=&quot;309&quot; data-ke-size=&quot;size16&quot;&gt;문제는 이 작업이 매번 사람이 직접 해야 하고,&lt;br /&gt;회의 내용이 길수록 누락이나 해석 오류가 발생하기 쉽다는 점이다.&lt;/p&gt;
&lt;p data-end=&quot;428&quot; data-start=&quot;376&quot; data-ke-size=&quot;size16&quot;&gt;이 과정을 AI로 자동화하면&lt;br /&gt;회의 &amp;rarr; 정리 &amp;rarr; 작업 생성까지 완전히 자동 연결할 수 있다.&lt;/p&gt;
&lt;hr data-end=&quot;433&quot; data-start=&quot;430&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;447&quot; data-start=&quot;435&quot; data-ke-size=&quot;size26&quot;&gt;전체 시스템 구조&lt;/h2&gt;
&lt;p data-end=&quot;464&quot; data-start=&quot;449&quot; data-ke-size=&quot;size16&quot;&gt;자동화 흐름은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;549&quot; data-start=&quot;466&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;480&quot; data-start=&quot;466&quot;&gt;회의 녹음 파일 확보&lt;/li&gt;
&lt;li data-end=&quot;495&quot; data-start=&quot;481&quot;&gt;음성 &amp;rarr; 텍스트 변환&lt;/li&gt;
&lt;li data-end=&quot;514&quot; data-start=&quot;496&quot;&gt;AI로 구조화된 회의록 생성&lt;/li&gt;
&lt;li data-end=&quot;527&quot; data-start=&quot;515&quot;&gt;액션 아이템 추출&lt;/li&gt;
&lt;li data-end=&quot;549&quot; data-start=&quot;528&quot;&gt;Jira API로 티켓 자동 생성&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;606&quot; data-start=&quot;551&quot; data-ke-size=&quot;size16&quot;&gt;이 구조를 한 번 만들어두면&lt;br /&gt;모든 회의가 자동으로 기록되고,&lt;br /&gt;실행 가능한 작업으로 전환된다.&lt;/p&gt;
&lt;hr data-end=&quot;611&quot; data-start=&quot;608&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;632&quot; data-start=&quot;613&quot; data-ke-size=&quot;size26&quot;&gt;1단계: 음성 &amp;rarr; 텍스트 변환&lt;/h2&gt;
&lt;p data-end=&quot;672&quot; data-start=&quot;634&quot; data-ke-size=&quot;size16&quot;&gt;Whisper 모델을 사용하면 회의 녹음을 텍스트로 변환할 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;684&quot; data-start=&quot;674&quot; data-ke-size=&quot;size16&quot;&gt;Python 예시:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1771563152901&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from openai import OpenAI

client = OpenAI()

def transcribe_audio(file_path):
with open(file_path, &quot;rb&quot;) as audio_file:
transcript = client.audio.transcriptions.create(
model=&quot;whisper-1&quot;,
file=audio_file
)
return transcript.text&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1013&quot; data-start=&quot;979&quot; data-ke-size=&quot;size16&quot;&gt;회의 파일이 mp3 또는 wav 형식이면 바로 처리 가능하다.&lt;/p&gt;
&lt;p data-end=&quot;1063&quot; data-start=&quot;1015&quot; data-ke-size=&quot;size16&quot;&gt;실무에서는 회의 종료 후 자동으로 파일이 특정 폴더에 저장되도록 설정해두는 것이 좋다.&lt;/p&gt;
&lt;hr data-end=&quot;1068&quot; data-start=&quot;1065&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1085&quot; data-start=&quot;1070&quot; data-ke-size=&quot;size26&quot;&gt;2단계: 회의록 구조화&lt;/h2&gt;
&lt;p data-end=&quot;1128&quot; data-start=&quot;1087&quot; data-ke-size=&quot;size16&quot;&gt;단순 텍스트를 그대로 저장하는 것은 의미가 없다.&lt;br /&gt;핵심은 &amp;ldquo;구조화&amp;rdquo;다.&lt;/p&gt;
&lt;p data-end=&quot;1128&quot; data-start=&quot;1087&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1138&quot; data-start=&quot;1130&quot; data-ke-size=&quot;size16&quot;&gt;프롬프트 예시:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1771563169913&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;역할: 당신은 프로젝트 매니저다.
아래 회의 텍스트를 정리하라.

형식:
1. 회의 개요
2. 주요 논의 사항
3. 결정 사항
4. 액션 아이템 (담당자 포함)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1249&quot; data-start=&quot;1239&quot; data-ke-size=&quot;size16&quot;&gt;Python 예시:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1771563190687&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def summarize_meeting(transcript):
prompt = f&quot;&quot;&quot;
아래 회의 내용을 구조화하라.

1. 회의 개요
2. 주요 논의 사항
3. 결정 사항
4. 액션 아이템 (담당자 포함)

회의 내용:
{transcript}
&quot;&quot;&quot;

response = client.chat.completions.create(
model=&quot;gpt-4o-mini&quot;,
messages=[{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: prompt}],
temperature=0.2
)

return response.choices[0].message.content&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;temperature를 낮게 설정하면&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1692&quot; data-start=&quot;1654&quot; data-ke-size=&quot;size16&quot;&gt;결과가 더 일관되게 나온다.&lt;/p&gt;
&lt;hr data-end=&quot;1697&quot; data-start=&quot;1694&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1717&quot; data-start=&quot;1699&quot; data-ke-size=&quot;size26&quot;&gt;3단계: 액션 아이템만 추출&lt;/h2&gt;
&lt;p data-end=&quot;1764&quot; data-start=&quot;1719&quot; data-ke-size=&quot;size16&quot;&gt;Jira 티켓을 만들기 위해&lt;br /&gt;액션 항목만 JSON 형태로 추출하는 것이 좋다.&lt;/p&gt;
&lt;p data-end=&quot;1774&quot; data-start=&quot;1766&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1774&quot; data-start=&quot;1766&quot; data-ke-size=&quot;size16&quot;&gt;프롬프트 예시:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1771563242219&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;액션 아이템만 JSON 배열로 반환하라.

형식:
[
{
&quot;title&quot;: &quot;&quot;,
&quot;description&quot;: &quot;&quot;,
&quot;assignee&quot;: &quot;&quot;
}
]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1911&quot; data-start=&quot;1884&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 하면 자동으로 Jira 생성이 가능해진다.&lt;/p&gt;
&lt;hr data-end=&quot;1916&quot; data-start=&quot;1913&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1939&quot; data-start=&quot;1918&quot; data-ke-size=&quot;size26&quot;&gt;4단계: Jira 티켓 자동 생성&lt;/h2&gt;
&lt;p data-end=&quot;1958&quot; data-start=&quot;1941&quot; data-ke-size=&quot;size16&quot;&gt;Jira REST API 예시:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1771563254343&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import requests

JIRA_URL = &quot;https://your-domain.atlassian.net/rest/api/3/issue&quot;
AUTH = (&quot;email@example.com&quot;, &quot;jira_api_token&quot;)

def create_jira_issue(title, description, assignee):
payload = {
&quot;fields&quot;: {
&quot;project&quot;: {&quot;key&quot;: &quot;PROJ&quot;},
&quot;summary&quot;: title,
&quot;description&quot;: description,
&quot;issuetype&quot;: {&quot;name&quot;: &quot;Task&quot;},
&quot;assignee&quot;: {&quot;name&quot;: assignee}
}
}

response = requests.post(
JIRA_URL,
json=payload,
auth=AUTH,
headers={&quot;Content-Type&quot;: &quot;application/json&quot;}
)

return response.json()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2632&quot; data-start=&quot;2582&quot; data-ke-size=&quot;size16&quot;&gt;이제 AI가 추출한 액션 아이템을 반복문으로 돌리면&lt;br /&gt;자동으로 Jira 티켓이 생성된다.&lt;/p&gt;
&lt;hr data-end=&quot;2637&quot; data-start=&quot;2634&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2654&quot; data-start=&quot;2639&quot; data-ke-size=&quot;size26&quot;&gt;실무 운영 시 고려사항&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;2825&quot; data-start=&quot;2656&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;2702&quot; data-start=&quot;2656&quot;&gt;개인정보 필터링&lt;br /&gt;회의 중 민감 정보가 포함될 수 있으므로 사전 필터링 필요&lt;/li&gt;
&lt;li data-end=&quot;2738&quot; data-start=&quot;2704&quot;&gt;긴 회의 처리&lt;br /&gt;1시간 이상 회의는 분할 요약 후 통합&lt;/li&gt;
&lt;li data-end=&quot;2786&quot; data-start=&quot;2740&quot;&gt;담당자 매핑&lt;br /&gt;AI가 추출한 이름을 실제 Jira 계정과 매핑하는 로직 필요&lt;/li&gt;
&lt;li data-end=&quot;2825&quot; data-start=&quot;2788&quot;&gt;로그 기록&lt;br /&gt;자동 생성된 티켓 이력을 남겨야 감사 추적 가능&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-end=&quot;2830&quot; data-start=&quot;2827&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2842&quot; data-start=&quot;2832&quot; data-ke-size=&quot;size26&quot;&gt;확장 아이디어&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2914&quot; data-start=&quot;2844&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2858&quot; data-start=&quot;2844&quot;&gt;회의록 자동 슬랙 공유&lt;/li&gt;
&lt;li data-end=&quot;2879&quot; data-start=&quot;2859&quot;&gt;주간 회의 요약 통합 리포트 생성&lt;/li&gt;
&lt;li data-end=&quot;2893&quot; data-start=&quot;2880&quot;&gt;반복 액션 자동 감지&lt;/li&gt;
&lt;li data-end=&quot;2914&quot; data-start=&quot;2894&quot;&gt;완료되지 않은 액션 자동 리마인드&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;2919&quot; data-start=&quot;2916&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2936&quot; data-start=&quot;2921&quot; data-ke-size=&quot;size26&quot;&gt;이 자동화의 진짜 가치&lt;/h2&gt;
&lt;p data-end=&quot;2961&quot; data-start=&quot;2938&quot; data-ke-size=&quot;size16&quot;&gt;이 시스템은 단순 회의록 자동화가 아니다.&lt;/p&gt;
&lt;p data-end=&quot;3006&quot; data-start=&quot;2963&quot; data-ke-size=&quot;size16&quot;&gt;회의에서 나온 &amp;ldquo;말&amp;rdquo;을&lt;br /&gt;바로 &amp;ldquo;실행 가능한 작업&amp;rdquo;으로 전환하는 시스템이다.&lt;/p&gt;
&lt;p data-end=&quot;3068&quot; data-start=&quot;3008&quot; data-ke-size=&quot;size16&quot;&gt;회의가 많을수록 생산성이 떨어지는 구조에서&lt;br /&gt;회의가 많아도 실행력이 유지되는 구조로 바꾸는 것이 핵심이다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>xxlayer</author>
      <guid isPermaLink="true">https://xxlayer.tistory.com/5</guid>
      <comments>https://xxlayer.tistory.com/5#entry5comment</comments>
      <pubDate>Fri, 20 Feb 2026 13:54:29 +0900</pubDate>
    </item>
    <item>
      <title>유튜브 채널 새 영상 업로드 감지 후 AI 요약 리포트 자동 생성하기 (실무 코드 포함)</title>
      <link>https://xxlayer.tistory.com/4</link>
      <description>&lt;p data-end=&quot;273&quot; data-start=&quot;53&quot; data-ke-size=&quot;size16&quot;&gt;경제&amp;middot;투자&amp;middot;기술 유튜브를 여러 개 구독하고 있다면 매일 모든 영상을 직접 보는 것은 사실상 불가능하다. 그렇다고 제목만 보고 넘어가면 중요한 시그널을 놓칠 수 있다. 이 글에서는 &lt;b&gt;YouTube 업로드 감지 &amp;rarr; 자막 수집 &amp;rarr; OpenAI 요약 &amp;rarr; 슬랙 전송&lt;/b&gt;까지 실제로 동작 가능한 수준의 코드 흐름을 포함해 설명한다. 단순 개념이 아니라, 바로 실험해볼 수 있는 구조를 기준으로 정리한다.&lt;/p&gt;
&lt;hr data-end=&quot;278&quot; data-start=&quot;275&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;295&quot; data-start=&quot;280&quot; data-ke-size=&quot;size26&quot;&gt;1. 전체 시스템 구조&lt;/h2&gt;
&lt;p data-end=&quot;310&quot; data-start=&quot;297&quot; data-ke-size=&quot;size16&quot;&gt;구성은 다음 네 단계다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;404&quot; data-start=&quot;312&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;332&quot; data-start=&quot;312&quot;&gt;특정 채널의 최신 영상 감지&lt;/li&gt;
&lt;li data-end=&quot;358&quot; data-start=&quot;333&quot;&gt;영상 자막(Transcript) 수집&lt;/li&gt;
&lt;li data-end=&quot;382&quot; data-start=&quot;359&quot;&gt;OpenAI API로 구조화 요약&lt;/li&gt;
&lt;li data-end=&quot;404&quot; data-start=&quot;383&quot;&gt;슬랙 또는 이메일로 자동 전송&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;459&quot; data-start=&quot;406&quot; data-ke-size=&quot;size16&quot;&gt;리눅스 서버 기준으로 cron에 등록해 10~30분마다 실행하도록 설정하면 완전 자동화가 된다.&lt;/p&gt;
&lt;hr data-end=&quot;464&quot; data-start=&quot;461&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;491&quot; data-start=&quot;466&quot; data-ke-size=&quot;size26&quot;&gt;2. YouTube 최신 영상 감지 코드&lt;/h2&gt;
&lt;p data-end=&quot;546&quot; data-start=&quot;493&quot; data-ke-size=&quot;size16&quot;&gt;먼저 YouTube Data API 키를 발급받는다.&lt;br /&gt;환경 변수에 저장해두는 것이 안전하다.&lt;/p&gt;
&lt;pre id=&quot;code_1771512696777&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export YOUTUBE_API_KEY=&quot;your_api_key&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;Python 코드 예시는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1771512727631&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import os
import requests

YOUTUBE_API_KEY = os.getenv(&quot;YOUTUBE_API_KEY&quot;)
CHANNEL_ID = &quot;UCxxxxxxxxxxxx&quot;  # 대상 채널 ID

def get_latest_video():
    url = &quot;https://www.googleapis.com/youtube/v3/search&quot;
    params = {
        &quot;key&quot;: YOUTUBE_API_KEY,
        &quot;channelId&quot;: CHANNEL_ID,
        &quot;part&quot;: &quot;snippet&quot;,
        &quot;order&quot;: &quot;date&quot;,
        &quot;maxResults&quot;: 1
    }

    res = requests.get(url, params=params)
    data = res.json()

    if &quot;items&quot; in data and len(data[&quot;items&quot;]) &amp;gt; 0:
        video = data[&quot;items&quot;][0]
        return video[&quot;id&quot;][&quot;videoId&quot;], video[&quot;snippet&quot;][&quot;title&quot;]

    return None, None&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무에서는 마지막으로 처리한 videoId를 파일이나 DB에 저장해두고, 새로운 ID일 경우에만 다음 단계로 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;1326&quot; data-start=&quot;1309&quot; data-ke-size=&quot;size26&quot;&gt;3. 영상 자막 수집 코드&lt;/h2&gt;
&lt;p data-end=&quot;1398&quot; data-start=&quot;1328&quot; data-ke-size=&quot;size16&quot;&gt;공식 API는 자막 접근이 제한적일 수 있어 youtube-transcript-api 라이브러리를 사용하는 것이 편리하다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1771513405389&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install youtube-transcript-api&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1771513587423&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from youtube_transcript_api import YouTubeTranscriptApi

def get_transcript(video_id):
    transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=[&quot;ko&quot;, &quot;en&quot;])
    text = &quot; &quot;.join([item[&quot;text&quot;] for item in transcript])
    return text&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1759&quot; data-start=&quot;1712&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1759&quot; data-start=&quot;1712&quot; data-ke-size=&quot;size16&quot;&gt;이때 자막 길이가 매우 길 수 있다. 바로 API에 넘기지 말고 정제 과정을 거친다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1771513606579&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def clean_text(text):
    text = text.replace(&quot;\n&quot;, &quot; &quot;)
    return text[:10000]  # 과도한 길이 제한&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1907&quot; data-start=&quot;1870&quot; data-ke-size=&quot;size16&quot;&gt;실무에서는 광고 멘트, 반복 문장 제거 로직을 추가하는 것이 좋다.&lt;/p&gt;
&lt;hr data-end=&quot;1912&quot; data-start=&quot;1909&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1937&quot; data-start=&quot;1914&quot; data-ke-size=&quot;size26&quot;&gt;4. OpenAI로 구조화 요약 요청&lt;/h2&gt;
&lt;p data-end=&quot;1965&quot; data-start=&quot;1939&quot; data-ke-size=&quot;size16&quot;&gt;OpenAI API 키도 환경 변수로 관리한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1771513620490&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export OPENAI_API_KEY=&quot;your_openai_key&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2033&quot; data-start=&quot;2020&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2033&quot; data-start=&quot;2020&quot; data-ke-size=&quot;size16&quot;&gt;Python 코드 예시:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1771513636353&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from openai import OpenAI

client = OpenAI()

def summarize_video(title, transcript):
    prompt = f&quot;&quot;&quot;
    역할: 당신은 투자 리서치 애널리스트다.
    아래 유튜브 영상 자막을 기반으로 투자 관점에서 정리하라.

    영상 제목: {title}

    출력 형식:
    1. 핵심 주장 3가지
    2. 긍정 요인
    3. 리스크 요인
    4. 시장 영향 분석
    5. 한 줄 결론

    자막:
    {transcript}
    &quot;&quot;&quot;

    response = client.chat.completions.create(
        model=&quot;gpt-4o-mini&quot;,
        messages=[{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: prompt}],
        temperature=0.3
    )

    return response.choices[0].message.content&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2604&quot; data-start=&quot;2569&quot; data-ke-size=&quot;size16&quot;&gt;여기서 temperature를 낮추면 결과의 일관성이 높아진다.&lt;/p&gt;
&lt;hr data-end=&quot;2609&quot; data-start=&quot;2606&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2627&quot; data-start=&quot;2611&quot; data-ke-size=&quot;size26&quot;&gt;5. 슬랙으로 자동 전송&lt;/h2&gt;
&lt;p data-end=&quot;2667&quot; data-start=&quot;2629&quot; data-ke-size=&quot;size16&quot;&gt;슬랙 Webhook URL을 생성한 뒤 다음 코드로 전송할 수 있다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1771513653033&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SLACK_WEBHOOK = &quot;https://hooks.slack.com/services/xxxx&quot;

def send_to_slack(message):
    payload = {&quot;text&quot;: message}
    requests.post(SLACK_WEBHOOK, json=payload)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;2851&quot; data-start=&quot;2848&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2870&quot; data-start=&quot;2853&quot; data-ke-size=&quot;size26&quot;&gt;6. 전체 실행 흐름 통합&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1771513667988&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def main():
    video_id, title = get_latest_video()
    if not video_id:
        return

    transcript = get_transcript(video_id)
    cleaned = clean_text(transcript)

    summary = summarize_video(title, cleaned)
    send_to_slack(summary)

if __name__ == &quot;__main__&quot;:
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3190&quot; data-start=&quot;3169&quot; data-ke-size=&quot;size16&quot;&gt;이 스크립트를 cron에 등록한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;crontab -e &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3219&quot; data-start=&quot;3216&quot; data-ke-size=&quot;size16&quot;&gt;예시:&lt;/p&gt;
&lt;pre id=&quot;code_1771513687150&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;*/30 * * * * /usr/bin/python3 /home/user/youtube_summary.py&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;3330&quot; data-start=&quot;3294&quot; data-ke-size=&quot;size16&quot;&gt;30분마다 실행되어 새 영상이 올라오면 자동으로 요약이 전달된다.&lt;/p&gt;
&lt;hr data-end=&quot;3335&quot; data-start=&quot;3332&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;3352&quot; data-start=&quot;3337&quot; data-ke-size=&quot;size26&quot;&gt;7. 비용 최적화 전략&lt;/h2&gt;
&lt;p data-end=&quot;3403&quot; data-start=&quot;3354&quot; data-ke-size=&quot;size16&quot;&gt;자막이 길 경우 한 번에 호출하면 비용이 증가한다.&lt;br /&gt;실무에서는 다음 전략을 사용한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3484&quot; data-start=&quot;3405&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3435&quot; data-start=&quot;3405&quot;&gt;2,000~3,000자 단위 분할 후 1차 요약&lt;/li&gt;
&lt;li data-end=&quot;3458&quot; data-start=&quot;3436&quot;&gt;부분 요약 결과를 다시 통합 요약&lt;/li&gt;
&lt;li data-end=&quot;3484&quot; data-start=&quot;3459&quot;&gt;제목과 설명란을 함께 전달해 맥락 강화&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;3526&quot; data-start=&quot;3486&quot; data-ke-size=&quot;size16&quot;&gt;또한 특정 키워드가 제목에 포함된 경우에만 요약하도록 필터링할 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;3530&quot; data-start=&quot;3528&quot; data-ke-size=&quot;size16&quot;&gt;예:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1771513700965&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if &quot;금리&quot; not in title and &quot;AI&quot; not in title:
    return
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;3605&quot; data-start=&quot;3602&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;3620&quot; data-start=&quot;3607&quot; data-ke-size=&quot;size26&quot;&gt;8. 확장 아이디어&lt;/h2&gt;
&lt;p data-end=&quot;3649&quot; data-start=&quot;3622&quot; data-ke-size=&quot;size16&quot;&gt;여기서 멈추지 않고 다음과 같은 확장이 가능하다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3722&quot; data-start=&quot;3651&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3668&quot; data-start=&quot;3651&quot;&gt;여러 채널 동시 모니터링&lt;/li&gt;
&lt;li data-end=&quot;3688&quot; data-start=&quot;3669&quot;&gt;특정 종목 언급 횟수 카운트&lt;/li&gt;
&lt;li data-end=&quot;3701&quot; data-start=&quot;3689&quot;&gt;감성 분석 추가&lt;/li&gt;
&lt;li data-end=&quot;3722&quot; data-start=&quot;3702&quot;&gt;주간 PDF 리포트 자동 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;3786&quot; data-start=&quot;3724&quot; data-ke-size=&quot;size16&quot;&gt;요약 결과를 구글 스프레드시트에 누적 저장하면&lt;br /&gt;한 달간 &amp;ldquo;금리 인하&amp;rdquo; 언급 빈도 같은 통계도 만들 수 있다.&lt;/p&gt;
&lt;hr data-end=&quot;3791&quot; data-start=&quot;3788&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;3799&quot; data-start=&quot;3793&quot; data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-end=&quot;3846&quot; data-start=&quot;3801&quot; data-ke-size=&quot;size16&quot;&gt;이 시스템의 핵심은 단순 요약이 아니라&lt;br /&gt;&amp;ldquo;영상 콘텐츠를 데이터화하는 것&amp;rdquo;이다.&lt;/p&gt;
&lt;p data-end=&quot;3913&quot; data-start=&quot;3848&quot; data-ke-size=&quot;size16&quot;&gt;YouTube API와 OpenAI API를 결합하면&lt;br /&gt;개인 투자자도 자신만의 리서치 자동화 환경을 만들 수 있다.&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;3997&quot; data-start=&quot;3915&quot; data-ke-size=&quot;size16&quot;&gt;영상을 소비하는 단계에서 끝나지 않고,&lt;br /&gt;영상에서 구조화된 인사이트를 추출하는 단계로 넘어가는 것.&lt;br /&gt;그것이 이 자동화 프로젝트의 진짜 가치다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>xxlayer</author>
      <guid isPermaLink="true">https://xxlayer.tistory.com/4</guid>
      <comments>https://xxlayer.tistory.com/4#entry4comment</comments>
      <pubDate>Fri, 20 Feb 2026 13:47:59 +0900</pubDate>
    </item>
    <item>
      <title>슬랙 알림을 AI로 자동 분류하는 업무 자동화 시스템 구축기</title>
      <link>https://xxlayer.tistory.com/3</link>
      <description>&lt;p data-end=&quot;293&quot; data-start=&quot;37&quot; data-ke-size=&quot;size16&quot;&gt;슬랙 채널이 늘어날수록 생산성은 오히려 떨어지는 경우가 많다. 프로젝트 채널, 운영 채널, 공지 채널, 장애 알림 채널까지 합치면 하루에 수백 개의 메시지가 쌓인다. 문제는 이 중 실제로 &amp;ldquo;지금 당장 확인해야 할 메시지&amp;rdquo;는 극히 일부라는 점이다. 모든 알림을 동일한 중요도로 받아들이면 집중력이 분산되고, 중요한 장애 신호를 놓칠 위험도 커진다. 이런 상황에서 AI를 활용한 자동 분류 시스템은 단순 편의 기능이 아니라 실질적인 업무 효율 개선 도구가 된다.&lt;/p&gt;
&lt;h2 data-end=&quot;317&quot; data-start=&quot;295&quot; data-ke-size=&quot;size26&quot;&gt;왜 슬랙 알림 자동 분류가 필요한가&lt;/h2&gt;
&lt;p data-end=&quot;383&quot; data-start=&quot;319&quot; data-ke-size=&quot;size16&quot;&gt;운영 환경이나 개발 조직에서는 슬랙이 사실상 실시간 협업 플랫폼 역할을 한다. 하지만 다음과 같은 문제가 반복된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;482&quot; data-start=&quot;385&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;406&quot; data-start=&quot;385&quot;&gt;장애 알림이 일반 대화에 묻힌다&lt;/li&gt;
&lt;li data-end=&quot;438&quot; data-start=&quot;407&quot;&gt;봇 메시지와 사람 메시지가 섞여 가독성이 떨어진다&lt;/li&gt;
&lt;li data-end=&quot;459&quot; data-start=&quot;439&quot;&gt;긴급 메시지를 뒤늦게 확인한다&lt;/li&gt;
&lt;li data-end=&quot;482&quot; data-start=&quot;460&quot;&gt;특정 키워드를 수동 검색해야 한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;652&quot; data-start=&quot;484&quot; data-ke-size=&quot;size16&quot;&gt;특히 장애 대응 팀의 경우, 모든 메시지를 직접 읽어야 한다는 부담 때문에 피로도가 급격히 올라간다. 단순 키워드 필터링만으로는 한계가 있다. &amp;ldquo;서버가 죽었다&amp;rdquo;는 표현 대신 &amp;ldquo;헬스체크가 계속 실패한다&amp;rdquo;처럼 우회적으로 표현될 수 있기 때문이다. 이 지점에서 자연어 이해가 가능한 AI가 효과를 발휘한다.&lt;/p&gt;
&lt;h2 data-end=&quot;668&quot; data-start=&quot;654&quot; data-ke-size=&quot;size26&quot;&gt;전체 시스템 아키텍처&lt;/h2&gt;
&lt;p data-end=&quot;709&quot; data-start=&quot;670&quot; data-ke-size=&quot;size16&quot;&gt;슬랙 메시지를 AI로 자동 분류하는 시스템은 크게 네 단계로 구성된다.&lt;/p&gt;
&lt;h3 data-end=&quot;729&quot; data-start=&quot;711&quot; data-ke-size=&quot;size23&quot;&gt;1단계: 슬랙 이벤트 수신&lt;/h3&gt;
&lt;p data-end=&quot;866&quot; data-start=&quot;731&quot; data-ke-size=&quot;size16&quot;&gt;Slack Events API를 활용해 특정 채널의 메시지를 실시간으로 수신한다. 봇을 생성하고 이벤트 구독을 설정하면 메시지가 발생할 때마다 웹훅 엔드포인트로 전달된다. 여기서 메시지 본문, 사용자 ID, 채널 정보, 타임스탬프를 추출한다.&lt;/p&gt;
&lt;h3 data-end=&quot;883&quot; data-start=&quot;868&quot; data-ke-size=&quot;size23&quot;&gt;2단계: 1차 필터링&lt;/h3&gt;
&lt;p data-end=&quot;1015&quot; data-start=&quot;885&quot; data-ke-size=&quot;size16&quot;&gt;모든 메시지를 AI에 전달하면 비용이 불필요하게 증가한다. 따라서 간단한 1차 필터를 둔다. 예를 들어 특정 채널만 대상으로 하거나, 길이가 너무 짧은 메시지는 제외할 수 있다. 또한 단순 이모지 반응이나 시스템 메시지는 필터링한다.&lt;/p&gt;
&lt;h3 data-end=&quot;1034&quot; data-start=&quot;1017&quot; data-ke-size=&quot;size23&quot;&gt;3단계: AI 분류 요청&lt;/h3&gt;
&lt;p data-end=&quot;1115&quot; data-start=&quot;1036&quot; data-ke-size=&quot;size16&quot;&gt;정제된 메시지를 OpenAI API에 전달해 카테고리를 분류하도록 요청한다. 단순 요약이 아니라 &amp;ldquo;업무 관점 분류&amp;rdquo;를 지시하는 것이 핵심이다.&lt;/p&gt;
&lt;h3 data-end=&quot;1132&quot; data-start=&quot;1117&quot; data-ke-size=&quot;size23&quot;&gt;4단계: 결과 재배포&lt;/h3&gt;
&lt;p data-end=&quot;1238&quot; data-start=&quot;1134&quot; data-ke-size=&quot;size16&quot;&gt;AI가 반환한 카테고리에 따라 메시지를 별도 채널로 재전송하거나, 중요도가 높은 경우 별도의 알림을 발생시킨다. 예를 들어 긴급 장애로 분류된 메시지는 온콜 채널로 자동 전달할 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;1290&quot; data-start=&quot;1240&quot; data-ke-size=&quot;size16&quot;&gt;이 구조를 한 번 만들어두면, 이후 분류 기준을 추가하거나 변경하는 것도 비교적 간단하다.&lt;/p&gt;
&lt;h2 data-end=&quot;1310&quot; data-start=&quot;1292&quot; data-ke-size=&quot;size26&quot;&gt;효과적인 프롬프트 설계 방법&lt;/h2&gt;
&lt;p data-end=&quot;1370&quot; data-start=&quot;1312&quot; data-ke-size=&quot;size16&quot;&gt;슬랙 메시지 분류의 핵심은 프롬프트 설계다. 다음과 같이 역할과 분류 기준을 명확히 정의하는 것이 좋다.&lt;/p&gt;
&lt;p data-end=&quot;1439&quot; data-start=&quot;1372&quot; data-ke-size=&quot;size16&quot;&gt;역할: 당신은 IT 운영 모니터링 담당자다.&lt;br /&gt;목표: 아래 슬랙 메시지를 분석해 카테고리를 분류하라.&lt;br /&gt;카테고리:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1505&quot; data-start=&quot;1440&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;1450&quot; data-start=&quot;1440&quot;&gt;긴급 장애&lt;/li&gt;
&lt;li data-end=&quot;1464&quot; data-start=&quot;1451&quot;&gt;일반 기술 이슈&lt;/li&gt;
&lt;li data-end=&quot;1480&quot; data-start=&quot;1465&quot;&gt;배포 및 변경 사항&lt;/li&gt;
&lt;li data-end=&quot;1494&quot; data-start=&quot;1481&quot;&gt;단순 정보 공유&lt;/li&gt;
&lt;li data-end=&quot;1505&quot; data-start=&quot;1495&quot;&gt;무시 가능&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;1515&quot; data-start=&quot;1507&quot; data-ke-size=&quot;size16&quot;&gt;출력 형식:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1549&quot; data-start=&quot;1516&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1524&quot; data-start=&quot;1516&quot;&gt;카테고리&lt;/li&gt;
&lt;li data-end=&quot;1535&quot; data-start=&quot;1525&quot;&gt;한 줄 요약&lt;/li&gt;
&lt;li data-end=&quot;1549&quot; data-start=&quot;1536&quot;&gt;긴급도 점수(1~5)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1632&quot; data-start=&quot;1551&quot; data-ke-size=&quot;size16&quot;&gt;이처럼 구조화된 출력 형식을 요구하면 이후 자동화 처리도 쉬워진다. 예를 들어 긴급도 점수가 4 이상인 경우에만 알림을 울리도록 설정할 수 있다.&lt;/p&gt;
&lt;h2 data-end=&quot;1652&quot; data-start=&quot;1634&quot; data-ke-size=&quot;size26&quot;&gt;Python 기반 구현 흐름&lt;/h2&gt;
&lt;p data-end=&quot;1684&quot; data-start=&quot;1654&quot; data-ke-size=&quot;size16&quot;&gt;Python으로 구현할 경우 기본 구조는 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1820&quot; data-start=&quot;1686&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;1716&quot; data-start=&quot;1686&quot;&gt;Flask 또는 FastAPI로 웹 서버 구성&lt;/li&gt;
&lt;li data-end=&quot;1746&quot; data-start=&quot;1717&quot;&gt;슬랙 이벤트 요청을 수신하는 엔드포인트 생성&lt;/li&gt;
&lt;li data-end=&quot;1772&quot; data-start=&quot;1747&quot;&gt;수신된 메시지를 JSON 형태로 파싱&lt;/li&gt;
&lt;li data-end=&quot;1791&quot; data-start=&quot;1773&quot;&gt;OpenAI API 호출&lt;/li&gt;
&lt;li data-end=&quot;1820&quot; data-start=&quot;1792&quot;&gt;결과에 따라 슬랙 Webhook으로 재전송&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;1922&quot; data-start=&quot;1822&quot; data-ke-size=&quot;size16&quot;&gt;여기서 중요한 점은 응답 속도다. 슬랙 이벤트는 일정 시간 내에 응답하지 않으면 재전송을 시도한다. 따라서 AI 호출은 비동기로 처리하거나, 큐 시스템을 도입하는 것이 안정적이다.&lt;/p&gt;
&lt;h2 data-end=&quot;1941&quot; data-start=&quot;1924&quot; data-ke-size=&quot;size26&quot;&gt;비용 및 성능 최적화 전략&lt;/h2&gt;
&lt;p data-end=&quot;2008&quot; data-start=&quot;1943&quot; data-ke-size=&quot;size16&quot;&gt;슬랙 메시지는 짧은 경우가 많지만, 채널이 많아지면 호출 횟수가 증가한다. 이를 최적화하기 위한 전략은 다음과 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2086&quot; data-start=&quot;2010&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2029&quot; data-start=&quot;2010&quot;&gt;동일 메시지 중복 호출 방지&lt;/li&gt;
&lt;li data-end=&quot;2052&quot; data-start=&quot;2030&quot;&gt;특정 시간대에는 요약 모드로 전환&lt;/li&gt;
&lt;li data-end=&quot;2073&quot; data-start=&quot;2053&quot;&gt;키워드 기반 사전 필터링 강화&lt;/li&gt;
&lt;li data-end=&quot;2086&quot; data-start=&quot;2074&quot;&gt;모델 크기 조정&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2151&quot; data-start=&quot;2088&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 모든 메시지를 실시간 분류하는 대신, 일반 채널은 5분 단위로 묶어 요약하는 방식으로 전환할 수 있다.&lt;/p&gt;
&lt;h2 data-end=&quot;2167&quot; data-start=&quot;2153&quot; data-ke-size=&quot;size26&quot;&gt;보안과 운영 고려사항&lt;/h2&gt;
&lt;p data-end=&quot;2218&quot; data-start=&quot;2169&quot; data-ke-size=&quot;size16&quot;&gt;슬랙 메시지에는 내부 시스템 정보가 포함될 수 있다. 따라서 다음 사항을 점검해야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2297&quot; data-start=&quot;2220&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2240&quot; data-start=&quot;2220&quot;&gt;API 키는 환경 변수로 관리&lt;/li&gt;
&lt;li data-end=&quot;2263&quot; data-start=&quot;2241&quot;&gt;메시지 로그는 별도 저장소에 보관&lt;/li&gt;
&lt;li data-end=&quot;2281&quot; data-start=&quot;2264&quot;&gt;외부 전송 데이터 최소화&lt;/li&gt;
&lt;li data-end=&quot;2297&quot; data-start=&quot;2282&quot;&gt;접근 제어 설정 강화&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2359&quot; data-start=&quot;2299&quot; data-ke-size=&quot;size16&quot;&gt;또한 장애 상황에서 AI 호출이 실패하더라도 기본 알림은 정상 작동하도록 이중 안전 장치를 두는 것이 좋다.&lt;/p&gt;
&lt;h2 data-end=&quot;2380&quot; data-start=&quot;2361&quot; data-ke-size=&quot;size26&quot;&gt;실무에서 기대할 수 있는 효과&lt;/h2&gt;
&lt;p data-end=&quot;2419&quot; data-start=&quot;2382&quot; data-ke-size=&quot;size16&quot;&gt;AI 기반 자동 분류 시스템을 도입하면 다음과 같은 변화가 생긴다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2485&quot; data-start=&quot;2421&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2441&quot; data-start=&quot;2421&quot;&gt;긴급 메시지를 놓칠 확률 감소&lt;/li&gt;
&lt;li data-end=&quot;2455&quot; data-start=&quot;2442&quot;&gt;알림 피로도 감소&lt;/li&gt;
&lt;li data-end=&quot;2469&quot; data-start=&quot;2456&quot;&gt;채널 가독성 개선&lt;/li&gt;
&lt;li data-end=&quot;2485&quot; data-start=&quot;2470&quot;&gt;온콜 대응 시간 단축&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2572&quot; data-start=&quot;2487&quot; data-ke-size=&quot;size16&quot;&gt;특히 운영 조직에서는 장애 감지와 대응 속도가 곧 서비스 품질과 직결된다. 단순한 편의 기능처럼 보이지만, 실제로는 대응 체계를 고도화하는 역할을 한다.&lt;/p&gt;
&lt;h2 data-end=&quot;2584&quot; data-start=&quot;2574&quot; data-ke-size=&quot;size26&quot;&gt;확장 아이디어&lt;/h2&gt;
&lt;p data-end=&quot;2619&quot; data-start=&quot;2586&quot; data-ke-size=&quot;size16&quot;&gt;이 시스템은 단순 분류를 넘어 다음 단계로 확장할 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2704&quot; data-start=&quot;2621&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2643&quot; data-start=&quot;2621&quot;&gt;반복 발생 장애 유형 자동 통계화&lt;/li&gt;
&lt;li data-end=&quot;2663&quot; data-start=&quot;2644&quot;&gt;특정 키워드 등장 빈도 분석&lt;/li&gt;
&lt;li data-end=&quot;2683&quot; data-start=&quot;2664&quot;&gt;주간 운영 리포트 자동 생성&lt;/li&gt;
&lt;li data-end=&quot;2704&quot; data-start=&quot;2684&quot;&gt;담당자 자동 태깅 시스템 구축&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2777&quot; data-start=&quot;2706&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;DB 연결 실패&amp;rdquo; 유형 메시지가 한 주에 5회 이상 발생하면 자동으로 개선 과제 티켓을 생성하도록 설계할 수 있다.&lt;/p&gt;
&lt;h2 data-end=&quot;2785&quot; data-start=&quot;2779&quot; data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-end=&quot;2885&quot; data-start=&quot;2787&quot; data-ke-size=&quot;size16&quot;&gt;슬랙 알림을 AI로 자동 분류하는 시스템은 구현 난이도 대비 효과가 큰 자동화 사례다. 단순 키워드 필터링을 넘어 맥락을 이해한 분류가 가능하다는 점이 가장 큰 차별점이다.&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;3003&quot; data-start=&quot;2887&quot; data-ke-size=&quot;size16&quot;&gt;알림에 휘둘리는 환경에서 벗어나고 싶다면, 슬랙 메시지 자동 분류 시스템은 충분히 도전해볼 만한 프로젝트다. 반복 확인 시간을 줄이고 중요한 신호에 집중할 수 있는 환경을 만드는 것이 진짜 자동화의 시작이다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>xxlayer</author>
      <guid isPermaLink="true">https://xxlayer.tistory.com/3</guid>
      <comments>https://xxlayer.tistory.com/3#entry3comment</comments>
      <pubDate>Thu, 19 Feb 2026 21:53:36 +0900</pubDate>
    </item>
    <item>
      <title>Python + OpenAI API로 이메일 요약 봇 만들기</title>
      <link>https://xxlayer.tistory.com/2</link>
      <description>&lt;p data-end=&quot;303&quot; data-start=&quot;37&quot; data-ke-size=&quot;size16&quot;&gt;업무 메일이 하루에 수십 통씩 쌓이는 환경이라면, 이미 자동화할 가치가 충분하다. 특히 참조로 포함된 긴 스레드나 여러 사람이 얽힌 논의 메일은 내용을 끝까지 읽지 않으면 맥락을 파악하기 어렵다. 중요한 의사결정 포인트가 메일 중간에 묻혀 있는 경우도 많다. 이런 반복 확인 작업을 줄이기 위해 Python과 OpenAI API를 활용해 이메일 요약 봇을 구축할 수 있다. 단순히 길이를 줄이는 것이 아니라, &amp;ldquo;오늘 내가 처리해야 할 내용&amp;rdquo; 중심으로 재구성하는 것이 핵심이다.&lt;/p&gt;
&lt;h2 data-end=&quot;325&quot; data-start=&quot;305&quot; data-ke-size=&quot;size26&quot;&gt;이메일 요약 자동화의 목표 정의&lt;/h2&gt;
&lt;p data-end=&quot;437&quot; data-start=&quot;327&quot; data-ke-size=&quot;size16&quot;&gt;먼저 목표를 명확히 해야 한다. 이메일 요약의 목적은 모든 메일을 줄이는 것이 아니라, 우선순위를 빠르게 판단할 수 있도록 돕는 것이다. 따라서 다음 세 가지 요소를 포함하도록 설계하는 것이 좋다.&lt;/p&gt;
&lt;p data-end=&quot;496&quot; data-start=&quot;439&quot; data-ke-size=&quot;size16&quot;&gt;첫째, 핵심 의사결정 사항&lt;br /&gt;둘째, 내가 회신해야 하는지 여부&lt;br /&gt;셋째, 일정이나 마감 기한 정보&lt;/p&gt;
&lt;p data-end=&quot;545&quot; data-start=&quot;498&quot; data-ke-size=&quot;size16&quot;&gt;이 세 요소가 자동으로 추출되면 단순 요약을 넘어 업무 관리 도구로 활용할 수 있다.&lt;/p&gt;
&lt;h2 data-end=&quot;561&quot; data-start=&quot;547&quot; data-ke-size=&quot;size26&quot;&gt;전체 시스템 아키텍처&lt;/h2&gt;
&lt;p data-end=&quot;594&quot; data-start=&quot;563&quot; data-ke-size=&quot;size16&quot;&gt;이메일 요약 봇은 다음과 같은 흐름으로 구성할 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;713&quot; data-start=&quot;596&quot; data-ke-size=&quot;size16&quot;&gt;1단계: 이메일 수집&lt;br /&gt;Gmail API 또는 Outlook Graph API를 사용해 최근 24시간 또는 읽지 않은 메일을 조회한다. 조회 시 발신자, 제목, 본문 텍스트, 수신 시간 정보를 함께 가져온다.&lt;/p&gt;
&lt;p data-end=&quot;817&quot; data-start=&quot;715&quot; data-ke-size=&quot;size16&quot;&gt;2단계: 1차 필터링&lt;br /&gt;광고 메일, 자동 알림 메일, 뉴스레터 등은 제외한다. 예를 들어 특정 발신자 도메인이나 제목 패턴을 기준으로 필터링하면 불필요한 토큰 사용을 줄일 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;903&quot; data-start=&quot;819&quot; data-ke-size=&quot;size16&quot;&gt;3단계: 프롬프트 구성&lt;br /&gt;메일 제목과 본문을 정리해 하나의 텍스트 블록으로 만든 뒤, 요약 목적에 맞는 지시문과 함께 OpenAI API에 전달한다.&lt;/p&gt;
&lt;p data-end=&quot;978&quot; data-start=&quot;905&quot; data-ke-size=&quot;size16&quot;&gt;4단계: 결과 재구성&lt;br /&gt;메일별 요약을 하나의 일일 리포트 형태로 묶는다. 예를 들어 &amp;ldquo;오늘 확인해야 할 메일 5건&amp;rdquo;처럼 정리한다.&lt;/p&gt;
&lt;p data-end=&quot;1034&quot; data-start=&quot;980&quot; data-ke-size=&quot;size16&quot;&gt;5단계: 결과 전송&lt;br /&gt;슬랙, 이메일, 노션, 구글 스프레드시트 등 원하는 채널로 자동 전송한다.&lt;/p&gt;
&lt;p data-end=&quot;1096&quot; data-start=&quot;1036&quot; data-ke-size=&quot;size16&quot;&gt;이 구조는 단순하지만 확장성이 높다. 이후 팀 단위 공유 기능이나 태그 자동 분류 기능을 추가할 수도 있다.&lt;/p&gt;
&lt;h2 data-end=&quot;1113&quot; data-start=&quot;1098&quot; data-ke-size=&quot;size26&quot;&gt;Python 구현 흐름&lt;/h2&gt;
&lt;p data-end=&quot;1145&quot; data-start=&quot;1115&quot; data-ke-size=&quot;size16&quot;&gt;Python으로 구현할 때는 크게 세 부분으로 나뉜다.&lt;/p&gt;
&lt;p data-end=&quot;1291&quot; data-start=&quot;1147&quot; data-ke-size=&quot;size16&quot;&gt;첫째, 이메일 API 인증 및 조회&lt;br /&gt;Gmail의 경우 OAuth 인증을 설정한 뒤 users.messages.list API를 호출해 최근 메일 ID를 가져온다. 이후 각 메시지의 본문을 추출한다. HTML 형식일 경우 텍스트로 변환하는 과정이 필요하다.&lt;/p&gt;
&lt;p data-end=&quot;1336&quot; data-start=&quot;1293&quot; data-ke-size=&quot;size16&quot;&gt;둘째, 요약 요청&lt;br /&gt;메일 제목과 본문 일부를 다음과 같은 형식으로 구성한다.&lt;/p&gt;
&lt;p data-end=&quot;1406&quot; data-start=&quot;1338&quot; data-ke-size=&quot;size16&quot;&gt;역할: 당신은 업무 비서다.&lt;br /&gt;목표: 아래 이메일을 기반으로 핵심 내용과 회신 필요 여부를 정리하라.&lt;br /&gt;출력 형식:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1440&quot; data-start=&quot;1407&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1416&quot; data-start=&quot;1407&quot;&gt;핵심 요약&lt;/li&gt;
&lt;li data-end=&quot;1427&quot; data-start=&quot;1417&quot;&gt;필요한 액션&lt;/li&gt;
&lt;li data-end=&quot;1440&quot; data-start=&quot;1428&quot;&gt;일정 관련 정보&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1473&quot; data-start=&quot;1442&quot; data-ke-size=&quot;size16&quot;&gt;이처럼 구조를 명확히 제시하면 결과의 일관성이 높아진다.&lt;/p&gt;
&lt;p data-end=&quot;1587&quot; data-start=&quot;1475&quot; data-ke-size=&quot;size16&quot;&gt;셋째, 결과 통합&lt;br /&gt;여러 메일의 요약 결과를 하나의 텍스트로 합쳐 &amp;ldquo;오늘의 이메일 브리핑&amp;rdquo; 형식으로 재정리한다. 이후 SMTP를 통해 자신에게 다시 보내거나, 슬랙 Webhook으로 전송할 수 있다.&lt;/p&gt;
&lt;h2 data-end=&quot;1602&quot; data-start=&quot;1589&quot; data-ke-size=&quot;size26&quot;&gt;프롬프트 설계 전략&lt;/h2&gt;
&lt;p data-end=&quot;1682&quot; data-start=&quot;1604&quot; data-ke-size=&quot;size16&quot;&gt;이메일 요약에서 가장 중요한 것은 맥락 보존이다. 단순히 줄이기만 하면 핵심이 빠질 수 있다. 다음과 같은 지시를 추가하면 품질이 향상된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1795&quot; data-start=&quot;1684&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1708&quot; data-start=&quot;1684&quot;&gt;의사결정 관련 문장은 반드시 포함하라&lt;/li&gt;
&lt;li data-end=&quot;1731&quot; data-start=&quot;1709&quot;&gt;질문 형태 문장은 별도로 표시하라&lt;/li&gt;
&lt;li data-end=&quot;1766&quot; data-start=&quot;1732&quot;&gt;내가 직접 답변해야 하는 경우 &amp;lsquo;회신 필요&amp;rsquo;로 표시하라&lt;/li&gt;
&lt;li data-end=&quot;1795&quot; data-start=&quot;1767&quot;&gt;날짜가 포함된 문장은 일정 항목으로 정리하라&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1831&quot; data-start=&quot;1797&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 설계하면 단순 요약이 아니라 액션 중심 리포트가 된다.&lt;/p&gt;
&lt;h2 data-end=&quot;1846&quot; data-start=&quot;1833&quot; data-ke-size=&quot;size26&quot;&gt;비용과 성능 최적화&lt;/h2&gt;
&lt;p data-end=&quot;1985&quot; data-start=&quot;1848&quot; data-ke-size=&quot;size16&quot;&gt;메일 본문이 길 경우 토큰 사용량이 급격히 늘어날 수 있다. 이를 방지하기 위해 1차 요약 단계를 추가하는 방법이 있다. 예를 들어 본문을 2,000자 단위로 나누어 요약한 뒤, 다시 최종 요약을 수행하면 비용을 줄이면서 품질을 유지할 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;2111&quot; data-start=&quot;1987&quot; data-ke-size=&quot;size16&quot;&gt;또한 모든 메일을 매번 호출하지 않고, 중요 키워드가 포함된 메일만 요약하도록 조건을 두는 것도 효과적이다. 예를 들어 &amp;ldquo;결정&amp;rdquo;, &amp;ldquo;승인&amp;rdquo;, &amp;ldquo;회의&amp;rdquo;, &amp;ldquo;마감&amp;rdquo; 같은 단어가 포함된 메일만 AI 호출 대상으로 삼을 수 있다.&lt;/p&gt;
&lt;h2 data-end=&quot;2123&quot; data-start=&quot;2113&quot; data-ke-size=&quot;size26&quot;&gt;보안 고려사항&lt;/h2&gt;
&lt;p data-end=&quot;2178&quot; data-start=&quot;2125&quot; data-ke-size=&quot;size16&quot;&gt;업무 메일에는 민감 정보가 포함될 수 있다. 외부 API로 전달하기 전에 다음을 점검해야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2233&quot; data-start=&quot;2180&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2201&quot; data-start=&quot;2180&quot;&gt;고객 이름이나 계정 정보 마스킹&lt;/li&gt;
&lt;li data-end=&quot;2218&quot; data-start=&quot;2202&quot;&gt;내부 시스템 주소 제거&lt;/li&gt;
&lt;li data-end=&quot;2233&quot; data-start=&quot;2219&quot;&gt;첨부파일 내용 제외&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2303&quot; data-start=&quot;2235&quot; data-ke-size=&quot;size16&quot;&gt;가능하다면 사내 프록시를 통해 API 호출을 통제하거나, 별도의 로그 기록을 남겨 감사 추적이 가능하도록 하는 것이 좋다.&lt;/p&gt;
&lt;h2 data-end=&quot;2315&quot; data-start=&quot;2305&quot; data-ke-size=&quot;size26&quot;&gt;확장 아이디어&lt;/h2&gt;
&lt;p data-end=&quot;2438&quot; data-start=&quot;2317&quot; data-ke-size=&quot;size16&quot;&gt;이메일 요약 봇은 단순 개인 도구에서 팀 단위 시스템으로 확장할 수 있다. 예를 들어 팀 공용 메일함을 모니터링해 자동 분류 후 담당자에게 배정하거나, 특정 프로젝트 관련 메일만 모아 주간 리포트로 재구성할 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;2544&quot; data-start=&quot;2440&quot; data-ke-size=&quot;size16&quot;&gt;또한 요약 데이터를 구글 스프레드시트에 누적 저장하면, 일정 지연 패턴이나 반복 이슈를 분석하는 데 활용할 수 있다. 이렇게 되면 단순 요약 도구가 아니라 업무 인사이트 도구로 발전한다.&lt;/p&gt;
&lt;h2 data-end=&quot;2552&quot; data-start=&quot;2546&quot; data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-end=&quot;2688&quot; data-start=&quot;2554&quot; data-ke-size=&quot;size16&quot;&gt;Python과 OpenAI API를 활용한 이메일 요약 봇은 구현 난이도가 높지 않으면서 체감 효과가 큰 자동화 사례다. 매일 쌓이는 메일을 일일이 확인하는 대신, 핵심 요약과 액션 항목만 정리된 리포트를 받아보는 환경을 만들 수 있다.&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;2763&quot; data-start=&quot;2690&quot; data-ke-size=&quot;size16&quot;&gt;반복적인 메일 확인 시간을 줄이고 더 중요한 판단과 설계에 집중하고 싶다면, 이메일 요약 자동화는 충분히 시도해볼 만한 프로젝트다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>xxlayer</author>
      <guid isPermaLink="true">https://xxlayer.tistory.com/2</guid>
      <comments>https://xxlayer.tistory.com/2#entry2comment</comments>
      <pubDate>Thu, 19 Feb 2026 21:48:41 +0900</pubDate>
    </item>
    <item>
      <title>ChatGPT로 매일 아침 자동 업무 리포트 생성하는 방법 (실전 예제 포함)</title>
      <link>https://xxlayer.tistory.com/1</link>
      <description>&lt;p data-end=&quot;287&quot; data-start=&quot;47&quot; data-ke-size=&quot;size16&quot;&gt;매일 아침 전날 업무를 정리해 보고서를 작성하는 데 시간을 쓰고 있다면, 이미 자동화 대상이 생긴 것이다. 특히 IT 조직에서는 Jira 티켓, Git 커밋, 배포 기록, 장애 로그 등 여러 시스템에 데이터가 흩어져 있어 단순 정리만으로도 상당한 시간이 소요된다. 이 반복 업무를 ChatGPT와 같은 생성형 AI로 자동화하면 보고 품질을 일정하게 유지하면서도 시간을 크게 절약할 수 있다. 실제 구현 흐름을 기준으로 정리해본다.&lt;/p&gt;
&lt;hr data-end=&quot;292&quot; data-start=&quot;289&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;318&quot; data-start=&quot;294&quot; data-ke-size=&quot;size26&quot;&gt;왜 일일 업무 리포트 자동화가 필요한가&lt;/h2&gt;
&lt;p data-end=&quot;392&quot; data-start=&quot;320&quot; data-ke-size=&quot;size16&quot;&gt;업무 리포트는 단순 요약처럼 보이지만 매일 반복되면 생산성을 갉아먹는다. 사람이 직접 작성하면 다음과 같은 문제가 발생하기 쉽다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;473&quot; data-start=&quot;394&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;409&quot; data-start=&quot;394&quot;&gt;중요한 항목이 빠진다&lt;/li&gt;
&lt;li data-end=&quot;428&quot; data-start=&quot;410&quot;&gt;표현 방식이 매번 달라진다&lt;/li&gt;
&lt;li data-end=&quot;447&quot; data-start=&quot;429&quot;&gt;숫자 비교가 정확하지 않다&lt;/li&gt;
&lt;li data-end=&quot;473&quot; data-start=&quot;448&quot;&gt;보고 대상에 맞는 톤을 유지하기 어렵다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;566&quot; data-start=&quot;475&quot; data-ke-size=&quot;size16&quot;&gt;자동화의 목적은 사람을 배제하는 것이 아니라, 반복 정리 작업을 줄이고 판단과 의사결정에 집중하게 만드는 것이다. 생성형 AI는 특히 구조화와 요약에 강점이 있다.&lt;/p&gt;
&lt;hr data-end=&quot;571&quot; data-start=&quot;568&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;588&quot; data-start=&quot;573&quot; data-ke-size=&quot;size26&quot;&gt;전체 시스템 구조 설계&lt;/h2&gt;
&lt;p data-end=&quot;622&quot; data-start=&quot;590&quot; data-ke-size=&quot;size16&quot;&gt;자동 업무 리포트 시스템은 크게 세 단계로 나눌 수 있다.&lt;/p&gt;
&lt;h3 data-end=&quot;639&quot; data-start=&quot;624&quot; data-ke-size=&quot;size23&quot;&gt;1단계: 데이터 수집&lt;/h3&gt;
&lt;p data-end=&quot;753&quot; data-start=&quot;641&quot; data-ke-size=&quot;size16&quot;&gt;Jira API로 전날 완료된 티켓을 조회하고, Git 로그에서 커밋 내역을 가져온다. 필요하다면 배포 기록이나 장애 이력도 함께 수집한다. 핵심은 &amp;ldquo;전날 기준&amp;rdquo;으로 데이터를 정확히 필터링하는 것이다.&lt;/p&gt;
&lt;h3 data-end=&quot;770&quot; data-start=&quot;755&quot; data-ke-size=&quot;size23&quot;&gt;2단계: 데이터 가공&lt;/h3&gt;
&lt;p data-end=&quot;875&quot; data-start=&quot;772&quot; data-ke-size=&quot;size16&quot;&gt;수집한 데이터를 그대로 AI에 전달하지 않는다. 완료, 진행 중, 이슈 발생 항목으로 구분해 하나의 정리된 텍스트 블록으로 만든다. 이 단계에서 구조가 명확할수록 결과 품질이 좋아진다.&lt;/p&gt;
&lt;h3 data-end=&quot;896&quot; data-start=&quot;877&quot; data-ke-size=&quot;size23&quot;&gt;3단계: AI 호출 및 전송&lt;/h3&gt;
&lt;p data-end=&quot;974&quot; data-start=&quot;898&quot; data-ke-size=&quot;size16&quot;&gt;정리된 데이터를 프롬프트에 삽입해 OpenAI API를 호출한다. 생성된 리포트를 이메일, 슬랙, 노션 등 원하는 채널로 자동 전송한다.&lt;/p&gt;
&lt;p data-end=&quot;1034&quot; data-start=&quot;976&quot; data-ke-size=&quot;size16&quot;&gt;이 세 단계를 명확히 분리하면 유지보수도 쉬워진다. 데이터 소스가 바뀌어도 전체 구조는 그대로 유지된다.&lt;/p&gt;
&lt;hr data-end=&quot;1039&quot; data-start=&quot;1036&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1057&quot; data-start=&quot;1041&quot; data-ke-size=&quot;size26&quot;&gt;프롬프트 설계가 핵심이다&lt;/h2&gt;
&lt;p data-end=&quot;1121&quot; data-start=&quot;1059&quot; data-ke-size=&quot;size16&quot;&gt;자동 리포트 품질은 프롬프트 설계에서 결정된다. 단순히 &amp;ldquo;요약해줘&amp;rdquo;라고 요청하면 결과가 일관되지 않을 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;1147&quot; data-start=&quot;1123&quot; data-ke-size=&quot;size16&quot;&gt;다음과 같이 구체적으로 지시하는 것이 좋다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1242&quot; data-start=&quot;1149&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1175&quot; data-start=&quot;1149&quot;&gt;역할 지정: 너는 IT 프로젝트 매니저다&lt;/li&gt;
&lt;li data-end=&quot;1200&quot; data-start=&quot;1176&quot;&gt;독자 지정: 경영진에게 보고할 문서다&lt;/li&gt;
&lt;li data-end=&quot;1242&quot; data-start=&quot;1201&quot;&gt;형식 지정: 개요, 완료 사항, 진행 중 이슈, 리스크 순서로 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1316&quot; data-start=&quot;1244&quot; data-ke-size=&quot;size16&quot;&gt;이 세 가지를 명확히 설정하면 리포트 품질이 안정적으로 유지된다. 특히 독자를 명시하면 문체와 강조 포인트가 자연스럽게 조정된다.&lt;/p&gt;
&lt;hr data-end=&quot;1321&quot; data-start=&quot;1318&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1342&quot; data-start=&quot;1323&quot; data-ke-size=&quot;size26&quot;&gt;Python으로 구현하는 방법&lt;/h2&gt;
&lt;p data-end=&quot;1361&quot; data-start=&quot;1344&quot; data-ke-size=&quot;size16&quot;&gt;구현 흐름은 생각보다 단순하다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1476&quot; data-start=&quot;1363&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;1385&quot; data-start=&quot;1363&quot;&gt;Jira 또는 내부 API 호출&lt;/li&gt;
&lt;li data-end=&quot;1406&quot; data-start=&quot;1386&quot;&gt;결과 데이터를 문자열로 정리&lt;/li&gt;
&lt;li data-end=&quot;1428&quot; data-start=&quot;1407&quot;&gt;프롬프트 템플릿에 데이터 삽입&lt;/li&gt;
&lt;li data-end=&quot;1447&quot; data-start=&quot;1429&quot;&gt;OpenAI API 호출&lt;/li&gt;
&lt;li data-end=&quot;1476&quot; data-start=&quot;1448&quot;&gt;응답 텍스트를 파일 저장 또는 이메일 전송&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;1603&quot; data-start=&quot;1478&quot; data-ke-size=&quot;size16&quot;&gt;리눅스 환경이라면 cron을 이용해 매일 오전 8시 50분에 실행되도록 설정할 수 있다. 윈도우 환경에서는 작업 스케줄러를 활용하면 된다. 이 과정을 한 번 설정해두면 사람이 개입하지 않아도 매일 자동으로 리포트가 생성된다.&lt;/p&gt;
&lt;hr data-end=&quot;1608&quot; data-start=&quot;1605&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1630&quot; data-start=&quot;1610&quot; data-ke-size=&quot;size26&quot;&gt;실제 운영 시 고려해야 할 사항&lt;/h2&gt;
&lt;p data-end=&quot;1675&quot; data-start=&quot;1632&quot; data-ke-size=&quot;size16&quot;&gt;자동화는 구현보다 운영이 더 중요하다. 다음 세 가지는 반드시 점검해야 한다.&lt;/p&gt;
&lt;h3 data-end=&quot;1686&quot; data-start=&quot;1677&quot; data-ke-size=&quot;size23&quot;&gt;예외 처리&lt;/h3&gt;
&lt;p data-end=&quot;1757&quot; data-start=&quot;1688&quot; data-ke-size=&quot;size16&quot;&gt;API 호출 실패나 네트워크 오류가 발생했을 때 빈 보고서가 생성되지 않도록 재시도 로직과 오류 로그 기록을 추가해야 한다.&lt;/p&gt;
&lt;h3 data-end=&quot;1768&quot; data-start=&quot;1759&quot; data-ke-size=&quot;size23&quot;&gt;비용 관리&lt;/h3&gt;
&lt;p data-end=&quot;1841&quot; data-start=&quot;1770&quot; data-ke-size=&quot;size16&quot;&gt;데이터 양이 많으면 토큰 사용량이 증가한다. 1차 요약 단계를 추가해 프롬프트 길이를 줄이면 비용을 효율적으로 관리할 수 있다.&lt;/p&gt;
&lt;h3 data-end=&quot;1849&quot; data-start=&quot;1843&quot; data-ke-size=&quot;size23&quot;&gt;보안&lt;/h3&gt;
&lt;p data-end=&quot;1922&quot; data-start=&quot;1851&quot; data-ke-size=&quot;size16&quot;&gt;고객 정보나 민감 데이터는 마스킹 후 전달해야 한다. 내부 로그가 그대로 외부 API로 전송되지 않도록 필터링 단계가 필요하다.&lt;/p&gt;
&lt;hr data-end=&quot;1927&quot; data-start=&quot;1924&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1954&quot; data-start=&quot;1929&quot; data-ke-size=&quot;size26&quot;&gt;단순 요약을 넘어 분석 리포트로 확장하기&lt;/h2&gt;
&lt;p data-end=&quot;2006&quot; data-start=&quot;1956&quot; data-ke-size=&quot;size16&quot;&gt;일일 업무 리포트는 단순 요약에 그치지 않는다. 다음과 같은 분석 항목을 추가할 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2066&quot; data-start=&quot;2008&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2026&quot; data-start=&quot;2008&quot;&gt;전일 대비 처리 건수 증감&lt;/li&gt;
&lt;li data-end=&quot;2045&quot; data-start=&quot;2027&quot;&gt;반복 발생 이슈 유형 분류&lt;/li&gt;
&lt;li data-end=&quot;2066&quot; data-start=&quot;2046&quot;&gt;특정 프로젝트 진행 속도 분석&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2149&quot; data-start=&quot;2068&quot; data-ke-size=&quot;size16&quot;&gt;과거 데이터를 함께 제공하면 AI가 변화 추이를 자연스럽게 정리해준다. 이 단계까지 확장하면 단순 보고서를 넘어 의사결정 자료로 활용할 수 있다.&lt;/p&gt;
&lt;hr data-end=&quot;2154&quot; data-start=&quot;2151&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2179&quot; data-start=&quot;2156&quot; data-ke-size=&quot;size26&quot;&gt;업무 자동화의 출발점으로 적합한 이유&lt;/h2&gt;
&lt;p data-end=&quot;2211&quot; data-start=&quot;2181&quot; data-ke-size=&quot;size16&quot;&gt;일일 업무 리포트 자동화는 다음 조건을 모두 만족한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2272&quot; data-start=&quot;2213&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2222&quot; data-start=&quot;2213&quot;&gt;반복적이다&lt;/li&gt;
&lt;li data-end=&quot;2235&quot; data-start=&quot;2223&quot;&gt;데이터 기반이다&lt;/li&gt;
&lt;li data-end=&quot;2252&quot; data-start=&quot;2236&quot;&gt;구조가 정형화되어 있다&lt;/li&gt;
&lt;li data-end=&quot;2272&quot; data-start=&quot;2253&quot;&gt;결과를 바로 확인할 수 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2382&quot; data-start=&quot;2274&quot; data-ke-size=&quot;size16&quot;&gt;ChatGPT를 활용한 자동 리포트 시스템은 구현 난이도는 높지 않지만 체감 효과는 크다. 반복 정리 작업을 줄이고 보고 품질을 일정하게 유지하며, 필요하다면 분석 요소까지 추가할 수 있다.&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;2433&quot; data-start=&quot;2384&quot; data-ke-size=&quot;size16&quot;&gt;업무 자동화를 고민하고 있다면, 가장 먼저 시도해볼 만한 프로젝트로 충분히 가치가 있다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>xxlayer</author>
      <guid isPermaLink="true">https://xxlayer.tistory.com/1</guid>
      <comments>https://xxlayer.tistory.com/1#entry1comment</comments>
      <pubDate>Thu, 19 Feb 2026 21:41:17 +0900</pubDate>
    </item>
  </channel>
</rss>