<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>메모장</title>
        <link>https://velog.io/</link>
        <description>환영합니다 :) 이 곳은 개인 공부를 정리하고 창의적으로 활용하기 위한 제 2의 전두엽으로 활용되고 있으며, 오류에 대한 피드백은  댓글로 남겨주시면 감사하겠습니다.</description>
        <lastBuildDate>Thu, 02 May 2024 03:05:11 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>메모장</title>
            <url>https://velog.velcdn.com/images/hahaeun-v/profile/9904f019-9ef2-4dd7-9905-f0ed1d2c7638/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. 메모장. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hahaeun-v" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[C#] Windows Forms App 없을때]]></title>
            <link>https://velog.io/@hahaeun-v/C-Windows-Forms-App-%EC%97%86%EC%9D%84%EB%95%8C</link>
            <guid>https://velog.io/@hahaeun-v/C-Windows-Forms-App-%EC%97%86%EC%9D%84%EB%95%8C</guid>
            <pubDate>Thu, 02 May 2024 03:05:11 GMT</pubDate>
            <description><![CDATA[<p>Visual Studio를 설치하고 새 프로젝트를 보면 Windows Forms App가 없는 것을 볼 수 있습니다. </p>
<p>Visual Studio Installer나 Visual Studio에서추가로 다운로드가 가능합니다. </p>
<p>Visual Studio 내부에서 
*<em>Visual Studio 실행 - 도구- 도구 및 기능 가져오기  *</em></p>
<p><code>.NET 데스크톱 개발</code>을 선택해서 수정을 눌러주면 추가적으로 다운로드를 실행합니다. </p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/54d6a4b4-d111-4396-b0ca-b73bb1c8f4d3/image.png" alt=""></p>
<p>Visual Studio 종료 후 재실행 하면 새프로젝트에 Windows Forms App 항목이 추가 된 것을 확인 할 수 있습니다. </p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/589092b4-e48b-49a2-97fd-5237113ff911/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[시스템 파일 확인 방법]]></title>
            <link>https://velog.io/@hahaeun-v/%EC%8B%9C%EC%8A%A4%ED%85%9C-%ED%8C%8C%EC%9D%BC-%ED%99%95%EC%9D%B8-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@hahaeun-v/%EC%8B%9C%EC%8A%A4%ED%85%9C-%ED%8C%8C%EC%9D%BC-%ED%99%95%EC%9D%B8-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Tue, 30 Apr 2024 18:33:45 GMT</pubDate>
            <description><![CDATA[<h1 id="msinfo32">MSinfo32</h1>
<ol>
<li>키보드의 윈도우 키 + R 을 누릅니다.</li>
<li>빈 칸에 MSinfo32를 입력하고 엔터키를 누릅니다.</li>
<li>시스템 정보 창이 열리면 왼쪽 위의 [파일] 메뉴를 클릭하고 [내보내기]를 클릭합니다.</li>
<li>다른 이름으로 내보내기 창이 열리면 바탕화면을 선택합니다.</li>
<li>파일 이름을 &quot;MSInfo&quot;로 하고 저장을 클릭합니다.</li>
</ol>
<ul>
<li>오류 항목 확인 방법<ul>
<li>텍스트 파일에서 키보드의 Ctrl + F를 눌러 [Windows 오류 보고] (또는 Windows Error Reporting)를 검색합니다.</li>
</ul>
</li>
</ul>
<br>

<ul>
<li>주요 확인 가능 정보:
운영 체제 버전 및 시스템 모델
CPU, 메모리, 하드 드라이브 및 기타 하드웨어 구성
실행 중인 프로세스 및 서비스
시스템 로그와 충돌 보고
네트워크 설정과 연결 정보</li>
</ul>
<p><br><br></p>
<h1 id="dxdiag">DxDiag</h1>
<ol start="2">
<li>CMD에 DxDiag 입력하고 엔터키를 누릅니다. </li>
<li>DxDiag 창이 열리면, 모든 정보 저장 버튼을 클릭합니다.</li>
</ol>
<ul>
<li>주요 확인 가능 정보:
디스플레이 장치 (그래픽 카드)의 정보
사운드 카드 및 입력 장치 정보
설치된 DirectX 버전
드라이버 충돌이나 오류</li>
</ul>
<hr>
<h1 id="mac에서">Mac에서</h1>
<p>시스템 프로필 보고서(System Profiler Report)</p>
<ol>
<li>애플 메뉴를 연 다음, 이 매킨토시에 관하여를 선택해주세요.</li>
<li>시스템 리포트를 클릭해주세요.
참고: 10.9.5. 또는 그 이전 버전에서는 추가 정보...를 선택하세요.</li>
<li>상단 메뉴에서 [파일]을 클릭하고 바탕 화면에 파일을 저장합니다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Docker 실행하기 ]]></title>
            <link>https://velog.io/@hahaeun-v/Docker-%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@hahaeun-v/Docker-%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 29 Apr 2024 06:32:45 GMT</pubDate>
            <description><![CDATA[<h1 id="docker란">Docker란?</h1>
<p>개발자가 컨테이너를 빌드, 배포, 실행, 업데이트, 관리할 수 있는 오픈소스 플랫폼입니다. </p>
<p>컨테이너를 활용했을 때 분산형 애플리케이션을 간편하게 개발하고 제공할 수 있습니다. 
<br><br></p>
<h3 id="컨테이너">컨테이너</h3>
<ul>
<li>데스크탑, 기존 IT, 클라우드 등 어디에서나 실행할 수 있도록 <span style="color:CadetBlue"><strong>단일 애플리케이션이나 마이크로서비스를 실행하는데 필요한 모든 것을 함께 패키징</span>한 소프트웨어 실행 유닛</strong>. 컨테이너는 OS 가상화를 활용함으로써 프로세스를 격리하고 자원의 양을 제어가 가능. 
<br><br></li>
</ul>
<h3 id="vm과-컨테이너의-차이">VM과 컨테이너의 차이</h3>
<ul>
<li>Virtual Machine<ul>
<li>컴퓨터를 에뮬레이션하는 것으로 <strong>물리적 하드웨어를 가상화</strong> 함. 따라서 단일 컴퓨터로 여러 운영체제를 사용해 여러 컴퓨터를 실행하듯 사용 가능.</li>
</ul>
</li>
<li>컨테이너<ul>
<li>컨테이너의 경우 하드웨어가 아닌 <strong>운영체제를 가상화</strong>. 따라서, 가상머신보다 가벼움이 특징.(Hypervisor를 사용하지 않아 더 빠른 리소스 프로비저닝과 새로운 애플리케이션의 가용성이 빠름) 
<br><br><br><br></li>
</ul>
</li>
</ul>
<h1 id="docker의-특징">Docker의 특징</h1>
<ul>
<li><p>컨테이너 생성 자동화: Docker에서는 애플리케이션 소스코드를 기반으로 컨테이너를 자동으로 빌드할 수 있습니다. </p>
</li>
<li><p>컨테이너 버전 관리 : Docker에서는 컨테이너 이미지의 여러 버전을 관리하고, 이전 버전으로 롤백하고, 버전을 빌드한 사용자와 그 방법 까지 추적이 가능합니다. 부분 업데이트도 가능합니다. </p>
</li>
<li><p>컨테이너 재사용 : 기존 컨테이너를 기본 이미지로, 특히 새 컨테이너를 빌드할 때 템플릿처럼 사용이 가능합니다. </p>
</li>
<li><p>공유 컨테이너 라이브러리 : 개발자는 사용자들이 제공한 수천개의 컨테이너가 있는 오픈 소스 레지스트리에 엑세스할 수 있습니다. 
<br><br><br><br></p>
</li>
</ul>
<h1 id="window-11-환경에서-docker-설치">Window 11 환경에서 Docker 설치</h1>
<p><br><br></p>
<h3 id="1-설정-확인">1. 설정 확인</h3>
<ul>
<li>설치 전 가상화 환경 확인
<img src="https://velog.velcdn.com/images/hahaeun-v/post/3aafa4b1-fb84-4ab2-85b0-e02850036d5b/image.png" alt=""></li>
</ul>
<p><em>작업관리자 CPU-가상화 [사용]</em></p>
<p><br><br></p>
<ul>
<li>제어판 &gt; 프로그램 설치 및 제거 &gt; window 기능 켜기/끄기 &gt; Hyper-V 체크
<img src="https://velog.velcdn.com/images/hahaeun-v/post/ef180110-5580-488a-958c-3b6caf863953/image.png" alt="">
<br><br></li>
</ul>
<h3 id="2-docker-installing">2. Docker installing</h3>
<ol>
<li><a href="https://docs.docker.com/get-docker/">Docker 사이트</a>에서 운영체제에 맞는 파일 다운로드<pre><code> - https://docs.docker.com/get-docker/</code></pre></li>
<li>다운로드 완료한 도커파일을 실행</li>
<li>다운로드 진행하며 다른 설정 수정없이 &quot;Ok&quot; 클릭</li>
<li>&quot;Close and restart&quot;하여 재부팅
<br><br></li>
</ol>
<h3 id="3-docker-run">3. Docker Run</h3>
<ul>
<li><p>설치된 도커를 실행해준다. </p>
</li>
<li><p>만약, WSL 오류메세지가 나오면 메세지 내의 링크 <a href="https://aka.ma/wsl2kernel">https://aka.ma/wsl2kernel</a> 로 이동해 패키지를 다운
<img src="https://velog.velcdn.com/images/hahaeun-v/post/5b4da481-0bea-4ded-96c2-d20625f60340/image.png" alt=""></p>
</li>
<li><p>도커 정상 실행시 회원가입(플랜 무료 0$ 선택) 또는 로그인</p>
</li>
<li><p>인증이 완료되면 &quot;Get started with Docker Desktop&quot;을 클릭하여 마무리</p>
</li>
<li><p>CMD에서 <code>docker -v</code>을 입력하면 정상 설치 확인 가능</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/ea501d4e-8805-426a-9ec1-3b818eda0400/image.png" alt="">
<br><br></p>
<h3 id="4-도커-관리-웹-ui">4. 도커 관리 웹 UI</h3>
<p>도커를 GUI 환경으로 쉽게 확인하고 관리할 수 있는 툴 들이 여러개 있다. 사용자가 원하는 환경을 선택해서 사용하기를 추천 (ex. Kitematic, portainer)</p>
<p><br><br><br><br></p>
<hr>
<h1 id="docker-용어">docker 용어</h1>
<ul>
<li><p>DockerFile : 이미지를 만들기 위한 명령어 세트가 포함된 텍스트 파일. DockerFile로 이미지 생성 프로세스 자동화 함.</p>
</li>
<li><p>Docker image : 컨테이너를 생성하는데 사용되는 불변의 템플릿. Docker image에는 <strong>실행 가능한 애플리케이션 소스 코드</strong>, <strong>코드가 컨테이너 형태로 실행되는데 필요한 모든 툴</strong>, <strong>라이브러리 및 종속 항목</strong>이 포함 됨. 이미지를 실행하면 컨테이너의 <strong>인스턴스</strong>가 된다.</p>
</li>
<li><p>Docker Container : Docker 이미지의 현재 실행중인 라이브 인스턴스를 의미. 이미지는 읽기 전용이라고 할 수 있고, 컨테이너는 현재 활성 상태이며 수명이 짧은 실행 가능 콘텐츠라고 할 수 있다. 관리자는 Docker 명령을 사용해 설정과 조건을 조정 가능.</p>
</li>
<li><p>Docker Hub : 공용 이미지 저장소로 다양한 컨테이너 이미지를 포함하며, 오픈 소스에 엑세스 가능._ like, GitHub._</p>
</li>
<li><p>Docker Volume : 컨테이너의 데이터를 지속적으로 저장할 수 있는 공간</p>
</li>
<li><p>Docker Compose : 멀티 컨테이너를 정의하고 실행하기 위한 도구. <code>멀티 컨테이너: 모든 컨테이너가 같은 Docker 호스트에서 실행되는 경우</code> Docker Compose는 애플리케이션에 포함될 서비스를 지정하는 YAML 파일을 생성, 그리고 하나의 명령어로 컨테이너를 배포하고 실행이 가능하다. </p>
</li>
</ul>
<p><br><br><br><br><br><br><br><br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] 프로그래머스 'n의 배수 고르기']]></title>
            <link>https://velog.io/@hahaeun-v/Java-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-n%EC%9D%98-%EB%B0%B0%EC%88%98-%EA%B3%A0%EB%A5%B4%EA%B8%B0</link>
            <guid>https://velog.io/@hahaeun-v/Java-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-n%EC%9D%98-%EB%B0%B0%EC%88%98-%EA%B3%A0%EB%A5%B4%EA%B8%B0</guid>
            <pubDate>Sun, 31 Mar 2024 18:04:04 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/a4ca992b-2e33-4e8c-aae5-1c12fb233087/image.png" alt=""></p>
<h2 id="📌-problem--httpsschoolprogrammerscokrlearncourses30lessons120905">📌 Problem : <a href="https://school.programmers.co.kr/learn/courses/30/lessons/120905">https://school.programmers.co.kr/learn/courses/30/lessons/120905</a></h2>
<p><br><br></p>
<h2 id="👉-approach">👉 Approach</h2>
<p>주어지는 n에 나누어 떨어지는 배수값을 int 배열로 반환하는 크게 어렵지않은 문제입니다. 
stream을 사용해 코드를 단순화하여 작성하는 방법과 배열을 직접 반복해 stream의 오버헤드 없이 연산하는 방법을 통해 풀어보았습니다. </p>
<p><br><br></p>
<h2 id="✔️-code">✔️ code</h2>
<pre><code class="language-java">import java.util.Arrays;

class Solution {
    public int[] solution(int n, int[] numlist) {
        // 배열값 중 0으로 나누어 떨어지는 값을 반환 
        return Arrays.stream(numlist).filter(i -&gt; i % n == 0).toArray();       
    }
}</code></pre>
<pre><code class="language-java">import java.util.Arrays;

class Solution {
    public int[] solution(int n, int[] numlist) {
        // 결과 배열의 크기 계산
        int count = 0;
        for (int num : numlist) {
            if (num % n == 0) {
                count++;
            }
        }

        // 결과 배열 생성 및 값 채워 넣기
        int[] answer = new int[count];
        int index = 0;
        for (int num : numlist) {
            if (num % n == 0) {
                answer[index++] = num;
            }
        }

        return answer;
    }
}</code></pre>
<p><br><br>
Arrays 클래스의 stream()에 대해 다음 포스팅에서 알아보겠습니다. </p>
<p><br><br><br><br><br><br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] 프로그래머스 '문자열 뒤집기'  ]]></title>
            <link>https://velog.io/@hahaeun-v/Java-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%92%A4%EC%A7%91%EA%B8%B0</link>
            <guid>https://velog.io/@hahaeun-v/Java-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%92%A4%EC%A7%91%EA%B8%B0</guid>
            <pubDate>Sat, 23 Mar 2024 15:14:03 GMT</pubDate>
            <description><![CDATA[<h2 id="📌-problem--httpsschoolprogrammerscokrlearncourses30lessons120822languagejava">📌 Problem : <a href="https://school.programmers.co.kr/learn/courses/30/lessons/120822?language=java">https://school.programmers.co.kr/learn/courses/30/lessons/120822?language=java</a></h2>
<p>기본적인 for문을 사용해 풀이하였는데 성능적으로 아쉬운 부분이 있어 여러가지 다른 풀이 방법을 함께 정리해보았습니다. </p>
<p><br><br>
<br></p>
<h2 id="👉-approach">👉 Approach</h2>
<p>메모리: 75.5 MB, 시간: 9.32 ms
반복문을 사용해 주어진 문자열의 length()-1 부터 0까지 반복합니다. 
초기화한 answer에 chatAt(index)로 문자를 추가해줍니다. </p>
<br>
<br>
<br>


<h2 id="✔️-code">✔️ Code</h2>
<pre><code class="language-java">class Solution {
    public String solution(String my_string) {
        String answer = &quot;&quot;;
        for(int i = my_string.length()-1; i &gt;= 0; i--){
            answer += my_string.charAt(i);
        }
        return answer;
    }
}</code></pre>
<br>
<br>
<br>

<h2 id="✌️approach">✌️Approach</h2>
<p>메모리: 75.8 MB, 시간: 0.03 ms    // StringBuilder
메모리: 73.7 MB, 시간: 0.07 ms    // StringBuffer</p>
<p>인스턴스를 생성할 때 reverse() 메소드로 문자열을 변경하여 strReversed 변수에 담아줍니다. 변수를 toString하여 리턴하는 패턴으로 StringBuilder와 StringBuffer 두 클래스를 동일한 로직을 사용합니다. 
이전 코드보다 성능이 상대적으로 좋아진 것을 확인 할 수 있습니다. </p>
<blockquote>
<p>StringBuilder와 StringBuffer는 가변적인 문자열을 다루는 클래스입니다. 두 클래스는 거의 동일한 기능을 제공하지만, 차이점은 스레드 안전성에 있습니다. StringBuilder는 스레드 안전하지 않고, StringBuffer는 스레드 안전합니다. 그러므로 단일 스레드 환경에서는 StringBuilder를 사용하는 것이 일반적으로 더 효율적입니다.</p>
</blockquote>
<blockquote>
<p>주요 메소드
append(): 문자열을 추가합니다.
insert(): 지정된 위치에 문자열을 삽입합니다.
delete(): 지정된 범위의 문자열을 삭제합니다.
deleteCharAt(): 지정된 인덱스의 문자를 삭제합니다.
replace(): 지정된 범위의 문자열을 다른 문
자열로 대체합니다.
reverse(): 문자열을 뒤집습니다.
toString(): String으로 변환합니다.</p>
</blockquote>
<br>
<br>
<br>


<h2 id="✔️-code-1">✔️ Code</h2>
<pre><code class="language-java">class Solution {
    public String solution(String my_string) {
        StringBuilder strReversed = new StringBuilder(my_string).reverse();
        // StringBuffer strReversed = new StringBuffer(my_string).reverse();
        String answer = strReversed.toString();
        return answer;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] 자바는 어떻게 실행되나요? - 개요]]></title>
            <link>https://velog.io/@hahaeun-v/Java-%EC%9E%90%EB%B0%94%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%8B%A4%ED%96%89%EB%90%98%EB%82%98%EC%9A%94</link>
            <guid>https://velog.io/@hahaeun-v/Java-%EC%9E%90%EB%B0%94%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%8B%A4%ED%96%89%EB%90%98%EB%82%98%EC%9A%94</guid>
            <pubDate>Thu, 14 Mar 2024 06:50:05 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/e8c5c99f-0be7-472d-b049-4faf39aa36da/image.png" alt=""></p>
<p>자바는 어떻게 실행되나요?</p>
<p>우리가 Java라고 작성하는 코드를 어떻게 인식하는지
내부 구조를 하나하나 뜯어보고 
프로세스 순서가 어떻게 되는지 
결과적으로 출력문이 어떻게 콘솔에 찍히는지 원리를 살펴보고자 합니다. </p>
<p>심화단계에 앞서 간단하게 JAVA의 개념과 특징에 대해 알아보겠습니다. </p>
<p><br><br><br></p>
<h2 id="1-개요">1. 개요</h2>
<p>1995년 객체 지향 프로그래밍 언어로 개발된 Java는 C#과 문법적으로 유사성이 많으며 한국에서 가장 많이 사용되는 언어중 하나이다.</p>
<p>자바는 크게 3가지 에디션 JavaSE, Jakarta EE(Java EE), Java ME 으로 나뉜다.</p>
<ul>
<li>JavaSE : Java 핵심 API와 기능 제공</li>
<li>Jakarta EE(Java EE) : 기업에서 운영하는 서버 페이지에 특화된 에디션. JSP와 서블릿을 비롯한 웹 어플리케이션에 관련된 기술 포함 됨</li>
<li>Java ME : 피처폰, PDA, 셋톱박스 등 임베디드 시스템에 특화 </li>
</ul>
<p><br><br></p>
<h2 id="2-특징">2. 특징</h2>
<p>Java는 플랫폼에 독립적인 언어로 C언어는 소스코드를 기계어로 직접 컴파일하여 링크하는 반면 자바 컴파일러는 바이트코드인 클래스 파일을 생성하고, 이 파일의 바이트코드를 읽은 뒤 기계어로 바꾸어 실행하는 것은 자바 가상 머신이다. </p>
<p>플랫폼에 종속적인 경우 윈도우 환경에서 빌드한 프로그램을 그대로 리눅스나 macOS에서 실행하는 것이 불가하다. 반면 자바로 작성된 프로그램은 자바 가상 머신만 설치되어 있다면 대체로 문제없이 동작한다. 이는 바이트 코드가 플랫폼이 아닌 자바 가상 머신에서 실행가능 하며, 프로그램 실행의 주체가 운영체제가 아닌 자바 가상 머신이기 때문이다. 이러한 특징을 일컬어 플랫폼에 독립적이라고 한다. </p>
<p>하지만 실상은 자바 가상 머신은 C언어로 쓰여진 이식성을 통해 이루어진 것으로 자바 가상 머신에 심하게 종속된 언어로 볼 수 있다. java의 플랫폼 독립성은 &#39;플랫폼에 맞는 자바 가상 머신이 설치된&#39; 상태라는 조건이 반드시 필요하다. 그럼에도, 플랫폼이 바뀐 상태에서 재컴파일 하지 않아도 바이너리를 그대로 쓸 수 있다는 것은 자바만의 특징이다. </p>
<p><br><br></p>
<h2 id="3-문제점">3. 문제점</h2>
<p>자바의 심각한 단점 중 하나는 실행하는 과정에서 JVM이 반드시 완전하게 로딩되어야 하기 때문에 프로그램의 초기 시작 시간이 비교적 오래 걸린다는 것이다. <em>이진 코드로 컴파일된 프로그램을 실행하는 것과 비교해 오래 걸린다. 런타임 자체가 아직 모듈화 되지 않았다는 가정하에.</em> &quot;Hello world!&quot; 하나를 찍는다고 해도 스레드가 10개 가량 뜨게 된다. Java 9부터는 라이브러리가 모듈화 되어 요즘과 같은 고사양 컴퓨터에서는 체감상 크게 차이나지 않는다. </p>
<p>그 외에도 </p>
<ul>
<li>가상 머신 바이트코드 실행 속도의 문제</li>
<li>가비지 컬렉션에 의한 메모리 프리징으로 실행 지연 문제 - Java 8부터 static 인스턴스와 리터럴 문자도 GC의 대상이 되었다. 클래스, 메소드, 배열의 메타 정보는 Metaspace(동적 리사이징이 가능)으로 이동해 힙 공간이 늘어나고 PermGen Area를 없애 성능이 대폭 향상되었다.  </li>
<li>불편한 예외 처리 - 다른 언어와 달리 검사가 필요한 예외는 프로그래머가 선언을 해줘야한다. 그렇지 않으면 컴파일이 안된다는 불편이 존재하는데 Exception 하나로 대충 던져 놓거나 폭탄 돌리기를 하는 경우가 발생하기도 한다. 하지만 발생할 수 있는 예외를 인지하고 처리하는 것에 있어서는 장점으로 취급되기도 한다. </li>
<li>다른 언어에 비해 긴 소스 코드 길이</li>
<li>클로저 미지원</li>
<li>문자열 비교가 상대적으로 불편 - primitive 타입 외에는 모두 Object로 처리하는 자바의 특징 때문에 String 또한 Object로 인식되어 주소로 비교된다. 특이한 점은 Object로 취급하면서도 문자열 자체는 메모리에 캐싱을 해둔다. 외부에서 XML, JSON의 문자열을 검증할 때 디버깅이 어려워 진다는 문제점이 있다.</li>
<li>서버 리스에 적합하지 않음 - 상시 가동이 아닌 리퀘스트 발생 시에만 애플리케이션이 가동되는 형태로 JVM이 완벽하게 기동되어야 하기 때문에 인터프리터보다 반응이 느리다. </li>
</ul>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>

<hr>
<p>참고
<a href="https://namu.wiki/w/Java/%ED%8F%89%EA%B0%80">wiki</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] 프로그래머스 '완주하지 못한 선수']]></title>
            <link>https://velog.io/@hahaeun-v/Java-%EC%99%84%EC%A3%BC%ED%95%98%EC%A7%80%EB%AA%BB%ED%95%9C%EC%84%A0%EC%88%98</link>
            <guid>https://velog.io/@hahaeun-v/Java-%EC%99%84%EC%A3%BC%ED%95%98%EC%A7%80%EB%AA%BB%ED%95%9C%EC%84%A0%EC%88%98</guid>
            <pubDate>Thu, 14 Mar 2024 05:00:33 GMT</pubDate>
            <description><![CDATA[<h1 id="📌-problem--httpsschoolprogrammerscokrlearncourses30lessons42576">📌 Problem : <a href="https://school.programmers.co.kr/learn/courses/30/lessons/42576">https://school.programmers.co.kr/learn/courses/30/lessons/42576</a></h1>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/e8b9f6c5-e987-427c-ad57-368ad479a102/image.png" alt=""></p>
<p><br><br></p>
<h1 id="👉-approach">👉 Approach</h1>
<h4 id="사용된-변수에-대한-설명">사용된 변수에 대한 설명</h4>
<ul>
<li>map : 선수의 이름과 중복 횟수를 카운팅</li>
<li>partPlayer : 참여자 이름 </li>
<li>comPlayer : 완주자 이름 </li>
</ul>
<h4 id="주요-로직">주요 로직</h4>
<ul>
<li>동명이인이 2이상이 될 수 있다는 부분을 고려하며 이름과 중복 횟수를 각각 key, value로 지정해 HashMap으로 횟수를 관리합니다. </li>
<li>첫번째 for문으로 참여자를 담으며 이미 존재하는 참여자는 getOrDefault를 이용해 기존 value에 1++합니다. </li>
<li>두번째 for문에서는 횟수를 차감하는데 이 때는 담아놓은 참여자와 꺼낸 완주자를 key로 비교합니다. </li>
</ul>
<p><br><br></p>
<h1 id="✔️-code">✔️ Code</h1>
<pre><code class="language-java">import java.util.HashMap;

class Solution {
    public String solution(String[] participant, String[] completion) {

        // 새로운 HashMap 생성
        HashMap&lt;String, Integer&gt; map = new HashMap&lt;&gt;();

        // 참여자를 담고 중복 횟수에 따라 증가
        for(String partPlayer: participant){
            map.put(partPlayer,map.getOrDefault(partPlayer,0) +1);
        }

        // 완주자로 조회하여 횟수 차감
        for(String comPlayer:completion){
            map.put(comPlayer,map.get(comPlayer) -1);
        }

        // 횟수가 1 이상인 key를 찾아 반환 
        for(String player: participant){
            if(map.get(player) &gt; 0) return player;
        }

        return null;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[HTTP] IP 인터넷 프로토콜]]></title>
            <link>https://velog.io/@hahaeun-v/HTTP</link>
            <guid>https://velog.io/@hahaeun-v/HTTP</guid>
            <pubDate>Tue, 05 Mar 2024 05:41:10 GMT</pubDate>
            <description><![CDATA[<br>

<h2 id="개요">개요</h2>
<p>네트워크 통신을 하기 위해서는 어떤것들이 필요한지 추상적이던 그 개념을 간단하게 짚고 넘어가고는 시간을 가져보고자 합니다.</p>
<p>복잡한 인터넷망을 어떤 규칙으로, 어떻게 안전하게 타고 다닐수 있는지 인터넷통신, IP, DNS, PORT 등 필수적인 요소를 명확하게 이해보는 것을 목표로 하며 김영한님의 <a href="https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC">HTTP 강의</a>를 토대로 작성하였습니다.
<br>
<br></p>
<h2 id="ipinternet-protocol이란">IP(Internet Protocol)이란?</h2>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/6e7ace6f-df6c-4863-8008-ffb78b3052d0/image.png" alt=""></p>
<p>근거리 통신을 할때는 LAN으로 MAC주소를 이용해 통신 할 수 있지만 </p>
<p>멀리 있는 PC와 통신을 하기위해서는 수많은 중간 노드를 거쳐 네트워크를 식별할 주소가 필요한데요. 여기서 의미하는 주소가 바로 IP 주소를 의미합니다.</p>
<br>

<p>인터넷 프로토콜의 관점에서 보면 보내는 클라이언트의 주소는 출발지 IP, 서버의 주소는 도착지 IP, 보내고자하는 내용은 전송 데이터라고 할 수 있습니다. </p>
<br>

<p>인터넷 프로토콜의 역할</p>
<ul>
<li>지정한 IP 주소에 데이터를 전달</li>
<li>패킷이라는 통신 단위로 데이터 전달</li>
</ul>
<br>

<p>IP 패킷안에 어떤것들이 담겨있는지 보기 위해 TCP/IP의 형태를 미리 보자면 아래와 같습니다. </p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/726cc11f-863d-4345-92e0-ec1e545364a7/image.png" alt=""></p>
<p>전송데이터를 TCP, IP가 감싸고 있는 형태로 
IP 패킷 안에는 </p>
<ul>
<li>버전</li>
<li>헤더길이</li>
<li>서비스타입</li>
<li>식별자</li>
<li>플래그</li>
<li>단편화 오프셋</li>
<li>Time-To-Live(TTL)</li>
<li>프로토콜</li>
<li>헤더 체크섬</li>
<li>송신자 IP주소</li>
<li>수신자 IP주소</li>
</ul>
<p>이러한 구성으로 패킷이 목적지에 도착하기 위해 필요한 값들이 담겨져 있습니다. </p>
<br>

<h3 id="인터넷-프로토콜-문제점">인터넷 프로토콜 문제점</h3>
<br>

<p>위에서 알아본 인터넷 프로토콜에는 몇가지 한계점이 있습니다. </p>
<ol>
<li>전송한 순서대로 도착하지 않음</li>
<li>패킷이 중간에 분실될 위험 존재 (비신뢰성)</li>
<li>어플리케이션 구분이 어려움 </li>
</ol>
<br>

<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/19ddfc2d-9e2b-4c72-8abb-d10dfe361c6c/image.png" alt=""></p>
 <br>

<p>IP 패킷들이 중간 노드를 거쳐가면서 다른 경로로 라우팅 되는 경우 패킷 전달 순서가 사용자의 의도와 달라질 수 있습니다. </p>
<p>또한 패킷이 중간에 소실될 위험이 있고,
PC가 여러 개의 프로그램을 동시에 사용할 때 IP만으로는 어플리케이션을 구분하기 어렵다는 문제점이 존재합니다. </p>
<p>이러한 한계점을 극복하고 보완한 프로토콜이 TCP 프로토콜입니다. </p>
<p>TCP 프로토콜에 대한 내용은 다음 포스팅에서 다루도록 하겠습니다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] HashSet 사용 설명서 ]]></title>
            <link>https://velog.io/@hahaeun-v/Java-HashSet-%EC%82%AC%EC%9A%A9-%EC%84%A4%EB%AA%85%EC%84%9C</link>
            <guid>https://velog.io/@hahaeun-v/Java-HashSet-%EC%82%AC%EC%9A%A9-%EC%84%A4%EB%AA%85%EC%84%9C</guid>
            <pubDate>Mon, 19 Feb 2024 12:14:14 GMT</pubDate>
            <description><![CDATA[<br>

<h3 id="hashset의-성격과-특징">HashSet의 성격과 특징</h3>
<ul>
<li>Set 인터페이스에서 지원하는 구현 클래스이다.</li>
<li>순서대로 저장되지 않는다.</li>
<li>중복된 요소를 허용하지 않는다. </li>
<li>내부 해시 함수를 통해 저장 위치가 결정되므로 비선형적 구조이다. </li>
<li>따라서 검색 속도가 빠르다.</li>
</ul>
<br>

<h3 id="주요-메소드">주요 메소드</h3>
<ol>
<li><p>add(E e): HashSet에 요소를 추가합니다. 이미 요소가 존재할 경우 추가되지 않고 false를 반환합니다.</p>
</li>
<li><p>remove(Object o): HashSet에서 지정된 요소를 제거합니다. 요소가 성공적으로 제거되면 true를 반환하고, 요소가 존재하지 않거나 제거에 실패하면 false를 반환합니다.</p>
</li>
<li><p>contains(Object o): HashSet에 지정된 요소가 포함되어 있는지 여부를 확인합니다. 요소가 있으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.</p>
</li>
<li><p>isEmpty(): HashSet이 비어 있는지 여부를 확인합니다. 비어 있으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.</p>
</li>
<li><p>size(): HashSet의 요소 수를 반환합니다.</p>
</li>
<li><p>clear(): HashSet에서 모든 요소를 제거합니다.</p>
</li>
<li><p>iterator(): HashSet의 요소를 반복하는 데 사용되는 Iterator를 반환합니다.</p>
</li>
</ol>
<br>

<h3 id="선언-방법">선언 방법</h3>
<pre><code>HashSet&lt;Integer&gt; set1 = new HashSet&lt;Integer&gt;();//HashSet생성
HashSet&lt;Integer&gt; set2 = new HashSet&lt;&gt;();//new에서 타입 파라미터 생략가능
HashSet&lt;Integer&gt; set3 = new HashSet&lt;Integer&gt;(set1);//set1의 모든 값을 가진 HashSet생성
HashSet&lt;Integer&gt; set4 = new HashSet&lt;Integer&gt;(10);//초기 용량(capacity)지정
HashSet&lt;Integer&gt; set5 = new HashSet&lt;Integer&gt;(10, 0.7f);//초기 capacity,load factor지정
HashSet&lt;Integer&gt; set6 = new HashSet&lt;Integer&gt;(Arrays.asList(1,2,3));//초기값 지정</code></pre><br>
<br><br>]]></description>
        </item>
        <item>
            <title><![CDATA[[AWS] S3 정책 설정 오류]]></title>
            <link>https://velog.io/@hahaeun-v/AWS-S3-%EC%A0%95%EC%B1%85-%EC%84%A4%EC%A0%95-%EC%98%A4%EB%A5%98</link>
            <guid>https://velog.io/@hahaeun-v/AWS-S3-%EC%A0%95%EC%B1%85-%EC%84%A4%EC%A0%95-%EC%98%A4%EB%A5%98</guid>
            <pubDate>Fri, 22 Dec 2023 15:10:18 GMT</pubDate>
            <description><![CDATA[<p><a href="https://awspolicygen.s3.amazonaws.com/policygen.html">정책 편집기</a></p>
<pre><code>{
  &quot;Id&quot;: &quot;정책_번호&quot;,
  &quot;Version&quot;: &quot;2012-10-17&quot;,
  &quot;Statement&quot;: [
    {
      &quot;Sid&quot;: &quot;시드_입력_필수아님&quot;,
      &quot;Action&quot;: [
        &quot;s3:DeleteObject&quot;,
        &quot;s3:GetObject&quot;,
        &quot;s3:ListBucket&quot;,
        &quot;s3:PutObject&quot;
      ],
      &quot;Effect&quot;: &quot;Allow&quot;,
      &quot;Resource&quot;: [
        &quot;arn:aws:s3:::`ARN_입력`/*&quot;,  
        &quot;arn:aws:s3:::`ARN_입력`&quot; 
      ],
      &quot;Principal&quot;: &quot;*&quot;
    }
  ]
}</code></pre><p><code>Action does not apply to any resource(s) in statement</code>오류가 나서 찾아보니
Resource 입력하는 부분에서 ARN 뒤에<code>/*</code>를 추가적으로 입력하라고 하는데 
혹시 해결이 안될 경우에는 <code>&quot;arn:aws:s3:::&#39;ARN_입력&#39;&quot;</code>를 추가적으로 입력해보자.</p>
<p>get, put, delete의 경우 버킷의 루트 경로가 아니라 객체 경로를 필요로 하기 때문</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[openai] Whisper API]]></title>
            <link>https://velog.io/@hahaeun-v/openai-Whisper-API</link>
            <guid>https://velog.io/@hahaeun-v/openai-Whisper-API</guid>
            <pubDate>Tue, 05 Dec 2023 15:45:55 GMT</pubDate>
            <description><![CDATA[<p>venv으로 <code>pip install openai</code> 실행</p>
<pre><code>(myvenv) C:\Lecture\ai-x\project\test_openai&gt;python -u &quot;c:\Lecture\ai-x\project\test_openai\openai_test_whisper.py&quot;
Traceback (most recent call last):
  File &quot;c:\Lecture\ai-x\project\test_openai\openai_test_whisper.py&quot;, line 2, in &lt;module&gt;
    client = OpenAI(
TypeError: OpenAI.__init__() got an unexpected keyword argument &#39;OPENAI_API_KEY&#39;</code></pre><p>api key를 OPENAI_API_KEY에 담았더니 에러가 발생했다. <code>api_key=&quot;sk-your_key&quot;</code>로 담아서 요청하면 해결된다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 간단한 웹소켓 WebSocket 실행기]]></title>
            <link>https://velog.io/@hahaeun-v/JavaScript-%EA%B0%84%EB%8B%A8%ED%95%9C-%EC%9B%B9%EC%86%8C%EC%BC%93-WebSocket-%EC%8B%A4%ED%96%89%EA%B8%B0</link>
            <guid>https://velog.io/@hahaeun-v/JavaScript-%EA%B0%84%EB%8B%A8%ED%95%9C-%EC%9B%B9%EC%86%8C%EC%BC%93-WebSocket-%EC%8B%A4%ED%96%89%EA%B8%B0</guid>
            <pubDate>Mon, 04 Dec 2023 16:03:32 GMT</pubDate>
            <description><![CDATA[<p>프로젝트 준비를 위해 웹소켓을 실행해보려고 합니다.<br>(스프링 부트 프로젝트로 빌드된 환경입니다.)</p>
<hr>
<br>

<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/324bbab4-d265-48f9-aa9b-da0fe64f2f21/image.png" alt=""></p>
<p>서버용 js파일을 하나 만들어주고 터미널에 명령어를 입력해줍니다.</p>
<p><code>npm init</code></p>
<p>실행하면 package name, version .. 등등 터미널에서 입력하는 과정이 있는데 현재는 테스트용 서버 실행이 목적이기 때문에 엔터, 엔터만 연타해보도록 합니다. </p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/68dd91cd-046c-4dcb-ae5b-37327a5fba90/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/00a4061a-a20e-4768-a07d-1f744e7b1712/image.png" alt=""></p>
<p>Is this OK? 가 나오면 엔터를 누르고 실행합니다. </p>
<p>실행한 후에 확인해보면 터미널을 실행한 경로에 json 파일이 생성된 것을 확인할 수 있습니다. </p>
<p>name은 패키지 이름이 default입니다. </p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/726d4ec5-5caa-4804-ac10-909e1c9deced/image.png" alt=""></p>
<p>웹소켓 연결을 쉽게 해주는 라이브러리를 실행합니다. </p>
<p><code>npm install express ws</code></p>
<p>새로운 json 파일이 생겼습니다. </p>
<hr>
<br>

<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/0f650077-2244-44b3-a36e-4d181af6d314/image.png" alt=""></p>
<p>테스트 해보기 위해 html 파일을 하나 생성해봅니다. html 구성에 간단하게 버튼을 만들어주었습니다. </p>
<pre><code class="language-html">&lt;button id=&quot;send&quot;&gt;메세지 보내기&lt;/button&gt;</code></pre>
<p>server.js 파일도 하나 생성해서 node.js 서버를 만들어줍니다. </p>
<pre><code class="language-javascript">const express = require(&#39;express&#39;);
const app = express();
const Websocket  = require(&#39;ws&#39;);

const socket = new Websocket.Server({
    port: 8003        // 웹소켓 port
});

app.listen(5000);    // 서버 port

app.use(&quot;/&quot;,function(req, res) {
    res.sendfile(__dirname + &#39;/main.html&#39;);
});</code></pre>
<p>처음에 인스톨했던 라이브러리를 변수로 담고 <em>(like import 구문)</em> 이것은 앞으로 웹소켓 서버 역할을 하게됩니다. 접속 포트는 5000번이고 웹소켓 포트는 8003번입니다. </p>
<p>터미널에 <code>$ node server.js</code> 실행하면 localhost로 오류없이 정상 실행되는 모습을 확인할 수 있습니다. </p>
<hr>
<br>


<p>그러면 웹소켓으로 메세지를 전송해보겟습니다. </p>
<p>유저가 메세지 전송요청을 보내기 위해 html에 웹소켓 연결을 추가해줍니다. </p>
<pre><code class="language-html">&lt;button id=&quot;send&quot; onclick=&quot;socket.send(&#39;hi&#39;)&quot;&gt;메세지 보내기&lt;/button&gt;

&lt;script&gt;
    let socket = new WebSocket(&quot;ws://localhost:8003&quot;)
&lt;/script&gt;</code></pre>
<p>유저의 요청을 받아보기 위해 server.js에도 추가해줍니다. </p>
<pre><code class="language-javascript">socket.on(&#39;connection&#39;, (ws, req) =&gt; {
    ws.on(&#39;message&#39;, (msg) =&gt; {
        console.log(&#39;서버에서 온 메세지 : &#39; + msg);
    });
});</code></pre>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/5a2bc046-f34e-4b68-8339-08ad4482aa3f/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/66ce0171-0be3-4e8b-8dc4-f48541ab3f4e/image.png" alt=""></p>
<p>다음과 같이 올린 데이터와 서버에서 받은 클라이언트(ws)의 메세지를 확인해보았습니다. </p>
<p>서버에서 클라이언트로 데이터를 보내려면 아래의 코드를 활용하면 됩니다. </p>
<pre><code class="language-javascript">socket.on(&#39;connection&#39;, (ws, req) =&gt; {
    ws.on(&#39;message&#39;, (data) =&gt; {
        console.log(&#39;클라이언트에게 보내는 메세지 : &#39; + data);
        ws.send(&#39;서버에서 보내는 메세지 : &#39; + data);
    });
    ws.send(&#39;보낸다 경로로 서버에서 : &#39; + req.socket.remoteAddress)
});</code></pre>
<hr>
<br>

<p>추가적으로 <a href="https://www.youtube.com/watch?v=yXPCg5eupGM">코딩애플</a>의 설명을 참고하였는데 버전 차이인지 아래 <code>new Websocket.Server</code>에서 Server가 인식이 안되는 문제가 있었지만 실행에서 문제는 없었습니다. </p>
<pre><code class="language-javascript">const Websocket  = require(&#39;ws&#39;);

const socket = new Websocket.Server({
    port: 8003        // 웹소켓 port
});</code></pre>
<p>다른 방법으로는 WebSocketServer를 인스턴스 생성하여 사용해도 동일하게 작동하기 때문에 혹시 지원되지 않는다면 아래 코드를 사용하면 됩니다. </p>
<pre><code class="language-javascript">const { WebSocketServer }  = require(&#39;ws&#39;);

const socket = new WebSocketServer({
    port: 8003
});</code></pre>
<hr>
<br>

<p>스프링 부트 환경에서 웹소켓을 사용했을 때 CORS 문제로 웹소켓 실행이 되지 않았는데 </p>
<p><code>npm install cors</code> </p>
<p>실행하고 cors 세팅을 추가해서 문제가 해결됐습니다. </p>
<pre><code class="language-javascript">const cors = require(&#39;cors&#39;);

app.use(cors());</code></pre>
<blockquote>
<p>문제 발생 이유를 간단히 설명하자면 스프링 부트 응용 프로그램과 Node.js 서버가 서로 다른 포트 또는 도메인에서 실행 중인 경우 CORS 문제가 발생될 수 있다고 합니다. 스프링 부트의 요청을 허용하려면 Node.js 서버에서 CORS 설정을 구성해야 해서 이를 위해 cors 미들웨어를 사용하였습니다. </p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] mediapipe 사용하기 ]]></title>
            <link>https://velog.io/@hahaeun-v/Python-mediapipe-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@hahaeun-v/Python-mediapipe-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 24 Nov 2023 12:54:23 GMT</pubDate>
            <description><![CDATA[<p>앞에서 미니콘다 설치가 완료됐다면 mediapipe를 위한 셋팅을 해봅시다.</p>
<p><code>$ python -m pip install mediapipe</code>
<code>$ pip install insightface</code></p>
<blockquote>
<p><code>insightface</code>가 아닌 원하는 라이브러리의 인스톨러를 실행하면된다. <code>Insightface</code>는 안면인식을 하는 모델로 상업적 서비스도 생성이 가능하다.</p>
</blockquote>
<p>인스톨을 하면 <code>ERROR: Failed building wheel for insightface</code> 에러가 발생하는데 살펴보면 tools가 필요하다고 나옵니다. </p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/21af765c-3c38-48ff-a029-daffb965fd5c/image.png" alt=""></p>
<p>에러 중간에 보면 <code>end of output</code> 에러 문구 상단의 주소로 들어가서 &quot;Microsoft C++ Build Tools&quot; 설치를 받아주면 됩니다. </p>
<p>메인화면은 <code>C## 데스크톱</code> 체크하고 우측 사이드바에 체크 박스를 두개만 체크 !</p>
<p><br><br></p>
<p><a href="https://developers.google.com/mediapipe/solutions/tasks">Mediapipe</a>의 가이드에 따라 설정해주면 되는데</p>
<p>먼저, Mediapipe의 작업을 위한 가장 기본 모듈이다.</p>
<pre><code class="language-python">import mediapipe as mp
from mediapipe.tasks import python
from mediapipe.tasks.python import vision
from mediapipe.tasks.python import text
from mediapipe.tasks.python import audio</code></pre>
<p><code>insightface</code>를 사용하기 위해서는 아래의 모듈을 임포트해주어야 합니다. </p>
<pre><code class="language-python">import mediapipe as mp
from mediapipe.tasks import python
from mediapipe.tasks.python import vision</code></pre>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/6a55dbf6-e2bb-42a8-95ac-25649f6388fe/image.png" alt=""></p>
<p>그리고 원하는 모델을 설치해서 가져오기 편한 경로에 위치시킵니다.</p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/282a8133-5b6a-4e20-9d90-07026da9d085/image.png" alt=""></p>
<blockquote>
<p>용량에 따라 정확도가 다르다. (다양한 테스트가 필요함)</p>
</blockquote>
<p>모델의 경로를 읽어오기 위해 설정을 해주는데 윈도우와 맥에 따라 경로가 다른데, 아래는 윈도우 환경 경로 예시로 참고해주세요.</p>
<p><code>model_path = &#39;efficientdet_lite0.tflite&#39;</code></p>
<p>vscode는 터미널과 코드에디터가 연동되있지 않기 때문에 연결을 해주어야 인식하므로 오류가 발생할 수 있기 때문에 당황하지말고 연결 후에 정상적으로 인식하는 것을 확인한다.</p>
<p>테스트를 위해 설정 후 이미지 파일이 정상적으로 열리는지 확인한다. </p>
<pre><code class="language-python"># 이미지 다운로드
#!wget -q -O image.jpg https://storage.googleapis.com/mediapipe-tasks/object_detector/cat_and_dog.jpg

IMAGE_FILE = &#39;image.jpg&#39;

import cv2
from google.colab.patches import cv2_imshow

img = cv2.imread(IMAGE_FILE)
cv2_imshow(img)</code></pre>
<p>추론 실행 및 결과 시각화 과정 예시이다. 원하는 파일을 입력하고 추론결과를 확인해볼 수 있다. </p>
<pre><code class="language-python"># STEP 1: Import the necessary modules.
import numpy as np
import mediapipe as mp
from mediapipe.tasks import python
from mediapipe.tasks.python import vision

# STEP 2: Create an ObjectDetector object.
base_options = python.BaseOptions(model_asset_path=&#39;efficientdet.tflite&#39;)
options = vision.ObjectDetectorOptions(base_options=base_options,
                                       score_threshold=0.5)
detector = vision.ObjectDetector.create_from_options(options)

# STEP 3: Load the input image.
image = mp.Image.create_from_file(IMAGE_FILE)

# STEP 4: Detect objects in the input image.
detection_result = detector.detect(image)

# STEP 5: Process the detection result. In this case, visualize it.
image_copy = np.copy(image.numpy_view())
annotated_image = visualize(image_copy, detection_result)
rgb_annotated_image = cv2.cvtColor(annotated_image, cv2.COLOR_BGR2RGB)
cv2_imshow(rgb_annotated_image)</code></pre>
<pre><code class="language-python">import cv2
import numpy as np

MARGIN = 10  # pixels
ROW_SIZE = 10  # pixels
FONT_SIZE = 1
FONT_THICKNESS = 1
TEXT_COLOR = (255, 0, 0)  # red

def visualize(
    image,
    detection_result
) -&gt; np.ndarray:

  &quot;&quot;&quot;Draws bounding boxes on the input image and return it.
  Args:
    image: The input RGB image.
    detection_result: The list of all &quot;Detection&quot; entities to be visualize.
  Returns:
    Image with bounding boxes.
  &quot;&quot;&quot;
  for detection in detection_result.detections:

    # Draw bounding_box
    bbox = detection.bounding_box
    start_point = bbox.origin_x, bbox.origin_y
    end_point = bbox.origin_x + bbox.width, bbox.origin_y + bbox.height
    cv2.rectangle(image, start_point, end_point, TEXT_COLOR, 3)

    # Draw label and score
    category = detection.categories[0]
    category_name = category.category_name
    probability = round(category.score, 2)
    result_text = category_name + &#39; (&#39; + str(probability) + &#39;)&#39;
    text_location = (MARGIN + bbox.origin_x,
                     MARGIN + ROW_SIZE + bbox.origin_y)
    cv2.putText(image, result_text, text_location, cv2.FONT_HERSHEY_PLAIN,
                FONT_SIZE, TEXT_COLOR, FONT_THICKNESS)

  return image</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] 미니콘다로 실행]]></title>
            <link>https://velog.io/@hahaeun-v/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%8B%A4%ED%96%89</link>
            <guid>https://velog.io/@hahaeun-v/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%8B%A4%ED%96%89</guid>
            <pubDate>Fri, 24 Nov 2023 08:02:25 GMT</pubDate>
            <description><![CDATA[<p><br><br><br></p>
<p>딥러닝을 위해서는 languege binding으로 아나콘다를 사용하는 것이 좋다. 컴파일이 안되어있는 파일이 있기 때문에 특히 windows환경에서는 환경설정 오류 가능성을 줄이기 위해 콘다를 사용하는 것을 권장한다. </p>
<p>아나콘다는 유료화되어 미니콘다를 사용해보려고 한다. 
<br><br></p>
<p>설치하기 전에 기존에 설치되었던 파이썬을 제거해서 환경에서 경로가 꼬이는 문제를 방지하고자 한다.</p>
<p><code>제어판</code> - <code>프로그램 제거</code> - <code>python</code> , <code>python launcher</code> 제거
<br><br></p>
<h2 id="1-미니콘다-설치">1. <a href="https://github.com/conda-forge/miniforge">미니콘다</a> 설치</h2>
<p>설치과정은 모두 기본설정을 따르고,
설치 단계에서 *<em>아래 사진의 <code>Add Miniforge to my PATH -</code>의 체크 박스를 &gt;&gt;&gt;<em>반드시</em>&lt;&lt;&lt; 체크해주면 된다. *</em></p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/b5599855-17c5-441a-82ea-745f2abfcb1f/image.png" alt=""></p>
<p>미니콘다의 파이썬이 환경변수에서 기존에 설치된 파이썬을 무시하고 실행하기 때문에 경고하는 내용인데 반드시 체크해야한다. 
<br><br></p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/05449745-cef1-4e20-88b6-fc5d8b65a7e9/image.png" alt=""></p>
<p>잠깐 환경변수를 살펴보면 환경변수의 PATH에서 vscode로 연결되어있는데 이것은 어느 경로든 cmd에서 <code>code .</code>명령어를 실행했을 때 vscode가 실행되는 이유이다. 
<br><br></p>
<p>다시 미니콘다로 돌아와서, </p>
<p><code>cmd</code>에서 <code>python</code>을 실행했을때 <code>conda-forge</code>로 실행되는 것을 확인하면 정상적으로 설치된것이다.
<img src="https://velog.velcdn.com/images/hahaeun-v/post/210a0ebc-c6a6-410a-88f3-88b4c86e94cb/image.png" alt=""></p>
<br>

<p>미니콘다를 활성화 해보자</p>
<p><code>$ conda create -n &#39;가상환경이름&#39; python=3.10</code>
<code>$ conda activate &#39;가상환경이름&#39;</code></p>
<p>여기까지 완료되면 기본적인 세팅은 완료된다.</p>
<p><code>conda env list</code>
지금까지 만든 가상환경 목록 확인 가능</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DB] sqllite3]]></title>
            <link>https://velog.io/@hahaeun-v/sqllite</link>
            <guid>https://velog.io/@hahaeun-v/sqllite</guid>
            <pubDate>Fri, 24 Nov 2023 00:52:29 GMT</pubDate>
            <description><![CDATA[<p>데이터베이스 관리 시스템으로 서버가 아닌 응용 프로그램에 넣어 사용하는 가벼운 데이터베이스이다. </p>
<p>간단한 앱을 만들어보기 위해서 사용해보려고한다. </p>
<p>DB 연결 설정 방법
먼저 가상환경에서 cmder에 라이브러리를 설치한다. 
<br><br></p>
<h2 id="1-라이브러리-설치">1. 라이브러리 설치</h2>
<pre><code class="language-python"># 설치 라이브러리
pip install sqlalchemy </code></pre>
<p><br><br></p>
<h2 id="2-db-연결-정의">2. DB 연결 정의</h2>
<p><code>&#39;Path&#39;/database.py</code>에 아래 내용을 기반으로 정의한다. </p>
<pre><code class="language-python">from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

DB_URL = &#39;sqlite:///todo.sqlite3&#39;

# 데이터베이스에 연결하는 엔진을 생성하는 함수
engine = create_engine(DB_URL, connect_args={&#39;check_same_thread&#39;: False})

# 데이터베이스와 상호 작용하는 세션을 생성하는 클래스
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

# SQLAlchemy의 선언적 모델링을 위한 기본 클래스
Base = declarative_base()</code></pre>
<br>

<h3 id="declarative_base-클래스의-기능"><code>declarative_base</code> 클래스의 기능</h3>
<ul>
<li>데이터베이스 모델 클래스를 정의하는 기능</li>
<li>데이터베이스 모델 클래스와 데이터베이스 테이블을 연결하는 기능</li>
<li>데이터베이스 모델 클래스를 사용하여 데이터베이스와 상호 작용하는 기능
<br><br></li>
</ul>
<h2 id="3-db-실행-정의">3. DB 실행 정의</h2>
<p><code>&#39;Path&#39;/main.py</code>에 아래 내용을 기반으로 정의한다.</p>
<pre><code class="language-python">from database import engine, SessionLocal 
from sqlalchemy.orm import Session
import models

# models에 정의한 모든 클래스, 연결한 DB엔진에 테이블로 생성
models.Base.metadata.create_all(bind=engine)

... 생략 ...
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        # 마지막에 무조건 닫음
        db.close()</code></pre>
<p><code>yield</code> 키워드는 FastAPI가 함수의 실행을 일시 중지하고 데이터베이스 세션을 호출자에게 반환하도록 지시한다. </p>
<p>여기에서 import된 database 는 database.py 로 모듈화 한 것을 사용하는 것이다. </p>
<p>DBeaver Community 23.2.5는 rdbms만 pro는 정형 비정형 다 보여준다. </p>
<h2 id="4-db-데이터-모델-정의">4. DB 데이터 모델 정의</h2>
<pre><code class="language-python">from sqlalchemy import Column, Integer, Boolean, Text
from database import Base

class Todo(Base):
    __tablename__ = &#39;todos&#39;
    id = Column(Integer, primary_key=True)
    task = Column(Text)
    completed = Column(Boolean, default=False)</code></pre>
<p><code>repr</code> 메소드는 객체를 문자열로 표현하기 위해 사용된다. <code>repr</code> 메소드를 호출하면 <code>&lt;Todo 1&gt;</code>형식의 문자열이 반환되도록 정의되었다. </p>
<hr>
<p><a href="https://dev.to/nditah/develop-a-simple-python-fastapi-todo-app-in-1-minute-8dg">참고 문서</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] 파일 읽고 쓰기]]></title>
            <link>https://velog.io/@hahaeun-v/Python-%ED%8C%8C%EC%9D%BC-%EC%9D%BD%EA%B3%A0-%EC%93%B0%EA%B8%B0</link>
            <guid>https://velog.io/@hahaeun-v/Python-%ED%8C%8C%EC%9D%BC-%EC%9D%BD%EA%B3%A0-%EC%93%B0%EA%B8%B0</guid>
            <pubDate>Thu, 23 Nov 2023 16:56:19 GMT</pubDate>
            <description><![CDATA[<br>

<h2 id="파일-열기">파일 열기</h2>
<p>파일을 다루기 위해서는 먼저 파일을 오픈해야한다. 이때 <code>open()</code> 함수를 이용한다. </p>
<h3 id="with-open과-open의-차이">with open과 open의 차이</h3>
<p><code>with open()</code>은 <code>close()</code>를 자동으로 해주기 때문에 비교적 코드가 간결하다. </p>
<p><code>open()</code>으로 작성하면 별칭이 아닌 변수로 바인딩하여 사용하고 명시적으로 <code>close()</code>해준다.</p>
<pre><code class="language-python"># with open()
with open(&quot;매수종목1.txt&quot;, &quot;w&quot;, encoding=&quot;utf8&quot;) as file:
    file.write(&quot;005930\n005380\n035420&quot;)

# open()
file = open(&quot;매수종목1.txt&quot;, &quot;w&quot;, encoding=&quot;utf8&quot;):
    file.write(&quot;005930\n005380\n035420&quot;)    </code></pre>
<p><br><br></p>
<h2 id="mode">mode</h2>
<p><code>open</code> 함수의 두번째 <code>arg</code>인 mode는 파일을 어떤 용도로 사용할지를 결정하는 역할을 한다. </p>
<ul>
<li><p>&#39;w&#39; : 쓰기 모드. 파일을 변경하거나 추가한다. 기존 파일이 없으면 새로 생성되고 기존 파일이 있는 경우에는 삭제하고 새로 생성한다. file pointer는 시작 부분에 위치</p>
</li>
<li><p>&#39;r&#39; : 읽기 모드. 파일의 정보를 읽기만 한다. file pointer는 시작 부분에 위치</p>
</li>
<li><p>&#39;r+&#39; : 읽기/쓰기 모드. 파일을 변경하고 읽을 때 사용한다. file pointer는 시작 부분에 위치</p>
</li>
<li><p>&#39;a+&#39;: 추가와 읽기 모드. 파일을 열어 읽을 수 있고 파일 끝에 데이터를 추가할 수 있다. file pointer는 끝 부분에 위치</p>
</li>
<li><p>생략: 읽기 모드</p>
</li>
</ul>
<p><br><br></p>
<h2 id="파일-쓰기">파일 쓰기</h2>
<h3 id="csv-파일-만들기">csv 파일 만들기</h3>
<pre><code class="language-python">import csv

with open(&quot;매수종목3.csv&quot;, mode=&quot;w&quot;, encoding=&quot;utf8&quot;, newline=&#39;&#39;) as file:
    writer = csv.writer(file)
    writer.writerow([&quot;종목명&quot;, &quot;종목코드&quot;, &quot;PER&quot;])
    writer.writerow([&quot;삼성전자&quot;, &quot;005930&quot;, 15.59])
    writer.writerow([&quot;NAVER&quot;, &quot;035420&quot;, 55.82])

with open(&quot;매수종목3.csv&quot;, mode=&quot;a+&quot;, encoding=&quot;utf8&quot;, newline=&quot;&quot;) as file:
    writer = csv.writer(file)
    writer.writerows([[&quot;종목명&quot;, &quot;종목코드&quot;, &quot;PER&quot;],\
                      [&quot;삼성전자&quot;, &quot;005930&quot;, 15.59],\
                        [&quot;NAVER&quot;, &quot;035420&quot;, 55.82]])</code></pre>
<p>코드를 먼저 살펴보면 현재 경로에 <code>매수종목3.csv</code> 파일을 <code>w</code> 모드로 생성하고 두번째 코드에서 <code>mode=&#39;a+&#39;</code>에 따라 정보를 추가한다. </p>
<p><code>writerow()</code>는 행 데이터를 추가하는데 매개변수는 <code>iterable</code>한 객체여야 한다. <code>writerows()</code>은 동시에 여러 헹 데이터를 추가하고자 할 때 사용되며 2차원 배열처럼 다중 배열을 이용해 작성할 수 있다. </p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/af823849-53a0-43d9-a4fa-2aaabe5c9d8f/image.png" alt=""></p>
<p><code>매수종목3.csv</code> 결과 </p>
<h2 id="파일-읽기">파일 읽기</h2>
<p>파일을 읽기위해 모드를 설정해주고 파일 객체를 메소드를 통해 받아온다. </p>
<p>파일 데이터를 읽어오는 여러 메소드를 결과를 보면서 비교해보자 </p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/48e8c56e-8c1c-422e-a48f-f312010bbc0a/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/fcf9e3b3-6d35-441f-857e-2afe54cc4bfb/image.png" alt=""></p>
<p><code>read()</code> 는 <code>size</code>를 입력하지 않으면 파일의 전체 데이터를 읽어온다. 지정하면 원하는 바이트만큼 받아올 수 있다. 예시에서는<code>size</code>를 3으로 지정해서 3 바이트를 받아왔다. <em>한글은 1글자 당 1로 인식한다.</em></p>
<p><code>readline()</code>은 한 줄씩 읽어온다. 그리고, 반환값을 출력했을때 마지막에 한 줄이 띄어져있음을 확인할 수 있다. 텍스트 파일은 라인별로 구성되어있는데 각 라인의 끝에는 보이지 않는 <code>new line</code>이 존재하기 때문이다. 파이썬에서는 이것을 <code>/n</code>으로 표기한다. </p>
<p><code>readline()</code>은 한 줄씩 list 타입으로 모두 받아온다. 역시 마찬가지로 <code>new line</code>이 입력되어있는 것을 볼 수 있다. </p>
<p>예시의 결과처럼 일부 데이터만 읽은 경우, 닫히지 않은 파일에서는 <code>file pointer</code>가 예상하는 위치가 아닐 수 있음을 유의해야 한다. </p>
<br>

<br>

<hr>
<p>참고</p>
<p><a href="https://docs.python.org/ko/3.10/library/csv.html?highlight=writerow#csv.csvwriter.writerow">파이썬 도큐먼트</a></p>
<p><a href="https://blog.naver.com/PostView.naver?blogId=hankrah&amp;logNo=221826216596">파이썬 파일다루기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] 파일 경로]]></title>
            <link>https://velog.io/@hahaeun-v/Python-%ED%8C%8C%EC%9D%BC-%EA%B2%BD%EB%A1%9C</link>
            <guid>https://velog.io/@hahaeun-v/Python-%ED%8C%8C%EC%9D%BC-%EA%B2%BD%EB%A1%9C</guid>
            <pubDate>Thu, 23 Nov 2023 14:43:12 GMT</pubDate>
            <description><![CDATA[<p>1.현재 파일의 이름 &amp; 경로</p>
<pre><code>import os

# 현재 파일 이름
print(__file__)


# 현재 파일 실제 경로
print(os.path.realpath(__file__))

# 현재 파일 절대 경로
print(os.path.abspath(__file__))</code></pre><p>2.현재 파일의 디렉토리 경로</p>
<pre><code>import os

# 현재 폴더 경로; 작업 폴더 기준
print(os.getcwd())

#현재 파일의 폴더 경로; 작업 파일 기준
print(os.path.dirname(os.path.realpath(__file__)))</code></pre><p>3.현재 디렉토리의 파일 리스트</p>
<pre><code>import os
print(os.listdir(os.getcwd()))</code></pre><p>4.작업 디렉토리 변경</p>
<pre><code>import os
os.chdir(&quot;/home/dada/test/&quot;)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] IndexError: Replacement index 3 out of range for positional args tuple]]></title>
            <link>https://velog.io/@hahaeun-v/Python-IndexError-Replacement-index-3-out-of-range-for-positional-args-tuple</link>
            <guid>https://velog.io/@hahaeun-v/Python-IndexError-Replacement-index-3-out-of-range-for-positional-args-tuple</guid>
            <pubDate>Thu, 23 Nov 2023 14:18:27 GMT</pubDate>
            <description><![CDATA[<p>print 함수에서 인덱스 부여가 잘못되어 발생한 오류이다. </p>
<pre><code class="language-python">    def info(self):
        print(&quot;바퀴수 : {0} \n가격 : {1} \n구동계 : {3}&quot;.\
              format(self.tier, self.price, self.machine))</code></pre>
<p>프린트문에 부여된 인덱스를 <code>{3}</code>에서 <code>{2}</code>로 수정하면 오류가 해결된다. </p>
<pre><code class="language-python">    def info(self):
        print(&quot;바퀴수 : {0} \n가격 : {1} \n구동계 : {2}&quot;.\
              format(self.tier, self.price))</code></pre>
<p>그리고 전달인자가 부족해도 동일한 내용의 IndexError 에러가 발생하므로 인덱스를 부여한 코드를 살펴보면 어렵지 않게 해결이 가능하다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] Fastapi 시작하기]]></title>
            <link>https://velog.io/@hahaeun-v/Python-Fastapi-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%8B%A4%ED%96%89</link>
            <guid>https://velog.io/@hahaeun-v/Python-Fastapi-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%8B%A4%ED%96%89</guid>
            <pubDate>Wed, 22 Nov 2023 16:27:52 GMT</pubDate>
            <description><![CDATA[<br>

<p>Fastapi는 현대적이고 빠르며, 파이썬 표준 타입 힌트에 기초한 Python3.6+의 API를 빌드하기 위한 웹 프레임워크이다. 
<br><br></p>
<h3 id="1-fastapi의-특징">1. fastapi의 특징</h3>
<p><a href="https://fastapi.tiangolo.com/ko/#performance">fastapi 공식 홈페이지</a>의 설명을 빌리자면, 
성능이 빠르고, 버그가 적고, 직관적이며, 사용이 쉽고, 코드가 짧고, 표준 기반이라는 특징을 지니고 있다. 그 중 가장 큰 장점은 개방형 표준 기반(마치 Postman) 클라이언트가 내장되어있다는 점이다. </p>
<p><br><br></p>
<h3 id="2-가상환경-준비">2. 가상환경 준비</h3>
<p>Cmder에서 가상환경 디렉토리를 생성한다. 
원하는 경로에서 가상환경을 생성한 후, 다른 탭에서 <code>activate.bat</code>를 실행한다. 
<br></p>
<p><code>python -m venv 가상환경이름</code>
<code>가상환경이름\Scripts\activate.bat</code></p>
<p>그리고, 작업할 dir로 이동한 후 <code>code .</code> 명령어를 사용하면 바로 실행할 수 있다. </p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/b0e8eae0-76e1-49ed-8b25-899cd32eb12c/image.png" alt=""></p>
<p><br><br></p>
<h3 id="3-fastapi-설치">3. fastapi 설치</h3>
<p>cmder로 다시 돌아와서 <a href="https://fastapi.tiangolo.com/ko/#performance">fastapi</a> 에 따라 api와 unicorn 서버를 설치하기 위해 아래 명령어를 실행한다. </p>
<p><code>pip install fastapi</code>
<code>python.exe -m pip install --upgrade pip</code>
<code>pip install &quot;uvicorn[standard]&quot;</code>
<code>pip install python-multipart</code> &gt; 멀티미디어</p>
<blockquote>
<p>uvicorn은 웹서버를 띄워주는 역할을 한다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/b4ade60c-344e-452e-a272-98c2e96ff98c/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/9cc0836f-a9ce-4a51-a9f6-d00fa0d00fa8/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/67eb609f-b02f-4d90-bcf3-970fbb7d1e77/image.png" alt=""></p>
<p><br><br></p>
<h3 id="4-예제-파일-만들기">4. 예제 파일 만들기</h3>
<pre><code class="language-python">from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get(&quot;/&quot;)
def read_root():
    return {&quot;Hello&quot;: &quot;World&quot;}


@app.get(&quot;/items/{item_id}&quot;)
def read_item(item_id: int, q: Union[str, None] = None):
    return {&quot;item_id&quot;: item_id, &quot;q&quot;: q}</code></pre>
<blockquote>
<p>fastapi 데코레이터 @app.get()은 앤드포인트 함수를 정의하는데 사용된다. 이 앤드포인트 함수는 URL 경로 또는 <code>/items/{item_id}</code>에 대한 요청을 처리한다.</p>
</blockquote>
<ul>
<li>첫번째 인수 path : <code>item_id</code>는 url경로를 나타낸다.</li>
<li>두번째 인수 response_model : 반환값의 형식을 지정하는데 사용된다. </li>
<li>세번째 인수 query_params : 는 쿼리 파라미터를 나타내는데 사용된다. </li>
</ul>
<p>q는 변수이고 타입은 str, none 둘다 가능하고 기본은 none이다. 문자열과 none도 허용한다는 뜻 </p>
<blockquote>
<p><code>item_id</code>는 <code>int</code>를 명시하고 있는데 이것은 fastapi가 Pydantic을 지원하기 때문이다.
Pydantic은 Python Type Hint를 사용한 데이터 유효성 검사 및 설정관리를 의미한다. 따라서, 약속되지 않은 값이 들어가지 않는 것을 방지한다. </p>
</blockquote>
<p><br><br></p>
<h3 id="5-서버에-올리기">5. 서버에 올리기</h3>
<p>서버를 띄우는 방법
<code>uvicorn main:app --reload</code></p>
<p>실시간으로 수정사항을 리로드하려면 아래 명령어를 cmder에 날린다.</p>
<p><code>uvicorn main:app --port=9000 --reload</code></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] 딕셔너리 활용]]></title>
            <link>https://velog.io/@hahaeun-v/Python-%EB%94%95%EC%85%94%EB%84%88%EB%A6%AC-%ED%99%9C%EC%9A%A9</link>
            <guid>https://velog.io/@hahaeun-v/Python-%EB%94%95%EC%85%94%EB%84%88%EB%A6%AC-%ED%99%9C%EC%9A%A9</guid>
            <pubDate>Tue, 21 Nov 2023 12:49:39 GMT</pubDate>
            <description><![CDATA[<br>

<h3 id="딕셔너리-란">딕셔너리 란</h3>
<p>java의 map과 유사한 형태를 띄고 있는 dictionary 자료형은 &#39;연관 배열&#39; 또는 해시(Hash)라고도 할 수 있다. </p>
<br>


<h3 id="딕셔너리-형태">딕셔너리 형태</h3>
<p>딕셔너리의 구조는 Key와 Value가 한 쌍으로 이루어진다. </p>
<pre><code class="language-pyhton">{Key1: Value1, Key2: Value2, Key3: Value3, ...}</code></pre>
<br>


<p>만약 value에 여러 값이 들어가야 한다면 값을 리스트로 복합속성을 띌 수도 있다.
<img src="https://velog.velcdn.com/images/hahaeun-v/post/e224b523-37e7-4aa6-bcc0-80b611a249cd/image.png" alt=""></p>
<pre><code class="language-python">inventory = {&#39;메로나&#39;:[300,20],
             &#39;비비빅&#39;:[400,3],
             &#39;죠스바&#39;:[250,100]}</code></pre>
<br>
<br>

<h3 id="key-이용해서-value-얻기">key 이용해서 value 얻기</h3>
<pre><code class="language-python">inventory[&#39;메로나&#39;]</code></pre>
<br>


<h4 id="get-함수">get() 함수</h4>
<p>get 함수는 첫번째 인자를 키로 가지고있는 value를 리턴한다. 리턴값이 없을 경우 두번째 인자를 default값으로 주어 임의의 값을 리턴시킬 수 있다. </p>
<pre><code class="language-python">inventory = {&#39;메로나&#39;:[300,20],
             &#39;비비빅&#39;:[400,3],
             &#39;죠스바&#39;:[250,100]}

inventory.get(&#39;메로나&#39;)
inventory.get(&#39;메로나&#39;, &#39;default_value&#39;)</code></pre>
<br>
<br>

<h3 id="딕셔너리-추가">딕셔너리 추가</h3>
<pre><code class="language-python">inventory[&#39;new&#39;] = 1234</code></pre>
<br>



<h4 id="zip-함수">zip() 함수</h4>
<p>지퍼를 올리는 것 처럼 양쪽의 데이터를 하나의 쌍을 짝지어주는 함수이다. </p>
<p>list, tuple, dic (딕셔너리)로 엮을 수 있다. 
주의할 점은 두가지 데이터 더미에서 인자의 길이가 다를 경우 <strong>짧은 인자를 기준으로 데이터가 엮이고 나머지는 버려지므로</strong> 이점을 인지해야한다. </p>
<p><img src="blob:https://velog.io/fa98f7c2-e4b1-43f4-ab38-a2692b46bc38" alt="업로드중.."></p>
<br>
<br>


<h3 id="딕셔너리-삭제">딕셔너리 삭제</h3>
<pre><code class="language-python">del inventory[&#39;new&#39;]</code></pre>
<p><img src="https://velog.velcdn.com/images/hahaeun-v/post/de2e2392-d4ec-40a9-a4fb-ef6c1fb19599/image.png" alt=""></p>
<br>



<h3 id="key-리스트-만들기">key 리스트 만들기</h3>
<pre><code class="language-python">del inventory[&#39;new&#39;]</code></pre>
<br>

]]></description>
        </item>
    </channel>
</rss>