<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>enjoy301</title>
        <link>https://velog.io/</link>
        <description>스타 폶 바럼</description>
        <lastBuildDate>Tue, 19 Jul 2022 14:52:55 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>enjoy301</title>
            <url>https://images.velog.io/images/silver_bell/profile/595b3e4d-fe23-47a6-92ab-6e30d46b48db/social.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. enjoy301. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/silver_bell" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[AWS Lambda PIL 오류 해결 (python)]]></title>
            <link>https://velog.io/@silver_bell/AWS-Lambda-PIL-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0-python</link>
            <guid>https://velog.io/@silver_bell/AWS-Lambda-PIL-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0-python</guid>
            <pubDate>Tue, 19 Jul 2022 14:52:55 GMT</pubDate>
            <description><![CDATA[<p>API Gateway에 연결된 lambda에서 이미지를 처리하는 라이브러리인 <strong>PIL</strong>을 사용하려는 중 아래의 에러를 마주했다.</p>
<blockquote>
<p><em>cannot import name &#39;_imaging&#39; from &#39;PIL&#39;</em></p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/silver_bell/post/9a71d3bd-268a-4b80-838b-1c295ee592e3/image.png" alt="cannot import name &#39;_imaging&#39; from &#39;PIL&#39;"></p>
<p>구글에 검색해보니 pillow 패키지의 compiled binaries 파일을 lambda가 처리하지 못해서 생기는 에러라고 합니다</p>
<p>복잡한 해결법을 찾았는데 그보다 더 쉽게 해결할 수 있어서 정리한다.
<a href="https://stackoverflow.com/questions/57197283/aws-lambda-cannot-import-name-imaging-from-pil#answer-62121096">복잡쓰한 해결법 보러가기!</a></p>
<h1 id="👍-해결">👍 해결</h1>
<blockquote>
<p>Don&#39;t reinvent the wheel. (바퀴를 재발명하지 마라)</p>
</blockquote>
<p>다른 사람이 만든 pillow 패키지가 포함된 layer를 추가 해주기만 하면 된다!!</p>
<h2 id="arn-layer">ARN layer</h2>
<p><a href="https://api.klayers.cloud/api/v2/p3.9/layers/latest/ap-northeast-2/html">https://api.klayers.cloud/api/v2/p3.9/layers/latest/ap-northeast-2/html</a> 에서 자기가 추가하고 싶은 패키지의 arn을 알아낸다.
(p3.9를 바꾸면 다른 버전의 파이썬도 확인할 수 있다.)</p>
<p><img src="https://velog.velcdn.com/images/silver_bell/post/9eb0ef31-eeda-47ad-b10b-04a543acc397/image.png" alt=""></p>
<p>지금은 pillow 패키지가 필요하니 <strong>arn:aws:lambda:ap-northeast-2:770693421928:layer:Klayers-p39-pillow:1</strong> 을 복사한다.</p>
<p>lambda 함수로 가서 맨 아래 Layers에 <strong>Add a layer</strong>를 누른다!
<img src="https://velog.velcdn.com/images/silver_bell/post/9d3ce213-6972-4c22-a100-5f4d5aff1265/image.png" alt=""></p>
<p>Specify an ARN을 누르고 아까 복사했던 arn을 붙여넣는다.</p>
<p><img src="https://velog.velcdn.com/images/silver_bell/post/21d128f9-9798-4bb4-aec0-fb7ab57bc9d1/image.png" alt=""></p>
<p>Add를 누른다. 끝 -</p>
<p><img src="https://velog.velcdn.com/images/silver_bell/post/66ec0565-965a-4cb7-b92a-1d959cd2794f/image.png" alt=""></p>
<h1 id="참고자료">참고자료</h1>
<p><a href="https://velog.io/@silver_bell/lambda-layer">lambda에 custom layer 적용하기</a>
<a href="https://github.com/keithrozario/Klayers">ARN of Python Packages as Lambda Layers</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS Lambda에 pymysql 설치하기 (package 설치하기)]]></title>
            <link>https://velog.io/@silver_bell/lambda-layer</link>
            <guid>https://velog.io/@silver_bell/lambda-layer</guid>
            <pubDate>Mon, 18 Jul 2022 13:13:19 GMT</pubDate>
            <description><![CDATA[<p>내 런타임은 <strong>python 3.9</strong>이지만 버전이 달라도, 사용하고싶은 패키지가 달라도 따라하면 안될 이유가 없다!</p>
<h1 id="개요">개요</h1>
<p>lambda 자체에 sql을 다루는 패키지들은 설치 되어있을 줄 알았지만 다음과 같은 에러를 마주했다.</p>
<p><img src="https://velog.velcdn.com/images/silver_bell/post/1b76178f-2617-446b-ad28-41472cd58c13/image.png" alt=""></p>
<p>패키지를 설치하고 싶은 경우 lambda layer을 이용하면 해결할 수 있다.</p>
<h1 id="lambda-layer">lambda layer</h1>
<p>AWS docs에 lambda layer에 대한 설명을 보면,</p>
<blockquote>
<p>Lambda layer은 Lambda 함수와 함께 사용할 수 있는 라이브러리 및 기타 종속성을 패키징하는 편리한 방법을 제공합니다. 계층을 사용하면 업로드된 배포 아카이브의 크기가 줄어들고 코드를 더 빠르게 배포할 수 있습니다.</p>
</blockquote>
<p>layer로 간단히 보면 2가지 기능을 할 수 있는데, 
첫번째는 pip로 설치해야하는 <strong>라이브러리를 lambda 함수에 추가</strong>하는 것과 
두번째는 <strong>여러 lambda 함수에서 공통으로 사용하는 함수를 패키징</strong>하는 기능이다.</p>
<p>layer를 적용하면 lambda 코드를 더 작게 만들 수 있고, 배포 시간이 단축된다.</p>
<h1 id="docker를-이용해-zip-파일-만들기">docker를 이용해 zip 파일 만들기</h1>
<p>AWS Lambda는 Amazon Linux에서 실행된다. 따라서 다른 OS에서 zip 파일을 만들면 패키지가 적용되지 않을 수 있다.</p>
<h2 id="ubuntu-실행">ubuntu 실행</h2>
<p>docker를 설치하고 cmd에 다음 명령어를 입력해 ubuntu 컨테이너를 실행한다.</p>
<pre><code>docker run -it ubuntu:20.04</code></pre><p><img src="https://velog.velcdn.com/images/silver_bell/post/3c523f7e-b305-45e2-939e-ec9700480e59/image.png" alt=""></p>
<p>cli로 진입하고 다음 명령어를 입력해 ubuntu 패키지를 업데이트한다.</p>
<pre><code>apt update</code></pre><p><img src="https://velog.velcdn.com/images/silver_bell/post/cc17bb16-c16c-4a48-b4ec-e5f1a6e36597/image.png" alt=""></p>
<h2 id="python-설치-전-설치">python 설치 전 설치</h2>
<p>파이썬 설치전, 파이썬 설치를 위한 설치를 한다</p>
<pre><code>apt install software-properties-common -y
add-apt-repository ppa:deadsnakes/ppa</code></pre><p>패키지 파일을 zip으로 압축하기 위한 zip 설치</p>
<pre><code>apt install zip -y</code></pre><h2 id="python-39-설치">python 3.9 설치</h2>
<p>lambda 런타임에 맞는 파이썬 버전을 설치해야한다!
pip도 같이 설치해준다.</p>
<pre><code>apt install python3.9 -y
apt install python3-pip -y</code></pre><h2 id="패키지-설치할-디렉토리-만들기">패키지 설치할 디렉토리 만들기</h2>
<p>아래 명령어를 입력하고 layer 디렉토리가 만들어졌는지 확인해보자</p>
<pre><code>mkdir -p layer/python/lib/python3.9/site-packages</code></pre><h2 id="pymysql-패키지-설치">pymysql 패키지 설치</h2>
<p>아래 명령어를 입력해서 pymysql를 설치한다. 저 부분만 바꾸면 다른 패키지를 설치할 수 있다!</p>
<pre><code>python3.9 -m pip install pymysql -t layer/python/lib/python3.9/site-packages/</code></pre><h2 id="zip파일로-만들기">zip파일로 만들기</h2>
<p>layer 디렉토리로 이동한 후,</p>
<pre><code>cd layer</code></pre><p>zip파일로 만들어 준다. 꼭 layer 디렉토리 안이여야 함!!</p>
<pre><code>zip -r mypackage.zip *</code></pre><p><img src="https://velog.velcdn.com/images/silver_bell/post/5a46153d-a72c-46dd-8148-9299478820df/image.png" alt=""></p>
<h1 id="layer에-적용">layer에 적용</h1>
<p>위의 순서대로 명령어를 따라치다보면 mypackage.zip 파일이 만들어졌을것이다. 
그 파일을 이제 lambda에 적용해보자!</p>
<h2 id="host로-zip파일-가져오기">host로 zip파일 가져오기</h2>
<p>ctrl+D를 눌러 ubuntu에서 빠져나오고 docker ps로 container id를 알아낸다.</p>
<pre><code>docker ps -a</code></pre><p><img src="https://velog.velcdn.com/images/silver_bell/post/58be9681-353f-4f8a-87d7-af2d396241b9/image.png" alt=""></p>
<p>위에서 알아낸 container id를 아래 13a9부분에 대입한다!
(비밀인데 대충 container id 앞 4~5자리만 입력해도 됨..!)</p>
<pre><code>docker cp 13a9:/layer/mypackage.zip .</code></pre><h2 id="새-layer-만들기">새 layer 만들기</h2>
<p>계층 - 계층 생성을 누른다</p>
<p><img src="https://velog.velcdn.com/images/silver_bell/post/c0c1a550-4aec-42cd-a2d4-a1f9917b287e/image.png" alt=""></p>
<p>업로드를 눌러 아까 복사한 mypackage.zip을 업로드하고 생성을 눌러준다.</p>
<p><img src="https://velog.velcdn.com/images/silver_bell/post/f14cb309-6ae7-4b51-adcb-3c70361fd7fa/image.png" alt=""></p>
<h2 id="lambda에-layer-추가하기">lambda에 layer 추가하기!</h2>
<p>아까 에러가 났었던 lambda 함수로 들어가서 코드 맨 아래에 Add a layer 버튼을 누른다</p>
<p><img src="https://velog.velcdn.com/images/silver_bell/post/6a6efd76-b486-4144-b445-0c00d4959673/image.png" alt=""></p>
<p>사용자 지정 계층을 선택하고 위에서 생성한 계층과 버전을 선택한뒤 추가를 누르면 끝!!!
(버전은 처음이면 1이 뜨고, 수정사항이 있을 때마다 1씩 올라간다.)
<img src="https://velog.velcdn.com/images/silver_bell/post/abe2d53c-f10e-4dd5-9278-3c695f767b5e/image.png" alt=""></p>
<h1 id="참고자료">참고자료</h1>
<p><a href="https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/configuration-layers.html">AWS Lambda docs</a>
<a href="https://www.geeksforgeeks.org/how-to-install-python-packages-for-aws-lambda-layers/">docker로 layer .zip파일 만드는 과정</a>
<a href="https://stackoverflow.com/questions/60824700/how-to-install-python3-9-on-linux-ubuntu-terminal">ubuntu에 python3.9 설치하기</a>
<a href="https://8iggy.tistory.com/67">layer 생성하기</a>
<a href="https://angelplayer.tistory.com/213">cryptograph 문제 해결</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[모바일에서의 소셜 로그인]]></title>
            <link>https://velog.io/@silver_bell/%EB%AA%A8%EB%B0%94%EC%9D%BC%EC%97%90%EC%84%9C%EC%9D%98-%EC%86%8C%EC%85%9C-%EB%A1%9C%EA%B7%B8%EC%9D%B8%EA%B3%BC-JWT</link>
            <guid>https://velog.io/@silver_bell/%EB%AA%A8%EB%B0%94%EC%9D%BC%EC%97%90%EC%84%9C%EC%9D%98-%EC%86%8C%EC%85%9C-%EB%A1%9C%EA%B7%B8%EC%9D%B8%EA%B3%BC-JWT</guid>
            <pubDate>Mon, 04 Jul 2022 06:14:53 GMT</pubDate>
            <description><![CDATA[<p>진행하는 프로젝트에서 클라이언트로 모바일(flutter)을 선택했고, 로그인 기능을 넣어야 했다. 
Kakao 소셜 로그인, Google 소셜 로그인을 지원할 예정이다.</p>
<h1 id="kakao-로그인">Kakao 로그인</h1>
<hr>
<h2 id="🥺-오해했던-점-🥺">🥺 오해했던 점 🥺</h2>
<h3 id="1-token의-사용법">1. token의 사용법</h3>
<p>Kakao에서 refresh token이랑 access token을 둘 다 주니까, client가 우리 서버의 api를 호출하려면 계속 카카오에 인가를 받아야 된다고 생각했다.</p>
<p>그게 아니라, kakao에서 로그인 한 것을 기반으로 우리 서버의 JWT을 생성해서 client로 전달해야하고, 
kakao token은 kakao 서버에서 사용자 정보를 받는 용도로 사용한다.</p>
<h3 id="2-모바일과-rest-api로-로그인-방법-차이">2. 모바일과 REST API로 로그인 방법 차이</h3>
<p>REST API의 방식은 우리 서버가 client와 kakao 인증서버 사이에서 redirect 해주고, 받은 token으로 유저 정보를 가져오는 방식이다.
(우리 서버가 자체적으로 유저 정보 가져오고 바로 DB에 저장)</p>
<p>그와 다르게 모바일에서는 앱 내에서 kakao 인증서버에 인가를 받고 유저 정보를 가져와서 우리 서버에 정보를 보내는 방식이다.
(모바일에서 자체적으로 유저 정보까지 다 가져오고 우리 서버로 보내기)</p>
<p><img src="https://velog.velcdn.com/images/silver_bell/post/964f3707-f2d4-471e-8183-57bb470ecb1f/image.png" alt=""></p>
<p>이 오해를 풀고난 뒤 docs의 그림을 보니까 왜 사용자 클라이언트와 서비스 서버 동시에 물려있는게 있는지 이해됐다.</p>
<p>모바일에서는 2개 물려있는 항목들은 사용자 클라이언트에서 진행되고, REST API 방식에서는 서비스 서버에서 진행된다.</p>
<h2 id="시퀀스-다이어그램">시퀀스 다이어그램</h2>
<p><img src="https://velog.velcdn.com/images/silver_bell/post/bfcaaec2-a806-4e45-acce-2a028227c5d4/image.png" alt=""></p>
<p>카카오 SDK에서 제공하는 loginWithKakaoTalk함수를 호출한다.</p>
<p>함수를 호출하면 SDK가 카카오톡을 실행하고, 앱 이용 동의를 받는 화면이 띄워진다.</p>
<p>동의를 하면 kakao 인증 서버에서 토큰이 넘어오고, 이 토큰은 TokenManager를 통해 내부적으로 관리된다.</p>
<p>로그인 한 후, kakao 인증 서버에 사용자 정보를 요청해서 받은 정보(user id, 이름 등)를 우리 서버로 보내 신규가입자면 회원가입처리, 아니면 JWT토큰을 발급한다.</p>
<h1 id="google-로그인">Google 로그인</h1>
<hr>
<p>기본적인건 Kakao와 다를바 없다. 
하지만 로그인이 완료한 뒤, 유저 정보를 서버로 보내는 부분이 약간 다르다.</p>
<blockquote>
<p>백엔드 서버와 통신하는 앱 또는 사이트에서 Google 로그인을 사용하는 경우 서버에서 현재 로그인한 사용자를 식별해야 할 수 있습니다. 
안전하게 하려면 사용자가 성공적으로 로그인한 후 HTTPS를 사용하여 <strong>사용자의 ID 토큰을 서버로</strong> 보냅니다. 
그런 다음 서버에서 ID 토큰의 무결성을 확인하고 <strong>토큰에 포함된 사용자 정보</strong>를 사용하여 세션을 설정하거나 새 계정을 만듭니다.</p>
</blockquote>
<p>공식 문서에 의하면 모바일 앱에서 바로 user ID를 보내는 방법은 보안에 취약할수도 있기에, token을 보내고 백엔드에서 검증하는 절차가 필요하다고 언급되어있다.</p>
<h2 id="시퀀스-다이어그램-1">시퀀스 다이어그램</h2>
<p><img src="https://velog.velcdn.com/images/silver_bell/post/4ff48935-8e72-4261-b490-7a8688ba7d05/image.png" alt=""></p>
<p>사용자가 구글 계정으로 인증을 하고 인증 서버에서 토큰을 주는 것까지는 동일하다.</p>
<p>유저의 정보를 누가 요청하는지가 다른데, 카카오는 클라이언트에서 직접 요청하고, 구글에서는 서버가 요청한다.</p>
<p>유저의 정보를 인증 서버로 부터 받아와서, user ID 값을 DB에서 찾아보고 있다면 로그인이 없다면 회원가입이 진행된다.</p>
<p>모두 완료된 후, 서버는 JWT를 발행해 client로 보낸다.</p>
<h1 id="참고자료">참고자료</h1>
<p><a href="https://okky.kr/article/1054459">refresh token 만료 기간</a>
<a href="https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#before-you-begin">kakao developers</a>
<a href="https://velog.io/@josworks27/%ED%9C%B4%EB%8C%80%ED%8F%B0-%EC%9D%B8%EC%A6%9D-%EB%A1%9C%EC%A7%81-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0">SMS 인증 로직</a>
<a href="https://developers.google.com/identity/sign-in/android/backend-auth">google developers</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[docker로 개발환경 세팅하기]]></title>
            <link>https://velog.io/@silver_bell/docker%EB%A1%9C-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@silver_bell/docker%EB%A1%9C-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 24 Jun 2022 13:47:01 GMT</pubDate>
            <description><![CDATA[<p>본격적으로 개발을 하기 전, 간단한 <strong>chat 기능 백엔드 목업 서버</strong>를 구성하기 위해 <strong>docker</strong>를 이용했다.</p>
<h1 id="개요">개요</h1>
<p><strong>django</strong>의 <strong>channels</strong>로 백엔드를 구성하고 <strong>redis</strong>를 <strong>메세지 브로커</strong>로 이용하여 개발용 목업서버를 구성하기로 생각했다.</p>
<p>각자의 개발환경에서 간단히 서버를 실행할 수 있어야 해서 docker를 이용하기로 했다.</p>
<h1 id="백엔드-구성">백엔드 구성</h1>
<p>django channels의 docs에 제공되어 있는 채팅 튜토리얼을 따라 진행했다. 
-&gt; <a href="https://channels.readthedocs.io/en/latest/tutorial/part_1.html">채팅 서버 튜토리얼 바로가기</a></p>
<p>완성된 코드는 깃허브에 올려놓았다. 
-&gt; <a href="https://github.com/enjoy301/django-chat-mock">채팅 서버 코드 깃허브 주소</a></p>
<p>이 글의 목적이 ❌django 코드를 리뷰하는 것❌이 아니기 때문에 링크로 대체한다!</p>
<h1 id="dockerfile-생성">Dockerfile 생성</h1>
<p>Django 프로젝트의 상위 디렉토리에 <strong>Dockerfile</strong>을 <strong>생성</strong>한다.</p>
<p>현재의 디렉토리 구조이다.</p>
<pre><code>django-chat-mock/
    Dockerfile
    djangoProject/
        manage.py
        ...</code></pre><p><strong>Dockerfile</strong>을 다음과 같이 작성한다.</p>
<pre><code>FROM python:3.8.9
RUN pip3 install django channels channels_redis
WORKDIR /usr/src/app
COPY . .
WORKDIR ./djangoProject
CMD [&quot;python3&quot;, &quot;manage.py&quot;, &quot;runserver&quot;, &quot;0.0.0.0:8000&quot;]
EXPOSE 8000</code></pre><h2 id="문법">문법</h2>
<h3 id="from">FROM</h3>
<p><strong>사용할 이미지</strong>를 입력한다. 우린 python 3.8.9 버전을 이용한다.</p>
<h3 id="run">RUN</h3>
<p>이미지가 올라가고 <strong>실행할 명령어</strong>를 입력한다. pip로 django, channels, channels_redis를 install 해준다.</p>
<h3 id="workdir">WORKDIR</h3>
<p>작업을 진행할 <strong>디렉토리</strong>를 지정한다. 없으면 만들어 줌!</p>
<h3 id="copy">COPY</h3>
<p>빌드를 진행하기전, <strong>호스트의 디렉토리</strong>를 <strong>복사</strong>한다. &quot;COPY . .&quot;을 통해 작성해놓은 django 프로젝트를 복사한다.</p>
<h3 id="cmd">CMD</h3>
<p>컨테이너를 <strong>시작</strong>할 때 <strong>실행할 명령어</strong>를 입력한다. &quot;python3 manage.py runserver 0.0.0.0.8000&quot; 명령어로 django 서버를 실행한다.</p>
<h3 id="expose">EXPOSE</h3>
<p>외부에 노출할 포트를 지정한다. 8000번 포트를 노출시킬 것이다.</p>
<h1 id="dockerfile-빌드-배포">Dockerfile 빌드, 배포</h1>
<p>먼저 다음의 명령어를 입력하여 <strong>dockerfile</strong>을 <strong>빌드</strong>한다.</p>
<pre><code>docker build --tag (docker hub 아이디)/(이미지 이름):(버전)

예시)
docker build --tag eunjong147/backend-chat-mock:1.0.0</code></pre><p><code>docker login</code> 로 도커 허브에 로그인해 준 다음,</p>
<p>아래의 명령어를 입력하여 <strong>image</strong>를 <strong>업로드</strong>한다.</p>
<pre><code>docker push (docker hub 아이디)/(이미지 이름):(버전)

예시)
docker push eunjong147/backend-chat-mock:1.0.0</code></pre><h1 id="docker-compose">docker-compose</h1>
<p>redis와 백엔드 서버, <strong>2개의 이미지</strong>를 <strong>사용</strong>해야하기 때문에 docker-compose를 이용한다.</p>
<p>docker-compose.yml 파일을 생성하고 다음과 같이 yml파일을 작성한다.</p>
<pre><code>version: &#39;3&#39;
services:
    backend:
        image: eunjong147/backend-chat-mock:1.0.0
        ports:
            - &quot;8000:8000&quot;
        depends_on:
            - redis
    redis:
        image: redis:5
        ports:
            - &quot;6379:6379&quot;</code></pre><h2 id="문법-1">문법</h2>
<h3 id="version">version</h3>
<p>도커 컴포즈 파일의 <strong>버전</strong>을 명시해준다.</p>
<h3 id="services">services</h3>
<p>컨테이너를 실행하기 위한 단위이다. backend 부분과 redis 부분으로 나뉜다.</p>
<h3 id="image">image</h3>
<p><strong>사용할 이미지</strong>를 명시해준다. backend service에서는 위에서 배포한 backend-chat-mock 이미지를 사용하고, redis service에서는 redis 5버전을 사용한다.</p>
<h3 id="ports">ports</h3>
<p><strong>포트포워딩</strong>을 지정한다. &lt;호스트의 포트&gt;:&lt;컨테이너의 포트&gt;로 바인딩한다.</p>
<h3 id="depends_on">depends_on</h3>
<p><strong>실행순서</strong>를 보장한다. backend service에서 redis service에 depends_on을 지정하면, redis 컨테이너가 먼저 실행된다.</p>
<h1 id="완료">완료!</h1>
<p><code>docker-compose up -d</code> 명령어를 통해 백그라운드로 <strong>실행</strong>하고,
<code>docker-compose down</code> 명령어를 통해 docker 컨테이너를 <strong>일시중지</strong>한다.</p>
<p>이제 docker-compose.yml 파일만 공유해주면 도커가 설치된 아무나 같은 환경에서 chat server를 실행할 수 있다.</p>
<h1 id="참고자료">참고자료</h1>
<p><a href="https://docs.docker.com/compose/compose-file/compose-file-v3/">docker docs</a>
<a href="https://heendoong.tistory.com/6">도커 파일 배포</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[대박 날 창업 아이템 선정 [SWM살아남기 EP.0]]]></title>
            <link>https://velog.io/@silver_bell/SWM%EC%82%B4%EC%95%84%EB%82%A8%EA%B8%B0-EP.0</link>
            <guid>https://velog.io/@silver_bell/SWM%EC%82%B4%EC%95%84%EB%82%A8%EA%B8%B0-EP.0</guid>
            <pubDate>Tue, 21 Jun 2022 12:20:27 GMT</pubDate>
            <description><![CDATA[<h1 id="들어가며">들어가며</h1>
<hr>
<p>6개월 간 진행하는 소프트웨어 마에스트로 과정에 합격하여 이 과정동안 진행할 아이템을 기획했다.</p>
<blockquote>
<p>소프트웨어 마에스트로란 최우수 SW 인재를 발굴하여, 체계적이고 파격적인 지원을 통해 SW 산업 발전에 기여하기 위해 기획된 정부 지원 사업.</p>
</blockquote>
<p>처음 합격하고 나도 이제 개발의 신이 되겠구나 했지만 이 정부 사업은 개발자를 기르기보단 <strong>창업자</strong>를 기르는 게 목적인 것 같다.</p>
<p>사업성을 고려하며 프로젝트 주제를 정한적이 단 한번도 없기 때문에 아이템 선정에만 약 1개월이 소모되었으며, 이 시간이 소중한 경험이라 생각하여 회고 형식으로 SWM 과정을 기록할 예정이다.</p>
<p><strong>3명에서 팀</strong>으로 진행되기 때문에 혼자 방구석에서 코딩할 때보다 더 많은 <strong>시행착오</strong>를 겪었다.</p>
<h1 id="아이템-선정하기">아이템 선정하기</h1>
<hr>
<p>위에 언급했듯, <strong>사업성을 고려하며 프로젝트 주제를 정한적이 단 한번도 없거니와 사업이 먼지도 잘 모르고 난 사업할 돈이 없다.</strong> (사업 대박나서 떼부자되고 싶긴 함.)</p>
<p>따라서 아이템을 선정하는 과정에서 여러 실패를 경험했다.</p>
<p>아래는 아이템을 선정했던 과정들이다.</p>
<h2 id="1-하고-싶은-아이디어-무작정-뱉고-고르기">1. 하고 싶은 아이디어 무작정 뱉고 고르기</h2>
<hr>
<p>나와 다른 팀원 중 한 분이 <strong>&quot;생활 속 필요한 소프트웨어 기록해놓기&quot;</strong>라는 비슷한 습관을 가지고 있었다. </p>
<blockquote>
<p>그럼 걍 그 중에 재밌어 보이는 거 고르자~!</p>
</blockquote>
<p>라는 잘못된 생각으로 소중한 시간 2주를 날렸다.</p>
<p>이때 선정한 아이템은 <strong>비디자이너가 쉽게 옷을 디자인할 수 있도록 AI를 이용해 돕고, 그 옷을 팔 수 있는 플랫폼</strong>이였다.
옷을 디자인해 파는 사람은 <strong>쉽고 빠르게 디자인</strong>해 수수료를 벌어가서 좋고,
옷을 사는 사람은 <strong>다양한 개성있는 옷</strong>을 살 수 있겠다고 생각했다.</p>
<p>아래는 우리의 팀이 적극적임을 어필하기 위해 만들었던 <strong>프로토타입</strong>의 랜딩페이지이다.
<img src="https://velog.velcdn.com/images/silver_bell/post/7c63e5a4-22a2-43fe-bd6d-334eb50edcbe/image.png" alt="홈페이지 프로토타입"></p>
<p>선정한 이유는</p>
<ol>
<li>옷에 관심있는 팀원이 2명이나 되었고,</li>
<li>옷 공장들 알아보고 하는 과정이 재밌어 보였고,</li>
<li>매력적이라고 생각했었다.</li>
</ol>
<p>멘토링을 여럿 받아보고 얻은 <strong>피드백</strong>들은 다음과 같다.</p>
<ol>
<li>이 아이템은 잘쳐줘야 &quot;있으면 좋다&quot; 수준</li>
<li>개성있는 옷인데 프린팅 반팔? 논리가 부족 + pain point 부족</li>
<li>마플이라는 유사 서비스 있는데 이 서비스만의 아이덴티티 부족</li>
</ol>
<p><strong><em>팩폭에 뚜두려 맞고 정신을 못차린채 아이디어를 피봇했다.</em></strong></p>
<h2 id="2-고객의-pain-point-중심으로-아이디어-내기">2. 고객의 pain point 중심으로 아이디어 내기</h2>
<hr>
<p>2주 정도 지난 시점에 알게 된 것은 <strong>고객, 고객의 pain point, 시장의 크기</strong>가 가장 중요하다는 것이다.</p>
<p>예비과정에서 들었던 디자인씽킹 프로그램을 토대로 
<strong>고객을 선정하고, 
고객의 pain point가 얼마나 되는지 생각해보고, 
어떻게 해결해 줄 수 있을지 생각해보았다.</strong></p>
<p><img src="https://velog.velcdn.com/images/silver_bell/post/7a1c3bcc-bb1e-4542-8903-c04c9898b35f/image.png" alt=""></p>
<p>고객들을 생각해보고 고객들의 <strong>고통의 빈도와 정도</strong>에 따라 좌표에 배치해보았다.</p>
<p>5~6시간을 소모하며 열띤 아이디어 발산을 했고 그 과정에서 굉장히 지쳐서 (그 당시엔 몰랐음), <strong><em>잘못된 아이디어를 골랐다</em></strong>.</p>
<blockquote>
<p>거닐어 다니는 것을 좋아하는 고객들을 위해 위치 기반으로 지도에 안개가 걷히는 걷기 보조 앱을 만들자!!</p>
</blockquote>
<p>이 날의 고된 토론에 지쳤었고, 아이디어를 선정하는 것 자체에 대해 지쳐있었다. 그래서 처음 나온 <strong>게임성</strong> 프로그램에 다들 열광했다.
(이때부터 <strong>&quot;회의는 최대 2시간까지만 연속으로 진행하고, 쉬는 시간을 가져야 한다.&quot;</strong> 라는 그라운드 룰을 도입했다.)</p>
<p><em><strong>다음날 정신을 차리고 다시 피봇했다.</strong></em></p>
<h2 id="3-갑자기-떠올리기-">3. 갑자기 떠올리기 (?)</h2>
<hr>
<p>절망에 빠져있는채로 맥도날드에서 에그 불고기 버거를 먹으며 햄버거 사진을 가족 단톡방에 보냈다.</p>
<p>그때 문득 든 생각!</p>
<blockquote>
<p>내가 보낸 이 사진은 어디로 가는거지?? 
우리 가족 사진들은 다 어디있지??</p>
</blockquote>
<p>그래서 <strong>가족의 추억을 기록하기 위한 어플</strong>을 만들기로 했다.</p>
<p>생각해본 이 아이템의 장점은 <strong>내가 곧 고객이며, 우리의 대부분은 가족이 있다. <del>(가족 한명만 원해도 다운로드 수가 약 4배이다..)</del></strong></p>
<p>하지만 아직 아이디어를 검증 해봐야하고, 구체화 해야하고, 기획서를 작성해야하며, 기획 발표 ppt를 만들어야된다는 사실에 눈가에 눈물이 흘렀다.</p>
<h1 id="멘토링-정리">멘토링 정리</h1>
<hr>
<p><strong>시장의 크기</strong>가 매우 중요함.
좋지 않은 제품이라도 시장이 크면 성공할 확률이 높다. <del>ex) 빗썸</del>
시장의 크기가 크면 많은 아이디어들이 있지만, 기피하지마!</p>
<p>많은 사람의 심각한 문제를 해결해 줄 제품이 최고지만 찾기 힘드니 <strong>많은 사람의 가벼운 문제</strong> or <strong>적은 사람들의 심각한 문제</strong>를 해결할 제품을 찾아야 함.</p>
<p>경쟁 제품에 비해 10배 좋게 만들어야함.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[생산성을 높여주는 IntelliJ  단축키 정리 (Mac)]]></title>
            <link>https://velog.io/@silver_bell/IntelliJ-%EC%9E%90%EC%A3%BC-%EC%93%B0%EB%8A%94-%EB%A7%A5-%EB%8B%A8%EC%B6%95%ED%82%A4-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@silver_bell/IntelliJ-%EC%9E%90%EC%A3%BC-%EC%93%B0%EB%8A%94-%EB%A7%A5-%EB%8B%A8%EC%B6%95%ED%82%A4-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Tue, 22 Mar 2022 03:41:13 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/silver_bell/post/75d42a61-b166-47f1-890e-7690b3de023b/IntelliJ_%E1%84%83%E1%85%A1%E1%86%AB%E1%84%8E%E1%85%AE%E1%86%A8%E1%84%8F%E1%85%B5_%E1%84%8C%E1%85%A5%E1%86%BC%E1%84%85%E1%85%B5.png" alt=""></p>
<p>김영한님의 스프링 강의를 보며 자주 쓰시는 단축키들을 정리해본다.</p>
<hr>
<h2 id="단축키">단축키</h2>
<ul>
<li><p>static import
⌥ + ↵</p>
</li>
<li><p>return 값 자동
⌥ + ⌘ + V</p>
</li>
<li><p>테스트 코드 생성
⌘ + ⇧ + T</p>
</li>
<li><p>해당 객체가 선언된 파일로 이동
⌘ + B</p>
</li>
<li><p>이전에 실행했던 파일 재실행
^ + R</p>
</li>
<li><p>생성자, 게터와 세터 자동 생성
⌘ + N</p>
</li>
<li><p>한 단어 선택
⌥ + ↑</p>
</li>
</ul>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[개발 관련 영어단어 선택 방법!]]></title>
            <link>https://velog.io/@silver_bell/%EA%B0%9C%EB%B0%9C-%EA%B4%80%EB%A0%A8-%EC%98%81%EC%96%B4%EB%8B%A8%EC%96%B4-%EC%84%A0%ED%83%9D-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@silver_bell/%EA%B0%9C%EB%B0%9C-%EA%B4%80%EB%A0%A8-%EC%98%81%EC%96%B4%EB%8B%A8%EC%96%B4-%EC%84%A0%ED%83%9D-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Wed, 09 Mar 2022 07:43:39 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>커밋 메세지 작성, 네이밍시 헷갈리는 영어단어를 정리해보았다.</p>
</blockquote>
<hr>
<h1 id="반대말-단어">반대말 단어</h1>
<blockquote>
<p>show의 반대말로 invisible을 쓰면 안된다. show의 반대말은 hide이다.</p>
</blockquote>
<p>show - hide
visible - invisible
under - over
or under - and over
import - export</p>
<hr>
<h1 id="비슷한-단어">비슷한 단어</h1>
<h3 id="중단의-의미">중단의 의미</h3>
<ul>
<li><strong><em>stop</em></strong> - 잠시 중단, 언제든 재시작 가능</li>
<li><strong><em>end</em></strong> - 완전히 중단, 재시작 가능성 전혀 없음</li>
<li><strong><em>finish</em></strong> - 재시작 고려할 필요도 없음</li>
<li><strong><em>pause</em></strong> - 일시 중단, 금방이라도 다시 재개</li>
<li><strong><em>suspend</em></strong> - 다음 단계의 시작 중단</li>
<li><strong><em>hold</em></strong> - 어떤한 의도로 중단중</li>
</ul>
<pre><code>// 사용자 등록 잠시 중단
// 다시 재개시 restartUserRegister 사용
stopUserRegister();

// 사용자 등록 중단
// 새롭게 시작하려면 beginUserRegister 사용
endUserRegister();

// 완전히 중단, 다시 재개시 에러
finishUserRegister();</code></pre><h3 id="get류">get류</h3>
<ul>
<li><strong><em>get</em></strong> - 일반적으로 가져올 대</li>
<li><strong><em>return</em></strong> - 안 씀</li>
<li><strong><em>retrieve</em></strong> - 검색해서 가져올 때</li>
<li><strong><em>fetch</em></strong> - 현재 포인터의 다음 주소의 값을 가져올 때</li>
</ul>
<h3 id="set류">set류</h3>
<ul>
<li><strong><em>set</em></strong> - 일반적인 값 변경, 값 설정시</li>
<li><strong><em>init</em></strong> - 초기화 설정</li>
<li><strong><em>register</em></strong> - 정해진 틀에 값 넣기</li>
<li><strong><em>create</em></strong> - 틀이 없을 때 틀 만들기</li>
</ul>
<h3 id="change류">change류</h3>
<ul>
<li><strong><em>change</em></strong> - 내용 단순 변경</li>
<li><strong><em>modify</em></strong> - 잘못된 것 바로잡기</li>
<li><strong><em>revise</em></strong> - 기존에 없던 것이 덧붙여져 달라졌을 때</li>
</ul>
<h3 id="parameter류">parameter류</h3>
<blockquote>
<p>Parameters are initialized to the values of the arguments supplied.</p>
</blockquote>
<ul>
<li><strong><em>parameter</em></strong> - 함수에 정의한 변수</li>
<li><strong><em>argument</em></strong> - 함수 호출 시 전달되는 값</li>
</ul>
<ul>
<li><strong><em>attribute</em></strong> - html 태그 안 속성</li>
<li><strong><em>property</em></strong> - html DOM에서 부르는 태그 안 속성</li>
</ul>
<hr>
<blockquote>
<p>정확한 단어를 쓰는 것도 중요하지만 일관성, 개연성이 훨씬 중요하다.</p>
</blockquote>
<h5 id="출처">출처</h5>
<h6 id="개발자의-글쓰기-김철수-지음">개발자의 글쓰기 (김철수 지음)</h6>
<h6 id="httpsdevelopermozillaorgen-usdocsglossaryparameter"><a href="https://developer.mozilla.org/en-US/docs/Glossary/Parameter">https://developer.mozilla.org/en-US/docs/Glossary/Parameter</a></h6>
]]></description>
        </item>
        <item>
            <title><![CDATA[Mysql user 비밀번호 변경]]></title>
            <link>https://velog.io/@silver_bell/Mysql-root-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EB%B3%80%EA%B2%BD</link>
            <guid>https://velog.io/@silver_bell/Mysql-root-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EB%B3%80%EA%B2%BD</guid>
            <pubDate>Sat, 15 Jan 2022 07:37:27 GMT</pubDate>
            <description><![CDATA[<p>다음은 mysql 버전 <strong>8.0 이상</strong>에서 user 비밀번호를 변경하는 방법이다.</p>
<p><strong>단순 비밀번호 변경 시</strong> 바로 <strong>4번</strong>부터 진행하면 된다.</p>
<h1 id="1-mysql-종료">1. mysql 종료</h1>
<pre><code>mysql.server stop</code></pre><h1 id="2-안전모드로-mysql-실행">2. 안전모드로 mysql 실행</h1>
<pre><code>/usr/local/opt/mysql/bin/mysqld_safe --skip-grant-tables &amp;</code></pre><h1 id="3-비밀번호-초기화">3. 비밀번호 초기화</h1>
<p>새 터미널을 열어준 뒤 다음 명령어를 입력한다.</p>
<pre><code># 터미널
mysql -u root</code></pre><pre><code># mysql 콘솔
use mysql;
UPDATE User SET authentication_string=null WHERE User=&#39;root&#39;;
exit;</code></pre><h1 id="4-새-비밀번호-입력">4. 새 비밀번호 입력</h1>
<p>2번의 터미널은 종료하고 다음 명령어를 입력한다.</p>
<pre><code># 단순 비밀번호 변경 시에는 뒤에 p옵션을 붙인다!
mysql -u root</code></pre><pre><code># mysql 콘솔
ALTER User &#39;root&#39;@&#39;localhost&#39; IDENTIFIED WITH caching_sha2_password BY &#39;새 비밀번호&#39;;
flush privileges;</code></pre><p><strong>암호화된 비밀번호</strong>가 db에 저장되어야 정상적으로 동작한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS EC2에 장고 프로젝트 설치하기 (for mac)]]></title>
            <link>https://velog.io/@silver_bell/AWS-EC2%EC%97%90-%EC%9E%A5%EA%B3%A0-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@silver_bell/AWS-EC2%EC%97%90-%EC%9E%A5%EA%B3%A0-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 14 Jan 2022 02:10:12 GMT</pubDate>
            <description><![CDATA[<p>지난 글에서 AWS VPC, EC2, Route53을 세팅했다. 이번 글에서는 지난 글에 이어 EC2에 장고 프로젝트를 설치해보자.</p>
<p>대략적으로 python 관련 라이브러리들을 설치하고, github에서 리포지토리를 클론하고, 서버를 열어서 접속하는 과정을 거친다.</p>
<h1 id="ec2-인스턴스에-접속하기">EC2 인스턴스에 접속하기</h1>
<p><code>ssh -i {내 프라이빗 키}.pem ubuntu@{EC2 인스턴스 퍼블릭 IPv4 DNS주소}</code></p>
<blockquote>
<p>UNPROTECTED PRIVATE KEY FILE! 에러시 <a href="https://velog.io/@silver_bell/AWS-EC2%EC%97%90-%EC%9E%A5%EA%B3%A0-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0">이전 글</a> 참고</p>
</blockquote>
<h1 id="git-python-설치-확인">git, python 설치 확인</h1>
<pre><code>git --version

python3 --version</code></pre><h1 id="pip-django-설치">pip, django 설치</h1>
<blockquote>
<p>제발 개발자면 리눅스에서 뭐 설치하기전에 <code>sudo apt update</code> 칩시다!!</p>
</blockquote>
<pre><code>sudo apt install python3-pip -y

sudo apt install python3-django -y</code></pre><p><strong>y 옵션</strong>은 설치시 나타나는 모든 물음에 <strong>동의</strong>한다는 뜻입니다.</p>
<h1 id="clone-repository">clone repository</h1>
<h3 id="ssh-key-생성-등록">ssh key 생성, 등록</h3>
<pre><code>cd ~/.ssh/
ssh-keygen -t rsa -b 4096 -C &#39;github e-mail 주소&#39;</code></pre><h3 id="ssh-agent-설정">ssh-agent 설정</h3>
<pre><code>eval $(ssh-agent -s)</code></pre><p>ssh-agent가 개인키의 비밀번호를 암호화 해 기억해두어 사용자가 처음 한 번만 입력하면 까먹어도 되게 함!</p>
<h3 id="개인-key-파일-등록">개인 key 파일 등록</h3>
<pre><code>ssh-add ~/.ssh/{key이름}</code></pre><blockquote>
<p>확장자 빼고 key 이름만 적으면 댐</p>
</blockquote>
<h3 id="github에-key-등록">github에 key 등록</h3>
<pre><code>cat ~/.ssh/{key이름}.pub</code></pre><p>위의 명령어를 실행한 결과를 전체 복사해서 아래의 경로에 붙여넣기 하면 됨</p>
<p>** 깃허브 -&gt; Settings -&gt; SSH and GPG keys -&gt; New SSH key **
<img src="https://images.velog.io/images/silver_bell/post/7418e0b6-0bc4-43e7-b1f9-ed7e45f9ca14/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-17%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.57.07.png" alt=""></p>
<h3 id="git-clone">git clone</h3>
<blockquote>
<p>클론할 리포지토리에서 <strong>SSH탭에서 주소 확인</strong> and <strong>Clone</strong></p>
</blockquote>
<pre><code>git clone {SSH 주소}</code></pre><p><img src="https://images.velog.io/images/silver_bell/post/5efbc092-5c98-47d4-9dfb-06aeb4268f79/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-17%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.01.00.png" alt=""></p>
<h1 id="django-세팅">django 세팅</h1>
<h3 id="가상환경-설정">가상환경 설정</h3>
<pre><code># python 가상환경 설치
sudo apt install python3.8-venv

# 가상환경 생성
python3 -m venv venv

# 가상환경 활성화
source ./venv/bin/activate</code></pre><h3 id="requirements-설치">requirements 설치</h3>
<pre><code>pip install -r requirements.txt</code></pre><h1 id="django-서버-실행">django 서버 실행</h1>
<pre><code>python manage.py runserver 0:8000</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Vue CLI로 뷰 시작하기]]></title>
            <link>https://velog.io/@silver_bell/Vue-CLI%EB%A1%9C-%EB%B7%B0-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@silver_bell/Vue-CLI%EB%A1%9C-%EB%B7%B0-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 11 Jan 2022 13:10:12 GMT</pubDate>
            <description><![CDATA[<h1 id="vue-cli란">Vue CLI란?</h1>
<p><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue">vue github</a></p>
<blockquote>
<p>Vue CLI is a full system for rapid Vue.js development</p>
</blockquote>
<blockquote>
<p>It ensures the various build tools work smoothly together with sensible defaults so you can focus on writing your app instead of spending days wrangling with configurations. 
At the same time, it still offers the flexibility to tweak the config of each tool without the need for ejecting.</p>
</blockquote>
<p>vue 프로젝트의 개발환경 설정시 개발자의 고민을 덜게 해주는 고마운 친구</p>
<hr>
<h1 id="vuejs-개발환경-설정">Vue.js 개발환경 설정</h1>
<h2 id="1-vue-cli-설치">1. Vue CLI 설치</h2>
<pre><code># npm 설치
npm install -g @vue/cli

# yarn 설치
yarn global add @vue/cli</code></pre><h2 id="2-vue-프로젝트-생성">2. Vue 프로젝트 생성</h2>
<pre><code>vue create (프로젝트 이름)</code></pre><blockquote>
<p>위의 명령어 입력시 아래의 화면이 뜬다. <br/></p>
</blockquote>
<ol>
<li>Vue2 버전의 기본 세팅</li>
<li>Vue3 버전의 기본 세팅</li>
<li>사용자 입맛대로 <br/>
세 개중 하나를 선택할 수 있다.</li>
</ol>
<p align="center">
<img src="https://images.velog.io/images/silver_bell/post/36d723a7-6f5a-445c-812a-21bd94f83b79/image.png" width="700"></p>

<h2 id="3-options-선택">3. Options 선택</h2>
<p>기본 babel과 eslint를 사용하는 선택지인 1번 2번이 빠르긴하지만, 3번 선택지가 더욱 구체적인 개발환경 설정이 가능하다. 
<img src="https://images.velog.io/images/silver_bell/post/811797ba-2567-464e-bcc8-5e3703c60639/image.png" height="200" width="500"></p>
<p>key arrow와 space로 선택하고 enter키를 눌러 다음으로 넘어간다.</p>
<blockquote>
<p>*<em>Choose Vue version *</em>
Vue 버전 선택 옵션 ( 2 or 3 )</p>
</blockquote>
<blockquote>
<p>*<em>Babel *</em>
Vue 코드를 javascript로 바꿔주는 컴파일러</p>
</blockquote>
<blockquote>
<p><strong>TypeScript</strong>
확장된 javascript, 정적 타입 언어 사용</p>
</blockquote>
<blockquote>
<p><strong>PWA Support</strong>
모바일 웹사이트에서 네이티브 앱과 같은 동작을 가능하게 하는 기술</p>
</blockquote>
<blockquote>
<p><strong>Router</strong>
SPA인 Vue는 Router를 설치해야지 주소의 이동이 가능하다</p>
</blockquote>
<blockquote>
<p><strong>Vuex</strong>
vue용 상태관리 라이브러리</p>
</blockquote>
<blockquote>
<p><strong>CSS Pre-processors</strong>
확장된 css (scss)</p>
</blockquote>
<blockquote>
<p><strong>Linter / Formatter</strong>
코딩 컨벤션을 엄격하게 지키게 해주는 도구</p>
</blockquote>
<blockquote>
<p><strong>Unit Testing</strong>
간단한 unit testing을 도와준다</p>
</blockquote>
<blockquote>
<p><strong>E2E Testing</strong>
종단간 testing을 도와준다</p>
</blockquote>
<h2 id="4-개발환경-세팅-완료">4. 개발환경 세팅 완료!!</h2>
<p align="center">
<img src="https://images.velog.io/images/silver_bell/post/69e21538-626d-49b2-9197-2eba26c3b0aa/image.png" width="700" ></p>

<p>take a while 후 환경 세팅이 끝난다 😎</p>
<h2 id="5-vue-실행">5. vue 실행</h2>
<p><code>cd my-project</code> </p>
<p>명령어로 디렉토리 이동 후</p>
<p><code>npm run serve</code> </p>
<p>명령어로 서버 실행해보면 끝!
<img src="https://images.velog.io/images/silver_bell/post/612b9577-486c-45fe-be8f-af9d70b4996b/image.png" height="30%" width="500"></p>
<h1 id="출처">출처</h1>
<blockquote>
<p><a href="https://cli.vuejs.org/guide/creating-a-project.html#vue-create">vue cli guide</a></p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>