<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개발자 로그: 변화를 위한 공간</title>
    <link>https://walkingplow.tistory.com/</link>
    <description>개발자 성장 로그</description>
    <language>ko</language>
    <pubDate>Sun, 28 Jun 2026 14:56:19 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>휘 Hwi</managingEditor>
    <image>
      <title>개발자 로그: 변화를 위한 공간</title>
      <url>https://tistory1.daumcdn.net/tistory/5131897/attach/294a63a5a3734c16865ea5c3f06085b4</url>
      <link>https://walkingplow.tistory.com</link>
    </image>
    <item>
      <title>좋은 API 문서 작성 방법</title>
      <link>https://walkingplow.tistory.com/94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;API 문서는 개발자와 사용자가 원활하게 API를 파악하고 사용할 수 있도록 돕는 문서&lt;/b&gt;&lt;span&gt;입니다.&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;b&gt;API 문서는 API의 기능을 분명하게 명시하고, 사용 방법과 관련 오류를 살펴볼 수 있게 해야&lt;/b&gt; 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일부 개발자들은 API 문서의 중요성을 간과하기도 합니다. 그러나 문서가 없다면 다른 사람들이 코드를 이해하는 데 많은 시간이 걸릴 것입니다. 개발자의 업무가 많은 경우에는 기술 문서를 작성하는 테크니컬 라이터가 이를 전문적으로 담당하기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오늘날 API 문서는 상품과 서비스의 일부로 간주되며 사용자 경험에도 중요한 영향&lt;/b&gt;을 미칩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글은 &lt;a href=&quot;https://www.writethedocs.org/guide/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&amp;lt;Write the Docs&amp;gt;&lt;/a&gt;를 참고하였으며, API 문서를 작성하는 데 필요한 6가지 고려 사항을 담고 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 개발을 시작하기 전에 문서를 작성하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;개발을 시작하기 전에 문서를 먼저 작성하는 것을 고려&lt;/b&gt;해보시기 바랍니다. 개발을 하지 않았는데 어떻게 문서를 작성할 수 있을까 싶지만, 해당 API가 어떤 기능을 할 것이며 이를 위해 사전에 필요한 사항들을 정리하는 것만으로도 유용합니다. 이를 통해 API 개발의 방향을 명확히 할 수 있으며, 문서 초안을 동료들에게 공유하고 피드백을 받을 수도 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 두괄식으로 명시하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;API 문서의 첫 부분에는 해당 API가 정확히 어떤 작업을 위한 것인지 개괄적으로 명시&lt;/b&gt;해야 합니다. 이를 통해 문서에 접근한 이들은 해당 문서가 본인에게 필요한 것인지 판단할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 개발한 API 문서에는 아주 다양한 기능들이 포함되어 있을 것입니다. API 호출에 필요한 인증, 헤더 타입 등 &lt;b&gt;이를 처음 보는 사용자가 어디서부터 어떻게 시작해야 하는지 기초적인 사항들을 도입부에서 설명&lt;/b&gt;하는 것이 좋습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 문서를 읽는 대상자를 고려하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API 문서를 읽는 대상은 크게 개발자와 사용자로 나눌 수 있습니다. &lt;b&gt;개발자와 사용자를 모두 고려하여 문서를 작성&lt;/b&gt;해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자들은 자신이 원하는 부분을 문서에서 빠르게 탐색하고 테스트하기를 원합니다. 이를 위해 &lt;b&gt;일관적인 문서 구조와 예시를 제공&lt;/b&gt;할 필요가 있습니다. 세부 사항으로는 일관적인 헤딩 사용, 하이퍼링크 제공, 문단 나누기 및 리스트 활용을 고려할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자들의 수준은 초보에서 고급까지 다양할 수 있습니다. &lt;b&gt;초보 수준의 사용자를 염두에 두되 고급 사용자도 원하는 정보를 정확하게 얻을 수 있도록&lt;/b&gt; 해야 합니다. 즉, &lt;b&gt;필수적인 정보들을 정확하게 담되 가능한 쉬운 용어를 사용&lt;/b&gt;하는 것이 좋습니다. API 문서는 개발 지식이 없는 사람이 보더라도 이해할 수 있을 정도로 쉽고 간결하게 작성되어야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 예시를 포함하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 개발자들은 API 문서에서 안내하는 예시 코드를 복사 및 붙여넣기 하여 사용하기를 선호합니다. 이를 통해 테스트를 진행하고, 필요에 맞춰 수정해서 빠르게 사용할 수 있기 때문입니다. &lt;b&gt;API의 핵심 엔드포인트를 테스트할 수 있는 예시를 제공하는 것이 좋습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 &lt;b&gt;응답 성공 예시와 에러 예시를 첨부&lt;/b&gt;해야 합니다 이 때 모든 에러가 아닌 가장 대표적인 에러들만 첨부하는 것이 좋습니다. 그렇지 않으면 문서가 너무 길어질 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 좋은 API 문서 참고하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 많은 기업들이 좋은 API 문서를 작성하여 제공하고 있습니다. 아래 사이트에 접속하여 &lt;b&gt;좋은 API 문서로 언급되는 예시들을 참고&lt;/b&gt;해보실 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Stripe: &lt;a href=&quot;https://stripe.com/docs&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://stripe.com/docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Google: &lt;a href=&quot;https://developers.google.com/gmail&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developers.google.com/gmail&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 충분한 시간을 들이기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 API 작성에는 시간이 필요합니다. API 문서는 개발자와 사용자를 위한 단순한 설명서가 아니라 상품의 일부이기도 합니다. &lt;b&gt;API 작성을 위해 충분한 시간을 확보&lt;/b&gt;해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사의 팀에서 일하고 있다면 다른 개발자 뿐만 아니라 기술 문서 작성자와 함께 문서에 대해 충분히 논의하는 것이 좋습니다. 만약, 팀 내부에서 &lt;b&gt;문서를 이해하지 못하는 사람이 있다면 개선이 필요하다는 의미&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API 문서는 한 번 작성하면 마무리 되는 작업이 아닙니다. &lt;b&gt;개발자와 사용자의 피드백을 반영하여 계속해서 문서를 업데이트&lt;/b&gt;해야 합니다&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상으로 좋은 API 문서 작성을 위한 사항들을 살펴봤습니다. 이를 정리하면 다음과 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&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;좋은 API 문서 참고하기&lt;/li&gt;
&lt;li&gt;충분한 시간을 들이기&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>101</category>
      <category>API 문서 작성</category>
      <author>휘 Hwi</author>
      <guid isPermaLink="true">https://walkingplow.tistory.com/94</guid>
      <comments>https://walkingplow.tistory.com/94#entry94comment</comments>
      <pubDate>Wed, 20 Apr 2022 09:50:41 +0900</pubDate>
    </item>
    <item>
      <title>깃 에러 해결: Permission denied (publickey) - TIL 12</title>
      <link>https://walkingplow.tistory.com/93</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;깃에서 새롭게 리포지토리를 생성하고 푸시를 하려는데 권한 없음(Permission denied) 오류가 발생했습니다. 깃허브 블로그에서 관련 문제 해결 방법을 참조하여 에러를 해결할 수 있었습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정확한 서버로 연결을 시도 중인지 확인하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확한 도메인으로 접속하고 있는지 확인하고자 한다면 터미널에 아래 명령어를 입력합니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;$ ssh -vT git@github.com
&amp;gt; OpenSSH_8.1p1, LibreSSL 2.7.3
&amp;gt; debug1: Reading configuration data /Users/you/.ssh/config
&amp;gt; debug1: Reading configuration data /etc/ssh/ssh_config
&amp;gt; debug1: /etc/ssh/ssh_config line 47: Applying options for *
&amp;gt; debug1: Connecting to github.com port 22.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연결 포트가 22로 설정되어 있다면 정확한 서버로 연결을 시도 중입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;깃 사용자 이메일로 로그인하고 있는지 확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깃에서는 모든 접속을 시도할 때 깃 사용자의 이메일 주소를 사용해야 합니다. 사용자 이름을 사용하고 있는지 확인하고, 다음 명령어를 통해 접속을 시도해봅니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;$ ssh -T GITHUB-USERNAME@github.com
&amp;gt; Permission denied (publickey).&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사용 중인 키 확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널을 열고 프라이빗 키가 생성되어 있으며 SSH에 로그되어 있는지 확인합니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# start the ssh-agent in the background
$ eval &quot;$(ssh-agent -s)&quot;
&amp;gt; Agent pid 59566
$ ssh-add -l -E sha256
&amp;gt; 2048 SHA256:274ffWxgaxq/tSINAykStUL7XWyRNcRTlcST1Ei7gBQ /Users/USERNAME/.ssh/id_rsa (RSA)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 &lt;code&gt;ssh-add&lt;/code&gt; 명령어를 통해 문자열이 반환되지 않는다면, 새로운 SSH 키를 추가하고 이를 깃허브와 연동해주어야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SSH 키 생성하기&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;터미널을 열고 깃허브 이메일 주소를 사용하여 키를 생성합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;$ ssh-keygen -t ed25519 -C &quot;your_email@example.com&quot;
&amp;gt; Generating public/private algorithm key pair.
&amp;gt; Enter a file in which to save the key (/Users/you/.ssh/id_algorithm): [Press enter]
&amp;gt; Enter passphrase (empty for no passphrase): [Type a passphrase]
&amp;gt; Enter same passphrase again: [Type passphrase again]&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ssh-agent에 생성한 키를 추가합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;$ eval &quot;$(ssh-agent -s)&quot;
&amp;gt; Agent pid 59566
$ ssh-add -K ~/.ssh/id_ed25519&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;깃허브 &lt;a href=&quot;https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Pofile - Settings로 이동하여 SSH Key를 추가&lt;/a&gt;해줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;연결 재확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 다시 연결을 시도해봅니다. 접속에 성공한다면 다음과 같은 메시지가 표시됩니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;$ ssh -T git@github.com
&amp;gt; Hi username! You've successfully authenticated...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고 자료&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.github.com/en/authentication/troubleshooting-ssh/error-permission-denied-publickey&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Error: Permission denied (publickey)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Generating a new SSH key and adding it to the ssh-agent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Adding a new SSH key to your GitHub account&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>TIL</category>
      <category>깃 ssh</category>
      <category>깃 에러 해결</category>
      <category>깃 오류</category>
      <category>깃 퍼블릭 키 등록</category>
      <author>휘 Hwi</author>
      <guid isPermaLink="true">https://walkingplow.tistory.com/93</guid>
      <comments>https://walkingplow.tistory.com/93#entry93comment</comments>
      <pubDate>Sat, 9 Apr 2022 20:28:54 +0900</pubDate>
    </item>
    <item>
      <title>HTML 새 탭에서 열기 방법과 탭내빙 공격</title>
      <link>https://walkingplow.tistory.com/92</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;HTML 링크를 클릭하면 대부분 새 탭에서 링크가 열립니다. 이를 통해 사용자는 기존의 페이지를 유지하며, 새로운 탭에서 브라우징을 계속할 수 있는 장점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서는 HTML 요소에 링크를 지정하는 방법, 새 탭에서 여는 방법, 이와 관련된 탭내빙 공격에 대해 알아보도록 하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;요소에 링크 적용하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;텍스트 또는 이미지 요소에 웹페이지 링크를 적용하기 위해서는 &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; 앵커 요소와 &lt;code&gt;href&lt;/code&gt; 속성을 사용합니다.&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;&amp;lt;p&amp;gt;Please check &amp;lt;a href=&quot;https://walkingplow.tistory.com&quot;&amp;gt;my website&amp;lt;a&amp;gt;.&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크를 클릭하면 브라우저는 현재 탭에서 해당 URL로 이동하게 됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;링크를 새 탭에서 열기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에 &lt;code&gt;target=&quot;_blank&quot;&lt;/code&gt; 속성을 추가하면 링크를 새 탭에서 열도록 할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;&amp;lt;p&amp;gt;Please check &amp;lt;a href=&quot;https://walkingplow.tistory.com&quot; target=&quot;_blank&quot;&amp;gt;my website&amp;lt;a&amp;gt;.&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크를 클릭하면 브라우저는 새 탭에서 해당 URL을 새롭게 열게 됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;target=&amp;rdquo;_blank&amp;rdquo;와 관련된 보안 위험&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크를 새 탭으로 여는 &lt;code&gt;target=&quot;_blank&quot;&lt;/code&gt;는 유용한 방법이지만, 탭내빙(Tabnabbing)이라는 보안 위험이 존재합니다. 탭내빙이란 HTML 문서 내의 링크를 클릭할 때, 기존 문서의 위치를 피싱 사이트로 변경하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 방지하기 위해서는 다음과 같이 추가적인 속성 &lt;code&gt;rel=&quot;noreferrer noopener&quot;&lt;/code&gt;을 지정해주어야 합니다.&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;&amp;lt;p&amp;gt;Please check &amp;lt;a href=&quot;https://walkingplow.tistory.com&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&amp;gt;my website&amp;lt;a&amp;gt;.&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;탭내빙이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;탭내빙은 &lt;code&gt;tagert=&quot;_blank&quot;&lt;/code&gt; 속성을 통해 브라우저 이벤트가 발생할 때, &lt;code&gt;window.object&lt;/code&gt; API를 통해 페이지 일부 권한을 획득하는 공격 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공격자는 탭내빙을 통해 새 탭으로 이동하게 한 기존 웹페이지를 다른 페이지로 리다이렉션 시킬 수 있습니다. 대부분의 사용자는 새롭게 열린 탭에 관심을 갖고 있기 때문에, 기존의 웹페이지가 변경된 것을 눈치채지 못할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가짜 웹사이트로 사용자가 다시 돌아와 로그인을 하거나 민감한 정보를 입력하게 될 경우, 공격자는 해당 정보를 가로챌 수도 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML 페이지에서 링크를 새 탭에서 열려면 &lt;code&gt;traget=&quot;_blank&quot;&lt;/code&gt; 속성을 사용할 수 있습니다. 그러나 이를 단독으로 사용하면 탭내빙 공격에 노출될 수 있으며, 따라서 &lt;code&gt;rel=&quot;noreferrer noopener&quot;&lt;/code&gt; 속성을 추가로 지정해주는 것이 좋습니다.&lt;/p&gt;</description>
      <category>HTML | CSS</category>
      <category>href</category>
      <category>html</category>
      <category>target=&amp;quot;_blank&amp;quot;</category>
      <category>새 탭에서 열기</category>
      <category>탭내빙</category>
      <author>휘 Hwi</author>
      <guid isPermaLink="true">https://walkingplow.tistory.com/92</guid>
      <comments>https://walkingplow.tistory.com/92#entry92comment</comments>
      <pubDate>Sat, 9 Apr 2022 18:45:51 +0900</pubDate>
    </item>
    <item>
      <title>CSS 요소 크기 설정: 절대적, 상대적 지정 방법</title>
      <link>https://walkingplow.tistory.com/91</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;CSS에서는 절대적 또는 상대적 크기 설정 방법으로 요소의 길이와 크기를 지정할 수 있습니다. 절대적 설정 속성으로는 &lt;code&gt;px&lt;/code&gt;, &lt;code&gt;cm&lt;/code&gt;, &lt;code&gt;in&lt;/code&gt; 등이 있으며, 상대적 설정 속성으로는 &lt;code&gt;em&lt;/code&gt;, &lt;code&gt;rem&lt;/code&gt; 등이 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;CSS 요소 크기 절대적 설정 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;절대적 설정은 요소의 실제 크기를 기준으로 하며, 모든 디바이스에서 동일하게 표현되는 것을 목표로 합니다. 물론, 디바이스에 따라 실제 표현에는 약간의 차이가 발생할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;px&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;px&lt;/code&gt; 또는 픽셀은 CSS에서 요소 크기를 설정하는 가장 일반적인 방법입니다. 1 픽셀은 1/96 인치를 의미하며, 다른 모든 절대적 길이 요소들은 1 픽셀을 기준으로 삼습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 픽셀이 처음 도입되었을 때는 모니터의 크기가 1024 x 768이었으며, 96 DPI(dots per inch)가 표준이었습니다. 즉, &lt;code&gt;1px = 1/96in&lt;/code&gt;은 당시를 기준으로 한 것입니다. 시간이 지나며 디바이스의 해상력이 높아졌지만, 여전히 당시의 1 픽셀을 기준으로 요소의 기본 크기를 지정하고 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;cm / mm&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;cm&lt;/code&gt; 또는 센티미터로 &lt;code&gt;1cm&lt;/code&gt;는 &lt;code&gt;37.8px&lt;/code&gt; 정도에 해당합니다. &lt;code&gt;mm&lt;/code&gt; 또는 밀리미터는 &lt;code&gt;1cm&lt;/code&gt;의 10분의 1인 &lt;code&gt;0.1cm&lt;/code&gt;에 해당합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;in / pt /pc&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;in&lt;/code&gt; 또는 인치는 대략 &lt;code&gt;96px&lt;/code&gt;에 해당합니다. &lt;code&gt;pt&lt;/code&gt; 또는 포인트는 &lt;code&gt;1.3333px&lt;/code&gt;에 해당하며, &lt;code&gt;pc&lt;/code&gt; 또는 피카스는 대략 &lt;code&gt;16px&lt;/code&gt;에 해당합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;CSS 요소 크기 상대적 설정 방법&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;em&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;em&lt;/code&gt;은 상위 부모 요소를 기준으로 크기를 결정합니다. 다음과 같이 &lt;code&gt;font-size: 1.5em;&lt;/code&gt;이 설정된 경우, 이는 상위 요소를 기준으로 1.5배의 폰트 사이즈로 설정됩니다.&lt;/p&gt;
&lt;pre class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;html {
  font-size: 20px
}

body {
  font-size: 1.5em;
}

p {
  font-size: 1.5em;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 CSS에서 &lt;code&gt;body&lt;/code&gt; 태그는 &lt;code&gt;html&lt;/code&gt; 태그를 기준으로 1.5배의 폰트 사이즈가 적용(&lt;code&gt;30px&lt;/code&gt;)되며, &lt;code&gt;p&lt;/code&gt; 태그는 부모 태그인 &lt;code&gt;body&lt;/code&gt;의 1.5배의 폰트 사이즈(&lt;code&gt;45px&lt;/code&gt;)가 적용됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;rem&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;rem&lt;/code&gt;은 Root &lt;code&gt;em&lt;/code&gt;을 의미하며 문서의 최상위 요소인 &lt;code&gt;html&lt;/code&gt; 요소를 기준으로 크기를 결정합니다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;html {
  font-size: 20px
}

body {
  font-size: 1.5em;
}

p {
  font-size: 1.5rem;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 동일한 상황에서 &lt;code&gt;p&lt;/code&gt; 태그의 폰트 사이즈를 &lt;code&gt;1.5rem&lt;/code&gt;으로 변경한 경우, &lt;code&gt;body&lt;/code&gt;요소가 아닌 최상위 요소인 &lt;code&gt;html&lt;/code&gt; 태그를 기준으로 1.5배의 폰트 사이즈인 &lt;code&gt;30px&lt;/code&gt;이 적용됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;%&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퍼센트는 부모 요소를 기준으로 상대적인 크기를 설정하는 방법입니다. 아래와 같이 CSS를 적용한 경우, &lt;code&gt;div&lt;/code&gt; 내 &lt;code&gt;p&lt;/code&gt;요소는 &lt;code&gt;200px&lt;/code&gt;의 절반인 &lt;code&gt;100px&lt;/code&gt; 크기를 갖게 됩니다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;div {
  width: 200px;
}

div p {
  width: 50%;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;vw&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;vw&lt;/code&gt;는 View Width를 의미하며, &lt;code&gt;1vw&lt;/code&gt;는 뷰포트 너비의 1%에 해당합니다. 즉, 다음과 같이 &lt;code&gt;100vw&lt;/code&gt;를 적용한 경우, 뷰포트 너비의 100%를 의미합니다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;body {
  width: 100vw;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 디바이스의 뷰포트에 따라 &lt;code&gt;body&lt;/code&gt; 요소의 전체 너비가 달라지는 것을 의미합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;vh&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;vh&lt;/code&gt;는 View Height를 의미하며, &lt;code&gt;1vh&lt;/code&gt;는 뷰포트 높이의 1%에 해당합니다. 아래의 경우 &lt;code&gt;div&lt;/code&gt; 요소는 뷰포트 높이의 50%를 차지하게 됩니다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;div {
  height: 50vh;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>HTML | CSS</category>
      <category>css</category>
      <category>요소 상대 크기</category>
      <category>요소 절대 크기</category>
      <category>요소 크기 설정</category>
      <author>휘 Hwi</author>
      <guid isPermaLink="true">https://walkingplow.tistory.com/91</guid>
      <comments>https://walkingplow.tistory.com/91#entry91comment</comments>
      <pubDate>Sat, 9 Apr 2022 17:41:52 +0900</pubDate>
    </item>
    <item>
      <title>쿠버네티스 기초 (1): 쿠버네티스의 개념과 사용 이유</title>
      <link>https://walkingplow.tistory.com/90</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;쿠버네티스의 개념&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠버네티스는 애플리케이션을 컨테이너화하여 관리 및 배포할 수 있도록 하는 확장 가능한 오픈 소스 플랫폼입니다. 컨테이너화는 각 애플리케이션이 동일한 OS를 공유하되, 별도의 독립된 공간에서 실행되도록 하는 것입니다. 이를 통해 서버의 유휴 자원을 효율적으로 관리할 수 있으며, 애플리케이션의 빠른 배포 및 관리가 가능합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;쿠버네티스를 사용하는 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠버네티스를 사용하는 이유는 무엇일까요? 이를 이해하기 위해서는 컨테이너식 배포 방법 중 하나인 쿠버네티스 이전의 물리적 서버 및 가상 머신 배포 방식을 살펴볼 필요가 있습니다. 아래 그림은 세 가지 배포 방식의 차이점을 시각적으로 정리한 것입니다. 이어지는 글은 그림에 대한 부가 설명입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2022-04-07 at 3.37.28 PM.png&quot; data-origin-width=&quot;1158&quot; data-origin-height=&quot;472&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c084lm/btryJvZOs1m/gpljTbwvKTfPZMUDglscq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c084lm/btryJvZOs1m/gpljTbwvKTfPZMUDglscq1/img.png&quot; data-alt=&quot;물리적 서버 배포, 가상 머신 배포, 컨테이너 배포의 차이점&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c084lm/btryJvZOs1m/gpljTbwvKTfPZMUDglscq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc084lm%2FbtryJvZOs1m%2FgpljTbwvKTfPZMUDglscq1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1158&quot; height=&quot;472&quot; data-filename=&quot;Screen Shot 2022-04-07 at 3.37.28 PM.png&quot; data-origin-width=&quot;1158&quot; data-origin-height=&quot;472&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;물리적 서버 배포, 가상 머신 배포, 컨테이너 배포의 차이점&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;물리적 서버 배포&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초창기 애플리케이션은 물리적 서버 위에 배포되었습니다. 실제 물리적 서버에서는 애플리케이션을 위한 리소스 영역을 규정할 방법이 없었고, 리소스 할당 문제가 발생했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 하나의 서버 위에서 여러 애플리케이션이 작동하고 있을 경우, 하나의 애플리케이션이 대부분의 리소스를 차지하고 있을 수 있습니다. 그 결과 다른 애플리케이션의 성능이 떨어지게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해 각 애플리케이션을 서로 다른 물리적 서버에서 실행할 수도 있지만, 예상대로 사용되지 않는 유휴 리소스가 존재할 것이며 비용이 낭비될 것입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;가상화 배포&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물리적 서버 배포에 대한 해결책으로 가상화 배포가 도입되었습니다. 이는 하나의 물리적 서버 CPU에 다수의 가상 머신(Virtual Machine)을 구축하는 방법입니다. 가상화를 통해 각 애플리케이션은 가상 머신들 위에서 독립적으로 구동됩니다. 위 그림에서 보듯, 기본 운영 시스템 위에 가상 머신 운영 체제가 구축됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 하나의 물리적 서버에서 리소스를 활용하는 것보다 효과적인 운영을 지원합니다. 또한 각 애플리케이션을 간편하게 추가 및 업데이트 할 수 있기 때문에 확장성이 개선됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;컨테이너 배포&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너(Container)는 가상 머신과 유사하지만 위 그림에서 보듯 각 애플리케이션은 동일한 운영 시스템(OS)을 공유합니다. 결과적으로 컨테이너는 VM에 비해 가볍습니다. 컨테이너는 가상 머신과 마찬가지로 자체 파일 시스템을 갖추고 있으며, CPU와 메모리, 처리 공간을 공유합니다. 기반이 되는 인프라와 분리되어 있기 때문에 클라우드나 OS 배포에 용이합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠버네티스와 같은 컨테이너 배포 방식은 다음과 같은 장점을 갖고 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;빠른 애플리케이션 생성 및 배포: 가상 머신 이미지에 비해 간편하고 효과적인 이미지 생성&lt;/li&gt;
&lt;li&gt;지속적인 개발, 통합, 배포: 이미지 불변성을 통해 안정적이고 주기적인 컨테이너 이미지 구축 및 배포와 효과적인 롤백&lt;/li&gt;
&lt;li&gt;클라우드 및 OS 배포 용이: 우분투, RHEL, 주요 퍼블릭 클라우드 등 어디에서나 구동&lt;/li&gt;
&lt;li&gt;독립적인 배포 및 관리: 애플리케이션은 독립적인 단위로 세분화되어 동적인 배포와 관리가 가능&lt;/li&gt;
&lt;li&gt;자원 분리와 활용: 애플리케이션 퍼포먼스를 예측하고 효과적으로 자원을 활용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고 자료: &lt;a href=&quot;https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/&lt;/a&gt;&lt;/p&gt;</description>
      <category>Kubernetest</category>
      <category>가상 머신</category>
      <category>배포</category>
      <category>서버</category>
      <category>애플리케이션</category>
      <category>컨테이너</category>
      <category>쿠버네티스</category>
      <author>휘 Hwi</author>
      <guid isPermaLink="true">https://walkingplow.tistory.com/90</guid>
      <comments>https://walkingplow.tistory.com/90#entry90comment</comments>
      <pubDate>Thu, 7 Apr 2022 15:51:40 +0900</pubDate>
    </item>
    <item>
      <title>커맨드 라인 터미널 기본 개념 설명</title>
      <link>https://walkingplow.tistory.com/89</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;커맨드 라인 또는 CLI(Command Line Interface)는 컴퓨터에게 실행할 명령(커맨드)을 입력하는 공간입니다. 우리가 흔히 알고 있는 터미널(Terminal)과 동일한 개념으로 두 가지 용어는 호환해서 사용할 수 있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 &lt;a href=&quot;https://www.freecodecamp.org/news/command-line-for-beginners/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Command Line for Beginners, FreeCodeCamp&lt;/a&gt;의 일부를 번역 및 정리한 글입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 컴퓨터 운영 체제는 CLI와 GUI(Graphic User Interface)를 제공하며 다음과 같은 차이점이 존재합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CLI: 컴퓨터가 작업을 수행할 수 있는 커맨드를 텍스트로 입력하는 인터페이스입니다.&lt;/li&gt;
&lt;li&gt;GUI: 그래픽 사용자 인터페이스를 의미하며, 사용자가 화면을 보고 클릭하면 해당하는 작업이 실행됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;터미널을 사용하는 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 살펴본 것처럼 대부분의 운영체제는 GUI라는 간편한 인터페이스를 제공합니다. 화면에서 아이콘을 클릭하면, 폴더가 열리거나 파일이 실행되는 아주 간편한 인터페이스입니다. 그렇다면 굳이 복잡한 터미널을 사용해야 할까요?&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;효율성 때문입니다. GUI에서는 여러 번의 클릭이 필요한 작업을 CLI에서는 하나의 커맨드로 처리할 수 있습니다. 따라서 CLI에 익숙해지면 더 빠르게 작업을 수행할 수 있습니다.&lt;/li&gt;
&lt;li&gt;CLI를 통해 작업을 더 쉽게 자동화할 수 있기 때문입니다. 특정 작업을 수행하는 스크립트를 짠 다음, 원하는 때에 자동으로 실행되도록 할 수 있습니다.&lt;/li&gt;
&lt;li&gt;때로는 CLI를 통해서만 컴퓨터와 상호작용할 수 있기 때문입니다. 예를 들어, 클라우드 플랫폼 서버와 통신하는 경우 GUI를 사용할 수 없는 경우가 많습니다. 이 때는 CLI 커맨드를 사용해야만 합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다양한 셸의 종류들&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셸(shell)은 CLI 역할을 하는 프로그램을 의미합니다. 각 셸은 서로 다른 문법과 특성을 갖고 있습니다. 맥이나 리눅스의 경우에는 Bash라는 기본 셸을 지원하며, Zsh는 Bash를 개선한 셸입니다. 윈도우는 기본적으로 Powrshell을 지원합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기본 커맨드 사용 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLI의 개념과 사용 이유에 대해 알아봤으니 이제 몇 가지 간단한 커맨드를 알아보도록 하겠습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;echo&lt;/code&gt;: 터미널에 전달하는 파라미터가 출력됩니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pwd&lt;/code&gt;: 현재 작업 디렉토리가 출력됩니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ls&lt;/code&gt;: 현재 디렉토리의 콘텐츠 목록이 출력됩니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;ls -a&lt;/code&gt;: 현재 디렉토리의 숨겨진 파일과 디렉토리가 출력됩니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ls -al&lt;/code&gt;: 현재 디렉토리의 모든 파일과 디렉토리가 출력됩니다(숨김 파일 포함).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd&lt;/code&gt;: 디렉토리 위치를 변경할 수 있습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;cd Desktop&lt;/code&gt;: 데스크톱 디렉토리로 이동합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd ..&lt;/code&gt;: 상위 디렉토리로 이동합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd&lt;/code&gt; : 홈 디렉토리로 이동합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mkdir&lt;/code&gt;: 새로운 디렉토리를 생성합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;mkdir test&lt;/code&gt; : test라는 이름의 디렉토리를 생성합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rmdir&lt;/code&gt;: 디렉토리를 삭제합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;rmdir test&lt;/code&gt;: test 디렉토리를 삭제합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;touch&lt;/code&gt;: 새로운 파일을 생성합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;touch test.txt&lt;/code&gt;: test.txt 파일을 생성합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rm&lt;/code&gt;: 파일을 삭제합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;rm test.txt&lt;/code&gt;: test.txt 파일을 삭제합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cp&lt;/code&gt;: 디렉토리 또는 파일을 복사합니다. 다음과 같이 두 가지 파라미터를 받습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;cp test.txt testCopy.txt&lt;/code&gt;: test.txt 파일을 복사하여 testCopy.txt에 복사합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cp test.txt ./testFolder/testCopy.txt&lt;/code&gt;: test.txt 파일을 복사하여 testFolder 디렉토리에 testCopy.txt로 복사합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mv&lt;/code&gt;: 디렉토리 또는 파일을 이동합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;mv test.txt ./testFolder/&lt;/code&gt;: testFolder로 test.txt 파일을 이동합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mv test.txt /.testFolder/testCopy.txt&lt;/code&gt;: 해당 디렉토리로 파일을 이동하며 이름을 testCopy.txt로 바꿉니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;head&lt;/code&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;head test.txt&lt;/code&gt;: test.txt 파일의 첫 부분을 출력합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tail&lt;/code&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;tail test.txt&lt;/code&gt;: test.txt 파일의 가장 마지막 부분을 출력합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--help&lt;/code&gt;: 특정 커맨드를 사용하는 방법을 출력합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;cd --help&lt;/code&gt;: cd 커맨드와 사용 방법이 출력됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;man&lt;/code&gt;: 특정 커맨드와 관련된 상세 도움말을 출력합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;man cd&lt;/code&gt;: cd 커맨드와 관련된 상세 정보가 출력됩니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;man bash&lt;/code&gt;: bash 셸에 관련된 모든 도움말이 출력됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널을 처음 접하면 친절하지 않은 인터페이스에 당황스러울 수도 있습니다. 그러나 커맨드 라인은 시간을 갖고 연습하며 학습할 필요가 있는 효율적이며 자동화를 위한 강력한 도구입니다! 터미널에 관한 자세한 학습은 &lt;a href=&quot;https://www.youtube.com/playlist?list=PLYQSCk-qyTW0d88jNocdi_YIFMA5Fnpug&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이곳의 유튜브 재생목록&lt;/a&gt;을 참고해보셔도 좋을 거 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Terminal |  Vim</category>
      <category>셸</category>
      <category>커맨드 라인</category>
      <category>터미널</category>
      <author>휘 Hwi</author>
      <guid isPermaLink="true">https://walkingplow.tistory.com/89</guid>
      <comments>https://walkingplow.tistory.com/89#entry89comment</comments>
      <pubDate>Thu, 7 Apr 2022 14:54:50 +0900</pubDate>
    </item>
    <item>
      <title>JWT 토큰 발급과 로그인 처리 방법</title>
      <link>https://walkingplow.tistory.com/88</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;JWT는 JSON Web Token의 약자로 JSON 형식의 웹 토큰을 의미합니다. 이를 통해 사용자 로그인 인증을 진행하거나 당사자 간에 정보를 교환할 수 있습니다. 이번 포스팅에서는 JWT란 무엇이며, 사용 이유, 토큰 발급과 사용 방법에 대해 알아보도록 하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HTTP의 특성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JWT에 대해 알아보기 전에 HTTP의 중요한 특성을 이해하고 있어야 합니다. HTTP는 서버와 클라이언트가 데이터를 주고 받는 대표적인 통신 프로토콜 중 하나입니다. 이러한 HTTP 프로토콜은 각 연결과 상태가 독립적이라는 특성을 갖고 있습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, HTTP는 connectionless(연결을 유지 하지 않음)하며, stateless(상태를 유지하지 않음)합니다(쉽게 말해 전에 무슨 일이 있었는지 전혀 모르고, 또 알려고도 하지 않는 특성입니다). 따라서 &lt;a href=&quot;https://walkingplow.tistory.com/79&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;쿠키 또는 세션&lt;/a&gt; 등 이전 정보를 기억할 수 있는 추가적인 조치가 없다면, 사용자가 로그인 한 다음 페이지를 이동하면 바로 다시 로그인을 해야하는 불편한 일이 발생할 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사용자 로그인을 처리하는 두 가지 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인 이야기를 계속 이어가 보겠습니다. 웹사이트에 로그인하는 사용자가 페이지를 이동할 때마다 새롭게 로그인해야 한다면 불편할 뿐더러 개인 정보가 유출될 수 있는 위험이 존재합니다. 웹에서 로그인을 처리하는 대표적인 방법으로는 세션 방식과 토큰 방식이 있으며, 다음과 같은 차이점이 존재합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;세션 방식: 서버의 메모리 또는 데이터베이스 등에 사용자의 정보를 저장하는 방식입니다. 서버는 사용자를 확인한 다음 세션 ID를 발급합니다. 토큰 방식에 비해 보안이 좋으나 서버의 자원이 상대적으로 많이 필요합니다.&lt;/li&gt;
&lt;li&gt;토큰 방식: 서버에서 발행하는 토큰을 사용자의 브라우저에 저장하는 방식입니다. 세션 방식에 비해 트래픽에 대한 부담이 적으나, 토큰이 유출될 경우 누구나 정보를 확인할 수 있어 보안이 상대적으로 떨어집니다. 또한 토큰에 담기는 데이터 크기가 길어지므로 잦은 요청 시 데이터 트래픽에 영향을 미칠 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 JWT 토큰 방식을 사용한 인가와 로그인 정보 전달에 대해 살펴보도록 하겠습니다. 이를 위해 먼저, JWT의 구조를 이해할 필요가 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;JWT 구조의 이해&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JWT 구조를 파악하고 시크릿 키를 통해 토큰을 발행하면 사용자 로그인을 처리할 수 있습니다. 그럼 이제, JWT 구조에 대해 본격적으로 알아보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JWT를 인코딩 및 디코딩할 수 있는 &lt;a href=&quot;https://jwt.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;다음 사이트&lt;/a&gt;에 들어가보시면 JWT의 작동 방식을 직관적으로 살펴볼 수 있습니다. 왼쪽이 인코딩된 토큰이며, 오른쪽은 인코딩하기 전 데이터(또는 디코딩 된)입니다. 오른쪽의 데이터가 하나라도 변경되면, 인코딩 된 값도 변합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2022-04-06 at 3.44.03 PM.png&quot; data-origin-width=&quot;1592&quot; data-origin-height=&quot;1066&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xFk3m/btryDP44ozS/dBGXW6c9KVR0UHwy3gOpUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xFk3m/btryDP44ozS/dBGXW6c9KVR0UHwy3gOpUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xFk3m/btryDP44ozS/dBGXW6c9KVR0UHwy3gOpUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxFk3m%2FbtryDP44ozS%2FdBGXW6c9KVR0UHwy3gOpUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1592&quot; height=&quot;1066&quot; data-filename=&quot;Screen Shot 2022-04-06 at 3.44.03 PM.png&quot; data-origin-width=&quot;1592&quot; data-origin-height=&quot;1066&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JWT는 세 가지 파트인 &lt;code&gt;header&lt;/code&gt;, &lt;code&gt;payload&lt;/code&gt;, &lt;code&gt;signature&lt;/code&gt;로 구성됩니다. 아래와 같은 구조를 가지며 &lt;code&gt;.&lt;/code&gt;을 통해 구분됩니다. &lt;code&gt;XXX&lt;/code&gt;는 헤더, &lt;code&gt;YYY&lt;/code&gt;는 페이로드, &lt;code&gt;ZZZ&lt;/code&gt;는 서명 부분에 해당합니다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;XXX.YYY.ZZZ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 파트에 대해 조금 더 자세히 살펴보도록 하겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;헤더(header)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;헤더에는 JWT를 검증하는 암호화 알고리즘, 토큰 타입 등이 포함됩니다.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
    &quot;alg&quot;: &quot;HS256&quot;,
    &quot;typ&quot;: &quot;JWT&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;페이로드(payload)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토큰에 담아 전송하는 데이터가 포함됩니다. 이러한 각 정보를 클레임(&lt;code&gt;claim&lt;/code&gt;)이라 하며, 이는 키-값으로 구성되어 있습니다. 클레임은 사전 정의된 registered clam, 개발자가 정의한 public claim, 두 주체 간에만 교환되는 기타 private claim으로 구분됩니다.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;sub&quot;: &quot;1234567890&quot;,
  &quot;name&quot;: &quot;John Doe&quot;,
  &quot;admin&quot;: true
}&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;헤더와 페이로드는 데이터를 16진수로 인코딩하는 것이며 암호화를 진행하는 것이 아닙니다. 따라서 누구나 이를 디코딩하여 정보를 확인할 수 있습니다. 즉, JWT에 담아 전달하는 값에는 민감한 정보를 담지 않아야 합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서명(signature)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서명을 위해서는 인코딩된 헤더와 페이로드, 시크릿 키, 알고리즘이 필요합니다. 서명을 통해 토큰을 인코딩 된 당시의 환경과 대조할 수 있으며, 진위 여부를 확인할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;access_token = jwt.encode({
  &quot;sub&quot;: &quot;1234567890&quot;,
  &quot;name&quot;: &quot;John Doe&quot;,
  &quot;admin&quot;: true
}, SECRET_KEY, algorithm='HS256')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 세 부분을 모두 조합하면 다음과 같은 JWT 토큰이 생성됩니다.&lt;/p&gt;
&lt;pre class=&quot;shell&quot; data-ke-language=&quot;shell&quot;&gt;&lt;code&gt;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.dyt0CoTl4WoVjAHI9Q_CwSKhl6d_9rhM3NrXuJttkao&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;JWT를 사용한 로그인 처리 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 JWT 토큰의 특성과 구조에 대해 이해했습니다. 다음과 같은 플로우를 통해 JWT를 활용하여 사용자 로그인을 처리할 수 있습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사용자가 아이디와 패스워드를 입력하여 로그인&lt;/li&gt;
&lt;li&gt;서버는 시크릿 키(secret key)를 통해 접근 토큰(access token) 발급&lt;/li&gt;
&lt;li&gt;사용자에게 JWT 전달&lt;/li&gt;
&lt;li&gt;로그인이 필요한 API 호출 시 헤더(header)에 JWT를 담아 전송함&lt;/li&gt;
&lt;li&gt;서버에서 JWT 서명을 확인하고 시크릿 키로 JWT를 디코드하여 사용자 정보를 획득&lt;/li&gt;
&lt;li&gt;서버에서 유저를 인식하고 요청 사항에 응답함&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고 자료:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;a href=&quot;https://velog.io/@zz3n/HTTP-%EC%9D%B8%EC%A6%9D-JWT&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;HTTP 인증과 JWT&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href=&quot;https://velog.io/@junghyeonsu/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%90%EC%84%9C-%EB%A1%9C%EA%B7%B8%EC%9D%B8%EC%9D%84-%EC%B2%98%EB%A6%AC%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;JWT의 개념과 사용&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://walkingplow.tistory.com/34&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;장고 bcrypt, JWT 인증 인가 방법&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Auth | Security</category>
      <category>JWT</category>
      <category>JWT 디코딩</category>
      <category>JWT 인코딩</category>
      <category>JWT 토큰 발급</category>
      <category>인가</category>
      <category>인증</category>
      <author>휘 Hwi</author>
      <guid isPermaLink="true">https://walkingplow.tistory.com/88</guid>
      <comments>https://walkingplow.tistory.com/88#entry88comment</comments>
      <pubDate>Wed, 6 Apr 2022 15:53:55 +0900</pubDate>
    </item>
    <item>
      <title>웹소켓 WebSocket 사용 방법 정리</title>
      <link>https://walkingplow.tistory.com/87</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;웹소켓 API는 사용자의 브라우저와 서버 간의 양방향 통신을 가능하게 하는 기술입니다. 웹소켓 API를 사용하면 업데이트를 위해 클라이언트에 정기적으로 요청을 전송하는 서버 폴(poll) 없이도 서버와 메시지를 주고 받을 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;웹소켓 사용 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;webSocket&lt;/code&gt; 객체를 통해 서버와 웹소켓 연결을 위한 API 생성과 관리를 진행할 수 있습니다. 웹소켓을 구성하려면 다음과 같이 &lt;code&gt;WebSocket()&lt;/code&gt; 생성자(constructor)를 사용할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 웹소켓 연결
const socket = new WebSocket('ws://localhost:8080')

// 연결 확인
socket.addEventListener('open', function(event)) {
    socket.send('Hello Server!');
});

// 메시지 수신
socket.addEventListener('message', function(event)) {
    console.log('Message from server ', event.data);
});&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HTTP와 웹소켓 차이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹소켓은 HTTP와 호환 가능하지만 두 프로토콜의 구조는 무척다릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP와 REST에서 클라이언트는 수많은 URL을 통해 애플리케이션과 상호작용합니다. 서버는 HTTP URL, 메소드, 헤더를 기반으로 요청을 처리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면, 웹소켓에는 보통 초기 접속을 위한 하나의 URL만 존재하는 경우가 많으며, 모든 애플리케이션 메시지가 동일한 TCP 연결에서 처리됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP는 사전 설정된 통신 규약을 따르는 프로토콜이지만, 웹소켓은 이러한 제약을 해결하는 새로운 프로토콜 솔루션입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;웹소켓 활용 예시&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹소켓을 사용하면 웹페이지를 동적이고 인터랙티브하게 만들 수 있습니다. 웹소켓은 언제 사용하는 것이 좋을까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 보겠습니다. 뉴스나 메일, 소셜 미디어 피드는 동적인 업데이트를 필요로 하지만, 몇 분 정도는 지연되도 괜찮을 수 있습니다. 반면, 게임이나 금융 앱과 같은 경우에는 실시간 업데이트가 필수적일 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전자와 같이 업데이트 주기가 상대적으로 길거나 메시지 크기가 작은 경우, HTTP 스트리밍이나 폴링이 효과적일 수 있습니다. 반면, 후자의 경우처럼 낮은 지연, 빠른 주기, 큰 메시지를 처리하려는 경우에는 웹소켓이 적합할 수 있습니다. 통신에 있어 고려해야 할 사항은 속도 뿐만 아니라 메시지의 크기입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하자면, 대부분의 경우에는 웹소켓을 사용하지 않고, Ajax와 HTTP 스트리밍 및 폴링을 통해 간결하고 효과적인 솔루션을 찾을 수 있습니다. 그러나 빠른 업데이트 및 큰 메시지의 처리가 필요한 경우에는 웹소켓을 사용한 실시간 통신을 적용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고 자료&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://codeburst.io/polling-vs-sse-vs-websocket-how-to-choose-the-right-one-1859e4e13bd9&quot;&gt;https://codeburst.io/polling-vs-sse-vs-websocket-how-to-choose-the-right-one-1859e4e13bd9&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/WebSocket&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/API/WebSocket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.spring.io/spring-framework/docs/5.0.4.RELEASE/spring-framework-reference/web.html#websocket&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.spring.io/spring-framework/docs/5.0.4.RELEASE/spring-framework-reference/web.html#websocket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@chullino/http%EC%97%90%EC%84%9C%EB%B6%80%ED%84%B0-websocket%EA%B9%8C%EC%A7%80-94df91988788&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://medium.com/@chullino/http%EC%97%90%EC%84%9C%EB%B6%80%ED%84%B0-websocket%EA%B9%8C%EC%A7%80-94df91988788&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Web | Internet</category>
      <category>HTTP</category>
      <category>웹소켓</category>
      <category>통신 프로토콜</category>
      <author>휘 Hwi</author>
      <guid isPermaLink="true">https://walkingplow.tistory.com/87</guid>
      <comments>https://walkingplow.tistory.com/87#entry87comment</comments>
      <pubDate>Wed, 6 Apr 2022 14:47:29 +0900</pubDate>
    </item>
    <item>
      <title>장고 SECRET_KEY 관리 방법: 환경 변수와 로컬 파일 설정</title>
      <link>https://walkingplow.tistory.com/85</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;장고에서는 프로젝트 생성 시 &lt;code&gt;settings.py&lt;/code&gt;에 자동으로 &lt;code&gt;SECRET_KEY&lt;/code&gt;를 생성해줍니다. 이는 세션, 메시지, 토큰, 암호화된 서명 등에 사용되므로 외부로 유출되지 않게 잘 관리해야 합니다. 특히나 프로젝트 협업을 진행할 때 사용하는 깃을 통해 직접 &lt;code&gt;SECRET_KEY&lt;/code&gt;나 데이터베이스의 암호, AWS 정보, 각종 소셜 로그인 API 키 등을 업로드해 공유할 경우 유출되어 큰 문제가 발생할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;SECRET_KEY&lt;/code&gt;를 프로젝트 파일과 구분하여 관리하는 방법으로는 1. 환경 변수 설정 2. 로컬 파일 생성이 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;환경 변수 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;환경 변수란 운영 체제(OS)에서 프로세스를 실행하기 위해 참조하는 변수를 의미합니다. 즉, 프로세스가 컴퓨터에서 작동하는 데 영향을 미치는 글로벌 환경의 동적인 값들을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;.bashrc&lt;/code&gt;, &lt;code&gt;.zshrc&lt;/code&gt; 파일 등에 다음과 같이 환경 변수를 설정하여 키를 관리할 수 있습니다. 배포 도구에 따라 환경 변수 설정 방법이 달라질 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 터미널에서 사용 중인 셸 확인
echo $SHELL
/bin/zsh

# 셸의 프로필 스크립트를 열기
vim ~/.zshrc

# 스크립트 내에 다음을 추가
export DJANGO_SECRET_KEY='django-insecure-w$cc...'
export DB_NAME='project'
...

# 저장 후 터미널로 빠져나와 zsh 명령어 입력
zsh

#환경 변수 설정 확인
echo $DJANGO_SECRET_KEY&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;환경 변수 설정을 마쳤다면 이제 장고의 &lt;code&gt;settings.py&lt;/code&gt;로 이동하여 다음과 같이 환경 변수를 지정해줍니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;# settings.py

import os
from django.core.exceptions import ImproperlyConfigured


def get_env_variable(var_name):
  &quot;&quot;&quot;환경 변수를 가져오거나 에러 메시지를 반환.&quot;&quot;&quot;
  try:
    return os.environ[var_name]
  except KeyError:
    error_msg = &quot;Set the {} environment variable&quot;.format(var_name)
    raise ImproperlyConfigured(error_msg)


SECRET_KEY = os.environ[&quot;DJANGO_SECRET_KEY&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;로컬 파일로 관리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 파일로 관리하는 가장 간단한 방법은 프로젝트에서 &lt;code&gt;my_settings.py&lt;/code&gt;를 만들고 내부에 데이터를 저장한 다음 이를 &lt;code&gt;.gitignore&lt;/code&gt;에 추가하여 추적을 방지하는 것입니다.&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;{
   &quot;django:&quot; {
    SECRET_KEY = 'django-insecure-w$cc...'
    DATABASES = {
          'default' : {
          'ENGINE': 'django.db.backends.mysql',
          'NAME': 'mysite',
          'USER': 'root',
          'PASSWORD': '****',
          'HOST': '127.0.0.1',
          'PORT': '3306',
          }
    }
  },
  &quot;aws&quot;: {
    AWS_ACCESS_KEY_ID = &quot;AKIA2WVSW...&quot;
    AWS_SECRET_ACCESS_KEY = &quot;psRKZoW+3..vQ&quot;
  } 
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 파일에서 &lt;code&gt;SECRET_KEY&lt;/code&gt;를 관리하는 보다 자세한 방법은 &lt;a href=&quot;https://walkingplow.tistory.com/17&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;장고 초기 세팅 포스팅&lt;/a&gt;을 참조해보시기 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고:&lt;br /&gt;&lt;a href=&quot;https://ehfgk78.github.io/2018/02/03/Django_secrets/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://ehfgk78.github.io/2018/02/03/Django_secrets/&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://wayhome25.github.io/django/2017/07/11/django-settings-secret-key/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://wayhome25.github.io/django/2017/07/11/django-settings-secret-key/&lt;/a&gt;&lt;/p&gt;</description>
      <category>Django</category>
      <category>SECRET_KEY</category>
      <category>시크릿 키</category>
      <category>장고</category>
      <category>장고 my_settings.py</category>
      <category>장고 시크릿 키 관리 방법</category>
      <category>장고 환경 변수 설정</category>
      <author>휘 Hwi</author>
      <guid isPermaLink="true">https://walkingplow.tistory.com/85</guid>
      <comments>https://walkingplow.tistory.com/85#entry85comment</comments>
      <pubDate>Sun, 13 Mar 2022 22:04:45 +0900</pubDate>
    </item>
    <item>
      <title>장고 개발 환경에 따라 settings.py 분리하는 방법</title>
      <link>https://walkingplow.tistory.com/84</link>
      <description>&lt;p&gt;장고에서는 개발 환경에 따라 &lt;code&gt;settings.py&lt;/code&gt;를 구분하여 목적에 맞게 서버 환경을 설정할 수 있습니다. 환경을 분리하는 이유는 원활한 협업, 코드의 유지 보수, 공개/비공개 처리, 라이브러리 및 데이터베이스 관리 등을 위해서입니다.&lt;/p&gt;
&lt;p&gt;개발 환경에는 기본적으로 서버에 연결하지 않으나 공통 사항들을 공유하는 &lt;code&gt;local&lt;/code&gt;과 &lt;code&gt;base&lt;/code&gt;가 있으며, AWS S3, RDS 등에 연동한 &lt;code&gt;development&lt;/code&gt;, 이를 실제로 배포하는 &lt;code&gt;production&lt;/code&gt;이 있습니다.&lt;/p&gt;
&lt;h2&gt;장고 settings.py 분리하는 방법&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;settings.py&lt;/code&gt;가 있는 로컬 환경에서 &lt;code&gt;settings&lt;/code&gt; 디렉토리를 생성합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;mkdir settings&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;이를 패키지화 해서 사용할 것이므로 &lt;code&gt;__init__.py&lt;/code&gt;를 생성해줍니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;cd settings
touch __init__.py&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;code&gt;settings.py&lt;/code&gt;의 이름을 &lt;code&gt;development.py&lt;/code&gt;로 변경하고 생성한 디렉토리를 이동합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;mv settings.py development.py
mv settings.py ./settings&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;code&gt;development.py&lt;/code&gt; 를 열어 &lt;code&gt;BASE_DIR&lt;/code&gt;를 다음과 같이 설정하여 부모 디렉토리의 위치를 설정합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;BASE_DIR = Path(__file__).resolve().parent.parent.parent&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;다음으로 &lt;code&gt;production.py&lt;/code&gt;를 만들어 다음과 같이 &lt;code&gt;development.py&lt;/code&gt;를 상속받고, 변경 사항들을 추가로 지정해줍니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-django&quot;&gt;from .local import *

DEBUG = False&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;실행은 다음의 명령어로 가능합니다. 원하는 환경의 설정 파일을 실행해주면 이를 바탕으로 서버가 실행됩니다. 이 과정에서 충돌이 나지 않고 서버가 잘 실행된다면, 설정이 정상적으로 완료된 것입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;python manage.py runserver --settings=myproejct.settings.development&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;python manage.py runserver --settings=myproejct.settings.production&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;참고 자료:&lt;br&gt;&lt;a href=&quot;https://ehfgk78.github.io/2018/02/02/Django-Settings_Requirements/&quot;&gt;https://ehfgk78.github.io/2018/02/02/Django-Settings_Requirements/&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://wikidocs.net/75560&quot;&gt;https://wikidocs.net/75560&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://cjh5414.github.io/django-settings-separate/&quot;&gt;https://cjh5414.github.io/django-settings-separate/&lt;/a&gt;&lt;/p&gt;</description>
      <category>Django</category>
      <category>settings.py</category>
      <category>장고</category>
      <category>장고 settings.py 분리</category>
      <category>장고 개발 환경 분리</category>
      <author>휘 Hwi</author>
      <guid isPermaLink="true">https://walkingplow.tistory.com/84</guid>
      <comments>https://walkingplow.tistory.com/84#entry84comment</comments>
      <pubDate>Sun, 13 Mar 2022 21:36:55 +0900</pubDate>
    </item>
  </channel>
</rss>