<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>DevMinGeonPark (MinGeonPark)</title><link>http://blex.me/@DevMinGeonPark</link><description>DevMinGeonPark's rss</description><atom:link href="http://blex.me/rss/@DevMinGeonPark" rel="self"/><language>ko</language><lastBuildDate>Wed, 17 Nov 2021 15:32:24 +0900</lastBuildDate><image><url>/resources/media/images/avatar/5f/DevMinGeonPark/oph7.png</url><title>DevMinGeonPark (MinGeonPark)</title><link>http://blex.me/@DevMinGeonPark</link></image><item><title>Jetbrains IDE 학생 라이센스 받기</title><link>http://blex.me/@DevMinGeonPark/jetbrains-ide-%ED%95%99%EC%83%9D-%EB%9D%BC%EC%9D%B4%EC%84%BC%EC%8A%A4-%EB%B0%9B%EA%B8%B0</link><description>&lt;p&gt;아직 대학생인 분들이 학생인증을 통해 공짜 라이센스를 받는 방법에 대해 알려드리겠습니다!&lt;/p&gt;
&lt;p&gt;저는 IntelliJ가 필요해서 IntelliJ로 설명드리겠습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;먼저 IntelliJ를 다운받습니다.&lt;br&gt;
&lt;a href="https://www.jetbrains.com/ko-kr/idea/download/#section=mac"&gt;https://www.jetbrains.com/ko-kr/idea/download/#section=mac&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;저는 Mac에서 M1으로 다운받지만 여러분에 맞는 운영체제로 다운받으시면됩니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/17//2021_11_17_15_9O0YhApVh5gM7yFkXb4v.jpg" src="/resources/media/images/content/2021/11/17//2021_11_17_15_9O0YhApVh5gM7yFkXb4v.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;설치를 진행하시면됩니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/17//2021_11_17_15_c23W9c690iMOgNJxDoHA.jpg" src="/resources/media/images/content/2021/11/17//2021_11_17_15_c23W9c690iMOgNJxDoHA.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;이제 실행 시켜놓고 라이센스를 받아야됩니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;아래 주소로 진입합니다.&lt;br&gt;
&lt;a href="https://www.jetbrains.com/ko-kr/community/education/#students"&gt;https://www.jetbrains.com/ko-kr/community/education/#students&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/17//2021_11_17_15_9om0qGgVxRISVlpDdAbY.jpg" src="/resources/media/images/content/2021/11/17//2021_11_17_15_9om0qGgVxRISVlpDdAbY.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;신청하기를 누르면 아래와 같은 폼이 나오는데 여러분의 이메일을 입력하시면됩니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/17//2021_11_17_15_tSVON6ezEJihU139u2ic.jpg" src="/resources/media/images/content/2021/11/17//2021_11_17_15_tSVON6ezEJihU139u2ic.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;여기서 중요한 점은 여러분들이 학교측에서 개설한 교육용 이메일만 가능합니다. 예를들어 Office365를 사용할 수 있는 outlook 이메일 같은 것이죠.&lt;/p&gt;
&lt;p&gt;저는 G-suit계정이 있어서 그걸로 진행했습니다.
&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/17//2021_11_17_15_RUNFo8Cf9f9qGI6MX3DY.jpg" src="/resources/media/images/content/2021/11/17//2021_11_17_15_RUNFo8Cf9f9qGI6MX3DY.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/17//2021_11_17_15_VHorfwhzGDIdWuwzpIWT.jpg" src="/resources/media/images/content/2021/11/17//2021_11_17_15_VHorfwhzGDIdWuwzpIWT.jpg.preview.jpg" alt=""&gt;
그럼 이런 라이센스를 받을 수 있습니다!&lt;br&gt;
반드시 여기 들어가서 라이센스 동의를 하셔야됩니다.&lt;br&gt;
이제 IntelliJ를 실행합니다.&lt;/p&gt;
&lt;p&gt;다음을 누르다보면 이런 라이센스 인증이 나옵니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/17//2021_11_17_15_vLT6P6ZT3WDlyTs5hPmn.jpg" src="/resources/media/images/content/2021/11/17//2021_11_17_15_vLT6P6ZT3WDlyTs5hPmn.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;여기서 방금 가입한 계정으로 Login을 진행하고 Activity를 하면 라이센스 인증 완료입니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/17//2021_11_17_15_8qZZW9lDJ5Ob6uLCuwVa.jpg" src="/resources/media/images/content/2021/11/17//2021_11_17_15_8qZZW9lDJ5Ob6uLCuwVa.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/17//2021_11_17_15_R1w2vpAQqaFCCTZKReTs.jpg" src="/resources/media/images/content/2021/11/17//2021_11_17_15_R1w2vpAQqaFCCTZKReTs.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;외에도 다양한 플랫폼에서 학교계정이 있으면 무료로 지원하는 경우가 많으니 필요하시면 알아보셔서 진행하시면 좋을듯합니다!&lt;/p&gt;
</description><pubDate>Wed, 17 Nov 2021 15:32:24 +0900</pubDate><guid>http://blex.me/@DevMinGeonPark/jetbrains-ide-%ED%95%99%EC%83%9D-%EB%9D%BC%EC%9D%B4%EC%84%BC%EC%8A%A4-%EB%B0%9B%EA%B8%B0</guid></item><item><title>M1 Monterey Java 11.0.13 설치 후 환경변수 설정하기</title><link>http://blex.me/@DevMinGeonPark/m1-monterey-java-11013-%EC%84%A4%EC%B9%98-%ED%9B%84-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0</link><description>&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/17//2021_11_17_15_sL29hhiOpCX5iXxdhJHx.jpg" src="/resources/media/images/content/2021/11/17//2021_11_17_15_sL29hhiOpCX5iXxdhJHx.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;최근에 Java를 사용할 일이 생겨서 M1 Mac에 Java 11.0.13 버전을 설치하는 방법을 정리하고자합니다.&lt;/p&gt;
&lt;p&gt;먼저 Java를 설치해야합니다.
Oracle 쪽에서 구하는 방법도 있지만, M1이라는 특수성을 고려해서 많이 사용하시는 Zulu OpenJDK를 활용하였습니다.&lt;/p&gt;
&lt;p&gt;먼저 아래의 주소에서 .dmg파일을 다운받아 실행해서 Java를 설치해주시면됩니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.azul.com/downloads/?version=java-11-lts&amp;amp;os=macos&amp;amp;architecture=arm-64-bit&amp;amp;package=jdk"&gt;https://www.azul.com/downloads/?version=java-11-lts&amp;amp;os=macos&amp;amp;architecture=arm-64-bit&amp;amp;package=jdk&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/17//2021_11_17_14_EKygKIYj05cl3ruVeBZ0.jpg" src="/resources/media/images/content/2021/11/17//2021_11_17_14_EKygKIYj05cl3ruVeBZ0.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;그러고나면 Java가 설정되어 있을텐데,
이상태로도 Java --version을 실행하면 버전이 나옵니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/17//2021_11_17_14_EZb8NemOggfizkEB52mp.jpg" src="/resources/media/images/content/2021/11/17//2021_11_17_14_EZb8NemOggfizkEB52mp.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;하지만 echo $JAVA_HOME를 실행하면 환경변수가 나오지 않습니다.&lt;/p&gt;
&lt;p&gt;환경변수를 설정해봅니다.&lt;/p&gt;
&lt;p&gt;본인 쉘의 종류에 따라 다르겠지만, Mac에서는 zsh쉘을 많이 사용하고 저 또한 iterm에서 zsh쉘을 사용하고 있기때문에 zsh쉘을 기준으로 설명드립니다.&lt;/p&gt;
&lt;p&gt;먼저 Java의 경로를 찾아야됩니다. 별 설정없이 JDK를 설치하셨다면&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;cd /Library/Java/JavaVirtualMachines
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위 경로에 들어가시면 본인의 JDK를 보실 수 있습니다&lt;/p&gt;
&lt;p&gt;이제 저처럼 ls와 cd를 통해 Home까지의 경로를 찾으시면됩니다. 저는 아래와 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/17//2021_11_17_15_c3UEfjUW85ZVt4uR9p9C.jpg" src="/resources/media/images/content/2021/11/17//2021_11_17_15_c3UEfjUW85ZVt4uR9p9C.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;/Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;그리고 마지막으로 환경변수를 설정하시면됩니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;vim ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;를 실행하시고 제일 아래로 내려가서 o를 누르시면 아래에 입력이 가능합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;#./zshrc Codes..
#setting Java
export JAVA_HOME=&amp;quot;여러분의 JAVA 경로&amp;quot;
export PATH=${PATH}:$JAVA_HOME/bin
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이제 확인해볼까요?&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;echo $JAVA_HOME
java -version
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/17//2021_11_17_15_MB9pzHh7fjgjB9DJvA0S.jpg" src="/resources/media/images/content/2021/11/17//2021_11_17_15_MB9pzHh7fjgjB9DJvA0S.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;썸네일 참고자료&lt;br&gt;
&lt;a href="https://alexmanrique.com/blog/development/2021/01/05/first-steps-using-java-in-macbook-air-m1.html"&gt;https://alexmanrique.com/blog/development/2021/01/05/first-steps-using-java-in-macbook-air-m1.html&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</description><pubDate>Wed, 17 Nov 2021 15:08:41 +0900</pubDate><guid>http://blex.me/@DevMinGeonPark/m1-monterey-java-11013-%EC%84%A4%EC%B9%98-%ED%9B%84-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0</guid></item><item><title>오라클 클라우드(OCI) 서버 구축하기 - 추가 사용자 생성</title><link>http://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EC%B6%94%EA%B0%80-%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%83%9D%EC%84%B1</link><description>&lt;blockquote&gt;
&lt;p&gt;목차&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EA%B5%AC%ED%9A%8D-%EC%83%9D%EC%84%B1"&gt;구획 생성&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EA%B0%80%EC%83%81%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%83%9D%EC%84%B1"&gt;네트워크 설정&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Instance 생성&lt;/li&gt;
&lt;li&gt;Nginx 설치&lt;/li&gt;
&lt;li&gt;MySQL 8 설치&lt;/li&gt;
&lt;li&gt;방화벽 설정&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;에러를 발견해서 다시 작성합니다.&lt;/strong&gt;
공개키방식으로 인증하는걸 채택하면서 생긴 문제가 추가 사용자로 접근하는걸 할줄 몰랐다는겁니다.&lt;br&gt;
이번에 알아보면서 추가 사용자를 생성하고 접근할 수 있는 방법을 익혀서 이렇게 기록으로 남기게 되었습니다.&lt;br&gt;
이 주제는 사진으로 찍게되면 모자이크 처리해야할 부분이 많아 보여 명령어 위주로 작성합니다.&lt;/p&gt;
&lt;h4 id="root-passwd-설정하기"&gt;root passwd 설정하기&lt;/h4&gt;&lt;p&gt;초기 root 패스워드를 설정해야합니다.
초기 인스턴스 생성 때 활용했던 방법을 통해 opc에 접근하고
sudo su로 루트로 진입합니다.&lt;br&gt;
아래의 방법으로 패스워드를 설정합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;opc@Instance-name$ sudo su
root@Instance-name# passwd
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="유저-생성-및-authorizedkeys-생성"&gt;유저 생성 및 authorized_keys 생성&lt;/h4&gt;&lt;p&gt;먼저 oracle-cloud - 컴퓨트 - 인스턴스 - 인스턴스 세부정보로 가셔서 아래로 내려가서 콘솔접속에서&lt;br&gt;
Cloud Shell을 실행하세요.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;{value} 안의 값은 변경가능한 값입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;user-name@Instance-name:path$ useradd {userName} &amp;amp;&amp;amp; adduser {userName}
user-name@Instance-name:path$ cd .. &amp;amp;&amp;amp; cd {userName} &amp;amp;&amp;amp; mkdir .ssh
user-name@Instance-name:path$ chmod 700 .ssh &amp;amp;&amp;amp; cd .ssh
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="server-측-ssh키-생성"&gt;Server 측 SSH키 생성&lt;/h4&gt;&lt;p&gt;서버측에서 먼저 ssh키를 생성합니다.&lt;br&gt;
위에서 저희는 root passwd를 설정했습니다. 웹에서 Oracle CloudShell 을 켜서 루트로 접근합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;&amp;gt; login : root
&amp;gt; passwd : 위에서 설정한 passwd
&amp;gt; root@Instance-name# ssh-keygen -t rsa -b 4096
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ssh-keygen은 git이 있거나 리눅스에서는 defult로 설치되어있습니다.
이제 방금 만든 key를 확인합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;&amp;gt; root@Instance-name# cat /.ssh/id_rsa.pub
&amp;gt; ssh-rsa AAAAB3NzaC1yc2EAAAADAQABA …………………………………………………………………
&amp;gt; …………………………………………………………………… = User-DaskTop-ID.local
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;여기서 반드시 ssh-rsa부터 여러분의 유저 아이디.local까지를 다 복사하셔야됩니다.&lt;br&gt;
이제 서버측은 잠시 나두고 client로 가보도록하죠.&lt;/p&gt;
&lt;h4 id="client-측-ssh키-생성"&gt;Client 측 SSH키 생성&lt;/h4&gt;&lt;p&gt;Client라고 표현했지만 쉽게 말하면 여러분들의 로컬 컴퓨터입니다.&lt;br&gt;
제 경우에는 주로 맥북으로 작업하지만, 맥은 최초 인스턴스 생성 때 ssh키를 넣어서 생성했으니 진행할 필요가없습니다.&lt;br&gt;
그래서 윈도우 컴퓨터로 진행하고있습니다.
&lt;strong&gt;참고로 윈도우 컴퓨터에서의 Console 접근 환경은 WSL2 입니다.&lt;/strong&gt;
WSL2 설정은 다음에 글로 작성해서 다루도록 하겠습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;실습 진행 중 윈도우 컴퓨터 환경&lt;/strong&gt;  &lt;br&gt;
Windows 10 Pro&lt;br&gt;
WSL2 Ubuntu LTS + Windows Terminal&lt;br&gt;
zsh + oh my zsh&lt;br&gt;
installed git&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;&amp;gt; user-name$ sudo ssh-keygen -t rsa -b 4096  
&amp;gt; user-name$ cd defult-path/.ssh  
&amp;gt; user-name$ cat id_rsa.pub  
&amp;gt; user-name$ echo &amp;gt;&amp;gt; {Server측 ssh-key} authorized_keys  
&amp;gt; user-name$ chmod 600 authorized_keys  

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;먼저 여기서 생성될 때 defult경로를 잘 보고 그 경로의 ssh에 접근해야합니다.
그리고 cat을 통해 id_rsa.pub 확인합니다. 이건 복사해두었다가 서버 측에 작성할 예정입니다.
마지막으로  authorized_keys 파일을 생성하고 600으로 권한을 변경합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;authorized_keys 생성 예시&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;vim authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABA …………………………………………………………………
&amp;gt; …………………………………………………………………… = User-DaskTop-ID.loca
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="server-측-authorizedkeys-생"&gt;Server 측 authorized_keys 생성&lt;/h4&gt;&lt;p&gt;다시 서버로 돌아갑니다.&lt;br&gt;
먼저 아까 만든 유저로 로그인하여  ssh 폴더로 접근합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;&amp;gt; user-name@Instance-name$ cd .ssh
&amp;gt; user-name@Instance-name$ vim authorized_keys
&amp;gt; user-name@Instance-name$ {client측 ssh-key} 
&amp;gt; user-name$ chmod 600 authorized_keys
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ssh폴더에서 client측에서 복사해둔 ssh키를 입력하고 authorized_keys로 파일을 생성합니다.&lt;br&gt;
그리고 마지막으로 600권한을 주게되면 실행 준비 완료입니다.&lt;/p&gt;
&lt;h4 id="접속-테스트"&gt;접속 테스트&lt;/h4&gt;&lt;p&gt;Client측에서 접근을 시도합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;&amp;gt; user-name@Instance-name$ ssh user-name@public-ip-address
&amp;gt; # OR
&amp;gt; user-name@Instance-name$ ssh -i defult-path/.ssh/is_rsa.pub user-name@public-ip-address
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="정리"&gt;정리&lt;/h4&gt;&lt;p&gt;정리하자면,&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;root passwd 설정이 되어야함.&lt;/li&gt;
&lt;li&gt;cloud shell을 통해 세팅해야함.&lt;/li&gt;
&lt;li&gt;server측에서 계정을 만들고 ssh키를 생성해야하며, authorized_keys를 만들어 접속하는 계정의 ssh키를 작성해야함.&lt;/li&gt;
&lt;li&gt;client측에서 ssh키를 생성하고 authorized_keys를 만들어 server측 계정에서 받은 ssh키를 입력해야함.&lt;/li&gt;
&lt;li&gt;결론적으로 server ( ssh, authorized_keys ), client ( ssh, authorized_keys )키가 완전하게 대칭되어야 접근가능.&lt;/li&gt;
&lt;/ol&gt;
</description><pubDate>Thu, 11 Nov 2021 10:45:29 +0900</pubDate><guid>http://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EC%B6%94%EA%B0%80-%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%83%9D%EC%84%B1</guid></item><item><title>오라클 클라우드(OCI) 서버 구축하기 - 인스턴스 생성</title><link>http://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EC%83%9D%EC%84%B1</link><description>&lt;blockquote&gt;
&lt;p&gt;목차&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EA%B5%AC%ED%9A%8D-%EC%83%9D%EC%84%B1"&gt;구획 생성&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EA%B0%80%EC%83%81%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%83%9D%EC%84%B1"&gt;네트워크 설정&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EC%83%9D%EC%84%B1"&gt;Instance 생성&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;추가 사용자 생성&lt;/li&gt;
&lt;li&gt;Nginx 설치&lt;/li&gt;
&lt;li&gt;MySQL 8 설치&lt;/li&gt;
&lt;li&gt;방화벽 설정&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;인스턴스 업로드는 바로 진행하려고했는데... 😅&lt;br&gt;
root유저 외에 유저에서 ssh 전용키 공유없이 접근하는걸 해보다가 잘안되서 해결한다고 오래걸렸습니다..&lt;br&gt;
적고보니 이부분은 다음 편에서 다뤄도 될.. 인스턴스 생성 쪽은 괜히 미뤘나봅니다 😊&lt;br&gt;
바로 시작하겠습니다! 오늘은 드디어 인스턴스를 생성해 보겠습니다.&lt;br&gt;
먼저 인스턴스 페이지로 들어시면됩니다.&lt;br&gt;
그럼 이런 창이 보이게 될껍니다.&lt;/p&gt;
&lt;h6 id="구획-변경"&gt;구획 변경&lt;/h6&gt;&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/10//2021_11_10_13_dlTJOG3Y7nWBQekH1vWa.jpg" src="/resources/media/images/content/2021/11/10//2021_11_10_13_dlTJOG3Y7nWBQekH1vWa.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;여기서 중요한 점은 구획입니다. 실수로 루트 사용자에 만들면 다시 만들어야 됩니다.&lt;br&gt;
옆에 구획을 저희가 만든 구획으로 변경합니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/10//2021_11_10_13_TsednySpdCqdq6hfNX6Y.jpg" src="/resources/media/images/content/2021/11/10//2021_11_10_13_TsednySpdCqdq6hfNX6Y.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;h6 id="인스턴스-생성"&gt;인스턴스 생성&lt;/h6&gt;&lt;p&gt;정확히 원하는 구획인지 확인되었다면 이제 인스턴스를 생성하도록합니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/10//2021_11_10_13_QnjtVJfTmPF5be1k05V4.jpg" src="/resources/media/images/content/2021/11/10//2021_11_10_13_QnjtVJfTmPF5be1k05V4.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;인스턴스 생성을 누르게 되면 위와같은 창이 뜨는데, 여기서 이름을 정합니다.&lt;br&gt;
참고로 여기서 정한 이름은 이후 서버 측 root에서 opc@servercompartment같이 유저명에 사용됩니다.&lt;br&gt;
배치는 무료 이용을 위해 그대로 둡니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/10//2021_11_10_13_yHyP0MT8NOPoTnmXUvws.jpg" src="/resources/media/images/content/2021/11/10//2021_11_10_13_yHyP0MT8NOPoTnmXUvws.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;저희가 원하는 OS는 CentOS8입니다. 따라서 아래에 이미지 구성을 변경해봅니다.&lt;/p&gt;
&lt;h6 id="ssh키-설정"&gt;ssh키 설정&lt;/h6&gt;&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/10//2021_11_10_13_59SoSuYjDb7keJuqgYRt.jpg" src="/resources/media/images/content/2021/11/10//2021_11_10_13_59SoSuYjDb7keJuqgYRt.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;중요한 부분입니다. 이 포스팅이 시간을 끌게 된 원흉입니다 ㅎㅎ..&lt;br&gt;
여기서 저희들은 두가지 방법 중 선택할 수 있습니다.&lt;br&gt;
자동으로 키 쌍을 생성해서 저장하고 그걸 공유하는 방법과 공용키를 이용해 접근하는 방법입니다.&lt;br&gt;
필자의 경우 이 글을 작성하기 전 까지만해도 자동 키쌍 생성을 이용했으나, 보안적으로 좋지않아보여 공용키로 변경하게되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/10//2021_11_10_13_6NuewrSlffVvglUVJwqi.jpg" src="/resources/media/images/content/2021/11/10//2021_11_10_13_6NuewrSlffVvglUVJwqi.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;여기에 주로 사용할 (주로 root나 opc에 접속할) ssh 공용키를 넣어주시면됩니다.&lt;/p&gt;
&lt;p&gt;아래처럼 구하면됩니다.&lt;/p&gt;
&lt;h6 id="ssh-키를-보는-linux-명령"&gt;ssh 키를 보는 linux 명령&lt;/h6&gt;&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/10//2021_11_10_13_fnlLPQlBWXCLn4Fp5RJg.jpg" src="/resources/media/images/content/2021/11/10//2021_11_10_13_fnlLPQlBWXCLn4Fp5RJg.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cat ~/.ssh/id_rsa.pub&lt;/code&gt;&lt;/p&gt;
&lt;h6 id="만약-공용키가-없다면"&gt;&lt;strong&gt;만약 공용키가 없다면&lt;/strong&gt;&lt;/h6&gt;&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/10//2021_11_10_13_NYLt78JRpNUrUMfzgN0M.jpg" src="/resources/media/images/content/2021/11/10//2021_11_10_13_NYLt78JRpNUrUMfzgN0M.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ssh-keygen -t rsa -b 409&lt;/code&gt;
를 입력하고 엔터를 계속 누르시면 됩니다.&lt;br&gt;
해당 명령의 경우 Git이 깔려있는 경우 기본 내장입니다.&lt;br&gt;
또한 실행한 후 첫 번째 출력 줄에 &lt;code&gt;/User/min/.ssh/id_rsa&lt;/code&gt;와 같이.&lt;br&gt;
&lt;code&gt;/root(맥: User)/min(usdr name)/.ssh&lt;/code&gt; 에 진입하면 &lt;code&gt;id_rsa.pub&lt;/code&gt;이 있을 것입니다.&lt;br&gt;
이제 이 파일을 위의 명령처럼&lt;br&gt;
&lt;code&gt;cat ~/.ssh/id_rsa.pub&lt;/code&gt; 하면 ssh키가 보일 겁니다 그걸 복사해서 붙여넣으시면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/10//2021_11_10_13_YCXxyY833Y9fN8KE1m6Y.jpg" src="/resources/media/images/content/2021/11/10//2021_11_10_13_YCXxyY833Y9fN8KE1m6Y.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/10//2021_11_10_13_6NuewrSlffVvglUVJwqi.jpg" src="/resources/media/images/content/2021/11/10//2021_11_10_13_6NuewrSlffVvglUVJwqi.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;이제 인스턴스 생성을 하면 아래와같은 info 페이지가 나옵니다. 처음에는 초록색이 아닌 다른 색이지만.. 초록색으로 바뀌면 시작할 준비를 마쳤다는 뜻입니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/10//2021_11_10_13_BQNs0DTGz4Z75ZCiRYoa.jpg" src="/resources/media/images/content/2021/11/10//2021_11_10_13_BQNs0DTGz4Z75ZCiRYoa.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;마지막으로 ssh 접근을하고 마치겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/10//2021_11_10_13_LJp6k5iTblyplctjJEcm.jpg" src="/resources/media/images/content/2021/11/10//2021_11_10_13_LJp6k5iTblyplctjJEcm.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;공개키방식 : &lt;code&gt;ssh opc@공용IP주소&lt;/code&gt;  &lt;br&gt;
전용키방식 : &lt;code&gt;ssh -i /전용키주소 opc@공용IP주소&lt;/code&gt;  &lt;br&gt;
혹시나 CentOS가 아니라면 사용자이름은 정해진 걸(인스턴스에 명시됨) 사용해주시면됩니다.&lt;br&gt;
-i 옵션은 전용키방식에서만 사용되는게 아니라 자동으로 필요한 키를 못찾을경우 지정해주는겁니다.&lt;/p&gt;
&lt;p&gt;이렇게하면 인스턴스를 마무리할 수 있습니다.&lt;/p&gt;
</description><pubDate>Wed, 10 Nov 2021 13:53:35 +0900</pubDate><guid>http://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EC%83%9D%EC%84%B1</guid></item><item><title>오라클 클라우드(OCI) 서버 구축하기 - 가상네트워크 생성</title><link>http://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EA%B0%80%EC%83%81%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%83%9D%EC%84%B1</link><description>&lt;blockquote&gt;
&lt;p&gt;목차&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EA%B5%AC%ED%9A%8D-%EC%83%9D%EC%84%B1"&gt;구획 생성&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EA%B0%80%EC%83%81%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%83%9D%EC%84%B1"&gt;네트워크 설정&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EC%83%9D%EC%84%B1"&gt;Instance 생성&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;추가 사용자 생성&lt;/li&gt;
&lt;li&gt;Nginx 설치&lt;/li&gt;
&lt;li&gt;MySQL 8 설치&lt;/li&gt;
&lt;li&gt;방화벽 설정&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;사실 하루에 한 글씩 업로드하고자 했으나.. 이래저래 겹쳐서 한번에 해서 업로드하게되었습니다. 😂
오늘은 저번 구획 생성 이후 가상 네트워크를 생성하는 글을 다루겠습니다. 🤓&lt;/p&gt;
&lt;p&gt;먼저 옆에 탭에서 가상 네트워크를 선택해주시면됩니다.
&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/8//2021_11_8_9_9JG33MexFrFVEi6AvBdU.jpg" src="/resources/media/images/content/2021/11/8//2021_11_8_9_9JG33MexFrFVEi6AvBdU.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;그러면 아래와 같이 루트기획 내에 가상 네트워크 창이 나올껍니다.&lt;/p&gt;
&lt;p&gt;여기서 VCN 마술사를 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/8//2021_11_8_9_S3xBpHarBKXvjH4uNbc2.jpg" src="/resources/media/images/content/2021/11/8//2021_11_8_9_S3xBpHarBKXvjH4uNbc2.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/8//2021_11_8_9_7qnch26MHYjiey3YAa2s.jpg" src="/resources/media/images/content/2021/11/8//2021_11_8_9_7qnch26MHYjiey3YAa2s.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/8//2021_11_8_9_xatQDb6v9w79S3v8ShQr.jpg" src="/resources/media/images/content/2021/11/8//2021_11_8_9_xatQDb6v9w79S3v8ShQr.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;이름 지정하시고 그대로 다음을 눌러 실행하시면됩니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/8//2021_11_8_9_bGKx1CNkLNNFgbdWVd7t.jpg" src="/resources/media/images/content/2021/11/8//2021_11_8_9_bGKx1CNkLNNFgbdWVd7t.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;생성되면 해당 페이지가 나오게됩니다. 여기서 공용 서브넷에 접속합니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/8//2021_11_8_9_U20mwXvyo2qrcB16UeHO.jpg" src="/resources/media/images/content/2021/11/8//2021_11_8_9_U20mwXvyo2qrcB16UeHO.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;여기서 Mysql과 HTTP, HTTPS의 포트를 허용하겠습니다.&lt;/p&gt;
&lt;p&gt;먼저 HTTP, HTTPS입니다.
&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/8//2021_11_8_9_yU7ded8HnhQEyWRse47x.jpg" src="/resources/media/images/content/2021/11/8//2021_11_8_9_yU7ded8HnhQEyWRse47x.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Mysql도 포트 허용합니다.
&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/8//2021_11_8_9_BbRQ0FSIaiG8BIv344yt.jpg" src="/resources/media/images/content/2021/11/8//2021_11_8_9_BbRQ0FSIaiG8BIv344yt.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;여기까지 마치고 다시 네트워크에 들어가보면 방금 만든 가상 네트워크가 생성된걸 보실 수 있습니다.
&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/8//2021_11_8_9_cZntOP2AqpsvMEdsUBHS.jpg" src="/resources/media/images/content/2021/11/8//2021_11_8_9_cZntOP2AqpsvMEdsUBHS.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;여기까지 마치시면 인스턴스 생성하기 위한 준비가 완료되었습니다. 이제 다음 시리즈에서 인스턴스를 생성해서 실행해보겠습니다.&lt;/p&gt;
</description><pubDate>Mon, 08 Nov 2021 09:57:32 +0900</pubDate><guid>http://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EA%B0%80%EC%83%81%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%83%9D%EC%84%B1</guid></item><item><title>오라클 클라우드(OCI) 서버 구축하기 - 구획 생성</title><link>http://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EA%B5%AC%ED%9A%8D-%EC%83%9D%EC%84%B1</link><description>&lt;blockquote&gt;
&lt;p&gt;목차&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EA%B5%AC%ED%9A%8D-%EC%83%9D%EC%84%B1"&gt;구획 생성&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EA%B0%80%EC%83%81%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%83%9D%EC%84%B1"&gt;네트워크 설정&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EC%83%9D%EC%84%B1"&gt;Instance 생성&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;추가 사용자 생성&lt;/li&gt;
&lt;li&gt;Nginx 설치&lt;/li&gt;
&lt;li&gt;MySQL 8 설치&lt;/li&gt;
&lt;li&gt;방화벽 설정&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;최근에는 과거와는 다르게 대부분의 서버를 클라우드를 먼저 생각하는 시대가 되었습니다.&lt;br&gt;
관리의 편의성, 보안 등 다양한 장점이 있겠지만, 서버 특성상 계속 켜져있어야되는데 그 비용 문제를 크게 개선해주는게 아마 큰 장점이지 않을까 싶습니다.&lt;br&gt;
그중 GCP, AWS, Azure 등 다양한 대기업에서 무료 클라우드를 제공하고 있어 학생이나 개인 개발자들이 자신만의 콘텐츠를 만들기 수월해 졌습니다다.&lt;br&gt;
개인적으로 Azure를 제외한 대부분의 클라우드를 사용해 보았지만,&lt;br&gt;
GCP도 AWS도 사용법이 어려워 비용문제에서 안전하지 않았다고 생각합니다.&lt;br&gt;
특히 AWS의 경우 해킹까지 당하면서 한번 크게 데일 뻔 한 적이 있어 자주 사용하지 않게되었습니다.
그러던 중 접한 OCI(Oracle Cloud Infrastructure)는 만족하면서 사용하고 있고, 비용문제도 한번 일어난 적이없다. 무료 서버를 타 플랫폼에 비해 푸짐하게 주는 것도 장점이라 생각합니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;OCI Free Tier&lt;/strong&gt;.&lt;br&gt;
1 OCPU(vCpu와 동일한 용어), 1 GByte 램, 그리고 50G Byte VM.Standard.E2.1.Micro 인스턴스 2대.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이번 시리즈에서는 혜자스러운 클라우드. OCI의 인스턴스 생성 및 네트워크 설정에 대해 알아보고,
CentOS 8을 설치해서 Mysql 서버를 올리는 것 까지 해볼려고합니다.&lt;/p&gt;
&lt;h4 id="사이트-찾아가기"&gt;사이트 찾아가기&lt;/h4&gt;&lt;p&gt;먼저 Oracle을 찾아가야합니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.oracle.com/"&gt;https://www.oracle.com/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/5//2021_11_5_13_33v27DV0zLcs0zQ4BBEn.jpg" src="/resources/media/images/content/2021/11/5//2021_11_5_13_33v27DV0zLcs0zQ4BBEn.jpg.preview.jpg" alt=""&gt;  &lt;br&gt;
오라클에 접속하면 옆에 &lt;strong&gt;View Account&lt;/strong&gt;를 눌러서 Sign in Cloud를 선택하면,&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/5//2021_11_5_13_sfa6s31q0YELGeKOOaNV.jpg" src="/resources/media/images/content/2021/11/5//2021_11_5_13_sfa6s31q0YELGeKOOaNV.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;이런 페이지가 나오게됩니다.  여기에 여러분의 아이디를 적게되면,&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/5//2021_11_5_13_QLQG1BGOFXpIb7cdqgC8.jpg" src="/resources/media/images/content/2021/11/5//2021_11_5_13_QLQG1BGOFXpIb7cdqgC8.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;위와 같이 나오게되고 다음을 누릅니다.&lt;/p&gt;
&lt;p&gt;그럼이제 로그인 할 수 있는 페이지가 나옵니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/5//2021_11_5_13_RFwiTN44SIfaid7pmqCF.jpg" src="/resources/media/images/content/2021/11/5//2021_11_5_13_RFwiTN44SIfaid7pmqCF.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;이제 클라우드 계정에 진입하면 저희가 흔히 알고있는 클라우드 인터페이스가 나오게됩니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/5//2021_11_5_13_F2yKvdImSqsArpMUwCgX.jpg" src="/resources/media/images/content/2021/11/5//2021_11_5_13_F2yKvdImSqsArpMUwCgX.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;이제 구획 페이지를 찾아갑니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/6//2021_11_6_19_7ya4G97HB52N2OCmEFvm.jpg" src="/resources/media/images/content/2021/11/6//2021_11_6_19_7ya4G97HB52N2OCmEFvm.jpg.preview.jpg" alt=""&gt;  &lt;br&gt;
&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/6//2021_11_6_19_tDO1E17tRo3DQOfPjlzQ.jpg" src="/resources/media/images/content/2021/11/6//2021_11_6_19_tDO1E17tRo3DQOfPjlzQ.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;구획페이지에 들어와서 구획 생성을 클릭합니다.
아마 막 계정을 생성한 사람은 root 구획 밖에 없을껍니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/8//2021_11_8_9_N4TfcrU6nRigFv7YvxvF.jpg" src="/resources/media/images/content/2021/11/8//2021_11_8_9_N4TfcrU6nRigFv7YvxvF.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;이제 구획을 생성합니다.&lt;br&gt;
구획이름은 아무거나 지어주셔도 괜찮습니다.&lt;br&gt;
상위구획은 루트로 해줍시다.&lt;/p&gt;
&lt;p&gt;이제 해당 구획에 네트워크를 생성하면됩니다. 네트워크 생성은 다음 글에서 다루도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;읽어주셔서 감사합니다 😊&lt;/p&gt;
</description><pubDate>Mon, 08 Nov 2021 09:43:14 +0900</pubDate><guid>http://blex.me/@DevMinGeonPark/%EC%98%A4%EB%9D%BC%ED%81%B4-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9Coci-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-%EA%B5%AC%ED%9A%8D-%EC%83%9D%EC%84%B1</guid></item><item><title>개념적으로 접근하는 자료구조 - 스택(Stack)</title><link>http://blex.me/@DevMinGeonPark/%EA%B0%9C%EB%85%90%EC%A0%81%EC%9C%BC%EB%A1%9C-%EC%A0%91%EA%B7%BC%ED%95%98%EB%8A%94-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%8A%A4%ED%83%9Dstack</link><description>&lt;p&gt;저희학교에서는 자료구조를 구술로 시험을 쳐서 학점을줍니다.&lt;br&gt;
이런 구술 테스트 중 공부한 내용을 잊지 않기 위해 앞으로는 정리하면서 해볼까합니다.&lt;br&gt;
&lt;strong&gt;기록은 기억보다 의미있는걸 믿기 때문입니다.&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id="스택"&gt;스택&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;스택&lt;/strong&gt;은 같은 구조와 크기의 자료를 정해진 &lt;strong&gt;방향&lt;/strong&gt;으로만 입출력 하는 구조입니다.&lt;br&gt;
여기서 정해진 방향이란 top이라 정의된 스택(Stack)의 가장 위 마지막에 삽입한 자료입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/4//2021_11_4_9_7pzyH1Yyb2hbRZmml0NI.jpg" src="/resources/media/images/content/2021/11/4//2021_11_4_9_7pzyH1Yyb2hbRZmml0NI.jpg.preview.jpg" alt=""&gt;
Data Structure in&lt;br&gt;
&lt;a href="https://dev.to/theoutlander/implementing-the-stack-data-structure-in-javascript-4164"&gt;https://dev.to/theoutlander/implementing-the-stack-data-structure-in-javascript-4164&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;위 사진와 같이 스택의 제일 위 마지막 자료를 top이라 정의하며, 스택은 이 top을 통해서만 데이터를 입출력력 합니다. 여기서 가장 중요한 점은 저장이 물리적으로 이루어지는게 아니라는 점입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;스택은 선형자료구조의 한쪽 끝(stack)에서만 발생하며 논리적인 구조를 통해 이를 수행합니다.&lt;/strong&gt;  &lt;br&gt;
당연히 Top을 통해서만 입출력이 이루어지기 때문에 우리가 알고있는 LIFO(Last-In-First-Out) 후입선출이라는 특징을 가지게 되죠.&lt;/p&gt;
&lt;p&gt;후입선출이라고 어렵게 말하면 잘 이해가 되지 않을텐데, 과거 연탄을 보관할 때를 생각해보면됩니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/4//2021_11_4_9_Br3xVRIurGrgMd8aCnaX.jpg" src="/resources/media/images/content/2021/11/4//2021_11_4_9_Br3xVRIurGrgMd8aCnaX.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;결국 제일 처음 넣은 연탄은 마지막에 사용하게되죠. 왜냐면 위에서만 꺼낼 수 있기 때문입니다.
이처럼 스택은 top을 통해서만 입출력을 진행하게됩니다.&lt;/p&gt;
&lt;h4 id="스택의-원소-삽입-삭제-과정"&gt;스택의 원소 삽입, 삭제 과정&lt;/h4&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/4//2021_11_4_9_Wd4UILIOVPz51G5iPzt1.jpg" src="/resources/media/images/content/2021/11/4//2021_11_4_9_Wd4UILIOVPz51G5iPzt1.jpg.preview.jpg" alt=""&gt;  &lt;br&gt;
스택의 삽입과 삭제를 나타낸 그림입니다.&lt;/p&gt;
&lt;h4 id="스택의-추상-자료형"&gt;스택의 추상 자료형&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;ADT Stack
   Data: 0개 이상의 원소를 가진 유한 선형자료구조
   연산 : 
            S ∈ Stack;  item ∈ Element;
            createStack(S) ::= 공백 스택 S를 생성하는 연산
            push(S, item) ::= 스택 S의 top에 원소(item)를 삽입하는 연산
            isEmpty(S) ::= 스택 S가 공백인지를 확인하는 연산
            pop(S) ::= 스택 S의 top에 있는 원소를 스택 S 에서 삭제하고 반환하는 연산
            delete(S) ::= 스택 S의 top에 있는 원소를 삭제하는 연산
            peek(S) ::= 스택 S의 top에 있는 원소를 반환하는 연산
End Stack
By 한빛아카데미(주) 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;스택은 위와같은 추상 자료형을 가집니다.&lt;br&gt;
중요한점은 push와 pop이 정의되어야한다는 점과 &lt;strong&gt;선형자료구조 형태라는 것입니다&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id="스택의-push-알고리즘"&gt;스택의 push 알고리즘&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;push(S,x)
    top &amp;lt;- top + 1
    if (top  stack_SIZE) then
        overflow;
    else
        s(top) &amp;lt;- x;
end push()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;스택도 결국 메인메모리에서 구현됩니다. 그리고 메모리의 용량은 한정되어있죠.&lt;br&gt;
스택에서도 용량이 가득차면 오류가 발생하겠죠. 이 오류를 overflow(오버플로우)라고합니다.&lt;br&gt;
스택의 push 알고리즘에서는 먼저 스택의 위치를 한번 증가시켜 스택의 사이즈를 넘었는지, 오버플로가 일어 났는지를 확인해야됩니다. 만약 넘지않았다면 스택에 저장하면 될일이지만, 넘었다면 저장할 곳이 없다는 것을 알려주는 것입니다.&lt;br&gt;
나중에 실제 고급언어로 구현된 스택도 작성해볼 생각이지만 오늘은 개념적으로 정의하는 스택이라는 테마기에 의사코드로 구현하였습니다.&lt;/p&gt;
&lt;h4 id="스택의-pop-알고리즘"&gt;스택의 pop 알고리즘&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;pop(S)
    if(top=-1) then underflow;
    else {
           return S(top);
           top &amp;lt;- top-1;
         }
end pop()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;pop 연산은 top의 원소를 삭제하고 반환하는 연산입니다.&lt;br&gt;
이런 삭제연산에서 중요 논점은 값이 -로 가게되는 시점입니다.&lt;br&gt;
컴퓨터는 -를 표현하지 못하죠. 저희는 컴퓨터의 -를 표현하기위해 보수법과 같은 기술을 이용합니다.&lt;br&gt;
하지만 스택은 앞에도 언급했듯 논리적인 구조입니다. 그런 스택이 -값을 가지게 되는건 비이상적인 값입니다.&lt;br&gt;
저희는 비이상적인 결과값을 '에러'라고 부르곤하죠.&lt;br&gt;
스택이 0이 아닌 -1이 되는시점. 이 시점을 에러 언더플로로 지정하고 그런 경우에 분기하는 것이 pop 알고리즘의 핵심입니다. delete와 조금 다른 점은 return을 통해 값을 &lt;strong&gt;반환&lt;/strong&gt;하는 것이죠.&lt;/p&gt;
&lt;h4 id="스택의-구현"&gt;스택의 구현&lt;/h4&gt;
&lt;p&gt;스택은 선형자료구조에서 이용가능한 논리적 구조입니다.&lt;br&gt;
그럼 대표적인 선형자료구조인 순차자료구조(array)와 연결자료구조(linked list)에서도 실제 구현이 가능하겠죠?&lt;/p&gt;
&lt;h6 id="순차자료구조를-이용한-스택의-구현"&gt;순차자료구조를 이용한 스택의 구현&lt;/h6&gt;
&lt;p&gt;이부분에서는 순차자료구조인 1차원배열(array)를 이용하여 구현한 예를 보여드리겠습니다.&lt;br&gt;
배열은 순차적인 자료구조입니다. 주요 특징은 물리적인구조와 논리적 구조가 같다는 것이있습니다.&lt;br&gt;
이런 배열에서 스택의 크기는 배열의 크기와 같습니다. 논리적인구조(스택)과 물리적인구조(배열)이 같기 때문이죠.&lt;br&gt;
스택에 저장된 원소의 순서는 순차적일 것입니다. &lt;strong&gt;순차&lt;/strong&gt;자료구조이기 때문에 스택의 원소들은 순서에따라 저장되어있을 것입니다. 여기서 순서는 top을 통해 스택에 저장된 순서겠죠.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/4//2021_11_4_10_9kIRP9xPdxM3h4weaw8X.jpg" src="/resources/media/images/content/2021/11/4//2021_11_4_10_9kIRP9xPdxM3h4weaw8X.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;스택, 배열의 첫번째 원소는 0이죠. 그럼 top의 첫번째 요소(값)은 몇일까요?
스택에 아무것도 없다는 가정하에 top = -1입니다.
왜냐면 첫번 째 값이 들어왔을 때 top=0이 되어 값을 가르켜야 되기 때문이죠.
이와 같은 개념으로 스택이 포화상태일 때 값도 n-1입니다. n개의 원소만큼 스택이 증가했기 때문이죠.&lt;/p&gt;
&lt;p&gt;순차 자료구조로 구현한 자료구조는 1차원 배열이라는 매우 간단한 구조를 사용해 쉽게 구현할 수 있다는 장점이있습니다. 하지만 배열의 고질적 문제인 물리적으로 고정된 크기로 이니해 스택 크기 변경에 어려움이있고, 고정된 크기 내에서 표현하고 이 크기는 먼저 동적할당되어있기 때문에, 빈 공간의 메모리가 낭비된다는 단점도 있습니다.&lt;/p&gt;
&lt;h6 id="연결-자료구조를-이용한-스택의-구현"&gt;연결 자료구조를 이용한 스택의 구현&lt;/h6&gt;
&lt;p&gt;연결자료구조, Linked List는 노드와 주소값을 통해 배열보다는 자유로운 크기를 가지고있죠.&lt;br&gt;
여기서는 다양한 연결자료구조 중에서 단순연결리스트를 통해 구현해보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/4//2021_11_4_11_4Q5UkgTcXoaTkpccUsKM.jpg" src="/resources/media/images/content/2021/11/4//2021_11_4_11_4Q5UkgTcXoaTkpccUsKM.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;단순 연결리스트 노드와 링크포인터로 이루어져있고,&lt;br&gt;
링크포인터를 통해 다음 원소의 주소를 가르켜 연결됩니다. 마지막 주소에서는 null값이 링크포인터로 들어가게되죠.&lt;br&gt;
스택을 구현하는 단순연결리스트는 첫번 째 주소에서 null값을 가집니다.&lt;br&gt;
그 이유는 스택은 top을 통해 제어되어야 하기 때문이죠.&lt;br&gt;
top은 사진처럼 n번째 요소를 가르키고 이 요소들은 주소를 통해 계쏙 연결되고 마지막에 이르러 첫 번째 원소에서 null을 가르킵니다.&lt;br&gt;
만약 스택에 원소가 한개라면 &lt;code&gt;Top -&amp;gt; 첫번째원소/null&lt;/code&gt;이 연결자료구조로 구현된스택의 모습이겠죠.&lt;br&gt;
그리고 두번째 원소가 생긴다면 top은 두번째 원소를 가르키는 것입니다. 스택은 후입선출의 구조를 지녔기에 제일 마지막 원소를 탑이 가르켜야되기때문입니다.&lt;/p&gt;
&lt;h4 id="스택의-응용"&gt;스택의 응용&lt;/h4&gt;
&lt;p&gt;스택의 후입선출 특징은 다양한 분야에서 응용이 가능합니다.&lt;/p&gt;
&lt;h6 id="역순-문자열-만들기"&gt;역순 문자열 만들기&lt;/h6&gt;
&lt;p&gt;흔히 프로그램 언어에서는 reverse 같은 이름으로 역순 문자열 출력을 지원합니다.&lt;br&gt;
string a = &amp;quot;ABCD&amp;quot;일 때, 이것을 리버스하면 &amp;quot;DCBA&amp;quot;입니다.&lt;br&gt;
보통 이런 역순문자열 출력은 스택에 의해 구현됩니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/4//2021_11_4_11_mxHFlaZ3pqJ2us4PlJxO.jpeg" src="/resources/media/images/content/2021/11/4//2021_11_4_11_mxHFlaZ3pqJ2us4PlJxO.jpeg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;위의 예시처럼 스택에 ABCD를 차례대로 push하면 위와같이 스택에 적제되고 이대로 문자열을 pop하면
DCBA로 출력할 수 있다.&lt;/p&gt;
&lt;h6 id="시스템-스택"&gt;시스템 스택&lt;/h6&gt;
&lt;p&gt;우리가 만든 프로그램을 실행할 때 주로 함수를 호출합니다.
그런데 호출된 함수는 일련의 과정을 수행하고 다시 return을 실행하죠.
시스템 스택은 이런 함수의 흐름을 제어하는 스택의 일종입니다.&lt;br&gt;
함수의 호출(Jump 명령)이 발생하면 시스템은 함수 수행에 필요한 지역변수, 매개변수, 수행 후 복귀할 주소 등의 정보를 스택프레임(Stack frame)에 저장하여 시스템 스택에 push합니다.&lt;br&gt;
그리고 해당 함수가 종료되면 시스템 스택의 top원소(스택 프레임)를 pop하면서 복귀주소를 얻어 다시 함수가 실행되던 어느 지점으로 돌아갑니다.&lt;/p&gt;
&lt;h6 id="c언어로-보는-시스템-스택의-흐름"&gt;C언어로 보는 시스템 스택의 흐름&lt;/h6&gt;
&lt;p&gt;C언어로 간단하게 설명해보자면.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-C"&gt;#include &amp;lt;stdio.h&amp;gt;
int main(void) {
   printf(&amp;quot;hello world&amp;quot;);
   return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;시스템 스택의 개념을 위에 적힌 C프로그램을 따라가며 설명해보겠습니다.
먼저 &lt;code&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/code&gt;는 stdio.h라는 헤더파일을 그대로 복사해서 해당 소스파일에 붙여넣겠다는 명령입니다. 여기서 stdio.h는 printf를 위해 정의되었습니다.&lt;br&gt;
그리고 main함수를 만나게 되는데 메인함수를 만나는 시점에서 시스템 스택은 stack_frame을 만들게됩니다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/4//2021_11_4_11_Pn1xsCuoYfcJl5nZeIYX.jpeg" src="/resources/media/images/content/2021/11/4//2021_11_4_11_Pn1xsCuoYfcJl5nZeIYX.jpeg.preview.jpg" alt=""&gt;  &lt;br&gt;
이 스택프레임은 main함수에 정보를 담고있습니다. 그중 가장 중요한 정보는 메인함수의 주소겠죠.
그리고 printf를 만나게되면서 printf의 주소가 위의 사진처럼 스택프레임의 형태로 push됩니다.. 당연히 top은 pirntf의 스택프레임을 가르키겠죠. 그리고 printf의 어느시점에서 return(혹은 어셈블리 복귀명령) 명령이 발생할 껍니다. 그 시점에 stack의 top이 가르키는 printf 스택 프레임은 pop됩니다. 마지막으로 return 0코드를 만나며 main의 스택프레임도 pop되며 시스템 스택은 공백스택이 되는 것이죠.&lt;/p&gt;
&lt;h4 id="수식의-괄호검사"&gt;수식의 괄호검사&lt;/h4&gt;
&lt;p&gt;파이썬을 제외한 대부분의 프로그램 언어들은 괄호를 사랑합니다.&lt;br&gt;
&amp;quot;[], {}, ()&amp;quot;와 같은 괄호들은 고급언어에서 언제나 등장하곤합니다.&lt;br&gt;
가장 대표적인 예가 if(조건문) { 실행문 } 입니다.&lt;br&gt;
그런데 이런 괄호들을 프로그램들은 어떻게 인식하는걸까요. 이 또한 스택과 관련있습니다.&lt;br&gt;
수식괄호검사가 실행되면 왼쪽괄호 &amp;quot;{&amp;quot;를 만나게되면 스택에 push
오른쪽 괄호 &amp;quot;}&amp;quot;를 만나게되면  pop하여 마지막 괄호와 종류가 같은지를 확인합니다.
마약 pop받은 괄호가 마지막 괄호와 다르면 에러겠죠? 바로 이 방식이 IDE가 우리에게 괄호에러를 알려주는 방식입니다. 자세한건 실제 코드와 함께 다음에 다뤄보도록하겠습니다.&lt;/p&gt;
&lt;h4 id="수식의-후위-표기법-변환"&gt;수식의 후위 표기법 변환&lt;/h4&gt;
&lt;p&gt;정보처리 기사 등을 치게되면 배우는 중위표기식, 전위표기식, 후위표기식은 실제 논리적 수식들을&lt;br&gt;
컴퓨터가 이해하게 바꾸는 방식이죠. 이 또한 스택을 이용합니다.
변환방법은 아래와 같습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;중위표기식을 후위 표기식으로 변환&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;왼쪽 괄호를 만나면 무시고 다음 문자를 읽는다&lt;/li&gt;
&lt;li&gt;피연산자를 만나면 출력한다.&lt;/li&gt;
&lt;li&gt;연산자를 만나면 스택에 push한다.&lt;/li&gt;
&lt;li&gt;오른쪽 괄호를 만나면 pop하여 출력한다.&lt;/li&gt;
&lt;li&gt;수식이 끝나면 스택이 공백이 될 때까지 pop하여 출력한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;이를 이용해 연산을 할 수 도있지만 이에 대한건 다음에 후위표기식에 대해 자세히 다룰 기회가 있으면 언급하도록 하겠습니다.&lt;/p&gt;
&lt;h4 id="미로탐색문제"&gt;미로탐색문제&lt;/h4&gt;
&lt;p&gt;지금까지 스택에 대해 알아봤습니다. 그런데 이 스택을 배우는 이유는 현실적으로 알고리즘 문제들을 풀기 위해서도 있습니다. 대표적인 알고리즘 문제 중 하나인 미로탐색문제(백 트레킹 알고리즘)은 스택을 이용하는 대표적인 알고리즘입니다. 자세한건 백준 문제풀이를 공부할 때 실제 미로탐색 문제를 만나면 다루겠지만&lt;br&gt;
&lt;strong&gt;현재 위치에서 가능한 방향을 스택에 저장했다가 막다른 길을 만나면 스택에서 다음 위치를 꺼내 반복하는 것&lt;/strong&gt;이 핵심이라 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;이처럼 스택은 매우 다양한 분야에서 사용됩니다.
오늘 글을 적으면서 저 자신도 스택에 대해 복습할 수 있었고,&lt;br&gt;
이 글을 미래에 다시 보게된다면 시험에 대한 추억과 함께 스택을 공부할 수 있겠죠.
&lt;strong&gt;기록은 기억보다 의미있습니다.&lt;/strong&gt; 제 기록이 언젠가 타인에게도 도움이 되길.
제가 제일 좋아하는 스티브잡스의 구절로 마무리 하겠습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Stay hungry Stay foolish
-Steve Jobs&lt;/p&gt;
&lt;/blockquote&gt;
</description><pubDate>Thu, 04 Nov 2021 12:05:12 +0900</pubDate><guid>http://blex.me/@DevMinGeonPark/%EA%B0%9C%EB%85%90%EC%A0%81%EC%9C%BC%EB%A1%9C-%EC%A0%91%EA%B7%BC%ED%95%98%EB%8A%94-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%8A%A4%ED%83%9Dstack</guid></item><item><title>Xamarin Form에서 SNS 인증하기</title><link>http://blex.me/@DevMinGeonPark/xamarin-form%EC%97%90%EC%84%9C-sns-%EC%9D%B8%EC%A6%9D%ED%95%98%EA%B8%B0</link><description>&lt;p&gt;과거에 잠깐 회사에서 개발할 때 Tstory에 작성한 글이다. BLEX 블로그를 겸하면서 옮겨서 다시 정리하고자한다.
참고로 해당 글은 해당 깃허브 소스를 참고해 현재 버전에 맞게 수정한 것에 불과하다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Blog&lt;/strong&gt;  &lt;br&gt;
&lt;a href="https://m.blog.naver.com/PostView.nhn?blogId=goldrushing&amp;amp;logNo=221482308506&amp;amp;proxyReferer=https:%2F%2Fwww.google.com%2F"&gt;https://m.blog.naver.com/PostView.nhn?blogId=goldrushing&amp;amp;logNo=221482308506&amp;amp;proxyReferer=https:%2F%2Fwww.google.com%2F&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Github&lt;/strong&gt;   &lt;br&gt;
&lt;a href="https://github.com/imagef5/Xamarin.SNS.Login.Sample"&gt;https://github.com/imagef5/Xamarin.SNS.Login.Sample&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="xamarinfrom"&gt;Xamarin.From&lt;/h4&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/3//2021_11_3_10_nNdXXwbU870NiBRZCmYz.jpg" src="/resources/media/images/content/2021/11/3//2021_11_3_10_nNdXXwbU870NiBRZCmYz.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;MS 측 .NET Framework를 이용해 크로스 플랫폼 앱을 개발하는 오픈소스 플랫폼이다.&lt;br&gt;
각 플랫폼의 Native UI를 C#을 통해 제어하는 형태로 거의 네이티브에 유사한 속도를 자랑한다.&lt;br&gt;
당시 주 언어가 C#이였기에 크로스플랫폼 개발 중 도입해 진행했었다.&lt;br&gt;
최고의 장점은 MS에서 관리하기에 VIsual Studio를 이용해 개발할 수 있다는게 장점이고 C#의 간결한 문법도 장점에 속한다. 하지만 사용자 층이 적고 한국어로 된 자료는 없다시피하다. 그래서인지 SNS에 관련된 오픈소스 특히 Kakao Auth 로그인은 관련 정보가 하나 뿐이였고 그마저도 4년은 지난 내용이였다.
이번에 진행하게 된 기회삼아 Xamarin의 SNS 인증 관련 코드를 최신화 해보고자했다.&lt;br&gt;
부족한 실력이라 많은 설명은 없으나 도움이 되길 기원한다.&lt;br&gt;
❗ 참고로 IOS쪽에서는 추가 설정이 필요하다. IOS쪽은 필자가 맞은 파트가 아니라서 정확히 모르겠다.&lt;/p&gt;
&lt;h4 id="nuget-pakagae-version-inf"&gt;Nuget Pakagae Version Info&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;C# Nuget&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Com.Airbnb.Xamarin.Forms.Lottie 4.0.8&lt;/li&gt;
&lt;li&gt;NETStandardLibary 2.0.3&lt;/li&gt;
&lt;li&gt;Newtonsoft.Json 12.0.3&lt;/li&gt;
&lt;li&gt;Prism.Unity.Forms 8.0.0.1909&lt;/li&gt;
&lt;li&gt;Xam.Plugins.Settings 3.1.1&lt;/li&gt;
&lt;li&gt;Xamarin.Auth 1.7.0&lt;/li&gt;
&lt;li&gt;Xamarin.Auth.XamarinnForms 1.7.0&lt;/li&gt;
&lt;li&gt;Xamarin.Essentials 1.6.1&lt;/li&gt;
&lt;li&gt;Xamarin.Forms 5.0.0.1931&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Android Nuget&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Com.Airbnb.Android.Lottie 3.5.0&lt;/li&gt;
&lt;li&gt;Android API Level 29&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h4 id="folder-tree"&gt;Folder Tree&lt;/h4&gt;
&lt;p&gt;더 많은 폴더가 있지만 수정이나 추가할 폴더만 표시해보았다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;├── C# NameSpace (사용자가 정하는 것)
│   ├── Extensions
│       ├── ISettingExtensions.cs
│   ├── Models
└── Services/Authentication
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="폴더-별-소스코드"&gt;폴더 별 소스코드&lt;/h4&gt;
&lt;p&gt;폴더 별로 소스코드를 작성한 것을 공유합니다.&lt;/p&gt;
&lt;h6 id="extensions-folder"&gt;Extensions Folder&lt;/h6&gt;
&lt;p&gt;Edtension 관련 파일이 들어가는 폴더입니다.
아래처럼 같이 솔루션 하위 폴더로 C# 네임스페이스에 만들고 정의합시다.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/3//2021_11_3_10_miCEAi6CN1me8AJt6qnE.jpg" src="/resources/media/images/content/2021/11/3//2021_11_3_10_miCEAi6CN1me8AJt6qnE.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ISettingExtensions.cs&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-C#"&gt;using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Plugin.Settings.Abstractions;

namespace [YourProjectName].Extensions
{
    public static class ISettingsExtensions
    {
        public static T GetValueOrDefault&amp;lt;T&amp;gt;(this ISettings settings, string key, T @default) where T : class
        {
            string serialized = settings.GetValueOrDefault(key, string.Empty);
            T result = @default;

            try
            {
                result = JsonConvert.DeserializeObject&amp;lt;T&amp;gt;(serialized);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($&amp;quot;Error deserializing settings value: {ex}&amp;quot;);
            }

            return result;
        }

        public static bool AddOrUpdateValue&amp;lt;T&amp;gt;(this ISettings settings, string key, T obj) where T : class
        {
            try
            {
                JsonSerializerSettings serializeSettings = GetSerializerSettings();
                string serialized = JsonConvert.SerializeObject(obj, serializeSettings);

                return settings.AddOrUpdateValue(key, serialized);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($&amp;quot;Error serializing settings value: {ex}&amp;quot;);
            }

            return false;
        }

        private static JsonSerializerSettings GetSerializerSettings()
        {
            return new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            };
        }

    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h6 id="models-folder"&gt;Models Folder&lt;/h6&gt;
&lt;p&gt;Models 폴더 입니다.&lt;br&gt;
아래처럼 같이 솔루션 하위 폴더로 C# 네임스페이스에 만들고 정의합시다.&lt;br&gt;
&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/3//2021_11_3_13_Xiz0LqvSzecSdxHaSvuF.jpg" src="/resources/media/images/content/2021/11/3//2021_11_3_13_Xiz0LqvSzecSdxHaSvuF.jpg.preview.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;🔥 참고 블로그에는 Kakao 외에도 구현되어 있으나 개발 당시 카카오 외에는 필요치않아서 제거했다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;User.cs&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;using System;

namespace [YourProjectName].Models
{
    public class User
    {
        public string Id { get; set; }
        public string Token { get; set; }
        public string RefreshToken { get; set; }
        public DateTime ExpiresIn { get; set; }
        public string Name { get; set; }
        public string NickName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public string Gender { get; set; }
        public string Birthday { get; set; }
        public string PictureUrl { get; set; }
        public bool LoggedInWithSNSAccount { get; set; }
        public SNSProvider Provider { get; set; }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;User 클래스의 경우 유저 인증에 필요한 모델들을 정의하는데,&lt;br&gt;
SNSProvider의 경우 카카오 인증만 구현할 땐 필요없는 모델이지만, 혹시나 다른 인증들을 구현할 기회가
생길까봐 유지했습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SNSProvider&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.Text;

namespace [YourProjectName].Models
{
    public enum SNSProvider
    {
        None = -1,
        Kakao,
        //카카오 외의 다른 sns로그인 이용시 추가
        //Line,
        //Facebook,
        //Naver,
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;OAuth2ProviderFactory&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;namespace [YourProjectName].Models.Providers
{
    public class OAuth2ProviderFactory
    {
        public static OAuth2Base CreateProvider(SNSProvider provider)
        {
            //OAuth2Base oAuth2 = null;
            OAuth2Base oAuth2 = KakaoOAuth2.Instance; ;
            
            /*
            switch (provider)
            {
                case SNSProvider.Kakao:
                    oAuth2 = KakaoOAuth2.Instance;
                    break;
                case SNSProvider.Line:
                    oAuth2 = LineOAuth2.Instance;
                    break;
                case SNSProvider.Facebook:
                    oAuth2 = FacebookOAuth2.Instance;
                    break;
                case SNSProvider.Naver:
                    oAuth2 = NaverOAuth2.Instance;
                    break;
            }
            */

            return oAuth2;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OAuth2ProviderFactory는 OAuth2 인증을 진행할 Provider의 인스턴스를 생성해주는 코드였으나, KaKao외에는 사용하지 않아서 주석처리했다. 혹시 필요하시면 주석을 제거하면 사용하는게 좋을듯 싶다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OAuth2Base.cs&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;using System;
using System.Threading.Tasks;
using Xamarin.Auth;

namespace [YourProjectName].Models.Providers
{
    public abstract class OAuth2Base
    {
        public string ProviderName { get; set; }
        public string Description { get; set; }
        public SNSProvider Provider { get; protected set; }
        public string ClientId { get; set; }
        public string ClientSecret { get; set; }
        public string Scope { get; set; }
        public Uri AuthorizationUri { get; set; }
        public Uri RedirectUri { get; set; }
        public Uri RequestTokenUri { get; set; }
        public Uri UserInfoUri { get; set; }
        public bool IsUsingNativeUI { get; set; } = false;

        public abstract Task&amp;lt;User&amp;gt; GetUserInfoAsync(Account account);
        public abstract Task&amp;lt;(bool IsRefresh, User User)&amp;gt; RefreshTokenAsync(User user);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OAuth2를 구현할 때 Auth 표준에서 필요한 필드들의 정의를 강제하기 위해 추상메서드로 구현했습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;KakaoUser.cs&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; using Newtonsoft.Json;

namespace [YourProjectName].Models.Providers
{
    [JsonObject]
    public class KakaoUser
    {
        [JsonProperty(&amp;quot;id&amp;quot;)]
        public string Id { get; set; }

        [JsonProperty(&amp;quot;kaccount_email&amp;quot;)]
        public string Email { get; set; }

        [JsonProperty(&amp;quot;kaccount_email_verified&amp;quot;)]
        public bool VerifiedEmail { get; set; }

        public Properties Properties { get; set; }
    }

    [JsonObject]
    public class Properties
    {
        [JsonProperty(&amp;quot;nickname&amp;quot;)]
        public string NickName { get; set; }

        [JsonProperty(&amp;quot;thumbnail_image&amp;quot;)]
        public string Thumbnail { get; set; }

        [JsonProperty(&amp;quot;profile_image&amp;quot;)]
        public string ProfileImage { get; set; }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;xamairn으로 SNS 인증을 하기위해서는 REST API로 구현해야됩니다.&lt;br&gt;
따라서 Json 형태로 받는 값들을 처리하기 위한 코드입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;KakaoOAuth2.cs&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Xamarin.Auth;

namespace [YourProjectName].Models.Providers
{
    public class KakaoOAuth2 : OAuth2Base
    {
        private static readonly Lazy&amp;lt;KakaoOAuth2&amp;gt; lazy = new Lazy&amp;lt;KakaoOAuth2&amp;gt;(() =&amp;gt; new KakaoOAuth2());

        public static KakaoOAuth2 Instance
        {
            get
            {
                return lazy.Value;
            }
        }

        private KakaoOAuth2()
        {
            Initialize();
        }

        void Initialize()
        {
            ProviderName = &amp;quot;Kakao&amp;quot;;
            Description = &amp;quot;Kakao Login Provider&amp;quot;;
            Provider = SNSProvider.Kakao;
            ClientId = &amp;quot;{YourKakao REST API App Key}&amp;quot;; //REST API App Key 입력
            ClientSecret = null; 
            Scope = null; //원하는 값 형태만 지정 
            AuthorizationUri = new Uri(&amp;quot;https://kauth.kakao.com/oauth/authorize&amp;quot;);
            RequestTokenUri = new Uri(&amp;quot;https://kauth.kakao.com/oauth/token&amp;quot;);
            RedirectUri = new Uri(&amp;quot;https://www.naver.com/oauth&amp;quot;);//oauth 경로가 있는 url (주로 자신의 블로그), 네이버는 임시로 설정했습니다.
            UserInfoUri = new Uri(&amp;quot;https://kapi.kakao.com/v2/user/me&amp;quot;); // V1과 V2는 다른 서버입니다.
        }

        #region Implement Abstract Method
        public override async Task&amp;lt;User&amp;gt; GetUserInfoAsync(Account account)
        {
            User user = null;
            string token = account.Properties[&amp;quot;access_token&amp;quot;];
            string refreshToke = account.Properties[&amp;quot;refresh_token&amp;quot;];
            int.TryParse(account.Properties[&amp;quot;expires_in&amp;quot;], out int expriesIn);

            var request = new OAuth2Request(&amp;quot;GET&amp;quot;, UserInfoUri, null, account); 
            var response = await request.GetResponseAsync();
            if (response != null &amp;amp;&amp;amp; response.StatusCode == HttpStatusCode.OK)
            {
                string userJson = await response.GetResponseTextAsync();
                var kakaoUser = JsonConvert.DeserializeObject&amp;lt;KakaoUser&amp;gt;(userJson);
                user = new User
                {
                    Id = kakaoUser.Id,
                    Token = token,
                    RefreshToken = refreshToke,
                    Name = kakaoUser.Properties.NickName,
                    Email = kakaoUser.Email,
                    ExpiresIn = DateTime.UtcNow.Add(new TimeSpan(expriesIn)),
                    PictureUrl = kakaoUser.Properties.ProfileImage,
                    Provider = SNSProvider.Kakao,
                    LoggedInWithSNSAccount = true,
                };
            }
            return user;
        }

        public override async Task&amp;lt;(bool IsRefresh, User User)&amp;gt; RefreshTokenAsync(User user)
        {
            bool refreshSuccess = false;
            if (user == null)
            {
                return (refreshSuccess, user);
            }

            Dictionary&amp;lt;string, string&amp;gt; dictionary = new Dictionary&amp;lt;string, string&amp;gt; { { &amp;quot;grant_type&amp;quot;, &amp;quot;refresh_token&amp;quot; }, { &amp;quot;refresh_token&amp;quot;, user.RefreshToken }, { &amp;quot;client_id&amp;quot;, ClientId } };
            var request = new Request(&amp;quot;POST&amp;quot;, RequestTokenUri, dictionary, null);
            var response = await request.GetResponseAsync();
            if (response != null &amp;amp;&amp;amp; response.StatusCode == HttpStatusCode.OK)
            {
                string tokenString = await response.GetResponseTextAsync();
                JObject jwtDynamic = JsonConvert.DeserializeObject&amp;lt;JObject&amp;gt;(tokenString);
                var accessToken = jwtDynamic.Value&amp;lt;string&amp;gt;(&amp;quot;access_token&amp;quot;);
                var refreshToken = jwtDynamic.Value&amp;lt;string&amp;gt;(&amp;quot;refresh_token&amp;quot;);
                var expiresIn = jwtDynamic.Value&amp;lt;int&amp;gt;(&amp;quot;expires_in&amp;quot;);


                user.Token = accessToken;
                user.RefreshToken = refreshToken;
                user.ExpiresIn = DateTime.UtcNow.Add(new TimeSpan(0, 0, expiresIn));

                refreshSuccess = true;
            }

            return (refreshSuccess, user);
        }
        #endregion
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Initialize() 메서드에서 ClientId는 설정해주셔야됩니다.&lt;br&gt;
카카오 Devleoer에 방문하셔서 REST API key를 받아 작성해주시면 됩니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Kakao Developers&lt;/strong&gt;  &lt;br&gt;
&lt;a href="https://developers.kakao.com/"&gt;https://developers.kakao.com/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h6 id="servicesauthentication-fo"&gt;Services/Authentication Folder&lt;/h6&gt;
&lt;p&gt;&lt;strong&gt;IAuthenticationService.cs&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;using System.Threading.Tasks;
using [YourProjectName].Models;

namespace [YourProjectName].Services.Authentication
{
    public interface IAuthenticationService
    {
        bool IsAuthenticated { get; }

        User AuthenticatedUser { get; }

        Task&amp;lt;bool&amp;gt; LoginAsync(string email, string password);

        Task LoginWithSNSAsync(SNSProvider provider);

        Task&amp;lt;bool&amp;gt; UserIsAuthenticatedAndValidAsync();

        Task LogoutAsync();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;먼저 Auth interface를 정의해줍니다.
__ Authentication.cs__&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Xamarin.Auth;
using Xamarin.Forms;
using [YourProjectName].Models;
using [YourProjectName].Models.Providers;

namespace [YourProjectName].Services.Authentication
{
    public class AuthenticationService : IAuthenticationService
    {
        OAuth2Base oAuth2;

        public bool IsAuthenticated =&amp;gt; AppSettings.User != null;

        public User AuthenticatedUser =&amp;gt; AppSettings.User;

        public Task&amp;lt;bool&amp;gt; LoginAsync(string email, string password)
        {
            var user = new User
            {
                Email = email,
                Name = email,
                LastName = string.Empty,
                PictureUrl = &amp;quot;&amp;quot;,
                Token = email,
                LoggedInWithSNSAccount = false,
                Provider = SNSProvider.None
            };

            AppSettings.User = user;

            return Task.FromResult(true);
        }

        public Task LoginWithSNSAsync(SNSProvider provider)
        {
            try
            {
                oAuth2 = OAuth2ProviderFactory.CreateProvider(provider);
                var authenticator = new OAuth2Authenticator(
                    oAuth2.ClientId,
                    oAuth2.ClientSecret,
                    oAuth2.Scope,
                    oAuth2.AuthorizationUri,
                    oAuth2.RedirectUri,
                    oAuth2.RequestTokenUri,
                    null,
                    oAuth2.IsUsingNativeUI);

                authenticator.Completed += async (s, e) =&amp;gt;
                {
                    if (e.IsAuthenticated)
                    {
                        var user = await oAuth2.GetUserInfoAsync(e.Account);

                        AppSettings.User = user;
                        MessagingCenter.Send(user, MessengerKey.AuthenticationRequested, true);
                        Debug.WriteLine(&amp;quot;Authentication Success&amp;quot;);
                    }
                };
                authenticator.Error += (s, e) =&amp;gt;
                {
                    Debug.WriteLine(&amp;quot;Authentication error: &amp;quot; + e.Message);
                };

                var presenter = new Xamarin.Auth.Presenters.OAuthLoginPresenter();
                presenter.Login(authenticator);

            }
            catch (Exception ex)
            {
                Debug.WriteLine(&amp;quot;Login Error : &amp;quot; + ex.Message);
                return Task.FromResult(false);
            }
            return Task.FromResult(true);
        }

        public async Task&amp;lt;bool&amp;gt; UserIsAuthenticatedAndValidAsync()
        {
            if (!IsAuthenticated)
            {
                return false;
            }
            else if (!AuthenticatedUser.LoggedInWithSNSAccount)
            {
                return true;
            }
            else
            {
                bool refreshSucceded = false;
                oAuth2 = OAuth2ProviderFactory.CreateProvider(AuthenticatedUser.Provider);
                try
                {
                    var utcNow = DateTime.UtcNow.AddMinutes(30);
                    if (AuthenticatedUser.ExpiresIn &amp;lt; utcNow)
                    {
                        var ret = await oAuth2.RefreshTokenAsync(AuthenticatedUser);
                        if (ret.IsRefresh)
                        {
                            AppSettings.User = ret.User;
                        }
                        else
                        {
                            AppSettings.RemoveUserData();
                        }

                        refreshSucceded = ret.IsRefresh;
                    }
                    else
                    {
                        refreshSucceded = true;
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine($&amp;quot;Error with refresh attempt: {ex}&amp;quot;);
                }

                return refreshSucceded;
            }
        }

        public Task LogoutAsync()
        {
            AppSettings.RemoveUserData();
            return Task.FromResult(true);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;실제로 Auth 요청이 이루어지는 코드입니다.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;이전 코드 (참고에있는 이전 개발자분 깃헙 참고)에서 변화된 부분들은 다 작성했다.
이후 메인페이지 등을 정의하면된다. 필자의 경우 profile을 가져올 필요가 없는 프로젝트 이기에 원 개발자 분 코드에서 사용하는 FFImage를 사용하지 않았다.&lt;/p&gt;
&lt;hr&gt;
&lt;h6 id="etc"&gt;etc&lt;/h6&gt;
&lt;p&gt;추가로 안드로이드 인터넷 사용권한을 부여해야된다.&lt;/p&gt;
&lt;p&gt;방법은 안드로이드 네임스페이스에 마우스 오른쪽 - &amp;gt; 속성 -&amp;gt; Android 매니페스트 -&amp;gt; 필수권한 -&amp;gt; INTERNET 항목을 선택하면된다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Android MainActivity.cs&lt;/strong&gt;  &lt;br&gt;
Android 인터넷 사용권한&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/3//2021_11_3_13_PJPCCcGmA6Juu20jjmJS.jpg" src="/resources/media/images/content/2021/11/3//2021_11_3_13_PJPCCcGmA6Juu20jjmJS.jpg.preview.jpg" alt=""&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img class="lazy" data-src="/resources/media/images/content/2021/11/3//2021_11_3_13_GPz09yjcF9lXNTHLIVCN.jpg" src="/resources/media/images/content/2021/11/3//2021_11_3_13_GPz09yjcF9lXNTHLIVCN.jpg.preview.jpg" alt=""&gt;.&lt;/p&gt;
&lt;p&gt;❗ 메인 Oncreate 메서드에서  아래 코드를 추가하지 않는다면 화면이 로딩 중에서 넘어가지 않는 오류가 발생한다. 유의하도록 하자.&lt;br&gt;
&lt;code&gt;global::Xamarin.Auth.Presenters.XamarinAndroid.AuthenticationConfiguration.Init(this,savedInstanceState)&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;BLEX를 이틀 째 사용중으로 당분간은 BLEX위주로 작성하면서 장단점을 잴 예정이다.
필자는 다크모드를 자주 사용하는데, 일반모드에서는 코드블록이 크게 거슬리지 않으나 다크모드의 경우 색감이 보기에 불편하지 않을까싶다.&lt;/p&gt;
&lt;/blockquote&gt;
</description><pubDate>Wed, 03 Nov 2021 11:10:26 +0900</pubDate><guid>http://blex.me/@DevMinGeonPark/xamarin-form%EC%97%90%EC%84%9C-sns-%EC%9D%B8%EC%A6%9D%ED%95%98%EA%B8%B0</guid></item><item><title>블로그 플랫폼에 대한 생각, BLEX를 선택한 이유</title><link>http://blex.me/@DevMinGeonPark/%EB%B8%94%EB%A1%9C%EA%B7%B8-%ED%94%8C%EB%9E%AB%ED%8F%BC%EC%97%90-%EB%8C%80%ED%95%9C-%EC%83%9D%EA%B0%81-blex%EB%A5%BC-%EC%84%A0%ED%83%9D%ED%95%9C-%EC%9D%B4%EC%9C%A0-1</link><description>&lt;p&gt;학교생활도 어느정도 적응했고, 이전부터 계획하던 블로그를 시작하려고 했다. 과거에 운영하던 Tstory 블로그가 있지만, 꾸준히 운영한 것도 아니였고 무엇보다 디자인이 직관적으로 눈에 들어오지 않아 마음에 들지 않았었다. 앞으로 blex를 포함해 다양한 플랫폼을 시도해도면서 내게 맞는 블로그를 찾아보겠지만, 현재로써는 blex가 제일 마음에 들고, 만약 다른 블로그로 가게된다면 아마 Github 쪽에서 커스텀해서 운영하지 않을까 싶다. 이 글에서는 블로그를 선택한 기준과 블로그 플랫폼들에 대한 개인적인 의견을 적어보려한다.&lt;/p&gt;
&lt;h4 id="블로그-선택-기준"&gt;블로그 선택 기준&lt;/h4&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;markdown을 지원해야함.&lt;/li&gt;
&lt;li&gt;디자인이 마음에 들어야함. (Simple is Bast)&lt;/li&gt;
&lt;li&gt;글 내용 쪽에 목차를 제공해야함&lt;/li&gt;
&lt;li&gt;깃허브처럼 글을 쓴 것에 대한 표시가 있었으면 좋겠음. (ex 잔디)&lt;/li&gt;
&lt;li&gt;전체적으로 가독성이 뛰어났으면 좋겠음 (코드, 글)&lt;/li&gt;
&lt;li&gt;검색 노출이 좋았으면 좋겠음.&lt;/li&gt;
&lt;li&gt;커스텀 자유도&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h4 id="tistory"&gt;Tistory&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;개인적으로 서브 블로그(검색유입용?)으로 생각 고려 중&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;선택기준에 부합하는가?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Markdown을 지원하기는 하나 뭔가 부족한 느낌.&lt;/li&gt;
&lt;li&gt;커스텀이 가능하다고는 하나 마음에 들지 않음. 마음가는게 없음.&lt;/li&gt;
&lt;li&gt;제공하지 않음. (커스텀은 가능한걸로 알고있음.)&lt;/li&gt;
&lt;li&gt;없음.&lt;/li&gt;
&lt;li&gt;가독성은 깔끔해서 나쁘지않으나 커스텀에 따라 다름, 개인적으로는 맘에안듬.&lt;/li&gt;
&lt;li&gt;검색 노출은 좋은 편이라고 생각됨.&lt;/li&gt;
&lt;li&gt;깃헙 블로그에 비해서는 떨어지지만 나름 높은 편&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h4 id="velog"&gt;Velog&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;마음에 드는 편이나, 필요한 기능들이 없는 편, BLEX를 제외하면 제일 좋긴했음.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;선택기준에 부합하는가?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Markdown 지원.&lt;/li&gt;
&lt;li&gt;깔끔한 디자인, 개인적으로 만족하나 몇몇부분은 고쳤으면 좋겠음.&lt;/li&gt;
&lt;li&gt;제공함. 매우 심플 마음에듬.&lt;/li&gt;
&lt;li&gt;없음.&lt;/li&gt;
&lt;li&gt;깔끔&lt;/li&gt;
&lt;li&gt;최근에는 많이 선택되는 편이라 그런지 꽤 노출이 잘되는 편.&lt;/li&gt;
&lt;li&gt;커스텀은 불가능한 걸로 알고 있음.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h4 id="github"&gt;Github&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;커스텀은 최고. 하지만 개발 능력이 부족.&lt;/li&gt;
&lt;li&gt;Hugo base로 개발을 진행하다가 현실적으로 아직 쉽지않은걸 느끼고 선회.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;선택기준에 부합하는가?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Markdown 지원.&lt;/li&gt;
&lt;li&gt;커스텀 그 자체.&lt;/li&gt;
&lt;li&gt;커스텀하면 가능.&lt;/li&gt;
&lt;li&gt;깃허브 연동이니 깃허브 잔디를 보면 됨. 따로는 구현해야할 듯.&lt;/li&gt;
&lt;li&gt;커스텀 가능.&lt;/li&gt;
&lt;li&gt;검색 노출은 모르겠음.&lt;/li&gt;
&lt;li&gt;커스텀 자유도는 최고.
(추가) github.io로 배포할 경우 정적 웹만 가능하여 아쉬운 점도 많음.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h4 id="blex"&gt;BLEX&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;개인적으로 보자마자 반했습니다. 디자인이 취향저격.&lt;/li&gt;
&lt;li&gt;필요했던 기능들은 다 가진 형태로 만족하는 중&lt;/li&gt;
&lt;li&gt;현재로써는 최선의 선택.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;선택기준에 부합하는가?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Markdown 지원.&lt;/li&gt;
&lt;li&gt;취향저격&lt;/li&gt;
&lt;li&gt;마음에 듬. 단지 글이 길어지면 짤리는 경향이 있는걸로 보임.&lt;/li&gt;
&lt;li&gt;취향 저격&lt;/li&gt;
&lt;li&gt;가독성 good&lt;/li&gt;
&lt;li&gt;티스토리 등에 비해서는 떨어지나 깃허브와 비슷하다고 봄.&lt;/li&gt;
&lt;li&gt;커스텀의 자유도는 없지만 소스가 공개되어 있어 어느정도 후에는 개인 블로그로 변경한다면 참고가능.
(추가) 현재로써는 메인 블로그로 고려 중&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;blex 잔디를 보면서 1일 1커밋하듯 1일 1 블로그하면 좋겠다. 부지런히 공부하자.
아직 글쓰는건 어색하고 어려운 일인 것 같습니다. 노력해야겠죠!
(!) 아직 마크다운에 익숙하지 않아 남들처럼 예쁘게는 못적겠다. 공부해야할 듯 :)&lt;/p&gt;
</description><pubDate>Tue, 02 Nov 2021 23:36:07 +0900</pubDate><guid>http://blex.me/@DevMinGeonPark/%EB%B8%94%EB%A1%9C%EA%B7%B8-%ED%94%8C%EB%9E%AB%ED%8F%BC%EC%97%90-%EB%8C%80%ED%95%9C-%EC%83%9D%EA%B0%81-blex%EB%A5%BC-%EC%84%A0%ED%83%9D%ED%95%9C-%EC%9D%B4%EC%9C%A0-1</guid></item></channel></rss>