<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>qnddj-kjh.log</title>
        <link>https://velog.io/</link>
        <description>욕심 많은 주니어 개발자입니다. </description>
        <lastBuildDate>Wed, 28 Jun 2023 02:13:52 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>qnddj-kjh.log</title>
            <url>https://images.velog.io/images/qnddj-kjh/profile/0b94e5ee-77e4-4691-b6aa-70fbe418e209/social.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. qnddj-kjh.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/qnddj-kjh" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[project] DevOps section4 프로젝트 회고]]></title>
            <link>https://velog.io/@qnddj-kjh/project-DevOps-section4-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@qnddj-kjh/project-DevOps-section4-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Wed, 28 Jun 2023 02:13:52 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/1919bfce-fb0f-4321-94eb-122d87457f9f/image.png" alt=""></p>
<p align="center">
      Q. 프로젝트가 끝난 지금, 어떤가요?</br>
    A. 으아ㅏㅏㅏㅏㅏ</br>
    지금의 나의 상태. 완성? 미완성? 그 애매한 경계에서 프로젝트가 마무리가 되었다</p>

<h1 id="📚project">📚Project</h1>
<p>제공해주는 주제가 있었는데 2가지 정도는 확정 주제고(이미 시나리오와 요구사항이 있는것!) 주제 자유해서 총 3가지의 주제를 고를 수 있었다. 주제를 고르는 순서는 랜덤 프로그램을 통해 공정하게 정해졌다. 
우리 조는 자유 주제를 선정했고, 자유 주제의 필수 포인트는 컨테이너 기반이었다. 컨테이너 기반으로 주제를 정해야하는 것. 
무엇을 할까 하며 폭풍 회의를 하다. 평소에 방송을 실시간으로 보지는 않지만 유튜브 러버로서 트위치라는 플랫폼에서 방송하는 분들의 유튜브를 보다보니 익숙한 시스템인 미션 후원 시스템에 대해서 제안을 했다. 
다른 팀원분들의 첨삭을 걸쳐 나쁘지 않다는 이야기가 나오고 얼떨결에 내가 제안한 주제로 결정되었다. 와!🙋‍♂️</p>
<h2 id="📑시스템-분석-및-요구사항">📑시스템 분석 및 요구사항</h2>
<p>다음은 팀원들과 시스템에 대해서 분석하고 요구사항에 대해서 미팅한 결과이다.</p>
<ul>
<li>프론트엔드는 일단 배제하였다 : 팀원들의 개발 레벨이 높지 않고, 완성에 집중하기 위해</li>
</ul>
<p><strong>프로젝트 주제: 미션 관리 서비스</strong></p>
<ul>
<li><p><strong>기능 요구사항</strong></p>
<ul>
<li>개인 사용자와 스트리머는 로그인 기능을 통해 토큰을 발급받을 수 있다.</li>
<li>토큰을 사용하는 로직 구현이 어렵다면 유저 데이터베이스에 접근해서 일치하는 사용자 정보가 있는 것을 확인하는 것으로 대체</li>
<li>개인 사용자 새로운 미션을 입력 및 조회할 수 있다.</li>
<li>스트리머는 미션에 대해 성공 및 실패를 선택할 수 있다.</li>
<li>성공 및 실패가 결정된 경우 개인 사용자는 해당 미션의 결과에 대한 email을 받을 수 있다.</li>
<li>미션을 수행하는 제한시간을 설정할 수 있다.</li>
<li>캐쉬를 충전하는 기능, 미션마다 포인트 설정, 성공하면 지급되야되고 실패 시 반환된다.</li>
<li>이미 생성된 미션에 경우 생성한 유저 이외의 유저도 캐쉬를 추가할 수 있다.</li>
</ul>
</li>
<li><p><strong>추가적인 사항</strong></p>
<ul>
<li>해당 미션에 성공할지 못할지에 대한 게임이 있다.</li>
</ul>
</li>
<li><p><strong>인프라 요구사항</strong></p>
<ul>
<li>시스템 전반에 가용성, 내결함성, 확장성, 보안성이 고려된 서비스들이 포함되어야한다.</li>
<li>하나 이상의 컴퓨팅 유닛에 대한 CI/CD 파이프라인이 구성되어야한다.</li>
<li>유저 데이터를 저장하고 있는 유저 데이터베이스는 다른 데이터베이스와 분리되어있어야한다.</li>
<li>미션 데이터를 기반으로 미션 성공에 대해 처리하는 시스템은 데이터 유실을 막기 위해 느슨하게 결합되어야한다.</li>
<li>시스템 메트릭 또는 저장된 데이터에 대한 하나 이상의 시각화된 모니터링 시스템이 구축되어야한다. </li>
</ul>
</li>
</ul>
<h2 id="🖌-다이어그램">🖌 다이어그램</h2>
<p>위의 시스템 분석과 요구사항을 토대로 다이어그램을 그렸다</p>
<h3 id="아키텍처">아키텍처</h3>
<p align="center"><img width="720px" height="460px" src="https://velog.velcdn.com/images/qnddj-kjh/post/11e9b300-8427-4cf4-a23a-c03f86684bf4/image.png"></p>
다방면으로 생각하면서 여러 아키텍처를 구상해봤었다 중간쯤  되었을 때 당시의 아키텍처
<p align="center"><img width="720px" height="460px" src="https://velog.velcdn.com/images/qnddj-kjh/post/229cce50-e3be-4fe1-809e-e2276a4703bd/image.png"></p>
최종 아키텍처와 비슷한 피드백중인 아키텍처 다이어그램

<p>아키텍처를 그려보면서 아쉬웠던게 생각보다 시스템이 간단하였다. 솔직히 말해서 3티어만 해도 충분히 시스템을 만들었다. 그래서 우리조는... 온 몸을 비틀어버렸다</p>
<p align="center"><img width="720px" height="460px" src="https://velog.velcdn.com/images/qnddj-kjh/post/15b50d8d-d735-497c-aacb-cf1a5ee7f614/image.png"></p>
3티어만으로도 충분한 시스템에서 우리 조가 선택한 것은 EDA (Event Driven Architecture) 였다.
이벤트 발생을 트리거로 이벤트 브릿지를 통해 자동으로 람다를 실행하도록 짜보았다. 
미션 후원 즉 돈이 중요한 시스템이기에 중복 요청 또는 요청 누락이 있어서는 안되는 점 등을 고려했다.
그래서 현금이 들어가는 빈번한 후원의 경우 nosql 에 별도의 이벤트 로그를 누적하는 방법을 채택하면서 위 다이어그램이 최종적으로 설계되었다.


<h3 id="db">DB</h3>
<p align="center"><img src="https://velog.velcdn.com/images/qnddj-kjh/post/3a9b1873-80c2-4c5b-af71-a14b8227e60d/image.png" width="480px" height="360px"></p>
조금 여러 형태를 지나 나온 형태인데 최종적으로 시스템이 만들어질 때 자잘구리하게 뭔가 다 못들어갔다...



<h2 id="🔧-개발-시작">🔧 개발 시작</h2>
<h3 id="처음부터-문제다-문제">처음부터 문제다 문제</h3>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/7ba6dc86-1b63-4c31-92d4-3827a37494d5/image.png" alt="">
처음 작업했던 것은 AWS VPC 작업을 통해 네트워크 공간을 개발하는 거였다.</p>
<p>하지만 여기서부터 잘못 되어갔는데... 뒤에 바로 말하겠다.
AWS VPC 작업 할 때 AWS Console 작업이 아닌 바로 Terraform 으로 들어갔다. 이유는 간단했는데 한번에 리소스를 관리할 수 있기 때문이었다.</p>
<p>잘못은 이 프로젝트의 시스템 인프라는 증명이 안되었다는 것
컨셉 증명을 확실히 하고 시스템을 처음에는 콘솔작업으로 한땀한땀 하여 &#39;hello world&#39; 가 나오는 간단한 애플리케이션이라도 배포를 하고 Terraform 으로 VPC 를 만들다 보니 이후에 모든 작업을 바로바로 Terraform 으로 작업을 하게 되었다. 1부터 하여야 할 것을 10부터 진행하고 있었다. 이러한 피드백을 받았을 때 &#39;앗&#39; 하는 충격과 동시에 시무룩해졌었다... 잘못도 잘못이지만... 그래도 노력한 게 있었던지라</p>
<p>그럼에도 시무룩하고 있을 시간은 없었고 작업은 해야했다. 피드백을 적극 수용하여 이후 이미  Terraform 으로 만들어진 리소스는 어쩔 수 없다고 생각하고 AWS Console 로 최대한 증명해가면서 작업하였다. </p>
<p align="center"><img width="420" height="260px" src="https://velog.velcdn.com/images/qnddj-kjh/post/720ad5f1-97fa-46b7-98ad-4e03ca36fe12/image.png"></p>
처음 인프라 담당에서 EKS 파트를 맡았을 때 걱정이 있지만 그림과 같은 인프라 시스템을 구축하였다.

<h3 id="eks-트러블-슈팅">EKS 트러블 슈팅</h3>
<p>EKS 작업 중 가장 나를 힘들게 했던것은 EKS Cluster 와 Worker Node 통신 에러 문제였다.
WorkerNode 는 Cluster 와 통신을 해야하는데 자꾸 통신 에러가 뜨면서 Bastion Host 를 통해 WorkerNode Instance 로 접속을 할 수 없었다.
그러던 중에 Worker Node 를 private subnet 중에 첫 번째 subnet 에 고정적으로 넣으면서 통신 에러 없이 Worker Node 가 잘 생성이 되면서 접속이 되었다! 이제 설정을 private subnet 전체를 지정하고 되겠지 기대하면서 다시 돌렸지만 에러가 돌아왔다.
여기서 잘 하시는 분은 바로 문제를 찾겠지만 문제는 네트워크 였었다. 통신 에러니깐 당연히 네트워크 에러가 맞지만 같은 VPC 안이라고 생각했던게 달랐었다. public host 에서 bastion host 가 있는 public subnet 은 private subnet 1번과 NAT Gateway 로 연결되어 있다.</p>
<ul>
<li>bastion host (public subnet 1번) 를 통해 worker node (private subnet 1번) 접속</li>
</ul>
<p>딱 이렇게 Bastion Host 만을 생각하고 작업을 해서 private subnet 1번에 worker node 를 배치하면 잘 되고 다른 곳은 연결이 안된다. 왜? NAT Gateway 가 private subnet 1번 하고만 연결 되어있으니깐. 또한 Worker Node Group 은 연결된 서브넷에 랜덤한 위치에 Worker Node 를 배치하기 시작한다</p>
<p>이 문제를 알게 되고나서 EKS 가 VPC 외부 시스템인걸 인지하게 되고 NAT 를 전부 연결하게 되면서 문제는 해결 되었다.</p>
<h3 id="kubectl-eks-접속-시-사용자-등록">kubectl EKS 접속 시 사용자 등록</h3>
<p>기본적으로 Amazon EKS 의 경우 Cluster 생성자가 사용자로 지정되어 있으며 master 권한을 가지고 있다. 외부에서 예를 들어 EKS 관리팀의 신입이 kubectl 을 통해 EKS 를 보고 싶을 때 사용자로 등록되어 있지 않다면 Cluster 를 확인할 수 없다.
AWS Cloud 환경을 우리 팀장님의 계정으로 만들었기에 추후 로드 밸런싱 작업을 위해 kubectl 접속이 필요했다. 그러기 위해 다음과 같은 사용자 추가 과정을 팀장님께 부탁을 드렸다.</p>
<ul>
<li>등록 하고자 하는 AWS IAM 사용자를 만든다.<ul>
<li>IAM 사용자는 내 AWS 계정에서 만들었다.</li>
<li>해당 IAM 사용자의 ARN 이 필요</li>
</ul>
</li>
<li>공통)<ul>
<li><pre><code class="language-bash"># AWS 권한 Config map 확인 명령어를 통해 
kubectl get -n kube-system configmap/aws-auth</code></pre>
</li>
</ul>
</li>
<li>방법1) eksctl 사용<ul>
<li><pre><code class="language-bash">eksctl create iamidentitymapping \
--cluster cluster-name \ # 클러스터 네임 (자신의 AWS 에 EKS 가 존재해야함)
--region=ap-northeast-2 \
--arn arn:aws:iam::111122223333:user/ggamzzak \ # 아까 생성한 사용자의 ARN
--group system:masters \
--profile my-profile # AWS Configure 를 통해 AWS CLI Access Profile 등록되어 있어야 한다.</code></pre>
</li>
</ul>
</li>
<li>방법2)<ul>
<li><pre><code class="language-bash"># AWS 권한 Config map 수정 명령어를 통해 수정이 가능하다. 
kubectl edit -n kube-system configmap/aws-auth</code></pre>
</li>
<li><pre><code># aws-auth.yml
mapUsers: |
 - userarn: arn:aws:iam::002672955123:user/test1
   username: test1
   groups:
   - system:masters
   # 여기서 아까 생성한 ARN 을 넣어주고 
 - userarn: arn:aws:iam::002672955123:user/test2
   username: test2
   groups:
   - system:masters  # 해당 유저의 권한을 설정한다.</code></pre></li>
</ul>
</li>
<li>사용자 추가후 kubectl 로 클러스터를 확인할 수 있다.<ul>
<li>kubectl 은 관리자 또는 클러스터 생성자로부터 kubeconfig 파일을 받아 연결이 가능하다.<h3 id="aws-loadbalancer-controller-자격-증명">AWS LoadBalancer Controller 자격 증명</h3>
<a href="https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/aws-load-balancer-controller.html">https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/aws-load-balancer-controller.html</a> 보면서 따라하였다
쿠버네티스가 직접 관리하는 사용자 계정을 의미하는 <strong>service account</strong>에 IAM role을 사용하기 위해, 생성한 클러스터(현재 실습에서의 <em>eks-demo</em>)에 <strong>IAM OIDC provider</strong>가 존재해야 합니다.</li>
<li>클러스터 생성자에게 생성의뢰<pre><code class="language-bash"># IAM OIDC(OpenID Connect) identity Provider를 생성
eksctl utils associate-iam-oidc-provider \
--region ap-northeast-2 \
--cluster mission-link-eks-cluster \
    --approve \
    --profile admin</code></pre>
</li>
</ul>
</li>
</ul>
<p>AWS Load Balancer Controller의 <code>kube-system</code> 네임스페이스에 <code>aws-load-balancer-controller</code>라는 Kubernetes 서비스 계정을 생성하고 IAM 역할의 이름으로 Kubernetes 서비스 계정에 주석을 답니다.</p>
<p><code>eksctl</code> 또는 AWS CLI 및 <code>kubectl</code>을 사용하여 IAM 역할 및 Kubernetes 서비스 계정을 생성할 수 있습니다.</p>
<ul>
<li>클러스터 생성자에게 생성의뢰</li>
</ul>
<pre><code class="language-bash"># Service Account 계정 생성
eksctl create iamserviceaccount \
  --cluster=mission-link-eks-cluster \
  --namespace=kube-system \
  --name=aws-load-balancer-controller \
  --role-name AmazonEKSLoadBalancerControllerRole \
  --attach-policy-arn=arn:aws:iam::123412341234:policy/AWSLoadBalancerControllerIAMPolicy \
  --profile admin \
  --approve</code></pre>
<p><code>cert-manager</code>다음 방법 중 하나를 사용하여 웹후크에 인증서 구성을 삽입하여 설치합니다 .</p>
<ul>
<li><p>노드에 컨테이너 레지스트리에 대한 액세스 권한이 있는 경우 웹후크에 인증서 구성을 삽입하도록 <code>quay.io</code> 설치합니다 .<code>cert-manager</code></p>
<pre><code class="language-bash">  kubectl apply \
      --validate=false \
      -f https://github.com/jetstack/cert-manager/releases/download/v1.5.4/cert-manager.yaml</code></pre>
</li>
</ul>
<p>AWS LoadBalancer 컨트롤러를 설치합니다.</p>
<p> 컨트롤러 사양을 다운로드하십시오. 컨트롤러에 대한 자세한 내용은 GitHub에서 <a href="https://kubernetes-sigs.github.io/aws-load-balancer-controller/">설명서를 참조하십시오.</a></p>
<ul>
<li>EKS 에 맞는 컨트롤러 버전을 써야한다</li>
<li>프로젝트의 경우 EKS 2.7 컨트롤러 </li>
</ul>
<pre><code class="language-bash">
curl -Lo v2_4_7_full.yaml https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.4.7/v2_4_7_full.yaml</code></pre>
<p>파일에 대해 편집한 항목:</p>
<ul>
<li><p><code>v2_4_7_full.yaml</code> 파일을 다운로드 한 경우 다음 명령을 실행하여 매니페스트에서 <code>ServiceAccount</code> 섹션을 제거합니다. 이 섹션을 제거하지 않으면 이전 단계에서 서비스 계정에 작성한 필수 주석이 덮어씌워집니다. 이 섹션을 제거하면 컨트롤러를 삭제할 경우 이전 단계에서 생성한 서비스 계정도 유지됩니다.</p>
<pre><code class="language-bash">  sed -i.bak -e &#39;561,569d&#39; ./v2_4_7_full.yaml</code></pre>
<p>  다른 파일 버전을 다운로드한 경우 편집기에서 파일을 열고 다음 줄을 제거합니다.</p>
<pre><code class="language-bash">  apiVersion: v1
  kind: ServiceAccount
  metadata:
    labels:
      app.kubernetes.io/component: controller
      app.kubernetes.io/name: aws-load-balancer-controller
    name: aws-load-balancer-controller
    namespace: kube-system
  ---</code></pre>
</li>
<li><p><em><code>my-cluster</code></em>를 해당 클러스터 이름으로 바꿔 파일의 <code>Deployment</code> <code>spec</code> 섹션에 있는 <code>your-cluster-name</code>을 해당 클러스터의 이름으로 바꿉니다.</p>
</li>
</ul>
<p>파일을 적용합니다.</p>
<pre><code class="language-bash">kubectl apply -f v2_4_7_full.yaml</code></pre>
<p><code>ngressClass</code> 및 <code>IngressClassParams</code> 매니페스트를 클러스터에 다운로드합니다.</p>
<pre><code class="language-bash">curl -Lo v2_4_7_ingclass.yaml https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.4.7/v2_4_7_ingclass.yaml</code></pre>
<p>상기 과정을 다 하였을때 Ingress 를 생성하면 AWS 에서 프로비저닝된 ALB 를 생성해주면서 pod 에 접근이 가능해진다.</p>
<h2 id="💭-회고">💭 회고</h2>
<p>드디어 말도 많고 탈도 많은 프로젝트가 끝났다. 너무나도 하고 싶었던 팀 단위의 프로젝트. 0에서 무언가를 쌓아가는건 확실히 어렵다는 것을 알게 되었다.</p>
<p>부트캠프를 하겠다고 마음 먹은지가 1년이 넘는데 당연하게도 백엔드 과정을 밟을 줄 알았었는데, 설마 데브옵스 과정을 밝게 될 줄은 상상도 못했다. 계기는 다니고 있던 회사에서 노후 시스템을 업그레이드 하면서 리눅스 환경에서 서버 세팅하고 네트워크 등록하고 하는 작업이 생각보다 재밌었다. 테스트로 서버가 잘 올라갔는지 테스트 할 때 잘 올라간 걸 확인하는 순간 그 뿌듯함이란...</p>
<p>이번 프로젝트에서 아쉬운점이 없지는 않다. 뭔가 더 데브옵스! 하는 아키텍처를 짰으면 하는데 처음에도 글에 썼듯이 온 몸 비틀기를 한 아키텍처가 나와서 아쉬웠고... 아이디어가 더 번쩍였으면 좋았을 거고... 중간중간 정리를 하는 습관을 더 들여야겠다는 생각도 들고...
앞으로 더 잘해가야겠다고 다짐하게 되었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[IaC] 가변적, 불변적 인프라스트럭처와 Terraform 상태유지]]></title>
            <link>https://velog.io/@qnddj-kjh/IaC-%EA%B0%80%EB%B3%80%EC%A0%81-%EB%B6%88%EB%B3%80%EC%A0%81-%EC%9D%B8%ED%94%84%EB%9D%BC%EC%8A%A4%ED%8A%B8%EB%9F%AD%EC%B2%98%EC%99%80-Terraform-%EC%83%81%ED%83%9C%EC%9C%A0%EC%A7%80</link>
            <guid>https://velog.io/@qnddj-kjh/IaC-%EA%B0%80%EB%B3%80%EC%A0%81-%EB%B6%88%EB%B3%80%EC%A0%81-%EC%9D%B8%ED%94%84%EB%9D%BC%EC%8A%A4%ED%8A%B8%EB%9F%AD%EC%B2%98%EC%99%80-Terraform-%EC%83%81%ED%83%9C%EC%9C%A0%EC%A7%80</guid>
            <pubDate>Fri, 12 May 2023 06:25:31 GMT</pubDate>
            <description><![CDATA[<h2 id="immutable-infrastructure-불변적-인프라스트럭처">Immutable Infrastructure (불변적 인프라스트럭처)</h2>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/60bcb66a-8932-444f-8b04-51b5fad7e7a9/image.png" alt=""></p>
<p>불변적 인프라스트럭처는 애완동물과 가축에 대한 비유로 자주 설명 합니다.</p>
<p>애완동물은 이름을 붙이며, 아프면 병원에 데려가고 가족처럼 보살펴줍니다.</p>
<p>하지만 가축은 이름이 아닌 태그를 붙이고, 전염병이 있을 경우에는 처분하게 됩니다.</p>
<p>불변적 인프라스트럭처의 정의는 서버가 설치된 이후 절대 변경되지 않는 형태의 인프라다.</p>
<p>여기서 수정은 기존의 서버를 제거하고 새롭게 만드는 것을 의미</p>
<p>멱등성의 법칙이 적용된다.</p>
<ul>
<li>멱등성 법칙 : 같은 작업을 여러 번 해도 결과가 동일하다. 한번 설정된 서버는 수정 없이 파기되므로 멱등성을 보장한다.</li>
</ul>
<h3 id="특징">특징</h3>
<ul>
<li>각 서버의 버전은 서로 독립적이며 두 가지 버전을 실행할 수 없다</li>
<li>변경이 필요할 때 새 버전의 서버를 생성하기 때문에 버전 문제를 추적이 가능하다.</li>
<li>각 서버의 구성이 일관되기 때문에 다른 서버를 테스트하고 롤아웃하기 쉽다</li>
<li>서버가 동일하게 유지되므로 예측 가능성을 높일 수 있다.</li>
<li>클라우드 기술과 같은 상호 의존적인 환경에 적합하다</li>
</ul>
<h3 id="단점">단점</h3>
<ul>
<li>데이터 저장소를 로컬 디스크에 복사하지 않고 외부화해야 한다.</li>
<li>기존 서버는 수정할 수 없어 문제 발생 시, 동일 구성의 서버에 대해 점검이 필요하다.</li>
</ul>
<hr>
<h2 id="mutable-infrastructure-가변적-인프라스트럭처">Mutable Infrastructure (가변적 인프라스트럭처)</h2>
<p>웹 서버를 만들고 기존의 변경 가능한 인프라에 배포했을 경우, 문제 발생시 서버를 쉽게 변경할 수 있다. 기존 데이터를 새 시스템으로 옮길 필요없이 기존 버전에 변경 사항을 적용한다.</p>
<h3 id="특징-1">특징</h3>
<ul>
<li>변경 필요시 처음부터 서버를 구축할 필요가 없다.</li>
<li>개별 서버에 대한 업데이트를 롤 아웃하여 프로세스 업데이트를 더 빠르게 할 수 있다.</li>
<li>각 서버를 개별 수준에서 이해할 수 있기 때문에 문제를 진단하기 쉽다.</li>
</ul>
<h3 id="단점-1">단점</h3>
<ul>
<li>각 서버의 구성이 고유하기 때문에 각 서버를 진단, 관리하는 것이 더 어려워진다. (Configure Draft)</li>
<li>서버에 대한 변경사항이 문서화되지 않기 때문에 추적이 어렵고 진단이 불가능하다.</li>
<li>DNS 오류, 네트워크 연결 불량과 같은 여러 이유로 업데이트가 실패할 수 있다</li>
<li>업데이트 추적 문제로 디버깅에 시간이 많이 걸린다. 문제에 대한 이해도 없이 여러 버전의 업데이트로 끝날 수 있다.</li>
</ul>
<hr>
<h2 id="차이">차이</h2>
<ul>
<li>불변적 인프라는 자동 배포를 지원한다.<ul>
<li>이 유형의 인프라는 주로 가상화를 중심으로 구축되기 때문에, 하드웨어와 소프트웨어 프로비저닝 및 디프로비저닝에 대해 걱정할 필요가 없다</li>
</ul>
</li>
<li>클라우드에서는 리소스 생성을 위한 모든 프로세스를 문서화할 수 있다</li>
<li>데브옵스는 종속성을 제한해야 시간이 절약된다.<ul>
<li>자동화된 테스트 및 배포를 지원하는 파이프라인을 생성할 때 수동 검증은 시간이 많이 소요되므로 새로운 어플리케이션을 더 빨리 시작하는 것을 방해한다. 변경할 수 없는 인프라를 사용하여 시나리오를 재현하고 자동으로 재해복구도 가능하다.</li>
</ul>
</li>
</ul>
<p>불변적 인프라는 장점으로 인프라의 안정성과 신뢰성이 향상되며, 변동성이 줄어들어 관리 및 유지보수가 용이해집니다. 또한, 인프라를 버전 관리하고 롤백이 가능하게 되므로 실수로 발생한 문제를 빠르게 수정할 수 있습니다.</p>
<hr>
<h2 id="terraform-상태유지">Terraform 상태유지</h2>
<ol>
<li>Terraform 코드 작성: Terraform을 사용하여 인프라를 정의하는 코드를 작성합니다. 이 코드는 실제 인프라 구성을 선언적으로 기술하며, 원하는 상태를 나타냅니다.</li>
<li>Terraform 초기화: <strong><code>terraform init</code></strong> 명령을 사용하여 Terraform 작업을 위한 초기화를 수행합니다. <strong><code>terraform init</code></strong> 명령은 Terraform 프로젝트를 초기화하고 필요한 백엔드 구성 및 모듈 등의 의존성을 설정합니다.</li>
<li>계획 수립: <strong><code>terraform plan</code></strong> 명령을 사용하여 Terraform 코드를 분석하고 변경 사항을 예측적으로 계획합니다. 이 단계에서 Terraform은 기존 인프라 상태와 코드의 상태를 비교하고 필요한 변경 사항을 탐지합니다.</li>
<li>변경 사항 적용: <strong><code>terraform apply</code></strong> 명령을 사용하여 Terraform 코드에 정의된 변경 사항을 실제 인프라에 적용합니다. Terraform은 변경 사항을 적용하기 전에 변경 내용을 사용자에게 미리 알리며, 사용자의 승인을 받습니다.</li>
<li>상태 관리: Terraform은 인프라의 상태를 추적하고 관리합니다. 인프라 상태 파일에는 현재 인프라 구성이 기록되며, 다음 실행에서 변경 사항을 탐지하고 적용하는 데 사용됩니다.</li>
</ol>
<p>이러한 과정을 통해 Terraform은 선언적인 코드를 사용하여 인프라의 최신 상태를 유지하고, 변경이 필요한 경우 변경 사항을 감지하고 적용하여 인프라를 업데이트합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[AWS] ACM SSL Certificate ]]></title>
            <link>https://velog.io/@qnddj-kjh/AWS-ACM-SSL-Certificate</link>
            <guid>https://velog.io/@qnddj-kjh/AWS-ACM-SSL-Certificate</guid>
            <pubDate>Tue, 25 Apr 2023 07:29:39 GMT</pubDate>
            <description><![CDATA[<h1 id="acm--amazon-certificate-manager">ACM : Amazon Certificate Manager</h1>
<p>AWS에서는 SSL/TLS 인증서에 대한 매니지먼트인 Amazon Certificate Manager 서비스를 무료로 제공한다.
이를 바탕으로 기존 서버 하나하나 일일이 SSL을 적용하였던 번잡한 작업들을 아마존 ACM 서비스를 통해 하나의 인증서로 여러 인스턴스에 적용할 수 있다.
_ACM 서비스에 대한 비용은 무료_이나, ELB/CloudFront/API Gateway 등 AWS 인프라에만 적용이 가능한 것을 인지해야 한다</p>
<h3 id="특징">특징</h3>
<ul>
<li>ACM 서비스에 대한 비용은 무료</li>
<li>ELB/CloudFront/API Gateway 등 AWS 인프라에만 적용이 가능</li>
<li>콘솔상에서 SSL 인증서 키페어는 다운로드가 불가능</li>
<li>오로지 AWS CLI를 통해 Public Key Pair만 다운로드가 가능</li>
<li>ACM 을 통해 SSL 인증서 발급한 경우 다른 사설기관에서 해당 인증서를 사용하지 못함을 의미</li>
</ul>
<hr>
<h2 id="인증서-요청">인증서 요청</h2>
<p>다음 이미지와 같이 인증서 요청을 AWS Console 을 통해 요청을 한다.
<strong>boong.dev</strong> 도메인은 필자가 Google Domains 를 통해 구입한 외부 도메인이며 <code>.dev</code> 도메인의 경우 AWS Route53 에서 지원하지 않고 있다.
도메인 등록은 이전 게시글에서 확인 가능합니다.
<a href="https://velog.io/@qnddj-kjh/AWS-Route-53-%EC%99%B8%EB%B6%80-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%A0%81%EC%9A%A9">[AWS] Route 53 외부 도메인 적용
</a>
<img src="https://velog.velcdn.com/images/qnddj-kjh/post/b9b397a6-14f7-4558-85a6-b50abfc4b912/image.png" alt="">
<img src="https://velog.velcdn.com/images/qnddj-kjh/post/f6097847-8125-446c-afe5-7533b7275c24/image.png" alt="">
<img src="https://velog.velcdn.com/images/qnddj-kjh/post/19c70c99-6f49-43d1-a9ce-50d6ab62352a/image.png" alt="">
검증 대기 중인 인증서 안으로 들어가서 <strong>Route S3에서 레코드 생성 버튼</strong>을 눌러 둘다 등록해 준다 </p>
<p>Route 53 을 사용하므로 Reoute 53 에 CNAME 을 등록하여 검증하며</p>
<p>외부 네임 서버를 이용시에는 외부 네임 서버에 해당 CNAME 을 등록하여 검증을 마쳐야 인증서가 정상적으로 등록 된다.
<img src="https://velog.velcdn.com/images/qnddj-kjh/post/571ccb62-3900-4cfe-aaff-a9fcea3cc16d/image.png" alt="">
정상적으로 발급된 모습</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[AWS] Route 53 외부 도메인 적용]]></title>
            <link>https://velog.io/@qnddj-kjh/AWS-Route-53-%EC%99%B8%EB%B6%80-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%A0%81%EC%9A%A9</link>
            <guid>https://velog.io/@qnddj-kjh/AWS-Route-53-%EC%99%B8%EB%B6%80-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%A0%81%EC%9A%A9</guid>
            <pubDate>Tue, 25 Apr 2023 07:18:38 GMT</pubDate>
            <description><![CDATA[<h1 id="route-53-custom-domain">Route 53 Custom Domain</h1>
<p>AWS Route 53 에서 지원하는 최상위 도메인 중에서 내가 원하는 <code>.dev</code> 도메인은 존재 하지 않았다. 그러면 어떻게 해야하나? 외부에서 도메인을 사서 등록하여 사용하는 방법이다.</p>
<p>Google Domains 에서 계속 눈독 들여왔던 도메인을 구입
<img src="https://velog.velcdn.com/images/qnddj-kjh/post/1b4b5ef8-72e0-4c01-badb-6a95e93524bf/image.png" alt=""></p>
<p>보시다시피 <code>.dev</code> 도메인은 보안 네임스페이스로 사용시 반드시 SSL 인증서가 필요하다. 즉 HTTPS 통신을 해야만 한다.</p>
<p>구입한 도메인을 이제 AWS Route 53 에 등록하여야 한다</p>
<p>Route 53 호스팅 영역 생성</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/ea0d2069-7e78-4405-a2d2-5805120abba3/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/1fefd26d-9f75-4a9b-978e-3f91018bf907/image.png" alt="나중에 라우팅 대상 값 모자이크 처리"></p>
<p>나중에 라우팅 대상 값 모자이크 처리</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/06564f66-642c-46cf-9e7a-7d07fecc8ac7/image.png" alt=""></p>
<p>라우팅 대상값을 맞춤 네임서버에 등록
전환되는 데에는 시간이 걸린다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[AWS] Sprint AWS 3tier-architecture 설계]]></title>
            <link>https://velog.io/@qnddj-kjh/AWS-Sprint-AWS-3tier-architecture-%EC%84%A4%EA%B3%84</link>
            <guid>https://velog.io/@qnddj-kjh/AWS-Sprint-AWS-3tier-architecture-%EC%84%A4%EA%B3%84</guid>
            <pubDate>Wed, 19 Apr 2023 11:47:31 GMT</pubDate>
            <description><![CDATA[<h1 id="diagram">Diagram</h1>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/a294aedb-eb12-4fa1-8d06-89d17af754d4/image.png" alt=""></p>
<ul>
<li>위 Diagram 중 S3 Bucket 정적 웹 사이트 호스팅과 EC2-RDS 연결까지 진행</li>
</ul>
<h1 id="s3-static-web-hosting">S3 static web hosting</h1>
<p>React 기반으로 작성된 Front 를 Build 하여 <code>S3 bucket</code> 에 업로드 한다.</p>
<ul>
<li>단, build 폴더로 업로드시 경로가 꼬일 수 있으니 조심</li>
</ul>
<p><code>Bucket</code> 의 속성에서 정적 웹 사이트 호스팅 편집</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/eb8a52f7-37c1-4676-a1f1-288fc98e9194/image.png" alt="">
<em>정적 웹 사이트 호스팅 설정, 리액트의 인덱스 문서 index.html 지정 등</em></p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/b2948990-911f-4221-a463-47257cc78d9e/image.png" alt="">
<em>Bucket 의 접속 정책 생성</em></p>
<h3 id="s3-정적-웹-사이트-접속">S3 정적 웹 사이트 접속</h3>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/98bfc9b4-f04c-44bb-a34a-854dcbee15ce/image.png" alt=""></p>
<h1 id="trouble-shooting"><strong>Trouble Shooting</strong></h1>
<h2 id="npm-run-build-시-에러">npm run build 시 에러</h2>
<h3 id="err_ossl_evp_unsupported">ERR_OSSL_EVP_UNSUPPORTED</h3>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/35feb066-75a0-4e76-822b-7797438caca4/image.png" alt="">
<code>ERR_OSSL_EVP_UNSUPPORTED</code></p>
<p>해당 에러는 모듈 중 하나 혹은 일부가 Node 17.x 부터 적용된 OpenSSL 3 버전의 규격에 맞지 않을 경우 발행 할 수 있다.</p>
<p>최하단을 보면 Node.js v18.15.0  으로 자신의 Node 버전을 확인 할 수 있다.</p>
<p><strong>해결 방안</strong></p>
<p>필자가 사용한 방법으로 다음 명령어를 사용하였다</p>
<p><code>npm audit fix --force</code></p>
<p>모듈의 버전업으로 문제를 해결하는데 어떤 모듈의 버전인지 확인하기 어렵고 번거롭기 때문이다. 문제된 모듈은 react-scripts 2.0.1 이었으며 업그레이드 후 문제가 해결되었다</p>
<ul>
<li>업그레이드 불가의 경우<ul>
<li>노드 버전의 다운그레이드다. 이전 버전의 노드 버전을 설치후 사용하면 된다.</li>
<li>다음 명령어로 openssl legacy 옵션을 설정하여 사용할 수 있다.<ul>
<li><code>react-scripts --openssl-legacy-provider start</code></li>
</ul>
</li>
</ul>
</li>
</ul>
<p>출처: <a href="https://ongamedev.tistory.com/484">https://ongamedev.tistory.com/484</a></p>
<h3 id="module-not-found-error-cant-resolve-fs-in-dotenvlib">Module not found: Error: Can’t resolve ‘fs’ in ../../../dotenv/lib</h3>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/5d172570-97ee-480f-81d3-2386472d7e91/image.png" alt=""></p>
<p>dotenv 모듈에서 사용하는 fs 를 못찾는다는데
react 는 기본 dotenv 를 내장하고 있는데 내장 dotenv 를 찾는게 아니라 직접 dotenv 를 끌고오는 코드가 있어서 상단 </p>
<pre><code class="language-bash">import dotenv from &quot;dotenv&quot;
dotenv.config()

또는

require(&#39;dotenv&#39;).config();</code></pre>
<p>삭제해준다</p>
<h1 id="server-setting">Server Setting</h1>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/0c9cad40-ebb8-4d1f-a6e9-6db002c06eb0/image.png" alt="">
<img src="https://velog.velcdn.com/images/qnddj-kjh/post/485187b0-5366-412c-9b1a-7b6b0fafa344/image.png" alt=""></p>
<h3 id="필요-프로그램-설치">필요 프로그램 설치</h3>
<p>git</p>
<p><code>sudo apt-get install git</code></p>
<p>node</p>
<p><code>sudo apt-get install nodejs</code></p>
<p>npm </p>
<p><code>sudo apt-get install npm</code></p>
<h2 id="백그라운드-실행">백그라운드 실행</h2>
<p>nohup 사용</p>
<h3 id="pm2-사용">pm2 사용</h3>
<h3 id="installing"><strong>Installing</strong></h3>
<p><code>sudo npm install pm2 -g</code></p>
<h3 id="running"><strong>Running</strong></h3>
<p><code>pm2 --name HelloWorld start npm --start</code></p>
<h3 id="listing-running-processes"><strong>Listing running processes</strong></h3>
<p><code>pm2 ps</code></p>
<h3 id="stopping"><strong>Stopping</strong></h3>
<p><code>pm2 delete 0</code></p>
<h3 id="checking-logs"><strong>Checking logs</strong></h3>
<p><code>pm2 logs</code></p>
<h2 id="세팅-결과">세팅 결과</h2>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/1e410ff0-cca2-4410-8e10-0f3bd7f2e145/image.png" alt="">
<em>서버 세팅 완료</em></p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/370128ec-f959-494c-a22e-93f9e256a81d/image.png" alt="">
<em>클라이언트와 서버가 연결된 모습</em></p>
<h3 id="trouble-shooting-1"><strong>Trouble Shooting</strong></h3>
<h2 id="git-clone-시-에러">Git clone 시 에러</h2>
<p>ec2 는 기존에 사용하던 머신이 아닌 새로운 가상 컴퓨터 이므로 등록을 다시 해줘야한다.</p>
<p><code>ssh-keygen -b 4096 -C &quot;[github 이름] [github 이메일]&quot;</code></p>
<p><code>~/.ssh/id_rsa.pub</code> 의 내용을 붙여 쓴다 </p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/a673a62f-45ed-4c1c-8476-ce259de39bb1/image.png" alt="">
다른 방법으로 http 로 clone</p>
<p><code>git clone https://github.com/cs-devops-bootcamp/sprint-aws.git</code></p>
<p>입력 시 username 과 password 입력을 요구한다 여기서 password 에 Repository Read Token 을 입력해준다 </p>
<ul>
<li>발급은  깃허브 깃허브 프로필의 셋팅 → developer setting → personal access → 레포 읽기 토큰 발행 → 복사 후 입력</li>
<li>username : 깃허브 유저네임</li>
</ul>
<h2 id="error-listen-eacces-permission-denied-000080">Error: listen EACCES: permission denied 0.0.0.0:80</h2>
<p>server code 확인시</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/d512b1fe-76a6-4dfe-8fb9-703c0a1e9dc9/image.png" alt="">
포트 번호를 80번으로 사용하는데 실행시키면</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/faea403f-90d3-4f9e-a710-9192653f362a/image.png" alt="">
<code>Error: listen EACCES: permission denied 0.0.0.0:80</code> 에러가 발생 해당 에러는</p>
<p>1024 이하 포트 번호 즉, well knows port 를 사용하려면 root 권한이 필요하고 node 는 해당 80번 포트에 대한 접근권한이 없다는 의미이다</p>
<p>해결 방안</p>
<ul>
<li><p>sudo 사용 : 안됨</p>
<ul>
<li>node를 root권한(sudo ...) 으로 실행시키면 당연히 안된다. 프로젝트 내에 노드모듈이 아니라 root의 노드모듈을 가져다 쓰기 때문임.</li>
</ul>
</li>
<li><p>폴더와 폴더의 하위 모든 파일을 root 로 권한 변경</p>
<ul>
<li>리눅스에서 기본적으로 1024번 미만의 TCP/IP 포트 번호는 일반 사용자가 사용할수 없다.  기본적으로 ubuntu의 계정으로 git pull을 받았기 때문에 서버 폴더와 해당 폴더의 모든 파일의 소유자가 ubuntu 였다.</li>
</ul>
</li>
<li><p>apache나 nginx 등을 이용해서 80번 포트로 받고 해당 내용을 node.js 쪽으로 전달 해주시면 될 것 같습니다.</p>
</li>
<li><p>iptables 를 통한 포트 우회</p>
<ul>
<li><p>포트 80을 사용하지 말고 8080과 같은 다른 포트에서 실행하고, 아래 명령으로 80을 해당 포트로 리디렉션 해서 사용하시거나...</p>
<p>  <code>sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080</code></p>
</li>
<li><p><strong>iptables 초기화</strong></p>
<ul>
<li><p>모든 chain에 설정된 모든 rule을 제거합니다.</p>
<p>  <code>iptables -F</code></p>
</li>
<li><p>기본 chain을 제외한 나머지 모든 chain에 설정된 모든 rule을 제거합니다.</p>
<p>  <code>iptables -X</code></p>
</li>
</ul>
</li>
<li><p>기본 조회입니다. 설정 상태를 볼 수 있다</p>
<p>  <code>iptables -L</code>- 기본 조회 , <code>iptables -L -v</code> - 상세조회</p>
</li>
<li><p>포트 포워딩 확인 할려면 해당 명령어 사용해서 조회</p>
<ul>
<li><code>sudo iptables -t nat -L --line-numbers</code>
<img src="https://velog.velcdn.com/images/qnddj-kjh/post/7760dceb-9f96-428c-88bc-71f16fd0d4f9/image.png" alt="">        </li>
</ul>
</li>
<li><p>포트 포워딩 삭제하는 명령어</p>
<ul>
<li><code>sudo iptalbes -t nat -D PREROUTING [number]</code></li>
<li>ex) <code>sudo iptables -t nat -D PREROUTING 1</code></li>
</ul>
</li>
</ul>
</li>
</ul>
<h1 id="rds">RDS</h1>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/99db9f75-ac7e-4f59-ae08-fcee1ed5e5e0/image.png" alt="">
<img src="https://velog.velcdn.com/images/qnddj-kjh/post/aada15f8-1ee1-44f6-9a3b-6c522458aaf4/image.png" alt="">
<img src="https://velog.velcdn.com/images/qnddj-kjh/post/83c282d1-f21e-41a6-850a-ce1128d89b41/image.png" alt="">
<img src="https://velog.velcdn.com/images/qnddj-kjh/post/98d86aa7-ebb7-413b-b17d-e038c76300b8/image.png" alt="">
<img src="https://velog.velcdn.com/images/qnddj-kjh/post/78b42a00-154f-4247-9b8f-546c728b808d/image.png" alt="">
퍼블릭 액세스는 나중에라도 꼭 차단을 하길 바란다.</p>
<h2 id="vpc-peering">VPC Peering</h2>
<p>VPC Peering이란 서로 다른 VPC간 통신이 가능하도록 연결하는 것을 말합니다. 서비스 구분이나 관리 목적에 따라 VPC 를 구분해 놓았을 때 VPC 간 통신이 필요할 때 사용합니다</p>
<h3 id="목표">목표</h3>
<p>여기서는 EC2 - RDS 간의 VPC 를 따로 두고 RDS 의 퍼블릭 액세스를 차단하기 위함입니다</p>
<p>이렇게 하였을 때 RDS 는 연결된 VPC 안 EC2 인스턴스를 통해서만 액세스 가능해지고 다른 VPC 를 가진 서비스에서도 VPC Peering 을 통해 Database 에 접근이 가능할 수 있도록 구성이 가능해 집니다.</p>
<h3 id="특징">특징</h3>
<ul>
<li>다른 계정간 생성 가능</li>
<li>다른 리전간 생성 가능</li>
<li>둘 다 가능</li>
</ul>
<h3 id="주의점">주의점</h3>
<ul>
<li>VPC 간의 CIDR 대역이 겹치면 안된다<ul>
<li><code>192.168.10.0/24</code> 대역과 <code>192.168.10.0/16</code> 대역을 갖고 있는 VPC 간에는 Peering 자체가 <strong>불가능</strong>하다</li>
</ul>
</li>
<li><strong>VPC Peering</strong> 이후 각 VPC 간 실제 통신을 위해서는 VPC 의 <strong>Route Table</strong> 에서 별도의 설정 필요<ul>
<li><strong>Route Table</strong> : VPC 의 서브넷들이 어떻게 동신되는지 정의해 놓은 테이블이다</li>
</ul>
</li>
</ul>
<h3 id="요약">요약</h3>
<p>VPC Peering 은 각각 다른 VPC 와 다른 CIDR 대역간의 연결을 위해 사용한다.</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/a39fbf42-824a-4f09-85b0-a1d6cf4a7b69/image.png" alt="">
VPC A(요청자) - VPC B(수락자) 를 연결하여 통신이 가능하게끔 만듭니다</p>
<p>A 와 B 가 바뀌어도 상관없지만, 수락자의 계정 또는 리전에서 <strong>요청을 수락하여야</strong> VPC Peering 이 완료됩니다.</p>
<h2 id="route-table-설정">Route Table 설정</h2>
<p>VPC Peering 을 생성해 VPC 간 네트워크 연결할 준비는 끝마쳤다.</p>
<p>이제 VPC Peering 을 사용하여 두 VPC 간의 연결을 하기 위해 Route Table 을 설정해줘야 한다.</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/73554720-042c-4cd5-8e03-90707de0fe98/image.png" alt="">
EC2 인스턴스의 라우팅 테이블의 정보이다</p>
<ul>
<li><code>0.0.0.0/0</code> - <code>igw-0d28...</code> : 인터넷 게이트웨이와 연결되어 인터넷을 사용가능하게 라우팅 된것</li>
<li><code>172.31.0.0/16</code> - <code>local</code> : local 연결이다</li>
</ul>
<p>이제 여기에 대상 VPC 의 CIDR 과 VPC ID 를 연결하고 서브넷 연결 또한 명시해주면 VPC 간의 통신이 이루어진다.</p>
<p>EC2 에서 RDS 로의 데이터 요청이므로 RDS 쪽에만 라우팅해주면 된다.</p>
<p>양방향 통신의 경우 양쪽다 설정해주면 된다.</p>
<p>RDS 는 당연히 보안그룹에서 인바운드 규칙으로 허용해주어야 한다.</p>
<h1 id="결과">결과</h1>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/27ea9733-0377-4ae6-958a-4e14fc2d691a/image.png" alt="">
<img src="https://velog.velcdn.com/images/qnddj-kjh/post/0046139b-8ae8-4e72-9051-fbea214c6652/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[AWS] EC2]]></title>
            <link>https://velog.io/@qnddj-kjh/AWS-EC2</link>
            <guid>https://velog.io/@qnddj-kjh/AWS-EC2</guid>
            <pubDate>Wed, 19 Apr 2023 10:22:41 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/e305baa8-1ae8-4241-958e-6df090f850ed/image.png" alt=""></p>
<h1 id="ec2--elastic-compute-cloud">EC2 : Elastic Compute Cloud</h1>
<p>AWS 에서 제공하는 클라우드 컴퓨팅 서비스로</p>
<p>AWS 에서 원격으로 제어 가능한 가상의 컴퓨터를 한 대 빌리는 것이다</p>
<p>이 가상의 컴퓨터로 서버, 스토리지, 데이터베이스 등의 작업을 할 수 있다</p>
<blockquote>
<p><strong><em>Elastic :</em></strong> 탄력(신축성)있는, 유연한</p>
</blockquote>
<h3 id="이점">이점</h3>
<ul>
<li>구성하는데 필요한 시간이 짧다</li>
<li>다양한 운영체제에 대한 선택이 가능하다<ul>
<li>AMI 라는 다양한 템플릿을 제공한다</li>
<li>AMI 를 통해서 필요한 용도에 따라 다양한 운영체제에 대한 선택이 가능하다<ul>
<li>ubuntu, redhat, ms, Linux 등</li>
</ul>
</li>
<li>CPU 와 RAM, 용량까지도 손쉽게 구성 가능하다</li>
</ul>
</li>
<li>사용한 만큼 지불하여서 저렴하다</li>
<li>사용자가 인스턴스를 완전히 제어 가능하다</li>
<li>보안 및 네트워크 구성, 스토리지 관리에 효과적이다</li>
</ul>
<h2 id=""></h2>
<blockquote>
<p><strong>Instance</strong>
AWS 에서 빌린 컴퓨터를 Instance 라 한다
Instance 는 직접 사용하는 컴퓨터와 다르게 아마존이 전 세계에 만들어 놓은 Data Center 에 만들어져 있기 때문에 네트워크(인터넷)를 통해 제어한다는 차이점만 있을 뿐 일반적인 컴퓨터와 다른 점 없다</p>
</blockquote>
<h3 id="aws-ec2-instance-생성-의미">AWS EC2 Instance 생성 의미</h3>
<p>선택한 AMI 를 토대로 운영체제, CPU, RAM 혹은 런타임 등이 구성된 컴퓨터를 빌리는 것</p>
<h1 id="instance-인스턴스">Instance (인스턴스)</h1>
<h2 id="instance-인스턴스-1">Instance (인스턴스)</h2>
<p>가상 컴퓨팅 환경으로, 하나의 가상 컴퓨터(서버)라고 생각한다.</p>
<p>인스턴스에서 실행하려는 애플리케이션 또는 소프트웨어에 필요한 메모리 양과 컴퓨팅 파워를 기준으로 인스턴스 유형을 선택한다</p>
<h3 id="인스턴스-유형">인스턴스 유형</h3>
<p>AWS 는 각 인스턴스의 사용 목적 (서버용, 머신러닝용, 게임용) 에 따라 타입별로 인스턴스에 이름을 부여해 구분 하고 있다.</p>
<p>인스턴스 유형은 다음으로 쪼개져 있다</p>
<ul>
<li>범용</li>
<li>컴퓨팅 최적화</li>
<li>메모리 최적화</li>
<li>스토리지 최적화</li>
<li>액셀러레이티드 컴퓨팅</li>
<li>이전 세대 인스턴스 유형</li>
</ul>
<p>인스턴스 유형은 굉장히 많고 자세한 내용은 다음 Reference 를 통해 알 수 있다</p>
<ul>
<li><strong><a href="https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/instance-types.html">AWS Docs</a></strong></li>
<li><strong><a href="https://aws.amazon.com/ko/ec2/instance-types/">AWS EC2 안내</a></strong></li>
</ul>
<h3 id="인스턴스-유형-읽는-법">인스턴스 유형 읽는 법</h3>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/5501fd3f-bee7-45fa-b010-f3d92ef4fca9/image.png" alt="missing">
<em>EC2 Instance Type의 작명 규칙 예시  출처: <a href="https://wisen.co.kr/pages/blog/blog-detail.html?idx=12078">https://wisen.co.kr/pages/blog/blog-detail.html?idx=12078</a></em></p>
<ul>
<li><p><code>c</code> : 인스턴스 유형 (패밀리) ( c 는 컴퓨팅 최적화 유형이다)</p>
</li>
<li><p><code>5</code> : 인스턴스 세대</p>
</li>
<li><p><code>d</code> : • C5d 인스턴스를 사용하면 로컬 NVMe 기반 SSD가 호스트 서버에 물리적으로 연결되며 C5 인스턴스 수명과 결합된 블록 수준의 스토리지를 제공 한다고 <a href="https://aws.amazon.com/ko/ec2/instance-types/">안내</a> 되어있다</p>
</li>
<li><p><code>9xlarge</code> : 인스턴스 사이즈로 xlarge 보다 더 큰 사이즈를 뜻함</p>
<p>  <img src="https://velog.velcdn.com/images/qnddj-kjh/post/76120a0d-5452-455c-aad4-76fafaa83bd4/image.png" alt=""></p>
</li>
</ul>
<h2 id="ami-amazone-machine-image">AMI (Amazone Machine Image)</h2>
<p>EC2 인스턴스를 생성할 때 사용하는 소프트웨어 구성이 기재된 템플릿이다</p>
<p>종류로는</p>
<ul>
<li>단순 운영체제(윈도우, 우분투, 리눅스 등)</li>
<li>특정 런타임 설치 템플릿 (우분투 + node.js, 윈도우 + JVM 등)</li>
<li>커스터마이징된 AMI</li>
</ul>
<p>등이 있다.</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/17e893f9-10c5-4fd7-ba1f-862ee6d92f44/image.png" alt="">
<em>AWS EC2 AMI 선택 화면</em></p>
<h2 id="ebselastic-block-storage"><strong>EBS(Elastic Block Storage)</strong></h2>
<p>인스턴스는 연산에 관한(CPU, 메모리 등) 처리를 하는데, 데이터를 저장하는 역할은 EBS 가 한다고 생각하면 된다.</p>
<p>클라우드에서 사용하는 가상 하드디스크(HDD) 역할이다</p>
<p>EBS 는 EC2 인스턴스에 사용할 영구 블록 스토리지 볼륨을 제공한다</p>
<p>단 몇분 내에 사용량을 많게 또는 적게 확장할 수 있으며, 프로비저닝 (빌리는 행위) 한 부분에 대해서만 저렴한 비용을 지불 할 수 있다</p>
<h3 id="볼륨-유형-타입">볼륨 유형 타입</h3>
<p>총 5가지 타입을 제공한다.</p>
<ul>
<li>범용 (General Purpose of GP3) : SSD</li>
<li>프로비저닝 된 IOPS (Provisioned IOPS or io2) : SSD</li>
<li>쓰루풋 최적화 (Throughput Optimized HDD or st1)</li>
<li>콜드 HDD (SC1)</li>
<li>마그네틱 (Standard)</li>
</ul>
<p>AWS 볼륨 유형 안내는 다음과 같다</p>
<ul>
<li><p><strong>SSD 볼륨</strong></p>
<p>  <img src="https://velog.velcdn.com/images/qnddj-kjh/post/cfcd5354-0bae-48ab-a8be-767cc6ae18ac/image.png" alt=""></p>
</li>
</ul>
<ul>
<li><p><strong>HDD 볼륨</strong></p>
<p>  !<img src="https://velog.velcdn.com/images/qnddj-kjh/post/f8405960-c47c-409a-bd51-3860b2136302/image.png" alt=""></p>
</li>
</ul>
<ul>
<li><strong>이전 세대 볼륨</strong></li>
</ul>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/2987b937-173e-4c1e-9488-f4a724af675a/image.png" alt=""></p>
<h2 id="인스턴스의-라이프-사이클">인스턴스의 라이프 사이클</h2>
<p>Amazon EC2 인스턴스는 시작한 순간부터 종료될 때까지 다양한 상태로 전환된다</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/13a8ead3-4b7a-496f-aeab-2bc5b820951f/image.png" alt=""></p>
<p><em>AWS EC2 라이프 사이클  출처: aws</em></p>
<table>
<thead>
<tr>
<th>인스턴스 상태</th>
<th>설명</th>
<th>인스턴스 사용 요금</th>
</tr>
</thead>
<tbody><tr>
<td>pending</td>
<td>인스턴스는 running 상태로 될 준비를 하고 있습니다.</td>
<td></td>
</tr>
<tr>
<td>인스턴스를 처음 시작하거나 pending 상태의 인스턴스를 다시 시작하면 stopped 상태가 됩니다.</td>
<td>미청구</td>
<td></td>
</tr>
<tr>
<td>running</td>
<td>인스턴스를 실행하고 사용할 준비가 되었습니다.</td>
<td>청구</td>
</tr>
<tr>
<td>stopping</td>
<td>인스턴스가 중지 또는 중지-최대 절전 모드로 전환할 준비를 하고 있습니다.</td>
<td>중지 준비 중인 경우 미청구</td>
</tr>
<tr>
<td>최대 절전 모드로 전환 준비 중인 경우 청구</td>
<td></td>
<td></td>
</tr>
<tr>
<td>stopped</td>
<td>인스턴스가 종료되고 사용이 불가합니다. 언제든지 인스턴스를 다시 시작할 수 있습니다.</td>
<td>미청구</td>
</tr>
<tr>
<td>shutting-down</td>
<td>인스턴스가 종료할 준비를 하고 있습니다.</td>
<td>미청구</td>
</tr>
<tr>
<td>terminated</td>
<td>인스턴스가 영구적으로 삭제되었으며 시작할 수 없습니다.</td>
<td>미청구</td>
</tr>
<tr>
<td>참고</td>
<td></td>
<td></td>
</tr>
<tr>
<td>- 종료된 인스턴스에 적용되는 예약 인스턴스는 결제 옵션에 따라 기간이 종료될 때까지 요금이 청구됩니다. 자세한 내용은 <a href="https://docs.aws.amazon.com/ko_kr/ko_kr/AWSEC2/latest/UserGuide/ec2-reserved-instances.html">https://docs.aws.amazon.com/ko_kr/ko_kr/AWSEC2/latest/UserGuide/ec2-reserved-instances.html</a> 섹션을 참조하세요.</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<hr>
<ul>
<li><input disabled="" type="checkbox"> 밑으로는 더 공부하기 더 자세하게<h2 id="인스턴스-구입-옵션"><strong>인스턴스 구입 옵션</strong></h2>
</li>
</ul>
<p>Amazon EC2는 사용자가 요구 사항에 따라 비용을 최적화할 수 있도록 다음과 같은 구입 옵션을 제공</p>
<ul>
<li><strong>온디맨드 인스턴스</strong> - 시작하는 인스턴스에 대한 비용을 초 단위로 지불합니다.</li>
<li><strong>절감형 플랜(Savings Plans)</strong> - 1년 또는 3년 기간 동안 시간당 USD로 일관된 사용량을 약정하여 Amazon EC2 비용을 절감할 수 있습니다.</li>
<li><strong>예약 인스턴스</strong> - 1년 또는 3년 기간 동안 인스턴스 유형 및 리전을 포함하여 일관된 인스턴스 구성을 약정하여 Amazon EC2 비용을 절감할 수 있습니다.</li>
<li><strong>스팟 인스턴스</strong> - 미사용 EC2 인스턴스를 요청하여 Amazon EC2 비용을 대폭 줄일 수 있습니다.</li>
<li><strong>전용 호스트</strong> - 인스턴스 실행을 전담하는 실제 호스트 비용을 지불하며, 기존의 소켓, 코어 또는 VM 소프트웨어별 라이선스를 가져와 비용을 절감합니다.</li>
<li><strong>전용 인스턴스</strong> - 단일 테넌트 하드웨어에서 실행되는 인스턴스 비용을 시간 단위로 지불합니다.</li>
<li><strong>용량 예약</strong> - 원하는 기간 동안 특정 가용 영역의 EC2 인스턴스에 대해 용량을 예약합니다.</li>
</ul>
<h2 id="네트워킹---instance-ip-주소-지정"><strong>네트워킹 - Instance IP 주소 지정</strong></h2>
<h3 id="프라이빗-ipv4"><strong>프라이빗 IPv4</strong></h3>
<p>프라이빗 IPv4 주소는 인터넷을 통해 연결할 수 없는 IP 주소입니다. </p>
<p>프라이빗 IPv4 주소는 동일 VPC에서 인스턴스 간의 통신을 위해 사용합니다. 인스턴스를 시작할 때 인스턴스에 기본 프라이빗 IPv4 주소와 내부 DNS 호스트 이름이 할당됩니다.</p>
<h3 id="퍼블릭-ipv4"><strong>퍼블릭 IPv4</strong></h3>
<p>퍼블릭 IP 주소는 인터넷을 통해 연결할 수 있는 IPv4 주소입니다. </p>
<p>퍼블릭 주소는 인스턴스와 인터넷의 상호 통신을 위해 사용될 수 있습니다. 인스턴스가 중지되거나 최대 절전 모드로 전환되거나 종료되면 인스턴스의 퍼블릭 IP 주소는 해제됩니다. 중지되거나 최대 절전 모드로 전환된 인스턴스가 시작되면 새 퍼블릭 IP 주소가 할당됩니다. 따라서 필요에 따라 인스턴스 간에 연결할 수 있는 영구 퍼블릭 IP 주소가 필요한 경우 탄력적 IP(Elastic IP) 주소를 대신하여 사용합니다.</p>
<h2 id="elastic-ip"><strong>Elastic IP</strong></h2>
<p>탄력적 IP 주소는 동적 클라우드 컴퓨팅을 위해 고안된 정적 IPv4 주소입니다. </p>
<p>탄력적 IP 주소는 AWS 계정에 할당되며 해제할 때까지 할당된 상태로 유지됩니다. 탄력적 IP 주소를 사용하면 주소를 계정의 다른 인스턴스에 신속하게 다시 매핑하여 인스턴스나 소프트웨어의 오류를 마스킹할 수 있습니다. 또는 도메인이 인스턴스를 가리키도록 도메인에 대한 DNS 레코드에 탄력적 IP 주소를 지정할 수 있습니다.
주의해야 할 점은 연결 해제한 탄력적 IP 주소는 명시적으로 릴리스할 때까지 계정에 할당되어 있습니다. 따라서 실행 중인 인스턴스와 <strong>연결되지 않은 탄력적 IP 주소에 대해서는 소액의 시간당 요금이 부과</strong>됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Docker] Docker Compose]]></title>
            <link>https://velog.io/@qnddj-kjh/Docker-Docker-Compose</link>
            <guid>https://velog.io/@qnddj-kjh/Docker-Docker-Compose</guid>
            <pubDate>Wed, 12 Apr 2023 09:14:34 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/833d2dfb-0177-453b-bcad-deb3c2004c56/image.png" alt=""></p>
<p>Docker Compose는 Dockerized 애플리케이션을 정의하고 실행하기 위한 도구입니다. </p>
<p>여러개의 컨테이너를 정의하고 실행하기 위한 YAML 파일로 작성됩니다. </p>
<blockquote>
<p>Dockerized란 Docker 컨테이너 내에서 실행되는 애플리케이션 또는 서비스를 의미합니다. 즉, Docker 컨테이너를 사용하여 애플리케이션을 패키징하고, 배포하며 실행하는 것을 의미</p>
</blockquote>
<h2 id="docker-compose-설치">Docker Compose 설치</h2>
<p><code>Docker docs</code> 에서 가장 권장하는 방법은 Docker Desktop 을 설치하는 것이다</p>
<p>Docker Desktop 이 설치되어진 경우 말고 Docker Engine 및 Docker CLI 가 이미 설치되어 있는 경우는 다음과 같다</p>
<h3 id="저장소를-사용하여-설치-하는-경우">저장소를 사용하여 설치 하는 경우</h3>
<ol>
<li><p>저장소를 설정하여야 한다. 저장소 설정의 경우 다음 링크를 통해 확인</p>
<p> <a href="https://docs.docker.com/engine/install/ubuntu/#set-up-the-repository">우분투</a> | <a href="https://docs.docker.com/engine/install/centos/#set-up-the-repository">센트OS</a> | <a href="https://docs.docker.com/engine/install/debian/#set-up-the-repository">데비안</a> | <a href="https://docs.docker.com/engine/install/fedora/#set-up-the-repository">페도라</a> | <a href="https://docs.docker.com/engine/install/rhel/#set-up-the-repository">RHEL</a> | <a href="https://docs.docker.com/engine/install/sles/#set-up-the-repository">SLES</a> .</p>
</li>
<li><p>패키지 인덱스를 업데이트 및 최신 버전의 Docker Compose 설치</p>
<pre><code class="language-bash"> # Ubuntu 기준 설명
 $ sudo apt-get update
 $ sudo apt-get install docker-compose-plugin</code></pre>
</li>
<li><p>버전을 확인 Docker Compose 설치 확인</p>
<pre><code class="language-bash"> $ docker compose version</code></pre>
</li>
</ol>
<h3 id="플러그인-수동-설치">플러그인 수동 설치</h3>
<ol>
<li><p>Compose CLI 플러그인을 다운로드하고 설치</p>
<pre><code class="language-bash"> DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
 mkdir -p $DOCKER_CONFIG/cli-plugins
 curl -SL https://github.com/docker/compose/releases/download/v2.17.2/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose</code></pre>
</li>
<li><p>바이너리에 실행 권한 적용</p>
<pre><code class="language-bash"> chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
 # 또는 모든 사용자를 위한 Compose 설치
 sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose</code></pre>
</li>
<li><p>설치 확인</p>
<pre><code class="language-bash"> $ docker compose version</code></pre>
</li>
</ol>
<h2 id="docker-compose">Docker Compose</h2>
<p>Docker Compose  의 최신 버전은 2023년 6월 말부터 Compose V1은 더 이상 지원되지 않으며 모든 Docker Desktop 버전에서 제거됨으로 Docker Compose V2 라고 봐도 무방하다.</p>
<p>Docker Compose V2 의 경우 명령어에서 변화가 있어 알아 두어야 한다.</p>
<pre><code class="language-bash">docker-compose up
# v1 에서의 사용 명령어
docker compose up
# v2 에서의 사용 명령어 </code></pre>
<h3 id="docker-compose-yaml-파일-작성하기"><strong>Docker Compose YAML 파일 작성하기</strong></h3>
<p>Docker Compose YAML 파일을 작성해서 Docker Compose 를 사용할 준비를 합니다. 이 파일은 여러 개의 컨테이너를 정의하고 각 컨테이너가 실행되는 방식을 설정합니다. </p>
<pre><code class="language-yaml"># Docker Compose YAML 파일의 예시
version: &quot;3.9&quot;

services:
  web:
    build: .
    ports:
      - &quot;5000:5000&quot;
    volumes:
      - .:/code
    depends_on:
      - redis
  redis:
    image: &quot;redis:alpine&quot;</code></pre>
<ul>
<li><strong><code>version</code> :</strong> Compose 파일의 버전</li>
<li><strong><code>services</code> :</strong> 컨테이너들의 설정을 정의</li>
<li>위 예시에서는 <strong><code>web</code></strong>과 <strong><code>redis</code></strong>라는 두 개의 컨테이너를 정의<ul>
<li>각각의 컨테이너 이미지 이름</li>
<li>Dockerfile 위치</li>
<li>포트 포워딩,</li>
<li>볼륨 마운트</li>
<li>다른 컨테이너에 대한 의존성이 정의</li>
</ul>
</li>
</ul>
<h3 id="사용-명령어">사용 명령어</h3>
<ul>
<li><p><strong>실행</strong></p>
<p>  Docker Compose YAML 파일을 작성한 후 해당 디렉토리에서 다음 명령어 사용</p>
<pre><code class="language-bash">  $ docker compose up
  # Docker Compose YAML 파일에서 정의된 모든 컨테이너를 빌드하고 실행한다
  # 기본적으로 docker-compose.yml 파일을 찾는다
  # -d detech 옵션을 사용하여 백그라운드 실행 가능

  # 특정 다른 이름의 파일을 사용해야 할 경우
  # -f 또는 --file 옵션을 사용 docker compose 가 사용할 파일 이름 지정
  $ docker compose -f docker-compose-dev.yml up
  # 여러번 사용하여 파일 추가 가능
  $ docker compose -f docker-compose.yml -f docker-compose.dev.yml up</code></pre>
</li>
<li><p><strong>중지</strong></p>
<p>  Docker Compose를 중지하려면 다음과 같이 <strong><code>docker-compose down</code></strong> 명령어를 사용합니다.</p>
<pre><code class="language-yaml">  $ docker compose down
  # docker compose 실행 중인 모든 컨테이너를 중지하고, 컨테이너, 네트워크 및 볼륨과 같은 모든 Docker 자원을 삭제</code></pre>
</li>
<li><p><strong>Docker Compose 로 관리할 수 있는 컨테이너 확인</strong></p>
<pre><code class="language-yaml">  $ docker compose ps
  # yml 없으면 나오는 경고문
  # no configuration file provided: not found</code></pre>
</li>
<li><p><strong>※ 주의</strong></p>
<ul>
<li>docker compose 모든 명령어는 docker compose 설정 파일이 있는 디렉토리에서 사용</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Docker] 기본적인 CLI 명령어]]></title>
            <link>https://velog.io/@qnddj-kjh/Docker-%EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9D%B8-CLI-%EB%AA%85%EB%A0%B9%EC%96%B4</link>
            <guid>https://velog.io/@qnddj-kjh/Docker-%EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9D%B8-CLI-%EB%AA%85%EB%A0%B9%EC%96%B4</guid>
            <pubDate>Wed, 12 Apr 2023 05:21:34 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/90e23b45-fda9-4450-8ef8-c6c35750ee20/image.png" alt=""></p>
<h1 id="도커-클라이언트-명령어">도커 클라이언트 명령어</h1>
<h2 id="도커-이미지의-내부-파일-구조-보기"><strong>도커 이미지의 내부 파일 구조 보기</strong></h2>
<ul>
<li><code>docker run ls</code><ul>
<li>명령어 진행 순서<ol>
<li>이미지를 이용해 컨테이너 생성</li>
<li>이미지 안에 들어 있는 파일 스냅숏(bin, dev, etc 등 : 리눅스 커널 디렉토리 부터 다양한 파일과 프로그램들) 이 컨테이너 안에 있는 하드디스크로 다운로드</li>
<li>이미지 이름 뒤에 다른 명령어를 추가했기 때문에( <code>ls</code> ) 원래 이미지에 들어 있는 기본 명령어는 무시되고 <code>ls</code> 명령어가 실행되어 파일 구조를 확인할 수 있다.</li>
</ol>
</li>
<li>주의 : 모든 도커 이미지에서 <code>ls</code> 명령어를 실행 할 수 있는 것이 아닌 <code>ls</code> 명령어를 사용할 수 있는 파일이 들어 있는 경우 사용가능하다. 다른 명령어 또한 마찬가지이다.</li>
</ul>
</li>
</ul>
<hr>
<h2 id="컨테이너-나열하기"><strong>컨테이너 나열하기</strong></h2>
<ul>
<li><p><code>docker ps</code></p>
<ul>
<li><p>ps = process status 약자이다.</p>
</li>
<li><p>실행중인 도커 컨테이너를 나열하여 보여주는 명령어이다.</p>
</li>
<li><p>출력 항목</p>
<ul>
<li><code>CONTAINER ID</code> : 컨테이너의 고유한 아이디 해시값, 실제로는 더 길지만 일부분만 출력, 중복이 안된다 (해시값이니깐)</li>
<li><code>IMAGE</code> : 컨테이너 생성 시 사용한 도커 이미지 이름</li>
<li><code>COMMAND</code> : 컨테이너 시작 시 실행될 명령어, 대부분 이미지에 내장되어 있어 별도 설정이 불필요 하다.</li>
<li><code>CREATED</code> : 컨테이너가 생성된 시각</li>
<li><code>STATUS</code> : 컨테이너의 상태, 실행 중 = Up, 종료 = Exited, 일시 정지 = Pause</li>
<li><code>PORTS</code> : 컨테이너가 개방한 포트와 호스트에 연결한 포트, 특별한 설정을 하지 않은 경우 출력되지 않는다</li>
<li><code>NAMES</code> : 컨테이너의 고유한 이름, 컨테이너 생성시 <code>--name</code> 옵션으로 이름을 설정하지 않으면 <strong>도커 엔진이 임의로 형용사와 명사를 조합해 설정</strong>, id와 마찬가지로 중복이 안된다. <code>dorcer rename &lt;원래이름&gt; &lt;변경할 이름&gt;</code>  명령어 사용으로 이름을 변경할 수 있다.</li>
</ul>
<h3 id="원하는-항목만-보기"><strong>원하는 항목만 보기</strong></h3>
</li>
<li><p><code>docker ps --format &#39;table {{.Name}} \t table {{.Image}}&#39;</code> 와 같이 쓴다.</p>
<h3 id="모든-도커-컨테이너를-나열"><strong>모든 도커 컨테이너를 나열</strong></h3>
</li>
<li><p><code>docker ps -a</code></p>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="도커-컨테이너의-생성과-실행"><strong>도커 컨테이너의 생성과 실행</strong></h2>
<p>도커 컨테이너에는 생명 주기가 있다. 다음 생명 주기 별 명령어를 알아보겠다./</p>
<p>생성 → 시작 → 실행 → 중지(재시작 가능한 상태) → 삭제</p>
<hr>
<h2 id="도커-컨테이너를-생성하고-실행하기"><strong>도커 컨테이너를 생성하고 실행하기</strong></h2>
<ul>
<li><code>docker run &lt;이미지 이름&gt;</code><ul>
<li>두 개의 명령어가 합쳐진 명령어이다.<ul>
<li><code>docker create &lt;이미지 이름&gt;</code> : 도커 이미지를 이용해 도커 컨테이너를 생성<ul>
<li>이미지 안 파일들을 도커 컨테이너의 하드디스크로 다운</li>
</ul>
</li>
<li><code>docker start &lt;컨테이너 ID/이름&gt;</code> : 생성된 도커 컨테이너 시작해서 실행<ul>
<li>이미지 안에 있는 시작 시 실행할 명령어 컨테이너 안에서 작동시킨다.</li>
<li><code>docker start -a &lt;컨테이너 ID/이름&gt;</code><ul>
<li><code>-a</code> 옵션 : <strong>attach</strong> 의 약자로 컨테이너를 실행한 후에 <strong>표준 입력(stdin), 표준 출력 (stdout), 표준 에러(stderr)</strong>를 가능하게 하고, 프로그램으로 입력 받은 내용을 터미널에 포여주는 역할을 하는 옵션</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="도커-컨테이너-멈추기"><strong>도커 컨테이너 멈추기</strong></h2>
<ul>
<li><code>docker stop &lt;중지할 컨테이너 ID/이름&gt;</code> or <code>docker kill &lt;중지할 컨테이너 ID/이름&gt;</code> 두 가지 명령어 사용</li>
<li>차이점<ul>
<li><code>docker stop</code> 은 <strong>Graceful(우아하게)하게</strong> 컨테이너를 중지시킨다.<ul>
<li>Graceful 하다 == 하고 있던 작업들을 모두 마치고 컨테이너를 중지시키는 것을 뜻함</li>
<li><code>docker stop</code> 명령어는 <code>SIGTERM</code> 이라는 것을 보내 진행 중인 프로세스를 정리하는 시간(Grace Period)을 갖게한 다음에 <code>SIGKILL</code>을 보내서 컨테이너를 중지 시킨다.</li>
</ul>
</li>
<li><code>docker kill</code> 은 어떠한 것도 기다리지 않고 <strong>즉시</strong> 컨테이너를 중지시킨다.<ul>
<li><code>docker kill</code> 은 <code>SIGTERM</code> 없이 <code>SIGKILL</code> 을 보내서 모든 프로세스를 멈추고 컨테이너를 중지 시킨다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="도커-컨테이너-삭제하기"><strong>도커 컨테이너 삭제하기</strong></h2>
<ul>
<li><code>docker rm &lt;중지할 컨테이너 ID/이름&gt;</code><ul>
<li>주의 : 삭제할 때에는 컨테이너가 중지된 상태여야 한다. 실행중이라면 오류 발생</li>
</ul>
</li>
</ul>
<h3 id="중지된-모든-컨테이너-삭제하기"><strong>중지된 모든 컨테이너 삭제하기</strong></h3>
<ul>
<li><code>docker rm</code>docker ps -a -q<code>: `&#39;` 홑 따옴표 아니다.</code> (그레이브)` 이거다</li>
</ul>
<h3 id="도커-이미지-삭제하기"><strong>도커 이미지 삭제하기</strong></h3>
<ul>
<li><code>docker rmi &lt;이미지 ID&gt;</code></li>
</ul>
<h3 id="사용하지-않는-데이터-삭제하기"><strong>사용하지 않는 데이터 삭제하기</strong></h3>
<ul>
<li><code>docker system prune</code></li>
</ul>
<hr>
<h2 id="실행-중인-컨테이너에-명령어-전달하기">실행 중인 컨테이너에 명령어 전달하기</h2>
<ul>
<li><code>docker exec &lt;컨테이너 ID&gt; &lt;명령어&gt;</code><ul>
<li>이미 실행중인 도커 컨테이너에 명령어를 보낸다.</li>
</ul>
</li>
</ul>
<hr>
<h2 id="레디스를-이용해-도커-컨테이너-이해">레디스를 이용해 도커 컨테이너 이해</h2>
<p><code>docker run redis</code> 로 레디스 서버 실행</p>
<p><code>redis-cli</code> 로 레디스 클라이언트 실행</p>
<p><strong>레디스 클라이언트 → 명령어 실행 <code>set value1 hello</code> → 레디스 서버</strong></p>
<p>하지만 <code>redis-cli</code> 명령어로 레디스 클라이언트를 실행하면 에러가 난다.</p>
<ul>
<li>이유는?<ul>
<li>레디스 클라이언트 실행 <code>redis-cli</code> : 실행하려 하지만 도커 컨테이너 밖이라 실행이 안된다.</li>
<li>도커 컨테이너 [ 레디스 서버 - 동작 중 ]</li>
</ul>
</li>
<li>해결은?<ul>
<li>도커 컨테이너 [ 레디스 클라이언트 → 레디스 서버 ] : 도커 컨테이너 안에서 실행하는 방법으로 해결해야 한다.</li>
<li>도커 컨테이너 안에서 레디스 클라이언트를 실행하기 위해 앞에서 배운 <code>exec</code> 명령어를 사용한다</li>
<li><code>docker exec -it &lt;레디스 컨테이너 ID&gt; redis-cli</code><ul>
<li>여기서 <code>-it</code> 옵션은?</li>
<li><code>-i</code>  :  interactive</li>
<li><code>-t</code>  : terminal</li>
<li><code>-it</code> 옵션이 없으면 <code>redis-cli</code> 를 실행과 동시에 종료된다.</li>
</ul>
</li>
<li>레디스 클라이언트가 실행되고 명령어를 칠 수 있게 된다 <code>set key1 hello</code>, → <code>get key1</code></li>
</ul>
</li>
</ul>
<hr>
<h3 id="실행-중인-컨테이너에서-터미널-사용하기">실행 중인 컨테이너에서 터미널 사용하기</h3>
<ul>
<li><code>docker exec -it sh &lt;컨테이너 ID&gt; sh</code></li>
<li>매번 <code>docker exec -it &lt;컨테이너 ID&gt; &lt;명령어&gt;</code> 명령어로 모두 입력하는 것은 비효율적인 작업이다. 비효율적인 면을 해결하기 위해 사용한다.</li>
<li>도커 컨테이너에 셸이나 터미널 환경으로 접속해 사용하는 명령어</li>
<li><code>Ctrl + D</code> 로 셸이나 터미널 환경에서 나올 수 있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Docker] 도커와 컨테이너]]></title>
            <link>https://velog.io/@qnddj-kjh/Docker-%EB%8F%84%EC%BB%A4%EC%99%80-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88</link>
            <guid>https://velog.io/@qnddj-kjh/Docker-%EB%8F%84%EC%BB%A4%EC%99%80-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88</guid>
            <pubDate>Tue, 11 Apr 2023 08:23:31 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/66a1932b-2147-40d6-b6d2-7be83cacbd24/image.png" alt=""></p>
<h1 id="도커와-컨테이너">도커와 컨테이너</h1>
<p>AWS 에서의 도커 정의:</p>
<ul>
<li>Docker는 애플리케이션을 신속하게 구축, 테스트 및 배포할 수 있는 소프트웨어 플랫폼입니다. Docker는 소프트웨어를 <a href="https://aws.amazon.com/ko/containers/">컨테이너</a> 라는 표준화된 유닛으로 패키징하며, 이 컨테이너에는 라이브러리, 시스템 도구, 코드, 런타임 등 소프트웨어를 실행하는 데 필요한 모든 것이 포함되어 있습니다. Docker를 사용하면 환경에 구애받지 않고 애플리케이션을 신속하게 배포 및 확장할 수 있으며 코드가 문제없이 실행될 것임을 확신할 수 있습니다.</li>
</ul>
<p>위키피디아에서 제공하는 도커의 정의:</p>
<ul>
<li>(Docker)는 <a href="https://ko.wikipedia.org/wiki/%EB%A6%AC%EB%88%85%EC%8A%A4">리눅스</a>의 <a href="https://ko.wikipedia.org/wiki/%EC%9D%91%EC%9A%A9_%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4">응용 프로그램</a>들을 프로세스 격리 기술들을 사용해 컨테이너로 실행하고 관리하는 <a href="https://ko.wikipedia.org/wiki/%EC%98%A4%ED%94%88_%EC%86%8C%EC%8A%A4">오픈 소스</a> 프로젝트이다.</li>
</ul>
<p>둘 모두 도커에 대해서 자세히 알기 어렵지만 컨테이너라는 개념이 나온다.</p>
<h2 id="컨테이너">컨테이너</h2>
<p>실생활에서의 컨테이너는 반복 사용 가능한 상자모양의 큰 수송 용기 물건을 담는 용도이다.</p>
<h3 id="도커에서의-컨테이너">도커에서의 컨테이너</h3>
<p>실세계에서 무언가를 담는 것처럼 도커에서의 컨테이너는 다양한 프로그램과 실행 환경을 컨테이너에 담고, 동일한 인터페이스를 제공하여 <strong>프로그램의 배포 및 관리</strong>를 단순하게 한다.</p>
<h3 id="도커-이미지와-도커-컨테이너">도커 이미지와 도커 컨테이너</h3>
<p> 도커 컨테이너를 만들기 위해서는 도커 이미지가 필요하다.</p>
<p>둘 정의</p>
<ul>
<li><strong>도커 컨테이너 :</strong> 코드와 모든 종속성을 패키지화하여 응용 프로그램이 한 컴퓨팅 환경에서 다른 컴퓨팅 환경으로 안정적으로 실행되도록 하는 소프트웨어 표준이다.</li>
<li><strong>도커 이미지 :</strong> 코드, 런타임, 시스템 도구, 시스템 라이브러리 및 설정과 같은 응용 프로그램을 실행하는 데 필요한 모든 것을 포함하는 가볍고 독립적이며 실행 가능한 소프트웨어 패키지이다.</li>
</ul>
<p>도커 이미지를 이용해 여러 개의 도커 컨테이너를 만들 수 있다. 이때 도커 컨테이너를 도커 이미지의 인스턴스라고 부른다.</p>
<h2 id="도커를-사용할-때의-흐름">도커를 사용할 때의 흐름</h2>
<ol>
<li><p>도커 클라이언트(CLI) 에 원하는 명령을 위한 명령어를 입력</p>
</li>
<li><p>도커 서버(도커 데몬)가 도커 클라이언트에 입력한 명령어를 전달받으면 명령어에 따른 이미지를 생성하고, 컨테이너를 실행한다. 그리고 해당 컨테이너에서 애플리케이션을 실행한다</p>
<ol>
<li><p>간단한 도커 사용</p>
</li>
<li><p>hello-world 라는 프로그램을 도커 환경에서 실행한다. 이미지의 이름이 hello-world이다.</p>
<pre><code class="language-docker">docker run hello-world</code></pre>
</li>
</ol>
<p> <strong>hello-world 프로그램 도커 내부 처리 과정</strong></p>
<ol>
<li>도커 클라이언트에 명령어를 입력하면 클라이언트에서 도커 서버로 요청</li>
<li>서버에서 hello-world 라는 이미지가 로컬에 이미 다운로드 되어 있는지 확인</li>
<li>이미지가 있으면 5번으로 없으면 <code>Unable to find image &#39;hello-world:latest&#39; locally&#39;</code> 문구 출력</li>
<li>도커 이미지가 저장된 도커 허브(<code>Docker Hub</code>)에서 hello-world 이미지를 가져오고, 로컬에 저장 후 보관한다. (이미지 캐시 보관 장소)</li>
<li>hello-world 이미지를 이용해서 컨테이너를 생성</li>
<li>생성된 컨테이너는 이미지에서 받은 설정이나 조건에 따라 프로그램을 실행한다.</li>
</ol>
</li>
</ol>
<h2 id="도커와-기존-가상화-기술의-차이점">도커와 기존 가상화 기술의 차이점</h2>
<h3 id="가상화-기술-이전-서버">가상화 기술 이전 서버</h3>
<p>하나의 서버, 하나의 운영체제, 하나의 프로그램만을 운영하여 안정적이지만 사용하지 않는 공간이 많아 비효율적</p>
<h3 id="하이퍼바이저-기반의-가상화-기술">하이퍼바이저 기반의 가상화 기술</h3>
<p>논리적으로 공간을 분할하여 가상 머신(VM) 이라는 독립적인 가상 환경에서 서버를 이용하는 기술을 이용해, 한 대의 서버로 여러 프로그램을 운영가능하게 되며 비효율적인 부분 해결.</p>
<p> 하이퍼바이저는 호스트 시스템에서 다수의 게스트 운영체제(OS) 를 구동할 수 있게 해주는 소프트웨어이며, 하드웨어를 가상화하면서 하드웨어와 각각의 가상 머신(VM) 을 모니터링하는 중간 관리자이기도 하다.</p>
<p><strong>하이퍼 바이저의 종류</strong></p>
<ul>
<li>하이퍼바이저<ul>
<li>네이티브 하이퍼바이저<ul>
<li>구성</li>
<li>하드웨어 → 하이퍼바이저 → OS</li>
</ul>
</li>
<li>호스트형 하이퍼바이저<ul>
<li>구성</li>
<li>하트웨어 → OS → 하이퍼바이저 → OS</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><strong>네이티브 하이퍼바이저 (bare metal, MS Azure 에서 사용하는 방식)</strong></p>
<ul>
<li>하이퍼바이저가 직접 하드웨어를 제어하기 때문에 자원을 효율적으로 사용 가능</li>
<li>별도의 호스트OS 가 없어 오버헤드가 적다</li>
<li>여러 하드웨어 드라이버를 세팅해야 하므로 설치가 어려움</li>
</ul>
<p><strong>호스트형 하이퍼바이저</strong></p>
<ul>
<li>OS 위에서 실행된다.</li>
<li>하드웨어 자원을 <strong>VM 내부의 게스트 OS</strong> 에 에뮬레이트 하는 방식 == 오버헤드가 크다</li>
<li>게스트 OS 종류에 대한 제약이 없고 구현이 쉽다.</li>
<li>대다수 많은 사람이 이용하는 VM</li>
</ul>
<p><strong>도커 컨테이너</strong> 는 가상 머신(VM)과 비교했을 떄 하이퍼바이저와 게스트OS 가 필요하지 않기 때문에 가볍다. 호스트 OS 위에 애플리케이션의 실행 패키지인 이미지만 배포하면 끝이다.</p>
<p><strong>가상 머신</strong>은 애플리케이션을 실행하기 위해 가상 머신을 실행하고 자원을 할당한 다음, 게스트 OS(무겁다)를 부팅해 애플리케이션을 실행한다. → 훨씬 복잡하고 무겁다.</p>
<h2 id="도커-컨테이너-격리-원리">도커 컨테이너 격리 원리</h2>
<p>리눅스의 Cgroup(control groups)과 네임스페이스(namespaces)에 대해 알아야 한다.</p>
<h3 id="cgroupcontrol-groups과-네임스페이스namespaces">Cgroup(control groups)과 네임스페이스(namespaces)</h3>
<p>다른 프로세스 사이에 벽을 만드는 <strong>리눅스 커널</strong>의 기능이다.</p>
<p>??? 도커를 사용하는 개발 환경 중 Windows 와 macOS 가 다수인데 어떻게 도커는 Linux 커널의 기능을 사용하는가? </p>
<p>→ <strong>도커 서버는 리눅스 VM 환경에서 실행되고 있기 때문이다</strong>. 따라서 모든 컨테이너가 리눅스 가상 머신에서 생성되며, 리눅스 커널이 컨테이너를 격리시키고 리소스를 나눠주게 된다.</p>
<p>Cgroup</p>
<ul>
<li>CPU, 메모리, 네트워크 대역폭, HD I/O 등 프로세스 그룹의 시스템 리소스 사용량을 관리</li>
</ul>
<p>네임스페이스</p>
<ul>
<li>하나의 시스템에서 프로세스를 격리시킬 수 있는 가상화 기술로 별개의 독립된 공간을 사용하는 것처럼 격리된 환경을 제공하는 경량 프로세스 가상화 기술이다.</li>
</ul>
<h3 id="도커-컨테이너-구조">도커 컨테이너 구조</h3>
<p>호스트 OS 는 공유하지만 하나의 컨테이너는 다른 컨테이너와 격리되며 그 안에서 실행되는 프로세스를 작동시키기 위해 필요한 양에 맞는 디스크, 네트워크, RAM 등이 할당되어 있다.</p>
<h2 id="도커-이미지">도커 이미지</h2>
<p>도커 이지미는 응용 프로그램을 실행하는 데 <strong>필요한 모든 것</strong>을 포함한다.</p>
<p>필요한 모든 것</p>
<ol>
<li>컨테이너가 시작될 때 실행할 명령어<ol>
<li>예) run kakaotalk</li>
</ol>
</li>
<li>파일 스냅숏<ol>
<li>파일 스냅숏은 디렉터리나 파일을 복사한 것</li>
</ol>
</li>
</ol>
<h3 id="도커-컨테이너-생성되는-순서">도커 컨테이너 생성되는 순서</h3>
<ol>
<li>도커 클라이언트에 <code>‘docker run &lt;이미지&gt;’</code> 명령어 실행</li>
<li>도커 이미지에 있는 파일 스냅숏을 컨테이너에 있는 하드 디스크로 옮긴다.
(컨테이너 안에서 애플리케이션을 설치하고 실행해야 하므로 컨테이너로 이동시킨다.)</li>
<li>도커 이미지가 가지고 있는 명령어(컨테이너가 실행될 때 사용할 명령어)를 컨테이너에 전달한다.</li>
<li>컨테이너가 실행될 때 명령어를 이용해 애플리케이션 실행</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프록시] Proxy]]></title>
            <link>https://velog.io/@qnddj-kjh/%ED%94%84%EB%A1%9D%EC%8B%9C-Proxy</link>
            <guid>https://velog.io/@qnddj-kjh/%ED%94%84%EB%A1%9D%EC%8B%9C-Proxy</guid>
            <pubDate>Fri, 07 Apr 2023 12:20:35 GMT</pubDate>
            <description><![CDATA[<h2 id="proxy">Proxy</h2>
<p>클라이언트와 서버 사이에서 중계 역할을 수행하는 컴퓨터 시스템이나 응용 프로그램을 말한다.</p>
<p>Proxy 사전적 의미로 <code>‘대리’</code> 하는 것을 뜻한다.</p>
<p>이것으로 컴퓨터에서 어떠한 작업을 대신하는 것을 뜻한다.</p>
<h2 id="proxy-server">Proxy Server</h2>
<p>프록시 서버는 클라이언트에서 서버로 접속을 할 때 직접적으로 접속하지 않고 중간에 대신 전달하는 서버를 의미한다.</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/b5ba8f57-ed63-423d-aa32-3155b083c896/image.png" alt="출처 : [https://hylog.vercel.app/posts/what-is-proxy](https://hylog.vercel.app/posts/what-is-proxy)">
출처 : <a href="https://hylog.vercel.app/posts/what-is-proxy">https://hylog.vercel.app/posts/what-is-proxy</a></p>
<h3 id="proxy-server-요청과-응답-과정">Proxy Server 요청과 응답 과정</h3>
<p><strong>과정</strong></p>
<ul>
<li>클라이언트에서 웹 브라우저를 URL 을 입력하여 프록시 서버로 Request 를 보낸다.</li>
<li>프록시 서버는 내부에서 설정된 요청받은 URL 과 연결된 웹 서버로 Request 를 보낸다.</li>
<li>Request 를 받은 웹 서버는 Response 를 보내준다</li>
<li>프록시 서버가 Response 를 받고 다시 클라이언트의 웹 브라우저로 Response 를 보낸다.</li>
</ul>
<p><strong>이점</strong></p>
<ul>
<li>클라이언트와 서버 간의 직접적인 통신을 막음</li>
<li>보안강화</li>
<li>로드 밸런싱 등의 기능을 수행</li>
</ul>
<h2 id="proxy-종류">Proxy 종류</h2>
<p><strong>웹 프록시 (Web Proxy)</strong></p>
<ul>
<li>웹 페이지를 요청하는 클라이언트와 웹 서버 사이에서 중계 역할을 수행</li>
<li>웹 프록시는 캐싱을 이용하여 웹 페이지를 빠르게 전송한다.</li>
<li>웹 필터링을 통해 사용자가 웹 사이트를 접근하는 것을 제어한다.</li>
</ul>
<p><strong>리버스 프록시 (Reverse Proxy)</strong></p>
<ul>
<li>웹 서버와 클라이언트 사이에서 요청을 수신하여 이를 내부 서버로 전달한다.</li>
<li>보안상 이유로 내부 서버에 직접 접근하지 않고, 외부에서 접근할 수 있는 공개적인 IP 주소를 사용하여 서버를 보호한다.</li>
</ul>
<p><strong>익명 프록시 (Anonymous Proxy)</strong></p>
<ul>
<li>사용자의 IP 주소를 숨기고, 웹 페이지를 요청하는 클라이언트와 웹 서버 사이에서 중계</li>
<li>인터넷 사용자의 개인 정보를 보호하기 위해 사용</li>
</ul>
<p><strong>투명 프록시 (Transparent Proxy)</strong> </p>
<ul>
<li>웹 페이지를 요청하는 클라이언트와 웹 서버 사이에서 중계</li>
<li>사용자의 IP 를 숨기지 않음</li>
<li>보안상의 이유로 내부 네트워크에 있는 서버에 직접 접근하지 않고 프록시를 거쳐야만 접근하도록 하는 방화벽 역할을 한다.</li>
</ul>
<p><strong>SOCKS 프록시 (SOCKS Proxy)</strong></p>
<ul>
<li>다양한 프로토콜을 지원하는 프록시</li>
<li>TCP 및 UDP 데이터를 전송가능</li>
<li>사용자 인증 기능 지원</li>
</ul>
<h2 id="proxy-의-역할">Proxy 의 역할</h2>
<p><strong>성능 개선</strong></p>
<p><strong>캐싱</strong></p>
<ul>
<li>이전에 요청한 내용을 캐시하여 동일 요청시 서버에 요청하지 않고 캐시된 데이터를 반환할 수 있다</li>
<li>네트워크 병목 현상 해결하고, 응답 속도를 향상시킬 수 있다.</li>
</ul>
<p><strong>익명화</strong></p>
<ul>
<li>클라이언트 IP 를 가릴 수 있어 익명성 제공</li>
<li>개인정보 사용자 프라이버시를 보호</li>
</ul>
<p><strong>필터링과 접근 제어</strong></p>
<ul>
<li>HTTP 요청 및 응답을 필터링하여 접근 제어, 콘텐츠 제한 웹 사용량 제한 등 수행</li>
<li>보안 강화와 네트워크 대역폭 절약 효과</li>
</ul>
<p><strong>보안</strong></p>
<ul>
<li>클라이언트 IP 주소 은닉</li>
<li>필터링을 통해 악성 코드나 스팸 차단</li>
</ul>
<p><strong>부하 분산 (로드 밸런싱)</strong></p>
<ul>
<li>여러 대의 서버에게 클라이언트들의 요청을 분산 시키는 로드 밸런싱 기능을 수행</li>
<li>서버의 부하를 분산시켜 서버의 성능을 향상</li>
<li>안정적인 서비스를 제공</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Devops/회고]Section 1. 실습과제]]></title>
            <link>https://velog.io/@qnddj-kjh/devops04s1team4</link>
            <guid>https://velog.io/@qnddj-kjh/devops04s1team4</guid>
            <pubDate>Wed, 05 Apr 2023 05:48:08 GMT</pubDate>
            <description><![CDATA[<h2 id="summary">Summary</h2>
<ul>
<li>간단하지만 시간이 촉박하다 3일의 시간이 주어지지만 2.5일 느낌</li>
<li>기능과 코드의 퀄리티를 높이기 보다는 협업을 중점을 두고 팀원들과 작업하였다</li>
<li>미숙한 git 사용법으로 충돌 에러를 많이 보았지만, 경험을 많이 쌓을 수 있었던 거 같기도…</li>
<li>설계는 어렵다…🥴</li>
</ul>
<hr>
<p>시작한지 얼마 안된 것 같은데 벌써 한달의 시간이 지나가고 있고 
첫 번째 프로젝트가 끝났습니다.</p>
<ul>
<li>리눅스 운영체제</li>
<li>웹서비스 개발 기초</li>
<li>Git </li>
<li>HTTP</li>
<li>WEB / WAS Server </li>
<li>데이터베이스</li>
</ul>
<p>한달의 시간이 훅 빠져나간 이유인 공부주제들...(많기도 하다🤮)</p>
<p>부트캠프를 수강하기도 전에도 계속 공부해오던 내용이라 적응하는 것에 중점을 둬서 공부했었다. 몰랐던 내용도 알게 되며 아직은 여유가 있었다고 느꼈다</p>
<hr>
<h2 id="첫-실습-프로젝트">첫 실습 프로젝트</h2>
<p>어떤 이유에선지 모르나 어찌저찌 팀장이 되었고, Section1. 프로젝트가 시작되었다.
프로젝트의 주제는 쇼핑몰로 정해졌다</p>
<h3 id="실습-목표">실습 목표</h3>
<p>실습의 중요한 목적은 다음과 같다</p>
<ul>
<li><strong>API 설계 및 문서를 작성</strong> 한다.</li>
<li>관계형 데이터베이스를 위한 <strong>데이터 모델링</strong>을 한다.</li>
<li>Git 을 이용한 <strong>협업을 진행</strong>한다.</li>
</ul>
<h3 id="제작-범위-및-기술-스택">제작 범위 및 기술 스택</h3>
<ul>
<li>Javascript</li>
<li>Fastify</li>
<li>PostgreSQL<ul>
<li>ElephantSQL 이용</li>
</ul>
</li>
<li>ERD 제작</li>
<li>API 문서 제작</li>
</ul>
<p>목표는 최소한의 CRUD 기능을 가진 한개의 API 서버를 만드는 것이다. 목표 자체는 그렇게 어렵지 않은 내용이라고 생각하고 나는 중점을 <strong>설계와 협업</strong>으로 눈을 돌리고 팀원과 작업을 진행하였다.</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/32ca3cba-a267-4b6d-a0d4-12fb2a92d9aa/image.png" alt="개발한 API">
개발이 끝나고 API 를 사용한 결과 화면</p>
<h2 id="issue">ISSUE</h2>
<p>작업을 끝내고 <code>push</code> 하는데에 문제가 생겼다.</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/8d83f992-7ebe-486a-8d2c-cd6a3bad2614/image.png" alt=""></p>
<p>힌트 문구를 보았을 때 내 local 과 remote 가 맞지 않기 때문에 git pull 작업을 하고 다시 시도해 보라고 유도해 주고 있다. 작업하던 내용들을 잃어 버리면 안되기에 <code>git stash</code> 로 임시 저장하고 <code>git pull</code> 을 해보았는데…</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/ef9b9125-a869-4742-9f79-9a123118e811/image.png" alt=""></p>
<p>git pull 조차 안된다. 하지만 치명적인 에러는 아니고 자세히 읽어 보면 설정을 해달라는 말인데.</p>
<p>git pull 방식을 정해 달라는 것이다. .</p>
<ul>
<li><p><strong>기존 pull</strong></p>
<ul>
<li><p>불필요한 merge commit 이 생성 아래 그림의 빨간색 부분</p>
</li>
<li><p>3-way merge 와 비슷하다.</p>
<p>  <img src="https://velog.velcdn.com/images/qnddj-kjh/post/1d5d0311-516d-4c34-899f-db534d5b97c7/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<ul>
<li><strong>git pull --ff-only</strong><ul>
<li>fast-forward 관계일 때만 pull을 허용한다.</li>
<li>fast-forwad 관계는?<ul>
<li>로컬저장소에만 새로운 commit이 있고, 원격저장소에는 없다.</li>
<li>원격저장소에만 새로운 commit이 있고, 로컬저장소에는 없다.</li>
</ul>
</li>
</ul>
</li>
<li><strong>git pull --rebase</strong><ul>
<li>새 브랜치가 시작된 분기점 commit이 존재한다. 이 분기점을 기준 브랜치의 가장 최근 commit으로 변경하는 작업.</li>
<li>로컬 브랜치의 시작점을 원격 브랜치의 마지막 commit으로 옮기는 식인 것 같다. 그 과정에서 conflict가 발생할 경우 이를 해결해줘야 할 듯 싶다.</li>
<li>git history가 깔끔해진다는 장점이 있지만, <strong>부주의하게 사용할 경우 별도의 알림 없이 git history를 영구적으로 변경할 수 있기 때문에 ff-only 방식을 더 추천한다고 한다.</strong></li>
</ul>
</li>
</ul>
<pre><code class="language-bash">git config pull.ff only</code></pre>
<p>위 세가지 방식중 ff 방싱이 추천되므로 명령어로 pull 방식 설정해 주고 다시 실행하였지만 </p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/777ce2fd-aa93-4995-b593-bea4aee8bb47/image.png" alt=""></p>
<p>fast-forwad 가 가능하지 않고 중단되었다고 나온다!</p>
<h3 id="강제-pull">강제 PULL</h3>
<p>수정 파일 보다 local 의 상태를 conflict 되기 전인 수정 전으로 되돌려야 할거 같아 이번 한 번은 강제적인 방법을 사용하였습니다.</p>
<pre><code class="language-bash">git fetch --all
git reset --hard personal/main
git pull personal main</code></pre>
<p>명령을 통해 수정전 상태로 돌리고 수정파일을 가져온뒤 재 push 하여 해결하였습니다.</p>
<p>강제를 하는 방법이므로 좋은 방법은 아니라고 생각합니다.
가장 좋은 방법은 conflict 된 파일을 찾아서 수정하여 push 를 하거나 stash 를 적극 활용하는 것이 가장 좋은 방법을 아닐까 싶습니다.</p>
<h2 id="마치며">마치며</h2>
<p>Java 의 SpringBoot 환경에서 공부하던 나에게 생각보다 처음이 많았다.</p>
<p>API 문서를 위한 도구를 사용해보기도 하고,
PostgreSQL 을 처음 써보기도 하며</p>
<ul>
<li>PostgresSQL 은 마음에 들었다. 조금씩 다른 부분이 있으나 RETURNING 이 있다는게 마음에 들었는지 Postgres 를 향한 첫 인상은 굉장이 좋았다 🤗</li>
</ul>
<p>Fastify 프레임워크를 처음 다뤄봤다.</p>
<ul>
<li>javascript 생태계 답게 굉장히 가볍고 간편한 느낌이 있다. 하지만 처음 사용하는 것이고, 실제 개발 단계는 1일에 가까워서 기능들을 다 활용하지는 못하는 것이 아쉬웠다. Javascript 언어를 잘 알지 못한다는 점도 한 몫했다.(ES6 도 한번은 공부해서 정리하는 게 좋지 않나 하고 생각이 들었다🤔)</li>
</ul>
<p>처음으로 협업을 하게 되었다.</p>
<ul>
<li>이전에도 같이 협업을 한 경우도 없잖아 있지만, 뭔가 인정하고 싶지 않은 결과물이나 작업이 매우 tiny 한 경우 였기에 이렇게 온전히 팀원들이 있고 git 을 사용해서 협업한 경우는 없기에 감격스러운 정도...😭</li>
<li>어떨결에 팀장을 하게 되었지만, 믿음직하지 못한 팀장을 잘 따라와준 팀원들에거 무한한 감사의 박수를 전합니다 👏👏👏</li>
</ul>
<h2 id="다짐">다짐</h2>
<p>다음 Section2. 는 Devops 영역의 발을 디딛는 것과 같은 주제들로 짜여있기에 집중해서 Section2 를 진행할 생각이다. 주제들을 듣기만 해도 너무 기대된다. 조금만 적어보자면</p>
<ul>
<li>Docker</li>
<li>AWS</li>
<li>CI/CD</li>
</ul>
<p>한 번씩 다 해보았지만 전문적으로 교육을 받아본적이 없이 어깨너머 배워왔던 입장이라 너무 두근두근하다. 잘 배워서 잘 써먹어야지😎</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[HTTP] Cookie]]></title>
            <link>https://velog.io/@qnddj-kjh/HTTP-Cookie</link>
            <guid>https://velog.io/@qnddj-kjh/HTTP-Cookie</guid>
            <pubDate>Wed, 22 Mar 2023 06:56:16 GMT</pubDate>
            <description><![CDATA[<h1 id="cookie">Cookie</h1>
<p>어떤 웹 사이트에 들어갔을 때, 서버가 일방적으로 클라이언트에 전달하는 작은 데이터 조각</p>
<ul>
<li>서버가 웹 브라우저에 정보를 저장하고 불러올 수 있는 수단</li>
<li>해당 도메인에 대해 쿠키가 존재하면, 웹 브라우저는 도메인에게 http 요청 시 쿠키를 함께 전달한다.</li>
</ul>
<h2 id="특징">특징</h2>
<p><strong>기본적으로는 쿠키는 오랜 시간 동안 유지될 수 있고, 자바스크립트를 이용해서 쿠키에 접근할 수 있기 때문에 쿠키에 민감한 정보를 담는 것은 위험하다</strong></p>
<ul>
<li>서버가 클라이언트에 데이터를 저장할 수 잇다.<ul>
<li>데이터를 저장한 이후 아무 때나 데이터를 가져올 수는 없다.</li>
<li>데이터를 저장한 이후 특정한 조건들이 만족한 경우에만 다시 가져올 수 있다.</li>
<li>이런 조건들은 다음 쿠키 옵션으로 표현</li>
</ul>
</li>
</ul>
<h3 id="쿠키-옵션">쿠키 옵션</h3>
<ul>
<li>Domain<ul>
<li>쿠키가 전송될 수 있는 도메인을 제한</li>
<li>해당 도메인의 서브도메인에서도 쿠키를 사용</li>
<li>도메인은 포트 및 서브 도메인 정보(<code>www</code> 등) , 세부 경로를 포함하지 않는다.</li>
</ul>
</li>
<li>Path<ul>
<li>쿠키가 전송될 수 있는 URL 경로를 제한</li>
<li>해당 경로와 하위 경로에서만 쿠키를 사용</li>
</ul>
</li>
<li>MaxAge / Expires<ul>
<li>쿠키의 만료 날짜를 지정</li>
<li>Expires 는 쿠키가 만료되는 날짜를 GMT 형식으로 지정</li>
<li>Max-Age 는 쿠키의 유효 기간을 초 단위로 지정</li>
<li>두 옵션이 모두 지정되지 않는 경우 브라우저 탭을 닫아야만 쿠키가 제거</li>
</ul>
</li>
<li>Secure<ul>
<li>HTTPS 연결에서만 쿠키를 전송</li>
</ul>
</li>
<li>SameSite<ul>
<li>쿠키가 외부 사이트로 전송되지 않도록 제한</li>
<li>CSRF(Cross-Site Request Forgery) 공격과 같은 보안 위협 방지</li>
</ul>
</li>
<li>HttpOnly<ul>
<li>JavaScript를 사용하여 쿠키에 액세스할 수 없도록 한다</li>
<li>XSS(Cross-Site Scripting) 공격과 같은 보안 위협에서 쿠키를 안전하게 보호</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Web] IP 와 DNS]]></title>
            <link>https://velog.io/@qnddj-kjh/Web-IP-%EC%99%80-DNS</link>
            <guid>https://velog.io/@qnddj-kjh/Web-IP-%EC%99%80-DNS</guid>
            <pubDate>Wed, 15 Mar 2023 12:48:28 GMT</pubDate>
            <description><![CDATA[<h1 id="public-ip-와-private-ip-차이">Public IP 와 Private IP 차이</h1>
<h2 id="public-ip-공인-ip">public IP (공인 IP)</h2>
<p>인터넷 사용자의 로컬 네트워크를 식별하기 위해 <strong>ISP(인터넷 서비스 공급자)가 제공하는 IP 주소</strong>
이다. 공용 IP 주소라고도 불리며 외부에 공개되어 있는 IP 주소이다.</p>
<ul>
<li>공인 IP 는 전세계에서 유일한 IP 주소를 갖는다.</li>
<li>외부에 공개되어 있기에 인터넷에 연결된 다른 PC 로부터의 접근가능. 따라서, 공인 IP 를 사용하는 경우 방화벽 등의 보안 프로그램을 설치할 필요가 있다.</li>
</ul>
<h2 id="private-ip-사설-ip">private IP (사설 IP)</h2>
<p>일반 가정이나 회사 내 등에 할당된 네트워크 IP 주소, 로컬 IP, 가상 IP 라고도 한다. IPv4의 주소 부족으로 인해 서브넷팅된 IP이기 떄문에 라우터에 의해 로컬 네트워크상의 PC 나 장치에 할당된다.</p>
<h3 id="사설-ip-주소-대역">사설 IP 주소 대역</h3>
<p>3가지 주소 대역으로 고정</p>
<ul>
<li>Class A : <strong>10</strong>.0.0.0 ~ 1<strong>0.</strong>255.255.255</li>
<li>Class B : <strong>172.16</strong>.0.0 ~ <strong>172.31</strong>.255.255</li>
<li>Class C : <strong>192.168</strong>.0.0 ~ <strong>192.168</strong>.255.255</li>
</ul>
<h2 id="차이점">차이점</h2>
<table>
<thead>
<tr>
<th></th>
<th>Public IP</th>
<th>Private IP</th>
</tr>
</thead>
<tbody><tr>
<td>할당 주체</td>
<td>IPS (인터넷 서비스 공급자)</td>
<td>라우터(공유기)</td>
</tr>
<tr>
<td>할당 대상</td>
<td>개인 또는 회사의 서버 (라우터)</td>
<td>개인 또는 회사의 기기</td>
</tr>
<tr>
<td>고유성</td>
<td>인터넷 상의 유일한 주소</td>
<td>하나의 네트워크 안에서 유일</td>
</tr>
<tr>
<td>공개 여부</td>
<td>내/외부 접근 가능</td>
<td>외부 접근 불가능</td>
</tr>
</tbody></table>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/33a9fd84-7c54-4bc0-9ec5-e030f87a36b9/image.png" alt=""></p>
<p>라우터는 중간에서 public IP 와 private IP 변경해주면서 데이터를 전송해 준다.</p>
<h1 id="터미널-nslookup-결과값">터미널 nslookup 결과값</h1>
<h2 id="nslookup">nslookup</h2>
<p><code>nslookup</code>은 name server 관련한 조회를 할 수 있으며, 도메인 이름 서버(DNS)에서 도메인 이름에 해당하는 IP 주소를 찾는 명령어입니다.</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/6a483e85-398f-4683-b1c7-5bdde72fe842/image.png" alt="코드스테이츠 기본 nslookup 결과값"></p>
<p>코드스테이츠 기본 nslookup 결과값</p>
<p>나타내어지는 정보는 다음과 같다</p>
<ul>
<li>이름 : 검색된 호스트 또는 도메인의 이름</li>
<li>검색된 호스트 IP 주소 : 검색된 호스트 또는 도메인의 IP 주소</li>
<li>유형 : DNS 레코드 유형, (A, AAAA, CNAME, MX, NS, PTR, SOA, SRV, TXT 등)<ul>
<li>DNS 레코드 : 도메인 이름과 관련된 정보를 저장하는 데이터베이스 레코드</li>
</ul>
</li>
<li>TTL : Time To Live 약자, DNS 레코드의 TTL 값을 나타낸다. 레코드가 캐시 될 수 있는 시간을 의미하며, 이 시간이 지나면 DNS 서버는 레코드를 다시 가져와야 한다.</li>
<li>서버 : 쿼리를 보낸 DNS 서버의 이름을 나타낸다.</li>
<li>로컬 컴퓨터의 DNS 서버 IP 주소 : 쿼리를 보낸 DNS 서버의 IP 주소</li>
</ul>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/e8c343e9-bfc6-49e2-91eb-c888cdd26710/image.png" alt="nslookup 정밀 모드 사용하여 코드스테이츠 도메인 검색"></p>
<p>nslookup 정밀 모드 사용하여 코드스테이츠 도메인 검색</p>
<pre><code class="language-bash"># nslookup 정밀 모드 사용법
nslookup
set debug
도메인 이름</code></pre>
<h1 id="httpgooglecom-검색-시-dns-에서-일어나는-일"><a href="http://google.com">http://google.com</a> 검색 시 DNS 에서 일어나는 일</h1>
<h3 id="dns">DNS</h3>
<ul>
<li>웹 사이트에서는 외우기 어려운 IP 주소 대신 도메인 이름을 사용한다.</li>
<li>도메인 이름을 실제 네트워크 상에서 사용하는 IP 주소로 바꾸고 해당 주소로 접속하는 과정이 필요</li>
<li>이러한 과정, 전체 시스템을 DNS(Domain Name System) 라고 한다.</li>
<li>시스템은 전세계적으로 약속된 규칙을 공유</li>
<li>상위 기관에서 인증된 기관에게 도메인을 생성하거나 IP 주소로 변경할 수 있는 <code>권한</code> 을 부여한다.</li>
<li>DNS 는 이처럼 상위 기관과 하위 기관 같은 <strong>계층 구조</strong>를 가지는 <strong>분산 데이터베이스 구조</strong>이다.</li>
</ul>
<h3 id="dns-구성-요소">DNS 구성 요소</h3>
<ul>
<li><p><strong>도메인 네임 스페이스 (Domain Name Space)</strong></p>
<ul>
<li><p><strong>도메인 주소 구조</strong></p>
<p>  <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/32505574-8129-479a-98ab-f2459d4d06d2/Untitled.png" alt="Untitled"></p>
<ul>
<li>주소 영역을 <code>.</code> 으로 구분 → 라벨 (Lavel)<ul>
<li>하나의 라벨 : 최대 63개의 문자 (64byte) 사용 가능</li>
<li>대소문자 구분 없이 <code>알파벳</code>, <code>-</code> 만 가능(ASCII 로 표현)</li>
<li>전체 도메인 주소 최대 크기 : 255 개의 문자 (255byte)</li>
</ul>
</li>
<li>주소 해석은 오른쪽 부터</li>
<li>최상위 주소는 항상 가장 오른쪽에 있는 <code>.(root)</code></li>
</ul>
</li>
<li><p><strong>도메인 네임 스페이스에 포함되는 각각의 노드들</strong></p>
<ul>
<li><strong>루트 도메인</strong><ul>
<li>네임 스페이스에서 이름 해석의 출발지 역할을 하는 노드 (서버)</li>
<li>최상위 도메인 서버의 정보를 가짐(<a href="http://www.iana.org/domains/root/servers">http://www.iana.org/domains/root/servers</a>)</li>
<li>전 세계 13개의 원본 root 서버가 존재</li>
</ul>
</li>
<li><strong>최상위 도메인 (Top Level Domain = TLD)</strong><ul>
<li>국가 코드 최상위 도메인(ccTLD : country code TLD)<ul>
<li><code>.kr</code>, <code>.jp</code> 등</li>
</ul>
</li>
<li>일반 최상위 도메인 (gTLD : global TLD)<ul>
<li><code>.net</code>, <code>.com</code>, <code>.org</code> 등</li>
</ul>
</li>
<li>ARPA : 역방향 조회 시 사용되는 최상위 도메인<ul>
<li><code>in-addr.arpa</code></li>
</ul>
</li>
</ul>
</li>
<li><strong>2차 도메인 (Second Level Domain, Sub Domain)</strong><ul>
<li>TLD 하위에서 관리되는 서브 도메인</li>
<li>국가 도메인 하위에 기관 유형에 따른 분류<ul>
<li><code>.co (일반회사)</code>, <code>.ac (교욱기관)</code>, <code>.go (정부기관)</code> 등</li>
</ul>
</li>
</ul>
</li>
<li><strong>서브 도메인 (Sub Domain)</strong><ul>
<li>상위 도메인에 소속되는 각 기관 또는 회사별 도메인<ul>
<li><code>google</code>, <code>naver</code> 등</li>
</ul>
</li>
</ul>
</li>
<li>하위 노드는 무한정 만들 수 있다. 문자수에는 제한 (255byte)</li>
</ul>
</li>
<li><p>도메인 → IP 주소 (정방향 조회)</p>
</li>
<li><p>IP 주소 → 도메인 주소 (역방향 조회)</p>
<ul>
<li>특수한 상황 (PTR/SPF 레코드를 이용한 스팸메일 필터링)</li>
</ul>
</li>
</ul>
</li>
<li><p>네임 서버 (Name Server)</p>
<ul>
<li>도메인 → IP 주소 : 네임 서비스 (Name Service)</li>
<li>Resolver (해석기) 로부터 요청받은 도메인 이름에 대한 IP 주소를 다시 Resolver (해석기) 로 전달해주는 역할을 수행</li>
<li>Primary, Secondary 서버로 구분된다.<ul>
<li>Primary : 도메인을 관리하는 주 네임서버</li>
<li>Secondary : 주 네임 서버가 고장 등으로 서비스 실패 시 네임 서버 역할 수행</li>
</ul>
</li>
</ul>
</li>
<li><p>리졸버 (Resolver)</p>
<ul>
<li>DNS 요청을 네임 서버로 전달하고, 네임 서버로부터 정보를 받아 클라이언트에게 제공하는 기능 제공</li>
</ul>
</li>
</ul>
<h2 id="검색시-일어나는-일">검색시 일어나는 일</h2>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/32d58a6f-e6e8-4df9-b45c-f11f494dcf3e/image.png" alt="DNS 동작 과정"></p>
<p>DNS 동작 과정</p>
<ol>
<li>Local DNS 에 <code>[http://google.com](http://google.com)</code> 라는 hostname 에 대한 IP 주소를 요청한다. Local DNS 에 도메인에 대한 IP 주소가 있는 경우 바로 응답한다.</li>
<li>없다면 다른 DNS 서버와 통신을 시작한다. 차례대로 최상위 Root DNS 서버에 질의 (DNS Query)</li>
<li><code>.com</code> 을 관리하는 DNS 서버를 응답해준다.</li>
<li>Local DNS 는 <code>.com</code> 을 관리하는 DNS 서버에게 질의</li>
<li><code>[google.com](http://google.com)</code> 을 관리하는 DNS 서버를 응답해준다.</li>
<li>Local DNS 는 <code>[google.com](http://google.com)</code> 을 관리하는 DNS 서버에게 질의</li>
<li><code>[google.com](http://google.com)</code> 에 대한 IP 주소를 응답해준다.</li>
<li>Local DNS 는 <code>[http://google.com](http://google.com)</code> 에 대하여 IP 주소를 캐싱하고 클라이언트에 IP 주소를 알려준다.</li>
</ol>
<p>출처</p>
<blockquote>
<p><a href="https://hanamon.kr/dns%EB%9E%80-%EB%8F%84%EB%A9%94%EC%9D%B8-%EB%84%A4%EC%9E%84-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B0%9C%EB%85%90%EB%B6%80%ED%84%B0-%EC%9E%91%EB%8F%99-%EB%B0%A9%EC%8B%9D%EA%B9%8C%EC%A7%80/">https://hanamon.kr/dns란-도메인-네임-시스템-개념부터-작동-방식까지/</a>
<a href="https://itsandtravels.blogspot.com/2018/11/dnsdomain-name-system-dns.html">https://itsandtravels.blogspot.com/2018/11/dnsdomain-name-system-dns.html</a>
<a href="https://susoterran.github.io/other/dns/">https://susoterran.github.io/other/dns/</a>
<a href="https://hanamon.kr/dns%EB%9E%80-%EB%8F%84%EB%A9%94%EC%9D%B8-%EB%84%A4%EC%9E%84-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B0%9C%EB%85%90%EB%B6%80%ED%84%B0-%EC%9E%91%EB%8F%99-%EB%B0%A9%EC%8B%9D%EA%B9%8C%EC%A7%80/"></a><a href="https://velog.io/@hidaehyunlee/%EA%B3%B5%EC%9D%B8Public-%EC%82%AC%EC%84%A4Private-IP%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90">https://velog.io/@hidaehyunlee/공인Public-사설Private-IP의-차이점</a>
<a href="https://m.blog.naver.com/on21life/221364194092">https://m.blog.naver.com/on21life/221364194092</a>
<a href="https://www.lesstif.com/system-admin/nslookup-20775988.html">https://www.lesstif.com/system-admin/nslookup-20775988.html</a>
chat-gpt</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux]서비스 관리]]></title>
            <link>https://velog.io/@qnddj-kjh/Linux%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B4%80%EB%A6%AC</link>
            <guid>https://velog.io/@qnddj-kjh/Linux%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B4%80%EB%A6%AC</guid>
            <pubDate>Tue, 14 Mar 2023 00:20:26 GMT</pubDate>
            <description><![CDATA[<h2 id="데몬과-서비스">데몬과 서비스</h2>
<h3 id="데몬">데몬</h3>
<p>리눅스 환경에서 시스템이 초기화가 끝난 후 <code>init</code> 이라는 특별한 프로그램에 의해 자발적으로 백그라운드에서 실행되는 프로그램을 의미한다.</p>
<p>멀티태스킹 운영체제에서 사용자가 직접적으로 제어하지 않고, 백그라운드에서 돌면서 여러 작업을 하는 프로그램을 의미한다. ex) Windows OS 의 Service</p>
<p>일반적으로 <em>백그라운드에서 작동하는 프로세스 라는 의미로 통용된다.</em> </p>
<p>리눅스에서 데몬은 <code>syslogd</code>, <code>httpd</code> 와 같이 프로그램 이름 끝에 <code>d</code> 가 붙는다. 상시 실행되며 다음과 같은 일을 함</p>
<ul>
<li>하드웨어 장치 관리</li>
<li>보조 기억장치와 디렉토리의 연결(마운트)</li>
<li>네트워크를 통한 프로세스간 통신(소켓)</li>
<li>애플리케이션 수준의 서비스 제공 → 보통 서비스라고 간략하게 줄여서 부름<ul>
<li>같은 프로그램을 지칭할 때 서비스와 데몬으로 번갈아가면서 부를 수 있는데, 운영체제의 관점은 ‘데몬’, 사용자 관점에서는 ‘서비스’ 라고 부를 따름이다.</li>
</ul>
</li>
</ul>
<h3 id="대표적인-데몬--web-server-httpd">대표적인 데몬 : Web Server (httpd)</h3>
<p>웹 페이지에 접근하고 결과를 얻으려면, 웹 페이지를 제공하는 프로세스가 상시 실행되어야 할 것이고 이러한 프로그램을 <strong>웹 서버</strong>라고 한다. 일반적으로 백그라운드에서 작동되므로, 데몬이라고 부를 수 있다.</p>
<h3 id="httpd-실습">httpd 실습</h3>
<p><strong>시나리오</strong></p>
<ul>
<li><p>간단한 HTML 파일 생성</p>
</li>
<li><p><code>curl</code> 유틸리티를 통해 해당 주소로 접속</p>
</li>
<li><p><strong>과정 코드</strong></p>
<pre><code class="language-bash">  # index.html 작성
  $ echo &quot;&lt;html&gt;&lt;body&gt;&lt;h1&gt; 첫 HTML 페이지 &lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;&quot; &gt; index.html

  # 웹 서버 실행, 8888 포트 열기
  $ busybox httpd -h . -p 8888

  # 웹 서버 접속
  $ curl http://localhost:8888

  # 프로세스 확인 명령을 통해 데몬이 실행중인지를 확인
  $ ps aux | grep httpd

  # PID 를 이용해 프로세스를 죽인다
  $ kill -9 PID

  # 웹 서버 다시 접속, 실패해야 정상
  $ curl http://localhost:8888</code></pre>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/0c0acad1-d665-40be-a563-6b98e5fba9d8/image.png" alt="실습결과"></p>
<p>실습 결과</p>
<ul>
<li>※ busybox 란?<ul>
<li>UNIX 명령해 유틸리티의 기능을 하나의 실행 파일 안에 통합시킨 소프트웨어다</li>
<li>작은 바이너리 속 350 여 개의 기능이 들어가 있어 임베디드 환경에서 많이 사용된다.</li>
<li>작은 용량으로 기능들이 간략화 되어 있어 빠진 기능들이 몇 있다.</li>
<li>busybox는 각종 유틸리티를 담은 일종의 “스위스 군용 칼”과 같은 리눅스용 애플리케이션으로, 아주 단순한 기능을 가진 웹 서버(httpd)를 포함하고 있습니다.</li>
<li>httpd는 기본적으로 데몬으로 실행되며, 위의 실습처럼 백그라운드에서 돌면서, 목적에 맞는 기능(여기서는 웹 서버의 역할)을 수행합니다.</li>
</ul>
</li>
</ul>
<h3 id="대표적인-데몬--cron">대표적인 데몬 : cron</h3>
<p>cron 데몬은 스케쥴에 따라 명령을 실행하는 도구이다.</p>
<h3 id="cron-실습">cron 실습</h3>
<p><strong>시나리오</strong></p>
<ul>
<li>매 분마다 날짜와 시스템 가동시간을 파일에 저장하는 명령을 실행</li>
<li><strong>실습 코드</strong></li>
</ul>
<pre><code class="language-bash">$ crontab -e
# 에디터 선택 대화창이 나온다.

# 에디터 선택 후 에디터가 열리면 맨 아랫줄에 입력
* * * * * echo $(/bin/date) - $(/usr/bin/uptime) &gt;&gt; ~/uptime.log

# 파일을 저장하고 닫는다.</code></pre>
<ul>
<li><code>date</code> 명령의 출력, <code>uptime</code> 명령 출력을 uptime.log 파일에 쌓는다</li>
<li><code>* * * * *</code> 는 매 분을 뜻한다.<ul>
<li><a href="https://crontab.guru/#0_20_*_*_*">https://crontab.guru/#0_20_<em>_</em>_*</a> 에서 다양한 예제를 확인할 수 있다.</li>
<li>매 10시 명령 수행은 <code>0 20 * * *</code> 이다</li>
</ul>
</li>
<li><strong>💡반드시 crontab 을 초기화 할 것</strong></li>
</ul>
<pre><code class="language-bash">$ crontab -r
$ crontab -l
no crontab for 사용자이름
# 마지막 줄이 출력되야 정상적으로 초기화 된다.</code></pre>
<h2 id="systemctl--서비스-관리">systemctl : 서비스 관리</h2>
<h3 id="데몬-확인하기">데몬 확인하기</h3>
<p><code>systemctl</code> : 모든 데몬의 목록 출력, 서비스 목록만 볼려면 <code>--type=service</code> 옵션 사용 (시스템 관리자들을 보통 서비스에 집중하므로)</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/4946f64f-dc23-4bde-86ac-f3f90aa9b86e/image.png" alt="별도의 실행 없이 cron.service 가 실행되어진 것을 확인 할 수 있다"></p>
<p>별도의 실행 없이 cron.service 가 실행되어진 것을 확인 할 수 있다</p>
<h3 id="systemctl">systemctl</h3>
<table>
<thead>
<tr>
<th>명령어</th>
<th>기능</th>
</tr>
</thead>
<tbody><tr>
<td>systemctl list-unit-files</td>
<td>설치된 유닛(데몬) 목록 출력</td>
</tr>
<tr>
<td>systemctl enable <unit></td>
<td>부팅시 유닛 활성화</td>
</tr>
<tr>
<td>systemctl disable <unit></td>
<td>부팅시 유닛 비활성화</td>
</tr>
<tr>
<td>systemctl start <unit></td>
<td>유닛 즉시 활성화</td>
</tr>
<tr>
<td>systemctl stop <unit></td>
<td>유닛 즉시 비활성화</td>
</tr>
<tr>
<td>systemctl restart <unit></td>
<td>유닛 즉시 재시작(비활성화 후 활성화)</td>
</tr>
<tr>
<td>systemctl status <unit></td>
<td>유닛 상태와 최근 로그 조회</td>
</tr>
<tr>
<td>- 시스템 관리자의 주 사용 목적</td>
<td></td>
</tr>
<tr>
<td>- 서비스의 상태 파악</td>
<td></td>
</tr>
<tr>
<td>- 정상 작동 파악</td>
<td></td>
</tr>
<tr>
<td>- 멈춘 경우 멈춰있는 이유 파악</td>
<td></td>
</tr>
<tr>
<td>- 최근 출력 로그를 읽는 것은 매우 중요합니다. Active가 failed일 경우, 로그에 그 원인이 반드시 존재합니다.</td>
<td></td>
</tr>
<tr>
<td>- 재시작</td>
<td></td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux]프로세스 관리]]></title>
            <link>https://velog.io/@qnddj-kjh/Linux%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EA%B4%80%EB%A6%AC</link>
            <guid>https://velog.io/@qnddj-kjh/Linux%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EA%B4%80%EB%A6%AC</guid>
            <pubDate>Mon, 13 Mar 2023 23:54:55 GMT</pubDate>
            <description><![CDATA[<h1 id="프로세스-스레드-멀티-스레드">프로세스, 스레드, 멀티 스레드</h1>
<hr>
<h2 id="프로그램과-프로세스">프로그램과 프로세스</h2>
<ul>
<li><strong>프로그램 :</strong>  프로그래밍 언어를 사용하여 수행절차를 표현해 놓은 명령어들의 집합. 정적인 상태의 파일</li>
<li><strong>프로세스</strong> : 운영체제로부터 메모리를 할당받고 실행 되고 있는 <strong>프로그램</strong><ul>
<li>하나의 프로그램을 여러 번 실행하면 여러 개의 프로스세(다중 프로세스)가 메모리 상에서 실행된다.</li>
</ul>
</li>
</ul>
<h2 id="스레드">스레드</h2>
<ul>
<li><strong>스레드 :</strong> 사전적 의미로는 한 가닥의 실. 프로세스 내에서 실제로 작업을 수행하는 주체를 의미한다. 모든 프로세스는 한 개 이상의 스레드가 존재하며 작업을 수행한다. 두 개 이상의 스레드를 가지는 프로세스를 멀티 스레드 프로세스라고 한다.<ul>
<li>한 프로세스 내에 스레드가 두 개라면 코드가 실행되는 흐름이 두 개 생긴다는 의미</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/a8914b69-1ca4-4803-9b66-57b489c37c9b/image.png" alt=""></p>
<h2 id="멀티-스레드">멀티 스레드</h2>
<ul>
<li><strong>멀티 스레드</strong> :  하나의 프로세스 내에서 둘 이상의 스레드가 동시에 작업을 수행하는 것을 의미한다. 또한, 멀티 프로세스는 여러 개의 CPU 를 사용하여 여러 프로세스를 동시에 수행하는 것을 의미한다.</li>
<li>※ 멀티 스레드와 멀티 프로세스 차이<ul>
<li>둘 모두 여러 흐름을 동시에 수행하는 공통점을 가지고 있다.</li>
<li>멀티 프로세스는 독립적인 메모리를 가지고 별도로 실행되지만, 멀티 스레드는 각 스레드가 속한 프로세스의 메모리를 공유한다는 점이 다르다.</li>
</ul>
</li>
<li><strong>멀티 스레드의 장점 :</strong> 멀티 스레드는 각 스레드들이 자신이 속한 프로세스의 메모리를 공유해서 시스템 자원의 낭비가 적다. 하나의 스레드가 작업을 할 때 다른 스레드가 별도의 작업을 할 수 있어 사용자와의 응답성도 좋아진다.</li>
</ul>
<h1 id="프로세스-관리">프로세스 관리</h1>
<h2 id="프로세스-실행-방식">프로세스 실행 <strong>방식</strong></h2>
<ul>
<li><strong>포그라운드 방식(foreground)</strong></li>
<li><strong>백그라운드 방식(background)</strong></li>
</ul>
<h3 id="포그라운드-방식">포그라운드 방식</h3>
<p>사용자가 명령을 입력하고 이를 해석하여 실행한 뒤 결과를 화면에 출력한다. 사용자는 결과를 확인 한 뒤 다른 명령어를 입력하는 대화식으로 작업을 수행하게 되는 방식이다.</p>
<p>포그라운드 방식으로 처리되는 프로세스를 포그라운드 프로세스라고 한다.</p>
<h3 id="백그라운드--방식">백그라운드  방식</h3>
<p>포그라운드 방식의 단점은 한 번에 하나의 명령을 실행하여 동시에 여러 프로세스를 실행하기 어려운 점이다.</p>
<p>백그라운드 방식은 프로세스가 실행되는 동안 뒤에서 다른 프로세스가 실행될 수 있다. 여러 개의 프로세스를 동시에 실행 가능하다.</p>
<h3 id="리눅스에서의-사용">리눅스에서의 사용</h3>
<pre><code class="language-bash">#포그라운드 방식
$ command
$ ping google.com

# 백그라운드 방식 - &amp; 추가
$ command &amp;
$ ping google.com &amp;

# nohup 명령어 (no hang up)
$ nohup command &amp;
$ nohup ping google.com &amp;</code></pre>
<p>여기서 백그라운드 방식은 <code>&amp;</code> 를 붙여서 실행하는데, 백그라운드 실행시 사용자의 터미널 세션이 종료되면 실행중인 프로세스도 종료된다. 사용자 터미널 세션이 종료되어도 프로세스를 실행하고 싶다면 <code>nohup</code> 명령어를 사용한다.</p>
<h3 id="프로세스-목록-확인">프로세스 목록 확인</h3>
<ul>
<li><p><code>ps</code></p>
<ul>
<li><p>현재 실행중인 프로세스의 목록을 확인 할 수 있다.</p>
<ul>
<li>PID : 프로세스 번호</li>
<li>TTY : 프로세스가 실행된 터미널의 종류와 번호</li>
<li>TIME : 프로세스 실행 시간</li>
<li>CMD : 실행되고 있는 프로그램의 이름(명령)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/3b92f9bf-605c-402c-bd0b-8c36cc3a89f7/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<p><strong>더 자세한 옵션</strong></p>
<ul>
<li><strong>UNIX 방식</strong><ul>
<li><code>-e</code> : 시스템에서 실행중인 모든 프로세스의 정보를 출력</li>
<li><code>-f</code> : 프로세스의 자세한 정보를 출력</li>
<li><code>-u uid</code> : uid 로 특정한 사용자에 대한 모든 프로세스의 정보 출력</li>
<li><code>-p pid</code> : pid 로 지정한 특정 프로세스의 정보 출력</li>
</ul>
</li>
<li><strong>BSD 방식</strong><ul>
<li><code>a</code> : 터미널에서 실행한 프로세스의 정보를 출력</li>
<li><code>u</code>: 프로세스 소유자의 이름, CPU 사용량, 메모리 사용량 등 상세 정보 출력</li>
<li><code>x</code> : 시스템에서 실행 중인 모든 프로세스의 정보 출력</li>
</ul>
</li>
</ul>
<p>가장 자주 사용하는 옵션 방식</p>
<ul>
<li><p><code>ps -ef</code> - UNIX , <code>ps aux</code> - BSD</p>
<ul>
<li><code>ps -ef</code> 출력 정보<ul>
<li>UID : 프로세스 실행한 사용자 ID</li>
<li>PPID : 부모 프로세스 번호</li>
<li>C : CPU 사용량 (%)</li>
<li>STIME : 프로세스의 시작 날짜 또는 시간</li>
<li>TTY : 프로세스가 실행된 터미널의 종류와 번호</li>
<li>STAT : 프로세스 상태</li>
</ul>
</li>
<li><code>ps aux</code> 출력 정보<ul>
<li>USER : 사용자 계정 이름</li>
<li>%CPU : CPU 사용량 (%)</li>
<li>%MEM : 물리 메모리 사용량 (%)</li>
<li>RSS : 사용하고 있는 물리적 메모리 크리 (kb)</li>
<li>VSZ : 사용하고 있는 가상 메모리 크기 (kb)</li>
<li>START : 프로세스 시작 시간</li>
</ul>
</li>
</ul>
</li>
<li><p><code>pstree</code></p>
<ul>
<li><p>컴퓨터의 전체 프로세스 구조 확인 명령어</p>
</li>
<li><p>트리구조로 도식화하여 프로세스를 확인할 수 있으며, 부모 관계를 파악할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/563ceffa-e122-4640-9a71-40a07f3fe506/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<h3 id="kill---프로세스-종료">kill - 프로세스 종료</h3>
<p>터미널에서 프로그램은 <code>ctrl + c</code> 로 종료할 수 있다. 단축키 사용시 이벤트가 발생되고, 이러한 이벤트를 프로세스에 전달하는 과정이 필요하다. 이 때, 이벤트를 프로세스에 알려주기 위해서 사용하는 것을 <strong>시그널(Signal)</strong> 이라고 한다.</p>
<p>특정 프로세스에 작업 중지, 실행 종료, 대기, 재시작, 강제 종료 등의 시그널을 전달하기 위해 <code>kill</code> 명령어를 사용한다. <code>kill -l</code> 사용하면 사용할 수 있는 시그널의 종류를 확인 할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/b7a4451e-5e4c-47c5-b755-f581c56662bd/image.png" alt=""></p>
<p>주 사용 시그널</p>
<ul>
<li>SIGHUP : 재시작</li>
<li>SIGINT : 실행 중지 = <code>ctrl + c</code></li>
<li>SIGKILL : 강제 종료</li>
<li>SIGTERM : 정상 종료 = 기본 명령</li>
<li>SIGCONT : 정지된 프로세스 실행</li>
<li>SIGSTOP : 터미널에서 입력되는 정지 시그널</li>
<li>SIGTSTP : 실행 정지 후 재실행 대기 = <code>ctrl + z</code></li>
</ul>
<p>사용 방법</p>
<pre><code class="language-bash">$ kill -&lt;시그널번호 or 시그널명&gt; %작업번호
$ kill -&lt;시그널번호 or 시그널명&gt; PID</code></pre>
<h3 id="jobs---백그라운드-프로세스-확인">jobs - 백그라운드 프로세스 확인</h3>
<ul>
<li><strong>프로세스 상태</strong><ul>
<li>Runnuing : 실행 중</li>
<li>Stopped : 일시 중단 (<code>ctrl + z</code>)</li>
<li>Terminated : 강제 종료 (<code>kill</code> 명령)</li>
<li>Done : 정상 종료</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/ba25ed4d-62e5-4297-9705-e83e962cc65e/image.png" alt=""></p>
<ul>
<li><code>[1]</code>, <code>[2]</code> 는 작업번호이다.</li>
<li><code>+</code> 는 현재 처리되고 있는 작업을 의미, <code>-</code> 다음에 작업할 프로세스를 의미한다.</li>
<li>필요하다면 <code>fg %&lt;작업번호&gt;</code> 명령을 통해 포그라운드로 전환 가능</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux] 출력 관련 명령어]]></title>
            <link>https://velog.io/@qnddj-kjh/Linux-%EC%B6%9C%EB%A0%A5-%EA%B4%80%EB%A0%A8-%EB%AA%85%EB%A0%B9%EC%96%B4</link>
            <guid>https://velog.io/@qnddj-kjh/Linux-%EC%B6%9C%EB%A0%A5-%EA%B4%80%EB%A0%A8-%EB%AA%85%EB%A0%B9%EC%96%B4</guid>
            <pubDate>Fri, 10 Mar 2023 08:49:58 GMT</pubDate>
            <description><![CDATA[<h1 id="표준-스트림과-stdin-stdout-stderr">표준 스트림과 stdin, stdout, stderr</h1>
<h3 id="표준-스트림standard-stream">표준 스트림(Standard Stream)</h3>
<hr>
<ul>
<li><strong>스트림(Stream) 이란?</strong><ul>
<li>프로그램이 드나드는 데이터를 흐름으로 표현한 단어</li>
<li>종류<ul>
<li>입력 스트림(Strandard input, STDIN, 0)</li>
<li>출력스트림(Standard output, STDOUT, 1)</li>
<li>오류 메시지 출력 스트림(Standard Error, STDERR, 2)</li>
</ul>
</li>
<li>실제 리눅스의 <code>/dev</code> 디렉토리에서 위 세 개의 표준 스트림을 앞서 언급한 파일 형태로 담고 있다.</li>
</ul>
</li>
<li><strong>stdin</strong><ul>
<li>표준 입력은 프로그램으로 들어가는 입력값의 데이터(보통은 문자열) 스트림이며, Standard Input 을 줄여서 <code>stdin</code> 으로 표현한다.</li>
<li>리눅스 쉘에서 표준 설정은 키보드이다.</li>
<li>모든 프로그램에서 입력을 요구하지 않으며, 대표적인 예로 비밀번호를 입력할 때 표준 입력 스트림을 사용한다.</li>
</ul>
</li>
<li><strong>stdout</strong><ul>
<li>표준 출력은 프로그램이 출력 데이터를 기록하는 스트림으로, Standard Output 을 <code>stdout</code> 으로 줄여 표현한다.</li>
<li>표준 출력은 텍스트 터미널에서 이루어지며, 표준 입력과 마찬가지로 모든 프로그램이 출력을 요구하는 것은 아니다.</li>
</ul>
</li>
<li><strong>stderr</strong><ul>
<li>표준 오류는 프로그램이 오류 메시지나 진단을 출력하기 위해 일반적으로 쓰이는 또다른 출력 스트림이다.</li>
<li>Standard Error 를 줄여 <code>stderr</code> 로 줄여 표현한다.</li>
</ul>
</li>
</ul>
<h3 id="파일-디스크립터-file-descriptor">파일 디스크립터 (file descriptor)</h3>
<p>리눅스의 모든 파일을 관리하는 방식</p>
<p>명령어 실행 (컴퓨터에게 작업을 요청 -&gt; 프로세스 생성)</p>
<ul>
<li>실제 프로그램을 실행시키는 작업</li>
<li>이러한 프로그램은 파일로 존재</li>
<li>파일을 실행 시키기 위해서는 먼저 파일을 열어야 한다.</li>
<li>파일이 열리면 커널이 해당 프로세스가 동작하는데 필요한 장치나 파일을 번호를 붙여 관리하며, 이러한 번호를 파일 디스크립터 테이블에 저장</li>
<li>자주 사용하는 장치들은 미리 번호가 예약되어 있다.</li>
</ul>
<h1 id="파이프라인과-리다이렉션">파이프라인과 리다이렉션</h1>
<hr>
<h3 id="리다이렉션redirection">리다이렉션(Redirection)</h3>
<p> 리눅스에서는 세 개의 표준 스트림을 자동으로 열게됩니다. 표준 스트림을 이용한 파이프라인과 리다이렉션이 가능합니다. 파이프라인은 한 명령의 출력을 다른 명령의 입력으로 사용하는 것이고, 리다이렉션은 명령의 입력이나 출력을 파일로 대체하는 것입니다.</p>
<p> 리눅스에서는 표준 입력, 표준 출력, 표준 오류를 파일로 리다이렉션 할 수 있습니다. 리다이렉션을 쓰고 싶다면 기호인 <code>&gt;</code>, <code>&lt;</code> 를 사용합니다. 다음은 몇 가지 예시입니다.</p>
<ul>
<li><strong>&gt;</strong> : 출력 리다이렉션<ul>
<li><code>command &gt; file</code> : <code>command</code> 의 출력을 <code>file</code> 로 저장합니다. <code>file</code> 이 존재하지 않으면 생성합니다. 이미 존재하는 파일이면 덮어씁니다.</li>
<li><code>command1 &gt; file1 2&gt;&amp;1</code> : <code>command1</code> 의 표준 출력과 표준 오류 출력을 모두 <code>file1</code> 로 리다이렉션합니다. <code>2&gt;&amp;1</code> 은 표준 오류 출력을 표준 출력으로 리다이렉션 하는 것을 의미합니다.</li>
</ul>
</li>
<li><strong>&gt;&gt;</strong> : 출력 리다이렉션(추가 모드)<ul>
<li><code>command &gt;&gt; file</code> : <code>command</code> 의 출력을 <code>file</code> 에 추가합니다. <code>file</code> 이 존재하지 않으면 생성합니다.</li>
</ul>
</li>
<li><strong>&lt;</strong> : 입력 리다이렉션<ul>
<li><code>command &lt; file</code> : <code>command</code> 의 입력을 <code>file</code> 로부터 읽어옵니다.</li>
</ul>
</li>
<li><strong>&lt;&lt;</strong> : 여러 줄의 입력을 받습니다.<ul>
<li><code>command &lt;&lt; EOF</code> : <code>EOF</code> 라는 문자열을 입력할 때까지 입력된 모든 내용을 <code>command</code> 의 입력으로 넘깁니다.</li>
</ul>
</li>
</ul>
<p>예시:</p>
<ul>
<li><p><code>ls &gt; file.txt</code> : <code>ls</code> 명령의 결과를 <code>file.txt</code> 파일에 저장합니다.</p>
</li>
<li><p><code>ps aux &gt; ps.txt</code> : <code>ps aux</code> 명령의 결과를 <code>ps.txt</code> 파일에 저장합니다.</p>
<ul>
<li><p>정확하게 말하자면, <code>ps aux</code> 의 출력 스트림을 ps.txt 이라는 파일로 전환하여 저장하는 것을 의미한다. 따라서 <code>ps aux</code> 명령의 결과는 콘솔의 화면이 아닌 <code>ps.txt</code> 파일에 기록된다.</p>
<p>  <img src="https://velog.velcdn.com/images/qnddj-kjh/post/ce7538f9-8ef1-4699-a7ae-4da8ec19d26f/image.png" alt="ps aux 명령이 실행되지 않고 ps.txt  파일에 저장되는 모습"></p>
</li>
</ul>
</li>
</ul>
<pre><code>    ps aux 명령이 실행되지 않고 ps.txt  파일에 저장되는 모습</code></pre><ul>
<li><code>cat &lt; file.txt</code> : <code>file.txt</code> 파일의 내용을 출력합니다.</li>
<li><code>sort &lt; file.txt &gt; sorted_file.txt</code> : <code>file.txt</code> 파일의 내용을 알파벳순으로 정렬한 후 <code>sorted_file.txt</code> 파일에 저장합니다.</li>
<li><code>head &lt; ps.txt</code> : <code>head</code> 명령은 파일의 처음 부분을 설명한 라인(line) 만큼 출력하는 명령이다. 기본값으로 10줄이 세팅 되어 있다. <code>ps.txt</code> 파일의 처음 10줄을 <code>head</code> 입력 스트림으로 전환하여 보내게 된다.<ul>
<li>응용 : <code>head &lt; ps.txt &gt; sample.txt</code><ol>
<li><code>ps.txt</code> 의 내용을 <code>head</code> 명령의 입력 스트림으로 전환하여 전송한다.</li>
<li><code>head</code> 명령은 입력 받은 <code>ps.txt</code> 의 내용에서 10줄을 출력한다.</li>
<li><code>head</code> 명령의 출력 스트림을 <code>sample.txt</code> 파일에 연결한다.</li>
<li><code>head</code> 명령의 출력 스트림은 결과를 <code>sample.txt</code> 파일에 저장한다.</li>
</ol>
</li>
</ul>
</li>
</ul>
<h3 id="파이프pipe">파이프(Pipe)</h3>
<p> 파이프(Pipe)는 한 명령어의 출력을 다른 명령어의 입력으로 사용할 수 있게 해주는 기능입니다. 파이프라인(Pipeline)은 파이프를 사용해 여러 명령어를 연결하여 실행하는 것입니다.</p>
<p> 파이프는 <code>|</code> 기호를 사용합니다. 다음은 파이프의 예시입니다.</p>
<ul>
<li><code>command1 | command2</code> : <code>command1</code> 의 출력 스트림을 <code>command2</code> 의 입력 스트림으로 전달합니다.</li>
</ul>
<p>예시:</p>
<ul>
<li><p><code>ls | grep file</code> : 디렉토리의 파일 목록을 출력하고, 그 중 &quot;file&quot; 이라는 문자열이 포함된 파일만 검색합니다.</p>
<ul>
<li><p><code>[/bin 디렉토리 안] ls -l | grep ssh</code> : 결과 <code>grep</code> 명령어는 추후에 정리</p>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/7c0eb74d-8799-4c06-9392-fa8fad57accf/image.png" alt="ssh 문자열이 들어있는 모든 파일들을 검색"></p>
</li>
</ul>
</li>
</ul>
<pre><code>ssh 문자열이 들어있는 모든 파일들을 검색</code></pre><ul>
<li><p><code>ps aux | grep firefox</code> : 프로세스 목록을 출력하고, 그 중 &quot;firefox&quot; 라는 문자열이 포함된 프로세스만 검색합니다.</p>
</li>
<li><p><code>cat file.txt | grep keyword | wc -l</code> : <code>file.txt</code> 파일의 내용 중 &quot;keyword&quot; 라는 문자열이 포함된 라인의 개수를 출력합니다.</p>
<p>위의 예시에서 <code>grep</code> 과 <code>wc</code> 는 앞선 명령어의 출력을 입력으로 받아 처리합니다. 이렇게 명령어를 파이프라인으로 연결함으로써, 여러 개의 명령어를 조합해 원하는 결과를 얻을 수 있습니다.</p>
</li>
</ul>
<h3 id="파이프라인-실행-과정">파이프라인 실행 과정</h3>
<p>터미널은 하나의 프로세스이고, 명령어 실행은 해당 터미널의 정보를 기준으로 백그라운드에 자식 프로세스가 fork 되어 명령어를 실행하게 된다.</p>
<p>즉 <code>ls</code> 명령어를 입력하면, 자식 프로세스 1개가 fork 되어 백그라운드에서 부모 프로세스의 정보를 기준으로 해당 명령어 즉, <code>stdin(표준 입력 스트림)</code> 을 통해 정보를 입력받고 <code>stdout(표준 출력 스트림)</code> 을 통해 <code>ls</code> 명령어를 호출한 터미널로 정보를 반환한다.</p>
<p>그럼 <code>파이프(Pipe)</code> 끼리 어떻게 연결되나?</p>
<pre><code class="language-bash">$ ls | sort | less</code></pre>
<p>동작과정</p>
<ol>
<li><code>ls</code> 를 실행하는 자식 프로세스 및 파이프 명령어 개수 만큼 프로세스를 fork 한다. 프로세스는 <code>wait</code> 상태로 대기한다.</li>
<li>부모 프로세스로부터 <code>stdin</code> 을 통해 정보를 받는다.</li>
<li><code>ls</code> 프로세스는 <code>ls</code> 명령을 실행한다.</li>
<li><code>ls</code> 프로세스는 <code>stdout</code> 을 통해 다음 자식 프로세스 <code>stdin</code> 으로 데이터를 출력한다.</li>
<li>반복하고 마지막 프로세스가 부모 프로세스로 <code>stdout</code> 을 return 하고 부모 프로세스는 결과를 출력한다.</li>
</ol>
<p>부모 프로세스 → … → <code>stdin</code> → 프로세스 내부 명령 실행 → <code>stdout</code> → <code>stdin</code> → … → 부모 프로세스</p>
<h1 id="출력-관련-명령어">출력 관련 명령어</h1>
<h2 id="파일-일기">파일 일기</h2>
<hr>
<h3 id="man--메뉴얼-출력-명령어">man : 메뉴얼 출력 명령어</h3>
<ul>
<li><code>man &lt;명령어&gt;</code></li>
<li>명령어에 대한 메뉴얼을 출력하는 명령어</li>
</ul>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/ac8019ff-a2e0-43e2-ac50-f129a5c36699/image.png" alt="">
<img src="https://velog.velcdn.com/images/qnddj-kjh/post/a5e5c231-c3e0-463f-9d59-68840508d685/image.png" alt=""></p>
<h3 id="cat--파일-내용-출력">cat : 파일 내용 출력</h3>
<ul>
<li><code>cat &lt;옵션&gt; &lt;파일 이름&gt;</code></li>
<li>파일 내용을 출력하는 명령어<ul>
<li>다른 CLI 도구나 파일로 리디렉션 하는 데 기본적으로 사용하는 명령이므로 잘 기억할 것</li>
</ul>
</li>
<li>자주 쓰는 옵션<ul>
<li><code>-n</code> : Line 번호와 함께 출력</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/67235bef-4097-4712-bbc4-ede14398003f/image.png" alt="-n 옵션으로 파일 내용 앞 line 번호가 쓰여진 것을 확인할 수 있다"></p>
<p>-n 옵션으로 파일 내용 앞 line 번호가 쓰여진 것을 확인할 수 있다</p>
<h3 id="more--파일을-화면-단위로-끊어서-출력">more : 파일을 화면 단위로 끊어서 출력</h3>
<ul>
<li><code>more &lt;옵션&gt; &lt;파일 이름&gt;</code></li>
<li>자주 쓰는 옵션<ul>
<li><code>+&lt;number&gt;</code> : 예) +3 : 입력한 line 을 포함한 페이지를 추력(3번째 줄부터 출력)</li>
<li><code>+/&lt;string&gt;</code> : 예) +/Gatsby : 입력한 문자열이 포함된 페이지를 추력 (Gatsby 문자열을 포함한 줄부터 출력)</li>
</ul>
</li>
</ul>
<h3 id="less--파일-내용-출력">less : 파일 내용 출력</h3>
<ul>
<li><code>less &lt;옵션&gt; &lt;파일 이름&gt;</code></li>
<li>자주쓰는 옵션<ul>
<li><code>-N</code> : line 번호와 함께 출력</li>
</ul>
</li>
</ul>
<h3 id="head--파일-앞부분-출력">head : 파일 앞부분 출력</h3>
<ul>
<li><code>head &lt;옵션&gt; &lt;파일 이름&gt;</code></li>
<li>자주 쓰는 옵션<ul>
<li><code>-n &lt;number&gt;</code>  : 지정한 라인까지 출력</li>
</ul>
</li>
</ul>
<h3 id="tail--파일-뒷부분-출력">tail : 파일 뒷부분 출력</h3>
<ul>
<li><code>tail &lt;옵션&gt; &lt;파일 이름&gt;</code></li>
<li>자주 쓰는 옵션<ul>
<li><code>-n &lt;number&gt;</code> : 지정한 라인까지 출력</li>
<li><code>-f</code> : 즉시 종료되지 않고, 파일의 내용이 추가되는 상태를 지켜보면서 계속 이어서 출력<ul>
<li><code>-f</code> 옵션은 시스템 관리자라면 필수적으로 알아야 하는 옵션</li>
<li>애플리케이션 로그가 쌓이는 것을 실시간으로 확인하고자 할 때 많이 사용한다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="이-외의-기타-명령어">이 외의 기타 명령어</h3>
<ul>
<li><p><code>wc</code> : 파일의 줄, 단어 및 문자 수를 계산하는 데 사용</p>
<ul>
<li>옵션<ul>
<li><code>-l</code> : 줄 수만 계산</li>
<li><code>-w</code> : 단어 수만 계산</li>
<li><code>-c</code> : 문자 수만 계산</li>
</ul>
</li>
</ul>
</li>
<li><p><code>awk</code> : awk는 텍스트 파일을 처리하는 프로그램으로, 파일이나 텍스트 데이터를 레코드와 필드로 구분하여 처리할 수 있습니다. 레코드는 텍스트 파일에서 행을 의미하며, 필드는 레코드 안에서 구분자로 구분된 데이터를 의미합니다. awk는 이러한 레코드와 필드를 기반으로 다양한 데이터 처리 작업을 수행할 수 있습니다. 대표적으로 데이터 추출, 통계, 변환 등의 작업이 있습니다. awk는 유닉스, 리눅스 등에서 기본적으로 제공되는 명령어 중 하나입니다.</p>
<ul>
<li><p>기본 구조 : <code>awk &#39;condition {action}&#39; &lt;파일 이름&gt;</code></p>
<p><code>awk</code>는 텍스트 파일을 처리하는 프로그램으로, 파일이나 텍스트 데이터를 레코드와 필드로 구분하여 처리하는 기능을 제공합니다. awk는 이러한 레코드와 필드를 기반으로 데이터를 추출하거나 통계, 변환 등의 작업을 수행할 수 있습니다.</p>
<p>자주 사용되는 기본적인 <code>awk</code> 명령어는 다음과 같습니다.</p>
</li>
<li><p><code>awk &#39;{ print $1 }&#39; file.txt</code> : <code>file.txt</code> 파일에서 첫 번째 필드를 출력합니다.</p>
</li>
<li><p><code>awk &#39;{ print $NF }&#39; file.txt</code> : <code>file.txt</code> 파일에서 마지막 필드를 출력합니다.</p>
</li>
<li><p><code>awk &#39;{ print NF }&#39; file.txt</code> : <code>file.txt</code> 파일에서 필드의 수를 출력합니다.</p>
</li>
<li><p><code>awk &#39;/pattern/ { print }&#39; file.txt</code> : <code>file.txt</code> 파일에서 &quot;pattern&quot;이 포함된 라인을 출력합니다.</p>
</li>
<li><p><code>awk &#39;{ s += $1 } END { print s }&#39; file.txt</code> : <code>file.txt</code> 파일에서 첫 번째 필드의 합을 출력합니다.</p>
<p>여러 가지 기능을 조합하여 사용할 수도 있습니다. 예를 들어, 다음과 같은 명령어는 <code>file.txt</code> 파일에서 첫 번째 필드가 3인 라인을 출력합니다.</p>
</li>
<li><p><code>awk &#39;$1 == 3 { print }&#39; file.txt</code></p>
</li>
</ul>
</li>
<li><p><code>cut</code> : 파일에서 특정 열을 추출, 기본 구분 기호는 <code>탭 문자</code>이다.</p>
<ul>
<li>옵션<ul>
<li><code>-f</code> :</li>
<li><code>-d</code> : 구분 기호 설정 옵션 (ex) <code>cut -d ‘,’</code> : 쉼표로 구분 기호를 설정</li>
<li><code>—output-delimiter</code> : 출력 구분 기호 설정 (기본 설정은 입력 구분 기호와 같다)</li>
</ul>
</li>
</ul>
</li>
<li><p><code>join</code> : 파일의 공통</p>
</li>
<li><p><code>paste</code> : 여러 텍스트 파일을 수평적으로 <code>join</code>, <code>merge</code> 하는 유닉스 커맨드 라인 유틸리티</p>
<p>  <img src="https://velog.velcdn.com/images/qnddj-kjh/post/371c1ae5-e4d9-4b75-820c-08cae652fc41/image.png" alt=""></p>
</li>
</ul>
<pre><code>- 예제 파일

![](https://velog.velcdn.com/images/qnddj-kjh/post/e5933db3-31f5-4211-afa4-927325d40ec9/image.png)


- 옵션
    - `-s` : 수평이 아닌 수직으로 값을 읽어서 수평으로 출력한다.

        ![](https://velog.velcdn.com/images/qnddj-kjh/post/0aba0e30-e995-4377-bd85-31e5aaad969d/image.png)


    - `-d` : 구분자를 지정할 수 있다.

    ![](https://velog.velcdn.com/images/qnddj-kjh/post/e5851bac-e9ba-46ca-8384-974b3ac1f9c0/image.png)</code></pre><ul>
<li><p><code>sed</code> : 문자열 대체 (찾기 및 바꾸기)</p>
<ul>
<li><p><code>sed &#39;s/&lt;찾을문자열&gt;/&lt;바꿀문자열&gt;</code></p>
<p>  <img src="https://velog.velcdn.com/images/qnddj-kjh/post/6e5b58fb-6512-43b8-a21f-88ee9d602202/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<pre><code>- 보시다시피 화면에 결과를 출력만 하고 파일은 바뀌지 않는다 리디렉션을 해주거나 `-i` 옵션을 주어 원본 파일을 변경해야 한다.
- 옵션
    - `-d` : 삭제
    - `-a` `-i` : 줄 추가 또는 삽입</code></pre><ul>
<li><p><code>sort</code> : 파일 내에서 줄이나 열을 정렬하는데 사용한다. 기본적으로 줄 시작 부분의 문자를 기준으로 다음 순서를 정렬한다.</p>
<ul>
<li><p>오름차순 숫자, 오름차순 문자(소문자 먼저, 그 다음 대문자)</p>
</li>
<li><p>옵션</p>
<ul>
<li><p><code>-r</code> : 정렬 기준 역순으로 바꾼다</p>
</li>
<li><p><code>-n</code> : 기본 정렬은 숫자 값이 아닌 문자로 숫자를 정렬한다. 숫자 값으로 정렬하려면 <code>-n</code> 옵션 사용</p>
</li>
<li><p><code>-k</code> : 줄의 시작이 아닌 특정 열을 기준으로 파일을 정렬할 때 사용</p>
<p>  <img src="https://velog.velcdn.com/images/qnddj-kjh/post/4fd8dee4-5bf9-4c90-a9b3-7d667ec8f582/image.png" alt="사용 예"></p>
</li>
<li><p><code>-u</code> : 정렬한 다음 중복을 제거한다</p>
</li>
<li><p><code>-f</code> : 대소문자 구분 안함</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p><code>uniq</code> : 중복된 항목을 제거하는 커맨드 라인 유틸리티, 보통 <code>sort</code> 명령어로 정렬을 한 결과를 파이프로 <code>uniq</code> 에 전달하여 중복 내용을 제거한다</p>
<ul>
<li><p>예제 파일</p>
<p>  <img src="https://velog.velcdn.com/images/qnddj-kjh/post/285cadac-a1c7-48df-b6c5-aa3106567a55/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<pre><code>- 사용법
    - `sort input.txt | uniq`

        ![](https://velog.velcdn.com/images/qnddj-kjh/post/7525ece0-4d07-4fc8-bc70-2e665a2786c0/image.png)



- 옵션
    - `-u` : 중복되지 않은 라인만 표시한다. 위 예제에서 line 과 bat 은 포함되지 않는다.
    - `-d` : 중복되는 라인만 표시한다. 위 예제에서 line 과 bat 이 해당된다.
    - `-c` : 중복 횟수를 세어 준다.
    - `-i` `--ignore-case` : 대소문자 구분 무시 옵션</code></pre><h2 id="파일-및-디렉토리-찾기-관련">파일 및 디렉토리 찾기 관련</h2>
<hr>
<h3 id="find--파일-검색">find : 파일 검색</h3>
<p>파일 검색 기본 명령어 중 하나. 파일 권한, 소유권, 수정 날짜, 크기 등과 같은 특정 기준에 따라 파일을 검색 할 수 있다.</p>
<ul>
<li><code>주의점</code> : 위치 선정을 하지 않을 경우 기본적으로 현재 디텍토리만 검색하기 때문에 원하는 결과를 얻지 못 할 수 있다. 찾고자 하는 위치를 지정해서 사용하는 것이 좋다.</li>
</ul>
<pre><code class="language-bash">$ find &lt;위치&gt; &lt;옵션&gt; 검색할 내용</code></pre>
<ul>
<li>옵션<ul>
<li><code>-name 내용</code> : 지정한 내용의 이름을 가진 파일을 찾음</li>
<li><code>-type &lt;옵션&gt;</code> : 옵션에 따른 형태를 가진 파일을 찾음</li>
</ul>
</li>
</ul>
<pre><code class="language-bash">$ find . -name &#39;이름&#39; # 찾을 파일 이름을 지정해서 찾기 . 는 현재 디렉토리를 뜻함
$ find . -name &#39;이름&#39; -type d # -type d 는 디렉토리만 찾기
$ sudo find / -size+10M # 10M 이상 찾기 디렉토리 권한 때문에 sudo 사용
# / 는 루트 디렉토리를 뜻함
$ find . -empty # 빈 파일 찾기
$ find . -newer practice.txt # practice 파일 보다 최근에 변경된 파일 찾기</code></pre>
<h3 id="locate--특정-파일-위치-찾기">locate : 특정 파일 위치 찾기</h3>
<p>특정 파일의 위치를 모를 때 활용 <code>find</code> 명령어에 비해 빠르지만 데이터베이스를 이용하기 때문에 정기적인 업데이트를 필요로 한다. <code>updatedb</code> 에 의해서 생성된 미리 빌드된 파일들의 데이터베이스를 통해 검색이 되기 때문. 속도 향상을 위해 만들어진 유틸리티 이므로 전체적인 효율성과 정확성은 조금 떨어진다.</p>
<ul>
<li><p><strong><strong><strong>**</strong></strong></strong>locate(mlocate) 프로그램 설치하기<strong><strong><strong>**</strong></strong></strong></p>
<p>  리눅스 배포판에 따라 <code>locate</code> 명령어가 기본으로 제공되는 경우도 있지만 없는 경우 설치가 필요. 기존에는 locate 패키지를 사용 최근에는 mlocate 패키지를 추천한다 (관리자 권한 필요)</p>
<pre><code class="language-bash">  $ sudo apt-get install mlocate</code></pre>
</li>
<li><p><code>locate</code> 명령어가 빠른 이유는 검색 DB 를 미리 생성하기 때문 (파일 목록 데이터베이스, <code>mlocate.db</code> 파일) 따라서 <code>locate</code> 명령어를 처음 사용하는 경우 DB 파일을 먼저 생성해야한다.</p>
</li>
<li><p><strong><strong><strong><strong><strong><strong><strong><strong>****</strong></strong></strong></strong></strong></strong></strong></strong>DB 파일 갱신하기(관리자 권한 필요)<strong><strong><strong><strong><strong><strong><strong><strong>****</strong></strong></strong></strong></strong></strong></strong></strong></p>
<pre><code class="language-bash">  $ sudo updatedb</code></pre>
</li>
<li><p><strong>사용예</strong></p>
<pre><code class="language-bash">  $ locate gatsby.txt  # 파일 이름으로 검색
  $ locate -n 10 *.txt # 검색할 파일 수 지정하여 찾기 모든 txt 파일 중 10개</code></pre>
</li>
</ul>
<h3 id="which--실행파일-위치-식별">which : 실행파일 위치 식별</h3>
<p><code>which</code> 명령어는 실행 가능한 파일의 경로를 찾아주는 프로그램입니다.</p>
<p>검색하려는 모든 파일이 실행 파일인 경우 <code>which</code> 명령어가 유용. <code>$PATH</code> 시스템 환경변수에서 이진 파일을 매우 효과적으로 검색</p>
<pre><code class="language-bash">$ which ls
usr/bin/ls

$ which python3
/usr/bin/python3</code></pre>
<h2 id="패턴으로-찾기-관련">패턴으로 찾기 관련</h2>
<hr>
<p><code>grep</code> 명령어를 사용하여 파일 내에서 특정 패턴을 검색할 수 있습니다.</p>
<pre><code>$ grep &lt;패턴&gt; &lt;파일명&gt;
</code></pre><p>사용 예</p>
<pre><code>$ grep &#39;hello&#39; file.txt
$ grep -i &#39;hello&#39; file.txt
$ grep -n &#39;hello&#39; file.txt
$ grep -r &#39;hello&#39; ./directory
</code></pre><ul>
<li>옵션</li>
</ul>
<pre><code>| 옵션 | 설명 |
| --- | --- |
| -i | 대소문자를 구분하지 않고 검색 |
| -v | 지정한 패턴을 포함하지 않는 라인을 출력 |
| -n | 라인 번호를 함께 출력 |
| -w | 지정한 패턴이 단어로 구분되어 있는 경우에만 검색 |
| -r | 하위 디렉토리를 포함하여 모든 파일에서 검색 |
| -l | 파일명만 출력 |
| -c | 일치하는 라인 수를 출력 |
| -H | 파일명을 출력 |
| -E | 확장 정규식 사용 |
| -F | 정규식이 아닌 문자열 검색 |
| -m | 최대 검색 결과 갯수 제한 |</code></pre><ul>
<li>예시 (끝에는 전부 파일명)<ul>
<li>단어 단위로 검색 : <code>grep -w</code></li>
<li>검색된 문자열이 포함된 라인 번호 출력 : <code>grep -n</code></li>
<li>하위 디렉토리를 포함한 모든 파일에서 문자열 검색 : <code>grep -r</code></li>
<li>최대 검색 결과 갯수 제한 : <code>grep -m 10</code></li>
<li>문자열 A로 시작해서 문자열 B로 끝나는 패턴 찾기 : <code>grep &#39;^A$B&#39;</code></li>
</ul>
</li>
</ul>
<h2 id="정규표현식">정규표현식</h2>
<p>정규표현식(regular expression)은 문자열을 처리하는 방법 중의 하나로 특정한 조건의 문자를 &#39;검색&#39;하거나 &#39;치환&#39;하는 과정을 매우 간편하게 처리할 수 있도록 하는 수단이다. 정규표현식은 일종의 패턴(pattern)이며, 이 패턴을 통해 문자열을 처리한다.</p>
<h3 id="정규표현식-문법">정규표현식 문법</h3>
<ul>
<li><code>.</code> : 임의의 한 문자</li>
<li><code>^</code> : 문장의 시작</li>
<li><code>$</code> : 문장의 끝</li>
<li><code>[]</code> : 문자의 집합 중 하나</li>
<li><code>[-]</code> : 문자의 집합 중 범위</li>
<li><code>()</code> : 그룹화</li>
<li><code>|</code> : or 연산자</li>
<li><code>?</code> : 0 또는 1회 발생</li>
<li>`` : 0회 이상 발생</li>
<li><code>+</code> : 1회 이상 발생</li>
<li><code>{n}</code> : n회 발생</li>
<li><code>{n,}</code> : n회 이상 발생</li>
<li><code>{n,m}</code> : n회 이상, m회 이하 발생</li>
</ul>
<h3 id="정규표현식-예제">정규표현식 예제</h3>
<ul>
<li><p><code>.</code></p>
<p>  모든 문자 하나를 의미합니다.</p>
</li>
<li><p><code>^</code></p>
<p>  문자열 또는 행의 시작을 의미합니다.</p>
</li>
<li><p><code>$</code></p>
<p>  문자열 또는 행의 끝을 의미합니다.</p>
</li>
<li><p><code>[]</code></p>
<p>  대괄호 안에 있는 문자 중 하나와 일치합니다.</p>
</li>
<li><p><code>[^]</code></p>
<p>  대괄호 안에 있는 문자를 제외한 문자 중 하나와 일치합니다.</p>
</li>
<li><p><code>[-]</code></p>
<p>  대괄호 안에 있는 문자의 범위와 일치합니다.</p>
</li>
<li><p><code>()</code></p>
<p>  괄호 안의 문자열을 그룹으로 묶습니다.</p>
</li>
<li><p><code>|</code></p>
<p>  둘 중 하나와 일치합니다.</p>
</li>
<li><p><code>?</code></p>
<p>  0회 또는 1회를 의미합니다.</p>
</li>
<li><p>``</p>
<p>  0회 이상을 의미합니다.</p>
</li>
<li><p><code>+</code></p>
<p>  1회 이상을 의미합니다.</p>
</li>
<li><p><code>{n}</code></p>
<p>  n회를 의미합니다.</p>
</li>
<li><p><code>{n,}</code></p>
<p>  n회 이상을 의미합니다.</p>
</li>
<li><p><code>{n,m}</code></p>
<p>  n회 이상, m회 이하를 의미합니다.</p>
</li>
</ul>
<h2 id="정규표현식을-사용하는-명령어">정규표현식을 사용하는 명령어</h2>
<ul>
<li><code>grep</code>: 파일 내에서 특정 패턴을 검색할 때 사용합니다.</li>
<li><code>sed</code>: 파일 내에서 문자열을 대체(찾기 및 바꾸기)할 때 사용합니다.</li>
<li><code>awk</code>: 파일 내에서 특정 패턴을 검색하고 조작할 때 사용합니다.</li>
<li><code>find</code>: 파일 검색 기본 명령어 중 하나입니다.</li>
<li><code>locate</code>: 특정 파일의 위치를 찾을 때 사용합니다.</li>
<li><code>which</code>: 실행 파일의 위치를 식별할 때 사용합니다.</li>
</ul>
<h3 id="출처">출처</h3>
<blockquote>
<p><a href="https://recipes4dev.tistory.com/171">https://recipes4dev.tistory.com/171</a>
<a href="https://www.lesstif.com/lpt/linux-uniq-95879394.html">https://www.lesstif.com/lpt/linux-uniq-95879394.html</a>
<a href="https://blog.ronin.cloud/10-simple-linux-commands/">https://blog.ronin.cloud/10-simple-linux-commands/</a>
<a href="http://hyeonjae-blog.logdown.com/posts/654302">http://hyeonjae-blog.logdown.com/posts/654302</a>
<a href="https://www.computerhope.com/unix/uuniq.htm">https://www.computerhope.com/unix/uuniq.htm</a>
<a href="https://hitomis.tistory.com/84">https://hitomis.tistory.com/84</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Node] 개발 환경 세팅]]></title>
            <link>https://velog.io/@qnddj-kjh/Node-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD-%EC%84%B8%ED%8C%85</link>
            <guid>https://velog.io/@qnddj-kjh/Node-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD-%EC%84%B8%ED%8C%85</guid>
            <pubDate>Tue, 01 Mar 2022 14:02:15 GMT</pubDate>
            <description><![CDATA[<h1 id="nodejs-개발-환경-세팅">Node.js 개발 환경 세팅</h1>
<h3 id="ide---visual-studio-code">IDE - Visual Studio Code</h3>
<p> 간단히 홈페이지에서 설치 하면 끝!</p>
<hr>
<h3 id="nodejs-설치">Node.js 설치</h3>
<ul>
<li>특징<ul>
<li>빠르다 </li>
<li>언어수준(Javascript)에서 비동기 완성</li>
<li>확장성</li>
</ul>
</li>
</ul>
<p>Node.js 또한 홈페이지에서 설치하면 끝이다.
version 은 LTS version 을 추천한다. LTS(Long Term Support) 장기간동안 지원하는 version 이다. 그렇지만 Node.js 의 최신의 기능을 사용하고 싶다면 Current Version 을 다운 받으면 된다.
Node 의 version 을 관리 할 수 있는 version manager 가 존재하는데 대표적으로 nvm, n 이 있다. 
<span style="color:#d3d3d3">필자는 n 을 사용하고 싶지만 windows 사용자라서 사용하지 못한다. ㅠ 그렇다고 nvm 사용하기에는 귀찮으므로 pass </span></p>
<hr>
<h3 id="formatting---prettier">Formatting - Prettier</h3>
<ol>
<li>vsc Extends 에서 Prettier 검색 후 install 
<img src="https://images.velog.io/images/qnddj-kjh/post/99a065c5-2e15-4e46-9b92-43e24e44849d/image.png" alt=""></li>
<li><code>npm install --save-dev prettier</code>  명령으로 prettier dependency 설치</li>
<li>프로젝트 디렉토리에 .prettierrc 설정파일 생성
<img src="https://images.velog.io/images/qnddj-kjh/post/bfe376a1-8167-4be3-b346-ad8aa3b62874/image.png" alt="">
위와 같이 Option 들을 끄고 킬 수 있다.<ul>
<li>semi : 세미콜론 유무</li>
<li>singleQuote : 홑따옴표 사용 유무
필자는 Java 를 많이 사용하고 있기에 위처럼 옵션을 주었다
더 다양한 옵션들이 존재하니 prettier 홈페이지에서 문서를 보면 된다.<blockquote>
<p><a href="https://prettier.io/docs/en/options.html">https://prettier.io/docs/en/options.html</a></p>
</blockquote>
</li>
</ul>
</li>
<li>해당 프로젝트에서 prettier 적용 
프로젝트 디렉토리에서 .vscode 패키지 생성 후 settings.json 파일을 만들어 준다.
해당 프로젝트에서 사용할 설정을 정해주는 것
<img src="https://images.velog.io/images/qnddj-kjh/post/220279b7-42a0-441b-9f74-6d4492c7a2e7/image.png" alt="">
javascript 를 저장할 때 포멧하고 기본 포멧터로 prettier 를 사용하겠다고 설정한 것이다.</li>
</ol>
<hr>
<h3 id="linting---eslint">Linting - ESLint</h3>
<ol>
<li>vsc Extends 에서 ESLint 확장팩 install
<img src="https://images.velog.io/images/qnddj-kjh/post/c0451bc1-bf50-46ed-9151-f1cacc4a0cb7/image.png" alt=""></li>
<li>ESLint dependency 추가
<code>npm install --save-dev eslint</code></li>
<li>ESLint 설정 파일 생성 .eslintrc.js
명령어로도 가능하다.
<code>npx eslint --init</code>
간단하게 설정하기 위해서 필자는 이미 설정된 airbnb 확장을 사용할 것이다.</li>
<li>airbnb 설정 적용
필요한 dependency 들을 설치합니다.
<code>npm install --save-dev eslint-config-airbnb-base eslint-plugin-import</code></li>
<li>.eslintrc.js 에서 설정 적용<pre><code class="language-javascript">module.exports = {
extends: [&quot;airbnb-base&quot;],
};</code></pre>
airbnb 설정이 적용이 되지만 여기서 prettier 와 eslint 가 충돌하는데 문제 해결을 위한 설정이 이미 만들어져 있다.
<code>npm install --save-dev eslint-config-prettier</code><pre><code class="language-javascript">module.exports = {
extends: [&quot;airbnb-base&quot;, &quot;prettier&quot;],
};</code></pre>
eslint 가 prettier 에서 고친 것에서 에러를 잡지 않게 설정되었다. 또 한가지 eslint-prettier plugin 이 잘 동작하기 위해서는 항상 맨 마지막에 넣어주는 것이 좋다.</li>
</ol>
<p>추가로 node 관련된 plugin 도 넣어보자.
<code>npm install --save-dev eslint-plugin-node</code></p>
<pre><code class="language-javascript">module.exports = {
  extends: [&quot;airbnb-base&quot;, &quot;plugin:node/recommended&quot; , &quot;prettier&quot;],
};</code></pre>
<p>이제 eslint 에서 node 관련된 에러도 잡아줄 것이다.</p>
<hr>
<h3 id="type-checking---typescript">Type Checking - TypeScript</h3>
<p>javascript 는 동적으로 타입이 변하는 언어이다. type checking 관련 문제가 안 생기게 하기 위해 Typescript 를 사용</p>
<ol>
<li><p>typescript dependency 추가
<code>npm install --save-dev typescript</code></p>
</li>
<li><p>js 파일 최상단 // @ts-check 추가</p>
</li>
</ol>
<p>이것만 해줘도 간단하게 type checking 이 가능하다.</p>
<p>node 관련 type 
<code>npm install --save-dev @types/node</code>
node 에서 자주 사용하는 객체들의 type 들이 정의되어 있다.
vscode 가 위의 정보를 바탕으로 type check 를 도와준다.</p>
<p>Javascript 로 프로젝트를 할 것이기 때문에 Typescript 의 type checking 만 도움 받을 것이다.</p>
<ol start="3">
<li>jsconfig.json 설정파일 생성
<img src="https://images.velog.io/images/qnddj-kjh/post/c2118170-90f3-4d13-ae7c-5d73ad588a21/image.png" alt="">
strict : 강하게 규칙을 잡는것
include : src 밑의 모든 폴더와 파일들 대상</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 1259번 팰린드롬수]]></title>
            <link>https://velog.io/@qnddj-kjh/%EB%B0%B1%EC%A4%80-1259%EB%B2%88-%ED%8C%B0%EB%A6%B0%EB%93%9C%EB%A1%AC%EC%88%98</link>
            <guid>https://velog.io/@qnddj-kjh/%EB%B0%B1%EC%A4%80-1259%EB%B2%88-%ED%8C%B0%EB%A6%B0%EB%93%9C%EB%A1%AC%EC%88%98</guid>
            <pubDate>Mon, 27 Dec 2021 05:55:54 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p><img src="https://images.velog.io/images/qnddj-kjh/post/06cfa6ff-6360-4625-bf12-77de13864a61/image.png" alt=""></p>
<h4 id="풀이">풀이</h4>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String input = &quot;0&quot;;
        while (!(input = br.readLine()).equals(&quot;0&quot;)) {
            int len = input.length();
            boolean flag = true;
            if (len != 1)
                for (int i = 0; i &lt; len / 2; i++) {
                    if (input.charAt(i) != input.charAt(len - 1 - i)) {
                        flag = false;
                    }
                }

            if (flag) {
                System.out.println(&quot;yes&quot;);
            } else {
                System.out.println(&quot;no&quot;);
            }
        }
    }
}</code></pre>
<h3 id="반성">반성</h3>
<p> 구현을 하는 문제이고 문자열을 얼마나 잘 다루는지 보는 문제인데...간단하게 생각안하고 또 어렵게 생각했다.
 처음 풀었던 방법은 앞 뒤 자르고 StringBuffer 써서 뒤를 다시 역순 정렬...그리고 비교하여 같으면 yes 아니면 no 출력으로 풀었는데 이 경우 33333 같은 홀수 일때 split 을 사용하면 잡을 수가 없기에 charAt 으로 순차적으로 앞뒤 비교하여 틀린순간 잡는 방법으로 바꾸었다...나는 멍청해...</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 15829번 Hashing]]></title>
            <link>https://velog.io/@qnddj-kjh/%EB%B0%B1%EC%A4%80-15829%EB%B2%88-Hashing</link>
            <guid>https://velog.io/@qnddj-kjh/%EB%B0%B1%EC%A4%80-15829%EB%B2%88-Hashing</guid>
            <pubDate>Mon, 27 Dec 2021 02:38:25 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p><img src="https://images.velog.io/images/qnddj-kjh/post/c3d6880a-5ba1-45c6-91ce-1a28f93e38ed/image.png" alt=""></p>
<pre><code class="language-java">public static main(String[] args) throw IOException {

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in);

    int l = Integer.parseInt(br.readLine());
    String s = br.readLine();

        long result = 0;
        long temp = 1;
        for (int i = 0; i &lt; l; i++) {
            result += ((s.charAt(i) - &#39;a&#39; + 1) * temp);
            temp = (temp * 31) % 1234567891;
        }

        System.out.println(result % 1234567891);
}
</code></pre>
<h3 id="주의">주의</h3>
<p>제곱이 들어가는 점이 가장 큰 주의점이다 
여기서 r로 지정된 31의 50제곱은 long 타입의 범위를 넘어간다.</p>
<p>중간 연산에서 계속해서 M 을 나누어 주는 연산을 돌려야 범위 안에서 계산이 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[HTTP] HTTP 기본]]></title>
            <link>https://velog.io/@qnddj-kjh/HTTP</link>
            <guid>https://velog.io/@qnddj-kjh/HTTP</guid>
            <pubDate>Mon, 27 Sep 2021 02:38:50 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><img src="https://images.velog.io/images/qnddj-kjh/post/5b54dc64-48c8-4031-a292-8567cb665d81/image.png" alt="">
HyperText 즉 HTML 이런 문서 간의 링크를 통해서 연결할 수 있는 것으로 전송하는 프로토콜로 시작되었고, 지금은 HTTP 메시지에 모든 것을 넣어서 전송한다.</p>
</blockquote>
<h1 id="http-기초">HTTP 기초</h1>
<h1 id="http">HTTP</h1>
<p>Hyper Text Transfer Protocol 의 약자로 HTML(하이퍼텍스트) 문서를 교환하기 위해 만들어진 프로토콜(통신 규약) 이다. 지금은 HTTP 메시지에 모든 것을 넣어서 전송한다.</p>
<ul>
<li><p>HTML, TEXT</p>
</li>
<li><p>이미지, 음성, 영상, 파일</p>
</li>
<li><p>JSON, XML (API) 등</p>
<p>거의 모든 형태의 데이터 전송 가능하고 서버간에 데이터를 주고 받을 때도 대부분 HTTP 사용하는 HTTP 시대이다.</p>
</li>
<li><p>웹상에서 네트워크로 서버끼리 통신을 할 때 어떠한 형식으로 서로 통신을 하자고 규정해 놓은 <strong>통신 형식</strong> 혹은 <strong>통신 구조</strong> 이다</p>
</li>
<li><p>HTTP 는 TCP/IP 기반으로 되어있다.</p>
</li>
<li><p>요청과 응답 구조로 되어있다.</p>
<ul>
<li>클라이언트가 HTTP request 를 서버에 보내면 HTTP response 를 보낸다.</li>
<li>모든 통신이 요청과 응답으로 이루어진다.</li>
</ul>
</li>
<li><p>HTTP 는 <code>Stateless</code> 이다</p>
<ul>
<li>state (상태) 를 저장하지 않는다</li>
<li>요청이 오면 그에 응답을 할 뿐, 요청/응답 이 서로 연결되어 있지 않다</li>
<li>각각의 요청과 응답은 독립적인 요청과 응답이다.</li>
<li>한계<ul>
<li>모든것을 무상태로 설계 할 순 없다 (대표적 예시: 로그인)</li>
<li>일반적으로 브라우저 쿠키와 서버 세션등을 사용해서 상태 유지</li>
<li>상태 유지는 최소한만 사용<h3 id="역사">역사</h3>
</li>
</ul>
</li>
</ul>
</li>
<li><p>HTTP/0.9 1991년: GET 메서드만 지원, HTTP 헤더 X</p>
</li>
<li><p>HTTP/1.0 1996년: 메서드, 헤더 추가</p>
</li>
<li><p><strong>HTTP/1.1 1997년: 가장 많이 사용, 우리에게 가장 중요한 버전</strong></p>
<ul>
<li>RFC2068(1997) -&gt; RFC2616(1999) -&gt; RFC7230~7235(2014)</li>
</ul>
</li>
<li><p>HTTP/2 2015년: 성능 개선</p>
</li>
<li><p>HTTP/3 진행중: TCP 대신에 UDP 사용, 성능 개선</p>
</li>
</ul>
<h3 id="기반-프로토콜">기반 프로토콜</h3>
<ul>
<li>TCP: HTTP/1.1, HTTP/2</li>
<li>UDP: HTTP/3 진행중</li>
</ul>
<h3 id="http-특징">HTTP 특징</h3>
<ul>
<li>클라이언트 서버 구조</li>
<li>무상태 프로토콜(스테이스리스), 비연결성</li>
<li>HTTP 메시지</li>
<li>단순함, 확장 가능<ul>
<li>무상태 프로토콜의 특징으로 응답 서버를 쉽게 바꿀 수 있다.</li>
<li>반대로 상태유지 (Stateful) 은 항상 같은 서버가 유지되어야 하여서 서버를 쉽게 바꿀 수 없다. (상태가 사라지니깐, 처음부터 다시 요청해야 한다.)</li>
</ul>
</li>
</ul>
<h1 id="http-message">HTTP Message</h1>
<p>서버와 클라이언트 간에 데이터가 교환되는 방식이며  ASCII 로 인코딩된 텍스트 정보이며 여러 줄로 되어있다. 메시지 타입은 두 가지가 있다.</p>
<ul>
<li>요청 (Request)</li>
<li>응답 (Response)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/qnddj-kjh/post/bf13a10f-defe-47d8-b713-b2841fea6c31/image.png" alt="HTTP message 구조   출처 : 코드스테이츠"></p>
<p>HTTP message 구조   출처 : 코드스테이츠</p>
<h3 id="http-request">HTTP Request</h3>
<p><strong>구조</strong></p>
<ul>
<li><p><strong>start-line (시작 줄)</strong></p>
<ul>
<li>HTTP 메서드<ul>
<li>서버가 수행해야 하는 동작을 나타낸다.</li>
</ul>
</li>
<li>요청 타겟<ul>
<li>주로 URL 또는 프로토콜, 포트, 도메인의 절대 경로로 나타낸다. 이들은 요청 컨텍스트에 의해 특정지어지고 요청 타겟 포맷은 HTTP 메소드에 따라 달라진다.</li>
<li>형식 존재<ul>
<li>origin : GET, POST, HEAD, OPTIONS<ul>
<li>ex) <code>POST / HTTP 1.1</code>, <code>HEAD /test.html?query=alibaba HTTP/1.1</code> 등</li>
</ul>
</li>
<li>absolute : 대부분 GET<ul>
<li>ex) <code>GET http://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1</code></li>
</ul>
</li>
<li>authority : HTTP 터널을 구축하는 경우에만 CONNECT 와 함께 사용<ul>
<li>ex) <code>CONNECT developer.mozilla.org:80 HTTP/1.1</code></li>
</ul>
</li>
<li>asterisk : OPTIONS 와 함께 별포 (<code>’*’</code>) 하나로 간단하게 서버 전체를 나타낸다.<ul>
<li>ex) <code>OPTIONS * HTTP/1.1</code></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>HTTP 버전<ul>
<li>응답 메시지에서 써야 할 HTTP 버전을 알려준다.</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>헤더 (Header)</strong></p>
<ul>
<li><p>클라이언트와 서버가 요청 또는 응답으로 부가적인 정보를 전송할 수 있도록 해준다</p>
</li>
<li><p>HTTP 헤더의 기본 구조를 따른다.</p>
<p>다양한 요청 헤더가 있는데 다음과 같은 몇몇 그룹으로 나눌 수 있다.</p>
</li>
<li><p>General : 요청과 응답 모두에 적용되지만 바디에서 최종적으로 전송되는 데이터와는 관련이 없는 헤더.</p>
</li>
<li><p>Request : 페치될 리소스나 클라이언트 자체에 대한 자세한 정보를 포함하는 헤더.</p>
</li>
<li><p>Response : 위치 또는 서버 자체에 대한 정보(이름, 버전 등)와 같이 응답에 대한 부가적인 정보를 갖는 헤더.</p>
</li>
<li><p>Entity : 컨텐츠 길이나 MIME 타입과 같이 엔티티 바디에 대한 자세한 정보를 포함하는 헤더.</p>
</li>
</ul>
</li>
<li><p><strong>본문 (Body)</strong></p>
</li>
</ul>
<h3 id="http-response">HTTP Response</h3>
<ul>
<li><p><strong>start-line (시작 줄)</strong></p>
<ul>
<li>HTTP 메서드<ul>
<li>서버가 수행해야 하는 동작을 나타낸다.</li>
</ul>
</li>
<li>상태 코드 (HTTP Status Code)</li>
<li>HTTP 버전<ul>
<li>응답 메시지에서 써야 할 HTTP 버전을 알려준다.</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>헤더 (Header)</strong></p>
<ul>
<li><p>클라이언트와 서버가 요청 또는 응답으로 부가적인 정보를 전송할 수 있도록 해준다</p>
</li>
<li><p>HTTP 헤더의 기본 구조를 따른다.</p>
<p>다양한 요청 헤더가 있는데 다음과 같은 몇몇 그룹으로 나눌 수 있다.</p>
</li>
<li><p>General : 요청과 응답 모두에 적용되지만 바디에서 최종적으로 전송되는 데이터와는 관련이 없는 헤더.</p>
</li>
<li><p>Request : 페치될 리소스나 클라이언트 자체에 대한 자세한 정보를 포함하는 헤더.</p>
</li>
<li><p>Response : 위치 또는 서버 자체에 대한 정보(이름, 버전 등)와 같이 응답에 대한 부가적인 정보를 갖는 헤더.</p>
</li>
<li><p>Entity : 컨텐츠 길이나 MIME 타입과 같이 엔티티 바디에 대한 자세한 정보를 포함하는 헤더.</p>
</li>
</ul>
</li>
<li><p><strong>본문 (Body)</strong></p>
<ul>
<li>본문은 요청의 마지막 부분에 들어갑니다. 모든 요청에 본문이 들어가지는 않습니다. <code>GET</code>, <code>HEAD</code>, <code>DELETE</code> , <code>OPTIONS</code>처럼 리소스를 가져오는 요청은 보통 본문이 필요가 없습니다. 일부 요청은 업데이트를 하기 위해 서버에 데이터를 전송합니다. 보통 (HTML 폼 데이터를 포함하는) <code>POST</code> 요청일 경우에 그렇습니다.</li>
<li>넓게 보면 본문은 두가지 종류로 나뉩니다.<ul>
<li>단일-리소스 본문(single-resource bodies): 헤더 두 개(<code>[Content-Type](https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Content-Type)</code>와 <code>[Content-Length](https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Content-Length)</code>)로 정의된 단일 파일로 구성됩니다.</li>
<li>다중-리소스 본문(multiple-resource bodies): 멀티파트 본문으로 구성되는 <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Basics_of_HTTP/MIME_types#multipartform-data">다중 리소스 본문</a>에서는 파트마다 다른 정보를 지니게 됩니다. 보통 <a href="https://developer.mozilla.org/en-US/docs/Learn/Forms">HTML 폼 (en-US)</a>과 관련이 있습니다.</li>
</ul>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>