<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>brickmate.log</title>
        <link>https://velog.io/</link>
        <description>Anything Possible!</description>
        <lastBuildDate>Tue, 30 Apr 2024 06:50:37 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>brickmate.log</title>
            <url>https://velog.velcdn.com/images/brickmate_-/profile/cd8110e0-982a-4c57-8f69-d117dace2f0f/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. brickmate.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/brickmate_-" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[AWS]Cloudfront + S3 정적 웹사이트 배포]]></title>
            <link>https://velog.io/@brickmate_-/AWSCloudfront-S3-%EC%A0%95%EC%A0%81-%EC%9B%B9%EC%82%AC%EC%9D%B4%ED%8A%B8-%EB%B0%B0%ED%8F%AC</link>
            <guid>https://velog.io/@brickmate_-/AWSCloudfront-S3-%EC%A0%95%EC%A0%81-%EC%9B%B9%EC%82%AC%EC%9D%B4%ED%8A%B8-%EB%B0%B0%ED%8F%AC</guid>
            <pubDate>Tue, 30 Apr 2024 06:50:37 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요 브릭메이트 Dong입니다. 오늘은 AWS Cloudfront와 S3를 연동시켜 정적 웹사이트를 배포하는 과정을 한번 진행해 보도록 하겠습니다. </p>
<h3 id="cloudfront란">Cloudfront란?</h3>
<p>CloudFront는 아마존 웹 서비스(AWS)에서 제공하는 콘텐츠 전송 네트워크(CDN) 서비스입니다. 전 세계에 분산된 엣지 로케이션에 캐시하여 사용자들에게 더 빠르고 안정적인 서비스를 제공합니다. 이는 사용자가 더 가까운 엣지 로케이션에서 콘텐츠를 가져오므로 응답 시간이 단축되고, 대용량 트래픽에 대비하여 확장성이 향상됩니다.</p>
<h3 id="s3란-무엇일까">S3란 무엇일까?</h3>
<p>S3는 사용자가 필요에 따라 데이터를 저장하고 검색할 수 있는 확장 가능한, 내구성이 뛰어난 저장소입니다. 데이터는 버킷(bucket)이라는 개별적인 저장소 컨테이너에 저장되며, 각 객체는 고유한 키를 가지고 있습니다. 또한, S3는 높은 내구성을 제공하여 데이터 손실이나 손상을 최소화한다는 장점이 있습니다.</p>
<p>그럼 바로 웹사이트 배포를 진행해보도록 하겠습니다!</p>
<h3 id="1-먼저-버킷을-생성해줍니다">1. 먼저 버킷을 생성해줍니다.</h3>
<p><img src="https://velog.velcdn.com/images/rlaehdwn0105/post/edbd164b-c7ca-4791-adbd-c324f3d70c84/image.png" alt=""></p>
<ul>
<li>모든 퍼블릭 엑세스 차단 설정 
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/95db40d7-3044-402e-8d92-4a18f3188141/image.png" alt=""></li>
<li>나머지는 기본설정을 해주고 버킷을 생성해줍시다. <h3 id="2-버킷-정적-웹-사이트-호스팅-활성화">2. 버킷 정적 웹 사이트 호스팅 활성화</h3>
</li>
<li>버킷 &gt; 속성 &gt; 정적 웹사이트 호스트 편집순서로 이동하면 됩니다!
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/c4747d7d-530a-49f7-add8-bd371e668ee8/image.png" alt=""><blockquote>
<p>기본페이지를 index.html파일로 설정해 줍시다. </p>
</blockquote>
</li>
</ul>
<h3 id="3-부트스트랩-템플릿-다운후-업로드">3. 부트스트랩 템플릿 다운후 업로드</h3>
<ul>
<li><p>부트스트랩에서 무료로 제공하는 예제 템플릿을 다운해줍니다.
<a href="https://startbootstrap.com/#google_vignette">https://startbootstrap.com/#google_vignette</a>
![]
(<a href="https://velog.velcdn.com/images/rlaehdwn0105/post/0155af83-3220-43cd-aac9-e91960ffddc2/image.png">https://velog.velcdn.com/images/rlaehdwn0105/post/0155af83-3220-43cd-aac9-e91960ffddc2/image.png</a>)</p>
</li>
<li><p>다운받은 파일을 버킷에 업로드 시켜줍시다.
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/e520c070-2d15-4da6-80ac-d5a1f3e22e29/image.png" alt=""></p>
</li>
<li><p>S3 호스팅 엔드포인트 주소로 접속해봅시다 
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/c454dae6-ba46-4ece-8c69-980cfc8386dd/image.png" alt=""></p>
</li>
<li><p>접속되지 않는 것을 확인할 수 있습니다. 
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/760996dc-a534-4ffa-a2d7-2cf25bd0646a/image.png" alt=""></p>
</li>
</ul>
<blockquote>
<p>퍼블릭 엑세스 요청을 막았기 떄문에 Public에 공개된 URL를 통해 접근할 수 없습니다. 그래서 Cloudfront을 통해 버킷에 접근을 해야합니다. 이 방법은 외부에서 직접적으로 S3에 접근할 수 없기 떄문에 보안에 효율적이며 이미지를 빠르게 캐싱할 수 있습니다.</p>
</blockquote>
<h3 id="4-cloudfront을-생성하여-s3와-연동시켜줍니다">4. Cloudfront을 생성하여 S3와 연동시켜줍니다.</h3>
<ul>
<li>도메인을 버킷을 선택해주고 Cloudfront에 대한 엑세스만 제할 할수 있게 원본 엑세스 제어 설정을 체크하고 OAC를 하나만들어 줍니다.<br><img src="https://velog.velcdn.com/images/rlaehdwn0105/post/e9339fb4-71d4-4854-9b3f-64e9b58c2bc4/image.png" alt=""></li>
<li>Redirect HTTP to HTTPS를 선택해줍니다.
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/7159c5df-bc61-46b6-a333-8863b83fb951/image.png" alt=""></li>
</ul>
<blockquote>
<p>현재 테스트만 진행할 것이기 떄문에 Origin Shield나 WAF는 사용하지 않도록 하겠습니다. </p>
</blockquote>
<ul>
<li>기본값 루트 객체를 index.html으로 설정해줍니다
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/377a4d69-19f5-491e-adfb-ba0bdb5f1a57/image.png" alt=""></li>
</ul>
<blockquote>
<p>Cloudfront URL에서 S3 페이지를 가져오기위해선 Cloudfonrt URL/index.html을 통해 접속해야하는데 이 과정을 생략하고 바로 URL주소에서 페이지를 처리하기위해서 설정해줍니다!</p>
</blockquote>
<h3 id="5-s3-버킷-정책-업데이트-진행">5. S3 버킷 정책 업데이트 진행</h3>
<ul>
<li>버킷정책을 복사해줍니다. 
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/ffacffcf-d6d9-4c30-bad4-655cf862df6e/image.png" alt=""></li>
<li>버킷 &gt; 권한 &gt; 버킷정책 &gt; 편집으로 복사해준 Json을 붙여줍니다.
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/06dd7787-993b-40db-9423-1f953041c213/image.png" alt=""></li>
</ul>
<h3 id="6-cloudfront-도메인-주소-확인">6. Cloudfront 도메인 주소 확인</h3>
<p><img src="https://velog.velcdn.com/images/rlaehdwn0105/post/701d0348-e3f1-406a-82b0-0b42498ad97a/image.png" alt=""></p>
<blockquote>
<p>Cloudfront 도메인으로 정적 웹페이지를 볼 수 있습니다!</p>
</blockquote>
<p>갑사합니다.</p>
<p>사진 참조 <a href="https://velog.io/@brickmate_-/posts">https://velog.io/@brickmate_-/posts</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[NCP] 로드밸런서 상품 소개]]></title>
            <link>https://velog.io/@brickmate_-/NCP-%EB%A1%9C%EB%93%9C%EB%B0%B8%EB%9F%B0%EC%84%9C-%EC%83%81%ED%92%88-%EC%86%8C%EA%B0%9C</link>
            <guid>https://velog.io/@brickmate_-/NCP-%EB%A1%9C%EB%93%9C%EB%B0%B8%EB%9F%B0%EC%84%9C-%EC%83%81%ED%92%88-%EC%86%8C%EA%B0%9C</guid>
            <pubDate>Mon, 29 Apr 2024 08:34:38 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요! 
브릭메이트 Arnold 입니다.
오늘은 NCP(Naver Cloud Platform)의 로드밸런서 상품에 대해 알아 보도록 하겠습니다.</p>
<h2 id="개요"><strong>개요</strong></h2>
<p>Load Balancer는 수신 트래픽을 다수의 서버로 분산시키는 서비스로서, 수신 트래픽을 등록된 멤버 서버로 분산시켜 가용성을 높이고 시스템 가동률을 조절하는 역할을 수행합니다.</p>
<p>VPC 플랫폼에서는 Network Load Balancer / Application Load Balancer / Network Proxy Load Balancer 가 제공되어 서비스에 적합한 로드밸런서를 선택할 수 있습니다.</p>
<h2 id="종류"><strong>종류</strong></h2>
<blockquote>
<p>부하처리 성능에 따라 Small / Medium / Large 중 선택할 수 있으며 로드밸런서마다 각각 초당 연결수 (CPS) 기준이 다릅니다.</p>
</blockquote>
<p>*<em>1. Application Load Balancer
*</em>                </p>
<ul>
<li><p>HTTP/HTTPS 트래픽에 대해서 패킷 헤더를 확인하여 Application 레벨에서의 분기처리를 제공합니다.
로드밸런서의 리스너에 Host Header기반 분기처리, URL Path Pattern 기반 분기처리, 가중치 기반 분기처리, Redirection 응답처리와 같은 규칙이 지원되어 보다 상세한 고급 서비스 구성이 가능합니다.</p>
<ul>
<li>각 30,000 / 60,000 / 90,000 개의 분산처리를 보장 </li>
</ul>
</li>
</ul>
<p>*<em>2. Network Load Balancer
*</em>    </p>
<ul>
<li><p>네트워크 로드밸런서는 초당 연결 수 기준 최소100,000개에서 최대 400,000개까지 성능을 보장하는 단계별 상품을 제공하여 고객 서비스 규모에 최적화된 분산처리 성능을 제공합니다. 
또한 네트워크 로드밸런서는 트래픽 분배만 수행하고 고객 서버에서 직접 응답하는 기능(DSR)을 구현하여 보다 빠르고 효율적인 서비스를 이용하실 수 있습니다.</p>
<ul>
<li>각 100,000 / 200,000 / 400,000 개의 분산처리를 보장</li>
</ul>
</li>
</ul>
<p>*<em>3. Network Proxy Load Balancer
*</em>    </p>
<ul>
<li><p>네트워크 프록시 로드밸런서는 프록시 방식의 통신을 제공하여 세션 유지가 필요한 TCP 기반 애플리케이션에 이용할 수 있습니다.
또한 애플리케이션 로드밸런서와 동일한 부하 분산 알고리즘을 적용할 수 있습니다.</p>
<ul>
<li>각 30,000 / 60,000 / 90,000 개의 분산처리를 보장</li>
</ul>
</li>
</ul>
<blockquote>
<p>KR존/서브넷 별 LB 생성지역 지정 가능 : VPC 환경에서는 <strong>본인이 원하는 KR존의 특정 서브넷에 LB생성 가능, KR-1/2 존에 각각 생성하여 고가용성을 확보</strong> 할 수 있습니다.</p>
</blockquote>
<h2 id="로드밸런싱-알고리즘">로드밸런싱 알고리즘</h2>
<p><img src="https://velog.velcdn.com/images/brickmate_-/post/d299e395-f64a-4f86-98c5-cd4d1e85434d/image.png" alt=""></p>
<ul>
<li>Round Robin : 클라이언트에서 요청이 오면 서버에 1개씩 분배하는 방식</li>
<li>Least Connection : 클라이언트 연결이 제일 적은 서버에게 새로운 커넥션을 분배하는 방식</li>
<li>Source IP Hash : 클라이언트 IP에 대한 해시테이블을 가지고 클라이언트 IP에 매핑되는 서버에 새로운 커넥션을 분배하는 방식</li>
</ul>
<h2 id="ssl-인증-및-암호화-설정">SSL 인증 및 암호화 설정</h2>
<ul>
<li>웹 기반의 콘솔에서 SSL 인증서를 추가할 수 있습니다. TLSv1, TLSv1.1, TLSv1.2 등 SSL 프로토콜 중 가능한 버전을 선택해 사용할 수 있으며, 적용된 SSL Ciphers를 설정할 수 있습니다. SSL 인증서는 Certificate Manager와 연동하여 편리하게 관리됩니다.</li>
</ul>
<h2 id="load-balancer-모니터링">Load Balancer 모니터링</h2>
<ul>
<li>로드밸런서에 대해서는 기본 모니터링 정보를 제공하며 서버 모니터링과 마찬가지로 기간 선택에 따라 모니터링 정보
수집 주기를 1분, 5분, 2시간, 1일 단위로 제공합니다. </li>
<li>네트워크 로드밸런서 모니터링은 Concurrent Connection, 초 당 Connection, Traffic In, (Un)Available hosts 등 5가지 항목의 정보를 제공하며, 애플리케이션 로드밸런서는 Traffic Out을 포함하여 6가지 항목을 제공합니다.</li>
</ul>
<h2 id="load-balancer-포트-설정">Load Balancer 포트 설정</h2>
<ul>
<li>여러 개의 로드밸런서 규칙을 동시에 설정할 수 있습니다. </li>
<li>로드밸런서 규칙을 설정할 때는 로드밸런서 포트를 다른 로드밸런서 규칙의 포트와 다르게 설정해야 합니다. 서버 포트는 다른 로드밸런서 규칙의 서버 포트와 동일하게 설정하셔도 됩니다.</li>
</ul>
<h2 id="lb-선택-기준-및-기능-비교"><strong>LB 선택 기준 및 기능 비교</strong></h2>
<img src="https://velog.velcdn.com/images/brickmate_-/post/0887eb2f-e202-4d03-ac71-5bb0fd87365a/image.png" width="50%" height="0%">


<table>
<thead>
<tr>
<th>기능</th>
<th>Network LB</th>
<th>Network Proxy LB</th>
<th>Application</th>
</tr>
</thead>
<tbody><tr>
<td>프로토콜</td>
<td>TCP</td>
<td>TCP, TLS</td>
<td>HTTP/HTTPS</td>
</tr>
<tr>
<td>상태확인</td>
<td>O</td>
<td>O</td>
<td>O</td>
</tr>
<tr>
<td>로깅</td>
<td>X</td>
<td>O</td>
<td>O</td>
</tr>
<tr>
<td>DSR</td>
<td>O</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>동일 인스턴스의여러 포트로로드밸런싱</td>
<td>X</td>
<td>X</td>
<td>O</td>
</tr>
<tr>
<td>HTTP 2.0</td>
<td>N/A</td>
<td>N/A</td>
<td>O</td>
</tr>
<tr>
<td>경로기반 라우팅</td>
<td>N/A</td>
<td>N/A</td>
<td>O (출시 예정)</td>
</tr>
<tr>
<td>SSL Offload</td>
<td>X</td>
<td>O</td>
<td>O</td>
</tr>
<tr>
<td>고정 세션</td>
<td>X</td>
<td>O</td>
<td>O</td>
</tr>
</tbody></table>
<h2 id="참고-url"><strong>참고 URL</strong></h2>
<ol>
<li>Ncloud VPC 환경 Load Balancer 가이드 : <strong><a href="https://guide.ncloud-docs.com/docs/loadbalancer-start-vpc">https://guide.ncloud-docs.com/docs/loadbalancer-start-vpc</a></strong></li>
</ol>
<hr>
<p>감사합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[NCP] AutoScaling 구현]]></title>
            <link>https://velog.io/@brickmate_-/NCP-AutoScaling-%ED%85%8C%EC%8A%A4%ED%8A%B8</link>
            <guid>https://velog.io/@brickmate_-/NCP-AutoScaling-%ED%85%8C%EC%8A%A4%ED%8A%B8</guid>
            <pubDate>Mon, 29 Apr 2024 02:18:45 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요. 브릭메이트 Dong입니다. 오늘은 간단하게 Autoscaling에 대해 설명드리고 네이버 클라우드 플랫폼(NCP)에서 테스트해보는 시간을 갖도록 하겠습니다. </p>
<h3 id="🚩-먼저-autoscaling이란-무엇일까요">🚩 먼저 Autoscaling이란 무엇일까요?</h3>
<ul>
<li>Autoscaling은 애플리케이션 또는 서비스의 트래픽 변화에 따라 자동으로 리소스를 조정하는 기술입니다. 예를 들어, 웹 애플리케이션의 사용자 수가 증가하면 서버 수를 자동으로 늘리고, 사용자 수가 감소하면 서버 수를 줄이는 것이 Autoscaling의 핵심 아이디어입니다. 이를 통해 서비스의 가용성과 성능을 최적화하고, 인프라 리소스를 효율적으로 활용할 수 있습니다. 특히 클라우드 컴퓨팅 환경에서 유용하며, 사용자의 수요에 신속하게 대응하여 비용을 절감할 수 있는 장점이 있습니다.</li>
</ul>
<h3 id="💆-autoscaling에는-두가지-확장-방식이있습니다-바로-수직적-확장scale-up-수평적-확장scale-out입니다">💆 Autoscaling에는 두가지 확장 방식이있습니다. 바로 수직적 확장(Scale-up), 수평적 확장(Scale-out)입니다.</h3>
<ol>
<li>Scale out (수평 확장):</li>
</ol>
<ul>
<li>Scale out은 시스템의 성능을 향상시키기 위해 여러 개의 인스턴스 또는 서버를 추가하는 것을 의미합니다.</li>
<li>예를 들어, 웹 애플리케이션의 부하가 증가하면 새로운 서버 인스턴스를 추가하여 트래픽을 분산시키는 것이 Scale out입니다.</li>
<li>Scale out은 주로 분산 시스템에서 사용되며, 확장성이 높은 애플리케이션을 구현하는 데 유용합니다.</li>
</ul>
<ol start="2">
<li>Scale up (수직 확장):</li>
</ol>
<ul>
<li>Scale up은 단일 서버 또는 인스턴스의 리소스(예: CPU, 메모리, 디스크 공간 등)를 증가시키는 것을 의미합니다.</li>
<li>예를 들어, 기존 서버의 메모리를 늘리거나 CPU를 업그레이드하여 더 많은 작업을 처리할 수 있는 더 강력한 서버로 스케일 업할 수 있습니다.</li>
<li>Scale up은 주로 단일 서버 환경에서 사용되며, 한정된 리소스를 가진 애플리케이션의 성능을 향상시키는 데 유용합니다.</li>
</ul>
<p>요약하면, Scale out은 서버 인스턴스를 추가하여 확장성을 향상시키는 반면, Scale up은 기존 서버의 성능을 강화하여 성능을 향상시키는 것입니다.</p>
<p>간단하게 이론을 봤으니 네이버클라우드 플랫폼에서 실제로 구축해보고 테스트해보면서 다시 한번 이해 해보는 시간을 갖도록 하겠습니다. 🤓</p>
<h3 id="🚣-아키텍처-구축-순서">🚣 아키텍처 구축 순서</h3>
<ul>
<li>Server 생성 </li>
<li>Application Load Balancer 생성(Target Group 포함) </li>
<li>Auto Scaling Launch Configuration 설정</li>
<li>Auto Scaling Group 설정</li>
<li>Cloud Insight Monitoring Event Rule 설정</li>
</ul>
<h3 id="1-테스트를-진행할-server를-하나-생성해줍시다">1. 테스트를 진행할 Server를 하나 생성해줍시다.</h3>
<p><img src="https://velog.velcdn.com/images/rlaehdwn0105/post/cccf118a-e782-4549-b15b-a6c2c617cd58/image.png" alt=""></p>
<blockquote>
<p>VPC와 Subnet을 생성했다는 가정하에 진행하도록 하겠습니다!</p>
</blockquote>
<h3 id="2-application-load-balancer-taget-group-생성">2. Application Load Balancer, Taget Group 생성</h3>
<p> <img src="https://velog.velcdn.com/images/rlaehdwn0105/post/74d47cb2-4f1d-44dd-b3aa-a8d56593c6ee/image.png" alt=""></p>
<blockquote>
<p>타겟 그룹에는 HTTP프로토콜 80포트를 타겟으로 해주면 됩니다! </p>
</blockquote>
<h3 id="3-server-image-생성">3. Server image 생성</h3>
<p><img src="https://velog.velcdn.com/images/rlaehdwn0105/post/a8fd58c5-423b-4aa7-bb8b-836c52949381/image.png" alt=""></p>
<blockquote>
<p>Auto Scaling Launch Configuration에서 사용할 Server Image를 생성해줍니다!</p>
</blockquote>
<h3 id="4-launch-configuration-생성">4. Launch Configuration 생성</h3>
<ul>
<li><p>미리생성해둔 서버이미지를 선택합니다.
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/b12d844d-12c1-487e-b7a2-5974968818b7/image.png" alt=""></p>
<blockquote>
<p>Launch Configuration은 Autoscaling작동시 서버타입을 지정해주는 역할을 합니다!</p>
</blockquote>
</li>
<li><p>init Script를 통해 미리 Apache를 설치하여 로드밸런서 라운드로빈 테스트를 진행할 것입니다. 
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/a5f48223-85b7-40ed-a0cd-20097485ebbc/image.png" alt=""></p>
<ul>
<li>init script 생성 
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/63d2fc24-f3db-4331-bf60-e193b30eb842/image.png" alt=""></li>
</ul>
</li>
<li><p>init script 코드 </p>
<pre><code>#! /bin/bash
yum install -y httpd 
systemctl start httpd 
cd /var/www/html
echo hostname : $HOSTNAME &gt; index.html
systemctl restart httpd</code></pre></li>
<li><p>Launch Configuration 생성완료
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/f2749469-3d2d-4be7-996c-8011e0d227c0/image.png" alt=""></p>
</li>
</ul>
<h3 id="5-auto-scaling-group-생성">5. Auto Scaling Group 생성</h3>
<ul>
<li><p>좀 전에 만든 Launch Configuration 선택해줍니다.
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/55b4cc39-328b-4ea0-af84-9d0194638cdf/image.png" alt=""></p>
</li>
<li><p>꼭 헬스 체크 유형을 로드밸런서를 선택해줍니다.
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/05bb8032-0f2f-4b50-991a-061f548b5693/image.png" alt=""></p>
<blockquote>
<p>최소 용량: 항상 유지해야 하는 최소 서버 수. 보통은 기본 용량을 충족하기 위해 설정돼요!
최대 용량: 시스템에서 허용되는 최대 서버 수. 확장 가능한 한도를 나타내요!
기대 용량: 유지하고 싶은 평균 서버 수. 트래픽 예측과 리소스 요구에 따라 조정돼요!</p>
</blockquote>
</li>
<li><p>정책설정
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/00f404e7-1619-4507-9750-4bac449d490f/image.png" alt=""></p>
<blockquote>
<p>Autoscaling이 작동하면 한번에 몇개의 서버를 늘릴지 줄일지 정하는 설정입니다. </p>
</blockquote>
</li>
<li><p>Auto Scaling Group 생성완료 
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/75489985-50ff-4d38-9d75-5f4900c9ef6e/image.png" alt=""></p>
<blockquote>
<p>모니터링 기능도 있지만 이번 실슴에선 생략하도록 하겠습니다! </p>
</blockquote>
</li>
</ul>
<h3 id="6-cloud-insight-monitoring-event-rule-설정">6. Cloud Insight Monitoring Event Rule 설정</h3>
<ul>
<li>Server(VPC)로 Rule을 생성합니다.
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/04c263ae-f1a2-4eca-b989-505bd2eb837f/image.png" alt=""></li>
<li>만들어두었던 인스턴스를 대상으로 그룹을 만들어줍니다.
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/f7491198-a06c-40bc-9641-91831dcecc8a/image.png" alt=""></li>
<li>CPU를 대상으로 한 템플릿을 만들어줍니다.
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/8e9d4cdf-8256-43cb-b8a0-11e1966305de/image.png" alt=""></li>
<li>Autoscaling 정책을 설정해줍니다.
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/fcc30ed1-4ff9-4b66-9dde-bda4e7a2ea86/image.png" alt=""></li>
</ul>
<blockquote>
<ul>
<li>방금까지 만든 Rule은 서버 CPU가 50%이상 부하시 Autoscaling으로 인해 서버가 생기는 룰만 만든것입니다. </li>
<li>위와 같은방법으로 CPU부하가 안정되었을시 서버가 줄어드는 정책 또한 만들어 주시면 됩니다. </li>
</ul>
</blockquote>
<h3 id="7-server-stress-부하-테스트">7. Server Stress 부하 테스트</h3>
<ul>
<li>SSH를 사용하여 서버에 접속해줍시다.</li>
<li>먼저 부하테스트를 진행하기전 Apache설치를 해줍시다.</li>
<li>Autoscaling 서버는 init script를 설정해놨기 떄문에 자동으로 설치가 될것입니다.</li>
<li>init script 코드를 직접 입력하여 설정해주시면 됩니다.</li>
<li>공인ip로 접속하여 설정이 잘되었는지 확인을 해봅시다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaehdwn0105/post/2e6bffa5-4cd5-4cf4-ab8f-85fbc53767d5/image.png" alt=""></p>
<ul>
<li>설정이 완료되었으니 Stress로 CPU과부하를 주어 Autoscaling을 테스트 해봅시다.<ul>
<li>yum -y install epel-release</li>
<li>yum -y install stress</li>
<li>위 명령어로 Stress툴을 깔아줍시다. </li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaehdwn0105/post/b9761adb-700c-4309-9164-d6f48fabbad3/image.png" alt=""></p>
<ul>
<li>stress --cpu -2 --timeout 400s(stress툴을 통해 CPU에 부하를 주는 명령어 입니다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaehdwn0105/post/5fa12abd-22cd-4af5-a105-bee18fbbeaf1/image.png" alt=""></p>
<h3 id="8-autoscaling-서버-확인">8. Autoscaling 서버 확인</h3>
<ul>
<li>Stress로 인해 서버 CPU에 부하가 걸린 모습을 확인할 수 있습니다.
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/825fc478-f78d-43e1-9d0e-3a0c1f44d83d/image.png" alt=""></li>
<li>Autoscaling이 작동하여 서버가 새로 하나 생성되는것을 볼 수 있습니다.
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/40793d73-2731-4725-be93-8d05da00f0df/image.png" alt=""></li>
<li>이제 서버가 생성되었으니 로드밸런서로 확인해보겠습니다.
<img src="https://velog.velcdn.com/images/rlaehdwn0105/post/fbb5aaf8-ffb7-4880-85ae-4732659c651d/image.png" alt=""><blockquote>
<p>Target상태를 보니 정상적으로 로드밸런서에 연결되었습니다! </p>
</blockquote>
</li>
<li>라운드 로빈이 정상적으로 작동하는것을 확인할 수 있습니다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaehdwn0105/post/7f8e8055-8a97-46c2-9784-09511c015114/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/rlaehdwn0105/post/ece766d0-7ab6-49fc-94e6-c17f04f32b8a/image.png" alt=""></p>
<p>지금까지 Autoscaling테스트를 진행해 보았습니다. 감사합니다!💆</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[NCP] Clova Speech & Studio API 활용 해보기]]></title>
            <link>https://velog.io/@brickmate_-/NCP-Clova-Speech-Studio-API-%ED%99%9C%EC%9A%A9-%ED%95%B4%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@brickmate_-/NCP-Clova-Speech-Studio-API-%ED%99%9C%EC%9A%A9-%ED%95%B4%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Mon, 29 Apr 2024 02:06:52 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/brickmate_-/post/dc4b7f3c-ccc2-439c-b459-1c28771bef13/image.png" alt=""></p>
<ul>
<li><strong>NCP Clova 에서 제공되는 API 를 통해 음성파일을 텍스트로 변환 후 요약 하는 API 서비스 만들기</strong></li>
</ul>
<p>안녕하세요 ! 브릭메이트 Arnold 입니다!
오늘은 NCP(Naver Cloud Platform)에서 제공하는 Clova Open API를 활용 하여 서비스를 구축 해 보겠습니다!</p>
<h4 id="💡-clova-speech--음성-파일을-텍스트로-변환-하는-기능">💡 Clova Speech : 음성 파일을 텍스트로 변환 하는 기능</h4>
<h4 id="💡-clova-studio-요약--장문의-텍스트를-요약-해-주는-기능">💡 Clova Studio (요약) : 장문의 텍스트를 요약 해 주는 기능</h4>
<blockquote>
</blockquote>
<ul>
<li>Develop Tools : VSCode</li>
<li>Language : Python 3.11.7 (HTML)</li>
<li>Web Framework : Flask 3.0.2</li>
<li>Open API : NCP Clova Speech, Clova Studio (summary)</li>
<li>참조 가이드 : <a href="https://api.ncloud-docs.com/docs/ai-application-service-clovaspeech-longsentence">https://api.ncloud-docs.com/docs/ai-application-service-clovaspeech-, longsentence</a> (Clova Speech)
<a href="https://guide.ncloud-docs.com/docs/clovastudio-playground01#%ED%85%8C%EC%8A%A4%ED%8A%B8%EC%95%B1%EC%83%9D%EC%84%B1">https://guide.ncloud-docs.com/docs/clovastudio-playground01#테스트앱생성</a> (Clova Studio)</li>
</ul>
<h3 id="👀-작업-과정">👀 작업 과정</h3>
<p>(사전에 Clova Speech 및 Clova Studio 서비스 신청 필요)</p>
<blockquote>
<pre><code>1. Object Storage 생성 &amp; Clova Speech api 동작 테스트 (변환 소스를 Object Storage의 음성파일로 설정)
2. Clova Studio 요약 api 동작 테스트 (텍스트 요약 테스트)
3. Clova Speech &amp; Studio API 동시에 사용 가능하게 만들기
4. 작업영역 및 html 파일 생성 &amp; Flask 테스트 애플리케이션 생성 
    - 사용자가 로컬에서 원하는 음성파일을 업로드 하여 텍스트 변환 후 요약 해주는 api 서비스 구현</code></pre></blockquote>
<h3 id="1-object-storage-생성--clova-speech-api-동작-테스트">1. Object Storage 생성 &amp; Clova Speech api 동작 테스트</h3>
<p>(변환 소스를 Object Storage의 음성파일로 설정)</p>
<ul>
<li>Object Storage 생성<img src="https://velog.velcdn.com/images/brickmate_-/post/2cfe556a-7ac3-4782-93a3-1150858db662/image.png" width="40%" height="0%">
</li>
</ul>
<hr>
<h4 id="clova-speech">Clova Speech</h4>
<ul>
<li>콘솔 접속 &gt; Clova Speech &gt; Domain &gt; 도메인 생성 (장문 or 단문) </li>
</ul>
<img src="https://velog.velcdn.com/images/brickmate_-/post/a6029c30-2b62-400d-977e-161640eb8d26/image.png" width="50%" height="0%">


<ul>
<li>저는 장문인식 &amp; Basic 서비스로 진행 하였습니다.</li>
<li>인식 대상 &amp; 결과파일 저장 경로를 이전에 생성한 Object Storage로 설정</li>
</ul>
<ul>
<li>빌더 실행 &gt; 설정 &gt; Secret Key 생성 및 기타 키 값들 확인<img src="https://velog.velcdn.com/images/brickmate_-/post/eecac15e-2a05-421b-9d3f-d20bbdd7aac9/image.png" width="60%" height="0%">


</li>
</ul>
<hr>
<ul>
<li>Object Storage에 음성 파일 업로드 하기
<img src="https://velog.velcdn.com/images/brickmate_-/post/b2889c98-1508-4353-aaa9-dee2d30b72ae/image.png" alt=""></li>
<li>10MB인 음성파일을 업로드 했습니다 (+ 권한 전체 공개로 설정하기). (약 4분 30초)</li>
</ul>
<hr>
<h4 id="-clova-speech-api-code">** Clova Speech API Code**</h4>
<pre><code class="language-python"># [clova speech api] (음성 파일을 텍스트로 변환하는 api)
import requests

# Clova Speech API 정보
CLOVA_SPEECH_SECRET_KEY = &#39;&#39; # Secret key 입력
CLOVA_SPEECH_INVOKE_URL = &#39;&#39; # Invoke URL 입력

def convert_speech_to_text(file_url):
    headers = {&#39;X-CLOVASPEECH-API-KEY&#39;: CLOVA_SPEECH_SECRET_KEY}
    data = {
        &#39;url&#39;: file_url,
        &#39;language&#39;: &#39;ko-KR&#39;,
        &#39;completion&#39;: &#39;sync&#39;    }
    response = requests.post(f&#39;{CLOVA_SPEECH_INVOKE_URL}/recognizer/url&#39;, headers=headers, json=data)
    return response.json()

if __name__ == &#39;__main__&#39;:
        // object storage 음성 파일 경로
    file_url = &#39;https://kr.object.ncloudstorage.com/bm-clova-api-bucket/%EC%9D%8C%EC%84%B1%ED%8C%8C%EC%9D%BC%201.mp4&#39; 
                    # Object Storage 음성 파일 URL 입력
    response = convert_speech_to_text(file_url)
    print(response)</code></pre>
<hr>
<h4 id="vscode로-api-동작-테스트">VScode로 api 동작 테스트</h4>
<ul>
<li>test.py 파일 생성 후 python 실행 및 결과 확인
<img src="https://velog.velcdn.com/images/brickmate_-/post/fce6a950-5138-4016-bacc-df0ec962e155/image.png" width="80%" height="0%"><img src="https://velog.velcdn.com/images/brickmate_-/post/e72532ac-53b0-49c9-be6f-374fd33be964/image.png" width="80%" height="0%"></li>
</ul>
<hr>
<h3 id="2-clova-studio-요약-api-동작-테스트">2. Clova Studio 요약 api 동작 테스트</h3>
<p>(텍스트 요약 테스트)</p>
<h4 id="clova-studio-httpsclovastudioncloudcom-접속">Clova Studio (<a href="https://clovastudio.ncloud.com/">https://clovastudio.ncloud.com/</a>) 접속</h4>
<ul>
<li>긴 글 요약 &gt; 테스트 앱 생성<img src="https://velog.velcdn.com/images/brickmate_-/post/73726da6-e896-4c3d-8f95-9f6807712df6/image.png" width="50%" height="0%">
<img src="https://velog.velcdn.com/images/brickmate_-/post/da809d5b-44d5-4459-86c9-98999377bca8/image.png" width="50%"  height="40%">


</li>
</ul>
<ul>
<li>생성 된 테스트 앱 api 코드 &amp; 키 값 확인</li>
</ul>
<img src="https://velog.velcdn.com/images/brickmate_-/post/5a082320-3c14-4e0d-9569-279f14d61d55/image.png" width="50%" height="0%">


<hr>
<h4 id="-clova-studio요약-api-code">** Clova Studio(요약) API Code**</h4>
<pre><code class="language-python"># [clova studio 요약 api] (장문을 요약 해주는 api)
import base64
import json
import http.client

class CompletionExecutor:
    def __init__(self, host, api_key, api_key_primary_val, request_id):
        self._host = host
        self._api_key = api_key
        self._api_key_primary_val = api_key_primary_val
        self._request_id = request_id

    def _send_request(self, completion_request):
        headers = {
            &#39;Content-Type&#39;: &#39;application/json; charset=utf-8&#39;,
            &#39;X-NCP-CLOVASTUDIO-API-KEY&#39;: self._api_key,
            &#39;X-NCP-APIGW-API-KEY&#39;: self._api_key_primary_val,
            &#39;X-NCP-CLOVASTUDIO-REQUEST-ID&#39;: self._request_id
        }

        conn = http.client.HTTPSConnection(self._host)
                                #api url 입력
        conn.request(&#39;POST&#39;, &#39;/testapp/v1/api-tools/summarization/v2/&#39;, json.dumps(completion_request), headers)
        response = conn.getresponse()
        result = json.loads(response.read().decode(encoding=&#39;utf-8&#39;))
        conn.close()
        return result

    def execute(self, completion_request):
        res = self._send_request(completion_request)
        if res[&#39;status&#39;][&#39;code&#39;] == &#39;20000&#39;:
            return res[&#39;result&#39;][&#39;text&#39;]
        else:
            return &#39;Error&#39;

if __name__ == &#39;__main__&#39;:
    completion_executor = CompletionExecutor(
        host=&#39;clovastudio.apigw.ntruss.com&#39;,
        api_key=&#39;~~ 테스트 앱에서 확인 가능&#39;,
        api_key_primary_val = &#39;API Gateway key 입력&#39;,
        request_id=&#39;~~ 테스트 앱에서 확인 가능&#39;
    )

    request_data = json.loads(&quot;&quot;&quot;{
  &quot;texts&quot; : [&quot;요약할 텍스트 입력&quot;],
  &quot;segMinSize&quot; : 300,
  &quot;includeAiFilters&quot; : true,
  &quot;autoSentenceSplitter&quot; : true,
  &quot;segCount&quot; : -1,
  &quot;segMaxSize&quot; : 1000
}&quot;&quot;&quot;, strict=False)

    response_text = completion_executor.execute(request_data)
    print(request_data)
    print(response_text)</code></pre>
<hr>
<h4 id="vscode로-api-동작-테스트-1">VScode로 api 동작 테스트</h4>
<ul>
<li>test.py 파일 생성 후 python 실행 및 결과 확인</li>
<li>text 란에 이전에 Clova Speech를 통해 텍스트로 변환 한 값을 입력 </li>
</ul>
<img src="https://velog.velcdn.com/images/brickmate_-/post/17bd830a-8ccd-4269-a1a0-32b33a784d10/image.png" width="50%" height="0%">

<ul>
<li>코드 실행 시 맨 아래에 요약된 값 확인</li>
</ul>
<hr>
<h3 id="3-clova-speech--studio-api-동시에-사용-가능하게-만들기">3. Clova Speech &amp; Studio API 동시에 사용 가능하게 만들기</h3>
<h4 id="object-storage에-새로운-음성-파일-업로드-및-python-코드-구현">Object Storage에 새로운 음성 파일 업로드 및 Python 코드 구현</h4>
<pre><code class="language-python">
# 코드 실행 시 결과(요약) 값 바로 출력 됨
import requests
import json
import http.client

# Clova Speech API 정보 입력
CLOVA_SPEECH_SECRET_KEY = &#39;&#39;
CLOVA_SPEECH_INVOKE_URL = &#39;&#39;

def convert_speech_to_text(file_url):
    headers = {&#39;X-CLOVASPEECH-API-KEY&#39;: CLOVA_SPEECH_SECRET_KEY}
    data = {
        &#39;url&#39;: file_url,
        &#39;language&#39;: &#39;ko-KR&#39;,
        &#39;completion&#39;: &#39;sync&#39;
    }
    response = requests.post(f&#39;{CLOVA_SPEECH_INVOKE_URL}/recognizer/url&#39;, headers=headers, json=data)
    return response.json()

class CompletionExecutor:
    def __init__(self, host, api_key, api_key_primary_val, request_id):
        self._host = host
        self._api_key = api_key
        self._api_key_primary_val = api_key_primary_val
        self._request_id = request_id

    def _send_request(self, completion_request):
        headers = {
            &#39;Content-Type&#39;: &#39;application/json; charset=utf-8&#39;,
            &#39;X-NCP-CLOVASTUDIO-API-KEY&#39;: self._api_key,
            &#39;X-NCP-APIGW-API-KEY&#39;: self._api_key_primary_val,
            &#39;X-NCP-CLOVASTUDIO-REQUEST-ID&#39;: self._request_id
        }

        conn = http.client.HTTPSConnection(self._host)
                                                # Clova Studio api값 입력
        conn.request(&#39;POST&#39;, &#39;/testapp/v1/api-tools/summarization/v2/ 값입력 &#39;, json.dumps(completion_request), headers)
        response = conn.getresponse()
        result = json.loads(response.read().decode(encoding=&#39;utf-8&#39;))
        conn.close()
        return result

    def execute(self, completion_request):
        res = self._send_request(completion_request)
        if res[&#39;status&#39;][&#39;code&#39;] == &#39;20000&#39;:
            return res[&#39;result&#39;][&#39;text&#39;]
        else:
            return &#39;Error&#39;

def execute_summarization(text):
    completion_executor = CompletionExecutor(
        host=&#39;clovastudio.apigw.ntruss.com&#39;,
       # Clova Studio 값 입력
           api_key=&#39;&#39;,
        api_key_primary_val = &#39;&#39;,
        request_id=&#39;&#39;
    )

    request_data = {
      &quot;texts&quot;: [text],
      &quot;segMinSize&quot;: 300,
      &quot;includeAiFilters&quot;: True,
      &quot;autoSentenceSplitter&quot;: True,
      &quot;segCount&quot;: -1,
      &quot;segMaxSize&quot;: 1000
    }

    return completion_executor.execute(request_data)

if __name__ == &#39;__main__&#39;:
    file_url = &#39;&#39;  # Object Storage 음성 파일 URL
    speech_to_text_response = convert_speech_to_text(file_url)
    # 음성 인식 결과를 텍스트로 추출
    recognized_text = speech_to_text_response.get(&#39;text&#39;, &#39;&#39;)
    # 추출된 텍스트를 요약 API로 전송
    summarized_text = execute_summarization(recognized_text)
    print(summarized_text)**</code></pre>
<p><strong>코드 작동 방식 :</strong> </p>
<ol>
<li>Speech API를 통해 Object Storage에 있는 음성파일을 텍스트로 변환 </li>
<li>변환된 텍스트를 Studio API를 통해 요약 생성</li>
</ol>
<hr>
<h4 id="vscode로-api-동작-테스트-2">VSCode로 api 동작 테스트</h4>
<ul>
<li>test.py 파일 생성 후 python 실행<img src="https://velog.velcdn.com/images/brickmate_-/post/51e664de-8c60-4638-bdf8-bae0d61152d9/image.png" width="60%" height="0%"></li>
<li>음성 파일 -&gt; 텍스트 변환 -&gt; 요약 한번에 구현 된 결과 확인</li>
</ul>
<hr>
<h3 id="4-작업영역-및-html-파일-생성--flask-테스트-애플리케이션-생성">4. 작업영역 및 html 파일 생성 &amp; Flask 테스트 애플리케이션 생성</h3>
<ul>
<li><p>사용자가 로컬에서 원하는 음성파일을 업로드 하여 텍스트 변환 후 요약 해주는 api 서비스 구현</p>
</li>
<li><p><strong>Flask 프레임워크를 사용</strong></p>
</li>
<li><p>사용자가 웹 폼을 통해 음성 파일 URL을 제출하면, 애플리케이션이 자동으로 음성을 텍스트로 변환하고, 이 텍스트를 요약하여 결과를 보여줍니다. (<strong>Speech → Studio 순서</strong>)</p>
</li>
<li><p><strong>작업 영역</strong></p>
<img src="https://velog.velcdn.com/images/brickmate_-/post/57188202-6305-463b-ab85-b3e9146c65e2/image.png" width="40%" height="0%">
</li>
<li><p>app.py : 메인 Python 코드 (Flask)</p>
</li>
<li><p>index.html : 메인 html 페이지</p>
</li>
<li><p>result.html : 업로드 결과 값 들을 나타내는 html 페이지</p>
</li>
<li><p>uploads : 사용자가 제출한 음성파일을 저장하는 폴더</p>
</li>
</ul>
<h4 id="apppy">app.py</h4>
<pre><code class="language-python">**from flask import Flask, request, render_template
import os
import requests
import http.client
import json

app = Flask(__name__)

UPLOAD_FOLDER = &#39;uploads&#39;
if not os.path.exists(UPLOAD_FOLDER):
    os.makedirs(UPLOAD_FOLDER)
app.config[&#39;UPLOAD_FOLDER&#39;] = UPLOAD_FOLDER

# Clova Speech API 정보
CLOVA_SPEECH_SECRET_KEY = &#39;값 입력&#39;
CLOVA_SPEECH_INVOKE_URL = &#39;https://clovaspeech-gw.ncloud.com/external/v1/값 입력&#39;

# Clova Studio 요약 API 정보
CLOVA_STUDIO_HOST = &#39;clovastudio.apigw.ntruss.com&#39;
CLOVA_STUDIO_API_KEY = &#39;값 입력&#39;
CLOVA_STUDIO_API_KEY_PRIMARY_VAL = &#39;값 입력&#39;
CLOVA_STUDIO_REQUEST_ID = &#39;id 입력&#39;

class CompletionExecutor:
    def __init__(self, host, api_key, api_key_primary_val, request_id):
        self._host = host
        self._api_key = api_key
        self._api_key_primary_val = api_key_primary_val
        self._request_id = request_id

    def _send_request(self, completion_request):
        headers = {
            &#39;Content-Type&#39;: &#39;application/json; charset=utf-8&#39;,
            &#39;X-NCP-CLOVASTUDIO-API-KEY&#39;: self._api_key,
            &#39;X-NCP-APIGW-API-KEY&#39;: self._api_key_primary_val,
            &#39;X-NCP-CLOVASTUDIO-REQUEST-ID&#39;: self._request_id
        }

        conn = http.client.HTTPSConnection(self._host)
        conn.request(&#39;POST&#39;, &#39;/testapp/v1/api-tools/summarization/v2/값 입력&#39;, json.dumps(completion_request), headers)
        response = conn.getresponse()
        data = response.read().decode(&#39;utf-8&#39;)

        # Check if the response body is not empty
        if not data:
            return {&#39;error&#39;: &#39;Empty response from Clova Studio API&#39;}

        result = json.loads(data)
        conn.close()
        return result

    def execute(self, completion_request):
        res = self._send_request(completion_request)

        # Check if &#39;status&#39; key exists in the response and if the code is &#39;20000&#39;
        if &#39;status&#39; in res and res[&#39;status&#39;].get(&#39;code&#39;) == &#39;20000&#39;:
            return res[&#39;result&#39;][&#39;text&#39;]
        elif &#39;error&#39; in res:
            return f&quot;Error: {res[&#39;error&#39;]}&quot;
        else:
            return &#39;Error: Unexpected response structure from Clova Studio API&#39;

def convert_speech_to_text(file_url):
    headers = {&#39;X-CLOVASPEECH-API-KEY&#39;: CLOVA_SPEECH_SECRET_KEY}
    data = {
        &#39;url&#39;: file_url,
        &#39;language&#39;: &#39;ko-KR&#39;,
        &#39;completion&#39;: &#39;sync&#39;
    }
    response = requests.post(f&#39;{CLOVA_SPEECH_INVOKE_URL}/recognizer/url&#39;, headers=headers, json=data)
    return response.json().get(&#39;text&#39;, &#39;&#39;)

def convert_speech_to_file(file_path):
    files = {&#39;media&#39;: open(file_path, &#39;rb&#39;)}
    params = {
        &#39;language&#39;: &#39;ko-KR&#39;,
        &#39;completion&#39;: &#39;sync&#39;,
        &#39;wordAlignment&#39;: True,
        &#39;fullText&#39;: True
    }
    headers = {&#39;X-CLOVASPEECH-API-KEY&#39;: CLOVA_SPEECH_SECRET_KEY}
    response = requests.post(f&#39;{CLOVA_SPEECH_INVOKE_URL}/recognizer/upload&#39;, headers=headers, files=files, data={&#39;params&#39;: json.dumps(params)})
    return response.json().get(&#39;text&#39;, &#39;&#39;)

def _send_request(self, completion_request):
    ...
    result = json.loads(data)
    print(&quot;API Response:&quot;, result)  # 응답 출력
    ...

@app.template_filter(&#39;newline_list&#39;)
def newline_list(summary):
    # Replace &#39; -&#39; with &#39;&lt;br&gt; -&#39; to create a line break before each list item, except for the first
    return summary.replace(&#39; -&#39;, &#39;&lt;br&gt; -&#39;)

# Apply the custom filter to the summary in the template with {{ summary|newline_list }}
@app.route(&#39;/&#39;, methods=[&#39;GET&#39;, &#39;POST&#39;])
def upload_file():
    if request.method == &#39;POST&#39;:
        file_url = request.form.get(&#39;file_url&#39;)
        voice_file = request.files.get(&#39;voice_file&#39;)

        if voice_file and voice_file.filename != &#39;&#39;:
            filepath = os.path.join(app.config[&#39;UPLOAD_FOLDER&#39;], voice_file.filename)
            voice_file.save(filepath)
            speech_to_text_response = convert_speech_to_file(filepath)

        elif file_url:
            speech_to_text_response = convert_speech_to_text(file_url)

        else:
            return &#39;URL이나 파일이 제공되지 않았습니다.&#39;, 400

        summarization_executor = CompletionExecutor(
            host=CLOVA_STUDIO_HOST,
            api_key=CLOVA_STUDIO_API_KEY,
            api_key_primary_val=CLOVA_STUDIO_API_KEY_PRIMARY_VAL,
            request_id=CLOVA_STUDIO_REQUEST_ID
        )

        request_data = {
            &quot;texts&quot;: [speech_to_text_response],
            &quot;segMinSize&quot;: 300,
            &quot;includeAiFilters&quot;: True,
            &quot;autoSentenceSplitter&quot;: True,
            &quot;segCount&quot;: -1,
            &quot;segMaxSize&quot;: 1000
        }
        response_text = summarization_executor.execute(request_data)

        if response_text != &#39;Error&#39;:
            return render_template(&#39;result.html&#39;, text=speech_to_text_response, summary=response_text)
        else:
            return &#39;요약 과정에서 오류가 발생했습니다.&#39;, 500

    return render_template(&#39;index.html&#39;)

if __name__ == &#39;__main__&#39;:
    app.run(debug=True)**</code></pre>
<hr>
<h4 id="코드-실행-flask-run">코드 실행 (flask run)</h4>
<img src="https://velog.velcdn.com/images/brickmate_-/post/bc357c5d-0dd6-40f9-abc5-a417f4e984c1/image.png" width="70%" height="0%">


<h4 id="1270015000-접속-해-보기">127.0.0.1:5000 접속 해 보기</h4>
<img src="https://velog.velcdn.com/images/brickmate_-/post/dce4359c-5c3a-4449-b325-be7ef3072be9/image.png" width="50%" height="0%">




<h4 id="음성-파일-object-storage-url-입력-후-제출-하기">음성 파일 (Object Storage) URL 입력 후 제출 하기</h4>
<ul>
<li>전체 공개 된 음성파일의 URL 혹은 presigned url 입력 후 테스트<img src="https://velog.velcdn.com/images/brickmate_-/post/04e7f67b-a870-4171-a8f2-33c20d9d7861/image.png" width="50%" height="0%">




</li>
</ul>
<h4 id="결과-확인">결과 확인</h4>
<img src="https://velog.velcdn.com/images/brickmate_-/post/d89ad2b2-8db5-4b27-adc7-6864d15ee916/image.png" width="50%" height="0%">

<ul>
<li>Clova Speech <img src="https://velog.velcdn.com/images/brickmate_-/post/8e923487-f3ca-436b-a0d8-13b5449d6efe/image.png"  width="30%" height="%">


</li>
</ul>
<ul>
<li>Clova Studio (Summary)<img src="https://velog.velcdn.com/images/brickmate_-/post/6cc7e66b-59a0-4880-96d6-02cb5f817613/image.png" width="50%" height="0%">



</li>
</ul>
<h4 id="사용자-pc에서-음성-파일-업로드-후-제출-해보기">사용자 PC에서 음성 파일 업로드 후 제출 해보기</h4>
<p>파일선택 &gt; 열기 &gt; 제출</p>
<img src="https://velog.velcdn.com/images/brickmate_-/post/7bbd0448-1639-41d3-9015-121452d23b4a/image.png" width="50%" height="0%">

<h4 id="결과-확인-1">결과 확인</h4>
<img src="https://velog.velcdn.com/images/brickmate_-/post/fb864ebd-7918-4ff8-a05c-cb4fd56052ff/image.png" width="40%" height="0%">


<hr>
<h4 id="감사합니다">감사합니다.</h4>
]]></description>
        </item>
    </channel>
</rss>