<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>resultofeffort</title>
    <link>https://resultofeffort.tistory.com/</link>
    <description>이건 첫 번째 레슨, 업무에서 마주친 문제 해결 경험 공유하기
이건 두 번째 레슨, 개인적으로 공부한 데이터/AI 지식을 기록하기
이건 세 번째 레슨, 다른 사람과 비교하지 말고 오직 어제의 나와 비교하기</description>
    <language>ko</language>
    <pubDate>Tue, 11 Aug 2026 23:29:42 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>ISFP의 블로그</managingEditor>
    <image>
      <title>resultofeffort</title>
      <url>https://tistory1.daumcdn.net/tistory/5265550/attach/9d98f8b6a454426e989780f51e6b438b</url>
      <link>https://resultofeffort.tistory.com</link>
    </image>
    <item>
      <title>공모전 사이트 17곳 총정리</title>
      <link>https://resultofeffort.tistory.com/157</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 링커리어&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://linkareer.com/&quot;&gt;https://linkareer.com/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링커리어는 대학생과 취업 준비생을 위한 공모전&amp;middot;대외활동&amp;middot;교육&amp;middot;인턴&amp;middot;채용 정보 플랫폼입니다. 공모전 메뉴가 별도로 마련되어 있어 아이디어, 마케팅, 디자인, 영상, IT 등 다양한 분야의 모집 공고를 찾아볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공고를 저장하거나 마감 일정을 확인할 수 있으며, 커뮤니티에서는 공모전 팀원 모집과 참가 관련 질문도 살펴볼 수 있습니다. 공모전 경험을 인턴이나 취업 준비와 연결하고 싶은 대학생에게 특히 유용합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 온오프믹스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://www.onoffmix.com/&quot;&gt;https://www.onoffmix.com/&lt;/a&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;전통적인 공모전뿐만 아니라 해커톤, 창업 경진대회, 아이디어 대회, 개발자 행사와 지원사업도 찾아볼 수 있습니다. IT&amp;middot;스타트업 분야의 공모전이나 오프라인 행사를 함께 찾는 사람에게 잘 맞습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 요즘것들&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://www.allforyoung.com/&quot;&gt;https://www.allforyoung.com/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘것들은 대학생과 청년을 위한 공모전, 대외활동, 교육, 인턴, 취업 및 청년정책 정보를 소개하는 플랫폼입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공모전뿐 아니라 서포터즈, 기자단, 봉사활동, 청년 지원사업 등을 함께 찾을 수 있어 대학생활에 필요한 활동 정보를 폭넓게 확인하기 좋습니다. 여러 종류의 대외활동을 비교하면서 자신에게 맞는 경험을 찾고 싶은 사람에게 추천할 만합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 스펙토리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://www.spectory.net/&quot;&gt;https://www.spectory.net/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스펙토리는 공모전, 대외활동, 공모사업 정보를 제공하는 전문 플랫폼입니다. 참가자를 위한 공고 정보뿐 아니라 공모전을 개최하는 기관을 위한 접수&amp;middot;심사&amp;middot;운영 시스템도 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기업이나 공공기관이 스펙토리를 통해 별도의 공모전 홈페이지를 운영하는 경우가 있어, 작품을 실제로 제출하는 과정에서도 자주 접할 수 있습니다. 지원 전에는 제출 형식, 파일 용량, 저작권 조건을 자세히 확인하는 것이 좋습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 캠퍼즈&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;http://www.campuz.net/&quot;&gt;http://www.campuz.net/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캠퍼즈는 대학생을 대상으로 공모전, 대외활동, 서포터즈, 봉사단과 체험단 정보를 제공해 온 사이트입니다. 대학생에게 필요한 교외활동 정보를 한곳에서 찾아보는 용도로 활용되어 왔습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 현재는 접속 환경에 따라 홈페이지 내용이 정상적으로 표시되지 않을 수 있습니다. 캠퍼즈에서 공고 제목을 확인했다면 공모전명이나 주최 기관명을 다시 검색해 최신 공식 공고가 있는지 확인하는 것이 안전합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 코워커&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://www.co-worker.co.kr/&quot;&gt;https://www.co-worker.co.kr/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코워커는 공모전과 공모사업, 채용 및 기관 정보를 함께 제공하는 지식정보&amp;middot;채용 플랫폼입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공모전뿐 아니라 정부기관, 공공기관, 재단, 협회 등이 운영하는 지원사업과 채용 정보도 함께 살펴볼 수 있습니다. 공공기관 공모전이나 정책 아이디어 공모, 사업 지원 프로그램을 찾는 사람에게 유용합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 씽유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://thinkyou.co.kr/&quot;&gt;https://thinkyou.co.kr/&lt;/a&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;middot;마케팅, 디자인, 사진, 영상, 문학, 학술, IT&amp;middot;소프트웨어 등 여러 분야의 공모전을 찾아볼 수 있습니다. 모집 기간과 참가 대상, 주최 기관, 접수 방법이 공고별로 정리되어 있어 관심 분야의 공모전을 비교하기 좋습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 에이이노브&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://ainnov.co.kr/&quot;&gt;https://ainnov.co.kr/&lt;/a&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;middot;아이디어, 사업&amp;middot;창업, IT&amp;middot;게임, 디자인, 영상, 논문&amp;middot;학술 등 관심 분야에 따라 공고를 찾아볼 수 있습니다. 공모전 상세 페이지에서 주요 일정과 참가 자격을 먼저 확인한 뒤 공식 접수 홈페이지로 이동하는 방식으로 활용하면 편리합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. 올콘&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://www.all-con.co.kr/&quot;&gt;https://www.all-con.co.kr/&lt;/a&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;middot;아이디어&amp;middot;마케팅, 디자인&amp;middot;그림&amp;middot;웹툰, 문학&amp;middot;학술, 과학&amp;middot;공학, 사진&amp;middot;영상 등 분야별 공모전을 확인할 수 있습니다. 참가 대상에 따라 공고를 구분해 볼 수 있어 자신이 지원할 수 있는 대회를 찾기 편리합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10. 콘테스트코리아&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://www.contestkorea.com/&quot;&gt;https://www.contestkorea.com/&lt;/a&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;middot;IT, 스포츠, 미술&amp;middot;디자인&amp;middot;웹툰, 음악, 사진&amp;middot;영상, 아이디어&amp;middot;창업 등 분야가 세분되어 있습니다. 참가 대상, 지역, 주최 기관, 상금과 특전 등의 조건을 설정해 공모전을 검색할 수 있다는 점이 특징입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;11. 공모전알고&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://www.contestalgo.com/&quot;&gt;https://www.contestalgo.com/&lt;/a&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;전체 공모전 목록뿐 아니라 인기 공모전과 주최사별 공고를 확인할 수 있습니다. 제공받은 링크가 기업회원 관리 페이지나 공모전 등록 페이지라면, 참가자는 위 대표 URL로 접속해 공모전 목록을 찾아보는 것이 편리합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;12. 씽굿&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://www.thinkcontest.com/&quot;&gt;https://www.thinkcontest.com/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;씽굿은 공모전 정보를 전문적으로 제공하는 공모전 미디어 플랫폼입니다. 공모전, 대외활동, 교육&amp;middot;강연 등의 모집 정보를 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공고 검색뿐 아니라 공모전 전략, 수상자 인터뷰, 수상작 갤러리와 가이드 콘텐츠를 함께 살펴볼 수 있다는 점이 장점입니다. 처음 공모전에 도전한다면 비슷한 분야의 기존 수상작을 참고해 작품의 구성과 표현 방식을 분석해 보는 것도 좋습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;13. 슈퍼투데이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://www.suto.co.kr/&quot;&gt;https://www.suto.co.kr/&lt;/a&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;아이디어나 디자인 작품을 제출하는 일반적인 공모전보다는 SNS 참여 이벤트, 설문 이벤트, 퀴즈, 체험단과 경품 행사를 찾을 때 더욱 유용합니다. 응모 현황을 관리하거나 다른 이용자의 당첨 후기를 확인하는 용도로도 활용할 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;14. 스펙업&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://cafe.naver.com/specup&quot;&gt;https://cafe.naver.com/specup&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스펙업은 대학생과 취업 준비생이 이용하는 네이버 카페입니다. 공모전, 대외활동, 인턴, 봉사활동과 취업 준비 정보를 함께 찾아볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카페 게시판과 내부 검색 기능을 이용해 관심 분야의 공모전을 찾을 수 있으며, 팀 단위 공모전에 함께 참가할 팀원을 모집할 때도 활용할 수 있습니다. 공모전과 취업 준비를 동시에 진행하는 대학생에게 잘 맞는 커뮤니티입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;15. 독취사&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://cafe.naver.com/dokchi&quot;&gt;https://cafe.naver.com/dokchi&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;독취사는 &amp;lsquo;독하게 취업하는 사람들&amp;rsquo;이라는 이름의 취업 준비 네이버 카페입니다. 대기업&amp;middot;공기업 채용, 인턴, 자기소개서, 면접과 자격증 정보뿐 아니라 공모전 및 대외활동 정보도 공유됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기업이나 기관이 운영하는 서포터즈, 기자단, 마케팅 대외활동과 공모전을 취업 정보와 함께 찾고 싶을 때 유용합니다. 특정 게시글 링크보다는 카페 대표 페이지로 들어가 공모전&amp;middot;대외활동 관련 게시판을 확인하는 것이 편리합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;16. 뎁스노트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://devsnote.com/p/seminar&quot;&gt;https://devsnote.com/p/seminar&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뎁스노트는 개발자와 IT 종사자를 위한 커뮤니티입니다. 제공한 대표 URL은 모집&amp;middot;홍보 영역의 세미나&amp;middot;이벤트&amp;middot;공모전 게시판으로 바로 연결됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI, 소프트웨어, 데이터, 정보보안, 오픈소스 분야의 경진대회와 해커톤을 찾는 사람에게 유용합니다. 일반 공모전 사이트에서 찾기 어려운 개발자 교육이나 기술 세미나 정보도 함께 확인할 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;17. PyTorchKR 행사&amp;middot;이벤트 홍보 게시판&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대표 URL:&lt;/b&gt; &lt;a href=&quot;https://discuss.pytorch.kr/c/promotion/12&quot;&gt;https://discuss.pytorch.kr/c/promotion/12&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PyTorchKR 행사&amp;middot;이벤트 홍보 게시판은 파이토치 한국 사용자 모임 커뮤니티에서 운영하는 홍보 공간입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI&amp;middot;머신러닝 경진대회, 데이터 분석 대회, 해커톤, 개발자 컨퍼런스, 교육과 부트캠프 정보를 찾을 때 유용합니다. 게시글은 외부 기관이 직접 홍보하는 경우가 있으므로 참가 일정과 규칙, 접수 주소는 연결된 공식 홈페이지에서 다시 확인하는 것이 좋습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;사이트 선택 방법&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;종합적인 공모전 정보를 찾는다면 링커리어, 씽유, 올콘, 콘테스트코리아와 씽굿을 먼저 확인해 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대학생 대외활동과 취업 정보를 함께 찾는다면 요즘것들, 스펙업과 독취사가 유용하며, AI&amp;middot;개발 분야에 관심이 있다면 뎁스노트와 PyTorchKR 행사&amp;middot;이벤트 홍보 게시판을 함께 확인하는 것이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 사이트에만 의존하기보다는 관심 분야에 맞는 사이트 두세 곳을 정해 주기적으로 확인하세요. 지원할 공모전을 발견했다면 마지막에는 반드시 주최 기관의 공식 공고에서 모집 기간, 참가 자격, 제출 형식과 저작권 조건을 확인해야 합니다.&lt;/p&gt;</description>
      <category>공모전</category>
      <category>공모전모음</category>
      <category>공모전정보</category>
      <category>공모전추천</category>
      <category>대외활동</category>
      <category>대외활동사이트</category>
      <category>대학생공모전</category>
      <category>아이디어공모전</category>
      <category>취업준비</category>
      <category>해커톤</category>
      <author>ISFP의 블로그</author>
      <guid isPermaLink="true">https://resultofeffort.tistory.com/157</guid>
      <comments>https://resultofeffort.tistory.com/157#entry157comment</comments>
      <pubDate>Fri, 31 Jul 2026 11:31:20 +0900</pubDate>
    </item>
    <item>
      <title>거버넌스</title>
      <link>https://resultofeffort.tistory.com/155</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1단계&amp;nbsp;&amp;mdash;&amp;nbsp;데이터베이스&amp;nbsp;기초&amp;nbsp;(토대)&lt;br /&gt;&lt;br /&gt;먼저&amp;nbsp;&quot;데이터를&amp;nbsp;표로&amp;nbsp;저장한다&quot;는&amp;nbsp;감을&amp;nbsp;잡아야&amp;nbsp;나머지가&amp;nbsp;이해돼요.&lt;br /&gt;-&amp;nbsp;테이블&amp;nbsp;/&amp;nbsp;행(row)&amp;nbsp;/&amp;nbsp;컬럼(column):&amp;nbsp;데이터를&amp;nbsp;담는&amp;nbsp;표의&amp;nbsp;구조&lt;br /&gt;-&amp;nbsp;기본키(Primary&amp;nbsp;Key):&amp;nbsp;각&amp;nbsp;행을&amp;nbsp;구분하는&amp;nbsp;고유&amp;nbsp;값&amp;nbsp;(예:&amp;nbsp;user_id)&lt;br /&gt;-&amp;nbsp;외래키(Foreign&amp;nbsp;Key):&amp;nbsp;다른&amp;nbsp;표와&amp;nbsp;연결하는&amp;nbsp;키&amp;nbsp;(예:&amp;nbsp;학습기록의&amp;nbsp;user_id&amp;nbsp;&amp;rarr;&amp;nbsp;사용자&amp;nbsp;표)&lt;br /&gt;-&amp;nbsp;데이터&amp;nbsp;타입:&amp;nbsp;문자(VARCHAR)&amp;middot;숫자(INT)&amp;middot;날짜(DATE)&amp;nbsp;등&lt;br /&gt;-&amp;nbsp; &amp;nbsp;목표:&amp;nbsp;&quot;테이블끼리&amp;nbsp;키로&amp;nbsp;연결된다&quot;를&amp;nbsp;이해&lt;br /&gt;&lt;br /&gt;2단계&amp;nbsp;&amp;mdash;&amp;nbsp;데이터&amp;nbsp;모델링&amp;nbsp;&amp;amp;&amp;nbsp;ERD&lt;br /&gt;&lt;br /&gt;&quot;어떤&amp;nbsp;테이블을&amp;nbsp;만들고&amp;nbsp;어떻게&amp;nbsp;연결할지&amp;nbsp;설계&quot;하는&amp;nbsp;단계.&lt;br /&gt;-&amp;nbsp;ERD&amp;nbsp;(Entity&amp;nbsp;Relationship&amp;nbsp;Diagram):&amp;nbsp;테이블(엔티티)과&amp;nbsp;관계를&amp;nbsp;그림으로&amp;nbsp;표현&lt;br /&gt;-&amp;nbsp;관계&amp;nbsp;종류:&amp;nbsp;1:1,&amp;nbsp;1:N,&amp;nbsp;N:M&amp;nbsp;(예:&amp;nbsp;트랙&amp;nbsp;1개&amp;nbsp;&amp;harr;&amp;nbsp;콘텐츠&amp;nbsp;여러&amp;nbsp;개&amp;nbsp;=&amp;nbsp;1:N)&lt;br /&gt;-&amp;nbsp;정규화(Normalization):&amp;nbsp;중복&amp;nbsp;없이&amp;nbsp;데이터를&amp;nbsp;나누는&amp;nbsp;원칙&amp;nbsp;(1NF&amp;middot;2NF&amp;middot;3NF,&amp;nbsp;개념만)&lt;br /&gt;-&amp;nbsp; &amp;nbsp;목표:&amp;nbsp;간단한&amp;nbsp;서비스(사용자&amp;middot;콘텐츠&amp;middot;구독)를&amp;nbsp;ERD로&amp;nbsp;그려볼&amp;nbsp;수&amp;nbsp;있기&lt;br /&gt;&lt;br /&gt;3단계&amp;nbsp;&amp;mdash;&amp;nbsp;택소노미&amp;nbsp;(분류&amp;nbsp;체계)&lt;br /&gt;&lt;br /&gt;콘텐츠&amp;middot;데이터를&amp;nbsp;&quot;어떤&amp;nbsp;기준으로&amp;nbsp;분류할지&quot;&amp;nbsp;정하는&amp;nbsp;것.&lt;br /&gt;-&amp;nbsp;택소노미&amp;nbsp;vs&amp;nbsp;온톨로지&amp;nbsp;차이(택소노미는&amp;nbsp;계층적&amp;nbsp;분류,&amp;nbsp;온톨로지는&amp;nbsp;관계까지)&lt;br /&gt;-&amp;nbsp;분류&amp;nbsp;축(facet)&amp;nbsp;설계:&amp;nbsp;난이도&amp;nbsp;/&amp;nbsp;주제&amp;nbsp;/&amp;nbsp;유형처럼&amp;nbsp;여러&amp;nbsp;기준으로&amp;nbsp;나누기&lt;br /&gt;-&amp;nbsp;분류값의&amp;nbsp;상호배타성&amp;middot;완전성:&amp;nbsp;겹치지&amp;nbsp;않고&amp;nbsp;빠짐없이&amp;nbsp;나누는&amp;nbsp;원칙&lt;br /&gt;-&amp;nbsp; &amp;nbsp;목표:&amp;nbsp;&quot;콘텐츠를&amp;nbsp;난이도&amp;middot;주제&amp;middot;유형으로&amp;nbsp;나눈&amp;nbsp;이유&quot;를&amp;nbsp;설명할&amp;nbsp;수&amp;nbsp;있기&lt;br /&gt;&lt;br /&gt;4단계&amp;nbsp;&amp;mdash;&amp;nbsp;데이터&amp;nbsp;거버넌스&amp;nbsp;&amp;amp;&amp;nbsp;품질관리&lt;br /&gt;&lt;br /&gt;&quot;데이터를&amp;nbsp;믿고&amp;nbsp;쓸&amp;nbsp;수&amp;nbsp;있게&amp;nbsp;관리&quot;하는&amp;nbsp;규칙.&lt;br /&gt;-&amp;nbsp;데이터&amp;nbsp;거버넌스:&amp;nbsp;데이터&amp;nbsp;관리&amp;nbsp;정책&amp;middot;책임&amp;middot;규칙의&amp;nbsp;전체&amp;nbsp;틀&lt;br /&gt;-&amp;nbsp;데이터&amp;nbsp;품질&amp;nbsp;6대&amp;nbsp;차원:&amp;nbsp;정확성&amp;nbsp;/&amp;nbsp;완전성(누락)&amp;nbsp;/&amp;nbsp;일관성&amp;nbsp;/&amp;nbsp;유효성&amp;nbsp;/&amp;nbsp;유일성(중복)&amp;nbsp;/&amp;nbsp;적시성&amp;nbsp;&amp;mdash;&amp;nbsp;이건&amp;nbsp;꼭&amp;nbsp;외워두세요&amp;nbsp;(면접&amp;nbsp;단골)&lt;br /&gt;-&amp;nbsp;데이터&amp;nbsp;딕셔너리&amp;nbsp;/&amp;nbsp;메타데이터:&amp;nbsp;각&amp;nbsp;컬럼이&amp;nbsp;무슨&amp;nbsp;뜻인지&amp;nbsp;정의한&amp;nbsp;문서&lt;br /&gt;-&amp;nbsp;정합성(Integrity):&amp;nbsp;데이터가&amp;nbsp;규칙에&amp;nbsp;맞고&amp;nbsp;서로&amp;nbsp;모순&amp;nbsp;없는&amp;nbsp;상태&lt;br /&gt;-&amp;nbsp; &amp;nbsp;목표:&amp;nbsp;&quot;품질&amp;nbsp;점검할&amp;nbsp;때&amp;nbsp;뭘&amp;nbsp;봤냐&quot;에&amp;nbsp;6대&amp;nbsp;차원으로&amp;nbsp;답하기&lt;br /&gt;&lt;br /&gt;5단계&amp;nbsp;(선택)&amp;nbsp;&amp;mdash;&amp;nbsp;실무&amp;nbsp;도구/키워드&lt;br /&gt;&lt;br /&gt;-&amp;nbsp;SQL&amp;nbsp;기본(SELECT&amp;middot;JOIN&amp;middot;GROUP&amp;nbsp;BY):&amp;nbsp;실제로&amp;nbsp;데이터&amp;nbsp;확인&amp;middot;점검할&amp;nbsp;때&amp;nbsp;씀&lt;br /&gt;-&amp;nbsp;BigQuery&amp;nbsp;/&amp;nbsp;데이터&amp;nbsp;웨어हाउस&amp;nbsp;개념&amp;nbsp;(이력서에&amp;nbsp;있으니&amp;nbsp;연결됨)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;div style=&quot;background-color: #f5f7fa; color: #1a2027; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;background-color: #f5f7fa; color: #1a2027; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이콘 주식회사&lt;/h3&gt;
&lt;span style=&quot;color: #2f6bff;&quot;&gt;3년 11개월&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #f5f7fa; color: #1a2027; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div style=&quot;color: #5c6b7a; text-align: right;&quot;&gt;2025.08 ~ 2026.08&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div style=&quot;color: #1a2027;&quot;&gt;AX실 &amp;middot; 매니저&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #5c6b7a;&quot;&gt;/ AI 대시보드 개발 &amp;middot; 데이터 분석&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;background-color: #2f6bff; color: #ffffff;&quot;&gt;정규직 &amp;middot; 4년차&lt;/span&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;AI(Gemini) 활용 대시보드 풀스택 개발 (프론트/백엔드)&lt;/li&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;사내 이원화 DB 통합&lt;/li&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;Tableau / Power BI 학습 성과 대시보드 구축&lt;/li&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;Airflow 기반 ETL 파이프라인 자동화&lt;/li&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;대회 홍보 업무 자동화&lt;/li&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;VOC 분석 및 학습&amp;ndash;대회 연계 플로우 개선&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div style=&quot;color: #5c6b7a; text-align: right;&quot;&gt;2024.08 ~ 2025.08&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div style=&quot;color: #1a2027;&quot;&gt;DS &amp;middot; 교육팀 &amp;middot; 매니저&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #5c6b7a;&quot;&gt;/ 학습 서비스 분석 &amp;middot; 경영 리포팅&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;background-color: #2f6bff; color: #ffffff;&quot;&gt;정규직 &amp;middot; 3년차&lt;/span&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;학습 트랙 효과 분석 및 C-level 대상 격주 정기 리포팅&lt;/li&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;BigQuery(MySQL 연동) 기반 경영 지표 대시보드 설계&amp;middot;구축&lt;/li&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;고객 이탈(Churn) 예측 모델 개발 및 타깃 리텐션 캠페인 운영&lt;/li&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;검색어 로그 분석을 통한 콘텐츠 제작 우선순위 도출&lt;/li&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;콘텐츠 진행률&amp;middot;이탈 구간 분석(히트맵) 및 개선 제안&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div style=&quot;color: #5c6b7a; text-align: right;&quot;&gt;2023.08 ~ 2024.08&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div style=&quot;color: #1a2027;&quot;&gt;DS &amp;middot; 교육팀 &amp;middot; 매니저&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #5c6b7a;&quot;&gt;/ 학습 콘텐츠 기획 &amp;middot; 서비스 운영&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;background-color: #2f6bff; color: #ffffff;&quot;&gt;정규직 &amp;middot; 2년차&lt;/span&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;콘텐츠 이용&amp;middot;검색 데이터 기반 PBL 자기주도학습 콘텐츠 기획&amp;middot;제작 (월 1개)&lt;/li&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;학습 수요&amp;middot;이용 데이터를 반영한 트랙(커리큘럼 패키지) 상품 기획 참여&lt;/li&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;구독 부가 혜택(랭커특강) 기획&amp;middot;운영 및 참여 데이터 점검&lt;/li&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;데이터 기반 AI 해커톤 기획&amp;middot;운영&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div style=&quot;color: #5c6b7a; text-align: right;&quot;&gt;2022.08 ~ 2023.07&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div style=&quot;color: #1a2027;&quot;&gt;DS 파트 &amp;middot; 매니저&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #5c6b7a;&quot;&gt;/ AI 교육 콘텐츠 &amp;middot; 해커톤 운영&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;background-color: #2f6bff; color: #ffffff;&quot;&gt;인턴 &amp;middot; 1년차&lt;/span&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;학습 서비스 DB 설계 참여(데이터 택소노미)&amp;middot;거버넌스 점검&lt;/li&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;AI 해커톤 기획&amp;middot;데이터 탐색&amp;middot;가공&amp;middot;운영 보조&lt;/li&gt;
&lt;li style=&quot;color: #1a2027;&quot;&gt;AI 교육 콘텐츠(파이썬 / 머신러닝 / 딥러닝) 제작 보조&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <author>ISFP의 블로그</author>
      <guid isPermaLink="true">https://resultofeffort.tistory.com/155</guid>
      <comments>https://resultofeffort.tistory.com/155#entry155comment</comments>
      <pubDate>Thu, 23 Jul 2026 11:40:24 +0900</pubDate>
    </item>
    <item>
      <title>[python] macOS에서 Apache Airflow 시작하기 (ETL 파이프라인 구축)</title>
      <link>https://resultofeffort.tistory.com/154</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1.Airflow 초기 설정&amp;nbsp;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;10&quot;&gt;Apache airflow는 Linux 기반이지만, macOS에서도 터미널을 통해 쉽게 설치하고 실행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;11&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;11&quot;&gt;&lt;b&gt;1.1. 가상환경 생성(conda)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;11&quot;&gt;anaconda를 사용해서 python 3.10 버전의 가상환경을 생성 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# Anaconda를 사용하여 Python 3.10 환경을 생성
conda create -n airflow_lab python=3.10

# 가상환경 활성화
conda activate airflow_lab&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1.2. Airflow 설치&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Airflow 공식 문서에서는 pip 로 설치를 권장하기 때문에 Airflow와 MySQL Provider 패키지는 pip 로 설치 합니다.&lt;br /&gt;mysqlclient는 conda로 설치해주었습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1765499617783&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# Airflow 설치
pip install apache-airflow

# MySQL Provider 설치
pip install apache-airflow-providers-mysql

# [중요] MySQL Client 설치 (이거 안 하면 에러 남)
conda install -c conda-forge mysqlclient&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1.3. 환경 변수 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;macOS의 시스템 보안 정책으로 인해 Airflow가 갑작스럽게 종료되는 현상이 발생할 수 있습니다. 이를 방지하기 위해 다음 환경변수를 설정합니다.&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;size18&quot;&gt;&lt;b&gt;⚠️ 주의: 이 설정은 현재 터미널에만 적용됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;해당 명령어는 현재 열려 있는 터미널 창을 닫으면 초기화됩니다. Airflow를 실행할 때마다 해당 명령어를 입력해 주어야 에러가 발생하지 않습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1765499617784&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# macOS 프록시 설정 (보안 정책 충돌 방지)
export no_proxy=&quot;*&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1.4. 서버 실행&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이제 Airflow 서버를 실행합니다. 실행 후 터미널에 표시되는 웹 주소(일반적으로 http://localhost:8080)로 접속하면 Airflow 대시보드를 확인할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1765499617784&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;airflow standalone&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot; data-path-to-node=&quot;6&quot;&gt;&lt;b&gt;2. Airflow 대시보드 접속하기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;7&quot;&gt;&lt;b&gt;2.1.터미널에서 인증정보 확인하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;7&quot;&gt;airflow standalone 명령어를 실행하면 여러 로그가 빠르게 출력됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;7&quot;&gt;로그가 나타나타가 멈추는 순간, 위쪽을 잘 살펴보면 다음과 같은 박스를 찾을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;7&quot;&gt;터미널에 출력된 Password 문자열을 복사해야 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;pre style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;Standalone mode created: ...
User: admin
Password: [여기에_적힌_복잡한_문자열]  &amp;lt;-- 이걸 복사하세요!
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;※ 주의: 만약 로그에 비밀번호가 안 보인다면?&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;Airflow 재실행 시에는 보안상 비밀번호가 로그에 뜨지 않습니다.&lt;br /&gt;이런 경우에는 새 터미널 창을 열어 아래 명령어중 하나를 실행하세요.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# 비밀번호 확인 명령어 (둘 중 하나 실행)
cat ~/airflow/standalone_admin_password.txt

# 또는 (Airflow 버전에 따라)
cat ~/airflow/simple_auth_manager_passwords.json.generated&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;admin:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&quot;이 부분이 비밀번호 입니다.&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;72&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wQbru/dJMcahCVTZU/0DyGKVzIE1aULe9of2WtcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wQbru/dJMcahCVTZU/0DyGKVzIE1aULe9of2WtcK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wQbru/dJMcahCVTZU/0DyGKVzIE1aULe9of2WtcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwQbru%2FdJMcahCVTZU%2F0DyGKVzIE1aULe9of2WtcK%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;857&quot; height=&quot;72&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;72&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;11&quot;&gt;&lt;b&gt;2.2.웹 브라우저에 접속하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;11&quot;&gt;웹 브라우저를(Chrome 등) 열고 주소창에 아래 주소를 입력합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1765499617785&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;http://localhost:8080&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; data-path-to-node=&quot;14&quot;&gt;&lt;b&gt;2.3.로그인 하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;14&quot;&gt;Airflow 로그인 화면이 표시되면 앞서 확인한 인증정보를 입력합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;14&quot;&gt;&lt;b&gt;- Username&lt;/b&gt;: admin 입력하시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;14&quot;&gt;&lt;b&gt;- Password&lt;/b&gt;: 위에서 복사한 비밀번호를 입력해줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;628&quot; data-origin-height=&quot;506&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kVYrv/dJMcacIo2RR/Tm8JCpywNeKG370xlROZiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kVYrv/dJMcacIo2RR/Tm8JCpywNeKG370xlROZiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kVYrv/dJMcacIo2RR/Tm8JCpywNeKG370xlROZiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkVYrv%2FdJMcacIo2RR%2FTm8JCpywNeKG370xlROZiK%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;387&quot; height=&quot;312&quot; data-origin-width=&quot;628&quot; data-origin-height=&quot;506&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;13&quot;&gt;로그인에 성공하면 Airflow 대시보드가 나타납니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2862&quot; data-origin-height=&quot;1364&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yGvtg/dJMcagKNCmC/AC2iHT1cNTTycPMXSaXCw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yGvtg/dJMcagKNCmC/AC2iHT1cNTTycPMXSaXCw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yGvtg/dJMcagKNCmC/AC2iHT1cNTTycPMXSaXCw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyGvtg%2FdJMcagKNCmC%2FAC2iHT1cNTTycPMXSaXCw0%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;673&quot; height=&quot;321&quot; data-origin-width=&quot;2862&quot; data-origin-height=&quot;1364&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot; data-path-to-node=&quot;9&quot;&gt;&lt;b&gt;3.실습용 데이터 생성하기&lt;/b&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;10&quot;&gt;Airflow와 연결하기 전에, Airflow가 가져올&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;실습용 데이터&lt;/b&gt;를 MySQL에 먼저 만들어 둬야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;10&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;11&quot;&gt;&lt;b&gt;3.1. MySQL 접속하기&lt;/b&gt;&lt;br /&gt;새로운 터미널 창을 열고 (command + n) 터미널에서 MySQL에 관리자 권한으로 접속합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;11&quot;&gt;(비밀번호가 있다면 입력 후 엔터, 비밀번호를 설정하신 적이 없다면 그냥 엔터!)&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;mysql -u root -p&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;558&quot; data-origin-height=&quot;219&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dGIxM5/dJMcadUM2cD/Ke7PRLWkrk3JK4HQ4RPyxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dGIxM5/dJMcadUM2cD/Ke7PRLWkrk3JK4HQ4RPyxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dGIxM5/dJMcadUM2cD/Ke7PRLWkrk3JK4HQ4RPyxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdGIxM5%2FdJMcadUM2cD%2FKe7PRLWkrk3JK4HQ4RPyxk%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;558&quot; height=&quot;219&quot; data-origin-width=&quot;558&quot; data-origin-height=&quot;219&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;13&quot;&gt;&lt;b&gt;3.2. 데이터 생성 SQL 실행 (복사+붙여넣기)&lt;/b&gt;&lt;br /&gt;접속된 MySQL 화면(mysql&amp;gt;)에 아래 SQL 문을 통째로 복사해서 붙여넣으세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;13&quot;&gt;&lt;u&gt;game_log_db라는 데이터베이스&lt;/u&gt;를 만들고, 그 안에 가상의 유저 로그 3개를 넣는 명령어입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;CREATE DATABASE IF NOT EXISTS game_log_db;
USE game_log_db;

CREATE TABLE IF NOT EXISTS access_log (
    user_id VARCHAR(50),
    event VARCHAR(50),
    created_at DATE
);

INSERT INTO access_log VALUES ('user_1', 'login', '2025-01-01');
INSERT INTO access_log VALUES ('user_2', 'logout', '2025-01-01');
INSERT INTO access_log VALUES ('user_3', 'level_up', '2025-01-01');

SELECT * FROM access_log;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;15&quot;&gt;&lt;b&gt;3.3. 확인 및 종료&lt;/b&gt;&lt;br /&gt;마지막에 SELECT 결과로 데이터 3줄이 잘 출력되었다면 성공입니다!&lt;br /&gt;exit를 입력해 MySQL을 빠져나옵니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;253&quot; data-origin-height=&quot;140&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bProlT/dJMcacIpkDN/X5RKNghQNOIOKK6A8hBMj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bProlT/dJMcacIpkDN/X5RKNghQNOIOKK6A8hBMj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bProlT/dJMcacIpkDN/X5RKNghQNOIOKK6A8hBMj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbProlT%2FdJMcacIpkDN%2FX5RKNghQNOIOKK6A8hBMj1%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;334&quot; height=&quot;185&quot; data-origin-width=&quot;253&quot; data-origin-height=&quot;140&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot; data-path-to-node=&quot;13&quot;&gt;&lt;b&gt;4.Airflow - MySQL 커넥션 설정&lt;/b&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Airflow에서 MySQL 데이터베이스에 접근하려면 먼저 연결 설정을 등록해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Airflow 웹 대시보드의 '관리자' 메뉴에서 커넥션을 추가합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;경로&lt;span&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;좌측&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;탭&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;관리자&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;커넥션들&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;커넥션&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;추가&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9m9rM/dJMcadAueQY/tYZS4D0D00aR7gmeL8qr11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9m9rM/dJMcadAueQY/tYZS4D0D00aR7gmeL8qr11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9m9rM/dJMcadAueQY/tYZS4D0D00aR7gmeL8qr11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9m9rM%2FdJMcadAueQY%2FtYZS4D0D00aR7gmeL8qr11%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;605&quot; height=&quot;320&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;320&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot; data-path-to-node=&quot;14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;14&quot;&gt;&lt;b&gt;4.1.기본 정보 입력&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;14&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;커넥션ID&lt;/b&gt;: game_mysql_conn&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;14&quot;&gt;(Airflow 가 이 연결 설정을 부를 때 사용하는 고유한 식별자입니다. python 코드에서 이 이름으로 DB에 접속합니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;14&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;커넥션 유형&lt;/b&gt;: Mysql&lt;br /&gt;(데이터베이스 유형을 지정합니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot; data-path-to-node=&quot;14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;4&quot;&gt;&lt;b&gt;4.2.데이터베이스 연결 정보 입력&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;5&quot;&gt;맥북 로컬 환경에서 에러 없이 연결하려면 아래&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;4가지는 꼭 채워야 합니다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;5&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;5&quot;&gt;1.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Host&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(호스트): localhost&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(주의: 127.0.0.1로 쓰면 맥북 보안 설정 때문에 연결이 거부될 수 있습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Login&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(로그인): root&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(MySQL 설치 시 기본 관리자 계정입니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Password&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(비밀번호): (본인 설정에 따라 다름)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(Mysqk울 설치할 때 비밀번호를 따로 설정 안 했다면 비워두세요.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;4.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Schema&lt;/b&gt;:&lt;span&gt;game_log_db&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;(앞서 생성한 데이터베이스 이름입니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span&gt;4.3.Mac OS 호환성 설정&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(이걸 입력해야 TCP/IP 통신 오류를 우회하여 소켓으로 직통 연결됩니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot; data-path-to-node=&quot;4&quot;&gt;경로는 터미널에서 mysql -u root -&amp;gt; status로 확인하세요.)&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1765499617787&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;{&quot;socket&quot;: &quot;/tmp/mysql.sock&quot;}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;왜 이 설정(Mac OS 호환성 설정)이 필요한가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;macOS에서 MySQL은 기본적으로 Unix Socket을 통해 통신합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TCP/IP로 연결하려고 하면 &amp;lsquo;Connection Refused&amp;rsquo; 에러가 발생할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 설정은 Airflow에게 소켓 통신 방식을 사용하도록 지시합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;MySQL&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;소켓&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;경로&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;확인하기&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;터미널에서&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;다음&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;명령어를&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;실행하여&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;정확한&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;경로를&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;확인하세요&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;pre style=&quot;background-color: #fafafa; color: #232425; text-align: start;&quot; data-source-line=&quot;104-107&quot;&gt;&lt;code&gt;Copymysql -u root
mysql&amp;gt; status
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;출력된 정보에서 'UNIX socket'으로 시작하는 라인을 찾으면, 소켓 파일의 경로를 확인할 수 있습니다 (보통 /tmp/mysql.sock).&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;만약&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;/var/run/mysqld/mysql.sock&lt;span&gt;이라면&lt;/span&gt;, Extra&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;필드를&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;그에&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;맞게&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;수정하면&lt;/span&gt;&lt;span&gt;&amp;nbsp;&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;636&quot; data-origin-height=&quot;521&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OX1oI/dJMcabCINN0/3qFmm1ZZjara1oWUZhDKn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OX1oI/dJMcabCINN0/3qFmm1ZZjara1oWUZhDKn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OX1oI/dJMcabCINN0/3qFmm1ZZjara1oWUZhDKn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOX1oI%2FdJMcabCINN0%2F3qFmm1ZZjara1oWUZhDKn1%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;636&quot; height=&quot;521&quot; data-origin-width=&quot;636&quot; data-origin-height=&quot;521&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;212&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cljPGf/dJMcahiDwQT/Zx5gVGuOYSPP9URk7K2XXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cljPGf/dJMcahiDwQT/Zx5gVGuOYSPP9URk7K2XXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cljPGf/dJMcahiDwQT/Zx5gVGuOYSPP9URk7K2XXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcljPGf%2FdJMcahiDwQT%2FZx5gVGuOYSPP9URk7K2XXk%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;621&quot; height=&quot;212&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;212&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot; data-path-to-node=&quot;14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;14&quot;&gt;저장을 누르고 커넥션 목록 화면으로 돌아옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;14&quot;&gt;리스트에 game_mysql_conn이 추가된 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;884&quot; data-origin-height=&quot;106&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccU6Rc/dJMcacO99kr/1yf305lUkFQzkzzv85aW91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccU6Rc/dJMcacO99kr/1yf305lUkFQzkzzv85aW91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccU6Rc/dJMcacO99kr/1yf305lUkFQzkzzv85aW91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FccU6Rc%2FdJMcacO99kr%2F1yf305lUkFQzkzzv85aW91%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;643&quot; height=&quot;77&quot; data-origin-width=&quot;884&quot; data-origin-height=&quot;106&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;이제&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Airflow&lt;span&gt;가&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;MySQL&lt;span&gt;에&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;접근할&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;있는&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;경로가&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;설정되었습니다&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;이&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;'game_mysql_conn'&lt;span&gt;이라는&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;연결&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;정보를&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;사용하여&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;다음&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;단계에서&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Python DAG&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;코드를&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;작성할&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;예정입니다&lt;/span&gt;.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot; data-path-to-node=&quot;16&quot;&gt;&lt;b&gt;5.DAG 파일 생성(ETL 구현)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Airflow와 MySQL 연결 설정이 끝났으니, 이제 실제로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;데이터를 추출(Extract)해서 파일로 저장(Load)하는 DAG&lt;/b&gt;를 작성해 봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;5&quot;&gt;&lt;b&gt;5.1. 데이터를 저장할 폴더 만들기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;6&quot;&gt;CSV 파일을 저장할 폴더가 없으면 에러가 발생할 수 있습니다. 터미널에서 미리 폴더를 생성해 줍니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;mkdir -p ~/airflow/data
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;8&quot;&gt;&lt;b&gt;5.2. DAG 파일 생성하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;8&quot;&gt;Airflow의 DAG 폴더 (~/airflow/dags/)에 Python 파일을 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;8&quot;&gt;이 DAG는 다음 기능을 수행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;8&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;8&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Extract&lt;/b&gt;: MySQL의 access_log 테이블에서 모든 데이터를 조회(SELECT)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;8&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Load&lt;/b&gt;: 조회된 데이터를 CSV 파일로 로컬 컴퓨터 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;8&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;8&quot;&gt;다음 명령어를 터미널에 복사하여 실행하면 DAG 파일이 생성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;10&quot;&gt;(터미널에 아래 내용을 그대로 복사+붙여넣기 하세요. 파일 생성과 내용 작성이 한 번에 됩니다!)&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;cat &amp;lt;&amp;lt;EOF &amp;gt; ~/airflow/dags/practice_connection.py
from airflow import DAG
from airflow.providers.common.sql.operators.sql import SQLExecuteQueryOperator
from airflow.operators.python import PythonOperator
from datetime import datetime
import csv

# ============================================
# 1단계: 데이터를 받아서 CSV 파일로 저장하는 함수 (Load)
# ============================================
def save_to_csv(**context):
    '''
    XCom(Airflow 우편함)에서 이전 Task가 조회한 데이터를 받아서
    CSV 파일로 저장합니다.
    '''
    # XCom에서 'read_db' Task의 결과 데이터를 꺼내옵니다
    data = context['ti'].xcom_pull(task_ids='read_db')
    
    # ⚠️ 중요: 아래 경로를 본인 사용자 이름에 맞게 수정하세요!
    # 예: /Users/[본인_사용자명]/airflow/data/game_log.csv
    file_path = '/Users/song/airflow/data/game_log.csv'
    
    # CSV 파일에 데이터를 쓰기 모드로 저장
    with open(file_path, 'w', newline='') as f:
        writer = csv.writer(f)
        writer.writerow(['user_id', 'event', 'date'])  # CSV 컬럼 제목
        for row in data:
            writer.writerow(row)  # 각 행의 데이터 입력
            
    print(f&quot;✅ 파일 저장 완료: {file_path}&quot;)

# ============================================
# 2단계: DAG(작업 흐름) 정의
# ============================================
with DAG(
    dag_id='mysql_to_csv_v1',        # Airflow 웹 대시보드에 보일 DAG 이름
    start_date=datetime(2025, 1, 1), # DAG 시작 날짜
    schedule='@daily',               # 매일 UTC 0시(한국시간 9시)에 자동 실행
    catchup=False                    # 과거 날짜의 미실행 작업을 실행하지 않음
) as dag:

    # [Task 1] MySQL 데이터베이스에서 데이터 조회하기 (Extract)
    read_db = SQLExecuteQueryOperator(
        task_id='read_db',                  # Task의 고유한 이름
        conn_id='game_mysql_conn',          # 아까 웹에서 설정한 MySQL 커넥션 ID
        sql=&quot;SELECT * FROM access_log;&quot;     # 실행할 SQL 쿼리
    )

    # [Task 2] 조회한 데이터를 파일로 변환하기 (Load)
    write_csv = PythonOperator(
        task_id='write_csv',                # Task의 고유한 이름
        python_callable=save_to_csv         # 실행할 Python 함수
    )

    # Task 의존성 설정: read_db를 먼저 실행 &amp;rarr; write_csv를 나중에 실행
    read_db &amp;gt;&amp;gt; write_csv
EOF&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot; data-path-to-node=&quot;3&quot;&gt;&lt;b&gt;6.실행 및 결과 확인 (Result)&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;407&quot; data-origin-height=&quot;93&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dmSMac/dJMcahXfPFU/QiTepKpp9uac1UKHxrZ9gK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dmSMac/dJMcahXfPFU/QiTepKpp9uac1UKHxrZ9gK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dmSMac/dJMcahXfPFU/QiTepKpp9uac1UKHxrZ9gK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdmSMac%2FdJMcahXfPFU%2FQiTepKpp9uac1UKHxrZ9gK%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;407&quot; height=&quot;93&quot; data-origin-width=&quot;407&quot; data-origin-height=&quot;93&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;4&quot;&gt;코드를 저장했다면 이제 Airflow 웹 화면에서 실행해 볼 차례입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot; data-path-to-node=&quot;4&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;5&quot;&gt;DAG 확인 및 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;5&quot;&gt;1. Airflow 웹 화면(localhost:8080)에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;[DAGs]&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;메뉴를 클릭하고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;새로고침(F5)&lt;/b&gt;을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;5&quot;&gt;2. 약 30초~1분 정도 기다리면 목록에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;mysql_to_csv_v1&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이 나타납니다.&lt;br /&gt;(만약 나오지 않는다면, Airflow 서버를 껐다 키신 후 진행해보세요)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;5&quot;&gt;3. 왼쪽의 토글 스위치(On/Off)를 켜서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;파란색(Unpaused)&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;상태로 만듭니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;899&quot; data-origin-height=&quot;276&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Nq3aD/dJMcac2EPrz/mFcg2fwoKNtqIfRf8CW3aK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Nq3aD/dJMcac2EPrz/mFcg2fwoKNtqIfRf8CW3aK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Nq3aD/dJMcac2EPrz/mFcg2fwoKNtqIfRf8CW3aK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNq3aD%2FdJMcac2EPrz%2FmFcg2fwoKNtqIfRf8CW3aK%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;899&quot; height=&quot;276&quot; data-origin-width=&quot;899&quot; data-origin-height=&quot;276&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;7&quot;&gt;4. 오른쪽의&amp;nbsp;&lt;b&gt;[▶] (Trigger DAG)&lt;/b&gt;&amp;nbsp;버튼을 눌러 작업을 실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;7&quot;&gt;5. 성공 여부 확인 (Web UI)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;7&quot;&gt;read_db와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;write_csv&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;두 작업이 모두 진한 초록색(Success)으로 변하면 성공입니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;7&quot;&gt;(만약 빨간색(Failed)이 뜬다면, 클릭해서 [Log]를 확인해야 합니다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;721&quot; data-origin-height=&quot;96&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ef6qSt/dJMcaaw3bcw/lkXsjYSbrCJArImBCdHk11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ef6qSt/dJMcaaw3bcw/lkXsjYSbrCJArImBCdHk11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ef6qSt/dJMcaaw3bcw/lkXsjYSbrCJArImBCdHk11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fef6qSt%2FdJMcaaw3bcw%2FlkXsjYSbrCJArImBCdHk11%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;721&quot; height=&quot;96&quot; data-origin-width=&quot;721&quot; data-origin-height=&quot;96&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;814&quot; data-origin-height=&quot;136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O7nUE/dJMcafSFbM6/wVsK4QBgKkpZkxjr46T8C0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O7nUE/dJMcafSFbM6/wVsK4QBgKkpZkxjr46T8C0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O7nUE/dJMcafSFbM6/wVsK4QBgKkpZkxjr46T8C0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO7nUE%2FdJMcafSFbM6%2FwVsK4QBgKkpZkxjr46T8C0%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;724&quot; height=&quot;121&quot; data-origin-width=&quot;814&quot; data-origin-height=&quot;136&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;9&quot;&gt;6. 최종 결과물 확인 (CSV 파일)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot; data-path-to-node=&quot;10&quot;&gt;마지막으로 터미널에서 아래 명령어를 입력해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;진짜 파일이 생성되었는지&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;확인합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# 파일 내용 출력하기
cat ~/airflow/data/game_log.csv&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot; data-path-to-node=&quot;12&quot;&gt;아래와 같이 MySQL에 들어있던 데이터가 콤마(,)로 구분된 텍스트 형태로 출력된다면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;ETL 파이프라인 구축 성공&lt;/b&gt;입니다!&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;80&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceRnqB/dJMcai9DFeB/7uzhFlI5dVZle7rqK77m61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceRnqB/dJMcai9DFeB/7uzhFlI5dVZle7rqK77m61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceRnqB/dJMcai9DFeB/7uzhFlI5dVZle7rqK77m61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FceRnqB%2FdJMcai9DFeB%2F7uzhFlI5dVZle7rqK77m61%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;503&quot; height=&quot;80&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;80&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>python</category>
      <author>ISFP의 블로그</author>
      <guid isPermaLink="true">https://resultofeffort.tistory.com/154</guid>
      <comments>https://resultofeffort.tistory.com/154#entry154comment</comments>
      <pubDate>Fri, 12 Dec 2025 09:38:14 +0900</pubDate>
    </item>
    <item>
      <title>[통계] 직관적 의사결정 vs 데이터 기반 의사결정</title>
      <link>https://resultofeffort.tistory.com/152</link>
      <description>&lt;pre id=&quot;code_1760083520465&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ㄹㄷㄹㄷㄹe

 문서 리스트
corpus = [
    &quot;나는 오늘 밥을 먹었다&quot;,
    &quot;밥을 먹고 운동을 했다&quot;,
    &quot;오늘 운동을 마치고 밥을 먹었다&quot;
]

# TF-IDF 벡터화
vectorizer = TfidfVectorizer()
tfidf_matrix = vectorizer.fit_transform(corpus)

# 코사인 유사도 계산
cosine_sim = cosine_similarity(tfidf_matrix, tfidf_matrix)

# 결과를 데이터프레임으로 보기 좋게 출력
df = pd.DataFrame(cosine_sim, index=[&quot;문서1&quot;, &quot;문서2&quot;, &quot;문서3&quot;], columns=[&quot;문서1&quot;, &quot;문서2&quot;, &quot;문서3&quot;])
print(&quot;코사인 유사도 행렬:&quot;)
print(df)
출처: https://resultofeffort.tistory.com/147 [resultofeffort:티스토리]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;두&amp;nbsp;가지&amp;nbsp;의사결정&amp;nbsp;방식의&amp;nbsp;이해&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 매일 수많은 의사결정을 내립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아침에 무엇을 입을지부터 저녁에는 무엇을 먹을지 말이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 선택을 할 때 우리가 사용하는 방식은 크게 두 가지로 나눌 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째는 &quot;직관적 의사결정&quot;입니다.&lt;br /&gt;이는 우리가 가장 많이 사용하는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 제가 티셔츠를 판매하는 판매자라고 해볼게요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;판매하고자 하는 티셔츠의 색상을 선택해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 이 티셔츠를 최대한 많이 팔아야 하는 판매자이기 때문에 사람들이 가장 많이 구매할 것 같은 색상을 고를 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검정색이 가장 많이 판매가 될 것 같으니 100개를 발주하고 핑크색은 팔리지 않을 것 같아서 발주를 넣지 않을 겁니다.&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;이러한 과정에서 데이터로 설명할 수 없는 아이디어나 접근 방법을 떠올리기도 합니다.&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;이는 객관적인 수치와 분석 결과를 바탕으로 하는 결정을 내리는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 넷플릭스에서 새로운 컨텐츠를 제작하려면 과거의 사람들이 가장 많이 소비한 컨텐츠의 종류와 분야, 시청자의 나이, 한달에 소비하는 시간을 고려해서 새로운 컨텐츠를 기획하고 생산하는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 기반의 의사결정의 장점은 객관성과 재현성입니다. 동일한 데이터로 동일한 분석을 한다면 누가 분석하든 비슷한 결론에 도달할 수 있습니다. 또한 결정의 근거를 명확히 제시할 수 있어서 다른 사람들을 설득하기도 쉽습니다.&amp;nbsp; 하지만 이 방식도 단점이 존재합니다. 데이터를 분석하는데 수많은 리소스가 소요되고, 무엇보다 과거의 데이터를 기반으로 미래를 예측하는 것이기 때문에&amp;nbsp; 전혀 새로운 상황에서는 한계가 있을 수 있습니다.&lt;/p&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; &amp;zwj; &amp;nbsp;데이터&amp;nbsp;사이언티스트가&amp;nbsp;갖춰야&amp;nbsp;할&amp;nbsp;역량&lt;br /&gt;&lt;br /&gt;그렇다면&amp;nbsp;데이터&amp;nbsp;기반&amp;nbsp;의사결정을&amp;nbsp;주도하는&amp;nbsp;데이터&amp;nbsp;사이언티스트는&amp;nbsp;어떤&amp;nbsp;능력을&amp;nbsp;갖춰야&amp;nbsp;할까요?&amp;nbsp;많은&amp;nbsp;사람들이&amp;nbsp;프로그래밍이나&amp;nbsp;통계학만&amp;nbsp;잘하면&amp;nbsp;된다고&amp;nbsp;생각하지만,&amp;nbsp;실제로는&amp;nbsp;훨씬&amp;nbsp;다양한&amp;nbsp;역량이&amp;nbsp;필요합니다.&lt;br /&gt;&lt;br /&gt;가장&amp;nbsp;기본이&amp;nbsp;되는&amp;nbsp;것은&amp;nbsp;당연히&amp;nbsp;기술적&amp;nbsp;역량입니다.&amp;nbsp;통계학의&amp;nbsp;기초&amp;nbsp;개념들을&amp;nbsp;이해하고,&amp;nbsp;Python이나&amp;nbsp;R&amp;nbsp;같은&amp;nbsp;프로그래밍&amp;nbsp;언어를&amp;nbsp;다룰&amp;nbsp;수&amp;nbsp;있어야&amp;nbsp;하죠.&amp;nbsp;SQL로&amp;nbsp;데이터베이스에서&amp;nbsp;필요한&amp;nbsp;데이터를&amp;nbsp;추출할&amp;nbsp;수&amp;nbsp;있어야&amp;nbsp;하고,&amp;nbsp;머신러닝&amp;nbsp;알고리즘들을&amp;nbsp;상황에&amp;nbsp;맞게&amp;nbsp;적용할&amp;nbsp;수&amp;nbsp;있어야&amp;nbsp;합니다.&amp;nbsp;하지만&amp;nbsp;이것만으로는&amp;nbsp;충분하지&amp;nbsp;않습니다.&lt;br /&gt;&lt;br /&gt;더&amp;nbsp;중요한&amp;nbsp;것은&amp;nbsp;분석적&amp;nbsp;사고력입니다.&amp;nbsp;복잡한&amp;nbsp;비즈니스&amp;nbsp;문제를&amp;nbsp;보았을&amp;nbsp;때&amp;nbsp;이것을&amp;nbsp;어떻게&amp;nbsp;데이터로&amp;nbsp;분석할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;형태로&amp;nbsp;바꿀&amp;nbsp;수&amp;nbsp;있는지&amp;nbsp;생각할&amp;nbsp;수&amp;nbsp;있어야&amp;nbsp;해요.&amp;nbsp;예를&amp;nbsp;들어&amp;nbsp;&quot;고객&amp;nbsp;만족도를&amp;nbsp;높이고&amp;nbsp;싶다&quot;는&amp;nbsp;막연한&amp;nbsp;요청을&amp;nbsp;받았을&amp;nbsp;때,&amp;nbsp;이를&amp;nbsp;&quot;고객&amp;nbsp;서비스&amp;nbsp;응답&amp;nbsp;시간과&amp;nbsp;만족도&amp;nbsp;점수&amp;nbsp;간의&amp;nbsp;관계&amp;nbsp;분석&quot;&amp;nbsp;같은&amp;nbsp;구체적인&amp;nbsp;분석&amp;nbsp;문제로&amp;nbsp;변환할&amp;nbsp;수&amp;nbsp;있어야&amp;nbsp;합니다.&lt;br /&gt;&lt;br /&gt;또한&amp;nbsp;비즈니스에&amp;nbsp;대한&amp;nbsp;이해도&amp;nbsp;필수입니다.&amp;nbsp;아무리&amp;nbsp;정교한&amp;nbsp;분석을&amp;nbsp;했더라도&amp;nbsp;그것이&amp;nbsp;실제&amp;nbsp;비즈니스에&amp;nbsp;어떤&amp;nbsp;의미가&amp;nbsp;있는지,&amp;nbsp;어떤&amp;nbsp;가치를&amp;nbsp;창출할&amp;nbsp;수&amp;nbsp;있는지&amp;nbsp;알지&amp;nbsp;못한다면&amp;nbsp;의미가&amp;nbsp;없거든요.&amp;nbsp;예를&amp;nbsp;들어&amp;nbsp;전자상거래&amp;nbsp;회사에서&amp;nbsp;일한다면&amp;nbsp;고객&amp;nbsp;획득&amp;nbsp;비용,&amp;nbsp;생애&amp;nbsp;가치,&amp;nbsp;전환율&amp;nbsp;같은&amp;nbsp;핵심&amp;nbsp;지표들을&amp;nbsp;이해하고&amp;nbsp;있어야&amp;nbsp;합니다.&lt;br /&gt;&lt;br /&gt;마지막으로,&amp;nbsp;많은&amp;nbsp;사람들이&amp;nbsp;간과하는&amp;nbsp;것이&amp;nbsp;커뮤니케이션&amp;nbsp;능력입니다.&amp;nbsp;데이터&amp;nbsp;분석&amp;nbsp;결과를&amp;nbsp;기술적&amp;nbsp;배경이&amp;nbsp;없는&amp;nbsp;경영진이나&amp;nbsp;동료들에게&amp;nbsp;이해하기&amp;nbsp;쉽게&amp;nbsp;설명할&amp;nbsp;수&amp;nbsp;있어야&amp;nbsp;해요.&amp;nbsp;복잡한&amp;nbsp;통계&amp;nbsp;분석&amp;nbsp;결과를&amp;nbsp;직관적인&amp;nbsp;시각화로&amp;nbsp;표현하고,&amp;nbsp;그것이&amp;nbsp;비즈니스에&amp;nbsp;미치는&amp;nbsp;영향을&amp;nbsp;스토리텔링으로&amp;nbsp;전달할&amp;nbsp;수&amp;nbsp;있어야&amp;nbsp;합니다.&lt;br /&gt;&lt;br /&gt;##&amp;nbsp; &amp;nbsp;통계적&amp;nbsp;의사결정&amp;nbsp;모형의&amp;nbsp;이해&lt;br /&gt;&lt;br /&gt;데이터&amp;nbsp;기반&amp;nbsp;의사결정을&amp;nbsp;체계적으로&amp;nbsp;수행하기&amp;nbsp;위해서는&amp;nbsp;일정한&amp;nbsp;프레임워크가&amp;nbsp;필요합니다.&amp;nbsp;가장&amp;nbsp;널리&amp;nbsp;사용되는&amp;nbsp;것&amp;nbsp;중&amp;nbsp;하나가&amp;nbsp;CRISP-DM&amp;nbsp;모형입니다.&amp;nbsp;이는&amp;nbsp;비즈니스&amp;nbsp;이해에서&amp;nbsp;시작해서&amp;nbsp;데이터&amp;nbsp;이해,&amp;nbsp;데이터&amp;nbsp;준비,&amp;nbsp;모델링,&amp;nbsp;평가,&amp;nbsp;배포까지의&amp;nbsp;순환적&amp;nbsp;과정을&amp;nbsp;제시합니다.&lt;br /&gt;&lt;br /&gt;예를&amp;nbsp;들어&amp;nbsp;온라인&amp;nbsp;쇼핑몰에서&amp;nbsp;고객&amp;nbsp;이탈을&amp;nbsp;예측하고&amp;nbsp;싶다고&amp;nbsp;해봅시다.&amp;nbsp;먼저&amp;nbsp;비즈니스&amp;nbsp;이해&amp;nbsp;단계에서는&amp;nbsp;왜&amp;nbsp;고객&amp;nbsp;이탈&amp;nbsp;예측이&amp;nbsp;중요한지,&amp;nbsp;어떤&amp;nbsp;비즈니스&amp;nbsp;가치를&amp;nbsp;창출할&amp;nbsp;수&amp;nbsp;있는지&amp;nbsp;명확히&amp;nbsp;해야&amp;nbsp;합니다.&amp;nbsp;데이터&amp;nbsp;이해&amp;nbsp;단계에서는&amp;nbsp;어떤&amp;nbsp;데이터가&amp;nbsp;있는지,&amp;nbsp;데이터의&amp;nbsp;품질은&amp;nbsp;어떤지&amp;nbsp;파악합니다.&amp;nbsp;데이터&amp;nbsp;준비&amp;nbsp;단계에서는&amp;nbsp;분석에&amp;nbsp;적합하도록&amp;nbsp;데이터를&amp;nbsp;정제하고&amp;nbsp;변환합니다.&amp;nbsp;모델링&amp;nbsp;단계에서는&amp;nbsp;적절한&amp;nbsp;머신러닝&amp;nbsp;알고리즘을&amp;nbsp;선택하고&amp;nbsp;모델을&amp;nbsp;구축합니다.&amp;nbsp;평가&amp;nbsp;단계에서는&amp;nbsp;모델의&amp;nbsp;성능을&amp;nbsp;검증하고,&amp;nbsp;마지막&amp;nbsp;배포&amp;nbsp;단계에서는&amp;nbsp;실제&amp;nbsp;업무에&amp;nbsp;적용합니다.&lt;br /&gt;&lt;br /&gt;또&amp;nbsp;다른&amp;nbsp;중요한&amp;nbsp;프레임워크는&amp;nbsp;통계적&amp;nbsp;가설검정입니다.&amp;nbsp;이는&amp;nbsp;특정&amp;nbsp;주장이나&amp;nbsp;가설이&amp;nbsp;통계적으로&amp;nbsp;의미가&amp;nbsp;있는지&amp;nbsp;객관적으로&amp;nbsp;판단하는&amp;nbsp;방법입니다.&amp;nbsp;예를&amp;nbsp;들어&amp;nbsp;새로운&amp;nbsp;웹사이트&amp;nbsp;디자인이&amp;nbsp;기존&amp;nbsp;디자인보다&amp;nbsp;전환율을&amp;nbsp;높인다고&amp;nbsp;주장할&amp;nbsp;때,&amp;nbsp;이를&amp;nbsp;단순히&amp;nbsp;&quot;느낌상&amp;nbsp;좋아&amp;nbsp;보인다&quot;가&amp;nbsp;아니라&amp;nbsp;통계적으로&amp;nbsp;검증할&amp;nbsp;수&amp;nbsp;있어야&amp;nbsp;합니다.&lt;br /&gt;&lt;br /&gt;##&amp;nbsp; &amp;nbsp;실무에서의&amp;nbsp;균형잡힌&amp;nbsp;접근&lt;br /&gt;&lt;br /&gt;하지만&amp;nbsp;실제&amp;nbsp;업무에서는&amp;nbsp;데이터와&amp;nbsp;직관을&amp;nbsp;완전히&amp;nbsp;분리해서&amp;nbsp;생각할&amp;nbsp;수&amp;nbsp;없습니다.&amp;nbsp;가장&amp;nbsp;효과적인&amp;nbsp;의사결정은&amp;nbsp;두&amp;nbsp;방식을&amp;nbsp;적절히&amp;nbsp;조합할&amp;nbsp;때&amp;nbsp;나옵니다.&amp;nbsp;직관으로&amp;nbsp;가설을&amp;nbsp;세우고&amp;nbsp;데이터로&amp;nbsp;검증하거나,&amp;nbsp;데이터&amp;nbsp;분석&amp;nbsp;결과를&amp;nbsp;직관과&amp;nbsp;경험으로&amp;nbsp;해석하는&amp;nbsp;것이죠.&lt;br /&gt;&lt;br /&gt;예를&amp;nbsp;들어,&amp;nbsp;데이터&amp;nbsp;분석&amp;nbsp;결과&amp;nbsp;특정&amp;nbsp;고객&amp;nbsp;그룹의&amp;nbsp;구매율이&amp;nbsp;급격히&amp;nbsp;떨어졌다고&amp;nbsp;나타났다면,&amp;nbsp;이것만으로는&amp;nbsp;원인을&amp;nbsp;알&amp;nbsp;수&amp;nbsp;없습니다.&amp;nbsp;이때&amp;nbsp;현장&amp;nbsp;경험이&amp;nbsp;풍부한&amp;nbsp;마케팅&amp;nbsp;담당자의&amp;nbsp;직관이&amp;nbsp;&quot;아,&amp;nbsp;최근에&amp;nbsp;경쟁사가&amp;nbsp;대대적인&amp;nbsp;할인&amp;nbsp;이벤트를&amp;nbsp;했었지&quot;라는&amp;nbsp;통찰을&amp;nbsp;제공할&amp;nbsp;수&amp;nbsp;있어요.&amp;nbsp;반대로&amp;nbsp;&quot;고객들이&amp;nbsp;모바일&amp;nbsp;앱을&amp;nbsp;더&amp;nbsp;선호할&amp;nbsp;것&amp;nbsp;같다&quot;는&amp;nbsp;직관적&amp;nbsp;가설을&amp;nbsp;세웠다면,&amp;nbsp;이를&amp;nbsp;A/B&amp;nbsp;테스트나&amp;nbsp;사용자&amp;nbsp;행동&amp;nbsp;데이터&amp;nbsp;분석으로&amp;nbsp;검증할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;결국&amp;nbsp;이&amp;nbsp;섹션에서&amp;nbsp;가장&amp;nbsp;중요한&amp;nbsp;것은&amp;nbsp;데이터&amp;nbsp;분석의&amp;nbsp;가치를&amp;nbsp;이해하는&amp;nbsp;것입니다.&amp;nbsp;데이터&amp;nbsp;기반&amp;nbsp;의사결정이&amp;nbsp;만능은&amp;nbsp;아니지만,&amp;nbsp;객관성과&amp;nbsp;재현성,&amp;nbsp;그리고&amp;nbsp;예측&amp;nbsp;가능성이라는&amp;nbsp;강력한&amp;nbsp;장점을&amp;nbsp;가지고&amp;nbsp;있다는&amp;nbsp;점을&amp;nbsp;알아야&amp;nbsp;합니다.&amp;nbsp;동시에&amp;nbsp;데이터&amp;nbsp;사이언티스트로서&amp;nbsp;성공하기&amp;nbsp;위해서는&amp;nbsp;기술적&amp;nbsp;역량뿐만&amp;nbsp;아니라&amp;nbsp;비즈니스&amp;nbsp;이해력과&amp;nbsp;커뮤니케이션&amp;nbsp;능력까지&amp;nbsp;갖춰야&amp;nbsp;한다는&amp;nbsp;점도&amp;nbsp;기억해두세요.&lt;/p&gt;</description>
      <author>ISFP의 블로그</author>
      <guid isPermaLink="true">https://resultofeffort.tistory.com/152</guid>
      <comments>https://resultofeffort.tistory.com/152#entry152comment</comments>
      <pubDate>Tue, 30 Sep 2025 18:23:05 +0900</pubDate>
    </item>
    <item>
      <title>[오류Error] RateLimitError: Error code: 429 - {'error': {'message': 'You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-erro</title>
      <link>https://resultofeffort.tistory.com/151</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;OpenAI 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;b&gt;&amp;gt; &amp;ldquo;You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: &lt;a href=&quot;https://platform.openai.com/docs/guides/error-codes/api-errors.&quot;&gt;https://platform.openai.com/docs/guides/error-codes/api-errors.&lt;/a&gt;&amp;rdquo; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;[오류] RateLimitError: 429 &amp;ndash; 현재 할당량을 초과했습니다. 요금제 및 결제 정보를 확인해 주세요.&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;&quot;&lt;b&gt;&lt;a href=&quot;https://platform.openai.com/docs/guides/error-codes/api-errors.&quot;&gt;https://platform.openai.com/docs/guides/error-codes/api-errors.&lt;/a&gt;&quot; 사이트에 접속하여&lt;/b&gt;&lt;br /&gt;에러 설명(429)을 살펴보니 &lt;b&gt;&amp;ldquo;API 월간 사용량 한도에 도달했거나, 선불 크레딧을 모두 사용했음을 나타냅니다.&amp;rdquo; 라고 적혀있었다.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;707&quot; data-origin-height=&quot;428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2pHaM/btsOu4zg47U/1FyS8D6IksldAICSq4DTS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2pHaM/btsOu4zg47U/1FyS8D6IksldAICSq4DTS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2pHaM/btsOu4zg47U/1FyS8D6IksldAICSq4DTS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2pHaM%2FbtsOu4zg47U%2F1FyS8D6IksldAICSq4DTS0%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;707&quot; height=&quot;428&quot; data-origin-width=&quot;707&quot; data-origin-height=&quot;428&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 난 현재 유료 계정을 사용 중이고 과도한 API 호출을 하지 않았는데도이런 에러가 발생했어서 .. 이유를 찾는데 좀 헤매다가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확인해보니 &amp;nbsp;&lt;b&gt;결제 수단(신용카드)이 등록되어 있지 않아 Auto-recharge가 작동하지 않았기 때문&lt;/b&gt;이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론적으로&amp;nbsp;Payment methods에 카드 등록을 해주니 해결이 되었음.&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. OpenAI Console &amp;rarr; Billing &amp;rarr; Payment methods &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2388&quot; data-origin-height=&quot;1172&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b94fgI/btsOt8bsdqg/FU1kRAXYNOvxWF5KKO4JU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b94fgI/btsOt8bsdqg/FU1kRAXYNOvxWF5KKO4JU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b94fgI/btsOt8bsdqg/FU1kRAXYNOvxWF5KKO4JU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb94fgI%2FbtsOt8bsdqg%2FFU1kRAXYNOvxWF5KKO4JU1%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;2388&quot; height=&quot;1172&quot; data-origin-width=&quot;2388&quot; data-origin-height=&quot;1172&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;2.&lt;/span&gt; Auto-recharge 설정 확인&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;- Billing &amp;rarr; Overview &amp;rarr; Auto-recharge가 On 상태인지 확인 &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;- (최소 잔액 $&lt;span&gt;5&lt;/span&gt; 이하 시, 자동으로 $&lt;span&gt;100&lt;/span&gt; 충전) &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;카드등록 해두니 자동으로 충전이 잘 된다..!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2836&quot; data-origin-height=&quot;1382&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwjL20/btsOuQnLtQi/KNRREUnMLMSPt9KWtwhAF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwjL20/btsOuQnLtQi/KNRREUnMLMSPt9KWtwhAF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwjL20/btsOuQnLtQi/KNRREUnMLMSPt9KWtwhAF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwjL20%2FbtsOuQnLtQi%2FKNRREUnMLMSPt9KWtwhAF1%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;2836&quot; height=&quot;1382&quot; data-origin-width=&quot;2836&quot; data-origin-height=&quot;1382&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;3.&lt;/span&gt; API 호출 재실행&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>오류Error</category>
      <category>AI개발</category>
      <category>API</category>
      <category>api오류</category>
      <category>autorecharge</category>
      <category>openai</category>
      <category>Python</category>
      <category>ratelimiterror</category>
      <category>결제관리</category>
      <category>트러블슈팅</category>
      <category>할당량초과</category>
      <author>ISFP의 블로그</author>
      <guid isPermaLink="true">https://resultofeffort.tistory.com/151</guid>
      <comments>https://resultofeffort.tistory.com/151#entry151comment</comments>
      <pubDate>Tue, 10 Jun 2025 14:09:35 +0900</pubDate>
    </item>
    <item>
      <title>[오류Error] Failed to start project studioError invoking remote method 'up': Error: Docker not installed or not running: ExecaError: Command failed with exit code 1: which docker</title>
      <link>https://resultofeffort.tistory.com/150</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #232425; text-align: start;&quot;&gt;LangGraph를 공부하던 중 Agentic Application을 만들기 위한 IDE인 LangGraph Studio라는 서비스를 알게 되었습니다. 이 도구가 AI 에이전트 개발을 시각적으로 도와준다고 하여 설치해보기로 했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;%EC%84%A4%EC%B9%98-%EA%B3%BC%EC%A0%95&quot; style=&quot;list-style-type: none; background-color: #ffffff; color: #232425; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;설치 과정&lt;/h2&gt;
&lt;p style=&quot;list-style-type: none; background-color: #ffffff; color: #232425; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;LangGraph Studio는 현재 맥북에서만 지원되는 것 같습니다. 공식 사이트에서 dmg 파일을 다운로드하여 설치했습니다.&lt;/p&gt;
&lt;p style=&quot;list-style-type: none; background-color: #ffffff; color: #232425; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;%EC%B2%AB-%EB%B2%88%EC%A7%B8-%EC%98%A4%EB%A5%98%3A-docker-%EA%B4%80%EB%A0%A8-%EB%AC%B8%EC%A0%9C&quot; style=&quot;list-style-type: none; background-color: #ffffff; color: #232425; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;첫 번째 오류: Docker 관련 문제&lt;/h2&gt;
&lt;p style=&quot;list-style-type: none; background-color: #ffffff; color: #232425; text-align: start;&quot; 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;602&quot; data-origin-height=&quot;235&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bf3Zhd/btsNoZ7Kpi1/MYtoKj33ddJkooEX18H8vK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bf3Zhd/btsNoZ7Kpi1/MYtoKj33ddJkooEX18H8vK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bf3Zhd/btsNoZ7Kpi1/MYtoKj33ddJkooEX18H8vK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbf3Zhd%2FbtsNoZ7Kpi1%2FMYtoKj33ddJkooEX18H8vK%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;602&quot; height=&quot;235&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;235&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1744967150936&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Failed to start project studio
Error invoking remote method 'up': Error: Docker not installed or not running: ExecaError: Command failed with exit code 1: which docker&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #232425; text-align: start;&quot;&gt;(도커가 필요한 줄 몰랐다.. 그래서 바로 Docker 를 설치해주었다.)&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;list-style-type: none; background-color: #ffffff; color: #232425; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;figure id=&quot;og_1744967889598&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Docker Desktop: The #1 Containerization Tool for Developers | Docker&quot; data-og-description=&quot;Docker Desktop is collaborative containerization software for developers. Get started and download Docker Desktop today on Mac, Windows, or Linux.&quot; data-og-host=&quot;www.docker.com&quot; data-og-source-url=&quot;https://www.docker.com/products/docker-desktop/&quot; data-og-url=&quot;https://www.docker.com/products/docker-desktop/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dEfGAM/hyYFzCcSmM/b0tjK3ShYlyB8usdKzb9SK/img.png?width=1110&amp;amp;height=580&amp;amp;face=0_0_1110_580,https://scrap.kakaocdn.net/dn/b5pN7I/hyYIcM7jrq/aQMRKGkDqkyvW1O1FGtkD1/img.png?width=1110&amp;amp;height=580&amp;amp;face=0_0_1110_580&quot;&gt;&lt;a href=&quot;https://www.docker.com/products/docker-desktop/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.docker.com/products/docker-desktop/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dEfGAM/hyYFzCcSmM/b0tjK3ShYlyB8usdKzb9SK/img.png?width=1110&amp;amp;height=580&amp;amp;face=0_0_1110_580,https://scrap.kakaocdn.net/dn/b5pN7I/hyYIcM7jrq/aQMRKGkDqkyvW1O1FGtkD1/img.png?width=1110&amp;amp;height=580&amp;amp;face=0_0_1110_580');&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;Docker Desktop: The #1 Containerization Tool for Developers | Docker&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Docker Desktop is collaborative containerization software for developers. Get started and download Docker Desktop today on Mac, Windows, or Linux.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.docker.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #232425; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;list-style-type: inherit;&quot;&gt;&lt;b&gt;Docker 설치 확인하기&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Docker가 설치되어 있지 않다면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.docker.com/products/docker-desktop/&quot;&gt;Docker 공식 사이트&lt;/a&gt;에서 운영체제에 맞는 Docker Desktop을 다운로드하여 설치한다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit;&quot;&gt;&lt;b&gt;Docker 실행 확인하기&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Docker Desktop을 실행하고, 상태 표시기(시스템 트레이/메뉴바)에서 Docker가 실행 중인지 확인한다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit;&quot;&gt;&lt;b&gt;Docker 버전 확인하기&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;LangGraph Studio는 Docker Compose 버전 2.22.0 이상을 요구합니다. 터미널에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;docker-compose --version&lt;span&gt;&amp;nbsp;&lt;/span&gt;명령으로 버전을 확인하고, 필요시 업데이트한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 style=&quot;list-style-type: none; background-color: #ffffff; color: #232425; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;%EB%91%90-%EB%B2%88%EC%A7%B8-%EC%98%A4%EB%A5%98%3A-.env-%ED%8C%8C%EC%9D%BC-%EB%AC%B8%EC%A0%9C&quot; style=&quot;list-style-type: none; background-color: #ffffff; color: #232425; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;두 번째 오류: .env 파일 문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #232425; text-align: start;&quot;&gt;Docker를 설치하고 실행한 후 LangGraph Studio를 다시 시작했더니 오류 메시지가 바뀌었다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;565&quot; data-origin-height=&quot;201&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9LdKX/btsNq0ySK88/GNGiG3NtxK3UlGRfuYezqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9LdKX/btsNq0ySK88/GNGiG3NtxK3UlGRfuYezqk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9LdKX/btsNq0ySK88/GNGiG3NtxK3UlGRfuYezqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9LdKX%2FbtsNq0ySK88%2FGNGiG3NtxK3UlGRfuYezqk%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;565&quot; height=&quot;201&quot; data-origin-width=&quot;565&quot; data-origin-height=&quot;201&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1744967433634&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Failed to start project studio
Error invoking remote method 'up': Error: Could not read env file: /Users/path/to/project/studio/.env&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #232425; text-align: start;&quot;&gt;LangGraph Studio가 API 키와 같은 환경 변수를 담고 있는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;.env&lt;span style=&quot;background-color: #ffffff; color: #232425; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;파일을 찾을 수 없어서 발생한 문제였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95-1&quot; style=&quot;list-style-type: none; background-color: #ffffff; color: #232425; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p style=&quot;list-style-type: none; background-color: #ffffff; color: #232425; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다행히 제가 사용하려던 프로젝트 폴더에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;.env.example&lt;span&gt;&amp;nbsp;&lt;/span&gt;파일이 이미 존재했습니다. 이 파일은 필요한 환경 변수의 템플릿 역할을 합니다.&lt;/p&gt;
&lt;p style=&quot;list-style-type: none; background-color: #ffffff; color: #232425; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1. .env.example&lt;span&gt;&amp;nbsp;&lt;/span&gt;파일을&lt;span&gt;&amp;nbsp;&lt;/span&gt;.env&lt;span&gt;&amp;nbsp;&lt;/span&gt;파일로 복사해주었습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1744968012024&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cp /path/to/project/studio/.env.example /path/to/project/studio/.env&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&amp;nbsp;텍스트 에디터로&lt;span&gt;&amp;nbsp;&lt;/span&gt;.env&lt;span&gt;&amp;nbsp;&lt;/span&gt;파일을 열고 OpenAI API 키를 입력했습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1744968033050&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;OPENAI_API_KEY=sk-my_api_key_here&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LangGraph Studio를 재시작했더니 드디어 정상적으로 로드 성공!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1916&quot; data-origin-height=&quot;965&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HlXqT/btsNrgBufSo/TY7DgnH3UmpZNMUS2vCjd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HlXqT/btsNrgBufSo/TY7DgnH3UmpZNMUS2vCjd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HlXqT/btsNrgBufSo/TY7DgnH3UmpZNMUS2vCjd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHlXqT%2FbtsNrgBufSo%2FTY7DgnH3UmpZNMUS2vCjd0%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;1916&quot; height=&quot;965&quot; data-origin-width=&quot;1916&quot; data-origin-height=&quot;965&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>오류Error</category>
      <category>Docker</category>
      <category>error</category>
      <category>langgraph</category>
      <category>langgraph studio</category>
      <category>해결</category>
      <author>ISFP의 블로그</author>
      <guid isPermaLink="true">https://resultofeffort.tistory.com/150</guid>
      <comments>https://resultofeffort.tistory.com/150#entry150comment</comments>
      <pubDate>Fri, 18 Apr 2025 18:21:55 +0900</pubDate>
    </item>
    <item>
      <title>[오류Error] VS Code Remote-SSH: &amp;quot;원격 호스트가 VS Code Server를 실행하기 위한 필수 구성 요소를 충족하지 않습니다&amp;quot; 오류 해결 후기</title>
      <link>https://resultofeffort.tistory.com/149</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;could&amp;nbsp;not&amp;nbsp;establish&amp;nbsp;connection&amp;nbsp;to&amp;nbsp;&quot;서버ip&quot;:&amp;nbsp;the&amp;nbsp;remote&amp;nbsp;host&amp;nbsp;does&amp;nbsp;not&amp;nbsp;meet&amp;nbsp;the&amp;nbsp;prerequisites&amp;nbsp;for&amp;nbsp;running&amp;nbsp;vs&amp;nbsp;code&amp;nbsp;server.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;s&gt;2시간 30분 삽질 완료^^&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;s&gt;그래도 해결했으니 진짜 다행...........&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;문제 상황&lt;/b&gt;&lt;/h2&gt;
&lt;p data-end=&quot;501&quot; data-start=&quot;408&quot; data-ke-size=&quot;size18&quot;&gt;오늘 출근해서 VS Code에서 Remote - SSH 기능을 사용하려고 했는데,&lt;br /&gt;SSH로는 접속이 잘 되는데도 불구하고 아래와 같은 에러 메시지가 반복적으로 발생하였음.&lt;/p&gt;
&lt;p data-end=&quot;501&quot; data-start=&quot;408&quot; data-ke-size=&quot;size18&quot;&gt;(분명 어제까지는 멀쩡하게 접속이 되었단 말이지.ㅠㅠㅠ)&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;&quot;원격 호스트가 VS Code Server를 실행하기 위한 필수 구성 요소를 충족하지 않습니다.&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;나의 환경&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;로컬 OS: macOS Sonoma 14.4.1 (Darwin x64 23.5.0, Apple Silicon)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;로컬 VS Code 버전: 1.99.2 (최신 버전)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;서버&lt;/span&gt; OS: Ubuntu 18.04 LTS (glibc: 2.27 / Node.js: v14.16.0)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;시도했던 해결 방법들 (실패)&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/etc/hosts 정리&lt;/li&gt;
&lt;li&gt;환경 변수 / 프록시 확인&lt;/li&gt;
&lt;li&gt;.zshrc / .bashrc 초기화&lt;/li&gt;
&lt;li&gt;known_hosts 삭제&lt;/li&gt;
&lt;li&gt;VS Code 초기화 &amp;amp; 재설치&lt;/li&gt;
&lt;li&gt;settings.json 수동 생성&lt;/li&gt;
&lt;li&gt;Remote-SSH 확장 재설치&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;rarr; &lt;b&gt;모두 실패.&lt;/b&gt;&lt;br /&gt;&lt;b&gt;원인은 glibc 2.27 환경에서 VS Code 최신 버전이 원격 서버 환경을 차단하기 때문.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;최종 해결 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;결론부터 말하자면, &quot;VS Code 버전 다운그레이드 + 자동 업데이트 비활성화&quot;가 답이었습니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;해결 순서 정리&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. VS Code 1.85.1 버전 설치 (기존에 설치 되어있는 Vs Code는 제거해주었음)&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;livescript&quot;&gt;&lt;code&gt;# 기존 VS Code 삭제
sudo rm -rf /Applications/Visual\ Studio\ Code.app
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;a title=&quot;https://code.visualstudio.com/updates/v1_85&quot; href=&quot;https://code.visualstudio.com/updates/v1_85&quot;&gt;  다운로드 링크 (VS Code 1.85.1)&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 업데이트 모드 끄기 (처음에 이거 안했더니 자동 업데이트 되서 다시 설치함^^)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;VS Code 실행 &amp;rarr; Cmd + , &amp;rarr; &quot;업데이트&quot; 검색 &amp;rarr; &lt;b&gt;응용 프로그램 &amp;gt; 업데이트 모드: &quot;none&quot;&lt;/b&gt; 으로 설정&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;272&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bs7i0f/btsNh74t65F/2qy9uDkg4nLKX54bCqYpa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bs7i0f/btsNh74t65F/2qy9uDkg4nLKX54bCqYpa1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bs7i0f/btsNh74t65F/2qy9uDkg4nLKX54bCqYpa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbs7i0f%2FbtsNh74t65F%2F2qy9uDkg4nLKX54bCqYpa1%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;583&quot; height=&quot;272&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;272&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 확장 프로그램에서 Remote - SSH 를 제거 후 다시 설치&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. 서버 접속 완료&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;참고&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1744340712023&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;The remote host may not meet vs code server's prerequisites for glibc and libstdc++ vscod&quot; data-og-description=&quot;I was working on the host server. Everything was great till yesterday and today when I start my server, suddenly error occurs in VS code. And my server is not connecting anymore. What should I do? ...&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/69626028/the-remote-host-may-not-meet-vs-code-servers-prerequisites-for-glibc-and-libstd&quot; data-og-url=&quot;https://stackoverflow.com/questions/69626028/the-remote-host-may-not-meet-vs-code-servers-prerequisites-for-glibc-and-libstd&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/exIS7/hyYCbbadOz/QliSDw8BCJnDwGm3k3eRDK/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316,https://scrap.kakaocdn.net/dn/fzUoS/hyYEzPr4rm/wT4UJtKyoxvslkTVWTIVuk/img.png?width=514&amp;amp;height=630&amp;amp;face=0_0_514_630,https://scrap.kakaocdn.net/dn/ibHlR/hyYEAU88GM/bmmOhTbDXkCrpX7KJksPk1/img.png?width=1482&amp;amp;height=200&amp;amp;face=0_0_1482_200&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/69626028/the-remote-host-may-not-meet-vs-code-servers-prerequisites-for-glibc-and-libstd&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/69626028/the-remote-host-may-not-meet-vs-code-servers-prerequisites-for-glibc-and-libstd&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/exIS7/hyYCbbadOz/QliSDw8BCJnDwGm3k3eRDK/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316,https://scrap.kakaocdn.net/dn/fzUoS/hyYEzPr4rm/wT4UJtKyoxvslkTVWTIVuk/img.png?width=514&amp;amp;height=630&amp;amp;face=0_0_514_630,https://scrap.kakaocdn.net/dn/ibHlR/hyYEAU88GM/bmmOhTbDXkCrpX7KJksPk1/img.png?width=1482&amp;amp;height=200&amp;amp;face=0_0_1482_200');&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;The remote host may not meet vs code server's prerequisites for glibc and libstdc++ vscod&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;I was working on the host server. Everything was great till yesterday and today when I start my server, suddenly error occurs in VS code. And my server is not connecting anymore. What should I do? ...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1744340736574&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;The remote host may not meet VS Code Server's prerequisites for glibc and libstdc++ &amp;middot; Issue #9501 &amp;middot; microsoft/vscode-remote-re&quot; data-og-description=&quot;There was no problem with remote SSH until 3 days ago. Now I'm getting the following error and I can't connect to the server The remote host may not meet VS Code Server's prerequisites for glibc an...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/microsoft/vscode-remote-release/issues/9501&quot; data-og-url=&quot;https://github.com/microsoft/vscode-remote-release/issues/9501&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/wD213/hyYCcnyoYb/3r00jA2kRfG3E1qWxqdKrk/img.png?width=1200&amp;amp;height=600&amp;amp;face=967_121_1049_211,https://scrap.kakaocdn.net/dn/Blvw5/hyYCgjcG96/5kWCOKFaFo5kfdQcoxlhM0/img.png?width=1200&amp;amp;height=600&amp;amp;face=967_121_1049_211&quot;&gt;&lt;a href=&quot;https://github.com/microsoft/vscode-remote-release/issues/9501&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/microsoft/vscode-remote-release/issues/9501&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/wD213/hyYCcnyoYb/3r00jA2kRfG3E1qWxqdKrk/img.png?width=1200&amp;amp;height=600&amp;amp;face=967_121_1049_211,https://scrap.kakaocdn.net/dn/Blvw5/hyYCgjcG96/5kWCOKFaFo5kfdQcoxlhM0/img.png?width=1200&amp;amp;height=600&amp;amp;face=967_121_1049_211');&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;The remote host may not meet VS Code Server's prerequisites for glibc and libstdc++ &amp;middot; Issue #9501 &amp;middot; microsoft/vscode-remote-re&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;There was no problem with remote SSH until 3 days ago. Now I'm getting the following error and I can't connect to the server The remote host may not meet VS Code Server's prerequisites for glibc an...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>오류Error</category>
      <category>glibc</category>
      <category>SSH</category>
      <category>vsode</category>
      <author>ISFP의 블로그</author>
      <guid isPermaLink="true">https://resultofeffort.tistory.com/149</guid>
      <comments>https://resultofeffort.tistory.com/149#entry149comment</comments>
      <pubDate>Fri, 11 Apr 2025 11:55:49 +0900</pubDate>
    </item>
    <item>
      <title>[pytorch] 시퀀스-투-시퀀스(seq2seq)</title>
      <link>https://resultofeffort.tistory.com/148</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;seq2seq의 기본 구조와 작동 원리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Sequence-to-Sequence(seq2seq) 모델은&amp;nbsp;&lt;b&gt;한 시퀀스&lt;/b&gt;를&amp;nbsp;&lt;b&gt;다른 시퀀스로 변환&lt;/b&gt;하는 신경망 모델입니다.&lt;br /&gt;예를 들어, &quot;안녕하세요&quot;라는 한국어 문장을 &quot;Hello&quot;라는 영어 문장으로 번역하는 것처럼, 입력 시퀀스를 받아서 다른 형태의 출력 시퀀스를 생성합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;인코더(Encoder)-디코더(Decoder) 아키텍처&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;seq2seq 모델은 크게 두 부분으로 구성됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;인코더 (Encoder)&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;인코더는 입력 시퀀스를 처리하여&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;컨텍스트 벡터(Context Vector)를&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;* 시퀀스: 시간적 순서 또는 일정한 순서에 따라 배열된 데이터의 집합을 의미함. 이는 데이터가 순차적으로 의존관계를 가지며, 앞뒤의 데이터가 서로 연결되어 있는 경우를 말함. 예를 들어, 문장, 음성, 음악, 비디오 등이 모두 시퀀스 데이터의 예임.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;인코더는 다음과 같이 동작합니다.&lt;br /&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-origin-width=&quot;481&quot; data-origin-height=&quot;330&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VkIsk/btsLBh2lXH4/VG3rtDgfW2pDE1FC4hsHsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VkIsk/btsLBh2lXH4/VG3rtDgfW2pDE1FC4hsHsK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VkIsk/btsLBh2lXH4/VG3rtDgfW2pDE1FC4hsHsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVkIsk%2FbtsLBh2lXH4%2FVG3rtDgfW2pDE1FC4hsHsK%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;313&quot; height=&quot;215&quot; data-origin-width=&quot;481&quot; data-origin-height=&quot;330&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;문장 &quot;I love cats&quot;를 예로 들면&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;1.&amp;nbsp;&lt;b&gt;첫 번째 입력: &quot;I&quot;&lt;/b&gt;&lt;br /&gt;- &lt;b&gt;입력&lt;/b&gt; &lt;br /&gt;단어 &amp;ldquo;l&amp;rdquo;의 임베딩 벡터 .&lt;br /&gt;초기 hidden state : 보통 [0, 0, 0] 또는 무작위 값으로 초기화.&lt;br /&gt;- &lt;b&gt;결과&lt;/b&gt; &lt;br /&gt;hidden state1: [0.2, -0.1, 0.1]&lt;br /&gt;&amp;nbsp;&lt;br /&gt;2.&amp;nbsp;&lt;b&gt;두 번째 입력: &amp;ldquo;love&amp;rdquo;&lt;/b&gt;&lt;br /&gt;- &lt;b&gt;입력&lt;/b&gt;&lt;br /&gt;단어 &amp;ldquo;love&amp;rdquo;의 임베딩 벡터.&lt;br /&gt;이전 hidden state : [0.2, -0.1, 0.1].&lt;br /&gt;- &lt;b&gt;결과&lt;/b&gt; &lt;br /&gt;hidden state2: [0.5, -0.2, 0.3].&lt;br /&gt;&amp;nbsp;&lt;br /&gt;3.&amp;nbsp;&lt;b&gt;세 번째 입력: &amp;ldquo;cat&amp;rdquo;&lt;/b&gt;&lt;br /&gt;- &lt;b&gt;입력&lt;/b&gt;&lt;br /&gt;단어 &amp;ldquo;cat&amp;rdquo;의 임베딩 벡터.&lt;br /&gt;이전 hidden state : [0.5, -0.2, 0.3].&lt;br /&gt;- &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;결과 &lt;br /&gt;hidden state3: [0.7, -0.3, 0.4].&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;이와 같이, 입력 단어들은 순차적으로 RNN을 통과하면서 hidden state를 업데이트하며, 입력 시퀀스의 마지막 hidden state가 컨텍스트 벡터로 사용됩니다.&lt;/b&gt;&lt;/span&gt;&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-origin-width=&quot;880&quot; data-origin-height=&quot;412&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uZHXn/btsLAa9F3sq/zyK37ByWQStyLMxKeUEiL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uZHXn/btsLAa9F3sq/zyK37ByWQStyLMxKeUEiL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uZHXn/btsLAa9F3sq/zyK37ByWQStyLMxKeUEiL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuZHXn%2FbtsLAa9F3sq%2FzyK37ByWQStyLMxKeUEiL1%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;525&quot; height=&quot;246&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;412&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;컨텍스트 벡터(context vector) 생성&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;- 마지막 hidden state : [0.7, -0.3, 0.4].&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;- 이 벡터는 입력 시퀀스의 정보를 압축한&amp;nbsp;컨텍스트 벡터로 사용됩니다.&lt;br /&gt;- 디코더는 이 컨텍스트 벡터를 바탕으로 출력 시퀀스를 생성합니다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;* 컨텍스트 벡터(마지막 hidden state)는 입력 시퀀스 전체를 요약한 벡터입니다. 이 벡터는 입력 시퀀스에 대한 모든 중요한 정보를 담고 있으며, 디코더가 이를 기반으로 출력 시퀀스를 생성합니다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;컨텍스트벡터는 &lt;b&gt;입력 문장의 길이와 관계없이 항상 같은 크기&lt;/b&gt;의 벡터로 변환합니다.&lt;br /&gt;예를 들어&lt;br /&gt;&amp;nbsp;- &quot;I&amp;nbsp;love&amp;nbsp;cats&quot;&amp;nbsp;(3 단어)&amp;nbsp;후&amp;rarr;&amp;nbsp;[0.8,&amp;nbsp;-0.5,&amp;nbsp;0.3]&amp;nbsp;(3차원&amp;nbsp;벡터)&lt;br /&gt;&amp;nbsp;- &quot;I&amp;nbsp;really&amp;nbsp;love&amp;nbsp;cute&amp;nbsp;cats&quot;&amp;nbsp;(5 단어)&amp;nbsp;&amp;rarr;&amp;nbsp;[0.7,&amp;nbsp;-0.6,&amp;nbsp;0.4]&amp;nbsp;(같은&amp;nbsp;3차원&amp;nbsp;벡터)&lt;br /&gt;이렇게 다른 길이의 문장도 같은 크기의 벡터로 표현됩니다.&lt;br /&gt;&lt;br /&gt;이런 과정을 통해 인코더는 가변 길이의 입력 문장을 &lt;b&gt;고정된 크기의 의미 있는 벡터&lt;/b&gt;로 변환할 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;디코더 (Decoder)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;디코더는 인코더에서 받은 &lt;b&gt;컨텍스트 벡터&lt;/b&gt;를 바탕으로 출력 시퀀스를 생성합니다. 디코더도 RNN 기반 구조를 가지며, 다음과 같이 동작합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;412&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uZHXn/btsLAa9F3sq/zyK37ByWQStyLMxKeUEiL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uZHXn/btsLAa9F3sq/zyK37ByWQStyLMxKeUEiL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uZHXn/btsLAa9F3sq/zyK37ByWQStyLMxKeUEiL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuZHXn%2FbtsLAa9F3sq%2FzyK37ByWQStyLMxKeUEiL1%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;525&quot; height=&quot;246&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;412&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1️⃣ &lt;b&gt;컨텍스트 벡터로 초기화&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;인코더에서 생성된 컨텍스트 벡터를 첫 hidden state로 사용하여 출력을 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- &lt;b&gt;초기 hidden state&lt;/b&gt;: &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;컨텍스트 벡터 [0.7, -0.3, 0.4]&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- &lt;b&gt;초기 입력&lt;/b&gt;: 시작 토큰 &lt;span&gt;&amp;lt;sos&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2️⃣ &lt;b&gt;출력 시퀀스 생성&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;입력 토큰(&lt;span&gt;&amp;lt; sos&amp;gt;&lt;/span&gt;)&lt;/b&gt;과 &lt;b&gt;hidden state&lt;/b&gt;를 사용하여 다음 단어를 예측합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예를 들어, &amp;ldquo;I love cats&amp;rdquo;라는 문장의 출력을 생성하는 과정을 단계적으로 살펴보겠습니다.&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;span style=&quot;color: #333333; text-align: start;&quot;&gt;1.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;첫 번째 예측&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;입력&lt;/b&gt;: &amp;lt;sos&amp;gt; 토큰 + 초기 hidden state &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;[0.7, -0.3, 0.4]&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;출력&lt;/b&gt;: &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&quot;I&quot;&lt;/span&gt; + 업데이트된 hidden state, cell state&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;두 번째 예측&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;입력&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;: &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&quot;I&quot;&lt;/span&gt; +&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;첫 번째 예측에서 계산된 hidden state, cell state&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;출력&lt;/b&gt;: &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&quot;love&quot;&lt;/span&gt; + 업데이트된 hidden state, cell state&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;3.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;세 번째 예측&lt;/b&gt;&lt;br /&gt;- &lt;b&gt;입력&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;: &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&quot;love&quot;&lt;/span&gt; +&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;두 번째 예측에서 계산된 hidden state, cell state&lt;/b&gt;&lt;br /&gt;- &lt;b&gt;출력&lt;/b&gt;: &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&quot;cats&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;4. &lt;b&gt;종료&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- &lt;b&gt;입력&lt;/b&gt;: &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&amp;ldquo;cats&amp;rdquo;&lt;/span&gt; (세 번째 출력 단어) + &lt;b&gt;세&amp;nbsp;번째 예측에서 계산된 hidden state, cell state&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;- &lt;b&gt;출력&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&lt;b&gt;단어: &lt;span&gt;&amp;lt;eos&amp;gt;&lt;/span&gt; (종료 토큰)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;디코더는 종료 토큰을 예측한 후 작업을 멈춥니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;디코더 과정에서 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Teacher Forcing&lt;/b&gt;&lt;/span&gt; 기법이 사용될 수 있습니다. (학습 시 &lt;b&gt;정답 토큰을 입력으로 사용하는 방법&lt;/b&gt;).&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Teacher Forcing 기법&lt;/b&gt;&lt;br /&gt;학습 과정에서만 사용되는 특별한 방법입니다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;일반적인 방식과 Teacher Forcing의 차이&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span&gt;&lt;span&gt;Teacher Forcing 사용 시 &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;입력: &amp;lt;START&amp;gt; &amp;rarr; 출력: &quot;나는&quot; (정답 사용) &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;입력: &quot;나는&quot;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;rarr; 출력: &quot;고양이를&quot; (정답 사용) &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;입력: &quot;고양이를&quot; &amp;rarr; 출력: &quot;좋아해&quot; (정답 사용) &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span&gt;Teacher Forcing 미사용 시 &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;입력: &amp;lt;START&amp;gt; &amp;rarr; 출력: &quot;나는&quot; (예측값 사용) &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;입력: &quot;나는&quot;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;rarr; 출력: &quot;강아지를&quot; (잘못된 예측) &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;입력: &quot;고양이를&quot; &amp;rarr; 출력: &quot;좋아해&quot; (오류 전파)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;학습 시: 모델이&lt;u&gt;&lt;i&gt;&lt;b&gt;&quot;강아지를&quot;이라고 잘못 예측했더라도, &lt;br /&gt;다음 입력으로 정답인 &quot;고양이를&quot;을 사용하여 학습하는 방법&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;입니다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;이렇게 하면 한 번의 오류가 후속 예측에 영향을 주지 않아 학습이 더 안정적입니다. &lt;br /&gt;하지만 &lt;b&gt;추론(Inference)&lt;/b&gt;할 때는 정답을 알 수 없으므로, 모델이 생성한 출력을 그대로 다음 입력으로 사용합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  hidden state는 어떻게 업데이트되나요?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;RNN, LSTM, GRU와 같은 순환 구조를 사용하며, 이들은 다음과 같은 방식으로 hidden state를 업데이트합니다.&lt;br /&gt;1. &lt;b&gt;입력&lt;/b&gt;: 현재 단어(&quot;나는&quot;)와 이전 hidden state&lt;br /&gt;2. &lt;b&gt;계산&lt;/b&gt;: RNN/LSTM/GRU가 입력 데이터를 처리하여 새로운 hidden state를 계산&lt;br /&gt;3. &lt;b&gt;출력&lt;/b&gt;: 다음 단어를 예측하고, 새로운 hidden state를 반환&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; &amp;nbsp; 왜 &quot;순환 신경망을 사용&quot; 할까?&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;RNN은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;이전 시점의 정보&lt;/b&gt;&lt;/span&gt;를 현재 시점의 처리에 활용할 수 있습니다.&amp;nbsp;예를 들어 &quot;cats&quot;를 처리할 때, 앞에 나온 &quot;I&quot;와 &quot;love&quot;의 정보도 함께 고려됩니다.&amp;nbsp;이를 통해 문장의 순서와 문맥 정보를 보존할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;b&gt;  &lt;/b&gt;단순 벡터 변환&amp;nbsp; &lt;/b&gt;vs. &lt;b&gt;컨텍스트 벡터&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&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;1204&quot; data-origin-height=&quot;230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1YGfV/btsLobVuGUj/MHzdzPvfDvopBDznAasYgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1YGfV/btsLobVuGUj/MHzdzPvfDvopBDznAasYgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1YGfV/btsLobVuGUj/MHzdzPvfDvopBDznAasYgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1YGfV%2FbtsLobVuGUj%2FMHzdzPvfDvopBDznAasYgK%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;530&quot; height=&quot;101&quot; data-origin-width=&quot;1204&quot; data-origin-height=&quot;230&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;단순 벡터 변환&lt;/b&gt;&lt;br /&gt;- 입력 데이터(예: 단어)를 임베딩(embedding)하여 고정된 차원의 벡터로 표현합니다.&lt;br /&gt;- 예: &quot;I&quot; &amp;rarr; [0.2, 0.8], &quot;love&quot; &amp;rarr; [0.5, 0.1], &quot;cats&quot; &amp;rarr; [0.3, 0.6].&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Seq2Seq의 컨텍스트 벡터&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;- 단순히 단어를 벡터로 변환하는 것을 넘어,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;입력 시퀀스의 순서와 의미를 학습&lt;/b&gt;한 결과입니다.&lt;br /&gt;- Encoder는 RNN, LSTM, GRU 같은 순환 구조를 통해 시퀀스를 순차적으로 처리하며,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;이전 단어들과의 관계를 반영한 hidden state&lt;/b&gt;를 생성합니다.&lt;br /&gt;- 마지막 hidden state(컨텍스트 벡터)는 단어 간의 연관성과 문맥적 의미를 포함합니다.&lt;br /&gt;- 예: &quot;I love cats&quot; &amp;rarr; [0.7, -0.4, 0.3]&lt;br /&gt;(이 값은 &quot;I&quot;, &quot;love&quot;, &quot;cats&quot;의 관계와 순서를 반영한 결과)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;seq2seq 모델의 주요 특징&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1️⃣ 가변 길이의 입력을 받아서 가변 길이의 출력을 생성할 수 있습니다.&lt;/b&gt; &lt;br /&gt;입력 문장의 길이가 고정되어 있지 않아도 된다는 의미인데요.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;예를 들어, 번역 작업에서&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;&quot;I&amp;nbsp;am&amp;nbsp;happy&quot;&amp;nbsp;(3 단어)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;&quot;I&amp;nbsp;am&amp;nbsp;very&amp;nbsp;very&amp;nbsp;happy&amp;nbsp;today&quot;&amp;nbsp;(6 단어)&lt;br /&gt;이렇게 길이가 다른 두 문장 모두를 입력으로 처리할 수 있습니다.&lt;br /&gt;전통적인 신경망은 보통 고정된 크기의 입력만 받을 수 있었지만, seq2seq는 이런 제약이 없습니다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;2️⃣ 문맥을 고려한 시퀀스 생성이 가능&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;이는 출력을 생성할 때 전체 입력 문장의 의미를 고려한다는 의미입니다.&lt;br /&gt;&amp;nbsp;예를 들어, &quot;bank&quot;라는 단어를 번역할 때&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;&quot;I&amp;nbsp;went&amp;nbsp;to&amp;nbsp;the&amp;nbsp;bank&amp;nbsp;to&amp;nbsp;withdraw&amp;nbsp;money&quot;&amp;nbsp;&amp;rarr;&amp;nbsp;&quot;은행&quot;으로&amp;nbsp;번역&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;&quot;I&amp;nbsp;sat&amp;nbsp;by&amp;nbsp;the&amp;nbsp;river&amp;nbsp;bank&quot;&amp;nbsp;&amp;rarr;&amp;nbsp;&quot;강둑&quot;으로&amp;nbsp;번역&lt;br /&gt;이처럼 같은 단어라도 문장 전체의 문맥을 보고 적절한 의미를 선택할 수 있습니다. 이는 인코더가 입력 문장 전체의 정보를 압축해서 저장하고, 디코더가 이 정보를 바탕으로 출력을 생성하기 때문에 가능합니다.&lt;br /&gt;&lt;br /&gt;예시를 하나 더 들어보겠습니다&lt;br /&gt;문장:&amp;nbsp;&quot;The&amp;nbsp;movie&amp;nbsp;was&amp;nbsp;not&amp;nbsp;bad&amp;nbsp;at&amp;nbsp;all&quot;&lt;br /&gt;이&amp;nbsp;문장을&amp;nbsp;한국어로&amp;nbsp;번역할&amp;nbsp;때,&amp;nbsp;seq2seq는&amp;nbsp;&quot;not&amp;nbsp;bad&quot;라는&amp;nbsp;표현이&amp;nbsp;실제로는&amp;nbsp;긍정적인&amp;nbsp;의미라는&amp;nbsp;것을&amp;nbsp;문맥상에서&amp;nbsp;파악하여&amp;nbsp;&quot;영화가&amp;nbsp;꽤&amp;nbsp;좋았다&quot;와&amp;nbsp;같이&amp;nbsp;적절하게&amp;nbsp;번역할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;단순히&amp;nbsp;단어&amp;nbsp;단위로&amp;nbsp;번역하면&amp;nbsp;&quot;영화는&amp;nbsp;나쁘지&amp;nbsp;않았다&quot;가&amp;nbsp;되어&amp;nbsp;뉘앙스가&amp;nbsp;달라질&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;3️⃣ 입력과 출력의 길이가 서로 다를 수 있음&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  Seq2Seq 모델의 한계점&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;b&gt;1.&amp;nbsp;긴&amp;nbsp;시퀀스&amp;nbsp;처리의&amp;nbsp;한계&lt;/b&gt;&lt;br /&gt;-&amp;nbsp;입력&amp;nbsp;시퀀스가&amp;nbsp;길어질수록&amp;nbsp;정보&amp;nbsp;손실이&amp;nbsp;발생&lt;br /&gt;-&amp;nbsp;초기에&amp;nbsp;입력된&amp;nbsp;정보가&amp;nbsp;마지막&amp;nbsp;컨텍스트&amp;nbsp;벡터에&amp;nbsp;충분히&amp;nbsp;반영되지&amp;nbsp;못하는&amp;nbsp;문제&amp;nbsp;(장기&amp;nbsp;의존성&amp;nbsp;문제)&lt;br /&gt;-&amp;nbsp;예시:&amp;nbsp;&quot;Last&amp;nbsp;month,&amp;nbsp;I&amp;nbsp;went&amp;nbsp;to&amp;nbsp;Paris...&quot;로&amp;nbsp;시작하는&amp;nbsp;긴&amp;nbsp;문장에서&amp;nbsp;마지막&amp;nbsp;부분을&amp;nbsp;생성할&amp;nbsp;때&amp;nbsp;&quot;Last&amp;nbsp;month&quot;라는&amp;nbsp;시간&amp;nbsp;정보가&amp;nbsp;잘&amp;nbsp;반영되지&amp;nbsp;않을&amp;nbsp;수&amp;nbsp;있음&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2.&amp;nbsp;고정&amp;nbsp;크기&amp;nbsp;컨텍스트&amp;nbsp;벡터의&amp;nbsp;병목&amp;nbsp;현상&lt;/b&gt;&lt;br /&gt;-&amp;nbsp;입력&amp;nbsp;문장의&amp;nbsp;길이와&amp;nbsp;관계없이&amp;nbsp;항상&amp;nbsp;같은&amp;nbsp;크기의&amp;nbsp;컨텍스트&amp;nbsp;벡터를&amp;nbsp;사용&lt;br /&gt;-&amp;nbsp;긴&amp;nbsp;문장의&amp;nbsp;경우&amp;nbsp;모든&amp;nbsp;정보를&amp;nbsp;제한된&amp;nbsp;크기의&amp;nbsp;벡터에&amp;nbsp;압축하다&amp;nbsp;보니&amp;nbsp;정보&amp;nbsp;손실이&amp;nbsp;불가피&lt;br /&gt;-&amp;nbsp;이는&amp;nbsp;나중에&amp;nbsp;어텐션(Attention)&amp;nbsp;메커니즘의&amp;nbsp;도입&amp;nbsp;계기가&amp;nbsp;됨&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3.&amp;nbsp;출력&amp;nbsp;생성의&amp;nbsp;일관성&amp;nbsp;문제&lt;/b&gt;&lt;br /&gt;-&amp;nbsp;한&amp;nbsp;번&amp;nbsp;잘못된&amp;nbsp;예측을&amp;nbsp;하면&amp;nbsp;그&amp;nbsp;오류가&amp;nbsp;이후&amp;nbsp;생성에&amp;nbsp;계속&amp;nbsp;영향을&amp;nbsp;미침&lt;br /&gt;-&amp;nbsp;예시:&amp;nbsp;&quot;I&amp;nbsp;am&quot;&amp;nbsp;&amp;rarr;&amp;nbsp;&quot;나는&quot;&amp;nbsp;&amp;rarr;&amp;nbsp;&quot;사과를&quot;&amp;nbsp;&amp;rarr;&amp;nbsp;&quot;먹었다&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;만약&amp;nbsp;&quot;나는&quot;&amp;nbsp;대신&amp;nbsp;&quot;그는&quot;이라고&amp;nbsp;잘못&amp;nbsp;예측하면,&amp;nbsp;이후&amp;nbsp;문장의&amp;nbsp;일관성이&amp;nbsp;무너질&amp;nbsp;수&amp;nbsp;있음&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4.&amp;nbsp;연산&amp;nbsp;비용과&amp;nbsp;속도&lt;/b&gt;&lt;br /&gt;-&amp;nbsp;시퀀스를&amp;nbsp;순차적으로&amp;nbsp;처리해야&amp;nbsp;하므로&amp;nbsp;병렬&amp;nbsp;처리가&amp;nbsp;어려움&lt;br /&gt;-&amp;nbsp;특히&amp;nbsp;긴&amp;nbsp;시퀀스의&amp;nbsp;경우&amp;nbsp;처리&amp;nbsp;시간이&amp;nbsp;크게&amp;nbsp;증가&lt;br /&gt;-&amp;nbsp;GPU를&amp;nbsp;활용한&amp;nbsp;병렬&amp;nbsp;처리의&amp;nbsp;이점을&amp;nbsp;충분히&amp;nbsp;활용하기&amp;nbsp;어려움&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5.&amp;nbsp;단방향&amp;nbsp;문맥&amp;nbsp;이해의&amp;nbsp;한계&lt;/b&gt;&lt;br /&gt;-&amp;nbsp;기본적인&amp;nbsp;seq2seq는&amp;nbsp;입력을&amp;nbsp;순차적으로만&amp;nbsp;처리&lt;br /&gt;-&amp;nbsp;문장의&amp;nbsp;전체적인&amp;nbsp;문맥을&amp;nbsp;양방향으로&amp;nbsp;이해하는&amp;nbsp;데&amp;nbsp;한계가&amp;nbsp;있음&lt;br /&gt;-&amp;nbsp;이는&amp;nbsp;나중에&amp;nbsp;양방향&amp;nbsp;RNN&amp;nbsp;(Bidirectional&amp;nbsp;RNN)의&amp;nbsp;도입&amp;nbsp;계기가&amp;nbsp;됨&lt;br /&gt;&lt;br /&gt;&lt;b&gt; &amp;nbsp;이러한&amp;nbsp;한계점들을&amp;nbsp;극복하기&amp;nbsp;위한&amp;nbsp;후속&amp;nbsp;발전&lt;/b&gt;&lt;br /&gt;-&amp;nbsp;어텐션&amp;nbsp;메커니즘&amp;nbsp;도입&lt;br /&gt;-&amp;nbsp;Transformer&amp;nbsp;아키텍처&amp;nbsp;개발&lt;br /&gt;-&amp;nbsp;양방향&amp;nbsp;인코더&amp;nbsp;사용&lt;br /&gt;-&amp;nbsp;빔&amp;nbsp;서치(Beam&amp;nbsp;Search)&amp;nbsp;같은&amp;nbsp;디코딩&amp;nbsp;전략&amp;nbsp;도입&lt;br /&gt;&lt;br /&gt;이러한&amp;nbsp;한계점들은&amp;nbsp;seq2seq&amp;nbsp;모델이&amp;nbsp;발전하는&amp;nbsp;과정에서&amp;nbsp;새로운&amp;nbsp;아키텍처와&amp;nbsp;기법들이&amp;nbsp;등장하는&amp;nbsp;계기가&amp;nbsp;되었으며,&amp;nbsp;현대의&amp;nbsp;많은&amp;nbsp;자연어&amp;nbsp;처리&amp;nbsp;모델들은&amp;nbsp;이러한&amp;nbsp;문제들을&amp;nbsp;해결하기&amp;nbsp;위한&amp;nbsp;다양한&amp;nbsp;개선&amp;nbsp;방법들을&amp;nbsp;포함하고&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1735605937157&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Encoder(nn.Module):
    def __init__(self, src_vocab_size, embedding_dim, hidden_units):
        super(Encoder, self).__init__()
        self.embedding = nn.Embedding(src_vocab_size, embedding_dim, padding_idx=0)
        self.lstm = nn.LSTM(embedding_dim, hidden_units, batch_first=True)

    def forward(self, x):     # x.shape == (batch_size, seq_len)
        # 1.단어 임베딩
        x = self.embedding(x) # 임베딩층 통과 후 x.shape = (batch_size, seq_len, embedding_dim)
        # 2.LSTM 처리
        _, (hidden, cell) = self.lstm(x) # hidden.shape == (1, batch_size, hidden_units), cell.shape == (1, batch_size, hidden_units)
        return hidden, cell # 인코더의 출력은 hidden state, cell state&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1735605947919&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Decoder(nn.Module):
    def __init__(self, tar_vocab_size, embedding_dim, hidden_units):
        super(Decoder, self).__init__()
        self.embedding = nn.Embedding(tar_vocab_size, embedding_dim, padding_idx=0)
        self.lstm = nn.LSTM(embedding_dim, hidden_units, batch_first=True)
        self.fc = nn.Linear(hidden_units, tar_vocab_size)

    def forward(self, x, hidden, cell): # x.shape == (batch_size, seq_len)
        # 1. 단어 임베딩
        x = self.embedding(x) # x.shape == (batch_size, seq_len, embedding_dim)

        # 2.LSTM 처리
        # 디코더의 LSTM으로 인코더의 hidden state, cell state를 전달.
        # output.shape == (batch_size, seq_len, hidden_units)
        # hidden.shape == (1, batch_size, hidden_units)
        # cell.shape == (1, batch_size, hidden_units)
        output, (hidden, cell) = self.lstm(x, (hidden, cell))
        # 3.출력 예측
        output = self.fc(output) # output.shape: (batch_size, seq_len, tar_vocab_size)

        # 디코더의 출력은 예측값, hidden state, cell state
        return output, hidden, cell&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1735605953194&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Seq2Seq(nn.Module):
    def __init__(self, encoder, decoder):
        super(Seq2Seq, self).__init__()
        self.encoder = encoder
        self.decoder = decoder

    def forward(self, src, trg):
        hidden, cell = self.encoder(src) # 인코더 입력 (정수 인코딩된 소스 시퀀스, 예: 영어 문장).

        # 훈련 중에는 디코더의 출력 중 오직 output만 사용한다.
        output, _, _ = self.decoder(trg, hidden, cell) # 디코더 입력 (정수 인코딩된 타겟 시퀀스, 예: 프랑스어 문장).
        return output
    
encoder = Encoder(src_vocab_size, embedding_dim, hidden_units)
decoder = Decoder(tar_vocab_size, embedding_dim, hidden_units)
model = Seq2Seq(encoder, decoder)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>pytorch</category>
      <category>Decoder</category>
      <category>Encoder</category>
      <category>nlp</category>
      <category>seq2seq</category>
      <category>디코더</category>
      <category>시퀀스투시퀀스</category>
      <category>어텐션메커니즘</category>
      <category>인공지능</category>
      <category>인코더</category>
      <category>자연어처리</category>
      <author>ISFP의 블로그</author>
      <guid isPermaLink="true">https://resultofeffort.tistory.com/148</guid>
      <comments>https://resultofeffort.tistory.com/148#entry148comment</comments>
      <pubDate>Tue, 31 Dec 2024 09:44:17 +0900</pubDate>
    </item>
    <item>
      <title>[pytorch] 코사인 유사도(Cosine Similarity) | 유클리드 거리 (Euclidean Distance) | 자카드 유사도(Jaccard Similarity) | 코사인 유사도를 이용한 영화 추천 시스템 | cosine_similarity</title>
      <link>https://resultofeffort.tistory.com/147</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;앞서 TF-IDF (Term Frequency-Inverse Document Frequency)를 사용하여 텍스트 데이터를 벡터화하는 방법을 배웠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이제, 이 TF-IDF 벡터를 활용하여 문서 간 유사도를 계산해보려 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;텍스트 데이터의 유사도를 측정하는 방법으로는 여러 가지가 있지만, 이번에는 &lt;b&gt;코사인 유사도 (Cosine Similarity)&lt;/b&gt;, &lt;b&gt;유클리드 거리 (Euclidean Distance)&lt;/b&gt;, 그리고 자카드 유사도 (Jaccard Similarity)를 사용하여 영화 추천 시스템을 구축해 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;유클리드 거리 vs 코사인 유사도 vs 자카드 유사도 비교&lt;/b&gt;&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 104.302%; height: 533px;&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;background-color: #9b9b9b; color: #ffffff; text-align: center;&quot;&gt;&lt;b&gt;기준&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #9b9b9b; color: #ffffff; text-align: center;&quot;&gt;&lt;b&gt;유클리드 거리&lt;br /&gt;(Euclidean Distance)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #9b9b9b; color: #ffffff; text-align: center;&quot;&gt;&lt;b&gt;코사인 유사도&lt;br /&gt;(Cosine Similarity)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #9b9b9b; color: #ffffff; text-align: center;&quot;&gt;&lt;span&gt;&lt;b&gt;자카드 유사도&lt;br /&gt;(Jaccard Similarity)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef; text-align: center;&quot;&gt;&lt;b&gt;측정 방식&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;벡터 간의 직선 거리&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;벡터 간의 각도&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;두 집합 간의 교집합과 합집합 비율&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef; text-align: center;&quot;&gt;&lt;b&gt;벡터 크기 영향&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9; text-align: center;&quot;&gt;벡터의 크기에 민감&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9; text-align: center;&quot;&gt;벡터의 크기를 무시하고 방향만 고려&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9; text-align: center;&quot;&gt;&lt;span&gt;벡터의 크기보다는 단어의 존재 여부에 중점&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef; text-align: center;&quot;&gt;&lt;b&gt;주요 활용 분야&amp;nbsp;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;수치 데이터 분석, 좌표 거리 측정&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;텍스트 데이터 분석, 추천 시스템&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;문서 유사도 분석, 검색 엔진 최적화&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef; text-align: center;&quot;&gt;&lt;b&gt;스케일링 필요 여부&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9; text-align: center;&quot;&gt;필수&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9; text-align: center;&quot;&gt;불필요&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9; text-align: center;&quot;&gt;&lt;span&gt;불필요&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef; text-align: center;&quot;&gt;&lt;b&gt;회소 행렬에서의 성능&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;부정확한 결과 가능&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;상대적으로 효율적&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;공통 단어가 적을 경우 부정확&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef; text-align: center;&quot;&gt;&lt;b&gt;문서 길이 영향&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9; text-align: center;&quot;&gt;영향 있음&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9; text-align: center;&quot;&gt;영향 없음&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9; text-align: center;&quot;&gt;&lt;span&gt;영향 없음 (단어의 존재 여부만 반영)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef; text-align: center;&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;- 좌표 공간에서의 실제 거리 측정 가능&lt;span&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;- 수치 데이터 분석에 유리&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;- 텍스트 데이터에서 문서 길이와 관계없이&lt;br /&gt;유사도 평가 가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;- 단어의 존재 여부만으로 유사도 측정 가능&lt;span&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;- 빠른 계산 속도&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #efefef; text-align: center;&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9; text-align: center;&quot;&gt;&lt;span&gt;- 벡터의 크기에 민감하여 텍스트 데이터에 부적합&lt;span&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;- 스케일링 필요&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9; text-align: center;&quot;&gt;&lt;span&gt;- 단어 간 문맥을 고려하지 못함&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #f9f9f9; text-align: center;&quot;&gt;&lt;span&gt;- 단어가 희귀할 경우 유사도 평가가 어려움&lt;span&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;- 연속형 데이터에는 부적합&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;- 코사인 유사도&lt;/b&gt;는 두 벡터 간의 방향을 기준으로 유사도를 측정합니다. 벡터의 크기와 관계없이 방향이 유사할수록 높은 유사도로 평가되기 때문에, 텍스트 데이터나 추천 시스템에서 자주 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- &lt;b&gt;유클리드 거리&lt;/b&gt;는 두 벡터 간의 직선거리를 측정합니다. 벡터 간의 거리가 가까울수록 두 텍스트가 더 유사하다고 판단합니다. 다만, 벡터의 크기에 영향을 받기 때문에 문서 길이에 따라 왜곡된 결과를 초래할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- &lt;b&gt;자카드 유사도&lt;/b&gt;는 두 집합 간의 유사도를 측정하는 방법으로, 공통된 요소의 비율을 기반으로 합니다. 텍스트 데이터를 집합 형태로 변환하여 단어의 중복도를 제거하고, 두 텍스트 간의 공통된 단어 비율을 비교합니다. 이 방법은 텍스트의 내용이 유사하지만 단어 빈도가 다른 경우에도 문서 간의 유사성을 잘 평가할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이제, 각 유사도 측정 방법을 활용하여 영화 줄거리 데이터를 분석하고, 사용자가 입력한 영화와 유사한 영화를 추천하는 시스템을 만들어 보겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;코사인 유사도(Cosine Similarity)란?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;코사인 유사도는 두 벡터 간의 &lt;b&gt;각도를 이용해 유사도를 측정&lt;/b&gt;하는 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;벡터의 크기가 아니라 &lt;b&gt;방향이 얼마나 유사한지&lt;/b&gt;를 평가하기 때문에, &lt;b&gt;텍스트 데이터나 추천 시스템&lt;/b&gt;에서 자주 활용됩니다.&lt;br /&gt;&lt;br /&gt;\[&lt;br /&gt;\text {Cosine&amp;nbsp;Similarity}(A,&amp;nbsp;B)&amp;nbsp;=&amp;nbsp;\frac {A&amp;nbsp;\cdot&amp;nbsp;B}{\|A\|&amp;nbsp;\|B\|}&lt;br /&gt;\]&lt;br /&gt;&lt;br /&gt;-&amp;nbsp;\(&amp;nbsp;A&amp;nbsp;\cdot&amp;nbsp;B&amp;nbsp;\):&amp;nbsp;두&amp;nbsp;벡터의&amp;nbsp;내적&lt;br /&gt;-&amp;nbsp;\(&amp;nbsp;\|A\|&amp;nbsp;\):&amp;nbsp;벡터&amp;nbsp;\(&amp;nbsp;A&amp;nbsp;\)의&amp;nbsp;크기(길이)&lt;br /&gt;-&amp;nbsp;\(&amp;nbsp;\|B\|&amp;nbsp;\):&amp;nbsp;벡터&amp;nbsp;\(&amp;nbsp;B&amp;nbsp;\)의&amp;nbsp;크기(길이)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;(문서 단어 행렬이나 TF-IDF 행렬을 통해서 문서의 유사도를 구하는 경우에는 문서 단어 행렬이나 &lt;b&gt;TF-IDF 행렬&lt;/b&gt;이 각각의 &lt;b&gt;벡터 A, B&lt;/b&gt;가 됩니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;코사인 유사도의 값이&lt;br /&gt;- &lt;b&gt;1에 가까울수록 두 벡터가 유사함&lt;/b&gt;을 의미합니다.&lt;br /&gt;- 0에 가까울수록 두 벡터가 서로 직각임을 의미합니다(즉, 유사하지 않음).&lt;br /&gt;- -1에 가까울수록 두 벡터가 반대 방향을 가리킴을 의미합니다(이 경우는 텍스트나 추천 시스템에서 거의 발생하지 않음).&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;i&gt;&lt;b&gt;코사인 유사도가 벡터의 크기에 영향을 받지 않는 이유&lt;/b&gt;&lt;/i&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식에서 보시다시피, 코사인 유사도는 &lt;b&gt;두 벡터의 내적을 각 벡터의 크기(길이)로 나눕니다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 과정을 통해 &lt;b&gt;벡터의 크기를 정규화&lt;/b&gt;하게 됩니다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;즉, &lt;b&gt;벡터의 크기가 아무리 커도&lt;/b&gt; 내적 값은 그 크기로 &lt;b&gt;나눠&lt;/b&gt;지기 때문에 &lt;b&gt;결과적으로 크기(길이)의 영향을 제거&lt;/b&gt;하게 됩니다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;예를 들어,&lt;br /&gt;&lt;b&gt;벡터의 크기가 다른 경우&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;벡터&amp;nbsp;\(&amp;nbsp;A&amp;nbsp;=&amp;nbsp;[1,&amp;nbsp;1]&amp;nbsp;\)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;벡터&amp;nbsp;\(&amp;nbsp;B&amp;nbsp;=&amp;nbsp;[2,&amp;nbsp;2]&amp;nbsp;\)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;코사인 유사도 계산&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\[&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;A&amp;nbsp;\cdot&amp;nbsp;B&amp;nbsp;=&amp;nbsp;1&amp;nbsp;\times&amp;nbsp;2&amp;nbsp;+&amp;nbsp;1&amp;nbsp;\times&amp;nbsp;2&amp;nbsp;=&amp;nbsp;4&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\[&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\|A\|&amp;nbsp;=&amp;nbsp;\sqrt {1^2&amp;nbsp;+&amp;nbsp;1^2}&amp;nbsp;=&amp;nbsp;\sqrt {2},&amp;nbsp;\quad&amp;nbsp;\|B\|&amp;nbsp;=&amp;nbsp;\sqrt {2^2&amp;nbsp;+&amp;nbsp;2^2}&amp;nbsp;=&amp;nbsp;\sqrt {8}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\[&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\text {Cosine&amp;nbsp;Similarity}(A,&amp;nbsp;B)&amp;nbsp;=&amp;nbsp;\frac {4}{\sqrt {2}&amp;nbsp;\times&amp;nbsp;\sqrt {8}}&amp;nbsp;=&amp;nbsp;\frac {4}{4}&amp;nbsp;=&amp;nbsp;1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;결과적으로, &lt;b&gt;벡터의 크기가 다르지만 방향이 동일하기 때문에 코사인 유사도는 1&lt;/b&gt;이 됩니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;벡터의 방향이 다른 경우&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;벡터&amp;nbsp;\(&amp;nbsp;A&amp;nbsp;=&amp;nbsp;[1,&amp;nbsp;0]&amp;nbsp;\)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;벡터&amp;nbsp;\(&amp;nbsp;B&amp;nbsp;=&amp;nbsp;[0,&amp;nbsp;1]&amp;nbsp;\)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;코사인 유사도 계산&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\[&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;A&amp;nbsp;\cdot&amp;nbsp;B&amp;nbsp;=&amp;nbsp;1&amp;nbsp;\times&amp;nbsp;0&amp;nbsp;+&amp;nbsp;0&amp;nbsp;\times&amp;nbsp;1&amp;nbsp;=&amp;nbsp;0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\[&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\|A\|&amp;nbsp;=&amp;nbsp;\sqrt {1^2&amp;nbsp;+&amp;nbsp;0^2}&amp;nbsp;=&amp;nbsp;1,&amp;nbsp;\quad&amp;nbsp;\|B\|&amp;nbsp;=&amp;nbsp;\sqrt {0^2&amp;nbsp;+&amp;nbsp;1^2}&amp;nbsp;=&amp;nbsp;1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\[&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\text {Cosine&amp;nbsp;Similarity}(A,&amp;nbsp;B)&amp;nbsp;=&amp;nbsp;\frac {0}{1&amp;nbsp;\times&amp;nbsp;1}&amp;nbsp;=&amp;nbsp;0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;여기서, &lt;b&gt;벡터의 크기가 같아도 방향이 다르기 때문에 코사인 유사도는 0&lt;/b&gt;이 됩니다.&lt;br /&gt;&lt;br /&gt;정리하자면,&lt;br /&gt;코사인 유사도는 &lt;b&gt;벡터의 크기를 정규화&lt;/b&gt;하기 때문에, &lt;b&gt;벡터의 길이(크기)&lt;/b&gt;에는 영향을 받지 않습니다. 대신, 두 벡터의 &lt;b&gt;방향(각도)&lt;/b&gt;에만 초점을 맞추어 유사도를 측정합니다. 따라서 &lt;b&gt;문서의 길이(단어 수)와 관계없이&lt;/b&gt;, &lt;b&gt;내용의 유사성&lt;/b&gt;을 더 잘 평가할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;텍스트 데이터에서 코사인 유사도는 어떻게 계산할까?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예를 들어, 세 개의 문서에 대해 TF-IDF를 계산했다고 가정해 보겠습니다.&lt;br /&gt;&lt;br /&gt;1. 문서 1의 TF-IDF 결과: `[0.5, 0.3, 0.0, 0.2]`&lt;br /&gt;2. 문서 2의 TF-IDF 결과: `[0.1, 0.7, 0.0, 0.4]`&lt;br /&gt;3. 문서 3의 TF-IDF 결과: `[0.0, 0.2, 0.6, 0.1]`&lt;br /&gt;&lt;br /&gt;TF-IDF 벡터를 사용해 코사인 유사도를 계산하는 과정은 다음과 같습니다.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\[&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\text{Cosine&amp;nbsp;Similarity}(A,&amp;nbsp;B)&amp;nbsp;=&amp;nbsp;\frac {A&amp;nbsp;\cdot&amp;nbsp;B}{\|A\|&amp;nbsp;\times&amp;nbsp;\|B\|}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\]&lt;br /&gt;&lt;br /&gt;만약, 우리가 문서 1과 문서 2의 코사인 유사도를 계산한다고 가정해 보겠습니다.&lt;br /&gt;&lt;br /&gt;-&amp;nbsp;문서&amp;nbsp;1의&amp;nbsp;벡터:&amp;nbsp;`[0.5,&amp;nbsp;0.3,&amp;nbsp;0.0,&amp;nbsp;0.2]`&lt;br /&gt;-&amp;nbsp;문서&amp;nbsp;2의&amp;nbsp;벡터:&amp;nbsp;`[0.1,&amp;nbsp;0.7,&amp;nbsp;0.0,&amp;nbsp;0.4]`&lt;br /&gt;&lt;br /&gt;1. 내적 계산 (\( A \cdot B \)):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\[&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;(0.5&amp;nbsp;\times&amp;nbsp;0.1)&amp;nbsp;+&amp;nbsp;(0.3&amp;nbsp;\times&amp;nbsp;0.7)&amp;nbsp;+&amp;nbsp;(0.0&amp;nbsp;\times&amp;nbsp;0.0)&amp;nbsp;+&amp;nbsp;(0.2&amp;nbsp;\times&amp;nbsp;0.4)&amp;nbsp;=&amp;nbsp;0.05&amp;nbsp;+&amp;nbsp;0.21&amp;nbsp;+&amp;nbsp;0&amp;nbsp;+&amp;nbsp;0.08&amp;nbsp;=&amp;nbsp;0.34&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\]&lt;br /&gt;&lt;br /&gt;2. 벡터의 크기 계산 (\( \|A\| \)와 \( \|B\| \)):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\[&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\|A\|&amp;nbsp;=&amp;nbsp;\sqrt {0.5^2&amp;nbsp;+&amp;nbsp;0.3^2&amp;nbsp;+&amp;nbsp;0.0^2&amp;nbsp;+&amp;nbsp;0.2^2}&amp;nbsp;=&amp;nbsp;\sqrt {0.25&amp;nbsp;+&amp;nbsp;0.09&amp;nbsp;+&amp;nbsp;0&amp;nbsp;+&amp;nbsp;0.04}&amp;nbsp;=&amp;nbsp;\sqrt {0.38}&amp;nbsp;\approx&amp;nbsp;0.616&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\[&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\|B\|&amp;nbsp;=&amp;nbsp;\sqrt {0.1^2&amp;nbsp;+&amp;nbsp;0.7^2&amp;nbsp;+&amp;nbsp;0.0^2&amp;nbsp;+&amp;nbsp;0.4^2}&amp;nbsp;=&amp;nbsp;\sqrt {0.01&amp;nbsp;+&amp;nbsp;0.49&amp;nbsp;+&amp;nbsp;0&amp;nbsp;+&amp;nbsp;0.16}&amp;nbsp;=&amp;nbsp;\sqrt {0.66}&amp;nbsp;\approx&amp;nbsp;0.812&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\]&lt;br /&gt;&lt;br /&gt;3. 코사인 유사도 계산:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\[&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\text {Cosine&amp;nbsp;Similarity}(A,&amp;nbsp;B)&amp;nbsp;=&amp;nbsp;\frac {0.34}{0.616&amp;nbsp;\times&amp;nbsp;0.812}&amp;nbsp;=&amp;nbsp;\frac {0.34}{0.500}&amp;nbsp;\approx&amp;nbsp;0.68&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;\]&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;코사인 유사도 (Cosine Similarity)의 장단점&lt;/b&gt;&lt;/h2&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;장점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- 코사인 유사도는 벡터의 크기(길이)가 아닌 &lt;b&gt;방향&lt;/b&gt;에 초점을 맞춰 두 벡터 간의 유사도를 측정하기 때문에 텍스트 데이터에서 &lt;b&gt;문서의 길이와 무관하게 내용의 유사성&lt;/b&gt;을 평가할 수 있어, 문서 분류, 추천 시스템 등에 효과적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- 희소 행렬(Sparse Matrix)에서 &lt;b&gt;0이 많은 경우에도&lt;/b&gt; 유사도를 측정하는 데 있어 &lt;b&gt;유클리드 거리보다&lt;/b&gt; 더 &lt;b&gt;정확한 결과&lt;/b&gt;를 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;- &lt;/span&gt;코사인 유사도는 벡터의 방향만 고려하므로, 벡터의 크기에 영향을 받지 않습니다. 따라서 &lt;b&gt;정규화 과정 없이&lt;/b&gt; 바로 유사도를 계산할 수 있어 &lt;b&gt;계산 비용을 줄일 수 있습니다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- 추천 시스템, 문서 검색, 클러스터링 등에서 문서 간의 &lt;b&gt;내용 유사성&lt;/b&gt;을 평가할 때 자주 사용됩니다. 특히 &lt;b&gt;텍스트 데이터&lt;/b&gt;와 같이 벡터의 크기보다는 &lt;b&gt;단어의 조합과 빈도가 중요한 경우&lt;/b&gt;에 유리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- 코사인 유사도는 단순히 &lt;b&gt;단어의 빈도와 중요도&lt;/b&gt;만을 사용하여 벡터를 비교하기 때문에, &lt;b&gt;단어 간의 문맥적 관계&lt;/b&gt;를 고려하지 못합니다. 예를 들어, &lt;b&gt;동의어나 유사한 의미를 가진 단어&lt;/b&gt;가 다른 벡터로 표현되면, 문서의 의미가 유사하더라도 낮은 유사도 값을 가질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예를 들어, &quot;car&quot;와 &quot;vehicle&quot;이 동의어이더라도, &quot;car&quot;가 한 문서에서 자주 등장해 TF-IDF 값이 낮고, &quot;vehicle&quot;이 다른 문서에서 드물게 등장해 TF-IDF 값이 높다면, 두 벡터는 다른 방향을 가질 수 있습니다. 이로 인해 코사인 유사도 값이 낮게 나오게 되는 거죠. &lt;b&gt;이를 해결하기 위해 Word2Vec, BERT와 같은 임베딩 기법을 활용하면 단어 간의 문맥을 반영하여 더 정확한 유사도 측정이 가능합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- 희소 행렬에서 공통으로 등장하는 단어가 거의 없는 경우, 대부분의 값이 0이 됩니다. 예를 들어, 'car'라는 단어가 &lt;b&gt;문서 1에만 1번 등장&lt;/b&gt;하고 다른 문서에는 전혀 등장하지 않는다면, &lt;b&gt;다른 문서에서는 해당 단어의 값이 모두 0&lt;/b&gt;이 됩니다. 이로 인해 문서 간 유사도를 비교할 때 코사인 유사도가 낮게 나올 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- &lt;b&gt;단어의 순서를 무시&lt;/b&gt;하고 벡터화된 단어 빈도만을 사용하기 때문에 &lt;b&gt;문장의 구조나 문맥&lt;/b&gt;을 반영하지 못해, 같은 단어들이 포함되어 있어도 &lt;b&gt;다른 의미를 가질 수 있는 문장들&lt;/b&gt;을 구분하지 못합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;결론적으로, &lt;i&gt;&lt;u&gt;코사인 유사도는&amp;nbsp;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;i&gt;&lt;u&gt;텍스트 데이터에서 &lt;b&gt;문서의 길이에 영향을 받지 않고&lt;/b&gt; 유사도를 측정할 수 있어, 추천 시스템과 텍스트 분류 등에 매우 적합하지만, &lt;b&gt;단어의 순서나 문맥&lt;/b&gt;을 고려하지 않기 때문에, &lt;b&gt;더 깊은 의미를 이해하는 데 한계&lt;/b&gt;가 있습니다.&lt;/u&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;따라서 &lt;b&gt;코사인 유사도는 텍스트 데이터에서 주로 사용&lt;/b&gt;되지만, 더 높은 수준의 이해가 필요한 분석에서는 &lt;b&gt;Word2Vec, BERT&lt;/b&gt;와 같은 &lt;b&gt;임베딩 기법&lt;/b&gt;을 사용할 수도 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;코사인 유사도를 이용한 텍스트 문서 유사도 분석 (예제)&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;우리가 앞서 학습한 TF-IDF를 이용해 문서를 벡터로 변환한 후, 코사인 유사도를 통해 문서 간 유사도를 측정해 보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731513302643&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import pandas as pd

# 예제 문서 리스트
corpus = [
    &quot;나는 오늘 밥을 먹었다&quot;,
    &quot;밥을 먹고 운동을 했다&quot;,
    &quot;오늘 운동을 마치고 밥을 먹었다&quot;
]

# TF-IDF 벡터화
vectorizer = TfidfVectorizer()
tfidf_matrix = vectorizer.fit_transform(corpus)

# 코사인 유사도 계산
cosine_sim = cosine_similarity(tfidf_matrix, tfidf_matrix)

# 결과를 데이터프레임으로 보기 좋게 출력
df = pd.DataFrame(cosine_sim, index=[&quot;문서1&quot;, &quot;문서2&quot;, &quot;문서3&quot;], columns=[&quot;문서1&quot;, &quot;문서2&quot;, &quot;문서3&quot;])
print(&quot;코사인 유사도 행렬:&quot;)
print(df)&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;574&quot; data-origin-height=&quot;192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1sZ1f/btsKH0VcVaV/oUPt2lOsdDLHwnSrotYFRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1sZ1f/btsKH0VcVaV/oUPt2lOsdDLHwnSrotYFRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1sZ1f/btsKH0VcVaV/oUPt2lOsdDLHwnSrotYFRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1sZ1f%2FbtsKH0VcVaV%2FoUPt2lOsdDLHwnSrotYFRk%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;538&quot; height=&quot;180&quot; data-origin-width=&quot;574&quot; data-origin-height=&quot;192&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;문서 1, 2, 3의 코사인 유사도 결과를 보면,&lt;br /&gt;문서 1과 문서 3의 유사도가 0.552로 가장 높습니다. 이는 두 문서에 &lt;b&gt;유사한 단어가 많이 포함&lt;/b&gt;되어 있다는 것을 의미합니다.&lt;br /&gt;또한 문서 2와 다른 문서들 간의 유사도는 상대적으로 낮습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;코사인 유사도를 이용한 영화 추천 시스템 (실습)&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;추천 시스템이란?&lt;br /&gt;- 추천 시스템은 사용자의 취향을 분석하여 관련된 콘텐츠(예: 영화, 음악, 도서)를 추천하는 시스템입니다.&lt;br /&gt;- 콘텐츠 기반 추천과 협업 필터링 추천 방식이 대표적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이제 코사인 유사도를 활용하여,&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f; text-align: start;&quot;&gt;좋아하는 영화를 &lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f; text-align: start;&quot;&gt;입력하면&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f; text-align: start;&quot;&gt; 해당 영화의 줄거리와 유사한 줄거리의 영화를 찾아서 추천하는&lt;/span&gt;&lt;/b&gt; 코드를 작성해 보도록 해요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;우선 사용할 데이터셋을 불러옵니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731514570321&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pandas as pd

# 인코딩을 'ISO-8859-1'로 지정하여 파일 로드
movies_df = pd.read_csv('movies_metadata_low.csv', encoding='ISO-8859-1')&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;`movies_metadata_low.csv` 파일에는 24개의 열(column)과 45466개의 행(row)이 포함되어 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;사용할 칼럼만 불러와서 확인해 볼게요.&lt;/p&gt;
&lt;pre id=&quot;code_1731514819842&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;movies_df[['title','overview']]&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;874&quot; data-origin-height=&quot;494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YZqDK/btsKHadngCY/l6bQBTg1v50JXaRDRkMzwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YZqDK/btsKHadngCY/l6bQBTg1v50JXaRDRkMzwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YZqDK/btsKHadngCY/l6bQBTg1v50JXaRDRkMzwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYZqDK%2FbtsKHadngCY%2Fl6bQBTg1v50JXaRDRkMzwK%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;582&quot; height=&quot;329&quot; data-origin-width=&quot;874&quot; data-origin-height=&quot;494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;title과 overview 칼럼에는 결측값이 존재하네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;이제 `overview`(줄거리 설명)을 활용해, &lt;b&gt;영화 간 유사도&lt;/b&gt;를 측정하고 &lt;b&gt;추천 시스템&lt;/b&gt;을 구축할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1️⃣ 데이터 전처리: overview 열에 &lt;b&gt;결측치 처리&lt;/b&gt; 및&lt;b&gt; 텍스트 전처리&lt;/b&gt;를 합니다.&lt;/h4&gt;
&lt;pre id=&quot;code_1731515160684&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

# Step 1: 결측치 처리 (overview 열에서 결측값을 빈 문자열로 대체)
movies_df['overview'] = movies_df['overview'].fillna('')&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;874&quot; data-origin-height=&quot;508&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K7uSi/btsKIPk7a5I/zW1nHpKKD8koS6yTcmiKw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K7uSi/btsKIPk7a5I/zW1nHpKKD8koS6yTcmiKw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K7uSi/btsKIPk7a5I/zW1nHpKKD8koS6yTcmiKw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK7uSi%2FbtsKIPk7a5I%2FzW1nHpKKD8koS6yTcmiKw0%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;585&quot; height=&quot;340&quot; data-origin-width=&quot;874&quot; data-origin-height=&quot;508&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;2️⃣ TF-IDF 벡터화: overview 텍스트를 &lt;b&gt;TF-IDF 벡터화&lt;/b&gt;하여 문서를 수치화합니다.&lt;/h4&gt;
&lt;pre id=&quot;code_1731515254689&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Step 2: TF-IDF 벡터화 (overview 텍스트를 수치화)
tfidf_vectorizer = TfidfVectorizer(stop_words='english')
tfidf_matrix = tfidf_vectorizer.fit_transform(movies_df['overview'])

# TF-IDF 행렬을 Pandas DataFrame으로 변환
tfidf_df = pd.DataFrame(tfidf_matrix.toarray(), columns=tfidf_vectorizer.get_feature_names_out())
print(tfidf_df)&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;952&quot; data-origin-height=&quot;824&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GIhdU/btsKHvBrrnO/OawfgWlDXK5mctOrSngTNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GIhdU/btsKHvBrrnO/OawfgWlDXK5mctOrSngTNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GIhdU/btsKHvBrrnO/OawfgWlDXK5mctOrSngTNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGIhdU%2FbtsKHvBrrnO%2FOawfgWlDXK5mctOrSngTNK%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;576&quot; height=&quot;499&quot; data-origin-width=&quot;952&quot; data-origin-height=&quot;824&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TF-IDF 벡터화한 결과를 보면 총 45466개의 행(row)과 19741개의 열(column)이 출력되었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이는 45466개의 영화가 있으며, 19741개의 고유한 단어들을 나타냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3️⃣ 코사인 유사도 계산: 영화 줄거리 간의 &lt;b&gt;코사인 유사도&lt;/b&gt;를 계산하여, 특정 영화와 유사한 영화를 찾습니다.&lt;/h4&gt;
&lt;pre id=&quot;code_1731515980521&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Step 3: 코사인 유사도 계산 (모든 영화 간의 유사도)
cosine_sim = cosine_similarity(tfidf_matrix, tfidf_matrix)
print('코사인 유사도 연산 결과 :',cosine_sim.shape)

&amp;gt; 코사인 유사도 연산 결과 : (45466, 45466)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;코사인 유사도 연산 결과로 생성된 행렬은 45466개의 행과 열을 가지고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이는 45466개의 각 문서 벡터(영화 줄거리 벡터)와 자기 자신을 포함한 다른 45466개의 문서 벡터 간의 유사도를 기록한 행렬입니다. 이 행렬에는 모든 영화 간의 상호 유사도가 기록되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이제 기존 데이터프레임으로부터 &lt;b&gt;영화의 타이틀을 key&lt;/b&gt;, &lt;b&gt;영화의 인덱스를 value&lt;/b&gt;로 하는 딕셔너리 movie_indices를 만들어둡니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f5f5f5; color: #333333; text-align: start;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# 영화 제목을 키(key)로, 데이터프레임의 인덱스를 값(value)으로 갖는 딕셔너리 생성
movie_indices = dict(zip(movies_df['title'], movies_df.index))
movie_indices

&amp;gt; {'Toy Story': 0,
 'Jumanji': 1,
 'Grumpier Old Men': 2,
 'Waiting to Exhale': 3,
 'Father of the Bride Part II': 4,
 'Heat': 5,
 'Sabrina': 888,
 'Tom and Huck': 7,
 'Sudden Death': 8,
 'GoldenEye': 9,
 'The American President': 10,
 'Dracula: Dead and Loving It': 11,
 'Balto': 12,
 'Nixon': 13,
 'Cutthroat Island': 14,
 'Casino': 15,
 'Sense and Sensibility': 16,
 'Four Rooms': 17,
 'Ace Ventura: When Nature Calls': 18,
 'Money Train': 19,
 'Get Shorty': 20,
 'Copycat': 21,
 'Assassins': 22,
 'Powder': 23,
 'Leaving Las Vegas': 24,
...
 'Robin Hood: Prince of Thieves': 998,
 'Mary Poppins': 999,
 'Dumbo': 1000,
 &quot;Pete's Dragon&quot;: 1001,
 ...}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;4️⃣ 추천 시스템 구현: 영화의 제목을 입력하면 사용자가 선택한 영화와 &lt;b&gt;가장 유사한 영화 5개를 추천&lt;/b&gt;합니다.&lt;/h4&gt;
&lt;pre id=&quot;code_1731517108671&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 코사인 유사도를 기반으로 영화 추천 함수 정의
def get_recommendations(title, cosine_sim=cosine_sim):
    # 선택한 영화의 인덱스 가져오기
    idx = movie_indices.get(title) # 주어진 영화 제목(title)에 해당하는 인덱스(idx) 값을 반환합니다. ex) 485
    if idx is None:
        return &quot;해당 영화 제목이 데이터에 없습니다.&quot;
    
    # 해당 영화와 다른 영화 간의 유사도 점수 추출
    sim_scores = list(enumerate(cosine_sim[idx])) # (영화 인덱스, 유사도 점수) -&amp;gt; [(0, 0.143), (1, 0.0)...]

    # 유사도 점수를 기준으로 정렬 (내림차순)
    sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)
    
    # 가장 유사한 영화 5개 선택 (자기 자신 제외)
    sim_scores = sim_scores[1:6] # [(0, 0.14393405169022885), (959, 0.13863297484628673), (2371, 0.13518346539986825), (3201, 0.12138975288943879), (2845, 0.1172780131667607)]

    # 추천 영화 목록 출력
    recommended_indices = [i[0] for i in sim_scores] # 영화 인덱스
    recommended_titles = movies_df['title'].iloc[recommended_indices] # 영화 제목
    return recommended_titles.tolist()

# 예시: 'Malice'와 유사한 영화 추천
get_recommendations(&quot;Malice&quot;)

&amp;gt; ['Toy Story', 'Bliss', 'Tinseltown', 'Judy Berlin', 'The Story of Us']&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;유클리드 거리 (Euclidean Distance)란?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;유클리드 거리는 &lt;b&gt;두 벡터 간의 직선거리를&lt;/b&gt; 의미합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;값이 작을수록 두 문서가 더 유사&lt;/b&gt;하다는 의미이며, 반대로 &lt;b&gt;값이 클수록 문서 간의 차이가 크다&lt;/b&gt;는 의미입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주로&amp;nbsp;좌표 공간에서 &lt;b&gt;두 점 사이의 거리&lt;/b&gt;를 구할 때 사용됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;\[&lt;br /&gt;\text {Euclidean&amp;nbsp;Distance}(A,&amp;nbsp;B)&amp;nbsp;=&amp;nbsp;\sqrt {\sum_{i=1}^{n}&amp;nbsp;(A_i&amp;nbsp;-&amp;nbsp;B_i)^2}&lt;br /&gt;\]&lt;br /&gt;&lt;br /&gt;-&amp;nbsp;\(&amp;nbsp;A&amp;nbsp;\)와&amp;nbsp;\(&amp;nbsp;B&amp;nbsp;\):&amp;nbsp;두&amp;nbsp;벡터&lt;br /&gt;-&amp;nbsp;\(&amp;nbsp;n&amp;nbsp;\):&amp;nbsp;벡터의&amp;nbsp;차원&amp;nbsp;수&lt;br /&gt;-&amp;nbsp;\(&amp;nbsp;A_i,&amp;nbsp;B_i&amp;nbsp;\):&amp;nbsp;두&amp;nbsp;벡터의&amp;nbsp;각&amp;nbsp;성분&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;b&gt;TF-IDF 벡터화&lt;/b&gt;를 통해 각 문서는 &lt;b&gt;수치화된 벡터&lt;/b&gt;로 변환됩니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;각 벡터는 &lt;b&gt;단어의 중요도&lt;/b&gt;를 반영한 값들로 구성되어 있으며, 단어마다 다른 &lt;b&gt;TF-IDF 점수&lt;/b&gt;를 가집니다.&lt;br /&gt;예를 들어, 두 문서가 비슷한 내용을 가지고 있다면, 이 두 문서의 TF-IDF 벡터는 &lt;b&gt;비슷한 값들을&lt;/b&gt; 갖게 되죠.&lt;br /&gt;&lt;br /&gt;거리 계산은 다음과 같이 이루어지는데요.&lt;br /&gt;&amp;nbsp;&amp;nbsp;\[&lt;br /&gt;&amp;nbsp;&amp;nbsp;\text {Euclidean&amp;nbsp;Distance}(A,&amp;nbsp;B)&amp;nbsp;=&amp;nbsp;\sqrt {\sum_{i=1}^{n}&amp;nbsp;(A_i&amp;nbsp;-&amp;nbsp;B_i)^2}&lt;br /&gt;&amp;nbsp;&amp;nbsp;\]&lt;br /&gt;여기서 \(A_i\)와 \(B_i\)는 두 문서의&amp;nbsp;&lt;b&gt;TF-IDF&amp;nbsp;벡터에서&amp;nbsp;각&amp;nbsp;단어의&amp;nbsp;중요도&lt;/b&gt;를&amp;nbsp;나타내는&amp;nbsp;값입니다.&lt;br /&gt;&lt;b&gt;TF-IDF 값이 비슷한 문서&lt;/b&gt;들은, 위 식에서 각 성분의 차이 \((A_i - B_i)\)가 작아지므로, &lt;b&gt;유클리드 거리 값이 작게&lt;/b&gt; 나오겠죠.&lt;br /&gt;&lt;br /&gt;만약, 아래와 같은 3개의 문서가 있는 경우&lt;br /&gt;-&amp;nbsp;문서&amp;nbsp;A:&amp;nbsp;&quot;고양이가&amp;nbsp;귀엽다&quot;&lt;br /&gt;-&amp;nbsp;문서&amp;nbsp;B:&amp;nbsp;&quot;고양이가&amp;nbsp;매우&amp;nbsp;귀엽다&quot;&lt;br /&gt;-&amp;nbsp;문서&amp;nbsp;C:&amp;nbsp;&quot;자동차를&amp;nbsp;운전하다&quot;&lt;br /&gt;&lt;br /&gt;TF-IDF로 벡터화하면 문서 A와 B는 비슷한 단어를 사용하므로 &lt;b&gt;유사한 벡터&lt;/b&gt;를 가질 것입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;반면, 문서 C는 전혀 다른 단어를 사용하므로 &lt;b&gt;벡터가 다를 것&lt;/b&gt;입니다.&lt;br /&gt;&lt;br /&gt;결국 유클리드 거리 계산 결과는,&lt;br /&gt;A와 B 간의 거리는 &lt;b&gt;짧고&lt;/b&gt; (비슷한 문서)&lt;br /&gt;A와 C 또는 B와 C 간의 거리는 &lt;b&gt;길어집니다.&lt;/b&gt; (내용이 다른 문서)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;텍스트 데이터에서 유클리드 거리를 어떻게 계산할까?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예를 들어, 세 개의 문서에 대해 TF-IDF를 계산했다고 가정해 보겠습니다.&lt;br /&gt;&lt;br /&gt;1.&amp;nbsp;문서&amp;nbsp;1의&amp;nbsp;TF-IDF&amp;nbsp;결과:&amp;nbsp;`[0.5,&amp;nbsp;0.3,&amp;nbsp;0.0,&amp;nbsp;0.2]`&lt;br /&gt;2.&amp;nbsp;문서&amp;nbsp;2의&amp;nbsp;TF-IDF&amp;nbsp;결과:&amp;nbsp;`[0.1,&amp;nbsp;0.7,&amp;nbsp;0.0,&amp;nbsp;0.4]`&lt;br /&gt;3.&amp;nbsp;문서&amp;nbsp;3의&amp;nbsp;TF-IDF&amp;nbsp;결과:&amp;nbsp;`[0.0,&amp;nbsp;0.2,&amp;nbsp;0.6,&amp;nbsp;0.1]`&lt;br /&gt;&lt;br /&gt;TF-IDF 벡터를 사용해 유클리드 거리를 계산하는 과정은 다음과 같습니다.&lt;br /&gt;&lt;br /&gt;\[&lt;br /&gt;\text{Euclidean&amp;nbsp;Distance}(A,&amp;nbsp;B)&amp;nbsp;=&amp;nbsp;\sqrt{\sum_{i=1}^{n}&amp;nbsp;(A_i&amp;nbsp;-&amp;nbsp;B_i)^2}&lt;br /&gt;\]&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;만약, 문서 1과 문서 2의 유클리드 거리를 계산한다면&lt;br /&gt;-&amp;nbsp;문서&amp;nbsp;1의&amp;nbsp;벡터:&amp;nbsp;`[0.5,&amp;nbsp;0.3,&amp;nbsp;0.0,&amp;nbsp;0.2]`&lt;br /&gt;-&amp;nbsp;문서&amp;nbsp;2의&amp;nbsp;벡터:&amp;nbsp;`[0.1,&amp;nbsp;0.7,&amp;nbsp;0.0,&amp;nbsp;0.4]`&lt;br /&gt;&lt;br /&gt;1. 벡터 성분 간의 차이 계산&lt;br /&gt;\[&lt;br /&gt;(0.5&amp;nbsp;-&amp;nbsp;0.1)^2&amp;nbsp;=&amp;nbsp;0.16&lt;br /&gt;\]&lt;br /&gt;\[&lt;br /&gt;(0.3&amp;nbsp;-&amp;nbsp;0.7)^2&amp;nbsp;=&amp;nbsp;0.16&lt;br /&gt;\]&lt;br /&gt;\[&lt;br /&gt;(0.0&amp;nbsp;-&amp;nbsp;0.0)^2&amp;nbsp;=&amp;nbsp;0&lt;br /&gt;\]&lt;br /&gt;\[&lt;br /&gt;(0.2&amp;nbsp;-&amp;nbsp;0.4)^2&amp;nbsp;=&amp;nbsp;0.04&lt;br /&gt;\]&lt;br /&gt;&lt;br /&gt;2. 차이 제곱합 계산&lt;br /&gt;\[&lt;br /&gt;0.16&amp;nbsp;+&amp;nbsp;0.16&amp;nbsp;+&amp;nbsp;0&amp;nbsp;+&amp;nbsp;0.04&amp;nbsp;=&amp;nbsp;0.36&lt;br /&gt;\]&lt;br /&gt;&lt;br /&gt;####&amp;nbsp;3.&amp;nbsp;제곱근&amp;nbsp;계산&lt;br /&gt;\[&lt;br /&gt;\sqrt {0.36}&amp;nbsp;=&amp;nbsp;0.6&lt;br /&gt;\]&lt;br /&gt;&lt;br /&gt;따라서, 문서 1과 문서 2의 유클리드 거리는 0.6입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;유클리드 거리 (Euclidean Distance)의 장단점&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- &lt;b&gt;두 벡터 간의 직선거리를&lt;/b&gt; 측정하기 때문에 개념적으로 매우 직관적입니다. 좌표 공간에서 두 점 사이의 거리와 동일한 방식으로 계산되므로, 수치화된 데이터를 분석할 때 쉽게 적용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- &lt;b&gt;수치형 데이터&lt;/b&gt;나 &lt;b&gt;좌표 공간에서의 거리 측정&lt;/b&gt;에 적합합니다. 예를 들어, 고객의 위치, 제품의 특징 벡터 등 수치형 데이터를 다룰 때 유용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- 벡터의 각 성분 간 차이를 고려하기 때문에, 데이터 간의 &lt;b&gt;절대적인 차이&lt;/b&gt;를 반영하는 데 유리합니다. 이로 인해 &lt;b&gt;벡터의 크기가 중요한 분석&lt;/b&gt;에서 유클리드 거리가 효과적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- 텍스트 데이터의 경우, 유클리드 거리는 &lt;b&gt;벡터의 크기에 영향을 받습니다&lt;/b&gt;. 즉, 문서가 길어지면 해당 벡터의 크기도 커지므로, 두 문서 간의 거리가 실제 유사성과 관계없이 멀어질 수 있습니다. 따라서 &lt;b&gt;문서 길이가 다를 경우&lt;/b&gt;, 유클리드 거리는 왜곡된 결과를 초래할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- &lt;b&gt;데이터의 스케일&lt;/b&gt;에 매우 민감합니다. 데이터의 범위가 다를 경우, 큰 값이 작은 값보다 더 큰 영향을 미치게 되므로,&lt;b&gt; 데이터를 스케일링(정규화) 하지&lt;/b&gt; 않으면 부정확한 결과를 가져올 수 있습니다. (TfidfVectorizer는 정규화를 포함하고 있어서 적용하지 않아도 됨)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- 텍스트 데이터를 TF-IDF로 변환하면, 보통 &lt;b&gt;희소 행렬(Sparse Matrix)&lt;/b&gt; 형태로 나타나게 됩니다. 희소 행렬에서 &lt;b&gt;0이 많은 경우&lt;/b&gt;, 벡터 성분 간의 차이 값이 커질 수 있어 &lt;b&gt;왜곡된 거리&lt;/b&gt;를 초래할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- 유클리드 거리는 &lt;b&gt;벡터의 크기 차이만을 반영&lt;/b&gt;하기 때문에 텍스트 데이터처럼 벡터의 &lt;b&gt;방향(내용의 유사성)이 중요한 경우&lt;/b&gt;에는 부적합할 수 있습니다. 예를 들어, &lt;b&gt;문서의 길이가 다르지만 내용이 유사한 문서&lt;/b&gt;들 간의 유사도를 정확히 평가하기 어렵습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;유클리드 거리를 이용한 텍스트 문서 유사도 분석 (예제)&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;TF-IDF로 벡터화한 문서 데이터를 활용해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;유클리드 거리&lt;/b&gt;를 계산하고, 문서 간 유사도를 측정해 보겠습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1️⃣ 예제 데이터 준비&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1731566393078&quot; class=&quot;nix&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;from sklearn.feature_extraction.text import TfidfVectorizer
import pandas as pd
from scipy.spatial.distance import euclidean

# 예제 문서 리스트
corpus = [
    &quot;나는 오늘 밥을 먹었다&quot;,
    &quot;밥을 먹고 운동을 했다&quot;,
    &quot;오늘 운동을 마치고 밥을 먹었다&quot;
]

# TF-IDF 벡터화
vectorizer = TfidfVectorizer()
tfidf_matrix = vectorizer.fit_transform(corpus).toarray()

# 문서 간 유클리드 거리 계산
def calculate_euclidean_distance(matrix):
    n = matrix.shape[0] # 문서의 개수
    distances = pd.DataFrame(index=range(n), columns=range(n)) # n x n 크기의 빈 데이터프레임 생성
    # 문서 간 유클리드 거리 계산
    for i in range(n):
        for j in range(n):
            distances.iloc[i, j] = euclidean(matrix[i], matrix[j])
    return distances

# 유클리드 거리 행렬 출력
euclidean_distances = calculate_euclidean_distance(tfidf_matrix)
euclidean_distances.index = [&quot;문서1&quot;, &quot;문서2&quot;, &quot;문서3&quot;]
euclidean_distances.columns = [&quot;문서1&quot;, &quot;문서2&quot;, &quot;문서3&quot;]
print(&quot;\n유클리드 거리 행렬:&quot;)
print(euclidean_distances)&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;570&quot; data-origin-height=&quot;174&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mfrTf/btsKJjtqtyM/q2UuY4T4rHAW5ylK9WE6Hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mfrTf/btsKJjtqtyM/q2UuY4T4rHAW5ylK9WE6Hk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mfrTf/btsKJjtqtyM/q2UuY4T4rHAW5ylK9WE6Hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmfrTf%2FbtsKJjtqtyM%2Fq2UuY4T4rHAW5ylK9WE6Hk%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;570&quot; height=&quot;174&quot; data-origin-width=&quot;570&quot; data-origin-height=&quot;174&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;문서 1, 2, 3의 유클리드 거리 결과를 보면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;1.&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;문서 1과 문서 3의&lt;/b&gt; 유클리드 거리가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;0.96&lt;/b&gt;으로 가장 가깝습니다. 즉, 이 두 문서는 서로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;가장 유사한 내용&lt;/b&gt;을 가지고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;2.&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;문서 1과 문서 2의&lt;/b&gt; 거리는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;1.32&lt;/b&gt;로, 서로 더&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;멀리 떨어져&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;있어 덜 유사합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;3.&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;문서 2와 문서 3의&lt;/b&gt; 거리는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;1.18&lt;/b&gt;입니다. 이 값은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;문서 1과 문서 2의&lt;/b&gt; 거리보다는 가깝지만,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;문서 1과 문서 3만큼&lt;/b&gt; 가깝지는 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;4.&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;자기 자신과의 거리는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;b&gt;항상 0&lt;/b&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;결론적으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;bull;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;문서1&lt;/b&gt;과&amp;nbsp;&lt;b&gt;문서 3이&lt;/b&gt;&lt;/span&gt; 가장 유사하며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;bull;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;b&gt;문서1&lt;/b&gt;과&lt;/span&gt;&amp;nbsp;&lt;b&gt;문서 2는&lt;/b&gt;&lt;/span&gt; 가장 덜 유사합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;유클리드 거리를 이용한 영화 추천 시스템 (실습)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;이제&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;영화 데이터셋&lt;/b&gt;을 활용하여, 영화 줄거리(&lt;span&gt;overview&lt;/span&gt;)를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;유클리드 거리&lt;/b&gt;로 비교해 유사한 영화를 추천하는 시스템을 구축해 보겠습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1️⃣ 데이터 준비 및 전처리&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;전처리까지는 위에서 진행한 코사인 유사도와 동일한 코드입니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1731566393081&quot; class=&quot;clean&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from scipy.spatial.distance import euclidean

# 데이터 로드 및 전처리
movies_df = pd.read_csv('movies_metadata_low.csv', encoding='ISO-8859-1')
movies_df['overview'] = movies_df['overview'].fillna('')

# TF-IDF 벡터화
tfidf_vectorizer = TfidfVectorizer(stop_words='english')
tfidf_matrix = tfidf_vectorizer.fit_transform(movies_df['overview']).toarray()

# 영화 제목과 인덱스를 매핑하는 딕셔너리 생성
movie_indices = dict(zip(movies_df['title'], movies_df.index))&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2️⃣ 유클리드 거리 기반 추천 함수 구현&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1731566393082&quot; class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;def get_recommendations_euclidean(title, n_recommendations=5):
    # 선택한 영화의 인덱스 가져오기
    idx = movie_indices.get(title)
    if idx is None:
        return &quot;해당 영화 제목이 데이터에 없습니다.&quot;
    
    # 선택한 영화의 TF-IDF 벡터
    target_vector = tfidf_matrix[idx]
    
    # 모든 영화와의 유클리드 거리 계산
    distances = []
    for i in range(len(tfidf_matrix)):
        # 선택된 영화(target_vector)와 모든 영화 간의 유클리드 거리를 계산
        dist = euclidean(target_vector, tfidf_matrix[i])
        distances.append((i, dist))
    
    # 거리 기준으로 정렬 (가까운 순)
    distances = sorted(distances, key=lambda x: x[1])
    
    # 가장 가까운 영화 n개 선택 (자기 자신 제외)
    recommended_indices = [i[0] for i in distances[1:n_recommendations + 1]]
    recommended_titles = movies_df['title'].iloc[recommended_indices]
    return recommended_titles.tolist()

# 예시: 'Malice'와 유사한 영화 추천
print(get_recommendations_euclidean(&quot;Malice&quot;))

&amp;gt; ['Wings of Courage', 'Roommates', 'Peanuts  Die Bank zahlt alles', 'Happy Weekend', 'The Superwife']&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;자카드&amp;nbsp;유사도(Jaccard&amp;nbsp;Similarity)란?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;자카드 유사도는 두 집합 간의 유사도를 측정하는 지표로, 두 집합의 교집합 크기를 합집합 크기로 나눈 값으로 정의됩니다.&lt;br /&gt;&lt;br /&gt;\[&lt;br /&gt;\text {Jaccard&amp;nbsp;Similarity}(A,&amp;nbsp;B)&amp;nbsp;=&amp;nbsp;\frac {|A&amp;nbsp;\cap&amp;nbsp;B|}{|A&amp;nbsp;\cup&amp;nbsp;B|}&lt;br /&gt;\]&lt;br /&gt;&lt;br /&gt;-&amp;nbsp;\(A\),&amp;nbsp;\(B\):&amp;nbsp;비교하고자&amp;nbsp;하는&amp;nbsp;두&amp;nbsp;개의&amp;nbsp;집합&lt;br /&gt;-&amp;nbsp;\(|A&amp;nbsp;\cap&amp;nbsp;B|\):&amp;nbsp;두&amp;nbsp;집합의&amp;nbsp;교집합&amp;nbsp;크기&lt;br /&gt;-&amp;nbsp;\(|A&amp;nbsp;\cup&amp;nbsp;B|\):&amp;nbsp;두&amp;nbsp;집합의&amp;nbsp;합집합&amp;nbsp;크기&lt;br /&gt;&lt;br /&gt;자카드 유사도 값은 &lt;b&gt;0부터 1 사이&lt;/b&gt;의 값을 가집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;- 1에 가까울수록&lt;/b&gt; 두 집합이 유사함을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;- 0에 가까울수록&lt;/b&gt; 두 집합이 겹치는 부분이 거의 없음을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;텍스트 데이터에서 자카드 유사도(Jaccard Similarity)는 어떻게 계산할까?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;아래와 같은 세 개의 문서가 있습니다.&lt;br /&gt;1. 문서 1: &quot;나는 오늘 밥을 먹었다&quot;&lt;br /&gt;2. 문서 2: &quot;밥을 먹고 운동을 했다&quot;&lt;br /&gt;3. 문서 3: &quot;오늘 운동을 마치고 밥을 먹었다&quot;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. 문서의 토큰화 (단어 집합 생성)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;우선, 각 문서를 단어 단위로 분리하여 집합으로 만듭니다.&lt;br /&gt;-&amp;nbsp;문서&amp;nbsp;1의&amp;nbsp;집합:&amp;nbsp;`{나는,&amp;nbsp;오늘,&amp;nbsp;밥을,&amp;nbsp;먹었다}`&lt;br /&gt;-&amp;nbsp;문서&amp;nbsp;2의&amp;nbsp;집합:&amp;nbsp;`{밥을,&amp;nbsp;먹고,&amp;nbsp;운동을,&amp;nbsp;했다}`&lt;br /&gt;-&amp;nbsp;문서&amp;nbsp;3의&amp;nbsp;집합:&amp;nbsp;`{오늘,&amp;nbsp;운동을,&amp;nbsp;마치고,&amp;nbsp;밥을,&amp;nbsp;먹었다}`&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. 자카드 유사도 계산&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;문서 1과 문서 2의 자카드 유사도&lt;br /&gt;-&amp;nbsp;교집합&amp;nbsp;(\(&amp;nbsp;A&amp;nbsp;\cap&amp;nbsp;B&amp;nbsp;\)):&amp;nbsp;`{밥을}`&lt;br /&gt;-&amp;nbsp;합집합&amp;nbsp;(\(&amp;nbsp;A&amp;nbsp;\cup&amp;nbsp;B&amp;nbsp;\)):&amp;nbsp;`{나는,&amp;nbsp;오늘,&amp;nbsp;밥을,&amp;nbsp;먹었다,&amp;nbsp;먹고,&amp;nbsp;운동을,&amp;nbsp;했다}`&lt;br /&gt;&lt;br /&gt;\[&lt;br /&gt;\text{Jaccard&amp;nbsp;Similarity}(A,&amp;nbsp;B)&amp;nbsp;=&amp;nbsp;\frac{|A&amp;nbsp;\cap&amp;nbsp;B|}{|A&amp;nbsp;\cup&amp;nbsp;B|}&amp;nbsp;=&amp;nbsp;\frac {1}{7}&amp;nbsp;\approx&amp;nbsp;0.143&lt;br /&gt;\]&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;자카드&amp;nbsp;유사도(Jaccard&amp;nbsp;Similarity)의&amp;nbsp;장단점&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;장점&lt;br /&gt;- 집합 간의 유사도를 단순히 교집합과 합집합의 비율로 측정하기 때문에 이해하기 쉽고 계산이 간단합니다.&lt;br /&gt;- &lt;b&gt;단어의 존재 여부&lt;/b&gt;에만 초점을 맞추므로, &lt;b&gt;이진 데이터(존재/부재)&lt;/b&gt;를 분석할 때 유용합니다. 예를 들어, 검색 엔진, 추천 시스템 등에서 주로 사용됩니다.&lt;br /&gt;- 빈도나 가중치 대신 &lt;b&gt;단어의 존재 여부만 고려&lt;/b&gt;하기 때문에, 단어 빈도 차이로 인한 영향이 적고, 노이즈에 강합니다.&lt;br /&gt;&lt;br /&gt;단점&lt;br /&gt;- &lt;b&gt;단어의 빈도나 중요도를 반영하지 않기 때문에&lt;/b&gt;, 문서에서 &lt;b&gt;단어가 얼마나 중요한지&lt;/b&gt;를 고려하지 못합니다. 즉, 단어가 여러 번 등장하더라도 단순히 한 번 존재하는 것과 동일하게 취급됩니다.&lt;br /&gt;- &lt;b&gt;단어의 문맥적 의미&lt;/b&gt;를 반영하지 못합니다. 따라서 &lt;b&gt;동의어나 유사한 의미를 가진 단어&lt;/b&gt;가 포함된 문서들이 실제로는 유사하더라도, 낮은 유사도 값을 가질 수 있습니다. 예를 들어, &quot;car&quot;와 &quot;vehicle&quot;이 각각 다른 문서에 포함된 경우, 자카드 유사도는 두 문서를 낮은 유사도로 평가할 수 있습니다.&lt;br /&gt;- 텍스트 데이터를 자카드 유사도로 비교할 때, &lt;b&gt;공통된 단어가 거의 없는 희소 행렬&lt;/b&gt;에서 유사도가 낮게 나옵니다. 특히, &lt;b&gt;단어가 많고 문서 간에 공통 단어가 적을수록&lt;/b&gt;&amp;nbsp;유사도가 낮아질 수 있어 정확한 유사도 측정이 어려워집니다.&lt;br /&gt;- 단어 수가 매우 적은 짧은 문서 간의 유사도 계산 시, &lt;b&gt;한 단어의 차이로도 유사도 값이 크게 변동&lt;/b&gt;할 수 있습니다.&lt;br /&gt;&lt;br /&gt;결론적으로, 자카드&amp;nbsp;유사도는&amp;nbsp;&lt;b&gt;단어의&amp;nbsp;존재&amp;nbsp;여부&lt;/b&gt;를 기준으로 간단하게 유사도를 측정할 수 있는 방법이지만, &lt;b&gt;단어의 빈도, 중요도, 문맥적 의미&lt;/b&gt;를 반영하지 못합니다. 특히, &lt;b&gt;희소한 데이터나 짧은 문서&lt;/b&gt;를 비교할 때는 신뢰도가 낮아질 수 있습니다. 이러한 이유로, 자카드 유사도는 &lt;b&gt;텍스트 데이터 분석보다는 이진 데이터 분석&lt;/b&gt;에 더 적합한 경우가 많습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;자카드 유사도를 이용한 텍스트 문서 유사도 분석 (예제)&lt;/b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1731575254780&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics import jaccard_score

# 예제 문서 리스트
corpus = [
    &quot;나는 오늘 밥을 먹었다&quot;,
    &quot;밥을 먹고 운동을 했다&quot;,
    &quot;오늘 운동을 마치고 밥을 먹었다&quot;
]

# CountVectorizer를 사용해 단어 집합 생성 (1-gram 기준)
vectorizer = CountVectorizer()
binary_matrix = vectorizer.fit_transform(corpus).toarray()

# 자카드 유사도 계산
def calculate_jaccard_similarity(matrix):
    n = matrix.shape[0]
    similarities = []
    for i in range(n):
        for j in range(i + 1, n):
            sim = jaccard_score(matrix[i], matrix[j], average='binary')
            similarities.append((f&quot;문서 {i + 1}&quot;, f&quot;문서 {j + 1}&quot;, sim))
    return similarities

# 결과 출력
jaccard_similarities = calculate_jaccard_similarity(binary_matrix)
for doc1, doc2, sim in jaccard_similarities:
    print(f&quot;{doc1}와 {doc2}의 자카드 유사도: {sim:.3f}&quot;)&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;504&quot; data-origin-height=&quot;108&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dua4LW/btsKJ2LCP2L/CJR76kNSfcyUiSt2Hn4K20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dua4LW/btsKJ2LCP2L/CJR76kNSfcyUiSt2Hn4K20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dua4LW/btsKJ2LCP2L/CJR76kNSfcyUiSt2Hn4K20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdua4LW%2FbtsKJ2LCP2L%2FCJR76kNSfcyUiSt2Hn4K20%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;443&quot; height=&quot;95&quot; data-origin-width=&quot;504&quot; data-origin-height=&quot;108&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;문서 1과 문서 3의 자카드 유사도(0.500)가 가장 높습니다. 즉, 문서 1과 문서 3이 다른 문서 쌍에 비해 공통된 단어를 더 많이 가지고 있어서 &lt;b&gt;가장 유사한&lt;/b&gt; 것으로 해석할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;b&gt;자카드 유사도&lt;/b&gt;&lt;/b&gt;&lt;b&gt;를 이용한 영화 추천 시스템 (실습)&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;이제&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;영화 데이터셋&lt;/b&gt;을 활용하여, 영화 줄거리(&lt;span&gt;overview&lt;/span&gt;)를&lt;b&gt;&lt;span&gt; 자카드 유사도&lt;/span&gt;&lt;/b&gt;로 비교해 유사한 영화를 추천하는 시스템을 구축해 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-size: 1.12em; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;자카드 유사도를 텍스트 데이터에 적용하려면, 먼저&lt;b&gt; TF-IDF 대신 이진 벡터&lt;/b&gt;를 사용해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;`&lt;b&gt;CountVectorizer&lt;/b&gt;`를 이용해 &lt;b&gt;이진 벡터&lt;/b&gt;로 변환한 후 자카드 유사도를 계산할 수 있습니다.&lt;br /&gt;(CountVectorizer(binary=True)를 사용하여 텍스트를 이진 벡터화합니다. 각 단어가 문서에 &lt;b&gt;존재하면 1, 없으면 0&lt;/b&gt;으로 표시합니다.)&lt;/p&gt;
&lt;pre id=&quot;code_1731575633070&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics import jaccard_score

# 데이터 로드 및 전처리
movies_df = pd.read_csv('movies_metadata_low.csv', encoding='ISO-8859-1')
movies_df['overview'] = movies_df['overview'].fillna('')

# CountVectorizer를 사용해 이진 벡터화
count_vectorizer = CountVectorizer(stop_words='english', binary=True)
binary_matrix = count_vectorizer.fit_transform(movies_df['overview']).toarray()

# 영화 제목과 인덱스를 매핑하는 딕셔너리 생성
movie_indices = dict(zip(movies_df['title'], movies_df.index))

def get_recommendations_jaccard(title, n_recommendations=5):
    # 선택한 영화의 인덱스 가져오기
    idx = movie_indices.get(title)
    if idx is None:
        return &quot;해당 영화 제목이 데이터에 없습니다.&quot;
    
    # 선택한 영화의 이진 벡터 가져오기
    target_vector = binary_matrix[idx]
    
    # 모든 영화와의 자카드 유사도 계산
    similarities = []
    for i in range(len(binary_matrix)):
        sim = jaccard_score(target_vector, binary_matrix[i])
        similarities.append((i, sim))
    
    # 유사도 기준으로 정렬 (내림차순)
    similarities = sorted(similarities, key=lambda x: x[1], reverse=True)
    
    # 가장 유사한 영화 n개 선택 (자기 자신 제외)
    recommended_indices = [i[0] for i in similarities[1:n_recommendations + 1]]
    recommended_titles = movies_df['title'].iloc[recommended_indices]
    return recommended_titles.tolist()

# 'Malice'와 유사한 영화 추천
print(get_recommendations_jaccard(&quot;Malice&quot;))

&amp;gt; ['Bliss', 'The Story of Us', 'Judy Berlin', 'American Graffiti', 'In Dreams']&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>pytorch</category>
      <category>cosine_similarity</category>
      <category>각도</category>
      <category>문서간유사도</category>
      <category>유사도</category>
      <category>유클리드거리</category>
      <category>자카드 유사도</category>
      <category>추천시스템</category>
      <category>코사인유사도</category>
      <category>크기</category>
      <category>텍스트 데이터</category>
      <author>ISFP의 블로그</author>
      <guid isPermaLink="true">https://resultofeffort.tistory.com/147</guid>
      <comments>https://resultofeffort.tistory.com/147#entry147comment</comments>
      <pubDate>Sun, 1 Dec 2024 23:13:18 +0900</pubDate>
    </item>
    <item>
      <title>[오류Error] Resource punkt_tab not found.  Please use the NLTK Downloader to obtain the resource:</title>
      <link>https://resultofeffort.tistory.com/146</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;텍스트 전처리 공부하는 중에 로컬에서 토크나이저를 수행하려고 하니 에러가 발생했다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;sent_text = sent_tokenize(content_text)&lt;/p&gt;
&lt;pre id=&quot;code_1731656276494&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
	&quot;name&quot;: &quot;LookupError&quot;,
	&quot;message&quot;: &quot;
**********************************************************************
  Resource punkt_tab not found.
  Please use the NLTK Downloader to obtain the resource:

  &amp;gt;&amp;gt;&amp;gt; import nltk
  &amp;gt;&amp;gt;&amp;gt; nltk.download('punkt_tab')
  
  For more information see: https://www.nltk.org/data.html

  Attempted to load tokenizers/punkt_tab/english/

  Searched in:
    - '/Users/song/nltk_data'
    - '/Users/song/opt/anaconda3/envs/song38/nltk_data'
    - '/Users/song/opt/anaconda3/envs/song38/share/nltk_data'
    - '/Users/song/opt/anaconda3/envs/song38/lib/nltk_data'
    - '/usr/share/nltk_data'
    - '/usr/local/share/nltk_data'
    - '/usr/lib/nltk_data'
    - '/usr/local/lib/nltk_data'
**********************************************************************
&quot;,
	&quot;stack&quot;: &quot;---------------------------------------------------------------------------
LookupError                               Traceback (most recent call last)
Cell In[8], line 2
      1 # 입력 코퍼스에 대해서 NLTK를 이용하여 문장 토큰화를 수행.
----&amp;gt; 2 sent_text = sent_tokenize(content_text)
      4 # # 각 문장에 대해서 구두점을 제거하고, 대문자를 소문자로 변환.
      5 # normalized_text = []
      6 # for string in sent_text:
   (...)
     10 # # 각 문장에 대해서 NLTK를 이용하여 단어 토큰화를 수행.
     11 # result = [word_tokenize(sentence) for sentence in normalized_text]

File ~/opt/anaconda3/envs/song38/lib/python3.8/site-packages/nltk/tokenize/__init__.py:119, in sent_tokenize(text, language)
    109 def sent_tokenize(text, language=\&quot;english\&quot;):
    110     \&quot;\&quot;\&quot;
    111     Return a sentence-tokenized copy of *text*,
    112     using NLTK's recommended sentence tokenizer
   (...)
    117     :param language: the model name in the Punkt corpus
    118     \&quot;\&quot;\&quot;
--&amp;gt; 119     tokenizer = _get_punkt_tokenizer(language)
    120     return tokenizer.tokenize(text)

File ~/opt/anaconda3/envs/song38/lib/python3.8/site-packages/nltk/tokenize/__init__.py:105, in _get_punkt_tokenizer(language)
     96 @functools.lru_cache
     97 def _get_punkt_tokenizer(language=\&quot;english\&quot;):
     98     \&quot;\&quot;\&quot;
     99     A constructor for the PunktTokenizer that utilizes
    100     a lru cache for performance.
   (...)
    103     :type language: str
    104     \&quot;\&quot;\&quot;
--&amp;gt; 105     return PunktTokenizer(language)

File ~/opt/anaconda3/envs/song38/lib/python3.8/site-packages/nltk/tokenize/punkt.py:1744, in PunktTokenizer.__init__(self, lang)
   1742 def __init__(self, lang=\&quot;english\&quot;):
   1743     PunktSentenceTokenizer.__init__(self)
-&amp;gt; 1744     self.load_lang(lang)

File ~/opt/anaconda3/envs/song38/lib/python3.8/site-packages/nltk/tokenize/punkt.py:1749, in PunktTokenizer.load_lang(self, lang)
   1746 def load_lang(self, lang=\&quot;english\&quot;):
   1747     from nltk.data import find
-&amp;gt; 1749     lang_dir = find(f\&quot;tokenizers/punkt_tab/{lang}/\&quot;)
   1750     self._params = load_punkt_params(lang_dir)
   1751     self._lang = lang

File ~/opt/anaconda3/envs/song38/lib/python3.8/site-packages/nltk/data.py:579, in find(resource_name, paths)
    577 sep = \&quot;*\&quot; * 70
    578 resource_not_found = f\&quot;\
{sep}\
{msg}\
{sep}\
\&quot;
--&amp;gt; 579 raise LookupError(resource_not_found)

LookupError: 
**********************************************************************
  Resource punkt_tab not found.
  Please use the NLTK Downloader to obtain the resource:

  &amp;gt;&amp;gt;&amp;gt; import nltk
  &amp;gt;&amp;gt;&amp;gt; nltk.download('punkt_tab')
  
  For more information see: https://www.nltk.org/data.html

  Attempted to load tokenizers/punkt_tab/english/

  Searched in:
    - '/Users/song/nltk_data'
    - '/Users/song/opt/anaconda3/envs/song38/nltk_data'
    - '/Users/song/opt/anaconda3/envs/song38/share/nltk_data'
    - '/Users/song/opt/anaconda3/envs/song38/lib/nltk_data'
    - '/usr/share/nltk_data'
    - '/usr/local/share/nltk_data'
    - '/usr/lib/nltk_data'
    - '/usr/local/lib/nltk_data'
**********************************************************************
&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;에러 메시지를 보면, &lt;span&gt;nltk&lt;/span&gt; 라이브러리가 &lt;span&gt;punkt_tab&lt;/span&gt; 리소스를 찾지 못해서 발생한 문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;punkt&lt;/span&gt;는 NLTK의 &lt;b&gt;문장 토큰화&lt;/b&gt;를 위해 필요한 데이터이기 때문에 &lt;span&gt;nltk.download()&lt;/span&gt; 함수를 사용하여 필요한 데이터를 설치해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;해결 방법&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1731656423627&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import nltk

# punkt 데이터 다운로드
nltk.download('punkt')&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>오류Error</category>
      <category>error</category>
      <category>konlpy</category>
      <category>nlp</category>
      <category>nltk</category>
      <category>punkt</category>
      <category>오류</category>
      <category>오블완</category>
      <category>자연어처리</category>
      <category>텍스트전처리</category>
      <category>티스토리챌린지</category>
      <category>해결</category>
      <category>형태소</category>
      <author>ISFP의 블로그</author>
      <guid isPermaLink="true">https://resultofeffort.tistory.com/146</guid>
      <comments>https://resultofeffort.tistory.com/146#entry146comment</comments>
      <pubDate>Fri, 22 Nov 2024 12:24:31 +0900</pubDate>
    </item>
  </channel>
</rss>