<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>SY Storage</title>
    <link>https://systorage.tistory.com/</link>
    <description>Node.js 백엔드 개발자의 개인 저장소</description>
    <language>ko</language>
    <pubDate>Mon, 25 May 2026 20:53:54 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>얼은펭귄</managingEditor>
    <image>
      <title>SY Storage</title>
      <url>https://tistory1.daumcdn.net/tistory/5315384/attach/db7727cd14e443239598da2918afe1ea</url>
      <link>https://systorage.tistory.com</link>
    </image>
    <item>
      <title>[Kubernetes] Ingress</title>
      <link>https://systorage.tistory.com/entry/Kubernetes-Ingress</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;트래픽을 클러스터로 가져오는 라우터/프록시의 역할을 한다.&lt;br /&gt;라우팅하는 규칙을 가지고 있다.&lt;br /&gt;Ingress를 관리하기 위해 Ingress Controller가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ingress Controller는 Ingress 리소스를 관리한다.&lt;br /&gt;Ingress에는 rule이 포함되어 있고 Ingress Controller는 rule을 적용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ingress Controller에는 많은 종류가 있지만 nginx로 진행한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Nginx ingress Controller&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 클러스터를 삭제하자&lt;/p&gt;
&lt;pre class=&quot;mel&quot;&gt;&lt;code&gt;kind delete cluster --name dev-cluster&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이후 새로운 클러스터를 생성한다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;# 01-cluster.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: dev-cluster
nodes:
- role: control-plane
  kubeadmConfigPatches:
    - |
      kind: InitConfiguration
      nodeRegistration:
        kubeletExtraArgs:
          node-labels: &quot;ingress-ready=true&quot;
  extraPortMappings:
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP
- role: worker
- role: worker


# metric-server 재설치&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;# 클러스터 생성
kind create cluster --config 01-cluster.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 아래에서 ingress-nginx를 설치한다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Ingress demo&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 2개의 파일을 생성하자&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;# 01-simple-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deploy
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 3
  template:
    metadata:
      labels:
        app: my-app
    spec:
      terminationGracePeriodSeconds: 1
      containers:
        - name: nginx
          image: vinsdocker/nginx-gke
---
apiVersion: v1
kind: Service
metadata:
  name: my-app
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 80

# 02-simple-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-app
                port:
                  number: 80&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두개 다 적용해보자&lt;/p&gt;
&lt;pre class=&quot;coq&quot;&gt;&lt;code&gt;kubectl apply -f .&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ingress는 kubectl get all로 가져와지지 않는다.&lt;br /&gt;대신 아래 명령어를 통해서 가져오자&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;kubectl get ing

# 결과
NAME         CLASS    HOSTS   ADDRESS     PORTS   AGE
my-ingress   &amp;lt;none&amp;gt;   *       localhost   80      49s&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요청을 보내보면 요청이 각각 다른 파드로 제대로 전달되는것을 확인할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt; ~/k8s-edu/sec10-ingress curl localhost
&amp;lt;H1&amp;gt;Hello my-deploy-5db6877498-7pbt2 &amp;lt;/H1&amp;gt;
 ~/k8s-edu/sec10-ingress curl localhost
&amp;lt;H1&amp;gt;Hello my-deploy-5db6877498-k4bp7 &amp;lt;/H1&amp;gt;
 ~/k8s-edu/sec10-ingress    curl localhost
&amp;lt;H1&amp;gt;Hello my-deploy-5db6877498-sc8st &amp;lt;/H1&amp;gt;
 ~/k8s-edu/sec10-ingress  curl localhost
&amp;lt;H1&amp;gt;Hello my-deploy-5db6877498-sc8st &amp;lt;/H1&amp;gt;
 ~/k8s-edu/sec10-ingress  curl localhost
&amp;lt;H1&amp;gt;Hello my-deploy-5db6877498-7pbt2 &amp;lt;/H1&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Path Based Routing&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 예시에서는 하나의 deployment에 대해서 적용했었다&lt;br /&gt;이번에는 3개 각각에 ingress를 적용해보자&lt;br /&gt;4개의 파일을 생성하자&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;# 01-product.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: product-app
spec:
  selector:
    matchLabels:
      app: product-app
  replicas: 2
  template:
    metadata:
      labels:
        app: product-app
    spec:
      terminationGracePeriodSeconds: 1
      containers:
        - name: product
          image: vinsdocker/k8s-ingress-product
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: product-service
spec:
  selector:
    app: product-app
  ports:
    - port: 80
      targetPort: 80


# 02-user.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-app
spec:
  selector:
    matchLabels:
      app: user-app
  replicas: 2
  template:
    metadata:
      labels:
        app: user-app
    spec:
      terminationGracePeriodSeconds: 1
      containers:
        - name: user
          image: vinsdocker/k8s-ingress-user
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: user-service
spec:
  selector:
    app: user-app
  ports:
    - port: 80
      targetPort: 80


# 03-home.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: home-app
spec:
  selector:
    matchLabels:
      app: home-app
  replicas: 1
  template:
    metadata:
      labels:
        app: home-app
    spec:
      terminationGracePeriodSeconds: 1
      containers:
        - name: home
          image: vinsdocker/k8s-ingress-home
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: home-service
spec:
  selector:
    app: home-app
  ports:
    - port: 80
      targetPort: 80


# 04-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
    - http:
        paths:
          - path: /product
            pathType: Prefix
            backend:
              service:
                name: product-service
                port:
                  number: 80
          - path: /user
            pathType: Prefix
            backend:
              service:
                name: user-service
                port:
                  number: 80
          - path: /
            pathType: Prefix
            backend:
              service:
                name: home-service
                port:
                  number: 80&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폴더 전체를 적용하자&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt; kubectl apply -f 03-path-based-routing&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 브라우저를 열어서 하나하나 들어가보자&lt;/p&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;localhost
localhost/product
localhost/user&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각의 파드에 도달하는 화면을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Dev/Qa Deploy&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폴더를 만들고 qa와 dev로 구분하자&lt;br /&gt;이후 아래 파일들을 만들자&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;#dev
#deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deploy
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 2
  template:
    metadata:
      labels:
        app: my-app
    spec:
      terminationGracePeriodSeconds: 1
      containers:
        - name: nginx
          image: vinsdocker/k8s-app:v2
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: my-app
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 80


#ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-app
                port:
                  number: 80&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;#qa
#deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deploy
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 2
  template:
    metadata:
      labels:
        app: my-app
    spec:
      terminationGracePeriodSeconds: 1
      containers:
        - name: nginx
          image: vinsdocker/k8s-app:v1
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: my-app
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 80


#ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-app
                port:
                  number: 80&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 2개의 namespace를 만들자&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;kubectl create ns dev
kubectl create ns qa&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 생성한 파일들을 해당 네임스페이스에 적용해보자&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;kubectl apply -f 04-host-based-routing/dev-workload -n dev

kubectl apply -f 04-host-based-routing/qa-workload -n qa

# 결과
deployment.apps/my-deploy created
service/my-app created
Error from server (BadRequest): error when creating &quot;04-host-based-routing/qa-workload/02-ingress.yaml&quot;: admission webhook &quot;validate.nginx.ingress.kubernetes.io&quot; denied the request: host &quot;_&quot; and path &quot;/&quot; is already defined in ingress dev/my-ingress
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dev는 생성된것을확인할 수 있다. 하지만 ingress는 에러가 난 것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Dev/QA routing issue&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 이런일이 생길까? (아래는 Nginx 컨트롤러에 한한다. 다른 컨트롤러는 다를수도 있다.)&lt;br /&gt;Ingress controller는 cluster 수준의 리소스이다.&lt;br /&gt;또한 ingress controller는 등록된 ingress의 rule들을 가져와서 컨트롤러에서 관리하는데 이미 경로가 등록되어있기 때문이다.&lt;br /&gt;그럼 해결하려면 어떻게 해야할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Host &amp;amp; Path based routing&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ingress 파일들을 host 따라서 routing 하게 변경해보자&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
    - host: &quot;dev.myapp.com&quot;
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-app
                port:
                  number: 80



# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
    - host: &quot;qa.myapp.com&quot;
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-app
                port:
                  number: 80&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 다시 생성해보면 제대로 생성되는 것을 확인할 수 있다&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;kubectl apply -f 04-host-based-routing/dev-workload -n dev
kubectl apply -f 04-host-based-routing/qa-workload -n qa&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 환경에서 host를 건드려서 임의로 테스트 할 수 있다.&lt;br /&gt;하지만 여기에서는 테스트 하지 않는다&lt;/p&gt;</description>
      <category>Kubernetes</category>
      <category>ingress</category>
      <category>ingress controller</category>
      <category>k8s</category>
      <category>kubernetes</category>
      <category>kubernetes 학습</category>
      <category>nginx ingress</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/235</guid>
      <comments>https://systorage.tistory.com/entry/Kubernetes-Ingress#entry235comment</comments>
      <pubDate>Mon, 30 Dec 2024 16:20:24 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes] HPA - Horizontal Pod Autoscaler</title>
      <link>https://systorage.tistory.com/entry/Kubernetes-HPA-Horizontal-Pod-Autoscaler</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Metric server 설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래는 아래 github에서 CLI 한줄이면 설치가 가능하지만&lt;br /&gt;이 글에서는 kind cluster로 학습하고 있기 때문에 설치가 불가능하다&lt;br /&gt;&lt;a href=&quot;https://github.com/kubernetes-sigs/metrics-server&quot;&gt;https://github.com/kubernetes-sigs/metrics-server&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체파일로 설치하자&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;# metrics-server.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    k8s-app: metrics-server
    rbac.authorization.k8s.io/aggregate-to-admin: &quot;true&quot;
    rbac.authorization.k8s.io/aggregate-to-edit: &quot;true&quot;
    rbac.authorization.k8s.io/aggregate-to-view: &quot;true&quot;
  name: system:aggregated-metrics-reader
rules:
- apiGroups:
  - metrics.k8s.io
  resources:
  - pods
  - nodes
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    k8s-app: metrics-server
  name: system:metrics-server
rules:
- apiGroups:
  - &quot;&quot;
  resources:
  - nodes/metrics
  verbs:
  - get
- apiGroups:
  - &quot;&quot;
  resources:
  - pods
  - nodes
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server-auth-reader
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server:system:auth-delegator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: system:metrics-server
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:metrics-server
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  ports:
  - name: https
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  strategy:
    rollingUpdate:
      maxUnavailable: 0
  template:
    metadata:
      labels:
        k8s-app: metrics-server
    spec:
      containers:
      - args:
        - --cert-dir=/tmp
        - --secure-port=4443
        - --kubelet-insecure-tls
        - --kubelet-preferred-address-types=InternalIP
        - --kubelet-use-node-status-port
        - --metric-resolution=15s
        image: k8s.gcr.io/metrics-server/metrics-server:v0.6.2
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /livez
            port: https
            scheme: HTTPS
          periodSeconds: 10
        name: metrics-server
        ports:
        - containerPort: 4443
          name: https
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /readyz
            port: https
            scheme: HTTPS
          initialDelaySeconds: 20
          periodSeconds: 10
        resources:
          requests:
            cpu: 100m
            memory: 200Mi
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 1000
        volumeMounts:
        - mountPath: /tmp
          name: tmp-dir
      nodeSelector:
        kubernetes.io/os: linux
      priorityClassName: system-cluster-critical
      serviceAccountName: metrics-server
      volumes:
      - emptyDir: {}
        name: tmp-dir
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
  labels:
    k8s-app: metrics-server
  name: v1beta1.metrics.k8s.io
spec:
  group: metrics.k8s.io
  groupPriorityMinimum: 100
  insecureSkipTLSVerify: true
  service:
    name: metrics-server
    namespace: kube-system
  version: v1beta1
  versionPriority: 100&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어를 적용해서 설치한 후 확인하고 진행하자&lt;/p&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;kubectl apply -f metrics-server.yaml

kubectl get pod -n kube-system

# 결과
NAME                                                READY   STATUS    RESTARTS   AGE
coredns-7c65d6cfc9-j7xg8                            1/1     Running   0          2d17h
coredns-7c65d6cfc9-l76fn                            1/1     Running   0          2d17h
etcd-dev-cluster-control-plane                      1/1     Running   0          2d17h
kindnet-kqh8m                                       1/1     Running   0          2d17h
kindnet-rvdl9                                       1/1     Running   0          2d17h
kindnet-x9xlp                                       1/1     Running   0          2d17h
kube-apiserver-dev-cluster-control-plane            1/1     Running   0          2d17h
kube-controller-manager-dev-cluster-control-plane   1/1     Running   0          2d17h
kube-proxy-dpnls                                    1/1     Running   0          2d17h
kube-proxy-nsq78                                    1/1     Running   0          2d17h
kube-proxy-xk7vs                                    1/1     Running   0          2d17h
kube-scheduler-dev-cluster-control-plane            1/1     Running   0          2d17h
metrics-server-7b445dfdc-jhnv8                      0/1     Running   0          29s # 이 부분이 1/1 이 되어야 한다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어를 통해 memory와 cpu 사용량을 볼 수 있다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 파드 사용량 (현재는 pod가 없음)
kubectl top pod

# 결과
No resources found in default namespace.

# 노드에서의 사용량
kubectl top nodes

# 결과
NAME                        CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
dev-cluster-control-plane   206m         1%     848Mi           10%
dev-cluster-worker          28m          0%     265Mi           3%
dev-cluster-worker2         32m          0%     292Mi           3%&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리소스의 단위는 아래와 같다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;Memory&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;1M, 50M, 1G&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;1Mi, 50Mi, 1Gi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;CPU&lt;/td&gt;
&lt;td style=&quot;width: 66.6666%;&quot; colspan=&quot;2&quot;&gt;1 (하나의 CPU), 100m (CPU 1/10), 500m (CPU 1/5) (실제로는 이렇지 않지만 이렇게 생각해도 무방하다.)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 컨테이너가 memory나 cpu가 한도를 초과하면 어떻게 될까?&lt;br /&gt;memory의 경우 kubelet이 컨테이너를 죽이고 재시작한다.&lt;br /&gt;CPU의 경우 컨테이너가 죽지 않고 쓰로틀링이 걸린다. (성능이 저하될 수 있다.)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Pod pending&lt;/h2&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;# 01-deploy-cpu-memory_usage.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deploy
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 3
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            requests:
              cpu: 2
              memory: 100Mi
            limits:
              cpu: 2
              memory: 100Mi&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 만들고 실행한 후 top으로 확인해보자&lt;br /&gt;위의 파일에서 request 보다 더 많은 리소스를 사용할 수 있도록 허용하고&lt;br /&gt;limit은 limit 보다 더 많은 리소스를 사용할 수는 없다.&lt;/p&gt;
&lt;pre class=&quot;subunit&quot;&gt;&lt;code&gt;kubectl apply -f 01-deploy-cpu-memory_usage.yaml

kubectl top pods
# 15초 간격으로 확인하기 때문에 pod를 실행하고 조금 기다린 후 다시 실행하자
error: metrics not available yet

kubectl top pods

# 결과
NAME                         CPU(cores)   MEMORY(bytes)
my-deploy-6bcdc9d88f-chvvm   0m           15Mi
my-deploy-6bcdc9d88f-hwvw8   0m           15Mi
my-deploy-6bcdc9d88f-xsdh4   0m           15Mi&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 파일처럼 CPU 수를 늘리고 replicaSet도 늘려서 적용해보자&lt;br /&gt;이 숫자는 worker CPU에 따라서 변경이 가능하다&lt;br /&gt;아래 예시는 CPU가 부족할때를 보기 위함이다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deploy
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 5
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            requests:
              cpu: 10
              memory: 100Mi
            limits:
              cpu: 10
              memory: 100Mi&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확인해보면 일부 pod가 pending 상태인걸 확인할 수 있다.&lt;br /&gt;describe로 확인해보자&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt; kubectl describe pod/my-deploy-6598fd5d9-q5frf

# 결과
...
Events:
  Type     Reason            Age                  From               Message
  ----     ------            ----                 ----               -------
  Warning  FailedScheduling  111s (x4 over 2m1s)  default-scheduler  0/3 nodes are available: 1 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: }, 2 Insufficient cpu. preemption: 0/3 nodes are available: 1 Preemption is not helpful for scheduling, 2 No preemption victims found for incoming pod.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pod에 CPU를 할당해야하지만 모든 CPU가 사용중이라서 불가능하다.&lt;br /&gt;해결방법은 실제로 노드를 늘리거나 pod를 줄이는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HPA template&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2개의 파일을 만들자&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;# 02-deploy-for-hpa.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deploy
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 1
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: nginx
          image: nginx
          startupProbe:
            httpGet:
              path: /
              port: 80
            periodSeconds: 1
            failureThreshold: 30
          readinessProbe:
            httpGet:
              path: /
              port: 80
            periodSeconds: 5
            failureThreshold: 3
          resources:
            requests:
              cpu: 50m
              memory: 10Mi
            limits:
              cpu: 50m
              memory: 10Mi
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 80
---
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  terminationGracePeriodSeconds: 1
  containers:
    - name: demo
      image: vinsdocker/util
      args:
        - &quot;sleep&quot;
        - &quot;3600&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 파일은 deployment와 데모를 위한 pod 그리고 외부 접속을 위한 service이다.&lt;br /&gt;&lt;b&gt;nginx version에 따라서 cpu나 memory가 더 필요하면 pod가 켜지지 않을 수도 있다. 적당히 조절해주자&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;# 03-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-deploy
  minReplicas: 1
  maxReplicas: 3
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 10
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 10&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 파일은 deployment를 감시하며 autoscaling을 할 HPA 파일이다&lt;br /&gt;이제 적용해보자&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;kubectl apply -f 02-deploy-for-hpa.yaml
kubectl apply -f 03-hpa.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 demo pod로 접속한 후 부하 테스트를 진행해서 pod가 auto scaling이 되는지 확인해보자&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;kubectl exec -it demo-pod -- bash

root@demo-pod:/# ab -n 20000 -c 5 http://nginx/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;694&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vuBjy/btsLBt9PQ6h/YQFuKjCSdzZyW4VQoYTu51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vuBjy/btsLBt9PQ6h/YQFuKjCSdzZyW4VQoYTu51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vuBjy/btsLBt9PQ6h/YQFuKjCSdzZyW4VQoYTu51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvuBjy%2FbtsLBt9PQ6h%2FYQFuKjCSdzZyW4VQoYTu51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;740&quot; height=&quot;558&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;694&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 CPU가 더 사용됨에 따라 auto scaling이 되는것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 후 작업이 완료되면 다시 1개로 돌아온다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HPA - Without Probe&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 2번에서 probe를 주석 처리 하자&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deploy
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 1
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: nginx
          image: nginx
#          startupProbe:
#            httpGet:
#              path: /
#              port: 80
#            periodSeconds: 1
#            failureThreshold: 30
#          readinessProbe:
#            httpGet:
#              path: /
#              port: 80
#            periodSeconds: 5
#            failureThreshold: 3
          resources:
            requests:
              cpu: 50m
              memory: 20Mi
            limits:
              cpu: 50m
              memory: 20Mi
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 80
---
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  terminationGracePeriodSeconds: 1
  containers:
    - name: demo
      image: vinsdocker/util
      args:
        - &quot;sleep&quot;
        - &quot;3600&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 적용해보자&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;kubectl apply -f 02-deploy-for-hpa.yaml
kubectl apply -f 03-hpa.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데모 파드로 접속한 후 요청을 보내보자&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;kubectl exec -it demo-pod -- bash

ab -n 20000 -c 5 http://nginx/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중간에 connection이 거절당하는 것을 확인할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;Benchmarking nginx (be patient)
Completed 2000 requests
Completed 4000 requests
Completed 6000 requests
Completed 8000 requests
Completed 10000 requests
Completed 12000 requests
apr_socket_recv: Connection refused (111)
Total of 12928 requests completed&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 이런일이 발생할까?&lt;br /&gt;오토스케일링은 발생한다. 하지만 Probe가 있으면 컨테이너가 준비 된 후에 요청을 받지만&lt;br /&gt;Probe가 없으면 컨테이너가 준비되기 전에도 요청을 받기 때문에 연결이 거부되는 상황이 생긴다.&lt;/p&gt;</description>
      <category>Kubernetes</category>
      <category>devops</category>
      <category>HorizontalPodAutoscaler</category>
      <category>HPA</category>
      <category>kubernetes</category>
      <category>kubernetes리소스관리</category>
      <category>kubernetes스케일링</category>
      <category>오토스케일링</category>
      <category>자동화</category>
      <category>클라우드네이티브</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/234</guid>
      <comments>https://systorage.tistory.com/entry/Kubernetes-HPA-Horizontal-Pod-Autoscaler#entry234comment</comments>
      <pubDate>Mon, 30 Dec 2024 10:22:58 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes] Persistent Volume &amp;amp; StatefulSet</title>
      <link>https://systorage.tistory.com/entry/Kubernetes-Persistent-Volume-StatefulSet</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스&amp;nbsp;같은&amp;nbsp;어플리케이션의&amp;nbsp;경우&amp;nbsp;스토리지가&amp;nbsp;필요하다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PV라고도 부른다.&lt;/li&gt;
&lt;li&gt;스토리지 추상화 또는 볼륨 플러그인이다.&lt;/li&gt;
&lt;li&gt;스토리지를 제공한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 26.0077%;&quot;&gt;Term&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 28.1008%;&quot;&gt;Description&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 45.8914%;&quot;&gt;example&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 26.0077%;&quot;&gt;Storage&amp;nbsp;class&lt;/td&gt;
&lt;td style=&quot;width: 28.1008%;&quot;&gt;스토리지 타입&lt;/td&gt;
&lt;td style=&quot;width: 45.8914%;&quot;&gt;aws EBS SSD, AWS EBS disk based 등등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 26.0077%;&quot;&gt;Persistent&amp;nbsp;Volume&amp;nbsp;Claim(PVC)&lt;/td&gt;
&lt;td style=&quot;width: 28.1008%;&quot;&gt;PV를 생성하라는 요청이다.&lt;/td&gt;
&lt;td style=&quot;width: 45.8914%;&quot;&gt;5GB의 GCP PD ssd를 app을 위해 생성하라고 요청한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 26.0077%;&quot;&gt;Persistent&amp;nbsp;Volume&amp;nbsp;(PV)&lt;/td&gt;
&lt;td style=&quot;width: 28.1008%;&quot;&gt;영구 볼륨인 실제 스토리지 이다.&lt;/td&gt;
&lt;td style=&quot;width: 45.8914%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Storage Class&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스토리지 클래스의 참조 문서&lt;br /&gt;&lt;a href=&quot;https://kubernetes.io/ko/docs/concepts/storage/storage-classes/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://kubernetes.io/ko/docs/concepts/storage/storage-classes/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;아래&amp;nbsp;명령어를&amp;nbsp;사용해서&amp;nbsp;모든&amp;nbsp;스토리지&amp;nbsp;클래스를&amp;nbsp;가져올수&amp;nbsp;있다.&lt;/p&gt;
&lt;pre id=&quot;code_1735520721038&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get storageclass
kubectl get sc&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Access Modes&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ReadWriteOnce&lt;/li&gt;
&lt;li&gt;ReadWriteOncePod&lt;/li&gt;
&lt;li&gt;ReadOnlyMany&lt;/li&gt;
&lt;li&gt;ReadWriteMany&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Persistent Volume Claim&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 파일을 생성하자&lt;/p&gt;
&lt;pre id=&quot;code_1735520769704&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#01-simple-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  storageClassName: standard
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5G


kubectl apply -f 01-simple-pvc.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;생성 후 아래 명령어를 통해 확인할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1735520781701&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get pvc

#결과
NAME     STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
my-pvc   Pending                                      standard       &amp;lt;unset&amp;gt;                 25s&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 상태가 pending인데 describe를 통해 확인해보자&lt;/p&gt;
&lt;pre id=&quot;code_1735520796778&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl describe pvc

# 결과
Name:          my-pvc
Namespace:     default
StorageClass:  standard
Status:        Pending
Volume:
Labels:        &amp;lt;none&amp;gt;
Annotations:   &amp;lt;none&amp;gt;
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:
Access Modes:
VolumeMode:    Filesystem
Used By:       &amp;lt;none&amp;gt;
Events:
  Type    Reason                Age               From                         Message
  ----    ------                ----              ----                         -------
  Normal  WaitForFirstConsumer  4s (x6 over 74s)  persistentvolume-controller  waiting for first consumer to be created before binding&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;pod와&amp;nbsp;연결하지&amp;nbsp;않아서&amp;nbsp;아직&amp;nbsp;기다리고&amp;nbsp;있는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;아래&amp;nbsp;파일을&amp;nbsp;생성하자&lt;/p&gt;
&lt;pre id=&quot;code_1735520816508&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#02-pod-with-pvc.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  terminationGracePeriodSeconds: 1
  restartPolicy: Never
  containers:
    - name: nginx
      image: nginx
      volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: pod-volume
  volumes:
    - name: pod-volume
      persistentVolumeClaim:
        claimName: my-pvc



kubectl apply -f 02-pod-with-pvc.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;적용&amp;nbsp;후&amp;nbsp;확인해보자&lt;/p&gt;
&lt;pre id=&quot;code_1735520832043&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get pvc

# 결과
NAME     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
my-pvc   Bound    pvc-27af6678-3a6c-4059-9c53-8404d125af4d   5G         RWO            standard       &amp;lt;unset&amp;gt;                 9m45s



kubectl describe pvc

# 결과
Name:          my-pvc
Namespace:     default
StorageClass:  standard
Status:        Bound
Volume:        pvc-27af6678-3a6c-4059-9c53-8404d125af4d
Labels:        &amp;lt;none&amp;gt;
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
               volume.beta.kubernetes.io/storage-provisioner: rancher.io/local-path
               volume.kubernetes.io/selected-node: dev-cluster-worker
               volume.kubernetes.io/storage-provisioner: rancher.io/local-path
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      5G
Access Modes:  RWO
VolumeMode:    Filesystem
Used By:       my-pod
Events:
  Type    Reason                 Age                   From
         Message
  ----    ------                 ----                  ----
         -------
  Normal  WaitForFirstConsumer   3m48s (x26 over 10m)  persistentvolume-controller
         waiting for first consumer to be created before binding
  Normal  Provisioning           104s                  rancher.io/local-path_local-path-provisioner-57c5987fd4-2k8pk_20c2ba64-75fe-4e53-83b3-a9646cfc0d09  External provisioner is provisioning volume for claim &quot;default/my-pvc&quot;
  Normal  ProvisioningSucceeded  102s                  rancher.io/local-path_local-path-provisioner-57c5987fd4-2k8pk_20c2ba64-75fe-4e53-83b3-a9646cfc0d09  Successfully provisioned volume pvc-27af6678-3a6c-4059-9c53-8404d125af4d&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;실제&amp;nbsp;생성된&amp;nbsp;볼륨을&amp;nbsp;가져와보자&lt;/p&gt;
&lt;pre id=&quot;code_1735520859218&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get pv
# 결과
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
pvc-27af6678-3a6c-4059-9c53-8404d125af4d   5G         RWO            Delete           Bound    default/my-pvc   standard       &amp;lt;unset&amp;gt;    2m27s


kubectl describe pv
# 결과
Name:              pvc-27af6678-3a6c-4059-9c53-8404d125af4d
Labels:            &amp;lt;none&amp;gt;
Annotations:       pv.kubernetes.io/provisioned-by: rancher.io/local-path
Finalizers:        [kubernetes.io/pv-protection]
StorageClass:      standard
Status:            Bound
Claim:             default/my-pvc
Reclaim Policy:    Delete
Access Modes:      RWO
VolumeMode:        Filesystem
Capacity:          5G
Node Affinity:
  Required Terms:
    Term 0:        kubernetes.io/hostname in [dev-cluster-worker]
Message:
Source:
    Type:          HostPath (bare host directory volume)
    Path:          /var/local-path-provisioner/pvc-27af6678-3a6c-4059-9c53-8404d125af4d_default_my-pvc
    HostPathType:  DirectoryOrCreate
Events:            &amp;lt;none&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제&amp;nbsp;실제&amp;nbsp;PV가&amp;nbsp;있는&amp;nbsp;도커&amp;nbsp;안으로&amp;nbsp;진입해서&amp;nbsp;확인해보자&lt;/p&gt;
&lt;pre id=&quot;code_1735520872603&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 진입할 worker는 위의 describe 결과로 확인하자
docker exec -it dev-cluster-worker bash
# 아래 경로는 위의 describe 경로를 확인하자
cd /var/local-path-provisioner/pvc-27af6678-3a6c-4059-9c53-8404d125af4d_default_my-pvc

# 파일을 생성한다
&quot;Hello PVC&quot; &amp;gt; index.html

#도커 진입 종료
exit&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제&amp;nbsp;port-forawd를&amp;nbsp;통해서&amp;nbsp;확인해보자&lt;/p&gt;
&lt;pre id=&quot;code_1735520888682&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl port-forward my-pod 8080:80&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;http://localhost:8080/&amp;nbsp;으로&amp;nbsp;접근해보면&amp;nbsp;Hello&amp;nbsp;PVC가&amp;nbsp;출력되는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;&lt;br /&gt;이제&amp;nbsp;파드를&amp;nbsp;삭제후&amp;nbsp;무슨일이&amp;nbsp;일어나는지&amp;nbsp;확인해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1735520985679&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl delete -f 02-pod-with-pvc.yaml
kubectl get pvc
kubectl get pv&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;pod를&amp;nbsp;삭제&amp;nbsp;후에도&amp;nbsp;pvc와&amp;nbsp;pv는&amp;nbsp;살아있는것을&amp;nbsp;확인할수&amp;nbsp;있다.&amp;nbsp;다시&amp;nbsp;pod를&amp;nbsp;생성해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1735520994724&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f 02-pod-with-pvc.yaml
kubectl port-forward my-pod 8080:80&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파드를 생성하고 port-forward를 적용하면 여전히 hello pvc가 나오는것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Persistent Volume - Delete&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파드와 PVC를 삭제하자 &lt;/p&gt;
&lt;pre id=&quot;code_1735521021580&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl delete -f 02-pod-with-pvc.yaml
kubectl delete -f 01-simple-pvc.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제&amp;nbsp;확인해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1735521027659&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get pv
kubectl get pvc&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;PVC를&amp;nbsp;지우면&amp;nbsp;PV는&amp;nbsp;자동으로&amp;nbsp;삭제되는걸&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Deployment with PVC&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deployment를 사용해서 3개의 replica가 동시에 pv안의 같은 파일에 쓰면 어떤일이 일어날까 &lt;br /&gt;아래&amp;nbsp;파일을&amp;nbsp;생성해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1735521049694&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#03-deployment-with-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  storageClassName: standard
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5G
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deploy
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 3
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: nginx
        image: nginx
        startupProbe: # for demo
          exec:
            command:
              - &quot;/bin/sh&quot;
              - &quot;-c&quot;
              - 'echo &quot;$(hostname)&amp;lt;/br&amp;gt;&quot; &amp;gt;&amp;gt; /usr/share/nginx/html/index.html'
        volumeMounts:
          - mountPath: /usr/share/nginx/html
            name: pod-volume
      volumes:
        - name: pod-volume
          persistentVolumeClaim:
            claimName: my-pvc



kubectl apply -f 03-deployment-with-pvc.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;아래&amp;nbsp;명령어를&amp;nbsp;확인해보면&amp;nbsp;pvc와&amp;nbsp;pv는&amp;nbsp;하나만&amp;nbsp;생성된걸&amp;nbsp;확인할&amp;nbsp;수있다. &lt;/p&gt;
&lt;pre id=&quot;code_1735521060668&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get pvc
kubectl get pv&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포트포워딩을 해서 확인해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1735521070056&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl port-forward deploy/my-deploy 8080:80

# localhost:8080접속
my-deploy-85dbd57976-49pdl
my-deploy-85dbd57976-8r9mh
my-deploy-85dbd57976-xc2jh&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과를 보면 한 파일에 3개의 pod가 write를 한 것을 확인할 수 있다. &lt;br /&gt;원할때는&amp;nbsp;이렇게&amp;nbsp;사용하고&amp;nbsp;원하지&amp;nbsp;않는다면&amp;nbsp;조심해서&amp;nbsp;사용하자 &lt;br /&gt;각각의&amp;nbsp;Pod가&amp;nbsp;pv를&amp;nbsp;갖기&amp;nbsp;위해서는&amp;nbsp;statefulSet을&amp;nbsp;사용해야&amp;nbsp;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;StatefulSet&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개념은 배포와 비슷하다. &lt;/p&gt;
&lt;pre id=&quot;code_1735521090117&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 04-simple-ss.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-ss
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 3
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: nginx
          image: nginx:1.14



kubectl apply -f 04-simple-ss.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;파일을&amp;nbsp;생성하고&amp;nbsp;적용해서&amp;nbsp;확인해보면&amp;nbsp;순차적으로&amp;nbsp;pod가&amp;nbsp;생성되는것을&amp;nbsp;확인할수&amp;nbsp;있다. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1735521098052&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;watch -t -x kubectl get all

# 결과
NAME          READY   STATUS    RESTARTS   AGE
pod/my-ss-0   1/1     Running   0          116s
pod/my-ss-1   1/1     Running   0          109s
pod/my-ss-2   1/1     Running   0          102s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    &amp;lt;none&amp;gt;        443/TCP   3d22h

NAME                     READY   AGE
statefulset.apps/my-ss   3/3     116s&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;생성된&amp;nbsp;파드를&amp;nbsp;확인해보면&amp;nbsp;실제로&amp;nbsp;random한&amp;nbsp;이름으로&amp;nbsp;생성되지&amp;nbsp;않고&amp;nbsp;index이름이&amp;nbsp;끝에&amp;nbsp;붙어서&amp;nbsp;생성되는걸&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;또한&amp;nbsp;한번에&amp;nbsp;모든&amp;nbsp;pod가&amp;nbsp;생성되지&amp;nbsp;않고&amp;nbsp;순차적으로&amp;nbsp;생성된다. &lt;br /&gt;pod를&amp;nbsp;하나&amp;nbsp;지워보자 &lt;/p&gt;
&lt;pre id=&quot;code_1735521107570&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl delete pod/my-ss-1

# 결과
NAME          READY   STATUS    RESTARTS   AGE
pod/my-ss-0   1/1     Running   0          3m44s
pod/my-ss-1   1/1     Running   0          19s
pod/my-ss-2   1/1     Running   0          3m30s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    &amp;lt;none&amp;gt;        443/TCP   3d22h

NAME                     READY   AGE
statefulset.apps/my-ss   3/3     3m44s&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;파드를&amp;nbsp;지워도&amp;nbsp;랜덤한&amp;nbsp;이름으로&amp;nbsp;생성되지&amp;nbsp;않고&amp;nbsp;다시&amp;nbsp;그&amp;nbsp;이름으로&amp;nbsp;생성되는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;replicaSet을&amp;nbsp;5개로&amp;nbsp;늘려서&amp;nbsp;적용&amp;nbsp;후&amp;nbsp;다시&amp;nbsp;2개로&amp;nbsp;변경한다음&amp;nbsp;적용해보자 &lt;br /&gt;pod가&amp;nbsp;index&amp;nbsp;끝부터&amp;nbsp;사라지는걸&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;pre id=&quot;code_1735521119135&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;NAME          READY   STATUS    RESTARTS   AGE
pod/my-ss-0   1/1     Running   0          5m13s
pod/my-ss-1   1/1     Running   0          108s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    &amp;lt;none&amp;gt;        443/TCP   3d22h

NAME                     READY   AGE
statefulset.apps/my-ss   2/2     5m13s&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번엔 이미지를 바꿔보자 &lt;/p&gt;
&lt;pre id=&quot;code_1735521129839&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
    spec:
      containers:
        - name: nginx
          image: nginx&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적용해보면 index 끝부터 바뀌는걸 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;StatefulSet with Service&lt;/h2&gt;
&lt;pre id=&quot;code_1735521145793&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#05-ss-svc.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-ss
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 3
  template:
    metadata:
      labels:
        app: my-app
    spec:
      terminationGracePeriodSeconds: 1
      containers:
        - name: nginx
          image: vinsdocker/nginx-gke
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 80
---
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  terminationGracePeriodSeconds: 1
  containers:
    - name: demo
      image: vinsdocker/util
      args:
        - &quot;sleep&quot;
        - &quot;3600&quot;


kubectl apply -f 05-ss-svc.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 demo-pod에 접속해서 호출해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1735521158123&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl exec -it demo-pod -- bash

# 결과
root@demo-pod:/# curl nginx
&amp;lt;H1&amp;gt;Hello my-ss-1 &amp;lt;/H1&amp;gt;
root@demo-pod:/# curl nginx
&amp;lt;H1&amp;gt;Hello my-ss-2 &amp;lt;/H1&amp;gt;
root@demo-pod:/# curl nginx
&amp;lt;H1&amp;gt;Hello my-ss-1 &amp;lt;/H1&amp;gt;
root@demo-pod:/# curl nginx
&amp;lt;H1&amp;gt;Hello my-ss-0 &amp;lt;/H1&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 service가 load balancing을 해주는 것을알수 있다. &lt;br /&gt;특정&amp;nbsp;pod에&amp;nbsp;접근하려면&amp;nbsp;어떻게&amp;nbsp;해야할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Headless Service&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;헤드리스 서비스는 IP가 없고 kube-proxy가 로드밸런싱을 하지 않는다. &lt;br /&gt;대신에&amp;nbsp;&amp;lt;pod-name&amp;gt;.&amp;lt;svc-name&amp;gt;&amp;nbsp;형식으로&amp;nbsp;DNS가&amp;nbsp;생성된다. &lt;/p&gt;
&lt;pre id=&quot;code_1735521183196&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 06-ss-headless-svc.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-ss
spec:
  serviceName: nginx
  selector:
    matchLabels:
      app: my-app
  replicas: 3
  template:
    metadata:
      labels:
        app: my-app
    spec:
      terminationGracePeriodSeconds: 1
      containers:
        - name: nginx
          image: vinsdocker/nginx-gke
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: ClusterIP
  clusterIP: None # headless service
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 80
---
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  terminationGracePeriodSeconds: 1
  containers:
    - name: demo
      image: vinsdocker/util
      args:
        - &quot;sleep&quot;
        - &quot;3600&quot;



 kubectl apply -f 06-ss-headless-svc.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제&amp;nbsp;파드에&amp;nbsp;접속해서&amp;nbsp;살펴보자 &lt;/p&gt;
&lt;pre id=&quot;code_1735521193166&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl exec -it demo-pod -- bash

# 결과
root@demo-pod:/# nslookup nginx
Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   nginx.default.svc.cluster.local
Address: 10.244.2.10
Name:   nginx.default.svc.cluster.local
Address: 10.244.2.9
Name:   nginx.default.svc.cluster.local
Address: 10.244.1.19

# 특정 IP만 얻기
root@demo-pod:/# nslookup my-ss-0.nginx
Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   my-ss-0.nginx.default.svc.cluster.local
Address: 10.244.2.9&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 요청을 해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1735521202100&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;root@demo-pod:/# curl nginx
&amp;lt;H1&amp;gt;Hello my-ss-1 &amp;lt;/H1&amp;gt;
root@demo-pod:/# curl nginx
&amp;lt;H1&amp;gt;Hello my-ss-1 &amp;lt;/H1&amp;gt;
root@demo-pod:/# curl my-ss-0.nginx
&amp;lt;H1&amp;gt;Hello my-ss-0 &amp;lt;/H1&amp;gt;
root@demo-pod:/# curl my-ss-0.nginx
&amp;lt;H1&amp;gt;Hello my-ss-0 &amp;lt;/H1&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 특정 pod로만 요청을 보낼수 있다. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Dynamic Persistent Volume Claim&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 생성하고 적용해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1735521222645&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 07-ss-pvc.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-ss
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 3
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: nginx
        image: nginx
        startupProbe: # for demo
          exec:
            command:
              - &quot;/bin/sh&quot;
              - &quot;-c&quot;
              - 'echo &quot;$(hostname)&amp;lt;/br&amp;gt;&quot; &amp;gt;&amp;gt; /usr/share/nginx/html/index.html'
        volumeMounts:
          - mountPath: /usr/share/nginx/html
            name: my-pvc
  volumeClaimTemplates:
    - metadata:
        name: my-pvc
      spec:
        storageClassName: standard
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 1G



kubectl apply -f 07-ss-pvc.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어를 통해 각각 pvc와 pv가 확인된걸 확인할 수 있다. &lt;/p&gt;
&lt;pre id=&quot;code_1735521238891&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get pvc
NAME                 STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
my-pvc-my-ss-0   Bound    pvc-624f0b5a-89e2-40e4-9ab9-7f260e6d7436   1G         RWO            standard       &amp;lt;unset&amp;gt;                 39s
my-pvc-my-ss-1   Bound    pvc-cd5916e7-f20d-4414-a3c7-eadb6e6c466a   1G         RWO            standard       &amp;lt;unset&amp;gt;                 22s
my-pvc-my-ss-2   Bound    pvc-c31dd928-3f4d-4c65-9cc9-8606db0b23b4   1G         RWO            standard       &amp;lt;unset&amp;gt;                 6s

kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                        STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
pvc-624f0b5a-89e2-40e4-9ab9-7f260e6d7436   1G         RWO            Delete           Bound    default/my-pvc-my-deploy-0   standard       &amp;lt;unset&amp;gt;                          69s
pvc-c31dd928-3f4d-4c65-9cc9-8606db0b23b4   1G         RWO            Delete           Bound    default/my-pvc-my-deploy-2   standard       &amp;lt;unset&amp;gt;                          37s
pvc-cd5916e7-f20d-4414-a3c7-eadb6e6c466a   1G         RWO            Delete           Bound    default/my-pvc-my-deploy-1   standard       &amp;lt;unset&amp;gt;                          52s&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포트포워딩을 통해 연결된 storage를 확인할 수 있다. &lt;/p&gt;
&lt;pre id=&quot;code_1735521251983&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl port-forward pod/my-ss-0 8080:80
# localhost:8080 접속
my-ss-0

kubectl port-forward pod/my-ss-1 8080:80
# localhost:8080 접속
my-ss-1

kubectl port-forward pod/my-ss-2 8080:80
# localhost:8080 접속
my-ss-2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;파일을&amp;nbsp;지우고&amp;nbsp;다시&amp;nbsp;적용해보면&amp;nbsp;PVC가&amp;nbsp;새로&amp;nbsp;생성되지&amp;nbsp;않는다. &lt;br /&gt;이미&amp;nbsp;존재하는&amp;nbsp;PVC를&amp;nbsp;사용한다. &lt;br /&gt;다시&amp;nbsp;포트&amp;nbsp;포워딩을&amp;nbsp;해보면&amp;nbsp;2번&amp;nbsp;적혀있는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;pre id=&quot;code_1735521262299&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl port-forward pod/my-ss-0 8080:80
# localhost:8080 접속
my-ss-0
my-ss-0

kubectl port-forward pod/my-ss-1 8080:80
# localhost:8080 접속
my-ss-1
my-ss-1

kubectl port-forward pod/my-ss-2 8080:80
# localhost:8080 접속
my-ss-2
my-ss-2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어를 통해서 모든 pvc를 삭제할 수 있다. &lt;/p&gt;
&lt;pre id=&quot;code_1735521270492&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl delete pvc --all&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>Kubernetes</category>
      <category>devops</category>
      <category>k8s</category>
      <category>kubernetes학습</category>
      <category>PersistentVolume</category>
      <category>PV</category>
      <category>PVC</category>
      <category>StatefulSet</category>
      <category>ubernetes</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/233</guid>
      <comments>https://systorage.tistory.com/entry/Kubernetes-Persistent-Volume-StatefulSet#entry233comment</comments>
      <pubDate>Mon, 30 Dec 2024 10:16:28 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes] Secret</title>
      <link>https://systorage.tistory.com/entry/Kubernetes-Secret</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Configmap과 동일하지만 민감한 데이터이다. &lt;br /&gt;value는&amp;nbsp;base64로&amp;nbsp;인코딩되어있다. &lt;br /&gt;사용사례는&amp;nbsp;ssh&amp;nbsp;key&amp;nbsp;file,&amp;nbsp;자격증명,&amp;nbsp;사비스&amp;nbsp;계정&amp;nbsp;정보&amp;nbsp;등을&amp;nbsp;저장한다. &lt;br /&gt;&lt;br /&gt;터미널에서&amp;nbsp;간단하게&amp;nbsp;생성할&amp;nbsp;수&amp;nbsp;도&amp;nbsp;있다. &lt;/p&gt;
&lt;pre id=&quot;code_1734604593912&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create secret generic my-secret --from-literal=[key]=[value]
ex) kubectl create secret generic my-secret --from-literal=username=vinoth --from-liter
al=password=admin123

# secret 가져오기
kubectl get secret

# secret 상세정보
kubectl get secret -o yaml
apiVersion: v1
items:
- apiVersion: v1
  data:
    password: YWRtaW4xMjM=
    username: dmlub3Ro
  kind: Secret
  metadata:
    creationTimestamp: &quot;2024-12-17T02:24:34Z&quot;
    name: my-secret
    namespace: default
    resourceVersion: &quot;1121&quot;
    uid: b3034f27-42f0-41d6-b95a-d3f95a511b44
  type: Opaque
kind: List
metadata:
  resourceVersion: &quot;&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 작성해보자 &lt;br /&gt;리눅스&amp;nbsp;터미널에서&amp;nbsp;문자열을&amp;nbsp;base64로&amp;nbsp;인코딩해서&amp;nbsp;입력해야한다. &lt;/p&gt;
&lt;pre id=&quot;code_1734604609303&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;echo -n test | base64                                                                                                                                                                                                                                  
dGVzdA== 

echo -n admin123 | base64
YWRtaW4xMjM=

#04-simple-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: app-secret
data:
  username: dGVzdA== # test
  password: YWRtaW4xMjM= # admin123&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 파드에 주입해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734604621031&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Secret
metadata:
  name: app-secret
data:
  username: dGVzdA== # test
  password: YWRtaW4xMjM= # admin123
---
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  restartPolicy: Never
  containers:
    - name: ubuntu
      image: ubuntu
      env:
        - name: &quot;app_username&quot;
          valueFrom:
            secretKeyRef:
              name: app-secret
              key: username
        - name: &quot;app_password&quot;
          valueFrom:
            secretKeyRef:
              name: app-secret
              key: password
      args:
        - env&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행하고 확인해보면 제대로 들어간것을 확인할 수 있다. &lt;/p&gt;
&lt;pre id=&quot;code_1734604630987&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f 04-simple-secret.yaml
kubectl get secret -o yaml

kubectl logs my-pod

# 결과
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=my-pod
app_password=admin123
app_username=test
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
HOME=/root&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 전체 env도 가능하다. &lt;/p&gt;
&lt;pre id=&quot;code_1734604639664&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Secret
metadata:
  name: app-secret
data:
  username: dGVzdA== # test
  password: YWRtaW4xMjM= # admin123
---
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  restartPolicy: Never
  containers:
    - name: ubuntu
      image: ubuntu
      envFrom:
      - secretRef:
          name: app-secret
      args:
        - env&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Secret - 파일 삽입&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;01번 파일을 base64로 인코딩하고 입력하자 &lt;/p&gt;
&lt;pre id=&quot;code_1734604666943&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 06-inject-secret-as-file.yaml
apiVersion: v1
kind: Secret
metadata:
  name: app-secret
data:
  app.key: |
    YXBpVmVyc2lvbjogdjENCmtpbmQ6IENvbmZpZ01hcA0KbWV0YWRhdGE6DQogIG5hbWU6IGFwcC1w
    cm9wZXJ0aWVzDQpkYXRhOg0KICBhcHBVcmw6ICJodHRwOi8vbXktYXBwLXNlcnZpY2UiDQogIHRp
    bWVvdXQ6ICIzMCINCi0tLQ0KYXBpVmVyc2lvbjogdjENCmtpbmQ6IFBvZA0KbWV0YWRhdGE6DQog
    IG5hbWU6IG15LXBvZA0Kc3BlYzoNCiAgcmVzdGFydFBvbGljeTogTmV2ZXINCiAgY29udGFpbmVy
    czoNCiAgICAtIG5hbWU6IHVidW50dQ0KICAgICAgaW1hZ2U6IHVidW50dQ0KICAgICAgZW52Og0K
    ICAgICAgICAtIG5hbWU6ICJyZXF1ZXN0LnRpbWVvdXQiDQogICAgICAgICAgdmFsdWVGcm9tOg0K
    ICAgICAgICAgICAgY29uZmlnTWFwS2V5UmVmOg0KICAgICAgICAgICAgICBuYW1lOiBhcHAtcHJv
    cGVydGllcw0KICAgICAgICAgICAgICBrZXk6IHRpbWVvdXQNCiAgICAgICAgLSBuYW1lOiAiYXBw
    bGljYXRpb24udXJsIg0KICAgICAgICAgIHZhbHVlRnJvbToNCiAgICAgICAgICAgIGNvbmZpZ01h
    cEtleVJlZjoNCiAgICAgICAgICAgICAgbmFtZTogYXBwLXByb3BlcnRpZXMNCiAgICAgICAgICAg
    ICAga2V5OiBhcHBVcmwNCiAgICAgIGFyZ3M6DQogICAgICAgIC0gZW52DQo=
---
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  terminationGracePeriodSeconds: 1
  restartPolicy: Never
  containers:
  - name: ubuntu
    image: ubuntu
    volumeMounts:
      - name: secret-volume
        mountPath: /usr/share/props
    args:
      - sleep
      - &quot;3600&quot;
  volumes:
  - name: secret-volume
    secret:
      secretName: app-secret&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적용하고 파드에 접속해서 확인해보면 파일이 복사된걸 확인할 수 있다. &lt;/p&gt;
&lt;pre id=&quot;code_1734604678647&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f 06-inject-secret-as-file.yaml
kubectl exec -it my-pod -- bash
cd /usr/share/props/

# 파일 확인
cat app.key

# 결과
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-properties
data:
  appUrl: &quot;http://my-app-service&quot;
  timeout: &quot;30&quot;
---
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  restartPolicy: Never
  containers:
    - name: ubuntu
      image: ubuntu
      env:
        - name: &quot;request.timeout&quot;
          valueFrom:
            configMapKeyRef:
              name: app-properties
              key: timeout
        - name: &quot;application.url&quot;
          valueFrom:
            configMapKeyRef:
              name: app-properties
              key: appUrl
      args:
        - env&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Kubernetes</category>
      <category>k8s</category>
      <category>k8s secret</category>
      <category>K8S 보안</category>
      <category>k8s 설정</category>
      <category>kubernetes</category>
      <category>Secret</category>
      <category>민감 정보 관리</category>
      <category>보안 관리</category>
      <category>비밀번호 관리</category>
      <category>인증 정보</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/232</guid>
      <comments>https://systorage.tistory.com/entry/Kubernetes-Secret#entry232comment</comments>
      <pubDate>Thu, 19 Dec 2024 19:38:50 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes] ConfigMap</title>
      <link>https://systorage.tistory.com/entry/Kubernetes-ConfigMap</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이&amp;nbsp;글에서는&amp;nbsp;구성&amp;nbsp;정보를&amp;nbsp;애플리케이션과&amp;nbsp;분리하는&amp;nbsp;방법을&amp;nbsp;소개한다. &lt;br /&gt;&lt;br /&gt;ConfigMap&amp;nbsp;과&amp;nbsp;secret&amp;nbsp;을&amp;nbsp;통해서&amp;nbsp;애플리케이션과&amp;nbsp;환경&amp;nbsp;정보를&amp;nbsp;분리할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;ConfigMap&amp;nbsp;은&amp;nbsp;민감하지&amp;nbsp;않은&amp;nbsp;데이터를&amp;nbsp;관리한다. &lt;br /&gt;secret은&amp;nbsp;증명서같은&amp;nbsp;민감한&amp;nbsp;데이터를&amp;nbsp;관리한다. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ConfigMap&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;속성을 key/value 형식으로 가능하다.&lt;/li&gt;
&lt;li&gt;속성으로 파일도 가능하다.&lt;/li&gt;
&lt;li&gt;최대 1MB이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ConfigMap - Demo&lt;/h2&gt;
&lt;pre id=&quot;code_1734604325700&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#01-simple-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-properties
data:
  appUrl: &quot;http://my-app-service&quot;
  timeout: &quot;30&quot;



kubectl apply -f 01-simple-configmap.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;파일을&amp;nbsp;생성하고&amp;nbsp;적용하고&amp;nbsp;kubectl&amp;nbsp;get&amp;nbsp;all로&amp;nbsp;확인해도&amp;nbsp;아무것도&amp;nbsp;없는것을&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;아래&amp;nbsp;명령어로&amp;nbsp;확인해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734604334381&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get configmap
# 위와 동일
kubectl get cm

# 결과
NAME               DATA   AGE
app-properties     2      60s
kube-root-ca.crt   1      3h9m&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자세하게 보려면 아래처럼 할 수 있다. &lt;/p&gt;
&lt;pre id=&quot;code_1734604345172&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl describe cm app-properties

#결과
Name:         app-properties
Namespace:    default
Labels:       &amp;lt;none&amp;gt;
Annotations:  &amp;lt;none&amp;gt;

Data
====
appUrl:
----
http://my-app-service

timeout:
----
30


BinaryData
====

Events:  &amp;lt;none&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ConfigmMap - 환경변수 주입&lt;/h2&gt;
&lt;pre id=&quot;code_1734604358942&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: ConfigMap
metadata:
  name: app-properties
data:
  appUrl: &quot;http://my-app-service&quot;
  timeout: &quot;30&quot;
---
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  restartPolicy: Never
  containers:
    - name: ubuntu
      image: ubuntu
      env:
        - name: &quot;request.timeout&quot;
          valueFrom:
            configMapKeyRef:
              name: app-properties
              key: timeout
        - name: &quot;application.url&quot;
          valueFrom:
            configMapKeyRef:
              name: app-properties
              key: appUrl
      args:
        - env&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;위&amp;nbsp;파일을&amp;nbsp;생성하고&amp;nbsp;적용해보자 &lt;br /&gt;로그를&amp;nbsp;확인해보면&amp;nbsp;환경변수가&amp;nbsp;제대로&amp;nbsp;적용된걸&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;pre id=&quot;code_1734604366798&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl logs my-pod

# 결과
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=my-pod
request.timeout=30
application.url=http://my-app-service
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
HOME=/root&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1734604379509&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 02-inject-cm-as-env.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-properties
data:
  appUrl: &quot;http://my-app-service&quot;
  timeout: &quot;30&quot;
---
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  restartPolicy: Never
  containers:
    - name: ubuntu
      image: ubuntu
      envFrom:
      - configMapRef:
          name: app-properties
      args:
        - env&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 파일 생성 후 이전 파일들을 지우고 로그를 확인해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734604396707&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 기존 정보 삭제
kubectl delete  -f 01-simple-configmap.yaml
configmap &quot;app-properties&quot; deleted
pod &quot;my-pod&quot; deleted

# 새로 적용
kubectl apply -f 02-inject-cm-as-env.yaml
configmap/app-properties created
pod/my-pod created

# 로그확인
kubectl logs my-pod

#결과
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=my-pod
appUrl=http://my-app-service
timeout=30
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOME=/root&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ConfigMap - 파일 삽입&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 정보를 삭제하고 파일을 생성한 후 적용해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734604416323&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 03-inject-cm-as-file.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-properties
data:
  application.properties: |
    appUrl=http://my-app-service
    timeout=30
    a.b.c=something
    username=sy



kubectl delete -f 02-inject-cm-as-env.yaml
kubectl apply -f 03-inject-cm-as-file.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제&amp;nbsp;확인해보면&amp;nbsp;잘&amp;nbsp;생성된것을&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;pre id=&quot;code_1734604432911&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get cm app-properties -o yaml

# 결과
apiVersion: v1
data:
  application.properties: |
    appUrl=http://my-app-service
    timeout=30
    a.b.c=something
    username=sy
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {&quot;apiVersion&quot;:&quot;v1&quot;,&quot;data&quot;:{&quot;application.properties&quot;:&quot;appUrl=http://my-app-service\ntimeout=30\na.b.c=something\nusername=sy\n&quot;},&quot;kind&quot;:&quot;ConfigMap&quot;,&quot;metadata&quot;:{&quot;annotations&quot;:{},&quot;name&quot;:&quot;app-properties&quot;,&quot;namespace&quot;:&quot;default&quot;}}
  creationTimestamp: &quot;2024-12-16T07:54:03Z&quot;
  name: app-properties
  namespace: default
  resourceVersion: &quot;18713&quot;
  uid: 7fbc03a8-8bc4-45d1-847c-be46a1e2878e&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;아래처럼&amp;nbsp;파일을&amp;nbsp;수정해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734604446878&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: ConfigMap
metadata:
  name: app-properties
data:
  application.properties: |
    appUrl=http://my-app-service
    timeout=30
    a.b.c=something
    username=sy
---
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  terminationGracePeriodSeconds: 1
  restartPolicy: Never
  containers:
  - name: ubuntu
    image: ubuntu
    volumeMounts:
      - name: config-volume
        mountPath: /user/share/props
    args:
      - sleep
      - &quot;3600&quot;
  volumes:
  - name: config-volume
    configMap:
      name: app-properties&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;적용하고&amp;nbsp;컨테이너에&amp;nbsp;진입해서&amp;nbsp;확인해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734604464164&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f 03-inject-cm-as-file.yaml

# 결과
configmap/app-properties created
pod/my-pod created

# 컨테이너 접속
kubectl exec -it my-pod -- bash
root@my-pod:/# cd /usr/share/props
root@my-pod:/usr/share/props# ll

# 결과
drwxrwxrwx 3 root root 4096 Dec 16 08:03 ./
drwxr-xr-x 1 root root 4096 Dec 16 08:03 ../
drwxr-xr-x 2 root root 4096 Dec 16 08:03 ..2024_12_16_08_03_44.82811588/
lrwxrwxrwx 1 root root   30 Dec 16 08:03 ..data -&amp;gt; ..2024_12_16_08_03_44.82811588/
lrwxrwxrwx 1 root root   29 Dec 16 08:03 application.properties -&amp;gt; ..data/application.properties

# 확인
cat application.properties

# 결과
appUrl=http://my-app-service
timeout=30
a.b.c=something
username=sy&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일이 잘 들어간것을 확인할 수 있다. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>Kubernetes</category>
      <category>configmap</category>
      <category>k8s</category>
      <category>K8S configmap</category>
      <category>k8s 설정</category>
      <category>kubernetes</category>
      <category>설정 관리</category>
      <category>애플리케이션 구성</category>
      <category>컨테이너 설정</category>
      <category>클라우드 네이티브</category>
      <category>환경 변수</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/231</guid>
      <comments>https://systorage.tistory.com/entry/Kubernetes-ConfigMap#entry231comment</comments>
      <pubDate>Thu, 19 Dec 2024 19:35:44 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes] Probes</title>
      <link>https://systorage.tistory.com/entry/Kubernetes-Probes</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;kubelet은&amp;nbsp;컨테이너가&amp;nbsp;시작되자마자&amp;nbsp;실제로&amp;nbsp;준비되지&amp;nbsp;않은&amp;nbsp;상황에서도&amp;nbsp;살아있고&amp;nbsp;준비된&amp;nbsp;상태라고&amp;nbsp;생각한다. &lt;br /&gt;아직 활성화 되지 않은 부분이 활성화 된 것처럼 취급되면 안된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;probe는&amp;nbsp;파드의&amp;nbsp;health&amp;nbsp;체크를&amp;nbsp;도와주는&amp;nbsp;도구일&amp;nbsp;뿐이다. &lt;br /&gt;파드내 어플이 시작 되었는지, 살아있는지, 요청을 받을 준비가 되었는지를 확인한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Probe Types&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Terms&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Live&amp;nbsp;=&amp;gt;&amp;nbsp;파드가&amp;nbsp;살아있는지?&lt;/li&gt;
&lt;li&gt;Ready =&amp;gt; 파드가 요청을 받을 준비가 되었는지?&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.31%;&quot;&gt;Probes&lt;/td&gt;
&lt;td style=&quot;width: 51.3566%;&quot;&gt;Description&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;Action If Fails&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.31%;&quot;&gt;startupProbe&lt;/td&gt;
&lt;td style=&quot;width: 51.3566%;&quot;&gt;컨테이너 내부 애플리케이션이 시작되었는지 확인&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;재시작&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.31%;&quot;&gt;livenessProbe&lt;/td&gt;
&lt;td style=&quot;width: 51.3566%;&quot;&gt;애플리케이션이 여전히 살아 있는지 확인&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;재시작&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.31%;&quot;&gt;readinessProbe&lt;/td&gt;
&lt;td style=&quot;width: 51.3566%;&quot;&gt;애플리케이션이 서비스로부터 요청을 처리할 준비가 되었는지 확인&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;서비스에서 제외&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;k8s는 위의 방법에 3가지 옵션을 제공한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;exec&lt;/b&gt;:&amp;nbsp;아무&amp;nbsp;커맨드를&amp;nbsp;체크하기&amp;nbsp;위해&amp;nbsp;실행한다&amp;nbsp;ex)&amp;nbsp;cat&amp;nbsp;/tmp/app.log&lt;/li&gt;
&lt;li&gt;&lt;b&gt;httpGet&lt;/b&gt;:&amp;nbsp;http&amp;nbsp;엔드포인트에&amp;nbsp;요청한다.&amp;nbsp;ex)&amp;nbsp;/health&lt;/li&gt;
&lt;li&gt;&lt;b&gt;tcpSocket&lt;/b&gt;:&amp;nbsp;앱이&amp;nbsp;특정&amp;nbsp;포트에서&amp;nbsp;수신&amp;nbsp;대기&amp;nbsp;중인지&amp;nbsp;확인한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 프로브에 어떤 옵션을 사용하던 상관없다 &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;프로브&amp;nbsp;속성은&amp;nbsp;아래와&amp;nbsp;같다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 42.5582%; height: 102px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 22.8248%; height: 17px;&quot;&gt;Properties&lt;/td&gt;
&lt;td style=&quot;width: 31.1142%; height: 17px;&quot;&gt;Default Values&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 22.8248%; height: 17px;&quot;&gt;initialDelaySeconds&lt;/td&gt;
&lt;td style=&quot;width: 31.1142%; height: 17px;&quot;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 22.8248%; height: 17px;&quot;&gt;periodSeconds&lt;/td&gt;
&lt;td style=&quot;width: 31.1142%; height: 17px;&quot;&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 22.8248%; height: 17px;&quot;&gt;timeoutSeconds&lt;/td&gt;
&lt;td style=&quot;width: 31.1142%; height: 17px;&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 22.8248%; height: 17px;&quot;&gt;successThreshold&lt;/td&gt;
&lt;td style=&quot;width: 31.1142%; height: 17px;&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 22.8248%; height: 17px;&quot;&gt;failureThreshold&lt;/td&gt;
&lt;td style=&quot;width: 31.1142%; height: 17px;&quot;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Startup Probe - httpGet&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실패하는 프로브를 생성하고 관찰해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734603898425&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#01-startup-httpget.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: nginx
      image: nginx
      startupProbe:
        httpGet:
          path: /dummy
          port: 80
        periodSeconds: 1
        failureThreshold: 3





kubectl apply -f .&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1734603911489&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl describe pod

# 결과
Events:
  Type     Reason     Age                From               Message
  ----     ------     ----               ----               -------
  Normal   Scheduled  27s                default-scheduler  Successfully assigned default/my-pod to dev-cluster-worker2
  Normal   Pulled     27s                kubelet            Successfully pulled image &quot;nginx&quot; in 1.579s (1.579s including waiting). Image size: 72099501 bytes.
  Normal   Pulled     22s                kubelet            Successfully pulled image &quot;nginx&quot; in 1.519s (1.519s including waiting). Image size: 72099501 bytes.
  Normal   Pulling    18s (x3 over 27s)  kubelet            Pulling image &quot;nginx&quot;
  Normal   Created    17s (x3 over 27s)  kubelet            Created container nginx
  Normal   Pulled     17s                kubelet            Successfully pulled image &quot;nginx&quot; in 1.542s (1.542s including waiting). Image size: 72099501 bytes.
  Normal   Started    16s (x3 over 27s)  kubelet            Started container nginx
  Warning  Unhealthy  14s (x9 over 26s)  kubelet            Startup probe failed: HTTP probe failed with statuscode: 404
  Normal   Killing    13s (x3 over 23s)  kubelet            Container nginx failed startup probe, will be restarted
  Warning  BackOff    13s                kubelet            Back-off restarting failed container nginx in pod my-pod_def&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;Startup&amp;nbsp;probe가&amp;nbsp;실패한걸&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;아래&amp;nbsp;처럼&amp;nbsp;변경하고&amp;nbsp;다시&amp;nbsp;시작해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734603922975&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: nginx
      image: nginx
      startupProbe:
        httpGet:
          path: /
          port: 80
        periodSeconds: 1
        failureThreshold: 3



kubectl apply -f .&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Startup Probe - tcpSocket&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마찬가지로 의도적으로 실패하는 코드를 만들어보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734603951676&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 02-startup-tcpsocket.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: mongo
      image: mongo
      startupProbe:
        tcpSocket:
          port: 27018
        periodSeconds: 1
        failureThreshold: 5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;적용후&amp;nbsp;살펴보면&amp;nbsp;startup&amp;nbsp;probe&amp;nbsp;가&amp;nbsp;실패한걸&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;pre id=&quot;code_1734603963934&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f 02-startup-tcpsocket.yaml
kubectl describe pod

# 결과
Events:
  Type     Reason     Age               From               Message
  ----     ------     ----              ----               -------
  Normal   Scheduled  22s               default-scheduler  Successfully assigned default/my-pod to dev-cluster-worker2
  Normal   Pulled     11s               kubelet            Successfully pulled image &quot;mongo&quot; in 12.796s (12.796s including waiting). Image size: 274465658 bytes.
  Normal   Pulling    6s (x2 over 22s)  kubelet            Pulling image &quot;mongo&quot;
  Normal   Killing    6s                kubelet            Container mongo failed startup probe, will be restarted
  Normal   Created    4s (x2 over 11s)  kubelet            Created container mongo
  Normal   Started    4s (x2 over 11s)  kubelet            Started container mongo
  Normal   Pulled     4s                kubelet            Successfully pulled image &quot;mongo&quot; in 1.536s (1.536s including waiting). Image size: 274465658 bytes.
  Warning  Unhealthy  0s (x9 over 10s)  kubelet            Startup probe failed: dial tcp 10.244.1.7:27018: connect: connection refused&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 후 27017로 포트번호를 변경하고 적용하면 생성되는걸 확인할 수 있다. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Startup Probe - exec&lt;/h2&gt;
&lt;pre id=&quot;code_1734603983129&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#03-startup-exec.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: nginx
      image: nginx
      startupProbe:
        exec:
          command:
            - &quot;cat&quot;
            - &quot;dummy.txt&quot;
        periodSeconds: 1
        failureThreshold: 3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;일반적으로&amp;nbsp;httpGet이나&amp;nbsp;tcpSocket을&amp;nbsp;더&amp;nbsp;선호하며&amp;nbsp;exec는&amp;nbsp;둘&amp;nbsp;다&amp;nbsp;안될&amp;nbsp;경우를&amp;nbsp;위한다. &lt;/p&gt;
&lt;pre id=&quot;code_1734603998097&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f 03-startup-exec.yaml
kubectl describe pod
# 결과
Events:
  Type     Reason     Age               From               Message
  ----     ------     ----              ----               -------
  Normal   Scheduled  13s               default-scheduler  Successfully assigned default/my-pod to dev-cluster-worker2
  Normal   Pulled     12s               kubelet            Successfully pulled image &quot;nginx&quot; in 1.506s (1.506s including waiting). Image size: 72099501 bytes.
  Normal   Pulled     6s                kubelet            Successfully pulled image &quot;nginx&quot; in 1.618s (1.618s including waiting). Image size: 72099501 bytes.
  Normal   Pulling    3s (x3 over 13s)  kubelet            Pulling image &quot;nginx&quot;
  Normal   Killing    3s (x2 over 8s)   kubelet            Container nginx failed startup probe, will be restarted
  Normal   Created    2s (x3 over 12s)  kubelet            Created container nginx
  Normal   Pulled     2s                kubelet            Successfully pulled image &quot;nginx&quot; in 1.568s (1.568s including waiting). Image size: 72099501 bytes.
  Normal   Started    1s (x3 over 12s)  kubelet            Started container nginx
  Warning  Unhealthy  1s (x7 over 11s)  kubelet            Startup probe failed: cat: dummy.txt: No such file or directory&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래처럼 파일을 변경하고 삭제 후 재실행하면 &lt;/p&gt;
&lt;pre id=&quot;code_1734604009148&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: nginx
      image: nginx
      startupProbe:
        exec:
          command:
            - &quot;cat&quot;
            - &quot;/usr/share/nginx/html/index.html&quot;
        periodSeconds: 1
        failureThreshold: 3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Liveness&amp;nbsp;Probe&lt;/h2&gt;
&lt;pre id=&quot;code_1734604024531&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#04-liveness-probe.yaml
# 실제로는 nignx를 사용한다
# nginx가 10초 되에 시작될 것이다.
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  terminationGracePeriodSeconds: 1
  containers:
    - name: probe-demo
      image: vinsdocker/k8s-probe-demo
      startupProbe:
        httpGet:
          path: /
          port: 80
        periodSeconds: 1
        failureThreshold: 3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이렇게&amp;nbsp;실행하면&amp;nbsp;실제로&amp;nbsp;10초&amp;nbsp;뒤에&amp;nbsp;nginx가&amp;nbsp;실행되는&amp;nbsp;docker&amp;nbsp;이기&amp;nbsp;때문에&amp;nbsp;실패한다&amp;nbsp;failureThreshold를&amp;nbsp;30으로&amp;nbsp;바꿔주자 &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1734604052803&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 실제로는 nignx를 사용한다
# nginx가 10초 되에 시작될 것이다.
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  terminationGracePeriodSeconds: 1
  containers:
    - name: probe-demo
      image: vinsdocker/k8s-probe-demo
      startupProbe:
        httpGet:
          path: /
          port: 80
        periodSeconds: 1
        failureThreshold: 30
      livenessProbe:
        httpGet:
          path: /live.html
          port: 80
        periodSeconds: 1
        failureThreshold: 3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적용하고 컨테이너가 실행중인것을 확인한 후 파드로 들어가보자&lt;/p&gt;
&lt;pre id=&quot;code_1734604065371&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f 04-liveness-probe.yaml
kubectl exec -it my-pod -- bash
root@my-pod:/# cd /usr/share/nginx/html
root@my-pod:/usr/share/nginx/html# ls
50x.html  index.html  live.html  ready.html&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제 여기서 live.html을 지워보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734604076150&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;root@my-pod:/usr/share/nginx/html# rm live.html
root@my-pod:/usr/share/nginx/html# command terminated with exit code 137&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;liveness&amp;nbsp;probe가&amp;nbsp;문제가&amp;nbsp;있다고&amp;nbsp;생각하고&amp;nbsp;파드를&amp;nbsp;재시작했다. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Readiness Probe&lt;/h2&gt;
&lt;pre id=&quot;code_1734604108709&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 05-readiness-probe.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  terminationGracePeriodSeconds: 1
  containers:
    - name: probe-demo
      image: vinsdocker/k8s-probe-demo
      startupProbe:
        httpGet:
          path: /
          port: 80
        periodSeconds: 1
        failureThreshold: 30
      livenessProbe:
        httpGet:
          path: /live.html
          port: 80
        periodSeconds: 1
        failureThreshold: 3
      readinessProbe:
        httpGet:
          path: /ready.html
          port: 80
        periodSeconds: 1
        failureThreshold: 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;파드를&amp;nbsp;준비하고&amp;nbsp;실행하자&amp;nbsp;그리고&amp;nbsp;내부로&amp;nbsp;접속해서&amp;nbsp;파일을&amp;nbsp;삭제해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734604126109&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl exec -it my-pod -- bash
root@my-pod:/# cd /usr/share/nginx/html/
root@my-pod:/usr/share/nginx/html# ls
50x.html  index.html  live.html  ready.html
root@my-pod:/usr/share/nginx/html# rm ready.html&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 컨테이너에 문제가 없기 때문에 파드는 재실행되지 않고 Ready 상태가 0인걸 확인할 수 있다. &lt;br /&gt;touch&amp;nbsp;ready.html&amp;nbsp;을&amp;nbsp;통해&amp;nbsp;다시&amp;nbsp;파일을&amp;nbsp;만들어주면&amp;nbsp;ready&amp;nbsp;상태가&amp;nbsp;1/1&amp;nbsp;로&amp;nbsp;바뀐것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Readiness Probe with service&lt;/h2&gt;
&lt;pre id=&quot;code_1734604151103&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#05-readiness-probe.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app: my-app
spec:
  terminationGracePeriodSeconds: 1
  containers:
    - name: probe-demo
      image: vinsdocker/k8s-probe-demo
      startupProbe:
        httpGet:
          path: /
          port: 80
        periodSeconds: 1
        failureThreshold: 30
      livenessProbe:
        httpGet:
          path: /live.html
          port: 80
        periodSeconds: 1
        failureThreshold: 3
      readinessProbe:
        httpGet:
          path: /ready.html
          port: 80
        periodSeconds: 1
        failureThreshold: 1
---
apiVersion: v1
kind: Service
metadata:
  name: my-app
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 80&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 적용하고 살펴보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734604161630&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#적용
kubectl apply -f 05-readiness-probe.yaml
#감시
watch -t -x kubectl describe svc my-app&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ready.html 파일을 삭제하면 Endpoint가 사라지지만 k8s 1.31에서는 그런 현상은 일어나지 않는다.&lt;/p&gt;</description>
      <category>Kubernetes</category>
      <category>devops</category>
      <category>k8s</category>
      <category>k8s probe</category>
      <category>kubernetes</category>
      <category>liveness Probe</category>
      <category>readiness probe</category>
      <category>startup probe</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/230</guid>
      <comments>https://systorage.tistory.com/entry/Kubernetes-Probes#entry230comment</comments>
      <pubDate>Thu, 19 Dec 2024 19:30:15 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes] Namespace</title>
      <link>https://systorage.tistory.com/entry/Kubernetes-Namespace</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;K8S&amp;nbsp;클러스터는&amp;nbsp;가상&amp;nbsp;클러스터를&amp;nbsp;생성하거나&amp;nbsp;클러스터를&amp;nbsp;분할하는&amp;nbsp;기능을&amp;nbsp;제공한다. &lt;br /&gt;기본적으로&amp;nbsp;클러스터내의&amp;nbsp;리소스&amp;nbsp;그룹을&amp;nbsp;격리한다. &lt;br /&gt;&lt;br /&gt;아래&amp;nbsp;명령어를&amp;nbsp;통해서&amp;nbsp;namespace를&amp;nbsp;가져올&amp;nbsp;수&amp;nbsp;있다 &lt;/p&gt;
&lt;pre id=&quot;code_1734603422905&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 둘 다 동일한 명령어
kubectl get namespace
kubectl get ns

# 결과 
NAME                 STATUS   AGE
default              Active   40m
kube-node-lease      Active   40m
kube-public          Active   40m
kube-system          Active   40m
local-path-storage   Active   40m&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;아래&amp;nbsp;명령어로&amp;nbsp;네임스페이스를&amp;nbsp;생성한다. &lt;/p&gt;
&lt;pre id=&quot;code_1734603442087&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create ns [네임스페이스 이름]
ex) kubectl create ns dev
ex) kubectl create ns qa

kubectl get ns

# 결과
NAME                 STATUS   AGE
default              Active   44m
dev                  Active   12s
kube-node-lease      Active   44m
kube-public          Active   44m
kube-system          Active   44m
local-path-storage   Active   44m
qa                   Active   9s&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어로 네임스페이스를 삭제한다. &lt;/p&gt;
&lt;pre id=&quot;code_1734603454016&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl detete ns [네임스페이스 이름]
ex) kubectl detete ns dev&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Namespace deploy demo&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 파일을 생성한다 그리고 qa namespace에 배포한다. &lt;/p&gt;
&lt;pre id=&quot;code_1734603475374&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service-deployment
spec:
  minReadySeconds: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 1
  selector:
    matchLabels:
      app: order-service
  replicas: 3
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service-container
          image: vinsdocker/k8s-app:v1
          ports:
            - name: &quot;app-port&quot;
              containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: my-app
spec:
  selector:
    app: order-service
  ports:
    - port: 80
      targetPort: 80
---
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  terminationGracePeriodSeconds: 1
  containers:
    - name: demo
      image: vinsdocker/util
      args:
        - &quot;sleep&quot;
        - &quot;3600&quot;



kubectl apply -f 06-rolling-update-demo.yaml -n qa&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 version을 2로 바꾼 후 dev에 배포한다. &lt;/p&gt;
&lt;pre id=&quot;code_1734603490467&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f 06-rolling-update-demo.yaml -n dev&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;결과확인을&amp;nbsp;해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734603505458&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get all -n qa

#결과
NAME                                            READY   STATUS    RESTARTS   AGE
pod/demo-pod                                    1/1     Running   0          94s
pod/order-service-deployment-56864789dc-fz9xw   1/1     Running   0          94s
pod/order-service-deployment-56864789dc-md5kt   1/1     Running   0          94s
pod/order-service-deployment-56864789dc-tsqrj   1/1     Running   0          94s

NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/my-app   ClusterIP   10.96.199.164   &amp;lt;none&amp;gt;        80/TCP    94s

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/order-service-deployment   3/3     3            3           94s

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/order-service-deployment-56864789dc   3         3         3       94s&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1734603513438&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get all -n dev

# 결과
NAME                                           READY   STATUS    RESTARTS   AGE
pod/demo-pod                                   1/1     Running   0          47s
pod/order-service-deployment-d684fb7c6-4xvqh   1/1     Running   0          47s
pod/order-service-deployment-d684fb7c6-6zp6x   1/1     Running   0          47s
pod/order-service-deployment-d684fb7c6-wzzxn   1/1     Running   0          47s

NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/my-app   ClusterIP   10.96.159.225   &amp;lt;none&amp;gt;        80/TCP    47s

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/order-service-deployment   3/3     3            3           47s

NAME                                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/order-service-deployment-d684fb7c6   3         3         3       47s&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 cluster-ip가 다른것을 확인할 수 있다. &lt;br /&gt;포트포워딩을&amp;nbsp;사용해서&amp;nbsp;v1과&amp;nbsp;v2에&amp;nbsp;접근할수&amp;nbsp;있는지&amp;nbsp;확인해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734603531363&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# v1 화면을 볼 수 있다.
kubectl port-forward svc/my-app 8080:80 -n qa

# v2 화면을 볼 수 있다.
kubectl port-forward svc/my-app 8080:80 -n dev&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;namespace를 삭제하면 안의 모든 리소스들이 삭제된다. &lt;br /&gt;&lt;br /&gt;yaml&amp;nbsp;파일에&amp;nbsp;metadata안의&amp;nbsp;namespace를&amp;nbsp;선언하면&amp;nbsp;-n&amp;nbsp;옵션&amp;nbsp;없이도&amp;nbsp;항상&amp;nbsp;해당&amp;nbsp;네임스페이스에서&amp;nbsp;생성한다.&lt;/p&gt;</description>
      <category>Kubernetes</category>
      <category>devops</category>
      <category>k8s</category>
      <category>kubernetes</category>
      <category>namespace</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/229</guid>
      <comments>https://systorage.tistory.com/entry/Kubernetes-Namespace#entry229comment</comments>
      <pubDate>Thu, 19 Dec 2024 19:20:21 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes] Service</title>
      <link>https://systorage.tistory.com/entry/Kubernetes-Service</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;파드&amp;nbsp;세트에&amp;nbsp;대한&amp;nbsp;논리적&amp;nbsp;추상화이다. &lt;br /&gt;안정적인&amp;nbsp;단일&amp;nbsp;엔드포인트를&amp;nbsp;통해&amp;nbsp;노출한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Demo&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sec04의 1번을 복사한다. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1734414967748&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 01-simple-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deploy
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 3
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이후&amp;nbsp;service&amp;nbsp;파일을&amp;nbsp;생성한다.&lt;/p&gt;
&lt;pre id=&quot;code_1734414980159&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 02-simple-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 80&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1734414991431&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f .&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;적용&amp;nbsp;후&amp;nbsp;세부&amp;nbsp;사항을&amp;nbsp;살펴보자&lt;/p&gt;
&lt;pre id=&quot;code_1734415010222&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl describe svc nginx

#결과
Name:                     nginx
Namespace:                default
Labels:                   &amp;lt;none&amp;gt;
Annotations:              &amp;lt;none&amp;gt;
Selector:                 app=my-app
Type:                     ClusterIP
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.96.192.111
IPs:                      10.96.192.111
Port:                     &amp;lt;unset&amp;gt;  80/TCP
TargetPort:               80/TCP
Endpoints:                10.244.1.9:80,10.244.2.10:80,10.244.1.10:80
Session Affinity:         None
Internal Traffic Policy:  Cluster
Events:                   &amp;lt;none&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올라가 있는 파드를 지우거나 늘리거나 변경되면 Endpoints가 즉시 업데이트 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Load Balancing&lt;/h2&gt;
&lt;pre id=&quot;code_1734415041292&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#03-svc-load-balancing.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deploy
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 3
  template:
    metadata:
      labels:
        app: my-app
    spec:
      terminationGracePeriodSeconds: 1
      containers:
        - name: nginx
          image: vinsdocker/nginx-gke
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: my-app
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 80
---
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  terminationGracePeriodSeconds: 1
  containers:
    - name: demo
      image: vinsdocker/util
      args:
        - &quot;sleep&quot;
        - &quot;3600&quot;



kubectl apply -f 03-svc-load-balancing.yaml.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클러스터 내부에서 파드끼리 통신하기 위한 demo-app과 로드밸런싱을 위한 service, my-app을 만든다. &lt;br /&gt;이후&amp;nbsp;pod&amp;nbsp;내부에&amp;nbsp;접속한다.&lt;/p&gt;
&lt;pre id=&quot;code_1734415051841&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl exec -it demo-pod -- bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 후 요청을 보내보면 매번 다른 pod 이름을 보여주는것을 확인할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1734415082800&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 반복
root@demo-pod:/# curl my-app&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;610&quot; data-origin-height=&quot;564&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/U5Sih/btsLlHt4UNP/9FT822WmZQhtlRjaPey8y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/U5Sih/btsLlHt4UNP/9FT822WmZQhtlRjaPey8y1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/U5Sih/btsLlHt4UNP/9FT822WmZQhtlRjaPey8y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FU5Sih%2FbtsLlHt4UNP%2F9FT822WmZQhtlRjaPey8y1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;610&quot; height=&quot;564&quot; data-origin-width=&quot;610&quot; data-origin-height=&quot;564&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Service Types&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 134px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;타입&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 40px;&quot;&gt;ClusterIP&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 40px;&quot;&gt;K8S 클러스터 내부에서 통신을 위한 타입이다. 클러스터 외부에서는 접근할 수 없다. 타입을 지정하지않으면 기본값이다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 40px;&quot;&gt;NodePort&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 40px;&quot;&gt;클러스터 외부에서 K8S 마스터/노드를 통해 특정 포트를 사용해서 접근할 수 있다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;LoadBalancer&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;외부에서 들어오는 트래픽을 수신하는데 사용된다. (AWS, GCP 같은 클라우드 업체에서 사용된다.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;* 클러스터 외부의 노출은 ingress를 사용하며 이는 나중에 학습한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Kind cluster with extra port mapping&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 클러스터를 삭제하고 추가 포트매핑을 한 클러스터를 생성해보자&lt;/p&gt;
&lt;pre id=&quot;code_1734415160292&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kind delete cluster --name dev-cluster&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;아래처럼 파일을 생성하고 클러스터를 생성하자&lt;/p&gt;
&lt;pre id=&quot;code_1734415176185&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: dev-cluster
nodes:
- role: control-plane
  extraPortMappings:
    - containerPort: 30001
      hostPort: 30001
      protocol: TCP
- role: worker
- role: worker


kind create cluster --config [yaml 파일]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어를 통해 port 매핑을 확인할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1734415192932&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker ps -a 

# 결과
CONTAINER ID   IMAGE                  COMMAND                  CREATED          STATUS          PORTS
                              NAMES
6e4af28b723c   kindest/node:v1.31.2   &quot;/usr/local/bin/entr&amp;hellip;&quot;   31 seconds ago   Up 28 seconds   0.0.0.0:30001-&amp;gt;30001/tcp, 127.0.0.1:45971-&amp;gt;6443/tcp   dev-cluster-control-plane
056d4e90bc99   kindest/node:v1.31.2   &quot;/usr/local/bin/entr&amp;hellip;&quot;   31 seconds ago   Up 28 seconds
                              dev-cluster-worker
76da068e1786   kindest/node:v1.31.2   &quot;/usr/local/bin/entr&amp;hellip;&quot;   31 seconds ago   Up 28 seconds
                              dev-cluster-worker2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Nodeport - Demo&lt;/h2&gt;
&lt;pre id=&quot;code_1734415212359&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 05-nodeport-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deploy
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 3
  template:
    metadata:
      labels:
        app: my-app
    spec:
      terminationGracePeriodSeconds: 1
      containers:
        - name: nginx
          image: vinsdocker/nginx-gke
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: my-app
spec:
  type: NodePort
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30001



kubectl apply -f 05-nodeport-service.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;watch 명령어로 확인해보면 NodePort가 있는것을 확인할 수 있고 &lt;br /&gt;아래&amp;nbsp;페이지로&amp;nbsp;들어가보면&amp;nbsp;접속이&amp;nbsp;되는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;http://localhost:30001/&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Rolling Update With Service&lt;/h2&gt;
&lt;pre id=&quot;code_1734415244536&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 06-rolling-update-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service-deployment
spec:
  minReadySeconds: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 1
  selector:
    matchLabels:
      app: order-service
  replicas: 3
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service-container
          image: vinsdocker/k8s-app:v1
          ports:
            - name: &quot;app-port&quot;
              containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: my-app
spec:
  selector:
    app: order-service
  ports:
    - port: 80
      targetPort: 80
---
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  terminationGracePeriodSeconds: 1
  containers:
    - name: demo
      image: vinsdocker/util
      args:
        - &quot;sleep&quot;
        - &quot;3600&quot;
        
        
kubectl apply -f 06-rolling-update-demo.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 파일을 생성하고 접속한다.&lt;/p&gt;
&lt;pre id=&quot;code_1734415258908&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl exec -it demo-pod -- bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;이후&amp;nbsp;아래&amp;nbsp;명령어를&amp;nbsp;쳐보면&amp;nbsp;V1이&amp;nbsp;나오는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1734415266993&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for i in {1..1000}; do curl -s http://my-app | grep -o &quot;&amp;lt;title&amp;gt;[^&amp;lt;]*&quot; | tail -c+8; done&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이때&amp;nbsp;빠르게&amp;nbsp;v2로&amp;nbsp;변경하고&amp;nbsp;적용하면&amp;nbsp;V1과&amp;nbsp;V2가&amp;nbsp;섞여서&amp;nbsp;나오는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;그러다가&amp;nbsp;모두&amp;nbsp;V2로&amp;nbsp;변경되는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>Kubernetes</category>
      <category>clusterip</category>
      <category>devops</category>
      <category>k8s</category>
      <category>kubernetes</category>
      <category>nodeport</category>
      <category>service</category>
      <category>Tutorial</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/228</guid>
      <comments>https://systorage.tistory.com/entry/Kubernetes-Service#entry228comment</comments>
      <pubDate>Tue, 17 Dec 2024 15:02:39 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes] Deployment</title>
      <link>https://systorage.tistory.com/entry/Kubernetes-Deployment</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;프로덕션에서&amp;nbsp;생성하고&amp;nbsp;사용할&amp;nbsp;것은&amp;nbsp;deployment이다. &lt;br /&gt;deployment는&amp;nbsp;replicaSet을&amp;nbsp;매니징한다. &lt;br /&gt;1&amp;nbsp;deployment&amp;nbsp;당&amp;nbsp;1서비스이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Demo&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 파일을 생성 후 적용해보면 결과를 확인할 수 있다. &lt;/p&gt;
&lt;pre id=&quot;code_1734338231347&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#01-simple-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deploy
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 3
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: nginx
          image: nginx&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1734338589886&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create -f 01-simple-deploy.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;적용하면&amp;nbsp;deployment를&amp;nbsp;생성하고&amp;nbsp;해당&amp;nbsp;deployment가&amp;nbsp;replicaset을&amp;nbsp;생성하며&amp;nbsp;replicaset이&amp;nbsp;pod들을&amp;nbsp;생성하는걸&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;584&quot; data-origin-height=&quot;242&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckt7Cz/btsLlsJCpEN/DuefZ1JjGoZfuGs4kURIDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckt7Cz/btsLlsJCpEN/DuefZ1JjGoZfuGs4kURIDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckt7Cz/btsLlsJCpEN/DuefZ1JjGoZfuGs4kURIDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fckt7Cz%2FbtsLlsJCpEN%2FDuefZ1JjGoZfuGs4kURIDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;584&quot; height=&quot;242&quot; data-origin-width=&quot;584&quot; data-origin-height=&quot;242&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;kubectl&amp;nbsp;craete와&amp;nbsp;kubectl&amp;nbsp;apply의&amp;nbsp;차이점&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 86px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 39.186%; height: 17px;&quot;&gt;Command&lt;/td&gt;
&lt;td style=&quot;width: 60.814%; height: 17px;&quot;&gt;Description&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 39.186%; height: 20px;&quot;&gt;kubectl create -f [파일이름]&lt;/td&gt;
&lt;td style=&quot;width: 60.814%; height: 20px;&quot;&gt;주어진 파일로 리소스를 생성한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 29px;&quot;&gt;
&lt;td style=&quot;width: 39.186%; height: 29px;&quot;&gt;kubectl&amp;nbsp;create&amp;nbsp;-f&amp;nbsp;.&lt;/td&gt;
&lt;td style=&quot;width: 60.814%; height: 29px;&quot;&gt;현재 디렉토리에서 모든 yaml파일을 기반으로 리소스를 생성한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 39.186%; height: 20px;&quot;&gt;kubectl&amp;nbsp;create&amp;nbsp;-f&amp;nbsp;&lt;a href=&quot;http://vinsguru.com/k8s.yaml&quot;&gt;http://vinsguru.com/k8s.yaml&lt;/a&gt; &lt;/td&gt;
&lt;td style=&quot;width: 60.814%; height: 20px;&quot;&gt;주어진 url로 리소스를 생성한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 77px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 37.9069%;&quot;&gt;Command&lt;/td&gt;
&lt;td style=&quot;width: 62.0931%;&quot;&gt;Description&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 37.9069%; height: 20px;&quot;&gt;kubectl&amp;nbsp;apply&amp;nbsp;-f&amp;nbsp;[파일이름]&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 62.0931%; height: 20px;&quot;&gt;주어진 파일로 리소스를 생성/업데이트한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 37.9069%; height: 20px;&quot;&gt;kubectl&amp;nbsp;apply&amp;nbsp;-f&amp;nbsp;.&lt;/td&gt;
&lt;td style=&quot;width: 62.0931%; height: 20px;&quot;&gt;현재 디렉토리에서 모든 yaml파일을 기반으로 리소스를 생성/업데이트한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 37.9069%; height: 20px;&quot;&gt;kubectl&amp;nbsp;apply&amp;nbsp;-f&amp;nbsp;&lt;a href=&quot;http://vinsguru.com/k8s.yaml&quot;&gt;http://vinsguru.com/k8s.yaml&lt;/a&gt; &lt;/td&gt;
&lt;td style=&quot;width: 62.0931%; height: 20px;&quot;&gt;주어진&amp;nbsp;url로&amp;nbsp;리소스를&amp;nbsp;생성/업데이트한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;create는&amp;nbsp;없으면&amp;nbsp;생성&amp;nbsp;있으면&amp;nbsp;에러를&amp;nbsp;내지만 &lt;br /&gt;apply는&amp;nbsp;없으면&amp;nbsp;생성&amp;nbsp;있으면&amp;nbsp;변경사항을&amp;nbsp;적용하며,&amp;nbsp;변경사항이&amp;nbsp;없으면&amp;nbsp;무시된다. &lt;br /&gt;위&amp;nbsp;01&amp;nbsp;파일이&amp;nbsp;실행된&amp;nbsp;삭제된&amp;nbsp;상태로&amp;nbsp;아래&amp;nbsp;명령어들을&amp;nbsp;차례로&amp;nbsp;실행해보면&amp;nbsp;결과를&amp;nbsp;알&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;pre id=&quot;code_1734338747665&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 정상적으로 생성
kubectl create -f 01-simple-deploy.yaml

# 다시 실행시 에러
kubectl create -f 01-simple-deploy.yaml
=&amp;gt; Error from server (AlreadyExists): error when creating &quot;01-simple-deploy.yaml&quot;: deployments.apps &quot;my-deploy&quot; already exists

# 만들어진 deploy 삭제
kubectl delete -f 01-simple-deploy.yaml

# 새로 생성
kubectl apply -f 01-simple-deploy.yaml
=&amp;gt; deployment.apps/my-deploy created

# 변경 사항 적용 (없으면 무시) 몇번을 반복해도 같은 결과만 나온다
kubectl apply -f 01-simple-deploy.yaml
=&amp;gt; deployment.apps/my-deploy configured&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Log &amp;amp; Port forward&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kubectl get 관련 커맨드는 아래와 같다. &lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 151px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;Command&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;Description&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;kubectl&amp;nbsp;get&amp;nbsp;[kind명]&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;특정 종류의 리소스를 나열한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;kubectl&amp;nbsp;get&amp;nbsp;[kind명]&amp;nbsp;[resource-name]&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;특정 리소스를 조회한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;kubectl&amp;nbsp;get&amp;nbsp;[kind명]&amp;nbsp;--show-labels&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;라벨을 표시한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;kubectl get [kind명] -l app=my-app&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;리소스를 쿼리한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;kubectl get [kind명] -o yaml&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;출력형식을 yaml형식으로 지정한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 122px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;Command&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;Description&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;kubectl&amp;nbsp;describe&amp;nbsp;[kind]&amp;nbsp;[resource-name]&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;리소스 설명하기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;kubectl&amp;nbsp;delete&amp;nbsp;[kind]&amp;nbsp;[resource-name]&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;리소스 삭제하기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;kubectl&amp;nbsp;logs&amp;nbsp;[kind]/[resource-name]&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;로그 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;kubectl&amp;nbsp;exec&amp;nbsp;-it&amp;nbsp;[kind]/[resource-name]&amp;nbsp;&amp;ndash;&amp;nbsp;bash&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;파드 컨테이너에 접근&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;kubectl&amp;nbsp;port-forward&amp;nbsp;[kind]/[resource-name]&amp;nbsp;8080:80&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;포트포워딩 설정&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Deployment revisions&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deploy는 서비스의 버전을 관리할 수 있다. 아래 예시를 통해 확인해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734338922590&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 02-deploy-rs.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service-deployment
spec:
  selector:
    matchLabels:
      app: order-service
  replicas: 3
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service-container
          image: vinsdocker/k8s-app:v1
          ports:
            - name: &quot;app-port&quot;
              containerPort: 80&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1734338931567&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f 02-deploy-rs.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성된걸 확인후 아래 파일처럼 변경해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734338963522&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service-deployment
spec:
  selector:
    matchLabels:
      app: order-service
  replicas: 2
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service-container
          image: vinsdocker/k8s-app:v1
          ports:
            - name: &quot;app-port&quot;
              containerPort: 80&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1734338970597&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f 02-deploy-rs.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;이렇게&amp;nbsp;진행하면&amp;nbsp;레플리카셋을&amp;nbsp;2개로&amp;nbsp;변경한다&amp;nbsp;컨테이너&amp;nbsp;스펙을&amp;nbsp;변경&amp;nbsp;해야&amp;nbsp;새로운&amp;nbsp;변경으로&amp;nbsp;감지&amp;nbsp;한다. &lt;br /&gt;이제&amp;nbsp;v2로&amp;nbsp;변경해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734338989592&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service-deployment
spec:
  selector:
    matchLabels:
      app: order-service
  replicas: 2
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service-container
          image: vinsdocker/k8s-app:v2
          ports:
            - name: &quot;app-port&quot;
              containerPort: 80

# 적용
kubectl apply -f 02-deploy-rs.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;명령어를&amp;nbsp;치고&amp;nbsp;확인해보면&amp;nbsp;새로운&amp;nbsp;레플리카셋이&amp;nbsp;생기고&amp;nbsp;기존&amp;nbsp;레플리카셋의&amp;nbsp;ready&amp;nbsp;갯수는&amp;nbsp;0인걸&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;&lt;br /&gt;이번에는&amp;nbsp;환경변수를&amp;nbsp;변경해보자 &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1734339006137&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service-deployment
spec:
  selector:
    matchLabels:
      app: order-service
  replicas: 2
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service-container
          image: vinsdocker/k8s-app:v2
          env:
            - name: DUMMY
              value: &quot;8&quot;
          ports:
            - name: &quot;app-port&quot;
              containerPort: 80

# 적용
 kubectl apply -f 02-deploy-rs.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변경 사항을 적용해보면 또 새로운 레플리카 셋이 생길 수 있다. &lt;br /&gt;이로&amp;nbsp;인해&amp;nbsp;알&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;사실은&amp;nbsp;컨테이너&amp;nbsp;동작에&amp;nbsp;새로운&amp;nbsp;변경&amp;nbsp;사항이&amp;nbsp;생기면&amp;nbsp;레플리카셋을&amp;nbsp;새로&amp;nbsp;생성하지만&amp;nbsp;레플리카셋의&amp;nbsp;갯수만&amp;nbsp;변경하면&amp;nbsp;단순히&amp;nbsp;pod의&amp;nbsp;갯수만&amp;nbsp;변경되는걸&amp;nbsp;확인할&amp;nbsp;수있다. &lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Rollout history&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 파일을 생성한 후 적용하고 포트 포워딩을 설정해주자. &lt;/p&gt;
&lt;pre id=&quot;code_1734339043056&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service-deployment
spec:
  selector:
    matchLabels:
      app: order-service
  replicas: 2
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service-container
          image: vinsdocker/k8s-app:v1
          ports:
            - name: &quot;app-port&quot;
              containerPort: 80

# 적용
kubectl apply -f 03-deploy-rollout.yaml
# 포트포워딩
kubectl port-forward deploy/order-service-deployment 8080:80&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 localhost:8080으로 접속해보면 V1 화면이 나오는 걸 확인할 수 있다. &lt;br /&gt;&lt;br /&gt;이제&amp;nbsp;v2&amp;nbsp;로&amp;nbsp;버젼을&amp;nbsp;바꿔서&amp;nbsp;진행해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734339061587&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service-deployment
spec:
  selector:
    matchLabels:
      app: order-service
  replicas: 2
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service-container
          image: vinsdocker/k8s-app:v2
          ports:
            - name: &quot;app-port&quot;
              containerPort: 80


kubectl apply -f 03-deploy-rollout.yaml
kubectl port-forward deploy/order-service-deployment 8080:80&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;이&amp;nbsp;후&amp;nbsp;다시&amp;nbsp;브라우저로&amp;nbsp;들어간&amp;nbsp;후&amp;nbsp;새로고칭하면&amp;nbsp;V2&amp;nbsp;화면이&amp;nbsp;나오는&amp;nbsp;것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;&lt;br /&gt;이제&amp;nbsp;터미널에서&amp;nbsp;아래&amp;nbsp;명령어를&amp;nbsp;입력한다. &lt;/p&gt;
&lt;pre id=&quot;code_1734339071372&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl rollout history deploy&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;그럼&amp;nbsp;2가지&amp;nbsp;수정본이&amp;nbsp;나오는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ooVA3/btsLleriFND/IJVtl2nEkaQaKEvwVBxa00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ooVA3/btsLleriFND/IJVtl2nEkaQaKEvwVBxa00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ooVA3/btsLleriFND/IJVtl2nEkaQaKEvwVBxa00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FooVA3%2FbtsLleriFND%2FIJVtl2nEkaQaKEvwVBxa00%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;112&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;112&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;그럼&amp;nbsp;이제&amp;nbsp;containers의&amp;nbsp;버전을&amp;nbsp;3로&amp;nbsp;바꾸고&amp;nbsp;다시&amp;nbsp;적용해보자 &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1734339085175&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;        # 생략
          image: vinsdocker/k8s-app:v3
        # 생략

 kubectl apply -f 03-deploy-rollout.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;다시&amp;nbsp;&amp;nbsp;kubectl rollout history deploy로 확인해보면 3개의 버전이 있는것을 확인할 수 있다. &lt;br /&gt;&lt;br /&gt;이제&amp;nbsp;port-forward를&amp;nbsp;한&amp;nbsp;후&amp;nbsp;localhost:8080으로&amp;nbsp;접속하면&amp;nbsp;V3&amp;nbsp;화면이&amp;nbsp;뜨는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;&lt;br /&gt;이제&amp;nbsp;롤백을&amp;nbsp;진행해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734339102969&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 이전 버전으로 돌아간다.
kubectl rollout undo deploy/order-service-deployment&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;다시&amp;nbsp;port-forward를&amp;nbsp;한&amp;nbsp;후&amp;nbsp;localhost:8080으로&amp;nbsp;접속하면&amp;nbsp;V2&amp;nbsp;화면이&amp;nbsp;뜨는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;342&quot; data-origin-height=&quot;183&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLqMd7/btsLlIFDwCj/ipFvLHBMYTa6fqOYrRqfe1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLqMd7/btsLlIFDwCj/ipFvLHBMYTa6fqOYrRqfe1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLqMd7/btsLlIFDwCj/ipFvLHBMYTa6fqOYrRqfe1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLqMd7%2FbtsLlIFDwCj%2FipFvLHBMYTa6fqOYrRqfe1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;342&quot; height=&quot;183&quot; data-origin-width=&quot;342&quot; data-origin-height=&quot;183&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;다시&amp;nbsp;history를&amp;nbsp;확인해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734339116062&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl rollout history deploy
# 결과
deployment.apps/order-service-deployment
REVISION  CHANGE-CAUSE
1         &amp;lt;none&amp;gt;
3         &amp;lt;none&amp;gt;
4         &amp;lt;none&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;다시&amp;nbsp;같은&amp;nbsp;명령을&amp;nbsp;실행한다 &lt;/p&gt;
&lt;pre id=&quot;code_1734339126176&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl rollout undo deploy/order-service-deployment&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포트포워딩 적용 후 확인해보면 version3로 돌아간것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Rollback&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 정의는 그대로 두고 새로 v1 부터 시작한다 &lt;br /&gt;또한&amp;nbsp;annotations을&amp;nbsp;추가하자 &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1734339149931&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service-deployment
  annotations:
    kubernetes.io/change-cause: &quot;deploying v1&quot;
spec:
  selector:
    matchLabels:
      app: order-service
  replicas: 2
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service-container
          image: vinsdocker/k8s-app:v1
          ports:
            - name: &quot;app-port&quot;
              containerPort: 80&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제&amp;nbsp;이전&amp;nbsp;deploy를&amp;nbsp;삭제하고&amp;nbsp;적용해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734340173073&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f 03-deploy-rollout.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;다시&amp;nbsp;히스토리를&amp;nbsp;확인해보면&amp;nbsp;CHANGE-CAUSE가&amp;nbsp;바뀐것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;pre id=&quot;code_1734340184508&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl rollout history deploy

# 결과
REVISION  CHANGE-CAUSE
1         deploying v1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제&amp;nbsp;위&amp;nbsp;작업에서&amp;nbsp;컨테이너를&amp;nbsp;v2&amp;nbsp;로&amp;nbsp;변경하고&amp;nbsp;annotaions도&amp;nbsp;v2로&amp;nbsp;변경&amp;nbsp;후&amp;nbsp;다시&amp;nbsp;확인하면&amp;nbsp;아래와&amp;nbsp;같다 &lt;/p&gt;
&lt;pre id=&quot;code_1734340195453&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl rollout history deploy

# 결과
REVISION  CHANGE-CAUSE
1         deploying v1
2         deploying v2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제&amp;nbsp;위&amp;nbsp;작업에서&amp;nbsp;컨테이너를&amp;nbsp;v3&amp;nbsp;로&amp;nbsp;변경하고&amp;nbsp;annotaions도&amp;nbsp;v3로&amp;nbsp;변경&amp;nbsp;후&amp;nbsp;적용하자 &lt;/p&gt;
&lt;pre id=&quot;code_1734340205580&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#결과
REVISION  CHANGE-CAUSE
1         deploying v1
2         deploying v2
3         deploying v3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이전&amp;nbsp;섹션에서&amp;nbsp;3인&amp;nbsp;상태에서&amp;nbsp;undo를&amp;nbsp;실행하면&amp;nbsp;v2로&amp;nbsp;가고&amp;nbsp;v2에서&amp;nbsp;undo를&amp;nbsp;실행하면&amp;nbsp;v3로&amp;nbsp;돌아갔다. &lt;br /&gt;1로&amp;nbsp;돌아가보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734340218385&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl rollout undo deploy/order-service-deployment --to-revision=1

kubectl rollout history deploy

# 결과
REVISION  CHANGE-CAUSE
2         deploying v2
3         deploying v3
4         deploying v1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Checking Rollout Changes&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 정보만 보면 헷갈릴수 있다. &lt;br /&gt;아래&amp;nbsp;명령어를&amp;nbsp;통해&amp;nbsp;자세히&amp;nbsp;알&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;pre id=&quot;code_1734340244472&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl rollout history deploy --revision=[번호]
ex) kubectl rollout history deploy --revision=4

#결과
deployment.apps/order-service-deployment with revision #4
Pod Template:
  Labels:       app=order-service
        pod-template-hash=56864789dc
  Annotations:  kubernetes.io/change-cause: deploying v1
  Containers:
   order-service-container:
    Image:      vinsdocker/k8s-app:v1
    Port:       80/TCP
    Host Port:  0/TCP
    Environment:        &amp;lt;none&amp;gt;
    Mounts:     &amp;lt;none&amp;gt;
  Volumes:      &amp;lt;none&amp;gt;
  Node-Selectors:       &amp;lt;none&amp;gt;
  Tolerations:  &amp;lt;none&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Min ready Seconds (최소 준비 시간)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 애플리케이션이 실행되는데는 시간이 걸린다. &lt;br /&gt;이&amp;nbsp;때&amp;nbsp;실제로&amp;nbsp;걸리는&amp;nbsp;시간을&amp;nbsp;deploy&amp;nbsp;yaml&amp;nbsp;파일에&amp;nbsp;정의해&amp;nbsp;둘&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;원래는&amp;nbsp;heath&amp;nbsp;check,&amp;nbsp;Probe등으로&amp;nbsp;확인하며&amp;nbsp;이&amp;nbsp;방법은&amp;nbsp;하드&amp;nbsp;코딩해서&amp;nbsp;알려주는&amp;nbsp;방법이다. &lt;/p&gt;
&lt;pre id=&quot;code_1734340267027&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 04-min-ready-seconds.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deploy
spec:
  minReadySeconds: 10
  selector:
    matchLabels:
      app: my-app
  replicas: 3
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: nginx
          image: nginx&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1734340284450&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f 04-min-ready-seconds.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;적용후&amp;nbsp;watch로&amp;nbsp;확인해보면&amp;nbsp;deploy의&amp;nbsp;AVAILABLE이&amp;nbsp;10초&amp;nbsp;뒤에&amp;nbsp;활성화&amp;nbsp;되는것을&amp;nbsp;확인&amp;nbsp;할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배포 전략&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 version1에서 version2를 배포하고 싶다고 할 때 변경사항을 어떻게 적용할건지를 정의한다. &lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 128px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;전략&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;설명&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot; rowspan=&quot;3&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 40px;&quot;&gt;recreate&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 40px;&quot;&gt;기존 파드를 종료하고 새로운 파드를 생성합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;rolling&amp;nbsp;update&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;변경 사항을 점진적으로 배포합니다. 기존 파드와 새로운 파드가 일시적으로 혼합될 수 있습니다. 아래 속성 들은 0 또는 %가 될 수 있다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot; rowspan=&quot;3&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;속성&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;maxSurge&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;생성할 수 있는 추가 파드의 최대 수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;maxUnavailable&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;종료할 수 있는 파드의 최대 수&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;recreate 전략&lt;/h2&gt;
&lt;pre id=&quot;code_1734340406669&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 05-deploy-recreate.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service-deployment
  annotations:
    kubernetes.io/change-cause: &quot;deploying v1&quot;
spec:
  minReadySeconds: 10
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: order-service
  replicas: 2
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service-container
          image: vinsdocker/k8s-app:v1
          ports:
            - name: &quot;app-port&quot;
              containerPort: 80
              
              
# 적용
kubectl apply -f 05-deploy-recreate.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;위&amp;nbsp;파일을&amp;nbsp;정의&amp;nbsp;한&amp;nbsp;후&amp;nbsp;실행한다. &lt;br /&gt;&lt;br /&gt;이&amp;nbsp;후&amp;nbsp;아래&amp;nbsp;파일처럼&amp;nbsp;변경하고&amp;nbsp;다시&amp;nbsp;apply&amp;nbsp;해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734340428895&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service-deployment
spec:
  minReadySeconds: 10
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: order-service
  replicas: 3
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service-container
          image: vinsdocker/k8s-app:v2
          ports:
            - name: &quot;app-port&quot;
              containerPort: 80

# 적용
kubectl apply -f 05-deploy-recreate.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확인해보면 먼저 존재하던 모든 파드들이 삭제되고 새로운 파드들이 새로 한번에 생기는걸 확인할 수 있다. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Rolling update - maxSurge&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 파일을 생성 후 실행해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734340452050&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 06-deploy-max-surge.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service-deployment
spec:
  minReadySeconds: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: &quot;100%&quot;
  selector:
    matchLabels:
      app: order-service
  replicas: 3
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service-container
          image: vinsdocker/k8s-app:v1
          ports:
            - name: &quot;app-port&quot;
              containerPort: 80


kubectl apply -f 06-deploy-max-surge.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;pod&amp;nbsp;3개가&amp;nbsp;켜진것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;이제&amp;nbsp;이미지를&amp;nbsp;v2로&amp;nbsp;바꿔보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734340470697&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
image: vinsdocker/k8s-app:v2
...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이후&amp;nbsp;실행을&amp;nbsp;해보면&amp;nbsp;순간적으로&amp;nbsp;파드가&amp;nbsp;6개가&amp;nbsp;되는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;671&quot; data-origin-height=&quot;294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/33fWi/btsLjGvZWRq/l8M1wYAxdYfqwFkGO8GplK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/33fWi/btsLjGvZWRq/l8M1wYAxdYfqwFkGO8GplK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/33fWi/btsLjGvZWRq/l8M1wYAxdYfqwFkGO8GplK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F33fWi%2FbtsLjGvZWRq%2Fl8M1wYAxdYfqwFkGO8GplK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;671&quot; height=&quot;294&quot; data-origin-width=&quot;671&quot; data-origin-height=&quot;294&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제 v3를 maxSurge 1 로 변경한 후 적용해보자&lt;/p&gt;
&lt;pre id=&quot;code_1734340482354&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
...
image: vinsdocker/k8s-app:v3
...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제&amp;nbsp;결과를&amp;nbsp;살펴보면&amp;nbsp;하나씩&amp;nbsp;파드가&amp;nbsp;교체되는&amp;nbsp;과정을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Rolling update - maxUnavailable&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 생성하고 실행해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1734340538763&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 07-deploy-max-unavailable.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service-deployment
spec:
  minReadySeconds: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 1
  selector:
    matchLabels:
      app: order-service
  replicas: 3
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service-container
          image: vinsdocker/k8s-app:v1
          ports:
            - name: &quot;app-port&quot;
              containerPort: 80


kubectl apply -f 07-deploy-max-unavailable.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v2로 변경한 후 실행해보면 하나씩 변경되는것을 확인할 수 있다 &lt;/p&gt;</description>
      <category>Kubernetes</category>
      <category>Application Deployment</category>
      <category>cloud</category>
      <category>container</category>
      <category>Deployment</category>
      <category>devops</category>
      <category>k8s</category>
      <category>kubernetes</category>
      <category>orchestration</category>
      <category>Scalability</category>
      <category>YAML</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/227</guid>
      <comments>https://systorage.tistory.com/entry/Kubernetes-Deployment#entry227comment</comments>
      <pubDate>Mon, 16 Dec 2024 18:16:54 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes] ReplicaSet</title>
      <link>https://systorage.tistory.com/entry/Kubernetes-ReplicaSet</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;ReplicaSet은 Pod를 매니징한다. &lt;br /&gt;예를 들어 nginx pod가 3개 있어야 한다고 하면 3개의 nginx pod를 유지한다. &lt;br /&gt;replicaSet의 restartPolicy는 always이며 바꿀수 없다. &lt;br /&gt;&lt;br /&gt;예를들어&amp;nbsp;아래&amp;nbsp;그림에서&amp;nbsp;노드2가&amp;nbsp;갑자기&amp;nbsp;죽었을때&amp;nbsp;pod의&amp;nbsp;개수를&amp;nbsp;유지하기&amp;nbsp;위해&amp;nbsp;다른&amp;nbsp;노드에&amp;nbsp;pod를&amp;nbsp;띄운다. &lt;br /&gt;직접적으로 생성하는건 프로덕션 레벨에서는 권장되지 않으며 Deployment가 ReplicaSet을 관리한다.&lt;br /&gt;이&amp;nbsp;글에서는&amp;nbsp;무엇을&amp;nbsp;관리해야하는지&amp;nbsp;명확히&amp;nbsp;하기&amp;nbsp;위해&amp;nbsp;metadata.labels를&amp;nbsp;사용한다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;237&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ddGSxK/btsLfw0xgod/trzHhhlILUOx3Y4GXEJH1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ddGSxK/btsLfw0xgod/trzHhhlILUOx3Y4GXEJH1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ddGSxK/btsLfw0xgod/trzHhhlILUOx3Y4GXEJH1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FddGSxK%2FbtsLfw0xgod%2FtrzHhhlILUOx3Y4GXEJH1k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;486&quot; height=&quot;237&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;237&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ReplicaSet 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주요 레퍼런스는 아래 링크에서 참고할 수 있다. &lt;br /&gt;&lt;a href=&quot;https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/replica-set-v1/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/replica-set-v1/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1733963381109&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 01-simple-rs.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: my-rs
spec:
  selector:
    # 맞는 레이블을 찾는다 (여러개가 가능하다)
    matchLabels:
      app: my-app
  # pod를 몇개로 유지할 것인지
  replicas: 3
  # pod의 개수가 맞지 않으면 기본적으로 실행할 pod의 내용
  template:
    metadata:
      name: my-pod
      labels:
        app: my-app
    spec:
      containers:
        - name: nginx
          image: nginx&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;kubectl&amp;nbsp;get&amp;nbsp;replicaset&amp;nbsp;명령어를&amp;nbsp;통해&amp;nbsp;replicaset을&amp;nbsp;가져올&amp;nbsp;수&amp;nbsp;있다(kubectl&amp;nbsp;get&amp;nbsp;rs로도&amp;nbsp;가능) &lt;br /&gt;kubectl&amp;nbsp;get&amp;nbsp;all&amp;nbsp;명령어를&amp;nbsp;통해&amp;nbsp;감시하자&lt;/p&gt;
&lt;pre id=&quot;code_1733963420016&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;watch -t -x kubectl get all&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제&amp;nbsp;아래&amp;nbsp;명령어를&amp;nbsp;실행해보면&amp;nbsp;pod가&amp;nbsp;3개&amp;nbsp;실행되는걸&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;pre id=&quot;code_1733963430967&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create -f 01-simple-rs.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;604&quot; data-origin-height=&quot;228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IDjif/btsLgGOqniG/dF4WuykVI9jl0sqzPDkXx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IDjif/btsLgGOqniG/dF4WuykVI9jl0sqzPDkXx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IDjif/btsLgGOqniG/dF4WuykVI9jl0sqzPDkXx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIDjif%2FbtsLgGOqniG%2FdF4WuykVI9jl0sqzPDkXx0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;604&quot; height=&quot;228&quot; data-origin-width=&quot;604&quot; data-origin-height=&quot;228&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이 때 템플릿&amp;nbsp;쪽의&amp;nbsp;metadata에&amp;nbsp;정의한대로&amp;nbsp;name이&amp;nbsp;생성되지&amp;nbsp;않는것을&amp;nbsp;알&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;pre id=&quot;code_1733963455258&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
template:
    metadata:
      name: my-pod
...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 하나를 삭제해보면 컨테이너가 삭제되고 즉시 다른 컨테이너가 확인되는걸 확인할 수있다. &lt;br /&gt;또는&amp;nbsp;모든&amp;nbsp;컨테이너를&amp;nbsp;삭제해도&amp;nbsp;모든&amp;nbsp;컨테이너가&amp;nbsp;다시&amp;nbsp;실행되는걸&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;pre id=&quot;code_1733963540934&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl delete pod --all&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;마지막으로 아래 명령어를 통해 replicaSet을 삭제하면 replicaSet 과 replicaSet이 관리하는 모든 pod들이 사라진다.&lt;/p&gt;
&lt;pre id=&quot;code_1733963551561&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl delete -f 01-simple-rs.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기존에 존재하는 pod와 replicaSet&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미존재하는 pod에 replicaSet을 적용해보자 &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1733963578752&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 02-multiple-pods.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-1
  labels:
    team: team-a
spec:
  containers:
    - name: nginx
      image: nginx
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-2
  labels:
    team: team-a
spec:
  containers:
    - name: nginx
      image: nginx
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-3
  labels:
    team: team-a
spec:
  containers:
    - name: nginx
      image: nginx&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1733963603059&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 03-existing-pod-manager.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: my-rs
spec:
  selector:
    matchLabels:
      team: team-a
  replicas: 2
  template:
    metadata:
      labels:
        team: team-a
    spec:
      containers:
        - name: nginx
          image: nginx&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;위&amp;nbsp;두&amp;nbsp;파일을&amp;nbsp;생성한&amp;nbsp;후&amp;nbsp;02&amp;nbsp;번을&amp;nbsp;실행한다.&lt;/p&gt;
&lt;pre id=&quot;code_1733963623220&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create -f 02-multiple-pods.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제&amp;nbsp;pod가&amp;nbsp;3개&amp;nbsp;생성되었다. &lt;br /&gt;이제 03번을 적용해보자&lt;/p&gt;
&lt;pre id=&quot;code_1733963640459&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create -f 03-existing-pod-manager.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 파드를 확인해보면 하나가 종료되고 2개만 남아있는것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;199&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A6Zre/btsLemYRwEa/u9c7n5HJaJIvLerpFuodmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A6Zre/btsLemYRwEa/u9c7n5HJaJIvLerpFuodmK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A6Zre/btsLemYRwEa/u9c7n5HJaJIvLerpFuodmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA6Zre%2FbtsLemYRwEa%2Fu9c7n5HJaJIvLerpFuodmK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;596&quot; height=&quot;199&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;199&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;추가로&amp;nbsp;남은&amp;nbsp;파드중&amp;nbsp;하나를&amp;nbsp;지워보면&amp;nbsp;03번에&amp;nbsp;정의된&amp;nbsp;my-rs이름으로&amp;nbsp;pod가&amp;nbsp;새로&amp;nbsp;생성되는걸&amp;nbsp;확인&amp;nbsp;할&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;pre id=&quot;code_1733963672822&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; kubectl delete pod/pod-2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;183&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xtxiQ/btsLfDrBTka/NtnalkxoMoAewV3eDx3gW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xtxiQ/btsLfDrBTka/NtnalkxoMoAewV3eDx3gW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xtxiQ/btsLfDrBTka/NtnalkxoMoAewV3eDx3gW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxtxiQ%2FbtsLfDrBTka%2FNtnalkxoMoAewV3eDx3gW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;596&quot; height=&quot;183&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;183&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Multiple ReplicaSet&lt;/h2&gt;
&lt;pre id=&quot;code_1733963972392&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 04-multiple-rs.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: my-rs-1
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 2
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: nginx
          image: nginx
---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: my-rs-2
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 2
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: nginx
          image: nginx&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;---을&amp;nbsp;기준으로&amp;nbsp;아래를&amp;nbsp;전부&amp;nbsp;주석처리&amp;nbsp;한&amp;nbsp;후&amp;nbsp;실행해보자.&lt;/p&gt;
&lt;pre id=&quot;code_1733963983254&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: my-rs-1
spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 2
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: nginx
          image: nginx
#---
#apiVersion: apps/v1
#kind: ReplicaSet
#metadata:
#  name: my-rs-2
#spec:
#  selector:
#    matchLabels:
#      app: my-app
#  replicas: 2
#  template:
#    metadata:
#      labels:
#        app: my-app
#    spec:
#      containers:
#        - name: nginx
#          image: nginx&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1733964003963&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create -f 04-multiple-rs.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;그럼&amp;nbsp;이제&amp;nbsp;rs-1의&amp;nbsp;replicaset은&amp;nbsp;실행되어&amp;nbsp;있는&amp;nbsp;상태이다. &lt;br /&gt;&lt;br /&gt;이제 주석을 해제하고 다시 실행해보자&lt;/p&gt;
&lt;pre id=&quot;code_1733964021561&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create -f 04-multiple-rs.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;그럼&amp;nbsp;my-rs-1은&amp;nbsp;이미&amp;nbsp;존재해서&amp;nbsp;에러가&amp;nbsp;나고&amp;nbsp;my-rs-2는&amp;nbsp;추가로&amp;nbsp;생성되는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVcUPz/btsLfVFtdEw/yQy5pXKk4ZIRzsML07fJq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVcUPz/btsLfVFtdEw/yQy5pXKk4ZIRzsML07fJq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVcUPz/btsLfVFtdEw/yQy5pXKk4ZIRzsML07fJq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVcUPz%2FbtsLfVFtdEw%2FyQy5pXKk4ZIRzsML07fJq0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;902&quot; height=&quot;341&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;341&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Describing replicaset&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어를 통해 replicaset에 대한 세부 정보를 볼 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1733964078112&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl describe rs/[rs이름]
ex) kubectl describe rs/my-rs-1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d6slgP/btsLerTeB0r/aLmEqjGaJBoQNNLCCTZNnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d6slgP/btsLerTeB0r/aLmEqjGaJBoQNNLCCTZNnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d6slgP/btsLerTeB0r/aLmEqjGaJBoQNNLCCTZNnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd6slgP%2FbtsLerTeB0r%2FaLmEqjGaJBoQNNLCCTZNnk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;647&quot; height=&quot;420&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;420&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ReplicaSet Match Expressions&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이도 가능하다. 하지만 실제 production level에서는 간단하게 사용하기 때문에 가능하다고 알아만 두자.&lt;/p&gt;
&lt;pre id=&quot;code_1733964109802&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spec:
  selector:
    matchLabels:
    - key: &quot;team&quot;
      operator: In
      values: [&quot;team-a&quot;, &quot;team-b&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Kubernetes</category>
      <category>k8s</category>
      <category>kubernetes</category>
      <category>replicaset</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/226</guid>
      <comments>https://systorage.tistory.com/entry/Kubernetes-ReplicaSet#entry226comment</comments>
      <pubDate>Thu, 12 Dec 2024 09:45:43 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes] Pod 기초 - 2</title>
      <link>https://systorage.tistory.com/entry/Kubernetes-Pod-%EA%B8%B0%EC%B4%88-2</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Pod&amp;nbsp;args&amp;nbsp;-&amp;nbsp;Exec&amp;nbsp;Form &lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;args&amp;nbsp;를&amp;nbsp;사용하면&amp;nbsp;docker&amp;nbsp;container에&amp;nbsp;인수를&amp;nbsp;전달할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;&lt;br /&gt;06-pod-args.yaml &lt;/p&gt;
&lt;pre id=&quot;code_1733465708496&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  restartPolicy: Never
  containers:
    - name: ubuntu
      image: ubuntu
#      이 방법도 가능하고 아래 방법도 가능하다
#      args: [&quot;date&quot;]
      args:
      - &quot;date&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Pod container logs &lt;/h2&gt;
&lt;pre id=&quot;code_1733465727559&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl logs [파드 이름]
ex) kubectl logs my-pod&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Pod args - shell form&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker 내부에 bash로 진입해서 shell 명령어를 실행하는 방법을 pod&amp;nbsp;정의&amp;nbsp;yaml&amp;nbsp;파일에서&amp;nbsp;정의한다. &lt;br /&gt;&lt;br /&gt;07-pod-shell-args.yaml&lt;/p&gt;
&lt;pre id=&quot;code_1733465772890&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  restartPolicy: Never
  containers:
    - name: ubuntu
      image: ubuntu
      args:
      - &quot;/bin/sh&quot;
      - &quot;-c&quot;
      - &quot;echo This is my path: $PATH&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 파드를 실행하고 로그를 확인해보면 yaml에 정의한 쉘 명령어가 실행된것을 확인할 수 있다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;578&quot; data-origin-height=&quot;148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Nj9Mm/btsLapzZEVI/PEACmhjWZqc7flg6j2RIJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Nj9Mm/btsLapzZEVI/PEACmhjWZqc7flg6j2RIJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Nj9Mm/btsLapzZEVI/PEACmhjWZqc7flg6j2RIJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNj9Mm%2FbtsLapzZEVI%2FPEACmhjWZqc7flg6j2RIJ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;578&quot; height=&quot;148&quot; data-origin-width=&quot;578&quot; data-origin-height=&quot;148&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Termination Grace Period&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pod의 종료 과정에서 kubelet이 컨테이너에게 종료 명령을 보내서 안전한 종료를 유도한다. &lt;br /&gt;하지만&amp;nbsp;때로는&amp;nbsp;pod가&amp;nbsp;실제로&amp;nbsp;반응하지&amp;nbsp;않는&amp;nbsp;절전&amp;nbsp;모드에&amp;nbsp;들어갈&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;그래서&amp;nbsp;k8s는&amp;nbsp;기본적으로&amp;nbsp;30초동안&amp;nbsp;기다린&amp;nbsp;후&amp;nbsp;pod&amp;nbsp;를&amp;nbsp;삭제한다. &lt;br /&gt;이&amp;nbsp;값을&amp;nbsp;변경할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;&lt;br /&gt;08-pod-termination-garce-period.yaml &lt;/p&gt;
&lt;pre id=&quot;code_1733465835881&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  restartPolicy: Never
  containers:
    - name: ubuntu
      image: ubuntu
      args:
      - &quot;sleep&quot;
      - &quot;3600&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;해당&amp;nbsp;pod를&amp;nbsp;정의하고&amp;nbsp;실행후&amp;nbsp;삭제해보면&amp;nbsp;Status가&amp;nbsp;Terminating으로&amp;nbsp;변경되고 &lt;br /&gt;30초&amp;nbsp;후에&amp;nbsp;해당&amp;nbsp;pod가&amp;nbsp;삭제되는걸&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;이&amp;nbsp;때&amp;nbsp;terminationGracePeriodSeconds&amp;nbsp;를&amp;nbsp;사용해서&amp;nbsp;종료되는&amp;nbsp;시간을&amp;nbsp;변경할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;pre id=&quot;code_1733465859055&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  restartPolicy: Never
  # 이 부분을 추가한다.
  terminationGracePeriodSeconds: 1
  containers:
    - name: ubuntu
      image: ubuntu
      args:
      - &quot;sleep&quot;
      - &quot;3600&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 pod 를실행하고 삭제해보면 &lt;br /&gt;1초&amp;nbsp;후&amp;nbsp;바로&amp;nbsp;pod가&amp;nbsp;삭제되는걸&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Pod command&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker의 entrypoint가 정의되어있으면 기존 args로 명령을 내려도 반응이 없다. &lt;br /&gt;&lt;br /&gt;09-pod-command.yaml &lt;/p&gt;
&lt;pre id=&quot;code_1733465897842&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  restartPolicy: Never
  containers:
    - name: entrypoint
      image: vinsdocker/k8s-entrypoint
      args:
        - &quot;date&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 pod를 정의하고 실행해서 로그를 확인해보자&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;472&quot; data-origin-height=&quot;163&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dTMOxW/btsK9XKuthC/9SmROa31bRDq4wfIPL1dK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dTMOxW/btsK9XKuthC/9SmROa31bRDq4wfIPL1dK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dTMOxW/btsK9XKuthC/9SmROa31bRDq4wfIPL1dK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdTMOxW%2FbtsK9XKuthC%2F9SmROa31bRDq4wfIPL1dK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;472&quot; height=&quot;163&quot; data-origin-width=&quot;472&quot; data-origin-height=&quot;163&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;date 명령어가 제대로 실행되지 않은것을 확인할 수 있다. &lt;br /&gt;command를 사용해서 명령어를 재정의할 수 있다. &lt;/p&gt;
&lt;pre id=&quot;code_1733467806138&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  restartPolicy: Never
  containers:
    - name: entrypoint
      image: vinsdocker/k8s-entrypoint
      command:
        - &quot;date&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;yaml 파일을 변경하고 다시 실행해서 로그를 확인해보면 재정의가 된 것을 확인할 수 있다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p5QBg/btsK9Uty0F0/Vr83lr1Gf89GJsQ6bx3jR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p5QBg/btsK9Uty0F0/Vr83lr1Gf89GJsQ6bx3jR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p5QBg/btsK9Uty0F0/Vr83lr1Gf89GJsQ6bx3jR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp5QBg%2FbtsK9Uty0F0%2FVr83lr1Gf89GJsQ6bx3jR0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;456&quot; height=&quot;158&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Environment variable&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pod yaml을 통해 생성하는 docker 컨테이너에 환경 변수를 전달하는 방법을 알아보자 &lt;br /&gt;몇가지&amp;nbsp;방법이&amp;nbsp;더&amp;nbsp;있지만&amp;nbsp;가장&amp;nbsp;기본적인&amp;nbsp;방법을&amp;nbsp;소개한다. &lt;br /&gt;env를 통해서 전달할 수 있다. &lt;br /&gt;&lt;br /&gt;10-pod-env.yaml &lt;/p&gt;
&lt;pre id=&quot;code_1733467839527&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  restartPolicy: Never
  containers:
    - name: ubuntu
      image: ubuntu
      env:
        - name: &quot;request.timeout&quot;
          value: &quot;10ms&quot;
        - name: &quot;spring.profiles.active&quot;
          value: &quot;dev&quot;
      args:
        - &quot;env&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 pod를 실행하고 로그를 확인해보면 &lt;br /&gt;정상적으로&amp;nbsp;환경&amp;nbsp;변수들이&amp;nbsp;전달된&amp;nbsp;것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;284&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csj3p5/btsLaIFTDsj/7P4YLbtyYHY8801dKPe9Tk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csj3p5/btsLaIFTDsj/7P4YLbtyYHY8801dKPe9Tk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csj3p5/btsLaIFTDsj/7P4YLbtyYHY8801dKPe9Tk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcsj3p5%2FbtsLaIFTDsj%2F7P4YLbtyYHY8801dKPe9Tk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;493&quot; height=&quot;284&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;284&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Exploring Pod Container&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원격 클러스터에서 실행중인 Pod에 접근하는 방법을 설명한다. &lt;br /&gt;&lt;br /&gt;기존에&amp;nbsp;생성했던&amp;nbsp;01&amp;nbsp;pod&amp;nbsp;를&amp;nbsp;실행&amp;nbsp;시키고&amp;nbsp;내부로&amp;nbsp;접근해보자 &lt;/p&gt;
&lt;pre id=&quot;code_1733467915928&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 파드 실행
 kubectl create -f 01-simple-pod.yaml
# 파드 내부 컨테이너에 bash 쉘로 접속
 kubectl exec -it my-pod -- bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내부 쉘로 접근 후 아래 명령어를 통해 내부 컨테이너에 접속한 것을 확인할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1733467929684&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 폴더 구조 보기
ls
# nginx container 이므로 curl 명령어를 통해 확인
curl localhost&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가가기&amp;nbsp;위해선&amp;nbsp;exit를&amp;nbsp;입력하면&amp;nbsp;된다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;747&quot; data-origin-height=&quot;565&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcA2rB/btsLajNtDWx/CAp1gkKK4Beq7G1GmdjMpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcA2rB/btsLajNtDWx/CAp1gkKK4Beq7G1GmdjMpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcA2rB/btsLajNtDWx/CAp1gkKK4Beq7G1GmdjMpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcA2rB%2FbtsLajNtDWx%2FCAp1gkKK4Beq7G1GmdjMpk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;747&quot; height=&quot;565&quot; data-origin-width=&quot;747&quot; data-origin-height=&quot;565&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Multi Container Pod - 1&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지는 yaml 파일을 생성해서 하나의 컨테이너만 생성을 했다. &lt;br /&gt;이&amp;nbsp;부분에서는&amp;nbsp;여러개의&amp;nbsp;컨테이너를&amp;nbsp;생성해보자 &lt;br /&gt;&lt;br /&gt;11-multi-containers.yaml&lt;/p&gt;
&lt;pre id=&quot;code_1733467977331&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: nginx-1
      image: nginx
    - name: nginx-2
      image: nginx&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이처럼&amp;nbsp;입력하고&amp;nbsp;실행&amp;nbsp;후&amp;nbsp;확인해보면&amp;nbsp;2개의&amp;nbsp;컨테이너중&amp;nbsp;하나만&amp;nbsp;실행되고&amp;nbsp;에러가&amp;nbsp;난다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;502&quot; data-origin-height=&quot;159&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vBvfm/btsK9A3auxK/qZGDJuKOd462hxk8gPGHnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vBvfm/btsK9A3auxK/qZGDJuKOd462hxk8gPGHnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vBvfm/btsK9A3auxK/qZGDJuKOd462hxk8gPGHnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvBvfm%2FbtsK9A3auxK%2FqZGDJuKOd462hxk8gPGHnK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;502&quot; height=&quot;159&quot; data-origin-width=&quot;502&quot; data-origin-height=&quot;159&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;describe를&amp;nbsp;통해&amp;nbsp;확인&amp;nbsp;해보자 &lt;br /&gt;이미지를&amp;nbsp;가져오는건&amp;nbsp;성공을&amp;nbsp;했고,&amp;nbsp;컨테이너&amp;nbsp;옆에서&amp;nbsp;nginx-2를&amp;nbsp;실행하는데&amp;nbsp;실패해서&amp;nbsp;재시작을&amp;nbsp;하는&amp;nbsp;것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;782&quot; data-origin-height=&quot;615&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvFY4Y/btsLaoHW3qz/geMQIPkeQsrVzoDOGW9NHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvFY4Y/btsLaoHW3qz/geMQIPkeQsrVzoDOGW9NHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvFY4Y/btsLaoHW3qz/geMQIPkeQsrVzoDOGW9NHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvFY4Y%2FbtsLaoHW3qz%2FgeMQIPkeQsrVzoDOGW9NHk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;782&quot; height=&quot;615&quot; data-origin-width=&quot;782&quot; data-origin-height=&quot;615&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제&amp;nbsp;문제는&amp;nbsp;nginx-2에서&amp;nbsp;발생하는&amp;nbsp;점을&amp;nbsp;확인했고 &lt;br /&gt;logs를&amp;nbsp;확인해보면&amp;nbsp;컨테이너가&amp;nbsp;2개이기&amp;nbsp;때문에&amp;nbsp;기본으로&amp;nbsp;nginx-1의&amp;nbsp;로그만&amp;nbsp;주는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;721&quot; data-origin-height=&quot;167&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dwGjyw/btsK8JGzGTX/VxNepCfk26NnZW9jA7IM11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dwGjyw/btsK8JGzGTX/VxNepCfk26NnZW9jA7IM11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dwGjyw/btsK8JGzGTX/VxNepCfk26NnZW9jA7IM11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdwGjyw%2FbtsK8JGzGTX%2FVxNepCfk26NnZW9jA7IM11%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;721&quot; height=&quot;167&quot; data-origin-width=&quot;721&quot; data-origin-height=&quot;167&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제 nginx-2의 대해서 로그를 확인 해보자&lt;/p&gt;
&lt;pre id=&quot;code_1733468050043&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; kubectl logs my-pod -c nginx-2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;로그를&amp;nbsp;확인&amp;nbsp;해보면&amp;nbsp;이미&amp;nbsp;포트가&amp;nbsp;사용&amp;nbsp;중이기&amp;nbsp;때문에&amp;nbsp;에러가&amp;nbsp;나는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;574&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vOHdJ/btsLaiOwZYo/V5Ba2j4c8J0zXqnBra5N21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vOHdJ/btsLaiOwZYo/V5Ba2j4c8J0zXqnBra5N21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vOHdJ/btsLaiOwZYo/V5Ba2j4c8J0zXqnBra5N21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvOHdJ%2FbtsLaiOwZYo%2FV5Ba2j4c8J0zXqnBra5N21%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;752&quot; height=&quot;574&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;574&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Multi Container Pod - 2 &lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 변경한다&lt;/p&gt;
&lt;pre id=&quot;code_1733468087589&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: nginx-1
      image: nginx
    - name: util
      image: vinsdocker/util&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;log를 확인해보면 util은 ubuntu 기반의 이미지 이기 때문에 실행이 완료되고 죽기 때문에 무한히 반복되는것을 확인할 수있다. &lt;br /&gt;&lt;br /&gt;아래처럼 파일을 변경해보자&lt;/p&gt;
&lt;pre id=&quot;code_1733468107216&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  terminationGracePeriodSeconds: 1
  containers:
    - name: nginx-1
      image: nginx
    - name: util
      image: vinsdocker/util
      args:
        - &quot;sleep&quot;
        - &quot;3600&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;다시&amp;nbsp;확인을&amp;nbsp;해보면&amp;nbsp;정상적으로&amp;nbsp;2개의&amp;nbsp;컨테이너가&amp;nbsp;잘&amp;nbsp;실행되고&amp;nbsp;있는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;354&quot; data-origin-height=&quot;75&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qdOJg/btsK8KyH16O/KZ4fmmdwTRKZKMz87Rv8PK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qdOJg/btsK8KyH16O/KZ4fmmdwTRKZKMz87Rv8PK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qdOJg/btsK8KyH16O/KZ4fmmdwTRKZKMz87Rv8PK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqdOJg%2FbtsK8KyH16O%2FKZ4fmmdwTRKZKMz87Rv8PK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;354&quot; height=&quot;75&quot; data-origin-width=&quot;354&quot; data-origin-height=&quot;75&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;pod로&amp;nbsp;접속해보면&amp;nbsp;기본적으로&amp;nbsp;nginx-1&amp;nbsp;로&amp;nbsp;접근되는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;pre id=&quot;code_1733468133816&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl exec -it my-pod -- bash

# 접근 후 뜨는 log
Defaulted container &quot;nginx-1&quot; out of: nginx-1, util&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어를 통해 특정 컨테이너로 접근할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1733468143230&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl exec -it [pod name] -c [container name] -- bash
ex) kubectl exec -it my-pod -c util -- bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제&amp;nbsp;util&amp;nbsp;컨테이너로&amp;nbsp;접근&amp;nbsp;후&amp;nbsp;curl&amp;nbsp;localhost를&amp;nbsp;입력하면&amp;nbsp;nginx에&amp;nbsp;접근하는것을&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;실제로&amp;nbsp;한&amp;nbsp;pod&amp;nbsp;에서&amp;nbsp;2개의&amp;nbsp;컨테이너가&amp;nbsp;떠있지만&amp;nbsp;같은&amp;nbsp;pod&amp;nbsp;안에서는&amp;nbsp;네트워크를&amp;nbsp;공유하기&amp;nbsp;때문에&amp;nbsp;요청이&amp;nbsp;가능하다. &lt;br /&gt;&lt;br /&gt;그래서&amp;nbsp;서로&amp;nbsp;다른&amp;nbsp;컨테이너에&amp;nbsp;접속해서&amp;nbsp;hostname&amp;nbsp;을&amp;nbsp;확인해보면&amp;nbsp;같은&amp;nbsp;호스트&amp;nbsp;name을&amp;nbsp;응답하는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;482&quot; data-origin-height=&quot;172&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LNhSn/btsLaGahvKF/flPobqAm6nmxb1OD59QOJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LNhSn/btsLaGahvKF/flPobqAm6nmxb1OD59QOJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LNhSn/btsLaGahvKF/flPobqAm6nmxb1OD59QOJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLNhSn%2FbtsLaGahvKF%2FflPobqAm6nmxb1OD59QOJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;482&quot; height=&quot;172&quot; data-origin-width=&quot;482&quot; data-origin-height=&quot;172&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;요약&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;pod&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;K8S에서 배포 가능한 가장 작은 단위이다.&lt;/li&gt;
&lt;li&gt;pod는 하나이상의 컨테이너로 실행할 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오직 하나의 컨테이너만 어플리케이션 컨테이너여야 한다.&lt;/li&gt;
&lt;li&gt;나머지 컨테이너는 도우미여야 한다. (sidecar container)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;파드의 모든 컨테이너는 하나의 노드에서 실행된다. (파드 하나에서 여러개의 컨테이너를 실행한 경우 노드 하나에서 모두 실행된다.)&lt;/li&gt;
&lt;li&gt;실제로는 직접 yaml 파일을 생성하지 않는다.&lt;/li&gt;
&lt;li&gt;파드는 VM과 비슷하고 컨테이너들은 프로세스와 비슷하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Pod status&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Pending&lt;/b&gt;: 노드가 아직 할당되지 않았음 &lt;br /&gt;&lt;b&gt;ContainerCreating&lt;/b&gt;:&amp;nbsp;kubelet이&amp;nbsp;컨테이너&amp;nbsp;생성중 &lt;br /&gt;&lt;b&gt;Running&lt;/b&gt;:&amp;nbsp;kubelet이&amp;nbsp;컨테이너를&amp;nbsp;시작함 &lt;br /&gt;&lt;b&gt;ErrImagePull&amp;nbsp;/ ImagePullBackOff &lt;/b&gt;:&amp;nbsp;이미지&amp;nbsp;pull&amp;nbsp;실패.&amp;nbsp;kubelet이&amp;nbsp;약간의&amp;nbsp;지연후&amp;nbsp;재시도함 &lt;br /&gt;&lt;b&gt;Completed&lt;/b&gt;:&amp;nbsp;컨테이너가&amp;nbsp;성공적으로&amp;nbsp;종료됨 &lt;br /&gt;&lt;b&gt;Error&lt;/b&gt;:&amp;nbsp;컨테이너가&amp;nbsp;오류와&amp;nbsp;함께&amp;nbsp;종료됨 &lt;br /&gt;&lt;b&gt;CrashLoopBackOff&lt;/b&gt;:&amp;nbsp;컨테이너를&amp;nbsp;실행하는데&amp;nbsp;문제가&amp;nbsp;있음.&amp;nbsp;kubelet이&amp;nbsp;지연후&amp;nbsp;재시도함&amp;nbsp;(이미지&amp;nbsp;풀링에&amp;nbsp;문제가&amp;nbsp;없을&amp;nbsp;때) &lt;br /&gt;&lt;b&gt;Terminating&lt;/b&gt;:&amp;nbsp;pod&amp;nbsp;삭제중&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Pod Container Restart policy&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Never&lt;/b&gt;: Completed / Error 어떤 상황도 다시 시작하지 않음 &lt;br /&gt;&lt;b&gt;Always&lt;/b&gt;:&amp;nbsp;Completed&amp;nbsp;/&amp;nbsp;Error&amp;nbsp;어떤&amp;nbsp;상황에서도&amp;nbsp;다시&amp;nbsp;시작함 &lt;br /&gt;&lt;b&gt;OnFailure&lt;/b&gt;:&amp;nbsp;Error&amp;nbsp;인&amp;nbsp;경우에만&amp;nbsp;다시&amp;nbsp;시작함. &lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;Kubectl Commands&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kubectl get nodes&lt;/b&gt;: 클러스터의 모든 노드 확인 &lt;br /&gt;&lt;b&gt;kubectl&amp;nbsp;create&amp;nbsp;-f&amp;nbsp;[파일이름]&lt;/b&gt;:&amp;nbsp;yaml파일을&amp;nbsp;기준으로&amp;nbsp;리소스&amp;nbsp;생성 &lt;br /&gt;&lt;b&gt;kubectl&amp;nbsp;delete&amp;nbsp;-f&amp;nbsp;[파일&amp;nbsp;이름]&lt;/b&gt;:&amp;nbsp;yaml파일을&amp;nbsp;기준으로&amp;nbsp;리소스&amp;nbsp;삭제 &lt;br /&gt;&lt;b&gt;kubectl&amp;nbsp;get&amp;nbsp;pod&lt;/b&gt;:&amp;nbsp;모든&amp;nbsp;파드&amp;nbsp;목록을&amp;nbsp;보여줌 &lt;br /&gt;&lt;b&gt;kubectl&amp;nbsp;get&amp;nbsp;pod&amp;nbsp;--show-lables&lt;/b&gt;:&amp;nbsp;파드의&amp;nbsp;레이블들을&amp;nbsp;보여줌 &lt;br /&gt;&lt;b&gt;kubectl&amp;nbsp;get&amp;nbsp;pod&amp;nbsp;-l&amp;nbsp;[레이블&amp;nbsp;이름]=[레이블&amp;nbsp;값]&lt;/b&gt;:&amp;nbsp;label을&amp;nbsp;기준으로&amp;nbsp;쿼리해서&amp;nbsp;파드를&amp;nbsp;보여줌 &lt;br /&gt;&lt;b&gt;kubectl&amp;nbsp;get&amp;nbsp;pod&amp;nbsp;-l&amp;nbsp;[레이블&amp;nbsp;이름]!=[레이블&amp;nbsp;값]&lt;/b&gt;:&amp;nbsp;label을&amp;nbsp;기준으로&amp;nbsp;쿼리해서&amp;nbsp;파드를&amp;nbsp;보여줌 &lt;br /&gt;&lt;b&gt;kubectl&amp;nbsp;get&amp;nbsp;pod&amp;nbsp;[파드&amp;nbsp;이름]&amp;nbsp;-o&amp;nbsp;yaml&lt;/b&gt;:&amp;nbsp;파드&amp;nbsp;정보를&amp;nbsp;yaml&amp;nbsp;형식으로&amp;nbsp;보여줌 &lt;br /&gt;&lt;b&gt;kubectl&amp;nbsp;describe&amp;nbsp;pod&amp;nbsp;[파드&amp;nbsp;이름]&lt;/b&gt;:&amp;nbsp;파드의&amp;nbsp;세부&amp;nbsp;정보를&amp;nbsp;보여줌 &lt;br /&gt;&lt;b&gt;kubectl&amp;nbsp;delete&amp;nbsp;pod&amp;nbsp;[파드&amp;nbsp;이름]&lt;/b&gt;:&amp;nbsp;파드&amp;nbsp;이름을&amp;nbsp;기준으로&amp;nbsp;파드&amp;nbsp;삭제 &lt;br /&gt;&lt;b&gt;kubectl&amp;nbsp;delete&amp;nbsp;pod&amp;nbsp;--all&lt;/b&gt;:&amp;nbsp;모든&amp;nbsp;파드&amp;nbsp;삭제 &lt;br /&gt;&lt;b&gt;kubectl&amp;nbsp;logs&amp;nbsp;[파드&amp;nbsp;이름]&lt;/b&gt;:&amp;nbsp;파드의&amp;nbsp;log&amp;nbsp;확인 &lt;br /&gt;&lt;b&gt;kubectl&amp;nbsp;logs&amp;nbsp;[파드&amp;nbsp;이름]&amp;nbsp;-c&amp;nbsp;[컨테이너&amp;nbsp;이름]&lt;/b&gt;:&amp;nbsp;파드의&amp;nbsp;여러개의&amp;nbsp;컨테이너중&amp;nbsp;특정&amp;nbsp;컨테이너&amp;nbsp;로그&amp;nbsp;확인 &lt;br /&gt;&lt;b&gt;kubectl&amp;nbsp;exec&amp;nbsp;-it&amp;nbsp;[파드이름]&amp;nbsp;-c&amp;nbsp;[컨테이너&amp;nbsp;이름]&amp;nbsp;--bash&lt;/b&gt;:&amp;nbsp;파드의&amp;nbsp;컨테이너안에&amp;nbsp;쉘로&amp;nbsp;접속 &lt;br /&gt;&lt;b&gt;kubectl&amp;nbsp;port-forward&amp;nbsp;[파드&amp;nbsp;이름]&amp;nbsp;[호스트&amp;nbsp;포트]:[컨테이너&amp;nbsp;포트]&lt;/b&gt;:&amp;nbsp;디버깅을&amp;nbsp;위해&amp;nbsp;API&amp;nbsp;접속을&amp;nbsp;위해&amp;nbsp;사용 &lt;/p&gt;</description>
      <category>Kubernetes</category>
      <category>cloud-native</category>
      <category>container</category>
      <category>devops</category>
      <category>k8s</category>
      <category>kubernetes</category>
      <category>orchestration</category>
      <category>POD</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/225</guid>
      <comments>https://systorage.tistory.com/entry/Kubernetes-Pod-%EA%B8%B0%EC%B4%88-2#entry225comment</comments>
      <pubDate>Fri, 6 Dec 2024 16:00:45 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes] Pod 기초 - 1</title>
      <link>https://systorage.tistory.com/entry/Kubernetes-Pod-%EA%B8%B0%EC%B4%88-1</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;워크로드는&amp;nbsp;K8S&amp;nbsp;클러스트&amp;nbsp;위에서&amp;nbsp;동작하는&amp;nbsp;애플리케이션이다. &lt;br /&gt;파드는&amp;nbsp;워크로드를&amp;nbsp;생성하는&amp;nbsp;기본&amp;nbsp;구성&amp;nbsp;요소이다. &lt;br /&gt;배포가능한&amp;nbsp;가장&amp;nbsp;작은&amp;nbsp;단위이다. &lt;br /&gt;파드는&amp;nbsp;하나&amp;nbsp;이상의&amp;nbsp;컨테이너를&amp;nbsp;실행할수&amp;nbsp;있다. &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;오직&amp;nbsp;하나의&amp;nbsp;컨테이너만&amp;nbsp;어플리케이션&amp;nbsp;컨테이너이고 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;나머지&amp;nbsp;컨테이너는&amp;nbsp;도우미이다. &lt;br /&gt;파드는&amp;nbsp;VM을&amp;nbsp;제공하고&amp;nbsp;컨테이너는&amp;nbsp;프로세스를&amp;nbsp;제공한다. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;간단한 파드 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;K8S 요소 yaml format은 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1732674392249&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: [api Version]
kind: [K8S의 워크로드 타입]
metadata:
    [리소스 이름, 추가 레이블]
spec:
    [워크로드 타입에 따라서 달라진다. 공식문서를 참고하자]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;참고할&amp;nbsp;공식문서 &lt;br /&gt;&lt;a href=&quot;https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;실습&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실습전&amp;nbsp;cluster&amp;nbsp;생성을&amp;nbsp;해야한다. &lt;br /&gt;&lt;br /&gt;터미널을&amp;nbsp;따로&amp;nbsp;하나&amp;nbsp;킨&amp;nbsp;후&amp;nbsp;아래&amp;nbsp;명령어를&amp;nbsp;입력하자. &lt;br /&gt;아래&amp;nbsp;명령어는&amp;nbsp;2초마다&amp;nbsp;kubectl&amp;nbsp;get&amp;nbsp;pod&amp;nbsp;명령어의&amp;nbsp;결과를&amp;nbsp;보여준다.&lt;/p&gt;
&lt;pre id=&quot;code_1732674738782&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;watch -t -x kubectl get pod&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;pod 정의&lt;/h3&gt;
&lt;pre id=&quot;code_1732674758623&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: nginx
      image: nginx&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;pod 생성&lt;/h3&gt;
&lt;pre id=&quot;code_1732674776061&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create -f 01-simple-pod.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;pod 삭제&lt;/h3&gt;
&lt;pre id=&quot;code_1732674779551&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl delete -f 01-simple-pod.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 pod를 생성한 후 &lt;br /&gt;kubectl&amp;nbsp;describe&amp;nbsp;pod&amp;nbsp;명령어를&amp;nbsp;통해&amp;nbsp;세부&amp;nbsp;사항을&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;문제가&amp;nbsp;발생했을때&amp;nbsp;디버깅을&amp;nbsp;위해&amp;nbsp;필요하며&amp;nbsp;가장&amp;nbsp;중요한&amp;nbsp;파트는&amp;nbsp;아래&amp;nbsp;Events&amp;nbsp;섹션이다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;472&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qjOut/btsKXpnd24N/XeR732CYZXhPhe3rkaYDTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qjOut/btsKXpnd24N/XeR732CYZXhPhe3rkaYDTK/img.png&quot; data-alt=&quot;describe 예시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qjOut/btsKXpnd24N/XeR732CYZXhPhe3rkaYDTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqjOut%2FbtsKXpnd24N%2FXeR732CYZXhPhe3rkaYDTK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;821&quot; height=&quot;472&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;472&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;describe 예시&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1087&quot; data-origin-height=&quot;144&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sEr4h/btsKYEXYgFL/k44RPCbfePbzrmChdTSjlk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sEr4h/btsKYEXYgFL/k44RPCbfePbzrmChdTSjlk/img.png&quot; data-alt=&quot;Events 섹션&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sEr4h/btsKYEXYgFL/k44RPCbfePbzrmChdTSjlk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsEr4h%2FbtsKYEXYgFL%2Fk44RPCbfePbzrmChdTSjlk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1087&quot; height=&quot;144&quot; data-origin-width=&quot;1087&quot; data-origin-height=&quot;144&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Events 섹션&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Pod 업데이트 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pod가 정의된 yaml을 create 한 후 변경 사항이 생겼을때 다시 kubectl create 을 하면 이미 존재한다는 에러가 발생한다 &lt;br /&gt;&lt;br /&gt;이&amp;nbsp;때&amp;nbsp;변경사항&amp;nbsp;적용을&amp;nbsp;위한&amp;nbsp;명령어는&amp;nbsp;아래와&amp;nbsp;같다.&lt;/p&gt;
&lt;pre id=&quot;code_1732674925480&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f [yaml file]
ex) kubectl apply -f 01-simple-pod.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Image&amp;nbsp;Pull&amp;nbsp;Backoff&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약&amp;nbsp;존재하지&amp;nbsp;않는&amp;nbsp;이미지를&amp;nbsp;가져오려고&amp;nbsp;하면&amp;nbsp;에러가&amp;nbsp;발생한다. &lt;br /&gt;pod가&amp;nbsp;정의된&amp;nbsp;yaml파일을&amp;nbsp;아래와같이&amp;nbsp;변경해보자&lt;/p&gt;
&lt;pre id=&quot;code_1732674959981&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: nginx
      image: nginx:ftgsedzfcvzx&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;파드를 생성하고 상태를 확인하면 에러가 난것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;422&quot; data-origin-height=&quot;68&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/287a3/btsKXref6jf/knxwtuV23TIlzJ2NTWSHK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/287a3/btsKXref6jf/knxwtuV23TIlzJ2NTWSHK1/img.png&quot; data-alt=&quot;Pod error&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/287a3/btsKXref6jf/knxwtuV23TIlzJ2NTWSHK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F287a3%2FbtsKXref6jf%2FknxwtuV23TIlzJ2NTWSHK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;422&quot; height=&quot;68&quot; data-origin-width=&quot;422&quot; data-origin-height=&quot;68&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Pod error&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kubectl describe pod 명령어를 통해 이벤트 섹션을 살펴보면 자세하게 알 수 있다. &lt;br /&gt;존재하지 않는 이미지를 가져오려고 해서 에러가 난 것을 확인 할 수 있다. &lt;br /&gt;&lt;br /&gt;로그를&amp;nbsp;살펴보면&amp;nbsp;이미지를&amp;nbsp;가져오지&amp;nbsp;못해서&amp;nbsp;바로&amp;nbsp;작업을&amp;nbsp;삭제하는것이&amp;nbsp;아니라&amp;nbsp;반복해서&amp;nbsp;이미지를&amp;nbsp;가져오려고&amp;nbsp;한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1077&quot; data-origin-height=&quot;187&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpKdNR/btsKWQlfF6E/jRW2KwtBt5odkCAwdGw4g0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpKdNR/btsKWQlfF6E/jRW2KwtBt5odkCAwdGw4g0/img.png&quot; data-alt=&quot;describe&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpKdNR/btsKWQlfF6E/jRW2KwtBt5odkCAwdGw4g0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpKdNR%2FbtsKWQlfF6E%2FjRW2KwtBt5odkCAwdGw4g0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1077&quot; height=&quot;187&quot; data-origin-width=&quot;1077&quot; data-origin-height=&quot;187&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;describe&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Crash&amp;nbsp;loop&amp;nbsp;Backoff&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 파일을 정의한다. &lt;br /&gt;아래&amp;nbsp;파일은&amp;nbsp;실패하는&amp;nbsp;docker&amp;nbsp;이미지&amp;nbsp;이다. &lt;br /&gt;02-failing-pod.yaml&lt;/p&gt;
&lt;pre id=&quot;code_1732675060345&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: failing-container
      image: vinsdocker/k8s-failing-container&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kubectl create -f 02-failing-pod.yaml 명령어를 통해 파일을 실행시키고 &lt;br /&gt;kubectl&amp;nbsp;get&amp;nbsp;pod&amp;nbsp;명령어를&amp;nbsp;통해&amp;nbsp;확인해보면&amp;nbsp;Restarts가&amp;nbsp;점점&amp;nbsp;증가하는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;그 후 Status가 CrashLoopBackOff 으로 변경된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제&amp;nbsp;kubectl&amp;nbsp;describe&amp;nbsp;pod&amp;nbsp;로&amp;nbsp;이벤트를&amp;nbsp;확인해보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uSmXn/btsKWTPKFwK/1U1S9zBc51UksX5sb2stw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uSmXn/btsKWTPKFwK/1U1S9zBc51UksX5sb2stw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uSmXn/btsKWTPKFwK/1U1S9zBc51UksX5sb2stw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuSmXn%2FbtsKWTPKFwK%2F1U1S9zBc51UksX5sb2stw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1086&quot; height=&quot;306&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;306&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노드를 성공적으로 할당하고, &lt;br /&gt;이미지를&amp;nbsp;성공적으로&amp;nbsp;가져온&amp;nbsp;후, &lt;br /&gt;컨테이너가&amp;nbsp;실패한&amp;nbsp;후의&amp;nbsp;로그들이&amp;nbsp;담겨있다. &lt;br /&gt;기본적으로&amp;nbsp;컨테이너를&amp;nbsp;다시&amp;nbsp;실행시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Pod status&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ready에서 1/1 의 앞은 현재 실행되고 있는 컨테이너 수, 뒤는 실제로 실행되어야 하는 컨테이너의 수이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;342&quot; data-origin-height=&quot;76&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTQ4nk/btsKW4czaPc/K0Anx7kwGAKOK7hTpMbvdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTQ4nk/btsKW4czaPc/K0Anx7kwGAKOK7hTpMbvdk/img.png&quot; data-alt=&quot;Running&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTQ4nk/btsKW4czaPc/K0Anx7kwGAKOK7hTpMbvdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTQ4nk%2FbtsKW4czaPc%2FK0Anx7kwGAKOK7hTpMbvdk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;342&quot; height=&quot;76&quot; data-origin-width=&quot;342&quot; data-origin-height=&quot;76&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Running&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;332&quot; data-origin-height=&quot;69&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bipRzY/btsKWh4n23c/H8K2JnK8K5Q3jjnpflaFPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bipRzY/btsKWh4n23c/H8K2JnK8K5Q3jjnpflaFPk/img.png&quot; data-alt=&quot;Error&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bipRzY/btsKWh4n23c/H8K2JnK8K5Q3jjnpflaFPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbipRzY%2FbtsKWh4n23c%2FH8K2JnK8K5Q3jjnpflaFPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;332&quot; height=&quot;69&quot; data-origin-width=&quot;332&quot; data-origin-height=&quot;69&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Error&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 137px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 29.1861%; height: 20px;&quot;&gt;Pending&lt;/td&gt;
&lt;td style=&quot;width: 70.8139%; height: 20px;&quot;&gt;노드가 아직 할당되지 않았음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 29.1861%; height: 20px;&quot;&gt;ContainerCreating&lt;/td&gt;
&lt;td style=&quot;width: 70.8139%; height: 20px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;kubelet이 컨테이너 생성중&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 29.1861%; height: 20px;&quot;&gt;Running&lt;/td&gt;
&lt;td style=&quot;width: 70.8139%; height: 20px;&quot;&gt;kubelet이&amp;nbsp;컨테이너를&amp;nbsp;시작함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 29.1861%; height: 20px;&quot;&gt;ErrImagePull&amp;nbsp;/&amp;nbsp;ImagePullBackOff&lt;/td&gt;
&lt;td style=&quot;width: 70.8139%; height: 20px;&quot;&gt;이미지 pull 실패. kubelet이 약간의 지연후 재시도함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 29.1861%; height: 20px;&quot;&gt;Completed&lt;/td&gt;
&lt;td style=&quot;width: 70.8139%; height: 20px;&quot;&gt;컨테이너가 성공적으로 종료됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 29.1861%; height: 20px;&quot;&gt;Error&lt;/td&gt;
&lt;td style=&quot;width: 70.8139%; height: 20px;&quot;&gt;컨테이너가 오류와 함께 종료됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 29.1861%; height: 17px;&quot;&gt;CrashLoopBackOff&lt;/td&gt;
&lt;td style=&quot;width: 70.8139%; height: 17px;&quot;&gt;컨테이너 실행에 문제가 있음. kubelet이 지연후 재시도 (이미지 pull에 문제가 없을 때)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 29.1861%;&quot;&gt;Terminating&lt;/td&gt;
&lt;td style=&quot;width: 70.8139%;&quot;&gt;pod 삭제중&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Pod labels&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 파일로 여러개의 Pod를 정의하는 방법이다 &lt;br /&gt;&lt;br /&gt;label은&amp;nbsp;키와&amp;nbsp;값의&amp;nbsp;쌍이다.&amp;nbsp;원하는&amp;nbsp;값을&amp;nbsp;정의할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;03-multiple-pods.yaml&lt;/p&gt;
&lt;pre id=&quot;code_1732675296673&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: pod-1
  labels:
    dept: dept-1
    team: team-a
spec:
  containers:
    - name: nginx
      image: nginx
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-2
  labels:
    dept: dept-1
    team: team-b
spec:
  containers:
    - name: nginx
      image: nginx
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-3
  labels:
    dept: dept-2
    team: team-a
spec:
  containers:
    - name: nginx
      image: nginx&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;pod 생성&lt;/h3&gt;
&lt;pre id=&quot;code_1732675312182&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create -f 03-multiple-pods.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;308&quot; data-origin-height=&quot;93&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ojR38/btsKXkfhKW7/3LwnGKQ6221lVyuZ17XLc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ojR38/btsKXkfhKW7/3LwnGKQ6221lVyuZ17XLc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ojR38/btsKXkfhKW7/3LwnGKQ6221lVyuZ17XLc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FojR38%2FbtsKXkfhKW7%2F3LwnGKQ6221lVyuZ17XLc0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;308&quot; height=&quot;93&quot; data-origin-width=&quot;308&quot; data-origin-height=&quot;93&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;pod&amp;nbsp;확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kubectl describe pod 을 사용하면 모든 파드를 가져온다 &lt;br /&gt;아래&amp;nbsp;명령어를&amp;nbsp;사용하면&amp;nbsp;단일&amp;nbsp;pod에&amp;nbsp;대한&amp;nbsp;정보만&amp;nbsp;가져올&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;pre id=&quot;code_1732675343076&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get pod [파드이름]
ex) kubectl get pod pod-1
kubectl describe pod [파드이름]
ex) kubectl describe pod pod-1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;label확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어를 사용하면 모든 파드의 label을 가져올 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1732675428869&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get pod --show-labels

# 결과 예시
NAME    READY   STATUS    RESTARTS   AGE     LABELS
pod-1   1/1     Running   0          3m16s   dept=dept-1,team=team-a
pod-2   1/1     Running   0          3m16s   dept=dept-1,team=team-b
pod-3   1/1     Running   0          3m16s   dept=dept-2,team=team-a&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;파드의 레이블을 검색할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1732675468969&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# label의 team이 team-a 인 pod만
kubectl get pod -l team=team-a

# 결과
NAME    READY   STATUS    RESTARTS   AGE
pod-1   1/1     Running   0          6m6s
pod-3   1/1     Running   0          6m6s

-------------------------------------------------------

# label의 team이 team-a 가 아닌 pod만
kubectl get pod -l team!=team-a

# 결과
NAME    READY   STATUS    RESTARTS   AGE
pod-2   1/1     Running   0          5m41s

-------------------------------------------------------

# label이 dept는 dept-1 이고 team은 team-a인 pod만
kubectl get pod -l dept=dept-1,team=team-a

# 결과
NAME    READY   STATUS    RESTARTS   AGE
pod-1   1/1     Running   0          7m22s&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Formatting output&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pod에 대한 정보를 좀 더 자세하게 제공한다.&lt;/p&gt;
&lt;pre id=&quot;code_1732675498493&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get pod -o wide

# 결과
NAME    READY   STATUS    RESTARTS   AGE   IP           NODE                  NOMINATED NODE   READINESS GATES
pod-1   1/1     Running   0          20h   10.244.1.7   dev-cluster-worker    &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
pod-2   1/1     Running   0          20h   10.244.2.5   dev-cluster-worker2   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
pod-3   1/1     Running   0          20h   10.244.1.8   dev-cluster-worker    &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;yaml 형식 출력으로 볼수 있는 명령어는 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1732675525478&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get pod [pod이름] -o yaml
ex) kubectl get pod pod-1 -o yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;409&quot; data-origin-height=&quot;683&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dP8mWJ/btsKY2RJNE3/y8ZpA8sve2tVfGIEg7Wvt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dP8mWJ/btsKY2RJNE3/y8ZpA8sve2tVfGIEg7Wvt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dP8mWJ/btsKY2RJNE3/y8ZpA8sve2tVfGIEg7Wvt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdP8mWJ%2FbtsKY2RJNE3%2Fy8ZpA8sve2tVfGIEg7Wvt1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;409&quot; height=&quot;683&quot; data-origin-width=&quot;409&quot; data-origin-height=&quot;683&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Deleteing a pod&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러개의 파드를 생성하고 특정 파드만 지우고 싶은 상황이 있을 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1732675553298&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# pod 생성
kubectl create -f 03-multiple-pods.yaml
# pod-2 삭제
kubectl delete pod pod-2
# pod-3 삭제
kubectl delete pod/pod-3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Port Forward&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠버네티스 클러스터의 node들은 네트워크를 통해 서로 연결이 되어있다. (노드 네트워킹) &lt;br /&gt;node&amp;nbsp;컨테이너들은&amp;nbsp;자체&amp;nbsp;IP&amp;nbsp;주소가&amp;nbsp;있다. &lt;br /&gt;쿠버네티스&amp;nbsp;API&amp;nbsp;서버에서&amp;nbsp;받는&amp;nbsp;요청을&amp;nbsp;컨테이너로&amp;nbsp;넘기기&amp;nbsp;위해서는&amp;nbsp;컨테이너의&amp;nbsp;포트를&amp;nbsp;열어&amp;nbsp;주어야&amp;nbsp;한다. &lt;br /&gt;&lt;br /&gt;아래와&amp;nbsp;같은&amp;nbsp;yaml&amp;nbsp;파일&amp;nbsp;정의를&amp;nbsp;통해&amp;nbsp;port를&amp;nbsp;노출할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;&lt;br /&gt;04-pod-port.yaml&lt;/p&gt;
&lt;pre id=&quot;code_1732675588812&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: nginx
      image: nginx
      ports:
      - name: &quot;web-port&quot;
        containerPort: 80&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;pod를&amp;nbsp;실행&amp;nbsp;시킨&amp;nbsp;이후&amp;nbsp;아래&amp;nbsp;명령어를&amp;nbsp;통해서&amp;nbsp;포트를&amp;nbsp;매핑한다.&lt;/p&gt;
&lt;pre id=&quot;code_1732675609932&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl port-forward [파드이름] [K8S 포트번호]:[docker port 번호]
ex) kubectl port-forward my-pod 8080:80&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;473&quot; data-origin-height=&quot;70&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dSpLE6/btsKYh9QPMQ/LXpdEKqsjkNtnBXA8yIIDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dSpLE6/btsKYh9QPMQ/LXpdEKqsjkNtnBXA8yIIDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dSpLE6/btsKYh9QPMQ/LXpdEKqsjkNtnBXA8yIIDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdSpLE6%2FbtsKYh9QPMQ%2FLXpdEKqsjkNtnBXA8yIIDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;473&quot; height=&quot;70&quot; data-origin-width=&quot;473&quot; data-origin-height=&quot;70&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;http://localhost:8080/&amp;nbsp;으로&amp;nbsp;접속하면&amp;nbsp;nginx&amp;nbsp;화면을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;이러한&amp;nbsp;방법은&amp;nbsp;디버깅에&amp;nbsp;유용하다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1098&quot; data-origin-height=&quot;485&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bh5t6q/btsKW7mPNLz/5GRbniuRMLtZ47d7IyZjqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bh5t6q/btsKW7mPNLz/5GRbniuRMLtZ47d7IyZjqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bh5t6q/btsKW7mPNLz/5GRbniuRMLtZ47d7IyZjqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbh5t6q%2FbtsKW7mPNLz%2F5GRbniuRMLtZ47d7IyZjqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1098&quot; height=&quot;485&quot; data-origin-width=&quot;1098&quot; data-origin-height=&quot;485&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Restart policy&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pod의 재시작 정책에 대해서 서술한다. &lt;br /&gt;&lt;br /&gt;05-restart-policy.yaml 을 정의한다.&lt;/p&gt;
&lt;pre id=&quot;code_1732675655347&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: ubuntu
      image: ubuntu&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pod를 실행하면 실행해야 할 작업이 없기 때문에 성공적으로 작업이 종료되고 영원히 재시작을 반복한다. &lt;br /&gt;&lt;br /&gt;kubectl get pod -o yaml 명령어를 통해 확인해보면&amp;nbsp;&amp;nbsp;restartPolicy가 Always로 정의가 된것을 확인할 수있다.&amp;nbsp; &lt;br /&gt;pod&amp;nbsp;spec에&amp;nbsp;정의가&amp;nbsp;되어있지&amp;nbsp;않으면&amp;nbsp;default이기&amp;nbsp;때문이다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;408&quot; data-origin-height=&quot;520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNg12i/btsKWLKVC0G/P3PwvHOkkkFzfqPuatKzM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNg12i/btsKWLKVC0G/P3PwvHOkkkFzfqPuatKzM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNg12i/btsKWLKVC0G/P3PwvHOkkkFzfqPuatKzM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNg12i%2FbtsKWLKVC0G%2FP3PwvHOkkkFzfqPuatKzM1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;408&quot; height=&quot;520&quot; data-origin-width=&quot;408&quot; data-origin-height=&quot;520&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;yaml&amp;nbsp;파일을&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;수정한다.&lt;/p&gt;
&lt;pre id=&quot;code_1732675700635&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  restartPolicy: Never # Always, Never(다시 시작하지 않음), OnFailure (실패했을 때만)
  containers:
    - name: ubuntu
      image: ubuntu&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제 다시 Pod 를 실행해보면 Status가 Completed 상태로 종료되고 restart가 이루어지지 않는것을 확인할 수 있다. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>Kubernetes</category>
      <category>cloud-native</category>
      <category>container</category>
      <category>devops</category>
      <category>kubernetes</category>
      <category>orchestration</category>
      <category>POD</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/224</guid>
      <comments>https://systorage.tistory.com/entry/Kubernetes-Pod-%EA%B8%B0%EC%B4%88-1#entry224comment</comments>
      <pubDate>Wed, 27 Nov 2024 11:49:37 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes] Cluster 학습</title>
      <link>https://systorage.tistory.com/entry/Kubernetes-Cluster-%ED%95%99%EC%8A%B5</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;클러스터는 네트워크에 연결된 물리적 or 가상 머신의 집합이며, 클러스터는&amp;nbsp;마스터와&amp;nbsp;노드로&amp;nbsp;구성된다. &lt;br /&gt;일반적으로 프로덕션 환경의 경우 하나 이상의 마스터가 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Master&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마스터의 컴포넌트는 api-server, stcd, controller-manager, scheduler로 구성된다. &lt;br /&gt;&lt;b&gt;api-server&lt;/b&gt;: 클라이언트가 클러스터와 대화하고 워크로드를 생성할 수 있는 API-서버 &lt;br /&gt;&lt;b&gt;etcd (et-c-d)&lt;/b&gt;: 클러스터 데이터를 저장할 분산 키 값 저장소 &lt;br /&gt;&lt;b&gt;controller-manager&lt;/b&gt;: 워크로드/노드 등을 지속적으로 모니터링하는 프로세스 &lt;br /&gt;&lt;b&gt;scheduler&lt;/b&gt;:&amp;nbsp;워크로드&amp;nbsp;스케줄러 &lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Node&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노드의 컴포넌트는 kubelet, container runtime (docker), kube-proxy 로 구성된다. &lt;br /&gt;&lt;b&gt;kubelet&lt;/b&gt;: 컨테이너를 만들고 모니터링하는 에이전트 &lt;br /&gt;&lt;b&gt;container runtime (docker)&lt;/b&gt;: 컨테이너를 만들기 위해 컨테이너 런타임이 깔려있어야 한다. (docker) &lt;br /&gt;&lt;b&gt;kube-proxy&lt;/b&gt;:&amp;nbsp;클러스터&amp;nbsp;내&amp;nbsp;워크로드&amp;nbsp;간의&amp;nbsp;통신을&amp;nbsp;위해&amp;nbsp;노드의&amp;nbsp;네트워크&amp;nbsp;규칙을&amp;nbsp;유지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;kubectl 설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시는 linux이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;link:&amp;nbsp;&lt;a href=&quot;https://kubernetes.io/ko/docs/tasks/tools/install-kubectl-linux/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://kubernetes.io/ko/docs/tasks/tools/install-kubectl-linux/&lt;/a&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1731993563310&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl -LO &quot;https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl&quot;
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;설치 확인&lt;/h3&gt;
&lt;pre id=&quot;code_1731993612343&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl version --client --output=yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;411&quot; data-origin-height=&quot;203&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xkj9C/btsKPx5w5B8/eMUX1vE8q5cfOPNVE5sYCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xkj9C/btsKPx5w5B8/eMUX1vE8q5cfOPNVE5sYCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xkj9C/btsKPx5w5B8/eMUX1vE8q5cfOPNVE5sYCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxkj9C%2FbtsKPx5w5B8%2FeMUX1vE8q5cfOPNVE5sYCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;411&quot; height=&quot;203&quot; data-origin-width=&quot;411&quot; data-origin-height=&quot;203&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;kind&amp;nbsp;설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 kind를 사용해서 학습을 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;link:&amp;nbsp;&lt;a href=&quot;https://kind.sigs.k8s.io/docs/user/quick-start/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://kind.sigs.k8s.io/docs/user/quick-start/&lt;/a&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1731993679208&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# For AMD64 / x86_64
[ $(uname -m) = x86_64 ] &amp;amp;&amp;amp; curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.25.0/kind-linux-amd64
# For ARM64
[ $(uname -m) = aarch64 ] &amp;amp;&amp;amp; curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.25.0/kind-linux-arm64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;설치 확인&lt;/h3&gt;
&lt;pre id=&quot;code_1731993703233&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kind version&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;281&quot; data-origin-height=&quot;57&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/chsp52/btsKOWkrZgL/prq7qguW2Sibj6JJrPgnN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/chsp52/btsKOWkrZgL/prq7qguW2Sibj6JJrPgnN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/chsp52/btsKOWkrZgL/prq7qguW2Sibj6JJrPgnN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fchsp52%2FbtsKOWkrZgL%2Fprq7qguW2Sibj6JJrPgnN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;281&quot; height=&quot;57&quot; data-origin-width=&quot;281&quot; data-origin-height=&quot;57&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;클러스터 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. kind cluster 구성 파일 01-cluster.yaml 을 만든다.&lt;/p&gt;
&lt;pre id=&quot;code_1731993767098&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# three node (two workers) cluster config
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: dev-cluster
nodes:
- role: control-plane
- role: worker
- role: worker&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;2.&amp;nbsp;클러스터&amp;nbsp;생성&lt;/p&gt;
&lt;pre id=&quot;code_1731993780908&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kind create cluster --config 01-cluster.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;679&quot; data-origin-height=&quot;321&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JQrrT/btsKPfcNiM7/3QD1fgTKrcovsV6JYa4kLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JQrrT/btsKPfcNiM7/3QD1fgTKrcovsV6JYa4kLk/img.png&quot; data-alt=&quot;결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JQrrT/btsKPfcNiM7/3QD1fgTKrcovsV6JYa4kLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJQrrT%2FbtsKPfcNiM7%2F3QD1fgTKrcovsV6JYa4kLk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;679&quot; height=&quot;321&quot; data-origin-width=&quot;679&quot; data-origin-height=&quot;321&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;3. 확인&lt;/p&gt;
&lt;pre id=&quot;code_1731993817152&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker ps -a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1076&quot; data-origin-height=&quot;104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Afq7n/btsKNbDcoEF/tu0sRgE7oK2FCCR212t83K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Afq7n/btsKNbDcoEF/tu0sRgE7oK2FCCR212t83K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Afq7n/btsKNbDcoEF/tu0sRgE7oK2FCCR212t83K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAfq7n%2FbtsKNbDcoEF%2Ftu0sRgE7oK2FCCR212t83K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1076&quot; height=&quot;104&quot; data-origin-width=&quot;1076&quot; data-origin-height=&quot;104&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;4. cat ~/.kube/config 를 쳐보면 구성파일을 확인해볼수 있다. server&amp;nbsp;를&amp;nbsp;보면&amp;nbsp;열려있는&amp;nbsp;포트를&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;&lt;br /&gt;5.&amp;nbsp;kubectl&amp;nbsp;version&amp;nbsp;--client&amp;nbsp;--output=yaml&amp;nbsp;명령어를&amp;nbsp;통해&amp;nbsp;서버의&amp;nbsp;version도&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;423&quot; data-origin-height=&quot;361&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjJe9h/btsKOj8dnCH/KxvabjiUZQqZnGbKpRlOBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjJe9h/btsKOj8dnCH/KxvabjiUZQqZnGbKpRlOBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjJe9h/btsKOj8dnCH/KxvabjiUZQqZnGbKpRlOBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjJe9h%2FbtsKOj8dnCH%2FKxvabjiUZQqZnGbKpRlOBk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;423&quot; height=&quot;361&quot; data-origin-width=&quot;423&quot; data-origin-height=&quot;361&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6.&amp;nbsp;노드&amp;nbsp;확인&lt;/p&gt;
&lt;pre id=&quot;code_1731993891571&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get nodes

# 결과
NAME                        STATUS   ROLES           AGE    VERSION
dev-cluster-control-plane   Ready    control-plane   118m   v1.31.2
dev-cluster-worker          Ready    &amp;lt;none&amp;gt;          118m   v1.31.2
dev-cluster-worker2         Ready    &amp;lt;none&amp;gt;          118m   v1.31.2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;클러스터&amp;nbsp;내부&amp;nbsp;확인&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Master 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 마스터에 shell로 접속한다&lt;/p&gt;
&lt;pre id=&quot;code_1731993944963&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker exec -it [마스터 컴포넌트ID] /bin/bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;2.&amp;nbsp;설정&amp;nbsp;파일들이&amp;nbsp;저장되어&amp;nbsp;있는&amp;nbsp;곳으로&amp;nbsp;이동한다.&lt;/p&gt;
&lt;pre id=&quot;code_1731993954006&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd /etc/kubernetes/manifests/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;3.&amp;nbsp;yaml들이&amp;nbsp;있는걸&amp;nbsp;확인&amp;nbsp;할&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;pre id=&quot;code_1731993973006&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ls -al&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;527&quot; data-origin-height=&quot;169&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/duDW9L/btsKNfeuRen/LXritICpc2e7uwj0bFfStK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/duDW9L/btsKNfeuRen/LXritICpc2e7uwj0bFfStK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/duDW9L/btsKNfeuRen/LXritICpc2e7uwj0bFfStK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FduDW9L%2FbtsKNfeuRen%2FLXritICpc2e7uwj0bFfStK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;527&quot; height=&quot;169&quot; data-origin-width=&quot;527&quot; data-origin-height=&quot;169&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;4.&amp;nbsp;이&amp;nbsp;yaml&amp;nbsp;file들은&amp;nbsp;실제로&amp;nbsp;실행되고&amp;nbsp;있는&amp;nbsp;프로세스이다.&lt;/p&gt;
&lt;pre id=&quot;code_1731993979794&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ps -aux&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1078&quot; data-origin-height=&quot;283&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oPPmD/btsKNcWo2ZQ/8LApLuL50JOIk12SMSCVS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oPPmD/btsKNcWo2ZQ/8LApLuL50JOIk12SMSCVS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oPPmD/btsKNcWo2ZQ/8LApLuL50JOIk12SMSCVS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoPPmD%2FbtsKNcWo2ZQ%2F8LApLuL50JOIk12SMSCVS0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1078&quot; height=&quot;283&quot; data-origin-width=&quot;1078&quot; data-origin-height=&quot;283&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Node 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. node에 shell로 접속한다.&lt;/p&gt;
&lt;pre id=&quot;code_1731994019790&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker exec -it [node 컴포넌트ID] /bin/bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;2.&amp;nbsp;마찬가지로&amp;nbsp;프로세스를&amp;nbsp;확인해보면&amp;nbsp;node에서&amp;nbsp;사용하는&amp;nbsp;프로세스들이&amp;nbsp;돌고&amp;nbsp;있는것을&amp;nbsp;확인할수&amp;nbsp;있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1090&quot; data-origin-height=&quot;240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ci4yfa/btsKOzpy2U4/mppxFKx2gXgKUaJvDEO4T1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ci4yfa/btsKOzpy2U4/mppxFKx2gXgKUaJvDEO4T1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ci4yfa/btsKOzpy2U4/mppxFKx2gXgKUaJvDEO4T1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fci4yfa%2FbtsKOzpy2U4%2FmppxFKx2gXgKUaJvDEO4T1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1090&quot; height=&quot;240&quot; data-origin-width=&quot;1090&quot; data-origin-height=&quot;240&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;학습이&amp;nbsp;끝나면&amp;nbsp;자원확보를&amp;nbsp;위해&amp;nbsp;클러스터를&amp;nbsp;삭제해주자&lt;/p&gt;
&lt;pre id=&quot;code_1731994038490&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kind delete cluster --name [클러스터 이름]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Kubernetes</category>
      <category>cluster</category>
      <category>devops</category>
      <category>docker</category>
      <category>k8s</category>
      <category>kubernetes</category>
      <category>kubernetescluster</category>
      <category>kubernetestutorial</category>
      <category>쿠버네티스</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/223</guid>
      <comments>https://systorage.tistory.com/entry/Kubernetes-Cluster-%ED%95%99%EC%8A%B5#entry223comment</comments>
      <pubDate>Tue, 19 Nov 2024 14:28:29 +0900</pubDate>
    </item>
    <item>
      <title>프로토콜 버퍼(protobuf)란?</title>
      <link>https://systorage.tistory.com/entry/%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C-%EB%B2%84%ED%8D%BCprotobuf%EB%9E%80</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 소개&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;현대 애플리케이션에서 데이터 직렬화의 중요성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘날의 소프트웨어 개발에서는 다양한 시스템과 애플리케이션 간에 데이터를 효율적으로 교환하는 것이 매우 중요합니다. 특히 마이크로서비스 아키텍처의 확산과 모바일 및 IoT 기기의 증가로 인해 네트워크 상에서 주고받는 데이터의 양과 빈도가 폭발적으로 늘어나고 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기존 직렬화 방식의 한계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전통적으로 데이터 교환에는 JSON이나 XML과 같은 텍스트 기반의 포맷이 많이 사용되어 왔습니다. 이러한 포맷은 사람이 읽기 쉽고 이해하기 편리하다는 장점이 있지만, 데이터 크기가 크고 파싱 속도가 느리며, 데이터 타입에 대한 명확한 정의가 부족하다는 단점이 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로토콜 버퍼의 등장 배경&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글은 내부 시스템에서 대용량의 데이터를 효율적으로 처리하기 위해 보다 빠르고 가벼운 직렬화 포맷이 필요했습니다. 그 결과로 개발된 것이 바로 프로토콜 버퍼(Protobuf)입니다. Protobuf는 바이너리 포맷을 사용하여 데이터 크기를 줄이고, 엄격한 스키마를 통해 데이터 무결성을 보장하며, 다양한 언어와 플랫폼에서 사용 가능하도록 설계되었습니다&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. Protobuf란 무엇인가?&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정의 및 개념&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로토콜 버퍼(Protobuf)는 구글에서 개발한 언어 중립적, 플랫폼 중립적, 확장 가능한 직렬화 메커니즘입니다. 구조화된 데이터를 바이너리 형태로 직렬화하고 역직렬화하는 데 사용되며, 이는 데이터 전송과 저장을 효율적으로 만듭니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;역사와 개발 배경&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글은 2001년부터 내부적으로 Protobuf를 사용해 왔으며, 2008년에 오픈 소스로 공개하였습니다. 그 이후로 많은 기업과 개발자들이 Protobuf를 채택하여 사용하고 있으며, 이는 효율성과 확장성 측면에서 큰 장점을 제공하기 때문입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 왜 Protobuf를 사용해야 하는가?&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;성능 비교: Protobuf vs. JSON vs. XML&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;데이터 크기&lt;/b&gt;: Protobuf는 바이너리 포맷을 사용하므로 JSON이나 XML보다 데이터 크기가 훨씬 작습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;전송 속도&lt;/b&gt;: 데이터 크기가 작기 때문에 네트워크를 통한 전송 속도가 빠릅니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;파싱 속도&lt;/b&gt;: 바이너리 포맷은 파싱이 빠르며, 이는 애플리케이션의 응답 시간을 개선합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이터 크기와 전송 속도&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 동일한 데이터를 Protobuf와 JSON으로 직렬화했을 때 Protobuf는 JSON 대비 최대 10배까지 작은 크기를 가질 수 있습니다. 이는 특히 모바일 네트워크나 제한된 대역폭 환경에서 큰 이점을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확장성과 호환성&lt;br /&gt;Protobuf는 스키마를 사용하여 데이터 구조를 정의하기 때문에 새로운 필드를 추가하거나 기존 필드를 변경하더라도 하위 호환성을 유지할 수 있습니다. 이는 시스템 간의 통합과 업데이트를 용이하게 만듭니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. Protobuf의 작동 원리&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스키마 정의(.proto 파일)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Protobuf는 .proto 파일에서 데이터 구조를 정의합니다. 이 파일에서는 메시지 타입, 필드, 데이터 타입 등을 명시적으로 지정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로토콜 컴파일러의 역할&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로토콜 컴파일러(protoc)는 .proto 파일을 읽고, 지정된 언어(Java, C++, Python 등)의 코드로 컴파일합니다. 이 코드는 직렬화 및 역직렬화 메서드를 포함하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;직렬화 및 역직렬화 과정&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;직렬화: 애플리케이션에서 생성된 객체를 Protobuf 메시지로 변환하고, 이를 바이너리 형태로 직렬화합니다.&lt;/li&gt;
&lt;li&gt;역직렬화: 받은 바이너리 데이터를 Protobuf 메시지로 역직렬화하고, 이를 애플리케이션에서 사용할 수 있는 객체로 변환합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. Protobuf 메시지 정의하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기본 문법과 규칙&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.proto 파일은 특정한 문법을 따릅니다. 가장 먼저 Protobuf 버전을 지정해야 하며, 그 다음 메시지와 필드를 정의합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731034123993&quot; class=&quot;bash&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;syntax = &quot;proto3&quot;;

message MessageName {
// 필드 정의
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;데이터 타입과 필드 번호의 중요성&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 필드는 데이터 타입, 이름, 태그 번호를 가집니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;데이터 타입&lt;/b&gt;: int32, string, bool 등 다양한 기본 타입과 사용자 정의 메시지를 사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;태그 번호&lt;/b&gt;: 각 필드는 고유한 태그 번호를 가지며, 이는 바이너리 포맷에서 필드를 식별하는 데 사용됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1731034191580&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;message User {
	int32 id = 1;
	string name = 2;
	string email = 3;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;옵션 필드와 반복 필드&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;옵션 필드&lt;/b&gt;: 필드가 필수적이지 않으며, 값이 없을 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;반복 필드&lt;/b&gt;: 동일한 타입의 필드가 여러 개 있을 수 있으며, 이는 리스트로 취급됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1731034378425&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;message Group {
	repeated User members = 1;
   	optional string str_field = 2;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 프로토콜 컴파일러 사용하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;설치 및 설정 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;프로토콜 컴파일러는 공식 홈페이지나 패키지 매니저를 통해 설치할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식 홈페이지: &lt;a href=&quot;https://grpc.io/docs/protoc-installation/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://grpc.io/docs/protoc-installation/&lt;/a&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1731034572794&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ex)
MacOS: brew install protobuf
Ubuntu: sudo apt-get install protobuf-compiler&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;다양한 언어로 코드 생성하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.proto 파일을 컴파일하여 원하는 언어의 코드를 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 장점과 단점&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Protobuf의 강점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;효율성&lt;/b&gt;: 작은 데이터 크기와 빠른 직렬화/역직렬화 속도&lt;/li&gt;
&lt;li&gt;&lt;b&gt;엄격한 스키마&lt;/b&gt;: 데이터 구조의 명확한 정의로 인한 무결성 보장&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다양한 언어 지원&lt;/b&gt;: 다수의 프로그래밍 언어에서 사용 가능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;확장성&lt;/b&gt;: 필드 추가 및 변경에 대한 유연한 대처&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;고려해야 할 단점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;가독성 부족&lt;/b&gt;: 바이너리 포맷이므로 디버깅이나 로깅 시 어려움&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스키마 필요&lt;/b&gt;: 모든 통신 주체가 동일한 스키마를 공유해야 함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;학습 곡선&lt;/b&gt;: 새로운 도구와 개념에 대한 학습 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 시 주의사항&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스키마 관리에 신경 써야 하며, 버전 관리를 철저히 해야 합니다.&lt;br /&gt;보안 측면에서 데이터 암호화나 인증을 추가로 고려해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 결론&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Protobuf의 미래와 전망&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로토콜 버퍼는 고성능의 데이터 직렬화가 필요한 다양한 분야에서 널리 사용되고 있습니다. 특히 마이크로서비스, 모바일 앱, IoT 등 네트워크 효율이 중요한 영역에서 그 가치는 더욱 부각되고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;최종 요약 및 추천&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Protobuf는 데이터 전송의 효율성을 극대화하고, 시스템 간의 호환성과 확장성을 제공하는 강력한 도구입니다. 기존의 JSON이나 XML 기반의 통신에서 성능 이슈를 겪고 있다면, Protobuf를 도입하여 개선해 볼 것을 추천합니다.&lt;/p&gt;</description>
      <category>면접</category>
      <category>API 설계</category>
      <category>API 통신</category>
      <category>fastapi 통합</category>
      <category>protobuf</category>
      <category>Protocol Buffers</category>
      <category>구조화 데이터</category>
      <category>데이터 직렬화</category>
      <category>서버 개발</category>
      <category>성능 최적화</category>
      <category>프로토콜 버퍼</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/222</guid>
      <comments>https://systorage.tistory.com/entry/%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C-%EB%B2%84%ED%8D%BCprotobuf%EB%9E%80#entry222comment</comments>
      <pubDate>Fri, 8 Nov 2024 13:13:14 +0900</pubDate>
    </item>
    <item>
      <title>[AI] ONNX란</title>
      <link>https://systorage.tistory.com/entry/AI-ONNX%EB%9E%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;ONNX (Open Neural Network Exchange)는 다양한 딥러닝 및 머신러닝 프레임워크 간의 모델 호환성을 보장하는 오픈 소스 표준 형식입니다.&lt;br /&gt;Microsoft와 Facebook이 주도하여 개발한 ONNX는 PyTorch, TensorFlow, scikit-learn 등에서 학습된 모델을 변환해, 다른 프레임워크나 하드웨어에서 효율적인 추론을 수행할 수 있도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ONNX의 필요성과 장점&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 모델 호환성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ONNX는 다양한 프레임워크 간의 모델 변환을 간소화합니다. 예를 들어, PyTorch로 학습한 모델을 TensorFlow에서 실행하거나, ONNX Runtime을 통해 추론 성능을 가속화할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 고성능 추론&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ONNX Runtime은 GPU, CPU뿐만 아니라 FPGA, TPU와 같은 다양한 하드웨어를 지원해, 효율적인 추론을 수행할 수 있도록 최적화됩니다​.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3.&amp;nbsp;모델&amp;nbsp;배포의&amp;nbsp;유연성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ONNX는 클라우드 및 엣지 환경 모두에서 효율적인 AI 모델 배포를 지원하며, 메모리와 연산 성능이 제한된 장치에서도 유용합니다​.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. ONNX의 한계와 고려사항&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;최신 연산자 지원&lt;/b&gt;: ONNX는 프레임워크마다 **다른 연산자(operator)**를 지원하는데, 일부 최신 모델이나 복잡한 연산은 ONNX로 변환할 때 문제가 발생할 수 있습니다. 이러한 경우 모델의 호환성을 확인하고, 필요 시 맞춤형 최적화가 필요합니다​&lt;br /&gt;&lt;b&gt;학습&amp;nbsp;작업&amp;nbsp;한계&lt;/b&gt;: ONNX는 주로 추론 작업에 최적화되어 있으며, 학습 작업에서는 제한적입니다. 따라서 추론 중심의 워크플로에 적합합니다​&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5.&amp;nbsp;결론&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ONNX는 AI 모델의 호환성과 최적화를 지원하는 강력한 도구로, 다양한 프레임워크와 하드웨어에서 모델의 효율적인 배포와 추론 성능 향상을 가능하게 합니다.&lt;br /&gt;&amp;nbsp;이를&amp;nbsp;통해&amp;nbsp;모델&amp;nbsp;개발과&amp;nbsp;배포의&amp;nbsp;복잡성을&amp;nbsp;줄이고,&amp;nbsp;엣지&amp;nbsp;컴퓨팅&amp;nbsp;환경에서도&amp;nbsp;효율적으로&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;ONNX는&amp;nbsp;특히&amp;nbsp;추론&amp;nbsp;작업의&amp;nbsp;최적화에&amp;nbsp;강점을&amp;nbsp;가지며,&amp;nbsp;다양한&amp;nbsp;플랫폼에서&amp;nbsp;일관된&amp;nbsp;성능을&amp;nbsp;제공하는&amp;nbsp;표준&amp;nbsp;형식으로&amp;nbsp;자리잡고&amp;nbsp;있습니다.&lt;/p&gt;</description>
      <category>AI</category>
      <category>AI</category>
      <category>ONNX</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/221</guid>
      <comments>https://systorage.tistory.com/entry/AI-ONNX%EB%9E%80#entry221comment</comments>
      <pubDate>Tue, 5 Nov 2024 14:31:13 +0900</pubDate>
    </item>
    <item>
      <title>[Linux] E: Unable to locate package ~~</title>
      <link>https://systorage.tistory.com/entry/Linux-E-Unable-to-locate-package</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬&amp;nbsp;도커를&amp;nbsp;실행시키고&amp;nbsp;vim&amp;nbsp;패키지&amp;nbsp;설치중&amp;nbsp;아래와&amp;nbsp;같은&amp;nbsp;에러가&amp;nbsp;발생했다.&lt;br /&gt;해결해보자.&lt;br /&gt;unable&amp;nbsp;to&amp;nbsp;locate&amp;nbsp;package&amp;nbsp;vim&lt;br /&gt;&lt;br /&gt;apt&amp;nbsp;패키지&amp;nbsp;관리자가&amp;nbsp;vim&amp;nbsp;패키지를&amp;nbsp;찾을&amp;nbsp;수&amp;nbsp;없어서&amp;nbsp;발생하는&amp;nbsp;문제이다.&lt;br /&gt;패키지&amp;nbsp;목록을&amp;nbsp;업데이트하고&amp;nbsp;설치하면&amp;nbsp;해결된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;1.&amp;nbsp;패키지&amp;nbsp;목록&amp;nbsp;업데이트&lt;/h2&gt;
&lt;pre id=&quot;code_1730708916742&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apt-get update&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 패키지 설치&lt;/h2&gt;
&lt;pre id=&quot;code_1730708944109&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apt-get install vim&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Linux</category>
      <category>Linux</category>
      <category>package</category>
      <category>vim</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/220</guid>
      <comments>https://systorage.tistory.com/entry/Linux-E-Unable-to-locate-package#entry220comment</comments>
      <pubDate>Mon, 4 Nov 2024 17:29:41 +0900</pubDate>
    </item>
    <item>
      <title>[Linux] ubuntu에서 Swap 메모리를 활용한 메모리 부족 문제 해결</title>
      <link>https://systorage.tistory.com/entry/Linux-ubuntu%EC%97%90%EC%84%9C-Swap-%EB%A9%94%EB%AA%A8%EB%A6%AC%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%B6%80%EC%A1%B1-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;모델 변환 작업 진행중 서버 메모리가 부족해서 프로세스가 강제로 죽는 현상이 생겼습니다.&lt;br /&gt;이를&amp;nbsp;해결하기&amp;nbsp;위해&amp;nbsp;진행했던&amp;nbsp;작업&amp;nbsp;및&amp;nbsp;공부&amp;nbsp;정리입니다.&lt;br /&gt;&lt;br /&gt;Linux&amp;nbsp;서버나&amp;nbsp;시스템을&amp;nbsp;사용하다&amp;nbsp;보면,&amp;nbsp;메모리가&amp;nbsp;부족해지는&amp;nbsp;경우가&amp;nbsp;발생할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;이러한&amp;nbsp;상황에서&amp;nbsp;성능&amp;nbsp;저하를&amp;nbsp;방지하거나&amp;nbsp;시스템이&amp;nbsp;멈추지&amp;nbsp;않도록&amp;nbsp;스왑(Swap)&amp;nbsp;메모리를&amp;nbsp;추가하는&amp;nbsp;것이&amp;nbsp;효과적인&amp;nbsp;해결&amp;nbsp;방법입니다.&lt;br /&gt;이&amp;nbsp;글에서는&amp;nbsp;Swap&amp;nbsp;메모리의&amp;nbsp;개념과&amp;nbsp;설정&amp;nbsp;방법을&amp;nbsp;소개하고,&amp;nbsp;부족한&amp;nbsp;메모리를&amp;nbsp;관리하는&amp;nbsp;최적의&amp;nbsp;방안을&amp;nbsp;설명합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;Swap&amp;nbsp;메모리란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스왑 메모리는 물리적인 RAM이 부족할 때 디스크 공간을 일시적인 가상 메모리로 사용하는 기능입니다.&lt;br /&gt;메모리가&amp;nbsp;부족한&amp;nbsp;경우,&amp;nbsp;사용하지&amp;nbsp;않는&amp;nbsp;데이터를&amp;nbsp;RAM에서&amp;nbsp;스왑&amp;nbsp;공간으로&amp;nbsp;옮기고&amp;nbsp;필요한&amp;nbsp;프로세스를&amp;nbsp;실행하는&amp;nbsp;데&amp;nbsp;메모리를&amp;nbsp;할당합니다.&lt;br /&gt;하지만&amp;nbsp;스왑&amp;nbsp;메모리는&amp;nbsp;디스크를&amp;nbsp;사용하기&amp;nbsp;때문에&amp;nbsp;속도가&amp;nbsp;느리다는&amp;nbsp;단점이&amp;nbsp;있다.&lt;br /&gt;그럼에도&amp;nbsp;불구하고,&amp;nbsp;메모리&amp;nbsp;부족으로&amp;nbsp;인한&amp;nbsp;시스템&amp;nbsp;크래시나&amp;nbsp;성능&amp;nbsp;저하를&amp;nbsp;방지하는&amp;nbsp;중요한&amp;nbsp;역할을&amp;nbsp;한다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1730704220181&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 현재 메모리 확인
free -h&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;607&quot; data-origin-height=&quot;82&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yhR1s/btsKv4XEGhl/JjALiYbmQtzk8vlloyrOtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yhR1s/btsKv4XEGhl/JjALiYbmQtzk8vlloyrOtk/img.png&quot; data-alt=&quot;메모리 정보&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yhR1s/btsKv4XEGhl/JjALiYbmQtzk8vlloyrOtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyhR1s%2FbtsKv4XEGhl%2FJjALiYbmQtzk8vlloyrOtk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;607&quot; height=&quot;82&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;607&quot; data-origin-height=&quot;82&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;메모리 정보&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;스왑&amp;nbsp;메모리&amp;nbsp;설정&amp;nbsp;방법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Swap 파일 생성하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 스왑 파일을 생성하여 사용할 디스크 공간을 확보합니다. 아래 명령어를 통해 4GB 크기의 스왑 파일을 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1730704831373&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo fallocate -l 4G /swapfile&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;fallocate&amp;nbsp;명령어는&amp;nbsp;빠르게&amp;nbsp;빈&amp;nbsp;파일을&amp;nbsp;생성합니다.&lt;br /&gt;/swapfile&amp;nbsp;경로는&amp;nbsp;스왑&amp;nbsp;파일의&amp;nbsp;위치를&amp;nbsp;나타내며,&amp;nbsp;원하는&amp;nbsp;이름과&amp;nbsp;경로로&amp;nbsp;변경할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;2.&amp;nbsp;Swap&amp;nbsp;파일&amp;nbsp;권한&amp;nbsp;설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보안 문제를 방지하기 위해 스왑 파일의 권한을 600으로 설정합니다. 이는 오직 관리자(root)만이 이 파일에 접근할 수 있도록 제한합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1730704864213&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo chmod 600 /swapfile&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;3.&amp;nbsp;Swap&amp;nbsp;파일&amp;nbsp;초기화&amp;nbsp;및&amp;nbsp;활성화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 스왑 파일을 스왑 영역으로 사용하기 위해 초기화합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1730704877968&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo mkswap /swapfile&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;그&amp;nbsp;후,&amp;nbsp;스왑&amp;nbsp;메모리를&amp;nbsp;활성화합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1730704883020&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo swapon /swapfile&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.&amp;nbsp;스왑&amp;nbsp;메모리&amp;nbsp;확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스왑 메모리가 제대로 활성화되었는지 확인하려면 다음 명령어를 사용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1730704900195&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;swapon --show&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이&amp;nbsp;명령어는&amp;nbsp;현재&amp;nbsp;활성화된&amp;nbsp;스왑&amp;nbsp;영역의&amp;nbsp;정보를&amp;nbsp;보여줍니다.&lt;br /&gt;free&amp;nbsp;-h&amp;nbsp;로&amp;nbsp;스왑&amp;nbsp;메모리가&amp;nbsp;늘어난걸&amp;nbsp;확인할&amp;nbsp;수도&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;{BE7D7BDB-572D-4864-A421-715F62330A60}.png&quot; data-origin-width=&quot;594&quot; data-origin-height=&quot;120&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwemf5/btsKv7GPTEN/ef87kFJBH1v64KS6nqgunK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwemf5/btsKv7GPTEN/ef87kFJBH1v64KS6nqgunK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwemf5/btsKv7GPTEN/ef87kFJBH1v64KS6nqgunK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcwemf5%2FbtsKv7GPTEN%2Fef87kFJBH1v64KS6nqgunK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;594&quot; height=&quot;120&quot; data-filename=&quot;{BE7D7BDB-572D-4864-A421-715F62330A60}.png&quot; data-origin-width=&quot;594&quot; data-origin-height=&quot;120&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 부팅 시 스왑 메모리 자동 활성화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재부팅 후에도 스왑 메모리가 유지되도록 /etc/fstab 파일에 스왑 파일을 추가합니다. 다음 명령어로 파일을 열어 편집합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1730704924478&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo vim /etc/fstab&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;파일의 맨 아래에 다음 내용을 추가합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1730704937097&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/swapfile none swap sw 0 0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제&amp;nbsp;저장하고&amp;nbsp;나가면&amp;nbsp;시스템이&amp;nbsp;재부팅될&amp;nbsp;때&amp;nbsp;자동으로&amp;nbsp;스왑&amp;nbsp;메모리를&amp;nbsp;활성화합니다.&lt;br /&gt;재부팅&amp;nbsp;후&amp;nbsp;다시&lt;br /&gt;free&amp;nbsp;-h&amp;nbsp;로&amp;nbsp;확인&amp;nbsp;할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;추가적인&amp;nbsp;메모리&amp;nbsp;최적화&amp;nbsp;방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;불필요한 프로세스 종료:&lt;/b&gt; 메모리를 많이 사용하는 프로세스를 확인하고 종료합니다.&lt;br /&gt;&lt;b&gt;캐시&amp;nbsp;정리:&lt;/b&gt; 디스크&amp;nbsp;캐시가&amp;nbsp;메모리를&amp;nbsp;차지하는&amp;nbsp;경우,&amp;nbsp;다음&amp;nbsp;명령어로&amp;nbsp;캐시를&amp;nbsp;정리할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1730704975351&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo sync; sudo sysctl -w vm.drop_caches=3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;메모리&amp;nbsp;업그레이드&lt;/b&gt;:&amp;nbsp;물리적인&amp;nbsp;RAM을&amp;nbsp;추가하는&amp;nbsp;것이&amp;nbsp;근본적인&amp;nbsp;해결책이&amp;nbsp;될&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Linux 환경에서 메모리 부족 문제를 해결하는 데 있어 스왑 메모리 추가는 유용한 방법입니다.&lt;br /&gt;스왑&amp;nbsp;파일을&amp;nbsp;생성하고&amp;nbsp;설정하는&amp;nbsp;과정은&amp;nbsp;간단하며,&amp;nbsp;시스템의&amp;nbsp;안정성을&amp;nbsp;높이는&amp;nbsp;데&amp;nbsp;큰&amp;nbsp;도움을&amp;nbsp;줍니다.&lt;br /&gt;다만,&amp;nbsp;스왑&amp;nbsp;메모리는&amp;nbsp;속도가&amp;nbsp;느리기&amp;nbsp;때문에&amp;nbsp;RAM을&amp;nbsp;대체할&amp;nbsp;수는&amp;nbsp;없으며,&amp;nbsp;물리적인&amp;nbsp;메모리&amp;nbsp;추가도&amp;nbsp;함께&amp;nbsp;고려하는&amp;nbsp;것이&amp;nbsp;좋습니다.&lt;br /&gt;스왑&amp;nbsp;메모리&amp;nbsp;설정은&amp;nbsp;메모리&amp;nbsp;부족&amp;nbsp;상황에서&amp;nbsp;중요한&amp;nbsp;역할을&amp;nbsp;하므로,&amp;nbsp;필요에&amp;nbsp;따라&amp;nbsp;적절히&amp;nbsp;설정하고&amp;nbsp;관리하는&amp;nbsp;습관을&amp;nbsp;가지는&amp;nbsp;것이&amp;nbsp;좋습니다.&lt;br /&gt;&lt;br /&gt;추가)&amp;nbsp;swap&amp;nbsp;메모리를&amp;nbsp;과도하게&amp;nbsp;사용하면&amp;nbsp;안되는&amp;nbsp;이유&lt;br /&gt;&lt;a href=&quot;https://systorage.tistory.com/entry/OS-%EA%B0%80%EC%83%81-%EB%A9%94%EB%AA%A8%EB%A6%ACswap-%EC%82%AC%EC%9A%A9-%EC%8B%9C-CPU-%EC%A0%90%EC%9C%A0%EC%9C%A8%EC%9D%B4-%ED%8F%AD%EC%A6%9D%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://systorage.tistory.com/entry/OS-%EA%B0%80%EC%83%81-%EB%A9%94%EB%AA%A8%EB%A6%ACswap-%EC%82%AC%EC%9A%A9-%EC%8B%9C-CPU-%EC%A0%90%EC%9C%A0%EC%9C%A8%EC%9D%B4-%ED%8F%AD%EC%A6%9D%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1730704354609&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[OS] 가상 메모리(swap) 사용 시 CPU 점유율이 폭증하는 이유&quot; data-og-description=&quot;연구팀을 위해 데이터를 뽑는 도중 큰 데이터를 뽑다가 서버를 터트렸다. 해당 원인에 대해서 공부했던 내용에 대해서 서술한다. 가상 메모리(swap)란? 가상 메모리는 물리적인 RAM이 부족할 때 디&quot; data-og-host=&quot;systorage.tistory.com&quot; data-og-source-url=&quot;https://systorage.tistory.com/entry/OS-%EA%B0%80%EC%83%81-%EB%A9%94%EB%AA%A8%EB%A6%ACswap-%EC%82%AC%EC%9A%A9-%EC%8B%9C-CPU-%EC%A0%90%EC%9C%A0%EC%9C%A8%EC%9D%B4-%ED%8F%AD%EC%A6%9D%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0&quot; data-og-url=&quot;https://systorage.tistory.com/entry/OS-%EA%B0%80%EC%83%81-%EB%A9%94%EB%AA%A8%EB%A6%ACswap-%EC%82%AC%EC%9A%A9-%EC%8B%9C-CPU-%EC%A0%90%EC%9C%A0%EC%9C%A8%EC%9D%B4-%ED%8F%AD%EC%A6%9D%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/wmRIN/hyXs2yPmg3/H056KYgG0izDlpl4gN9rMK/img.png?width=640&amp;amp;height=640&amp;amp;face=0_0_640_640,https://scrap.kakaocdn.net/dn/tuzXh/hyXs08QcEh/8NDuSLQgUbkzsGxH3xsNs1/img.png?width=640&amp;amp;height=640&amp;amp;face=0_0_640_640&quot;&gt;&lt;a href=&quot;https://systorage.tistory.com/entry/OS-%EA%B0%80%EC%83%81-%EB%A9%94%EB%AA%A8%EB%A6%ACswap-%EC%82%AC%EC%9A%A9-%EC%8B%9C-CPU-%EC%A0%90%EC%9C%A0%EC%9C%A8%EC%9D%B4-%ED%8F%AD%EC%A6%9D%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://systorage.tistory.com/entry/OS-%EA%B0%80%EC%83%81-%EB%A9%94%EB%AA%A8%EB%A6%ACswap-%EC%82%AC%EC%9A%A9-%EC%8B%9C-CPU-%EC%A0%90%EC%9C%A0%EC%9C%A8%EC%9D%B4-%ED%8F%AD%EC%A6%9D%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/wmRIN/hyXs2yPmg3/H056KYgG0izDlpl4gN9rMK/img.png?width=640&amp;amp;height=640&amp;amp;face=0_0_640_640,https://scrap.kakaocdn.net/dn/tuzXh/hyXs08QcEh/8NDuSLQgUbkzsGxH3xsNs1/img.png?width=640&amp;amp;height=640&amp;amp;face=0_0_640_640');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[OS] 가상 메모리(swap) 사용 시 CPU 점유율이 폭증하는 이유&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;연구팀을 위해 데이터를 뽑는 도중 큰 데이터를 뽑다가 서버를 터트렸다. 해당 원인에 대해서 공부했던 내용에 대해서 서술한다. 가상 메모리(swap)란? 가상 메모리는 물리적인 RAM이 부족할 때 디&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;systorage.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Linux</category>
      <category>Linux</category>
      <category>memory</category>
      <category>swap</category>
      <category>메모리</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/219</guid>
      <comments>https://systorage.tistory.com/entry/Linux-ubuntu%EC%97%90%EC%84%9C-Swap-%EB%A9%94%EB%AA%A8%EB%A6%AC%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%B6%80%EC%A1%B1-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0#entry219comment</comments>
      <pubDate>Mon, 4 Nov 2024 16:26:45 +0900</pubDate>
    </item>
    <item>
      <title>[MSA] MSA란? MSA의 장 / 단점</title>
      <link>https://systorage.tistory.com/entry/MSA-MSA%EB%9E%80-MSA%EC%9D%98-%EC%9E%A5-%EB%8B%A8%EC%A0%90</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;마이크로서비스 아키텍처(Microservice Architecture, MSA)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마이크로서비스 아키텍처(MSA)는 소프트웨어 시스템을 작은 독립적인 서비스로 분리하여 각 서비스가 독립적으로 개발, 배포, 확장 및 관리되도록 설계된 아키텍처입니다. 각 마이크로서비스는 특정 도메인이나 비즈니스 기능을 담당하며, 다른 서비스와는 API나 메시지 큐를 통해 통신합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전통적인 모놀리식 아키텍처에서 모든 기능이 하나의 큰 시스템에 포함되는 것과 달리, MSA는 각 기능을 독립된 단위로 나누어 시스템의 유연성과 확장성을 극대화하는 데 초점을 둡니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;MSA의 주요 특징&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;독립성&lt;/b&gt;: 각 마이크로서비스는 독립적으로 개발, 배포, 그리고 확장이 가능하며, 다른 서비스에 영향을 주지 않고 업데이트할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;분산 시스템&lt;/b&gt;: 마이크로서비스는 분산 시스템의 형태를 띄고 있으며, 서비스 간 통신은 주로 REST API, gRPC, 메시지 큐 등을 통해 이루어집니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다양한 기술 스택&lt;/b&gt;: 각 마이크로서비스는 개별적으로 선택된 프로그래밍 언어, 데이터베이스, 프레임워크를 사용할 수 있어, 각 서비스에 최적화된 기술을 선택할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;작은 규모&lt;/b&gt;: 마이크로서비스는 각각 작은 단위로 나뉘어 있으며, 하나의 서비스가 특정 기능만을 담당하는 구조입니다. 이는 코드베이스가 작아져 유지보수가 용이해집니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점:&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;독립적 배포&lt;/b&gt;: 각 서비스가 독립적으로 배포 및 확장이 가능하여 빠른 개발과 배포가 가능합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유연성&lt;/b&gt;: 다양한 기술 스택을 사용하여 각 서비스에 최적화된 기술을 선택할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;탄력성&lt;/b&gt;: 한 서비스의 장애가 전체 시스템에 영향을 미치지 않도록 격리할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점:&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;복잡성 증가&lt;/b&gt;: 서비스 간 통신, 데이터 일관성 유지 등이 복잡해질 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;배포 및 관리 어려움&lt;/b&gt;: 다수의 서비스가 존재하기 때문에 배포, 모니터링, 로깅 등이 어려워질 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;네트워크 지연&lt;/b&gt;: 서비스 간 통신이 네트워크를 통해 이루어지므로 지연이 발생할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>면접</category>
      <category>MSA</category>
      <category>면접</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/218</guid>
      <comments>https://systorage.tistory.com/entry/MSA-MSA%EB%9E%80-MSA%EC%9D%98-%EC%9E%A5-%EB%8B%A8%EC%A0%90#entry218comment</comments>
      <pubDate>Sat, 12 Oct 2024 14:16:12 +0900</pubDate>
    </item>
    <item>
      <title>Typescript Omit과 Partial 의 차이점</title>
      <link>https://systorage.tistory.com/entry/Typescript-Omit%EA%B3%BC-Partial-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript는 정적 타입을 지원하여 코드의 안정성과 유지보수성을 높이는 데 도움을 줍니다. 이 중에서도 &lt;code&gt;Omit&lt;/code&gt;과 &lt;code&gt;Partial&lt;/code&gt;은 매우 유용한 유틸리티 타입으로, 각각 객체 타입을 변형하는 데 사용됩니다. 이번 글에서는 &lt;code&gt;Omit&lt;/code&gt;과 &lt;code&gt;Partial&lt;/code&gt;의 차이점을 자세히 설명하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Partial&amp;lt;T&amp;gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Partial&lt;/code&gt; 유틸리티 타입은 주어진 타입 &lt;code&gt;T&lt;/code&gt;의 모든 프로퍼티를 선택적으로 만듭니다. 즉, 모든 프로퍼티가 있어도 되고 없어도 되는 상태가 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 예시&lt;/h3&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;interface User {
    id: number;
    name: string;
    email: string;
}

type PartialUser = Partial&amp;lt;User&amp;gt;;

const user1: PartialUser = {};
const user2: PartialUser = { id: 1 };
const user3: PartialUser = { name: 'Alice', email: 'alice@example.com' };&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;특징&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 프로퍼티가 선택적(Optional)으로 변환됩니다.&lt;/li&gt;
&lt;li&gt;주로 객체의 일부 프로퍼티만 업데이트할 때 유용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Omit&amp;lt;T, K&amp;gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Omit&lt;/code&gt; 유틸리티 타입은 주어진 타입 &lt;code&gt;T&lt;/code&gt;에서 특정 프로퍼티 &lt;code&gt;K&lt;/code&gt;를 제거한 새로운 타입을 만듭니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 예시:&lt;/h3&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;interface User {
    id: number;
    name: string;
    email: string;
}

type UserWithoutEmail = Omit&amp;lt;User, 'email'&amp;gt;;

const user: UserWithoutEmail = { id: 1, name: 'Alice' };&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;특징&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주어진 타입에서 특정 프로퍼티를 제거하여 새로운 타입을 만듭니다.&lt;/li&gt;
&lt;li&gt;주로 특정 프로퍼티를 제외한 나머지 프로퍼티만 필요할 때 유용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;차이점 정리&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;변형 방식&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt;: 모든 프로퍼티를 선택적으로 만듭니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Omit&amp;lt;T, K&amp;gt;&lt;/code&gt;: 특정 프로퍼티를 제거하여 새로운 타입을 만듭니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사용 목적&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt;: 객체의 일부만 업데이트하거나, 선택적인 프로퍼티를 가질 때 사용합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Omit&amp;lt;T, K&amp;gt;&lt;/code&gt;: 불필요한 프로퍼티를 제거하고 필요한 프로퍼티만 가지는 타입을 만들 때 사용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시 적용 상황&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt;: API 요청에서 선택적인 업데이트 데이터를 보낼 때.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Omit&amp;lt;T, K&amp;gt;&lt;/code&gt;: 데이터베이스 엔터티에서 민감한 정보를 제외한 데이터를 반환할 때.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Partial&lt;/code&gt;과 &lt;code&gt;Omit&lt;/code&gt;은 TypeScript에서 객체 타입을 변형하는 데 매우 유용한 도구입니다. &lt;code&gt;Partial&lt;/code&gt;은 모든 프로퍼티를 선택적으로 만들어 부분 업데이트나 선택적 프로퍼티를 다룰 때 유용하고, &lt;code&gt;Omit&lt;/code&gt;은 특정 프로퍼티를 제거하여 필요한 데이터만 다룰 때 유용합니다. 각 유틸리티 타입의 특징과 사용 목적을 잘 이해하고 적절하게 활용하면 더욱 안정적이고 유지보수하기 쉬운 코드를 작성할 수 있습니다.&lt;/p&gt;</description>
      <category>Programming/Typescript</category>
      <category>omit</category>
      <category>partial</category>
      <category>TypeScript</category>
      <category>소프트웨어 개발</category>
      <category>웹 개발</category>
      <category>유틸리티 타입</category>
      <category>코드 품질</category>
      <category>타입 변형</category>
      <category>타입스크립트 사용법</category>
      <category>프로그래밍</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/215</guid>
      <comments>https://systorage.tistory.com/entry/Typescript-Omit%EA%B3%BC-Partial-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90#entry215comment</comments>
      <pubDate>Thu, 8 Aug 2024 17:14:35 +0900</pubDate>
    </item>
    <item>
      <title>마이크로서비스 아키텍처(MSA)에서 모듈 간 통신 방법</title>
      <link>https://systorage.tistory.com/entry/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98MSA%EC%97%90%EC%84%9C-%EB%AA%A8%EB%93%88-%EA%B0%84-%ED%86%B5%EC%8B%A0-%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;마이크로서비스 아키텍처(MSA)는 각각의 독립적인 서비스들이 서로 협력하여 전체 시스템을 구성하는 구조입니다. 이러한 서비스들 간의 통신은 MSA의 핵심 요소 중 하나이며, 이를 효율적으로 설계하는 것이 중요합니다. 이번 블로그 글에서는 MSA에서 각 모듈 간 통신 방법에 대해 자세히 설명하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 동기 통신 (Synchronous Communication)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.1 HTTP/REST&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 일반적인 통신 방법으로, RESTful API를 사용하여 서비스 간 HTTP 요청과 응답을 주고받습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;: 간단하고 이해하기 쉬움, 웹 표준 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;: 높은 레이턴시, 네트워크 장애 시 서비스 중단 가능성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP/REST는 대부분의 웹 애플리케이션에서 사용되는 방식으로, 서비스 간의 데이터를 주고받는 데 있어 가장 직관적이고 널리 사용됩니다. 특히 JSON 포맷을 주로 사용하여 데이터를 직렬화하며, 다양한 언어와 프레임워크에서 쉽게 구현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.2 gRPC&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글이 개발한 고성능 RPC 프레임워크로, HTTP/2를 사용하여 통신합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 장점&lt;/b&gt;: 성능이 좋고, 양방향 스트리밍 가능, 프로토콜 버퍼 사용으로 데이터 직렬화 효율성 높음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;: 설정이 복잡하고, REST에 비해 상대적으로 덜 친숙함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gRPC는 서비스 간 통신에서 높은 성능과 효율성을 제공합니다. 특히, 큰 데이터 세트와 빈번한 호출이 필요한 경우 유리합니다. 또한, 프로토콜 버퍼(Protocol Buffers)를 사용하여 직렬화 효율성을 극대화합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 비동기 통신 (Asynchronous Communication)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.1 메시지 큐 (Message Queue)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RabbitMQ, Apache Kafka와 같은 메시지 큐 시스템을 사용하여 서비스 간 비동기적으로 메시지를 전달합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;: 높은 확장성, 비동기적 처리로 인해 서비스 독립성 향상, 메시지 손실 방지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;: 복잡한 설정과 운영 관리, 메시지 지연 발생 가능성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메시지 큐를 사용하면 서비스 간의 강한 결합을 피하고, 각 서비스가 독립적으로 동작할 수 있습니다. 이는 서비스 장애가 다른 서비스에 영향을 미치지 않도록 하며, 높은 트래픽 상황에서도 안정적인 처리를 보장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.2 이벤트 스트리밍 (Event Streaming)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Apache Kafka, Amazon Kinesis와 같은 시스템을 사용하여 이벤트 기반으로 데이터 스트림을 처리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;: 실시간 데이터 처리, 높은 처리량, 데이터 복구 및 재처리 용이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;: 설정과 운영의 복잡성, 데이터 일관성 관리 어려움&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트 스트리밍은 대용량의 실시간 데이터를 처리하는 데 적합하며, 이벤트 소싱(event sourcing) 패턴을 구현할 때 유용합니다. 각 이벤트는 시스템의 상태 변화를 나타내며, 이러한 이벤트들을 스트림 형태로 처리하여 실시간 분석 및 모니터링에 활용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 서비스 디스커버리 (Service Discovery)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3.1 클라이언트 사이드 디스커버리 (Client-Side Discovery)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트가 직접 서비스 레지스트리를 조회하여 사용할 서비스의 위치를 결정하는 방식입니다. 예를 들어, Netflix의 Eureka가 대표적인 도구입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;: 간단한 구현, 클라이언트의 유연성 증가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;: 클라이언트의 복잡성 증가, 클라이언트와 서비스 레지스트리 간의 통신 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3.2 서버 사이드 디스커버리 (Server-Side Discovery)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트 요청이 로드 밸런서를 거쳐 서비스 레지스트리를 조회하고, 적절한 서비스 인스턴스로 요청을 라우팅하는 방식입니다. 예를 들어, AWS의 Elastic Load Balancer가 대표적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;: 클라이언트의 단순화, 중앙 집중식 로드 밸런싱&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;: 로드 밸런서의 복잡성 증가, 추가적인 네트워크 홉 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. API Gateway API&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게이트웨이는 모든 서비스 요청을 단일 진입점에서 처리하고, 각 서비스로 요청을 라우팅합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;: 중앙 집중식 인증 및 권한 관리, 로깅 및 모니터링 용이, CORS 처리 등 다양한 기능 제공&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;: 단일 장애 지점(Single Point of Failure) 가능성, 성능 병목 발생 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API Gateway는 마이크로서비스 아키텍처에서 매우 중요한 역할을 하며, 다양한 기능을 통해 서비스 간 통신을 효율적으로 관리하고 보안성을 높일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSA에서 각 모듈 간 통신은 시스템의 성능과 안정성에 큰 영향을 미칩니다. 동기 통신과 비동기 통신 방식, 서비스 디스커버리, API 게이트웨이 등 다양한 통신 방법을 적절히 조합하여 사용함으로써 마이크로서비스 간의 효율적인 협업을 구현할 수 있습니다. 각 통신 방법의 장단점을 이해하고, 시스템의 요구사항에 맞게 최적의 방식을 선택하는 것이 중요합니다.&lt;/p&gt;</description>
      <category>면접</category>
      <category>gRPC</category>
      <category>HTTP</category>
      <category>MSA</category>
      <category>REST</category>
      <category>동기 통신</category>
      <category>마이크로서비스 아키텍처</category>
      <category>메시지 큐</category>
      <category>비동기 통신</category>
      <category>서비스 통신</category>
      <category>이벤트 스트리밍</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/214</guid>
      <comments>https://systorage.tistory.com/entry/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98MSA%EC%97%90%EC%84%9C-%EB%AA%A8%EB%93%88-%EA%B0%84-%ED%86%B5%EC%8B%A0-%EB%B0%A9%EB%B2%95#entry214comment</comments>
      <pubDate>Thu, 8 Aug 2024 17:08:16 +0900</pubDate>
    </item>
    <item>
      <title>서버로 파일을 전송하는 여러가지 방법</title>
      <link>https://systorage.tistory.com/entry/%EC%84%9C%EB%B2%84%EB%A1%9C-%ED%8C%8C%EC%9D%BC%EC%9D%84-%EC%A0%84%EC%86%A1%ED%95%98%EB%8A%94-%EC%97%AC%EB%9F%AC%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;파일&amp;nbsp;전송은&amp;nbsp;서버와&amp;nbsp;클라이언트&amp;nbsp;간의&amp;nbsp;중요한&amp;nbsp;기능&amp;nbsp;중&amp;nbsp;하나입니다.&amp;nbsp;다양한&amp;nbsp;방식으로&amp;nbsp;파일을&amp;nbsp;전송할&amp;nbsp;수&amp;nbsp;있으며,&amp;nbsp;각각의&amp;nbsp;방식은&amp;nbsp;특정한&amp;nbsp;요구&amp;nbsp;사항과&amp;nbsp;상황에&amp;nbsp;맞게&amp;nbsp;선택될&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;아래에서는&amp;nbsp;여러&amp;nbsp;가지&amp;nbsp;파일&amp;nbsp;전송&amp;nbsp;방법에&amp;nbsp;대해&amp;nbsp;자세히&amp;nbsp;설명합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HTTP 파일 업로드&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTML Form과 multipart/form-data를 이용한 전송&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML 폼을 사용하여 파일을 업로드하는 가장 일반적인 방법입니다. 이 방식은 multipart/form-data 인코딩 타입을 사용하여 파일을 전송합니다. 클라이언트는 파일을 포함한 폼 데이터를 서버로 전송하고, 서버는 이를 받아 처리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;REST API와 파일 업로드 라이브러리 사용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REST API를 통해 파일을 업로드하는 방법입니다. 서버에서는 파일 업로드를 처리하기 위해 Multer와 같은 라이브러리를 사용합니다. 클라이언트는 multipart/form-data 형식으로 파일을 전송하며, 서버는 이를 받아 저장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;WebSocket을 통한 파일 전송&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WebSocket을 이용하면 양방향 실시간 데이터 전송이 가능합니다. 이는 실시간 파일 전송이 필요한 애플리케이션에 적합합니다. WebSocket은 지속적인 연결을 유지하여 데이터가 빠르게 전송될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;FTP(File Transfer Protocol)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FTP는 파일 전송을 위한 전통적인 프로토콜입니다. FTP 서버를 설정하고, FTP 클라이언트를 통해 파일을 전송할 수 있습니다. FTP는 주로 대용량 파일 전송에 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SFTP(Secure File Transfer Protocol)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SFTP는 SSH 기반의 보안 파일 전송 프로토콜입니다. FTP와 달리 암호화된 채널을 통해 파일을 전송하여 보안을 강화합니다. 주로 보안이 중요한 환경에서 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Chunked File Upload&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 작은 청크로 나누어 부분적으로 전송한 후 서버에서 재조립하는 방법입니다. 이는 대용량 파일 전송 시 유용하며, 네트워크 상태가 불안정한 경우에도 효과적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Cloud Storage Services&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS S3, Google Cloud Storage, Azure Blob Storage와 같은 클라우드 스토리지 서비스를 이용한 파일 업로드 방법입니다. 클라이언트는 클라우드 스토리지 서비스의 API를 사용하여 파일을 업로드합니다. 이는 높은 가용성과 확장성을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;RPC(Remote Procedure Call) 프로토콜&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gRPC와 같은 RPC 프로토콜을 이용한 파일 전송 방법입니다. RPC는 함수 호출을 통해 원격 서버와 통신할 수 있게 해주며, 파일 전송 시에도 사용될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;P2P(Peer-to-Peer) 파일 전송&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WebRTC와 같은 P2P 기술을 이용하여 클라이언트 간 파일을 직접 전송한 후 서버에 전달하는 방법입니다. 이는 서버 부하를 줄이고, 빠른 파일 전송을 가능하게 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SMB(Server Message Block) 또는 NFS(Network File System)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네트워크 파일 시스템을 사용하여 파일을 공유하고 전송하는 방법입니다. 이는 주로 내부 네트워크에서 파일을 공유할 때 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Command Line Tools&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;scp, rsync 등의 명령줄 도구를 이용한 파일 전송 방법입니다. 이는 주로 서버 관리자가 파일을 전송할 때 사용되며, 스크립트를 통해 자동화할 수도 있습니다.&lt;br /&gt;&lt;br /&gt;이처럼&amp;nbsp;다양한&amp;nbsp;파일&amp;nbsp;전송&amp;nbsp;방법이&amp;nbsp;있으며,&amp;nbsp;각각의&amp;nbsp;방법은&amp;nbsp;특정한&amp;nbsp;요구&amp;nbsp;사항과&amp;nbsp;상황에&amp;nbsp;맞게&amp;nbsp;선택될&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;적절한&amp;nbsp;파일&amp;nbsp;전송&amp;nbsp;방식을&amp;nbsp;선택하여&amp;nbsp;효율적이고&amp;nbsp;안전한&amp;nbsp;파일&amp;nbsp;전송을&amp;nbsp;구현할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;</description>
      <category>면접</category>
      <category>chunkedupload</category>
      <category>ftp</category>
      <category>http업로드</category>
      <category>rest api</category>
      <category>RPC</category>
      <category>sftp</category>
      <category>websocket</category>
      <category>서버개발</category>
      <category>클라우드스토리지</category>
      <category>파일전송</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/213</guid>
      <comments>https://systorage.tistory.com/entry/%EC%84%9C%EB%B2%84%EB%A1%9C-%ED%8C%8C%EC%9D%BC%EC%9D%84-%EC%A0%84%EC%86%A1%ED%95%98%EB%8A%94-%EC%97%AC%EB%9F%AC%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95#entry213comment</comments>
      <pubDate>Tue, 6 Aug 2024 12:55:29 +0900</pubDate>
    </item>
    <item>
      <title>버블 정렬, 선택 정렬, 삽입 정렬 비교</title>
      <link>https://systorage.tistory.com/entry/%EB%B2%84%EB%B8%94-%EC%A0%95%EB%A0%AC-%EC%84%A0%ED%83%9D-%EC%A0%95%EB%A0%AC-%EC%82%BD%EC%9E%85-%EC%A0%95%EB%A0%AC-%EB%B9%84%EA%B5%90</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;정렬&amp;nbsp;알고리즘의&amp;nbsp;Big&amp;nbsp;O&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;알고리즘&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;시간 복잡도 (Best)&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;시간 복잡도 (Average)&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;시간 복잡도 (Worst)&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;공간 복잡도&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;버블 정렬&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;O(n)&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;O(n^2)&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;O(n^2)&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;삽입 정렬&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;O(n)&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;O(n^2)&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;O(n^2)&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;선택 정렬&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;O(n^2)&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;O(n^2)&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;O(n^2)&lt;/td&gt;
&lt;td style=&quot;width: 20%; text-align: center;&quot;&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 이 세 가지 정렬 알고리즘은 2차 정렬 알고리즘이라고 불립니다. 이는 시간 복잡도가 O(n^2) 이기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버블 정렬, 삽입 정렬의 경우 정렬이 거의 다 되어있으면 시간 복잡도가 O(N) 입니다. (Best)&lt;br /&gt;하지만 선택 정렬의 경우 최솟값을 찾기위해 끝까지 다 보기 때문에 모든 경우에서 O(n^2) 입니다. (Best)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;요약&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정렬은 기본입니다.&lt;/li&gt;
&lt;li&gt;버블 정렬, 선택 정렬, 삽입 정렬은 모두 대략 비슷합니다.&lt;/li&gt;
&lt;li&gt;모두 평균 시간 복잡도가 이차적입니다.&lt;/li&gt;
&lt;li&gt;우리는 더 나은 방법을 찾을 수 있지만, 더 복잡한 알고리즘이 필요합니다.&lt;/li&gt;
&lt;li&gt;데이터 셋이 매우 작을 때 효과적입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버블 정렬, 선택 정렬, 삽입 정렬은 모두 시간 복잡도가 O(n^2)인 기본적인 정렬 알고리즘입니다. 작은 데이터 셋에서는 효과적이지만, 큰 데이터 셋에서는 비효율적일 수 있습니다. 따라서 더 나은 성능을 위해서는 퀵 정렬, 병합 정렬 등의 복잡한 알고리즘을 고려해야 합니다. 이 글에서는 세 가지 기본 정렬 알고리즘의 작동 방식과 시간 복잡도를 비교하여 정리했습니다.&lt;/p&gt;</description>
      <category>Algorithm/Theory</category>
      <category>bigo</category>
      <category>데이터구조</category>
      <category>버블정렬</category>
      <category>삽입정렬</category>
      <category>선택정렬</category>
      <category>시간복잡도</category>
      <category>알고리즘비교</category>
      <category>정렬알고리즘</category>
      <category>코딩기초</category>
      <category>프로그래밍</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/212</guid>
      <comments>https://systorage.tistory.com/entry/%EB%B2%84%EB%B8%94-%EC%A0%95%EB%A0%AC-%EC%84%A0%ED%83%9D-%EC%A0%95%EB%A0%AC-%EC%82%BD%EC%9E%85-%EC%A0%95%EB%A0%AC-%EB%B9%84%EA%B5%90#entry212comment</comments>
      <pubDate>Fri, 19 Jul 2024 17:28:05 +0900</pubDate>
    </item>
    <item>
      <title>삽입 정렬 (Insertion Sort)</title>
      <link>https://systorage.tistory.com/entry/%EC%82%BD%EC%9E%85-%EC%A0%95%EB%A0%AC-Insertion-Sort</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;삽입 정렬(Insertion Sort) 소개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삽입&amp;nbsp;정렬은&amp;nbsp;비교적&amp;nbsp;간단하고&amp;nbsp;직관적인&amp;nbsp;정렬&amp;nbsp;알고리즘입니다.&amp;nbsp;작은&amp;nbsp;데이터를&amp;nbsp;정렬할&amp;nbsp;때는&amp;nbsp;매우&amp;nbsp;효율적이지만,&amp;nbsp;데이터의&amp;nbsp;양이&amp;nbsp;많아지면&amp;nbsp;비효율적이&amp;nbsp;될&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;삽입&amp;nbsp;정렬의&amp;nbsp;기본&amp;nbsp;아이디어는&amp;nbsp;이미&amp;nbsp;정렬된&amp;nbsp;부분&amp;nbsp;배열을&amp;nbsp;확장해&amp;nbsp;나가면서&amp;nbsp;새로운&amp;nbsp;요소를&amp;nbsp;올바른&amp;nbsp;위치에&amp;nbsp;삽입하는&amp;nbsp;것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;삽입&amp;nbsp;정렬의&amp;nbsp;의사&amp;nbsp;코드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열에서 두 번째 요소를 선택하여 시작합니다.&lt;br /&gt;두&amp;nbsp;번째&amp;nbsp;요소를&amp;nbsp;이전&amp;nbsp;요소와&amp;nbsp;비교하고&amp;nbsp;필요한&amp;nbsp;경우&amp;nbsp;스왑합니다.&lt;br /&gt;다음&amp;nbsp;요소로&amp;nbsp;계속&amp;nbsp;진행하고,&amp;nbsp;잘못된&amp;nbsp;순서일&amp;nbsp;경우&amp;nbsp;정렬된&amp;nbsp;부분(즉,&amp;nbsp;왼쪽)을&amp;nbsp;반복하여&amp;nbsp;요소를&amp;nbsp;올바른&amp;nbsp;위치에&amp;nbsp;배치합니다.&lt;br /&gt;배열이&amp;nbsp;정렬될&amp;nbsp;때까지&amp;nbsp;이&amp;nbsp;과정을&amp;nbsp;반복합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;삽입&amp;nbsp;정렬&amp;nbsp;구현&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 삽입 정렬을 JavaScript의 ES6 문법으로 구현한 예제입니다:&lt;/p&gt;
&lt;pre id=&quot;code_1721375364389&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const insertionSort = (arr) =&amp;gt; {
  for (let i = 1; i &amp;lt; arr.length; i++) {
    let currentVal = arr[i];
    let j;
    for (j = i - 1; j &amp;gt;= 0 &amp;amp;&amp;amp; arr[j] &amp;gt; currentVal; j--) {
      arr[j + 1] = arr[j];
    }
    arr[j + 1] = currentVal;
  }
  return arr;
};

// 사용 예시
let array = [5, 2, 9, 1, 5, 6];
console.log(insertionSort(array)); // [1, 2, 5, 5, 6, 9]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이&amp;nbsp;코드에서는&amp;nbsp;insertionSort&amp;nbsp;함수가&amp;nbsp;주어진&amp;nbsp;배열을&amp;nbsp;삽입&amp;nbsp;정렬&amp;nbsp;방식으로&amp;nbsp;정렬합니다.&amp;nbsp;for&amp;nbsp;루프를&amp;nbsp;통해&amp;nbsp;배열의&amp;nbsp;두&amp;nbsp;번째&amp;nbsp;요소부터&amp;nbsp;시작하여&amp;nbsp;각&amp;nbsp;요소를&amp;nbsp;이미&amp;nbsp;정렬된&amp;nbsp;부분&amp;nbsp;배열에&amp;nbsp;삽입합니다.&amp;nbsp;내부&amp;nbsp;for&amp;nbsp;루프는&amp;nbsp;현재&amp;nbsp;요소가&amp;nbsp;올바른&amp;nbsp;위치에&amp;nbsp;삽입될&amp;nbsp;때까지&amp;nbsp;이전&amp;nbsp;요소들과&amp;nbsp;비교하여&amp;nbsp;요소들을&amp;nbsp;한&amp;nbsp;칸씩&amp;nbsp;뒤로&amp;nbsp;이동시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;삽입&amp;nbsp;정렬&amp;nbsp;빅오(Big-O)&amp;nbsp;복잡도&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삽입 정렬의 시간 복잡도는 다음과 같습니다:&lt;br /&gt;&lt;br /&gt;최악의&amp;nbsp;경우:&amp;nbsp;O(n^2)&lt;br /&gt;배열이&amp;nbsp;역순으로&amp;nbsp;정렬되어&amp;nbsp;있는&amp;nbsp;경우가&amp;nbsp;최악의&amp;nbsp;경우입니다.&lt;br /&gt;최선의&amp;nbsp;경우:&amp;nbsp;O(n)&lt;br /&gt;배열이&amp;nbsp;이미&amp;nbsp;정렬되어&amp;nbsp;있는&amp;nbsp;경우가&amp;nbsp;최선의&amp;nbsp;경우입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;삽입&amp;nbsp;정렬의&amp;nbsp;특징&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;안정성: 삽입 정렬은 안정 정렬 알고리즘입니다. 이는 같은 값의 요소들이 정렬 후에도 기존의 순서를 유지한다는 것을 의미합니다.&lt;/li&gt;
&lt;li&gt;적응성: 거의 정렬된 배열에 대해 매우 효율적입니다. 이는 최선의 경우 시간 복잡도가 O(n)인 이유입니다.&lt;/li&gt;
&lt;li&gt;간단함: 구현이 매우 간단하고 직관적입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;삽입 정렬의 장단점&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구현이 쉽고, 이해하기 쉽습니다.&lt;/li&gt;
&lt;li&gt;적은 데이터나 거의 정렬된 데이터에 대해 효율적입니다.&lt;/li&gt;
&lt;li&gt;안정 정렬 알고리즘입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터의 양이 많아질수록 비효율적입니다.&lt;/li&gt;
&lt;li&gt;최악의 경우 시간 복잡도가 O(n^2)입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삽입 정렬은 그리 복잡하지 않으면서도 작동 방식이 매우 직관적입니다. 작은 데이터 세트나 이미 어느 정도 정렬된 데이터에 대해 효율적으로 사용할 수 있습니다. 그러나 큰 데이터 세트에 대해서는 다른 정렬 알고리즘(예: 퀵 정렬, 병합 정렬)보다 성능이 떨어질 수 있습니다. 따라서 상황에 맞게 적절한 정렬 알고리즘을 선택하는 것이 중요합니다.&lt;br /&gt;&lt;br /&gt;이&amp;nbsp;글에서는&amp;nbsp;삽입&amp;nbsp;정렬의&amp;nbsp;기본&amp;nbsp;개념과&amp;nbsp;구현&amp;nbsp;방법,&amp;nbsp;그리고&amp;nbsp;시간&amp;nbsp;복잡도와&amp;nbsp;특징에&amp;nbsp;대해&amp;nbsp;알아보았습니다.&amp;nbsp;이를&amp;nbsp;통해&amp;nbsp;삽입&amp;nbsp;정렬의&amp;nbsp;작동&amp;nbsp;방식을&amp;nbsp;이해하고,&amp;nbsp;실제로&amp;nbsp;코드로&amp;nbsp;구현할&amp;nbsp;수&amp;nbsp;있을&amp;nbsp;것입니다.&lt;/p&gt;</description>
      <category>Algorithm/Theory</category>
      <category>데이터구조</category>
      <category>빅오표기법</category>
      <category>삽입정렬</category>
      <category>시간복잡도</category>
      <category>알고리즘</category>
      <category>자바스크립트</category>
      <category>정렬</category>
      <category>정렬알고리즘</category>
      <category>코딩</category>
      <category>프로그래밍</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/211</guid>
      <comments>https://systorage.tistory.com/entry/%EC%82%BD%EC%9E%85-%EC%A0%95%EB%A0%AC-Insertion-Sort#entry211comment</comments>
      <pubDate>Fri, 19 Jul 2024 16:52:53 +0900</pubDate>
    </item>
    <item>
      <title>선택 정렬 (Selection Sort)</title>
      <link>https://systorage.tistory.com/entry/%EC%84%A0%ED%83%9D-%EC%A0%95%EB%A0%AC-Selection-Sort</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;선택 정렬 소개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선택 정렬은 정렬 알고리즘 중 하나로, 버블 정렬과 비슷하지만 큰 값을 배열 끝에 위치시키는 대신 작은 값을 한 번에 하나씩 위치에 배열하는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;선택 정렬 동작 방식&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;첫 번째 요소를 가장 작은 값으로 저장합니다.&lt;/li&gt;
&lt;li&gt;이 요소를 배열의 다음 요소와 비교하여 더 작은 수를 찾을 때까지 계속합니다.&lt;/li&gt;
&lt;li&gt;더 작은 수를 찾으면, 그 작은 수를 새로운 &quot;최소값&quot;으로 지정하고 배열의 끝까지 계속합니다.&lt;/li&gt;
&lt;li&gt;&quot;최소값&quot;이 처음 시작한 값(인덱스)이 아닌 경우, 두 값을 교환합니다.&lt;/li&gt;
&lt;li&gt;배열이 정렬될 때까지 다음 요소로 이 과정을 반복합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;선택 정렬 의사 코드&lt;/h3&gt;
&lt;pre id=&quot;code_1721040148769&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{for i from 0 to n-1:
    minIndex = i
    for j from i+1 to n:
        if array[j] &amp;lt; array[minIndex]:
            minIndex = j
    if minIndex != i:
        swap(array[i], array[minIndex])}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;선택 정렬 구현&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 ES2015(JavaScript) 버전의 선택 정렬 구현 예제입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1721145385777&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function selectionSort(arr) {
  const swap = (arr, idx1, idx2) =&amp;gt;
    ([arr[idx1], arr[idx2]] = [arr[idx2], arr[idx1]]);

  for (let i = 0; i &amp;lt; arr.length; i++) {
    let lowest = i;
    for (let j = i + 1; j &amp;lt; arr.length; j++) {
      if (arr[j] &amp;lt; arr[lowest]) {
        lowest = j;
      }
    }
    if (i !== lowest) {
      swap(arr, i, lowest);
    }
  }

  return arr;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;선택 정렬 빅오 복잡도&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선택 정렬의 시간 복잡도는 O(n^2)입니다. 이는 이중 for 루프를 사용하여 배열의 각 요소를 비교하기 때문입니다. 선택 정렬은 다음과 같은 점에서 버블 정렬보다 효율적입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;스왑 횟수&lt;/b&gt;: 선택 정렬은 각 반복이 끝날 때 한 번만 스왑을 수행합니다. 이는 불필요한 스왑을 줄여줍니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;단순성&lt;/b&gt;: 구현이 간단하여 이해하기 쉽습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;공간 복잡도&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선택 정렬은 추가적인 배열을 사용하지 않고 주어진 배열 내에서 정렬을 수행하기 때문에 공간 복잡도는 O(1)입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;선택 정렬의 장점과 단점&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구현이 간단하고 이해하기 쉽습니다.&lt;/li&gt;
&lt;li&gt;데이터의 양이 적을 때는 효율적입니다.&lt;/li&gt;
&lt;li&gt;주어진 배열 내에서 정렬을 수행하기 때문에 추가 메모리가 필요하지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도가 O(n^2)이기 때문에 대량의 데이터에 대해서는 비효율적입니다.&lt;/li&gt;
&lt;li&gt;안정 정렬이 아닙니다. (같은 값의 요소들이 정렬 후에도 입력 순서가 유지되지 않을 수 있습니다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;선택 정렬의 활용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선택 정렬은 데이터의 양이 적고, 간단한 정렬을 필요로 하는 경우에 유용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선택 정렬은 단순하지만, 알고리즘의 기본 개념을 이해하는 데 도움이 됩니다. 더 복잡한 알고리즘을 배우기 전에 선택 정렬을 이해하고 구현해 보는 것이 좋습니다.&lt;/p&gt;</description>
      <category>Algorithm/Theory</category>
      <category>데이터 구조</category>
      <category>빅오 복잡도</category>
      <category>선택 정렬</category>
      <category>소프트웨어 개발</category>
      <category>알고리즘</category>
      <category>자바스크립트</category>
      <category>정렬</category>
      <category>코드 예제</category>
      <category>코딩</category>
      <category>프로그래밍</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/210</guid>
      <comments>https://systorage.tistory.com/entry/%EC%84%A0%ED%83%9D-%EC%A0%95%EB%A0%AC-Selection-Sort#entry210comment</comments>
      <pubDate>Mon, 15 Jul 2024 19:46:07 +0900</pubDate>
    </item>
    <item>
      <title>버블 정렬 (Bubble Sort) 정렬 알고리즘 소개</title>
      <link>https://systorage.tistory.com/entry/%EB%B2%84%EB%B8%94-%EC%A0%95%EB%A0%AC-Bubble-Sort-%EC%A0%95%EB%A0%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%86%8C%EA%B0%9C</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;정렬이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정렬이란 컬렉션(ex: 배열)의 항목을 재배열하는 과정을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 배워야 하나?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정렬은 프로그래밍에서 매우 흔하게 사용됩니다.&lt;/li&gt;
&lt;li&gt;데이터를 정렬할 수 있는 방법은 많고, 각각 장단점이 있습니다.&lt;/li&gt;
&lt;li&gt;특정 상황에서 더 빠른 알고리즘이 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;목표&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;버블 정렬&lt;/li&gt;
&lt;li&gt;선택 정렬&lt;/li&gt;
&lt;li&gt;삽입 정렬&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기본 내장 JS 정렬&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;array 내장 sort&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MDN을 살펴보면 문자열은 A, B, C, D 순으로 나오지만 숫자는 오름차순이 아닌 것을 알 수 있습니다. 그 이유는 기본 정렬 순서가 문자열 유니코드에 따르기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 정렬 방식, 정렬의 기준이 되는 속성, 비교 대상을 실제로 지정할 수 있다면 다른 결과를 낼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;버블 정렬 개요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버블 정렬의 개념은 예를 들어 배열을 오름차순으로 정렬한다면, 더 큰 숫자가 한 번에 하나씩 뒤로 이동한다는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시:&lt;/p&gt;
&lt;pre id=&quot;code_1720964234950&quot; class=&quot;angelscript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;[5, 3, 4, 1, 2]
[3, 5, 4, 1, 2]
[3, 4, 5, 1, 2]
[3, 4, 1, 5, 2]
[3, 4, 1, 2, 5]
...
[1, 2, 3, 4, 5]가 될 때까지 반복&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복을 거듭하면서 정렬해야 하는 항목의 수가 감소합니다. 교환을 해야 할 때 사용해야 하는 방법은 아래와 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1720964260716&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ES5
function swap(arr, idx1, idx2) {
    var temp = arr[idx1];
    arr[idx1] = arr[idx2];
    arr[idx2] = temp;
}

// ES2015
const swap = (arr, idx1, idx2) =&amp;gt; {
    [arr[idx1], arr[idx2]] = [arr[idx2], arr[idx1]];
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버블 정렬은 단순한 구조로 인해 쉽게 이해할 수 있는 알고리즘입니다. 하지만 성능 면에서는 비효율적입니다. 특히 배열의 크기가 커질수록 성능이 급격히 저하됩니다. 버블 정렬은 안정 정렬(stable sort)로 동일한 값의 요소들이 원래의 순서를 유지한다는 장점이 있습니다. 또한, 내부 정렬(in-place sort)로 추가적인 메모리 공간을 거의 사용하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;버블 정렬 의사코드&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;i라는 변수를 사용하여 배열의 끝에서 시작하여 처음까지 반복합니다.&lt;/li&gt;
&lt;li&gt;내부 반복문에서는 j라는 변수를 사용하여 처음부터 i-1까지 반복합니다.&lt;/li&gt;
&lt;li&gt;만약 arr[j]가 arr[j+1]보다 크다면, 두 값을 서로 교환(swap)합니다.&lt;/li&gt;
&lt;li&gt;정렬된 배열을 반환합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;버블 정렬 구현&lt;/h2&gt;
&lt;pre id=&quot;code_1720964329756&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function bubbleSort(arr) {
    for(let i = arr.length; i &amp;gt; 0; i--) {
        for(let j = 0; j &amp;lt; i - 1; j++) {
            if(arr[j] &amp;gt; arr[j+1]) {
                const temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
    return arr;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버블 정렬을 구현한 위의 예시는 기본적인 구조를 보여줍니다. 배열의 끝에서부터 처음까지 반복하면서 각 요소를 비교하고 필요한 경우 교환합니다. 하지만 이렇게 구현된 버블 정렬은 이미 정렬이 완료된 경우에도 배열 끝까지 계속 탐색을 하며 비효율적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;버블 정렬 최적화&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버블 정렬의 성능을 향상시키기 위해 몇 가지 최적화 기법을 사용할 수 있습니다. 그 중 하나는 루프가 마지막으로 실행됐을 때 교환이 있었는지를 확인하는 것입니다. 만약 교환이 없었다면 배열은 이미 정렬된 상태이므로 반복을 중지할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1720964374855&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function bubbleSort(arr) {
    let noSwaps;
    for(let i = arr.length; i &amp;gt; 0; i--) {
        noSwaps = true;
        for(let j = 0; j &amp;lt; i - 1; j++) {
            if(arr[j] &amp;gt; arr[j+1]) {
                const temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
                noSwaps = false;
            }
        }
        if(noSwaps) break;
    }
    return arr;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 최적화된 버블 정렬 구현은 불필요한 반복을 줄여 성능을 향상시킵니다. 루프가 실행될 때 교환이 없었다면, 배열이 이미 정렬된 상태이므로 더 이상의 반복을 중지할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;버블 정렬의 특성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버블 정렬은 간단하지만 비효율적인 정렬 알고리즘입니다. 실제 사용보다는 교육 목적으로 많이 사용됩니다. 이 알고리즘을 이해하면 더 복잡한 정렬 알고리즘을 배우는 데 도움이 됩니다. 또한, 안정 정렬 알고리즘으로 동일한 값의 순서가 유지됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;안정 정렬 (Stable Sort)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버블 정렬은 안정 정렬 알고리즘입니다. 이는 동일한 값의 요소들이 원래의 순서를 유지한다는 것을 의미합니다. 예를 들어, 객체 배열을 특정 키로 정렬할 때, 같은 키 값을 가진 객체들이 버블 정렬을 통해서도 순서가 바뀌지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;내부 정렬 (In-place Sort)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버블 정렬은 추가적인 메모리 공간을 거의 사용하지 않는 내부 정렬 알고리즘입니다. 배열 자체에서 직접 교환 작업을 수행하기 때문에, 메모리 사용량이 매우 적습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;단점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;성능이 좋지 않습니다. 특히, 배열의 크기가 클수록 시간 복잡도 O(n^2)로 인해 성능이 급격히 저하됩니다.&lt;/li&gt;
&lt;li&gt;큰 배열을 정렬하는 데 적합하지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;버블 정렬의 실제 사용 사례&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버블 정렬은 대부분의 경우 비효율적이지만, 간단한 구현과 이해하기 쉬운 알고리즘 구조로 인해 교육 목적으로 자주 사용됩니다. 예를 들어, 알고리즘과 자료 구조를 처음 배우는 학생들에게 버블 정렬은 기본적인 정렬 개념을 이해하는 데 큰 도움이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;버블 정렬의 빅오 복잡도&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;평균 및 최악의 경우: O(n^2)&lt;/li&gt;
&lt;li&gt;최상의 경우: O(n) (이미 정렬된 경우)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;추가 리소스&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://visualgo.net/en/sorting&quot;&gt;Visualgo&lt;/a&gt;: 다양한 알고리즘을 시각적으로 볼 수 있는 사이트입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm/Theory</category>
      <category>Bubble Sort</category>
      <category>JavaScript</category>
      <category>sorting algorithms</category>
      <category>데이터 구조</category>
      <category>버블 정렬</category>
      <category>알고리즘</category>
      <category>자바스크립트</category>
      <category>정렬</category>
      <category>컴퓨터과학</category>
      <category>프로그래밍</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/209</guid>
      <comments>https://systorage.tistory.com/entry/%EB%B2%84%EB%B8%94-%EC%A0%95%EB%A0%AC-Bubble-Sort-%EC%A0%95%EB%A0%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%86%8C%EA%B0%9C#entry209comment</comments>
      <pubDate>Sun, 14 Jul 2024 22:42:22 +0900</pubDate>
    </item>
    <item>
      <title>검색 알고리즘</title>
      <link>https://systorage.tistory.com/entry/%EA%B2%80%EC%83%89-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;검색 알고리즘은 컴퓨터 과학에서 필수적인 주제입니다. 데이터를 효율적으로 검색하는 방법을 이해하면 프로그램의 성능을 크게 향상시킬 수 있습니다. 이 글에서는 다양한 검색 알고리즘을 소개하고, 각각의 구현 방법과 시간 복잡도를 설명합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;목표&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;선형 검색&lt;/li&gt;
&lt;li&gt;분류된 배열에서의 이진 검색&lt;/li&gt;
&lt;li&gt;나이브 문자열 검색 알고리즘&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;선형 검색 소개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선형 검색은 가장 간단한 검색 방법 중 하나입니다. 이 방법은 배열의 각 요소를 순서대로 확인하여 값이 일치하는지 확인합니다. JavaScript에서는 indexOf, includes, find, findIndex와 같은 배열 함수를 사용하여 선형 검색을 수행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 번에 하나씩 검색하는 이 방법을 선형 검색이라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;선형 검색 연습&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열과 값을 받아들이고 그 값이 배열 안에 존재하는 경우, 그 인덱스를 반환하는 linearSearch 함수를 작성합니다. 값이 배열 안에 존재하지 않으면 -1을 반환합니다. 이 함수를 구현할 때 indexOf를 사용하지 마세요!&lt;/p&gt;
&lt;pre id=&quot;code_1720620820924&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    function linearSearch(index){
  
    }
    
    // linearSearch([10, 15, 20, 25, 30], 15) // 1
    // linearSearch([9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 4) // 5
    // linearSearch([100], 100) // 0
    // linearSearch([1,2,3,4,5], 6) // -1
    // linearSearch([9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 10) // -1
    // linearSearch([100], 200) // -1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정답&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1720620801427&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;function linearSearch(arr, val) {
    for (let i = 0; i &amp;lt; arr.length; i++) {
        if (arr[i] === val) {
            return i;
        }
    }
    return -1;
}

// 예시 사용법
console.log(linearSearch([10, 15, 20, 25, 30], 15)); // 1
console.log(linearSearch([9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 4)); // 5
console.log(linearSearch([100], 100)); // 0
console.log(linearSearch([1, 2, 3, 4, 5], 6)); // -1
console.log(linearSearch([9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 10)); // -1
console.log(linearSearch([100], 200)); // -1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;선형 검색 빅오 (Big O)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선형 검색의 시간복잡도는 다음과 같습니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최선의 경우: O(1) (첫 번째 요소에 있는 경우)&lt;/li&gt;
&lt;li&gt;최악의 경우: O(n) (마지막 요소에 있는 경우)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 일반적인 시간복잡도는 O(n)입니다. 데이터가 분류되지 않았을 때 사용하는 좋은 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이진 검색 소개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이진 검색은 정렬된 배열에서 더 빠른 검색 방법을 제공합니다. 이진 검색은 배열을 절반으로 나누어 검색 범위를 줄여나가는 분할 정복 알고리즘입니다. 이 방법은 정렬된 배열에서만 작동합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이진 검색 연습&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정렬된 배열과 값을 받아들이고 값이 존재하는 경우 그 인덱스를 반환하는 binarySearch 함수를 작성합니다. 값이 존재하지 않으면 -1을 반환합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1720620907850&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function binarySearch(arr, value){}
binarySearch([1,2,3,4,5],2) // 1
binarySearch([1,2,3,4,5],3) // 2
binarySearch([1,2,3,4,5],5) // 4
binarySearch([1,2,3,4,5],6) // -1
binarySearch([
  5, 6, 10, 13, 14, 18, 30, 34, 35, 37, 
  40, 44, 64, 79, 84, 86, 95, 96, 98, 99
], 10) // 2
binarySearch([
  5, 6, 10, 13, 14, 18, 30, 34, 35, 37, 
  40, 44, 64, 79, 84, 86, 95, 96, 98, 99
], 95) // 16
binarySearch([
  5, 6, 10, 13, 14, 18, 30, 34, 35, 37, 
  40, 44, 64, 79, 84, 86, 95, 96, 98, 99
], 100) // -1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정답&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1720620981720&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function binarySearch(arr, elem) {
  let start = 0;
  let end = arr.length - 1;
  let middle = Math.floor((start + end) / 2);
  while (arr[middle] !== elem &amp;amp;&amp;amp; start &amp;lt;= end) {
    if (elem &amp;lt; arr[middle]) {
      end = middle - 1;
    } else {
      start = middle + 1;
    }
    middle = Math.floor((start + end) / 2);
  }
  return arr[middle] === elem ? middle : -1;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이진 검색 빅오 (Big O)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이진 검색의 시간복잡도는 다음과 같습니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최선의 경우: O(1) (첫 번째 비교에서 찾은 경우)&lt;/li&gt;
&lt;li&gt;최악의 경우: O(log N) (반복적으로 반으로 나누는 경우)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 일반적인 시간복잡도는 O(log N)입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;나이브 문자열 검색&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나이브 문자열 검색은 문자열 안에서 부분 문자열을 찾는 간단한 방법입니다. 긴 문자열과 짧은 문자열을 비교하여 일치하는 경우를 찾습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;나이브 문자열 검색 구현&lt;/h2&gt;
&lt;pre id=&quot;code_1720621053075&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function naiveSearch(long, short) {
    let count = 0;
    for(let i = 0; i &amp;lt; long.length; i++) {
        for(let j = 0; j &amp;lt; short.length; j++) {
            if(short[j] !== long[i + j]) {
                console.log(&quot;Break&quot;);
                break;
            }
            if(j === short.length - 1) {
                count++;
            }
        }
    }
    return count;
}
naiveSearch(&quot;lorie loled&quot;, &quot;lol&quot;); // 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm/Theory</category>
      <category>검색 알고리즘</category>
      <category>나이브 문자열 검색</category>
      <category>데이터 검색</category>
      <category>선형 검색</category>
      <category>시간 복잡도</category>
      <category>알고리즘</category>
      <category>이진 검색</category>
      <category>자바스크립트</category>
      <category>코딩 연습</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/208</guid>
      <comments>https://systorage.tistory.com/entry/%EA%B2%80%EC%83%89-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98#entry208comment</comments>
      <pubDate>Wed, 10 Jul 2024 23:20:09 +0900</pubDate>
    </item>
    <item>
      <title>(더 어려운) 재귀 연습 문제 1부</title>
      <link>https://systorage.tistory.com/entry/%EB%8D%94-%EC%96%B4%EB%A0%A4%EC%9A%B4-%EC%9E%AC%EA%B7%80-%EC%97%B0%EC%8A%B5-%EB%AC%B8%EC%A0%9C-1%EB%B6%80</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제1&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;문자열을 받아들이고 그 문자열의 역순인 문자열을 반환하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;reverse&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수를 작성합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1720515866354&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function reverse(string){
}

// reverse('awesome') // 'emosewa'
// reverse('rithmschool') // 'loohcsmhtir'&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정답&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1720602915792&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function reverse(string) {
  if (string.length === 1) {
    return string;
  }
  return reverse(string.slice(1)) + string[0];
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제2&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;전달된 문자열이 팔린드롬(앞으로 읽으나 뒤로 읽으나 동일한 문자)인 경우 true 를 반환하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;isPalindrome&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;이라는 재귀(recursive) 함수를 작성하시오. 팔린드롬이 아닐 경우 false 를 반환합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1720603090530&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// isPalindrome('awesome') // false
// isPalindrome('foobar') // false
// isPalindrome('tacocat') // true
// isPalindrome('amanaplanacanalpanama') // true
// isPalindrome('amanaplanacanalpandemonium') // false

function isPalindrome(str){

}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;정답&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1720603148478&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 내 정답
function isPalindrome(str){
    function helper(str2) {
        if (str2.length === 1) {
            return str2;
        }
        return helper(str2.slice(1)) + str2[0]
    }
    return str === helper(str) ? true : false;
}

// 정답지
function isPalindrome(str){
    if(str.length === 1) return true;
    if(str.length === 2) return str[0] === str[1];
    if(str[0] === str.slice(-1)) return isPalindrome(str.slice(1,-1))
    return false;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제3&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;배열과 콜백을 받아들이는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;someRecursive&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;라는 재귀(recursive) 함수를 작성하시오. 이 함수는 배열의 단일 값이 콜백에 전달될 때 true를 반환하면 true를 반환합니다. 그렇지 않으면 false를 반환합니다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1720603370841&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SAMPLE INPUT / OUTPUT
// const isOdd = val =&amp;gt; val % 2 !== 0;

// someRecursive([1,2,3,4], isOdd) // true
// someRecursive([4,6,8,9], isOdd) // true
// someRecursive([4,6,8], isOdd) // false
// someRecursive([4,6,8], val =&amp;gt; val &amp;gt; 10); // false

function someRecursive(){
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;정답&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1720603432312&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SAMPLE INPUT / OUTPUT
// const isOdd = val =&amp;gt; val % 2 !== 0;

// someRecursive([1,2,3,4], isOdd) // true
// someRecursive([4,6,8,9], isOdd) // true
// someRecursive([4,6,8], isOdd) // false
// someRecursive([4,6,8], val =&amp;gt; val &amp;gt; 10); // false

// 내 정답
function someRecursive(arr, func){
    if (arr.length === 0) {
     return false;   
    }
    if(func(arr.pop())) {
        return true
    }
    return someRecursive(arr, func)
}

// 정답지
function someRecursive(array, callback) {
    if (array.length === 0) return false;
    if (callback(array[0])) return true;
    return someRecursive(array.slice(1),callback);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제4&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;배열의 배열을 받아들이고 모든 값이 평활화(flattened)된 새 배열을 반환하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;flatten&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;이라는 재귀(recursive ) 함수를 작성합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1720603558722&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function flatten(){
    
}

// flatten([1, 2, 3, [4, 5] ]) // [1, 2, 3, 4, 5]
// flatten([1, [2, [3, 4], [[5]]]]) // [1, 2, 3, 4, 5]
// flatten([[1],[2],[3]]) // [1,2,3]
// flatten([[[[1], [[[2]]], [[[[[[[3]]]]]]]]]]) // [1,2,3&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;정답&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1720604134076&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function flatten(oldArr) {
  let newArr = [];
  for (let i = 0; i &amp;lt; oldArr.length; i++) {
    if (Array.isArray(oldArr[i])) {
      newArr = newArr.concat(flatten(oldArr[i]));
    } else {
      newArr.push(oldArr[i]);
    }
  }
  return newArr;
}

// flatten([1, 2, 3, [4, 5] ]) // [1, 2, 3, 4, 5]
// flatten([1, [2, [3, 4], [[5]]]]) // [1, 2, 3, 4, 5]
// flatten([[1],[2],[3]]) // [1,2,3]
// flatten([[[[1], [[[2]]], [[[[[[[3]]]]]]]]]]) // [1,2,3]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Algorithm/Theory</category>
      <category>알고리즘</category>
      <category>연습 문제</category>
      <category>재귀</category>
      <category>재귀 연습</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/207</guid>
      <comments>https://systorage.tistory.com/entry/%EB%8D%94-%EC%96%B4%EB%A0%A4%EC%9A%B4-%EC%9E%AC%EA%B7%80-%EC%97%B0%EC%8A%B5-%EB%AC%B8%EC%A0%9C-1%EB%B6%80#entry207comment</comments>
      <pubDate>Wed, 10 Jul 2024 18:36:54 +0900</pubDate>
    </item>
    <item>
      <title>재귀 연습 문제</title>
      <link>https://systorage.tistory.com/entry/%EC%9E%AC%EA%B7%80-%EC%97%B0%EC%8A%B5-%EB%AC%B8%EC%A0%9C</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;문제 1&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;밑과 지수를 받아들이는 power라는 함수를 작성합니다. 이 함수는 밑의 거듭제곱을 지수로 반환해야 합니다. 이 함수는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Math.pow()&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;의 기능을 모방해야 합니다. 음의 밑과 지수에 대해서는 신경쓰지 마세요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1720511182863&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// power(2,0) // 1
// power(2,2) // 4
// power(2,4) // 16

function power(){}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정답&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1720511191226&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// power(2,0) // 1
// power(2,2) // 4
// power(2,4) // 16

function power(num, pow){
    if(pow === 0) {
        return 1;
    }
    return num * power(num, pow - 1)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 2&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;숫자를 받아 해당 숫자의 계승(팩토리얼)을 반환하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;팩토리얼&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수를 작성하시오.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;팩토리얼은 정수와 그 아래의 모든 정수의 곱입니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어, 4 팩토리얼 (4!)은 4 * 3 * 2 * 1 = 2입니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;팩토리얼 0(0!)은 항상 1입니다.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1720511236987&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//factorial(1) // 1
// factorial(2) // 2
// factorial(4) // 24
// factorial(7) // 5040

function factorial(){
   
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정답&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1720511488671&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//factorial(1) // 1
// factorial(2) // 2
// factorial(4) // 24
// factorial(7) // 5040

function factorial(x){
   if (x &amp;lt; 0 ) {return 0;}
   if (x &amp;lt;= 1 ) {return 1;}
   return x * factorial(x-1);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제3&lt;/h2&gt;
&lt;div style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-purpose=&quot;safely-set-inner-html:rich-text-viewer:html&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;숫자 배열을 받아 모든 숫자의 곱을 반환하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;productOfArray라는 함수를 작성하시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1720512892720&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// productOfArray([1,2,3]) // 6
// productOfArray([1,2,3,10]) // 60

function productOfArray(arr) {}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정답&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1720512914984&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function productOfArray(arr) {
    if(arr.length === 0) {
        return 1;
    }
    return arr[0] * productOfArray(arr.slice(1));
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제4&lt;/h2&gt;
&lt;div style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-purpose=&quot;safely-set-inner-html:rich-text-viewer:html&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;숫자를 받으면 0부터 함수에 전달된 숫자까지의 모든 숫자를 더하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;recursiveRange&lt;/b&gt;라는 함수를 작성하시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1720514076184&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// recursiveRange(6) // 21
// recursiveRange(10) // 55 

function recursiveRange(num){}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정답&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1720514099423&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function recursiveRange(x){
   if (x === 0 ) {return 0;}
   return x + recursiveRange(x-1);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제5&lt;/h2&gt;
&lt;div style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-purpose=&quot;safely-set-inner-html:rich-text-viewer:html&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;숫자를 받아 피보나치 수열의 n번째 숫자를 반환하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;fib&lt;/b&gt;라는 재귀 함수를 작성하시오. 피보나치 수열은 1, 1로 시작하는 1, 1, 2, 3, 5, 8, ...의 정수의 수열이며, 모든 수는 이전 두 수의 합과 같다는 것을 명심하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1720514151762&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// fib(4) // 3
// fib(10) // 55
// fib(28) // 317811
// fib(35) // 9227465

function fib(num){}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정답&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1720514344691&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// fib(4) // 3
// fib(10) // 55
// fib(28) // 317811
// fib(35) // 9227465

function fib(num){
    if (num &amp;lt;= 2) {
        return 1;
    }
    return fib(num-1) + fib(num-2);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm/Theory</category>
      <category>연습 문제</category>
      <category>재귀</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/206</guid>
      <comments>https://systorage.tistory.com/entry/%EC%9E%AC%EA%B7%80-%EC%97%B0%EC%8A%B5-%EB%AC%B8%EC%A0%9C#entry206comment</comments>
      <pubDate>Tue, 9 Jul 2024 17:40:28 +0900</pubDate>
    </item>
    <item>
      <title>재귀 (Recursion)</title>
      <link>https://systorage.tistory.com/entry/%EC%9E%AC%EA%B7%80-Recursion</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;재귀의 기본 개념&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재귀는 문제를 더 작은 부분으로 나누어, 종료점에 도달할 때까지 반복적으로 수행하는 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;목표&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;재귀가 무엇인지, 어떻게 유용하게 사용할 수 있는지 이해하기&lt;/li&gt;
&lt;li&gt;재귀 함수 작성의 두 가지 핵심 요소&lt;/li&gt;
&lt;li&gt;호출 스택이 재귀와 어떤 관련이 있는지 이해하기&lt;/li&gt;
&lt;li&gt;헬퍼 메소드 재귀와 순수 재귀의 차이점과 비교&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;재귀 함수를 사용하는 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재귀는 자기 자신을 호출하는 절차로, 많은 상황에서 유용하게 사용됩니다. 복잡한 데이터 구조나 알고리즘을 다룰 때 재귀가 큰 도움이 될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JSON.parse / JSON.stringify&lt;/li&gt;
&lt;li&gt;document.getElementById와 같은 DOM 탐색 알고리즘&lt;/li&gt;
&lt;li&gt;객체 순회 (Object traversal)&lt;/li&gt;
&lt;li&gt;복잡한 알고리즘에서 재귀로 작성하는 것이 더 깔끔하고 이해하기 쉬운 경우가 많습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;호출 스택과 재귀&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거의 모든 프로그래밍 언어에는 함수 호출을 관리하는 보이지 않는 데이터 구조가 있습니다. 호출된 함수는 다른 함수가 반환될 때까지 기다리며, 이를 관리하는 것이 호출 스택입니다. JavaScript의 경우 호출 스택이 이 역할을 담당합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;첫 번째 재귀 함수&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 재귀 함수든 반드시 갖춰야 하는 두 가지 요소가 있습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;종료 조건 (Base Case)&lt;/li&gt;
&lt;li&gt;서로 다른 입력값 (Different Input)&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1720437714487&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 카운트다운을 재귀로 구현하는 경우
function countDown(num) {
// 종료 조건
    if(num &amp;lt;= 0) {
        console.log(&quot;All done!&quot;);
        return;
    }
    console.log(num);
    // 서로 다른 입력값을 위한 --
    num--;
    countDown(num);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;두 번째 재귀 함수&lt;/h2&gt;
&lt;pre id=&quot;code_1720437757744&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function sumRange(num) {
    if(num === 1) {
        return 1;
    }
    return num + sumRange(num - 1);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sumRange(3)을 호출했을 때,&lt;/p&gt;
&lt;pre id=&quot;code_1720437779307&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;3 + sumRange(2)
2 + sumRange(1)
1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 순서대로 실행되어 6이 반환됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;반복문으로 팩토리얼 구현하기&lt;/h2&gt;
&lt;pre id=&quot;code_1720437807334&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function factorial(num) {
    let total = 1;
    for(let i = num; i &amp;gt; 1; i--) {
        total *= i;
    }
    return total;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;재귀 호출로 팩토리얼 구현하기&lt;/h2&gt;
&lt;pre id=&quot;code_1720437822351&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function factorial(num) {
    if(num === 1) return 1;
    return num * factorial(num - 1);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;재귀의 잠재적 위험&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재귀 함수에는 몇 가지 잠재적 위험이 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;종료 조건이 없거나 잘못 설정된 경우&lt;/li&gt;
&lt;li&gt;반환 값을 잊거나 잘못 반환하는 경우&lt;/li&gt;
&lt;li&gt;Maximum call stack size exceeded 에러 발생 (스택 오버플로우)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;헬퍼 메소드 재귀&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재귀 함수를 다른 함수로 감싸서 처리하는 방법입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1720437896284&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function collectOddValues(arr){
// 외부에 변수를 선언해서 활용
    let result = []
    function helper(helperInput){
        if(helperInput.length === 0) {
            return;
        }
        if(helperInput[0] % 2 !== 0){
            result.push(helperInput[0])
        }
        helper(helperInput.slice(1))
    }
    helper(arr)
    return result;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;순수 재귀&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 데이터 구조를 사용하지 않고 필요한 모든 코드가 함수 자체에 포함됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1720437920451&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function collectOddValues(arr) {
    let newArr = [];

    if(arr.length === 0) {
        return newArr;
    }
    if(arr[0] % 2 !== 0) {
        newArr.push(arr[0]);
    }

    newArr = newArr.concat(collectOddValues(arr.slice(1)));
    return newArr;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배열을 사용하고 헬퍼 메소드 없이 순수 재귀 솔루션을 작성할 때 배열을 복사하는 slice, spread 연산자, concat 등을 사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;문자열은 변경할 수 없으므로 slice, substr, 또는 substring을 사용해서 복사해야 합니다.&lt;/li&gt;
&lt;li&gt;객체의 경우 Object.assign이나 spread 연산자를 사용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm/Theory</category>
      <category>순수 재귀</category>
      <category>알고리즘</category>
      <category>자바스크립트</category>
      <category>재귀</category>
      <category>재귀 예제</category>
      <category>재귀 위험</category>
      <category>재귀 함수</category>
      <category>프로그래밍</category>
      <category>헬퍼 메소드</category>
      <category>호출 스택</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/205</guid>
      <comments>https://systorage.tistory.com/entry/%EC%9E%AC%EA%B7%80-Recursion#entry205comment</comments>
      <pubDate>Mon, 8 Jul 2024 20:26:20 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] 2023-07-05</title>
      <link>https://systorage.tistory.com/entry/TIL-2023-07-05</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;공부는 못하고 면접 준비만 주구장창...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;면접 질문 정리 및 포트폴리오 추가&lt;/li&gt;
&lt;li&gt;면접&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>TIL</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/204</guid>
      <comments>https://systorage.tistory.com/entry/TIL-2023-07-05#entry204comment</comments>
      <pubDate>Fri, 5 Jul 2024 17:25:54 +0900</pubDate>
    </item>
    <item>
      <title>문제 해결 패턴 연습 문제</title>
      <link>https://systorage.tistory.com/entry/%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%ED%8C%A8%ED%84%B4-%EC%97%B0%EC%8A%B5-%EB%AC%B8%EC%A0%9C</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 1&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;sameFrequency &lt;/b&gt;라는 함수를 작성하세요. 두 개의 양의 정수가 주어졌을 때, 두 숫자의 자릿수가 같은 빈도를 갖는지 구합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여러분의 솔루션은 반드시 다음과 같은 복잡성을 가져야 합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Time: O(N)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;예시&lt;/p&gt;
&lt;div style=&quot;background-color: #282c34; color: #bbbbbb;&quot;&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;sameFrequency(182, 281); // true
sameFrequency(34, 14); // false
sameFrequency(3589578, 5879385); // true
sameFrequency(22, 222); // false&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정답&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1719813592413&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function sameFrequency(num1, num2) {
  // 빈도수를 담아둘 객체
  const frequency1 = {};
  const frequency2 = {};

  // string화
  const str1 = num1.toString();
  const str2 = num2.toString();

  const str1Length = str1.length;
  const str2Length = str2.length;

  // 길이가 같지 않다면 빈도수가 다름
  if (str1Length !== str2Length) {
    return false;
  }

  // 각 문자별로 객체에 빈도수를 저장
  for (let i = 0; i &amp;lt; str1Length; i++) {
    const s = str1[i];
    frequency1[s] = (frequency1[s] || 0) + 1;
  }
  for (let i = 0; i &amp;lt; str2Length; i++) {
    const s = str2[i];
    frequency2[s] = (frequency2[s] || 0) + 1;
  }

  for (let t in frequency1) {
    if (frequency2[t] !== frequency1[t]) {
      return false;
    }
  }

  return true;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 2&lt;/h2&gt;
&lt;div style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-purpose=&quot;safely-set-inner-html:rich-text-viewer:html&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;가변적인 수의 인수&lt;/b&gt;(a variable number of arguments)를 받아들이고 전달된 인자 중 중복이 있는지 확인하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;areThereDuplicates&lt;/b&gt;라는 함수를 구현합니다.&amp;nbsp; 빈도 카운터 패턴 또는 다중 포인터 패턴을 사용하여 이 문제를 해결할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Time - O(n)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Space - O(n)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;예시&lt;/p&gt;
&lt;pre id=&quot;code_1719814044370&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;areThereDuplicates(1, 2, 3); // false
areThereDuplicates(1, 2, 2); // true
areThereDuplicates('a', 'b', 'c', 'a'); // true&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정답&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1719814074619&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function areThereDuplicates(...arr) {
  // 갯수를 담아둘 객체를 생성
  const obj = {};

  // 반복문을 돌면서 하나씩 저장
  for (let i = 0; i &amp;lt; arr.length; i++) {
    const current = arr[i];
    // 이미 객체가 있는 경우 return ture
    if (obj[current]) {
      return true;
    }
    obj[current] = (obj[current] || 0) + 1;
  }
  // 마지막에 도달한 경우 return false
  return false;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 3&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;averagePair&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;라는 함수를 작성합니다. 정렬된 정수 배열과 목표 평균이 주어졌을 때, 배열에 쌍의 평균이 목표 평균과 같은 값의 쌍이 있는지 확인합니다. 목표 평균과 일치하는 쌍이 두 개 이상 있을 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Time: O(N)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Space: O(1)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;예시&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1719815123500&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;averagePair([1,2,3],2.5) // true
averagePair([1,3,3,5,6,7,10,12,19],8) // true
averagePair([-1,0,3,4,5,6], 4.1) // false
averagePair([],4) // false&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정답&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1719815963645&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function averagePair(arr, avg) {
  //   양쪽에 포인터를 하나씩 둠
  let left = 0;
  let right = arr.length - 1;
  //   평균의 값을 2배 한 값을 구함.
  const avg2 = avg * 2;
  // 포인터 왼쪽이 작아질때까지 반복문을 돔.
  while (left &amp;lt; right) {
    // 양 포인터의 값을 합함.
    const sum = arr[left] + arr[right];
    // 합이 같은 경우 정답
    if (sum === avg2) {
      return true;
    } else if (sum &amp;lt; avg2) {
      // 만약 포인터의 값을 합한게 2배 값보다 작다면 왼쪽 포인터를 늘림.
      left++;
    } else {
      // 만약 포인터의 값을 합한게 2배 값보다 크다면 오른쪽 포인터를 줄임.
      right--;
    }
  }
  // 전부 반복했는데 정답이 없는 경우
  return false;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 4&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;두 문자열을 받아 첫 번째 문자열의 문자가 두 번째 문자열의 문자의 일부에 포함되는지 확인하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;isSubsequence&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;라는 함수를 작성합니다. 즉, 이 함수는 첫 번째 문자열의 문자가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;순서가 바뀌지 않고&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;두 번째 문자열의 어딘가에 나타나는지 확인해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Time: O(N + M)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Space: O(1)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;예시&lt;/p&gt;
&lt;pre id=&quot;code_1719816131213&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;isSubsequence('hello', 'hello world'); // true
isSubsequence('sing', 'sting'); // true
isSubsequence('abc', 'abracadabra'); // true
isSubsequence('abc', 'acb'); // false (order matters)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정답&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1719816660614&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function isSubsequence(str1, str2) {
  let i = 0;
  let j = 0;
  if (!str1) {
      return true
      
  };
  while (j &amp;lt; str2.length) {
    if (str2[j] === str1[i]) {
        i++
    };
    if (i === str1.length) {
        return true
        
    };
    j++;
  }
  return false;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 5&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정수의 배열과 숫자가 주어졌을 때, 함수에 전달된 숫자의 길이를 가진 하위 배열의 최대 합을 구하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;maxSubarraySum&lt;/b&gt;이라는 함수를 작성하세요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;하위 배열은 원래 배열의&lt;span&gt;&amp;nbsp;&lt;/span&gt;연속적인&lt;span&gt;&amp;nbsp;&lt;/span&gt;요소로 구성되어야 한다는 점에 유의하세요. 아래 첫 번째 예제에서 [100, 200, 300]은 원래 배열의 하위 배열이지만 [100, 300]은 그렇지 않습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Time:&lt;span&gt;&amp;nbsp;&lt;/span&gt;O(N)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Space:&lt;span&gt;&amp;nbsp;&lt;/span&gt;O(1)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;예시&lt;/p&gt;
&lt;pre id=&quot;code_1719816711851&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;maxSubarraySum([100,200,300,400], 2) // 700
maxSubarraySum([1,4,2,10,23,3,1,0,20], 4)  // 39 
maxSubarraySum([-3,4,0,-2,6,-1], 2) // 5
maxSubarraySum([3,-2,7,-4,1,-1,4,-2,1],2) // 5
maxSubarraySum([2,3], 3) // null&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정답&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1719822559053&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function maxSubarraySum(arr, num) {
  // 최대 합 선언
  let maxSum = 0;
  // 임시 합
  let tempSum = 0;
  // num보다 arr의 길이가 작으면  null return
  if (arr.length &amp;lt; num) {
    return null;
  }

  // 첫번째 임시 합을 구함
  for (let i = 0; i &amp;lt; num; i++) {
    tempSum += arr[i];
  }

  // 현재 최대 합은 첫번째 합
  maxSum = tempSum;

  for (let i = num; i &amp;lt; arr.length; i++) {
    // 반복문을 돌며 앞에 숫자를 빼고 뒤에 숫자를 더함.
    tempSum = tempSum - arr[i - num] + arr[i];
    // 둘 중 더 큰 값이 maxSum
    maxSum = Math.max(maxSum, tempSum);
  }

  return maxSum;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 6&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양수 배열과 양수라는 두 개의 매개 변수를 받아들이는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;minSubArrayLen&lt;/b&gt;이라는 함수를 작성하세요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 함수는 합이 함수에 전달된 정수보다 크거나 같은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;인접한&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;하위 배열의 최소 길이를 반환해야 합니다. 값이 없는 경우 0을 반환합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Time: O(n)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Space: O(1)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;예시&lt;/p&gt;
&lt;pre id=&quot;code_1719822618298&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;minSubArrayLen([2,3,1,2,4,3], 7) // 2 -&amp;gt; because [4,3] is the smallest subarray
minSubArrayLen([2,1,6,5,4], 9) // 2 -&amp;gt; because [5,4] is the smallest subarray
minSubArrayLen([3,1,7,11,2,9,8,21,62,33,19], 52) // 1 -&amp;gt; because [62] is greater than 52
minSubArrayLen([1,4,16,22,5,7,8,9,10],39) // 3
minSubArrayLen([1,4,16,22,5,7,8,9,10],55) // 5
minSubArrayLen([4, 3, 3, 8, 1, 2, 3], 11) // 2
minSubArrayLen([1,4,16,22,5,7,8,9,10],95) // 0&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;정답&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1719825789880&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const minSubArrayLen = (nums, sum) =&amp;gt; {
  // 전체값, 시작 인덱스 끝 인덱스, 최소 길이 변수 초기화
  let total = 0;
  let start = 0;
  let end = 0;
  let minLen = Infinity;

  // start가 배열의 길이보다 작은 동안 루프를 반복
  while (start &amp;lt; nums.length) {
    // 현재 윈도우의 합이 sum보다 작고 end가 배열의 끝에 도달하지 않은 경우
    // end를 증가시키면서 윈도우를 확장하고 total에 nums[end] 값을 더함
    if (total &amp;lt; sum &amp;amp;&amp;amp; end &amp;lt; nums.length) {
      total += nums[end];
      end++;
    } else if (total &amp;gt;= sum) {
      // 현재 윈도우의 합이 sum보다 크거나 같은 경우, 최소 길이를 계산하여 minLen을 업데이트한다.
      // 그런 다음, start를 증가시키면서 윈도우를 축소하고 total에서 nums[start] 값을 뺀다.
      minLen = Math.min(minLen, end - start);
      total -= nums[start];
      start++;
    }
    // current total less than required total but we reach the end, need this or else we'll be in an infinite loop
    else {
      break;
    }
  }

  return minLen === Infinity ? 0 : minLen;
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 7&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;문자열을 받아 모든 고유 문자가 포함된 가장 긴 하위 문자열의 길이를 반환하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;findLongestSubstring&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;이라는 함수를 작성하세요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;Time: O(n)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #2d2f31; text-align: start;&quot;&gt;예시&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1719825850551&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;findLongestSubstring('') // 0
findLongestSubstring('rithmschool') // 7
findLongestSubstring('thisisawesome') // 6
findLongestSubstring('thecatinthehat') // 7
findLongestSubstring('bbbbbb') // 1
findLongestSubstring('longestsubstring') // 8
findLongestSubstring('thisishowwedoit') // 6&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정답&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1719825958981&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function findLongestSubstring(str) {
  let longest = 0;
  let seen = {};
  let start = 0;
 
  for (let i = 0; i &amp;lt; str.length; i++) {
    let char = str[i];
    if (seen[char]) {
      start = Math.max(start, seen[char]);
    }
    longest = Math.max(longest, i - start + 1);
    seen[char] = i + 1;
  }
  return longest;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Algorithm/Theory</category>
      <category>JavaScript</category>
      <category>문제 해결</category>
      <category>알고리즘</category>
      <category>연습 문제</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/203</guid>
      <comments>https://systorage.tistory.com/entry/%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%ED%8C%A8%ED%84%B4-%EC%97%B0%EC%8A%B5-%EB%AC%B8%EC%A0%9C#entry203comment</comments>
      <pubDate>Mon, 1 Jul 2024 18:32:52 +0900</pubDate>
    </item>
    <item>
      <title>문제 해결 패턴</title>
      <link>https://systorage.tistory.com/entry/%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%ED%8C%A8%ED%84%B4</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 해결 패턴 소개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그래밍 문제를 효과적으로 해결하기 위해 다양한 문제 해결 패턴이 존재합니다. 이 글에서는 대표적인 문제 해결 패턴을 소개하고, 각 패턴에 대한 예시와 코드 리팩토링을 통해 성능을 개선하는 방법을 설명합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;빈도수 세기 패턴 (Frequency Counters)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빈도수 세기 패턴은 값의 빈도를 수집하기 위해 객체나 집합을 사용하는 방법입니다. 이를 통해 배열이나 문자열에서 중첩 루프(O(N^2))를 사용하지 않고 효율적으로 문제를 해결할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시 문제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 개의 배열을 입력으로 받는 same이라는 함수를 작성하세요.&lt;br /&gt;이 함수는 첫 번째 배열의 모든 값이 두 번째 배열에서 제곱된 값과 일치하면 true를 반환해야 합니다.&lt;br /&gt;값의 빈도수도 동일해야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1719506315991&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;same([1,2,3], [4,1,9]) // true
same([1,2,3], [1,9]) // false
same([1,2,1], [4,4,1]) // false (빈도가 같아야 함.)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1719505971507&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function same(arr1, arr2) {
    if (arr1.length !== arr2.length) {
        return false;
    }
    for (let i = 0; i &amp;lt; arr1.length; i++) {
        let correctIndex = arr2.indexOf(arr1[i] ** 2);
        if (correctIndex === -1) {
            return false;
        }
        arr2.splice(correctIndex, 1);
    }
    return true;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간복잡도: O(N^2)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리팩토링 후&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빈도수 세기 패턴을 적용한 리팩토링된 코드입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1719506021491&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function same(arr1, arr2) {
    if (arr1.length !== arr2.length) {
        return false;
    }
    let frequencyCounter1 = {};
    let frequencyCounter2 = {};
    for (let val of arr1) {
        frequencyCounter1[val] = (frequencyCounter1[val] || 0) + 1;
    }
    for (let val of arr2) {
        frequencyCounter2[val] = (frequencyCounter2[val] || 0) + 1;
    }
    for (let key in frequencyCounter1) {
        if (!(key ** 2 in frequencyCounter2)) {
            return false;
        }
        if (frequencyCounter2[key ** 2] !== frequencyCounter1[key]) {
            return false;
        }
    }
    return true;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간 복잡도: O(N)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다중 포인터 패턴 (Multiple Pointers)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다중 포인터 패턴은 인덱스나 위치에 해당하는 포인터나 값을 만든 다음 사용하여 특정 조건에 따라 시작 지점이나 끝 지점을 이동시키며 문제를 해결하는 방법입니다. 최소한의 공간 복잡도로 문제를 해결하는 데 매우 효율적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시 문제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정렬된 정수 배열을 입력으로 받아들이는 sumZero라는 함수를 작성하세요.&lt;br /&gt;이 함수는 합이 0이 되는 첫 번째 쌍을 찾아야 합니다.&lt;br /&gt;합이 0이 되는 두 값을 포함하는 배열을 반환하거나, 그런 쌍이 존재하지 않는 경우 undefined를 반환해야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1719506331670&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sumZero([-3,-2,-1,0,1,2,3]) // [-3,3] 
sumZero([-2,0,1,3]) // undefined
sumZero([1,2,3]) // undefined&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1719506223140&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function sumZero(arr) {
    for (let i = 0; i &amp;lt; arr.length; i++) {
        for (let j = i + 1; j &amp;lt; arr.length; j++) {
            if (arr[i] + arr[j] === 0) {
                return [arr[i], arr[j]];
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간 복잡도: O(N^2)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리팩토링 후&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다중 포인터 패턴을 적용한 리팩토링된 코드입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1719506393396&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function sumZero(arr){
    let left = 0;
    let right = arr.length - 1;
    while(left &amp;lt; right){
        let sum = arr[left] + arr[right];
        if(sum === 0){
            return [arr[left], arr[right]];
        } else if(sum &amp;gt; 0){
            right--;
        } else {
            left++;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간&amp;nbsp;복잡도&amp;nbsp;O(N)&lt;br /&gt;공간 복잡도 O(1)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;슬라이딩 윈도우 패턴 (Sliding Window)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;슬라이딩 윈도우 패턴은 배열이나 문자열 등의 데이터 부분 집합을 추적하는 데 매우 유용한 패턴입니다. 특정 조건에 따라 윈도우가 증가하거나 이동하며 문제를 해결합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시 문제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정수 배열과 n이라는 숫자를 입력으로 받아 n개의 연속된 요소들의 최대 합을 계산하는 maxSubarraySum 함수를 작성하세요.&lt;/p&gt;
&lt;pre id=&quot;code_1719506515097&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;maxSubarraySum([1,2,5,2,8,1,5],2) // 10
maxSubarraySum([1,2,5,2,8,1,5],4) // 17
maxSubarraySum([4,2,1,6],1) // 6
maxSubarraySum([4,2,1,6,2],4) // 13
maxSubarraySum([],4) // null&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1719506527137&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function maxSubarraySum(arr, num) {
  if ( num &amp;gt; arr.length){
    return null;
  }
  var max = -Infinity;
  for (let i = 0; i &amp;lt; arr.length - num + 1; i ++){
    temp = 0;
    for (let j = 0; j &amp;lt; num; j++){
      temp += arr[i + j];
    }
    if (temp &amp;gt; max) {
      max = temp;
    }
  }
  return max;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간 복잡도: O(N^2)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리팩토링 후&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;슬라이딩 윈도우 패턴을 적용한 리팩토링된 코드입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1719506578050&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function maxSubarraySum(arr, num){
  let maxSum = 0;
  let tempSum = 0;
  if (arr.length &amp;lt; num) return null;
  for (let i = 0; i &amp;lt; num; i++) {
    maxSum += arr[i];
  }
  tempSum = maxSum;
  for (let i = num; i &amp;lt; arr.length; i++) {
    tempSum = tempSum - arr[i - num] + arr[i];
    maxSum = Math.max(maxSum, tempSum);
  }
  return maxSum;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간&amp;nbsp;복잡도&amp;nbsp;O(N)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;분할과 정복 패턴 (Divide and Conquer)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분할과 정복 패턴은 데이터 세트를 더 작은 조각으로 나누고, 그런 다음 데이터의 부분 집합에 대해 프로세스를 반복하는 방법입니다. 이를 통해 시간 복잡도를 크게 줄일 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시 문제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정렬된 정수 배열을 입력으로 받아 주어진 값을 찾아 그 값이 위치한 인덱스를 반환하는 search 함수를 작성하세요. 값이 발견되지 않으면 -1을 반환해야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1719506645194&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;search([1,2,3,4,5,6],4) // 3
search([1,2,3,4,5,6],6) // 5
search([1,2,3,4,5,6],11) // -1&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1719506661045&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function search(arr, val){
    for(let i = 0; i &amp;lt; arr.length; i++){
        if(arr[i] === val){
            return i;
        }
    }
    return -1;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간 복잡도: O(N)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리팩토링 후&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분할과 정복 패턴을 적용한 리팩토링된 코드입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1719506702306&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function search(array, val) {

    let min = 0;
    let max = array.length - 1;

    while (min &amp;lt;= max) {
        let middle = Math.floor((min + max) / 2);
        let currentElement = array[middle];

        if (array[middle] &amp;lt; val) {
            min = middle + 1;
        }
        else if (array[middle] &amp;gt; val) {
            max = middle - 1;
        }
        else {
            return middle;
        }
    }

    return -1;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간 복잡도: O(Log N)&lt;/p&gt;</description>
      <category>Algorithm/Theory</category>
      <category>공간 복잡도</category>
      <category>다중 포인터</category>
      <category>문제 해결 패턴</category>
      <category>분할 정복</category>
      <category>빈도수 세기</category>
      <category>슬라이딩 윈도우</category>
      <category>시간 복잡도</category>
      <category>알고리즘</category>
      <category>자바스크립트</category>
      <category>효율성</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/202</guid>
      <comments>https://systorage.tistory.com/entry/%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%ED%8C%A8%ED%84%B4#entry202comment</comments>
      <pubDate>Fri, 28 Jun 2024 15:46:00 +0900</pubDate>
    </item>
    <item>
      <title>문제 해결 접근법</title>
      <link>https://systorage.tistory.com/entry/%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%EC%A0%91%EA%B7%BC%EB%B2%95</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;목표&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;알고리즘이 무엇인지 이해합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;알고리즘을 해결할 계획을 세웁니다.&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;알고리즘이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알고리즘은 특정 작업을 달성하기 위한 과정이나 일련의 단계를 의미합니다. 이는 컴퓨터 과학에서 매우 중요한 개념으로, 문제 해결의 기본입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;알고리즘을 알아야 하는 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그래밍에서 수행하는 거의 모든 작업에는 기본적이든 복잡하든 일종의 알고리즘이 포함됩니다. 문제를 효율적으로 해결하기 위해서는 알고리즘을 이해하고 활용하는 능력이 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 해결을 위한 계획을 수립하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1단계: 문제를 이해하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제를 이해하는 것은 첫 번째 단계입니다. 다음 질문들을 통해 문제를 명확히 할 수 있습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;문제를 내 방식대로 생각할 수 있는가?&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;문제가 어떤 입력값을 가지고 있는가?&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;문제에 대한 해결책에서 나와야 하는 결과가 무엇인가?&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;입력값이 출력값을 결정할 수 있는가?&lt;/b&gt; (문제를 해결할 수 있는 충분한 정보를 가지고 있는가?)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;문제의 일부인 데이터의 중요한 부분에 어떻게 레이블을 지정해야 하는가?&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제: 두 숫자의 합계를 반환하는 함수 작성하기&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;덧셈을 수행하는 함수&lt;/li&gt;
&lt;li&gt;입력이 정수인지, 실수인지, 큰 숫자인지 확인&lt;/li&gt;
&lt;li&gt;결과가 정수인지, 실수인지, 큰 숫자인지 확인&lt;/li&gt;
&lt;li&gt;한 숫자만 입력한 경우 처리 방법 결정 (예: null, undefined, +0)&lt;/li&gt;
&lt;li&gt;입력값과 결과값을 명확히 정의&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2단계: 구체적 예시를 찾아보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시를 통해 문제를 더 잘 이해할 수 있습니다. 예시는 온전성 검사를 제공하므로 최종 해결책이 제대로 작동하는지 확인할 수 있습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;간단한 예시로 시작하기&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;좀 더 복잡한 예시로 진행하기&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;빈 입력값이 있는 예제 살펴보기&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유효하지 않은 입력값이 있는 예제 살펴보기&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3단계: 세부 분석&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제를 해결하기 위한 단계를 명확하게 작성합니다. 기본적인 구성 요소들을 정의합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시: 문자열을 입력받아 각 문자 개수를 반환하는 함수&lt;/p&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1719475552706&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function charCount(str) {
    // 반환할 객체 생성
    // 문자열을 순회하며, 각 문자에 대해...
        // 만약 문자가 숫자/문자이고 객체에 키가 있다면, 카운트를 하나 증가
        // 만약 문자가 숫자/문자이고 객체에 없으면, 객체에 추가하고 값을 1로 설정
        // 만약 문자가 다른 것(공백, 마침표 등)이면 아무 것도 하지 않음
    // 마지막에 객체 반환
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4단계: 해결 또는 단순화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제의 핵심 어려움을 찾으면 일시적으로 이를 무시하고, 단순화된 해결책을 작성한 후 어려움을 다시 통합합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시:&lt;/p&gt;
&lt;pre id=&quot;code_1719475595670&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function charCount(str) {
    // 반환할 객체 생성
    const result = {};
    // 문자열을 순회하며, 각 문자에 대해...
    for(let i = 0; i &amp;lt; str.length; i++) {
        const char = str[i].toLowerCase()
        // 만약 문자가 숫자/문자이고 객체에 키가 있다면, 카운트를 하나 증가
        if(result[char] &amp;gt; 0) {
            result[char]++;
        }else{
        // 만약 문자가 숫자/문자이고 객체에 없으면, 객체에 추가하고 값을 1로 설정
            result[char] = 1;
        }
    }
        // 만약 문자가 다른 것(공백, 마침표 등)이면 아무 것도 하지 않음 (일단은 무시)
    // 마지막에 객체 반환
    return result;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5단계: 되돌아 보기와 리팩터링&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리팩터링 질문:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;결과를 확인할 수 있는가?&lt;/li&gt;
&lt;li&gt;결과를 다른 방법으로 도출할 수 있는가?&lt;/li&gt;
&lt;li&gt;한눈에 이해할 수 있는가?&lt;/li&gt;
&lt;li&gt;다른 문제에 이 결과나 방법을 사용할 수 있는가?&lt;/li&gt;
&lt;li&gt;해결책의 성능을 향상시킬 수 있는가?&lt;/li&gt;
&lt;li&gt;다른 리팩터링 방법을 생각해볼 수 있는가?&lt;/li&gt;
&lt;li&gt;다른 사람들은 이 문제를 어떻게 해결했는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1719475646163&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function charCount(str) {
    const result = {};
    for(let i = 0; i &amp;lt; str.length; i++) {
        const char = str[i].toLowerCase();
        if(/[a-z0-9]/.test(char)) {
            if(result[char] &amp;gt; 0) {
                result[char]++;
            }else{
                result[char] = 1;
            }
        }
    }
    return result;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리팩터링 후&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1719475665048&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function charCount(str) {
    const result = {};
    for(let char of str) {
        char = char.toLowerCase();
        if(/[a-z0-9]/.test(char)) {
            result[char] = ++result[char] || 1;
        }   
    }
    return result;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더&amp;nbsp;리팩토링을&amp;nbsp;하면&amp;nbsp;charAt()을&amp;nbsp;사용하면&amp;nbsp;더&amp;nbsp;빠르다.&lt;/p&gt;</description>
      <category>Algorithm/Theory</category>
      <category>JavaScript</category>
      <category>개발자</category>
      <category>리팩터링</category>
      <category>문제해결</category>
      <category>알고리즘</category>
      <category>자바스크립트</category>
      <category>코딩</category>
      <category>프로그래밍</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/201</guid>
      <comments>https://systorage.tistory.com/entry/%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%EC%A0%91%EA%B7%BC%EB%B2%95#entry201comment</comments>
      <pubDate>Thu, 27 Jun 2024 17:09:35 +0900</pubDate>
    </item>
    <item>
      <title>Javascript에서 배열과 오브젝트의 빅오 (Big - O)</title>
      <link>https://systorage.tistory.com/entry/Javascript%EC%97%90%EC%84%9C-%EB%B0%B0%EC%97%B4%EA%B3%BC-%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8A%B8%EC%9D%98-%EB%B9%85%EC%98%A4-Big-O</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Javascript에서 배열과 객체는 자주 사용되는 데이터 구조입니다. 이 글에서는 배열과 객체의 성능을 빅오 표기법(Big O Notation)을 통해 비교하고, 배열의 시작 부분에 요소를 추가하는데 비용이 많이 드는 이유와 내장 메서드의 런타임 성능을 분석합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;객체의 빅오 표기법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체는 정렬되지 않은 데이터 구조로, key-value 쌍으로 저장됩니다. 객체는 정렬이 필요 없을 때, 빠른 접근, 입력, 제거를 원할 때 유용합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;객체의 빅오&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;삽입&lt;/b&gt;: O(1)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;삭제&lt;/b&gt;: O(1)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;탐색&lt;/b&gt;: O(N)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;접근&lt;/b&gt;: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;내장 메서드의 빅오&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Object.keys&lt;/b&gt;: O(N)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Object.values&lt;/b&gt;: O(N)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Object.entries&lt;/b&gt;: O(N)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;hasOwnProperty&lt;/b&gt;: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배열의 빅오 표기법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열은 정렬된 데이터 구조로, 특정 위치에 요소를 추가하거나 제거할 때 성능 차이가 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;배열의 빅오&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;삽입&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;끝에 추가하면 O(1)&lt;/li&gt;
&lt;li&gt;앞에 추가하면 O(N) (모든 인덱스를 재정렬해야 하기 때문)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;삭제&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;끝에 추가하면 O(1)&lt;/li&gt;
&lt;li&gt;앞을 삭제하면 O(N) (모든 인덱스를 재정렬해야 하기 때문)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;탐색&lt;/b&gt;: O(N)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;접근&lt;/b&gt;: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;내장 메서드의 빅오&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;push&lt;/b&gt;: O(1)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;pop&lt;/b&gt;: O(1)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;shift&lt;/b&gt;: O(N)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;unshift&lt;/b&gt;: O(N)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;concat&lt;/b&gt;: O(N)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;slice&lt;/b&gt;: O(N)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;splice&lt;/b&gt;: O(N)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;sort&lt;/b&gt;: O(N * log N)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;forEach/map/filter/reduce&lt;/b&gt;: O(N)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열의 시작 부분에 요소를 추가하거나 제거하는 작업은 배열의 모든 요소를 이동시켜야 하므로 O(N)의 시간이 소요됩니다. 반면, 배열의 끝에 요소를 추가하거나 제거하는 작업은 O(1)로 더 효율적입니다. 따라서, 비어있는 배열을 제외하고는 push()와 pop()이 shift()와 unshift()보다 항상 빠릅니다.&lt;/p&gt;</description>
      <category>Algorithm/Theory</category>
      <category>JavaScript</category>
      <category>개발자</category>
      <category>객체</category>
      <category>배열</category>
      <category>빅오표기법</category>
      <category>성능</category>
      <category>프로그래밍</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/200</guid>
      <comments>https://systorage.tistory.com/entry/Javascript%EC%97%90%EC%84%9C-%EB%B0%B0%EC%97%B4%EA%B3%BC-%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8A%B8%EC%9D%98-%EB%B9%85%EC%98%A4-Big-O#entry200comment</comments>
      <pubDate>Wed, 26 Jun 2024 16:29:03 +0900</pubDate>
    </item>
    <item>
      <title>빅오 표기법 (Big-O Notation)</title>
      <link>https://systorage.tistory.com/entry/%EB%B9%85%EC%98%A4-%ED%91%9C%EA%B8%B0%EB%B2%95-Big-O-Notation</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;목표&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;빅오 표기법의 필요성&lt;/li&gt;
&lt;li&gt;빅오 표기법이 무엇인지&lt;/li&gt;
&lt;li&gt;빅오 표기법의 간단한 표현법&lt;/li&gt;
&lt;li&gt;시간복잡도와 공간복잡도의 정의&lt;/li&gt;
&lt;li&gt;빅오 표기법을 이용한 알고리즘 표기법&lt;/li&gt;
&lt;li&gt;로그(log)가 무엇인지&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;빅오 표기법의 필요성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 문제를 해결하는 두 가지 방법이 있을 때, 하나는 루프를 사용하고, 다른 하나는 리스트나 문자열을 사용하는 방법일 수 있습니다. 무엇이 더 나은지 알기 위해서는 빅오 표기법이 필요합니다. 빅오 표기법을 사용하면 코드를 일반화하고 비교하며 성능을 평가할 수 있는 시스템을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1부터 N까지 모든 숫자를 더하는 함수를 예로 들어보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1719382225803&quot; class=&quot;javascript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;// 첫 번째 방법: 루프 사용
function addUpTo(n) {
  let total = 0;
  for (let i = 0; i &amp;lt;= n; i++) {
    total += i;
  }
  return total;
}

// 두 번째 방법: 수학적 공식 사용
function addUpTo(n) {
  return (n * (n + 1)) / 2;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;어떤 방법이 더 나을까요?&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어떤 것이 더 빠를까요?&lt;/li&gt;
&lt;li&gt;어떤 것이 더 적은 메모리를 사용할까요?&lt;/li&gt;
&lt;li&gt;어떤 것이 더 읽기 쉬울까요?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;성능 평가 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선, 코드가 얼마나 빠른지를 설명할 때는 아래와 같이 평가할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1719382291729&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let t1 = performance.now();
addUpTo(100000000);
let t2 = performance.now();
console.log(`Time: ${(t2 - t1) / 1000} seconds`);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동일한 작업을 하지만 두 번째 코드가 훨씬 빠릅니다. 그러나 performance.now()로 두 시간을 단순히 빼는 것은 불확실하고 완전히 믿을 수 없습니다. 기계마다, 매번 실행할 때마다 결과가 달라질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 코드 실행 시간을 재는 것보다 컴퓨터가 처리해야 하는 연산 갯수를 세면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어&lt;/p&gt;
&lt;pre id=&quot;code_1719382346158&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function addUpTo(n) {
  return (n * (n + 1)) / 2;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드는 * 연산 1번, + 연산 1번, / 연산 1번, 총 3번의 연산이 이루어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만&lt;/p&gt;
&lt;pre id=&quot;code_1719382362289&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function addUpTo(n) {
  let total = 0;
  for (let i = 0; i &amp;lt;= n; i++) {
    total += i;
  }
  return total;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 함수는 대충 5n + 2 만큼 연산이 일어납니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;초기화(let total = 0): 1번&lt;/li&gt;
&lt;li&gt;변수 선언(let i = 0): 1번&lt;/li&gt;
&lt;li&gt;비교 연산(i &amp;lt;= n): n번 (루프가 n+1번 돌아가므로)&lt;/li&gt;
&lt;li&gt;증가 연산(i++): n번 및 n번 선언&lt;/li&gt;
&lt;li&gt;덧셈 연산(total += i): n번&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런식으로 연산을 모두 세는건 쉽지 않은 작업이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 점은 N이 커질수록 연산의 갯수도 N만큼 늘어난다는 점입니다. 전체적인 추세가 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빅오는 대략적으로 연산의 수를 세는 것에 붙인 공식적인 표현입니다. 입력된 내용이 늘어날수록 알고리즘의 실행 시간이 어떻게 변하는지 설명하는 공식적인 방식입니다. 빅오는 입력 크기와 실행 시간의 관계를 나타냅니다. 일반적으로 가장 높은 실행 시간 값들을 나타냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;빅오 표기법의 간단한 표현법&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;O(1)&lt;/b&gt;: 상수 시간 (입력 크기에 관계없이 일정한 시간)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;O(log n)&lt;/b&gt;: 로그 시간 (입력 크기가 커질수록 시간이 느리게 증가)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;O(n)&lt;/b&gt;: 선형 시간 (입력 크기에 비례하여 시간 증가)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;O(n log n)&lt;/b&gt;: 로그 선형 시간 (예: 퀵 정렬)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;O(n^2)&lt;/b&gt;: 이차 시간 (입력 크기의 제곱에 비례하여 시간 증가)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;O(2^n)&lt;/b&gt;: 지수 시간 (입력 크기에 따라 시간 폭발적으로 증가)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;O(n!)&lt;/b&gt;: 팩토리얼 시간 (입력 크기에 따라 시간 급격히 증가)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;big_o_notation_graph.png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NY65o/btsId2NX5w8/VSYKOL6SZIfbMcOX2sm1qk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NY65o/btsId2NX5w8/VSYKOL6SZIfbMcOX2sm1qk/img.png&quot; data-alt=&quot;시간복잡도 그래프&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NY65o/btsId2NX5w8/VSYKOL6SZIfbMcOX2sm1qk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNY65o%2FbtsId2NX5w8%2FVSYKOL6SZIfbMcOX2sm1qk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;740&quot; height=&quot;444&quot; data-filename=&quot;big_o_notation_graph.png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;시간복잡도 그래프&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;산술 연산은 상수입니다. N의 값에 관계없이 일정한 시간입니다. (예: 2 + 2, 1000000 + 2)&lt;/li&gt;
&lt;li&gt;변수에 값을 저장하는 것은 별다른 시간 차이가 없습니다. (예: x = 100, x = 100000)&lt;/li&gt;
&lt;li&gt;배열에서 인덱스를 사용하거나 객체에서 키를 사용해서 찾는 것은 상수 시간입니다.&lt;/li&gt;
&lt;li&gt;루프가 있으면 복잡도가 루프의 길이와 안에 있는 연산의 곱이 됩니다. for문을 사용해서 배열을 처리할 경우 O(n)입니다.&lt;/li&gt;
&lt;li&gt;루프 중첩이 있다면 O(n^2)입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시간 복잡도와 공간 복잡도&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지는 시간과 관련된 부분을 걱정했습니다. 이를 시간 복잡도(Time Complexity)라고 합니다. 이제는 입력이 커질수록 알고리즘이 얼마나 많은 공간을 차지하는지에 대해서 얘기해보겠습니다. 이를 공간 복잡도(Space Complexity)라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공간 복잡도는 알고리즘이 사용하는 메모리의 양을 나타냅니다. 이는 주로 두 가지 요소로 구성됩니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;고정 공간 (Fixed Space): 알고리즘이 사용하는 상수 공간입니다. 예: 함수 내에서 선언되는 변수들&lt;/li&gt;
&lt;li&gt;가변 공간 (Variable Space): 알고리즘의 입력 크기에 따라 달라지는 공간입니다. 예: 동적으로 할당되는 배열이나 리스트&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시를 통해 공간 복잡도를 살펴보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1719382890359&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// O(1) 공간 복잡도: 고정 공간만 사용
function addUpTo(n) {
  return (n * (n + 1)) / 2;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 함수는 입력 크기와 상관없이 일정한 공간만을 사용합니다. 따라서 공간 복잡도는 O(1)입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1719382905622&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// O(n) 공간 복잡도: 가변 공간 사용
function createArray(n) {
  let arr = [];
  for (let i = 0; i &amp;lt; n; i++) {
    arr.push(i);
  }
  return arr;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 함수는 입력 크기 n에 비례하여 배열을 생성합니다. 따라서 공간 복잡도는 O(n)입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공간 복잡도는 알고리즘의 효율성을 평가하는 데 중요한 요소입니다. 입력 크기가 커질수록 알고리즘이 사용하는 메모리가 어떻게 변하는지 이해하면, 더 효율적인 알고리즘을 설계할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;로그(log)란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그는 특정 숫자를 몇 번 곱해야 다른 숫자가 되는지를 나타내는 수학적 개념입니다. 예를 들어, log2(8) = 3은 2를 몇 번 곱해야 8이 되는지를 나타냅니다. 로그 시간 복잡도는 이와 같이 큰 문제를 작은 문제로 나누는 알고리즘에서 주로 나타납니다. 예: 이진 탐색은 로그 시간 복잡도를 가집니다.&lt;/p&gt;</description>
      <category>Algorithm/Theory</category>
      <category>개발자</category>
      <category>공간복잡도</category>
      <category>빅오표기법</category>
      <category>시간복잡도</category>
      <category>알고리즘</category>
      <category>프로그래밍</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/199</guid>
      <comments>https://systorage.tistory.com/entry/%EB%B9%85%EC%98%A4-%ED%91%9C%EA%B8%B0%EB%B2%95-Big-O-Notation#entry199comment</comments>
      <pubDate>Wed, 26 Jun 2024 15:34:22 +0900</pubDate>
    </item>
    <item>
      <title>[Ubuntu] Please install all available updates for your release before upgrading 문제 해결</title>
      <link>https://systorage.tistory.com/entry/Ubuntu-Please-install-all-available-updates-for-your-release-before-upgrading-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;서버에 설치되어 있는 node.js&amp;nbsp; 버전을 20으로 올리기 위해서 ubuntu 버전을 18 버전에서 20 버전으로 업그레이드하는 도중&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;Please install all available updates for your release before upgrading&quot; 라는 오류 메세지를 마주했다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 이 문제를 해결한 과정을 공유하고자 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. version 업데이트 전에 패키지 업데이트 및 업그레이드&lt;/p&gt;
&lt;pre id=&quot;code_1704869799667&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt update
sudo apt upgrade&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. mognodb 관련 패키지들이 업데이트 되지않음&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Pasted Image 20240110141426_283.png&quot; data-origin-width=&quot;1346&quot; data-origin-height=&quot;92&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sKjVs/btsDhWMCjAi/f81vyZ1pbC1S6cAuEDQPHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sKjVs/btsDhWMCjAi/f81vyZ1pbC1S6cAuEDQPHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sKjVs/btsDhWMCjAi/f81vyZ1pbC1S6cAuEDQPHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsKjVs%2FbtsDhWMCjAi%2Ff81vyZ1pbC1S6cAuEDQPHK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;740&quot; height=&quot;51&quot; data-filename=&quot;Pasted Image 20240110141426_283.png&quot; data-origin-width=&quot;1346&quot; data-origin-height=&quot;92&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 현재 ubuntu 버전 확인 및 업데이트 진행&lt;/p&gt;
&lt;pre id=&quot;code_1704870257161&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;lsb_release -a // 현재 버전 확인
sudo do-release-upgrade // 업그레이드 가능한 ubuntu 버전으로 업그레이드&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. Please install all available updates for your release before upgrading 오류 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리서치 결과 해당 패키지들을 지우고 다시 삭제하는 방법이 있었지만 지우지 못하는 상황이였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 개별적으로 패키지들을 업데이트 해줬다. 왜 인지는 잘 모르겠으나 위 1번 명령어로 전체 업데이트가 되지 않았다.&lt;/p&gt;
&lt;pre id=&quot;code_1704870398284&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt install --only-upgrade 패키지명

sudo apt install --only-upgrade mongodb-org
sudo apt install --only-upgrade mongodb-org-database
sudo apt install --only-upgrade mongodb-org-mongos
sudo apt install --only-upgrade mongodb-org-server
sudo apt install --only-upgrade mongodb-org-shell
sudo apt install --only-upgrade mongodb-org-tools&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 개별적인 업데이트 완료 후 버전 업그레이드&lt;/p&gt;</description>
      <category>Linux</category>
      <category>Linux</category>
      <category>ubuntu</category>
      <category>오류해결</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/185</guid>
      <comments>https://systorage.tistory.com/entry/Ubuntu-Please-install-all-available-updates-for-your-release-before-upgrading-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0#entry185comment</comments>
      <pubDate>Wed, 10 Jan 2024 16:09:18 +0900</pubDate>
    </item>
    <item>
      <title>[기타] 역기획 이란?</title>
      <link>https://systorage.tistory.com/entry/%EA%B8%B0%ED%83%80-%EC%97%AD%EA%B8%B0%ED%9A%8D-%EC%9D%B4%EB%9E%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 제품과 서비스의 세계에서 굉장히 중요한 역할을 하는 &quot;역기획&quot;에 대해 이야기하려고 한다. 좋아하는 게임이나 사용하는 앱, 서비스가 어떻게 구성되었는지 궁금해하셨던 적이 있다면, 이런 호기심을 해결해 줄 도구가 바로 역기획입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;역기획이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역기획은 주로 게임, 소프트웨어, 서비스 등의 제품을 분석하여 그 제품의 기획 과정을 추정하거나 재구성하는 방법을 말한다. 제품이 어떻게 구성되었는지, 왜 그렇게 설계되었는지를 이해하는 것이 주 목적이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;왜&amp;nbsp;역기획을&amp;nbsp;해야하는가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;경쟁 분석&lt;/b&gt;: 다른 회사의 제품을 분석하여 그 특징, 장단점을 파악하고, 자사의 제품과 비교하는데 사용될 수 있다.&lt;br /&gt;&lt;b&gt;학습&amp;nbsp;목적&lt;/b&gt;: 개발자나 디자이너들이 특정 기술이나 디자인 패턴을 배우기 위해 좋은 예시로 사용된다.&lt;br /&gt;&lt;b&gt;기능&amp;nbsp;개선&amp;nbsp;및&amp;nbsp;참고&lt;/b&gt;: 기존의 제품에서 어떤 부분이 잘 작동하는지, 어떤 부분이 개선되어야 하는지를 파악하여 참고하거나 기능 개선에 활용될 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;역기획의&amp;nbsp;절차&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;제품 사용&lt;/b&gt;: 먼저 해당 제품을 철저히 사용하여 기능과 사용자 경험을 파악한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;문서화&lt;/b&gt;: 사용한 경험과 제품의 주요 기능, 구조, 디자인 패턴 등을 문서화한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;분석&lt;/b&gt;: 문서화된 정보를 바탕으로 제품의 핵심 목표, 사용자 대상, 기술적인 구조 등을 분석한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;결과 공유&lt;/b&gt;: 역기획의 결과를 팀 또는 관련된 사람들과 공유하며, 얻어진 통찰을 바탕으로 토론하고 향후 방향성을 결정한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;역기획은 제품 개발에 깊은 통찰력을 제공하며, 다양한 측면에서의 제품 이해와 개선에 큰 도움이 된다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>기타</category>
      <category>경쟁분석</category>
      <category>디자인패턴</category>
      <category>사용자경험</category>
      <category>서비스디자인</category>
      <category>역기획</category>
      <category>제품개발</category>
      <category>제품디자인</category>
      <category>제품분석</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/184</guid>
      <comments>https://systorage.tistory.com/entry/%EA%B8%B0%ED%83%80-%EC%97%AD%EA%B8%B0%ED%9A%8D-%EC%9D%B4%EB%9E%80#entry184comment</comments>
      <pubDate>Fri, 15 Sep 2023 14:49:42 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 가상 메모리(swap) 사용 시 CPU 점유율이 폭증하는 이유</title>
      <link>https://systorage.tistory.com/entry/OS-%EA%B0%80%EC%83%81-%EB%A9%94%EB%AA%A8%EB%A6%ACswap-%EC%82%AC%EC%9A%A9-%EC%8B%9C-CPU-%EC%A0%90%EC%9C%A0%EC%9C%A8%EC%9D%B4-%ED%8F%AD%EC%A6%9D%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;연구팀을 위해 데이터를 뽑는 도중 큰 데이터를 뽑다가 서버를 터트렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 원인에 대해서 공부했던 내용에 대해서 서술한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;가상 메모리(swap)란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가상 메모리는 물리적인 RAM이 부족할 때 디스크 공간의 일부를 RAM처럼 사용하는 시스템이다. 이는 임시 방편으로 RAM이 부족한 상황에서 프로세스를 계속 실행하게 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 사용자가 8GB RAM을 갖춘 컴퓨터에서 10GB의 메모리를 요구하는 대규모 응용 프로그램을 실행하려고 시도한다면, 실제 물리적인 RAM만으로는 충분하지 않다. 이때, 운영체제는 2GB의 데이터를 하드 디스크의 swap 영역에 저장하게 된다.&lt;br /&gt;&lt;br /&gt;이로 인해 사용자는 마치 10GB의 RAM이 있는 것처럼 프로그램을 실행할 수 있다. 하지만, 디스크 I/O는 RAM보다 느리므로 swap을 사용할 때의 성능은 RAM을 직접 사용할 때보다 느릴 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;가상 메모리의 동작 원리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때 물리 메모리(RAM)가 부족하게 되면, 운영체제는 잘 사용하지 않는 메모리 페이지를 가상 메모리 영역으로 이동(swap out)시킨다. 반대로, 해당 페이지가 다시 필요하면 가상 메모리에서 물리 메모리로 다시 가져온다(swap in). 이 때 디스크 I/O를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CPU 점유율의 급증의 원인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;I/O 연산: 디스크 I/O는 RAM에 비해 상당히 느리다. swap 영역에 데이터를 쓰거나 읽는 것은 RAM에서 직접 데이터를 처리하는 것에 비해 훨씬 오래 걸린다. 따라서, swap을 자주 사용하면 이로 인해 발생하는 I/O 연산이 CPU 부하를 증가시킨다.&lt;br /&gt;&lt;br /&gt;페이지 폴트: 물리 메모리에서 페이지가 사라지고 swap 영역으로 이동하면, 해당 페이지에 접근할 때 페이지 폴트(page fault)가 발생한다. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;페이지 폴트(page fault)는 프로세스가 접근하려고 하는 메모리 페이지가 물리적인 메모리(RAM)에 로드되어 있지 않을 때 발생하는 상황을 말한다. 페이지 폴트가 발생하면 운영체제는 해당 페이지를 물리 메모리에 로드해야 한다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;이런 페이지 폴트 처리도 CPU 부하를 증가시키는 원인 중 하나이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해결 방안&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 추가: 물리 메모리를 추가하여 RAM 용량을 늘리는 것이 가장 확실한 해결책이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 개선: 가상 메모리를 사용하지 않게 코드를 잘 짜자 (ex) 큰 데이터를 전부 메모리에 올리지 않는다)&lt;br /&gt;&lt;br /&gt;가상 메모리는 물리 메모리가 부족할 때 임시로 사용하는 메모리로, 성능 문제의 주요 원인이 될 수 있다. 이를 효과적으로 관리하려면 시스템의 메모리 사용 패턴을 잘 이해하고, 적절한 최적화 방법을 적용해야 한다.&lt;/p&gt;</description>
      <category>Computer Science/Operating System</category>
      <category>RAM</category>
      <category>swap</category>
      <category>가상 메모리</category>
      <category>디스크 I/O</category>
      <category>메모리 관리</category>
      <category>성능 최적화</category>
      <category>시스템 성능</category>
      <category>운영체제</category>
      <category>페이지 폴트</category>
      <category>하드웨어</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/183</guid>
      <comments>https://systorage.tistory.com/entry/OS-%EA%B0%80%EC%83%81-%EB%A9%94%EB%AA%A8%EB%A6%ACswap-%EC%82%AC%EC%9A%A9-%EC%8B%9C-CPU-%EC%A0%90%EC%9C%A0%EC%9C%A8%EC%9D%B4-%ED%8F%AD%EC%A6%9D%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0#entry183comment</comments>
      <pubDate>Thu, 14 Sep 2023 14:40:25 +0900</pubDate>
    </item>
    <item>
      <title>[Shebang] Shebang(#!)이란?</title>
      <link>https://systorage.tistory.com/entry/Shebang-Shebang%EC%9D%B4%EB%9E%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;개발자라면 한번쯤 파일 최상단에 #!로 시작하는 &quot;#! /bin/bash&quot; 또는 &quot;#!/usr/bin/env node&quot; 이런 형식의 문자열을 본적이 있을것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 프로그래밍 스크립트에서 자주 볼 수 있는 &amp;lsquo;Shebang&amp;rsquo;이라는 특수한 기호에 대해 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Shebang이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Shebang은 스크립트의 가장 윗부분에 위치하는 #!로 시작하는 라인을 말한다. 주로 Unix와 유사한 운영체제에서 사용되며, 이 라인은 스크립트를 실행할 때 어떤 인터프리터를 사용할 것인지 시스템에게 알려준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예시&lt;/h2&gt;
&lt;pre id=&quot;code_1694154023573&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#!/bin/bash
echo &quot;Hello, World!&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 스크립트에서 #!/bin/bash는 이 스크립트를 bash 쉘로 실행하라는 것을 나타낸다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1694154053838&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#!/usr/bin/env node
console.log(&quot;Hello from Node.js!&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스크립트는 Node.js 환경에서 실행된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;왜 Shebang이 필요할까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스크립트는 여러가지 프로그래밍 언어로 작성될 수 있다. 예를 들어, Python, Perl, Ruby, Node.js 등 다양한 언어가 있다. Shebang은 스크립트를 실행할 때 적절한 인터프리터를 자동으로 선택해서 사용하게 도와준다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;#!/usr/bin/env의&amp;nbsp;의미&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 시스템에서는 특정 인터프리터의 절대 경로를 shebang에 직접 지정한다. 그러나 #!/usr/bin/env를 사용하면 환경변수 $PATH에서 해당 인터프리터를 검색하여 사용한다. 이 방식은 스크립트가 여러 시스템에서 동작할 때 인터프리터의 위치가 다를 수 있으므로 유용하다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;주의할 점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Shebang은 반드시 파일의 첫 줄에 있어야 한다.&lt;br /&gt;Shebang 뒤에 오는 경로는 인터프리터의 절대 경로여야 한다. 예: #!/usr/bin/python3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Shebang은 스크립트를 작성하고 실행할 때 꼭 알아두면 좋은 지식 중 하나이다. Shebang을 보게 되면, 그 의미와 용도를 정확히 이해할 수 있을 것이다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>기타</category>
      <category>bash</category>
      <category>ENV</category>
      <category>node.js</category>
      <category>Shebang</category>
      <category>Unix</category>
      <category>스크립트</category>
      <category>인터프리터</category>
      <category>프로그래밍</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/182</guid>
      <comments>https://systorage.tistory.com/entry/Shebang-Shebang%EC%9D%B4%EB%9E%80#entry182comment</comments>
      <pubDate>Fri, 8 Sep 2023 15:24:31 +0900</pubDate>
    </item>
    <item>
      <title>[암호화 기법] 봉투 암호화 (Envelope encryption)</title>
      <link>https://systorage.tistory.com/entry/%EC%95%94%ED%98%B8%ED%99%94-%EA%B8%B0%EB%B2%95-%EB%B4%89%ED%88%AC-%EC%95%94%ED%98%B8%ED%99%94-Envelope-encryption</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;데이터&amp;nbsp;보안은&amp;nbsp;현대&amp;nbsp;디지털&amp;nbsp;환경에서&amp;nbsp;가장&amp;nbsp;중요한&amp;nbsp;주제&amp;nbsp;중&amp;nbsp;하나입니다.&amp;nbsp;봉투&amp;nbsp;암호화는&amp;nbsp;이&amp;nbsp;보안&amp;nbsp;전략의&amp;nbsp;핵심적인&amp;nbsp;부분으로&amp;nbsp;자리&amp;nbsp;잡았습니다.&amp;nbsp;이&amp;nbsp;기법을&amp;nbsp;통해&amp;nbsp;기업들은&amp;nbsp;중요한&amp;nbsp;정보를&amp;nbsp;안전하게&amp;nbsp;보호하면서도&amp;nbsp;효율적인&amp;nbsp;키&amp;nbsp;관리를&amp;nbsp;유지할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;이&amp;nbsp;글에서는&amp;nbsp;봉투&amp;nbsp;암호화의&amp;nbsp;근본적인&amp;nbsp;원리부터&amp;nbsp;구체적인&amp;nbsp;작동&amp;nbsp;방식까지&amp;nbsp;한층&amp;nbsp;더&amp;nbsp;깊게&amp;nbsp;알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 봉투 암호화의 기본 원리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;봉투 암호화는 이름에서 알 수 있듯이 '봉투'의 개념을 기반으로 합니다. 여기서 '봉투'는 마스터 키에 의해 암호화된 데이터 키를 의미하며, 이 데이터 키는 실제 데이터의 암호화와 복호화에 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2.&amp;nbsp;봉투&amp;nbsp;암호화의&amp;nbsp;주요&amp;nbsp;구성요소&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 가지 주요 키로 구성됩니다.&lt;br /&gt;&lt;br /&gt;데이터&amp;nbsp;키(Data&amp;nbsp;Key):&amp;nbsp;이&amp;nbsp;키는&amp;nbsp;실제&amp;nbsp;데이터를&amp;nbsp;암호화하거나&amp;nbsp;복호화하는&amp;nbsp;데&amp;nbsp;사용됩니다.&amp;nbsp;각&amp;nbsp;데이터&amp;nbsp;세트&amp;nbsp;또는&amp;nbsp;세션마다&amp;nbsp;새로운&amp;nbsp;데이터&amp;nbsp;키가&amp;nbsp;생성될&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;마스터&amp;nbsp;키(Master&amp;nbsp;Key):&amp;nbsp;데이터&amp;nbsp;키를&amp;nbsp;암호화하고&amp;nbsp;복호화하는&amp;nbsp;데&amp;nbsp;사용됩니다.&amp;nbsp;이&amp;nbsp;키는&amp;nbsp;안전하게&amp;nbsp;보관되어야&amp;nbsp;하며,&amp;nbsp;키&amp;nbsp;관리의&amp;nbsp;중심이&amp;nbsp;됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3.&amp;nbsp;암호화&amp;nbsp;과정의&amp;nbsp;세부&amp;nbsp;사항&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;봉투 암호화의 암호화 과정은 다음과 같이 진행됩니다.&lt;br /&gt;&lt;br /&gt;1. 데이터 키 생성: 먼저, 유니크한 데이터 키가 생성됩니다.&lt;br /&gt;2. 실제 데이터 암호화: 생성된 데이터 키를 사용하여 원본 데이터를 암호화합니다.&lt;br /&gt;3. 데이터 키 암호화: 마스터 키를 사용하여 데이터 키를 암호화합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-08-25 오후 2.02.11.png&quot; data-origin-width=&quot;1172&quot; data-origin-height=&quot;1498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d5O4Cq/btssf2CvbyE/aPgTWa6LfrR87yHVF26z1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d5O4Cq/btssf2CvbyE/aPgTWa6LfrR87yHVF26z1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d5O4Cq/btssf2CvbyE/aPgTWa6LfrR87yHVF26z1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd5O4Cq%2Fbtssf2CvbyE%2FaPgTWa6LfrR87yHVF26z1K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;720&quot; height=&quot;920&quot; data-filename=&quot;스크린샷 2023-08-25 오후 2.02.11.png&quot; data-origin-width=&quot;1172&quot; data-origin-height=&quot;1498&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 복호화 과정의 세부 사항&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 안전하게 복호화하려면 다음 과정을 따릅니다.&lt;br /&gt;&lt;br /&gt;1. 데이터 키 복호화: 마스터 키를 사용하여 암호화된 데이터 키를 복호화합니다.&lt;br /&gt;2. 실제 데이터 복호화: 복호화된 데이터 키를 사용하여 암호화된 데이터를 복호화하여 원본 데이터를 얻습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-08-25 오후 2.03.00.png&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;1144&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t9eky/btsscCxD3mm/it4RH1V7Q8h3XrnwyhSfvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t9eky/btsscCxD3mm/it4RH1V7Q8h3XrnwyhSfvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t9eky/btsscCxD3mm/it4RH1V7Q8h3XrnwyhSfvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft9eky%2FbtsscCxD3mm%2Fit4RH1V7Q8h3XrnwyhSfvK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;720&quot; height=&quot;758&quot; data-filename=&quot;스크린샷 2023-08-25 오후 2.03.00.png&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;1144&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 봉투 암호화의 장점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;봉투 암호화는 중앙화된 키 관리 시스템을 통해 기업이 키 관리의 복잡성을 크게 줄일 수 있도록 해줍니다. 또한, 각 데이터나 세션마다 다른 데이터 키를 생성할 수 있기 때문에 데이터 별로 고유한 보안 레벨을 제공합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;6.&amp;nbsp;실제&amp;nbsp;활용&amp;nbsp;사례:&amp;nbsp;클라우드&amp;nbsp;서비스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS의 KMS(Key Management Service)와 같은 클라우드 기반의 키 관리 서비스는 봉투 암호화를 활용하여 사용자의 데이터를 효과적으로 보호합니다. 이를 통해 클라우드 환경에서도 데이터의 보안을 철저히 유지할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;봉투&amp;nbsp;암호화는&amp;nbsp;현대&amp;nbsp;디지털&amp;nbsp;보안&amp;nbsp;전략의&amp;nbsp;핵심&amp;nbsp;부분으로,&amp;nbsp;데이터의&amp;nbsp;보호와&amp;nbsp;효율적인&amp;nbsp;키&amp;nbsp;관리를&amp;nbsp;동시에&amp;nbsp;가능하게&amp;nbsp;합니다.&amp;nbsp;이러한&amp;nbsp;이해를&amp;nbsp;바탕으로&amp;nbsp;기업과&amp;nbsp;개인은&amp;nbsp;더욱&amp;nbsp;강력한&amp;nbsp;보안&amp;nbsp;환경을&amp;nbsp;구축할&amp;nbsp;수&amp;nbsp;있을&amp;nbsp;것입니다.&lt;/p&gt;</description>
      <category>기타</category>
      <category>AWSKMS</category>
      <category>데이터보안</category>
      <category>디지털보안전략</category>
      <category>봉투암호화</category>
      <category>암호화</category>
      <category>클라우드보안</category>
      <category>키관리체계</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/181</guid>
      <comments>https://systorage.tistory.com/entry/%EC%95%94%ED%98%B8%ED%99%94-%EA%B8%B0%EB%B2%95-%EB%B4%89%ED%88%AC-%EC%95%94%ED%98%B8%ED%99%94-Envelope-encryption#entry181comment</comments>
      <pubDate>Fri, 25 Aug 2023 14:03:42 +0900</pubDate>
    </item>
    <item>
      <title>[Javascript] async 함수를 사용할때 return이 없어도 되는가?</title>
      <link>https://systorage.tistory.com/entry/Javascript-async-%ED%95%A8%EC%88%98%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%A0%EB%95%8C-return%EC%9D%B4-%EC%97%86%EC%96%B4%EB%8F%84-%EB%90%98%EB%8A%94%EA%B0%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 프로그래밍에는 많은 난관이 있다. JavaScript에서는 이를 간단하게 만들어 주는 async/await 패턴이 있다. 하지만 이 패턴 내에서도 종종 개발자들이 혼란스러워하는 부분이 있다. 그 중 하나가 바로 async 함수 내부의 return에 관한 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기본적인 함수와 반환 값&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 함수에서 값을 반환하지 않으면, 해당 함수는 undefined를 반환합니다. 그렇다면 async 함수에서는 어떻게 될까&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1692161573646&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function normalFunction() {
  console.log(&quot;This is a normal function&quot;);
}

const result = normalFunction();
console.log(result);  // undefined&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;async&amp;nbsp;함수의&amp;nbsp;기본&amp;nbsp;동작&amp;nbsp;방식&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;async 함수는 항상 Promise 객체를 반환한다. 만약 함수 내에서 명시적으로 값을 반환하지 않는다면, 그 함수는 undefined 값을 resolve하는 Promise를 반환한다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1692161627051&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const asyncFunction = async () =&amp;gt; {
  await SomethingPromise();
  console.log(&quot;This is an async function&quot;);
}

const asyncResult = await asyncFunction();
console.log(asyncResult);  // undefined&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 async 함수는 이렇게 동작하는가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript의 async/await 패턴의 주 목적은 비동기 코드를 마치 동기 코드처럼 쓰게 만드는 것이다. async 함수가 Promise를 반환함으로써, await 은 해당 Promise가 resolve되거나 reject될 때까지 기다릴 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, async 함수 내에서 반환된 값이 없더라도, 함수 자체가 끝나면 해당 Promise는 resolve 상태가 되어 await 다음의 코드가 실행될 수 있게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 개발 과정에서, async 함수 내에서 항상 값을 반환할 필요는 없다. 종종 데이터를 가져오거나 다른 비동기 작업을 수행한 후에, 그 결과를 반환하지 않고 다른 작업을 진행하는 경우도 많다. 이러한 패턴을 이해하면, 비동기 코드의 흐름과 동작 방식을 더욱 잘 이해하고 활용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;JavaScript의 async/await는 비동기 로직을 쉽게 이해하고 구현할 수 있도록 도와준다. 함수의 종료와 Promise의 resolve 시점을 명확하게 파악하는 것은 이 패턴을 효과적으로 활용하기 위한 중요한 핵심입니다.&lt;/p&gt;</description>
      <category>Programming/Javascript</category>
      <category>async/await</category>
      <category>JavaScript</category>
      <category>Promise</category>
      <category>개발노하우</category>
      <category>비동기프로그래밍</category>
      <category>코딩팁</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/180</guid>
      <comments>https://systorage.tistory.com/entry/Javascript-async-%ED%95%A8%EC%88%98%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%A0%EB%95%8C-return%EC%9D%B4-%EC%97%86%EC%96%B4%EB%8F%84-%EB%90%98%EB%8A%94%EA%B0%80#entry180comment</comments>
      <pubDate>Wed, 16 Aug 2023 14:02:21 +0900</pubDate>
    </item>
    <item>
      <title>[Mongodb] explain을 활용한 mongodb 쿼리 최적화</title>
      <link>https://systorage.tistory.com/entry/Mongodb-explain%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-mongodb-%EC%BF%BC%EB%A6%AC-%EC%B5%9C%EC%A0%81%ED%99%94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;MongoDB, 대용량 데이터를 처리하고 저장하는 데 있어서 매우 효과적인 NoSQL 데이터베이스라는 사실은 이미 잘 알려져 있다. 하지만 대량의 데이터를 다루다 보면 쿼리의 효율성은 중요한 이슈가 된다. 그래서 MongoDB는 사용자들이 쿼리 성능을 향상시킬 수 있도록 explain() 메소드를 제공한다. 나의 경우 쿼리가 인덱스를 타는지 여부를 확인하기 위해 사용했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;explain()&amp;nbsp;메소드는&amp;nbsp;MongoDB&amp;nbsp;쿼리가&amp;nbsp;어떻게&amp;nbsp;동작하며&amp;nbsp;어떻게&amp;nbsp;최적화될&amp;nbsp;수&amp;nbsp;있는지에&amp;nbsp;대한&amp;nbsp;정보를&amp;nbsp;제공한다.&amp;nbsp;이&amp;nbsp;메소드의&amp;nbsp;사용법은&amp;nbsp;간단하다.&amp;nbsp;작성한&amp;nbsp;쿼리에&amp;nbsp;.explain()을&amp;nbsp;추가하면&amp;nbsp;된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1690957598701&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;db.getCollection(&quot;test&quot;).find({test: &quot;Test&quot;}).explain()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MongoDB는 .explain()에 대해 세 가지 모드를 제공한다. &quot;queryPlanner&quot;, &quot;executionStats&quot;, &quot;allPlansExecution&quot;이 그것이다. 이들 모드는 각각 쿼리의 최적화 계획, 실제 실행 통계, 그리고 MongoDB 쿼리 최적화기가 고려한 모든 계획에 대한 통계를 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.explain()&amp;nbsp;메소드를&amp;nbsp;실행하면,&amp;nbsp;반환되는&amp;nbsp;정보는&amp;nbsp;복잡한&amp;nbsp;JSON&amp;nbsp;객체&amp;nbsp;형태이다.&amp;nbsp;이&amp;nbsp;객체는&amp;nbsp;여러&amp;nbsp;중요한&amp;nbsp;정보를&amp;nbsp;포함하고&amp;nbsp;있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;queryPlanner: MongoDB 쿼리 플래너가 쿼리를 어떻게 해석했는지, 어떤 인덱스가 사용되었는지 등의 정보를 제공한다.&lt;/li&gt;
&lt;li&gt;executionStats: 쿼리 실행에 관한 상세 통계를 제공한다. 여기에는 쿼리 실행 시간, 검토된 문서의 수, 반환된 문서의 수 등의 정보가 포함되어 있다.&lt;/li&gt;
&lt;li&gt;serverInfo:&amp;nbsp;쿼리를&amp;nbsp;실행한&amp;nbsp;서버에&amp;nbsp;대한&amp;nbsp;정보를&amp;nbsp;제공한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 중에서 winningPlan과 executionStats 섹션은 특히 중요하다. winningPlan 섹션은 쿼리 최적화기가 선택한 최적의 쿼리 실행 계획을 보여주며, 이 정보를 통해 인덱스가 올바르게 사용되었는지, 스캔된 문서의 수가 적절한지 등을 판단할 수 있다. executionStats 섹션은 쿼리 실행에 관한 상세 통계를 제공하며, nReturned, executionTimeMillis, totalKeysExamined, totalDocsExamined 등의 필드를 통해 쿼리의 효율성을 평가할 수 있다.&lt;br /&gt;&lt;br /&gt;하지만&amp;nbsp;.explain()&amp;nbsp;메소드는&amp;nbsp;시스템에&amp;nbsp;부하를&amp;nbsp;줄&amp;nbsp;수&amp;nbsp;있으므로,&amp;nbsp;실제&amp;nbsp;서비스&amp;nbsp;환경에서는&amp;nbsp;주의해서&amp;nbsp;사용해야&amp;nbsp;한다.&amp;nbsp;대신,&amp;nbsp;개발&amp;nbsp;환경이나&amp;nbsp;별도의&amp;nbsp;테스트&amp;nbsp;환경에서&amp;nbsp;사용하는&amp;nbsp;것이&amp;nbsp;바람직하다.&amp;nbsp;이&amp;nbsp;포스트가&amp;nbsp;MongoDB&amp;nbsp;쿼리&amp;nbsp;최적화에&amp;nbsp;있어서&amp;nbsp;도움이&amp;nbsp;되길&amp;nbsp;바란다.&lt;/p&gt;</description>
      <category>DataBase/MongoDB</category>
      <category>ExecutionStats</category>
      <category>explain</category>
      <category>MongoDB</category>
      <category>NoSQL</category>
      <category>WinningPlan</category>
      <category>데이터베이스</category>
      <category>쿼리최적화</category>
      <category>퍼포먼스최적화</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/179</guid>
      <comments>https://systorage.tistory.com/entry/Mongodb-explain%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-mongodb-%EC%BF%BC%EB%A6%AC-%EC%B5%9C%EC%A0%81%ED%99%94#entry179comment</comments>
      <pubDate>Wed, 2 Aug 2023 15:31:24 +0900</pubDate>
    </item>
    <item>
      <title>Contact</title>
      <link>https://systorage.tistory.com/notice/178</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;email&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gangsuyun6@gmail.com&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;github&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/rkdden&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/rkdden&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/notice/178</guid>
      <pubDate>Mon, 26 Jun 2023 17:28:55 +0900</pubDate>
    </item>
    <item>
      <title>[Error] 갑자기 도메인 접속이 안될때 해결방법</title>
      <link>https://systorage.tistory.com/entry/Error-%EA%B0%91%EC%9E%90%EA%B8%B0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%A0%91%EC%86%8D%EC%9D%B4-%EC%95%88%EB%90%A0%EB%95%8C-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최근 팀에서 특이한 문제를 경험했다. 서비스 중인 도메인에 대해서 가끔 접속이 가능했다가 안되는 상황이 반복되었다. 해당 원인을 찾은 과정과 해결 방법에 대해 소개한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결하기 위해서 여러가지 방법으로 문제를 확인했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시에서 설명을 위해 접속이 안되는 도메인은 example.com 으로 가정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 서버의 IP는 0.0.0.0으로 가정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;네트워크 구조가 단순하게 설명하면&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Cloudflare -- Load&lt;span&gt;&amp;nbsp;&lt;/span&gt;balancer -- Server&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;구조로 되어 있었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;서버의 IP로 직접 접근&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법은 성공했다. IP 주소를 통해서 직접 접근이 가능한 것은 서버 자체에는 문제가 없다는 것을 의미했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;로드밸런서로 접근&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법역시 성공했다. 로드밸런서를 통해서 접근이 가능했던것은 마찬가지로 로드밸런서 자체에는 문제가 없다는 것을 의미했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;네임서버로 접근&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 문제가 발생했다. 네임서버를 통해서 접근할 수 없다는 것은 DNS에 문제가 있다는 것을 나타냈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 네임서버 자체는 정상적으로 작동하고 있었고, example.com에 대해서만 조회가 되었다 안되었다 했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;nslookup, dig, ping 을 사용한 네트워크 상태 확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 또한 마찬가지로 서버, 로드밸런서, 네임서버 자체에는 문제가 없었으나&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 &quot;도메인(example.com)&quot;에서만 문제가 발생했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 원인을 파악해도 원인을 찾을수가 없었다. 일시적으로 통신사쪽 문제라고 결론을 짓고 다음날까지 기다려보아도 문제가 해결되지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Whois 조회&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 검사결과를 바탕으로 원인을 줄여나간 결과, 결과적으로 도메인 자체에 문제가 있을수 있다는 생각이 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Whois에서 example.com을 조회후 정보를 확인한 결과 해당 도메인이 &quot;clientHold&quot; 상태인것을 확인했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;clientHold는 도메인이 일시적으로 사용 중지된 상태를 나타내는데, 이는 보통 도메인 소유자가 도메인을 삭제하거나  결제 실패등 다양한 이유로 발생할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결과&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과적으로는 팀중 한명이 실수로 도메인을 삭제해서 일어난 현상이였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 어떻게 도메인 접속이 되었다가 안 되었다가 하는 현상이 일어났을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 DNS의 작동 방식과 관련이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DNS는 인터넷의 전화번호부와 같다. 사용자가 웹사이트의 도메인 이름을 입력하면, DNS는 이 이름을 해당 웹사이트의 IP 주소로 변환한다. 그런데 이 변환 정보가 저장되는 네임서버에 변경사항이 생기면, 그 정보가 모든 네임서버에 전파되는 데는 시간이 걸린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인이 삭제되면, 해당 도메인에 대한 정보가 네임서버에서 제거된다. 하지만 이 정보가 모든 네임서버에 즉시 반영되지는 않는다. 따라서, 어떤 네임서버는 아직 도메인 정보를 가지고 있을 수 있고, 어떤 네임서버는 도메인 정보를 이미 제거했을 수 있다.&lt;br /&gt;&lt;br /&gt;이런 상황에서 사용자가 웹사이트에 접속하려고 하면, 사용자의 장치(핸드폰, 노트북 등)는 DNS 쿼리를 통해 도메인 이름을 IP 주소로 변환하려고 시도한다. 만약 DNS 쿼리가 도메인 정보를 아직 가지고 있는 네임서버로 전달되면, 웹사이트 접속이 성공적으로 이루어진다. 그러나 도메인 정보를 이미 제거한 네임서버로 전달되면, 웹사이트 접속이 실패하게 된다.&lt;br /&gt;&lt;br /&gt;이렇게 해서, 도메인 삭제 후 도메인 접속이 되었다 안 되었다하는 현상이 발생하게 된 것이다.&lt;br /&gt;&lt;br /&gt;이렇게 팀에서 도메인 문제를 찾아내고 해결할 수 있었다.&lt;/p&gt;</description>
      <category>Error</category>
      <category>dns</category>
      <category>whois</category>
      <category>네임서버</category>
      <category>도메인</category>
      <category>서버 관리</category>
      <category>웹사이트 접속 문제</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/177</guid>
      <comments>https://systorage.tistory.com/entry/Error-%EA%B0%91%EC%9E%90%EA%B8%B0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%A0%91%EC%86%8D%EC%9D%B4-%EC%95%88%EB%90%A0%EB%95%8C-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95#entry177comment</comments>
      <pubDate>Fri, 23 Jun 2023 13:27:14 +0900</pubDate>
    </item>
    <item>
      <title>[Github Actions] GitHub Actions을 이용한 Slack 알림 설정하기</title>
      <link>https://systorage.tistory.com/entry/Github-Actions-GitHub-Actions%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-Slack-%EC%95%8C%EB%A6%BC-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;GitHub Actions는 CI/CD를 위한 강력한 도구이다. 소프트웨어 개발 과정에서 다양한 작업들을 자동화할 수 있는데, 그 중 하나가 빌드나 테스트의 성공 및 실패를 Slack으로 알림 보내는 것이다. 이 글에서는 GitHub Actions과 Slack을 연동하는 방법에 대해 설명한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;슬랙 앱 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저,&amp;nbsp;Slack&amp;nbsp;알림을&amp;nbsp;받기&amp;nbsp;위해서는&amp;nbsp;Slack&amp;nbsp;앱이&amp;nbsp;필요하다.&lt;br /&gt;&lt;br /&gt;1. &lt;a href=&quot;https://api.slack.com/apps&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Slack API 사이트&lt;/a&gt;에 접속&lt;br /&gt;2. &quot;Create an App&quot; 버튼을 클릭한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-16 오후 3.18.43.png&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;497&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CRQQd/btskee6u9WN/XEOrPW8OPczTTA9aMk1hK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CRQQd/btskee6u9WN/XEOrPW8OPczTTA9aMk1hK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CRQQd/btskee6u9WN/XEOrPW8OPczTTA9aMk1hK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCRQQd%2Fbtskee6u9WN%2FXEOrPW8OPczTTA9aMk1hK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;540&quot; height=&quot;434&quot; data-filename=&quot;스크린샷 2023-06-16 오후 3.18.43.png&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;497&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;3. &quot;From scratch&quot; 옵션을 선택하고 앱 이름과 워크스페이스를 설정한 후, &quot;Create App&quot;을 클릭한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-16 오후 3.19.57.png&quot; data-origin-width=&quot;519&quot; data-origin-height=&quot;369&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxWPzt/btsj8Ywgvvv/LFTOiGtOM0FSAIfC6ki981/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxWPzt/btsj8Ywgvvv/LFTOiGtOM0FSAIfC6ki981/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxWPzt/btsj8Ywgvvv/LFTOiGtOM0FSAIfC6ki981/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxWPzt%2Fbtsj8Ywgvvv%2FLFTOiGtOM0FSAIfC6ki981%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;540&quot; height=&quot;384&quot; data-filename=&quot;스크린샷 2023-06-16 오후 3.19.57.png&quot; data-origin-width=&quot;519&quot; data-origin-height=&quot;369&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;4. 왼쪽 메뉴에서 &quot;Incoming Webhooks&quot;을 클릭하고, 페이지 상단의 &quot;Activate Incoming Webhooks&quot; 스위치를 켠다.&lt;br /&gt;5. &quot;Add New Webhook to Workspace&quot;를 클릭하여 새 웹훅을 추가한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-16 오후 3.21.24.png&quot; data-origin-width=&quot;819&quot; data-origin-height=&quot;1055&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bodhTe/btskeunlvJb/YpNb8EfCFuAcK6Qv7309q0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bodhTe/btskeunlvJb/YpNb8EfCFuAcK6Qv7309q0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bodhTe/btskeunlvJb/YpNb8EfCFuAcK6Qv7309q0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbodhTe%2FbtskeunlvJb%2FYpNb8EfCFuAcK6Qv7309q0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;540&quot; height=&quot;696&quot; data-filename=&quot;스크린샷 2023-06-16 오후 3.21.24.png&quot; data-origin-width=&quot;819&quot; data-origin-height=&quot;1055&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;6. 알림을 받고 싶은 채널을 선택하고, &quot;허용&quot; 버튼을 누른다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-16 오후 3.23.38.png&quot; data-origin-width=&quot;645&quot; data-origin-height=&quot;487&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tshpW/btskaFpI38s/iJVCXK6PdQwVLdrlpK4H70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tshpW/btskaFpI38s/iJVCXK6PdQwVLdrlpK4H70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tshpW/btskaFpI38s/iJVCXK6PdQwVLdrlpK4H70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtshpW%2FbtskaFpI38s%2FiJVCXK6PdQwVLdrlpK4H70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;645&quot; height=&quot;487&quot; data-filename=&quot;스크린샷 2023-06-16 오후 3.23.38.png&quot; data-origin-width=&quot;645&quot; data-origin-height=&quot;487&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;7. 생성된 웹훅 URL을 복사 한다. 이 URL은 GitHub Actions 설정에서 사용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;GitHub Actions 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 GitHub Actions를 설정하여 빌드나 테스트 결과를 Slack으로 보낼 수 있도록 한다.&lt;br /&gt;&lt;br /&gt;1. GitHub 저장소로 이동하여 &quot;.github/workflows&quot; 디렉토리를 생성한다. 여기에 워크플로우 파일을 생성한다. (예: &quot;main.yml&quot;) (이미 있다면 생략해도 괜찮다.)&lt;br /&gt;2. 워크플로우 파일에 steps 마지막에 다음과 같이 작성하여 Slack 성공또는 실패 알림을 보낼 수 있도록 설정한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;성공한 경우에만 보내는 알림&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1686897275525&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;- name: Notify Slack on Success
  if: success() # 이 step은 job이 성공한 경우에만 실행된다.
  id: slack-success
  uses: slackapi/slack-github-action@v1.24.0
  with:
    payload: |
      {
        &quot;channel&quot;: &quot;채널 ID&quot;,
        &quot;attachments&quot;: [
          {
            &quot;color&quot;: &quot;#36a64f&quot;, # 성공시 연두색
            &quot;title&quot;: &quot;${{ github.repository }}&quot;, # 제목은 깃헙 레포지토리
            &quot;title_link&quot;: &quot;https://github.com/${{github.repository}}&quot;, # 제목 클릭시 레포지토리로 이동
            &quot;text&quot;: &quot;GitHub Action 성공&quot;,
            &quot;fields&quot;: [
              {
                &quot;title&quot;: &quot;Repository&quot;,
                &quot;value&quot;: &quot;${{ github.repository }}&quot;,
                &quot;short&quot;: true
              },
              {
                &quot;title&quot;: &quot;Tag&quot;,
                &quot;value&quot;: &quot;${{ github.ref_name }}&quot;,
                &quot;short&quot;: true
              }
            ]      
          }
        ]
      }
  env:
    SLACK_WEBHOOK_URL: &quot;위에서 설정한 WEBHOOK URL&quot;
    SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-16 오후 3.37.48.png&quot; data-origin-width=&quot;393&quot; data-origin-height=&quot;100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvRtd9/btskexdngTD/UOYwQIcKrv9OUNB3GHZIEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvRtd9/btskexdngTD/UOYwQIcKrv9OUNB3GHZIEK/img.png&quot; data-alt=&quot;성공시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvRtd9/btskexdngTD/UOYwQIcKrv9OUNB3GHZIEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvRtd9%2FbtskexdngTD%2FUOYwQIcKrv9OUNB3GHZIEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;420&quot; height=&quot;107&quot; data-filename=&quot;스크린샷 2023-06-16 오후 3.37.48.png&quot; data-origin-width=&quot;393&quot; data-origin-height=&quot;100&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;성공시&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실패한 경우에만 보내는 알림&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1686897368792&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;- name: Notify Slack on Failure
  if: failure() # 이 step은 job이 실패한 경우에만 실행됩니다.
  id: slack-failure
  uses: slackapi/slack-github-action@v1.24.0
  with:
    payload: |
      {
        &quot;channel&quot;: &quot;채널 ID&quot;,
        &quot;attachments&quot;: [
          {
            &quot;color&quot;: &quot;#ff0000&quot;, # 실패시 빨간색
            &quot;title&quot;: &quot;${{ github.repository }}&quot;, # 제목은 깃헙 레포지토리
            &quot;title_link&quot;: &quot;https://github.com/${{github.repository}}&quot;, # 제목 클릭시 레포지토리로 이동
            &quot;text&quot;: &quot;GitHub Action 실패 :x:&quot;,
            &quot;fields&quot;: [
              {
                &quot;title&quot;: &quot;Repository&quot;,
                &quot;value&quot;: &quot;${{ github.repository }}&quot;,
                &quot;short&quot;: true
              },
              {
                &quot;title&quot;: &quot;Tag&quot;,
                &quot;value&quot;: &quot;${{ github.ref_name }}&quot;,
                &quot;short&quot;: true
              }
            ]      
          }
        ]
      }
  env:
    SLACK_WEBHOOK_URL: &quot;위에서 설정한 WEBHOOK URL&quot;
    SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-16 오후 3.38.25.png&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;99&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQFzKH/btskfc0QujB/7urUNul8ChCRs0tKakaLC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQFzKH/btskfc0QujB/7urUNul8ChCRs0tKakaLC0/img.png&quot; data-alt=&quot;실패 시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQFzKH/btskfc0QujB/7urUNul8ChCRs0tKakaLC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQFzKH%2Fbtskfc0QujB%2F7urUNul8ChCRs0tKakaLC0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;420&quot; height=&quot;107&quot; data-filename=&quot;스크린샷 2023-06-16 오후 3.38.25.png&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;99&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실패 시&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성공 실패 여부 관계없이 알림을 보내고 싶다면 두개 다 추가하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결과&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글을 통해 GitHub Actions과 Slack을 연동하는 방법에 대해 알아보았다. 이제 빌드나 테스트의 성공, 실패 여부에 따라 자동으로 Slack 알림을 받을 수 있다. CI/CD 프로세스를 더욱 효율적으로 관리할 수 있게 되었습니다. 이 외에도 GitHub Actions은 다양한 자동화 작업을 수행할 수 있으니, 더 많은 활용 방법을 찾아보시기 바란다.&lt;/p&gt;</description>
      <category>기타</category>
      <category>automation</category>
      <category>CI/CD</category>
      <category>devops</category>
      <category>github actions</category>
      <category>notifications</category>
      <category>Programming</category>
      <category>slack</category>
      <category>software development</category>
      <category>webhooks</category>
      <category>workflow</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/176</guid>
      <comments>https://systorage.tistory.com/entry/Github-Actions-GitHub-Actions%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-Slack-%EC%95%8C%EB%A6%BC-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0#entry176comment</comments>
      <pubDate>Fri, 16 Jun 2023 15:40:45 +0900</pubDate>
    </item>
    <item>
      <title>[MongoDB] MongoDB 검색 성능 극대화 방법: 인덱스와 컴파운드 인덱스의 활용</title>
      <link>https://systorage.tistory.com/entry/MongoDB-MongoDB-%EA%B2%80%EC%83%89-%EC%84%B1%EB%8A%A5-%EA%B7%B9%EB%8C%80%ED%99%94-%EB%B0%A9%EB%B2%95-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EC%99%80-%EC%BB%B4%ED%8C%8C%EC%9A%B4%EB%93%9C-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EC%9D%98-%ED%99%9C%EC%9A%A9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 MongoDB에서 데이터 검색 성능을 최대한 높이기 위한 방법을 소개한다. 이 방법의 핵심은 '인덱스'와 '컴파운드 인덱스'라는 두 개념을 이해하고 활용하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 인덱스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덱스는 MongoDB에서 데이터를 효율적으로 찾기 위한 데이터 구조다. 인덱스가 없을 경우, MongoDB는 쿼리에 맞는 문서를 찾기 위해 컬렉션의 모든 문서를 검색해야 한다. 하지만 인덱스가 있을 경우, MongoDB는 인덱스를 활용하여 필요한 문서를 더 빠르게 찾을 수 있다. 예를 들어, MongoDB에서 'username'이라는 필드에 인덱스를 추가하는 방법은 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1686619076014&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;db.users.createIndex({ username: 1 });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 컴파운드 인덱스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴파운드 인덱스는 두 개 이상의 필드를 결합한 인덱스를 말한다. 이 인덱스는 필드의 순서에 따라 정렬되며, 이 순서는 쿼리 성능에 큰 영향을 미친다. 예를 들어, MongoDB에서 'username' 필드와 'email' 필드에 컴파운드 인덱스를 추가하는 방법은 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1686619129132&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;db.users.createIndex({ username: 1, email: 1 });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 인덱스와 컴파운드 인덱스의 차이점 및 사용 시기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덱스와&amp;nbsp;컴파운드&amp;nbsp;인덱스의&amp;nbsp;차이점을&amp;nbsp;이해했으니,&amp;nbsp;각각&amp;nbsp;언제&amp;nbsp;사용해야&amp;nbsp;하는지를&amp;nbsp;알아볼&amp;nbsp;필요가&amp;nbsp;있다.&amp;nbsp;인덱스는&amp;nbsp;단일&amp;nbsp;필드에&amp;nbsp;대한&amp;nbsp;빠른&amp;nbsp;조회를&amp;nbsp;가능하게&amp;nbsp;해주며,&amp;nbsp;컴파운드&amp;nbsp;인덱스는&amp;nbsp;여러&amp;nbsp;필드를&amp;nbsp;결합하여&amp;nbsp;빠른&amp;nbsp;조회를&amp;nbsp;가능하게&amp;nbsp;해준다.&amp;nbsp;따라서,&amp;nbsp;단일&amp;nbsp;필드를&amp;nbsp;자주&amp;nbsp;쿼리하는&amp;nbsp;경우에는&amp;nbsp;인덱스를,&amp;nbsp;여러&amp;nbsp;필드를&amp;nbsp;동시에&amp;nbsp;쿼리하는&amp;nbsp;경우에는&amp;nbsp;컴파운드&amp;nbsp;인덱스를&amp;nbsp;사용하는&amp;nbsp;것이&amp;nbsp;좋다.&amp;nbsp;그러나&amp;nbsp;인덱스&amp;nbsp;생성&amp;nbsp;및&amp;nbsp;유지에도&amp;nbsp;비용이&amp;nbsp;발생하므로,&amp;nbsp;필요한&amp;nbsp;만큼만&amp;nbsp;인덱스를&amp;nbsp;생성하고&amp;nbsp;유지하는&amp;nbsp;것이&amp;nbsp;중요하다.&amp;nbsp;인덱스가&amp;nbsp;검색&amp;nbsp;성능을&amp;nbsp;향상시키지만,&amp;nbsp;과도하게&amp;nbsp;생성하면&amp;nbsp;오히려&amp;nbsp;성능&amp;nbsp;저하를&amp;nbsp;일으킬&amp;nbsp;수&amp;nbsp;있다.&lt;br /&gt;&lt;br /&gt;이를&amp;nbsp;통해&amp;nbsp;MongoDB의&amp;nbsp;검색&amp;nbsp;성능을&amp;nbsp;극대화하는&amp;nbsp;방법을&amp;nbsp;이해하였다.&amp;nbsp;적절한&amp;nbsp;인덱스와&amp;nbsp;컴파운드&amp;nbsp;인덱스의&amp;nbsp;활용을&amp;nbsp;통해&amp;nbsp;MongoDB에서&amp;nbsp;데이터를&amp;nbsp;더&amp;nbsp;효율적으로&amp;nbsp;검색할&amp;nbsp;수&amp;nbsp;있다는&amp;nbsp;것을&amp;nbsp;기억하자.&lt;/p&gt;</description>
      <category>DataBase/MongoDB</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/175</guid>
      <comments>https://systorage.tistory.com/entry/MongoDB-MongoDB-%EA%B2%80%EC%83%89-%EC%84%B1%EB%8A%A5-%EA%B7%B9%EB%8C%80%ED%99%94-%EB%B0%A9%EB%B2%95-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EC%99%80-%EC%BB%B4%ED%8C%8C%EC%9A%B4%EB%93%9C-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EC%9D%98-%ED%99%9C%EC%9A%A9#entry175comment</comments>
      <pubDate>Tue, 13 Jun 2023 10:20:44 +0900</pubDate>
    </item>
    <item>
      <title>[Elasticsearch] Elasticsearch에서 발생한 데이터 타입 변경 문제와 해결</title>
      <link>https://systorage.tistory.com/entry/Elasticsearch-Elasticsearch%EC%97%90%EC%84%9C-%EB%B0%9C%EC%83%9D%ED%95%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85-%EB%B3%80%EA%B2%BD-%EB%AC%B8%EC%A0%9C%EC%99%80-%ED%95%B4%EA%B2%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Elasticsearch 환경에서 로그 데이터의 특정 프로퍼티를 string 타입에서 object 타입으로 변경하는 과정에서 문제가 발생하였다. 데이터 타입을 변경한 후 해당 로그가 더 이상 기록되지 않았다. 해당 문제의 원인 파악과 해결 방법을 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Elasticsearch는 스키마가 유연한 문서 기반 데이터베이스로서, 데이터의 구조를 미리 정의하지 않고도 데이터를 저장할 수 있다. 하지만 데이터를 한 번 특정 형식으로 인덱싱하면, 이후 해당 인덱스의 맵핑을 변경할 수 없다.&lt;br /&gt;&lt;br /&gt;나의 경우, 문자열(string)로 인덱싱된 특정 필드를 나중에 객체(object)로 변경하려고 하면 문제가 발생했다. Elasticsearch는 새로운 데이터를 기존 인덱스에 맞게 강제로 변환하려고 시도하며, 이 과정에서 에러가 발생하게 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;해결법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결하기 위해 주로 다음 두 가지 방법이 사용된다.&lt;br /&gt;&lt;br /&gt;1. 새로운 인덱스를 만들고, 새로운 맵핑을 정의한 후 데이터를 재인덱싱한다. 이를 통해 데이터 구조의 변경을 수용할 수 있다.&lt;br /&gt;&lt;br /&gt;2. 필드 이름을 변경하여 새로운 필드로 취급하게 만든다. 이 경우, 기존 데이터와 새로운 데이터가 동일한 인덱스 내에 다른 필드로 존재하게 된다.&lt;br /&gt;&lt;br /&gt;이&amp;nbsp;문제를&amp;nbsp;방지하기&amp;nbsp;위한&amp;nbsp;핵심&amp;nbsp;전략은&amp;nbsp;데이터의&amp;nbsp;구조를&amp;nbsp;미리&amp;nbsp;잘&amp;nbsp;계획하고,&amp;nbsp;필요한&amp;nbsp;경우&amp;nbsp;적절한&amp;nbsp;맵핑을&amp;nbsp;사용하는&amp;nbsp;것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 데이터가 저장된 경우 input type을 마음대로 바꾸지말자..&lt;/p&gt;</description>
      <category>Error</category>
      <category>elasticsearch</category>
      <category>error</category>
      <category>데이터타입변경</category>
      <category>맵핑</category>
      <category>문제해결</category>
      <category>인덱싱</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/174</guid>
      <comments>https://systorage.tistory.com/entry/Elasticsearch-Elasticsearch%EC%97%90%EC%84%9C-%EB%B0%9C%EC%83%9D%ED%95%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85-%EB%B3%80%EA%B2%BD-%EB%AC%B8%EC%A0%9C%EC%99%80-%ED%95%B4%EA%B2%B0#entry174comment</comments>
      <pubDate>Tue, 23 May 2023 18:26:00 +0900</pubDate>
    </item>
    <item>
      <title>[Node.js] assert.doesNotThrow와 assert.doesNotReject의 차이점</title>
      <link>https://systorage.tistory.com/entry/Nodejs-assertdoesNotThrow%EC%99%80-assertdoesNotReject%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Node.js에서는&amp;nbsp;코드의&amp;nbsp;동작을&amp;nbsp;검증하기&amp;nbsp;위해&amp;nbsp;다양한&amp;nbsp;단언(assertion)&amp;nbsp;함수들을&amp;nbsp;제공하고&amp;nbsp;있다.&amp;nbsp;이&amp;nbsp;중&amp;nbsp;assert.doesNotThrow()와&amp;nbsp;assert.doesNotReject()&amp;nbsp;함수는&amp;nbsp;코드&amp;nbsp;블록이&amp;nbsp;에러를&amp;nbsp;발생시키지&amp;nbsp;않는다는&amp;nbsp;것을&amp;nbsp;확인하는데&amp;nbsp;사용된다.&amp;nbsp;그러나&amp;nbsp;이&amp;nbsp;두&amp;nbsp;함수는&amp;nbsp;각각&amp;nbsp;다른&amp;nbsp;유형의&amp;nbsp;코드에&amp;nbsp;적용되므로&amp;nbsp;그&amp;nbsp;차이점을&amp;nbsp;이해하는&amp;nbsp;것이&amp;nbsp;중요하다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;b&gt;assert.doesNotThrow(block[, error][, message])&lt;/b&gt;: 이 함수는 동기 코드 블록이 주어진 에러를 발생시키지 않는지 확인한다. 만약 코드 블록이 에러를 발생시키면, 그 에러는 무시되고 대신 AssertionError가 발생한다. 선택적으로 error 인자를 제공하여 특정 타입의 에러만 검사할 수 있다. 아래는 예시이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1684049566367&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const assert = require('assert');

function doesNotError() {
  if (Math.random() &amp;lt; 0.5) {
    throw new Error('Random error!');
  }
}

try {
  assert.doesNotThrow(
    doesNotError,
    Error,
    'The function doesNotError has thrown an exception'
  );
  console.log('The function doesNotError has not thrown an exception');
} catch (err) {
  console.error(err);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;b&gt;assert.doesNotReject(block[, error][, message])&lt;/b&gt;: 이 함수는 비동기 코드 블록이 주어진 에러를 발생시키지 않는지 확인한다. block은 Promise를 반환해야 한다. 만약 Promise가 거부되면, 그 거부 값은 무시되고 대신 AssertionError가 발생한다. 아래는 예시이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1684049654695&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const assert = require('assert');

async function doesNotReject() {
  if (Math.random() &amp;lt; 0.5) {
    throw new Error('Random error!');
  }
}

assert.doesNotReject(
  doesNotReject(),
  Error,
  'The function doesNotReject has thrown an exception'
)
.then(() =&amp;gt; console.log('The function doesNotReject has not thrown an exception'))
.catch((err) =&amp;gt; console.error(err));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국,&amp;nbsp;assert.doesNotThrow()는&amp;nbsp;동기&amp;nbsp;코드를,&amp;nbsp;assert.doesNotReject()는&amp;nbsp;Promise를&amp;nbsp;반환하는&amp;nbsp;비동기&amp;nbsp;코드를&amp;nbsp;검사하는데&amp;nbsp;사용된다.&amp;nbsp;이들&amp;nbsp;함수를&amp;nbsp;이해하고&amp;nbsp;적절히&amp;nbsp;사용함으로써,&amp;nbsp;코드가&amp;nbsp;예상대로&amp;nbsp;동작하는지&amp;nbsp;확신할&amp;nbsp;수&amp;nbsp;있고,&amp;nbsp;그렇지&amp;nbsp;않다면&amp;nbsp;어디서&amp;nbsp;문제가&amp;nbsp;발생하는지를&amp;nbsp;식별할&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming/Node.js</category>
      <category>assertion</category>
      <category>async</category>
      <category>JavaScript</category>
      <category>nodejs</category>
      <category>TypeScript</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/173</guid>
      <comments>https://systorage.tistory.com/entry/Nodejs-assertdoesNotThrow%EC%99%80-assertdoesNotReject%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90#entry173comment</comments>
      <pubDate>Sun, 14 May 2023 16:36:35 +0900</pubDate>
    </item>
    <item>
      <title>[Typescript] TypeScript의 모듈 파일과 전역 모듈의 차이점 및 예제</title>
      <link>https://systorage.tistory.com/entry/Typescript-TypeScript%EC%9D%98-%EB%AA%A8%EB%93%88-%ED%8C%8C%EC%9D%BC%EA%B3%BC-%EC%A0%84%EC%97%AD-%EB%AA%A8%EB%93%88%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EB%B0%8F-%EC%98%88%EC%A0%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript는 자바스크립트에 정적 타입을 도입하여 코드의 안정성과 가독성을 높이게 된다. TypeScript를 사용하면 코드 구조화가 중요한데, 이에 관련하여 모듈 파일과 전역 모듈에 대해 설명하고자 한다. 예제 코드를 통해 이를 이해해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 전역 모듈과 모듈 파일의 정의&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript에서 파일은 기본적으로 다음 두 가지로 구분된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전역 모듈: 파일에 아무런 import나 export 문이 없는 경우, 해당 파일은 전역 모듈로 간주된다.&lt;/li&gt;
&lt;li&gt;모듈 파일: 파일에 import나 export 문이 하나라도 있는 경우, 해당 파일은 모듈 파일로 간주된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 전역 모듈의 특징 및 예제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전역 모듈에서 정의된 요소들은 전역 범위에서 사용할 수 있다. 이 경우, 다른 파일에서 정의된 요소들을 명시적으로 가져올 필요가 없다. &amp;nbsp;그러나&amp;nbsp;이&amp;nbsp;방식은&amp;nbsp;TypeScript&amp;nbsp;컴파일&amp;nbsp;과정에서는&amp;nbsp;오류가&amp;nbsp;발생하지&amp;nbsp;않지만,&amp;nbsp;실행&amp;nbsp;시간에&amp;nbsp;오류가&amp;nbsp;발생할&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 다음과 같은 전역 모듈 파일이 있다고 가정해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1683470570575&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// globalModule.ts
class GlobalClass {
  public sayHello() {
    console.log(&quot;Hello from GlobalClass&quot;);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 파일에서 GlobalClass를 사용하려면, 아무런 import 문 없이 사용할 수 있다. 그러나 런타임에서는 오류가 발생된다.&lt;/p&gt;
&lt;pre id=&quot;code_1683470687301&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// main.ts 
const instance = new GlobalClass();
instance.sayHello(); // 출력: Hello from GlobalClass&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 전역 모듈을 사용하면 코드 관리가 어려워지고, 이름 충돌이 발생할 가능성이 높아진다. 따라서 권장되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 모듈 파일의 특징 및 예제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모듈 파일에서 정의된 요소들은 기본적으로 해당 파일 범위 내에서만 사용할 수 있다. 다른 파일에서 이 요소들을 사용하려면, 명시적으로 export해야 하고, 다른 파일에서 이 요소들을 사용하려면 import를 통해 가져와야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 다음과 같은 모듈 파일이 있다고 가정해보자.&lt;/p&gt;
&lt;pre id=&quot;code_1683470861704&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// moduleFile.ts
export class ModuleClass {
	public sayHello() {
		console.log(&quot;Hello from ModuleClass&quot;); 
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;다른 파일에서 ModuleClass를 사용하려면, import를 통해 명시적으로 가져와야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683470913238&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// main.ts
import { ModuleClass } from &quot;./moduleFile&quot;;
const instance = new ModuleClass();
instance.sayHello(); // 출력: Hello from ModuleClass&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4.&amp;nbsp;아무&amp;nbsp;import&amp;nbsp;문이&amp;nbsp;없을&amp;nbsp;때&amp;nbsp;동작하지&amp;nbsp;않는&amp;nbsp;이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무 import 문이 없는 경우, 해당 파일은 전역 모듈로 간주되어 해당 파일에서 정의된 요소들이 전역 범위에서 사용 가능하다.&lt;br /&gt;&lt;br /&gt;반면에,&amp;nbsp;파일에&amp;nbsp;import&amp;nbsp;문이&amp;nbsp;있는&amp;nbsp;경우&amp;nbsp;해당&amp;nbsp;파일은&amp;nbsp;모듈&amp;nbsp;파일로&amp;nbsp;간주되어&amp;nbsp;해당&amp;nbsp;파일에서&amp;nbsp;정의된&amp;nbsp;요소들이&amp;nbsp;다른&amp;nbsp;파일에서&amp;nbsp;사용되지&amp;nbsp;않게&amp;nbsp;된다.&amp;nbsp;이&amp;nbsp;경우,&amp;nbsp;다른&amp;nbsp;파일에서&amp;nbsp;사용하려면&amp;nbsp;해당&amp;nbsp;요소를&amp;nbsp;export하고&amp;nbsp;사용하려는&amp;nbsp;파일에서&amp;nbsp;import하여야&amp;nbsp;한다.&lt;br /&gt;&lt;br /&gt;이러한&amp;nbsp;이유로,&amp;nbsp;아무&amp;nbsp;import&amp;nbsp;문이&amp;nbsp;없는&amp;nbsp;파일에서는&amp;nbsp;동작하지만&amp;nbsp;import&amp;nbsp;문이&amp;nbsp;있는&amp;nbsp;경우&amp;nbsp;동작하지&amp;nbsp;않는&amp;nbsp;상황이&amp;nbsp;발생할&amp;nbsp;수&amp;nbsp;있다.&lt;br /&gt;&lt;br /&gt;예를 들어, 다음과 같은 전역 모듈과 모듈 파일이 있다고 가정해보자.&lt;/p&gt;
&lt;pre id=&quot;code_1683470992624&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// globalModule.ts
class GlobalClass {
  public sayHello() {
    console.log(&quot;Hello from GlobalClass&quot;);
  }
}

// moduleFile.ts
export class ModuleClass {
  public sayHello() {
    console.log(&quot;Hello from ModuleClass&quot;);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;main.ts&amp;nbsp;파일에서&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;import&amp;nbsp;문이&amp;nbsp;없으면,&amp;nbsp;GlobalClass는&amp;nbsp;사용&amp;nbsp;가능하지만&amp;nbsp;ModuleClass는&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;없다.&lt;/p&gt;
&lt;pre id=&quot;code_1683471035577&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// main.ts
const globalInstance = new GlobalClass();
globalInstance.sayHello(); // 런타임 오류: GlobalClass is not defined

const moduleInstance = new ModuleClass(); // 오류: ModuleClass를 찾을 수 없음
moduleInstance.sayHello();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;main.ts&amp;nbsp;파일에서&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;ModuleClass를&amp;nbsp;import하면,&amp;nbsp;이제&amp;nbsp;ModuleClass도&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;pre id=&quot;code_1683471056697&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// main.ts
import { ModuleClass } from &quot;./moduleFile&quot;;

const globalInstance = new GlobalClass();
globalInstance.sayHello(); // 출력: Hello from GlobalClass

const moduleInstance = new ModuleClass();
moduleInstance.sayHello(); // 출력: Hello from ModuleClass&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;주의사항&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript는 자바스크립트와 호환성을 유지하기 때문에, 자바스크립트의 모듈 시스템이 동작하는 방식에 따라 결과가 다를 수 있다. 실제 프로젝트에서 코드를 작성할 때는 모듈 시스템을 고려하고, 해당 프로젝트의 설정과 환경에 맞게 코드를 작성해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 무슨 소리냐면 typescript 컴파일러는 오류가 아니라고 인식하는데 실제로 컴파일되서 나온 파일을 실행하면 에러가 난다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5.&amp;nbsp;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript에서는 전역 모듈보다 모듈 파일을 사용하여 코드를 구조화하는 것이 좋다. 모듈 파일은 코드의 구조화와 이름 충돌 방지, 재사용 가능한 코드 작성에 도움이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;전역 모듈을 사용할 때 발생할 수 있는 문제를 피하려면, 각 요소를 명시적으로 export하고 import하여 사용하는 모듈 파일을 활용하는 것이 좋다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming/Typescript</category>
      <category>Export</category>
      <category>Import</category>
      <category>TypeScript</category>
      <category>모듈</category>
      <category>모듈 파일</category>
      <category>이름 충돌</category>
      <category>전역 모듈</category>
      <category>코드 구조화</category>
      <category>코드 재사용</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/172</guid>
      <comments>https://systorage.tistory.com/entry/Typescript-TypeScript%EC%9D%98-%EB%AA%A8%EB%93%88-%ED%8C%8C%EC%9D%BC%EA%B3%BC-%EC%A0%84%EC%97%AD-%EB%AA%A8%EB%93%88%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EB%B0%8F-%EC%98%88%EC%A0%9C#entry172comment</comments>
      <pubDate>Sun, 7 May 2023 23:55:26 +0900</pubDate>
    </item>
    <item>
      <title>[Node.js] 자주 발생하는 TypeError 해결하기: 'Cannot read property of undefined'</title>
      <link>https://systorage.tistory.com/entry/Nodejs-%EC%9E%90%EC%A3%BC-%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94-TypeError-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0-Cannot-read-property-of-undefined</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Node.js를 이용한 개발이 점점 인기를 얻고 있다. 그러나 개발 과정에서 발생할 수 있는 다양한 오류들로 인해, 개발자들이 진행에 어려움을 겪을 때가 많다. 이번 글에서는 Node.js 개발 중 자주 마주치는 오류 중 하나인 &quot;TypeError: Cannot read property 'x' of undefined&quot;에 대해 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;TypeError: Cannot read property 'x' of undefined&quot; 오류는 객체가 정의되지 않았을 때 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체의 속성이나 메서드에 접근하려고 시도하면 이 오류가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 오류의 일반적인 원인들은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 변수 또는 객체 초기화 누락 가장 일반적인 원인은 변수 또는 객체를 선언했지만 초기화하지 않은 경우&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우 해당 변수는 기본적으로 undefined 값을 가지게 되며, 이 변수의 속성에 접근하려고 하면 오류가 발생한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683007785451&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let user;
console.log(user.name); // TypeError: Cannot read property 'name' of undefined&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결법은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수 또는 객체를 초기화하거나, 속성 접근 전에 해당 변수 또는 객체가 정의되었는지 확인한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683007836556&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let user = {};
console.log(user.name); // undefined (오류 발생하지 않음)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;revenue_unit_wrap&quot;&gt;
  &lt;div class=&quot;revenue_unit_item adsense responsive&quot;&gt;
    &lt;div class=&quot;revenue_unit_info&quot;&gt;반응형&lt;/div&gt;
    &lt;script src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
    &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-host=&quot;ca-host-pub-9691043933427338&quot; data-ad-client=&quot;ca-pub-3354283732433468&quot; data-ad-format=&quot;auto&quot;&gt;&lt;/ins&gt;
    &lt;script&gt;(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;2. 비동기 작업에서의 동기화 문제&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.js에서 비동기 작업을 처리하는 동안 데이터를 가져오거나 처리하는 과정에서 오류가 발생할 수 있다.&amp;nbsp; 비동기 작업이 완료되기 전에 속성에 접근하려고 하면 오류가 발생한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683007970350&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let user;
fs.readFile('user.json', 'utf8', (err, data) =&amp;gt; {
	user = JSON.parse(data); 
}); 

console.log(user.name); // TypeError: Cannot read property 'name' of undefined&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결법은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 작업이 완료되었음을 확인하거나, 콜백 함수, Promise, async/await 등의 비동기 작업 처리 방법을 사용하여 동기화 문제를 해결한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683008015885&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;fs.readFile('user.json', 'utf8', (err, data) =&amp;gt; {
	const user = JSON.parse(data); console.log(user.name); // 오류 발생하지 않음 
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결론&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.js 개발 중 &quot;TypeError: Cannot read property 'x' of undefined&quot; 오류는 변수 초기화 누락 또는 비동기 작업 동기화 문제로 인해 발생할 수 있다. 오류를 해결하기 위해서는 변수 초기&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;화를 확인하고, 비동기 작업을 올바르게 처리해야 한다. 이렇게 하면 이러한 오류를 효과적으로 방지하고 Node.js 개발 경험을 개선할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming/Node.js</category>
      <category>error</category>
      <category>JavaScript</category>
      <category>node.js</category>
      <category>TypeError</category>
      <author>얼은펭귄</author>
      <guid isPermaLink="true">https://systorage.tistory.com/171</guid>
      <comments>https://systorage.tistory.com/entry/Nodejs-%EC%9E%90%EC%A3%BC-%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94-TypeError-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0-Cannot-read-property-of-undefined#entry171comment</comments>
      <pubDate>Tue, 2 May 2023 15:15:27 +0900</pubDate>
    </item>
  </channel>
</rss>