<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>조현성의 블로그</title>
    <link>https://hsjo.tistory.com/</link>
    <description>AI와 코드로 서비스를 만들며, 일과 삶에서 얻은 생각을 정리하고, 직접 써보고 겪은 것들을 기록합니다.</description>
    <language>ko</language>
    <pubDate>Sat, 24 Oct 2026 08:33:18 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>조현성</managingEditor>
    <image>
      <title>조현성의 블로그</title>
      <url>https://tistory1.daumcdn.net/tistory/9060674/attach/b7f31e24a3424417807ecdf86b5de737</url>
      <link>https://hsjo.tistory.com</link>
    </image>
    <item>
      <title>율이네의 삼성의나라 에버랜드와 호암미술관 방문 스토리</title>
      <link>https://hsjo.tistory.com/20</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-10-18 오후 6.41.55.png&quot; data-origin-width=&quot;2798&quot; data-origin-height=&quot;1574&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AdHV1/dJMb999hABn/nw1jvriRnftH1BykuQgK8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AdHV1/dJMb999hABn/nw1jvriRnftH1BykuQgK8K/img.png&quot; data-alt=&quot;에버랜드 호랑이 우리나라&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AdHV1/dJMb999hABn/nw1jvriRnftH1BykuQgK8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAdHV1%2FdJMb999hABn%2Fnw1jvriRnftH1BykuQgK8K%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;2798&quot; height=&quot;1574&quot; data-filename=&quot;스크린샷 2026-10-18 오후 6.41.55.png&quot; data-origin-width=&quot;2798&quot; data-origin-height=&quot;1574&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;에버랜드 호랑이 우리나라&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가을이 왔다. 용인에 터를 잡고 사는 우리에게 가을은 멀리 가지 않아도 찾아오는 계절이다. 요즘 율이는 동물에 푹 빠져 있다. 그래서 이번 가을의 첫 목적지는 호랑이로 정했다. 율이의 별명이 '율랑이'인 데에는 다 이유가 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;율이는 아직 놀이기구를 탈 수 없다. 그래도 책장을 넘기며 손가락으로 짚던 동물들을 눈앞에서 보면 얼마나 좋아할까 싶었다. 그 상상 하나로 오후 반차를 냈고, 우리는 에버랜드로 향했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평일 금요일이니 한산할 거라는 기대는 주차장에서 깨졌다. 주차장은 이미 가득 차 있었다. 입구부터 소풍 온 초∙중∙고생들로 발 디딜 틈이 없었다. 가을 소풍 시즌이라는 것을 깜빡했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;iframe src=&quot;https://www.google.com/maps/embed?pb=!1m5!3m3!1m2!1s0x357b5403ce34d773%3A0x1fa18ab619238098!2z7JeQ67KE656c65Oc!5e0!3m2!1sko!2skr!4v1792317845088!5m2!1sko!2skr&quot; width=&quot;600&quot; height=&quot;450&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1mvZX/dJMcadcHEOS/n2nN3ArWv9z3Z7wYRW5Wdk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1mvZX/dJMcadcHEOS/n2nN3ArWv9z3Z7wYRW5Wdk/img.jpg&quot; data-origin-width=&quot;4284&quot; data-origin-height=&quot;5712&quot; data-is-animation=&quot;false&quot; data-filename=&quot;KakaoTalk_Photo_2026-10-18-18-51-35 002.jpeg&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1mvZX/dJMcadcHEOS/n2nN3ArWv9z3Z7wYRW5Wdk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1mvZX%2FdJMcadcHEOS%2Fn2nN3ArWv9z3Z7wYRW5Wdk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4284&quot; height=&quot;5712&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cueV2E/dJMcadjJqra/M0svEFwrxSnd9rCwnw9TS1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cueV2E/dJMcadjJqra/M0svEFwrxSnd9rCwnw9TS1/img.jpg&quot; data-origin-width=&quot;4284&quot; data-origin-height=&quot;5712&quot; data-is-animation=&quot;false&quot; data-filename=&quot;KakaoTalk_Photo_2026-10-18-18-51-34 001.jpeg&quot; style=&quot;width: 49.4186%;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cueV2E/dJMcadjJqra/M0svEFwrxSnd9rCwnw9TS1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcueV2E%2FdJMcadjJqra%2FM0svEFwrxSnd9rCwnw9TS1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4284&quot; height=&quot;5712&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;엄마의 힘&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학생들 사이를 헤치며 사파리부터 가기로 했다. 가는 길에 만나는 동물들을 하나씩 율이에게 보여 주었다. 율이가 동물을 가리킬 때마다 우리도 덩달아 신이 났다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔직히 이 구간의 주인공은 엄마였다. 월화수목금금금으로 달려온 직장 생활 탓에 아빠의 체력은 이미 바닥이었다. 유모차를 밀고, 율이를 안아 올리고, 다음 동물을 찾아 앞장선 사람은 엄마였다. 사진 속 뒷모습이 그날의 고마움을 다 말해 준다.&amp;nbsp;&lt;/p&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/mW0JW/dJMcahGghfa/ZMBJ1vENxGE6kleO4MSXe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mW0JW/dJMcahGghfa/ZMBJ1vENxGE6kleO4MSXe0/img.png&quot; data-origin-width=&quot;2250&quot; data-origin-height=&quot;3000&quot; data-is-animation=&quot;false&quot; data-filename=&quot;blob&quot; data-widthpercent=&quot;50&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mW0JW/dJMcahGghfa/ZMBJ1vENxGE6kleO4MSXe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmW0JW%2FdJMcahGghfa%2FZMBJ1vENxGE6kleO4MSXe0%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;2250&quot; height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AjtWw/dJMcaaAul7S/CpQIoTI8JBP40kqAGIQwBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AjtWw/dJMcaaAul7S/CpQIoTI8JBP40kqAGIQwBk/img.png&quot; data-origin-width=&quot;2250&quot; data-origin-height=&quot;3000&quot; data-is-animation=&quot;false&quot; data-filename=&quot;blob&quot; data-widthpercent=&quot;50&quot; style=&quot;width: 49.4186%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AjtWw/dJMcaaAul7S/CpQIoTI8JBP40kqAGIQwBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAjtWw%2FdJMcaaAul7S%2FCpQIoTI8JBP40kqAGIQwBk%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;2250&quot; height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;사파리 앞&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드디어 사파리 앞에 도착했다. 안내판에 적힌 대기 시간은 1시간 40분이었다. 우리는 말없이 눈을 마주쳤고, 동시에 포기를 선택했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;우리는 원래 인형 사러 온거야.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;맞아, 놀이기구 타러 온 게 아니지.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서로를 열심히 세뇌하며 발길을 돌렸다. 그래도 그냥 돌아가기는 아쉬웠다. 율이를 위해 회전목마를 한 바퀴 태워 주었다. 오르락내리락하는 말 위에서 율이는 마차를 차겠다고 했다가 말을 타겠다고 했다가 엄마아빠의 인내심의 끝을 보게 했다. 그 모습을 보고서야 우리는 미련 없이 집으로 철수했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_Photo_2026-10-18-19-06-14.jpeg&quot; data-origin-width=&quot;5712&quot; data-origin-height=&quot;4284&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kwKPt/dJMcahzyeAv/Hzafl2vTBfjaAywyp5Ohjk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kwKPt/dJMcahzyeAv/Hzafl2vTBfjaAywyp5Ohjk/img.jpg&quot; data-alt=&quot;딥슬립&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kwKPt/dJMcahzyeAv/Hzafl2vTBfjaAywyp5Ohjk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkwKPt%2FdJMcahzyeAv%2FHzafl2vTBfjaAywyp5Ohjk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;5712&quot; height=&quot;4284&quot; data-filename=&quot;KakaoTalk_Photo_2026-10-18-19-06-14.jpeg&quot; data-origin-width=&quot;5712&quot; data-origin-height=&quot;4284&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;딥슬립&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나름대로 신나게 놀았던 모양이다. 율이는 차에 타자마자 깊이 잠들었다. 오늘 하루가 율이에게 괜찮았다는 가장 확실한 대답이었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;율이를 재운 뒤 장인어른, 장모님과 한잔하며 내일은 어디서 가을을 느낄지 이야기했다. 이런저런 후보가 오간 끝에 결론은 호암미술관이었다. 어제는 에버랜드, 오늘은 호암미술관이다. 우리는 '삼성의 나라'를 이틀 연속 가기로 한 것이다.&amp;nbsp;&lt;/p&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/0lEOC/dJMcaa8oKSm/FHWl6oKC4RFKuTViglTiH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0lEOC/dJMcaa8oKSm/FHWl6oKC4RFKuTViglTiH1/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;2622&quot; data-filename=&quot;KakaoTalk_Photo_2026-10-18-19-09-49 001.png&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0lEOC/dJMcaa8oKSm/FHWl6oKC4RFKuTViglTiH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0lEOC%2FdJMcaa8oKSm%2FFHWl6oKC4RFKuTViglTiH1%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;1206&quot; height=&quot;2622&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MaoLT/dJMcaa8oKSl/5l53ilIAlnPRIftlp0sVg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MaoLT/dJMcaa8oKSl/5l53ilIAlnPRIftlp0sVg1/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;2622&quot; data-filename=&quot;KakaoTalk_Photo_2026-10-18-19-09-50 002.png&quot; style=&quot;width: 49.4186%;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MaoLT/dJMcaa8oKSl/5l53ilIAlnPRIftlp0sVg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMaoLT%2FdJMcaa8oKSl%2F5l53ilIAlnPRIftlp0sVg1%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;1206&quot; height=&quot;2622&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;호암미술관 예약&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고백하자면 나는 반신반의했다. 호암미술관은 처음이었다. 사대문 안 고궁이나 용산의 박물관에 비하면 관람료가 꽤 나가는 편이었다. 그만한 값을 하는 곳인지 감이 오지 않았다. 그래도 가을 추억 하나 남기는 셈 치고 바로 예약했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예약을 마치면 QR코드가 나온다. 이 QR이 있어야 주차장에 들어갈 수 있다. 현장에서 당황하지 않으려면 미리 예약하고 QR을 챙겨 두어야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 다녀온 뒤, 출발 전의 걱정과 의심은 모두 사라졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;iframe src=&quot;https://www.google.com/maps/embed?pb=!1m5!3m3!1m2!1s0x357b54015677da07%3A0xcff4a95464f52880!2z7Zi47JWU66-47Iig6rSA!5e0!3m2!1sko!2skr!4v1792318652759!5m2!1sko!2skr&quot; width=&quot;600&quot; height=&quot;450&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호암미술관은 이 계절, 이런 날씨에 꼭 와야 하는 곳이다. 율이는 지나가는 공작색도, 곳곳의 포토 스팟도 모두 좋아했다. 어른들은 우리와 함께 이 좋은 계절에 이 날씨에 할 수 있다는 것에 좋아 하셨다. 3대가 함께 걸어도 누구 하나 지루해하지 않았다. 우리는 이렇게 가을의 추억 한 페이지를 또 남기고 왔다.&lt;/p&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/lc1JI/dJMcackEzNk/ZXqEuJjwNtPb7FTGHEAJb1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lc1JI/dJMcackEzNk/ZXqEuJjwNtPb7FTGHEAJb1/img.jpg&quot; data-origin-width=&quot;4284&quot; data-origin-height=&quot;5712&quot; data-is-animation=&quot;false&quot; data-filename=&quot;KakaoTalk_Photo_2026-10-18-19-15-13 001.jpeg&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lc1JI/dJMcackEzNk/ZXqEuJjwNtPb7FTGHEAJb1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flc1JI%2FdJMcackEzNk%2FZXqEuJjwNtPb7FTGHEAJb1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4284&quot; height=&quot;5712&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ANcKo/dJMcackEzNj/fAzaMPOmJ9XEH26YYKzxNk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ANcKo/dJMcackEzNj/fAzaMPOmJ9XEH26YYKzxNk/img.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; data-is-animation=&quot;false&quot; data-filename=&quot;KakaoTalk_Photo_2026-10-18-19-15-14 004.jpeg&quot; style=&quot;width: 49.4186%;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ANcKo/dJMcackEzNj/fAzaMPOmJ9XEH26YYKzxNk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FANcKo%2FdJMcackEzNj%2FfAzaMPOmJ9XEH26YYKzxNk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3024&quot; height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eJwWDu/dJMcaiSP9sk/KgUQt6KTo9yKjmDKqf7W1K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eJwWDu/dJMcaiSP9sk/KgUQt6KTo9yKjmDKqf7W1K/img.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; data-is-animation=&quot;false&quot; data-filename=&quot;KakaoTalk_Photo_2026-10-18-19-15-13 002.jpeg&quot; style=&quot;width: 49.4186%; margin-right: 10px; margin-top: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eJwWDu/dJMcaiSP9sk/KgUQt6KTo9yKjmDKqf7W1K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeJwWDu%2FdJMcaiSP9sk%2FKgUQt6KTo9yKjmDKqf7W1K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3024&quot; height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b07aOK/dJMcaiSP9sq/kx2RszxkO3SOpapnwtLYpK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b07aOK/dJMcaiSP9sq/kx2RszxkO3SOpapnwtLYpK/img.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; data-is-animation=&quot;false&quot; data-filename=&quot;KakaoTalk_Photo_2026-10-18-19-15-14 003.jpeg&quot; style=&quot;width: 49.4186%; margin-top: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b07aOK/dJMcaiSP9sq/kx2RszxkO3SOpapnwtLYpK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb07aOK%2FdJMcaiSP9sq%2Fkx2RszxkO3SOpapnwtLYpK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3024&quot; height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;호암미술관&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>local</category>
      <category>가을나들이</category>
      <category>아이와가볼만한곳</category>
      <category>에버랜드</category>
      <category>에버랜드사파리</category>
      <category>용인가볼만한곳</category>
      <category>용인나들이</category>
      <category>육아일기</category>
      <category>주말나들이</category>
      <category>호암미술관</category>
      <category>호암미술관예약</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/20</guid>
      <comments>https://hsjo.tistory.com/20#entry20comment</comments>
      <pubDate>Sun, 18 Oct 2026 19:16:09 +0900</pubDate>
    </item>
    <item>
      <title>SIP가 연결하고 RTP가 나른다, 인터넷 전화는 두 길로 간다</title>
      <link>https://hsjo.tistory.com/19</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;아날로그 우편과 디지털 데이터의 밤.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VaHIm/dJMcabeQ5pw/dDnxuDnSEDzWQA2wPZD5NK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VaHIm/dJMcabeQ5pw/dDnxuDnSEDzWQA2wPZD5NK/img.png&quot; data-alt=&quot;약속은 한 길로, 목소리는 다른 길로 간다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VaHIm/dJMcabeQ5pw/dDnxuDnSEDzWQA2wPZD5NK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVaHIm%2FdJMcabeQ5pw%2FdDnxuDnSEDzWQA2wPZD5NK%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;1672&quot; height=&quot;941&quot; data-filename=&quot;아날로그 우편과 디지털 데이터의 밤.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;약속은 한 길로, 목소리는 다른 길로 간다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;통화 중에 상대의 목소리가 툭툭 끊긴다. 그런데 전화는 끊기지 않는다. 몇 초 뒤 목소리가 돌아오고 대화는 이어진다. 반대의 경우도 있다. 전화는 분명히 걸렸고 상대도 받았는데 아무 소리도 들리지 않는다. 컨택센터에서 일하며 두 번째 장애를 몇 번 봤다. 처음에는 &quot;전화가 안 된다&quot;는 한 가지 문제로 들렸다. 아니었다. 인터넷 전화는 한 통화가 두 길로 간다. 걸고 받고 끊는 약속은 SIP가 맡고, 목소리는 RTP가 나른다. 약속의 길은 멀쩡한데 소리의 길이 막히면 &quot;걸렸는데 안 들리는&quot; 전화가 된다. 이 글은 &lt;a href=&quot;https://hsjo.tistory.com/14&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;챗봇 용어 글&lt;/a&gt;의 전화 편이다. 전화가 인터넷을 지날 때 화살표 위를 오가는 것들의 이름을 한글과 영문으로 함께 적는다. SIP, UDP, RTP, 그리고 전화를 브라우저로 가져온 WebRTC와 웹소켓이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01_two-roads.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z229P/dJMcaiZmoPw/wFZARCOIQK5jJ6HAKJ7Ulk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z229P/dJMcaiZmoPw/wFZARCOIQK5jJ6HAKJ7Ulk/img.png&quot; data-alt=&quot;한 통화는 두 길로 간다, 약속의 길과 소리의 길은 프로토콜도 포트도 다르다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z229P/dJMcaiZmoPw/wFZARCOIQK5jJ6HAKJ7Ulk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz229P%2FdJMcaiZmoPw%2FwFZARCOIQK5jJ6HAKJ7Ulk%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;2400&quot; height=&quot;1560&quot; data-filename=&quot;01_two-roads.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;한 통화는 두 길로 간다, 약속의 길과 소리의 길은 프로토콜도 포트도 다르다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전화가 대표번호에서 상담사까지 가는 여섯 단계는 &lt;a href=&quot;https://hsjo.tistory.com/5&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;IPCC 글&lt;/a&gt;에 적었다. 그 글에서 SIP와 RTP를 한 번씩 소개했지만 용어마다 자리를 잡아 주지는 않았다. 이 글은 그 자리를 잡는다. 어느 솔루션의 화면을 열어도, 어느 통신사의 제안서를 읽어도 나오는 말들이고, 뜻을 알면 장애 보고서의 한 줄이 읽힌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;한 통화는 두 길로 간다&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터넷 전화는 약속과 소리를 따로 보낸다. 약속의 길은 &quot;너에게 전화를 걸겠다, 받겠다, 끊겠다&quot;는 신호가 오가는 길이고, 소리의 길은 목소리를 잘게 썬 조각이 흐르는 길이다. 두 길은 쓰는 규칙이 다르고 지나는 문(포트)도 다르다. 그래서 한 길만 막히는 일이 생기고, 그것이 &quot;걸렸는데 안 들리는&quot; 전화다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 한 길로 보내지 않는가. 웹 페이지를 받을 때 쓰는 TCP는 조각이 빠지면 다시 보내 달라고 해서 반드시 채운다. 정확하지만 기다린다. 목소리는 기다릴 수 없다. 조금 전의 한 음절을 다시 받아 끼워 넣느니 버리고 다음 소리를 내는 편이 낫다. 반대로 &quot;전화를 끊겠다&quot;는 약속은 한 글자도 빠지면 안 된다. 그래서 소리는 빠르지만 책임지지 않는 길로, 약속은 느려도 확실한 길로 보낸다. 이 구분은 처음부터 설계에 있었다. 소리의 길이 쓰는 UDP의 표준 문서는 첫 장에서 &quot;순서와 신뢰가 필요한 데이터는 TCP를 쓰라&quot;고 적어 두었다. 출처는 &lt;a href=&quot;https://www.rfc-editor.org/info/rfc768/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;RFC 768&lt;/a&gt;(1980, 2026-10-18 조회)이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;이름이 생긴 순서&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02_timeline.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PjX0l/dJMcadKBq2R/Yf29bvol403Z0SAlDMRkoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PjX0l/dJMcadKBq2R/Yf29bvol403Z0SAlDMRkoK/img.png&quot; data-alt=&quot;전화망에서 인터넷으로, 다시 브라우저로, 표준 문서가 나온 순서&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PjX0l/dJMcadKBq2R/Yf29bvol403Z0SAlDMRkoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPjX0l%2FdJMcadKBq2R%2FYf29bvol403Z0SAlDMRkoK%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;2400&quot; height=&quot;1400&quot; data-filename=&quot;02_timeline.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1400&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;전화망에서 인터넷으로, 다시 브라우저로, 표준 문서가 나온 순서&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글의 용어들은 한꺼번에 생기지 않았다. 표준 문서가 나온 순서대로 놓으면 전화가 어디서 어디로 옮겨 왔는지 보인다. 1980년에 UDP가 나왔다. 1996년에 소리 조각을 나르는 RTP의 첫 판이 나왔고 2003년에 지금 판(&lt;a href=&quot;http://rfc-editor.org/rfc/rfc3550&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;RFC 3550&lt;/a&gt;)으로 갱신됐다. 2002년에 통화를 걸고 끊는 SIP(&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc3261&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;RFC 3261&lt;/a&gt;)가 지금 모양으로 정리됐다. 여기까지가 전화를 전화망에서 인터넷으로 옮긴 표준이다. 2011년에 브라우저와 서버가 양방향으로 말하는 웹소켓(&lt;a href=&quot;http://rfc-editor.org/rfc/rfc6455&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;RFC 6455&lt;/a&gt;)이 나왔고, 2014년에 SIP를 웹소켓 위에 싣는 방법(&lt;a href=&quot;https://www.rfc-editor.org/info/rfc7118/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;RFC 7118&lt;/a&gt;)이 나왔고, 2021년에 브라우저 실시간 통신의 전체 그림을 묶은 WebRTC 개요(&lt;a href=&quot;https://www.rfc-editor.org/info/rfc8825/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;RFC 8825&lt;/a&gt;)가 나왔다. 이쪽은 전화를 브라우저로 옮긴 표준이다. 전부 2026-10-18에 rfc-editor.org에서 조회했다. 두 묶음 사이에 십 년 남짓이 있고, 컨택센터의 상담사 자리에서 전화기가 사라지기 시작한 때가 그 사이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;약속의 길&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03_signal-road.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1960&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgMHD3/dJMcahl8rRh/q7k9VhXF2B9ysKBrPxj7l1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgMHD3/dJMcahl8rRh/q7k9VhXF2B9ysKBrPxj7l1/img.png&quot; data-alt=&quot;약속의 길, 초대에서 종료까지 SIP 메시지가 오가고 초대 안의 쪽지가 소리의 길을 정한다, 같은 자리에 선 고유 규칙 SCCP&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgMHD3/dJMcahl8rRh/q7k9VhXF2B9ysKBrPxj7l1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgMHD3%2FdJMcahl8rRh%2Fq7k9VhXF2B9ysKBrPxj7l1%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;2400&quot; height=&quot;1960&quot; data-filename=&quot;03_signal-road.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1960&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;약속의 길, 초대에서 종료까지 SIP 메시지가 오가고 초대 안의 쪽지가 소리의 길을 정한다, 같은 자리에 선 고유 규칙 SCCP&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;SIP(세션 개시 프로토콜, Session Initiation Protocol).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 통화 한 건, 표준의 말로는 세션 하나를 만들고 바꾸고 끝내는 규칙이다. 거는 쪽이 초대(INVITE)를 보내고, 받는 쪽이 응답(200 OK)을 돌려주고, 거는 쪽이 확인(ACK)을 보내면 통화가 선다. 끊을 때는 종료(BYE)다. 표준 문서는 이것을 &quot;참가자 한 명 이상과 세션을 만들고, 고치고, 끝내는 응용 계층 신호 프로토콜&quot;이라고 정의한다(&lt;a href=&quot;https://www.rfc-editor.org/info/rfc3261/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;RFC 3261&lt;/a&gt; 초록). 전화번호는 sip:번호@도메인 꼴의 주소가 된다. 교환기와 CTI가 &quot;어느 번호로 전화가 들어왔다&quot;를 아는 것은 이 메시지를 읽기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;등록과 프록시(REGISTER, proxy).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 전화기는 켜질 때 &quot;나는 지금 이 주소에 있다&quot;를 서버에 올린다. 이것이 등록이다. 걸려 온 초대를 상대의 현재 주소로 보내 주는 서버가 프록시다. 상담사가 자리를 옮겨도 같은 내선으로 전화를 받을 수 있는 이유가 이 둘이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;SDP(세션 기술, Session Description Protocol).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 초대 안에 실려 가는 쪽지다. &quot;내 소리는 이 주소의 이 포트로 보내 달라, 나는 이런 코덱을 쓸 수 있다&quot;가 적혀 있다. 받는 쪽도 응답에 같은 쪽지를 실어 보낸다. 약속의 길이 소리의 길의 주소를 정해 주는 자리가 여기다. 두 쪽지에 겹치는 코덱이 없으면 통화는 섰는데 소리는 나지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;SCCP(스키니, Skinny Client Control Protocol).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; SIP와 같은 자리에 서는 또 하나의 약속 규칙이다. 다만 공개 표준이 아니라 한 교환기 제조사가 자기 전화기와 자기 교환기 사이에만 쓰려고 만든 고유 규칙이고, 이름 그대로 &quot;얇은(skinny)&quot; 단말을 전제한다. 전화기는 판단하지 않는다. 버튼이 눌렸다는 사실만 교환기에 보내고, 화면에 무엇을 띄울지, 어느 램프를 켤지, 어떤 소리를 울릴지는 전부 교환기가 전화기에게 지시한다. SIP 전화기가 스스로 초대를 만들고 응답하는 것과 반대다. 그래서 그 제조사의 교환기를 쓰는 센터에서는 상담사 책상의 전화기가 SIP가 아니라 스키니로 말하는 경우가 많고, 교환기 연동을 시작할 때 첫 질문이 &quot;전화기는 SIP인가 스키니인가&quot;가 된다. 통신사나 다른 장비 같은 바깥과는 교환기가 SIP로 통역한다. 소리의 길은 똑같이 RTP라서, 뒤에 나올 소리 사본 뜨기는 신호가 무엇이든 된다. 새로 들이는 장비는 SIP로 가는 흐름이지만 현장의 전화기는 수명이 길어 두 말이 한 센터에 섞여 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;소리의 길&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04_media-road.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgMrAT/dJMcabTBO0y/70y71zj6MBRtl7MKTjHtH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgMrAT/dJMcabTBO0y/70y71zj6MBRtl7MKTjHtH1/img.png&quot; data-alt=&quot;소리의 길, 목소리가 조각이 되어 번호와 시각 도장을 달고 UDP로 가고 지터 버퍼에서 다시 줄을 선다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgMrAT/dJMcabTBO0y/70y71zj6MBRtl7MKTjHtH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgMrAT%2FdJMcabTBO0y%2F70y71zj6MBRtl7MKTjHtH1%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;2400&quot; height=&quot;1640&quot; data-filename=&quot;04_media-road.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;소리의 길, 목소리가 조각이 되어 번호와 시각 도장을 달고 UDP로 가고 지터 버퍼에서 다시 줄을 선다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;UDP(사용자 데이터그램 프로토콜, User Datagram Protocol).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 조각을 던지기만 하는 전송 규칙이다. 받았는지 확인하지 않고, 빠져도 다시 보내지 않고, 순서도 맞춰 주지 않는다. 그 대신 빠르다. 소리의 길이 UDP를 고른 이유는 앞 절에 적었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;RTP(실시간 전송 프로토콜, Real-time Transport Protocol).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 목소리를 짧은 조각으로 잘라 조각마다 순서 번호와 시각 도장을 붙여 보내는 규칙이다. 받는 쪽은 순서 번호로 빠진 조각과 뒤바뀐 조각을 알아채고, 시각 도장으로 조각을 제자리에 놓는다. 표준은 순서 번호가 조각마다 하나씩 늘고 받는 쪽이 그것으로 손실을 알아낸다고 적는다(&lt;a href=&quot;https://www.rfc-editor.org/info/rfc3550/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;RFC 3550&lt;/a&gt;). 빠진 조각은 돌아오지 않는다. 통화 중에 한 음절이 뚝 빠지는 것은 조각 하나가 길에서 사라졌고 아무도 다시 보내지 않았기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;RTCP(RTP 제어 프로토콜, RTP Control Protocol).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; RTP 옆을 따라다니며 소리는 나르지 않고 보고만 한다. 조각이 몇 개 빠졌는지, 도착 간격이 얼마나 흔들렸는지를 주기적으로 상대에게 보낸다. 통화 품질 장표의 원재료다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;코덱(부호기, codec).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 목소리를 숫자로 바꾸고 다시 소리로 되돌리는 약속이다. 전화망 품질의 G.711은 초당 8천 번 소리를 재서 한 바이트로 적는 방식이고 mu-law와 a-law 두 갈래가 있다. 인터넷용으로는 Opus(&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc6716&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;RFC 6716&lt;/a&gt;)가 널리 쓰인다. 양쪽이 같은 코덱을 골라야 소리가 나고, 고르는 자리는 앞 절의 SDP 쪽지다. 내가 만든 봇 시스템이 아니라 현장의 보이스봇 쪽 이야기를 하나 적으면, 봇이 만든 답을 음성 합성 서버가 전화 코덱(8kHz의 mu-law 또는 a-law)으로 돌려주고 게이트웨이가 그대로 전화에 실어 내보낸다. 코덱이 맞아야 변환 없이 바로 나간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;소리가 상하는 세 가지&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;05_three-impairments.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ltsPC/dJMb99OUcai/TTaKKZJAbHcKHNKSrKTxMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ltsPC/dJMb99OUcai/TTaKKZJAbHcKHNKSrKTxMk/img.png&quot; data-alt=&quot;지연과 지터와 손실, 지터 버퍼가 흔들림을 고르게 펴고 150ms가 자연스러움의 경계다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ltsPC/dJMb99OUcai/TTaKKZJAbHcKHNKSrKTxMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FltsPC%2FdJMb99OUcai%2FTTaKKZJAbHcKHNKSrKTxMk%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;2400&quot; height=&quot;1520&quot; data-filename=&quot;05_three-impairments.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;지연과 지터와 손실, 지터 버퍼가 흔들림을 고르게 펴고 150ms가 자연스러움의 경계다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소리의 길에서 품질을 말할 때 쓰는 낱말은 셋이다.&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%; text-align: center;&quot;&gt;&lt;b&gt;낱말&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; text-align: center;&quot;&gt;&lt;b&gt;뜻&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; text-align: center;&quot;&gt;&lt;b&gt;귀에 들리는 증상&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; text-align: center;&quot;&gt;&lt;b&gt;손잡이&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;지연(delay)&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;입에서 귀까지 걸리는 시간&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;말이 겹치고 서로 기다린다&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;경로와 장비 수를 줄인다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;지터(jitter)&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;조각 도착 간격의 흔들림&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;목소리가 떨리거나 늘어진다&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;지터 버퍼로 고르게 편다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;손실(loss)&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;조각이 사라진 비율&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;음절이 뚝 빠진다&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;망을 고치거나 손실 은닉을 켠다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;지터 버퍼(jitter buffer).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 받는 쪽이 조각을 바로 틀지 않고 잠깐 모았다가 고른 간격으로 재생하는 작은 창고다. 창고를 키우면 떨림은 줄지만 지연이 는다. 전화 장비의 설정 화면에 늘 있는 손잡이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;얼마나 늦으면 불편한가. 국제 표준 권고 하나가 기준을 준다. 입에서 귀까지 한 방향 지연이 150ms 아래면 대부분의 통화가 자연스럽고, 망 설계에서는 400ms를 넘기지 말라고 적는다. 출처는 ITU-T 권고 &lt;a href=&quot;https://www.itu.int/rec/T-REC-G.114&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;G.114&lt;/a&gt;(2003년 판, 2026-10-18 조회)다. 150ms에는 코덱이 소리를 바꾸는 시간과 지터 버퍼에서 기다리는 시간이 다 들어간다. 그래서 창고를 무턱대고 키울 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;브라우저로 온 전화&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;06_browser.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dsEEQ2/dJMcagUXOFq/1w3UQmSDGXuWT3zji3pdDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dsEEQ2/dJMcagUXOFq/1w3UQmSDGXuWT3zji3pdDK/img.png&quot; data-alt=&quot;브라우저로 온 전화, 웹소켓이 약속을 나르고 ICE가 길을 찾고 SRTP가 소리를 잠근다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dsEEQ2/dJMcagUXOFq/1w3UQmSDGXuWT3zji3pdDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdsEEQ2%2FdJMcagUXOFq%2F1w3UQmSDGXuWT3zji3pdDK%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;2400&quot; height=&quot;1640&quot; data-filename=&quot;06_browser.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;브라우저로 온 전화, 웹소켓이 약속을 나르고 ICE가 길을 찾고 SRTP가 소리를 잠근다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;웹소켓(WebSocket).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 브라우저와 서버가 한 번 악수한 뒤 양쪽에서 아무 때나 메시지를 보낼 수 있는 통로다. TCP 위에 있고, 웹 페이지처럼 매번 요청하고 답을 기다리지 않아도 된다. 표준은 &quot;열기 악수 뒤에 메시지 틀을 주고받는, TCP 위의 양방향 통신&quot;으로 정의한다(&lt;a href=&quot;http://rfc-editor.org/rfc/rfc6455&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;RFC 6455&lt;/a&gt; 초록). 전화에서 웹소켓이 나르는 것은 소리가 아니라 약속이다. 브라우저는 SIP를 직접 보낼 수 없어서 SIP 메시지를 웹소켓 메시지 안에 넣어 보내는데, 그 방법을 정한 표준이 &lt;a href=&quot;http://rfc-editor.org/rfc/rfc7118&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;RFC 7118&lt;/a&gt;이다. 그러니까 브라우저 전화의 약속의 길은 &quot;웹소켓 위의 SIP&quot;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;WebRTC(웹 실시간 통신, Web Real-Time Communication).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 브라우저가 플러그인 없이 마이크와 스피커를 쓰고 상대와 직접 소리를 주고받게 하는 표준 묶음이다. 소리의 길은 그대로다. 여전히 UDP 위의 RTP다. 다만 세 가지가 더 붙는다. 첫째, 암호화가 기본이다. 소리는 SRTP(안전한 RTP, Secure RTP)로 잠그고 열쇠는 DTLS로 교환한다. 브라우저는 잠그지 않은 통화를 허용하지 않는다. 둘째, 길 찾기가 붙는다. 집이나 사무실의 브라우저는 공유기(NAT) 뒤에 있어서 상대가 바로 찾아올 수 없다. ICE(상호 연결 수립, Interactive Connectivity Establishment)라는 절차가 후보 길을 모아 되는 길을 고르는데, STUN 서버에 물어 자기 바깥 주소를 알아내고 그래도 안 되면 TURN 서버를 중계로 쓴다. 셋째, 약속의 길은 표준이 정하지 않았다. WebRTC 개요(&lt;a href=&quot;http://rfc-editor.org/rfc/rfc8825&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;RFC 8825&lt;/a&gt;)는 세션을 여는 신호가 보통 TLS로 보호된 웹 기술 위에서 응용별 방식으로 오간다고만 적는다. 컨택센터는 그 빈자리에 앞 문단의 웹소켓 위 SIP를 넣거나 솔루션 고유의 신호 방식을 넣는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 묶음이 있어서 상담사 자리에 전화기가 없어도 되고, 고객이 전화번호 없이 웹 페이지의 상담 버튼으로 통화할 수 있다. &lt;a href=&quot;https://hsjo.tistory.com/5&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;IPCC 글&lt;/a&gt;의 마지막 절이 그 장면이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;실제로 본 세 장면&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;07_three-scenes.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HOb1F/dJMcacrA8i3/9RS1O1Vac0NiAxRyPssqjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HOb1F/dJMcacrA8i3/9RS1O1Vac0NiAxRyPssqjK/img.png&quot; data-alt=&quot;전화망 없이 앱으로 시연하고, 스위치에서 소리 사본을 뜨고, 종료 사유 코드로 누가 끊었는지 안다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HOb1F/dJMcacrA8i3/9RS1O1Vac0NiAxRyPssqjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHOb1F%2FdJMcacrA8i3%2F9RS1O1Vac0NiAxRyPssqjK%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;2400&quot; height=&quot;1720&quot; data-filename=&quot;07_three-scenes.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;전화망 없이 앱으로 시연하고, 스위치에서 소리 사본을 뜨고, 종료 사유 코드로 누가 끊었는지 안다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;&lt;u&gt;첫째&lt;/u&gt; 장면은 전화망 없이 보이스봇을 보여 주던 일이다.&lt;/b&gt;&lt;/span&gt; 센터의 전화 장비와 연결하지 않고 봇만 시연하려니 전화 대신 소리를 보낼 길이 필요했고, WebRTC로 마이크 소리를 보내는 스마트폰 앱을 따로 만들었다. 흐름은 토큰을 받고, 미디어 서버에 붙고, 마이크를 켜고, 대화 시작을 알리고, 음성 인식 결과를 받고, 봇의 답을 받는 순서였다. 전화기 마이크가 아니라 스마트폰 마이크라서 주변 소음이 그대로 들어왔고, 짧은 &quot;네&quot;가 소음에 묻히는 일이 있었다. 소리의 길이 바뀌면 소리의 성질도 바뀐다는 것을 그때 배웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;&lt;u&gt;둘째 장면은&lt;/u&gt; 상담사의 통화를 실시간 음성 인식에 넣는 일이다.&lt;/b&gt;&lt;/span&gt; 가장 흔한 방법은 전화기가 꽂힌 스위치의 한 포트를 미러 포트로 지정해 RTP 조각의 사본을 다른 서버로 흘려보내고, 그 서버의 게이트웨이가 조각을 걸러 소리를 복원해 인식기에 넘기는 것이다. RTP가 &quot;복사할 수 있는 조각&quot;이라서 가능한 구성이고, 전화기의 약속의 길이 SIP든 스키니든 소리의 길은 같은 RTP라서 신호 규칙과 상관없이 된다. 대신 그 서버는 미러 포트가 물리적으로 닿는 자리에만 둘 수 있어서, 서버를 어디에 둘지가 인식기가 아니라 네트워크 담당의 결정이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;셋째 장면은 민원이다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; &quot;상담사가 먼저 끊었다&quot;는 민원이 들어오면 누가 끊었는지를 증명해야 한다. 답은 약속의 길에 있다. 종료(BYE)를 누가 보냈는지가 교환기의 통화 기록에 사유 코드로 남고, 그 코드는 공개 표준 &lt;a href=&quot;https://www.itu.int/rec/T-REC-Q.850&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Q.850&lt;/a&gt;(2026-10-18 조회)의 사유 코드를 따른다. 내가 본 센터의 기록에서는 상담사가 끊은 호와 고객이 끊은 호가 다른 숫자로 남았고, 정상 종료를 뜻하는 코드는 16이었다. 민원 대응은 그 칸을 여는 데서 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;걸렸는데 안 들린다, 그리고 열쇠 하나에 접속 하나&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;08_two-failures.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bf2J2I/dJMcahMZNI9/g3Vtv8EokZlpzPbEaswQDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bf2J2I/dJMcahMZNI9/g3Vtv8EokZlpzPbEaswQDk/img.png&quot; data-alt=&quot;실패 둘과 고치는 법, 한쪽만 들리는 통화와 웹소켓 열쇠 하나로 여러 접속&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bf2J2I/dJMcahMZNI9/g3Vtv8EokZlpzPbEaswQDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbf2J2I%2FdJMcahMZNI9%2Fg3Vtv8EokZlpzPbEaswQDk%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;2400&quot; height=&quot;1440&quot; data-filename=&quot;08_two-failures.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실패 둘과 고치는 법, 한쪽만 들리는 통화와 웹소켓 열쇠 하나로 여러 접속&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째 실패는 도입의 장애다. 전화는 걸리는데 소리가 한쪽만 들리거나 아예 안 들린다. 약속의 길은 넘어왔는데 소리의 길이 방화벽이나 NAT에 막힌 것이다. 방화벽은 전화를 모른다. SIP 쪽지에 적힌 포트로 RTP가 들어오리라는 것을 모르니 막는다. 고치는 법은 경계에 전화를 아는 장비를 두는 것이다. 센터 쪽에서는 SBC가 그 일을 하고(&lt;a href=&quot;https://hsjo.tistory.com/5&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;IPCC 글&lt;/a&gt;의 2절), 브라우저 쪽에서는 ICE가 STUN으로 길을 찾다가 안 되면 TURN 중계로 돌아간다. 장애 보고서에 &quot;신호는 됐는데 미디어가 안 온다&quot;라고 적혀 있으면 이 경우다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째 실패는 웹소켓 쪽이다. 세션 열쇠 하나로 여러 접속을 허용하면 같은 열쇠를 가진 다른 창이 대화를 엿듣거나 접속을 쏟아부어 서버를 눌러앉힐 수 있다. 고치는 법은 열쇠 하나에 활성 접속 하나다. 다만 여기에 함정이 있었다. 재접속을 아예 막아 버리면 모바일에서 앱이 뒤로 갔다 오거나 와이파이와 LTE 사이를 오갈 때 끊긴 통로를 다시 잇지 못해 정상 사용자만 손해를 본다. 그래서 규칙은 &quot;열쇠를 발급한 적이 있는지 확인하고, 세션당 활성 접속은 하나만 두되, 끊기면 다시 잇는 것은 허용한다&quot;가 됐다. 웹소켓은 전화의 소리가 아니라 약속을 나르는 통로이지만, 통로가 끊기고 다시 붙는 성질은 전화의 세션과 똑같이 설계해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;용어를 자리에 놓고 나면 장애 보고서가 읽힌다. &quot;신호는 됐는데 미디어가 안 온다&quot;는 약속의 길은 살고 소리의 길이 막혔다는 말이고, &quot;지터가 크다&quot;는 조각의 도착 간격이 흔들려 창고를 키우거나 망을 봐야 한다는 말이고, &amp;ldquo;BYE를 누가 보냈나&amp;rdquo;는 민원의 증거가 어디 있는지 가리키는 말이고, &quot;전화기가 스키니다&quot;는 교환기 바깥에서는 SIP만 보이고 안쪽 전화기와는 다른 말을 쓴다는 말이다. SIP가 연결하고 RTP가 나른다. 브라우저로 오면서 웹소켓이 약속을 싣고 ICE가 길을 찾고 SRTP가 소리를 잠갔지만, 두 길이라는 뼈대는 1980년의 UDP 문서가 그어 둔 선 그대로다. 다음 글은 여기까지 쌓은 시스템 전체를 어떻게 한눈에 보는가다. 통합 로그와 모니터링을 어떻게 짜고, 이중화 시험과 성능 시험을 어떤 순서로 하는지를 적는다.&lt;/p&gt;</description>
      <category>tech</category>
      <category>AICC</category>
      <category>RTP</category>
      <category>sccp</category>
      <category>SIP</category>
      <category>VoIP</category>
      <category>webrtc</category>
      <category>websocket</category>
      <category>웹소켓</category>
      <category>인공지능 컨택센터</category>
      <category>인터넷 전화</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/19</guid>
      <comments>https://hsjo.tistory.com/19#entry19comment</comments>
      <pubDate>Sun, 18 Oct 2026 17:51:50 +0900</pubDate>
    </item>
    <item>
      <title>대화를 이어 가는 것은 기억이 아니라 기록이다, 컨텍스트</title>
      <link>https://hsjo.tistory.com/18</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;인간과 로봇의 기록 공유 작업흐름.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ezb4G0/dJMcadKBlwX/XOg9kKSBsAzmRt7h563Z0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ezb4G0/dJMcadKBlwX/XOg9kKSBsAzmRt7h563Z0K/img.png&quot; data-alt=&quot;상담사 앞에 떠 있는 것은 기억이 아니라 기록이다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ezb4G0/dJMcadKBlwX/XOg9kKSBsAzmRt7h563Z0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fezb4G0%2FdJMcadKBlwX%2FXOg9kKSBsAzmRt7h563Z0K%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;1672&quot; height=&quot;941&quot; data-filename=&quot;인간과 로봇의 기록 공유 작업흐름.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;상담사 앞에 떠 있는 것은 기억이 아니라 기록이다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난주에 산 셔츠가 사진과 다른 색으로 왔다고 하자. 고객센터에 전화를 걸어 주문번호를 찾으려고 영수증을 뒤지는데, 상담사가 먼저 말한다. &quot;그제 받으신 파란색 린넨 셔츠 말씀이시죠. 출고 기록에는 회색이 나간 것으로 찍혀 있네요.&quot; &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;고객은 아직 아무것도 설명하지 않았다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 상담사가 기억력이 좋아서가 아니다. 전화가 연결되는 순간 모니터에 주문일, 수령일, 주문한 색상과 종류, 그리고 창고에서 실제로 나간 색상이 떠 있었기 때문이다. 상담사는 기억하지 않는다. 기록을 본다. 봇도 똑같다. 내가 만든 봇 시스템에서 대화를 이어 가는 것은 모델의 기억이 아니라 봇이 들고 있는 기록이고, 그 기록의 이름이 컨텍스트(문맥, context)다. 이 글은 그 기록에 무엇이 들어 있고, 어디에 두고, 언제 지우고, 거대 언어 모델에게 어떻게 건네는지를 적는다. 장면과 문장은 예시다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01_record-not-memory.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yFk7g/dJMcah0v7ww/8QiyTrYDZD8weiYk10o55k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yFk7g/dJMcah0v7ww/8QiyTrYDZD8weiYk10o55k/img.png&quot; data-alt=&quot;상담사 모니터의 기록과 봇이 들고 있는 기록, 둘 다 기억이 아니라 기록이다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yFk7g/dJMcah0v7ww/8QiyTrYDZD8weiYk10o55k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyFk7g%2FdJMcah0v7ww%2F8QiyTrYDZD8weiYk10o55k%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;2400&quot; height=&quot;1560&quot; data-filename=&quot;01_record-not-memory.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;상담사 모니터의 기록과 봇이 들고 있는 기록, 둘 다 기억이 아니라 기록이다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hsjo.tistory.com/17&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;지난 글&lt;/a&gt;은 벡터가 &quot;무엇을 묻는가&quot;를 찾아 주는 이야기였고, 끝에 컨텍스트는 &quot;지금 어디까지 왔는가&quot;를 기억한다고 썼다. &lt;a href=&quot;https://hsjo.tistory.com/14&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;용어 글&lt;/a&gt;에서는 컨텍스트를 &quot;대화가 어디까지 왔는지를 봇이 들고 있는 상태&quot;라고 한 줄로 적었다. 이 글은 그 한 줄을 연다. 한 가지를 먼저 가른다. 앞의 두 글에서 &quot;기록&quot;은 점수 원값을 통계용으로 남기는 일이었다. 이 글의 기록은 다르다. 대화를 이어 가기 위해 봇이 지금 손에 들고 있는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;컨텍스트는 무엇인가&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨텍스트는 봇이 대화 한 판에 대해 들고 있는 기록이다. 네 가지가 들어 있다. 지금 대화가 시나리오의 어느 칸에 서 있는지, 지금까지 채운 값이 무엇인지, 바깥 시스템에서 조회해 온 것이 무엇인지, 그리고 다음에 어떤 입력을 기다리는지다. &quot;어떤 색으로 바꿔 드릴까요&quot;라는 질문 뒤에 &quot;파란색이요&quot;가 오면 그것이 교환할 색상이라는 것을 아는 이유는 봇이 &quot;지금 교환 색상을 묻는 칸에 서 있고 색상 하나를 기다린다&quot;는 기록을 들고 있기 때문이다. 기록이 없으면 &quot;파란색이요&quot;는 아무 뜻도 없는 글자다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옷 장면으로 돌아가면 기록은 두 종류다. 대화 밖에서 가져온 기록과 대화 안에서 쌓인 기록이다. 주문일, 주문한 색상, 출고된 색상은 고객이 말한 것이 아니라 봇이 전화번호나 주문번호로 주문 시스템을 조회해서 가져온 것이다. &quot;교환할게요&quot;라는 선택과 &quot;사이즈는 그대로요&quot;라는 답은 대화 안에서 쌓인 것이다. 둘은 출처가 다르지만 같은 자리에 들어간다. 봇의 다음 문장은 둘을 구분하지 않고 꺼내 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;이름이 생긴 자리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 일에 이름이 붙은 곳은 대화 시스템 연구다. 연구에서 &quot;대화 상태 추적(dialog state tracking)&quot;이라 부른다. 2013년에 공개 과제로 열린 대화 상태 추적 챌린지(DSTC)는 이 일을 &quot;대화가 진행되는 동안 사용자가 원하는 것을 추정하는 일&quot;로 정의했다. 사람이 하는 말은 한 번에 다 나오지 않고 중간에 고쳐지기도 하니, 턴마다 들어온 증거를 모아 지금까지의 상태를 갱신하는 것이 과제였다. 출처는 Williams 외, &lt;a href=&quot;https://aclanthology.org/W13-4065/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;The Dialog State Tracking Challenge&lt;/a&gt;(SIGDIAL 2013, 2026-10-18 조회)다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상용 봇 빌더는 같은 것을 &quot;컨텍스트&quot;라는 이름의 부품으로 넣었다. 공개 문서 기준으로 한 빌더는 인텐트마다 입력 컨텍스트와 출력 컨텍스트를 붙이고, 컨텍스트에 수명을 둔다. 기본 수명은 5턴이고 후속 인텐트는 2턴이며, 어떤 컨텍스트든 20분이 지나면 사라진다. 출처는 &lt;a href=&quot;https://docs.cloud.google.com/dialogflow/es/docs/contexts-input-output?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Dialogflow 문서의 컨텍스트 항목&lt;/a&gt;(2026-10-18 조회)이다. 이 숫자들은 그 제품의 기본값일 뿐이지만, &quot;기록에는 수명이 있다&quot;는 생각이 처음부터 들어 있었다는 점은 뒤에서 다시 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;왜 모델에게 맡기면 안 되는가&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02_three-ways.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTDvTJ/dJMcac53oo0/P8oU7lDpNKpuAw6zMynahK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTDvTJ/dJMcac53oo0/P8oU7lDpNKpuAw6zMynahK/img.png&quot; data-alt=&quot;세 가지 길, 모델에게 기억시키기와 전부 다시 보내기와 봇이 기록을 들고 필요한 만큼만 건네기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTDvTJ/dJMcac53oo0/P8oU7lDpNKpuAw6zMynahK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTDvTJ%2FdJMcac53oo0%2FP8oU7lDpNKpuAw6zMynahK%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;2400&quot; height=&quot;1560&quot; data-filename=&quot;02_three-ways.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;세 가지 길, 모델에게 기억시키기와 전부 다시 보내기와 봇이 기록을 들고 필요한 만큼만 건네기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거대 언어 모델 (LLM, large language model)을 붙이면 이 기록을 모델이 알아서 해 줄 것 같다. 그렇지 않다. 모델은 한 번 호출될 때 받은 글자를 읽고 답을 만들고 끝난다. 다음 호출은 처음부터다. 방금 한 말도 다음 호출에는 없다. &lt;a href=&quot;https://hsjo.tistory.com/16&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;RAG 글&lt;/a&gt;에서 모델은 매번 처음 보는 문서를 읽는다고 썼는데, 대화도 마찬가지다. 모델은 매 턴 처음 만난 사람이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 길이 셋이다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;첫째는 모델에게 기억시키는 것이다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 문서라면 파인 튜닝(미세 조정, fine-tuning)이 있지만, 대화는 손님마다 다르고 지금 이 순간 바뀌고 있어서 가르칠 대상이 아니다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;둘째는 매 호출마다 지금까지의 대화를 전부 다시 보내는 것이다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 되기는 한다. 그런데 모델이 한 번에 읽을 수 있는 글자의 양에는 한계가 있고, 이것을 컨텍스트 창(context window)이라 부른다. 공개 문서 기준으로 한 모델 제공사는 컨텍스트 창을 모델이 한 번의 요청에서 참조할 수 있는 글자 전체의 양으로 설명한다(&lt;a href=&quot;https://platform.claude.com/docs/en/build-with-claude/context-windows&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Understanding the context window&lt;/a&gt;, 2026-10-18 조회). 대화가 길어질수록 보낼 양이 늘고, 보내는 양만큼 비용과 시간이 들고, 상담에 필요 없는 말까지 다 섞인다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;셋째는 봇이 기록을 따로 들고 있다가, 모델이 필요할 때 필요한 만큼만 글자로 만들어 건네는 것이다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 내 시스템은 셋째 길이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 이름이 둘 겹친다. 봇의 대화 컨텍스트와 모델의 컨텍스트 창이다. 둘은 다른 것이다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.4961%; text-align: center;&quot;&gt;&lt;b&gt;구분&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 42.0543%; text-align: center;&quot;&gt;&lt;b&gt;봇의 대화 컨텍스트&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 43.4495%; text-align: center;&quot;&gt;&lt;b&gt;모델의 컨텍스트 창&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.4961%;&quot;&gt;무엇인가&lt;/td&gt;
&lt;td style=&quot;width: 42.0543%;&quot;&gt;봇이 저장소에 들고 있는 기록&lt;/td&gt;
&lt;td style=&quot;width: 43.4495%;&quot;&gt;모델이 한 번 호출에 읽을 수 있는 글자의 양&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.4961%;&quot;&gt;누가 관리하나&lt;/td&gt;
&lt;td style=&quot;width: 42.0543%;&quot;&gt;봇 엔진&lt;/td&gt;
&lt;td style=&quot;width: 43.4495%;&quot;&gt;모델 제공사&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.4961%;&quot;&gt;얼마나 가나&lt;/td&gt;
&lt;td style=&quot;width: 42.0543%;&quot;&gt;세션이 끝날 때까지&lt;/td&gt;
&lt;td style=&quot;width: 43.4495%;&quot;&gt;그 호출 한 번&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.4961%;&quot;&gt;둘의 관계&lt;/td&gt;
&lt;td style=&quot;width: 42.0543%;&quot;&gt;기록 중 일부를 글자로 만들어 창 안에 넣는다&lt;/td&gt;
&lt;td style=&quot;width: 43.4495%;&quot;&gt;창에 들어온 것만 읽는다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;기록에 무엇을 담는가&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03_what-is-in-it.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1540&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/deWmv3/dJMcahl8mjh/5LiNk5Q0jRAGDs6vf9eLtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/deWmv3/dJMcahl8mjh/5LiNk5Q0jRAGDs6vf9eLtK/img.png&quot; data-alt=&quot;세션 상태 한 장, 현재 칸과 채운 값과 다음에 기다리는 입력 (값은 예시)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/deWmv3/dJMcahl8mjh/5LiNk5Q0jRAGDs6vf9eLtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdeWmv3%2FdJMcahl8mjh%2F5LiNk5Q0jRAGDs6vf9eLtK%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;2400&quot; height=&quot;1540&quot; data-filename=&quot;03_what-is-in-it.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1540&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;세션 상태 한 장, 현재 칸과 채운 값과 다음에 기다리는 입력 (값은 예시)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 시스템에서 대화 한 판의 기록은 세션 상태라는 작은 덩어리 하나다. 세 칸이다. 지금 서 있는 노드의 번호, 변수들, 그리고 대화의 상태다. 변수에는 폼으로 받은 값(교환 사유, 희망 사이즈), 기간계를 조회해 받은 값(주문 정보 한 묶음), 모델이 만든 답, 봇 전체에 공통인 전역 파라미터가 들어간다. 상태는 진행 중, 완결, 이탈, 오류 중 하나다. 옷 장면이라면 노드는 &quot;교환 사유 확인&quot;, 변수에는 주문 조회 결과와 &quot;색상 불일치&quot;가 들어 있고, 상태는 진행 중이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에 하나가 더 붙어 나간다. 엔진은 응답을 돌려줄 때마다 봇이 한 말과 함께 &quot;다음에 어떤 입력을 기다리는지&quot;를 같이 보낸다. 선택지를 기다리면 선택지 목록을, 폼을 기다리면 칸들을 보낸다. 화면은 이것을 보고 버튼을 그리거나 입력칸을 그린다. &quot;파란색이요&quot;가 교환할 색상인 줄 아는 것은 바로 이 기다리는 입력 덕분이다. 기록은 &quot;지금까지&quot;만 적는 것이 아니라 &quot;다음에 올 것&quot;도 적는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;기록은 어디에 두는가&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04_where-it-lives.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBxOvG/dJMcafoiH55/zWH4qthmSJBoD4c0x8zYVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBxOvG/dJMcafoiH55/zWH4qthmSJBoD4c0x8zYVk/img.png&quot; data-alt=&quot;아무것도 기억하지 않는 서버 두대와 저장소의 세션 행, 기록은 서버가 아니라 저장소에 있다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBxOvG/dJMcafoiH55/zWH4qthmSJBoD4c0x8zYVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBxOvG%2FdJMcafoiH55%2FzWH4qthmSJBoD4c0x8zYVk%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;2400&quot; height=&quot;1600&quot; data-filename=&quot;04_where-it-lives.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;아무것도 기억하지 않는 서버 두대와 저장소의 세션 행, 기록은 서버가 아니라 저장소에 있다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 엔진을 만들 때 정한 원칙이 하나 있다. 엔진은 저장소도 통신도 모른다. 시나리오와 세션 상태를 받아서, 한 걸음 진행하고, 새 세션 상태를 돌려줄 뿐이다. 그 상태를 어디에 둘지는 엔진 바깥, 대화 API의 몫이다. 대화 API는 매 요청마다 저장소에서 세션 상태를 꺼내 엔진에 넘기고, 돌아온 새 상태를 다시 저장소에 쓴다. 상태는 데이터베이스의 세션 행 하나에 있다. 서버의 메모리에는 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 나눈 이유는 서버를 두 대 두기 위해서였다. 폐쇄망 납품에서는 서버 한 대가 꺼져도 대화가 끊기면 안 된다. 서버가 아무것도 기억하지 않으면 두 대 중 어느 쪽이 요청을 받아도 같은 저장소에서 같은 기록을 꺼내 같은 대답을 한다. 사용자는 서버가 바뀐 것을 모른다. 상담사가 자리를 비웠을 때 옆자리 상담사가 같은 화면을 열고 이어 받는 것과 같다. 기록이 사람의 머리에 있으면 인계가 안 되고, 화면에 있으면 된다. 세션 번호는 128비트 난수라서 추측으로 남의 기록을 열 수 없고, 세션끼리는 변수를 공유하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션 행에는 하나가 더 적혀 있다. 대화를 시작할 때의 시나리오 버전이다. 대화가 진행되는 중에 저작자가 시나리오를 고쳐 배포해도 진행 중인 대화는 시작할 때의 버전을 끝까지 쓴다. 바뀐 시나리오는 다음 새 대화부터다. 이것이 없으면 사용자가 선택지 셋 중 둘째를 골랐는데 그 사이 선택지가 넷으로 바뀌어 엉뚱한 칸으로 가는 일이 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기록을 남기되 가리는 것도 있다. 생년월일처럼 민감 표시가 된 폼 값은 저장소에 쓸 때와 통계 이벤트로 남길 때 가린다. 상담사 모니터에도 카드번호 가운데 자리는 별표로 보이는 것과 같다. 기록은 대화를 잇기 위한 것이지 모아 두기 위한 것이 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;기록을 글자로 만든다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;05_record-to-text.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzjLSR/dJMcafoiL6C/f6IfKD99HTBWiNtkVEvoeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzjLSR/dJMcafoiL6C/f6IfKD99HTBWiNtkVEvoeK/img.png&quot; data-alt=&quot;변수가 봇 문장과 모델 지시문에 끼워지고, 모델의 답은 다시 기록으로 들어온다 (문장은 예시)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzjLSR/dJMcafoiL6C/f6IfKD99HTBWiNtkVEvoeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzjLSR%2FdJMcafoiL6C%2Ff6IfKD99HTBWiNtkVEvoeK%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;2400&quot; height=&quot;1680&quot; data-filename=&quot;05_record-to-text.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1680&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;변수가 봇 문장과 모델 지시문에 끼워지고, 모델의 답은 다시 기록으로 들어온다 (문장은 예시)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기록은 들고만 있으면 쓸모가 없다. 봇의 말에 들어가야 한다. 들어가는 방법은 보간(끼워 넣기, interpolation)이다. 시나리오의 문장에 {{변수}}라고 적어 두면 엔진이 말할 때 기록의 값으로 바꿔 넣는다. &amp;ldquo;{{cust.name}}님, {{order.color}} {{order.item}} 교환 접수를 도와드릴게요&amp;rdquo;가 &quot;홍길동님, 파란색 린넨 셔츠 교환 접수를 도와드릴게요&quot;가 된다. 변수 이름에 점을 찍어 묶음 안의 값을 꺼낼 수 있고, 없는 변수는 빈 글자로 바뀐다. 봇 문장만이 아니라 기간계를 부를 때 보내는 값, 모델에게 주는 지시문에도 같은 규칙이 적용된다. 전역 파라미터만 조금 다르다. 저장소에 쓰지 않고 매 걸음 최신값을 다시 끼운다. 운영자가 영업시간 문구를 고치면 진행 중인 대화에도 다음 말부터 반영되게 하려는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델에게 건넬 때도 같은 보간이다. 시나리오의 llm 노드는 지시문 한 덩어리를 가지고 있고, 엔진은 그 안의 {{변수}}를 기록 값으로 채운 뒤 모델에 보낸다. 대화 전체를 보내지 않는다. 시나리오를 그린 사람이 &quot;이 자리에서 모델이 알아야 할 것&quot;을 지시문에 변수로 적어 둔 것만 간다. 예시로 적으면 이렇다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;고객 {{cust.name}}님이 {{order.date}}에 받은 {{order.color}} {{order.item}}의 교환을 요청했다. 사유는 {{reason}}이다. 출고 기록의 색상은 {{shipped.color}}다. 고객에게 교환 절차를 세 문장 안으로 안내하라.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RAG이 켜진 노드라면 그 앞에 찾아온 근거 문단이 붙는다. 모델이 돌려준 답은 봇의 말이 되는 동시에 변수에 저장된다. 다음 노드가 그 답을 다시 쓸 수 있다. 기록에서 나간 것이 글자가 되고, 글자로 돌아온 것이 기록이 된다. 모델의 컨텍스트 창에 들어가는 것은 이 덩어리 하나이고, 봇의 대화 컨텍스트는 그동안 저장소에 그대로 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;딴 질문을 하고 돌아오기&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;06_interrupt-and-return.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1840&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boE17x/dJMcaatIBXP/ASB0vT7ZqtbIS6RoypxPI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boE17x/dJMcaatIBXP/ASB0vT7ZqtbIS6RoypxPI1/img.png&quot; data-alt=&quot;선택지를 기다리는데 딴 말이 오면, 기록은 그대로 두고 답한 뒤 원래 자리로 돌아온다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boE17x/dJMcaatIBXP/ASB0vT7ZqtbIS6RoypxPI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboE17x%2FdJMcaatIBXP%2FASB0vT7ZqtbIS6RoypxPI1%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;2400&quot; height=&quot;1840&quot; data-filename=&quot;06_interrupt-and-return.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1840&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;선택지를 기다리는데 딴 말이 오면, 기록은 그대로 두고 답한 뒤 원래 자리로 돌아온다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;봇이 &quot;교환 / 반품 / 상담사 연결&quot; 세 버튼을 보여 주고 기다리는데 사용자가 버튼 대신 &quot;반품하면 배송비는 누가 내요&quot;라고 친다. 이것이 끼어들기(돌발 발화, digression)다. 내 시스템의 엔진은 자유 발화가 오면 먼저 지금 서 있는 칸의 입력으로 받을 수 있는지 본다. 버튼 라벨과 같은 문장이면 그 버튼을 누른 것으로 본다. 한 칸짜리 폼을 기다리는데 형식에 맞는 문장이면 그 값으로 받는다. 둘 다 아니면 엔진은 기록을 한 글자도 바꾸지 않고 &quot;이 말은 못 받았다&quot;는 표식만 달아 돌려보낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;표식을 받은 대화 API는 의도 분류를 돌린다. 어떤 인텐트에 임계값 이상으로 걸리면 다음 절의 전환으로 간다. 걸리지 않으면 지식을 한 번 검색하고, 충분히 가까운 조각이 있으면 그 근거로 모델이 답한다. 그리고 원래 기다리던 입력, 그러니까 아까의 세 버튼을 다시 보여 준다. 배송비 질문에 답하고 &quot;교환 / 반품 / 상담사 연결&quot;로 돌아오는 것이다. 지식에서도 못 찾으면 &quot;질문을 잘 이해하지 못했습니다. 아래에서 골라 주시거나 다르게 말씀해 주세요&quot;를 내고 역시 세 버튼으로 돌아온다. 어느 길이든 기록은 건드리지 않았으므로 돌아올 자리가 남아 있다. 끼어들기 처리의 핵심은 답을 잘하는 것보다 돌아올 자리를 지우지 않는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;다른 용건으로 넘어갈 때, 그리고 내가 틀린 곳&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;07_switch-and-failure.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ojMAy/dJMcadYfV0S/18GzmjiQvGEAZerq0sKYR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ojMAy/dJMcadYfV0S/18GzmjiQvGEAZerq0sKYR1/img.png&quot; data-alt=&quot;시나리오를 갈아탈 때 기록이 비면 본인 확인을 다시 받는다, 고치는 법은 한 통화 단위의 기록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ojMAy/dJMcadYfV0S/18GzmjiQvGEAZerq0sKYR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FojMAy%2FdJMcadYfV0S%2F18GzmjiQvGEAZerq0sKYR1%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;2400&quot; height=&quot;1640&quot; data-filename=&quot;07_switch-and-failure.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;시나리오를 갈아탈 때 기록이 비면 본인 확인을 다시 받는다, 고치는 법은 한 통화 단위의 기록&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;끼어든 말이 다른 인텐트에 걸리면 이야기가 다르다. 교환 시나리오 중에 &quot;카드를 잃어버렸어요&quot;라고 하면 카드 분실 인텐트가 걸리고, 세션은 카드 분실 시나리오로 옮겨 탄다. 내 시스템은 이때 새 시나리오를 처음부터 시작하고, 세션 행의 시나리오와 버전을 새것으로 바꿔 적는다. 교환 대화는 거기서 끝난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에 내가 아직 고치지 못한 것이 있다. 새 시나리오를 처음부터 시작할 때 변수는 빈 상태에서 출발한다. 전역 파라미터만 다시 들어간다. 그래서 교환 시나리오에서 본인 확인을 마쳤어도 카드 분실 시나리오는 본인 확인을 다시 받는다. 사용자 입장에서는 방금 생년월일을 말했는데 또 묻는 봇이다. 상담사라면 같은 통화 안에서 다시 묻지 않는다. 원인은 기록의 단위를 시나리오로 잡은 데 있다. 고치는 법은 기록을 두 층으로 나누는 것이다. 시나리오 안에서만 쓰는 값과 한 통화 동안 유지할 값(본인 확인 여부, 조회한 고객 정보)을 가르고, 전환할 때 뒤쪽만 들고 간다. 무엇을 들고 갈지는 저작자가 정한다. 다 들고 가면 앞 시나리오의 &quot;교환 사유&quot;가 카드 분실 시나리오에 남아 엉뚱한 보간이 생긴다. 이 글을 쓰는 시점에 내 시스템은 시나리오 단위이고, 이것은 설계 선택이라기보다 아직 안 한 일이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기록이 꼬였을 때의 마지막 안전장치도 하나 있다. 한 번의 진행에서 노드를 50개 넘게 지나면 엔진은 대화를 오류로 끝낸다. 시나리오에 실수로 고리가 생기면 봇이 같은 자리를 영원히 돌면서 기록만 자라는데, 그것을 막는 상한이다. 사용자는 &quot;대화 진행 한도를 초과했습니다&quot;를 보고, 저작자는 시나리오를 고친다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;언제 지우는가&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;08_when-to-forget.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qhefr/dJMcadjJnk3/6wvrtT4hfZZrFZuJJzVQ80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qhefr/dJMcadjJnk3/6wvrtT4hfZZrFZuJJzVQ80/img.png&quot; data-alt=&quot;세션은 완결∙이탈∙오류 세 갈래로 끝나고, 끝난 뒤에 온 말은 새 대화가 된다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qhefr/dJMcadjJnk3/6wvrtT4hfZZrFZuJJzVQ80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqhefr%2FdJMcadjJnk3%2F6wvrtT4hfZZrFZuJJzVQ80%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;2400&quot; height=&quot;1520&quot; data-filename=&quot;08_when-to-forget.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;세션은 완결∙이탈∙오류 세 갈래로 끝나고, 끝난 뒤에 온 말은 새 대화가 된다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기록은 영원히 두지 않는다. 세션은 세 갈래로 끝난다.&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 13.7984%; text-align: center;&quot;&gt;&lt;b&gt;끝나는 길&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.4729%; text-align: center;&quot;&gt;&lt;b&gt;언제&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 44.7286%; text-align: center;&quot;&gt;&lt;b&gt;기록은&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 13.7984%;&quot;&gt;완결&lt;/td&gt;
&lt;td style=&quot;width: 41.4729%;&quot;&gt;시나리오의 끝 노드에 닿았을 때&lt;/td&gt;
&lt;td style=&quot;width: 44.7286%;&quot;&gt;상태를 완결로 바꾸고 더 받지 않는다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 13.7984%;&quot;&gt;이탈&lt;/td&gt;
&lt;td style=&quot;width: 41.4729%;&quot;&gt;일정 시간 아무 말이 없을 때&lt;/td&gt;
&lt;td style=&quot;width: 44.7286%;&quot;&gt;상태를 이탈로 바꾸고 마지막 노드를 적어 둔다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 13.7984%;&quot;&gt;오류&lt;/td&gt;
&lt;td style=&quot;width: 41.4729%;&quot;&gt;복구할 수 없는 문제가 났을 때&lt;/td&gt;
&lt;td style=&quot;width: 44.7286%;&quot;&gt;상태를 오류로 바꾸고 안내 문구를 낸다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;끝난 세션에 말을 보내면 &quot;대화가 만료되었습니다. 새로 시작해 주세요&quot;가 돌아오고, 다음 말은 새 세션이 된다. 이탈의 기준 시간을 얼마로 둘지가 운영의 결정이다. 너무 짧으면 잠깐 자리를 비운 사용자가 돌아와 처음부터 다시 한다. 너무 길면 어제 하던 교환 대화가 오늘 아침에 이어진다. 앞에서 본 빌더가 컨텍스트에 턴 수명과 분 단위 만료를 함께 둔 이유도 같다. 이탈한 세션의 마지막 노드를 적어 두는 것은 통계를 위해서다. 어느 칸에서 사람들이 떠나는지가 쌓이면 그 칸의 문장을 고친다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상담사가 &quot;그제 받으신 파란색 린넨 셔츠 말씀이시죠&quot;라고 먼저 말할 수 있는 것은 기억력이 아니라 모니터의 기록 때문이고, 봇이 &quot;파란색이요&quot;를 교환할 색상으로 알아듣는 것도 모델의 기억이 아니라 봇이 들고 있는 기록 때문이다. 내 시스템에서 그 기록은 현재 칸, 변수, 상태, 기다리는 입력을 담은 세션 상태 하나이고, 서버가 아니라 저장소에 있어서 서버가 바뀌어도 대화가 이어지고, 필요한 만큼만 글자로 만들어 모델에게 건네진다. 만들면서 배운 것은 기록을 잘 쌓는 일보다 지우지 않을 것과 지울 것을 가르는 일이 어렵다는 점이었다. 끼어들기에서는 지우지 않아야 돌아오고, 전환에서는 일부만 들고 가야 하고, 세션이 끝나면 지워야 한다. 다음에 내 시스템에서 손댈 곳은 그 가운데 전환이다.&lt;/p&gt;</description>
      <category>tech</category>
      <category>AICC</category>
      <category>context</category>
      <category>context window</category>
      <category>dialog state tracking</category>
      <category>Session</category>
      <category>대화 상태 추적</category>
      <category>세션</category>
      <category>인공지능 컨택센터</category>
      <category>컨텍스트</category>
      <category>컨텍스트 창</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/18</guid>
      <comments>https://hsjo.tistory.com/18#entry18comment</comments>
      <pubDate>Sun, 18 Oct 2026 16:20:13 +0900</pubDate>
    </item>
    <item>
      <title>같은 뜻을 다른 말로 물어도 찾아낸다, 벡터화와 벡터 검색</title>
      <link>https://hsjo.tistory.com/17</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;형태를 넘어선 패턴 매칭.png&quot; data-origin-width=&quot;1774&quot; data-origin-height=&quot;887&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/37d5W/dJMcaiSPYuc/Sp6Ab96GdvAgOSLP5FYKO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/37d5W/dJMcaiSPYuc/Sp6Ab96GdvAgOSLP5FYKO0/img.png&quot; data-alt=&quot;다른 말로 물어도 같은 자리에 꽂힌다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/37d5W/dJMcaiSPYuc/Sp6Ab96GdvAgOSLP5FYKO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F37d5W%2FdJMcaiSPYuc%2FSp6Ab96GdvAgOSLP5FYKO0%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;1774&quot; height=&quot;887&quot; data-filename=&quot;형태를 넘어선 패턴 매칭.png&quot; data-origin-width=&quot;1774&quot; data-origin-height=&quot;887&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다른 말로 물어도 같은 자리에 꽂힌다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사내 규정을 찾는 검색창에 &quot;카드 잃어버리면 어떻게 해요&quot;라고 친다. 결과가 없다. 문서에는 &quot;분실&quot;이라고 적혀 있기 때문이다. 글자를 맞추는 검색은 &quot;잃어버리다&quot;와 &quot;분실&quot;이 같은 뜻이라는 것을 모른다. 그래서 사람은 검색창 앞에서 문서가 쓸 법한 말을 추측한다. 봇은 그 추측을 사용자에게 시킬 수 없다. 사용자는 자기 말로 묻는다. 내가 만든 챗봇 시스템에 &quot;카드 분실 신고 안내&quot;라는 가상의 규정 문서를 올리고 &quot;카드 잃어버리면 어떻게 해요&quot;라고 물으면, 글자는 하나도 겹치지 않는데 그 문서의 첫 대목이 1등으로 올라온다. 문장을 숫자로 바꾸고, 숫자끼리 닮은 정도를 재서 찾기 때문이다. 이 글은 그 두 가지, 벡터화와 벡터 검색을 신입사원이 따라올 수 있는 속도로 적는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01_keyword-vs-vector.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sVujW/dJMcaaAua8M/2acNlkdnI3ZMYELt30AHFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sVujW/dJMcaaAua8M/2acNlkdnI3ZMYELt30AHFK/img.png&quot; data-alt=&quot;글자를 맞추는 검색은 분실과 잃어버렸어요를 잇지 못하고, 뜻을 재는 검색은 잇는다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sVujW/dJMcaaAua8M/2acNlkdnI3ZMYELt30AHFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsVujW%2FdJMcaaAua8M%2F2acNlkdnI3ZMYELt30AHFK%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;2400&quot; height=&quot;1520&quot; data-filename=&quot;01_keyword-vs-vector.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;글자를 맞추는 검색은 분실과 잃어버렸어요를 잇지 못하고, 뜻을 재는 검색은 잇는다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hsjo.tistory.com/16&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;지난 글&lt;/a&gt;에서 RAG의 묻는 길은 질문과 닮은 조각을 찾아 모델에게 건네는 길이었다. 그 &quot;닮은 조각을 찾는&quot; 자리가 이 글이다. 조각을 숫자로 바꾸는 임베딩이 무엇인지, 닮음을 어떻게 재는지, 저장된 수천 개 중에서 어떻게 골라내는지, 그리고 내 시스템에서 이것이 지식 검색 말고 어디에 또 쓰이는지를 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;글자를 맞추는 검색이 못하는 것&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색의 오래된 방식은 글자를 맞추는 것이다. 질문에 든 낱말이 문서에 있으면 찾고 없으면 못 찾는다. 키워드 검색(keyword search)이라 부른다. 빠르고 설명하기 쉽다. &quot;분실&quot;로 찾았으니 &quot;분실&quot;이 든 문서가 나온다. 그런데 &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;사람의 말은 같은 뜻을 여러 모양으로 쓴다. 잃어버렸다, 분실했다, 없어졌다, 안 보인다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 문서는 그중 하나로 적혀 있고 사용자는 다른 하나로 묻는다. 동의어 사전을 만들어 &quot;잃어버리다 = 분실&quot;을 적어 두면 풀리지만, 사전은 사람이 생각해 낸 짝만 안다. &quot;카드가 어디 갔는지 모르겠어요&quot;는 어느 사전에도 없다. 한국어는 어미와 조사가 붙어 글자 모양이 더 자주 바뀐다. &quot;잃어버렸어요&quot;, &quot;잃어버린&quot;, &quot;잃어버리면&quot;이 글자로는 다 다르다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;&lt;b&gt;구분&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;&lt;b&gt;키워드 검색&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;&lt;b&gt;벡터 검색&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;무엇을 비교하나&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;글자가 겹치는가&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;뜻이 닮았는가&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&quot;분실&quot;과 &quot;잃어버렸어요&quot;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;못 잇는다&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;잇는다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;왜 찾았는지&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;겹친 낱말을 보여 줄 수 있다&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;점수만 준다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;준비물&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;색인&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;임베딩 모델과 벡터 저장소&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뜻을 재는 검색은 반대로 간다. 문장을 글자가 아니라 뜻의 자리로 바꿔 두고, 자리가 가까운 것을 찾는다. 의미 검색(semantic search)이라고도 부르고, 그 자리를 숫자로 적은 것이 벡터라서 벡터 검색(vector search)이라고도 부른다. 글자가 하나도 안 겹쳐도 찾고, 대신 왜 찾았는지를 글자로 설명하지 못한다. 점수 하나를 돌려줄 뿐이다. 이 차이가 뒤에서 운영 이야기로 이어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문장을 숫자로 바꾼다, 벡터화&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02_embedding-map.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AKbao/dJMcackEpOo/x7YUatE8f2qCC5m5VfRPjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AKbao/dJMcackEpOo/x7YUatE8f2qCC5m5VfRPjK/img.png&quot; data-alt=&quot;문장 하나가 숫자 1,024개의 목록이 되고, 뜻이 닮은 문장끼리 가까운 자리에 놓인다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AKbao/dJMcackEpOo/x7YUatE8f2qCC5m5VfRPjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAKbao%2FdJMcackEpOo%2Fx7YUatE8f2qCC5m5VfRPjK%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;2400&quot; height=&quot;1600&quot; data-filename=&quot;02_embedding-map.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;문장 하나가 숫자 1,024개의 목록이 되고, 뜻이 닮은 문장끼리 가까운 자리에 놓인다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벡터(vector)는 숫자를 줄 세운 목록이다. 지도 위의 한 점을 가로 숫자와 세로 숫자 둘로 적듯, 문장 하나를 숫자 여러 개로 적은 것이다. 내 시스템의 임베딩 모델은 문장 하나를 숫자 1,024개로 바꾼다. 숫자 하나하나가 무엇을 뜻하는지는 사람이 읽을 수 없다. 읽을 수 있는 것은 두 목록이 얼마나 닮았는가뿐이다. 그런데 그것으로 충분하다. 임베딩 모델은 엄청난 양의 글을 읽으며 &quot;같은 자리에 올 수 있는 말은 뜻이 비슷하다&quot;는 쪽으로 숫자를 맞춰 온 모델이라, 뜻이 비슷한 문장은 비슷한 숫자 목록이 나온다. 지도에 비유하면 &quot;카드 분실 신고&quot;와 &quot;카드 잃어버렸어요&quot;는 같은 동네에 찍히고, &quot;앱 로그인 방법&quot;은 먼 동네에 찍힌다. 문장을 이 지도 위의 점으로 바꾸는 일이 벡터화이고, 그 일을 하는 모델이 임베딩 모델(embedding model)이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 가지 성질이 뒤의 모든 것을 떠받친다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;첫째, 같은 문장은 언제나 같은 벡터다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 그래서 저장해 둔 벡터와 지금 만든 벡터를 비교할 수 있다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;둘째, 모델이 다르면 같은 문장이라도 다른 숫자가 나온다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 다른 모델로 만든 벡터끼리는 같은 지도 위에 있지 않아 비교가 성립하지 않는다. 그래서 임베딩 모델을 바꾸면 저장해 둔 벡터를 전부 다시 만들어야 하고, 내 시스템은 벡터를 저장할 때 몇 차원인지를 함께 적어 둔다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;셋째, 벡터의 길이, 곧 숫자의 개수는 모델이 정하고 저장소는 그 길이로 칸을 판다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 내 시스템의 칸은 1,024개이고, 다른 길이의 벡터가 들어오면 저장을 거부하고 &quot;임베딩 모델 설정을 확인하라&quot;고 알린다. 조용히 받아 두면 나중에 비교가 전부 틀리기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 시스템이 쓰는 임베딩 모델은 bge-m3다. 폐쇄망에서도 돌아야 해서 로컬 모델이어야 했고, 한국어 검색 품질이 확인된 것 중에서 골랐다. 대화 모델은 인터넷 API와 로컬 모델을 스위치로 바꾸지만 임베딩 모델은 바꾸지 않는다. 둘째 성질 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;닮음을 재는 자, 코사인 유사도&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03_cosine.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bj3JtB/dJMcab7bDBR/FCWJiUHSv130km5cSu6D60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bj3JtB/dJMcab7bDBR/FCWJiUHSv130km5cSu6D60/img.png&quot; data-alt=&quot;길이가 아니라 방향을 잰다, 같은 방향 1∙비슷한 방향 0.8∙무관 0 (숫자는 예시)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bj3JtB/dJMcab7bDBR/FCWJiUHSv130km5cSu6D60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbj3JtB%2FdJMcab7bDBR%2FFCWJiUHSv130km5cSu6D60%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;2400&quot; height=&quot;1480&quot; data-filename=&quot;03_cosine.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1480&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;길이가 아니라 방향을 잰다, 같은 방향 1∙비슷한 방향 0.8∙무관 0 (숫자는 예시)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 벡터가 닮았는지를 재는 자가 코사인 유사도(cosine similarity)다. 두 점 사이의 거리를 재는 것이 아니라 두 화살표가 얼마나 같은 방향을 보는지를 잰다. 원점에서 각 점으로 화살표를 그었을 때 두 화살표가 겹치면 1, 직각이면 0이다. 길이를 재지 않는 이유는 문장의 길이나 표현의 세기가 벡터의 길이로 새기 때문이다. &quot;카드 분실&quot;과 &quot;카드를 분실했는데 어떻게 해야 하나요&quot;는 화살표 길이는 달라도 방향은 거의 같다. 방향만 보면 둘이 닮았다고 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 시스템은 벡터를 PostgreSQL의 pgvector 확장에 저장하고, 그 확장이 주는 코사인 연산자를 그대로 쓴다. 이 연산자는 유사도가 아니라 거리를 돌려준다. 거리는 1에서 유사도를 뺀 값이라, 같은 방향이면 0, 무관하면 1이다. 그래서 점수로 보여 줄 때는 1에서 거리를 빼서 유사도로 바꾼다. 같은 문장이면 1.0, 뜻이 가까우면 0.8 언저리, 무관하면 0 근처다. 이 숫자들은 예시이고, 실제 값은 모델과 문장에 따라 다르다. 중요한 것은 점수가 &quot;맞다&amp;middot;틀리다&quot;가 아니라 &quot;얼마나 닮았나&quot;라는 연속된 값이라는 점이다. 어디서부터 닮았다고 볼지는 사람이 정한다. 그것이 뒤에 나오는 임계값이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;찾는 법, 거리 순으로 줄을 세운다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04_search-order.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfBSCR/dJMcagm2DUF/hkGXQ28BOr9NDBkKLBp7J1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfBSCR/dJMcagm2DUF/hkGXQ28BOr9NDBkKLBp7J1/img.png&quot; data-alt=&quot;질문 벡터와의 거리 순으로 전부 줄 세워 위에서 k개, 많아지면 HNSW 색인으로 근처만 본다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfBSCR/dJMcagm2DUF/hkGXQ28BOr9NDBkKLBp7J1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfBSCR%2FdJMcagm2DUF%2FhkGXQ28BOr9NDBkKLBp7J1%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;2400&quot; height=&quot;1560&quot; data-filename=&quot;04_search-order.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;질문 벡터와의 거리 순으로 전부 줄 세워 위에서 k개, 많아지면 HNSW 색인으로 근처만 본다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벡터 검색은 결국 줄 세우기다. 질문을 벡터로 바꾸고, 저장된 벡터 하나하나와의 거리를 재고, 가까운 순으로 정렬해 위에서 k개를 꺼낸다. 내 시스템은 이 정렬을 데이터베이스 안에서 한다. 벡터를 밖으로 꺼내 비교하지 않고, 데이터베이스에 &quot;이 벡터와 가까운 순으로 정렬해 위에서 넷&quot;이라고 묻는다. 지식 검색은 넷, 의도 분류는 가장 가까운 하나를 가져온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장된 벡터를 전부 비교하는 방식을 순차 비교라 한다. 조각 수천 개, 예문 수백 개 규모에서는 이것으로 충분하다. 수십만, 수백만으로 늘어나면 전부 비교하는 시간이 느껴지기 시작한다. 그때 켜는 것이 HNSW(계층 탐색 그래프, hierarchical navigable small world) 색인이다. 저장할 때 벡터끼리 &quot;이웃&quot;을 미리 이어 두고, 검색할 때는 아무 점에서 출발해 질문과 더 가까운 이웃으로 건너뛰며 근처만 보는 방식이다. 전부 비교하지 않으므로 빠르고, 대신 아주 드물게 진짜 1등을 놓칠 수 있다. 내 시스템은 시연 규모라 색인을 켜지 않았고, 켜는 한 줄만 주석으로 적어 두었다. 작게 시작할 때는 순차 비교가 정답이고, 색인은 느려졌을 때 켜는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;쓰임 하나, 지식 검색&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 글의 묻는 길이 이 줄 세우기다. 문서를 조각으로 나눠 조각마다 벡터를 저장해 두고, 질문 벡터와 가까운 조각 넷을 꺼내 출처를 붙여 모델에게 건넨다. 도입의 장면이 그것이다. &quot;카드 잃어버리면 어떻게 해요&quot;의 벡터는 &quot;분실 신고가 접수되는 즉시 카드는 정지되며&quot;라는 조각의 벡터와 가깝다. 글자는 겹치지 않는데 자리가 가깝다. 이 글에서는 여기까지만 잇고, 같은 줄 세우기가 다른 데도 쓰인다는 쪽으로 간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;쓰임 둘, 버튼 대신 말로 들어오는 의도 분류&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;05_intent-classify.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SzR9W/dJMcagUXGZg/05SVxX8iwakyxeSKHvda5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SzR9W/dJMcagUXGZg/05SVxX8iwakyxeSKHvda5K/img.png&quot; data-alt=&quot;예문을 벡터로 저장해 두고, 자유 발화와 가장 가까운 예문의 인텐트로 보낸다 (숫자는 예시)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SzR9W/dJMcagUXGZg/05SVxX8iwakyxeSKHvda5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSzR9W%2FdJMcagUXGZg%2F05SVxX8iwakyxeSKHvda5K%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;2400&quot; height=&quot;1720&quot; data-filename=&quot;05_intent-classify.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;예문을 벡터로 저장해 두고, 자유 발화와 가장 가까운 예문의 인텐트로 보낸다 (숫자는 예시)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;봇은 버튼으로 시작한다. 사용자가 버튼 대신 &quot;카드를 잃어버렸어요&quot;라고 치면, 봇은 그 말이 어느 시나리오로 가야 하는지 정해야 한다. 이것이 의도 분류이고, 인텐트(의도, intent)라는 말은 &lt;a href=&quot;https://hsjo.tistory.com/14&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;용어글&lt;/a&gt;에 있다. 내 시스템은 이 분류를 벡터 검색으로 한다. 인텐트마다 예시 발화를 몇 개 등록한다. &quot;카드를 잃어버렸어요&quot;, &quot;카드 분실 신고하려고요&quot;, &quot;카드가 없어졌어요&quot;를 카드분실 인텐트에 넣는 식이다. 등록하는 순간 각 예문을 벡터로 바꿔 함께 저장한다. 사용자가 자유 발화를 치면 그 문장을 벡터로 바꿔 저장된 모든 예문 중 가장 가까운 하나를 찾고, 그 예문이 속한 인텐트와 점수를 돌려준다. 설계 문서의 예시로는 &quot;카드를 잃어버렸어요&quot;가 카드분실의 한 예문과 0.83으로 가장 가깝다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점수가 나왔다고 끝이 아니다. 인텐트마다 임계값(threshold)이 있다. 0에서 1 사이의 선이고, 점수가 그 선을 넘어야 &quot;이 인텐트가 맞다&quot;로 친다. 예시의 임계값이 0.7이면 0.83은 통과다. 통과하면 대화 세션이 그 인텐트의 시나리오로 옮겨 탄다. 사용자가 보던 버튼 화면이 사라지고 카드분실 시나리오의 첫 질문이 나온다. 미달이면 지난 글에서 본 폴백으로 간다. 지식을 한 번 검색해 보고, 그것도 멀면 &quot;다시 말씀해 주세요&quot;다. 분류할 때마다 발화 원문, 고른 인텐트, 점수 원값, 임계값, 통과 여부를 이벤트로 남긴다. 예문이 하나도 없는 봇은 임베딩 계산 자체를 건너뛰고, 같은 예문을 다시 등록하면 조용히 건너뛴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임계값은 봇의 성격이다. 낮추면 엉뚱한 말도 어느 인텐트로 자신 있게 보내고, 높이면 맞는 말에도 모른다고 한다. 이 숫자를 인텐트마다 따로 두는 이유는 인텐트마다 예문의 밀도가 다르기 때문이다. 예문이 많고 표현이 고른 인텐트는 높은 선을 견디고, 예문이 적은 인텐트는 낮춰야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;임계값을 정하는 상자&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;06_classify-test.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byPYQJ/dJMcadYfPGl/cBTFKXlIkaTSStIiu50J30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byPYQJ/dJMcadYfPGl/cBTFKXlIkaTSStIiu50J30/img.png&quot; data-alt=&quot;분류 시험 상자, 문장 하나에 통과여부∙점수∙임계값∙가장 가까운 예문이 보인다 (숫자는 예시)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byPYQJ/dJMcadYfPGl/cBTFKXlIkaTSStIiu50J30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyPYQJ%2FdJMcadYfPGl%2FcBTFKXlIkaTSStIiu50J30%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;2400&quot; height=&quot;1440&quot; data-filename=&quot;06_classify-test.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;분류 시험 상자, 문장 하나에 통과여부∙점수∙임계값∙가장 가까운 예문이 보인다 (숫자는 예시)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임계값을 머리로 정할 수는 없다. 그래서 인텐트 관리 화면에 분류 시험 상자를 두었다. 문장을 넣으면 저장하지 않고 분류만 돌려, 어느 인텐트로 갔는지, 점수가 얼마였는지, 임계값이 얼마였는지, 어느 예문과 가장 가까웠는지를 보여 준다. 마지막 칸이 중요하다. 점수만 보면 왜 그 인텐트로 갔는지 알 수 없지만, 가장 가까운 예문을 보면 안다. &quot;카드가 어디 갔는지 모르겠어요&quot;가 카드분실로 갔다면 &quot;카드가 없어졌어요&quot;라는 예문 덕분이고, 엉뚱한 인텐트로 갔다면 그쪽에 비슷한 예문이 있는 것이다. 벡터 검색이 &quot;왜&quot;를 글자로 설명하지 못하는 약점을 이 칸이 메운다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영이 시작되면 상자 대신 장표를 본다. 인텐트별 점수의 분포를 막대로 그리고 임계값을 선으로 긋는다. 선 바로 아래에 막대가 몰려 있으면 선이 높은 것이고, 선 바로 위에 통과한 것들이 몰려 있는데 그 뒤에 사용자가 이탈했다면 오분류를 의심한다. 임계값에 미달해 폴백으로 간 발화 원문은 목록으로 쌓이고, 그중 맞는 인텐트가 있는 것은 한 번의 클릭으로 그 인텐트의 예문으로 올린다. 올리는 순간 벡터가 저장되므로 다음 분류부터 반영된다. 예문 목록은 CSV로 내보내고 가져온다. 운영자가 엑셀에서 예문을 다듬어 다시 올리는 일이 많기 때문이고, 가져올 때 기존 인텐트의 임계값 같은 설정은 덮어쓰지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가짜 임베딩으로 세 번 틀렸다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;07_stub-lessons.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mT5WA/dJMcablTfo8/cYn6PialjgoP9HTIr8gq71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mT5WA/dJMcablTfo8/cYn6PialjgoP9HTIr8gq71/img.png&quot; data-alt=&quot;가짜 임베딩 세 번, 뭉침과 어긋남을 지나 글자 짝의 주머니로&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mT5WA/dJMcablTfo8/cYn6PialjgoP9HTIr8gq71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmT5WA%2FdJMcablTfo8%2FcYn6PialjgoP9HTIr8gq71%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;2400&quot; height=&quot;1520&quot; data-filename=&quot;07_stub-lessons.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가짜 임베딩 세 번, 뭉침과 어긋남을 지나 글자 짝의 주머니로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 중에는 진짜 임베딩 모델을 매번 돌릴 수 없어서 가짜 임베딩을 쓴다. 문장을 받아 모양만 같은 벡터를 돌려주는 함수다. 테스트는 이 가짜로 &quot;저장했다가 검색하면 나오는가&quot;를 확인한다. 그런데 가짜라도 벡터 검색이 성립하려면 지켜야 할 성질이 있었고, 그것을 세 번 틀리고 나서야 알았다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 6.74419%; text-align: center;&quot;&gt;&lt;b&gt;차수&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 27.4418%; text-align: center;&quot;&gt;&lt;b&gt;만든 방식&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 36.7442%; text-align: center;&quot;&gt;&lt;b&gt;생긴 문제&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 29.0698%; text-align: center;&quot;&gt;&lt;b&gt;잡아낸 테스트&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 6.74419%; text-align: center;&quot;&gt;1차&lt;/td&gt;
&lt;td style=&quot;width: 27.4418%;&quot;&gt;글자를 앞칸부터 차례로 접어 넣음&lt;/td&gt;
&lt;td style=&quot;width: 36.7442%;&quot;&gt;짧은 문장끼리 방향이 비슷해져 엉뚱한 문장도&amp;nbsp;&lt;br /&gt;0.7을 넘음&lt;/td&gt;
&lt;td style=&quot;width: 29.0698%;&quot;&gt;미달이어야 할 문장이 통과&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 6.74419%; text-align: center;&quot;&gt;2차&lt;/td&gt;
&lt;td style=&quot;width: 27.4418%;&quot;&gt;글자의 절대 위치를 섞어 흩뿌림&lt;/td&gt;
&lt;td style=&quot;width: 36.7442%;&quot;&gt;제목이 앞에 붙은 조각과 원문 질문이 전혀 다른&amp;nbsp;&lt;br /&gt;벡터가 되어 같은 문장도 못 찾음&lt;/td&gt;
&lt;td style=&quot;width: 29.0698%;&quot;&gt;지식 검색에서 같은 문장이 1등이 아님&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 6.74419%; text-align: center;&quot;&gt;3차&lt;/td&gt;
&lt;td style=&quot;width: 27.4418%;&quot;&gt;연속 두 글자(바이그램, bigram)을&lt;br /&gt;세어 주머니에 담음&lt;/td&gt;
&lt;td style=&quot;width: 36.7442%;&quot;&gt;같은 문장 1.0, 부분 포함은 높음,&amp;nbsp;&lt;br /&gt;무관은 0 근처&lt;/td&gt;
&lt;td style=&quot;width: 29.0698%;&quot;&gt;둘 다 통과&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1차는 &quot;다른 뜻이면 멀어야 한다&quot;를 어겼고, 2차는 &quot;같은 뜻이면 가까워야 한다&quot;를 어겼다. 3차가 둘을 함께 지킨 이유는 글자의 위치를 버리고 글자 짝의 개수만 세었기 때문이다. 제목이 앞에 붙어도 뒤의 글자 짝은 그대로 남는다. 진짜 모델은 이보다 훨씬 똑똑하지만 지켜야 할 성질은 같다. 같은 뜻이면 가깝고 다른 뜻이면 멀다. 이 두 줄을 테스트로 먼저 못 박아 두지 않으면, 검색이 틀려도 모델 탓인지 저장 탓인지 임계값 탓인지 가를 수 없다. 테스트가 세 번 잡아 주지 않았으면 진짜 모델을 붙인 뒤에 같은 문제를 더 비싸게 만났을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;실제로 돌아간 세 장면&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;08_three-scenes.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mYIn2/dJMcaf9oXMi/KJ03nBWXIWvBOn10t6iD9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mYIn2/dJMcaf9oXMi/KJ03nBWXIWvBOn10t6iD9K/img.png&quot; data-alt=&quot;다른 말로 물어도 같은 대목, 자유 발화가 시나리오로, PDF가 글자가 되어 같은 길로&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mYIn2/dJMcaf9oXMi/KJ03nBWXIWvBOn10t6iD9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmYIn2%2FdJMcaf9oXMi%2FKJ03nBWXIWvBOn10t6iD9K%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;2400&quot; height=&quot;1640&quot; data-filename=&quot;08_three-scenes.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다른 말로 물어도 같은 대목, 자유 발화가 시나리오로, PDF가 글자가 되어 같은 길로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째 장면은 도입의 것이다. &quot;카드 분실 신고 안내&quot;라는 가상 규정 문서를 올린다. 문서는 제목 경계에서 잘려 &quot;신고 즉시 효력&quot;, &quot;신고 방법&quot;, &quot;해외에서 분실한 경우&quot; 같은 조각이 되고 조각마다 벡터가 붙는다. 채팅에서 &quot;카드 잃어버리면 어떻게 해요&quot;라고 묻는다. 1등은 &quot;분실 신고가 접수되는 즉시 카드는 정지되며&quot;로 시작하는 조각이다. &quot;분실하면 보상돼요&quot;라고 물어도 같은 조각이 1등이고, &quot;해외여행 중에 없어졌어요&quot;라고 물으면 해외 분실 조각이 올라온다. 글자가 아니라 뜻으로 찾았다는 것이 이 장면에서 눈에 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째 장면은 버튼 화면에서 일어난다. 봇이 선택지 셋을 보여 주는데 사용자가 버튼을 누르지 않고 &quot;카드를 잃어버렸어요&quot;라고 친다. 봇 엔진은 그 문장이 선택지 라벨과 같은지 먼저 보고, 아니면 의도 분류로 넘긴다. 분류가 카드분실 인텐트를 임계값 이상으로 고르면 세션이 카드분실 시나리오로 옮겨 타고 첫 질문이 나온다. 사용자는 버튼을 찾을 필요가 없었다. 공개 채팅 화면의 버튼 아래에 &quot;직접 입력해도 됩니다&quot;라는 입력칸이 있는 이유다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째 장면은 PDF다. 현장의 규정 문서는 대부분 PDF라서 글자 파일만 받는 것으로는 부족했다. PDF에서 글자만 뽑아내는 부품을 붙였고, 한국어 PDF의 글자가 깨지지 않도록 글꼴 대응표를 로컬에 두었다. 뽑아낸 글자는 글자 파일과 같은 길, 그러니까 청킹과 임베딩과 저장으로 들어간다. 스캔한 PDF는 글자가 아니라 그림이라 뽑을 것이 없고, 그때는 &quot;글자가 없는 문서&quot;라고 알려 준다. 벡터화는 글자에서 시작하므로 글자가 없으면 아무것도 시작되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 장면 모두 임베딩이 로컬에서 돌았다. 폐쇄망에서는 문서가 박스 밖으로 나가면 안 되므로 임베딩 모델도 안에 있어야 한다. 인터넷 API로 임베딩을 하면 문서 조각 전부가 밖으로 나간다. 지식 검색의 조각이든 의도 분류의 예문이든 마찬가지다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;같은 뜻을 다른 말로 물어도 찾아낸다&quot;는 문장은 마법처럼 들리지만 안을 열면 세 가지뿐이다. 문장을 숫자 목록으로 바꾸고, 두 목록이 같은 방향을 보는 정도를 재고, 가까운 순으로 줄을 세운다. 그 위에 사람이 정하는 것이 둘 있다. 어디서부터 닮았다고 볼지(임계값)와, 틀렸을 때 어디를 볼지(시험 상자와 점수 원값). 가짜 임베딩으로 세 번 틀리면서 배운 것도 결국 그 두 줄이었다. 같은 뜻이면 가깝고 다른 뜻이면 멀다. 이것이 지켜지는지를 먼저 확인하고, 임계값은 그다음에 정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글은 봇이 대화의 어디까지 왔는지를 들고 있는 컨텍스트다. 벡터가 &quot;무엇을 묻는가&quot;를 찾아 준다면, 컨텍스트는 &quot;지금 어디까지 왔는가&quot;를 기억한다.&lt;/p&gt;</description>
      <category>tech</category>
      <category>AICC</category>
      <category>cosine similarity</category>
      <category>Embedding</category>
      <category>intent classification</category>
      <category>vector search</category>
      <category>벡터 검색</category>
      <category>의도 분류</category>
      <category>인공지능 컨택센터</category>
      <category>임베딩</category>
      <category>코사인 유사도</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/17</guid>
      <comments>https://hsjo.tistory.com/17#entry17comment</comments>
      <pubDate>Sun, 18 Oct 2026 10:46:45 +0900</pubDate>
    </item>
    <item>
      <title>인공지능에게 가르치지 말고 읽을 문서를 건넨다, RAG과 LLM 연동</title>
      <link>https://hsjo.tistory.com/16</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;문서 자동화 아카이브 워크플로우.png&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uR3tc/dJMcafuVrgI/p8MtPtN21dEC2nW3ZZ96Wk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uR3tc/dJMcafuVrgI/p8MtPtN21dEC2nW3ZZ96Wk/img.png&quot; data-alt=&quot;문서는 서랍에 두고, 질문이 오면 닮은 쪽을 꺼내 읽어 준다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uR3tc/dJMcafuVrgI/p8MtPtN21dEC2nW3ZZ96Wk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuR3tc%2FdJMcafuVrgI%2Fp8MtPtN21dEC2nW3ZZ96Wk%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;1536&quot; height=&quot;1024&quot; data-filename=&quot;문서 자동화 아카이브 워크플로우.png&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;문서는 서랍에 두고, 질문이 오면 닮은 쪽을 꺼내 읽어 준다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;우리 회사 문서로 인공지능을 학습시켜 주세요.&quot; 챗봇에 거대 언어 모델을 붙이자는 이야기가 나오면 거의 이 문장이 따라온다. 나도 그렇게 말했고, 내가 만든 챗봇 시스템의 화면에도 문서를 올리는 버튼 이름을 &quot;학습&quot;이라고 붙였다. 그런데 그 버튼이 하는 일은 학습이 아니다. 문서에서 글자를 꺼내고, 조각으로 나누고, 조각마다 숫자 목록을 붙여 저장한다. 모델은 한 글자도 바뀌지 않는다. 질문이 오면 그 조각 중 닮은 것 몇 개를 골라 모델에게 건네고, 모델은 건네받은 것을 읽고 답한다. 가르치는 것이 아니라 읽을 문서를 건네는 것이다. 이 방식의 이름이 RAG(검색 증강 생성, &lt;span&gt;retrieval-augmented &lt;/span&gt;&lt;span&gt;generation)이고, 이 글은 &lt;/span&gt;&lt;span&gt;그것이 봇과 모델 사이 어디에 어떻게 &lt;/span&gt;&lt;span&gt;붙는지를 적는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01_teach-vs-hand.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIk6MX/dJMcafoiqZR/DamQ0IUFcDcMfDSEBn22F1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIk6MX/dJMcafoiqZR/DamQ0IUFcDcMfDSEBn22F1/img.png&quot; data-alt=&quot;가르치는 것과 건네는 것, 모델은 한글자도 바뀌지 않는다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIk6MX/dJMcafoiqZR/DamQ0IUFcDcMfDSEBn22F1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIk6MX%2FdJMcafoiqZR%2FDamQ0IUFcDcMfDSEBn22F1%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;2400&quot; height=&quot;1600&quot; data-filename=&quot;01_teach-vs-hand.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가르치는 것과 건네는 것, 모델은 한글자도 바뀌지 않는다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hsjo.tistory.com/15&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;지난 글&lt;/a&gt;에서 거대 언어 모델은 뜻을 고르는 상자와 계획을 세우는 상자에 넣고, 답을 내는 상자에는 넣지 않는다고 썼다. 돈과 규정이 있는 답은 사람이 적은 시나리오 문장으로 낸다는 뜻이었다. 그런데 시나리오에 없는 자유 질문은 남는다. &quot;실손 청구에 진단서 대신 소견서를 내도 되나요&quot; 같은 말이다. 답을 내는 상자에 모델을 넣되, 모델의 기억이 아니라 우리 문서를 읽고 답하게 하는 장치가 RAG이다. 이 글은 RAG이 무엇이고 왜 생겼는지부터 시작해, 그것이 봇과 모델 사이에 붙는 자리까지 간다. 문서를 숫자로 바꾸는 원리와 닮은 조각을 찾는 검색의 안쪽은 다음 글들에서 따로 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;거대 언어 모델은 무엇을 모르는가&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거대 언어 모델(LLM, large language model)은 인터넷에 있는 엄청난 양의 글을 읽고 &quot;다음에 올 말&quot;을 맞히는 훈련을 받은 프로그램이다. 그래서 말을 잘한다. 그런데 상담봇에 넣어 보면 네 가지가 걸린다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;첫째, 훈련이 끝난 날 이후의 일은 모른다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 모델을 만든 뒤에 바뀐 규정은 모델 안에 없다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;둘째, 공개되지 않은 문서는 모른다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 우리 회사의 약관, 사내 규정, 지난달 바뀐 수수료 안내는 인터넷에 없으니 모델도 본 적이 없다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;셋째, 모르는 것을 모른다고 하지 않고 그럴듯하게 지어낸다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 다음 말을 맞히도록 훈련됐기 때문에 근거가 없어도 문장은 완성된다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;넷째, 무엇을 근거로 답했는지 말하지 못한다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 모델의 기억은 숫자 덩어리라서 &quot;어느 문서 몇 쪽&quot;이 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상담봇은 이 넷을 하나도 허용하지 못한다. 바뀐 규정을 틀리게 말하면 안 되고, 우리 약관을 알아야 하고, 모르면 모른다고 해야 하고, 고객이 &quot;그게 어디에 적혀 있나요&quot;라고 물으면 보여 줄 수 있어야 한다. 모델을 그대로 붙이면 말은 유창한데 네 가지가 전부 빈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;세 가지 길, 그리고 RAG이라는 이름&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 모델에게 우리 문서를 알려 줄 방법을 찾게 된다. 길은 셋이다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;첫째는 다시 가르치는 것이다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 우리 문서로 모델을 추가로 훈련한다. 파인 튜닝(미세 조정, fine-tuning)이라 부른다. 비용이 크고, 문서가 바뀔 때마다 다시 해야 하고, 가르쳐도 모델이 그것을 꼭 기억한다는 보장이 없고, 여전히 출처를 말하지 못한다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;둘째는 질문할 때마다 문서를 통째로 붙여 넣는 것이다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 모델이 한 번에 읽을 수 있는 글자 수에는 한계가 있고, 읽는 양만큼 비용과 시간이 들고, 관계없는 내용이 많이 섞이면 답이 흐려진다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;셋째는 질문과 관계있는 대목만 찾아서 건네는 것이다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 문서를 미리 잘라 두고, 질문이 오면 닮은 조각 몇 개를 찾아 모델에게 읽히고 답하게 한다. 이것이 RAG(검색 증강 생성, retrieval-augmented generation)이다. 이름을 풀면 &quot;검색으로 보강한 생성&quot;이다. 생성은 모델이 답 문장을 만드는 일이고, 검색은 그 전에 근거를 찾아 주는 일이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 이름은 2020년에 나왔다. 페이스북 인공지능 연구진이 쓴 논문의 제목이 그대로 &quot;지식 집약 작업을 위한 검색 증강 생성&quot;이었다. 논문은 모델 안의 기억과 모델 밖의 기억(문서를 벡터로 바꿔 둔 색인)을 함께 쓰는 구조를 제안했고, 밖의 기억을 붙이면 답이 더 구체적이고 사실에 가까워진다고 보고했다. 그때는 위키백과를 밖의 기억으로 썼다. 지금 현장에서는 위키백과 자리에 우리 회사 문서가 들어간다. 출처는 Lewis 외, &lt;a href=&quot;https://arxiv.org/abs/2005.11401&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks&lt;/a&gt;(arXiv, 2020-05, 2026-10-17 조회)다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;챗봇에서 RAG이 거의 필수가 된 이유는 앞의 네 가지 가운데 셋이 한꺼번에 풀리기 때문이다. 바뀐 문서는 다시 올리면 되고, 우리 문서는 서랍에 넣어 두면 되고, 답에 출처가 붙는다. 남는 하나, 지어내는 버릇은 지시문으로 누른다. &quot;건네준 근거에 없는 내용은 모른다고 답하라.&quot; 그 지시문이 실제로 어떻게 생겼는지는 뒤에서 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가르치는 것과 건네는 것은 다르다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02_two-paths.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YZTgC/dJMcacdTpFI/snxXAeajKQnKXRgvkFKCp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YZTgC/dJMcacdTpFI/snxXAeajKQnKXRgvkFKCp0/img.png&quot; data-alt=&quot;RAG의 두 길, 넣는 길과 묻는 길&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YZTgC/dJMcacdTpFI/snxXAeajKQnKXRgvkFKCp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYZTgC%2FdJMcacdTpFI%2FsnxXAeajKQnKXRgvkFKCp0%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;2400&quot; height=&quot;1560&quot; data-filename=&quot;02_two-paths.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;RAG의 두 길, 넣는 길과 묻는 길&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학습은 모델의 안을 바꾸는 일이다. 문장을 수없이 보여 주어 모델의 숫자들을 조정하고, 끝나면 모델이 그 내용을 기억한다. 비용이 크고, 문서가 바뀌면 다시 해야 하고, 무엇을 근거로 답했는지 모델도 사람도 말하지 못한다. RAG은 모델의 안을 건드리지 않는다. 길이 둘이다. 넣는 길은 문서를 미리 조각으로 나눠 저장해 두는 길이고, 묻는 길은 질문이 올 때 닮은 조각을 찾아 모델에게 건네는 길이다. 모델은 매번 처음 보는 문서를 읽고 답한다. 그래서 문서를 바꾸면 다음 질문부터 바로 바뀐 내용으로 답하고, 어느 문서의 어느 대목을 근거로 답했는지 출처를 달 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 시스템에서 이 둘은 화면도 다르다. 넣는 길은 지식 관리 화면이고, 문서를 올리면 끝이다. 묻는 길은 채팅 화면이고, 사용자는 RAG이 있는지 모른다. 둘 사이에는 저장소 하나가 있다. 조각과 조각마다의 숫자 목록을 담은 표다. 넣는 길이 그 표를 채우고 묻는 길이 그 표를 읽는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;넣는 길, 문서가 조각이 되기까지&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03_chunking.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LlkuZ/dJMcajqq1OF/XPXD9GdFVe3MDsNpmKlcQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LlkuZ/dJMcajqq1OF/XPXD9GdFVe3MDsNpmKlcQ1/img.png&quot; data-alt=&quot;청킹 규칙, 제목 경계에서 가르고 제목을 앞붙이고 600자로 묶고 120자를 겹친다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LlkuZ/dJMcajqq1OF/XPXD9GdFVe3MDsNpmKlcQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLlkuZ%2FdJMcajqq1OF%2FXPXD9GdFVe3MDsNpmKlcQ1%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;2400&quot; height=&quot;1680&quot; data-filename=&quot;03_chunking.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1680&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;청킹 규칙, 제목 경계에서 가르고 제목을 앞붙이고 600자로 묶고 120자를 겹친다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서를 올리면 네 단계가 돈다. 글자 추출, 청킹, 임베딩, 저장이다. 글자 추출은 txt와 md는 그대로이고 PDF는 글자만 뽑아낸다. 청킹(조각 내기, chunking)은 긴 문서를 검색 단위인 조각, 곧 청크(chunk)로 나누는 일이다. 임베딩(embedding)은 조각 하나를 숫자 수백 개의 목록, 곧 벡터(vector)로 바꾸는 일이다. 뜻이 비슷한 문장은 숫자 목록도 비슷하게 나온다는 성질을 쓴다. 왜 그렇게 되는지는 다음 글에서 풀고, 여기서는 &quot;뜻을 숫자로 적어 둔 것&quot;이라고만 알면 된다. 저장은 조각과 벡터를 나란히 표에 넣는 일이다. 내 시스템은 외부 벡터 데이터베이스를 따로 두지 않고 PostgreSQL의 pgvector 확장에 넣는다. 실행 파일 하나로 설치하는 제품이라 부품을 늘리지 않으려는 선택이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 나누는가. 문서 전체를 벡터 하나로 만들면 &quot;이 문서 어딘가에 답이 있다&quot;까지만 알 수 있다. 문단 크기로 나눠야 &quot;정확히 이 대목&quot;을 찾아 모델에게 근거로 줄 수 있다. 그래서 어떻게 나누는지가 답의 질을 정한다. 내 시스템의 규칙은 셋이다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;첫째, 마크다운 제목 줄에서 먼저 자른다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 제목은 주제의 경계라서 한 조각이 두 주제에 걸치지 않게 한다. 그리고 제목 줄을 그 절의 모든 조각 앞에 붙인다. 조각만 읽어도 어느 절의 내용인지 알게 하려는 것인데, 이것이 검색 품질에 생각보다 크게 작용한다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;둘째, 절 안에서는 문단을 이어 붙이다가 600자를 넘으면 조각을 끊는다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 한 문단에서 반 페이지 사이, 프롬프트에 서너 개 넣을 크기다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;셋째, 문단 하나가 600자보다 길면 120자씩 겹치는 창으로 자른다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 겹침을 두는 이유는 경계에 걸린 문장이 어느 조각에서도 온전히 읽히게 하기 위해서다. 숫자는 내 시스템의 기본값이고 문서의 성격에 따라 바꾼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업로드가 끝나면 다음 질문부터 바로 그 문서로 답한다. 서버를 다시 켜지 않는다. 화면의 버튼 이름이 &quot;학습&quot;이어도 실제로는 이 네 단계이고, 중간에 임베딩이 실패하면 문서를 실패 상태로 남겨 화면이 알린다. 조각으로 나눌 내용이 없는 빈 문서, 한 건에 20MB를 넘는 문서는 받지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제목을 앞붙이는 규칙에는 대가가 있었다. 개발 중에는 진짜 임베딩 모델 대신 가짜 임베딩을 썼다. 글자의 위치를 해시해 벡터를 만드는 방식이었는데, 제목이 앞에 붙은 조각과 원문 그대로인 질문이 전혀 다른 벡터가 되어 같은 문장을 넣어도 찾지 못했다. 테스트가 잡아냈다. 연속한 두 글자의 묶음을 세는 방식으로 바꾸고 나서야 같은 문장은 1.0, 부분이 포함되면 높은 점수, 무관한 문장은 0 근처가 나왔다. 교훈은 가짜 임베딩에 그치지 않는다. 조각 앞에 무엇을 붙였다면 질문 쪽도 같은 조건에서 비교되는지 확인해야 한다. 조각에는 제목이 있고 질문에는 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;묻는 길, 질문이 답이 되기까지&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04_prompt-assembly.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/w6az0/dJMcajxrn1M/WhXf0eiebAfpnFwHlBdMWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/w6az0/dJMcajxrn1M/WhXf0eiebAfpnFwHlBdMWk/img.png&quot; data-alt=&quot;프롬프트 조립, 근거 세 조각에 출처를 붙이고 지시문을 앞에 둔다 (문장은 예시)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/w6az0/dJMcajxrn1M/WhXf0eiebAfpnFwHlBdMWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fw6az0%2FdJMcajxrn1M%2FWhXf0eiebAfpnFwHlBdMWk%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;2400&quot; height=&quot;1480&quot; data-filename=&quot;04_prompt-assembly.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1480&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프롬프트 조립, 근거 세 조각에 출처를 붙이고 지시문을 앞에 둔다 (문장은 예시)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 자유 질문을 치면 네 단계가 돈다. 질문을 임베딩하고, 저장된 조각 중 질문의 벡터와 가장 닮은 것부터 몇 개를 고르고(닮은 정도를 재는 자가 코사인 유사도(cosine similarity)이고, 두 숫자 목록이 같은 방향을 보는 정도라고 생각하면 된다), 그 조각들로 근거 문단을 조립하고, 지시문과 함께 모델에게 보낸다. 내 시스템은 기본으로 네 개를 고른다. 많이 넣을수록 좋을 것 같지만 모델이 읽어야 할 양이 늘고, 관계없는 조각이 섞여 들어가 답을 흐린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조립이 이 길의 핵심이다. 조각마다 머리에 &quot;[근거 1 - 출처: 파일 이름]&quot;을 붙여 한 문단으로 만들고, 그 앞에 지시문을 둔다. 내 시스템의 지시문은 세 문장이다. 다음 근거만 사용해 답하라. 답에 출처를 표시하라. 근거에 없는 내용은 모른다고 답하라. 그 뒤에 근거 문단, 그 뒤에 시나리오의 노드가 원래 가지고 있던 지시문과 사용자의 질문이 온다. 모델이 받는 것은 결국 글자 한 덩어리다. 조립이 끝난 모양을 예시로 적으면 이렇다(문서 이름과 문장은 예시다).&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;다음 근거만 사용해 답하고, 답에 [출처: 파일명]을 표시하라. 근거에 없는 내용은 모른다고 답하라.&lt;br /&gt;[근거 1 - 출처: 실손청구_서류안내.md] 진단서를 발급받기 어려운 경우 담당 의사의 소견서로 대신할 수 있다. 소견서에는 진단명과 치료 기간이 적혀 있어야 한다. [근거 2 - 출처: 실손청구_서류안내.md] 입원 청구는 입퇴원 확인서를 함께 낸다.[근거 3 - 출처: 접수채널.md] 서류는 앱, 팩스, 지점 방문으로 낼 수 있다.&lt;br /&gt;고객의 질문에 보험사 상담봇으로서 답하라. 질문: 실손 청구에 진단서 대신 소견서를 내도 되나요&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델은 이 덩어리를 읽고 답 문장을 만들고, 지시대로 문장 끝에 출처를 단다. 사용자 화면에는 답과 함께 참조한 문서 이름이 보인다. 세 번째 근거처럼 질문과 관계가 먼 조각이 섞이는 것이 보통이고, 모델이 그것을 무시하게 하는 것도 지시문의 몫이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출처를 달게 하는 이유는 신뢰 때문만이 아니다. 운영에서 &quot;이 답이 왜 나왔는가&quot;를 추적하는 유일한 끈이다. 답이 틀렸을 때 모델을 탓할지 문서를 탓할지 조각 나누기를 탓할지는 출처를 보고 가른다. 근거 조각이 맞는데 답이 틀렸으면 모델이나 지시문 문제이고, 근거 조각부터 엉뚱하면 검색이나 청킹 문제이고, 맞는 조각이 아예 없으면 문서가 없는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;봇의 어디에 붙는가, 두 자리&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;05_two-attach-points.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/copC26/dJMcafhssNE/4NGq4hjVMhth2IkKsivwPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/copC26/dJMcafhssNE/4NGq4hjVMhth2IkKsivwPk/img.png&quot; data-alt=&quot;RAG이 봇에 붙는 자리 둘, LLM 노드의 옵션과 인텐트 미달 폴백&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/copC26/dJMcafhssNE/4NGq4hjVMhth2IkKsivwPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcopC26%2FdJMcafhssNE%2F4NGq4hjVMhth2IkKsivwPk%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;2400&quot; height=&quot;1720&quot; data-filename=&quot;05_two-attach-points.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;RAG이 봇에 붙는 자리 둘, LLM 노드의 옵션과 인텐트 미달 폴백&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RAG은 새 봇이 아니다. 시나리오 봇에 두 자리로 붙는다. &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;첫째 자리는 시나리오의 노드다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 내 시스템의 시나리오는 상자 일곱 종류로 그리는데, 그중 llm 노드가 모델에게 자유 응답을 시키는 상자다. 이 상자에 useRag라는 옵션 하나가 있다. 켜면 그 노드의 지시문을 질의로 삼아 지식을 검색하고 근거를 주입한 뒤 모델을 부른다. 끄면 근거 없이 모델만 부른다. 시나리오를 그리는 사람 입장에서 RAG은 상자의 체크 박스 하나다. 예약 시나리오를 진행하다가 &quot;취소 규정을 설명해 주는 노드&quot;를 하나 두고 useRag를 켜면, 그 자리에서만 규정 문서를 읽고 답한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;u&gt;&lt;b&gt;둘째 자리는 폴백이다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 사용자가 버튼을 누르는 대신 자유 발화를 쳤는데 어떤 인텐트에도 점수가 미치지 못하면, 지난 글들의 봇은 &quot;다시 말씀해 주세요&quot;로 갔다. 내 시스템은 그 전에 지식을 한 번 검색한다. 가장 가까운 조각의 점수가 기준값 이상이면 그 조각을 근거로 모델이 답하고, 봇은 원래 기다리던 입력, 그러니까 아까 보여 준 선택지나 폼을 다시 기다린다. 흐름을 끊지 않는다. 기준값 미만이면 원래의 일반 폴백으로 간다. 내 시스템의 기준값은 0.3이다. 이 숫자는 임베딩 모델과 문서에 따라 달라서 운영에서 조정한다. 기준을 낮추면 엉뚱한 문서로 자신 있게 답하고, 높이면 답할 수 있는 질문에도 모른다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 자리의 차이는 &quot;누가 검색을 시작하는가&quot;다. 첫째 자리는 시나리오를 그린 사람이 &quot;여기서 문서를 읽어라&quot;라고 정한 것이고, 둘째 자리는 사용자가 시나리오 밖으로 나갔을 때 봇이 스스로 문서를 뒤지는 것이다. 둘 다 같은 검색 함수를 부르고 같은 지시문으로 모델에 간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;못 찾았을 때와 못 불렀을 때&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;06_failures-and-log.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mIqQ6/dJMcaamJh3i/CxazlvxpsJ5Xijl6gVimiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mIqQ6/dJMcaamJh3i/CxazlvxpsJ5Xijl6gVimiK/img.png&quot; data-alt=&quot;실패 처리 셋과 기록, 검색 없음과 검색 실패와 모델 다운, 그리고 점수는 원값으로 남긴다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mIqQ6/dJMcaamJh3i/CxazlvxpsJ5Xijl6gVimiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmIqQ6%2FdJMcaamJh3i%2FCxazlvxpsJ5Xijl6gVimiK%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;2400&quot; height=&quot;1720&quot; data-filename=&quot;06_failures-and-log.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실패 처리 셋과 기록, 검색 없음과 검색 실패와 모델 다운, 그리고 점수는 원값으로 남긴다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RAG을 붙이면 실패할 곳이 둘 더 생긴다. 검색과 모델이다. 내 시스템은 셋으로 나눠 처리한다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25.0775%; text-align: center;&quot;&gt;&lt;b&gt;상황&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 54.3798%; text-align: center;&quot;&gt;&lt;b&gt;봇이 하는 일&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20.5426%; text-align: center;&quot;&gt;&lt;b&gt;원칙&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25.0775%;&quot;&gt;검색 결과가 없다&lt;/td&gt;
&lt;td style=&quot;width: 54.3798%;&quot;&gt;&quot;관련 문서를 찾지 못했습니다&quot;를 포함해 답한다&lt;/td&gt;
&lt;td style=&quot;width: 20.5426%;&quot;&gt;근거 없는 답 금지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25.0775%;&quot;&gt;검색 자체가 실패했다&lt;/td&gt;
&lt;td style=&quot;width: 54.3798%;&quot;&gt;근거 없이 모델만 불러 답하고 실패를 기록한다&lt;/td&gt;
&lt;td style=&quot;width: 20.5426%;&quot;&gt;대화는 계속&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25.0775%;&quot;&gt;모델이 죽었거나 시간을 넘겼다&lt;/td&gt;
&lt;td style=&quot;width: 54.3798%;&quot;&gt;&quot;AI 응답을 잠시 사용할 수 없습니다&quot;를 내고 시나리오의 다음 상자로 간다&lt;/td&gt;
&lt;td style=&quot;width: 20.5426%;&quot;&gt;모델이 죽어도 봇은 산다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째가 지난 글들의 원칙과 같다. 봇이 멈춰도 전화는 살아야 하듯, 모델이 멈춰도 시나리오는 가야 한다. RAG과 모델은 시나리오 위에 얹힌 부품이지 시나리오의 바닥이 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처리만큼 중요한 것이 기록이다. 검색할 때마다 질문, 가장 가까운 조각의 점수, 고른 조각 수, 근거로 썼는지, 어느 문서의 조각이었는지를 가공하지 않은 원값으로 남긴다. 점수를 &quot;높음&amp;middot;낮음&quot;으로 바꿔 저장하면 나중에 기준값을 바꿀 때 과거를 다시 볼 수 없다. 원값이 쌓이면 세 가지 장표가 나온다. 근거를 쓴 답의 추이, 문서별 기여도(어느 문서가 답을 만드는가), 그리고 근거 없는 질문 목록이다. 마지막 것이 가장 쓸모 있다. 사용자가 물었는데 닮은 조각이 없었던 질문들이고, 다음에 올릴 문서가 무엇인지 알려 주는 목록이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;검색 시험 화면, 지식이 부족한 대목을 찾는다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;07_search-test.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmTi5u/dJMcaf9oJeg/Pg2uE2LdqalKvSMC4F5n41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmTi5u/dJMcaf9oJeg/Pg2uE2LdqalKvSMC4F5n41/img.png&quot; data-alt=&quot;검색 시험 화면, 질문 하나에 조각과 점수와 출처가 그대로 보인다 (점수는 예시)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmTi5u/dJMcaf9oJeg/Pg2uE2LdqalKvSMC4F5n41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmTi5u%2FdJMcaf9oJeg%2FPg2uE2LdqalKvSMC4F5n41%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;2400&quot; height=&quot;1560&quot; data-filename=&quot;07_search-test.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;검색 시험 화면, 질문 하나에 조각과 점수와 출처가 그대로 보인다 (점수는 예시)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지식 관리 화면에 검색 시험 상자를 하나 두었다. 질문을 넣으면 모델을 부르지 않고 검색만 돌려, 고른 조각의 본문과 점수와 출처 파일 이름을 그대로 보여 준다. 답이 이상할 때 가장 먼저 여는 화면이다. 질문을 넣어 보면 세 가지 중 하나가 보인다. 맞는 조각이 1등에 높은 점수로 있으면 검색은 정상이고 문제는 모델이나 지시문이다. 맞는 조각이 아래쪽에 낮은 점수로 있으면 청킹을 의심한다. 제목이 안 붙었거나, 조각이 너무 길어 여러 주제가 섞였거나, 질문의 표현과 문서의 표현이 다른 경우다. 맞는 조각이 아예 없으면 문서가 없는 것이고, 근거 없는 질문 목록에 같은 질문이 쌓여 있을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 화면이 있어야 RAG을 운영할 수 있다. 모델의 답만 보고는 어디가 틀렸는지 모른다. 답은 마지막 단계의 결과이고, 그 앞에 검색이 있고, 그 앞에 청킹이 있고, 그 앞에 문서가 있다. 시험 상자는 그 사슬을 거꾸로 올라가게 해 준다. 시나리오를 저작하는 사람이 문서를 올린 직후에 할 일도 이것이다. 사용자가 할 법한 질문을 다섯 개쯤 넣어 보고 1등 조각이 맞는지 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;모델은 바꿔 끼우고 문서는 안에 둔다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;08_adapter-switch.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kDy9R/dJMcahzxQg9/YhvdkT4TWKncrDwjPGyiiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kDy9R/dJMcahzxQg9/YhvdkT4TWKncrDwjPGyiiK/img.png&quot; data-alt=&quot;LLM 어댑터, 대화 모델은 스위치로 바꾸고 임베딩 모델은 고정한다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kDy9R/dJMcahzxQg9/YhvdkT4TWKncrDwjPGyiiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkDy9R%2FdJMcahzxQg9%2FYhvdkT4TWKncrDwjPGyiiK%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;2400&quot; height=&quot;1560&quot; data-filename=&quot;08_adapter-switch.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;LLM 어댑터, 대화 모델은 스위치로 바꾸고 임베딩 모델은 고정한다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 연결은 모델 쪽이다. &amp;ldquo;AI에게 물어본다&amp;rdquo;는 행위를 하나의 규격으로 정해 두고 실제 상대는 갈아 끼우는 구조를 어댑터(adapter)라 부른다. 규격은 셋이다. 질문을 주고 답 문장을 받는 것, 같은 일을 글자 조각 단위로 흘려 받는 것, 문장을 벡터로 바꾸는 것. 이 규격만 지키면 봇 엔진과 저작 도구의 코드는 한 글자도 바뀌지 않는다. 내 시스템은 인터넷 LLM API와 폐쇄망 안의 작은 언어 모델(sLLM, small large language model)을 이 규격 뒤에 두고, 설정값 하나와 화면의 토글로 바꾼다. 로컬 쪽은 llama.cpp의 llama-server를 서브프로세스로 띄우고 기본 모델로 Qwen3-8B를 쓴다. 시연에서는 같은 질문을 두 모델로 번갈아 보내고, 랜선을 뽑은 상태에서도 로컬 쪽이 답하는 것을 보여 준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스위치가 바꾸는 것은 대화 모델뿐이다. 임베딩 모델은 바꾸지 않는다. 임베딩 모델을 바꾸면 저장해 둔 모든 조각의 벡터와 인텐트 예문의 벡터가 전부 다시 계산 대상이 되기 때문이다. 같은 문장이라도 모델이 다르면 다른 숫자가 나와 서로 비교할 수 없다. 그래서 임베딩은 처음부터 별도 절차로 두고 로컬 모델 bge-m3로 고정했다. 대화 규격과 임베딩 규격을 처음부터 나눈 이유도 여기 있다. 인터넷 쪽 API 가운데 임베딩 기능이 없는 것이 있어서, 한 규격에 합치면 &quot;구현했지만 항상 실패하는 함수&quot;가 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폐쇄망에서는 임베딩도 로컬에서 돌린다. 그래야 문서가 박스 밖으로 나가지 않는다. 인터넷 모델을 쓰는 설정에서도 문서 조각은 질문이 올 때 근거로 보내지는 몇 개뿐이고, 문서 전체가 밖으로 나가는 일은 없다. 금융권처럼 문서를 밖에 둘 수 없는 곳에서 RAG을 쓸 수 있는 이유가 이 구조다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;학습시켜 주세요&quot;라는 말을 들으면 이제 이렇게 되묻는다. 모델이 그것을 기억하게 하고 싶은가, 아니면 그것을 읽고 답하게 하고 싶은가. 거의 언제나 뒤쪽이다. 문서는 바뀌고, 답에는 출처가 필요하고, 문서는 밖으로 나가면 안 된다. 세 조건 모두 가르치는 쪽이 아니라 건네는 쪽을 가리킨다. 내 시스템의 버튼 이름은 &quot;학습&quot;이지만 하는 일은 조각 내기와 저장이고, 모델은 질문이 올 때마다 처음 보는 문서를 읽는다. 연결은 결국 둘이었다. 시나리오의 상자 하나에 붙는 옵션과, 시나리오 밖으로 나간 말을 받아 주는 폴백. 그리고 그 둘을 운영하게 해 주는 것은 모델이 아니라 점수를 원값으로 남긴 기록과 검색 시험 화면이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글은 이 글이 건너뛴 두 곳으로 들어간다. 봇이 대화의 어디까지 왔는지 들고 있는 컨텍스트 하나로 한 편, 그리고 문서를 벡터로 바꾸는 방법과 벡터를 검색하는 방법과 실제로 쓴 사례로 한 편이다.&lt;/p&gt;</description>
      <category>tech</category>
      <category>AICC</category>
      <category>Chunking</category>
      <category>Embedding</category>
      <category>LLM</category>
      <category>RAG</category>
      <category>거대 언어 모델</category>
      <category>검색 증강 생성</category>
      <category>인공지능 컨택센터</category>
      <category>임베딩</category>
      <category>청킹</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/16</guid>
      <comments>https://hsjo.tistory.com/16#entry16comment</comments>
      <pubDate>Sat, 17 Oct 2026 18:10:17 +0900</pubDate>
    </item>
    <item>
      <title>답을 찾아 주던 봇이 일을 끝낸다, Agentic AICC</title>
      <link>https://hsjo.tistory.com/15</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;골든 케이블 자동화 워크플로우.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vSh0A/dJMcaiFgnWI/C063Dm8BEOtyHL0CkRLSY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vSh0A/dJMcaiFgnWI/C063Dm8BEOtyHL0CkRLSY1/img.png&quot; data-alt=&quot;목표를 받아 계획하고, 도구를 부르고, 실패하면 다시 계획하고, 사람에게 묻는다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vSh0A/dJMcaiFgnWI/C063Dm8BEOtyHL0CkRLSY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvSh0A%2FdJMcaiFgnWI%2FC063Dm8BEOtyHL0CkRLSY1%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;1672&quot; height=&quot;941&quot; data-filename=&quot;골든 케이블 자동화 워크플로우.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;목표를 받아 계획하고, 도구를 부르고, 실패하면 다시 계획하고, 사람에게 묻는다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;보험금 청구 진행 상황은 앱에서 확인하실 수 있습니다.&quot; 봇이 이렇게 답하면 고객은 앱을 연다. 봇은 답을 찾아 준 것이고, 일은 고객이 한다. 올해 4월에 왜 지금 컨택센터를 다시 설계하는가를 쓰면서 나는 컨택센터의 세 단계를 연결, 이해, 행동이라고 불렀다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전화를 맞는 팀에 연결하는 단계가 IPCC이고, 고객이 무엇을 묻는지 알아듣는 단계가 AICC이고, 알아들은 뒤에 청구 건을 조회하고 서류를 안내하고 콜백을 잡는 단계가 그다음이다. 그다음 단계에 붙는 이름이 에이전틱 AICC(스스로 움직이는 인공지능 컨택센터, Agentic AICC)다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;답을 찾는 단계에서 일을 끝내는 단계로 넘어가는 것, 그것이 이 말의 본질이다. 이 글은 그 봇이 전화의 길 위 어디에 서고, 안에서 무엇이 돌고, 어디에서 사람이 끼어드는지를 번호를 매겨 따라간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hsjo.tistory.com/14&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;지난 글&lt;/a&gt;에서 챗봇의 한 턴은 말을 받고, 뜻을 고르고, 다음을 정하고, 답을 내는 네 상자였다. 일을 끝내는 봇은 그중 셋째 상자가 달라진다. 사람이 그려 둔 흐름도에서 다음 상자를 고르는 대신, 목표를 받아 스스로 계획을 세우고 도구를 부르고 결과를 보고 다시 계획한다. 전화가 지나는 길은 그대로다. 고객이 대표번호를 누르면 통신사 지능망과 교환기와 CTI를 지나 IVR에 닿고, IVR이 버튼 대신 말을 받기로 하면 게이트웨이를 거쳐 봇 엔진에 들어오고, 봇이 끝내면 종료하고 못 끝내면 상담사에게 돌아간다. 이 글에서는 그 길을 1부터 9로 두고, 봇 엔진 안쪽에 10부터 14를 더한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;열네 단계, 봇 엔진 안에 다섯 단계가 더 생긴다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01_fourteen-steps.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kCnnC/dJMcahsTewQ/PibDrkkplmpStfNIm5E7Sk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kCnnC/dJMcahsTewQ/PibDrkkplmpStfNIm5E7Sk/img.png&quot; data-alt=&quot;열네 단계, 봇 엔진 안에서 계획하고 부르고 확인하고 묻고 돌려준다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kCnnC/dJMcahsTewQ/PibDrkkplmpStfNIm5E7Sk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkCnnC%2FdJMcahsTewQ%2FPibDrkkplmpStfNIm5E7Sk%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;2400&quot; height=&quot;1800&quot; data-filename=&quot;01_fourteen-steps.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1800&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;열네 단계, 봇 엔진 안에서 계획하고 부르고 확인하고 묻고 돌려준다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;⑩&amp;nbsp;봇 엔진 &amp;rarr; 오케스트레이터.&lt;/b&gt;&lt;/span&gt; 봇이 고객의 말에서 뜻을 골랐다. 그런데 그 뜻이 안내 한 문장으로 끝나지 않는다. &quot;실손 청구 서류를 냈는데 보완 요청이 왔어요&quot;가 그런 말이다. 왜 보완 요청이 왔는지 조회해야 하고, 무엇이 빠졌는지 안내해야 하고, 다시 낼 서류를 접수해야 한다. 이때 봇 엔진은 시나리오의 다음 상자를 고르는 대신, 그 말을 목표 한 문장으로 바꿔 오케스트레이터(지휘자, orchestrator)에게 넘긴다. &quot;이 고객의 청구 건에서 무엇이 부족한지 알아내고 다음 할 일을 끝내라.&quot; 지휘자가 필요한 이유는 간단하다. 시나리오는 사람이 미리 그려 둔 길만 간다. 조회해 봐야 할 일이 정해지는 목표는 길을 미리 다 그릴 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;⑪ 오케스트레이터 &amp;rarr; 도구.&lt;/b&gt;&lt;/span&gt; 지휘자는 목표를 받으면 계획을 세우고 첫 칸을 정한다. 첫 칸은 대개 조회다. 그 조회를 실제로 하는 것이 도구다. 상담 프로그램이 API(응용 프로그램 접속 규격, application programming interface)로 열어 둔 조회와 처리 기능 하나하나가 도구이고, 청구 건 조회, 서류 접수 케이스 생성, 콜백 예약이 각각 도구 하나다. 지휘자가 도구를 부르는 것을 도구 호출(tool call)이라 부른다. 에이전트는 스스로 아무것도 하지 못한다. 할 수 있는 일은 열린 도구의 목록까지다. 그래서 봇을 들이기 전에 상담 프로그램의 어떤 기능이 API로 열려 있는지를 먼저 본다. 봇은 센터의 보안망 안으로 들어가지 않는다. 센터가 안에서 API를 만들어 규격을 주면 봇이 그것을 쓴다. 처음부터 API가 열리는 센터는 드물다. 그래서 파일을 올려 돌리는 시험 운영을 먼저 하고, 효과를 본 뒤에 연동으로 가는 두 단계가 흔하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;⑫ 결과 확인 &amp;rarr; 다시 계획.&lt;/b&gt;&lt;/span&gt; 도구가 답을 돌려주면, 또는 정해진 시간 안에 돌려주지 않으면 지휘자가 결과를 읽는다. 읽은 뒤에 계획의 다음 칸을 정한다. 조회한 청구 건에 서류가 빠져 있으면 다음 칸은 서류 안내다. 조회가 실패했으면 다른 조건으로 다시 조회하거나, 그 일을 포기하고 사람에게 넘기는 쪽으로 계획을 바꾼다. 이 되돌아오는 화살표가 시나리오와 에이전트를 가르는 선이다. 시나리오는 실패하면 멈추거나 폴백으로 간다. 에이전트는 실패를 읽고 다시 계획한다. 정해진 시간 안에 답이 없을 때 무엇으로 돌아갈지도 여기서 정해 둔다. 시나리오가 원래 하던 답으로 돌아가고, 그런 일이 얼마나 잦은지 기록한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;⑬ 사람 승인 구간.&lt;/b&gt;&lt;/span&gt; 계획의 다음 칸이 되돌리기 어려운 일이면 지휘자는 실행하기 전에 멈춘다. 케이스를 만들고, 콜백을 잡고, 계약을 바꾸는 일이 그렇다. 고객에게 &quot;추가 서류 접수 케이스를 만들고 담당자 콜백을 내일로 잡겠습니다, 맞으세요&quot;라고 묻고 분명한 답을 받는다. 센터 안에서는 상담사가 승인하는 구간을 둘 수도 있다. 멈추는 이유는 알아듣는 것도 틀릴 수 있고 계획도 틀릴 수 있어서다. 승인 구간은 그 틀림을 사람이 잡는 자리다. 돈이 오가는 일을 봇의 판단만으로 실행하지 않는다는 것은 시나리오 봇에서나 에이전트에서나 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;⑭ 결과 보고 &amp;rarr; ⑨로 합류.&lt;/b&gt;&lt;/span&gt; 계획의 마지막 칸이 끝났거나, 지휘자가 더 할 수 없다고 판단하면 결과를 돌려준다. 끝났으면 무엇을 했는지 고객에게 말하고 종료한다. 못 끝냈으면 지휘자가 한 일과 못 한 일의 목록을 들고 상담사에게 넘긴다. 넘기는 주체는 여전히 게이트웨이와 교환기다. 에이전트가 멈춰도 전화는 살아야 하기 때문이다. 그리고 상담사 화면에 에이전트가 조회한 것과 만든 것이 떠야 고객이 같은 말을 두 번 하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전틱이라는 말에 들어 있어야 하는 세 가지&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02_tree-vs-agent.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1660&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lCvY8/dJMcaatH6mK/JfXc3NPfz5G0QQTdWWL721/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lCvY8/dJMcaatH6mK/JfXc3NPfz5G0QQTdWWL721/img.png&quot; data-alt=&quot;시나리오 트리는 그려 둔 분기를 따라가고, 에이전트는 계획하고 부르고 확인하고 다시 계획한다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lCvY8/dJMcaatH6mK/JfXc3NPfz5G0QQTdWWL721/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlCvY8%2FdJMcaatH6mK%2FJfXc3NPfz5G0QQTdWWL721%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;2400&quot; height=&quot;1660&quot; data-filename=&quot;02_tree-vs-agent.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1660&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;시나리오 트리는 그려 둔 분기를 따라가고, 에이전트는 계획하고 부르고 확인하고 다시 계획한다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올해 초 보고서를 쓰다가 에이전틱이라는 말을 어디까지 써도 되는지 정해야 했다. 봇에 큰 언어 모델을 붙이면 전부 에이전틱이라 부르는 자료가 많았다. 그때 내가 정한 기준은 셋이다. 추론(reasoning)이 있는가. 목표를 받아 지금 할 일을 스스로 고르는가. 재귀(recursive)가 있는가. 한 일의 결과를 다시 자기 입력으로 받는가. 루프(loop)가 있는가. 실패하면 스스로 다시 불러 재추론하고 재계획하는가. 셋 중 하나라도 없으면 그것은 큰 언어 모델을 붙인 시나리오 봇이지 에이전트가 아니다. 그리고 셋이 다 있어도 사람 승인 구간이 없으면 운영에 넣지 못한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시나리오 트리와 비교하면 차이가 분명하다. 트리는 사람이 그린 분기를 따라간다. 상자마다 할 말이 적혀 있고 화살표마다 조건이 적혀 있다. 조건에 없는 일이 생기면 폴백으로 간다. 에이전트는 상자가 아니라 목표와 도구를 받는다. 어느 도구를 어떤 순서로 부를지는 그때 정하고, 결과가 계획과 다르면 순서를 바꾼다. 트리가 나쁜 것이 아니다. 길이 정해진 일은 트리가 더 정확하고 더 싸다. 에이전트는 길을 미리 다 그릴 수 없는 일에만 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가상 보험사에서 열네 단계가 도는 모습&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03_insurance-case.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yLCtJ/dJMcag1yu6D/7XlvS12fpsd0ZEdbCUPSEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yLCtJ/dJMcag1yu6D/7XlvS12fpsd0ZEdbCUPSEk/img.png&quot; data-alt=&quot;청구 조회에서 콜백 예약까지, 도구 넷과 승인 구간 하나 (가상 보험사 예시)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yLCtJ/dJMcag1yu6D/7XlvS12fpsd0ZEdbCUPSEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyLCtJ%2FdJMcag1yu6D%2F7XlvS12fpsd0ZEdbCUPSEk%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;2400&quot; height=&quot;1560&quot; data-filename=&quot;03_insurance-case.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;청구 조회에서 콜백 예약까지, 도구 넷과 승인 구간 하나 (가상 보험사 예시)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보험사를 예로 드는 이유는 연결과 이해와 행동이 다 필요하기 때문이다. 고객의 말은 &quot;교통사고가 났는데 접수부터 하고 싶어요&quot;, &quot;실손 청구 서류를 이미 냈는데 왜 보완 요청이 왔는지 모르겠어요&quot;, &quot;갱신 보험료가 왜 올랐는지 설명 듣고 싶어요&quot;다. 버튼으로 끝나지 않는 말이다. 답을 찾아 주던 봇은 두 번째 고객에게 앱을 안내하고 끝났다. 일을 끝내는 봇은 이렇게 돈다. 봇이 말에서 &quot;청구 보완&quot;이라는 뜻을 고르고 지휘자에게 목표를 넘긴다(⑩). 지휘자가 청구 건 조회 도구를 부른다(⑪). 결과에 진단서가 빠져 있다. 다음 칸을 서류 안내로 정한다(⑫). 안내 뒤 고객이 &quot;그럼 다시 내야 하나요&quot;라고 묻는다. 지휘자가 추가 제출 케이스 생성과 담당자 콜백 예약을 계획하고, 실행 전에 고객에게 묻는다(⑬). 고객이 맞다고 하면 케이스 생성 도구와 콜백 예약 도구를 부르고, 둘 다 성공한 것을 확인한 뒤 무엇을 했는지 말하고 끊는다(⑭). 콜백 예약 도구가 실패하면 계획이 바뀐다. 케이스는 만들어졌고 콜백만 안 잡혔으니 그 상태 그대로 상담사에게 넘긴다. 상담사 화면에는 조회 결과와 만들어진 케이스 번호가 떠 있다. 이것은 가상의 예시이고 실제 센터의 흐름은 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2026년의 봇 구조에서 지휘자는 어디에 서는가&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04_roles-and-failure.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kKKrQ/dJMcacydNoF/9qk5Uq5moKxKicFu6VSpsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kKKrQ/dJMcacydNoF/9qk5Uq5moKxKicFu6VSpsk/img.png&quot; data-alt=&quot;보이스 게이트웨이와 의도 라우터와 대화 엔진, 그리고 짧은 &amp;quot;네&amp;quot;가 버려진 장면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kKKrQ/dJMcacydNoF/9qk5Uq5moKxKicFu6VSpsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkKKrQ%2FdJMcacydNoF%2F9qk5Uq5moKxKicFu6VSpsk%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;2400&quot; height=&quot;1720&quot; data-filename=&quot;04_roles-and-failure.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;보이스 게이트웨이와 의도 라우터와 대화 엔진, 그리고 짧은 &quot;네&quot;가 버려진 장면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 보이스봇을 뜯어 보면 세 덩어리로 나뉜다. 보이스 게이트웨이(voice gateway)는 소리를 받고, 말이 시작되고 끝나는 구간을 찾고, 음성인식과 음성합성을 돌린다. 의도 라우터(intent router)는 고객의 말에서 의도를 분류해 대화 엔진의 대화 API를 시작, 대화, 종료 순으로 부르고, &quot;응&quot;, &quot;그래요&quot;처럼 흩어진 긍정과 부정을 네와 아니오로 표준화해 엔진에 넘긴다. 제품마다 이 자리를 다른 이름으로 부르지만 하는 일은 같다. 대화 엔진(dialog engine)은 시나리오를 돌린다. 의도 라우터가 의도를 분류하려면 시나리오 이름과 업무 설명과 예문이 필요하고, 대화 엔진은 바깥과 잇기 전에 혼자서 세션을 만들고 대화하고 끝낼 수 있어야 한다. 이 글의 ⑩에서 ⑭까지를 맡는 지휘자는 의도 라우터 위에 선다고 나는 본다. 여러 시나리오와 도구 위에서 목표를 들고 있는 자리이고, 현장에서는 이 자리를 따로 담당으로 두기 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조에서 겪은 실패 하나를 적는다. 전화망 없이 봇을 시연하려고 스마트폰 앱으로 소리를 보내는 클라이언트를 만든 적이 있다. 통화망 마이크가 아니라 스마트폰 마이크라 주변 소음이 그대로 들어왔고, 음성 쪽에서 소음을 거르려고 짧은 발화를 예외로 처리해 둔 상태였다. 그 결과 고객의 짧은 &quot;네&quot;가 대화 API로 전달되지 않았고, 봇은 묵음으로 판정해 재질문을 반복하다가 횟수를 넘겨 통화를 끝냈다. 음성인식은 &quot;네&quot;를 제대로 받아 적었는데 그 글자가 봇까지 가지 않은 것이다. 당장은 시연 발화를 긴 문장으로 바꿔 넘겼다. 고치는 법은 음성 쪽의 예외 규칙과 의도 라우터의 긍정&amp;middot;부정 표준화 규칙을 같은 표에 적어 두고, 짧은 긍정 답이 어디서 버려지는지를 단계마다 로그로 보는 것이다. 덩어리가 셋이면 글자가 사라지는 자리도 셋이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;큰 언어 모델은 어느 상자에 들어가는가&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;05_llm-boxes.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ru5BV/dJMcagghp8m/5zzzJoziiUIpF8sZYqrXq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ru5BV/dJMcagghp8m/5zzzJoziiUIpF8sZYqrXq1/img.png&quot; data-alt=&quot;큰 언어 모델이 들어가는 상자와 들어가지 않는 상자&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ru5BV/dJMcagghp8m/5zzzJoziiUIpF8sZYqrXq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRu5BV%2FdJMcagghp8m%2F5zzzJoziiUIpF8sZYqrXq1%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;2400&quot; height=&quot;1280&quot; data-filename=&quot;05_llm-boxes.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1280&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;큰 언어 모델이 들어가는 상자와 들어가지 않는 상자&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큰 언어 모델(LLM, large language model)을 붙이면 봇이 에이전트가 되는 것이 아니다. 모델은 상자 하나에 들어가는 부품이고, 어느 상자에 넣는지가 설계다. 내가 모델을 넣는 상자는 둘이다. 뜻을 고르는 상자와 계획을 세우는 상자다. &quot;예&quot;와 &quot;아니오&quot;로 끝나지 않는 모호한 말, 예를 들어 &quot;서류를 냈는데 왜 또 내라는 건지&quot;를 해석하는 데 모델이 낫다. 목표를 받아 어느 도구를 먼저 부를지 정하는 데도 모델이 낫다. 넣지 않는 상자도 둘이다. 답을 내는 상자와 도구를 실행하는 상자다. 돈이 오가거나 규정이 있는 일의 답은 사람이 적어 둔 시나리오 문장으로 낸다. 모델은 없는 말을 지어낼 수 있고 정책을 어길 수 있다. 도구는 모델이 부르기로 정하는 것이지 모델이 실행하는 것이 아니다. 실행은 승인 구간을 지난 뒤 API가 한다. 음성 채널이라면 하나가 더 붙는다. 모델이 문장을 만들고 음성합성이 그것을 소리로 바꾸는 시간이 고객에게는 침묵이다. 그 침묵을 시나리오가 받아 주지 못하면 고객은 끊는다. 절차가 정해진 일은 시나리오로, 모호한 말의 해석은 모델로. 음성에서는 모델을 제한된 구간에만 둔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공개 문서가 에이전트를 나누는 방식도 같은 그림이다. 아마존커넥트(Amazon Connect) 관리자 안내서는 인공지능 에이전트를 네 유형으로 적고, 그중 에이전틱 셀프서비스는 오케스트레이터가 여러 단계를 거쳐 도구를 부르고 필요하면 사람에게 넘기는 방식이라고 설명한다. 출처는 AWS 공개 문서 &lt;a href=&quot;https://docs.aws.amazon.com/connect/latest/adminguide/create-ai-agents.html&quot;&gt;Create AI agents&lt;/a&gt;와 &lt;a href=&quot;https://docs.aws.amazon.com/connect/latest/adminguide/agentic-self-service.html&quot;&gt;Use agentic self-service&lt;/a&gt;다(2026-10-17 조회).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마무리&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올해 초에 세 단계를 연결, 이해, 행동이라고 쓸 때는 행동이 가장 먼 단계로 보였다. 6월에 AmazonConnect 개인 계정으로 인스턴스를 만들고 번호를 받아 첫 통화를 연결했을 때 나는 아직 첫 단계에 있었다. 지금은 행동 단계가 먼 것이 아니라 순서가 있는 것으로 보인다. 도구가 API로 열려 있는가, 승인 구간이 어디인가, 실패하면 무엇으로 돌아가는가. 이 셋이 정해지지 않은 센터에 모델을 붙이면 답을 더 길게 찾아 줄 뿐 일은 끝내지 못한다. 답을 찾아 주던 봇이 일을 끝내려면 모델이 아니라 이 셋이 먼저다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글들은 이 글의 상자 안으로 들어간다. 큰 언어 모델에 문서를 찾아 건네는 RAG(검색 증강 생성, retrieval-augmented generation)을 봇과 잇는 방법, 봇이 대화의 어디까지 왔는지 들고 있는 컨텍스트 하나만으로 한 편, 그리고 문서를 벡터로 바꾸고 벡터를 검색하고 실제로 쓴 사례까지. 하나씩 따로 쓴다.&lt;/p&gt;</description>
      <category>tech</category>
      <category>Agentic AICC</category>
      <category>ai agent</category>
      <category>ai 에이전트</category>
      <category>AICC</category>
      <category>orchestrator</category>
      <category>Tool Call</category>
      <category>도구 호출</category>
      <category>에이전틱 AICC</category>
      <category>오케스트레이터</category>
      <category>인공지능 컨택센터</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/15</guid>
      <comments>https://hsjo.tistory.com/15#entry15comment</comments>
      <pubDate>Sat, 17 Oct 2026 09:11:25 +0900</pubDate>
    </item>
    <item>
      <title>플랫폼이 달라도 챗봇을 움직이는 말은 같다, 챗봇 용어 정리</title>
      <link>https://hsjo.tistory.com/14</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;세 가지 AI 파이프라인 장치.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RELyb/dJMcacrygdd/tTCwNIidSR8AsOEeff1WKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RELyb/dJMcacrygdd/tTCwNIidSR8AsOEeff1WKk/img.png&quot; data-alt=&quot;다른 상자, 같은 부품&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RELyb/dJMcacrygdd/tTCwNIidSR8AsOEeff1WKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRELyb%2FdJMcacrygdd%2FtTCwNIidSR8AsOEeff1WKk%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;1672&quot; height=&quot;941&quot; data-filename=&quot;세 가지 AI 파이프라인 장치.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다른 상자, 같은 부품&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;챗봇 일을 처음 맡은 사람이 저작 도구를 열면 화면 왼쪽에 낯선 말이 줄지어 있다. 인텐트, 엔티티, 슬롯, 폴백, 컨텍스트. 어떤 도구는 같은 것을 의도, 개체, 파라미터, 미인식 응답, 문맥이라고 부른다. 영문으로 배운 사람과 한글로 배운 사람이 같은 회의에서 다른 말을 쓰고, 둘 다 맞다. 내가 처음 겪은 혼란도 그것이었다. 도구가 어려운 것이 아니라 말이 두 벌이었다. 이 글은 그 말을 한 벌로 묶는다. 챗봇을 어떤 플랫폼으로 만들든 부품은 같고 이름만 다르다. 그래서 용어마다 한글과 영문을 함께 적는다. 한국어로 만났을 때와 영문으로 만났을 때 느낌이 다르고, 둘 다 알아야 한 가지를 아는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hsjo.tistory.com/13&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;지난 글&lt;/a&gt;까지 보이스봇과 거는 봇을 전화의 길 위에서 봤다. 이 글은 그 봇들의 안쪽, 글자를 다루는 부분의 말을 정리한다. 전화와 교환기 같은 인프라 용어와 상담사를 돕는 인공지능의 용어는 여기 없다. 오직 챗봇의 말이다. 보이스봇은 챗봇에 귀와 입을 붙인 것이라 마지막 절에 보이스봇에만 있는 말을 덧붙인다. 여섯 묶음, 순서는 봇이 말을 받아 답을 내기까지의 순서다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 챗봇이 무엇인가&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01_one-turn.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1120&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XwXFq/dJMcaiSNmTm/oeLmy0vxRnyEqzh8ALFlb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XwXFq/dJMcaiSNmTm/oeLmy0vxRnyEqzh8ALFlb0/img.png&quot; data-alt=&quot;챗봇의 한 턴, 발화에서 답까지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XwXFq/dJMcaiSNmTm/oeLmy0vxRnyEqzh8ALFlb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXwXFq%2FdJMcaiSNmTm%2FoeLmy0vxRnyEqzh8ALFlb0%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;2400&quot; height=&quot;1120&quot; data-filename=&quot;01_one-turn.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1120&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;챗봇의 한 턴, 발화에서 답까지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;챗봇(대화 로봇, chatbot).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 사람의 말을 받아 정해진 방식으로 답하는 프로그램이다. 이름에 &quot;봇&quot;이 붙었다고 스스로 생각하지 않는다. 사람이 미리 적어 둔 뜻의 목록과 대화의 흐름을 따라간다. 챗봇을 잘 만든다는 것은 똑똑한 프로그램을 고르는 일이 아니라 목록과 흐름을 잘 적는 일이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;대화형 인터페이스(conversational interface, CUI).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 버튼과 메뉴 대신 말로 조작하는 방식이다. 챗봇은 그 한 종류다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;턴(한 번 주고받기, turn).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 사용자가 한 번 말하고 봇이 한 번 답하는 것이 한 턴이다. 한 턴 안에서 봇이 하는 일은 넷이다. 말을 받고, 뜻을 알아내고, 다음에 할 일을 고르고, 답을 만든다. 도식 1이 그 한 턴이고, 이 글의 모든 용어가 이 네 상자 중 어딘가에 들어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;대화(다이얼로그, dialog).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 턴이 여러 번 이어진 것이다. 그런데 어떤 플랫폼은 다이얼로그라는 말을 시나리오 한 덩어리의 이름으로 쓴다. 쓰려는 플랫폼의 사용 설명서에서 어느 뜻인지 먼저 확인한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;규칙형, 시나리오형, 인공지능형, 생성형(rule-based, scenario-based, AI-based, generative).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇을 나누는 흔한 네 이름이다. 규칙형은 정해진 단어가 보이면 정해진 답을 낸다. 시나리오형은 사람이 그린 흐름도를 따라간다. 인공지능형은 말의 뜻을 모델이 고르고, 답은 여전히 사람이 적은 것을 낸다. 생성형은 답까지 모델이 만든다. 현장의 봇은 대개 시나리오형과 인공지능형의 섞임이다. 뜻은 모델이 고르고 흐름과 답은 사람이 적는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;웰컴 메시지(인사말, welcome message, intro).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇이 먼저 하는 첫 말이다. 인트로, 웰컴 인텐트, 시작 노드라고도 부른다. 여기서 봇이 할 수 있는 일을 한 줄로 말해 주지 않으면 사용자는 아무 말이나 하고 봇은 못 알아듣는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;종료 메시지(end message).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇이 대화를 닫는 말이다. 채팅 창은 전화와 달리 끊어지지 않아서 닫는 자리를 따로 둔다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;스몰토크(잡담, small talk).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; &quot;고마워&quot;, &quot;너 누구야&quot; 같은 업무 밖의 말에 답하는 작은 묶음이다. 없어도 봇은 돌아가지만 있으면 덜 차갑다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 말을 알아 듣는 것&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02_utterance-intent-entity-slot.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1540&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xm6m0/dJMcabeOz46/fBF2WEJzn65crJPhHzS3JK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xm6m0/dJMcabeOz46/fBF2WEJzn65crJPhHzS3JK/img.png&quot; data-alt=&quot;한 문장이 인텐트와 엔티티와 슬롯으로 나뉜다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xm6m0/dJMcabeOz46/fBF2WEJzn65crJPhHzS3JK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxm6m0%2FdJMcabeOz46%2FfBF2WEJzn65crJPhHzS3JK%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;2400&quot; height=&quot;1540&quot; data-filename=&quot;02_utterance-intent-entity-slot.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1540&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;한 문장이 인텐트와 엔티티와 슬롯으로 나뉜다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;발화(사용자가 한 말, utterance, user input).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 사용자가 한 턴에 친 글자 한 덩어리다. &quot;내일 오후 세 시에 강남점 예약해 줘&quot;가 발화 하나다. 봇은 이 문장을 그대로 이해하지 않는다. 두 가지로 쪼갠다. 무엇을 하려는가와 그 일에 필요한 값은 무엇인가. 앞이 인텐트, 뒤가 엔티티다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;인텐트(의도, intent).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 발화가 하려는 일의 이름이다. &quot;예약&quot;, &quot;예약 변경&quot;, &quot;영업시간 문의&quot;처럼 사람이 미리 정해 둔 목록에서 하나가 골라진다. 봇이 알아듣는다는 말은 발화를 이 목록의 한 칸에 넣는다는 뜻이다. 목록에 없는 일은 아무리 말해도 봇에게는 없는 일이다. 그래서 봇을 만들 때 가장 먼저 쓰는 문서가 인텐트 목록이고, 업무 하나가 인텐트 하나다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03_intent-list.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNXq1e/dJMcag1wri4/hEbpKKY81RxF7kVXjvPQy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNXq1e/dJMcag1wri4/hEbpKKY81RxF7kVXjvPQy1/img.png&quot; data-alt=&quot;인텐트 목록의 예, 업무 하나가 인텐트 하나&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNXq1e/dJMcag1wri4/hEbpKKY81RxF7kVXjvPQy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNXq1e%2FdJMcag1wri4%2FhEbpKKY81RxF7kVXjvPQy1%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;2400&quot; height=&quot;1480&quot; data-filename=&quot;03_intent-list.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1480&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;인텐트 목록의 예, 업무 하나가 인텐트 하나&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;예문(학습 발화, training phrases, sample utterances).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 인텐트마다 적어 두는 &quot;이렇게 말하면 이 인텐트&quot;의 보기 문장이다. &quot;예약하고 싶어요&quot;, &quot;자리 있나요&quot;, &quot;내일 갈 수 있을까요&quot;가 모두 예약 인텐트의 예문이다. 어미만 바꾼 문장을 늘리는 것은 소용이 없고, 실제 고객이 쓰는 짧은 문장을 열 개 안팎 넣는 것이 낫다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;의도 분류(intent classification).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 발화를 인텐트 목록 중 하나로 고르는 일이다. 모델이 하고, 인식이나 매칭이라고도 부른다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;신뢰도(confidence score)와 임계값(threshold).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 모델은 인텐트를 고를 때 &quot;이 인텐트일 확률&quot;을 함께 낸다. 그것이 신뢰도다. 정해 둔 선, 곧 임계값보다 낮으면 봇은 골랐어도 모른다고 한다. 임계값을 올리면 틀린 답이 줄고 모르는 답이 는다. 이 한 숫자가 봇의 성격을 정한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;미인식과 오인식(no match, misrecognition).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 미인식은 어느 인텐트도 고르지 못한 것이고, 오인식은 다른 인텐트를 고른 것이다. 미인식은 폴백으로 가고, 오인식은 엉뚱한 답으로 간다. 운영에서 더 아픈 쪽은 오인식이다. 사용자는 봇이 모른다고 할 때보다 자신 있게 틀릴 때 떠난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;엔티티(개체, entity).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 발화 안에서 뽑아내는 값이다. &quot;내일&quot;, &quot;오후 세 시&quot;, &quot;강남점&quot;이 엔티티다. 값의 종류마다 이름이 있고 엔티티 타입, 슬롯 타입이라고도 부른다. 인텐트가 &quot;무엇을&quot;이면 엔티티는 &quot;어떤 값으로&quot;다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;시스템 엔티티와 사용자 정의 엔티티(system entity, custom entity).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 날짜, 시간, 숫자, 전화번호처럼 플랫폼이 미리 만들어 둔 것이 시스템 엔티티다. 지점 이름, 상품 이름처럼 그 봇에만 있는 값은 사용자가 목록으로 만든다. 사용자 정의 엔티티의 목록이 곧 그 봇이 아는 세상의 범위다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;유의어 사전(동의어, synonyms).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 같은 값을 가리키는 다른 표기를 묶는 목록이다. &quot;강남점&quot;, &quot;강남&quot;, &quot;강남 지점&quot;을 하나의 값으로 본다. 음성인식이 자주 틀리는 발음도 여기에 넣어 두면 봇이 알아듣는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;정규식 엔티티(regex entity).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 주문 번호처럼 모양이 정해진 값을 &quot;숫자 여덟 자리&quot; 같은 글자 패턴으로 뽑는 방식이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;슬롯(빈칸, slot).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 인텐트 하나를 처리하려면 반드시 있어야 하는 값의 자리다. 예약 인텐트에는 날짜, 시간, 지점, 인원이라는 네 칸이 있다. 엔티티는 발화에서 뽑은 값이고 슬롯은 그 값이 들어갈 자리다. 플랫폼에 따라 슬롯과 파라미터를 같은 뜻으로 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;슬롯 필링(빈칸 채우기, slot filling).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 발화에서 뽑은 엔티티로 슬롯을 채우고, 비어 있는 칸은 봇이 되물어 채우는 과정이다. &quot;내일 오후 세 시에 강남점 예약해 줘&quot;에는 인원이 없다. 그래서 봇이 &quot;몇 분이세요&quot;라고 묻는다. 이 되묻는 문장이 슬롯 질문이다. 슬롯 필링이 끝나야 인텐트가 실행된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;필수 슬롯과 선택 슬롯(required slot, optional slot).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 없으면 일을 할 수 없는 칸과 없어도 되는 칸이다. 필수가 많을수록 봇은 많이 묻고 사용자는 빨리 지친다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;슬롯 질문(프롬프트, slot prompt).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 빈 슬롯을 채우려고 봇이 하는 질문이다. 플랫폼에서 프롬프트라고 부르는 경우가 많은데, 생성형 봇에서 말하는 프롬프트와는 다른 뜻이다. 같은 단어가 두 가지 뜻으로 쓰이는 대표적인 예라 처음 보는 사람이 가장 많이 헷갈린다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04_slot-form.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oftC0/dJMcafuS86I/GkSrZ3KH34rFWPld5BakZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oftC0/dJMcafuS86I/GkSrZ3KH34rFWPld5BakZ1/img.png&quot; data-alt=&quot;슬롯은 신청서의 빈칸이다, 문장에서 꺼내 쓰고 없으면 묻는다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oftC0/dJMcafuS86I/GkSrZ3KH34rFWPld5BakZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoftC0%2FdJMcafuS86I%2FGkSrZ3KH34rFWPld5BakZ1%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;2400&quot; height=&quot;1600&quot; data-filename=&quot;04_slot-form.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;슬롯은 신청서의 빈칸이다, 문장에서 꺼내 쓰고 없으면 묻는다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;자연어 이해(NLU, natural language understanding).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 발화에서 인텐트와 엔티티를 뽑는 일 전체를 부르는 이름이다. 이 묶음의 용어는 거의 다 자연어 이해 안의 말이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;자연어 처리(NLP, natural language processing).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 글자를 다루는 기술 전체의 이름이다. 띄어쓰기를 고치고, 낱말을 쪼개고, 오타를 바로잡는 일부터 검색까지 넓게 가리킨다. 자연어 이해는 자연어 처리 안의 한 갈래다. 봇에서는 자연어 처리가 글자를 다듬고 자연어 이해가 뜻을 고른다고 나누어 보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;형태소 분석과 토큰화(morphological analysis, tokenization).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇은 문장을 통째로 보지 않고 조각으로 쪼개서 본다. 그 조각중 뜻을 가진 가장 작은 단위가 형태소(morpheme)다. &quot;예약해줘&quot;는 한 덩어리로 보이지만 안에는 &quot;예약&quot;(일의 이름), &quot;하&quot;(한다는 동작), &quot;어&quot;와 &quot;주&quot;와 &quot;어&quot;(부탁하는 말투)라는 형태소가 들어 있다. 더 쪼개면 뜻이 사라지는 지점까지 쪼갠 것이 형태소이고, 그래서 &quot;예&quot;와 &quot;약&quot;으로는 나누지 않는다. 문장을 조각으로 쪼개는 일이 토큰화이고, 쪼갠 조각마다 &quot;이것은 명사, 이것은 어미&quot;처럼 역할을 붙이는 일이 형태소 분석이다. 한국어에서 이 일이 특히 중요한 이유가 있다. &quot;예약해줘&quot;, &quot;예약해 주세요&quot;, &quot;예약할게요&quot;는 글자로 보면 서로 다른 세 문장이지만, 쪼개면 셋 다 &quot;예약&quot;이라는 같은 조각을 품고 있다. 쪼개지 않으면 모델에게 이 셋은 다른 글자 덩어리이고, 쪼개면 같은 뜻이다. 영어는 띄어쓰기가 단어를 나눠 주지만 한국어는 조사와 어미가 단어에 붙어 있어 쪼개는 단계가 따로 필요하다. 플랫폼이 알아서 하지만, 사전에 없는 말은 엉뚱하게 쪼개진다. 새로 생긴 지점 이름이 &quot;판교&quot;와 &quot;점&quot;으로 갈라지면 지점 값이 뽑히지 않는다. 봇이 어떤 말을 못 알아듣는다고 할 때 원인의 하나가 여기 있고, 고치는 법은 그 말을 사용자 정의 엔티티나 유의어 사전에 넣어 한 조각으로 보게 하는 것이다. 도식 5가 이 과정이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;05_tokenization.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DqthO/dJMcafhp8dO/GkIoJMdRK6an2fMS8Ir3ok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DqthO/dJMcafhp8dO/GkIoJMdRK6an2fMS8Ir3ok/img.png&quot; data-alt=&quot;붙어 있는 말을 쪼개야 같은 뜻이 보인다, 토큰화와 형태소 분석&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DqthO/dJMcafhp8dO/GkIoJMdRK6an2fMS8Ir3ok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDqthO%2FdJMcafhp8dO%2FGkIoJMdRK6an2fMS8Ir3ok%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;2400&quot; height=&quot;1560&quot; data-filename=&quot;05_tokenization.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;붙어 있는 말을 쪼개야 같은 뜻이 보인다, 토큰화와 형태소 분석&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;키워드 매칭과 의미 이해(keyword matching, semantic understanding).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; &quot;예약&quot;이라는 글자가 있으면 예약 인텐트로 보내는 것이 키워드 매칭, 글자가 없어도 &quot;내일 자리 있을까요&quot;를 예약으로 보내는 것이 의미 이해다. 예문이 적으면 모델도 키워드 매칭처럼 군다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;학습 데이터와 모델, 학습(training data, model, training).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 인텐트마다 적어 둔 예문과 엔티티 목록을 모두 합친 것이 학습 데이터다. 봇에게 &quot;이런 말은 이 뜻&quot;이라고 가르치는 교재다. 이 교재를 통째로 읽혀서 만든 결과물이 모델이다. 모델은 예문 목록 자체가 아니라 예문을 많이 본 뒤에 생긴 판단 기준이다. 그래서 교재에 없는 문장 &quot;내일 갈 수 있을까요&quot;가 와도 가장 가까운 인텐트인 예약을 고를 수 있다. 교재로 기준을 만드는 과정이 학습이고, 저작 도구의 학습 또는 빌드 버튼이 그것이다. 교재를 고쳐도 다시 읽히기 전에는 기준이 바뀌지 않는다. 처음 만드는 사람이 가장 자주 하는 실수가 예문을 고치고 학습을 안 누르는 것이다. 고친 것이 테스트에 보이지 않는 이유가 그것이다. 도식 6이 이 관계다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;06_training.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K3v9T/dJMcahl5Inn/7gkvoUt4J3t1GZjMk6kIBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K3v9T/dJMcahl5Inn/7gkvoUt4J3t1GZjMk6kIBk/img.png&quot; data-alt=&quot;학습 데이터는 교재, 모델은 그 교재로 생긴 판단 기준&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K3v9T/dJMcahl5Inn/7gkvoUt4J3t1GZjMk6kIBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK3v9T%2FdJMcahl5Inn%2F7gkvoUt4J3t1GZjMk6kIBk%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;2400&quot; height=&quot;1520&quot; data-filename=&quot;06_training.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;학습 데이터는 교재, 모델은 그 교재로 생긴 판단 기준&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인식률 재는 법(정확도, accuracy)과 테스트 세트(test set). 봇이 얼마나 잘 알아듣는지를 숫자로 재는 법은 시험과 같다. 먼저 시험지를 만든다. 실제 사용자가 한 발화를 모아 사람이 문장마다 정답 인텐트를 적어 둔 묶음이 테스트 세트다. 그 시험지를 봇에게 풀게하고, 봇이 고른 인텐트가 정답과 같으면 맞음, 다르면 틀림으로 센다. 다른 인텐트를 고른 오인식도, 아무것도 못 고른 미인식도 똑같이 틀림이다. 공식은 하나다. 인식률은 맞힌 발화 수를 전체 발화 수로 나누고 100을 곱한 값이다. 예를 들어 발화 열 개 중 여덟 개를 맞히면 8 &amp;divide; 10 &amp;times; 100으로 80퍼센트다. 인텐트별로도 따로 세어, 주차 인텐트만 낮으면 주차 예문을 보탠다. 여기서 지켜야 할 것이 하나 있다. 시험지는 교재와 달라야 한다. 학습에 쓴 예문을 시험지로 쓰면 봇은 이미 본 문제를 푸는 것이라 거의 다 맞히고, 그 숫자는 아무 뜻이 없다. 그래서 테스트 세트는 학습에 넣지 않은 실제 발화로 만들고, 봇을 고칠 때마다 같은 시험지로 다시 본다. 점수가 떨어지면 고친 것이 다른 인텐트를 흔든 것이다. 도식 7이 시험지와 공식이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;07_accuracy.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgVRPr/dJMcaiSNoYA/e64SHvOUs06btFibQQjFI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgVRPr/dJMcaiSNoYA/e64SHvOUs06btFibQQjFI0/img.png&quot; data-alt=&quot;인식률은 시험지로 잰다, 맞힌 수를 전체 수로 나눈다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgVRPr/dJMcaiSNoYA/e64SHvOUs06btFibQQjFI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgVRPr%2FdJMcaiSNoYA%2Fe64SHvOUs06btFibQQjFI0%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;2400&quot; height=&quot;1640&quot; data-filename=&quot;07_accuracy.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;인식률은 시험지로 잰다, 맞힌 수를 전체 수로 나눈다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 대화를 설계하는 것&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;08_flow-nodes-fallback.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brll8l/dJMcafBG0WO/jkTKnWuMMDacSk07JoAjak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brll8l/dJMcafBG0WO/jkTKnWuMMDacSk07JoAjak/img.png&quot; data-alt=&quot;시나리오의 노드와 분기와 재질문과 컨펌과 폴백&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brll8l/dJMcafBG0WO/jkTKnWuMMDacSk07JoAjak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbrll8l%2FdJMcafBG0WO%2FjkTKnWuMMDacSk07JoAjak%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;2400&quot; height=&quot;1520&quot; data-filename=&quot;08_flow-nodes-fallback.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;시나리오의 노드와 분기와 재질문과 컨펌과 폴백&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;시나리오(대화 흐름, scenario, flow, story, dialog).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 인텐트가 정해진 뒤 봇이 밟는 순서를 그린 흐름도다. 플랫폼마다 플로우, 스토리, 다이얼로그, 대화 흐름이라고 부른다. 상자와 화살표로 그리고, 상자마다 봇이 할 말이나 할 일이 적혀 있다. 인텐트 하나에 시나리오 하나가 기본이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;노드(상자, node, block, step).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 시나리오의 상자 하나다. 말하는 노드, 묻는 노드, 조건을 보는 노드, 바깥 시스템을 부르는 노드가 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;분기(조건, branch, condition).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 값에 따라 길이 갈리는 노드다. &quot;인원이 넷을 넘으면 단체 예약 시나리오로&quot;처럼 적는다. 분기가 많을수록 봇은 정확해지고 흐름도는 읽기 어려워진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;파라미터(변수, parameter, variable).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 대화 중에 봇이 기억해 두는 값이다. 슬롯에서 채운 값, 바깥 시스템에서 받은 값, 분기에 쓸 표시가 여기에 들어간다. 어떤 값이 어디서 들어와 어디서 쓰이는지 표로 적어 두지 않으면 시나리오가 커질 때 아무도 손대지 못한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;컨텍스트(문맥, context).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 대화가 어디까지 왔는지를 봇이 들고 있는 상태다. &quot;몇 분이세요&quot; 뒤에 온 &quot;넷&quot;이 인원이라는 것을 아는 것이 컨텍스트다. 없으면 봇은 턴마다 처음 만난 사람처럼 군다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;세션(한 번의 대화, session)과 세션 만료(session timeout).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 대화를 시작해 끝낼 때까지가 한 세션이다. 일정 시간 말이 없으면 세션이 끝나고 컨텍스트와 파라미터가 지워진다. 너무 짧으면 잠깐 자리를 비운 사용자가 처음부터 다시 하고, 너무 길면 어제 대화가 오늘 이어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;싱글턴과 멀티턴(single-turn, multi-turn).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 한 턴에 끝나는 대화와 여러 턴이 이어져야 끝나는 대화다. &quot;영업시간 알려 줘&quot;는 싱글턴이고 예약은 멀티턴이다. 멀티턴을 만들려면 컨텍스트와 슬롯 필링이 있어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;재질문(다시 묻기, re-prompt).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇이 물었는데 답이 없거나 못 알아들을 답일 때 다시 묻는 것이다. 몇 번까지 묻고 그 뒤 어디로 보낼지를 저작 전에 정한다. 재질문 문장은 원래 질문과 달라야 한다. 같은 말을 두 번 들으면 사용자는 봇이 고장 났다고 느낀다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;컨펌(재확인, confirmation).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 실행 전에 &quot;내일 오후 세 시 강남점 네 분, 맞으세요&quot;라고 한 번 더 묻는 노드다. 되돌리기 어려운 일, 돈이 오가는 일 앞에는 반드시 둔다. 알아듣는 것은 틀릴 수 있고, 컨펌은 그 틀림을 사용자가 잡게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;폴백(못 알아들었을 때의 답, fallback).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 미인식일 때 봇이 하는 말과 가는 길이다. 디폴트 폴백 인텐트, 미인식 응답, 노 매치라고도 부른다. &quot;다시 말씀해 주세요&quot;만 적어 두면 사용자는 같은 말을 반복하고 또 폴백을 본다. 좋은 폴백은 할 수 있는 일을 버튼으로 보여 주고, 반복되면 사람에게 넘긴다. 폴백이 얼마나 자주 나오는지가 봇의 건강 지표다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;09_common-intent-interrupt.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwlBHM/dJMcahMXfHM/ll06OeHBMbwSXlmgobpVk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwlBHM/dJMcahMXfHM/ll06OeHBMbwSXlmgobpVk1/img.png&quot; data-alt=&quot;공통 의도와 끼어들기, 옆길로 갔다가 돌아온다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwlBHM/dJMcahMXfHM/ll06OeHBMbwSXlmgobpVk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwlBHM%2FdJMcahMXfHM%2Fll06OeHBMbwSXlmgobpVk1%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;2400&quot; height=&quot;1320&quot; data-filename=&quot;09_common-intent-interrupt.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1320&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;공통 의도와 끼어들기, 옆길로 갔다가 돌아온다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;공통 의도(글로벌 인텐트, global intent, common intent).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 어느 시나리오를 진행 중이든 알아들어야 하는 말이다. &quot;처음으로&quot;, &quot;이전으로&quot;, &quot;다시 말해 줘&quot;, &quot;상담원 연결&quot;이 그것이다. 시나리오마다 따로 적지 않고 한 곳에 두고 어디서나 걸리게 한다. 어떤 시나리오에서는 걸리면 안 되는 경우가 있어 범위를 정해 둔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;끼어들기(돌발 발화, interruption, digression).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 예약을 진행하다가 사용자가 &quot;주차는 되나요&quot;라고 딴 질문을 하는 경우다. 봇이 답하고 다시 &quot;몇 분이세요&quot;로 돌아오면 끼어들기를 처리한 것이다. 돌아올 때 채운 슬롯이 지워지는 플랫폼이 있어 규칙을 먼저 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;이어하기, 처음으로, 이전으로(resume, restart, goback).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 이어하기는 끊긴 대화를 아까 자리에서 계속하는 것이고, 처음으로는 세션을 지우고 웰컴으로, 이전으로는 바로 앞 노드로 가는 공통 의도다. 이전으로는 봇이 지나온 노드를 기억해야 해서 플랫폼이 지원하는지 먼저 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;해피패스와 예외경로(happy path, exception path).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 사용자가 봇이 바라는 대로 답해서 끝까지 가는 길이 해피 패스, 안 하거나 못 알아듣거나 바깥 시스템이 오류를 낼 때 가는 길이 예외 경로다. 처음 만드는 시나리오는 해피 패스만 있고, 운영에서 사용자가 걷는 길은 대부분 예외 경로다. 흐름도에 예외 경로를 그려 두지 않으면 봇이 어디서 멈추는지 아무도 모른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;페르소나(봇의 성격, persona)와 톤앤매너(tone and manner).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇의 성격을 한 장에 적은 문서가 페르소나 정의서다. 봇 이름, 역할 한 줄, 말투(존댓말인지, 요체와 니다체의 비율, 한 문장 길이), 하지 않는 말, 모를 때 하는 말, 첫인사와 끝인사, 그리고 같은 뜻의 문장을 이 말투로 고친 예를 적는다. 여러 사람이 시나리오를 나눠 쓰면 노드마다 말투가 달라지는데, 정의서가 그것을 막는다. 시나리오를 쓰기 전에 먼저 만들고, 저작 중에 계속 보탠다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;대화 설계서(VUX, CUX, conversation design document).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 시나리오 하나를 저작 도구에 옮기기 전에 종이 위에 다 그려 둔 문서다. 다섯 묶음으로 쓴다. 흐름도(노드∙분기∙예외 경로를 화살표로), 노드별 문장표(노드 번호, 봇 문장, 받는 답, 다음 노드), 파라미터 표(이름, 어디서 오나, 어디서 쓰나), 예외 경로표(상황, 멘트, 어디로 보내나), 연동 표(API 이름, 보내는 값, 받는 값). 표지에 시나리오 이름과 인텐트와 버전을 적는다. 음성이면 VUX(voice user experience), 글자면 CUX(conversational user experience)라고 부른다. 저작 전에 확정해야 저작이 두 번 되지 않는다. 도식 10이 정의서 한 장과 설계서 다섯 묶음이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;10_persona-design-doc.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wDFzK/dJMcaikUs4I/uHwTjabvtKlJM290JLlc41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wDFzK/dJMcaikUs4I/uHwTjabvtKlJM290JLlc41/img.png&quot; data-alt=&quot;페르소나 정의서 한 장과 대화 설계서 다섯 묶음&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wDFzK/dJMcaikUs4I/uHwTjabvtKlJM290JLlc41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwDFzK%2FdJMcaikUs4I%2FuHwTjabvtKlJM290JLlc41%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;2400&quot; height=&quot;1680&quot; data-filename=&quot;10_persona-design-doc.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1680&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;페르소나 정의서 한 장과 대화 설계서 다섯 묶음&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. 답하는 방식&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;11_answer-types.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFu5cL/dJMcafIzKHr/PPQpqN5kphYD5npNc94sNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFu5cL/dJMcafIzKHr/PPQpqN5kphYD5npNc94sNK/img.png&quot; data-alt=&quot;답하는 방식 네 가지와 하이브리드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFu5cL/dJMcafIzKHr/PPQpqN5kphYD5npNc94sNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFu5cL%2FdJMcafIzKHr%2FPPQpqN5kphYD5npNc94sNK%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;2400&quot; height=&quot;1200&quot; data-filename=&quot;11_answer-types.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;답하는 방식 네 가지와 하이브리드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;텍스트 응답(text response).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇이 글자로 내는 답이다. 채팅 창에서 긴 글은 읽히지 않으니 한 번에 길게 쓰지 않는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;응답 템플릿과 변수 치환(response template, variable substitution).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; &quot;{지점} {날짜} 예약이 완료되었습니다&quot;처럼 빈칸에 파라미터 값을 끼워 답을 만드는 방식이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;리치 메시지(rich message).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 글자가 아닌 답의 묶음이다. 버튼(button)은 고르게 하고, 카드(card)는 제목과 그림과 버튼을 한 상자에 담고, 캐러셀(carousel)은 카드를 옆으로 넘기게 하고, 퀵 리플라이(quick reply)는 입력창 위에 짧은 선택지를 띄운다. 채널마다 지원이 달라 같은 봇이 웹에서는 캐러셀을, 메신저에서는 글자만 보여 주기도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;입력 폼(form).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 날짜 선택처럼 글자 대신 위젯으로 값을 받는 방식이다. 슬롯 필링을 화면으로 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;동적 노드(API 연동, dynamic node, API call).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 바깥 시스템에 묻고 그 답으로 말을 만드는 노드다. 예약 가능한 시간을 조회하고 예약을 실제로 넣는 일이 여기서 일어난다. 봇이 &quot;일을 끝낸다&quot;는 말은 이 노드가 있다는 뜻이다. 바깥 시스템이 아직 없을 때는 가짜 값을 넣어 두고 시나리오를 먼저 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;웹훅(풀필먼트, webhook, fulfillment).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 동적 노드가 바깥 시스템을 부르는 방식이다. 정해진 주소로 값을 보내고 답을 받는다. 커넥터, 액션이라고도 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;FAQ봇(자주 묻는 질문 봇, FAQ bot).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 질문과 답을 쌍으로 적어 두고 비슷한 질문이 오면 그 답을 보여 주는 봇이다. 흐름이 없어 만들기 가장 쉽고 가장 먼저 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;검색형 답변(retrieval-based answer).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 질문과 비슷한 문서를 문서 더미에서 찾아 보여 주는 방식이다. FAQ 봇이 쌍을 미리 적는 것이라면 검색형은 문서를 통째로 넣고 찾게 한다. 답을 만들지 않고 찾는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;시나리오형 답변(scenario-based answer).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 묶음 3의 흐름을 따라 노드에 적힌 말을 내는 방식이다. 일을 끝내는 봇은 대개 이 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;생성형 답변(LLM, generative answer).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 큰 언어 모델이 답 문장을 그 자리에서 만든다. 문서를 찾아 모델에 건네고 그 근거로 쓰게 하는 방식이 RAG(검색 증강 생성, retrieval-augmented generation)다. 자연스럽지만 없는 말을 지어낼 수 있어, 돈이 오가거나 규정이 있는 일은 시나리오로 답하고 생성형은 모호한 말을 해석하는 보조로 쓰는 경우가 많다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;하이브리드(hybrid).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 위 방식을 섞은 봇이다. 인텐트를 고르는 데는 모델을, 답은 시나리오를, 흐름 밖 질문은 검색형이나 생성형을 쓰는 식이다. 현장의 봇은 거의 하이브리드이고, 어느 질문을 어느 방식에 보낼지가 설계의 핵심이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5. 만들고 운영하는 것&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;12_builder-engine-channel.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDU4FI/dJMcafV4J7O/91EnKcrKFrhF79zviBcJwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDU4FI/dJMcafV4J7O/91EnKcrKFrhF79zviBcJwK/img.png&quot; data-alt=&quot;봇 빌더와 대화 엔진과 채널과 로그&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDU4FI/dJMcafV4J7O/91EnKcrKFrhF79zviBcJwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDU4FI%2FdJMcafV4J7O%2F91EnKcrKFrhF79zviBcJwK%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;2400&quot; height=&quot;1320&quot; data-filename=&quot;12_builder-engine-channel.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1320&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;봇 빌더와 대화 엔진과 채널과 로그&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;봇 빌더(저작 도구, bot builder, authoring tool).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 인텐트와 예문과 엔티티를 적고 시나리오를 그리는 화면이다. 왼쪽에 인텐트 목록, 가운데에 흐름도, 오른쪽에 노드 속성이 있는 것은 플랫폼이 달라도 비슷하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;대화 엔진(대화 관리자, dialog engine, dialog manager).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 빌더에서 만든 것을 실제로 돌리는 부분이다. 발화를 받아 모델에 묻고, 컨텍스트를 들고, 시나리오의 다음 노드를 고르고, 답을 낸다. 사용자가 만나는 것은 엔진이고, 만드는 사람이 만나는 것은 빌더다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;테스트 콘솔(시뮬레이터, test console, simulator).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 빌더 안에서 봇과 대화해 보는 창이다. 어떤 인텐트로 갔는지, 신뢰도가 얼마였는지, 어떤 엔티티가 뽑혔는지 보여 준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;배포(퍼블리시, publish), 버전(version), 개발계와 운영계(development, production).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 빌더에서 고친 것을 사용자에게 내보내는 것이 배포다. 배포마다 버전이 남아 되돌릴 수 있다. 개발계에서 고치고 테스트한 뒤 운영계로 올린다. 운영계에서 바로 고치는 봇은 언젠가 사용자 앞에서 깨진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;채널(channel).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇이 사용자를 만나는 창구다. 웹사이트의 채팅 창(웹챗 위젯, web chat widget), 메신저, 앱 안의 창이 각각 채널이다. 봇 하나에 채널 하나만 붙는 플랫폼도 있고 여러 채널에 붙는 플랫폼도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;프리메이드 봇(템플릿 봇, premade bot, template).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 업종별로 미리 만들어 둔 봇이다. 복사해서 시작하면 인텐트와 시나리오의 뼈대가 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;발화 로그와 대화 로그(utterance log, conversation log).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 사용자가 실제로 한 말과 봇의 답의 기록이다. 예문은 만드는 사람이 상상한 말이고 로그는 사용자가 실제로 한 말이다. 둘은 늘 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;미인식 발화 검토와 재학습(unmatched utterance review, retraining).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 로그에서 폴백으로 간 발화를 모아 있어야 했던 인텐트에 예문으로 넣고 다시 학습하는 일이다. 봇은 열자마자 잘하지 않는다. 이 반복이 봇을 키운다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;운영자 포털과 권한(admin portal, permissions).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 로그와 지표를 보고 문의를 넘겨받는 화면이다. 누가 고칠 수 있고 누가 보기만 하는지를 권한으로 나눈다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;13_metrics.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1040&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkVV6Y/dJMcacryiNh/cKgQzXtQzBbJkhtMfVnTwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkVV6Y/dJMcacryiNh/cKgQzXtQzBbJkhtMfVnTwk/img.png&quot; data-alt=&quot;지표 다섯 개, 어디서 새는지 본다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkVV6Y/dJMcacryiNh/cKgQzXtQzBbJkhtMfVnTwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkVV6Y%2FdJMcacryiNh%2FcKgQzXtQzBbJkhtMfVnTwk%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;2400&quot; height=&quot;1040&quot; data-filename=&quot;13_metrics.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1040&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;지표 다섯 개, 어디서 새는지 본다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;지표(metrics).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇이 잘 돌아가는지 보는 숫자다. 완결률(self-service rate)은 봇이 사람 없이 끝낸 비율, 이관율(handoff rate)은 사람에게 넘긴 비율, 폴백률(fallback rate)은 못 알아들은 턴의 비율, 이탈률(drop-off rate)은 중간에 떠난 비율, 만족도(CSAT)는 사용자가 매긴 점수다. 다섯 숫자는 한 깔때기다. 인식률 하나만 보는 봇은 알아듣고도 끝내지 못하는 문제를 못 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;이관(핸드오프, handoff)과 라이브챗(live chat).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇이 사람에게 대화를 넘기는 것이 이관, 넘긴 뒤 사람이 같은 창에서 이어 답하는 것이 라이브챗이다. 인텐트와 채운 슬롯과 대화 기록을 함께 넘겨야 사용자가 같은 말을 두 번 하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;상담사 전환 조건(escalation rule).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 언제 넘길지의 규칙이다. 사용자가 요청할 때, 폴백이 정해진 횟수를 넘을 때, 특정 인텐트가 걸릴 때, 바깥 시스템이 오류를 낼 때. 시나리오 바깥 한 곳에 적어 둔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;6. 보이스봇에만 있는 것&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보이스봇은 챗봇 앞에 귀를, 뒤에 입을 붙인 것이다. 귀가 음성인식(STT, speech-to-text), 입이 음성합성(TTS, text-to-speech)이다. 그 사이는 위의 묶음과 같다. 그래서 보이스봇에만 있는 말은 귀와 입 근처에 몰려 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;바지인(말 끊고 들어오기, barge-in).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇이 말하는 중에 사용자가 말하면 봇이 멈추고 듣는 것이다. 안내를 끝까지 들어야 하는 구간에서는 끈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;묵음과 무응답(silence, no input).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇이 물었는데 아무 소리가 없는 것이다. 전화에서는 기다리는 시간을 정해 두고 지나면 재질문으로 간다. 미인식과는 다른 길이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;DTMF 입력(다이얼 버튼, dual-tone multi-frequency).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 말 대신 전화기 숫자 버튼으로 값을 받는 것이다. 생년월일처럼 말로 받으면 틀리기 쉬운 값에 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;SSML(음성 합성 표시 언어, speech synthesis markup language).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇이 읽을 문장에 속도, 쉼, 강조를 표시하는 방식이다. 글자 답은 그대로 보이지만 소리 답은 읽는 속도와 쉼이 뜻을 바꾼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;끝점 검출(EPD, end point detection).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 사용자가 말을 끝낸 지점을 찾는 것이다. 빠르면 말을 자르고 늦으면 봇이 느려진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;보이스 게이트웨이(voice gateway).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 전화와 봇 사이에서 소리와 글자를 주고받는 자리다. 챗봇에는 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 챗봇 일을 맡았을 때 가장 오래 걸린 것은 도구를 익히는 일이 아니라 회의에서 오가는 말을 알아듣는 일이었다. 한쪽은 인텐트라 하고 한쪽은 의도라 하고, 어떤 문서는 슬롯이고 어떤 화면은 파라미터였다. 그래서 이 글은 용어마다 한글과 영문을 같이 적었다. 어느 플랫폼의 화면을 열어도 그것이 이 글의 어느 상자인지 찾을 수 있게.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;챗봇을 움직이는 말은 결국 네 상자다. 말을 받고, 뜻을 고르고, 다음을 정하고, 답을 낸다. 플랫폼이 달라도 이 네 상자는 같고, 부품의 이름이 다를 뿐이다. 다음 글은 큰 언어 모델이 이 네 상자 중 어디에 들어가고 어디에는 들어가면 안 되는지다. 돕는 봇에서 대신 끝내는 봇으로 가는 길의 첫 글이다.&lt;/p&gt;</description>
      <category>tech</category>
      <category>AICC</category>
      <category>chatbot</category>
      <category>Entity</category>
      <category>Intent</category>
      <category>Slot Filling</category>
      <category>엔티티</category>
      <category>인공지능 컨택센터</category>
      <category>인텐트</category>
      <category>챗봇</category>
      <category>챗봇 용어</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/14</guid>
      <comments>https://hsjo.tistory.com/14#entry14comment</comments>
      <pubDate>Wed, 14 Oct 2026 23:28:55 +0900</pubDate>
    </item>
    <item>
      <title>받는 봇 다음은 거는 봇이다, PDS 아웃바운드 보이스봇</title>
      <link>https://hsjo.tistory.com/13</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;야간 콜 라우팅 자동화 파이프라인.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJgtvP/dJMb999eUPF/dZ8B4Nho9EaltE16HwxtD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJgtvP/dJMb999eUPF/dZ8B4Nho9EaltE16HwxtD0/img.png&quot; data-alt=&quot;받는 봇 옆에 거는 봇, 입구와 출구만 다르다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJgtvP/dJMb999eUPF/dZ8B4Nho9EaltE16HwxtD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJgtvP%2FdJMb999eUPF%2FdZ8B4Nho9EaltE16HwxtD0%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;1672&quot; height=&quot;941&quot; data-filename=&quot;야간 콜 라우팅 자동화 파이프라인.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;받는 봇 옆에 거는 봇, 입구와 출구만 다르다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모르는 번호로 전화가 오면 받지 않는다. 나도 그렇고, 내 주변도 그렇다. 그런데 그 번호의 반대편에는 하루 종일 그 전화를 거는 사람이 있다. 계약이 제대로 체결됐는지 확인하는 전화, 납입이 밀렸다고 알리는 전화, 해지가 접수됐다고 안내하는 전화, 예약을 바꾸겠느냐고 묻는 전화. 묻는 말이 정해져 있고 답도 몇 가지로 정해져 있는 전화다. 받는 전화를 봇이 받는다면 거는 전화도 봇이 걸 수 있지 않은가. 그 질문에서 이 글이 시작한다. 거는 봇은 받는 봇과 재료가 같다. 다른 것은 전화가 들어오는 입구와 결과가 나가는 출구다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hsjo.tistory.com/11&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;지난 글&lt;/a&gt;에서 보이스봇은 고객이 건 전화를 IVR이 받아 봇에게 넘기고, 못 끝내면 상담사에게 돌리는 봇이었다. 이 글의 봇은 반대쪽에 선다. 센터가 전화를 거는 쪽이고, 전화를 거는 장치는 PDS(Predictive Dialing System, 자동 발신 장치)다. 목록을 주면 알아서 걸고, 받은 통화만 사람이나 봇에게 넘기는 장치다. 상담사에게 넘기던 자리에 봇을 세우면 아웃바운드 보이스봇이 된다. 금융권이 이 봇에 가장 먼저 관심을 두는 이유는 거는 전화가 많아서이기도 하지만, 그 전화가 안내와 확인과 동의라는 정해진 절차이고, 사람이 하면 숙련도에 따라 품질이 달라지기 때문이다. 이 글은 거는 봇이 지나는 길을 아홉 단계로 번호를 매겨 따라간다. 번호마다 언제 넘어가는지, 어떻게 넘어가는지, 왜 거기를 거치는지를 적는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;전화를 걸기 전에, 목록과 캠페인&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01_nine-steps-outbound.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ALqLK/dJMcagAzmgw/9PTXyGRpY09Pr7RXobcekk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ALqLK/dJMcagAzmgw/9PTXyGRpY09Pr7RXobcekk/img.png&quot; data-alt=&quot;거는 봇의 아홉 단계, 목록에서 결과까지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ALqLK/dJMcagAzmgw/9PTXyGRpY09Pr7RXobcekk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FALqLK%2FdJMcagAzmgw%2F9PTXyGRpY09Pr7RXobcekk%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;2400&quot; height=&quot;1720&quot; data-filename=&quot;01_nine-steps-outbound.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;거는 봇의 아홉 단계, 목록에서 결과까지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;① 업무 시스템 &amp;rarr; 캠페인 DB.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 거는 전화는 목록에서 시작한다. 업무 시스템에서 오늘 전화할 고객을 뽑아 정해진 시각에 배치로 콜리스트를 적재한다. 적재하는 길은 센터마다 다르다. 운영 포탈에 엑셀을 올리는 곳도 있고, 파일 전송으로 받는 곳도 있고, API로 넘기는 곳도 있다. 처음 도입하는 센터는 대개 엑셀 업로드로 시작한다. 고객사 시스템과 API로 잇는 일이 보안망과 방화벽 때문에 가장 큰 허들이라, 먼저 파일로 돌려 효과를 보고 그다음에 연동으로 간다. 목록에는 전화번호만 있는 것이 아니다. 봇이 통화 중에 읽어 줄 값, 그러니까 계약 번호나 안내할 항목이 함께 실린다. 그래서 목록의 항목을 정하는 일이 시나리오를 짜는 일과 같이 간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;② 캠페인 등록 &amp;rarr; PDS 발신.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 목록을 캠페인으로 묶어 운영 포탈에 등록하고 실행 차수를 정하면 다이얼러가 전화를 걸기 시작한다. 여기까지는 봇이 아니라 콜 인프라의 일이다. 시나리오 저작을 가르칠 때도 캠페인 등록과 실행 차수는 저작 도구 밖의 일로 떼어 둔다. 발신 시각과 재시도 간격도, 고객 휴대전화에 뜨는 발신번호도 시나리오가 아니라 캠페인과 회선의 설정이다. 그런데 봇을 들이는 사람이 이 영역에서 꼭 확인해야 하는 것이 하나 있다. 발신번호다. 고객 휴대전화에 뜨는 번호는 고객이 다시 걸 수 있는 번호여야 한다. 모르는 번호라 받지 않는 문제는 봇이 아무리 잘 말해도 풀 수 없고, 콜 인프라 쪽에서 발신번호를 센터 번호로 지정하고 &lt;span&gt;발신번호 안내 서비스에 등록하는 것&lt;/span&gt;&lt;span&gt;으로 줄인다. 응답률은 시나리오가 아니라&lt;/span&gt;&lt;span&gt; 번호가 정한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;연결된 통화만 봇에게 온다&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02_entry-pds-to-bot.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAOTas/dJMcajcX3mA/RNhdIHXj0cI62D498u23t1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAOTas/dJMcajcX3mA/RNhdIHXj0cI62D498u23t1/img.png&quot; data-alt=&quot;다이얼러가 건 전화 중 받는 것만 봇의 입구로&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAOTas/dJMcajcX3mA/RNhdIHXj0cI62D498u23t1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAOTas%2FdJMcajcX3mA%2FRNhdIHXj0cI62D498u23t1%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;2400&quot; height=&quot;1440&quot; data-filename=&quot;02_entry-pds-to-bot.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다이얼러가 건 전화 중 받는 것만 봇의 입구로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;u&gt;③ PDS &amp;rarr; 봇 게이트웨이&lt;/u&gt; &amp;rarr; 봇.&lt;/b&gt;&lt;/span&gt; 다이얼러가 건 전화 가운데 고객이 받은 통화만 봇에게 온다. 부재와 통화 중과 결번은 다이얼러가 거르고 결과 코드만 남긴다. 받은 통화는 봇 게이트웨이와 연동 허브를 거쳐 봇 엔진에 &quot;새 통화&quot;로 들어오고, 그 요청에 고객 ID와 통화 식별자와 캠페인 이름과 몇 번째 시도인지가 실린다. 받는 봇에서 IVR이 하던 일을 거는 봇에서는 다이얼러가 한다. 게이트웨이 입장에서 봇은 여전히 전화기 한 대이고, 봇 입장에서는 전화가 어디서 왔는지가 요청의 변수 몇 개로만 다르다. 그래서 받는 봇과 거는 봇은 같은 엔진, 같은 저작 도구를 쓴다. 교환기를 바꾸는 사업에서 봇을 다시 시험할 때 구간이 셋인데, 대표번호 IVR에서 봇으로 넘어가는 구간, 봇에서 상담사로 넘어가는 구간, 그리고 다이얼러에서 봇으로 들어오는 구간이다. 거는 봇의 입구는 세 구간 중 하나로 따로 센다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;④ 봇이 먼저 말한다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 받는 전화에서는 고객이 말을 걸고 봇이 답한다. 거는 전화는 반대다. 자연스럽기로는 고객이 &quot;여보세요&quot;라고 한 뒤에 시작하는 쪽이지만, 그 방식은 불가능해서 연결되는 순간 봇이 멘트를 시작한다. 이유는 소리에 있다. 통화연결음과 자동응답기의 톤 신호를 음성인식이 짧은 &quot;네&quot;로 알아듣는 일이 생기고, 그것을 엔진에서 기술적으로 걸러내면 진짜 &quot;네&quot;와 &quot;어&quot;까지 놓친다. 음성 인터페이스에서 완전한 정확도는 없고, 대부분은 시나리오로 보정한다. 그래서 거는 봇의 첫 멘트는 짧고, 누구에게 거는 전화인지와 무슨 일로 거는지를 먼저 말한 뒤에 고객의 대답을 받는다. 몇 번째 시도인지에 따라 멘트를 달리한다. 처음 거는 전화와 어제 못 받아 다시 거는 전화는 첫 문장이 달라야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;확인하고, 동의를 받고, 녹취로 남긴다&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03_confirm-consent-record.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDZr7p/dJMcadDD42v/eDrkR4T7CneEtxAS4T20H1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDZr7p/dJMcadDD42v/eDrkR4T7CneEtxAS4T20H1/img.png&quot; data-alt=&quot;본인확인에서 구간 녹취까지, 돈이 오가는 길&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDZr7p/dJMcadDD42v/eDrkR4T7CneEtxAS4T20H1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDZr7p%2FdJMcadDD42v%2FeDrkR4T7CneEtxAS4T20H1%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;2400&quot; height=&quot;1480&quot; data-filename=&quot;03_confirm-consent-record.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1480&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;본인확인에서 구간 녹취까지, 돈이 오가는 길&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;⑤ 본인확인.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 거는 전화는 누가 받았는지 봇이 모른다. 번호의 주인이 아니라 가족이 받을 수도 있다. 그래서 안내를 시작하기 전에 본인을 확인한다. 금융권에서는 주민등록번호를 봇이 수집하지 않는다. 고유식별정보라 수집이 원칙적으로 금지되어 있어 생년월일이나 휴대전화 인증 같은 대체 수단으로 간다. 번호 입력은 말 대신 다이얼 버튼(DTMF)으로 받는 경우가 많고, 그 값은 전 구간을 암호화해 봇 플랫폼에서는 풀지 않고 기간계로 보낸 뒤 맞는지 아닌지만 돌려받는다. 봇의 로그에는 전부 마스킹되어 남는다. 봇이 &quot;수집&quot;하는 것이 아니라 &quot;처리&quot;만 하더라도 검토 대상이 된다는 것을 보안 검토에서 배웠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;⑥ 안내와 확인.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 본인이 맞으면 봇이 묻기 시작한다. 같은 상품이라도 계약마다 확인할 항목이 다르면 스크립트를 동적으로 구성한다. 목록에 실린 값과 통화 직전에 조회한 최신 값으로 그 고객의 문장을 만든다. 고객이 시나리오 밖의 질문을 하면, 예를 들어 &quot;피보험자가 누구예요&quot;라고 물으면, 답을 하고 원래 흐름으로 돌아온다. 끼어들기라고 부른다. 고객이 모른다고 하면 되묻지 않고 다음 질문으로 넘어가고 결과에는 모른다는 값을 남긴다. 처음 연 봇은 모른다는 답에도 계속 되물었고, 운영 피드백을 받고 나서 바꿨다. 재질문 정책은 저작하기 전에 정한다. 원래 질문을 한 번, 되묻기를 정해진 횟수, 그 뒤에는 상담사 연결을 권하거나 끊는다. 이 숫자는 봇을 만드는 사람이 아니라 업무를 아는 사람이 정한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;⑦ 처리와 동의 녹취.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 안내만 하던 봇이 처리까지 하면 돈이 오간다. 밀린 납입금을 지금 출금해도 되는지 묻고 동의를 받아 출금하는 식이다. 법적 효력이 있는 동의 구간은 통화 전체 녹취와 별개로 따로 남긴다. 녹취 가능 여부를 조회하고, 녹취 키를 발급받고, 그 구간만 녹취한 뒤 완료 전문을 보내는 세 단계다. 통화 식별자(UCID)가 녹취와 상담이력과 봇 로그를 잇는 열쇠다. 돈이 오가는 처리는 음성만으로 판단하지 않는다. &quot;네&quot; 한 마디로 출금하지 않고, 분명한 문장을 받고 필요하면 인증 번호를 함께 받는다. 되돌리기 어려운 처리에서 한 번 더 묻는 비용은 작고 잘못 처리한 비용은 크다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;결과를 남기고, 못 받으면 다시 걸고, 못 끝내면 넘긴다&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04_result-retry-handoff.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kFZwr/dJMcaiLQYvl/hkvOcwlTjk6kB2esAH0tMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kFZwr/dJMcaiLQYvl/hkvOcwlTjk6kB2esAH0tMk/img.png&quot; data-alt=&quot;호가 끊기기 전에 결과를, 못 받으면 문자를, 못 끝내면 상담사를&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kFZwr/dJMcaiLQYvl/hkvOcwlTjk6kB2esAH0tMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkFZwr%2FdJMcaiLQYvl%2FhkvOcwlTjk6kB2esAH0tMk%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;2400&quot; height=&quot;1440&quot; data-filename=&quot;04_result-retry-handoff.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;호가 끊기기 전에 결과를, 못 받으면 문자를, 못 끝내면 상담사를&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;⑧ 결과 저장.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 거는 전화의 목적은 통화가 아니라 결과다. 확인했는지, 동의했는지, 출금했는지, 모른다고 했는지가 코드로 남아야 다음 일이 돌아간다. 결과를 기다리는 곳은 셋이다. 다이얼러는 이 번호를 다시 걸지 말지 정하려고 결과가 필요하다. 업무 시스템은 계약이나 납입의 상태를 바꾸려고 결과가 필요하다. 상담 이력은 나중에 상담사가 이 고객을 만났을 때 봇이 무슨 말을 했는지 보려고 결과가 필요하다. 봇은 이 셋을 통화가 끝난 뒤에 모아서 저장하지 않고, 호가 끊기기 전에 한 번에 갱신한다. 한 통화에서 계약 여러 건을 차례로 다룰 때도 마찬가지다. 결과 코드는 API로 업무 시스템에 돌려주고, 운영자는 같은 결과를 운영 포탈에서 캠페인별로 본다. 통화 내용은 봇이 몇 줄로 요약해 상담 메모로 넘긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;⑨ 못 받거나 못 끝내면.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 고객이 받지 않으면 다이얼러가 정해진 횟수까지 다시 걸고, 그래도 못 받으면 문자를 보낸다. 거는 봇의 끝에는 늘 문자가 붙는다. 받았지만 봇이 못 끝내면 상담사에게 넘긴다. 봇이 먼저 권하기보다 고객이 요청하거나, 봇이 답할 수 없다고 안내하고 연결을 권하고 고객이 동의하는 순서로 설계한다. 넘기는 주체는 봇이 아니라 게이트웨이다. 봇 엔진이 오류를 내면 게이트웨이가 기본 음원을 틀고 지정된 번호로 돌리는 것이 기본값이라, 상담사 연결이 없어야 하는 시나리오는 예외를 따로 걸어야 한다. 상담사에게 넘어가면 상담 프로그램에 봇 아이콘이 켜지고, 봇이 어디까지 진행했는지와 상담사가 이어서 할 항목의 스크립트가 뜬다. 고객이 봇에게 한 말을 상담사에게 다시 하지 않게 하는 것은 받는 봇과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;금융권이 먼저 묻는 것&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;금융권 센터에 거는 봇을 들일 때 기술보다 먼저 오는 것은 검토 세트다. 아키텍처도, 데이터 흐름도, 업무 흐름도 세 가지를 보안 부서에 내고, 봇이 다루는 개인정보 항목을 표로 뽑아 항목마다 저장 여부와 로그 마스킹 규칙을 정한다. 망이 분리되어 있어 시나리오 파일과 오류 로그를 밖으로 들고 나올 수 없고, 화면 캡처와 글자 발췌로 주고받는다. 이 절차는 개발 일정과 별도로 흐르고, 대개 더 오래 걸린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시나리오는 거래성과 조회성으로 나눈다. 조회성은 틀려도 다시 물으면 되지만, 거래성은 운영 중에 실패하면 고객이 지점에 가야 하는 일이 생긴다. 그래서 전수 검수는 거래성부터 한다. 전수 검수의 병목은 사람이 아니라 조건에 맞는 테스트 고객 데이터다. 성공하는 경우만이 아니라 실패하는 경우와 경계의 경우를 테스트 케이스에 넣어야 하고, 그 데이터는 운영 데이터가 아니라 개발 환경에서 만들어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오픈은 한 번에 하지 않는다. 다이얼러 없이 콜 인프라만 연동해 봇이 한 통 거는 시연, 안내형 업무만 여는 1차, 처리형까지 여는 2차로 간다. 그리고 연 뒤에 완결률을 올리는 기간을 일정에 넣는다. 봇은 열자마자 잘하지 않는다. 고객의 답은 무궁무진하고, 시나리오는 운영 피드백으로 다듬어진다. 이 기간이 없는 일정표는 오픈 날이 끝이라고 믿는 일정표다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거는 봇을 처음 봤을 때는 받는 봇과 다른 제품인 줄 알았다. 실제로 거는 봇이 별도 상품으로 묶여 관리 포털이 둘로 나뉜 구성도 있었다. 지금은 같은 봇에 입구와 출구가 다르다고 말한다. 입구는 IVR이 아니라 다이얼러이고, 연결된 통화만 들어온다. 봇이 먼저 말하고, 본인을 확인하고, 동의는 구간 녹취로 남긴다. 출구는 결과 코드이고, 못 받으면 문자가, 못 끝내면 상담사가 받는다. 이 길을 아홉 번호로 그려 두면 금융권의 보안 검토도 같은 그림 위에서 답할 수 있다. 데이터 흐름도가 곧 이 그림이기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 배운 것은 거는 봇의 품질이 인식률이 아니라 목록과 번호와 결과 코드에서 난다는 것이다. 목록이 틀리면 봇이 엉뚱한 사람에게 말하고, 번호가 낯설면 아무도 받지 않고, 결과 코드가 없으면 전화를 건 이유가 사라진다. 다음 글은 받는 봇과 거는 봇에서 계속 나온 말들, 인텐트와 엔티티와 슬롯과 시나리오와 폴백 같은 용어를 한 장에 정리한다.&lt;/p&gt;</description>
      <category>tech</category>
      <category>AICC</category>
      <category>outbound</category>
      <category>PDS</category>
      <category>Voicebot</category>
      <category>구간 녹취</category>
      <category>보이스봇</category>
      <category>아웃바운드 보이스봇</category>
      <category>인공지능 컨택센터</category>
      <category>자동 발신 시스템</category>
      <category>캠페인 콜</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/13</guid>
      <comments>https://hsjo.tistory.com/13#entry13comment</comments>
      <pubDate>Wed, 14 Oct 2026 20:33:18 +0900</pubDate>
    </item>
    <item>
      <title>컨택센터는 빌려 쓰고 데이터는 내가 가진다 CCaaS</title>
      <link>https://hsjo.tistory.com/12</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;도시를 잇는 안전한 데이터 연결.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sCe3j/dJMcackAWgN/Uk9kyHibcB6vxsJqpgYx00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sCe3j/dJMcackAWgN/Uk9kyHibcB6vxsJqpgYx00/img.png&quot; data-alt=&quot;센터는 남의 건물에, 데이터는 내 금고에&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sCe3j/dJMcackAWgN/Uk9kyHibcB6vxsJqpgYx00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsCe3j%2FdJMcackAWgN%2FUk9kyHibcB6vxsJqpgYx00%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;1672&quot; height=&quot;941&quot; data-filename=&quot;도시를 잇는 안전한 데이터 연결.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;센터는 남의 건물에, 데이터는 내 금고에&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인공지능 컨택센터의 그림을 다 그리고 나면 질문이 하나 남는다. 이 그림을 어디에 두는가. 교환기, CTI, IVR, 녹취, 상담 프로그램, 음성인식, 봇, 전부 내 건물의 서버실에 놓을 수도 있고, 남의 건물에서 빌려 쓸 수도 있다. 구성도만 보면 둘은 같은 그림이다. 그런데 현장에서 이 결정은 서버의 위치가 아니라 전혀 다른 네 군데에서 갈리고, 빌려 쓰기로 한 센터일수록 한 가지는 반드시 내 손에 남겨야 한다. 데이터다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞선 글들에서 인공지능 컨택센터(AICC)를 상담의 앞과 옆과 뒤에 인공지능이 앉는 센터로 그렸다. 재료인 음성인식과 음성합성과 자연어 처리와 자연어 이해, 소리를 대 주는 녹취, 통화 중에 받아 적고 찾아 주는 옆자리, 통화 뒤에 정리하는 뒷자리, 상담사보다 먼저 받는 앞자리의 보이스봇. 이 글은 그 묶음의 마지막이다. 그림을 어디에 둘지, 요즘 말로 CCaaS가 무엇인지, 인공지능을 넣은 효과는 무엇으로 재는지를 보고, 마지막에 아홉 단계와 요소들을 표 두 개로 결산한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;어디에 두는가, 구축형∙클라우드∙CCaaS&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01_onprem-cloud-ccaas.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EkGA2/dJMcafoe53s/8kgQsw02f2mQ0c1Nxoy6b1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EkGA2/dJMcafoe53s/8kgQsw02f2mQ0c1Nxoy6b1/img.png&quot; data-alt=&quot;같은 그림, 다른 장소, 그리고 SaaS 묶음&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EkGA2/dJMcafoe53s/8kgQsw02f2mQ0c1Nxoy6b1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEkGA2%2FdJMcafoe53s%2F8kgQsw02f2mQ0c1Nxoy6b1%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;2400&quot; height=&quot;1680&quot; data-filename=&quot;01_onprem-cloud-ccaas.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1680&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;같은 그림, 다른 장소, 그리고 SaaS 묶음&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 그린 그림을 어디에 두는가. 두 가지 답이 있다. 내 건물에 서버를 사서 두는 구축형(On-Premise)과, 남의 건물의 서버를 빌려 쓰는 클라우드(서비스형)다. 구성도만 보면 둘은 같다. 교환기, CTI, IVR, 녹취, 상담 프로그램, 음성인식, 봇이 똑같이 그려진다. 다른 것은 네모의 위치다. 그런데 현장에서 차이는 서버 위치가 아니라 네 군데에서 드러난다. 회선, 전화기, 보안 통로, 호전환이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회선과 전화기는 전화가 센터에 들어오는 경계와 상담사 자리의 이야기다. 센터가 밖에 있으니 전화는 인터넷이나 SIP 트렁크로 오고, 경계에는 게이트웨이 대신 SBC가 서고, 상담사 자리의 전화기는 대개 브라우저가 된다. 보안 통로는 상담 프로그램과 전화기가 밖에 있는 센터까지 가는 길이다. 보통 VPN을 뚫고, 금융권이면 어느 주소로만 나갈 수 있는지를 목록으로 적는다. 호전환은 가장 작은 글자로 적혀 있지만 가장 자주 도입을 가르는 항목이다. 센터가 내 건물에 있을 때 상담사가 다른 부서 내선으로 전화를 돌리는 것은 같은 교환기 안의 일이라 공짜다. 센터가 클라우드에 있으면 그 내선은 바깥 번호가 되어 통화료가 붙는다. 호전환이 많은 센터일수록 이 한 줄을 먼저 본다. 보이스봇을 클라우드에 두고 내 건물의 교환기에 붙일 때도 같은 질문이 돌아온다. 봇으로 넘길 때마다 전화망을 타면 착신 요금이 생기고, SIP 트렁크로 이으면 생기지 않는다. 경계에 서는 SBC가 여기서 다시 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구축형, 그중에서도 금융권 구축형에서 일정을 정하는 것은 개발이 아니다. 학습 서버 조달, 아이피 발급, 방화벽 신청, 서버 취약점 점검, 이중화 시험, 상담사에게 노출하지 않는 파일럿 운영 같은 절차다. 음성인식 한 줄을 넣는 사업에서도 이 절차가 개발보다 오래 걸린다. 그래서 구축형 일정표는 개발 일정이 아니라 절차 일정으로 그린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CCaaS(Contact Center as a Service)는 클라우드 중에서도 센터의 모든 부분을 서비스로 받는 방식이다. 서비스로 받는다는 말이 추상적이라 풀어 쓰면 이렇다. 전통적인 IT에서는 네트워크, 서버, 저장장치, 운영체제, 미들웨어, 데이터, 애플리케이션을 전부 내가 관리한다. 그중 아래 몇 층을 빌리면 IaaS, 애플리케이션 아래까지 빌리면 PaaS, 애플리케이션까지 전부 빌리면 SaaS(Software as a Service)다. 컨택센터는 애플리케이션이 하나가 아니다. 전화를 다루는 콜 애플리케이션(교환기&amp;middot;CTI&amp;middot;IVR), 상담 프로그램, 녹취, 음성인식과 텍스트 분석, 봇 저작 도구, 문자 발송이 각각 하나의 애플리케이션이다. 이것들을 각각 SaaS로 받아 하나로 묶은 것이 CCaaS다. 그래서 CCaaS는 제품 하나가 아니라 묶음이고, 묶음을 묶는 것은 각 애플리케이션 사이의 연동 규격이다. 상담 프로그램이 전화기의 상태를 어떻게 받는지, 콜백을 어떻게 넘기는지, 녹취를 어떻게 듣는지, 실시간 대화록을 어떻게 받는지 같은 규격이 CCaaS의 뼈대다. &quot;엔진은 사고 분류와 지식과 표본은 기른다&quot;는 원칙은 CCaaS에서도 그대로다. 엔진은 서비스로 받지만 분류 체계와 지식과 표본은 여전히 센터의 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라우드 센터가 구축형과 다르게 구는 지점이 하나 더 있다. 고객의 데이터를 들고 있지 않으려 한다. 고객 정보는 고객사 시스템에 두고, 상담 화면에 띄울 때만 API로 불러 쓴다. 봇이 기간계 시스템을 조회할 때도 봇이 직접 들어가지 않고 중간에 연동 창구를 두고 그 창구가 대신 묻는다. 처음에는 번거로운 설계로 보였다. 지금은 반대로 본다. 센터가 밖에 있을수록 데이터는 안에 있어야 한다. 그래야 센터를 바꿔도 고객 정보는 그대로다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;효과를 재는 자, 세 가지 효과와 여섯 개의 눈금&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인공지능 컨택센터의 효과를 설명하는 자리에서 늘 세 가지가 나온다. 상담사의 앞과 옆과 뒤, 세 자리와 짝이 맞는다. 옆자리는 통화 한 건에서 지식을 찾는 시간을 줄인다. 뒷자리는 전화를 끊고 나서 하는 후처리를 줄인다. 앞자리는 상담사에게 가는 반복 문의를 줄인다. 셋을 합쳐 상담 처리 여력이라고 부른다. 그 여력을 사람을 줄이는 데 쓰는 센터도 있지만, 내가 본 좋은 센터는 응대 속도를 올리고 한 사람이 받는 업무 범위를 넓히고 고객의 대기를 줄이는 데 썼다. 효과는 비용에서 나는 것이 아니라 서비스 수준에서 난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;숫자를 적지 않는 이유가 있다. 효과는 센터마다 다르고, 같은 센터에서도 무엇을 어떻게 세는가에 따라 달라진다. 그래서 효과를 말하기 전에 눈금을 먼저 정한다. 센터가 보는 눈금은 보통 여섯이다. 서비스(몇 초 안에 몇 퍼센트를 받는가), 데이터(통화 중 몇 퍼센트가 글자가 되는가), 효율(후처리 시간과 지식 검색 시간), 품질(자동 분류가 상담사의 확정과 얼마나 맞는가, 한 번에 해결된 비율), 확산(반복 문의 중 봇이 끝낸 비율), 운영(문의가 몰릴 때 얼마나 빨리 알아채는가). 인공지능을 넣기 전에 이 여섯 눈금의 현재 값을 재 두지 않으면, 넣은 뒤에 좋아졌는지를 아무도 말하지 못한다. 눈금을 재는 일 자체가 인공지능을 넣기 전에 할 일의 일부다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조건도 있다. 상담사 수가 그대로인 센터에서 &quot;다시 건 고객을 먼저 연결&quot;하는 규칙을 넣으면, 누군가 먼저 연결되는 만큼 다른 누군가가 포기호가 된다. 봇이 전화의 절반만 끝내도 효과는 있지만, 되돌리기 어려운 처리까지 봇에게 맡기지는 않는다. 봇도 음성인식도 열자마자 잘하지 않고 가르쳐 가며 나아지므로, 연 뒤 다듬는 기간이 일정에 들어 있어야 한다. 효과는 인공지능이 만들지 않는다. 눈금과 조건과 다듬는 시간이 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;결산, 아홉 단계와 요소들을 한 표로&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전화가 상담사에게 닿는 여섯 단계와 보이스봇이 끼어드는 세 단계, 그리고 번호가 붙지 않는 두 자리를 한 표에 모은다. 번호 순서가 아니라 전화가 실제로 지나는 순서다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02_summary-nine.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdVaMX/dJMcaiZjM8H/pQHqcFP2l7MMZ3rQzQyCP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdVaMX/dJMcaiZjM8H/pQHqcFP2l7MMZ3rQzQyCP0/img.png&quot; data-alt=&quot;결산, 아홉 단계와 두 자리를 한 장으로&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdVaMX/dJMcaiZjM8H/pQHqcFP2l7MMZ3rQzQyCP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdVaMX%2FdJMcaiZjM8H%2FpQHqcFP2l7MMZ3rQzQyCP0%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;2400&quot; height=&quot;1640&quot; data-filename=&quot;02_summary-nine.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;결산, 아홉 단계와 두 자리를 한 장으로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.96121%; text-align: center;&quot;&gt;&lt;b&gt;단계&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.3799%; text-align: center;&quot;&gt;&lt;b&gt;어디에서 어디로&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 40.6588%; text-align: center;&quot;&gt;&lt;b&gt;언제&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.96121%; text-align: center;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 49.3799%;&quot;&gt;고객 &amp;rarr; 통신사 지능망&lt;/td&gt;
&lt;td style=&quot;width: 40.6588%;&quot;&gt;대표 번호를 누른 순간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.96121%; text-align: center;&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;width: 49.3799%;&quot;&gt;지능망 &amp;rarr; 게이트웨이 또는 SBC &amp;rarr; 교환기&lt;/td&gt;
&lt;td style=&quot;width: 40.6588%;&quot;&gt;전화가 센터 문 앞에 온 순간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.96121%; text-align: center;&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;width: 49.3799%;&quot;&gt;교환기 &amp;rarr; CTI&lt;/td&gt;
&lt;td style=&quot;width: 40.6588%;&quot;&gt;통화 요청이 교환기에 닿은 순간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.96121%; text-align: center;&quot;&gt;4&lt;/td&gt;
&lt;td style=&quot;width: 49.3799%;&quot;&gt;CTI &amp;rarr; IVR&lt;/td&gt;
&lt;td style=&quot;width: 40.6588%;&quot;&gt;CTI가 IVR로 돌리라고 명령한 순간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.96121%; text-align: center;&quot;&gt;7&lt;/td&gt;
&lt;td style=&quot;width: 49.3799%;&quot;&gt;IVR &amp;rarr; 보이스봇 게이트웨이&lt;/td&gt;
&lt;td style=&quot;width: 40.6588%;&quot;&gt;시나리오가 버튼 대신 말을 받기로 한 순간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.96121%; text-align: center;&quot;&gt;8&lt;/td&gt;
&lt;td style=&quot;width: 49.3799%;&quot;&gt;게이트웨이 &amp;rarr; 봇 엔진(음성인식 &amp;rarr; 자연어 이해 &amp;rarr; 대화엔진 &amp;rarr; 음성합성)&lt;/td&gt;
&lt;td style=&quot;width: 40.6588%;&quot;&gt;고객의 첫 마디가 들어온 순간부터 말할 때마다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.96121%; text-align: center;&quot;&gt;9&lt;/td&gt;
&lt;td style=&quot;width: 49.3799%;&quot;&gt;봇 &amp;rarr; 종료, 또는 IVR로 복귀해 5로 합류&lt;/td&gt;
&lt;td style=&quot;width: 40.6588%;&quot;&gt;일을 마쳤거나, 상담사를 원하거나, 알아듣지 못한 횟수가 상한선을 넘은 순간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.96121%; text-align: center;&quot;&gt;5&lt;/td&gt;
&lt;td style=&quot;width: 49.3799%;&quot;&gt;IVR &amp;rarr; CTI&lt;/td&gt;
&lt;td style=&quot;width: 40.6588%;&quot;&gt;스킬이 정해진 순간&lt;br /&gt;(봇이 알아낸 의도가 스킬이 된다)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.96121%; text-align: center;&quot;&gt;6&lt;/td&gt;
&lt;td style=&quot;width: 49.3799%;&quot;&gt;CTI &amp;rarr; 상담사/상담프로그램/녹취&lt;/td&gt;
&lt;td style=&quot;width: 40.6588%;&quot;&gt;상담사 한 명이 정해진 순간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.96121%; text-align: center;&quot;&gt;옆자리&lt;/td&gt;
&lt;td style=&quot;width: 49.3799%;&quot;&gt;녹취 &amp;rarr; 실시간 음성인식 &amp;rarr; 실시간 저장소 &amp;rarr; 상담 어시스트 화면&amp;nbsp;&lt;br /&gt;(대화록∙핵심질문&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;∙지식&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;∙말점검&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;∙유형추천)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 40.6588%;&quot;&gt;상담사가 통화하는 동안&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.96121%; text-align: center;&quot;&gt;뒷자리&lt;/td&gt;
&lt;td style=&quot;width: 49.3799%;&quot;&gt;녹취 &lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;&amp;rarr; 사후 음성인식 &lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;&amp;rarr; 통합DB &lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;&amp;rarr; 텍스트분석(요약&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;∙분류&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;∙열쇠말)&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;&amp;rarr; 품질평가 &lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;&amp;rarr; 학습서버&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 40.6588%;&quot;&gt;통화가 끝난 뒤&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라우드 컨택센터를 처음 설계할 때 고객 정보를 센터 밖에 두지 않으려는 설계가 번거롭게 보였다. 화면에 띄울 때마다 불러오고, 봇이 조회할 때마다 연동 창구를 거쳐야 했다. 지금은 반대로 본다. 센터가 밖에 있을수록 데이터는 안에 있어야 한다. 그래야 센터를 바꿔도 고객 정보는 그대로고, 엔진을 바꿔도 분류와 지식과 표본은 그대로다. 컨택센터는 빌려 쓸 수 있다. 회선과 전화기와 보안 통로와 호전환, 이 네 가지를 먼저 보고 나면 빌려 쓰는 쪽이 더 가벼운 경우가 많다. 다만 데이터는 내가 가진다. 이 한 줄이 인공지능 컨택센터를 어디에 두든 변하지 않는 원칙이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인공지능 컨택센터 이야기는 여기서 한 바퀴를 돌았다. 상담사를 대신하는 센터가 아니라 상담사의 앞과 옆과 뒤에 인공지능이 앉고, 그 밑에 센터가 기른 분류와 지식과 표본이 깔리고, 그 전부를 내 건물에 두거나 빌려 쓰는 센터. 다음 글은 이 세 자리의 인공지능이 &quot;돕는&quot; 것을 넘어 &quot;대신 끝내는&quot; 자리로 가는 길이다. 답을 찾아 주는 단계에서 일을 끝내는 단계로. 그 길에도 번호가 붙는다.&lt;/p&gt;</description>
      <category>tech</category>
      <category>AICC</category>
      <category>CCaaS</category>
      <category>Cloud Contact Center</category>
      <category>On-Premise</category>
      <category>SaaS</category>
      <category>구축형</category>
      <category>인공지능 컨택센터</category>
      <category>컨택센터 효과 측정</category>
      <category>클라우드 컨택센터</category>
      <category>호전환</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/12</guid>
      <comments>https://hsjo.tistory.com/12#entry12comment</comments>
      <pubDate>Wed, 14 Oct 2026 19:12:25 +0900</pubDate>
    </item>
    <item>
      <title>보이스봇은 상담사에게 가지 않아도 되는 전화를 그 앞에서 끝낸다</title>
      <link>https://hsjo.tistory.com/11</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;로봇이 연결하는 야간 콜센터 업무 흐름.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oDWzs/dJMcadwToSc/VuNSRkfgfzeapIhHh1RBfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oDWzs/dJMcadwToSc/VuNSRkfgfzeapIhHh1RBfK/img.png&quot; data-alt=&quot;상담사 앞에 선 봇, 끝내거나 넘기거나&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oDWzs/dJMcadwToSc/VuNSRkfgfzeapIhHh1RBfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoDWzs%2FdJMcadwToSc%2FVuNSRkfgfzeapIhHh1RBfK%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;1672&quot; height=&quot;941&quot; data-filename=&quot;로봇이 연결하는 야간 콜센터 업무 흐름.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;상담사 앞에 선 봇, 끝내거나 넘기거나&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;무엇을 도와드릴까요.&quot; 요즘 고객센터에 전화하면 버튼 안내 대신 이 말이 먼저 나온다. 말을 하면 알아듣고, 간단한 일은 그 자리에서 끝내고, 못 끝내면 상담사에게 넘긴다. 이것이 보이스봇이고, 인공지능 컨택센터에서 가장 눈에 띄는 자리다. 눈에 띄는 만큼 오해도 많다. 봇이 상담사를 대신한다고도 하고, 봇이 먹통이면 센터가 멈춘다고도 한다. 둘 다 아니다. 보이스봇의 목적은 하나다. 상담사에게 가지 않아도 되는 전화를 그 앞에서 끝내는 것. 그리고 봇이 멈춰도 전화는 살아 있게 만든다. 이 글은 그 두 가지가 어떻게 가능한지를 전화가 지나는 길 위에서 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전화는 고객이 대표번호를 누른 뒤 통신사 지능망, 교환기, CTI, IVR을 지나 상담사에게 닿는다. 보이스봇은 그 길의 IVR에서 갈라져 나왔다가 다시 돌아오는 세 단계로 끼어든다. 이 글에서는 그 세 단계를 7, 8, 9로 부르고 단계마다 언제, 어떻게, 왜를 적는다. 앞선 글에서 인공지능은 상담사 책상의 앞∙옆∙뒤 세자리에 앉는다고 했다. 옆자리는 통화 중에 받아 적고 찾아 주는 상담 어시스트, 뒷자리는 통화 뒤에 요약하고 분류하고 점수를 매기는 텍스트 분석과 품질 평가다. 이 글은 남은 한 자리, 상담사보다 먼저 받는 앞자리다. 보이스봇과 함께 글자로 받는 챗봇, 화면으로 고르게 하는 보이는 ARS, 전화와 다른 창구를 잇는 옴니채널, 그리고 봇을 사기 전에 센터가 길러 두어야 하는 세 가지까지 간다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;앞자리, 보이스봇이 전화의 길 위에 서는 세 단계&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옆자리와 뒷자리가 자리를 잡으면 앞자리로 간다. 상담사보다 먼저 받는 인공지능이다. 전화의 길 위에 서는 보이스봇부터 번호를 따라간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;7. IVR &amp;rarr; 보이스봇 게이트웨이, 버튼 대신 말을 받기로 한 순간&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01_step7-ivr-gateway.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vYo7q/dJMcacx914w/2SHkHzWGDK5bRlAjTURYlk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vYo7q/dJMcacx914w/2SHkHzWGDK5bRlAjTURYlk/img.png&quot; data-alt=&quot;IVR이 전화를 게이트웨이에 넘긴다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vYo7q/dJMcacx914w/2SHkHzWGDK5bRlAjTURYlk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvYo7q%2FdJMcacx914w%2F2SHkHzWGDK5bRlAjTURYlk%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;2400&quot; height=&quot;1360&quot; data-filename=&quot;01_step7-ivr-gateway.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1360&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;IVR이 전화를 게이트웨이에 넘긴다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;언제.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; IVR이 시나리오를 돌리다가, 이 전화는 버튼이 아니라 말로 받겠다고 정한 순간이다. 전화가 들어오자마자 &quot;무엇을 도와드릴까요&quot;로 시작하는 센터도 있고, 특정 메뉴에서만 봇으로 넘기는 센터도 있다. 어느 쪽이든 IVR 시나리오의 상자 하나가 &quot;보이스봇으로&quot;라고 적혀 있다. IVR 시나리오의 분기 목적지는 원래 스킬, 그러니까 어떤 상담사 무리로 보낼지였다. 이제 목적지가 하나 더 생겼다. 스킬 아니면 봇이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;어떻게.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; IVR은 소리를 알아듣지 못한다. 버튼 소리만 안다. 그래서 IVR 옆에 통역을 둔다. 보이스봇 게이트웨이다. IVR과 게이트웨이 사이의 약속은 MRCP(Media Resource Control Protocol)라는 공개 표준이고(RFC 6787), 그 안에서 통화는 SIP로 열고 소리는 RTP로 나른다. 전화를 여는 약속과 소리를 나르는 약속, 전화망의 두 줄기가 그대로다. 게이트웨이 입장에서 봇은 전화기 한 대와 같고, IVR 입장에서 봇은 &quot;말을 알아듣는 안내 멘트 서버&quot;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;왜.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇은 소리와 글자를 다루는 프로그램이라 전화망에 꽂을 손이 없다. 그 손을 대신 내주는 것이 게이트웨이다. 그리고 봇이 멈춰도 전화는 살아 있어야 한다. 게이트웨이가 중간에 있으면 봇이 답을 못 할 때 기본 안내를 틀고 상담사에게 돌릴 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;8. 게이트웨이 &amp;rarr; 봇 엔진, 재료 셋이 한 바퀴 돈다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02_step8-bot-engine.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bA95dW/dJMb99OP1JL/aXNT0TdG4V3pvNjuFWc8z1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bA95dW/dJMb99OP1JL/aXNT0TdG4V3pvNjuFWc8z1/img.png&quot; data-alt=&quot;봇 엔진 안, 소리&amp;amp;rarr;글자&amp;amp;rarr;뜻&amp;amp;rarr;답&amp;amp;rarr;소리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bA95dW/dJMb99OP1JL/aXNT0TdG4V3pvNjuFWc8z1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbA95dW%2FdJMb99OP1JL%2FaXNT0TdG4V3pvNjuFWc8z1%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;2400&quot; height=&quot;1400&quot; data-filename=&quot;02_step8-bot-engine.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1400&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;봇 엔진 안, 소리&amp;rarr;글자&amp;rarr;뜻&amp;rarr;답&amp;rarr;소리&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;언제.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 게이트웨이가 봇 엔진에 &quot;새 통화&quot;를 알리고 고객의 첫 마디가 들어온 순간부터, 고객이 말할 때마다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;어떻게.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 재료 셋이 순서대로 돈다. 음성인식이 고객의 말을 글자로 적고, 자연어 처리가 오타를 고치고 낱말을 쪼개 글자를 다듬고, 자연어 이해가 의도와 값을 뽑고, 대화 엔진이 그 의도에 맞는 시나리오에서 다음에 할 말을 고르고, 음성합성이 그 말을 소리로 만들어 게이트웨이에 돌려준다. 시나리오는 사람이 저작 도구에서 상자와 화살표로 그린 흐름도이고, IVR 시나리오와 같은 모양인데 버튼 대신 의도로 갈린다. 이 한 바퀴가 도는 시간이 고객이 느끼는 &quot;봇의 반응 속도&quot;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;왜.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇은 소리를 듣고 판단하지 않는다. 글자를 읽고 판단한다. 음성인식이 글자를 틀리게 적으면 그 뒤가 다 틀린다. 통화 연결음이나 대기음을 &quot;네&quot;로 알아들은 적이 있다. 엔진은 소리를 글자로 바꿨을 뿐 잘못한 것이 없다. 그래서 돈이 오가거나 되돌리기 어려운 처리는 시나리오에서 한 번 더 묻는다. &quot;네&quot; 대신 &quot;진행하겠습니다&quot;처럼 분명한 말을 받고, 필요하면 인증번호를 함께 받는다. 봇의 품질은 인식률이 아니라 시나리오가 정한다. 그리고 그 시나리오가 다루는 의도의 목록은 뒷자리의 텍스트 분석을 위해 정리한 분류 체계에서 나온다. 봇이 옆자리와 뒷자리 다음인 이유가 여기서 다시 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;9. 봇 &amp;rarr; 종료 또는 상담사 이관, 끝내거나 넘기거나&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03_step9-handoff.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1540&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/usrdO/dJMcaaHeRZ8/FQgUDpO192kLm0hmHFBc00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/usrdO/dJMcaaHeRZ8/FQgUDpO192kLm0hmHFBc00/img.png&quot; data-alt=&quot;끝내면 종료, 못 끝내면 상담사에게 가는길로 합류&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/usrdO/dJMcaaHeRZ8/FQgUDpO192kLm0hmHFBc00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FusrdO%2FdJMcaaHeRZ8%2FFQgUDpO192kLm0hmHFBc00%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;2400&quot; height=&quot;1540&quot; data-filename=&quot;03_step9-handoff.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1540&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;끝내면 종료, 못 끝내면 상담사에게 가는길로 합류&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;언제.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 봇이 시나리오 끝까지 가서 고객의 일을 마쳤을 때, 또는 고객이 &quot;상담사 연결해 주세요&quot;라고 말했거나 봇이 알아듣지 못한 횟수가 상한을 넘었을 때.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;어떻게.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 마쳤으면 마무리 멘트를 하고 끊는다. 넘겨야 하면 게이트웨이가 전화를 IVR과 교환기 쪽으로 되돌리고, 전화는 IVR이 스킬을 정해 CTI에 돌려주는 단계로 합류한다. 봇이 알아낸 의도가 곧 스킬이 된다. &quot;보험금 청구 진행&quot;을 묻던 고객은 청구 담당 스킬로, &quot;주소 변경&quot;을 말하던 고객은 계약 변경 스킬로 간다. 봇이 고객과 나눈 대화와 넘기는 이유는 상담 프로그램으로 전달되어 상담사 화면에 뜬다. 그래야 고객이 봇에게 한 말을 상담사에게 처음부터 다시 하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;왜.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 이관의 주체는 봇이 아니라 게이트웨이와 교환기다. 봇이 먹통이어도 전화는 살아야 하기 때문이다. 그래서 어떤 의도가 어느 스킬로 가는지, 어떤 실패에서 넘기고 어떤 실패에서 끊을지를 봇을 만들기 전에 표로 정한다. 봇이 받는 전화는 결국 상담사에게 가는 길로 돌아온다. 봇은 그 길의 앞부분을 잠시 대신할 뿐이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;앞자리의 나머지 둘, 챗봇과 보이는 ARS&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;챗봇은 글자 창구에 서는 봇이다. 보이스봇과 재료가 같고 음성인식과 음성합성만 뺀 것이다. 고객이 친 글자를 자연어 처리로 다듬고 자연어 이해로 의도를 고르는 것은 보이스봇과 똑같고, 의도를 못 고르면 자연어 처리의 검색으로 자주 묻는 질문에서 비슷한 글을 찾아 보여 준다. 글자로 들어오니 알아듣기는 쉽지만 대신 끝이 없다. 전화는 끊으면 끝나는데 채팅 창은 고객이 닫을 때까지 열려 있다. 그래서 챗봇은 자유롭게 묻는 창과 버튼으로 고르는 메뉴를 섞어 만들고, 버튼은 한 화면에 열 개를 넘기지 않는다. 챗봇이 답하는 자주 묻는 질문의 목록은 뒷자리의 텍스트 분석이 &quot;반복 문의&quot;로 뽑아 준 것에서 나온다. 여기서도 뒷자리가 앞자리의 재료가 된다. 내부 직원을 상대하는 헬프데스크에서는 챗봇이 사내 포털의 자주 묻는 질문과 한 몸이 되어, 전화를 걸기 전에 스스로 해결하는 창구가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보이는 ARS는 통화 위에 뜬 웹 화면이다. 전화 중에 휴대전화 화면이 켜지고 메뉴가 그림으로 보인다. 역할은 셋으로 갈린다. IVR이 화면을 &quot;요청&quot;하고, 따로 있는 웹 서버가 화면을 &quot;띄우고&quot;, 통화는 IVR이 &quot;유지하다가 끊는다&quot;. 화면이 떠 있는 동안 음성 입력은 멈춘다. 설계의 승부처는 통화와 화면의 시간을 맞추는 일이다. 화면마다 입력 제한 시간이 있고, 마지막 &quot;상담원 연결/종료&quot; 화면에는 반드시 시간 제한을 둔다. 고객이 아무것도 안 누르면 통화가 계속 살아 있기 때문이다. 앱이 없는 휴대전화에는 문자로 1회용 링크를 보내는 길을 따로 둔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;채널이 많은 것과 채널이 이어진 것, 멀티채널과 옴니채널&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04_multi-vs-omni.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GgFaM/dJMcadYcalw/SP92fmUUCI4aSD518ROfR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GgFaM/dJMcadYcalw/SP92fmUUCI4aSD518ROfR0/img.png&quot; data-alt=&quot;열려만 있는 창구와 이어진 창구&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GgFaM/dJMcadYcalw/SP92fmUUCI4aSD518ROfR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGgFaM%2FdJMcadYcalw%2FSP92fmUUCI4aSD518ROfR0%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;2400&quot; height=&quot;1600&quot; data-filename=&quot;04_multi-vs-omni.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;열려만 있는 창구와 이어진 창구&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전화만 받던 센터가 채팅, 메신저, 문자, 메일을 함께 받으면 멀티채널이다. 창구가 여러 개 열려 있다는 뜻이다. 그런데 창구가 여럿 열려 있는 것과 창구끼리 이어져 있는 것은 다르다. 고객이 채팅으로 묻다가 전화를 걸었을 때 상담사 화면에 조금 전 채팅이 보이면 이어진 것이고, 보이지 않아 고객이 처음부터 다시 설명하면 열려만 있는 것이다. 이어진 쪽을 옴니채널이라고 부른다. 차이는 창구의 수가 아니라 고객의 맥락이 창구를 넘어 따라가는가에 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현장에서 채널이 전화와 이어지는 자리는 두 곳이다. 하나는 전화가 들어오는 순간, IVR 안이다. 메뉴 하나가 &quot;채팅으로 상담하시려면&quot;으로 되어 있고, 고객이 누르면 IVR이 메신저로 상담 링크를 보내고 통화를 끊는다. 보이는 ARS도 같은 자리에서 시작한다. 다른 하나는 전화가 끝나는 순간이다. IVR의 통화 종료 신호가 문자 발송을 부른다. 상담사 연결 전에 끊긴 고객에게 &quot;다시 연락드리겠습니다&quot;를 보내거나, 업무 시간이 끝난 뒤 걸려온 전화를 콜백 목록에 넣는다. 처음에는 이런 연결이 챗봇의 기능인 줄 알았다. 아니었다. 전부 IVR 시나리오의 상자 하나였다. 전화와 다른 채널을 잇는 것은 인공지능이 아니라 IVR이고, 인공지능은 그 이어진 창구 위에서 일한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;엔진은 사고 모델은 기른다, 인공지능 앞에 만들어야 하는 세 가지&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;05_assets-before-ai.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cToprM/dJMcafV3B6i/2q7Mr8hAwBBzxXnbrFYuIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cToprM/dJMcafV3B6i/2q7Mr8hAwBBzxXnbrFYuIk/img.png&quot; data-alt=&quot;엔진은 공유, 모델∙분류∙지식은 센터마다 기른다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cToprM/dJMcafV3B6i/2q7Mr8hAwBBzxXnbrFYuIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcToprM%2FdJMcafV3B6i%2F2q7Mr8hAwBBzxXnbrFYuIk%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;2400&quot; height=&quot;1320&quot; data-filename=&quot;05_assets-before-ai.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1320&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;엔진은 공유, 모델∙분류∙지식은 센터마다 기른다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 읽으면 한 가지 패턴이 보인다. 음성인식 엔진은 사서 쓰지만 그 센터의 말을 배운 모델은 센터마다 기른다. 텍스트 분석 엔진은 사서 쓰지만 상담 유형의 분류 체계는 센터가 만든다. 지식 추천 엔진은 사서 쓰지만 추천할 지식은 센터가 정리한다. 품질 평가 엔진은 사서 쓰지만 기준표는 센터가 짠다. 인공지능 컨택센터에서 &quot;인공지능&quot;은 사는 것이고, 그것을 쓸모 있게 만드는 세 가지는 기르는 것이다. 분류 체계, 지식, 그리고 그 센터의 말을 받아 적은 표본.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 세 가지는 솔루션을 바꿔도 남는다. 음성인식 엔진을 바꾸면 모델은 다시 배워야 하지만 표본은 그대로 쓴다. 텍스트 분석 솔루션을 바꿔도 분류 체계는 그대로다. 지식은 어느 추천 엔진에 넣어도 지식이다. 그래서 인공지능을 넣기로 한 센터가 당장 할 일은 엔진을 고르는 것이 아니라 이 셋을 만드는 것이다. 분류 체계는 시스템과 증상과 처리로 유형을 다시 정의하고 안 쓰는 유형을 지우는 일, 지식은 매뉴얼과 공지와 자주 묻는 질문을 지식 단위로 쪼개 표준 답변을 붙이는 일, 표본은 실제 통화 수십 시간을 사람이 받아 적어 지금 음성인식이 얼마나 틀리는지 재는 일이다. 셋 다 솔루션 없이 시작할 수 있고, 셋 다 센터 운영자가 주인이다. 인공지능 사업에서 일정을 늘리는 것은 개발이 아니라 이 셋이 없는 상태에서 시작한 것이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;센터가 봇을 들일 준비가 얼마나 됐는지를 볼 때 나는 다섯 가지를 본다. 콜 인프라가 갖춰졌는가. 통화가 글자가 되고 있는가(어느 모드까지). 그 글자로 분류와 요약이 돌고 있는가. 지식이 구조화되어 있는가. 그리고 운영 기반, 그러니까 이중화와 개발계와 보안 절차가 있는가. 앞의 넷이 있어도 마지막이 없으면 바꿀 때마다 운영계를 건드려야 해서 아무도 바꾸지 못한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보이스봇 도입을 설명할 때 전에는 인식률부터 말했다. 숫자가 있어야 설득이 되는 줄 알았다. 지금은 세 가지를 먼저 말한다. 봇은 어디에 서는가. IVR 옆에, 전화의 길을 잠시 대신하는 자리에 선다. 봇이 못 끝내면 어떻게 되는가. 게이트웨이와 교환기가 전화를 상담사에게 돌리고, 봇이 알아낸 의도가 스킬이 되어 고객은 같은 말을 두 번 하지 않는다. 봇이 알아듣게 하려면 무엇이 먼저 있어야 하는가. 그 센터의 말을 배운 음성인식, 정리된 분류 체계, 읽어 줄 지식이다. 이 세 가지에 답이 있으면 봇은 들일 수 있다. 상담사에게 가지 않아도 되는 전화를 그 앞에서 끝내고, 나머지는 상담사에게 넘기는 봇이다. 봇이 상담사를 대신하는 것이 아니라 상담사가 받지 않아도 되는 전화를 대신 받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글은 지금까지 그린 그림을 어디에 두는가다. 내 건물에 서버를 두는 구축형과 남의 건물을 빌려 쓰는 클라우드, 그리고 센터의 모든 부분을 서비스로 받는 CCaaS. 그리고 인공지능을 넣은 효과를 무엇으로 재는지와, 아홉 단계와 요소들을 한 표로 정리한 결산까지 간다.&lt;/p&gt;</description>
      <category>tech</category>
      <category>AICC</category>
      <category>ivr</category>
      <category>mrcp</category>
      <category>Omnichannel</category>
      <category>Voicebot</category>
      <category>보이는 ARS</category>
      <category>보이스봇</category>
      <category>옴니채널</category>
      <category>인공지능 컨택센터</category>
      <category>챗봇</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/11</guid>
      <comments>https://hsjo.tistory.com/11#entry11comment</comments>
      <pubDate>Tue, 13 Oct 2026 22:48:52 +0900</pubDate>
    </item>
    <item>
      <title>상담사는 통화만 하고 받아쓰기와 찾기와 정리는 인공지능이 맡는다</title>
      <link>https://hsjo.tistory.com/10</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;썸네일.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OkyMa/dJMcabeMQeA/ECea2eUnDmzfyoxSC4AjnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OkyMa/dJMcabeMQeA/ECea2eUnDmzfyoxSC4AjnK/img.png&quot; data-alt=&quot;상담사는 말만 하고, 옆과 뒤에서 손이 움직인다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OkyMa/dJMcabeMQeA/ECea2eUnDmzfyoxSC4AjnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOkyMa%2FdJMcabeMQeA%2FECea2eUnDmzfyoxSC4AjnK%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;1672&quot; height=&quot;941&quot; data-filename=&quot;썸네일.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;상담사는 말만 하고, 옆과 뒤에서 손이 움직인다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;잠시만요, 확인해 보겠습니다.&quot; 고객센터에 전화해 본 사람이면 이 말 뒤의 침묵을 안다. 수화기 너머에서 자판 소리가 나고, 상담사는 방금 들은 말을 받아 적고, 매뉴얼을 뒤지고, 옆자리에 묻는다. 전화가 끝나면 그 상담사에게는 또 다른 일이 남는다. 무슨 상담이었는지 유형을 고르고, 몇 줄을 적고, 필요하면 후속 처리를 건다. 상담사의 하루는 통화보다 통화 앞뒤의 일이 길다. 상담사를 돕는 인공지능이 손을 대는 곳이 바로 거기다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 글에서 상담사를 돕는 인공지능의 재료를 봤다. 소리를 글자로 바꾸는 음성인식, 글자를 다루는 자연어 처리와 알아듣는 자연어 이해, 그리고 소리를 대 주는 녹취. 이 글은 그 재료가 상담사 옆자리와 뒷자리에서 실제로 하는 일이다. 인공지능 컨택센터에서 인공지능은 상담사 책상의 세 자리에 앉는다. 상담사보다 먼저 받는 앞자리, 통화 중에 거드는 옆자리, 통화 뒤에 정리하는 뒷자리. 이 글은 그 중 옆과 뒤, 상담사를 대신하지 않고 돕는 두 자리를 다룬다. 먼저 상담사의 한 통을 칸으로 나눈다. 그래야 &quot;돕는다&quot;가 어디에 돕는 것인지 보인다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;상담사의 한 통은 여섯 칸으로 나뉜다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01_call-six-cells.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/doppDU/dJMcaa1oA6U/huh4oV5H6VsJUTqQmLYEyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/doppDU/dJMcaa1oA6U/huh4oV5H6VsJUTqQmLYEyK/img.png&quot; data-alt=&quot;한 통의 여섯 칸, 인공지능이 끼어드는 칸은 넷&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/doppDU/dJMcaa1oA6U/huh4oV5H6VsJUTqQmLYEyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdoppDU%2FdJMcaa1oA6U%2Fhuh4oV5H6VsJUTqQmLYEyK%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;2400&quot; height=&quot;1520&quot; data-filename=&quot;01_call-six-cells.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;한 통의 여섯 칸, 인공지능이 끼어드는 칸은 넷&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인공지능이 상담사를 &quot;돕는다&quot;는 말을 구체적으로 하려면 상담사의 한 통을 칸으로 나눠야 한다. 전화가 들어온다(인입). 고객이 무엇을 묻는지 알아듣는다(문의 파악). 답을 찾는다(지식 탐색). 안내하고 해결한다(안내∙해결). 전화를 끊고 기록한다(후처리). 그 기록이 통계와 다음 상담에 쓰인다(이력 활용). 여섯 칸이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인공지능이 들어오기 전의 여섯 칸은 이렇다. 인입은 대기 시간이 전부다. 문의 파악은 귀로 듣고 되묻는다. 지식 탐색은 매뉴얼을 뒤지고 옆자리에 묻고 메신저로 선배에게 묻는다. 안내는 상담사의 기억에 따라 조금씩 다르다. 후처리는 유형을 손으로 고르고 몇 줄을 타이핑한다. 이력은 건수만 집계되고 녹취는 필요할 때 사람이 듣는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인공지능이 들어온 뒤의 여섯 칸은 이렇다. 인입은 그대로다(다만 문의가 갑자기 몰리면 알려 준다). 문의 파악에는 실시간 대화록이 올라오고 핵심 질문이 짚인다. 지식 탐색에는 지식이 화면에 먼저 추천된다. 안내에는 표준 답변이 떠 있고 해결 여부가 기록된다. 후처리에는 유형과 요약이 자동으로 채워져 상담사는 확인만 한다. 이력에는 반복 문의가 자주 묻는 질문으로 뽑히고 고객의 소리가 분석된다. 여섯 칸 중 인공지능이 끼어드는 칸은 넷이고, 그중 시간이 가장 많이 줄어드는 칸은 지식 탐색과 후처리다. 이 두 칸이 상담사의 한 통에서 통화 자체 다음으로 긴 칸이기 때문이다. 옆자리는 둘째&amp;middot;셋째&amp;middot;넷째 칸에 앉고, 뒷자리는 다섯째&amp;middot;여섯째 칸에 앉는다. 앞자리의 봇은 첫째 칸 앞에 선다. 세 자리를 이 여섯 칸 위에 올려놓으면 &quot;돕는다&quot;가 어디를 돕는 것인지 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;옆자리, 상담 어시스트는 받아 적고 찾아 준다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02_assist-realtime.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/doUCup/dJMcabMXeSm/GcvN0pZQcAcUk7hFbin5N1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/doUCup/dJMcabMXeSm/GcvN0pZQcAcUk7hFbin5N1/img.png&quot; data-alt=&quot;녹취가 복사한 소리가 글자로 되어 화면으로&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/doUCup/dJMcabMXeSm/GcvN0pZQcAcUk7hFbin5N1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdoUCup%2FdJMcabMXeSm%2FGcvN0pZQcAcUk7hFbin5N1%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;2400&quot; height=&quot;1280&quot; data-filename=&quot;02_assist-realtime.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1280&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;녹취가 복사한 소리가 글자로 되어 화면으로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상담사 옆자리의 인공지능은 전화가 상담사에게 연결되는 순간부터 끊길 때까지 일한다. 소리는 녹취에서 온다. 녹취 서버는 통화가 연결되는 순간부터 고객 쪽 소리와 상담사 쪽 소리를 따로 복사해 저장하는 장치이고, 인공지능 컨택센터에서는 그 소리를 인공지능에게 넘기는 공급원이기도 하다. 녹취가 받은 소리를 음성인식 서버로 흘려보내고, 음성인식이 한 문장씩 글자로 바꿔 실시간 저장소에 놓고, 상담 어시스트가 그것을 가져가 상담 프로그램 화면에 올린다. 상담사 화면 한쪽에 고객과 자기 말이 말풍선으로 올라온다. 고객 쪽 소리와 상담사 쪽 소리가 따로 흐르기 때문에 누가 한 말인지 구분된다. 이 화면을 실시간 대화록이라고 부르고, 말이 끝나고 글자가 뜨기까지 몇 초 안에 들어와야 상담사가 쓴다. 늦게 뜨는 글자는 없는 글자와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글자가 올라오면 그 위에서 네 가지 일이 더 일어난다. 첫째, 핵심 질문 짚기. 자연어 처리가 대화에서 상품명이나 민원의 종류 같은 열쇠말을 뽑아 &quot;지금 고객이 묻는 것은 이것&quot;을 표시한다. 둘째, 지식 추천. 짚은 열쇠말과 비슷한 뜻의 문서를 자연어 처리의 검색으로 지식관리에서 찾아 안내문, 약관, 처리 절차, 장애 공지를 화면에 미리 올려 둔다. 상담사가 검색창에 치기 전에 답이 올라와 있는 셈이다. 셋째, 말 점검. 반드시 해야 하는 안내 문장이 상담사 쪽 글자에 나왔는지 자연어 처리로 맞춰 보고, 아직 안 했으면 표시해 주고, 써서는 안 되는 표현이 나오면 알려 준다. 넷째, 상담 유형 추천. 자연어 이해가 통화가 끝나기도 전에 &quot;이 상담은 이 유형 같다&quot;를 골라 둔다. 봇이 고객의 의도를 고르는 것과 같은 기술로 상담의 유형을 고르는 것이다. 통화가 끝나면 상담사는 맞으면 누르고 틀리면 고른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;통화가 끝난 뒤에도 옆자리의 화면은 쓸모가 있다. 녹취를 다시 들을 때 소리와 글자가 함께 움직인다. 글자를 누르면 그 부분의 소리가 나오고, 소리를 들으면 그 글자에 불이 들어온다. 민원 통화를 처음부터 끝까지 다시 듣는 대신 글자로 훑다가 필요한 곳만 듣는다. 관리자가 상담사의 통화를 코칭할 때 가장 많이 쓰는 화면이기도 하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 자리가 중요한 이유는 고객이 아니라 상담사 쪽에 있다. 고객은 봇을 만나지 않아도 이 자리의 덕을 본다. 상담사가 &quot;잠시만요, 확인해 보겠습니다&quot;라고 말하는 시간이 줄어든다. 신입 상담사와 숙련 상담사의 차이도 여기서 줄어든다. 숙련 상담사의 머릿속에 있던 &quot;이 질문에는 이 문서&quot;가 화면에 올라오기 때문이다. 여러 업무를 한 사람이 받는 작은 센터일수록 이 효과가 크다. 상담 어시스트는 상담사를 대신하지 않는다. 상담사가 손으로 하던 받아쓰기와 찾기를 대신한다. 내가 본 인공지능 컨택센터의 효과 중 가장 조용하고 가장 꾸준한 것이 이 자리였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;뒷자리 하나, 텍스트 분석은 통화 뒤에 글자를 읽는다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03_ta-qa.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dexmWV/dJMcaatEdiN/zTp0iUYhnEa4GtkERAUFF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dexmWV/dJMcaatEdiN/zTp0iUYhnEa4GtkERAUFF1/img.png&quot; data-alt=&quot;텍스트 분석과 품질 평가, 대화록이 숫자와 점수가 되기까지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dexmWV/dJMcaatEdiN/zTp0iUYhnEa4GtkERAUFF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdexmWV%2FdJMcaatEdiN%2FzTp0iUYhnEa4GtkERAUFF1%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;2400&quot; height=&quot;1640&quot; data-filename=&quot;03_ta-qa.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;텍스트 분석과 품질 평가, 대화록이 숫자와 점수가 되기까지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전화가 끊기면 상담사에게 남는 일이 있다. 무슨 상담이었는지 유형을 고르고, 내용을 몇 줄로 적고, 필요하면 후속 처리를 건다. 이것을 후처리라고 부르고, 통화 시간만큼 길어지기도 한다. 뒷자리의 첫 번째 인공지능인 텍스트 분석이 이 일을 받는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;텍스트 분석은 통화가 끝났다는 신호를 받으면 그 통화의 대화록 전체를 읽는다. 옆자리가 한 문장씩 읽는다면 뒷자리는 통화 한 건을 통째로 읽는다. 그리고 세 가지를 만든다. 요약문, 상담 유형, 열쇠말. 셋 다 자연어 처리다. 요약은 긴 글을 짧게 줄이는 기술이고, 상담 유형은 글을 미리 정한 목록 중 하나로 가르는 분류이며(봇의 자연어 이해와 같은 식구다), 열쇠말은 중요한 낱말을 뽑는 추출이다. 여기에 고객이 화가 났는지 읽는 감성 분석을 붙이는 센터도 있다. 요약문은 상담사가 적던 몇 줄을 대신하고, 상담 유형은 통계의 뼈대가 되며, 열쇠말은 &quot;이번 달에 어떤 문의가 늘었나&quot;를 셀 때 쓴다. 상담 유형은 자동으로 적지 않고 상담사 화면에 띄워 확정을 받는다. 보통 후보를 두어 개 보여 주고 상담사가 고른다. 통화가 끝난 직후에 분석이 아직 안 끝나 있을 수도 있어서, 정해진 시간 안에 답이 안 오면 상담사가 직접 고르게 둔다. 자동으로 고른 값과 상담사가 확정한 값은 둘 다 남긴다. 둘이 자주 다르면 텍스트 분석을 다시 가르칠 때가 된 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 분류 체계 이야기를 해야 한다. 텍스트 분석이 고르는 &quot;상담 유형&quot;은 센터가 미리 정해 둔 목록이다. 대분류, 중분류, 소분류로 수십에서 수백 개가 된다. 이 목록이 엉성하면 아무리 좋은 분석도 엉성한 답을 낸다. 같은 문의가 세 군데 유형에 걸쳐 있거나, 쓰지 않는 유형이 수십 개 남아 있거나, 상담사마다 다른 유형을 고르는 센터에서는 자동 분류가 자리를 잡지 못한다. 그래서 텍스트 분석을 넣기 전에 분류 체계부터 다시 짠다. 이 일은 솔루션이 아니라 센터 운영자가 하고, 보통 몇 주가 걸린다. 인공지능을 넣는 사업에서 가장 오래 걸리는 일이 코딩이 아니라 이 목록 정리인 경우가 흔하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 사람이 확정하는가. 기록의 책임이 여전히 상담사에게 있기 때문이다. 그리고 텍스트 분석은 음성인식이 적어 준 글자만 읽는다. 글자가 비어 있으면 &quot;통화가 없었는지, 음성인식이 멈췄는지&quot;를 구분하지 못한다. 뒷자리의 통계가 어느 날 텅 비어 있으면 가장 먼저 보는 곳은 텍스트 분석이 아니라 그 앞의 음성인식과 녹취다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;뒷자리 둘, 품질 평가는 전수로 보고 사람은 일부만 듣는다&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상담 품질 평가(QA)는 원래 관리자가 녹취를 골라 듣고 기준표에 점수를 매기는 일이었다. 기준표에는 보통 이런 항목이 있다. 첫인사와 끝인사를 했는가, 반드시 안내해야 하는 문장을 빠뜨리지 않았는가, 금지된 표현을 쓰지 않았는가, 고객의 말을 끊지 않았는가, 안내가 정확했는가. 하루에 들을 수 있는 통화는 몇 건뿐이라 표본으로 뽑아 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대화록이 글자로 있으면 이 기준표의 상당 부분을 전수로 확인할 수 있다. 필수 안내 문장이 들어 있는지, 금지 표현이 나왔는지는 자연어 처리의 문장 맞추기 문제다. 토씨가 조금 달라도 같은 문장으로 알아보는 것이 글자 검색과 다른 점이다. 고객이 언성을 높였는지는 감성 분석이 읽는다. 사람이 듣는 것은 그중 확인이 필요한 통화뿐이다. 점수가 낮은 통화, 고객이 언성을 높인 통화, 상담사가 이의를 제기한 통화. 품질 평가의 결과는 상담사별 점수와 코칭 기록으로 남고, 상담사는 자기 통화의 글자를 보며 어디서 점수가 깎였는지 확인한다. 옆자리의 &quot;말 점검&quot;이 통화 중에 미리 알려 주는 것과 뒷자리의 품질 평가가 통화 뒤에 점수를 매기는 것은 같은 기준표를 두 번 쓰는 셈이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;품질 평가가 모든 센터에 같은 무게는 아니다. 고객에게 상품을 파는 센터에서는 불완전 판매를 걸러내는 일이라 핵심이고, 회사 안의 직원을 상대하는 내부 헬프데스크에서는 친절보다 정확한 안내와 해결 여부가 중요해 기준표를 다시 짠다. 기준표가 센터마다 다르니 평가도 센터마다 다시 설계한다. 여기에도 같은 원칙이 붙는다. 품질 평가는 글자를 읽는다. 음성인식이 비면 평가도 빈다. 그래서 센터 운영자는 &quot;글자가 안 올라온다&quot;는 말을 들으면 음성인식과 녹취부터 보고, &quot;글자는 있는데 점수가 안 나온다&quot;는 말을 들으면 품질 평가를 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상담사를 돕는 인공지능이 하는 일을 한 줄로 줄이면 제목 그대로다. 상담사는 통화만 하고, 받아쓰기와 찾기와 정리는 인공지능이 맡는다. 받아쓰기는 실시간 대화록이, 찾기는 지식 추천이, 정리는 요약과 분류와 점수가 가져간다. 전화를 대신 받는 봇이 없어도 이 두 자리만으로 센터는 달라진다. 내가 본 인공지능 컨택센터의 효과 중 가장 조용하고 가장 꾸준한 것이 이 자리였다는 말을 앞에서 했는데, 조용한 이유도 같다. 고객은 봇을 만나지 않았고, 상담사는 평소처럼 통화했고, 다만 &quot;잠시만요&quot;가 짧아졌을 뿐이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 센터에 인공지능을 넣자는 이야기가 나오면 나는 봇보다 이 두 자리를 먼저 묻는다. 통화가 글자가 되고 있는가, 그 글자 위에 지식이 올라오는가, 통화가 끝나면 유형과 요약이 채워지는가. 이 셋이 돌아야 봇이 알아들을 말과 읽어 줄 지식이 생긴다. 다음 글은 그 봇이다. 상담사보다 먼저 전화를 받는 보이스봇이 전화의 길 어디에 서는지, 챗봇과 보이는 ARS는 무엇이 다른지, 그리고 그 전에 센터가 길러 두어야 하는 세 가지를 본다.&lt;/p&gt;</description>
      <category>tech</category>
      <category>Agent Assist</category>
      <category>AICC</category>
      <category>kms</category>
      <category>QA</category>
      <category>TA</category>
      <category>상담 어시스트</category>
      <category>상담 품질 평가</category>
      <category>인공지능 컨택센터</category>
      <category>텍스트 분석</category>
      <category>후처리 자동화</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/10</guid>
      <comments>https://hsjo.tistory.com/10#entry10comment</comments>
      <pubDate>Tue, 13 Oct 2026 00:38:06 +0900</pubDate>
    </item>
    <item>
      <title>상담사를 돕는 인공지능은 무엇으로 만들어지는가, STT&amp;middot;TTS&amp;middot;NLP&amp;middot;NLU</title>
      <link>https://hsjo.tistory.com/9</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;썸네일.png&quot; data-origin-width=&quot;1774&quot; data-origin-height=&quot;887&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LzZ50/dJMcaggcK8c/2fnOp6jrps0PHOVqFrck30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LzZ50/dJMcaggcK8c/2fnOp6jrps0PHOVqFrck30/img.png&quot; data-alt=&quot;소리를 글자로, 글자를 소리로, 그 사이에 선 재료들&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LzZ50/dJMcaggcK8c/2fnOp6jrps0PHOVqFrck30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLzZ50%2FdJMcaggcK8c%2F2fnOp6jrps0PHOVqFrck30%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;1774&quot; height=&quot;887&quot; data-filename=&quot;썸네일.png&quot; data-origin-width=&quot;1774&quot; data-origin-height=&quot;887&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;소리를 글자로, 글자를 소리로, 그 사이에 선 재료들&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보이스봇, 상담사 화면에 올라오는 실시간 대화록, 통화가 끝나면 저절로 채워지는 요약문. 겉모습은 전혀 다르다. 그런데 뜯어 보면 같은 부품으로 만들어져 있다. 소리를 글자로 바꾸는 부품, 글자를 소리로 바꾸는 부품, 글자를 다루고 알아듣는 부품. 그리고 그 부품들에 소리를 대 주는 장치가 하나 있다. 녹취다. 센터에 인공지능을 넣을 때 먼저 정할 것이 어느 봇을 살지가 아니라 이 부품들을 어떻게 갖출지인 이유가 여기에 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 글에서 인공지능 컨택센터(AICC)를 한 장의 지도로 그렸다. 인공지능은 상담사 책상의 세 자리에 앉는다. 상담사보다 먼저 받는 앞자리, 통화 중에 거드는 옆자리, 통화 뒤에 정리하는 뒷자리. 전화를 대신 받는 앞자리는 눈에 띄고, 옆자리와 뒷자리는 눈에 띄지 않지만 효과는 그쪽이 꾸준하다. 이 글은 그 세 자리가 공통으로 쓰는 재료와, 재료에 소리를 공급하는 녹취를 본다. 요소의 이름은 다음 글부터 하나씩 나오고, 여기서는 그 요소들이 무엇으로 만들어지는지만 본다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;재료 세 가지, 소리를 글자로∙글자를 소리로∙글자를 다루기&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01_ingredients.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFDp8G/dJMcaaf6C7I/sJAaw9TFMbU9Wuvnk6GEl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFDp8G/dJMcaaf6C7I/sJAaw9TFMbU9Wuvnk6GEl1/img.png&quot; data-alt=&quot;소리를 글자로, 글자를 소리로, 글자를 다루고 알아듣기, 그리고 누가 무엇을 쓰나&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFDp8G/dJMcaaf6C7I/sJAaw9TFMbU9Wuvnk6GEl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFDp8G%2FdJMcaaf6C7I%2FsJAaw9TFMbU9Wuvnk6GEl1%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;2400&quot; height=&quot;1640&quot; data-filename=&quot;01_ingredients.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1640&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;소리를 글자로, 글자를 소리로, 글자를 다루고 알아듣기, 그리고 누가 무엇을 쓰나&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인공지능 컨택센터의 구성 요소는 이름이 많지만 재료는 셋이다. 소리를 글자로 바꾸는 음성인식, 글자를 소리로 바꾸는 음성합성, 그리고 글자를 다루는 기술. 세 번째 재료는 이름이 둘이다. 글자를 다루는 기술 전체를 자연어 처리(NLP)라고 부르고, 그중 &quot;무슨 뜻인지 알아듣는&quot; 부분을 자연어 이해(NLU)라고 부른다. 둘을 섞어 쓰는 자료가 많아 처음 배우는 사람이 가장 헷갈리는 자리라 따로 풀어 쓴다. 보이스봇은 세 재료를 다 쓰고, 상담사 옆자리와 뒷자리는 주로 음성인식과 자연어 처리를 쓴다. 재료가 같으니 센터 하나에 음성인식 엔진은 보통 하나다. 봇도 그것을 쓰고 상담사 옆자리도 그것을 쓴다. 이 셋을 모르면 뒤의 모든 요소가 블랙박스로 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;b&gt;음성인식(STT, Speech To Text).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 전화에서 흘러온 소리를 글자로 적는다. 사람이 받아쓰는 속기사와 같은 일인데, 다른 점이 셋 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02_stt.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KUQXB/dJMcaatD6HB/afpkVVPc68eNP2EOYtxUa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KUQXB/dJMcaatD6HB/afpkVVPc68eNP2EOYtxUa0/img.png&quot; data-alt=&quot;음성인식, 실시간과 사후, 그리고 학습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KUQXB/dJMcaatD6HB/afpkVVPc68eNP2EOYtxUa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKUQXB%2FdJMcaatD6HB%2FafpkVVPc68eNP2EOYtxUa0%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;2400&quot; height=&quot;1440&quot; data-filename=&quot;02_stt.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;음성인식, 실시간과 사후, 그리고 학습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, 문장 단위로 끊는다. 말이 멈추는 지점(발화 끝)을 찾아 그 사이를 한 덩어리로 글자로 바꾼다. 상담사 화면에 말풍선이 한 개씩 올라오는 것은 이 덩어리 하나가 끝날 때마다다. 둘째, 두 가지 방식으로 돈다. 통화 중에 바로바로 적는 실시간 방식과, 통화가 끝난 뒤 녹취 파일을 통째로 적는 사후 방식이다. 둘은 같은 엔진을 쓰지만 다른 모듈이고 다른 자리에 쓰인다. 실시간은 옆자리로, 사후는 뒷자리로 간다. 셋째, 배워야 한다. 처음 가져온 음성인식은 일반 말은 잘 알아듣지만 그 센터의 상품 이름, 지점 이름, 전문 용어, 오류 코드는 자주 틀린다. 그래서 그 센터의 실제 통화를 사람이 받아 적은 표본으로 가르친다. 배우는 서버와 일하는 서버가 따로 있는 이유다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인식률은 &quot;잘 알아듣는 것 같다&quot;로 재지 않고 그 정답지와 글자 단위로 견주어 오류율로 잰다. 솔직히 이 숫자는 늘 기대보다 낮게 나온다. 상담사의 말은 헤드셋으로 또렷하게 들어오지만 고객의 말은 지하철에서, 스피커폰으로, 아이가 우는 거실에서 들어오기 때문이다. 고객 쪽 인식률이 상담사 쪽보다 늘 낮다. 그리고 엔진은 사서 쓰지만 그 센터의 말을 배운 모델은 센터마다 다시 기른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;음성합성(TTS, Text To Speech).&lt;/b&gt;&lt;/span&gt;&lt;/u&gt; 글자를 소리로 읽는다. 전화를 받으면 먼저 나오는 IVR의 안내 멘트는 원래 성우가 녹음한 파일이었다. 멘트가 바뀔 때마다 성우를 다시 부를 수 없으니, 글자만 고치면 소리가 나오는 음성합성이 그 자리를 대신해 왔다. 보이스봇 이전에도 IVR 옆에는 음성합성 서버가 있었다. 보이스봇은 이것을 훨씬 많이 쓴다. 봇이 하는 모든 말이 글자에서 시작하기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03_tts.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxbLcY/dJMcadRhIRg/SEjaFZEjrATMMRKdBaMtik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxbLcY/dJMcadRhIRg/SEjaFZEjrATMMRKdBaMtik/img.png&quot; data-alt=&quot;음성합성, 글자가 전화 목소리가 되기까지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxbLcY/dJMcadRhIRg/SEjaFZEjrATMMRKdBaMtik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxbLcY%2FdJMcadRhIRg%2FSEjaFZEjrATMMRKdBaMtik%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;2400&quot; height=&quot;1200&quot; data-filename=&quot;03_tts.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;음성합성, 글자가 전화 목소리가 되기까지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현장에서 음성합성은 &quot;읽어 주는 기능&quot; 하나가 아니라 묶음이다. 자주 쓰는 문장은 미리 만들어 저장해 두고 꺼내 쓴다. 그래야 봇의 첫마디가 늦지 않는다. 영문 약어나 상품명은 어떻게 읽을지 사전에 적어 둔다. 목소리는 시나리오 단위로 고른다. 그리고 전화망에 맞게 소리를 낮춘다. 전화는 음악을 듣는 길이 아니라서 소리의 결이 거칠다. 음성합성이 아무리 고운 소리를 만들어도 전화기에서는 전화 음질로 들린다. 성우 녹음과 음성합성은 멘트 번호로 서로 바꿔 끼울 수 있게 둔다. 급하게 바꿀 멘트는 합성으로, 오래 쓸 인사말은 녹음으로 가는 식이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;b&gt;자연어 처리(NLP, Natural Language Processing).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 글자를 다루는 기술 전체의 이름이다. 국어 선생님이 하는 일을 떠올리면 된다. 문장을 낱말로 쪼개고(형태소 분석), 오타를 고치고, 같은 뜻의 다른 말을 알아보고(동의어 사전), 글이 무엇에 관한 글인지 가르고(분류), 중요한 낱말을 뽑고(열쇠말 추출), 긴 글을 짧게 줄이고(요약), 글의 기분을 읽고(감성 분석), 비슷한 글을 찾는다(검색). 컨택센터에서 음성인식이 만든 글자는 전부 이 기술을 한 번 이상 거친다. 상담 유형을 나누는 것도, 통화를 몇 줄로 줄이는 것도, 이번 달 많이 나온 낱말을 세는 것도, 지식 중에서 지금 상담에 맞는 문서를 찾는 것도 자연어 처리다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;b&gt;자연어 이해(NLU, Natural Language Understanding).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 자연어 처리 중에서 &quot;이 사람이 무엇을 하려는가&quot;를 알아듣는 부분이다. &quot;보험금 청구가 어디까지 됐나요&quot;에서 의도는 &quot;청구 진행 조회&quot;다. 문장 안의 값도 함께 뽑는다. 날짜, 금액, 번호, 지점 이름. 이것을 개체라고 부른다. 자연어 이해는 의도마다 예문을 수십 개씩 넣어 가르치고, 그 앞에 자연어 처리의 오타 사전과 동의어 사전을 붙여 &quot;청구&quot;와 &quot;청구금&quot;과 &quot;보험금&quot;이 같은 뜻임을 알게 한다. 봇이 &quot;다시 한번 말씀해 주세요&quot;라고 하는 순간은 대개 음성인식이 아니라 여기서 막힌 순간이다. 글자는 제대로 적혔는데 어느 의도인지 못 고른 것이다. 자연어 처리가 글자를 &quot;다루는&quot; 기술이라면 자연어 이해는 그중 글자를 &quot;알아듣는&quot;기술이고, 봇은 알아들어야 다음 말을 고를 수 있어서 자연어 이해를 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;누가 무엇을 쓰는지 미리 적어 두면 뒤의 글이 읽기 쉽다. 보이스봇과 챗봇은 자연어 이해를 쓴다(고객의 말이 어느 의도인지 골라야 시나리오로 갈 수 있다). 상담 어시스트는 자연어 처리로 열쇠말을 뽑아 핵심 질문을 짚고 지식을 찾고, 자연어 이해로 상담 유형을 추천 한다. 텍스트 분석은 자연어 처리의 분류∙요약∙열쇠말∙감성 분석을 거의 다 쓴다. 품질 평가는 자연어 처리로 필수 문장이 있는지 맞춰 보고 고객의 기분을 읽는다. 지식관리는 자연어 처리의 검색을 쓴다. 자연어 이해가 봇의 재료라면 자연어 처리는 옆자리와 뒷자리 전체의 재료다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;녹취, 인공지능이 소리를 받는 자리&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04_recording.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/J17H7/dJMcaieenI9/wqMbjkpZqXz27z0VHQOxzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/J17H7/dJMcaieenI9/wqMbjkpZqXz27z0VHQOxzk/img.png&quot; data-alt=&quot;녹취는 기록이자 인공지능의 소리 공급원&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/J17H7/dJMcaieenI9/wqMbjkpZqXz27z0VHQOxzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJ17H7%2FdJMcaieenI9%2FwqMbjkpZqXz27z0VHQOxzk%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;2400&quot; height=&quot;1320&quot; data-filename=&quot;04_recording.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1320&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;녹취는 기록이자 인공지능의 소리 공급원&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;녹취 서버는 상담사에게 전화가 연결되는 순간부터 통화의 소리(RTP)를 복사해 저장한다. 원래 그것은 기록을 위한 장치였다. 민원이 들어오면 다시 듣고, 법으로 남겨야 하는 통화를 보관하는 장치. 인공지능 컨택센터에서 녹취는 하나의 역할을 더 맡는다. 상담사 옆자리와 뒷자리의 인공지능에게 소리를 넘기는 공급원이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 교환기가 아니라 녹취인가? 교환기는 전화를 연결하는 장치라 소리를 밖으로 내주는 일에 서툴다. 녹취는 처음부터 소리를 복사하려고 만든 장치다. 이미 고객 쪽 소리와 상담사 쪽 소리를 따로 받고 있다. 두 사람이 동시에 말해도 누가 한 말인지 갈라지는 이유이고, 이것을 화자 분리라고 부른다. 화자 분리가 안 된 녹취로는 뒤의 분석이 절반밖에 안 된다. 상담사가 필수 안내를 했는지 보려면 상담사쪽 소리가 따로 있어야 하기 때문이다. 녹취를 쓸 수 없는 센터에서는 네트워크 스위치에서 소리를 복사하는 장비를 따로 두기도 하지만, 통화가 암호화되어 있으면 그 길은 막힌다. 어느 쪽이든 원칙은 같다. 상담사 옆자리와 뒷자리는 녹취가 없으면 성립하지 않는다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;05_data-flow.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bg7XBs/dJMcadYbnVX/miAk6lPWay3FPCySN4X5S0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bg7XBs/dJMcadYbnVX/miAk6lPWay3FPCySN4X5S0/img.png&quot; data-alt=&quot;소리가 글자가 되어 흐르는 길, 네 가지 모드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bg7XBs/dJMcadYbnVX/miAk6lPWay3FPCySN4X5S0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbg7XBs%2FdJMcadYbnVX%2FmiAk6lPWay3FPCySN4X5S0%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;2400&quot; height=&quot;1560&quot; data-filename=&quot;05_data-flow.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;소리가 글자가 되어 흐르는 길, 네 가지 모드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;녹취에서 나온 소리가 글자가 되어 어디로 가는지를 한 줄로 그리면 이렇다. 녹취가 화자별 소리를 음성인식에 넘긴다. 음성인식이 글자로 바꾼다. 글자는 두 곳에 놓인다. 실시간 저장소와 통합 데이터베이스. 실시간 저장소의 글자는 상담 어시스트가 바로 가져가 화면에 올리고, 통합 데이터베이스의 글자는 텍스트 분석과 품질 평가가 통화가 끝난 뒤 가져간다. 음성인식이 틀린 말은 따로 모아 학습 서버로 보내고, 다시 배운 모델을 일하는 서버에 올린다. 이 한 줄에 모드가 넷 있다. 통화 중에 발화 단위로 흐르는 실시간, 통화가 끝난 뒤 파일 단위로 바꾸는 준실시간, 관리자가 녹취 화면에서 한 건을 눌러 바꾸는 단건, 과거 녹취를 한꺼번에 바꾸는 일괄. 센터가 &quot;음성인식을 넣었다&quot;고 할 때 네 모드 중 어디까지 들어왔는지가 그 센터의 깊이다. 요청할 때만 한 건씩 바꾸는 센터와, 모든 통화가 끝나자마자 글자가 되는 센터는 같은 엔진을 쓰고도 전혀 다른 센터다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 한 가지가 따라온다. 통화가 언제 시작되고 끝났는지를 누가 알려 주는가다. 녹취와 음성인식은 소리만 받지 전화의 사정을 모른다. &quot;이 소리가 어느 통화의 것인지, 상담사가 받은 순간이 언제인지&quot;는 CTI와 상담 프로그램이 알려 준다. 이 신호가 어긋나면 상담사가 받기 전의 통화 연결음이 글자로 찍히거나, 녹취와 글자의 시각이 몇 초 어긋난다. 전화의 사정을 아는 것은 CTI뿐이라, 인공지능이 들어와도 통화의 주인은 여전히 CTI다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재료를 요소보다 먼저 말하게 된 것은 요소의 이름으로 설명하다 막힌 뒤부터다. 상담 어시스트가 무엇이냐는 질문에 화면의 기능을 나열하면 듣는 사람은 끝까지 블랙박스를 보고 있다. 음성인식이 문장 단위로 글자를 올리고, 자연어 처리가 그 글자에서 열쇠말을 뽑고, 그 소리는 녹취가 복사해 준 것이라고 말하면 그제야 그림이 선다. 그래서 지금은 순서를 바꿔 말한다. 엔진은 센터 하나에 하나이고, 그 엔진에 그 센터의 말을 가르치는 일과 소리를 끊기지 않게 대 주는 일이 요소 열 개를 받치고 있다. 봇을 고르는 일은 그다음이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글은 이 재료가 상담사 옆과 뒤에서 실제로 하는 일이다. 상담사의 한 통을 여섯 칸으로 나누고, 통화 중에 받아 적고 찾아 주는 상담 어시스트, 통화 뒤에서 요약하고 분류하고 점수를 매기는 텍스트 분석과 품질 평가를 본다. 상담사를 돕는 인공지능이 어디를 돕는지가 거기서 보인다.&lt;/p&gt;</description>
      <category>tech</category>
      <category>AICC</category>
      <category>NLP</category>
      <category>NLU</category>
      <category>STT</category>
      <category>tts</category>
      <category>음성인식</category>
      <category>음성합성</category>
      <category>인공지능 컨택센터</category>
      <category>자연어 이해</category>
      <category>자연어 처리</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/9</guid>
      <comments>https://hsjo.tistory.com/9#entry9comment</comments>
      <pubDate>Mon, 12 Oct 2026 20:23:52 +0900</pubDate>
    </item>
    <item>
      <title>인공지능은 컨택센터 어디에서 상담사를 돕는가, AICC란 무엇인가</title>
      <link>https://hsjo.tistory.com/8</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;썸네일.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EYDxa/dJMcafPkti6/9QLIaQ6CJ1W1tYBsWpDFV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EYDxa/dJMcafPkti6/9QLIaQ6CJ1W1tYBsWpDFV1/img.png&quot; data-alt=&quot;상담사 책상의 앞&amp;amp;middot;옆&amp;amp;middot;뒤에 선 세 개의 빛&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EYDxa/dJMcafPkti6/9QLIaQ6CJ1W1tYBsWpDFV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEYDxa%2FdJMcafPkti6%2F9QLIaQ6CJ1W1tYBsWpDFV1%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;1672&quot; height=&quot;941&quot; data-filename=&quot;썸네일.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;상담사 책상의 앞&amp;middot;옆&amp;middot;뒤에 선 세 개의 빛&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객센터에 전화를 걸면 요즘은 &quot;무엇을 도와드릴까요&quot;라는 말이 먼저 나온다. 버튼을 누르는 대신 말을 하면 알아듣고, 상담사에게 넘어가면 상담사는 내가 방금 한 말을 이미 알고 있다. 이것을 인공지능 컨택센터, AICC(Artificial Intelligence Contact Center)라고 부른다. 그런데 사람 대신 기계가 전화를 받는 센터라고 하면 절반만 맞다. 전화를 대신 받는 인공지능은 눈에 띄는 한 자리일 뿐이고, 인공지능 컨택센터의 효과 대부분은 눈에 띄지 않는 두 자리에서 난다. 상담사 옆에서 받아 적는 자리와, 상담사 뒤에서 정리하는 자리다. 현장에서 센터가 인공지능을 들이는 순서도 그렇다. 상담사를 돕는 자리가 먼저고, 상담사를 대신하는 자리는 그다음이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 그 세 자리가 어디인지를 한 장에 그리는 글이다. 지난 글에서 전화 한 통이 상담사에게 닿기까지 여섯 단계를 번호로 따라갔다. 이번에는 같은 그림을 그대로 두고, 인공지능이 어느 번호 사이에 서는지, 센터가 인공지능을 어떤 순서로 들이는지, 그때 기존 시스템은 어떻게 되는지를 본다. 음성인식(STT), 음성합성(TTS), 자연어 처리(NLP)와 자연어 이해(NLU), 녹취, 상담 어시스트, 텍스트 분석(TA), 상담 품질 평가(QA), 화자 인증, 보이스봇, 챗봇, 보이는 ARS. 이름이 열 개가 넘지만 전부 세 자리 중 하나에 앉는다. 요소 하나하나는 이어지는 글에서 차례로 뜯고, 이 글은 그 지도다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;전체 그림, 아홉 단계와 두 자리&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01_nine-steps.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxRVR0/dJMcafPktm2/UGqIWao8eQzQPZoKtL9sFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxRVR0/dJMcafPktm2/UGqIWao8eQzQPZoKtL9sFk/img.png&quot; data-alt=&quot;아홉 단계, 여섯 개 위에 세 개가 얹힌다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxRVR0/dJMcafPktm2/UGqIWao8eQzQPZoKtL9sFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxRVR0%2FdJMcafPktm2%2FUGqIWao8eQzQPZoKtL9sFk%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;2400&quot; height=&quot;1800&quot; data-filename=&quot;01_nine-steps.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1800&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;아홉 단계, 여섯 개 위에 세 개가 얹힌다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 글의 IPCC(Internet Protocol Contact Center)가 전화를 인터넷 방식으로 다루는 센터였다면, AICC는 그 센터에 인공지능이 자리를 잡은 센터다. 지난 글의 여섯 단계를 한 줄씩만 다시 적는다.&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;③ 교환기가 받고 CTI에 &quot;전화가 왔다&quot;고 알린다.&lt;/li&gt;
&lt;li&gt;④ CTI가 IVR로 보내고, IVR이 시나리오를 돌린다. 고객이 버튼을 누른다.&lt;/li&gt;
&lt;li&gt;⑤ IVR이 스킬을 정해 CTI에 돌려준다.&lt;/li&gt;
&lt;li&gt;⑥ CTI가 대기 중인 상담사에게 연결하고, 상담사 화면에 고객 정보를 띄운다. 녹취가 소리를 저장하기 시작한다.&lt;/li&gt;
&lt;/ul&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;⑦ IVR이 버튼 대신 &quot;말&quot;을 받기로 하고, 전화를 보이스봇 게이트웨이로 넘긴다.&lt;/li&gt;
&lt;li&gt;⑧ 게이트웨이가 고객의 소리를 봇 엔진에 보낸다. 엔진은 소리를 글자로 바꾸고(STT), 글자를 다듬고 뜻을 알아듣고(NLP&amp;middot;NLU), 답을 글자로 만들고, 다시 소리로 바꿔(TTS) 돌려준다.&lt;/li&gt;
&lt;li&gt;⑨ 봇이 일을 끝냈으면 전화를 끊고, 끝내지 못했으면 IVR로 돌아와 ⑤로 합류한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 번호가 붙지 않는 자리가 둘 더 있다. ⑥ 이후 상담사가 통화하는 동안 옆에서 돕는 자리(상담 어시스트)와, 통화가 끝난 뒤에서 정리하는 자리(텍스트 분석&amp;middot;품질 평가)다. 이 둘은 전화의 길을 바꾸지 않는다. 그래서 번호 대신 &quot;자리&quot;로 부른다. 두 자리 모두 소리를 녹취에서 받는다. 지난 글에서 녹취는 기록을 남기는 장치였다. 인공지능 컨택센터에서 녹취는 인공지능에게 소리를 공급하는 장치가 된다. 그 이야기는 다음 글에서 한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;AICC는 네 단계로 자란다, 보이스봇은 두 번째가 아니다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02_four-stages.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B5VaU/dJMcaa1nEQ0/G3brFsGRuke2RvvWcIO3aK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B5VaU/dJMcaa1nEQ0/G3brFsGRuke2RvvWcIO3aK/img.png&quot; data-alt=&quot;콜 인프라 &amp;amp;rarr; 상담 효율화 &amp;amp;rarr; 상담 자동화 &amp;amp;rarr; 개인화&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B5VaU/dJMcaa1nEQ0/G3brFsGRuke2RvvWcIO3aK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB5VaU%2FdJMcaa1nEQ0%2FG3brFsGRuke2RvvWcIO3aK%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;2400&quot; height=&quot;1280&quot; data-filename=&quot;02_four-stages.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1280&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;콜 인프라 &amp;rarr; 상담 효율화 &amp;rarr; 상담 자동화 &amp;rarr; 개인화&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현장에서 센터의 인공지능 도입을 설명할 때 나는 네 단계로 나눈다. &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;첫째 콜 인프라.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 지난 글의 교환기&amp;middot;CTI&amp;middot;IVR&amp;middot;녹취&amp;middot;통계&amp;middot;상담 프로그램이 갖춰진 상태다. 인공지능은 없다. 통화를 연결하고 기록하는 것이 전부다. &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;둘째 상담 효율화.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 음성인식으로 통화를 글자로 만들고, 그 글자 위에 텍스트 분석과 상담 어시스트와 지식관리와 자동 품질 평가를 얹는다. 상담사의 후처리와 지식 탐색 시간이 줄고, 통화가 데이터가 된다. &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;셋째 상담 자동화.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 보이스봇과 챗봇과 셀프 서비스가 반복 문의를 상담사 앞에서 끝낸다. 상담사에게 들어오는 전화 자체가 준다. &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;넷째 개인화.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 고객의 이력과 여정을 보고 문의가 생기기 전에 안내하거나 장애를 예방한다. 생성형 모델이 들어오는 자리이고, 이 묶음의 글이 끝난 뒤 따로 다룰 주제다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 이 순서가 거꾸로인 줄 알았다. 보이스봇이 눈에 띄니 그것부터 넣는 것이 자연스러워 보였다. 그런데 순서를 바꿔 보면 이유가 드러난다. 보이스봇이 고객의 말을 알아들으려면 그 센터의 말을 배운 음성인식이 있어야 하고, 어떤 문의가 어떤 처리로 끝나는지 정리된 분류 체계가 있어야 하고, 답으로 읽어 줄 지식이 정리되어 있어야 한다. 이 셋은 전부 둘째 단계에서 만들어진다. 둘째 단계 없이 셋째 단계로 가면 봇은 알아듣지 못하는 말을 &quot;다시 한번 말씀해 주세요&quot;로 받고, 결국 상담사에게 넘긴다. 상담사를 돕는 인공지능이 먼저고 상담사를 대신하는 인공지능이 그다음인 것은 철학이 아니라 순서의 문제다. 이 글의 세 자리로 말하면 옆자리와 뒷자리가 둘째 단계이고, 앞자리가 셋째 단계다. 그래서 이어지는 글들도 옆과 뒤를 먼저 다루고 앞을 나중에 다룬다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;AICC는 IPCC를 버리지 않는다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03_aicc-blocks.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cprFN8/dJMcac5X8go/ADLuzqFodCb4LMWQRKdozK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cprFN8/dJMcac5X8go/ADLuzqFodCb4LMWQRKdozK/img.png&quot; data-alt=&quot;기존 블록 위에 인공지능 블록이 얹힌다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cprFN8/dJMcac5X8go/ADLuzqFodCb4LMWQRKdozK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcprFN8%2FdJMcac5X8go%2FADLuzqFodCb4LMWQRKdozK%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;2400&quot; height=&quot;1400&quot; data-filename=&quot;03_aicc-blocks.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1400&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;기존 블록 위에 인공지능 블록이 얹힌다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째 단계부터는 인공지능이 들어오지만, 첫째 단계의 그림은 그대로 남는다. 구성도를 그려 보면 바닥에는 지난 글의 전화 시스템이 그대로 있다. 교환기, CTI, IVR, 녹취. 그 옆에는 상담사가 하루 종일 보는 상담 프로그램이 있다. 고객 조회, 상담 이력, 지식 검색, 콜백 예약이 들어 있는 보통의 웹 시스템이다. 그 옆에는 전화가 아닌 창구들이 있다. 채팅, 메신저 상담, 문자, 메일. 인공지능은 이 세 덩어리 위에 얹힌다. 전화 시스템에서 소리를 받고, 상담 프로그램에 글자를 돌려주고, 채팅 창구에서 질문을 받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 센터에 인공지능을 넣는 일은 새 집을 짓는 일이 아니라 집에 사람을 들이는 일에 가깝다. 벽과 배선은 그대로다. 누가 어느 방에 앉아 무슨 일을 맡는지가 바뀐다. 전화를 나누는 일은 여전히 CTI가 하고, 전화의 통계도 CTI가 만든다. 봇이 들어와도 이 주인은 바뀌지 않는다. 그러면 들어온 사람들은 어느 방에 앉는가.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인공지능이 서는 세 자리, 상담사의 앞과 옆과 뒤&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04_three-seats.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnqaSc/dJMcaiLOlAx/cMIN4YJrolGaqVD1AkL71K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnqaSc/dJMcaiLOlAx/cMIN4YJrolGaqVD1AkL71K/img.png&quot; data-alt=&quot;상담사의 앞&amp;amp;middot;옆&amp;amp;middot;뒤, 세 자리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnqaSc/dJMcaiLOlAx/cMIN4YJrolGaqVD1AkL71K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnqaSc%2FdJMcaiLOlAx%2FcMIN4YJrolGaqVD1AkL71K%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;2400&quot; height=&quot;1520&quot; data-filename=&quot;04_three-seats.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1520&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;상담사의 앞&amp;middot;옆&amp;middot;뒤, 세 자리&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사무실 하나를 떠올리면 된다. 상담사가 가운데 책상에 앉아 있다. 그 앞에는 손님을 먼저 맞는 안내 직원이 있고, 옆에는 대화를 받아 적고 필요한 서류를 찾아 주는 속기사 겸 사서가 있고, 뒤에는 끝난 일을 분류하고 정리하는 서무가 있다. 인공지능 컨택센터의 구성 요소는 전부 이 세 자리 중 하나에 들어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;옆자리, 통화 중에 거드는 인공지능.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 상담 지원, 영어로는 Agent Assist라고 부른다. 실시간 음성인식이 대화를 글자로 올리고, 자연어 처리가 그 글자에서 주제를 짚고, 지식관리(KMS, Knowledge Management System)가 주제에 맞는 안내문과 절차를 꺼내 준다. 옆자리의 목적은 상담사가 고객의 말을 받아 적느라, 서류를 찾느라 고객을 기다리게 하지 않는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;뒷자리, 전화가 끝난 뒤에 일하는 인공지능.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 업무 지능화라고 부른다. 사후 음성인식이 통화 전체를 글자로 만들면, 텍스트 분석(TA, Text Analytics)이 요약하고 분류하고, 상담 품질 평가(QA, Quality Assurance)가 기준표로 통화를 점검한다. 통화 처음에 목소리로 본인을 확인하는 화자 인증도 하는 일로는 여기에 둔다. 뒷자리의 목적은 상담사가 전화를 끊고 나서 하던 일, 그러니까 후처리를 줄이는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;앞자리, 상담사보다 먼저 받는 인공지능.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 상담 자동화라고 부른다. 전화에서 말로 묻고 답하는 보이스봇, 채팅 창에서 글자로 묻고 답하는 챗봇, 전화 중에 휴대전화 화면을 띄워 눈으로 고르게 하는 보이는 ARS다. 고객이 센터에 들어오는 길을 순서대로 놓으면 이렇게 된다. 듣고 고르던 버튼식 ARS에서, 보면서 고르는 보이는 ARS로, 말로 고르는 보이스봇으로, 그리고 전화 밖의 챗봇으로. 앞자리의 목적은 하나다. 상담사에게 가지 않아도 되는 전화를 그 앞에서 끝내는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이름이 많아 보여도 지도는 이 한 장이다. 네 단계 중 둘째가 옆과 뒤이고 셋째가 앞이며, 셋 다 지난 글의 여섯 단계 위에 얹힌다. 다음 글부터는 이 지도를 들고 방마다 들어간다. 먼저 세 자리가 공통으로 쓰는 재료와 소리를 대 주는 녹취, 그다음 옆과 뒤, 그다음 앞, 마지막으로 이 전체를 내 건물에 둘지 빌려 쓸지다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인공지능 컨택센터가 무엇이냐는 질문을 받으면 전에는 보이스봇부터 설명했다. 눈에 띄는 것부터 말하는 것이 쉬웠다. 네 단계와 세자리를 따로 보기 시작한 뒤로 답이 바뀌었다. 전화의 길에 끼어든 것은 ④와 ⑤ 사이의 세 단계뿐이고, 그보다 먼저 와 있어야 하는 것은 전화의 길이 아니라 상담사 책상의 옆과 뒤였다. 지금은 이렇게 답한다. 상담사를 대신하는 센터가 아니라, 상담사의 앞과 옆과 뒤에 인공지능이 앉은 센터다. 그리고 그 셋은 지난 글의 전화 시스템을 허물지 않고 그 위에 얹힌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글은 세 자리가 공통으로 쓰는 재료다. 소리를 글자로 바꾸는 음성인식, 글자를 소리로 바꾸는 음성합성, 글자를 다루는 자연어 처리와 뜻을 알아듣는 자연어 이해, 그리고 그 재료에 소리를 대 주는 녹취. 이 넷을 모르면 뒤의 모든 요소가 블랙박스로 보인다.&lt;/p&gt;</description>
      <category>tech</category>
      <category>Agent Assist</category>
      <category>AI Contact Center</category>
      <category>ai 컨택센터</category>
      <category>AICC</category>
      <category>Contact Center</category>
      <category>보이스봇</category>
      <category>상담사 지원 AI</category>
      <category>인공지능 컨택센터</category>
      <category>컨택센터 구조</category>
      <category>콜센터 AI</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/8</guid>
      <comments>https://hsjo.tistory.com/8#entry8comment</comments>
      <pubDate>Sun, 11 Oct 2026 20:48:35 +0900</pubDate>
    </item>
    <item>
      <title>결혼 6주년, 올해도 흑백사진 한 장 | 조율과 함께한 두 번째 촬영</title>
      <link>https://hsjo.tistory.com/7</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;결혼기념일 썸네일.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tsPeq/dJMcagHrTNK/GZxuv7VMbQlyGDySQbYqHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tsPeq/dJMcagHrTNK/GZxuv7VMbQlyGDySQbYqHk/img.png&quot; data-alt=&quot;썸네일&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tsPeq/dJMcagHrTNK/GZxuv7VMbQlyGDySQbYqHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtsPeq%2FdJMcagHrTNK%2FGZxuv7VMbQlyGDySQbYqHk%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;1672&quot; height=&quot;941&quot; data-filename=&quot;결혼기념일 썸네일.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;썸네일&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;매년 10월 10일, 우리는 흑백사진을 찍는다&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매년 결혼기념일이면 우리는 흑백사진을 찍는다. 어느새 여섯 번째다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결혼을 준비할 때 다른 것은 내 마음대로 하지 못했는데, 딱 하나 날짜만큼은 내 마음대로 정할 수 있었다. 2020년 10월 10일. 숫자가 좋아서 꼭 이 날 결혼하고 싶었다. 장인어른께서 불러 주셨던 &amp;ldquo;10월의 어느 멋진 날에&amp;rdquo;도 이 날짜와 함께 영원히 기억될 것만 같았다. 지금도 10월이 되면 그 노래가 먼저 떠오른다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;두 번째로 함께한 조율&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작년부터는 조율이 함께하고 있다. 올해로 2회차. 작년 사진과 나란히 놓고 보니 그새 아기 티를 벗고 벌써 어린이가 된 것만 같다. 작년에는 품에 안겨서 찍었는데, 올해는 혼자 앉아 케이크를 들고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;촬영은 석촌에 있는 오디티모드 잠실점에서 2년 연속으로 진행했다. 같은 날짜, 같은 장소에서 찍으니 1년 사이의 변화가 그대로 보여서 좋다.&lt;/p&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/wyL2X/dJMb999ch8v/5qUb4lqDNXu4oTce5jltl1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wyL2X/dJMb999ch8v/5qUb4lqDNXu4oTce5jltl1/img.jpg&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;1440&quot; data-is-animation=&quot;false&quot; data-filename=&quot;IMG_0423.JPG&quot; style=&quot;width: 52.9849%; margin-right: 10px;&quot; data-widthpercent=&quot;53.61&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wyL2X/dJMb999ch8v/5qUb4lqDNXu4oTce5jltl1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwyL2X%2FdJMb999ch8v%2F5qUb4lqDNXu4oTce5jltl1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;960&quot; height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvnsOc/dJMcajcVix2/0OkEClzwGxwuiJktnUdwok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvnsOc/dJMcajcVix2/0OkEClzwGxwuiJktnUdwok/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;420&quot; data-origin-height=&quot;728&quot; data-filename=&quot;IMG_0895.PNG&quot; style=&quot;width: 45.8523%;&quot; data-widthpercent=&quot;46.39&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvnsOc/dJMcajcVix2/0OkEClzwGxwuiJktnUdwok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvnsOc%2FdJMcajcVix2%2F0OkEClzwGxwuiJktnUdwok%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;420&quot; height=&quot;728&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;작년과 올해 비교 &amp;mdash; 2회차 진행중&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;급상승한 촬영 난이도&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조율의 참여로 촬영 난이도가 급상승했다. 가만히 있어 주지 않는 것은 기본이고, 카메라보다 소품에 관심이 더 많다. 안 그래도 나는 사진 찍히는 체질이 아닌데, 아이까지 챙기며 표정을 만들려니 쉽지 않았다. 어렵사리 이번 촬영도 마무리했다.&lt;/p&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/nXNFV/dJMcaiLOi3B/RfJpxKYbXtBxAcs3r33RS1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nXNFV/dJMcaiLOi3B/RfJpxKYbXtBxAcs3r33RS1/img.jpg&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;2100&quot; data-filename=&quot;IMG_0884.JPG&quot; style=&quot;width: 51.1197%; margin-right: 10px;&quot; data-widthpercent=&quot;51.72&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nXNFV/dJMcaiLOi3B/RfJpxKYbXtBxAcs3r33RS1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnXNFV%2FdJMcaiLOi3B%2FRfJpxKYbXtBxAcs3r33RS1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;2100&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbCk0C/dJMcairw3PQ/dX9wmWea7tNTm0vBKXGgHk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbCk0C/dJMcairw3PQ/dX9wmWea7tNTm0vBKXGgHk/img.jpg&quot; data-origin-width=&quot;2731&quot; data-origin-height=&quot;4096&quot; data-is-animation=&quot;false&quot; data-filename=&quot;IMG_0913.JPG&quot; style=&quot;width: 47.7175%;&quot; data-widthpercent=&quot;48.28&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbCk0C/dJMcairw3PQ/dX9wmWea7tNTm0vBKXGgHk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbCk0C%2FdJMcairw3PQ%2FdX9wmWea7tNTm0vBKXGgHk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2731&quot; height=&quot;4096&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;힘든 촬영&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;아기와 회전초밥집, 오늘의 교훈&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11시 반 예약이었는데 인쇄할 사진을 고르는 것까지 마치고 나니 허기가 졌다. 원래는 롯데월드몰 안의 맛집에 가려고 했지만, 주차하는 시간도 아까워서 근처 회전초밥집으로 바로 들어갔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;율이를 고려하지 못한 선택이었다. 공깃밥은 주문할 수 없었고, 양념이 된 초밥의 밥은 아기가 먹기엔 무리였다. 결국 불고기 우동을 시켜서 불고기라도 골라 먹였다. 다음부터 아기를 데리고 초밥집에 갈 때는 신중해야 한다는 교훈을 얻었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2884&quot; data-origin-height=&quot;1626&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ul8Qk/dJMcacky8vH/a6JP818SR8KdGFeAPEYwRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ul8Qk/dJMcacky8vH/a6JP818SR8KdGFeAPEYwRk/img.png&quot; data-alt=&quot;회전초밥집&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ul8Qk/dJMcacky8vH/a6JP818SR8KdGFeAPEYwRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ful8Qk%2FdJMcacky8vH%2Fa6JP818SR8KdGFeAPEYwRk%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;2884&quot; height=&quot;1626&quot; data-origin-width=&quot;2884&quot; data-origin-height=&quot;1626&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;회전초밥집&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;딸기라떼 긴급 수혈&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;밥을 제대로 못 먹어서인지, 카페에서 딸기라떼를 원샷 때려버리는 조율. 컵을 두 손으로 붙잡고 놓지 않았다. 미안한 마음 반, 웃긴 마음 반이었다.&lt;/p&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/UUaA4/dJMcacrvqCk/MNBckydtGIJsqfxh5wIhD1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UUaA4/dJMcacrvqCk/MNBckydtGIJsqfxh5wIhD1/img.jpg&quot; data-origin-width=&quot;5712&quot; data-origin-height=&quot;4284&quot; data-is-animation=&quot;false&quot; data-filename=&quot;KakaoTalk_Photo_2026-10-11-18-23-46 001.jpeg&quot; style=&quot;width: 63.2558%; margin-right: 10px;&quot; data-widthpercent=&quot;64&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UUaA4/dJMcacrvqCk/MNBckydtGIJsqfxh5wIhD1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUUaA4%2FdJMcacrvqCk%2FMNBckydtGIJsqfxh5wIhD1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;5712&quot; height=&quot;4284&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baHxQP/dJMcacrvqCn/LFwRKlPGF0kmKqaSYz1nUk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baHxQP/dJMcacrvqCn/LFwRKlPGF0kmKqaSYz1nUk/img.jpg&quot; data-origin-width=&quot;4284&quot; data-origin-height=&quot;5712&quot; data-is-animation=&quot;false&quot; data-filename=&quot;KakaoTalk_Photo_2026-10-11-18-23-46 002.jpeg&quot; style=&quot;width: 35.5814%;&quot; data-widthpercent=&quot;36&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baHxQP/dJMcacrvqCn/LFwRKlPGF0kmKqaSYz1nUk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaHxQP%2FdJMcacrvqCn%2FLFwRKlPGF0kmKqaSYz1nUk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4284&quot; height=&quot;5712&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;딸기라떼 긴급 수혈&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;요상한(?) 케이크로 마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막은 석촌의 케키하우스 케이크카페에서 공수해 온 요상한(?) 케이크다. 숫자 6 초를 꽂고 불을 붙이니, 그제야 여섯 번째 결혼기념일이 실감 났다.&lt;/p&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/betSnu/dJMcagtL0wE/k2RK1P9ziHjVn0VgzX3JG1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/betSnu/dJMcagtL0wE/k2RK1P9ziHjVn0VgzX3JG1/img.jpg&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;KakaoTalk_Photo_2026-10-11-18-25-56 001.jpeg&quot; style=&quot;width: 56.4784%; margin-right: 10px;&quot; data-widthpercent=&quot;57.14&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/betSnu/dJMcagtL0wE/k2RK1P9ziHjVn0VgzX3JG1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbetSnu%2FdJMcagtL0wE%2Fk2RK1P9ziHjVn0VgzX3JG1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NTNQj/dJMcag1tPeL/K9jDCs4w7FbebXrrWirSgk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NTNQj/dJMcag1tPeL/K9jDCs4w7FbebXrrWirSgk/img.jpg&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;1440&quot; data-filename=&quot;KakaoTalk_Photo_2026-10-11-18-25-57 002.jpeg&quot; style=&quot;width: 42.3588%;&quot; data-widthpercent=&quot;42.86&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NTNQj/dJMcag1tPeL/K9jDCs4w7FbebXrrWirSgk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNTNQj%2FdJMcag1tPeL%2FK9jDCs4w7FbebXrrWirSgk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;810&quot; height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>family</category>
      <category>가족사진</category>
      <category>결혼6주년</category>
      <category>결혼기념일</category>
      <category>석촌사진관</category>
      <category>아기랑외식</category>
      <category>오디티모드</category>
      <category>오디티모드잠실점</category>
      <category>육아일기</category>
      <category>케키하우스</category>
      <category>흑백사진</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/7</guid>
      <comments>https://hsjo.tistory.com/7#entry7comment</comments>
      <pubDate>Sun, 11 Oct 2026 19:30:46 +0900</pubDate>
    </item>
    <item>
      <title>전화는 어떻게 컨택센터 시스템에 연결되는가, IPCC 여섯 단계로 따라가는 전화의 길</title>
      <link>https://hsjo.tistory.com/5</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;썸네일.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bc5DTy/dJMcablNtBx/h0NCOBnRaorPgdsKrIEBG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bc5DTy/dJMcablNtBx/h0NCOBnRaorPgdsKrIEBG0/img.png&quot; data-alt=&quot;썸네일&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bc5DTy/dJMcablNtBx/h0NCOBnRaorPgdsKrIEBG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbc5DTy%2FdJMcablNtBx%2Fh0NCOBnRaorPgdsKrIEBG0%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;1672&quot; height=&quot;941&quot; data-filename=&quot;썸네일.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;썸네일&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몇 해 전에 만든 사내 교육자료를 다시 열었다. 한 장이 눈에 들어왔다. 왼쪽에 고객, 오른쪽 끝에 상담사, 그 사이에 교환기∙CTI∙IVR이 아이콘으로 서 있고 화살표마다 ⓵ 부터 ⓺ 까지 번호가 붙어 있다. 그림 아래에는 번호마다 한 줄씩, 어느 시스템에서 어느 시스템으로 왜 넘어가는지가 적혀 있다. 나는 늘 이렇게 설명해 왔다. 장비 이름을 하나씩 외우게 하는 것이 아니라, 전화 한 통에 번호를 매기고 그 번호를 따라가게 한다. 그림만 보면 네모와 화살표지만 번호를 따라 읽으면 길이 된다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2226&quot; data-origin-height=&quot;1150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btnqWP/dJMcajqldt7/keTrKpt8lRKcYA3kAWQnUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btnqWP/dJMcajqldt7/keTrKpt8lRKcYA3kAWQnUK/img.png&quot; data-alt=&quot;IPCC 콜플로우&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btnqWP/dJMcajqldt7/keTrKpt8lRKcYA3kAWQnUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtnqWP%2FdJMcajqldt7%2FkeTrKpt8lRKcYA3kAWQnUK%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;2226&quot; height=&quot;1150&quot; data-origin-width=&quot;2226&quot; data-origin-height=&quot;1150&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;IPCC 콜플로우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 그 한 장을 글로 다시 쓴 것이다. 고객이 대표번호를 누르는 순간부터 상담사가 &quot;네, 고객센터 입니다&quot;라고 말하기까지 전화는 여섯 단계를 지난다. 단계마다 세 가지를 적는다. 언제 넘어가는가, 어떻게 넘어가는가, 왜 거기를 거쳐야 하는가. 다음 글에서는 같은 그림의 어느 번호 사이에 인공지능이 끼어드는지를, 그 다음 글에서는 인공지능이 스스로 일을 끝내는 자리를 다룬다. 전화가 어떻게 들어오는지 모르면 인공지능이 어디에 서 있는지도 알 수 없다. (신입이나 경력 입사자를 받으면 늘 이 그림부터 꺼내는 이유다.)&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;전체 그림, 전화 한 통이 지나는 여섯 단계&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01_six-steps.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rqNtP/dJMcahF9ZVK/tQdlrs7WDrst6e5JvXUQ91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rqNtP/dJMcahF9ZVK/tQdlrs7WDrst6e5JvXUQ91/img.png&quot; data-alt=&quot;전화 한 통이 지나는 여섯 단계&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rqNtP/dJMcahF9ZVK/tQdlrs7WDrst6e5JvXUQ91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrqNtP%2FdJMcahF9ZVK%2FtQdlrs7WDrst6e5JvXUQ91%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;2400&quot; height=&quot;1440&quot; data-filename=&quot;01_six-steps.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;전화 한 통이 지나는 여섯 단계&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콜센터, 고객센터, 컨택센터는 같은 곳이다. 부르는 사람이 다를 뿐이다. 시스템을 만드는 쪽에서는 IPCC(Internet Protocol Contact Center)라고 부른다. 전화를 인터넷 방식으로 다루는 컨택센터라는 뜻이고, 지금 운영되는 컨택센터는 거의 다 이것이다. 그 IPCC 안에서 전화 한통은 이렇게 움직인다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;고객이 대표번호로 전화를 건다. 전화는 통신사의 지능망으로 간다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;지능망이 대표번호를 컨택센터의 실제 착신번호로 바꿔 보낸다. 전화망의 전화가 인터넷의 전화로 바뀌는 곳이다. 전용회선이면 음성 게이트웨이가, SIP 트렁크면 SBC가 그 일을 한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;교환기(PBX)가 전화를 받고, CTI에 &quot;전화가 왔다&quot;고 알린다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;CTI가 전화를 IVR로 보내고, IVR이 시나리오를 실행한다. 고객이 버튼을 누른다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;IVR이 고객 입력으로 스킬을 정해 CTI에 돌려준다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;CTI가 그 스킬의 대기 중인 상담사에게 전화를 연결하고, 동시에 상담사 화면에 고객 정보를 띄운다. 전원 통화 중이면 &quot;4.&quot;의 대기 시나리오로 돌아간다.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여섯 줄이 전부다. 이제 번호를 하나씩 따라간다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 고객 &amp;rarr; 통신사 지능망, 대표번호는 회선이 아니라 이름이다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02_step1-intelligent-network.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDy1WY/dJMcaiFayCV/OgXy214Txb8tYatOgzIPbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDy1WY/dJMcaiFayCV/OgXy214Txb8tYatOgzIPbk/img.png&quot; data-alt=&quot;통신사 지능망&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDy1WY/dJMcaiFayCV/OgXy214Txb8tYatOgzIPbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDy1WY%2FdJMcaiFayCV%2FOgXy214Txb8tYatOgzIPbk%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;2400&quot; height=&quot;1260&quot; data-filename=&quot;02_step1-intelligent-network.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;통신사 지능망&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;언제.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 고객이 휴대전화에서 대표번호를 누르는 순간이다. 15나 16으로 시작하는 짧은 번호, 또는 보통의 지역번호 전화다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;어떻게.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 전화는 통신사의 전화망을 탄다. 전화망의 이름은 PSTN(Public Switched Telephone Network), 공중 교환전화망이다. 집 전화 시절부터 쓰던 그 망이다. 그 안에 지능망이라는 층이 있다. 대표번호는 지능망에 등록된 번호이고, 지능망은 이 번호로 들어온 전화를 미리 정해 둔 실제 착신번호로 바꿔 보낸다. 이것을 착신전환이라고 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;왜.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 처음에는 대표번호가 그냥 전화번호인 줄 알았다. 아니었다. 대표번호는 회선이 아니라 이름이다. 실제 회선 번호를 바꿔도 고객이 아는 번호는 그대로 둘 수 있고, 같은 번호로 들어온 전화를 센터 여러 곳에 나눠 보낼 수도 있다. 교환기를 통째로 바꾸는 대개체 사업에서 고객이 아무것도 모르고 지나가는 것은 이 층이 있기 때문이다. 그래서 전화는 고객에게서 바로 컨택센터로 오지 않고 지능망을 한 번 거친다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 지능망 &amp;rarr; 음성 게이트웨이 또는 SBC, 경계를 넘는 길은 둘이다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03_step2-gateway-sbc.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTRVkP/dJMcafhmAfD/WSxQZw3koh3tKKkYkF3Ka0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTRVkP/dJMcafhmAfD/WSxQZw3koh3tKKkYkF3Ka0/img.png&quot; data-alt=&quot;VG 또는 SBC&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTRVkP/dJMcafhmAfD/WSxQZw3koh3tKKkYkF3Ka0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTRVkP%2FdJMcafhmAfD%2FWSxQZw3koh3tKKkYkF3Ka0%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;2400&quot; height=&quot;1560&quot; data-filename=&quot;03_step2-gateway-sbc.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1560&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;VG 또는 SBC&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;언제.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 지능망이 착신전환한 전화가 컨택센터의 문 앞에 도착했을 때다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;어떻게.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 컨택센터 안쪽은 전화망이 아니라 인터넷망이다. 상담사 책상 위의 전화기는 전화선이 아니라 랜선에 꽂혀 있다. 그래서 경계에서 전화망의 전화를 인터넷의 전화로 바꿔야 하는데, 이 경계를 넘는 길이 둘이다. 어느 길인지는 업종이 정하는 것이 아니라 세 가지 질문이 정한다. 회선이 전화 회선인가 SIP인가. 망이 전용인가 공용인가. 안쪽 시스템끼리 주고받는 전화가 전화망을 타는가.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;길 A는 전용회선과 음성 게이트웨이다. 통신사와 센터 사이에 그 센터만 쓰는 회선을 깐다. E1/PRI 같은 전화 회선이거나 통신사의 전용 이더넷 회선이다. 센터 쪽 끝에 음성 게이트웨이(VG, Voice Gateway)를 둔다. 한쪽에는 전화망 인터페이스가, 다른 쪽에는 이더넷 인터페이스가 있어서 전화망의 신호와 소리를 인터넷 패킷으로 바꾸고 반대로도 바꾼다. 이 방식이 VoIP(Voice Over Internet Protocol)다. 전화가 인터넷을 한 번도 타지 않는다. 은행∙보험∙카드사의 센터와 공공기관 민원센터가 대개 이 길이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;길 B는 SIP 트렁크와 SBC다. 통신사가 처음부터 전화를 SIP 메시지와 RTP 패킷으로 넘겨준다. 인터넷으로 오거나 통신사의 공용 IP망으로 온다. 센터 쪽 끝에는 게이트웨이 대신 SBC(Session Border Controller)가 선다. 클라우드 컨택센터, 재택 상담, 회선을 새로 깔기 어려운 규모의 센터가 이 길이다. 전용회선 비용이 없고 좌석을 늘리기는 쉽지만, 공용망을 지나는 만큼 경계를 지키는 장비가 필요하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;금융권이 길 A를 고르는 이유는 셋이다. 금융회사는 업무망을 인터넷과 분리하라는 규정 아래 있어서, 전화가 인터넷을 타는 구성은 보안성 검토를 통과하기 어렵다. 통화 품질을 통신사가 회선 단위로 책임져야 민원이 났을 때 책임 소재가 분명하다. 녹취와 고객 정보가 공용망을 지나지 않는다. 그래서 금융권의 규칙은 &quot;VG만 쓴다&quot;가 아니라 &quot;인터넷을 타지 않는다&quot;다. 그 규칙 안에서 장비는 회선이 정한다. 전용회선이 E1/PRI 같은 전화 회선이면 VG가 통역을 맡고, 통신사가 전용 IP망으로 SIP를 넘겨주면 VG는 없고 SBC가 선다. 대형 은행의 차세대 센터는 전용망 안에서도 SBC를 둔다. 수백 회선의 세션을 세고 제한하고, 통신사와 교환기 사이의 SIP 차이를 맞추고, 통화 상태를 모니터링하는 일은 게이트웨이의 일이 아니라 SBC의 일이기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SBC가 등장하는 경우는 그 밖에 둘이 더 있다. 하나는 돈이다. 공공기관 민원센터에서 상담사가 다른 부서로 전화를 돌릴 때 그 호가 전화망을 거치면 통신료가 붙는다. 아날로그 회선으로 돌리면 장비는 안 사도 통신료가 늘고, SBC를 두고 SIP로 돌리면 장비는 사지만 통신료가 준다. 보안성 검토 자리에서 이 둘을 놓고 SBC를 고른다. 클라우드 보이스봇을 고객사 교환기에 붙일 때도 같다. 봇과 교환기 사이를 전화망으로 이으면 착신료가 생기고, SIP 트렁크와 SBC로 이으면 생기지 않는다. 다른 하나는 전화기다. 클라우드 컨택센터에서 상담사 전화기를 VPN 없이 붙이려면 경계에서 주소를 바꿔 주는 장비가 있어야 하는데 그것이 SBC다. SBC가 없으면 전화기마다 VPN을 걸어야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;병원은 또 다른 모양이다. 원내 교환기와 내선 전화기 수천 대가 이미 있어서 그걸 전부 클라우드로 옮기면 내선 라이선스 비용이 커진다. 그래서 원내 교환기를 그대로 두고, 교환기에서 E1/PRI 회선을 뽑아 VG를 거쳐 클라우드 컨택센터로 호를 넘긴다. 길 A와 길 B가 한 건물 안에서 만나는 셈이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03b_boundary-decision.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDhcpU/dJMcabeLc66/mR1p4mGEphpn2JcPk5y690/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDhcpU/dJMcabeLc66/mR1p4mGEphpn2JcPk5y690/img.png&quot; data-alt=&quot;경계 장비는 세 가지 질문이 정한다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDhcpU/dJMcabeLc66/mR1p4mGEphpn2JcPk5y690/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDhcpU%2FdJMcabeLc66%2FmR1p4mGEphpn2JcPk5y690%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;2400&quot; height=&quot;1720&quot; data-filename=&quot;03b_boundary-decision.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;경계 장비는 세 가지 질문이 정한다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느 길이든 이 경계를 지나면 전화는 SIP와 RTP가 된다. 그래서 다음 질문이 남는다. 화살표 위를 실제로 무엇이 지나가는가.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04_sip-sequence.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjfn8u/dJMcaiyrXXS/apnuP0pF48KXp5GndPnaG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjfn8u/dJMcaiyrXXS/apnuP0pF48KXp5GndPnaG1/img.png&quot; data-alt=&quot;신호는 SIP가 맡는다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjfn8u/dJMcaiyrXXS/apnuP0pF48KXp5GndPnaG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbjfn8u%2FdJMcaiyrXXS%2FapnuP0pF48KXp5GndPnaG1%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;2400&quot; height=&quot;1260&quot; data-filename=&quot;04_sip-sequence.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;신호는 SIP가 맡는다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터넷으로 전화를 보낸다고 하면 목소리를 잘게 잘라 보내는 것만 떠올리기 쉽다. 나도 그랬다. 그런데 전화에는 목소리보다 먼저 가는 것이 있다. &quot;지금 전화 걸겠다&quot;, &quot;받았다&quot;, &quot;끊겠다&quot; 라는 약속이다. 이 약속을 신호라고 부르고 목소리를 미디어라고 부른다. 둘은 다른 프로토콜을 쓰고 다른 길로 간다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신호는 SIP(Session Initiation Protocol)가 맡는다. 인터넷 표준 문서 RFC 3261에 정의된 프로토콜이고, 이름 그대로 세션, 즉 통화 한 건을 시작하고 끝내는 규칙이다. 게이트웨이를 지나는 순간 고객의 전화는 SIP 메시지가 된다. 거는 쪽이 INVITE를 보내고, 받는 쪽이 200 OK로 답하고, 거는 쪽이 ACK로 확인하면 통화가 성립한다. 끊을 때는 BYE다. 전화번호도 이메일 주소처럼 생긴 SIP 주소로 바뀐다. sip:번호@도메인 같은 꼴이다. 뒤에 나올 교환기와 CTI가 &quot;어느 번호로 전화가 들어왔다&quot;를 아는 것은 전부 이 SIP 메시지를 읽기 때문이다. INVITE 안에는 SDP(Session Description Protocol)라는 명세가 들어 있어서, 소리를 어떤 코덱으로 압축할지와 어느 주소/포트로 보낼지를 서로 합의한다. 전화망에서 오래 쓰인 코덱은 G.711이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;05_rtp-udp.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d5RRjJ/dJMcai54UVr/NQLMK4E0mKGIsXJLfLhcrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d5RRjJ/dJMcai54UVr/NQLMK4E0mKGIsXJLfLhcrK/img.png&quot; data-alt=&quot;소리는 RTP가 맡는다, UDP 위로 간다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d5RRjJ/dJMcai54UVr/NQLMK4E0mKGIsXJLfLhcrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd5RRjJ%2FdJMcai54UVr%2FNQLMK4E0mKGIsXJLfLhcrK%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;2400&quot; height=&quot;1320&quot; data-filename=&quot;05_rtp-udp.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1320&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;소리는 RTP가 맡는다, UDP 위로 간다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소리는 RTP(Real-time Transport Protocol)가 맡는다. RFC 3550이다. 목소리를 짧은 조각으로 잘라 패킷마다 순서 번호와 시각을 붙여 보내고, 받는 쪽은 순서대로 이어 붙여 스피커로 낸다. 여기서 중요한 선택이 하나 있다. RTP는 TCP가 아니라 UDP(User Datagram Protocol) 위에서 간다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 UDP인가. 웹 페이지를 받는 TCP는 패킷이 빠지면 다시 보내 달라고 해서 반드시 채운다. 정확하지만 기다린다. 전화는 기다릴 수 없다. 조금 전의 목소리를 다시 받아 끼워 넣느니 버리고 다음 소리를 내는 편이 낫다. 통화 중에 한 음절이 뚝 빠지는 것은 그래서다. 패킷이 길에서 사라졌고 아무도 다시 보내지 않았다. UDP는 확인도 재전송도 하지 않는다. 그 대신 빠르다. 전화는 정확한 프로토콜이 아니라 빠른 프로토콜을 골랐다. RTP 옆에는 RTCP(RTP Control Protocol)가 따라다닌다. 소리를 나르지는 않고 패킷이 얼마나 빠졌는지, 얼마나 늦었는지, 도착 간격이 얼마나 들쭉날쭉한지(지터)를 주기적으로 상대에게 보고한다. 통화 품질 이야기가 나오면 결국 이 보고서를 본다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;06_dtmf.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wYde6/dJMcafhmUAP/15swgkee9hDom8p3IQQqZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wYde6/dJMcafhmUAP/15swgkee9hDom8p3IQQqZK/img.png&quot; data-alt=&quot;버튼소리 DTMF, 소리에서 이벤트로&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wYde6/dJMcafhmUAP/15swgkee9hDom8p3IQQqZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwYde6%2FdJMcafhmUAP%2F15swgkee9hDom8p3IQQqZK%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;2400&quot; height=&quot;1260&quot; data-filename=&quot;06_dtmf.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;버튼소리 DTMF, 소리에서 이벤트로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객이 &quot;4&quot;에서 누를 버튼도 이 길로 간다. 버튼 소리를 DTMF(Dual-Tone Multi-Frequency)라고 하는데, 전화망에서는 두 주파수를 섞은 실제 소리였다. 인터넷에서는 소리로 보내면 압축에 뭉개질 수 있어서 RTP 패킷 안에 &quot;지금 3번이 눌렸다&quot;는 이벤트로 따로 실어 보낸다(RFC 4733). 양쪽 장비의 이 설정이 다르면 전화는 되는데 IVR이 버튼을 못 알아듣는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 SBC가 하는 일을 적어 둔다. SIP와 RTP가 공용망에서 컨택센터 안으로 들어오려면 건물의 경계를 넘어야 한다. 경계에는 방화벽이 있는데 방화벽은 전화를 모른다. SIP 메시지 안에는 &quot;소리는 이 주소 이 포트로 보내라&quot;는 내부 주소가 적혀 있고, 방화벽과 NAT(Network Address Translation, 사설 주소를 공인 주소로 바꾸는 장치)는 메시지 안에 적힌 그 주소까지 바꿔 주지 않는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전화는 걸리는데 소리가 한쪽만 들리는 장애, 신호는 됐는데 미디어가 안 오는 장애가 여기서 난다. 그래서 경계에 전화를 아는 장비를 따로 둔다. SBC(Session Border Controller), 세션 경계 제어기다. 경비실이라고 생각하면 된다. 바깥에서 오는 SIP는 전부 SBC에서 한 번 끊기고, SBC가 안쪽으로 다시 건다. 밖에서는 SBC의 주소만 보이고 교환기∙CTI∙녹취 서버의 주소는 보이지 않는다. 통신사와 우리 교환기가 SIP를 조금씩 다르게 쓸 때 헤더를 고쳐 맞추고, 코덱이 다르면 변환하고, 동시에 들어올 수 있는 통화 수를 제한하고, 비정상적인 호출이 쏟아지면 막고, 통화를 암호화할 때는 양쪽 끝이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔직히 나는 오랫동안 SBC를 &quot;있으면 좋은 장비&quot;로 생각했다. 아니었다. 통신사 회선이 전용선이 아니라 인터넷일 때, 상담사가 사무실 밖에서 일할 때, 컨택센터가 클라우드에 있을 때 SBC는 있으면 좋은 것이 아니라 없으면 전화가 안 되는 것이다. 교육자료의 클라우드 구성도에도 SBC가 구름 모양으로 그려져 있었는데 그때 나는 그 네모를 설명하지 않고 넘어갔다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;왜.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 망이 둘이기 때문이다. 전용회선 길에서는 바깥이 전화망이고 안쪽이 인터넷망이라서 통역(게이트웨이)이 있어야 하고, SIP 트렁크 길에서는 바깥이 공용망이고 경계가 전화를 모르기 때문에 경비실(SBC)이 있어야 한다. 어느 장비를 두는지는 업종이 아니라 회선의 종류, 망이 전용인지 공용인지, 안쪽 전화가 전화망을 타는지가 정한다. 어느 길이든 여기를 지나면 전화는 SIP 메시지와 RTP 패킷이 되어 교환기 앞에 선다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 교환기 &amp;rarr; CTI, 전화는 연결됐지만 아직 누구인지 모른다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;07_step3-pbx-cti.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AwYX3/dJMcah7pmCh/aMKjKfu4DllsbV7bCvcqhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AwYX3/dJMcah7pmCh/aMKjKfu4DllsbV7bCvcqhK/img.png&quot; data-alt=&quot;교환기는 연결하고 CTI는 판단한다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AwYX3/dJMcah7pmCh/aMKjKfu4DllsbV7bCvcqhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAwYX3%2FdJMcah7pmCh%2FaMKjKfu4DllsbV7bCvcqhK%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;2400&quot; height=&quot;1260&quot; data-filename=&quot;07_step3-pbx-cti.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;교환기는 연결하고 CTI는 판단한다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;언제.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 게이트웨이가 통역했거나 SBC가 안쪽으로 다시 건 INVITE가 교환기에 도착했을 때다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;어떻게.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 교환기는 PBX(Private Branch Exchange), 사설 교환기다. 옛날 회사의 전화 교환원이 하던 일을 장비가 한다. 외부 번호 하나로 들어온 전화를 안쪽 내선 수백 개 중 하나로 돌리고, 내선끼리 연결하고, 보류∙전환∙회의를 처리한다. IP 시대의 교환기는 IP-PBX이고, 하는 일은 결국 SIP 메시지를 받아 어느 내선으로 보낼지 정하는 것이다. 그런데 교환기 혼자서는 &quot;이 전화를 누구에게 줄지&quot;를 똑똑하게 정하지 못한다. 빈 내선에 돌리는 정도다. 그래서 교환기 옆에 CTI(Computer Telephony Integration)가 붙어 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CTI는 교환기에서 일어나는 모든 사건을 받는다. 전화가 왔다, 어느 번호에서 왔다, 어느 내선이 받았다, 보류했다, 끊었다. 그리고 반대로 교환기에 명령도 내린다. 이 전화를 저 내선으로 보내라, 이 전화를 IVR로 돌려라. 전화기와 컴퓨터는 원래 서로 모르는 사이인데, CTI가 둘을 소개해 준다. (상담사 화면에서 &quot;받기&quot; 버튼을 누르면 전화기가 울리기를 멈추는 것도 CTI가 교환기에 명령해서다.) 통계도 여기서 갈린다. 교환기에는 회선이 몇 통 들어오고 끊겼는지를 세는 교환기 통계가 있고, CTI에서는 상담사별로 몇 통을 받고 얼마나 기다리게 했는지를 세는 콜 통계가 있다. 세는 것이 다르니 두 숫자가 같을 이유가 없다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;왜.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 교환기는 연결은 하지만 판단은 못 하기 때문이다. 전화가 오면 교환기는 CTI에 &quot;왔다&quot;고 알리고 다음 지시를 기다린다. CTI가 &quot;IVR로 보내라&quot;고 하면 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;4.&lt;/b&gt;&lt;/span&gt;로 넘어간다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. CTI &amp;rarr; IVR, 상담사보다 먼저 받는 기계&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;언제.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; CTI가 새로 들어온 전화를 IVR로 돌리라고 교환기에 명령한 순간이다. 고객이 처음 듣는 목소리는 사람이 아니라 이것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;어떻게.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; IVR(Interactive Voice Response)이고, 우리말로는 ARS(Automatic Response System)라고 부른다. 같은 것이다. IVR은 미리 그려 둔 시나리오를 실행한다. 시나리오 흐름도는 처음 보면 복잡한 그림이지만 뜯어 보면 여섯 상자의 반복이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;08_step4-ivr-flow.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;2260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d12v5M/dJMcah7pp8y/fpOTbD0x4DNxHLXK3ELxTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d12v5M/dJMcah7pp8y/fpOTbD0x4DNxHLXK3ELxTK/img.png&quot; data-alt=&quot;IVR 시나리오의 뼈대&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d12v5M/dJMcah7pp8y/fpOTbD0x4DNxHLXK3ELxTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd12v5M%2FdJMcah7pp8y%2FfpOTbD0x4DNxHLXK3ELxTK%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;2400&quot; height=&quot;2260&quot; data-filename=&quot;08_step4-ivr-flow.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;2260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;IVR 시나리오의 뼈대&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;(4-1) 업무시간인지, 휴일인지 확인한다. 아니면 안내 멘트를 들려 주고 끝낸다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;(4-2) 업무시간이면 인사 멘트를 읽는다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;(4-3) 메뉴를 읽어 준다. 정비는 1번, 상담은 2번, 상담원 연결은 0번 같은 식이다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;(4-4) 고객이 누른 버튼을 확인한다. 잘못 누르거나 제한 시간 안에 안 누르면 다시 묻는다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;(4-5) 다시 묻는 횟수를 센다. 제한을 넘으면 사과 멘트와 함께 끊는다. 제한 안이면 (4-3)으로 돌아간다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;(4-6) 버튼이 제대로 들어오면 그 번호에 맞는 상담사 그룹을 고른다. 이 그룹을 스킬(Skill)이라고 부른다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;b&gt;2.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 에서 말한 DTMF 이벤트가 (4-4)에서 쓰인다. 버튼이 소리로 올지 이벤트로 올지가 게이트웨이와 IVR 사이에 맞아 있어야 (4-4)가 동작한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;왜.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 상담사에게 보내기 전에 이 전화가 무슨 전화인지 알아야 하기 때문이다. 정비 예약 전화와 사고 접수 전화를 같은 상담사에게 보내면 그 상담사가 다시 돌려야 한다. IVR이 하는 일은 결국 하나다. 질문 몇 개로 전화에 이름표를 붙이는 것. 그 이름표가 스킬이고, 스킬이 정해지면 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;b&gt;5.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 로 넘어간다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5. IVR &amp;rarr; CTI, 스킬이 정해졌으니 사람을 고른다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;09_step5-routing.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBgSHw/dJMcah0qtoS/PVR6cnMnSb7YSK4Igpqko1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBgSHw/dJMcah0qtoS/PVR6cnMnSb7YSK4Igpqko1/img.png&quot; data-alt=&quot;스킬이 정해졌으니 사람을 고른다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBgSHw/dJMcah0qtoS/PVR6cnMnSb7YSK4Igpqko1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBgSHw%2FdJMcah0qtoS%2FPVR6cnMnSb7YSK4Igpqko1%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;2400&quot; height=&quot;1260&quot; data-filename=&quot;09_step5-routing.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;스킬이 정해졌으니 사람을 고른다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;언제.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; IVR이 (4-6)에서 스킬을 정해 CTI에 &quot;이 전화는 이 스킬&quot;이라고 돌려준 순간이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;어떻게.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; CTI는 그 스킬에 속한 상담사 중 지금 대기 중인 사람을 고른다. 이것이 라우팅이다. 가장 오래 쉰 사람에게 주거나, 숙련도 순으로 주거나, 규칙은 센터마다 다르다. 대기 중인 사람이 없으면 전화를 큐에 넣는다. 큐에 있는 동안 고객은 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;b&gt;4.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 의 대기 시나리오를 듣는다. 대기 멘트, 조금 더 길어지면 다른 멘트, 더 길어지면 콜백 안내나 종료. 교육자료 그림에서 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;b&gt;6.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 옆에 &quot;모든 상담사가 통화 중이면 다시 IVR 대기 시나리오로&quot;라고 적어 둔 것이 이 되돌아가는 화살표다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;왜.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 스킬과 사람은 다른 것이기 때문이다. 스킬은 &quot;어떤 상담사여야 하는가&quot;이고 라우팅은 &quot;그중 누구인가&quot;다. 그래서 IVR은 사람을 고르지 않고 CTI에 돌려준다. CTI가 사람을 고르면 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;b&gt;6.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 이다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;6. CTI &amp;rarr; 상담사, 전화기가 울리고 화면이 뜬다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;10_step6-agent-desk.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eHZKMK/dJMcacruYU0/6OfMS3w9otYK8fLX5PPce1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eHZKMK/dJMcacruYU0/6OfMS3w9otYK8fLX5PPce1/img.png&quot; data-alt=&quot;전화기가 울리고 화면이 뜬다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eHZKMK/dJMcacruYU0/6OfMS3w9otYK8fLX5PPce1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeHZKMK%2FdJMcacruYU0%2F6OfMS3w9otYK8fLX5PPce1%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;2400&quot; height=&quot;1260&quot; data-filename=&quot;10_step6-agent-desk.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;전화기가 울리고 화면이 뜬다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;언제.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; CTI가 상담사 한 명을 골라 교환기에 &quot;이 전화를 이 내선으로&quot;라고 명령한 순간이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;어떻게.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 두 가지가 동시에 일어난다. 하나는 상담사의 전화기가 울리는 것이고, 다른 하나는 상담사의 화면에 고객 정보가 뜨는 것이다. 후자를 화면 팝업(Screen Pop)이라고 부른다. CTI가 &quot;이 번호에서 전화가 왔다&quot;는 사건을 상담 프로그램에 넘기면 상담 프로그램이 그 번호로 고객을 찾아 띄운다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상담 프로그램이 상담AP(Agent Program)다. 상담사가 하루 종일 보는 화면이고, 구조는 보통의 웹 시스템과 같다. 웹 서버, 애플리케이션 서버, 데이터베이스. 고객 조회, 상담 이력 입력, 전환, 콜백 예약이 다 여기에 있다. 전화 시스템이 연결을 담당한다면 상담AP는 기억을 담당한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난번에 무엇을 물었는지, 어떤 서류를 냈는지는 전화기가 아니라 이 화면에 있다. 통화가 시작되면 녹취 서버가 RTP를 복사해 저장한다. 상담사가 다른 상담사에게 넘겨야 하면 호전환을 한다. 바로 넘기는 1단계 전환과, 먼저 받을 사람과 통화한 뒤 넘기는 2단계 전환이 있다. 통화가 끝나면 CTI가 종료 사건을 기록하고, 콜 통계에 한 줄이 추가되고, 상담사는 상담AP에 이력을 적는다. 관리자는 관리자 화면에서 지금 몇 명이 통화 중이고 몇 통이 대기 중인지를 본다. 전화 한 통이 끝났다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;11_webrtc.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YadDx/dJMcaiSKbx7/FkxrmvRaOWtfr9hqHJysY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YadDx/dJMcaiSKbx7/FkxrmvRaOWtfr9hqHJysY0/img.png&quot; data-alt=&quot;전화기 없이 전화를 받는 법, WebRTC&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YadDx/dJMcaiSKbx7/FkxrmvRaOWtfr9hqHJysY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYadDx%2FdJMcaiSKbx7%2FFkxrmvRaOWtfr9hqHJysY0%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;2400&quot; height=&quot;1380&quot; data-filename=&quot;11_webrtc.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1380&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;전화기 없이 전화를 받는 법, WebRTC&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 상담사 자리에 전화기가 없는 경우를 적어야 한다. 요즘 컨택센터에는 그런 자리가 늘고 있다. 상담사는 헤드셋을 PC에 꽂고 브라우저를 연다. 전화는 브라우저로 온다. 이것을 가능하게 한 것이 WebRTC(Web Real-Time Communication)다. 브라우저가 플러그인 없이 마이크와 스피커를 쓰고 다른 쪽과 직접 미디어를 주고받게 하는 표준이고, W3C와 IETF가 함께 정했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WebRTC는 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;b&gt;2.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 의 두 줄기를 브라우저 안으로 가져온 것이다. 소리는 여전히 RTP로, UDP 위로 간다. 다만 암호화가 기본이다. SRTP(Secure RTP)로 소리를 암호화하고 그 열쇠는 DTLS(Datagram Transport Layer Security)로 교환한다. 브라우저는 암호화되지 않은 통화를 허용하지 않는다. 경계를 넘는 방법도 다르다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저는 집이나 사무실의 NAT 뒤에 있으므로 ICE(Interactive Connectivity Establishment)라는 절차로 자기 바깥 주소를 알아내고(STUN), 직접 연결이 안 되면 중계 서버를 거친다(TURN). &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;b&gt;2.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 에서 SBC가 하던 일의 일부를 브라우저와 중계 서버가 나눠 맡는 셈이다. 신호는 정해져 있지 않아서 컨택센터 쪽에서는 보통 SIP를 웹소켓 위에 실어 보내거나 솔루션 자체의 신호 방식을 쓴다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;왜 이게 중요한가.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 상담사가 집에서 일할 수 있고, 고객이 전화번호 없이 웹 페이지의 &quot;상담원 연결&quot; 버튼으로 통화할 수 있고, 컨택센터 자체가 클라우드에 있어도 상담사 쪽에 전화 장비를 둘 필요가 없다. 교육자료에는 WebRTC가 한 줄도 없었다. 그때는 상담사 자리에 전화기가 있는 것이 당연했다. 지금은 반대로 본다. 클라우드 컨택센터에서 상담사 쪽 전화기는 대부분 WebRTC다. 다음 글에서 다룰 인공지능 컨택센터와 클라우드 구성은 이 전제 위에 서 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;왜.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 전화기와 화면이 같이 움직여야 하기 때문이다. 전화만 연결되고 화면이 안 뜨면 상담사는 &quot;고객님 성함이 어떻게 되시죠&quot; 부터 다시 시작한다. &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;b&gt;6.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 은 전화를 사람에게 주는 단계가 아니라 전화와 기억을 같은 순간에 사람에게 주는 단계다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;결산, 여섯 단계를 한 표로&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;12_summary.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/T01ql/dJMcadX95mk/Qx5Lz5iYKwq4YuJEsP9yik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/T01ql/dJMcadX95mk/Qx5Lz5iYKwq4YuJEsP9yik/img.png&quot; data-alt=&quot;결산, 여섯 단계를 한 장으로&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/T01ql/dJMcadX95mk/Qx5Lz5iYKwq4YuJEsP9yik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FT01ql%2FdJMcadX95mk%2FQx5Lz5iYKwq4YuJEsP9yik%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;2400&quot; height=&quot;1440&quot; data-filename=&quot;12_summary.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;결산, 여섯 단계를 한 장으로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 140px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 6.97674%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;단계&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 23.3723%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;어디에서 어디로&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 29.651%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;언제&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 6.97674%; text-align: center; height: 20px;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 23.3723%; height: 20px;&quot;&gt;고객 &amp;rarr; 통신사 지능망&lt;/td&gt;
&lt;td style=&quot;width: 29.651%; height: 20px;&quot;&gt;대표번호를 누른 순간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 6.97674%; text-align: center; height: 20px;&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;width: 23.3723%; height: 20px;&quot;&gt;지능망 &amp;rarr; 게이트웨이 또는 SBC &amp;rarr; 교환기&lt;/td&gt;
&lt;td style=&quot;width: 29.651%; height: 20px;&quot;&gt;전화가 센터 문 앞에 온 순간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 6.97674%; text-align: center; height: 20px;&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;width: 23.3723%; height: 20px;&quot;&gt;교환기 &amp;rarr; CTI&lt;/td&gt;
&lt;td style=&quot;width: 29.651%; height: 20px;&quot;&gt;INVITE가 교환기에 닿은 순간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 6.97674%; text-align: center; height: 20px;&quot;&gt;4&lt;/td&gt;
&lt;td style=&quot;width: 23.3723%; height: 20px;&quot;&gt;CTI &amp;rarr; IVR&lt;/td&gt;
&lt;td style=&quot;width: 29.651%; height: 20px;&quot;&gt;CTI가 IVR로 돌리라고 명령한 순간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 6.97674%; text-align: center; height: 20px;&quot;&gt;5&lt;/td&gt;
&lt;td style=&quot;width: 23.3723%; height: 20px;&quot;&gt;IVR &amp;rarr; CTI&lt;/td&gt;
&lt;td style=&quot;width: 29.651%; height: 20px;&quot;&gt;스킬이 정해진 순간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 6.97674%; text-align: center; height: 20px;&quot;&gt;6&lt;/td&gt;
&lt;td style=&quot;width: 23.3723%; height: 20px;&quot;&gt;CTI &amp;rarr; 상담사∙상담AP∙녹취&lt;/td&gt;
&lt;td style=&quot;width: 29.651%; height: 20px;&quot;&gt;상담사 한 명이 정해진 순간&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;번호를 매겨 보니 장비 이름은 여섯 개가 아니라 열 개가 넘는데 단계는 여섯 개다. 장비를 외우면 열 개를 외워야 하고, 단계를 따라가면 여섯 번만 &quot;왜&quot;를 물으면 된다. 교육자료를 다시 열고 알게 된 것은 그림이 틀렸다는 것이 아니라, 그림 아래 여섯 줄이 그림보다 중요하다는 것이었다. 장애가 나면 어느 네모를 볼지가 아니라 어느 번호에서 멈췄는지를 먼저 묻는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글에서는 이 그림을 그대로 두고 번호 사이 어디에 인공지능이 끼어드는지를 본다. 전화 한 통의 길은 그대로다. 받는 쪽이 달라질 뿐이다.&lt;/p&gt;</description>
      <category>tech</category>
      <category>Contact Center</category>
      <category>cti</category>
      <category>IPCC</category>
      <category>ivr</category>
      <category>SBC</category>
      <category>SIP</category>
      <category>VoIP</category>
      <category>webrtc</category>
      <category>컨택센터 구조</category>
      <category>콜센터 시스템</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/5</guid>
      <comments>https://hsjo.tistory.com/5#entry5comment</comments>
      <pubDate>Sat, 10 Oct 2026 20:53:51 +0900</pubDate>
    </item>
    <item>
      <title>팀장 발령 한 달 후기, 첫날 공지한 운영원칙 네 가지는 지켜졌는가?</title>
      <link>https://hsjo.tistory.com/4</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01 썸네일 &amp;amp;mdash; 발령일 저녁의 메일.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPxQyH/dJMcacShEBh/gTa85blVk4i2azEFquD2K1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPxQyH/dJMcacShEBh/gTa85blVk4i2azEFquD2K1/img.png&quot; data-alt=&quot;발령일 저녁의 메일&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPxQyH/dJMcacShEBh/gTa85blVk4i2azEFquD2K1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPxQyH%2FdJMcacShEBh%2FgTa85blVk4i2azEFquD2K1%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;1672&quot; height=&quot;941&quot; data-filename=&quot;01 썸네일 &amp;mdash; 발령일 저녁의 메일.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;발령일 저녁의 메일&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전자결재로 발령 문서를 받은 날 퇴근 무렵, 나는 팀 전체에 메일을 한 통 보냈다. 인사말 아래에 운영원칙이라고 이름 붙인 네 줄을 적었다. 계약 범위 밖의 요청은 팀장이 48시간 안에 판단해서 직접 답한다. 고객사마다 정∙부 담당을 두고 매주 월요일 오전에 이슈관리대장을 갱신한다. 보고는 한 페이지로 하고 팀장 회신은 늦어도 24시간 안에 한다. 야간∙주말 작업은 사전에 보고하고 수당과 보상휴가는 팀장이 직접 챙긴다. 그 아래에 사람마다 맡을 일을 표로 붙였다. 2026년 9월 10일이었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 달이 지났다. 이 글은 그 네 줄을 지금 다시 읽는 기록이다. 팀장이 되면 무엇이 달라지는지를 일반론으로 쓰려는 것이 아니다. 내가 첫날 무엇을 약속했고, 그 약속이 한 달 동안 어떤 일과 부딪혔으며, 어느 것이 남고 어느 것이 뒤집혔는지를 날짜와 함께 적는다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 네 줄은 팀원이었을 때의 기억에서 나왔다&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영원칙 네 가지는 그날 저녁에 생각해 낸 것이 아니다. 나는 구축 현장에 십수 번 상주 PM(프로젝트 관리자, Project Manager)으로 나가 있었고, 그 전에는 운영팀에서 장비와 소프트웨어를 만지기도 했다. 그때 팀장에게 바랐던 것이 네 줄에 그대로 들어 있다. 범위 밖 요청을 들고 왔을 때 누군가 빨리 결정해 주길 바랐다. 고객 이슈가 누구 책임인지 매번 다시 정하지 않길 바랐다. 보고서를 열 장 쓰는 대신 한 장으로 끝내길 바랐다. 밤에 일하면 그게 어딘가에 기록되길 바랐다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02 1절 &amp;amp;mdash; 현장 상주 시절.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wHmC2/dJMcajqkETj/T1Yuwwf1EevYVFe7y5vaxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wHmC2/dJMcajqkETj/T1Yuwwf1EevYVFe7y5vaxk/img.png&quot; data-alt=&quot;현장 상주 시절&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wHmC2/dJMcajqkETj/T1Yuwwf1EevYVFe7y5vaxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwHmC2%2FdJMcajqkETj%2FT1Yuwwf1EevYVFe7y5vaxk%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;1672&quot; height=&quot;941&quot; data-filename=&quot;02 1절 &amp;mdash; 현장 상주 시절.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;현장 상주 시절&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러니까 네 줄은 선언이라기보다 채무 목록에 가깝다. 내가 받고 싶었던 것을 이제 내가 갚겠다는 목록. (쓸 때는 몰랐다. 한 달 뒤에 보니 그렇게 읽힌다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메일을 보내고 나서 임원에게서 회신이 왔다. 다섯 가지였다. 표정과 태도를 긍정적으로 유지할 것, 안팎의 다른 팀과 협업할 것, 원청과 협력사에 공식 회신을 보낼 때는 반드시 참조를 넣을 것, 포상은 특정인이 아니라 전체를 대상으로 근거 있게 할 것, 특정인과의 친분을 드러내지 말 것. 내 네 줄이 &quot;팀 안에서 어떻게 일할 것인가&quot;였다면 임원의 다섯 줄은 &quot;팀 밖에서 어떻게 보일 것인가&quot;였다. 나는 안쪽만 보고 있었다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 48시간 안에 답하려면 먼저 무엇이 있는지 알아야 했다.&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 원칙은 첫 주에 바로 벽에 부딪혔다. 범위 밖 요청인지 아닌지를 판단하려면 계약 범위를 알아야 하는데, 나는 이 팀의 계약을 다 알지 못했다. 전임 팀장은 다른 조직으로 옮겼고 인수인계 문서는 내 손에 없었다. 파트장으로 이 팀의 절반을 보던 사람이 팀장이 되면 나머지 절반이 자동으로 보일 줄 알았다. 아니었다. 메일 참조에 내가 없던 사업이 생각보다 많았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 그 주 금요일 밤부터 메일함을 처음부터 다시 읽었다. 사업별로 폴더를 나누고, 계약∙견적∙정산이 걸린 스레드를 따로 모으고, 스레드마다 지금 상태가 무엇인지 한 줄씩 적었다. 이틀이 걸렸다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 질문이 하나 생겼다. 전임자에게 무엇을 물어봐야 하는지를 어떻게 아는가. 모르는 것이 무엇인지 모르는 상태였다. 내가 쓴 방법은 역추적이다. 전임자가 마지막 발신자인데 답장이 없는 스레드, 전임자가 팀원에게 지시만 했고 결과가 메일에 없는 건, 전임자가 원청이나 협력사와 직접 주고받아 내가 참조에 없던 건. 이 세 조건으로 메일함을 걸러 &quot;전임자만 아는 것&quot; 목록을 만들었다. 9월 20일 일요일에 그 목록을 포함한 현황 문서 일곱 개가 나왔다. 할 일 리스트, 사업 현황판, 유지보수 현황판, 견적/계약 현황, 정기 보고 의무, 교육 일정, 인수인계 요청 리스트 등이었다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;03 2절 &amp;amp;mdash; 메일함 역추적.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/djZ3Bo/dJMcaatBNrC/jskTtz0Msh3eufgRgKPHk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/djZ3Bo/dJMcaatBNrC/jskTtz0Msh3eufgRgKPHk1/img.png&quot; data-alt=&quot;메일함 역추적&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/djZ3Bo/dJMcaatBNrC/jskTtz0Msh3eufgRgKPHk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdjZ3Bo%2FdJMcaatBNrC%2FjskTtz0Msh3eufgRgKPHk1%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;1672&quot; height=&quot;941&quot; data-filename=&quot;03 2절 &amp;mdash; 메일함 역추적.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;메일함 역추적&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔직히 일요일이 통째로 들어갔다. 그래도 월요일 아침 주간회의에 들어갈 때 손에 든 것이 있었다. 범위 밖 요청에 48시간 안에 답한다는 원칙은 그 뒤로 지킬 수 있는 원칙이 됐다. 첫 주와 둘째 주의 차이는 내 판단력이 아니라 손에 든 문서였다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 이슈관리대장보다 먼저 필요한 것은 사람 수였다&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 원칙은 한 달 동안 한 번도 제대로 돌아가지 않았다. 고객별 정∙부 담당은 첫날 표로 정했다. 그런데 매주 월요일 이슈관리대장을 갱신했는지는 내 기록 어디에도 없다. 기록에 없으면 안 한 것으로 친다. 이유는 분명하다. 담당을 정하는 것과 담당할 사람이 있는 것은 다른 문제였다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9월 21일 월요일, 임원 회의가 끝나자마자 인력계획이 가장 급한 일이 됐다. 지시는 구체적이었다. 직무 그룹별로 지금 사람이 몇 명이고, 앞으로 들어올 사업 기준으로 몇 명이 필요하며, 모자라는 수를 어떻게 채울지를 엑셀 한 장에 넣으라는 것. 나는 직무를 여섯 개로 나눴다. 관리, PL(프로젝트 리더, Project Leader), 음성기술 엔지니어, 봇기술 엔지니어, 시나리오 지원, 시나리오 저작. 명부에는 23명이 있었지만 전출∙계약종료∙휴직 예정을 빼면 16명이었고, 고객사에 상주 중인 사람과 내부 업무 전담을 빼면 당장 프로젝트에 넣을 수 있는 사람은 14명이었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 필요한 사람 수를 사업 네 개를 다 한다는 전제로 셌다. 48명이 나왔다. 부족이 34명. 이 숫자를 들고 간 보고에서 임원은 최대치가 아니라 올해 안에 실제로 확보할 수를 가져오라고 했다. 조건부 사업을 빼고 다시 세니 필요 32명, 부족 18명. 엑셀 파일은 다섯 판이 됐다. 9월 23일 한 판, 9월 28일 네 판. 같은 사람을 세는데 보고 때마다 숫자가 달라진 것은 내가 틀려서가 아니라 질문이 달라져서였다. &quot;다 하려면 몇 명인가&quot;와 &quot;올해 몇 명을 뽑을 것인가&quot;는 다른 질문이다. 나는 첫 질문에 답하고 있었고 임원은 두 번째 질문을 하고 있었다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04 3절 &amp;amp;mdash; 사람 수 세기.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c3Mv1a/dJMcaatBNvj/N4sklo3Q32qVn24D98XJP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c3Mv1a/dJMcaatBNvj/N4sklo3Q32qVn24D98XJP0/img.png&quot; data-alt=&quot;사람 수 세기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c3Mv1a/dJMcaatBNvj/N4sklo3Q32qVn24D98XJP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc3Mv1a%2FdJMcaatBNvj%2FN4sklo3Q32qVn24D98XJP0%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;1672&quot; height=&quot;941&quot; data-filename=&quot;04 3절 &amp;mdash; 사람 수 세기.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;사람 수 세기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람을 세는 동안 사람을 만났다. 9월 28일부터 10월 7일까지 팀원 열네 명과 1:1 면담을 했다. 면담에 시간을 쓰지 말고 필요한 배치는 바로 시행하라는 조언도 들었다. 나는 면담을 했다. 다만 면담 결과를 기다리느라 결정을 미루지는 않았다. 전출과 계약종료처럼 이미 정해진 것은 면담 전에 확정했고, 면담은 &quot;어디에 배치할까&quot;가 아니라 &quot;이 사람이 어떤 일을 하고 싶어 하는가&quot;를 듣는 자리로 썼다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면담과 회의는 전부 회의 노트로 남겼다. 9월 22일에 노트 도구를 하나 정하면서 인력 관리용 데이터베이스 다섯 개와 대시보드를 만들었다가 그날 저녁에 전부 지웠다. (만드는 데 반나절, 지우는 데 한 문장.) 남긴 것은 미팅 목록 하나와 열 세 개뿐이다. 이름, 유형, 생성 일시, 회의가 끝나면 유형 하나를 고르는 것이 내가 할 일의 전부다. 한 달 동안 거기 37건이 쌓였다. 회의22, 면담 14, 분류 안 한 것 1. 면담에서 나온 말은 원문과 결정을 분리해 둔다. 사람에 관한 말은 그렇게 두는 편이 안전하다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. 한 페이지 보고는 지켜졌고, 24시간 회신은 측정하지 못했다&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째 원칙의 앞 절반은 지켜졌다. 뒤 절반은 모른다. 보고를 한 페이지로 하겠다는 약속은 지켰다기보다 지킬 수밖에 없었다. 읽는 사람이 한 페이지 이상 읽지 않기 때문이다. 9월 23일 인력계획 임원 보고는 엑셀 시트 한 장이었고, 9월 24일에는 고객사에 보낼 컨설팅 자료를 하루에 두 번째 판에서 다섯 번째 판까지 고쳤다. 추석 연휴 첫날이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10월 8일에는 경영진 보고용 장표를 첫 판에서 네 번째 판의 세 번째 수정본까지 하루에 만들었다. 그날 장표를 고치며 적어 둔 지적 두 줄을 그대로 옮기면 이렇다. &quot;경영진 보고인데 글자가 너무 작다.&quot;, &quot;약어를 쓰지 마라. 읽는 사람은 약어를 모른다.&quot; 한 페이지 원칙은 분량의 문제가 아니라 읽는 사람의 문제였다. 열 장을 한 장으로 줄이는 일이 아니라, 읽는 사람이 모르는 단어를 빼는 일이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;05 4절 &amp;amp;mdash; 한 페이지 보고.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pJdo6/dJMcaatBNxy/GPhVU1S0DG3D9pKOKfj3HK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pJdo6/dJMcaatBNxy/GPhVU1S0DG3D9pKOKfj3HK/img.png&quot; data-alt=&quot;한 페이지 보고&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pJdo6/dJMcaatBNxy/GPhVU1S0DG3D9pKOKfj3HK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpJdo6%2FdJMcaatBNxy%2FGPhVU1S0DG3D9pKOKfj3HK%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;1672&quot; height=&quot;941&quot; data-filename=&quot;05 4절 &amp;mdash; 한 페이지 보고.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;한 페이지 보고&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;24시간 회신은 재지 못했다. 받은 메일에 내가 몇 시간 만에 답했는지를 세어 보지 않았다. 메일함은 있는데 자가 없었다. 지키지 않았다는 뜻이 아니라 확인할 수 없다는 뜻이다. 다음 달에는 잴 생각이다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5. 네 번째 원칙은 가장 먼저 시험대에 올랐다&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;야간∙주말 보상을 팀장이 챙긴다는 네 번째 원칙은 네 개 중 가장 쉬워 보였다. 수당 신청서에 서명하는 일 아닌가. 아니었다. 이 원칙은 &quot;야근이 생기면&quot;이라는 전제를 깔고 있었고, 나는 야근이 생기지 않게 하는 것이 팀장 일이라고 생각했지 야근을 어떻게 세고 어떻게 갚을지는 생각하지 않았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10월 1일 목요일. 낮에는 본부 사업계획 토론회에 있었다. 저녁에 운영 중인 서비스에 결함이 발생했다. 그날 18시 36분에 나는 원청에 메일을 보냈다. 여덟 명을 투입해 대상 건을 수작업으로 조회하기 시작한다는 내용이다. 보낸 편지함에 그 시각이 찍혀 있다. 그날 밤 자정을 조금 넘겨 회의가 있었고, 새벽 1시에 원청 PM과 다시 협의했고, 새벽 5시에 절충안을 보냈다. 아침 8시 26분에 다시 회의, 9시 31분에 팀 내부 회의. 회의 노트의 생성 시각이 그대로 그 밤의 타임라인이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;06 5절 &amp;amp;mdash; 결함의 밤.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ugAI6/dJMb99ONEqk/LEexZsD6qp3NN5A2ZDPpF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ugAI6/dJMb99ONEqk/LEexZsD6qp3NN5A2ZDPpF0/img.png&quot; data-alt=&quot;결함의 밤&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ugAI6/dJMb99ONEqk/LEexZsD6qp3NN5A2ZDPpF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FugAI6%2FdJMb99ONEqk%2FLEexZsD6qp3NN5A2ZDPpF0%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;1672&quot; height=&quot;941&quot; data-filename=&quot;06 5절 &amp;mdash; 결함의 밤.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;결함의 밤&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 질문이 바뀌었다. 야근을 막을 수 있는가가 아니라, 막을 수 없는 야근을 어떻게 기록할 것인가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;투입 인원 전원의 출퇴근 시각을 날짜별로 적고 본인과 PM이 서명하는 대장을 만들었다. 그 대장이 수당과 보상휴가의 근거다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네 번째 원칙은 지켜졌는가. 보상을 챙기는 체계는 생겼다. 야근은 줄지 않았다. 둘 다 사실이다. 팀장이 되기 전의 나는 이 둘이 같은 문장이라고 생각했다. 지금은 다른 문장이라는 것을 안다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;6. 마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네 줄 중에서 첫 번째는 둘째 주부터 지킬 수 있게 됐고, 두 번째는 지키지 못했고, 세 번째는 절반만 확인됐고, 네 번째는 뜻이 바뀌었다. 한 달 전의 나는 네 줄을 &quot;팀장이 팀에게 하는 약속&quot;으로 썼다. 지금 보니 네 줄은 전부 &quot;팀장이 먼저 알아야 하는 것&quot;의 목록이었다. 계약 범위를 알아야 48시간 안에 답하고, 사람 수를 알아야 담당을 두고, 읽는 사람을 알아야 한 장으로 쓰고, 야근을 세어야 갚는다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;07 6절 &amp;amp;mdash; 보낸 편지함.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdqUp7/dJMcajxkI8J/9zUOr6holSC9IC7cqCzPY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdqUp7/dJMcajxkI8J/9zUOr6holSC9IC7cqCzPY0/img.png&quot; data-alt=&quot;보낸 편지함&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdqUp7/dJMcajxkI8J/9zUOr6holSC9IC7cqCzPY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdqUp7%2FdJMcajxkI8J%2F9zUOr6holSC9IC7cqCzPY0%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;1672&quot; height=&quot;941&quot; data-filename=&quot;07 6절 &amp;mdash; 보낸 편지함.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;보낸 편지함&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 달 이 글을 다시 읽을 나에게 두 가지를 적어 둔다. 이슈관리대장은 월요일 아침 첫 일정으로 넣어라. 그리고 24시간 회신은 재라. 재지 않은 원칙은 지킨 것도 어긴 것도 아니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫날 보낸 메일은 아직 보낸 편지함에 있다. 지우지 않을 생각이다.&lt;/p&gt;</description>
      <category>thinking</category>
      <category>1on1 면담</category>
      <category>First-time Manager</category>
      <category>Team Lead</category>
      <category>리더십</category>
      <category>신임 팀장</category>
      <category>인력계획</category>
      <category>중간관리자</category>
      <category>팀 운영원칙</category>
      <category>팀장 발령</category>
      <category>팀장 후기</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/4</guid>
      <comments>https://hsjo.tistory.com/4#entry4comment</comments>
      <pubDate>Thu, 8 Oct 2026 22:05:00 +0900</pubDate>
    </item>
    <item>
      <title>프롬프트를 GitHub에 기록하며 일하는 법, 대화가 끝나도 맥락은 남는다</title>
      <link>https://hsjo.tistory.com/3</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01_thumbnail.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/li86J/dJMcahTyPrK/7zBJIXYXlYThXLqNkWw511/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/li86J/dJMcahTyPrK/7zBJIXYXlYThXLqNkWw511/img.png&quot; data-alt=&quot;썸네일&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/li86J/dJMcahTyPrK/7zBJIXYXlYThXLqNkWw511/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fli86J%2FdJMcahTyPrK%2F7zBJIXYXlYThXLqNkWw511%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;2400&quot; height=&quot;1260&quot; data-filename=&quot;01_thumbnail.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;썸네일&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인공지능과 일하는 사람이라면 한 번은 겪는다. 어제 한참 같이 정한 규칙을 오늘 새 대화에서 처음부터 다시 설명하고 있는 자신을 발견하는 일이다. &quot;이전 대화를 참고해서&quot;라고 써 봐도 소용없다. 새 대화는 백지다. 그래서 지난 대화를 통째로 복사해 붙여 보고, 요약을 메모해 두었다가 붙여 보고, 그러다 바쁜 날 하나를 빠뜨리고, 빠뜨린 날 인공지능이 안 하기로 한 일을 다시 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 이 문제를 쭉 겪었다. 큰 작업은 대화 하나로 끝나지 않았고, 대화를 넘길 때마다 맥락이 깎였다. 그래서 연습한 것이 있다. 맥락을 인공지능에게 맡기지 않는 것. 지금은 이렇게 한다. 작업 하나가 끝나면 그 대화를 파일 하나로 저장소에 남긴다. 결정이 나면 표에 한 줄을 추가한다. 대화가 70%쯤 차면 다음 대화가 읽을 인수인계 문서를 받아 둔다. 그리고 전부 GitHub에 올린다. 대화창이 닫혀도, 모델이 바뀌어도, 노트북이 바뀌어도 맥락은 저장소에 있다. 클로드(Claude)로 하던 일을 GPT가 이어받는 것도 된다. 둘이 같은 폴더를 읽기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 그 방법을 깃(Git)을 모르는 사람도 따라 할 수 있게 적은 것이다. 지금 내 GitHub 저장소는 전부 이 구조로 돌아간다. 중간에 규칙이 깨진 날도 적었다. 그날이 지금 구조의 절반을 만들었다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 인공지능은 책상 위에 있는 것만 읽는다&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인공지능이 기억하는 범위는 지금 열려 있는 대화 하나다. 이 범위를 컨텍스트(context) 또는 컨텍스트 창(context window)이라고 부른다. 내가 이해한 방식으로 바꾸면 책상이다. 책상 위에 올라온 종이만 읽을 수 있고, 책상은 대화마다 새로 치워진다. 책상에는 크기가 있어서 대화가 길어지면 앞에 놓은 종이부터 밀려 떨어진다. 긴 대화의 끝에서 인공지능이 앞에서 정한 규칙을 어기는 건 고집이 아니다. 그 종이가 이미 바닥에 있는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2208&quot; data-origin-height=&quot;1894&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dClXjs/dJMcai53fyA/mtckmDIHVChDgWJfhsrUwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dClXjs/dJMcai53fyA/mtckmDIHVChDgWJfhsrUwK/img.png&quot; data-alt=&quot;컨텍스트 윈도우&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dClXjs/dJMcai53fyA/mtckmDIHVChDgWJfhsrUwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdClXjs%2FdJMcai53fyA%2FmtckmDIHVChDgWJfhsrUwK%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;2208&quot; height=&quot;1894&quot; data-origin-width=&quot;2208&quot; data-origin-height=&quot;1894&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;컨텍스트 윈도우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 이걸 모델이 해결해 줄 문제로 생각했다. 컨텍스트 창은 매년 커지고, 대화를 기억하는 기능도 하나씩 붙는다. 기다리면 되지 않을까. 그런데 창이 커져도 일은 그보다 빨리 길어지고, 기억 기능은 그 회사의 그 서비스 안에서만 동작한다. 내 일은 도구 하나에 머물지 않는다. 그래서 질문을 바꿨다. 인공지능이 기억하게 만드는 게 아니라, 내가 기억을 들고 다니면 어떤가. 기억을 인공지능 안이 아니라 밖에 두고, 새 대화가 시작될 때 그 기억을 책상 위에 올려 주는 것이다. 이 글 전체는 그 &quot;밖&quot;을 어디에 어떤 모양으로 두는가에 대한 이야기다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 기억은 메모 앱이 아니라 저장소에 둔다&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기억을 밖에 둔다고 하면 메모 앱이나 노션(Notion)이 먼저 떠오른다. 나도 그 생각을 했다. 그런데 그 방식은 결국 내 손을 거친다. 내가 메모를 열고, 복사하고, 새 대화에 붙여야 한다. 바쁜 날 그 과정이 빠지고, 빠진 날 사고가 난다. 요즘의 인공지능 코딩 도구(클로드 코드 Claude Code, 코덱스 Codex 같은 것들)는 작업 폴더 안의 파일을 스스로 읽는다. 그러니 기억은 그 폴더 안에, 파일로 있어야 한다. 내 손이 아니라 도구가 집어 들게.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 폴더를 깃으로 관리하고 GitHub에 올리는 이유는 두 가지다. 결정은 바뀐다. &quot;카테고리는 여섯 개&quot;가 다음 날 일곱 개가 된다. 메모 앱은 마지막 상태만 남지만 깃은 매 변경을 저장하고, 언제 무엇이 어떻게 바뀌었는지 되돌려 볼 수 있다. 몇 달 뒤 &quot;왜 이렇게 됐지?&quot;에 답하려면 이 이력이 필요하다. 그리고 나는 노트북을 자주 바꾼다. 로컬에만 있는 것은 없는 것으로 친다. GitHub에 있으면 새 기기에서 내려받는 것으로 끝난다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깃과 GitHub를 처음 듣는 사람을 위해 한 문단만 쓴다. 깃은 폴더의 변경 이력을 저장하는 프로그램이다. &quot;지금 상태를 저장한다&quot;가 커밋(commit)이다. GitHub는 그 저장 내역을 올려 두는 인터넷 창고다. 내 컴퓨터에서 창고로 올리는 게 푸시(push), 창고에서 내려받는 게 풀(pull)이다. 비공개(private)로 만들면 나만 본다. 이 글에서 쓰는 깃 명령은 네 개다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔직히 처음엔 어색했다. 저장소는 코드를 두는 곳이라 배웠고, 대화 기록을 거기 넣는 게 맞나 싶었다. 그런데 코드는 결정의 결과물이고 대화는 결정 그 자체다. 결과물만 남기고 결정을 버리는 쪽이 거꾸로였다. 지금은 코드가 한 줄도 없는 저장소도 있다. 이 블로그의 저장소가 그렇다. 글 원고와 설정값과 대화 기록만 있다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 기록은 세 층으로 쌓는다&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;02_three-layers.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJw44K/dJMcackwDg6/QB6I2KpoJiAGtk6Zv05YBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJw44K/dJMcackwDg6/QB6I2KpoJiAGtk6Zv05YBK/img.png&quot; data-alt=&quot;기록은 세 층이다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJw44K/dJMcackwDg6/QB6I2KpoJiAGtk6Zv05YBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJw44K%2FdJMcackwDg6%2FQB6I2KpoJiAGtk6Zv05YBK%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;2400&quot; height=&quot;1260&quot; data-filename=&quot;02_three-layers.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;기록은 세 층이다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 대화를 통째로 저장하면 되는 줄 알았다. 전체 대화를 파일로 떨어뜨려 두면 기억이 보존되지 않을까. 그런데 전체 대화는 길고 대부분이 시행착오다. 새 대화에 그걸 다 올리면 책상이 처음부터 꽉 찬다. 필요한 건 양이 아니라 층이었다. 지금은 세 층으로 쌓는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맨 아래가 대화 기록이다. 작업 하나가 끝날 때마다 prompt/ 폴더에 파일 하나를 쓴다. 파일명은 번호, 날짜, 한 줄 주제이고 번호는 0001부터 빈 번호 없이 올라간다. 아래는 이 블로그 저장소에 며칠 전 실제로 생긴 파일이다. 스킨을 고치고 실물을 확인한 작업이었다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1791373224777&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 0057 - skin-1.15-live-check (1.15 적용 실물 확인)
## 1. 메타
- 날짜 2026-10-06 &amp;middot; 태스크 tistory(루트) &amp;middot; 모델 Fable 5.1 &amp;middot; 도구: 내장 브라우저
## 2. Prompt 전문
&amp;gt; 1.15 적용했습니다. 실물 확인해 주세요
## 3. Response 핵심
- 홈 실물: 카드 네모 기호 제거 확인, 히트맵 제목 &quot;1 posts in the last year&quot;(페이지 제외). 통과.
- 관찰(미처리): 히트맵이 가로 스크롤되는 중간 폭에서 &quot;25&quot; 조각이 남음. 다음 릴리스에 포함.
## 4. 결과
- STATUS 스킨 행 v1.15, LATEST.md 갱신.
## 5. 다음 할 일
- 두 번째 글 주제 결정. 색인 반영 확인(며칠 뒤).&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다섯 절이다. 메타, 내 요청 원문, 답의 핵심, 결과, 다음 할 일. 2번은 요약하지 않고 내 말을 그대로 둔다. 몇 달 뒤 읽을 때 내가 그때 무엇을 원했는지는 요약이 아니라 원문에 남아 있다. 3번에는 &quot;안 한 것과 그 이유&quot;가 들어간다. 위 파일의 &quot;관찰(미처리)&quot;가 그것이다. 이 줄이 없으면 다음 대화에서 또 하자고 한다. 그리고 이 파일은 내가 쓰지 않는다. 인공지능이 쓴다. 작업이 끝나면 &quot;기록해&quot; 한 마디다. 형식은 지침 파일에 적어 두었고, 나는 읽고 틀린 것을 고친다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가운데가 인수인계다. LATEST.md 한 장. 교대 근무의 인수인계 노트와 같은 것으로, 밤 근무자가 아침 근무자에게 지금 상태와 오늘 할 일과 조심할 것을 적어 주는 그 노트다. 내 것은 여덟 절이다. 이 작업이 무엇이고 마감은 언제인가, 확정된 것, 진행 중인 작업과 현재 상태, 다음 대화가 열어 볼 파일 순서, 미해결, 첫 행동, 금지 사항, 재사용할 명령. 이것도 인공지능이 쓴다. 내가 보내는 요청은 거의 같은 문장이다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;현재 대화의 컨텍스트가 너무 높아 새로운 대화 세션을 열고 진행하겠습니다. 우리 대화의 모든 맥락과 디렉토리에 있는 모든 파일과 히스토리를 분석한 후 대응할 수 있도록 신규 대화 세션에서 보낼 프롬프트 상세 내용을 작성해 주세요. 본문에 바로 붙여 넣을 수 있도록 상세하게 작성해 주시기 바랍니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 LATEST.md가 새로 쓰이고 같은 내용이 화면에도 나온다. 나는 새 대화를 열고 &quot;LATEST.md 기준으로 이어서.&quot; 한 줄을 보낸다. 이전 LATEST.md 는 지우지 않고 prompt/ 폴더에 핸드오프 기록으로 남긴다. 인수인계 노트도 이력이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맨 위가 결정이다. context/decisions.md에 표 하나가 있고, 결정이 확정될 때마다 한 줄을 붙인다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1791373610301&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;| 날짜 | 결정 | 결정자 | 출처 |
|---|---|---|---|
| 2026-10-05 | 카테고리 이름은 영어 소문자로 통일 | 조현성 | prompt/0019 |
| 2026-10-06 | 두 번째 글 카테고리 tech | 조현성 | prompt/0060 |&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;규칙은 추가만 한다는 것이다. 지우거나 고치지 않는다. 뒤집힌 결정은 뒤집은 결정을 새 줄로 넣는다. 그래야 &quot;처음엔 여섯 개였다가 일곱 개로 바뀌었다&quot;가 남는다. 출처 칸의 번호를 따라가면 그날의 대화 전문이 나오고, 대화 기록의 결과 절에는 커밋이 적혀 있다. 결정에서 대화로, 대화에서 변경으로 이어진다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 층 바깥에 파일이 하나 더 있다. 저장소 맨 위의 CLAUDE.md다. 도구에 따라 AGENTS.md라고 부른다. 인공지능 코딩 도구가 대화를 시작할 때 자동으로 읽는 파일이고, 여기에 &quot;시작하면 LATEST.md부터 읽어라&quot;, &quot;작업 1건이 끝나면 prompt/에 기록하라&quot;, &quot;결정은 decisions.md에 한 줄&quot;을 적는다. 내가 매번 하던 잔소리를 글로 옮긴 것이다. 잔소리는 내가 기억해서 하는 게 아니라 매번 자동으로 읽히는 곳에 있어야 한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. 70%라는 선&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법에서 내가 가장 지키는 습관은 숫자 하나를 보는 것이다. 대화가 끝날 즈음 컨텍스트 사용량을 확인하고, 70%를 넘으면 그 대화에서 새 작업을 시작하지 않는다. 위의 인수인계 문장을 보내고, LATEST.md를 받고, 새 대화를 연다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 70인가. 책상이 꽉 차기 직전이 가장 위험하기 때문이다. 90%에서 인수인계를 쓰면 인수인계에 들어가야 할 종이가 이미 바닥에 떨어진 뒤다. 70%는 아직 모든 종이가 책상 위에 있을 때다. 다만 70이 정확한 숫자라는 근거는 없다. 내 경험치다. 60이어도 되고 75여도 될 것이다. 중요한 건 자기 숫자를 하나 정하고, 넘으면 대화를 끊는 것이다. 잘 흐르고 있는 대화를 끊는 건 아깝다. 그래도 끊는다. 잘 흐르는 대화의 끝에서 앞의 규칙이 조용히 무너지는 걸 보는 쪽이 더 아깝다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5. 규칙이 깨진 날&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;규칙을 다 세우고도 크게 어긴 날이 있다. 2026년 9월 20일, 인공지능은 여섯 시간 동안 커밋을 22개 했고 prompt/ 기록은 하나도 남기지 않았다. 지침 파일에는 &quot;작업 1건마다 기록&quot;이라고 적혀 있었다. 적혀 있었지만 바빴고, 나도 인공지능도 넘어갔다. 그날 기록 폴더를 열어 보고 알았다. 여섯 시간 동안 어떤 결정이 왜 났는지는 커밋 메시지 몇 글자 말고는 없었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 지침을 더 세게 쓰려고 했다. &quot;예외 없음&quot;, &quot;반드시&quot;. 그런데 그 말은 이미 있었다. 글자로 되는 일이 아니었다. 사람도 인공지능도 바쁘면 글자를 건너뛴다. 그래서 규칙을 의지에서 빼서 기계에 넘겼다. 훅(hook)이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;훅은 정해진 순간에 자동으로 실행되는 작은 스크립트다. 클로드 코드는 &quot;대화가 시작될 때&quot;와 &quot;인공지능이 답을 마칠 때&quot; 같은 순간에 내 스크립트를 끼울 수 있게 해 준다. 나는 두 개를 쓴다. 핵심만 남기면 이렇다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시작 훅은 저장소를 최신으로 당기고 기억을 책상 위에 올린다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1791374036247&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#!/bin/bash
ROOT=&quot;$(git rev-parse --show-toplevel 2&amp;gt;/dev/null)&quot; || exit 0
git -C &quot;$ROOT&quot; pull -q --rebase origin HEAD
[ -f LATEST.md ] &amp;amp;&amp;amp; { echo &quot;=== LATEST.md ===&quot;; cat LATEST.md; }
[ -f &quot;$ROOT/context/decisions.md&quot; ] &amp;amp;&amp;amp; { echo &quot;=== 최근 결정 ===&quot;; tail -20 &quot;$ROOT/context/decisions.md&quot;; }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;훅이 출력한 글은 인공지능의 첫 화면에 그대로 들어간다. 내가 &quot;읽어&quot;라고 하기 전에 읽혀 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;종료 훅은 변경이 있으면 커밋하고 푸시한다. 그리고 9월 20일에 추가한 부분이 뒤에 붙어 있다. 기록 없이 커밋이 쌓였으면 턴을 끝내지 못하게 막는다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1791374088513&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#!/bin/bash
ROOT=&quot;$(git rev-parse --show-toplevel 2&amp;gt;/dev/null)&quot; || exit 0
cd &quot;$ROOT&quot; &amp;amp;&amp;amp; git add -A
if ! git diff --cached --quiet; then
  git commit -q -m &quot;auto: $(date '+%Y-%m-%d %H:%M')&quot;
  git pull -q --rebase origin HEAD &amp;amp;&amp;amp; git push -q origin HEAD
fi
# 마지막 prompt/ 기록 뒤로 커밋 3개 이상, 90분 경과면 기록을 요구한다
LAST=&quot;$(git log -1 --format=%H -- prompt/)&quot;
N=&quot;$(git rev-list --count &quot;$LAST..HEAD&quot;)&quot;
AGE=$(( $(date +%s) - $(git log -1 --format=%ct -- prompt/) ))
if [ &quot;$N&quot; -ge 3 ] &amp;amp;&amp;amp; [ &quot;$AGE&quot; -ge 5400 ]; then
  echo '{&quot;decision&quot;:&quot;block&quot;,&quot;reason&quot;:&quot;prompt/ 기록 없이 커밋이 쌓였다. 기록을 쓰고 끝내라.&quot;}'
fi&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인공지능이 답을 마치려 할 때 훅이 &quot;기록 없이 커밋 N개&quot;를 발견하면 종료를 거부하고 이유를 돌려준다. 인공지능은 그 이유를 읽고 기록을 쓴 뒤에야 턴을 끝낼 수 있다. 그 뒤로 같은 사고는 없다. 90분이라는 조건은 같은 날 덧붙였다. 처음엔 커밋 개수만 봤는데, 긴 작업 하나를 하는 동안 자동 커밋이 쌓여서 같은 작업 안에서 두 번 막혔다. 규칙을 기계에 넘기면 기계도 틀린다. 틀리면 고친다. 사람에게 다시 맡기는 것보다는 낫다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 시작하는 사람은 이 절을 건너뛰어도 된다. 훅 없이 손으로 커밋해도 방법은 돌아간다. 다만 언젠가 자기만의 9월 20일을 겪을 것이고, 그때 돌아와서 읽으면 된다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;6. 도구에 묶이지 않는다&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 읽으면 눈치챘을 것이다. 이 방법에는 특정 인공지능이 없다. 파일은 마크다운이고, 저장소는 깃이고, 인수인계는 사람이 읽는 글이다. 어느 모델이든 읽는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 그렇게 시작했다. prompt/ 폴더 규칙은 2026년 6월 15일, 내 첫 iOS 앱 가계부(gageboo)의 저장소에서 처음 만들었다.&lt;/p&gt;
&lt;figure id=&quot;og_1791374310902&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Gageboo : Expense Tracker App - App Store&quot; data-og-description=&quot;Download Gageboo : Expense Tracker by HYUNSUNG JO on the App Store. See screenshots, ratings and reviews, user tips, and more apps like Gageboo : Expense&amp;hellip;&quot; data-og-host=&quot;apps.apple.com&quot; data-og-source-url=&quot;https://apps.apple.com/us/app/gageboo-expense-tracker/id6791876552&quot; data-og-url=&quot;https://apps.apple.com/us/app/gageboo-expense-tracker/id6791876552&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/btlhgr/dJMb9kUqbsx/0NVfShtLp9vRM2ZhZdTvp0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dhTkvN/dJMb86Ppjtm/gYQhdQTYdEuXXiJZm7eHvK/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://apps.apple.com/us/app/gageboo-expense-tracker/id6791876552&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://apps.apple.com/us/app/gageboo-expense-tracker/id6791876552&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/btlhgr/dJMb9kUqbsx/0NVfShtLp9vRM2ZhZdTvp0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dhTkvN/dJMb86Ppjtm/gYQhdQTYdEuXXiJZm7eHvK/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&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;Gageboo : Expense Tracker App - App Store&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Download Gageboo : Expense Tracker by HYUNSUNG JO on the App Store. See screenshots, ratings and reviews, user tips, and more apps like Gageboo : Expense&amp;hellip;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;apps.apple.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 폴더의 안내문 첫 줄은 지금도 &quot;코덱스(Codex) 세션의 주요 프롬프트와 응답 핵심을 보존한다&quot;다. GPT 계열 도구로 시작한 규칙이다. 6월 15일부터 8월 2일까지 그 저장소에는 대화 기록 270개와 커밋 339개가 쌓였다. 8월에 아이디어 저장소를 만들 때 같은 규칙을 그대로 옮겼고, 지금은 주로 클로드 코드로 일한다. 도구는 바뀌었고 폴더는 그대로다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인수인계 문서는 특정 도구의 문법이 아니라 글이라서 클로드에 붙이든 GPT에 붙이든 같은 글을 붙인다. 이건 어느 모델이 낫다는 글이 아니다. 기억을 모델 밖에 두면 모델을 고를 자유가 생긴다는 말이다. 기억이 대화창 안에 있으면 그 대화창을 만든 회사에 묶인다. 기억이 내 저장소에 있으면 묶이지 않는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 업계에서 컨텍스트 엔지니어링(context engineering)이라는 말이 쓰이기 시작했다. 프롬프트 한 줄을 다듬는 게 아니라 모델이 읽을 맥락 전체를 설계한다는 뜻이다. 내가 하는 일을 그 말로 부를 수 있다면, 그 설계의 첫 결정은 &quot;맥락을 어느 회사의 서버가 아니라 내 저장소에 둔다&quot; 였다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도구마다 다른 건 지침 파일 이름 하나다. 어떤 도구는 CLAUDE.md를 읽고 어떤 도구는 AGENTS.md를 읽는다. 내용은 한 곳에 두고 다른 이름의 파일은 그 파일을 가리키게 하면 된다. 이름이 무엇이든 첫 줄은 같아야 한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;시작하면 LATEST.md 부터 읽어라.&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;7. 마무리&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법의 핵심은 기술이 아니었다. 인공지능은 지난 대화를 기억하지 않는다는 것을 받아들이고, 기억을 내가 들고 다니기로 정한 것이다. 그러고 나니 대화가 끊기는 게 두렵지 않다. 70%가 되면 인수인계를 받고 새 대화를 연다. 모델이 바뀌어도 폴더는 그대로고, 노트북이 바뀌어도 clone 한 번이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미래의 나에게 적어 둔다. 기록을 건너뛰고 싶은 날이 온다. 바쁘고, 잘 되고 있고, 이건 기억하겠지 싶은 날이다. 그날이 9월 20일이었다. 기억하겠지 싶은 것은 기억나지 않는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대화는 끝난다. 맥락은 파일에 남는다.&amp;nbsp;&lt;/p&gt;</description>
      <category>tech</category>
      <category>AGENTS.md</category>
      <category>ChatGPT</category>
      <category>claude code</category>
      <category>claude.md</category>
      <category>context engineering</category>
      <category>Github 백업</category>
      <category>바이브코딩</category>
      <category>컨텍스트 유지</category>
      <category>프롬프트 기록</category>
      <category>핸드오프 프롬프트</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/3</guid>
      <comments>https://hsjo.tistory.com/3#entry3comment</comments>
      <pubDate>Wed, 7 Oct 2026 21:19:43 +0900</pubDate>
    </item>
    <item>
      <title>인공지능 친화적인 PRD 작성법, 앱 또는 웹 서비스 개발시 필수</title>
      <link>https://hsjo.tistory.com/2</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01_thumbnail.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pAfe4/dJMcaa8eJuE/e5i3akXjdVDjy5NKAYwtBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pAfe4/dJMcaa8eJuE/e5i3akXjdVDjy5NKAYwtBk/img.png&quot; data-alt=&quot;썸네일&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pAfe4/dJMcaa8eJuE/e5i3akXjdVDjy5NKAYwtBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpAfe4%2FdJMcaa8eJuE%2Fe5i3akXjdVDjy5NKAYwtBk%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;2400&quot; height=&quot;1260&quot; data-filename=&quot;01_thumbnail.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;썸네일&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론부터 말하면, 인공지능에게 코드를 맡길 때의 PRD(Product Requirements Document, 제품 요구사항 정의서)는 사람을 설득하는 문서가 아니라 기계가 참조하는 사양서다. 2025년에 아래 영상 처럼 PRD를 정리 했었고, 이 영상에서 언급한 26항목은 지금도 뼈대로 쓸 만하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=7_LX2e_-JNg&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/corAkm/dJMb82M0wrg/CGBskySK0c3K08SR9pGLAk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/bGEs1j/dJMb87gtUmv/AVI3fIvxCyzvCpgpjxqrAK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;바이브코딩 EP.02 - 인공지능 친화적 PRD 작성법 (협업의 문법) | iOS 앱 개발&amp;middot;출시 시리즈&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/7_LX2e_-JNg&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;다만 특정 모델에 묶인 &quot;최적화 블록&quot;은 빼고, 환경 명세, 작업 목록, 검증 방법, 미확정 질문, 변경 이력을 독립 항목으로 수정해서 고쳤다. 그리고 목차만으로는 아무것도 시작되지 않는다. 아이디어가 생겼을 때 어떤 순서로, 어떤 프롬프트로 인공지능에게 시키는지까지 적어야 다음에 또 쓸 수 있다. 그래서 이 글의 뒷 부분에는 내가 실제로 쓰는 프롬프트 전문을 그대로 붙였다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 바로 코딩하고 싶은 마음부터&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이디어가 생기면 손이 먼저 간다. 프로젝트를 만들고, 화면 하나 띄우고, &quot;이런 앱 만들어줘&quot;라고 시키고 싶다. 인공지능이 코드를 빨리 만들어주는 시대이니 더 그렇다. 빠르면 좋은 것 아닌가? 어차피 고치는 것도 인공지능이 하는데 일단 보고 나서 정하면 되는 것 아닌가? 솔직히 나도 매번 그렇게 생각한다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;그런데 인공지능은 막히지 않는다. 모르겠다고 멈추지도 않는다. 내가 기준을 주지 않으면 그럴듯한 코드로 빈칸을 채운다. 어떤 저장 방식을 쓸지, 에러를 어디서 처리할지, 유료 기능의 경계를 어디에 둘지 같은 결정을 기계가 대신 내린다. 문제는 그 결정이 매번 다르다는 것이다. 오늘 세션의 인공지능과 내일 세션의 인공지능은 다른 판단을 한다. 그렇게 쌓인 코드는 나중에 내가 설명할 수 없는 코드가 된다. 그건 개발이 아니라 부채다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;그래서 문서를 먼저 쓴다. 느려 보이지만 실제로는 방향을 고정하는 일이다. 모호한 문장 하나가 잘못된 코드 수백 줄이 된다는 말은 과장이 아니다. 나는 그 수백 줄을 지워 본 적이 있다. (지우는 것도 인공지능이 하긴 한다. 그래도 내 시간은 간다.)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 사람이 읽는 PRD와 인공지능이 읽는 PRD는 다르다&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PRD는 원래 사람을 설득하는 문서로 배운다. 왜 이걸 만드는지, 시장이 얼마나 큰지, 경쟁자가 누구인지, 돈은 어떻게 버는지가 앞에 온다. 나도 그런 PRD를 여러번 썼다. 투자자나 동료가 읽을 문서라면 그 순서가 맞다. 그런데 인공지능은 설득이 필요 없다. 시장 규모를 읽어도 코드가 달라지지 않는다. 인공지능에게 필요한 건 두 가지다. 모순 없는 결정과, 무엇이 끝인지 아는 기준. 그래서 나는 PRD를 두 종류로 나눠서 생각한다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;사람용 PRD는 &quot;왜&quot;를 설득한다. 문단으로 쓰고, 로드맵으로 끝나고, 검토자가 질문을 던진다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;인공지능용 PRD는 &quot;무엇을 어떻게&quot;를 참조하게 한다. 표와 ID와 목록으로 쓰고, 수용 기준과 작업 목록으로 끝난다. 질문은 검토자가 아니라 문서 안에 미리 적어 둔다. 인공지능이 모르는 것을 묻지 않고 정해 버리기 때문이다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;이 글은 두 번째 것만 다룬다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uygw2/dJMb9988aT6/iOPH2AKkx3hO7vLWG8KCz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uygw2/dJMb9988aT6/iOPH2AKkx3hO7vLWG8KCz1/img.png&quot; data-alt=&quot;사람용 vs 인공지능용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uygw2/dJMb9988aT6/iOPH2AKkx3hO7vLWG8KCz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fuygw2%2FdJMb9988aT6%2FiOPH2AKkx3hO7vLWG8KCz1%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;2400&quot; height=&quot;1260&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;사람용 vs 인공지능용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 2025년에 정리해 둔 26항목&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래가 내가 2025년에 정리해 두고 쓰던 목차다. GPT 기반으로 만든 것이라 24번에 &quot;GPT-5 최적화 블록&quot;이 들어 있다. 당시에는 이게 맞았다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;요약 (Executive Summary)&lt;/li&gt;
&lt;li&gt;문제 정의와 맥락 (Problem Statement &amp;amp; Context)&lt;/li&gt;
&lt;li&gt;목표∙비목표∙성공지표 (Goals, Non-Goals, Success Metrics)&lt;/li&gt;
&lt;li&gt;페르소나와 JTBD (Personas &amp;amp; Jobs To Be Done)&lt;/li&gt;
&lt;li&gt;주요 사용 사례와 사용자 스토리 (Top Use Cases &amp;amp; User Stories, Gherkin)&lt;/li&gt;
&lt;li&gt;범위와 우선순위 (Scope &amp;amp; Prioritization, MoSCow/RICE)&lt;/li&gt;
&lt;li&gt;앱 플로우와 정보 구조 (App Flow &amp;amp; Information Architecture)&lt;/li&gt;
&lt;li&gt;UI/UX 요구사항 (Tokens∙Components∙A11y∙Localization)&lt;/li&gt;
&lt;li&gt;플랫폼∙기술 결정과 에러 도메인 (Platform &amp;amp; Tech Decisions + Error Domain)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;데이터 모델 (Entities∙JSON∙Relationships/States)&lt;/li&gt;
&lt;li&gt;API 개요 (Auth∙Endpoints∙Errors∙Rate Limit)&lt;/li&gt;
&lt;li&gt;오프라인∙동기화∙캐싱 (Offline∙Sync∙Caching)&lt;/li&gt;
&lt;li&gt;보안∙개인정보∙컴플라이언스 (Security∙Privacy∙Compliance)&lt;/li&gt;
&lt;li&gt;성능 목표와 품질 기준 (Performance SLOs &amp;amp; Quality Bars)&lt;/li&gt;
&lt;li&gt;분석∙텔레메트리 (Analytics &amp;amp; Telemetry)&lt;/li&gt;
&lt;li&gt;알림∙인앱 메시징 (Notifications &amp;amp; In-App Messaging)&lt;/li&gt;
&lt;li&gt;수익화∙가격정책 (Monetization &amp;amp; Pricing)&lt;/li&gt;
&lt;li&gt;실험 (Experimentation, A/B∙Feature Flags)&lt;/li&gt;
&lt;li&gt;수용 기준과 테스트 계획 (Acceptance Criteria &amp;amp; Test Plan + Coverage Mapping)&lt;/li&gt;
&lt;li&gt;위험∙가정∙의존성 (Risks∙Assumptions∙Dependencies)&lt;/li&gt;
&lt;li&gt;출시 계획과 마일스톤 (Release Plan &amp;amp; Milestones)&lt;/li&gt;
&lt;li&gt;범위 외 항목 (Out of Scope)&lt;/li&gt;
&lt;li&gt;용어집 (Glossary)&lt;/li&gt;
&lt;li&gt;AI 프롬프트 엔벨로프 (AI Prompt Envelope, GPT-5 Optimized Block)&lt;/li&gt;
&lt;li&gt;핸드오프 템플릿 (Handoffs Templates)&lt;/li&gt;
&lt;li&gt;PRD 품질 체크리스트 (AI &amp;amp; Human)&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. 실제로 써 보니&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 목차로 PRD를 한 파일에 썼다. 그 문서를 &quot;요구사항의 유일한 원천&quot;으로 지정하고, 코드 생성 도구가 세션을 시작할 때마다 먼저 읽게 했고, 구현은 문서에 적힌 작업 번호 순서대로 한 번에 하나씩 시켰다. 그래서 26항목은 충분했을까? 절반은 그렇고 절반은 아니었다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;잘된 것은 분명했다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;작업을 T-01, T-02처럼 번호로 쪼개 놓으니 커밋 하나가 작업 하나가 됐다. &quot;앱 만들어줘&quot;가 아니라 &quot;T-04 거래 목록 화면&quot;처럼 시키면 인공지능도 범위를 넘지 않는다. 금지 목록도 효과가 컸다. 자체 서버 금지, 광고 금지, 외부 SDK 금지. 이 세 줄이 개발 내내 수십 번의 결정을 대신했다. 인공지능이 &quot;이 기능은 서버가 있으면 편한데요&quot;라고 제안할 때마다 문서가 대신 거절해 줬다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;에러 키를 아래 형식으로 미리 정해 둔 것도 좋았다. 화면마다 다른 에러 처리가 생기지 않았다.&lt;/p&gt;
&lt;pre class=&quot;swift&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;swift&quot;&gt;&lt;code&gt;error.{domain}.{reason}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;우연히 잘된 것도 하나 있다. 18번 실험 항목에 &quot;서버가 없으므로 A/B 테스트는 하지 않는다&quot;라고 한 줄 적어 두었다. 없는 기능을 없다고 쓴 그 한 줄이, 인공지능이 실험 코드를 멋대로 넣는 일을 막았다. 빈칸으로 두었다면 아마 그럴듯한 실험 프레임워크가 생겼을 것이다. (상상만 해도 지우고 싶다.)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;안 된 것도 있었다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;24번 항목 하나가 너무 커졌다. 코딩 규칙, 폴더 구조, 작업 순서, 금지 목록이 전부 그 안에 들어갔다. PRD에서 가장 긴 절이 &quot;무엇을 만들 것인가&quot;가 아니라 &quot;어떻게 만들 것인가&quot;였다. 미확정 질문 목록은 26번 체크리스트 끝에 붙어 있어서 눈에 잘 띄지 않았다. 빌드∙테스트 명령은 PRD에 없었다. 별도 문서에 두었더니 세션마다 두 문서를 함께 읽혀야 했다. 그리고 문서가 v0.1에서 멈췄다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;질문의 답이 나오고 결정이 바뀌었는데, 그 변화는 프롬프트 기록에만 쌓이고 PRD는 처음 그대로였다. 나중에 PRD를 다시 열었을 때 &quot;이게 지금도 맞는 말인가?&quot;를 매번 의심해야 했다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;정리하면 이렇다. 26항목은 &quot;무엇을 만들 것인가&quot;를 적는 데는 충분했다. 부족한 건 인공지능이 실제로 일할 때 매 세션 꺼내 보는 것들이었다. 명령, 작업 순서, 완료 기준, 아직 정하지 않은 것, 그리고 바뀐 것.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eqKXpZ/dJMcacLKH0w/prDAFvKeCatijPXgubiRN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eqKXpZ/dJMcacLKH0w/prDAFvKeCatijPXgubiRN1/img.png&quot; data-alt=&quot;26항목 판정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eqKXpZ/dJMcacLKH0w/prDAFvKeCatijPXgubiRN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeqKXpZ%2FdJMcacLKH0w%2FprDAFvKeCatijPXgubiRN1%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;2400&quot; height=&quot;1260&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;26항목 판정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5. 그래서 이렇게 고쳤다&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;26항목을 하나씩 다시 봤다. 판정은 다섯 가지였다. 그대로 둘 것, 조건부로 둘 것, 줄일 것, 합칠 것, 분해할 것.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;유지가 열여섯이다. 1, 3, 5, 6, 7, 8, 9, 10, 11, 13, 14, 19, 20, 23, 25, 26번은 그대로 둔다. 조건부가 다섯이다. 오프라인(12), 분석(15), 알림(16), 수익화(17), 실험(18)은 제품에 따라 없을 수 있는데, 없으면 비워 두지 말고 &quot;해당 없음&quot; 한 줄을 남긴다. 축소가 셋이다. 문제정의(2)는 세 문단이면 충분하고, 페르소나(4)는 두 명이면 되고, 출시계획(21)은 날짜가 없으면 단계만 적는다. 합침이 하나다. 범위 외(22)는 비목표(3)와 같은 말이라 3번으로 넣는다. 분해가 하나다. 프롬프트 엔벨로프(24)는 모델 종속 블록을 지우고, 규칙은 저장소 지침 파일로, 작업 순서는 새 항목으로 뺀다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;유지한 항목 중에도 강화한 것이 있다. 7번은 화면마다 ID(S-01, S-02)를 붙이고 상태 전이를 글로 쓴다. 9번의 에러 도메인 표는 그대로 두되 환경 명세를 밖으로 뺀다. 19번은 수용 기준마다 ID(AC-01)를 붙이고 작업(T-xx)과 짝을 맞춘다. 14번은 숫자로만 쓴다. &quot;빠르게&quot;는 금지다. &quot;첫 화면 1초 이내&quot;라고 써야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mQjXb/dJMcaiE6WNM/aOSfaz10i5rgMiszFPaqa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mQjXb/dJMcaiE6WNM/aOSfaz10i5rgMiszFPaqa0/img.png&quot; data-alt=&quot;2026년에 새로 넣은 다섯 항목&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mQjXb/dJMcaiE6WNM/aOSfaz10i5rgMiszFPaqa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmQjXb%2FdJMcaiE6WNM%2FaOSfaz10i5rgMiszFPaqa0%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;2400&quot; height=&quot;1260&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2026년에 새로 넣은 다섯 항목&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;그리고 다섯 항목을 새로 넣었다. 전부 내가 빠뜨려서 비용을 치른 것들이다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;환경 명세와 명령.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 언어와 런타임 버전, 최소 지원 OS, 패키지 관리자, 빌드∙테스트∙린트 명령. 명령이 문서에 없으면 인공지능이 추측한다. 추측은 매번 다르다. 어떤 날은 되고 어떤 날은 안되는 빌드는 대부분 여기서 나온다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;작업 목록(T-xx).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; T-01부터 순서대로. 각 작업에 어떤 기능(F-xx)을 만들고, 어떤 수용 기준(AC-xx)이 닫히는지, 커밋 단위가 무엇인지 적는다. 한 번에 한 작업, 커밋 하나가 작업 하나. 그냥 24번 안에 두면 안 되나? 처음에는 나도 그렇게 두었다. 그런데 인공지능은 문서의 절 번호로 작업을 찾는다. &quot;24.2절의 T-03&quot;보다 &quot;19절 T-03&quot;이 짧고, 짧은 참조는 세션이 바뀌어도 틀리지 않는다. 숨어 있을 때와 독립 항목일 때의 차이는 생각보다 크다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;검증 방법.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; &quot;끝났다&quot;를 증명하는 명령과 결과. 빌드 성공, 테스트 통과, 경고 0건, 화면 캡처. 완료를 선언하는 쪽이 인공지능이기 때문에, 기준을 문서에 두지 않으면 &quot;완료했습니다&quot;라는 말을 믿을 수밖에 없다. 나는 그 말을 믿었다가 경고 다섯 개를 나중에 직접 찾은 적이 있다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;미확정 질문과 기본값(Q-xx).&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; Q-01부터. 아직 내가 정하지 않은 것과, 답이 나올 때까지 쓸 임시 기본값을 같이 적는다. 기본값이 없으면 인공지능이 임의로 정한다. 기본값이 있으면 인공지능은 그 값을 쓰고 &quot;Q-03 확정 대기&quot;라는 주석을 남긴다. 솔직한 빈칸이 그럴듯한 가짜 확정보다 낫다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;변경 이력.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 버전, 날짜, 바뀐 절, 이유. v0.1을 v0.2로 올릴 때 무엇이 바뀌었는지 인공지능도 알아야 한다. 이게 없으면 문서는 첫날에 멈추고, 결정은 대화 기록 속으로 흩어진다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;마지막으로 한 가지를 문서 밖으로 뺐다. 코딩 규칙, 폴더 구조, 금지 목록은 PRD가 아니라 저장소의 지침 파일에 둔다. 도구마다 파일 이름이 다르다. 어떤 도구는 AGENTS.md를 읽고 어떤 도구는 CLAUDE.md를 읽는다. 이름이 무엇이든 그 파일 첫 줄에 &quot;요구사항의 유일한 원천은 PRD&quot;라고 적는다. PRD는 무엇을 만들지 맡고, 지침 파일은 어떻게 만들지를 맡는다. 쉽게 말하면 PRD는 설계도이고 지침 파일은 잔소리를 문서로 적어 둔 것이다. 잔소리는 매 세션 자동으로 읽히는 곳에 있어야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGSVcp/dJMcaaf2d29/kLOhuLxmuQwSR20pxxILR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGSVcp/dJMcaaf2d29/kLOhuLxmuQwSR20pxxILR0/img.png&quot; data-alt=&quot;설계도와 잔소리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGSVcp/dJMcaaf2d29/kLOhuLxmuQwSR20pxxILR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGSVcp%2FdJMcaaf2d29%2FkLOhuLxmuQwSR20pxxILR0%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;2400&quot; height=&quot;1260&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;설계도와 잔소리&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;6. 2026년판 AI-Ready PRD 26항목&lt;/b&gt;&lt;/h4&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;li&gt;페르소나와 JTBD&lt;/li&gt;
&lt;li&gt;사용 사례와 사용자 스토리 (Gherkin)&lt;/li&gt;
&lt;li&gt;범위와 우선순위 (P0∙P1∙P2)&lt;/li&gt;
&lt;li&gt;화면 ID∙맵플로우∙상태 전이&lt;/li&gt;
&lt;li&gt;UI/UX 요구사항 (토큰∙컴포넌트∙접근성∙현지화)&lt;/li&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;li&gt;오프라인∙동기화∙캐싱 (해당 없음 가능)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;보안∙개인정보∙심사 기준&lt;/li&gt;
&lt;li&gt;성능 목표와 품질 기준&lt;/li&gt;
&lt;li&gt;분석∙알림∙수익화∙실험 (각각 해당 여부 명시)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;수용 기준 (AC-xx)&lt;/li&gt;
&lt;li&gt;작업 목록 (T-xx)&amp;nbsp;&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;li&gt;미확정 질문과 기본값 (Q-xx)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;품질 체크리스트&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개수는 26개 그대로다. 바뀐 건 구성과 순서다. 수용 기준, 작업 목록, 검증 방법이 문서 뒤쪽에 나란히 선다. 인공지능이 가장 자주 읽는 세 절이 한 곳에 모여 있다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;7. 쓰는 방식도 정해 둔다&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차보다 중요한 것이 쓰는 방식이다. 내가 지키는 건 다섯 가지다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;한 파일에 둔다. 마크다운이 HTML보다 가볍고, 인공지능이 줄 단위로 참조하기 쉽다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;모든 것에 ID를 붙인다. 기능은 F, 화면은 S, 수용 기준은 AC, 작업은 T, 질문은 Q. 절은 번호로 부른다. &quot;PRD 19절 T-03&quot;이라고 말하면 인공지능과 내가 같은 곳을 본다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;그림 대신 글로 쓴다. 상태 전이는 표나 목록으로. 이미지 속 글자는 인공지능이 놓친다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;형용사를 숫자로 바꾼다. &quot;빠르게&quot;는 &quot;첫 화면 1초 이내&quot;로, &quot;안정적으로&quot;는 &quot;재실행 시 데이터 손실 0건&quot;으로.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;없는 것은 &quot;해당 없음&quot;이라고 쓴다. 빈칸은 빠뜨린 것과 구분되지 않는다. 인공지능은 빈칸을 채우는 쪽으로 움직인다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;8. 아이디어가 있을 때, 인공지능에게 이렇게 시킨다&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지가 문서 이야기다. 그런데 목차와 규칙만 있으면 다음 프로젝트에서 또 처음부터 고민한다. 프롬프트까지 글에 넣어야 하나 싶었다. 넣어야 한다. 다음 프로젝트를 시작하는 나는 오늘의 나보다 더 많이 잊어버린 상태일 것이고, 그때 필요한 건 원칙이 아니라 복사해서 중괄호만 채우면 되는 문장이기 때문이다. 내가 쓰는 순서는 일곱 단계다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nqdj8/dJMcab6151E/AuPk8TFa6eqtPlDusKMxQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nqdj8/dJMcab6151E/AuPk8TFa6eqtPlDusKMxQk/img.png&quot; data-alt=&quot;7단계 순서&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nqdj8/dJMcab6151E/AuPk8TFa6eqtPlDusKMxQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnqdj8%2FdJMcab6151E%2FAuPk8TFa6eqtPlDusKMxQk%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;2400&quot; height=&quot;1260&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;7단계 순서&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;제약을 먼저 적는다. 플랫폼, 투입 시간, 기간, 금지 사항, 수익 목표.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;아이디어 검증을 시킨다. 동의 편향 금지, 실패 시나리오 먼저.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;아이디어를 고르고, 내가 정할 것을 정한다. 이름, 가격, 최소 OS 같은 것.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;PRD 작성을 시킨다. 26개 절 전부, 추측 금지, 질문은 Q-xx로 모으게.&lt;/li&gt;
&lt;li&gt;질문에 답하고 v0.2로 올린다. 변경 이력에 적는다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;저장소 지침 파일을 만들게 한다. 규칙, 명령, 세션 규칙.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;첫 세션을 시작한다. 읽기&amp;rarr;계획&amp;rarr;승인&amp;rarr;T-01&amp;rarr;검증&amp;rarr;기록&amp;rarr;커밋.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 단계의 프롬프트는 아래와 같다. 중괄호 안은 내가 채우는 자리다. 태그 형식(, )은 어느 모델이든 구조를 잘 알아보기 때문에 쓴다. 특정 모델 이름은 넣지 않는다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;8-1. 아이디어 검증 프롬프트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인공지능에게 &quot;아이디어 좀 줘&quot;라고 하면 그럴듯한 쓰레기가 나온다. 제약과 거절 규칙을 먼저 넣어야 한다. 특히 &quot;이 아이디어가 실패하는 가장 유력한 시나리오&quot;를 먼저 쓰게 하는 규칙이 핵심이다. 이게 없으면 인공지능은 내 기분을 맞추는 쪽으로 간다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;&amp;lt;role&amp;gt;
당신은 앱 스토어와 서비스 시장의 수익 데이터에 근거해 판단하는 제품 분석가입니다.
임무는 나를 기분 좋게 만드는 것이 아니라 정확하게 판단하는 것입니다.
가능성이 낮은 아이디어를 그럴듯하게 포장하면 임무 실패입니다.
&amp;lt;/role&amp;gt;

&amp;lt;context&amp;gt;
- 개발자: 1인 개발, 본업 병행, 주당 약 {N}시간 투입
- 플랫폼: {iOS 전용 / 웹 / 둘 다}
- 기술: {예: SwiftUI + MVVM, async/await} / {예: React + Spring Boot}
- 코딩 방식: 에이전틱 코딩 도구가 PRD를 보고 구현. 기획&amp;middot;PRD도 인공지능과 함께 작성
- MVP 기간: {N}주 이내
- 수익 목표: 출시 후 {N}일 이내 월 {금액}
- 운영 원칙: 외부 SDK&amp;middot;서버 의존 최소화, 광고 모델 배제, 1인이 수년간 유지보수 가능한 구조
- 내가 이미 가진 아이디어: {있으면 한 줄, 없으면 &quot;없음&quot;}
&amp;lt;/context&amp;gt;

&amp;lt;task&amp;gt;
위 조건에서 수익 목표 달성 확률이 가장 높은 아이디어 TOP 5를 제시하세요.
PRD는 아직 작성하지 마세요. 아이디어를 검토한 뒤 별도로 요청합니다.
&amp;lt;/task&amp;gt;

&amp;lt;rules&amp;gt;
1. 동의 편향 금지: 각 아이디어마다 &quot;이 아이디어가 실패하는 가장 유력한 시나리오&quot;를
&amp;nbsp;&amp;nbsp; 먼저 쓰고, 그럼에도 살아남는 근거를 그 다음에 쓰세요.
2. 숫자 날조 금지: 수익 산식의 모든 가정(다운로드 수, 결제 전환율, 가격)을 명시하고,
&amp;nbsp;&amp;nbsp; 확인 불가한 수치는 &quot;추정&quot;이라고 표기하세요.
3. 웹 검색이 가능하면 경쟁 제품과 시장 근거를 검색해 확인하세요.
&amp;nbsp;&amp;nbsp; 불가능하면 학습 데이터 기준임을 명시하세요.
4. 경쟁 존재 = 시장 존재입니다. 경쟁 강도와 차별화 가능성을 분리해서 평가하고,
&amp;nbsp;&amp;nbsp; &quot;경쟁이 많아서 탈락&quot; 같은 단순 판단은 금지합니다.
5. 1인 + {N}주 MVP로 불가능한 유형은 처음부터 제외하세요:
&amp;nbsp;&amp;nbsp; 실시간 서버 필수, 콘텐츠 대량 제작 필요, 네트워크 효과 의존, 법적 인허가 필요.
6. 평가 축에 &quot;이 제품의 핵심 가치를 개발자 본인이 판정할 수 있는가&quot;를 반드시 넣으세요.
&amp;nbsp;&amp;nbsp; 취향이 무기인 시장(디자인&amp;middot;감성&amp;middot;맛)과 공학이 무기인 시장(저장&amp;middot;계산&amp;middot;동기화)을 구분하세요.
7. 시작 전에 모호한 점이 있으면 최대 3개까지 먼저 질문하세요. 없으면 바로 진행하세요.
8. 확신이 없는 부분은 확신이 없다고 쓰세요.
&amp;lt;/rules&amp;gt;

&amp;lt;output_format&amp;gt;
각 아이디어를 다음 구조로:

## N. 제품 이름(가칭) &amp;mdash; 한 줄 가치 제안
- 타깃 사용자와 결제 순간: 누가, 어떤 순간에, 왜 돈을 내는가
- 수익 모델: 구독 / 일회성 결제 / 유료 앱 중 택1 + 가격
- 수익 산식: 필요 결제자 수 &amp;times; 객단가 (가정 명시)
- 경쟁 현황: 대표 제품 2~3개와 각각의 약점
- 실패 시나리오: 가장 유력한 것 1개
- 핵심 가치 판정 가능성: 개발자가 좋고 나쁨을 스스로 판단할 수 있는가 (상&amp;middot;중&amp;middot;하와 이유)
- MVP 범위: 핵심 기능 3개 이하
- 출시 후 {N}일 검증 지표: 무엇을 보고 계속/중단을 결정하는가

마지막에:
1. 5개 비교 표: 수익 가능성 / 개발 난이도 / 경쟁 강도 / 운영 부담 / 판정 가능성 (각 상&amp;middot;중&amp;middot;하)
2. 당신의 1순위 추천 + 핵심 근거 1개 + 반대 논거 1개
&amp;lt;/output_format&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;결과가 마음에 들지 않으면 퇴짜를 놓는다. 그때 이유를 한 줄이라도 적는다. &quot;돈은 될 것 같은데 만들고 싶지 않다&quot;, &quot;본업과 연결되는 걸로&quot;, &quot;수익 목표를 낮춰도 된다&quot;. 퇴짜의 이유가 쌓이면 어느 순간 인공지능이 평가 축 자체를 바꾼 제안을 들고 온다. 반려는 낭비가 아니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;8-2. 내가 정할 것을 먼저 정한다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이디어를 골랐으면 PRD를 시키기 전에 내가 결정할 것부터 적는다. 제품 이름, 가격, 최소 지원 OS, 1차 지원 언어, 무료와 유료의 경계, 출시 목표일. 전부 정하지 않아도 된다. 정하지 않은 것은 &quot;없음&quot;이라고 쓰면 인공지능이 Q-xx로 모아 온다. 중요한 건 내가 정할 것을 인공지능이 정하게 두지 않는 것이다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;8-3. PRD 작성 프롬프트&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;&amp;lt;role&amp;gt;
당신은 PRD 작성자입니다. 이 PRD의 독자는 사람이 아니라 코드 생성 도구입니다.
도구는 이 문서만 보고 코드를 생성하므로, 모호한 문장 하나가 잘못된 코드 수백 줄이 됩니다.
모든 문장은 구현 가능하고 테스트 가능해야 합니다.
&amp;lt;/role&amp;gt;

&amp;lt;input&amp;gt;
선택한 아이디어: {8-1 결과에서 고른 아이디어 전체 붙여넣기}
운영자가 이미 결정한 사항: {이름, 가격, 최소 OS, 언어, 출시일 등. 없으면 &quot;없음&quot;}
운영자가 절대 하지 않을 것: {예: 자체 서버, 광고, 외부 분석 SDK, 은행 연동}
&amp;lt;/input&amp;gt;

&amp;lt;guardrails&amp;gt;
구현 가드레일. PRD 전체와 생성 코드에 예외 없이 적용:
1. 아키텍처: {예: SwiftUI + MVVM (View &amp;harr; ViewModel &amp;harr; UseCase/Repository &amp;harr; Service)}
2. 동시성: {예: async/await만 사용, completion handler 금지}
3. 에러: 단일 에러 타입, 키는 error.{domain}.{reason} 형식
4. 현지화: 사용자 노출 문자열은 전부 키로 작성, 코드 안 직접 문자열 금지
5. 주석: 파일&amp;middot;함수 단위로 무엇/왜/원리까지. 처음 보는 사람도 이해 가능하게
6. 테스트: 모든 ViewModel(또는 서비스)에 최소 1개의 자동 테스트
7. 외부 라이브러리: 기본 0개. 추가는 운영자 사전 승인
8. 돈&amp;middot;날짜&amp;middot;수량 계산은 부동소수점 금지 (Decimal 또는 정수)
&amp;lt;/guardrails&amp;gt;

&amp;lt;structure&amp;gt;
아래 26개 절을 모두 작성하세요. 절 번호를 바꾸지 마세요.
1. 변경 이력 (v0.1, 오늘 날짜, &quot;최초 작성&quot;)
2. 요약
3. 문제 정의와 맥락 (세 문단 이내, 시장 자료 없음)
4. 목표&amp;middot;비목표&amp;middot;성공 지표 (범위 외 항목 포함)
5. 페르소나와 JTBD (두 명, 가상 이름)
6. 사용 사례와 사용자 스토리 (Gherkin: Given/When/Then)
7. 범위와 우선순위 (P0&amp;middot;P1&amp;middot;P2, 기능마다 F-xx ID)
8. 화면 ID 맵(S-xx)&amp;middot;플로우&amp;middot;상태 전이 (글과 표로, 그림 없음)
9. UI/UX 요구사항 (디자인 토큰 값, 컴포넌트 사전, 접근성, 현지화 키 규칙)
10. 플랫폼&amp;middot;기술 결정과 에러 도메인 표 (에러 키 / 발생 지점 / 사용자 메시지 키 / 복구 동작)
11. 환경 명세와 명령 (언어&amp;middot;런타임 버전, 최소 OS, 패키지 관리자, 빌드&amp;middot;테스트&amp;middot;린트 명령 전문)
12. 데이터 모델 (엔티티, JSON 예시, 관계와 상태)
13. API 개요 (서버 없으면 &quot;해당 없음&quot; + 로컬 데이터 흐름)
14. 오프라인&amp;middot;동기화&amp;middot;캐싱 (해당 없으면 &quot;해당 없음&quot;과 이유 한 줄)
15. 보안&amp;middot;개인정보&amp;middot;심사 기준 (스토어 심사 항목, 권한 요청 문구)
16. 성능 목표와 품질 기준 (전부 숫자. 형용사 금지)
17. 분석&amp;middot;알림&amp;middot;수익화&amp;middot;실험 (네 가지 각각 해당 여부를 먼저 쓰고, 해당하면 상세)
18. 수용 기준 (AC-xx. 전부 관측 가능한 결과로)
19. 작업 목록 (T-xx. 순서대로. 각 작업: 기능 ID / 내용 / 닫히는 AC / 커밋 메시지 초안)
20. 검증 방법 (완료 선언 조건: 빌드&amp;middot;테스트&amp;middot;경고 0건&amp;middot;캡처. 명령 전문)
21. 위험&amp;middot;가정&amp;middot;의존성 (가정은 &quot;확정 전 기본값&quot;으로 명시)
22. 출시 단계 (날짜 없으면 단계만)
23. 용어집
24. 핸드오프 템플릿 (기능 스펙 / 플로우 / 구현 계획 세 가지)
25. 미확정 질문과 기본값 (Q-xx. 질문 / 영향 범위 / 확정 전 기본값)
26. 품질 체크리스트 자체 검증 결과
&amp;lt;/structure&amp;gt;

&amp;lt;rules&amp;gt;
1. 모든 절: 짧은 문장 + 표 + (해당 시) JSON 예시. 설명 문단은 세 문장 이내.
2. 추측 금지: 운영자 결정이 필요한 항목은 본문에 [확인 필요: Q-xx]로 표기하고,
&amp;nbsp;&amp;nbsp; 25절에 모으세요. 임의로 채우지 마세요. 단, 확정 전 기본값은 반드시 제안하세요.
3. 수용 기준은 전부 테스트 가능한 문장으로. &quot;오프라인 저장 후 재실행 시 데이터가 남아 있다&quot; 수준.
4. 에러는 전부 키로 통일합니다.
5. 없는 것은 &quot;해당 없음&quot;이라고 쓰세요. 빈 절을 남기지 마세요.
6. 작성 완료 후 26절에서 아래 체크리스트를 스스로 적용해 항목별 통과/미통과를 표로 보고하고,
&amp;nbsp;&amp;nbsp; 미통과 항목은 수정 후 다시 보고하세요.
&amp;nbsp;&amp;nbsp; 체크리스트: 모순 지시 없음 / 8~12절 누락 없음 / 모든 사용자 텍스트가 키로 명시 /
&amp;nbsp;&amp;nbsp; 에러 도메인 표 존재 / 핵심 엔티티 상태 전이 정의 / 수용 기준 테스트 가능 /
&amp;nbsp;&amp;nbsp; AC와 T가 1:1 이상 연결 / 11절 명령이 실제 실행 가능한 형태 / 25절 질문마다 기본값 존재
7. 구현 지시, 코딩 규칙, 폴더 구조는 이 문서에 넣지 마세요. 그것은 별도의 저장소 지침 파일이 맡습니다.
&amp;lt;/rules&amp;gt;

&amp;lt;output&amp;gt;
PRD 전문을 마크다운 한 파일로 작성하세요. 파일명: PRD_{제품이름}_v0.1.md
&amp;lt;/output&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;결과를 읽고 25절의 질문에 답한다. 답을 주면서 &quot;v0.2로 올리고 1절 변경 이력에 무엇이 바뀌었는지 적어라&quot;고 시킨다. 이 한 줄이 문서가 첫날에 멈추는 것을 막는다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;8-4. 저장소 지침 파일 프롬프트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PRD가 끝나면 &quot;어떻게 만들 것인가&quot;를 저장소 지침 파일로 뺀다. 도구가 읽는 파일 이름을 확인해서 그 이름으로 만들게 한다.&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;&amp;lt;task&amp;gt;
PRD_{제품이름}_v0.2.md를 정독한 뒤, 코드 생성 도구가 매 세션 자동으로 읽는 저장소 지침 파일
{AGENTS.md 또는 CLAUDE.md}의 초안을 작성하세요.
&amp;lt;/task&amp;gt;

&amp;lt;must_include&amp;gt;
1. 첫 줄: &quot;요구사항의 유일한 원천은 PRD_{제품이름}_v0.2.md. 세션 시작 시 정독.&quot;
2. 제품 원칙 (PRD 4절 비목표와 금지 사항을 &quot;~하지 않는다&quot; 문장으로)
3. 아키텍처와 폴더 구조 (실제 디스크 경로 기준)
4. 빌드&amp;middot;테스트&amp;middot;린트 명령 (PRD 11절 전문 그대로)
5. 코드 규칙 (가드레일 전문)
6. 현지화 키 규칙, 에러 키 규칙
7. 테스트 규칙 (파일 생성 시점, 이름 규칙)
8. 커밋 규칙: {type}: {요약}. 한 커밋 = PRD 19절의 T-xx 하나
9. 미확정 질문 처리: Q-xx에 의존하는 코드에 도달하면 운영자에게 질문하고,
&amp;nbsp;&amp;nbsp; 답변 전에는 PRD 25절의 기본값 + &quot;// TODO(Q-xx): 운영자 확정 대기&quot; 주석으로만 처리. 임의 확정 금지
10. 세션 규칙
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 규칙 1: 모든 작업은 prompt/{4자리번호}_{YYYY-MM-DD}_{주제}.md 로 기록 (메타 / 프롬프트 전문 / 응답 핵심 / 결과 / 메모)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 규칙 2: 한 작업 완료 조건 = 빌드 성공 + 해당 테스트 통과 + AC 충족 + 경고 0건. 충족 시 커밋&amp;middot;푸시. 미충족 시 커밋 금지하고 이유 보고
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 규칙 3: 한 세션 = 한 작업(T-xx). 끝내지 못한 채 다음 T로 진입 금지. 종료 시 완료한 T / 커밋 해시 / 다음 시작점 / 미해결 질문 보고
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 규칙 4: 운영자가 이해하지 못했다고 말한 코드는 커밋하지 않는다
&amp;lt;/must_include&amp;gt;

&amp;lt;rules&amp;gt;
- &quot;잊지 말 것&quot;, &quot;주의할 것&quot; 같은 당부 대신 규칙 자체를 쓰세요. 이 파일은 매 세션 자동 로딩됩니다.
- PRD와 충돌하는 내용이 있으면 쓰지 말고 운영자에게 질문하세요.
&amp;lt;/rules&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;8-5. 첫 세션 착수 프롬프트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장소를 만들고, PRD와 지침 파일을 넣고, 첫 세션을 시작한다. 여기서 핵심은 &quot;승인 후에만 파일을 만든다&quot;는 한 줄이다. 인공지능은 실행 도구이고 결정권은 나에게 있다. 저장소의 주인은 나다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;&amp;lt;role&amp;gt;
당신은 {제품이름}의 유일한 구현 엔지니어입니다.
운영자는 본업 병행 1인 개발자이며, 결정 권한은 운영자에게 있고 당신은 실행 도구입니다.
운영자가 읽고 이해하지 못하는 코드는 존재해서는 안 됩니다.
&amp;lt;/role&amp;gt;

&amp;lt;source_of_truth&amp;gt;
PRD_{제품이름}_v0.2.md가 유일한 요구사항 원천입니다. 시작 전 전체를 정독하세요.
PRD와 충돌하는 구현 판단이 필요하면 임의로 결정하지 말고 운영자에게 질문하세요.
PRD 25절의 Q-xx는 미해결입니다. 해당 항목에 의존하는 코드에 도달하면
① 운영자에게 질문하고 ② 답변 전에는 기본값 + &quot;// TODO(Q-xx): 운영자 확정 대기&quot; 주석으로만 처리하세요.
&amp;lt;/source_of_truth&amp;gt;

&amp;lt;first_session_tasks&amp;gt;
이번 세션에서 아래를 순서대로 수행하세요.
1. {AGENTS.md 또는 CLAUDE.md}, PRD, prompt/README.md를 읽는다
2. 현재 저장소 구조를 확인한다
3. PRD 19절의 T-01을 위해 어떤 파일을 만들거나 바꿀지 계획을 먼저 보고한다
4. 운영자 승인 후에만 파일을 생성하거나 수정한다
5. PRD 11절의 명령으로 빌드와 테스트를 실행한다
6. PRD 20절의 검증 방법대로 결과를 보고한다 (빌드 / 테스트 / 경고 0건 / 캡처)
7. prompt/0001_{오늘날짜}_t-01-{주제}.md 기록을 남긴다
8. 완료 조건을 충족하면 커밋하고 푸시한 뒤 해시를 보고한다
9. 다음 세션 시작점(T-02)과 미해결 질문을 보고한다
&amp;lt;/first_session_tasks&amp;gt;

&amp;lt;report_format&amp;gt;
생성&amp;middot;변경 파일 트리 + 각 파일 1줄 설명 + 검증 결과 + 커밋 해시
&amp;lt;/report_format&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bX8cA7/dJMcaa8eH4Z/kMu8iJOrCmqT7XtpLrm1L0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bX8cA7/dJMcaa8eH4Z/kMu8iJOrCmqT7XtpLrm1L0/img.png&quot; data-alt=&quot;세션 루프&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bX8cA7/dJMcaa8eH4Z/kMu8iJOrCmqT7XtpLrm1L0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbX8cA7%2FdJMcaa8eH4Z%2FkMu8iJOrCmqT7XtpLrm1L0%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;2400&quot; height=&quot;1260&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;세션 루프&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;8-6. 이후 세션 프롬프트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 세션부터는 짧다. 규칙은 이미 지침 파일에 있기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;세션 시작. {AGENTS.md 또는 CLAUDE.md}와 prompt/README.md의 규칙 적용을 확인하고,
PRD 19절 기준 다음 작업(T-xx)을 한 작업 단위로 실행하세요.
계획을 먼저 보고하고, 승인 후 진행합니다.
완료 시 20절 검증 방법으로 결과를 보고하고, 기록&amp;middot;커밋&amp;middot;푸시 후 해시와 다음 시작점을 보고하세요.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;작업이 몇 개 진행되고 나서 리듬이 잡히면 &quot;앞으로 T-05부터 T-10까지 승인 없이 진행하라&quot;고 범위를 넓혀도 된다. 다만 커밋 금지 조건(빌드 실패, 테스트 실패, 내가 이해 못 한 코드)은 그대로 둔다. 속도를 올리는 건 규칙을 없애는게 아니라 승인 단위를 키우는 것이다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;9. 마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서를 먼저 쓰면 느릴 것 같다. 그런데 실제로 해 보면 PRD를 쓴 날 바로 뼈대 작업이 시작되고, 문서가 결정을 대신하기 때문에 인공지능은 묻지 않고 만들고, 나는 확인만 하면 된다. 느린 건 문서가 아니다. 문서 없이 쌓인 코드를 나중에 다시 읽고, 왜 이렇게 됐는지 추적하고, 결국 지우는 시간이 느리다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;목차를 고친 건 작은 변화다. 더 큰 변화는 프롬프트를 글로 남겼다는 것이다. 다음 아이디어가 떠오르면 나는 이 글의 8절을 열어서 중괄호를 채우기만 하면 된다. 이 글은 남에게 설명하는 글이기도 하지만, 그보다 먼저 다음 프로젝트를 시작할 나를 위한 기록이다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;인공지능은 모르는 것을 묻지 않고 정한다. 그래서 묻기 전에 적어 둔다. 바뀌는 것이 생기면 이 글의 변경 이력에 적겠다.&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&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;2026-10-05 v1 첫 발행&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>tech</category>
      <category>AGENTS.md</category>
      <category>AI-Ready PRD</category>
      <category>AI코딩</category>
      <category>PRD</category>
      <category>Spec-Driven Development</category>
      <category>바이브코딩</category>
      <category>스펙주도개발</category>
      <category>앱개발</category>
      <category>요구사항문서</category>
      <category>인공지능 PRD</category>
      <author>조현성</author>
      <guid isPermaLink="true">https://hsjo.tistory.com/2</guid>
      <comments>https://hsjo.tistory.com/2#entry2comment</comments>
      <pubDate>Tue, 6 Oct 2026 03:44:37 +0900</pubDate>
    </item>
  </channel>
</rss>