<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Somaz의 IT 공부 일지</title>
    <link>https://somaz.tistory.com/</link>
    <description>DevOps 엔지니어로서 CI/CD 파이프라인, 클라우드 인프라, 자동화에 대한 깊은 이해를 가지고 있습니다.
Kubernetes, Docker, Terraform, AWS, GitHub Actions, GitLab CI/CD 등을 활용하여
개발 워크플로우를 최적화하고 시스템 안정성을 향상시키는 데 집중하고 있습니다.</description>
    <language>ko</language>
    <pubDate>Tue, 19 May 2026 10:10:51 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Somaz</managingEditor>
    <image>
      <title>Somaz의 IT 공부 일지</title>
      <url>https://tistory1.daumcdn.net/tistory/5151683/attach/9d4d53f0d6ba4bcd932d69e22fa279b0</url>
      <link>https://somaz.tistory.com</link>
    </image>
    <item>
      <title>ingress-nginx &amp;rarr; nginx-gateway-fabric 마이그레이션 실전 기록 (온프레미스 K8s, 11개 인스턴스)</title>
      <link>https://somaz.tistory.com/510</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ingress-nginx가 유지보수 모드로 전환되고 Kubernetes Gateway API가 v1.2로 GA되면서, 운영 중인 온프레미스 클러스터의 ingress-nginx 11개 인스턴스를 nginx-gateway-fabric(NGF) 2.0으로 이관했다.&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;&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;span style=&quot;color: #000000;&quot;&gt;전환 대상과 규모는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;항목	내용
대상 클러스터	온프레미스 Kubespray (K8s v1.34)
기존 Ingress 컨트롤러	ingress-nginx 11개 인스턴스 (기본 nginx 1개 + nginx-public-a~j 10개)
LoadBalancer	MetalLB L2 (내부 IP 14개 고정 할당)
마이그레이션 대상 앱	infra 직배포 11개 + ArgoCD ApplicationSet 9개 + 별도 레포 2개
전환 후 구조	단일 NGF 컨트롤 플레인 + 11 Gateway CR (per-Gateway Deployment)
다운타임	클래스당 약 30초~1분 (IP swap 구간만)&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 목표 3가지는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;- 리소스/운영 부담 감축: ingress-nginx 11개 helm release &amp;rarr; NGF 1개 설치 + 11개 Gateway CR로 단순화한다
- DNS/방화벽 무변경: MetalLB IP를 그대로 유지해 외부 라우팅 설정 재작업을 제거한다
- 롤백 용이성: 병렬 배포 후 점진 cutover 방식으로 다운타임을 최소화한다&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 글은 단순 튜토리얼이 아니라 &lt;b&gt;실제 마이그레이션 중 내렸던 아키텍처 결정, 만난 문제, 그리고 해결 과정&lt;/b&gt;을 실측 기록과 함께 정리한 실전 문서다. 같은 전환을 앞둔 분들께 레퍼런스가 되길 바란다.&lt;/span&gt;&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-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qG0Rd/dJMcadobpem/28Wfs6ssROyR31oyjdG8Ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qG0Rd/dJMcadobpem/28Wfs6ssROyR31oyjdG8Ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qG0Rd/dJMcadobpem/28Wfs6ssROyR31oyjdG8Ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqG0Rd%2FdJMcadobpem%2F28Wfs6ssROyR31oyjdG8Ck%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 왜 nginx-gateway-fabric인가&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ingress-nginx 프로젝트는 유지보수 모드로 전환 방침이 공지됐고, 공식 후계 방향은 Kubernetes SIG Network에서 표준화한 Gateway API다. Gateway API 구현체는 여러 개(Istio, Envoy Gateway, Cilium, Contour, NGF 등)이지만 다음 이유로 NGF 2.0을 선택했다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;1. 기존 스택 재사용: 데이터 플레인이 그대로 nginx라서 로그&amp;middot;튜닝 노하우가 유지된다
2. per-Gateway Deployment 네이티브 지원: Gateway CR 하나당 nginx Deployment가 자동 프로비저닝된다. 기존 &quot;클래스 분리 = 릴리스 분리&quot; 모델과 궁합이 좋다
3. 단일 컨트롤 플레인 + N 데이터 플레인: helm release 11개 &amp;rarr; 1개로 축소되면서도 IP&amp;middot;클래스 분리 요구는 유지된다
4. CRD 기반 정책 확장: ClientSettingsPolicy, UpstreamSettingsPolicy, BackendTLSPolicy 등으로 기존 어노테이션 대부분이 대체된다&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;div class=&quot;txc-textbox&quot; style=&quot;background-color: #ffffff; border: #cbcbcb 3px double; padding: 10px;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;Gateway API가 Ingress 대비 갖는 본질적 장점은&amp;nbsp;&lt;/span&gt;&lt;b&gt;리소스 경계의 명확화&lt;/b&gt;&lt;span style=&quot;text-align: start;&quot;&gt;다. &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;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Ingress는 &quot;cluster-scoped 관심사(리스너, TLS, 클래스)&quot;와 &quot;app-scoped 관심사(라우팅 규칙)&quot;가 한 오브젝트에 섞여 있었는데, Gateway API는 이를 `GatewayClass` / `Gateway` / `HTTPRoute` 로 분리한다. &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;color: #000000; text-align: start;&quot;&gt;클러스터 관리자와 앱 개발자의 권한 경계가 자연스럽게 그려진다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&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;
&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;color: #000000;&quot;&gt;2. 아키텍처 결정: 1 GatewayClass + 11 Gateway&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;초기 오판과 수정&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처음 설계 단계에서는 &quot;ingress-nginx 11개 인스턴스 = ingressClass 11개&quot;였으니 NGF도 자연스럽게 &lt;b&gt;11 GatewayClass&lt;/b&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;color: #000000;&quot;&gt;NGF 2.x는 설치당 &lt;b&gt;단일 GatewayClass&lt;/b&gt;만 reconcile한다. 컨트롤러 실행 시 `--gatewayclass=ngf` 플래그로 한 클래스만 지정되고, 나머지는 무시된다. 여러 GatewayClass가 필요하면 NGF를 여러 번 설치해야 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설계를 다음과 같이 수정했다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;markdown&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;- 1개 GatewayClass: `ngf` (NGF chart가 자동 생성)
- 11개 Gateway: `ngf`, `ngf-public-a` ~ `ngf-public-j` (모두 `gatewayClassName: ngf`)
- 11개 NginxProxy CR: Gateway의 `infrastructure.parametersRef`로 참조한다. MetalLB IP를 `service.loadBalancerIP`로 고정한다
- **Tenancy boundary = Gateway 이름**. 앱의 HTTPRoute는 `parentRefs`로 특정 Gateway에 attach하면 자동으로 해당 데이터 플레인(과 IP)으로 라우팅된다&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;즉 &quot;11 클래스 분리&quot;가 아니라 &quot;11 Gateway 분리&quot;로 같은 멀티테넌시를 달성&lt;/b&gt;&lt;/u&gt;한다. NGF가 Gateway별로 독립된 nginx Deployment를 띄워주기 때문에 &lt;b&gt;프로세스 격리까지 그대로&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;디렉토리 구조 (최종)&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;network/nginx-gateway-fabric/
├── Chart.yaml                      # upstream mirror (version + appVersion = single source)
├── helmfile.yaml.gotmpl            # Chart.yaml을 readFile+fromYaml로 자동 참조
├── values.yaml                     # upstream default (helm pull)
├── values.schema.json              # upstream schema
├── values/
│   └── mgmt.yaml                   # 커스텀 override (replicas, telemetry off 등)
├── cr-chart/                       # Phase 7+에서 manifests/ 리팩터 결과
│   ├── Chart.yaml
│   ├── values.yaml
│   └── templates/
│       ├── gateways.yaml           # 11 Gateway
│       ├── nginxproxies.yaml       # 11 NginxProxy (LB IP pin)
│       └── servicemonitor.yaml
└── upgrade.sh                      # external-oci canonical&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;&lt;b&gt;Chart.yaml single source:&lt;/b&gt; `version`(chart 자체)과 `appVersion`(NGF 소프트웨어 = git tag)을 단일 소스로 두고, `helmfile.yaml.gotmpl` 에서 `readFile` + `fromYaml` 로 자동 참조한다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`Chart.yaml` 만 갱신해도 `chart version` 과 `prepare hook` 의&amp;nbsp; `?ref=v&amp;lt;APP_VER&amp;gt; ` 경로가 자동 `sync` 된다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Hook 설계&lt;/b&gt; (apply/destroy)&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;prepare: 모든 명령 전 &amp;rarr; Gateway API CRDs + NGF 자체 CRDs를 선설치한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;postsync: apply 후 &amp;rarr; Gateway/NginxProxy를 적용한다 (초기엔 kubectl apply, 이후 로컬 차트로 전환한다)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;preuninstall: destroy 전 &amp;rarr; 커스텀 CR을 제거한다 (컨트롤러 살아있을 때 finalizer 처리)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;postuninstall: destroy 후 &amp;rarr; CRDs + namespace를 제거한다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OCI 차트 업그레이드 스크립트&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NGF는 OCI registry(`oci://ghcr.io/nginx/charts/nginx-gateway-fabric`)로만 배포된다. 기존 업그레이드 canonical 스크립트는 `helm search repo` 로 최신 버전을 자동 탐지하는데, OCI는 이 명령을 지원하지 않는다.&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;color: #000000;&quot;&gt;그래서 `external-oci.sh` canonical을 새로 만들었다. 최신 버전 탐지 로직만 GitHub Releases API(`api.github.com/repos/$GITHUB_REPO/releases/latest`)를 사용해 `tag_name` 에서 prefix(기본 v)를 제거해 chart 버전을 추출하도록 교체했다. `GITHUB_TOKEN` 환경변수가 있으면 rate limit이 60&amp;rarr;5,000 req/h로 완화된다.&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;&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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 어노테이션 &amp;rarr; Gateway API 변환 매핑&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ingress-nginx에서 쓰던 어노테이션을 Gateway API + NGF CRD로 옮기는 표다. 실제 환경에서 쓰던 어노테이션만 정리했다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;ingress-nginx 어노테이션	Gateway API / NGF 대체	용도
force-ssl-redirect: &quot;true&quot;	HTTPRoute + RequestRedirect filter (HTTP 리스너에만)	HTTPS 강제 앱
force-ssl-redirect: &quot;false&quot;	미설정 (기본)	대부분의 앱
ssl-passthrough: &quot;true&quot;	TLSRoute + listener tls.mode: Passthrough	사용 앱 없음 &amp;rarr; 제외
backend-protocol: &quot;HTTPS&quot;	BackendTLSPolicy (gateway.networking.k8s.io/v1)	TLS backend 앱
backend-protocol: &quot;HTTP&quot;	기본	일반 HTTP backend
rewrite-target: /	URLRewrite filter (ReplacePrefixMatch)	경로 재작성 앱
proxy-body-size: &quot;500m&quot;	ClientSettingsPolicy.spec.body.maxSize: &quot;500m&quot;	업로드 큰 앱
proxy-body-size: &quot;0&quot; (무제한)	ClientSettingsPolicy.spec.body.maxSize: &quot;0&quot;	컨테이너 레지스트리
proxy-read/send-timeout: &quot;300&quot;	HTTPRoute timeouts.request + timeouts.backendRequest	장시간 연결 앱
proxy-buffering: &quot;off&quot;	ProxySettingsPolicy.spec.buffering.disable	SSE 스트리밍 앱
proxy-http-version: &quot;1.1&quot;	NGF 기본값 &amp;rarr; no-op, 제거	-
limit-rps: &quot;15&quot;	RateLimitPolicy (key, rate, burst)	레이트 리밋 앱
limit-connections: &quot;25&quot;	NGF native 미지원 (SnippetsFilter 우회 가능)	동시 연결 제한
configuration-snippet	SnippetsFilter CRD (NGF 1.4+)	최후 수단&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;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;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;몇 가지 실전 포인트&lt;/b&gt;&lt;/u&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;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;txc-textbox&quot; style=&quot;background-color: #ffffff; border: #cbcbcb 3px double; padding: 10px;&quot;&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;`force-ssl-redirect` 는 sibling HTTPRoute 2개로 분리한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하나는 HTTP listener에 attach해서 `RequestRedirect filter` 만 두고, 다른 하나는 HTTPS listener에 실제 라우팅 규칙을 둔다. 301 대신&amp;nbsp;&lt;b&gt;307&lt;/b&gt;을 쓰는 게 안전하다. 301은 `POST` 를 `GET` 으로 바꿔버려 webhook이나 API 수신자가 깨진다.&lt;/span&gt;&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;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;`backend-protocol: HTTPS` 는 BackendTLSPolicy로 해결한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ECK 기반 Elasticsearch의 경우 operator가 내부 Secret에 CA를 넣어주는데, 차트에서 lookup 함수로 이를 읽어 ConfigMap으로 자동 복제하도록 했다. operator가 CA를 rotate하면 다음 `helm upgrade` 에서 자동 갱신된다.&lt;/span&gt;&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;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;`limit-connections` 는 NGF 네이티브 미지원이 발목을 잡았다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`limit_conn` directive가 NGF policy로 노출되지 않아, 해당 기능을 포기하고 앱 레벨 신뢰로 전환했다. `SnippetsFilter` 로 우회 가능하지만 표면적이 넓어져 스코프에서 제외했다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&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;
&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;color: #000000;&quot;&gt;4. Zero-downtime 병렬 모드 전략&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가장 중요한 전략적 결정이다. &quot;어떻게 해야 실트래픽 영향 없이, 롤백 한 번에 되돌릴 수 있게 전환할까?&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 원칙: ingress + httproute 동시 공존&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;앱 전환 전 기간에 걸쳐 &lt;b&gt;모든 앱은 `ingress.enabled: true` + `httproute.enabled: true` 공존 상태&lt;/b&gt;로 유지했다. 다음 조건을 동시에 충족시키는 설계다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DNS는 계속 기존 MetalLB IP를 가리킨다 &amp;rarr; 사용자 트래픽은 ingress-nginx로 향한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HTTPRoute는 임시 IP에만 닿는다 &amp;rarr; 개발자가 `curl --resolve` 로만 검증할 수 있다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;롤백 = `httproute.enabled: false` 토글 1개로 끝난다 (ingress는 애초 건드리지 않았으므로 복구 불필요하다)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전 환경(prod/dev/qa/staging) 동일 절차 &amp;rarr; 환경별 차등이 없다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MetalLB 풀 확장&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MetalLB 풀에 임시 검증용 IP 11개를 추가했다. 기존 서비스가 쓰던 IP와 겹치지 않도록 사전에 `kubectl get svc -A`&amp;nbsp; 및 수동 예약 IP(베어메탈 노드 등)를 모두 식별한 뒤 사용 가능 구간만 선점했다. 이 임시 IP들은 Phase 6 cutover 시 실 IP로 swap된다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;검증 패턴&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;임시 IP로 `smoke test` 하는 표준 명령은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;elixir&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# NGF 임시 IP 검증
curl -sS --resolve &amp;lt;hostname&amp;gt;:80:&amp;lt;temp-ip&amp;gt; \
     -o /dev/null -w &quot;%{http_code}\n&quot; \
     http://&amp;lt;hostname&amp;gt;/

# 기존 ingress-nginx 대조 (실 IP)
curl -sS --resolve &amp;lt;hostname&amp;gt;:80:&amp;lt;real-ip&amp;gt; \
     -o /dev/null -w &quot;%{http_code}\n&quot; \
     http://&amp;lt;hostname&amp;gt;/&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;두 응답이 같으면 OK다. 각 Phase에서 롤백 훈련을 1회 필수로 진행했다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`httproute.enabled: false` 토글 &amp;rarr; `helmfile apply` &amp;rarr; 임시 IP 404, 실 IP 200 (기존 경로 무영향) 확인한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`httproute.enabled: true` 복구 &amp;rarr; 임시 IP 200 회복한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전 과정 각 단계 10초 내 완료되고 실트래픽은 시종 무영향이다&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;차트별 HTTPRoute 템플릿 통일&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 차트에 HTTPRoute 템플릿을 추가하면서 values 스키마를 통일했다. 개별 앱 차트와 ApplicationSet 공용 base 차트가 동일한 모양을 쓰도록 했다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;httproute:
  enabled: false
  parentRefs:
    - name: ngf
      namespace: nginx-gateway
      # sectionName: https   # HTTPS only 필요 시
  hostnames: []
  rules:
    - matches:
        - path: { type: PathPrefix, value: / }
      # filters:
      #   - type: URLRewrite
      #     urlRewrite: { path: { type: ReplacePrefixMatch, replacePrefixMatch: / } }
      # timeouts:
      #   request: 300s
      #   backendRequest: 300s
      backendRefs:
        - port: 80   # name 생략 시 chart fullname 자동
  httpsRedirect:
    enabled: false   # true면 HTTP&amp;rarr;HTTPS 301 sibling route 자동 생성&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;이 스키마 하나로 단순 라우팅부터 rewrite, timeout, HTTPS redirect까지 전부 커버된다. 한 앱에서 먼저 패턴을 검증한 뒤 그대로 복제했다.&lt;/span&gt;&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;&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;
&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;color: #000000;&quot;&gt;5. TLS Wildcard 단일화 + cert-manager 미래 전환 설계&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현 환경 제약&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용 중인 도메인이 DNS API를 제공하지 않는 registrar로 관리된다. 이 제약이 결정적이었다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&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;color: #000000;&quot;&gt;cert-manager + Let's Encrypt &lt;b&gt;DNS-01 challenge 불가&lt;/b&gt; (registrar가 DNS API를 제공하지 않는다)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HTTP-01은 &lt;b&gt;wildcard 불가&lt;/b&gt; (ACME 스펙상)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;rarr; self-signed wildcard cert 수동 관리가 사실상 유일한 옵션이다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;기존에는 앱마다 개별 self-signed Secret을 두고 있었다. 이를 단일 wildcard Secret 중앙 관리로 통합했다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단일 Secret 중앙 관리 구조&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;Secret &quot;wildcard-tls&quot; (nginx-gateway ns)
  └─ CN=*.example.com
     SAN: example.com, *.example.com
     10년 validity
  │
  ▼
Gateway &quot;ngf&quot; listeners:
  - name: http          (port 80)
  - name: https         (port 443, hostname: &quot;*.example.com&quot;,
                         certificateRefs: wildcard-tls)
  │
  ▼
각 앱 HTTPRoute:
  parentRefs[*].sectionName 생략 (기본): HTTP + HTTPS 양쪽 listener 자동 부착
  parentRefs[*].sectionName: https        : 명시적 HTTPS only
  parentRefs[*].sectionName: http         : httpsRedirect sibling route 전용&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;차트 역할 = 아무것도 안 함 (중요)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여기가 가장 오래 고민한 지점이다. TLS를 어디서 소유하게 할 것인가?&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;color: #000000;&quot;&gt;&lt;b&gt;결론: 차트는 TLS-agnostic 유지한다. TLS는 Gateway layer 책임이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;차트에 Certificate CR 템플릿을 넣지 않는다 &amp;rarr; cert-manager 강제 의존을 회피하고 Gateway API 철학 위배를 방지한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;차트에 Secret/secretName values를 넣지 않는다 &amp;rarr; Gateway layer가 소유한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`httproute.parentRefs[].sectionName` + `httpsRedirect.enabled` 옵션만 유지한다 &amp;rarr; 앱별로 listener 선택과 HTTPS 강제 여부만 토글한다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이렇게 하면 나중에 registrar를 옮기거나 별도 DNS 서비스로 이관해 cert-manager를 도입해도 &lt;b&gt;전환 비용이 거의 0&lt;/b&gt;이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&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;color: #000000;&quot;&gt;Gateway 변경 0 (Secret 이름/ns 동일 유지)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;차트 변경 0 (애초에 Secret을 모른다)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;앱 values 변경 0&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;작업량: cert-manager ca issuer + Certificate CR 1개를 추가한다. 기존 Secret을 덮어쓰도록 설정하면 자동 갱신을 획득한다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;수동 갱신 부담도 확정적으로 감소했다. 앱별 self-signed Secret 여러 장 &amp;rarr; wildcard 1장(10년 유효)으로 단일화된다.&lt;/b&gt;&lt;/u&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;통일 vs 보존 방침&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;이제 wildcard가 있으니 모든 앱에 `sectionName: https` + `httpsRedirect: true` 통일하자&quot;는 &lt;b&gt;거절했다&lt;/b&gt;. 이유는 세 가지다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;cert-manager 전환 편의성은 Secret 이름/ns 고정만으로 이미 확보된다 &amp;mdash; sectionName 통일과 무관하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;내부 API 클라이언트가 301/307 redirect를 안정적으로 따르는지 앱마다 검증하는 부담이 발생한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부 포트 포워딩 경로는 redirect로 깨진다 (RequestRedirect는 scheme만 바꾸고 host/port는 유지되기 때문이다)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&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;&lt;span style=&quot;color: #000000;&quot;&gt;원칙은 &lt;b&gt;&quot;기존 Ingress 동작 보존&quot;&lt;/b&gt;이다. HTTP였던 앱은 HTTP 유지, HTTPS 강제였던 앱만 HTTPS 강제로 간다.&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6. Phase 6 Cutover: 실전 트러블슈팅&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여기가 가장 많이 배운 구간이다. 11개 클래스를 영향도 낮은 순으로 cutover하고, 프로덕션 핵심 클래스를 마지막에 처리했다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;원래 가정&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처음엔 단순하게 가정했다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`ingress-nginx controller replicas=0` 으로 축소 &amp;rarr; IP 해제된다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NginxProxy의 loadBalancerIP를 실 IP로 수정 &amp;rarr; `helmfile apply`&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;끝&lt;/span&gt;&lt;/li&gt;
&lt;/ol&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;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;&lt;span style=&quot;text-align: start;&quot;&gt;첫 클래스부터 연이어 문제가 터졌다. 총 8개 이슈를 발견&amp;middot;해결한 과정을 정리한다.&lt;/span&gt;&lt;/b&gt;&lt;/u&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이슈 1: replicas=0으로는 MetalLB IP가 해제되지 않는다&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`kubectl scale deploy/&amp;lt;release&amp;gt;-controller --replicas=0` 으로 pod를 0으로 만들어도 MetalLB가 IP를 계속 점유한다. pool 포화 상태라 NGF가 같은 IP를 받을 수 없었다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;원인&lt;/b&gt;: `externalTrafficPolicy: Cluster` + `spec.loadBalancerIP` 지정 + pool 포화 조합에서는 &lt;b&gt;Service 객체가 살아있는 한&lt;/b&gt; MetalLB가 IP를 반환하지 않는다. pod 유무는 무관하다.&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;color: #000000;&quot;&gt;&lt;b&gt;해결&lt;/b&gt;: Service를 ClusterIP로 `patch` 하고 loadBalancerIP 필드를 명시적으로 제거한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;scilab&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;kubectl patch svc &amp;lt;release&amp;gt;-controller -n ingress-nginx --type=json -p='[
  {&quot;op&quot;:&quot;replace&quot;,&quot;path&quot;:&quot;/spec/type&quot;,&quot;value&quot;:&quot;ClusterIP&quot;},
  {&quot;op&quot;:&quot;remove&quot;,&quot;path&quot;:&quot;/spec/loadBalancerIP&quot;}
]'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;이걸 `cutover.sh` Step 2로 영구화했다.&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이슈 2: helmfile apply로 manifests/ 변경이 적용 안 된다&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`manifests/nginxproxies.yaml` 에서 IP만 수정하고 `helmfile apply` 를 돌렸는데 `hook` 이 실행되지 않았다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;원인&lt;/b&gt;: helmfile은 &lt;b&gt;chart 자체 diff가 없으면&lt;/b&gt; `release-level postsync hook` 을 건너뛴다. `manifests/` 파일은 chart 밖 raw kubectl 대상이라 helmfile 관점에선 변경 없음으로 판단된다.&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;color: #000000;&quot;&gt;&lt;b&gt;해결&lt;/b&gt;: manifest-only 변경은 `kubectl diff` -f + `kubectl apply -f` 를 직접 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;maxima&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;kubectl diff -f manifests/nginxproxies.yaml
kubectl apply -f manifests/nginxproxies.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;이후 이 문제를 구조적으로 해결하기 위해 `manifests/` 디렉토리를 로컬 CR chart로 리팩터했다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이제 `helmfile diff` 가 Gateway/NginxProxy IP 변경까지 완전 커버한다. 이 차트는 Phase 7+ 정리 단계에서 공개 Helm 차트로 별도 분리해 배포했다. 자세한 내용은 7.5절에서 다룬다.&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이슈 3: ValidatingWebhookConfiguration이 Ingress UPDATE/DELETE를 막는다&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;첫 클래스 cutover 후 ArgoCD prune이 Ingress를 삭제하려는데 2분 timeout이 걸렸다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;원인&lt;/b&gt;: `&amp;lt;release&amp;gt;-admission ValidatingWebhookConfiguration(VWC)` 이 살아있는데, endpoint Service는 방금 ClusterIP로 patch됐고 pod는 0개다. 즉 admission webhook 호출이 무응답 &amp;rarr; Ingress UPDATE/DELETE가 전부 실패한다(ArgoCD prune 포함).&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;color: #000000;&quot;&gt;&lt;b&gt;해결&lt;/b&gt;: cutover 과정에서 VWC를 선삭제한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;arduino&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;kubectl delete validatingwebhookconfiguration &amp;lt;release&amp;gt;-admission&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;선제 삭제가 필수다. 안 하면 후속 이슈 4까지 연쇄 발생한다.&lt;/span&gt;&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이슈 4: foregroundDeletion finalizer stuck&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;첫 클래스에서 Ingress 리소스가 삭제 명령 후에도 Terminating 상태로 영구 대기했다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;원인&lt;/b&gt;: `ArgoCD cascade delete` 가 `foregroundDeletion finalizer` 를 부여하는데, GC가 dependent 없는 Ingress인데도 제거하지 못한다.&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;color: #000000;&quot;&gt;&lt;b&gt;해결&lt;/b&gt;: finalizer를 직접 제거한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;kubectl get ingress &amp;lt;name&amp;gt; -n &amp;lt;ns&amp;gt; -o jsonpath='{.metadata.finalizers}'
# [foregroundDeletion] 확인되면:
kubectl patch ingress &amp;lt;name&amp;gt; -n &amp;lt;ns&amp;gt; -p '{&quot;metadata&quot;:{&quot;finalizers&quot;:null}}' --type=merge&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;&lt;b&gt;핵심 관찰:&lt;/b&gt; 이슈 3(VWC 선삭제)를 먼저 처리하면 이 finalizer stuck 자체가 발생하지 않는다. 이후 클래스에선 재발이 없었다. 근본 원인은 VWC, finalizer stuck은 그 증상 중 하나였던 셈이다.&lt;/span&gt;&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이슈 5: 내부 pod &amp;rarr; 퍼블릭 도메인 &amp;rarr; LB IP 경로가 2분 timeout된다&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여섯 번째 클래스 cutover에서 발견했다. 내부 CI generator 스테이지가 멈추기 시작했다. 외부 클라이언트에선 정상, 클러스터 내부 pod &amp;rarr; LB IP 경로만 깨졌다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;원인&lt;/b&gt;: NGF chart default로 `NginxProxy.kubernetes.service.externalTrafficPolicy: Local` 이다. 내부 pod &amp;rarr; LB IP 경로는 kube-proxy가 &lt;b&gt;해당 노드에 local endpoint가 있을 때만&lt;/b&gt; 포워딩한다. NGF 데이터플레인 pod가 `replica=1` 이라 대부분 노드에서 miss가 발생했다. 기존 ingress-nginx는 Cluster였기에 영향이 없었다.&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;color: #000000;&quot;&gt;&lt;b&gt;해결&lt;/b&gt;: 11개 NginxProxy에 `service.externalTrafficPolicy: Cluster` 를 명시한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;apiVersion: gateway.nginx.org/v1alpha1
kind: NginxProxy
metadata:
  name: ngf-public-f
  namespace: nginx-gateway
spec:
  kubernetes:
    service:
      type: LoadBalancer
      externalTrafficPolicy: Cluster   # &amp;larr; 이 한 줄
      loadBalancerIP: &amp;lt;real-ip&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;&lt;b&gt;Trade-off 기록:&lt;/b&gt; ETP: Cluster는 client source IP를 SNAT한다. HTTPRoute backend에서 원본 IP가 필요하면 `X-Forwarded-For` 헤더를 사용해야 한다(NGF 기본 주입). &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너 레지스트리 audit log의 source_ip 컬럼처럼 client IP 기반 기능은 XFF 기반으로 재설정 확인이 필요하다.&lt;/span&gt;&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이슈 6: 라우터 ARP 캐시&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MetalLB pool이 포화 상태라 한 임시 IP가 외부 클라이언트에서만 RST, 내부에선 정상인 이상한 현상이 있었다.&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;color: #000000;&quot;&gt;&lt;b&gt;원인&lt;/b&gt;: 라우터의 stale ARP 캐시다.&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;color: #000000;&quot;&gt;&lt;b&gt;해결&lt;/b&gt;: 실 IP로 cutover되면서 자동 해결됐다. 임시 IP의 ARP 엔트리는 캐시 만료되면서 정리됐다.&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;color: #000000;&quot;&gt;&lt;b&gt;부가 발견&lt;/b&gt;: 라우터 UI를 실측한 결과 모든 포워드 규칙이 MetalLB LB IP:80 기반이었다. Phase 6에서 동일 IP를 NGF에 재할당하므로 &lt;b&gt;라우터 설정 변경 불필요, 자동 전환&lt;/b&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이슈 7: ArgoCD values 토글 누락 시 Ingress 재생성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ApplicationSet 앱에서 cutover 후 `ingress.enabled: false` 로 내리지 않으면 ArgoCD가 Ingress를 계속 재생성한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;해결&lt;/b&gt;: cutover Step 5에 영구 등록한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# applicationset/values/&amp;lt;project&amp;gt;/&amp;lt;service&amp;gt;/&amp;lt;env&amp;gt;.values.yaml
ingress:
  enabled: false   # Phase 6 cutover 후 필수
httproute:
  enabled: true
  # ...&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;변경 커밋&amp;middot;푸시 후 ArgoCD refresh를 즉시 트리거하려면 다음을 쓴다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;kubectl annotate application &amp;lt;name&amp;gt; -n argocd \
        argocd.argoproj.io/refresh=normal --overwrite&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;기본 auto-sync polling이 3분 주기라 수 분간 반영이 안 되는 것처럼 보이는 함정을 피할 수 있다.&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이슈 8: cutover.sh smoke 출력이 &quot;HTTP 2000&quot;으로 깨져 보인다&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`$(curl ... || echo &quot;0&quot;)` 에서 curl이 성공했을 때 `success stdout` 과 `echo &quot;0&quot;` 가 합쳐져 이상한 출력이 나왔다.&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;color: #000000;&quot;&gt;&lt;b&gt;해결&lt;/b&gt;: `${CODE:-000}` 기본값과 `HTTP_CODE` 분리 검사로 정리했다. 스크립트 이슈라 사소하지만, 한밤중 cutover 중 출력 혼란을 일으키는 타입의 버그라 기록해둘 만하다.&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최종 cutover 절차 (cutover.sh 요약)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위 8개 이슈를 모두 반영한 클래스당 표준 절차다.&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;대기 확인: `kubectl get svc -n ingress-nginx &amp;lt;release&amp;gt;-controller -o wide`&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ingress-nginx Service &amp;rarr; ClusterIP patch + loadBalancerIP 제거 (이슈 1)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`ingress-nginx deployment replicas=0`&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`manifests/nginxproxies.yaml` 해당 Gateway IP를 실 IP로 수정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`kubectl diff -f manifests/nginxproxies.yaml` &amp;rarr; `kubectl apply -f` (이슈 2)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ApplicationSet values / infra values에서 `ingress.enabled: false` 토글 (이슈 7)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VWC 선삭제: `kubectl delete validatingwebhookconfiguration &amp;lt;release&amp;gt;-admission` (이슈 3)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MetalLB 재할당 확인 + smoke test (`curl --resolve &amp;lt;host&amp;gt;:80:&amp;lt;real-ip&amp;gt;`)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;finalizer stuck 잔존 Ingress 있으면 패치로 제거한다 (이슈 4)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;24시간 안정 모니터링한다. 비핵심 클래스는 다음 클래스 cutover 병행이 가능하다. 핵심 클래스만 1~2일 누적 관측 후 진입한다&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;실 다운타임은 Step 2 patch 실행 ~ Step 5 NGF Service IP swap 완료까지 약 30초~1분 구간만 해당한다.&lt;/b&gt;&lt;/u&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아래의 레포를 참고해보길 바란다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/network/tree/main/nginx-gateway-fabric&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/somaz94/network/tree/main/nginx-gateway-fabric&lt;/a&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;color: #000000;&quot;&gt;7. 결과 및 교훈&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최종 상태&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style10&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지표&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Before&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;After&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;helm release&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;11 (ingress-nginx)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1 (NGF)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ingress 리소스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;24개&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0개&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HTTPRoute 리소스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;15개&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gateway CR&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;11개&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MetalLB 할당 IP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동일 규모 유지&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동일 규모 유지&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;self-signed TLS Secret&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;앱별 개별&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1 (wildcard)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;cert 갱신 주기&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;앱별 개별&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10년 1장&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&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;color: #000000;&quot;&gt;MetalLB pool은 cutover 완료 후 축소 조정했다. 검증용 임시 IP 대부분을 반납하고 여유 IP를 소량 남겼다.&lt;/span&gt;&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Phase 7+ 후속 작업&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;원래 1주 대기 후 정리할 예정이었던 작업들을 당일 연속 처리했다. 판단 근거는 &quot;롤백 비용은 drift 상태든 destroyed 상태든 동일(`helmfile apply` 1회)&quot;였다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&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;color: #000000;&quot;&gt;ingress-nginx 11개 `helm release helmfile destroy` 를 완료한다 (namespace까지 clean)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`network/ingress-nginx/` &amp;rarr; `network/_optional/ingress-nginx/` 로 이동한다 (git mv + README에 archive 상태 명시)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MetalLB pool을 축소한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NGF manifests/ &amp;rarr; local CR chart로 전환한다 (helm ownership 라벨/annotation 수동 부여 후 adopt)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너 레지스트리를 chart-native HTTPRoute로 전환한다 (zero-downtime 4단계)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;per-app self-signed TLS Secret을 폐기한다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;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;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;chart-native HTTPRoute 전환은 zero-downtime 기법&lt;/b&gt;&lt;/u&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;color: #000000;&quot;&gt;새 route를 먼저 생성해 기존과 동일 hostname 중복 상태로 공존시키고(older-wins 규칙으로 기존이 트래픽 유지), 새 Policy는 TargetConflict 상태로 대기한다. 기존 HTTPRoute 삭제 순간 conflict 해소 &amp;rarr; 새 `Policy Accepted=True` 로 즉시 전환된다. &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;color: #000000;&quot;&gt;트래픽이 transparent하게 swap된다.&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;&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;
&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;7.5 nginx-gateway-cr 차트 공개 배포&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Phase 7+에서 가장 공 들인 작업은 manifests/ 디렉토리를 &lt;b&gt;로컬 Helm 차트로 리팩터&lt;/b&gt;한 뒤, 그 차트를 아예 &lt;b&gt;공개 저장소로 분리 배포&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;배경.&lt;/b&gt; 내부 `manifests/` 디렉토리 방식은 이슈 2(`helmfile apply` 가 chart 자체 diff 없으면 hook skip)를 피하기 위해 `kubectl apply -f` 로 우회해야 했다. 구조적으로 helmfile 파이프라인 밖에 있는 리소스가 된다. Phase 6 cutover 중 IP swap할 때마다 `kubectl diff` + `kubectl apply` 를 수동으로 섞어야 하는 게 불편했다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;왜 공개로 분리했나.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NGF 자체 차트는 OCI registry로 활발히 릴리스되고 있고 템플릿 20개 이상을 수동 추적하기엔 부담이 크다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우리가 override하려는 건 NGF 내부 템플릿이 아니라 &lt;b&gt;NGF 컨트롤러가 reconcile하는 별도 CR들&lt;/b&gt;(Gateway, NginxProxy)이다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 리소스들은 내 환경만의 특수성이 없다 &amp;mdash; &quot;Gateway + NginxProxy(LB IP pin) + ServiceMonitor&quot;는 per-Gateway 멀티테넌시가 필요한 모든 NGF 사용자에게 공통적이다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;내부 레포에만 둘 이유가 없고, Helm 차트 관습대로 공개 저장소에 두는 게 버전 관리&amp;middot;재사용&amp;middot;문서화 모두에 유리하다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;차트 저장소&lt;/b&gt;: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/helm-charts/tree/main/charts/nginx-gateway-cr&quot;&gt;https://github.com/somaz94/helm-charts/tree/main/charts/nginx-gateway-cr&lt;/a&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;차트가 생성하는 리소스&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gateway &amp;mdash; 11개든 1개든 values에 배열로 선언한 만큼 생성된다. 각 Gateway는 `gatewayClassName: ngf` 기본값을 따른다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NginxProxy &amp;mdash; 각 Gateway의 `infrastructure.parametersRef` 대상. `service.loadBalancerIP` 로 MetalLB/클라우드 LB의 고정 IP를 pin한다. `externalTrafficPolicy: Cluster` 기본값 (이슈 5 반영)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ServiceMonitor &amp;mdash; NGF chart가 생성해주지 않는 Prometheus 메트릭 수집용 리소스. Prometheus Operator 설치된 환경에서 바로 수집 가능하다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;사용 방법 (helmfile 기준)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# helmfile.yaml.gotmpl (두 release를 needs로 연결)
repositories:
  - name: somaz
    url: https://charts.somaz.blog

releases:
  - name: nginx-gateway-fabric
    namespace: nginx-gateway
    chart: oci://ghcr.io/nginx/charts/nginx-gateway-fabric
    version: 2.5.1
    # ... NGF 컨트롤러 설정

  - name: nginx-gateway-cr
    namespace: nginx-gateway
    chart: somaz/nginx-gateway-cr
    version: &amp;lt;chart-version&amp;gt;
    needs:
      - nginx-gateway/nginx-gateway-fabric
    values:
      - values/cr.yaml&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;values 예시 (per-Gateway 멀티테넌시 시나리오)&lt;/b&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# values/cr.yaml &amp;mdash; 실제 필드명은 차트 README 확인
gateways:
  - name: ngf
    loadBalancerIP: &amp;lt;main-ip&amp;gt;
    listeners:
      - name: http
        port: 80
        protocol: HTTP
      - name: https
        port: 443
        protocol: HTTPS
        tls:
          certificateRefs:
            - name: wildcard-tls
  - name: ngf-public-a
    loadBalancerIP: &amp;lt;public-a-ip&amp;gt;
    # ...&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;이 차트가 맞는 사용자&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;per-Gateway 멀티테넌시가 필요한 경우 &amp;mdash; 즉 Gateway마다 별도 LoadBalancer IP를 할당하고 싶은 환경&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 ingress-nginx 멀티 인스턴스 패턴(ingressClass별 분리)에서 이관하려는 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;베어메탈/온프레미스 + MetalLB 조합에서 IP를 수동 pin해야 하는 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ServiceMonitor까지 한 번에 자동 생성되길 바라는 경우&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;이 차트가 오버킬인 사용자&lt;/b&gt;: Gateway 1개만 필요하거나 클라우드 LB를 동적 할당 받는 게 문제없는 환경이라면, NGF 공식 차트의 nginxGateway.gateway 섹션만으로도 충분할 가능성이 높다. v2.5부터 NGF 자체 차트도 Gateway provisioning을 어느 정도 지원한다.&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;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;얻은 것&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&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;color: #000000;&quot;&gt;`helmfile diff` 하나로 Gateway/NginxProxy IP 변경까지 전부 볼 수 있다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;cutover가 &quot;values 한 줄 수정 &amp;rarr; helmfile apply&quot; 루틴으로 축소된다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;내부 manifests/ 디렉토리 + kubectl 수동 조합이 사라진다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다음 클러스터에서 같은 패턴을 재사용할 때 values만 갈아끼우면 된다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;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;color: #000000;&quot;&gt;처음부터 공개 차트로 만들었다면 Phase 1~6도 조금 더 깔끔했을 것이다. 하지만 실전에서 `manifests/` &amp;rarr; local chart &amp;rarr; 공개 chart 순서로 진화시킨 덕분에 &quot;어느 추상화 수준에서 어떤 문제가 해결되는지&quot;를 단계별로 확인할 수 있었다. &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;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;결과물만 놓고 보면 공개 차트부터 시작하는 게 맞겠지만, 그 결과물에 도달하기까지는 앞선 두 단계가 필요했다.&lt;/b&gt;&lt;/u&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;&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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배운 것들&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;설계 가정은 문서보다 먼저 의심해야 한다.&lt;/b&gt; &quot;11 인스턴스니까 11 GatewayClass&quot;는 NGF 2.x 공식 문서를 제대로 안 읽은 채 기존 멘탈 모델에 끼워 맞춘 결과였다. 실측 전에 구현체별 제약을 1차 소스로 확인하는 습관이 필요하다.&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;color: #000000;&quot;&gt;&lt;b&gt;병렬 모드의 가치는 롤백이 아니라 심리적 안전감&lt;/b&gt;이었다. 실제로 병렬 모드 기간 중 롤백을 trigger한 적은 없다. 하지만 &quot;토글 하나로 되돌릴 수 있다&quot;는 사실이 있었기에 금요일 저녁에도 cutover를 진행할 수 있었다. 이 점은 다음 전환 작업에서도 반복할 가치가 있다.&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;color: #000000;&quot;&gt;&lt;b&gt;문제의 80%는 cutover 1시간에 몰려 있다.&lt;/b&gt; 설계, 차트 작성, 병렬 모드 검증은 상대적으로 평온했다. 실제 IP swap 시점에 이슈 1~6이 연달아 터졌고, 특히 이슈 5(ETP: Local)는 내부 서비스가 특정 시간 동안 timeout을 내는 silent failure라 발견이 늦었을 수 있다. Cutover 시점에 &lt;b&gt;CI, webhook, cross-service 호출 같은 내부 트래픽 모니터링&lt;/b&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;color: #000000;&quot;&gt;&lt;b&gt;ETP 같은 기본값 하나가 운영 전체를 바꾼다.&lt;/b&gt; NGF chart default가 ETP: Local인 건 보안&amp;middot;성능 관점에서 합리적 기본값이지만, 기존 ingress-nginx Cluster 환경에서 옮겨오면 &lt;b&gt;내부 호출 경로가 silent하게 깨진다&lt;/b&gt;. 전환 도구의 default와 기존 환경의 가정 차이를 항목별로 체크하는 표를 만들어두는 게 다음엔 더 좋겠다.&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;color: #000000;&quot;&gt;&lt;b&gt;TLS 소유권은 Gateway layer에 둬야 한다.&lt;/b&gt; 차트에 cert/secret values를 넣고 싶은 유혹이 강하다. 참아야 한다. Gateway API의 리소스 경계 철학을 따르면, 차트는 HTTP 라우팅만 알고 TLS는 모르는 게 맞다. 이 원칙 덕분에 cert-manager 미래 전환 시 차트 코드 변경 0으로 끝낼 수 있다.&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리글&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ingress-nginx &amp;rarr; nginx-gateway-fabric 마이그레이션은 단순히 새 컨트롤러로 갈아타는 작업이 아니었다. Kubernetes의 L7 라우팅 모델이 Ingress 시대의 &quot;한 덩어리&quot;에서 Gateway API 시대의 &quot;명확한 리소스 경계&quot;로 진화한다는 사실을, 11개 인스턴스를 옮기면서 체감하는 과정이었다.&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;color: #000000;&quot;&gt;결과적으로 helm release 11개가 1개로, 개별 self-signed cert가 wildcard 1장으로, 흩어져 있던 어노테이션이 CRD 기반 정책으로 정리됐다. 외부에서 보면 DNS도 방화벽도 그대로지만, 내부 운영 부담은 뚜렷하게 줄었다.&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;color: #000000;&quot;&gt;특히 &lt;b&gt;병렬 모드 전략&lt;/b&gt;과 &lt;b&gt;TLS Gateway layer 소유 원칙&lt;/b&gt;은 다른 전환 작업에도 그대로 재활용할 수 있는 패턴이 됐다. 병렬 모드는 롤백 비용을 values 토글 수준으로 낮췄고, TLS 경계 분리는 cert-manager로의 미래 전환 비용을 0에 가깝게 만들었다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Phase 6의 이슈 1~8은 공식 문서 어디에도 정리되어 있지 않은, 실제 운영 환경에서만 드러나는 함정들이었다. 특히 externalTrafficPolicy: Local 기본값 차이는 cutover 한참 뒤에 드러날 수도 있었던 silent failure라 가장 아찔했다. 비슷한 전환을 앞둔 분들이 이 글을 읽고 최소 1시간은 아낄 수 있기를 바란다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다음 과제는 X-Forwarded-For 기반 audit log 복원과 Gateway API v1.3 신규 기능(특히 GRPCRoute 정식 활용) 검토다. 이것도 기록으로 남길 예정이다.&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;&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://gateway-api.sigs.k8s.io/&quot;&gt;Kubernetes Gateway API 공식 문서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/nginx/nginx-gateway-fabric&quot;&gt;nginx-gateway-fabric GitHub&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/nginx/nginx-gateway-fabric/pkgs/container/charts%2Fnginx-gateway-fabric&quot;&gt;NGF Helm Chart (OCI)&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/helm-charts/tree/main/charts/nginx-gateway-cr&quot;&gt;&lt;b&gt;nginx-gateway-cr (본 글에서 공개한 차트)&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://gateway-api.sigs.k8s.io/blog/&quot;&gt;Gateway API v1.2 Release Notes&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://gateway-api.sigs.k8s.io/guides/migrating-from-ingress/&quot;&gt;ingress-nginx &amp;rarr; Gateway API 마이그레이션 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://metallb.io/&quot;&gt;MetalLB Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.nginx.com/nginx-gateway-fabric/overview/custom-policies/&quot;&gt;NGF Custom Policies&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://gateway-api.sigs.k8s.io/api-types/backendtlspolicy/&quot;&gt;BackendTLSPolicy Spec&lt;/a&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;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;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Container Orchestration/Kubernetes</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/510</guid>
      <comments>https://somaz.tistory.com/510#entry510comment</comments>
      <pubDate>Thu, 14 May 2026 00:00:47 +0900</pubDate>
    </item>
    <item>
      <title>Claude Code 멀티 에이전트 (Sub-agents) 사용법</title>
      <link>https://somaz.tistory.com/516</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code의 멀티 에이전트는 정확히는 &lt;b&gt;Sub-agents (서브에이전트)&lt;/b&gt; 기능이다. 서브에이전트는 자체 시스템 프롬프트, 자체 컨텍스트 윈도우, 자체 도구 접근 권한, 자체 권한 모드를 가진 격리된 Claude 인스턴스로, 메인 대화 컨텍스트를 깨끗하게 유지하면서 특정 작업을 위임할 수 있다.&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;color: #000000;&quot;&gt;DevOps 작업 (Terraform, Kubernetes, ArgoCD 등)에 바로 활용 가능한 구조다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bexw4A/dJMcabK0hCE/d3jntwbaZKvU9iMxTogjKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bexw4A/dJMcabK0hCE/d3jntwbaZKvU9iMxTogjKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bexw4A/dJMcabK0hCE/d3jntwbaZKvU9iMxTogjKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbexw4A%2FdJMcabK0hCE%2Fd3jntwbaZKvU9iMxTogjKK%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;1. 핵심 개념&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서브에이전트의 가장 큰 가치는 &lt;b&gt;컨텍스트 보존&lt;/b&gt;이다. 테스트 실행, 문서 조회, 로그 파일 처리는 상당한 컨텍스트를 소비하는데, 이를 서브에이전트에 위임하면 verbose한 출력은 서브에이전트 컨텍스트에 머물고 관련 요약만 메인 대화로 돌아온다.&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;color: #000000;&quot;&gt;또한 여러 서브에이전트가 &lt;b&gt;동시에 실행&lt;/b&gt;될 수 있어 복잡한 워크플로우를 극적으로 단축시킨다. 예: 코드 리뷰 중 `style-checker`, `security-scanner`, `test-coverage` 서브에이전트를 동시 실행할 수 있다.&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;&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;
&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;color: #000000;&quot;&gt;2. 서브에이전트 생성 방법&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;방법 A: /agents 명령 (권장)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code 터미널에서 실행한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;/agents&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&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;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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;방법 B: 파일 직접 작성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서브에이전트는 YAML frontmatter를 가진 Markdown 파일이며, 스코프에 따라 다른 위치에 저장한다. 같은 이름의 서브에이전트가 여러 개일 때는 우선순위가 높은 위치가 이긴다.&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;color: #000000;&quot;&gt;저장 위치는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;프로젝트 전용&lt;/b&gt;: `.claude/agents/` &amp;mdash; 팀과 Git으로 공유한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;사용자 전역&lt;/b&gt;: `~/.claude/agents/` &amp;mdash; 모든 프로젝트에서 사용한다.&lt;/span&gt;&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 서브에이전트 파일 구조&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;---
name: terraform-reviewer
description: Terraform 코드 리뷰 및 보안 검토 전문 에이전트. Terraform 파일 변경사항이 있을 때 자동 호출.
tools: Read, Grep, Glob, Bash
model: sonnet
---

당신은 Terraform 인프라 코드 리뷰 전문가입니다.

검토 항목:
1. 보안: IAM 정책, 보안 그룹, 암호화 설정
2. 모범 사례: 모듈화, 변수 사용, tagging
3. 비용 최적화: 인스턴스 타입, 스토리지 클래스
4. State 관리: backend 설정, locking

결과는 다음 형식으로 보고:
-   Critical: 즉시 수정 필요
-   Warning: 권장 개선사항
-   Suggestion: 선택적 개선&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. DevOps 워크플로우용 추천 에이전트 구성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EKS, GKE, Terraform, ArgoCD 같은 인프라 환경에 맞춘 예시 팀이다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;.claude/agents/
├── terraform-reviewer.md      # IaC 리뷰
├── k8s-manifest-validator.md  # Kubernetes manifest 검증
├── argocd-troubleshooter.md   # ArgoCD 동기화 문제 분석
├── helm-chart-builder.md      # Helm chart 작성
└── gitlab-ci-optimizer.md     # GitLab CI/CD 파이프라인 최적화&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;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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. 호출 방법&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;자동 위임&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;description을 잘 작성하면 Claude가 자동으로 적절한 서브에이전트를 선택한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;명시적 호출&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특정 서브에이전트 사용을 보장하려면 프롬프트에서 이름을 언급한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;smali&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;Use the code-reviewer agent to check the authentication module&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&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;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;color: #000000;&quot;&gt;예시는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;armasm&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;terraform-reviewer 서브에이전트로 modules/eks 디렉토리 검토해줘&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;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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6. 병렬 실행 (멀티 에이전트의 장점)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;독립적인 조사를 위해 여러 서브에이전트를 동시에 spawn할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;Research the authentication, database, and API modules in parallel using separate subagents&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;각 서브에이전트가 독립적으로 자기 영역을 탐색하고 Claude가 결과를 종합한다. 연구 경로가 서로 의존하지 않을 때 가장 잘 작동한다.&lt;/span&gt;&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;&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;span style=&quot;color: #000000;&quot;&gt;DevOps 예시는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;EKS 클러스터 업그레이드 준비를 위해 병렬로 조사해줘:
- k8s-compatibility-checker 로 API deprecation 확인
- helm-chart-builder 로 차트 호환성 검토
- terraform-reviewer 로 EKS 모듈 변경사항 점검&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;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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;7. YAML Frontmatter 주요 필드&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;필드&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;name&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에이전트 식별자 (kebab-case 권장)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;description&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;언제 호출되는지 명확히 기술 (자동 위임에 핵심)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;tools&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;허용 도구 목록 (생략 시 모든 도구 상속)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;model&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;sonnet, opus, haiku 중 선택&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에이전트별로 &lt;b&gt;도구 범위를 제한&lt;/b&gt;해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PM과 Architect는 읽기 위주 (search, docs) 도구를 사용한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Implementer는 Edit / Write / Bash + UI 테스팅 도구를 사용한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Release는 필요한 것만 사용한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;tools를 생략하면 암묵적으로 모든 도구 접근을 허용하는 것이니 의도적으로 설정해야 한다.&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;8. 운영 팁&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;재시작 필요&lt;/b&gt;: `.claude/agents/` 에 정의된 에이전트는 시작 시에만 로드된다. 실행 중 새 에이전트 파일을 만들면 세션을 재시작해야 로드된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;확인&lt;/b&gt;: `/agents` 명령으로 현재 로드된 에이전트 목록을 확인한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Git 관리&lt;/b&gt;: 프로젝트 레벨 에이전트는 `.claude/agents/` 를 커밋해 팀과 공유한다.&lt;/span&gt;&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;9. 빌트인 서브에이전트 활용&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;직접 만들지 않아도 빌트인 에이전트들이 자동으로 작동한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&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;style10&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이름&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;용도&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Explore&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드베이스 검색과 이해를 위한 빠른 read-only 에이전트. Haiku로 실행되어 빠르고 저렴하다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Plan&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Plan 모드 (/plan)에서 코드베이스 조사를 수행한다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;general-purpose&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;탐색 + 수정이 모두 필요한 작업을 처리한다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;claude-code-guide&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code 자체 사용법 질문에 답변한다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;statusline-setup&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;터미널 상태 표시줄 설정을 담당한다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;&lt;span style=&quot;color: #000000;&quot;&gt;마치며&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서브에이전트는 Claude Code를 단순한 코딩 어시스턴트에서 &lt;b&gt;팀 단위의 AI 워크플로우&lt;/b&gt;로 확장시켜주는 핵심 기능이다. 특히 DevOps 환경처럼 Terraform, Kubernetes, ArgoCD, CI/CD 파이프라인 등 서로 다른 도메인이 얽혀있는 작업에서는 각 영역에 특화된 에이전트를 구성해두면 컨텍스트 오염 없이 깊이 있는 분석이 가능하다.&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;color: #000000;&quot;&gt;처음부터 완벽한 에이전트 팀을 만들 필요는 없다. &lt;b&gt;자주 반복하는 작업 하나&lt;/b&gt;부터 시작해 서브에이전트로 분리해보고, 점진적으로 팀을 확장해 나가는 것이 좋다. 예를 들어 매번 같은 패턴으로 검토하는 Terraform PR 리뷰, 반복적인 ArgoCD 동기화 이슈 디버깅, Helm 차트 업그레이드 호환성 점검 같은 작업이 1순위 후보가 된다.&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;color: #000000;&quot;&gt;또한 `.claude/agents/` 디렉토리를 &lt;b&gt;Git으로 관리&lt;/b&gt;하면 팀원 전체가 동일한 품질의 검토와 작업 프로세스를 공유할 수 있어, 단순한 개인 생산성 도구를 넘어 &lt;b&gt;팀 표준화 도구&lt;/b&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;color: #000000;&quot;&gt;작은 에이전트 하나부터 시작해서, 자신만의 DevOps 워크플로우를 자동화해보길 추천한다.&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;&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;
&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;공식 문서: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://code.claude.com/docs/en/sub-agents&quot;&gt;https://code.claude.com/docs/en/sub-agents&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;100+ 사전 제작 에이전트 모음 (DevOps, K8s 카테고리 풍부): &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/VoltAgent/awesome-claude-code-subagents&quot;&gt;https://github.com/VoltAgent/awesome-claude-code-subagents&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;185개 에이전트 + 16개 오케스트레이터: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/wshobson/agents&quot;&gt;https://github.com/wshobson/agents&lt;/a&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;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;
&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;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>IT Tool</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/516</guid>
      <comments>https://somaz.tistory.com/516#entry516comment</comments>
      <pubDate>Wed, 13 May 2026 14:12:44 +0900</pubDate>
    </item>
    <item>
      <title>EKS 프로덕션 배포 가이드: 502 에러 제로 달성기</title>
      <link>https://somaz.tistory.com/476</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&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 style=&quot;color: #000000;&quot;&gt;AWS Load Balancer Controller의 ReadinessGate 기능으로 EKS 배포 시 발생하는 모든 502 에러를 제거했다. &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;color: #000000;&quot;&gt;단 한 줄의 label 설정으로 가능하다. 온프렘 환경에서의 대안도 함께 다룬다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nVwAD/dJMcai21Lib/xywaMLcKKYkatS3ag8rx2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nVwAD/dJMcai21Lib/xywaMLcKKYkatS3ag8rx2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nVwAD/dJMcai21Lib/xywaMLcKKYkatS3ag8rx2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnVwAD%2FdJMcai21Lib%2FxywaMLcKKYkatS3ag8rx2K%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제 인식: 지표와 현실의 괴리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로덕션 환경에서 다음과 같은 상황을 경험해본 적 있으신가요?&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1763530017590&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# ArgoCD Dashboard
✅ Sync Status: Healthy
✅ Health Status: Healthy
✅ All Pods: Running (3/3)

# 동시에 Grafana Alert
  HTTP 502 Spike: 708 errors in 70 seconds
  User Impact: ~2,000 affected requests&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;근본 원인: 두 시스템의 비대칭적 타이밍&lt;/span&gt;&lt;/h3&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;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes의 관점&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# Pod 생성부터 Ready까지: 평균 12-18초
T+0s:  Pod 스케줄링
T+5s:  컨테이너 시작
T+10s: readinessProbe 통과
T+12s: Pod Status = Ready
T+12s: Endpoint 등록 완료&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&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;color: #000000;&quot;&gt;Kubernetes는 readinessProbe 성공만으로 Pod가 트래픽을 받을 준비가 됐다고 판단한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS ALB의 관점&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# Target 등록부터 Healthy까지: 최소 60초
T+0s:  Target 등록 감지
T+1s:  상태: initial
T+30s: 첫 번째 Health Check 통과
T+60s: 두 번째 Health Check 통과 
T+60s: Target Status = healthy&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&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;color: #000000;&quot;&gt;ALB는 최소 2회의 Health Check(기본 30초 간격)를 통과해야 Target을 사용한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제의 핵심&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;Kubernetes Ready (T+12s)
       &amp;darr;
    48초의 갭 
       &amp;darr;
ALB Healthy (T+60s)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&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;color: #000000;&quot;&gt;이 48초 동안 Kubernetes는 새 Pod로 트래픽을 보내지만, ALB는 아직 해당 Pod를 사용하지 않는다. '&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결과적으로 트래픽이 블랙홀에 빠진다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실패한 해결 시도들&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시도 1: terminationGracePeriodSeconds 증가&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;spec:
  terminationGracePeriodSeconds: 240&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결과&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배포 시간 4배 증가 (3분 &amp;rarr; 12분)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시작 시점 문제는 미해결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spot Instance 회수 시 여전히 에러 발생&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시도 2: Health Check 빈도 증가&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;alb.ingress.kubernetes.io/healthcheck-interval-seconds: '5'
alb.ingress.kubernetes.io/healthy-threshold-count: '2'&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결과&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;60초 &amp;rarr; 10초로 개선&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여전히 10초간 에러 발생&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;False positive 증가로 불안정&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시도 3: Replica 과다 배치&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;spec:
  replicas: 10  # 원래 3개&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결과&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 3배 증가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해결책: ReadinessGate (EKS)&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 아이디어&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 방식의 문제는 Kubernetes가 ALB의 상태를 모른다는 것이다. ReadinessGate는 이 정보를 연결한다.&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;기존: readinessProbe &amp;rarr; Pod Ready&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;개선: readinessProbe + ALB healthy &amp;rarr; Pod Ready&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동작 원리&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS Load Balancer Controller가 Pod 생성을 감지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;즉시 ALB에 Target 사전 등록&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ALB Health Check 상태를 지속 모니터링&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Health Check 통과 확인 후에야 Pod를 Ready로 마킹&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes가 이제서야 트래픽 전송 시작&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;핵심&lt;/b&gt;: &quot;사전 등록(Pre-registration)&quot;이다. Pod가 Ready가 되기 전에 이미 ALB 등록을 완료해둔다.&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;&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;
&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;color: #000000;&quot;&gt;구현&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1단계: Controller 설치 (이미 설치되어 있다면 스킵)&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dsconfig&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# IAM Policy
curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.6.0/docs/install/iam_policy.json
aws iam create-policy \
    --policy-name AWSLoadBalancerControllerIAMPolicy \
    --policy-document file://iam_policy.json

# ServiceAccount
eksctl create iamserviceaccount \
  --cluster=prod-cluster \
  --namespace=kube-system \
  --name=aws-load-balancer-controller \
  --attach-policy-arn=arn:aws:iam::123456789012:policy/AWSLoadBalancerControllerIAMPolicy \
  --approve

# Helm 설치
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=prod-cluster \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2단계: ReadinessGate 활성화&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;kubectl label namespace production \
  elbv2.k8s.aws/pod-readiness-gate-inject=enabled&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;끝이다. Mutating Webhook이 자동으로 모든 Pod에 ReadinessGate를 주입한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3단계: 검증&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 배포 후 Pod 확인
kubectl get pod -n production

NAME                    READY   STATUS    READINESS GATES
api-server-new-abc     0/1     Running   0/1        # ALB 대기 중
api-server-new-abc     1/1     Running   1/1        # 60초 후 준비 완료&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 상세 확인
kubectl describe pod api-server-new-abc


Readiness Gates:
  Type                                            Status
  target-health.alb.ingress.k8s.aws/api-service   True

Conditions:
  Type                                            Status
  ContainersReady                                 True
  target-health.alb.ingress.k8s.aws/api-service   True
  Ready                                           True&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;온프렘 환경에서의 대안&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS Load Balancer Controller는 AWS 전용이지만, &lt;b&gt;ReadinessGate 자체는 Kubernetes 표준 기능&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;옵션 1: Service Mesh (가장 권장)&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Istio나 Linkerd는 자동으로 트래픽 관리를 최적화한다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Istio DestinationRule로 자동 Circuit Breaking
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: api-service
spec:
  host: api-service
  trafficPolicy:
    connectionPool:
      http:
        http1MaxPendingRequests: 1
        maxRequestsPerConnection: 1
    outlierDetection:
      consecutiveErrors: 2
      interval: 10s
      baseEjectionTime: 30s
      maxEjectionPercent: 100
      minHealthPercent: 0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동으로 비정상 Pod 제외&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Progressive Traffic Shifting&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Connection Draining 자동 처리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;별도 ReadinessGate 불필요&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;옵션 2: 실용적 조합 (Service Mesh 없이)&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ReadinessGate 없이도 충분히 안정적인 배포가 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
spec:
  replicas: 3
  
  # 1. Pod Ready 후 추가 대기
  minReadySeconds: 30
  
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  
  template:
    spec:
      containers:
      - name: app
        image: api-server:v2
        
        # 2. 빠른 readiness 체크
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 3
          successThreshold: 1
          failureThreshold: 2
        
        # 3. 종료 시 대기 시간 확보
        lifecycle:
          preStop:
            exec:
              command: [&quot;/bin/sh&quot;, &quot;-c&quot;, &quot;sleep 20&quot;]
      
      terminationGracePeriodSeconds: 45&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;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;color: #000000;&quot;&gt;&lt;b&gt;핵심 설정 설명&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&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;color: #000000;&quot;&gt;&lt;b&gt;minReadySeconds: 30&lt;/b&gt;&lt;/span&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;color: #000000;&quot;&gt;Pod가 Ready 된 후 30초 추가 대기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부 LB가 헬스체크 할 시간 확보&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&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;color: #000000;&quot;&gt;&lt;b&gt;preStop sleep 20&lt;/b&gt;&lt;/span&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;color: #000000;&quot;&gt;SIGTERM 전송 후 20초 대기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부 LB가 연결을 끊을 시간 제공&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&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;color: #000000;&quot;&gt;&lt;b&gt;maxUnavailable: 0&lt;/b&gt;&lt;/span&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;color: #000000;&quot;&gt;항상 최소 replica 수 유지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트래픽 처리 가능한 Pod 보장&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;옵션 3: NGINX Ingress 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# NGINX ConfigMap 최적화
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-configuration
  namespace: ingress-nginx
data:
  # 연결 재사용
  upstream-keepalive-connections: &quot;100&quot;
  upstream-keepalive-timeout: &quot;60&quot;
  
  # 비정상 백엔드 빠른 제거
  upstream-fail-timeout: &quot;5s&quot;
  upstream-max-fails: &quot;2&quot;
  
  # 헬스체크 간격
  upstream-check-interval: &quot;5s&quot;
  upstream-check-timeout: &quot;3s&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Ingress 설정
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress
  annotations:
    nginx.ingress.kubernetes.io/upstream-hash-by: &quot;$binary_remote_addr&quot;
    nginx.ingress.kubernetes.io/load-balance: &quot;ewma&quot;
spec:
  ingressClassName: nginx
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 80&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;옵션 4: HAProxy 헬스체크 조정&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;온프렘에서 HAProxy를 사용한다면&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# /etc/haproxy/haproxy.cfg
backend k8s_api_backend
    balance roundrobin
    option httpchk GET /health
    http-check expect status 200
    
    # 빠른 헬스체크
    default-server inter 3s fall 2 rise 2 check
    
    # Graceful Shutdown 지원
    default-server on-marked-down shutdown-sessions
    
    server pod1 10.0.1.10:8080 check
    server pod2 10.0.1.11:8080 check
    server pod3 10.0.1.12:8080 check&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;옵션 5: Custom ReadinessGate Controller (고급)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완벽한 동기화가 필요하다면 Custom Controller를 개발할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Pod에 ReadinessGate 추가
apiVersion: v1
kind: Pod
metadata:
  name: api-server
spec:
  readinessGates:
  - conditionType: &quot;custom-lb.example.com/healthy&quot;
  
  containers:
  - name: app
    image: api-server:v2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;go&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;// Custom Controller 예시 (의사코드)
func reconcilePod(pod *v1.Pod) {
    // 1. 외부 LB 상태 확인 (HAProxy/F5/등)
    lbHealthy := checkExternalLBHealth(pod.Status.PodIP)
    
    // 2. ReadinessGate 조건 업데이트
    if lbHealthy {
        updatePodCondition(pod, 
            &quot;custom-lb.example.com/healthy&quot;, 
            v1.ConditionTrue)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;color: #000000;&quot;&gt;온프렘 환경별 권장 사항&lt;/span&gt;&lt;/h3&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;환경&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;권장 방법&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;효과&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡도&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Istio/Linkerd 있음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Service Mesh 활용&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;95%&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쉬움&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NGINX Ingress&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;옵션2 + NGINX 최적화&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;90%&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;보통&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HAProxy 전용&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;옵션2 + HAProxy 설정&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;85%&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;보통&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완벽 추구&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Custom Controller&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;100%&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;어려움&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;빠른 적용&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;옵션2만 적용&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;80%&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;쉬움&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;종료 프로세스 최적화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시작 과정은 해결했지만, Pod 종료 시에도 502가 발생할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;preStop Hook 추가&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;lifecycle:
  preStop:
    exec:
      command: [&quot;/bin/sh&quot;, &quot;-c&quot;, &quot;sleep 18&quot;]

terminationGracePeriodSeconds: 45&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;타이밍 계산&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;T+0s:&amp;nbsp;&amp;nbsp;SIGTERM 발송 + preStop 실행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;T+0s:&amp;nbsp;&amp;nbsp;Endpoint에서 제거&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;T+2s:&amp;nbsp;&amp;nbsp;ALB Controller 감지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;T+3s:&amp;nbsp;&amp;nbsp;ALB Target Draining 시작&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;T+18s: preStop 완료, 애플리케이션 종료 시작&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;T+43s: 애플리케이션 종료 완료&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;T+45s:&amp;nbsp;Pod&amp;nbsp;완전&amp;nbsp;제거&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;18초의 preStop이 ALB가 안전하게 연결을 끊을 시간을 제공한다.&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중요: terminationGracePeriodSeconds 계산&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;preStop sleep 시간&lt;/b&gt;과 &lt;b&gt;애플리케이션 종료 시간&lt;/b&gt;을 합친 값이 terminationGracePeriodSeconds보다 &lt;b&gt;반드시 작아야&lt;/b&gt;&amp;nbsp;한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그렇지 않으면 Kubernetes가 SIGKILL로 프로세스를 강제 종료한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 올바른 설정
lifecycle:
  preStop:
    exec:
      command: [&quot;/bin/sh&quot;, &quot;-c&quot;, &quot;sleep 18&quot;]
terminationGracePeriodSeconds: 45&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;계산&lt;/b&gt;&lt;/span&gt;&lt;/div&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;color: #000000;&quot;&gt;preStop: 18초 &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;+ 애플리케이션 graceful shutdown: 20초 &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;+ 버퍼: 7초 &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;= 총 45초&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 잘못된 설정
lifecycle:
  preStop:
    exec:
      command: [&quot;/bin/sh&quot;, &quot;-c&quot;, &quot;sleep 35&quot;]
terminationGracePeriodSeconds: 45&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;계산&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;preStop: 35초&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;+ 애플리케이션 graceful shutdown: 15초&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;= 총 50초&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;rarr; terminationGracePeriodSeconds(45초) 초과!&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;rarr; SIGKILL로 강제 종료됨&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;권장 설정 가이드&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;애플리케이션 종료 예상 시간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;preStop sleep&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;terminationGracePeriodSeconds&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~10초 (대부분의 웹 앱)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;15-20초&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;45초&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~20초 (DB 연결 많음)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;15초&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;60초&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~30초 (배치 작업 있음)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;15초&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;75초&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~60초 (긴 요청 처리)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;20초&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;120초&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;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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;애플리케이션 종료 시간 측정 방법&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 1. 로컬에서 측정
time kubectl exec &amp;lt;pod-name&amp;gt; -- kill -TERM 1

# 2. 로그로 확인
kubectl logs &amp;lt;pod-name&amp;gt; | grep -i &quot;shutdown&quot;
# [2024-11-19 10:23:45] Starting graceful shutdown...
# [2024-11-19 10:24:02] Shutdown complete (17s)

# 3. Prometheus로 모니터링
histogram_quantile(0.95, 
  rate(app_shutdown_duration_seconds_bucket[5m])
)&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Deregistration Delay 조정&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;metadata:
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-target-group-attributes: |
      deregistration_delay.timeout_seconds=25&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;기본값 300초는 과도하다. 대부분의 HTTP 요청은 몇 초 내에 완료되므로 25초면 충분하다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;온프렘 환경: HAProxy의 경우 `server-state-file-name` 을 활용하여 Graceful Shutdown을 구현할 수 있다.&lt;/span&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;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성과 측정&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배포 전 (2주간 28회 배포)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;502 에러 발생률: 100% (28/28)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배포당 평균 에러 수: 700건&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;평균 영향 시간: 68초&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자 문의: 17건&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;긴급&amp;nbsp;대응:&amp;nbsp;4회&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배포 후 (2주간 34회 배포)&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;502 에러 발생률: 0% (0/34)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배포당 평균 에러 수: 0건&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;평균 영향 시간: 0초&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자 문의: 0건&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;긴급&amp;nbsp;대응:&amp;nbsp;0회&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;Trade-off: Pod Ready 시간 +55초&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 55초는 사용자 신뢰와 비교하면 저렴한 비용이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;온프렘 성과 (minReadySeconds + preStop 조합)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;502 에러 발생률: 5% (2/34) - 95% 개선&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배포당 평균 에러 수: 12건 - 98% 감소&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;평균&amp;nbsp;영향&amp;nbsp;시간:&amp;nbsp;3초&amp;nbsp;-&amp;nbsp;96%&amp;nbsp;단축&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;모니터링 설정&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Prometheus Alert&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;- alert: PodReadinessGateStuck
  expr: |
    (time() - kube_pod_created{namespace=&quot;production&quot;}) &amp;gt; 180
    and kube_pod_status_ready{condition=&quot;false&quot;} == 1
    and kube_pod_status_phase{phase=&quot;Running&quot;} == 1
  for: 1m
  annotations:
    summary: &quot;Pod stuck waiting for ALB&quot;

# 온프렘용 추가 알림
- alert: SlowPodReadiness
  expr: |
    (time() - kube_pod_created{namespace=&quot;production&quot;}) &amp;gt; 60
    and kube_pod_status_ready{condition=&quot;false&quot;} == 1
  for: 30s
  annotations:
    summary: &quot;Pod taking longer than expected to be ready&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Grafana Dashboard&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;json&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;{
  &quot;panels&quot;: [{
    &quot;title&quot;: &quot;Pod Readiness vs ALB Health&quot;,
    &quot;targets&quot;: [{
      &quot;expr&quot;: &quot;kube_pod_status_ready{condition='true'}&quot;
    }, {
      &quot;expr&quot;: &quot;aws_alb_target_health_count{state='healthy'}&quot;
    }]
  }, {
    &quot;title&quot;: &quot;Deployment Error Rate&quot;,
    &quot;targets&quot;: [{
      &quot;expr&quot;: &quot;rate(http_requests_total{status=~'5..'}[1m])&quot;
    }]
  }]
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;color: #000000;&quot;&gt;주의사항&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. Target Type 확인 (EKS)&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 반드시 IP 모드여야 함
kubectl get ingress -o yaml | grep target-type
# alb.ingress.kubernetes.io/target-type: ip&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;Instance 모드에서는 ReadinessGate가 작동하지 않는다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. HPA 고려&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ReadinessGate로 인해 스케일 아웃이 느려질 수 있다. Replica를 여유있게 설정해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;spec:
  minReplicas: 3  # 최소값을 높게
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        averageUtilization: 50  # 여유있게&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;온프렘: minReadySeconds를 사용하는 경우도 동일하게 적용된다. HPA가 너무 공격적이면 배포가 느려질 수 있다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. Controller 가용성 (EKS)&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Webhook failure policy
podMutatorWebhookConfig:
  failurePolicy: Ignore  # Controller 장애 시에도 배포 진행&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 온프렘 특수 고려사항&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;Long-lived 연결&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;WebSocket이나 gRPC 같은 긴 연결이 있다면 preStop 시간을 늘려야 한다. (20초 &amp;rarr; 40초)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;중요&lt;/b&gt;: terminationGracePeriodSeconds도 함께 늘려야 한다 (45초 &amp;rarr; 90초)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Sticky Session&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Session affinity가 필요하면 LB 설정 확인 필수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NGINX: nginx.ingress.kubernetes.io/affinity: &quot;cookie&quot;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;External LB 헬스체크&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;F5, NetScaler 등 외부 LB는 헬스체크 간격이 더 길 수 있음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;minReadySeconds를 그에 맞게 조정 (30초 &amp;rarr; 60초)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. terminationGracePeriodSeconds 계산 실수 방지&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;흔한 실수들&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 실수 1: preStop이 너무 김
lifecycle:
  preStop:
    exec:
      command: [&quot;sleep&quot;, &quot;40&quot;]
terminationGracePeriodSeconds: 45
# &amp;rarr; 애플리케이션 종료 시간이 5초밖에 없음!



# 실수 2: 애플리케이션 종료가 느린데 시간 부족
lifecycle:
  preStop:
    exec:
      command: [&quot;sleep&quot;, &quot;15&quot;]
terminationGracePeriodSeconds: 30
# &amp;rarr; DB 연결 종료에 20초 걸리는 앱은 강제 종료됨!



# 올바른 설정: 충분한 버퍼
lifecycle:
  preStop:
    exec:
      command: [&quot;sleep&quot;, &quot;15&quot;]
terminationGracePeriodSeconds: 60
# &amp;rarr; preStop(15초) + 앱종료(30초) + 버퍼(15초) = 60초&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;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;color: #000000;&quot;&gt;&lt;b&gt;안전한 계산 공식&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;terminationGracePeriodSeconds =&amp;nbsp; preStop sleep 시간 + 애플리케이션 최대 종료 시간 + 안전 버퍼(10-20초)&lt;/span&gt;&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;&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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트러블슈팅&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Pod가 Ready 안될 때 (EKS)&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 1. ALB Target 상태 확인
POD_IP=$(kubectl get pod &amp;lt;pod-name&amp;gt; -o jsonpath='{.status.podIP}')
aws elbv2 describe-target-health \
  --target-group-arn &amp;lt;arn&amp;gt; \
  --targets Id=${POD_IP}

# 2. Controller 로그 확인
kubectl logs -n kube-system \
  -l app.kubernetes.io/name=aws-load-balancer-controller \
  | grep readiness-gate

# 3. Security Group 확인
# ALB SG &amp;rarr; Pod SG 트래픽 허용 확인&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Pod가 Ready 안될 때 (온프렘)&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 1. readinessProbe 로그 확인
kubectl logs &amp;lt;pod-name&amp;gt; | grep -i health

# 2. 수동 헬스체크
kubectl exec &amp;lt;pod-name&amp;gt; -- curl -f http://localhost:8080/health

# 3. minReadySeconds 대기 중인지 확인
kubectl get pod &amp;lt;pod-name&amp;gt; -o yaml | grep -A5 &quot;conditions:&quot;

# 4. 외부 LB 헬스체크 확인 (HAProxy)
echo &quot;show stat&quot; | socat stdio /var/run/haproxy.sock | grep &amp;lt;pod-ip&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Pod가 강제 종료되는 경우&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 1. 종료 시간 확인
kubectl logs &amp;lt;pod-name&amp;gt; --previous | tail -50
# &quot;signal: killed&quot; 메시지가 있다면 SIGKILL로 강제 종료된 것

# 2. 이벤트 확인
kubectl get events --field-selector involvedObject.name=&amp;lt;pod-name&amp;gt;
# &quot;Killing container&quot; 메시지 확인

# 3. preStop 실행 시간 측정
kubectl logs &amp;lt;pod-name&amp;gt; --previous | grep -i &quot;prestop\|shutdown&quot;
# preStop 시작과 종료 시간 차이 확인

# 4. terminationGracePeriodSeconds 확인
kubectl get pod &amp;lt;pod-name&amp;gt; -o yaml | grep terminationGracePeriodSeconds&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;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;color: #000000;&quot;&gt;&lt;b&gt;해결 방법&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# terminationGracePeriodSeconds를 충분히 늘리기
spec:
  terminationGracePeriodSeconds: 90  # 45초 &amp;rarr; 90초로 증가
  template:
    spec:
      containers:
      - lifecycle:
          preStop:
            exec:
              command: [&quot;sleep&quot;, &quot;20&quot;]  # 기존 유지&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여전히 502 발생 시 (공통)&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 배포 중 실시간 모니터링
watch -n 1 'kubectl get pods -l app=api-server -o wide'

# Endpoint 변경 추적
kubectl get endpoints api-service --watch

# 에러 로그 실시간 확인
kubectl logs -f -l app=api-server --all-containers&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;결론&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EKS 환경&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;kubectl label namespace &amp;lt;your-namespace&amp;gt; \
  elbv2.k8s.aws/pod-readiness-gate-inject=enabled&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;온프렘 환경&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ReadinessGate 자동화가 없어도 충분히 안정적인 배포가 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;온프렘 vs EKS 비교&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EKS (ReadinessGate)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;온프렘 (최적화)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;502 에러 제거율&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;100%&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;90-95%&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구현 복잡도&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;매우 쉬움&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쉬움&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추가 배포 시간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;+55초&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;+30초&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;유지보수&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;
&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;
&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubernetes-sigs.github.io/aws-load-balancer-controller/&quot;&gt;AWS Load Balancer Controller Docs&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-readiness-gate&quot;&gt;Kubernetes Pod Readiness Gates&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination&quot;&gt;Kubernetes Pod Termination&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://istio.io/latest/docs/concepts/traffic-management/&quot;&gt;Istio Traffic Management&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubernetes.github.io/ingress-nginx/&quot;&gt;NGINX Ingress Controller&lt;/a&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;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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>Container Orchestration/Kubernetes</category>
      <category>EKS #Kubernetes #AWS #ReadinessGate #DevOps #무중단배포 #온프렘 #Istio #NGINX #GracefulShutdown</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/476</guid>
      <comments>https://somaz.tistory.com/476#entry476comment</comments>
      <pubDate>Tue, 12 May 2026 00:00:44 +0900</pubDate>
    </item>
    <item>
      <title>tcpdump로 네트워크 문제 진단하기: SSH 연결 지연 해결 실전 가이드</title>
      <link>https://somaz.tistory.com/473</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최근 GitHub SSH 연결이 비정상적으로 느린 문제를 겪었다. git pull을 실행하면 30초 이상 기다려야 하는 상황이었죠. &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;color: #000000;&quot;&gt;&quot;네트워크가 느린가?&quot; 하고 넘어갈 수도 있었지만, &lt;b&gt;tcpdump&lt;/b&gt;를 사용해 정확한 원인을 찾아냈다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 글에서는 tcpdump의 기본 사용법부터 실전 문제 해결 사례까지 다룬다.&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;&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;2226&quot; data-origin-height=&quot;2162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQhV7f/dJMb9LjIvp1/nXHx137wCgE0Mpya0n8yBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQhV7f/dJMb9LjIvp1/nXHx137wCgE0Mpya0n8yBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQhV7f/dJMb9LjIvp1/nXHx137wCgE0Mpya0n8yBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQhV7f%2FdJMb9LjIvp1%2FnXHx137wCgE0Mpya0n8yBk%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;2226&quot; height=&quot;2162&quot; data-origin-width=&quot;2226&quot; data-origin-height=&quot;2162&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;tcpdump란?&lt;/span&gt;&lt;/h3&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;color: #000000;&quot;&gt;tcpdump는 네트워크 인터페이스를 통과하는 패킷을 실시간으로 캡처하고 분석하는 커맨드라인 도구이다. 네트워크 문제 진단, 보안 분석, 성능 최적화의 필수 도구이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;왜 tcpdump를 사용해야 할까?&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;정확한 진단&lt;/b&gt;: 추측이 아닌 실제 패킷 데이터로 문제 파악&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실시간 모니터링&lt;/b&gt;: 문제 발생 시점의 트래픽 즉시 확인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;가벼움&lt;/b&gt;: GUI 없이 서버에서도 사용 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;표준 도구&lt;/b&gt;: 대부분의 Unix/Linux 시스템에 기본 설치&lt;/span&gt;&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;&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;color: #000000;&quot;&gt;기본 사용법&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 기본 명령어&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1761527272806&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 모든 인터페이스의 패킷 캡처 (root 권한 필요)
sudo tcpdump -i any

# 특정 인터페이스만 캡처
sudo tcpdump -i en0

# 캡처 개수 제한
sudo tcpdump -i any -c 10

# 중단: Ctrl+C&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 필터링&lt;/span&gt;&lt;/h4&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;호스트 필터링&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 특정 호스트
sudo tcpdump host github.com

# 특정 IP
sudo tcpdump host 20.200.245.247

# 송신만
sudo tcpdump src host 192.168.1.100

# 수신만
sudo tcpdump dst host 192.168.1.100&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;포트 필터링&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 특정 포트
sudo tcpdump port 22
sudo tcpdump port 80

# 포트 범위
sudo tcpdump portrange 8000-9000

# 송신 포트
sudo tcpdump src port 443&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로토콜 필터링&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;sudo tcpdump tcp
sudo tcpdump udp
sudo tcpdump icmp&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;조합 필터 (BPF - Berkeley Packet Filter)&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# AND 조건
sudo tcpdump host github.com and port 22

# OR 조건
sudo tcpdump port 80 or port 443

# NOT (제외)
sudo tcpdump not host 192.168.1.1

# 복합 조건
sudo tcpdump 'host github.com and (port 22 or port 443)'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 출력 옵션&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# verbose 모드 (더 자세한 정보)
sudo tcpdump -v
sudo tcpdump -vv
sudo tcpdump -vvv  # 최대 상세도

# 패킷 내용 출력
sudo tcpdump -X  # HEX + ASCII
sudo tcpdump -A  # ASCII만

# 타임스탬프 형식
sudo tcpdump -tttt  # 읽기 쉬운 형식

# 출력 라인 버퍼링 해제 (실시간 확인)
sudo tcpdump -l&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 파일 저장 및 읽기&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 파일로 저장 (pcap 형식)
sudo tcpdump -w capture.pcap

# 파일에서 읽기
tcpdump -r capture.pcap

# 필터링하며 저장
sudo tcpdump -w ssh-traffic.pcap host github.com and port 22

# 파일 크기 제한 (100MB마다 새 파일)
sudo tcpdump -w capture.pcap -C 100

# 파일 개수 제한 (5개만 유지, 순환)
sudo tcpdump -w capture.pcap -C 100 -W 5&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실전 활용 사례&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사례 1: SSH 연결 지연 문제 진단&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;문제&lt;/b&gt;: GitHub SSH 연결이 30초 이상 소요&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;&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 1: 문제 재현하며 패킷 캡처&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 터미널 1: tcpdump 실행
sudo tcpdump -i any host github.com and port 22

# 터미널 2: SSH 연결 시도
ssh -T git@github.com&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 2: 패킷 분석&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;캡처된 로그&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;18:48:28.709 IP 10.10.11.3.56034 &amp;gt; 20.200.245.247.ssh: Flags [S], seq 2418154065
18:48:28.709 IP 10.10.11.3.56034 &amp;gt; 20.200.245.247.ssh: SSH: SSH-2.0-OpenSSH_9.7
18:48:58.672 IP 20.200.245.247.ssh &amp;gt; 10.10.11.3.56034: SSH: SSH-2.0-85ba476&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;분석 결과&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;18:48:28 - SSH 버전 교환 시작&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;18:48:58 - GitHub 서버 응답 (30초 지연!)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TCP 연결은 정상, &lt;b&gt;SSH 키 교환 단계에서 지연&lt;/b&gt; 발생&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 3: 해결&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SSH config 최적화 또는 HTTPS로 전환&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dsconfig&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 방법 1: SSH config 최적화
vi ~/.ssh/config
# KexAlgorithms curve25519-sha256 추가

# 방법 2: HTTPS로 전환 (즉시 해결)
git remote set-url origin https://github.com/user/repo.git&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;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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사례 2: 특정 서비스 연결 확인&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 웹 서버 연결 확인
sudo tcpdump -i any 'host example.com and (port 80 or port 443)'

# DNS 쿼리 확인
sudo tcpdump -i any port 53

# 데이터베이스 연결 확인
sudo tcpdump host db-server and port 3306&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사례 3: TCP 3-way Handshake 확인&lt;/span&gt;&lt;/h4&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;연결 수립 과정 모니터링&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;coq&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;sudo tcpdump -i any 'tcp[tcpflags] &amp;amp; (tcp-syn|tcp-ack|tcp-fin) != 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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정상 연결&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;SYN    &amp;rarr; 클라이언트가 연결 요청
SYN-ACK &amp;rarr; 서버가 수락
ACK    &amp;rarr; 클라이언트가 확인&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사례 4: 느린 네트워크 구간 찾기&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 특정 호스트와의 모든 트래픽 캡처 (타임스탬프 포함)
sudo tcpdump -tttt -i any host api.example.com

# 응답 시간 측정
# SYN 전송 시각과 SYN-ACK 수신 시각 차이 확인&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;color: #000000;&quot;&gt;고급 활용 팁&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. TCP 플래그 필터링&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# SYN 패킷만
sudo tcpdump 'tcp[tcpflags] &amp;amp; tcp-syn != 0'

# RST (연결 거부) 패킷
sudo tcpdump 'tcp[tcpflags] &amp;amp; tcp-rst != 0'

# FIN (연결 종료) 패킷
sudo tcpdump 'tcp[tcpflags] &amp;amp; tcp-fin != 0'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 패킷 크기 필터&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 큰 패킷만 (1000바이트 이상)
sudo tcpdump 'ip[2:2] &amp;gt; 1000'

# 작은 패킷만
sudo tcpdump 'ip[2:2] &amp;lt; 100'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 네트워크 대역 필터&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 특정 서브넷
sudo tcpdump net 192.168.1.0/24

# 서브넷 제외
sudo tcpdump not net 10.0.0.0/8&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 실시간 분석과 파일 저장 동시에&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;glsl&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# tee를 활용한 동시 출력
sudo tcpdump -i any -l host github.com | tee capture.log&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트러블슈팅 체크리스트&lt;/span&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;span style=&quot;color: #000000;&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;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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1단계: 연결 확인&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 패킷이 전송되는가?
sudo tcpdump -c 10 host TARGET_HOST&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2단계: 프로토콜 확인&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;glsl&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 어떤 프로토콜을 사용하는가?
sudo tcpdump -i any host TARGET_HOST&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3단계: 응답 시간 측정&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# SYN &amp;rarr; SYN-ACK 시간 차이 확인
sudo tcpdump -tttt host TARGET_HOST and port TARGET_PORT&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4단계: 에러 패킷 확인&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# RST, FIN 등 비정상 종료 패킷
sudo tcpdump 'tcp[tcpflags] &amp;amp; (tcp-rst|tcp-fin) != 0'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5단계: 패킷 내용 분석&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 실제 데이터 확인
sudo tcpdump -X -s 0 host TARGET_HOST&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;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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;tcpdump vs Wireshark&lt;/span&gt;&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특징&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;tcpdump&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Wireshark&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인터페이스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CLI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GUI&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용 환경&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서버, 원격&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데스크톱&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실시간 분석&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;상세 분석&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리소스 사용&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;조합 사용&lt;/b&gt;: tcpdump로 캡처 &amp;rarr; Wireshark로 상세 분석&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# tcpdump로 캡처
sudo tcpdump -w capture.pcap

# Wireshark로 열기
wireshark capture.pcap&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;color: #000000;&quot;&gt;주의사항&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 권한&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;tcpdump는 root 권한이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# sudoers 설정으로 특정 사용자 허용 가능
sudo visudo
# username ALL=(ALL) NOPASSWD: /usr/sbin/tcpdump&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 개인정보 보호&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;캡처된 패킷에는 민감한 정보가 포함될 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;평문 비밀번호 (HTTP, FTP 등)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쿠키, 세션 토큰&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API 키&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;암호화되지 않은 프로토콜 사용 시 주의!&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 성능 영향&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로덕션 환경에서는&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;필터를 정확히 지정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;불필요한 패킷 캡처 최소화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&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;color: #000000;&quot;&gt;자주 사용하는 명령어 모음&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 1. HTTP 트래픽 모니터링
sudo tcpdump -i any -A 'tcp port 80'

# 2. HTTPS 핸드셰이크 확인
sudo tcpdump -i any 'tcp port 443 and (tcp[tcpflags] &amp;amp; tcp-syn != 0)'

# 3. DNS 쿼리 디버깅
sudo tcpdump -i any -vvv port 53

# 4. 특정 IP 간 모든 트래픽
sudo tcpdump host 192.168.1.100 and host 192.168.1.200

# 5. 브로드캐스트/멀티캐스트 패킷
sudo tcpdump ether broadcast or ether multicast

# 6. ARP 패킷
sudo tcpdump arp

# 7. IPv6 트래픽
sudo tcpdump ip6

# 8. ICMP (ping) 패킷
sudo tcpdump icmp

# 9. 비정상 연결 종료 모니터링
sudo tcpdump 'tcp[tcpflags] &amp;amp; tcp-rst != 0'

# 10. 재전송 패킷 확인 (간접적)
sudo tcpdump -tttt 'tcp[tcpflags] &amp;amp; tcp-push != 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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결론&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;tcpdump는 네트워크 문제를 추측이 아닌 &lt;b&gt;데이터&lt;/b&gt;로 진단할 수 있게 해주는 강력한 도구이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 글에서 다룬 SSH 연결 지연 문제도 tcpdump 없이는 &quot;네트워크가 느리다&quot;는 막연한 추측에 그쳤을 것이다. 하지만 tcpdump로 정확히 &lt;b&gt;SSH 키 교환 단계&lt;/b&gt;에서 30초 지연이 발생한다는 것을 확인하고, 근본 원인을 해결할 수 있었다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 요약&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;필터링이 핵심&lt;/b&gt; - 정확한 필터로 원하는 트래픽만 캡처&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;타임스탬프 활용&lt;/b&gt; - 지연 구간을 정확히 측정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;플래그 분석&lt;/b&gt; - SYN, ACK, RST 등으로 연결 상태 파악&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;파일 저장&lt;/b&gt; - 나중에 상세 분석 가능&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 문제가 발생하면, 일단 &lt;b&gt;tcpdump부터 실행&lt;/b&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;&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.tcpdump.org/manpages/tcpdump.1.html&quot;&gt;tcpdump 공식 문서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://biot.com/capstats/bpf.html&quot;&gt;Berkeley Packet Filter (BPF) 문법&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.wireshark.org/docs/dfref/&quot;&gt;Wireshark Display Filter Reference&lt;/a&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;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;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt;&lt;/p&gt;</description>
      <category>Network</category>
      <category>Network</category>
      <category>ssh</category>
      <category>tcpdump</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/473</guid>
      <comments>https://somaz.tistory.com/473#entry473comment</comments>
      <pubDate>Tue, 5 May 2026 00:00:43 +0900</pubDate>
    </item>
    <item>
      <title>Kubernetes 스토리지 타입 완벽 가이드: iSCSI, NFS...</title>
      <link>https://somaz.tistory.com/466</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes에서 퍼시스턴트 스토리지(Persistent Storage)를 구성할 때 가장 먼저 마주하는 질문은 &lt;b&gt;&quot;어떤 스토리지 타입을 선택해야 할까?&quot;&lt;/b&gt; 이다. NFS는 간단하지만 성능이 걱정되고, iSCSI는 빠르다지만 설정이 복잡해 보인다. 클라우드 환경이라면 또 다른 선택지들이 있다.&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;color: #000000;&quot;&gt;이 글에서는 Kubernetes 환경에서 사용되는 주요 스토리지 타입들의 특징과 장단점을 비교하고, 상황에 맞는 최적의 선택을 할 수 있도록 가이드를 제공한다. 실무 경험을 바탕으로 각 스토리지 타입이 어떤 워크로드에 적합한지 구체적인 사례와 함께 살펴보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k0TO6/dJMcac9AmOw/ICIrlvhnTb3rFDL0T2QCK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k0TO6/dJMcac9AmOw/ICIrlvhnTb3rFDL0T2QCK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k0TO6/dJMcac9AmOw/ICIrlvhnTb3rFDL0T2QCK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk0TO6%2FdJMcac9AmOw%2FICIrlvhnTb3rFDL0T2QCK1%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;1. 스토리지 타입의 기본 개념&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;블록 스토리지 (Block Storage) vs 파일 스토리지 (File Storage)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;블록 스토리지&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터를 고정 크기의 블록으로 나누어 저장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OS가 직접 파일 시스템을 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮은 레이턴시와 높은 IOPS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예: iSCSI, Ceph RBD, AWS EBS&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;파일 스토리지&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파일과 디렉토리 구조로 데이터 저장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크를 통해 파일 시스템 공유&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 클라이언트가 동시 접근 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예: NFS, SMB/CIFS&lt;/span&gt;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. NFS (Network File System)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특징&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NFS는 1984년 Sun Microsystems가 개발한 분산 파일 시스템 프로토콜이다. 네트워크를 통해 원격 파일 시스템을 로컬처럼 마운트할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1760320821196&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# NFS PV 예시
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity:
    storage: 100Gi
  accessModes:
    - ReadWriteMany  # 여러 Pod 동시 접근
  nfs:
    server: 192.168.1.100
    path: /data/k8s
  mountOptions:
    - nfsvers=4.1
    - hard
    - timeo=600&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장점&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;간단한 설정&lt;/b&gt;: 별도의 클라이언트 소프트웨어 설치 불필요&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ReadWriteMany 지원&lt;/b&gt;: 여러 Pod가 동시에 읽기/쓰기 가능&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;낮은 진입 장벽&lt;/b&gt;: 대부분의 NAS가 기본 지원&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;운영 편의성&lt;/b&gt;: 파일 시스템 레벨에서 직접 관리 가능&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단점&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;낮은 성능&lt;/b&gt;: 네트워크 오버헤드로 인한 레이턴시&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;단일 장애점&lt;/b&gt;: NFS 서버가 다운되면 모든 클라이언트 영향&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;제한적인 IOPS&lt;/b&gt;: 동시 접속이 많으면 성능 저하&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;파일 락 이슈&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;적합한 사용 사례&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;공유 설정 파일&lt;/b&gt;: ConfigMap 대체용 대용량 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;정적 컨텐츠&lt;/b&gt;: 이미지, CSS, JS 등 웹 에셋&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;로그 수집&lt;/b&gt;: 여러 Pod의 로그를 중앙 집중화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ML 데이터셋&lt;/b&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실무 팁&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1760320885379&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# NFS 성능 최적화 옵션
mountOptions:
  - nfsvers=4.1          # NFSv4.1 사용 (성능 향상)
  - hard                 # 서버 장애 시 재시도 (soft는 데이터 손실 위험)
  - timeo=600            # 타임아웃 60초
  - retrans=2            # 재전송 횟수
  - rsize=1048576        # 읽기 버퍼 1MB
  - wsize=1048576        # 쓰기 버퍼 1MB
  - tcp                  # TCP 사용 (UDP보다 안정적)
  - noatime              # 액세스 타임 업데이트 비활성화 (성능 향상)&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&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;color: #000000;&quot;&gt;3. iSCSI (Internet Small Computer System Interface)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특징&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;iSCSI는 IP 네트워크를 통해 SCSI 명령을 전송하는 블록 레벨 스토리지 프로토콜이다. SAN(Storage Area Network)의 저렴한 대안으로 널리 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1760325886473&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# iSCSI PV 예시 (Synology CSI 사용)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-pvc
spec:
  accessModes:
    - ReadWriteOnce  # 단일 노드만 접근
  storageClassName: synology-iscsi
  resources:
    requests:
      storage: 50Gi&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장점&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;높은 성능&lt;/b&gt;: 블록 레벨 접근으로 낮은 레이턴시&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;높은 IOPS&lt;/b&gt;: 데이터베이스 워크로드에 적합&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;동적 프로비저닝&lt;/b&gt;: CSI 드라이버로 자동 볼륨 생성&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스냅샷 지원&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단점&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;복잡한 설정&lt;/b&gt;: initiator 설치 및 설정 필요&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ReadWriteOnce만 지원&lt;/b&gt;: 한 노드만 마운트 가능&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;네트워크 의존성&lt;/b&gt;: 네트워크 품질에 성능 영향&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;멀티패스 설정 복잡&lt;/b&gt;: HA 구성 시 추가 작업 필요&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;적합한 사용 사례&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;데이터베이스&lt;/b&gt;: PostgreSQL, MySQL, MongoDB&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고성능 워크로드&lt;/b&gt;: Elasticsearch, Redis&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;단일 인스턴스 애플리케이션&lt;/b&gt;: 상태 저장 앱&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;가상 머신 이미지&lt;/b&gt;: KubeVirt 등에서 사용&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실무 팁&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1760325944797&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 노드에 iSCSI initiator 설치 필요
# Ubuntu/Debian
apt-get install open-iscsi

# RHEL/CentOS
yum install iscsi-initiator-utils

# initiator name 확인
cat /etc/iscsi/initiatorname.iscsi

# iSCSI 서비스 시작
systemctl enable --now iscsid
systemctl enable --now open-iscsi&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;iSCSI가 ReadWriteOnce만 지원하는 기술적 이유&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;iSCSI는 왜 여러 노드에서 동시 마운트가 불가능할까요? 이는&amp;nbsp;&lt;b&gt;블록 디바이스의 근본적인 특성&lt;/b&gt;&amp;nbsp;때문이다.&lt;/span&gt;&lt;/p&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1. 파일 시스템 메타데이터 충돌&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1760327093942&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;┌─────────────┐         ┌─────────────┐
│   Node 1    │         │   Node 2    │
│             │         │             │
│  ext4 FS    │         │  ext4 FS    │
└──────┬──────┘         └──────┬──────┘
       │                       │
       └───────┐       ┐───────┘
               │       │
         ┌─────▼───────▼─────┐
         │   iSCSI Volume    │
         │   (블록 디바이스)   │
         └───────────────────┘&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;문제 상황&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Node 1이 파일을 생성하면 파일 시스템 메타데이터(inode, 블록 할당 테이블) 업데이트&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Node 2는 이 변경사항을 모르고 동일한 블록에 쓰기 시도&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결과: 파일 시스템 손상&lt;/b&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;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;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2. 캐시 일관성 문제&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일반 파일 시스템(ext4, xfs 등)은 단일 호스트에서 사용하도록 설계되었다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1760327135349&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Node 1의 동작
1. 블록 A를 읽어서 메모리 캐시에 저장
2. 캐시의 내용을 수정
3. 나중에 디스크에 flush (write-back)

# Node 2의 동작 (동시에)
1. 동일한 블록 A를 읽음 (오래된 데이터)
2. 수정하고 디스크에 쓰기
3. Node 1의 변경사항이 사라짐 ❌&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;&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;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;3. 락(Lock) 메커니즘 부재&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NFS는 네트워크 락 매니저(NLM)를 통해 파일 락을 관리하지만, 일반 블록 디바이스는 이런 메커니즘이 없다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1760327159589&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;NFS:
Client 1 &amp;rarr; &quot;파일 A 잠금 요청&quot; &amp;rarr; NFS Server
                                 &amp;darr;
                              [Lock Manager]
                                 &amp;darr;
Client 2 &amp;rarr; &quot;파일 A 접근 시도&quot; &amp;rarr; &quot;대기...&quot;

iSCSI:
Client 1 &amp;rarr; 직접 블록 쓰기 &amp;rarr;  ┐
                             ├&amp;rarr; [충돌!] ❌
Client 2 &amp;rarr; 직접 블록 쓰기 &amp;rarr;  ┘&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;&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;4. 해결 방법: 클러스터 파일 시스템&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ReadWriteMany를 블록 스토리지에서 사용하려면 &lt;b&gt;클러스터 파일 시스템&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GFS2 (Red Hat)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1760327211032&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 분산 락 매니저 필요
pacemaker + dlm + gfs2&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OCFS2 (Oracle)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1760327224728&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# O2CB 클러스터 스택 필요
o2cb + ocfs2&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이러한 파일 시스템들은&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;분산 락 메커니즘 내장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;캐시 일관성 프로토콜 구현&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메타데이터 동기화 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;하지만 복잡하고 오버헤드가 크다&lt;/b&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;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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;요약&lt;/span&gt;&lt;/p&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NFS (파일 레벨)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;iSCSI (블록 레벨)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;락 관리&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NFS 서버가 중앙 관리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;없음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;메타데이터&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서버가 일원화 관리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 클라이언트가 독립적&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;캐시 동기화&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NFS 프로토콜로 처리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;불가능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;다중 접근&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;안전 ✅&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;결론:&lt;/b&gt; iSCSI는 블록 디바이스를 직접 노출하기 때문에, 일반 파일 시스템으로는 다중 노드 접근이 불가능하다. 이것이 ReadWriteOnce만 지원하는 근본적인 이유&lt;/i&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;&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&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;color: #000000;&quot;&gt;4. Ceph RBD (RADOS Block Device)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특징&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ceph는 오픈소스 분산 스토리지 시스템으로, 블록, 파일, 오브젝트 스토리지를 모두 제공한다. RBD는 Ceph의 블록 스토리지 인터페이스이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1760325983132&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Ceph RBD StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ceph-rbd
provisioner: rbd.csi.ceph.com
parameters:
  clusterID: your-cluster-id
  pool: kubernetes
  imageFeatures: layering
  csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
  csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
reclaimPolicy: Delete
allowVolumeExpansion: 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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장점&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고가용성&lt;/b&gt;: 데이터 복제로 장애 허용&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;확장성&lt;/b&gt;: 페타바이트 규모까지 확장 가능&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;자가 치유&lt;/b&gt;: 자동 복구 기능&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;볼륨 확장&lt;/b&gt;: 온라인 크기 조정 지원&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스냅샷/클론&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단점&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;운영 복잡도&lt;/b&gt;: 클러스터 관리가 어려움&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;리소스 소모&lt;/b&gt;: 최소 3대 이상의 노드 필요&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;학습 곡선&lt;/b&gt;: Ceph 전문 지식 필요&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;디버깅 어려움&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;적합한 사용 사례&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;온프레미스 프라이빗 클라우드&lt;/b&gt;: OpenStack 환경&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;대규모 클러스터&lt;/b&gt;: 수백 대 이상의 노드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고가용성 필수&lt;/b&gt;: 데이터 유실 불가 환경&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;하이브리드 스토리지&lt;/b&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&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;color: #000000;&quot;&gt;5. 클라우드 네이티브 스토리지&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS EBS (Elastic Block Store)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1760326036790&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# AWS EBS StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs-gp3
provisioner: ebs.csi.aws.com
parameters:
  type: gp3
  iops: &quot;3000&quot;
  throughput: &quot;125&quot;
  encrypted: &quot;true&quot;
allowVolumeExpansion: 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;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SSD 타입: gp3 (범용), io2 (고성능), st1 (처리량 최적화)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최대 16,000 IOPS (io2 Block Express는 256,000)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 백업 (스냅샷)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가용영역(AZ) 종속&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GCP Persistent Disk&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1760326058428&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# GCP PD StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: pd-ssd
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-ssd
  replication-type: regional-pd  # 리전 간 복제
allowVolumeExpansion: 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;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;타입: pd-standard (HDD), pd-ssd (SSD), pd-extreme (NVMe)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Regional PD로 다중 AZ 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 암호화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최대 100,000 IOPS&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Azure Managed Disk&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1760326085059&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Azure Disk StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: azure-disk-premium
provisioner: disk.csi.azure.com
parameters:
  storageaccounttype: Premium_LRS
  kind: Managed
allowVolumeExpansion: 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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;타입: Standard HDD, Standard SSD, Premium SSD, Ultra Disk&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Zone-redundant storage (ZRS) 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최대 160,000 IOPS (Ultra Disk)&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6. 스토리지 타입 비교표&lt;/span&gt;&lt;/h3&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NFS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;iSCSI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ceph RBD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라우드 블록&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Access Mode&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;RWO, RWX, ROX&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;RWO&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;RWO&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;RWO&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;성능 (IOPS)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;레이턴시&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5-20ms&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1-5ms&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1-5ms&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;lt;1ms&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;설정 난이도&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;운영 복잡도&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고가용성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;❌ (단일 서버)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;△ (멀티패스)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;동적 프로비저닝&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;△&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;볼륨 확장&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;❌&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스냅샷&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;△&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비용&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&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;color: #000000;&quot;&gt;7. 선택 가이드: 당신의 상황에 맞는 스토리지는?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시나리오별 추천&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;여러 Pod에서 설정 파일을 공유하고 싶어요&quot;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;rarr; &lt;b&gt;NFS&lt;/b&gt; 선택&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ReadWriteMany 필요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 요구사항 낮음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;PostgreSQL 데이터베이스를 운영할 거예요&quot;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;rarr; &lt;b&gt;iSCSI 또는 클라우드 블록 스토리지&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높은 IOPS 필요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮은 레이턴시 중요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;온프레미스에서 프로덕션 클러스터를 구축해요&quot;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;rarr; &lt;b&gt;Ceph RBD&lt;/b&gt; 고려&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고가용성 필수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;충분한 하드웨어 리소스 있음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;클라우드(AWS/GCP/Azure)에서 실행해요&quot;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;rarr; &lt;b&gt;클라우드 네이티브 스토리지&lt;/b&gt; 강력 추천&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관리 오버헤드 최소화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 백업/복구&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;의사결정 플로우차트&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1760326678602&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;클라우드 환경인가?
├─ YES &amp;rarr; 클라우드 네이티브 스토리지 사용
└─ NO
   └─ ReadWriteMany 필요한가?
      ├─ YES &amp;rarr; NFS
      └─ NO &amp;rarr; 높은 성능 필요한가?
         ├─ YES &amp;rarr; iSCSI (소규모) or Ceph (대규모)
         └─ NO &amp;rarr; NFS로 충분&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실무 예시: Synology NAS와 CSI Driver&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;많은 중소기업과 홈랩 사용자들이 Synology NAS를 Kubernetes 스토리지로 활용한다. Synology는 iSCSI와 NFS를 모두 지원하며, CSI 드라이버를 통해 동적 프로비저닝도 가능하다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Synology CSI Chart 소개&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/christian-schlichtherle/synology-csi-chart&quot;&gt;Synology CSI Chart&lt;/a&gt;는 Synology 공식 CSI 드라이버를 Helm으로 쉽게 설치할 수 있도록 만든 커뮤니티 프로젝트이다.&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;&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 기능&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;동적 프로비저닝&lt;/b&gt;: PVC 생성 시 자동으로 LUN 생성&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2개의 StorageClass 자동 생성&lt;/b&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;synology-csi-delete: PVC 삭제 시 볼륨도 삭제&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;synology-csi-retain: PVC 삭제해도 볼륨은 유지&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스냅샷 지원&lt;/b&gt;: VolumeSnapshot으로 백업/복구&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;커스터마이징 가능&lt;/b&gt;: affinity, nodeSelector, tolerations 설정&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설치 방법&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 사전 요구사항&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1760327385073&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 모든 노드에 iSCSI initiator 설치 필요
# Ubuntu/Debian
sudo apt-get install open-iscsi

# RHEL/CentOS
sudo yum install iscsi-initiator-utils

# 서비스 시작
sudo systemctl enable --now iscsid&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Synology NAS 설정&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DSM 7: &lt;b&gt;SAN Manager&lt;/b&gt; 패키지 설치&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DSM 6: &lt;b&gt;iSCSI Manager&lt;/b&gt; 패키지 설치&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Helm 저장소 추가&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1760327411807&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;helm repo add synology-csi-chart https://christian-schlichtherle.github.io/synology-csi-chart
helm repo update&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. values.yaml 설정&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1760327427757&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# custom-values.yaml
clientInfoSecret:
  clients:
    - host: 192.168.1.100          # Synology NAS IP
      port: 5000                   # DSM 포트 (HTTPS는 5001)
      https: false                 # HTTPS 사용 여부
      username: k8s-csi-user       # DSM 사용자
      password: &quot;your-password&quot;    # 비밀번호

storageClasses:
  - name: synology-iscsi-delete
    reclaimPolicy: Delete
    volumeBindingMode: Immediate
    parameters:
      protocol: iscsi              # 프로토콜: iscsi
      fsType: ext4
    # 성능 테스트 활성화
    test: true

  - name: synology-iscsi-retain
    reclaimPolicy: Retain
    parameters:
      protocol: iscsi
      fsType: ext4

# iSCSI 타겟 설정 (선택사항)
node:
  tolerations:
    - key: &quot;node-role.kubernetes.io/control-plane&quot;
      operator: &quot;Exists&quot;
      effect: &quot;NoSchedule&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;&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 설치&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1760327444996&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;helm install synology-csi synology-csi-chart/synology-csi \
  --namespace synology-csi \
  --create-namespace \
  -f custom-values.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;&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. 설치 확인&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1760327460223&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# CSI Controller 확인
kubectl get pods -n synology-csi -l app=synology-csi-controller

# CSI Node 확인 (모든 노드에서 실행)
kubectl get pods -n synology-csi -l app=synology-csi-node

# StorageClass 확인
kubectl get storageclass

# 출력 예시:
# NAME                       PROVISIONER            RECLAIMPOLICY
# synology-iscsi-delete      csi.san.synology.com   Delete
# synology-iscsi-retain      csi.san.synology.com   Retain&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용 예시&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터베이스용 PVC&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1760327487571&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-data
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: synology-iscsi-retain  # 데이터 보호
  resources:
    requests:
      storage: 50Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:16
        env:
        - name: POSTGRES_PASSWORD
          value: &quot;password&quot;
        volumeMounts:
        - name: data
          mountPath: /var/lib/postgresql/data
        ports:
        - containerPort: 5432
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: postgres-data&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스냅샷 생성 및 복구&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1760327507241&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 스냅샷 생성
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: postgres-snapshot-20250114
spec:
  volumeSnapshotClassName: synology-snapshotclass
  source:
    persistentVolumeClaimName: postgres-data
---
# 스냅샷에서 복구
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-data-restored
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: synology-iscsi-retain
  dataSource:
    name: postgres-snapshot-20250114
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
  resources:
    requests:
      storage: 50Gi&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Synology CSI vs 순수 NFS 비교&lt;/span&gt;&lt;/h4&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;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style11&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Synology CSI (iSCSI)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;순수 NFS&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;동적 프로비저닝&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅ 자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;❌ 수동 PV 생성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;성능&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ReadWriteMany&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;❌ (iSCSI), ✅ (NFS 모드)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스냅샷&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;❌&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;볼륨 확장&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;❌&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;설정 복잡도&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;color: #000000;&quot;&gt;&lt;b&gt;추천&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;DB, 고성능&lt;/b&gt;: Synology CSI (iSCSI 모드)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;공유 파일&lt;/b&gt;: Synology CSI (NFS 모드) 또는 순수 NFS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;간단한 테스트&lt;/b&gt;: 순수 NFS&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;color: #000000;&quot;&gt;8. 실무 체크리스트&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 요구사항 확인&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;필요한 IOPS 계산 (예: DB는 보통 1000+ IOPS)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;레이턴시 요구사항 (예: 실시간 처리는 5ms 이하)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처리량(Throughput) 확인 (MB/s)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가용성 요구사항&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;RTO/RPO 목표 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 복제 필요 여부&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;접근 패턴&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;단일 Pod 접근 vs 다중 Pod 접근&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;읽기 위주 vs 쓰기 위주&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;순차 접근 vs 랜덤 접근&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영 역량&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;운영팀의 기술 수준&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;24/7 모니터링 가능 여부&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&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;color: #000000;&quot;&gt;9. 하이브리드 전략&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예시: 전자상거래 플랫폼&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1760326759374&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 데이터베이스 - iSCSI (고성능)
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-pvc
spec:
  storageClassName: iscsi-high-performance
  accessModes: [ReadWriteOnce]
  resources:
    requests:
      storage: 100Gi

---
# 상품 이미지 - NFS (공유)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: product-images-pvc
spec:
  storageClassName: nfs-shared
  accessModes: [ReadWriteMany]
  resources:
    requests:
      storage: 500Gi

---
# 로그 수집 - NFS (중앙화)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: logs-pvc
spec:
  storageClassName: nfs-logs
  accessModes: [ReadWriteMany]
  resources:
    requests:
      storage: 200Gi&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;color: #000000;&quot;&gt;10. 트러블슈팅 가이드&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NFS 성능 이슈&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1760326780452&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# NFS 마운트 옵션 확인
mount | grep nfs

# NFS 서버 상태 확인
showmount -e nfs-server-ip

# 네트워크 레이턴시 측정
ping -c 100 nfs-server-ip

# NFS 성능 테스트
dd if=/dev/zero of=/mnt/nfs/testfile bs=1M count=1024&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;iSCSI 연결 문제&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1760326797496&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# initiator 상태 확인
systemctl status iscsid

# 세션 확인
iscsiadm -m session

# 타겟 재스캔
iscsiadm -m node --rescan

# 로그 확인
journalctl -u iscsid -f&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ceph 클러스터 상태&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1760326812257&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 클러스터 상태
ceph status

# OSD 상태
ceph osd tree

# Pool 상태
ceph osd pool stats

# 성능 통계
ceph osd perf&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes 스토리지 선택은 단순히 기술적 사양만으로 결정되지 않는다. 팀의 운영 역량, 예산, 성능 요구사항, 그리고 미래의 확장 계획까지 종합적으로 고려해야 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 요약&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;클라우드 환경이라면&lt;/b&gt; 고민할 필요 없이 클라우드 네이티브 스토리지를 사용하면된다. AWS EBS, GCP PD, Azure Disk는 최고의 성능과 안정성을 제공하며, 운영 부담도 최소화된다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;온프레미스 환경이라면&lt;/b&gt; 워크로드를 분석해보자.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;공유 파일이 필요하면 &lt;b&gt;NFS&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터베이스나 고성능 워크로드는 &lt;b&gt;iSCSI&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대규모 프로덕션 환경이고 전문 인력이 있다면 &lt;b&gt;Ceph&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;가장 중요한 것은&lt;/b&gt; 작게 시작해서 점진적으로 확장하는 것이다. 처음부터 완벽한 스토리지 아키텍처를 구축하려 하지 말자. NFS로 시작해서 성능 병목이 생기면 iSCSI로 마이그레이션하는 것도 충분히 합리적인 접근이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스토리지는 Kubernetes 환경에서 가장 복잡하고 중요한 영역 중 하나이다. 하지만 각 타입의 특성을 이해하고, 실무 경험을 쌓아가다 보면 어느새 최적의 선택을 자신 있게 할 수 있게 될 것이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Remember&lt;/b&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;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/storage-classes/&quot;&gt;Kubernetes Storage Classes Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://landscape.cncf.io/card-mode?category=cloud-native-storage&quot;&gt;CNCF Storage Landscape&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://wiki.linux-nfs.org/wiki/index.php/Performance&quot;&gt;Linux NFS Performance Tuning&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/storage_administration_guide/ch-iscsi&quot;&gt;iSCSI Best Practices&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/christian-schlichtherle/synology-csi-chart&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;u&gt;Synology Helm Chart&lt;/u&gt;&lt;/a&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;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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>Container Orchestration/Kubernetes</category>
      <category>Kubernetes</category>
      <category>kubernetes storage type</category>
      <category>Linux</category>
      <category>storage</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/466</guid>
      <comments>https://somaz.tistory.com/466#entry466comment</comments>
      <pubDate>Tue, 28 Apr 2026 00:00:21 +0900</pubDate>
    </item>
    <item>
      <title>Public Helm Chart Repository 구축하기 &amp;mdash; 로컬 차트에서 ArtifactHub까지</title>
      <link>https://somaz.tistory.com/508</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사내에서 관리하던 Helm 차트를 여러 클러스터에서 공유하다 보면 결국 한계에 부딪힌다. 한 클러스터용으로 작성한 차트가 다른 클러스터에서도 유용한데, 복사해서 쓰다 보면 버전이 어긋나고 CI가 깨지고, 팀 밖으로는 공유할 방법이 없다.&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;color: #000000;&quot;&gt;이번 포스팅에서는 사내 차트 하나를 &lt;b&gt;공개된 Dual Distribution Helm Chart Repository&lt;/b&gt;로 추출하는 전체 과정을 정리한다. GitHub Pages(커스텀 서브도메인) 기반의 전통적인 Helm Repo와 OCI Registry(GHCR)에 동시에 배포하고, ArtifactHub에 등록해 카탈로그에서 검색 가능하게 만들며, CI/CD와 거버넌스 체계까지 갖추는 방법이다.&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;color: #000000;&quot;&gt;예시로 사용한 차트는 nginx-gateway-cr이다. NGINX Gateway Fabric 컨트롤러 Chart를 보완하는 Custom Resource(Gateway, NginxProxy, ServiceMonitor)를 묶은 차트다. 여기서 다루는 패턴은 공개하고 싶은 어떤 차트에도 그대로 적용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b68vf7/dJMcahRDZo9/oF9JxUziUhd3vV4t6St7k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b68vf7/dJMcahRDZo9/oF9JxUziUhd3vV4t6St7k1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b68vf7/dJMcahRDZo9/oF9JxUziUhd3vV4t6St7k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb68vf7%2FdJMcahRDZo9%2FoF9JxUziUhd3vV4t6St7k1%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;왜 별도의 Charts Repository를 만들었는가?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;차트를 분리하기 전에, 정말 별도 레포가 필요한지 솔직하게 점검할 필요가 있었다. 세 가지 질문으로 결정했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다른 클러스터나 다른 팀이 이 차트를 재사용할 가능성이 있는가? &lt;b&gt;있다.&lt;/b&gt; 복사/붙여넣기는 바로 drift가 발생한다. 차트를 추출해야 한다.&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;color: #000000;&quot;&gt;나중에 추가로 공개할 사내 차트가 더 있는가? &lt;b&gt;최소 2~3개는 더 있다.&lt;/b&gt; 레포 하나당 차트 하나가 아니라 &lt;b&gt;모노레포 구조&lt;/b&gt;(`charts/&amp;lt;name&amp;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;color: #000000;&quot;&gt;카탈로그에서 검색되는 것도 목표인가? &lt;b&gt;그렇다.&lt;/b&gt; 깔끔한 공개 URL과 적절한 메타데이터가 필요하다.&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;color: #000000;&quot;&gt;모노레포 결정은 중요하다. 업계 표준인 `bitnami/charts`, `prometheus-community/helm-charts`, `grafana/helm-charts` 모두 이 패턴을 쓴다. ArtifactHub는 개별 차트를 `Chart.yaml`의 name 필드로 색인하기 때문에 레포 이름이 차트 검색에 영향을 주지 않는다. 차트 이름만 중요하다.&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;&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;color: #000000;&quot;&gt;레포지토리 네이밍&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;helm-charts는 다소 일반적이긴 하지만 `username/org` 와 결합하면 충분히 명확해진다. `github.com/&amp;lt;user&amp;gt;/helm-charts` 전체 경로는 모호할 여지가 없다. 고려했던 다른 후보들은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`&amp;lt;user&amp;gt;-charts` &amp;mdash; 브랜딩은 명확하지만 약간 중복&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`helm-deck` &amp;mdash; 창의적이지만 기존 helm-*-template 레포들과 패턴이 맞지 않음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`&amp;lt;chart-name&amp;gt;-chart` &amp;mdash; 단일 차트 레포에만 적합&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존에 helm-chart-template, helm-base-app-template 같은 *-template 계열 레포가 있다면, helm-charts(복수형, &quot;실제 컬렉션&quot;)가 자연스러운 네이밍 쌍을 이룬다.&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Repository 레이아웃&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최종 레이아웃은 다음과 같다. N개 차트까지 확장 가능한 구조다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;reasonml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;helm-charts/
├── .github/
│   ├── CODEOWNERS                                 # * @&amp;lt;user&amp;gt;
│   ├── dependabot.yml                             # github-actions weekly
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── ISSUE_TEMPLATE/
│   │   ├── config.yml                             # issue chooser
│   │   ├── bug_report.yml
│   │   └── feature_request.yml
│   └── workflows/
│       ├── lint.yml                               # ct lint + helm template + kubeconform
│       ├── release.yml                            # chart-releaser + GHCR OCI
│       ├── gitlab-mirror.yml                      # backup mirror
│       ├── dependabot-auto-merge.yml
│       ├── stale-issues.yml
│       ├── issue-greeting.yml
│       └── contributors.yml
├── charts/
│   └── nginx-gateway-cr/
│       ├── Chart.yaml
│       ├── values.yaml
│       ├── values.schema.json                     # JSON Schema (draft-07)
│       ├── README.md
│       ├── .helmignore
│       └── templates/
│           ├── _helpers.tpl
│           ├── gateways.yaml
│           ├── nginxproxies.yaml
│           ├── servicemonitor-controller.yaml
│           ├── servicemonitor-dataplane.yaml
│           ├── referencegrants.yaml
│           └── NOTES.txt
├── README.md
├── CONTRIBUTING.md
├── CONTRIBUTORS.md                                # auto-generated
├── SECURITY.md
├── Makefile                                       # local automation
├── LICENSE                                        # Apache-2.0
├── artifacthub-repo.yml                           # ownership claim
└── .gitignore&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;&lt;b&gt;라이선스는&lt;/b&gt; Apache-2.0을 선택했다. Kubernetes/Helm 생태계의 사실상 표준이다(Helm, Kubernetes, NGINX Gateway Fabric, 주요 차트 컬렉션 모두 Apache-2.0). &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;Chart 설계 &amp;mdash; 확장성 우선&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사내용 nginx-gateway-cr은 단순했다. 두 클러스터에서 쓸 만큼의 필드만 있으면 됐다. 공개로 전환하려면 한 번도 만나본 적 없는 사용자의, 한 번도 본 적 없는 클러스터를 염두에 두고 설계해야 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다섯 가지 확장성 패턴&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1. Empty-by-default (기본값은 비어있음)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# values.yaml
gateways: []
referenceGrants: []
serviceMonitor:
  controller:
    enabled: false
  dataplane:
    enabled: false&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;`values` 없이 `helm install` 을 실행하면 어떤 리소스도 생성되지 않는다. 안전한 No-op 기본값이다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자는 `gateways` 를 채워서 명시적으로 `opt-in` 한다. default 네임스페이스에 예상치 못한 리소스가 생기지 않는다.&lt;/span&gt;&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;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2. Defaults + Per-entry Overrides&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;proxy:                          # 글로벌 defaults
  replicas: 1
  service:
    externalTrafficPolicy: Cluster

gateways:
  - name: app
    loadBalancerIP: 10.0.0.10
    proxy:                      # per-gateway override (deep-merge)
      replicas: 3
      service:
        annotations:
          metallb.universe.tf/address-pool: prod-pool&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;템플릿에서 `mergeOverwrite (deepCopy $defaultProxy) (default dict $gw.proxy)` 를 쓰면 최종 spec이 만들어진다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;3. Shorthand + Full-control 공존&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 일반적인 케이스(HTTP + HTTPS 종료)를 위한 shorthand
gateways:
  - name: app
    https:
      enabled: true
      hostname: &quot;*.example.com&quot;
      tlsSecretName: wildcard-example-tls

  # 복잡한 케이스(TLS Passthrough, TCP, gRPC 등)는 전체 listener 오버라이드
  - name: tcp
    listeners:
      - name: tls-passthrough
        protocol: TLS
        port: 8443
        tls:
          mode: Passthrough
        allowedRoutes:
          kinds:
            - kind: TLSRoute&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;`listeners` 가 설정되면 shorthand는 무시된다. 쉬운 기본값과 완전한 제어력을 모두 제공하는 방식이다.&lt;/span&gt;&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;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;4. Escape Hatch &amp;mdash; 예외 상황을 위한 탈출구&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;proxy:
  kubernetesExtra: {}     # spec.kubernetes로 merge
  specExtra: {}           # spec(top-level)로 merge&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;NGF의 `NginxProxy` CRD에는 수십 개의 필드가 있다. 모두 values에 1급 필드로 노출하면 스키마가 지저분해진다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자주 쓰는 것들(replicas, resources, externalTrafficPolicy, logging, rewriteClientIP, telemetry, ipFamily)만 노출하고, Escape Hatch 키 두 개(`kubernetesExtra`, `specExtra`)로 다른 필드에도 접근할 수 있게 했다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;5. 스키마로 검증되는 입력값&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;json&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;// values.schema.json (일부)
{
  &quot;$schema&quot;: &quot;http://json-schema.org/draft-07/schema#&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;additionalProperties&quot;: false,
  &quot;properties&quot;: {
    &quot;proxy&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;additionalProperties&quot;: false,
      &quot;properties&quot;: {
        &quot;replicas&quot;: { &quot;type&quot;: &quot;integer&quot;, &quot;minimum&quot;: 0 },
        &quot;service&quot;: {
          &quot;type&quot;: &quot;object&quot;,
          &quot;properties&quot;: {
            &quot;externalTrafficPolicy&quot;: {
              &quot;type&quot;: &quot;string&quot;,
              &quot;enum&quot;: [&quot;Cluster&quot;, &quot;Local&quot;]
            }
          }
        }
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;`helm install` 시 이 스키마가 자동으로 실행된다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;음수 replicas, enum 오타, 알 수 없는 최상위 키 &amp;mdash; 모두 Kubernetes 오브젝트가 생성되기 전에 거부된다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;덤으로 ArtifactHub가 이 스키마를 기반으로 차트 페이지에 values 입력 폼을 렌더링해 준다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;subunit&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;$ helm template t charts/nginx-gateway-cr --set proxy.replicas=-1
Error: values don't meet the specifications of the schema(s) in the following chart(s):
nginx-gateway-cr:
- proxy.replicas: Must be greater than or equal to 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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;CI/CD Workflow 구성&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;워크플로우는 총 8개다. 각자 하나의 일만 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`lint.yml` &amp;mdash; PR 검증&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PR이 들어오면 3단계로 검증한다.&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;`ct lint`&lt;/b&gt; &amp;mdash; chart-testing의 표준 검증(Chart.yaml, README, 버전 증가 여부)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;`helm template`&lt;/b&gt; &amp;mdash; 템플릿 문법 오류와 스키마 위반 감지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;`kubeconform`&lt;/b&gt; &amp;mdash; 렌더링된 매니페스트를 Kubernetes core + CRD 스키마로 검증(&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/datreeio/CRDs-catalog&quot;&gt;datreeio CRDs catalog&lt;/a&gt; 사용)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`release.yml` &amp;mdash; main push가 모든 걸 트리거&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;&lt;b&gt;트리거는 `Chart.yaml` 의 `version` 증가지, `git tag` 가 아니다.&lt;/b&gt; `chart-releaser-action` 이 `Chart.yaml` 의 `version` 을 읽고 이전 릴리즈보다 높으면 자동으로 tag(`&amp;lt;chart&amp;gt;-&amp;lt;version&amp;gt;`)를 만든다. git tag를 수동으로 실행할 일이 없다.&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;color: #000000;&quot;&gt;&lt;b&gt;`concurrency.cancel-in-progress: false`&lt;/b&gt; &amp;mdash; 릴리즈는 반드시 끝까지 완료되어야 한다. 중간에 취소되면 일관성 없는 상태가 된다(tag는 생성됐는데 .tgz는 없거나, 반대거나).&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보조 Workflow&lt;/span&gt;&lt;/h3&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Workflow&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;용도&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;gitlab-mirror.yml&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;main push마다 GitLab으로 백업 미러링&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;dependabot-auto-merge.yml&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;minor/patch 의존성 PR을 squash-merge로 자동 병합&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;stale-issues.yml&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;30일간 활동 없는 이슈를 stale 표시, 7일 후 close&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;issue-greeting.yml&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;새 이슈에 환영 메시지 자동 댓글&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;contributors.yml&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;릴리즈 후 CONTRIBUTORS.md 자동 업데이트&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;Distribution &amp;mdash; Static + OCI Dual 배포&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Helm Chart를 공개 배포하는 방법은 두 가지다. 대부분의 프로젝트는 하나만 고른다. 여기서는 둘 다 한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&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;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GitHub Pages (Static)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GHCR (OCI)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;사용자 명령어&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`helm repo add` 후 `helm install`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`helm install oci://...` (한 번에)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Helm 버전&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3.0+&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3.8+ 필요&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ArtifactHub&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`index.yaml` 로 자동 색인&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수동 등록 필요&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;검색성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;강함(ArtifactHub 검색 가능)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;약함(URL을 알아야 함)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;인증 모델&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Public HTTP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;토큰 인증(Private 지원)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;호스팅&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GitHub Pages(무료)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GHCR 스토리지(Free tier)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&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;color: #000000;&quot;&gt;왜 둘 다? ArtifactHub 검색성은 Static Repo에서 온다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OCI는 현대적 표준이며, 커스텀 도메인에 문제가 생겼을 때의 Fallback 역할도 한다(뒤에서 자세히). 비용은 거의 없다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`chart-releaser` 가 이미 `.tgz` 를 만드니, 두 번째 목적지로 밀어넣는 건 bash 몇 줄 추가면 된다.&lt;/span&gt;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;Bootstrap 함정 #1 &amp;mdash; gh-pages Chicken-and-Egg 문제&lt;/span&gt;&lt;/h3&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;color: #000000;&quot;&gt;처음 push하면 릴리즈 워크플로우가 다음과 같이 실패한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;subunit&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;fatal: invalid reference: origin/gh-pages
Error: exit status 128&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;`chart-releaser-action` 은 `gh-pages` 브랜치가 이미 존재한다고 가정한다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 브랜치에 새 `index.yaml` 과 `.tgz` 를 일반 커밋으로 추가하는 방식이다. 갓 만든 레포에는 gh-pages 브랜치가 없다.&lt;/span&gt;&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;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;해결 방법&lt;/b&gt; &amp;mdash; 빈 orphan 브랜치를 한 번만 수동으로 만든다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;mipsasm&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;git switch --orphan gh-pages
git commit --allow-empty -m &quot;chore: initialize gh-pages branch&quot;
git push -u origin gh-pages
git switch main&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;그 다음 실패한 릴리즈 워크플로우를 다시 실행한다. 이후부터는 `chart-releaser` 가 알아서 `gh-pages` 를 관리한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주의할 점은 `chart-releaser-action` 이 이걸 자동 부트스트랩하지 않는다는 것이다. 이 액션은 사용자가 이미 GitHub Pages를 설정했다고 가정한다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대부분은 첫 릴리즈 전에 설정해 두기 때문이다. Pages 설정이 전혀 없는 갓 만든 레포에서만 이 Edge Case가 발생한다. 자동 부트스트랩 관련 Open Discussion이 있긴 하지만, 현재는 수동 Workaround가 권장 경로다.&lt;/span&gt;&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;&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;color: #000000;&quot;&gt;Custom Domain 설정&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 URL은 `https://&amp;lt;user&amp;gt;.github.io/helm-charts` 다. 이것도 잘 작동한다. 다만 (대부분의 개인 계정 사용자가 그렇듯) `&amp;lt;user&amp;gt;.github.io` 프로필 사이트에 커스텀 도메인(예: 블로그)을 연결해 뒀다면, 모든 프로젝트 페이지가 그 커스텀 도메인으로 301 리다이렉트된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;groovy&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;https://&amp;lt;user&amp;gt;.github.io/helm-charts/index.yaml
  &amp;rarr; 301 Moved Permanently
  &amp;rarr; http://&amp;lt;your-blog-domain&amp;gt;/helm-charts/index.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;문제는&lt;b&gt; ArtifactHub가 URL을 확인할 때 301 리다이렉트를 따라가지 않는다는 점&lt;/b&gt;이다. 등록이 다음 에러로 실패한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;livecodeserver&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;An error occurred adding the repository: invalid input:
the url provided does not point to a valid Helm repository&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;&lt;b&gt;해결책&lt;/b&gt;은 전용 서브도메인을 쓰는 것이다. 3단계로 처리한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. DNS &amp;mdash; CNAME 레코드 추가&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DNS 제공자에서 레코드를 추가한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 34px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Type&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Host&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Value&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TTL&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CNAME&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;charts&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;lt;user&amp;gt;.github.io&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;180&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;span style=&quot;color: #000000;&quot;&gt;전파 확인&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;dig +short charts.example.com
# 예상 결과:
# &amp;lt;user&amp;gt;.github.io.
# 185.199.108.153
# 185.199.109.153
# 185.199.110.153
# 185.199.111.153&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;(IP들은 GitHub Pages anycast 대역이다. DNS가 제대로 해석되면 보인다.)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. gh-pages 브랜치에 CNAME 파일 추가&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GitHub Pages는 서빙할 브랜치의 루트에서 CNAME 파일을 읽어 도메인을 결정한다. gh-pages에 추가한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;mipsasm&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;git switch gh-pages
git pull --rebase origin gh-pages
echo &quot;charts.example.com&quot; &amp;gt; CNAME
git add CNAME
git commit -m &quot;chore: add CNAME for charts.example.com custom domain&quot;
git push origin gh-pages
git switch main&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. GitHub Pages 설정에서 HTTPS 활성화&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;레포의 &lt;b&gt;Settings &amp;rarr; Pages&lt;/b&gt;로 이동한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CNAME 파일을 push하면 GitHub가 커스텀 도메인을 자동 감지한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1~3분 기다리면 DNS 체크가 통과된다(도메인 옆에 ✓ 표시).&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;**&quot;Enforce HTTPS&quot;**에 체크한다. GitHub가 Let's Encrypt 인증서를 프로비저닝한다(1~15분).&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 검증&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;curl -I https://charts.example.com/index.yaml
# HTTP/2 200
# content-type: text/yaml&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;ArtifactHub 등록&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;URL이 정상 작동하면 &lt;a style=&quot;color: #000000;&quot; href=&quot;https://artifacthub.io&quot;&gt;artifacthub.io&lt;/a&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 1 &amp;mdash; 메타데이터 파일 생성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`artifacthub-repo.yml` 을 레포에 추가한다(ID는 일단 비워둬도 된다).&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# artifacthub-repo.yml
repositoryID: &quot;&quot;
owners:
  - name: &amp;lt;your-github-handle&amp;gt;
    email: &amp;lt;your-email&amp;gt;&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;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;color: #000000;&quot;&gt;이 파일은 ArtifactHub가 fetch할 때 소유권을 증명한다. `&lt;b&gt;index.yaml` 과 같은 URL에서 서빙되어야 한다.&lt;/b&gt; 즉 `main` 이 아니라 `gh-pages` 브랜치 루트에 있어야 한다. chart-releaser는 이 파일을 자동으로 복사하지 않으므로 한 번 수동으로 추가한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;git switch gh-pages
git checkout main -- artifacthub-repo.yml
git add artifacthub-repo.yml
git commit -m &quot;chore: add ArtifactHub repository metadata&quot;
git push origin gh-pages
git switch main&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;chart-releaser는 `gh-pages` 의 파일을 삭제하지 않으므로 한 번 올려두면 영원히 유지된다. 자동화할 필요가 없다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 2 &amp;mdash; Repository 등록&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://artifacthub.io&quot;&gt;artifacthub.io&lt;/a&gt; &amp;rarr; 로그인(GitHub OAuth, 무료) &amp;rarr; Control Panel &amp;rarr; &lt;b&gt;Add repository&lt;/b&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;필드&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;값&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비고&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kind&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Helm charts&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OCI는 별도 Kind&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Name&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;lt;your-handle&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;helm repo add alias로 쓰임&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Display name&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;lt;Your Handle&amp;gt; Helm Charts&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;카탈로그 표시명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;URL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://charts.example.com&quot;&gt;https://charts.example.com&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;커스텀 도메인&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Disabled&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OFF&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;카탈로그에 표시되게 유지&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Security scanner disabled&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OFF&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;참조하는 컨테이너 이미지를 Trivy가 자동 스캔&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&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;color: #000000;&quot;&gt;ArtifactHub가 repositoryID(UUID)를 할당한다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 값을 `artifacthub-repo.yml` 에 복사해 넣고 `main` 과 `gh-pages` 양쪽에 commit, push한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 3 &amp;mdash; 기다리기&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ArtifactHub는 약 30분마다 자동 sync한다. 첫 sync 후:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;차트가 카탈로그에 노출된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;Verified Publisher&quot; 배지가 붙는다(repositoryID가 일치하면).&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`values.schema.json` 기반 입력 폼이 각 차트 페이지에 활성화된다.&lt;/span&gt;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리스크 &amp;mdash; 도메인이 만료되면 어떻게 되는가?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;반드시 나오는 질문이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리소스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;charts.example.com이 죽었을 때 영향&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;helm repo add ... (신규 설치)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DNS 실패&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;helm repo update&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실패&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이미 설치된 릴리즈&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Helm이 .tgz를 로컬 캐시&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ArtifactHub 카탈로그 엔트리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Unreachable 표시, 결국 제거됨&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;OCI 설치 (oci://ghcr.io/...)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;영향 없음&lt;/b&gt; &amp;mdash; GitHub 소유 도메인&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;정확히 이것 때문에 양쪽에 배포하는 것이다.&lt;/b&gt; GHCR에 올린 OCI 배포물이 안전망이다. 커스텀 도메인이 다운되더라도 사용자는 이렇게 전환하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;helm install &amp;lt;release&amp;gt; oci://ghcr.io/&amp;lt;user&amp;gt;/charts/&amp;lt;chart-name&amp;gt; --version &amp;lt;ver&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;다른 건 아무것도 바꿀 필요 없다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;README에 두 가지 설치 방법을 모두 기재하고(OCI를 Backup 옵션으로 눈에 띄게), 도메인 등록기관에서 자동 갱신을 켜두자. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;로컬 자동화 &amp;mdash; 다중 차트 대응 Makefile&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Makefile은 단일 차트에서도 써볼 만큼 간단하고, 차트가 늘어나면 더 빛을 본다. 패턴은 CHART=&amp;lt;name&amp;gt;으로 한 차트로 범위를 좁히고, 기본값은 charts/ 아래 전체 차트로 동작하는 방식이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;유용한 타겟들&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style10&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Target&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;용도&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;make help&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 생성 도움말(kubebuilder 스타일 awk 파서)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;make charts&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 차트와 현재 버전 나열&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;make lint [CHART=...]&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;helm lint&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;make ct-lint&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;chart-testing lint(CI와 동일)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;make template [CHART=...]&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;helm template 스모크 렌더&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;make validate [CHART=...]&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kubeconform으로 k8s + CRD 스키마 검증&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;make ci&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위 전체를 순서대로 실행&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;make package [CHART=...]&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;helm package &amp;rarr; .cr-release-packages/&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;make version CHART=&amp;lt;name&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현재 버전 출력&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;make bump CHART=&amp;lt;name&amp;gt; LEVEL=patch|minor|major&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Chart.yaml 버전 증가, 다음 단계 안내 출력&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;make scaffold CHART=&amp;lt;new&amp;gt; FROM=&amp;lt;existing&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 차트를 시작점으로 복사&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;bump 활용&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;릴리즈 플로우가 다음과 같이 정리된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;make bump CHART=nginx-gateway-cr LEVEL=patch
# Chart.yaml의 artifacthub.io/changes annotation 편집
git commit -am &quot;feat(nginx-gateway-cr): describe change&quot;
git push    # release.yml 자동 트리거&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;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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;거버넌스 파일&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CONTRIBUTING.md&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PR 프로세스, 버전 bump 규칙, 로컬 검증 명령어를 문서화하고 `Makefile` 을 참조시킨다. 이게 없으면 의욕 넘치는 Contributor가 차트 버전을 올려야 한다는 걸 모른다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SECURITY.md&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;취약점 신고를 위한 Private Channel(GitHub Security Advisories + 이메일 Fallback)을 제공하고 대응 시간을 명시한다. 인프라 차트처럼 프로덕션 트래픽에 영향을 줄 수 있는 경우, 일반 OSS 라이브러리보다 훨씬 중요하다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.github/PULL_REQUEST_TEMPLATE.md&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 PR에 차트 인식 체크리스트가 자동으로 채워진다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;autohotkey&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;- [ ] `Chart.yaml`의 `version`을 SemVer에 맞게 bump
- [ ] `Chart.yaml`의 `artifacthub.io/changes`에 엔트리 추가
- [ ] `values.yaml` 구조가 바뀌었다면 `values.schema.json` 업데이트
- [ ] values나 동작이 바뀌었다면 차트 `README.md` 업데이트
- [ ] 로컬에서 `helm lint`와 `helm template` 실행&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.github/ISSUE_TEMPLATE/*&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;차트 이름, 차트 버전, helm 버전, k8s 버전, 사용한 values, 예상 동작과 실제 동작을 묻는 YAML 기반 폼 템플릿이다. 이게 없으면 디버깅이 5번의 주고받기 댓글로 시작된다.&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;color: #000000;&quot;&gt;`config.yml` 에 &quot;Security vulnerability&quot; 링크를 `SECURITY.md` 로 걸고, Blank Issue를 비활성화해서 사용자가 항상 템플릿을 선택하게 한다.&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영하면서 얻은 교훈&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;`chart-releaser-action` 은 `gh-pages` 를 부트스트랩해 주지 않는다. 첫 릴리즈 전에 orphan 브랜치를 수동으로 만들어야 한다. 안 그러면 애매한 에러 메시지로 10분을 디버깅하게 된다.&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;color: #000000;&quot;&gt;&lt;b&gt;ArtifactHub는 HTTP 301 리다이렉트를 따라가지 않는다.&lt;/b&gt; `&amp;lt;user&amp;gt;.github.io` 프로필 사이트에 커스텀 도메인이 걸려 있다면 전용 서브도메인 없이는 프로젝트 레포를 등록할 수 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;`artifacthub-repo.yml` 은 `main` 이 아니라 `gh-pages` 에 있어야 한다.&lt;/b&gt; 소유권 검증을 위해 `index.yaml` 과 같은 URL에서 서빙되어야 하기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;`chart-releaser-action` 은 `gh-pages` 의 파일을 삭제하지 않는다.&lt;/b&gt; 수동으로 추가한 파일(`CNAME`, `artifacthub-repo.yml`)은 한 번 올려두면 영원히 유지된다. 자동화할 필요가 없다.&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;color: #000000;&quot;&gt;&lt;b&gt;릴리즈 트리거는 `Chart.yaml` 의 version 증가지 `git tag` 가 아니다.&lt;/b&gt; 관습적인 `v1.0.0` 태깅 방식은 여기선 적용되지 않는다. `chart-releaser` 가 `&amp;lt;chart&amp;gt;-&amp;lt;version&amp;gt;` 태그를 자동으로 만든다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;차트 `.tgz` 파일은 `gh-pages` 에 직접 호스팅되지 않고 GitHub Release Attachment로 호스팅된다.&lt;/b&gt; `gh-pages` 의 `index.yaml` 은 그 다운로드 URL을 참조한다. 이게 `chart-releaser-action` 의 표준 동작이다.&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;color: #000000;&quot;&gt;&lt;b&gt;OCI 배포는 커스텀 도메인이 만료되는 날을 위한 보험&lt;/b&gt;이다. 구축 비용은 bash 몇 줄, 복구 가치는 측정 불가다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;`values.schema.json` 은 차트에 추가할 수 있는 가장 높은 ROI의 단일 아이템&lt;/b&gt;이다. 사용자 실수를 조기에 잡고, ArtifactHub 폼을 자동 생성하며, 스키마를 machine-readable하게 문서화한다. 이 모든 게 파일 하나에서 나온다.&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;color: #000000;&quot;&gt;&lt;b&gt;차트별 `artifacthub.io/changes` annotation&lt;/b&gt;이 ArtifactHub의 &quot;What's new&quot; 탭을 채운다. 사용자에게 커밋 메시지를 읽으라고 하는 것보다 훨씬 나은 UX다.&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;color: #000000;&quot;&gt;&lt;b&gt;`dependabot-auto-merge.yml` 은 첫날부터 넣어야 한다.&lt;/b&gt; 안 그러면 의존성 PR이 쌓여서 읽지 않게 되고, dependabot의 목적이 사라진다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;공개 Helm Chart Repository를 구축하는 건 대부분 배관 작업이다. 어려운 건 차트 작성이 아니라, GitHub Actions와 GitHub Pages, GHCR, 커스텀 DNS, ArtifactHub를 하나의 파이프라인으로 잘 작동하게 연결하는 것이다. 각 시스템 자체는 복잡하지 않다. 마찰은 이음새에서 발생한다.&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;color: #000000;&quot;&gt;이 포스팅의 패턴들은 실전에서 검증됐고, 앞으로의 나를 위해서라도 문서화해 둘 가치가 있었다. 차트를 공개하려는 사람이 바로 쓸 수 있는 청사진이 필요하다면, 이 Repository 구조와 두 개의 주요 Workflow, 그리고 Bootstrap 함정부터 시작하면 된다. 나머지는 차트 컬렉션이 커지면서 자연스럽게 확장된다.&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;color: #000000;&quot;&gt;실제 동작하는 결과물을 보고 싶다면 &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/helm-charts&quot;&gt;helm-charts 레포지토리(GitHub)&lt;/a&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;&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/helm/chart-releaser-action&quot;&gt;Helm chart-releaser-action&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/helm/chart-testing&quot;&gt;chart-testing&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/yannh/kubeconform&quot;&gt;kubeconform&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/datreeio/CRDs-catalog&quot;&gt;datreeio CRDs catalog&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://artifacthub.io/docs/topics/repositories/helm-charts/&quot;&gt;ArtifactHub Helm repository docs&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://helm.sh/docs/topics/registries/&quot;&gt;Helm OCI registries&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://gateway-api.sigs.k8s.io/&quot;&gt;Gateway API&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/nginx/nginx-gateway-fabric&quot;&gt;NGINX Gateway Fabric&lt;/a&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Container Orchestration/Kubernetes</category>
      <category>₩</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/508</guid>
      <comments>https://somaz.tistory.com/508#entry508comment</comments>
      <pubDate>Fri, 24 Apr 2026 00:00:15 +0900</pubDate>
    </item>
    <item>
      <title>AWS 모니터링 스택 완전 분석 - CloudWatch vs X-Ray vs 3rd Party 솔루션</title>
      <link>https://somaz.tistory.com/465</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현대 클라우드 네이티브 애플리케이션에서 포괄적인 모니터링과 가시성 전략은 &lt;b&gt;시스템 성능, 사용자 경험, 운영 상태에 대한 실시간 인사이트를 제공하는 필수 요소&lt;/b&gt;이다. AWS는 강력한 네이티브 모니터링 도구들의 생태계를 제공하는 동시에, 서드파티 솔루션들은 특화된 기능과 멀티클라우드 호환성을 제공한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모니터링 환경은 단순한 메트릭 수집을 넘어 분산 추적, 애플리케이션 성능 모니터링(APM), 지능형 알림 시스템을 포괄하는 방향으로 발전했다. 조직들은 &lt;b&gt;CloudWatch와 X-Ray 같은 AWS 네이티브 솔루션과 Datadog, New Relic, Prometheus&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 포괄적인 분석에서는 &lt;b&gt;다양한 모니터링 접근법의 기술적 역량, 아키텍처 패턴, 비용 영향을 검토&lt;/b&gt;한다. 여러 도구를 효과적으로 결합하는 통합 모니터링 아키텍처 구축 방법, 소음을 줄이면서 중요한 문제를 신속하게 감지하는 지능형 알림 전략, 전체 모니터링 스택의 비용을 최적화하는 방법을 탐구한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2366&quot; data-origin-height=&quot;2254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blUCMH/btsQFq7Y6Kj/bWfUroN30xT41pSDYjdvi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blUCMH/btsQFq7Y6Kj/bWfUroN30xT41pSDYjdvi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blUCMH/btsQFq7Y6Kj/bWfUroN30xT41pSDYjdvi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblUCMH%2FbtsQFq7Y6Kj%2FbWfUroN30xT41pSDYjdvi1%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;2366&quot; height=&quot;2254&quot; data-origin-width=&quot;2366&quot; data-origin-height=&quot;2254&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS&amp;nbsp;모니터링&amp;nbsp;스택&amp;nbsp;완전&amp;nbsp;분석&amp;nbsp;-&amp;nbsp;CloudWatch&amp;nbsp;vs&amp;nbsp;X-Ray&amp;nbsp;vs&amp;nbsp;3rd&amp;nbsp;Party&amp;nbsp;솔루션&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS 네이티브 모니터링 생태계&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS 모니터링 생태계는 CloudWatch를 중심으로 하는 통합된 서비스들로 구성되어 있다. 이 생태계는 인프라 메트릭부터 애플리케이션 성능까지 포괄적인 가시성을 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1168&quot; data-origin-height=&quot;1502&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dTfNfZ/btsQCQteY5F/vgvX1rqdvOJI8rkfl8a9vK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dTfNfZ/btsQCQteY5F/vgvX1rqdvOJI8rkfl8a9vK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dTfNfZ/btsQCQteY5F/vgvX1rqdvOJI8rkfl8a9vK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdTfNfZ%2FbtsQCQteY5F%2FvgvX1rqdvOJI8rkfl8a9vK%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;791&quot; height=&quot;1017&quot; data-origin-width=&quot;1168&quot; data-origin-height=&quot;1502&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Amazon CloudWatch: 기초 모니터링&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;CloudWatch&lt;/b&gt;는 AWS 인프라 모니터링의 중추 신경계 역할을 하며, 포괄적인 메트릭, 로그, 알림 기능을 제공한다. 모든 AWS 서비스와의 깊은 통합으로 대부분의 사용 사례에서 추가적인 에이전트 배포 없이 통합된 모니터링을 가능하게 한다.&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;color: #000000;&quot;&gt;&lt;b&gt;Amazon CloudWatch&lt;/b&gt;는 인프라 메트릭, 애플리케이션 로그, 커스텀 비즈니스 메트릭을 포괄하는 기초적인 모니터링 기능을 제공한다. 이 서비스는 추가 구성 없이 AWS 서비스로부터 자동으로 메트릭을 수집하여, 리소스 활용률, 성능, 운영 상태에 대한 즉각적인 가시성을 제공한다.&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;color: #000000;&quot;&gt;&lt;b&gt;CloudWatch&lt;/b&gt;의 강점은 AWS 생태계와의 원활한 통합에 있다. EC2, RDS, Lambda, ECS 같은 서비스들은 자동으로 CloudWatch에 메트릭을 발행하여, 복잡한 설정 절차 없이 포괄적인 모니터링을 가능하게 한다. 커스텀 메트릭을 통해 조직은 인프라 메트릭과 함께 비즈니스별 KPI를 추적하여 통합적인 모니터링 대시보드를 생성할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메트릭과 차원 데이터&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudWatch는 정교한 필터링과 집계를 가능하게 하는 차원 모델을 사용하여 메트릭을 조직한다. 메트릭은 타임스탬프, 값, 데이터 분석을 위한 컨텍스트를 제공하는 선택적 차원들을 포함한다. 이 구조는 복잡한 쿼리를 지원하고 특정 메트릭 조합에 대한 정밀한 알림을 가능하게 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메트릭 카테고리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수집 방식&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;세분화&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보관 기간&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS 서비스 메트릭&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1분 표준&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;15개월&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;커스텀 애플리케이션 메트릭&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API/SDK&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1초~1일&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;15개월&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;세부 모니터링&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스별 활성화&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1분 세부&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;15개월&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고해상도 메트릭&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;커스텀 발행&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1초 해상도&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3시간~15개월&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudWatch 로그와 인사이트&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudWatch Logs는 강력한 검색 및 분석 기능을 가진 중앙화된 로그 관리를 제공한다. Log Insights는 로그 분석을 위한 SQL 유사 쿼리를 제공하여 신속한 문제 해결과 트렌드 식별을 가능하게 한다. 이 서비스는 자동 파싱 기능으로 구조화되고 비구조화된 로그 형식을 지원한다.&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;color: #000000;&quot;&gt;로그 그룹은 관련 로그 스트림을 조직하고 보관 정책, 액세스 제어, 구독 필터를 제공한다. 구독 필터는 추가 처리나 아카이브를 위해 Kinesis, Lambda, 외부 시스템으로의 실시간 로그 스트리밍을 가능하게 한다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS X-Ray: 분산 추적의 탁월함&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS X-Ray는 성능 병목 지점과 서비스 의존성을 드러내는 포괄적인 추적 기능을 통해 분산 애플리케이션에 대한 깊은 가시성을 제공한다. 많은 AWS 서비스에 대한 자동 계측과 커스텀 추적 지원으로 X-Ray는 상세한 애플리케이션 성능 분석을 가능하게 한다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;분산 추적 아키텍처&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS X-Ray는 분산 애플리케이션을 통한 완전한 요청 흐름을 나타내는 추적을 캡처하고 분석한다. 각 추적은 개별 서비스 호출을 나타내는 세그먼트, 다운스트림 작업을 위한 하위 세그먼트, 검색 가능한 메타데이터를 제공하는 주석으로 구성된다.&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;color: #000000;&quot;&gt;X-Ray의 서비스 맵은 자동으로 애플리케이션 아키텍처와 서비스 의존성을 시각화하여 성능 특성과 장애 패턴을 드러낸다. 이 시각적 표현은 팀이 복잡한 분산 시스템을 이해하고 최적화 기회를 식별하는 데 도움을 준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1916&quot; data-origin-height=&quot;1580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNXomc/btsQCNDg4Ok/2gM9hQPZklYx1Ndkal4Xf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNXomc/btsQCNDg4Ok/2gM9hQPZklYx1Ndkal4Xf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNXomc/btsQCNDg4Ok/2gM9hQPZklYx1Ndkal4Xf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNXomc%2FbtsQCNDg4Ok%2F2gM9hQPZklYx1Ndkal4Xf1%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;1916&quot; height=&quot;1580&quot; data-origin-width=&quot;1916&quot; data-origin-height=&quot;1580&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 분석과 인사이트&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X-Ray Analytics는 추적 데이터에 대한 정교한 쿼리를 가능하게 하여 성능 패턴, 오류 트렌드, 서비스 핫스팟을 식별한다. 분석 엔진은 응답 시간, 오류 상태, 서비스 이름, 커스텀 주석별 필터링을 지원하여 정밀한 성능 분석을 가능하게 한다.&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;color: #000000;&quot;&gt;응답 시간 분포 분석은 다양한 백분위수에 걸친 성능 특성을 드러내어 팀이 현실적인 SLA 목표를 설정하고 조사가 필요한 이상값 요청을 식별하는 데 도움을 준다.&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;&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;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;통합 패턴과 계측&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X-Ray는 자동 계측과 커스텀 SDK 구현을 통해 AWS 서비스와 통합된다. Lambda 함수, ECS 컨테이너, EC2 인스턴스는 최소한의 구성 변경으로 X-Ray 추적을 활성화할 수 있다.&lt;/span&gt;&lt;/p&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스 유형&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;계측 방법&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구성 노력&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 세분화&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Lambda 함수&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;환경 변수&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최소&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;함수 + 다운스트림 호출&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ECS/Fargate&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X-Ray 데몬 사이드카&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보통&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너 + 하위세그먼트&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 인스턴스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X-Ray 데몬 + SDK&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수동 설정&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;애플리케이션 + 인프라&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API Gateway&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;내장 추적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구성 토글&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API 호출 + 백엔드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서드파티 모니터링 솔루션&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서드파티 모니터링 플랫폼은 AWS 네이티브 도구를 보완하는 특화된 기능, 고급 분석, 멀티클라우드 지원을 제공한다. Datadog, New Relic, Prometheus 같은 솔루션들은 특정 모니터링 요구사항과 조직 선호도에 대한 고유한 기능을 제공한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Datadog: 포괄적인 가시성 플랫폼&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Datadog는 고급 APM 기능, 인프라 모니터링, 지능형 알림을 통한 엔드투엔드 가시성을 제공한다. 이 플랫폼은 복잡한 분산 시스템에 대한 통합된 가시성을 제공하는 메트릭, 추적, 로그 간의 상관관계 분석에서 탁월하다.&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;color: #000000;&quot;&gt;주요 차별화 요소로는 정교한 이상 징후 탐지, 예측 분석, 광범위한 통합 생태계가 있다. Datadog의 합성 모니터링 기능은 시뮬레이션된 사용자 트랜잭션을 통한 사전 예방적 문제 감지를 가능하게 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 기능&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;통합 대시보드&lt;/b&gt;: 모든 모니터링 데이터에 대한 단일 창구&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고급 APM&lt;/b&gt;: 코드 수준 가시성을 제공하는 깊은 애플리케이션 성능 인사이트&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;머신러닝&lt;/b&gt;: 자동 이상 징후 감지 및 트렌드 분석&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;합성 모니터링&lt;/b&gt;: 시뮬레이션된 트랜잭션을 통한 사전 예방적 모니터링&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안 모니터링&lt;/b&gt;: 위협 감지를 포함한 SIEM 기능&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;New Relic: 애플리케이션 중심 모니터링&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;New Relic은 상세한 코드 수준 인사이트와 사용자 경험 분석을 제공하는 애플리케이션 성능 모니터링에 중점을 둔다. 이 플랫폼은 포괄적인 오류 추적, 배포 영향 분석, 용량 계획 기능을 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;New Relic의 강점은 애플리케이션 성능, 데이터베이스 쿼리, 외부 서비스 의존성에 대한 상세한 가시성을 제공하는 애플리케이션 중심 접근법에 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;차별화된 기능&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;오류 분석&lt;/b&gt;: 근본 원인 분석을 포함한 포괄적인 오류 추적&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;배포 추적&lt;/b&gt;: 코드 배포에 대한 성능 영향 분석&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;사용자 경험&lt;/b&gt;: 성능 인사이트를 제공하는 실제 사용자 모니터링&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;쿼리 성능&lt;/b&gt;: 데이터베이스 성능 분석 및 최적화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Kubernetes 모니터링&lt;/b&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Prometheus와 Grafana: 오픈소스의 탁월함&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Prometheus와 Grafana는 광범위한 사용자 정의 옵션과 활발한 커뮤니티 지원을 제공하는 강력한 오픈소스 모니터링 기능을 제공한다. 이 조합은 엔터프라이즈급 기능을 가진 비용 효과적인 모니터링을 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Prometheus 생태계는 지능적 라우팅을 위한 AlertManager, 메트릭 수집을 위한 다양한 익스포터, 광범위한 통합 기능을 포함한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3140&quot; data-origin-height=&quot;1030&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgtY3O/btsQCOCdAk2/nf8Ew5XsCtPgCM7Ts8ZD30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgtY3O/btsQCOCdAk2/nf8Ew5XsCtPgCM7Ts8ZD30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgtY3O/btsQCOCdAk2/nf8Ew5XsCtPgCM7Ts8ZD30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgtY3O%2FbtsQCOCdAk2%2Fnf8Ew5XsCtPgCM7Ts8ZD30%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;3140&quot; height=&quot;1030&quot; data-origin-width=&quot;3140&quot; data-origin-height=&quot;1030&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모니터링 솔루션 비교 분석&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;솔루션&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;강점&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최적 사용 사례&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 모델&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;통합 노력&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudWatch&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네이티브 AWS 통합, 자동 메트릭&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS 중심 인프라&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용량 기반&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최소&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X-Ray&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;분산 추적, 서비스 맵&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마이크로서비스 디버깅&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추적당 가격&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보통&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Datadog&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고급 분석, ML 인사이트&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;멀티클라우드 환경&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;호스트당 구독&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보통&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;New Relic&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;애플리케이션 중심 APM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;애플리케이션 성능 집중&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자/데이터 수집당&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보통&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Prometheus/Grafana&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오픈소스, 사용자 정의 가능&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 민감 배포&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인프라 비용만&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;통합 모니터링 아키텍처 설계&lt;/span&gt;&lt;/h3&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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다계층 모니터링 전략&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;엔터프라이즈 모니터링 아키텍처는 특정 목적을 위해 다양한 도구를 결합하는 다계층 전략을 일반적으로 사용한다. 이 접근법은 각 플랫폼의 강점을 활용하면서 비용 효율성과 운영 단순성을 유지한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아키텍처는 인프라 메트릭, 애플리케이션 성능, 분산 추적, 비즈니스 인텔리전스 간의 모니터링 책임을 분할하여 각 계층에 대한 특화된 최적화를 가능하게 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3058&quot; data-origin-height=&quot;988&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dK2jol/btsQFzwIY83/Oi5VSHkaboY1DbnvKqDhk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dK2jol/btsQFzwIY83/Oi5VSHkaboY1DbnvKqDhk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dK2jol/btsQFzwIY83/Oi5VSHkaboY1DbnvKqDhk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdK2jol%2FbtsQFzwIY83%2FOi5VSHkaboY1DbnvKqDhk0%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;3058&quot; height=&quot;988&quot; data-origin-width=&quot;3058&quot; data-origin-height=&quot;988&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;&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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 흐름과 통합 패턴&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;통합 모니터링 아키텍처는 모니터링 데이터를 적절한 분석 플랫폼으로 집계, 상관관계 분석, 라우팅하는 정교한 데이터 흐름 패턴을 필요로 한다. 이벤트 기반 아키텍처는 실시간 처리를 가능하게 하는 반면, 배치 처리는 기록 분석 및 보고를 처리한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;통합 패턴은 다양한 모니터링 도구와 분석 플랫폼 간의 서로 다른 데이터 형식, 샘플링 비율, 지연 시간 요구사항을 수용해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지능형 알림 전략&lt;/span&gt;&lt;/h3&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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;알림 피로 방지&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현대 알림 시스템은 중요한 문제가 즉각적인 주의를 받도록 보장하면서 알림 피로를 방지하기 위해 민감성과 실용성의 균형을 맞춰야 한다. 지능형 알림은 머신러닝, 상관관계 분석, 맥락 정보를 사용하여 노이즈를 줄이고 신호 품질을 향상시킨다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동적 임계값 관리&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정적 임계값은 자연적인 애플리케이션 변동성과 계절적 패턴으로 인해 종종 거짓 양성을 생성한다. 동적 임계값 시스템은 기록 데이터, 머신러닝 알고리즘, 맥락 정보를 사용하여 적응적 알림 기준을 설정한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이상 징후 감지 알고리즘은 정적 임계값이 위반되지 않은 경우에도 문제를 나타낼 수 있는 비정상적인 패턴을 식별하여 사전 예방적 문제 감지 기능을 제공한다.&lt;/span&gt;&lt;/p&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;style10&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;알림 유형&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;감지 방법&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;응답 시간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에스컬레이션 경로&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중요 시스템 장애&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정적 임계값 + 상관관계&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;즉시&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대기자 &amp;rarr; 관리자 &amp;rarr; 경영진&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 저하&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동적 기준선 + ML&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5분&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;팀 채팅 &amp;rarr; 대기자&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;용량 경고&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트렌드 분석 + 예측&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;30분&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이메일 &amp;rarr; 팀 리드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비즈니스 메트릭 이상&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;통계적 분석&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1시간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대시보드 &amp;rarr; 이해관계자&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대시보드 설계 원칙&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;계층화된 정보 아키텍처&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;효과적인 대시보드 설계는 상세한 분석을 위한 드릴다운 기능을 가진 고수준 요약을 제시하는 계층화된 정보 아키텍처를 사용한다. 경영진 대시보드는 비즈니스 메트릭과 전반적인 시스템 상태에 중점을 두는 반면, 운영 대시보드는 문제 해결을 위한 기술적 세부사항을 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대시보드 계층구조&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;경영진 수준&lt;/b&gt;: 비즈니스 KPI, SLA 준수, 비용 트렌드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;운영 수준&lt;/b&gt;: 시스템 메트릭, 성능 지표, 알림 상태&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;기술 수준&lt;/b&gt;: 상세 메트릭, 추적 분석, 디버그 정보&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;인시던트 대응&lt;/b&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;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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실시간 vs 기록 분석&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대시보드 설계는 실시간 모니터링 요구사항과 기록 분석 기능의 균형을 맞춰야 한다. 실시간 대시보드는 문제에 대한 즉각적인 대응을 가능하게 하는 반면, 기록 뷰는 트렌드 분석, 용량 계획, 사후 인시던트 검토를 지원한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2974&quot; data-origin-height=&quot;558&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZRxVv/btsQEFxMaJG/XrFLyPnX6hK8jmf8HOKHkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZRxVv/btsQEFxMaJG/XrFLyPnX6hK8jmf8HOKHkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZRxVv/btsQEFxMaJG/XrFLyPnX6hK8jmf8HOKHkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZRxVv%2FbtsQEFxMaJG%2FXrFLyPnX6hK8jmf8HOKHkk%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;2974&quot; height=&quot;558&quot; data-origin-width=&quot;2974&quot; data-origin-height=&quot;558&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시각적 설계와 사용자 경험&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설계 가이드라인&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;색상 코딩&lt;/b&gt;: 상태 표시를 위한 일관된 색상 스키마 (녹색/노란색/빨간색)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;정보 밀도&lt;/b&gt;: 인지적 과부하를 피하는 균형 잡힌 정보 밀도&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;네비게이션&lt;/b&gt;: 관련 뷰 간의 맥락적 연결을 가진 직관적 네비게이션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;반응형 설계&lt;/b&gt;: 대기 엔지니어를 위한 모바일 친화적 레이아웃&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;접근성&lt;/b&gt;: 색맹 친화적 팔레트와 스크린 리더 호환성&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 전략&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS 네이티브 비용 관리&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudWatch와 X-Ray 비용은 데이터 볼륨, 메트릭 빈도, 보관 기간에 따라 확장된다. 전략적 비용 최적화는 가격 모델을 이해하고 적절한 데이터 보관 및 샘플링 정책을 구현하는 것을 요구한다.&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;&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;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudWatch 비용 최적화&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;메트릭 필터링&lt;/b&gt;: 필수 커스텀 메트릭만 발행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;로그 보관&lt;/b&gt;: 계층화된 보관 정책 구현&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;대시보드 최적화&lt;/b&gt;: 위젯 수와 새로고침 빈도 최소화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예약 용량&lt;/b&gt;: 예측 가능한 워크로드에 CloudWatch Logs 예약 용량 사용&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X-Ray 비용 최적화&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;샘플링 규칙&lt;/b&gt;: 추적 볼륨을 줄이기 위한 지능적 샘플링 구현&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;서비스 우선순위&lt;/b&gt;: 중요한 서비스는 높은 샘플링, 백그라운드 작업은 낮은 샘플링&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보관 관리&lt;/b&gt;: 적절한 추적 보관 기간 구성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;지역 최적화&lt;/b&gt;: 애플리케이션과 가장 가까운 지역에 X-Ray 배포&lt;/span&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; data-ke-style=&quot;style10&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스&amp;nbsp;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 구성요소&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최적화 전략&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;잠재적 절약&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudWatch 메트릭&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;커스텀 메트릭 ($0.30/메트릭/월)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메트릭 집계, 필터링&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;30-50%&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudWatch 로그&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수집 + 저장&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로그 레벨 필터링, 보관 정책&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;40-60%&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X-Ray 추적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기록된 추적당&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지능적 샘플링 규칙&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;50-80%&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudWatch 대시보드&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대시보드당 월별&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;통합된 대시보드&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;20-40%&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;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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서드파티 솔루션 비용 분석&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서드파티 모니터링 솔루션은 일반적으로 데이터 볼륨, 호스트 수, 기능 사용량에 따라 비용이 확장되는 구독 기반 가격 모델을 사용한다. 비용 최적화는 신중한 기능 선택과 데이터 볼륨 관리를 요구한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 전략&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;기능 선택&lt;/b&gt;: 필요한 모니터링 기능만 활성화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;데이터 샘플링&lt;/b&gt;: 고볼륨, 저가치 데이터에 대한 샘플링 구현&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보관 정책&lt;/b&gt;: 보관 요구사항과 저장 비용의 균형&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;라이센스 최적화&lt;/b&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;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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하이브리드 아키텍처 비용 혜택&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하이브리드 모니터링 아키텍처는 포괄적인 커버리지를 유지하면서 각 플랫폼의 비용 효과적인 기능을 활용하여 상당한 비용 절약을 달성할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;nix&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 비용 최적화된 모니터링 구성
resource &quot;aws_cloudwatch_log_group&quot; &quot;cost_optimized_logs&quot; {
  for_each = {
    critical    = { retention = 90, class = &quot;STANDARD&quot; }
    important   = { retention = 30, class = &quot;STANDARD&quot; }
    general     = { retention = 7,  class = &quot;INFREQUENT_ACCESS&quot; }
    debug       = { retention = 3,  class = &quot;INFREQUENT_ACCESS&quot; }
  }

  name              = &quot;/aws/application/${each.key}&quot;
  retention_in_days = each.value.retention
  log_group_class   = each.value.class

  tags = {
    Environment = &quot;production&quot;
    LogLevel    = each.key
    CostTier    = each.value.class
  }
}

# 비용 최적화를 위한 메트릭 필터링
resource &quot;aws_cloudwatch_log_metric_filter&quot; &quot;cost_optimized_errors&quot; {
  name           = &quot;CriticalErrorsOnly&quot;
  log_group_name = aws_cloudwatch_log_group.cost_optimized_logs[&quot;critical&quot;].name
  pattern        = &quot;[timestamp, request_id, level=ERROR|FATAL, ...]&quot;

  metric_transformation {
    name      = &quot;CriticalErrors&quot;
    namespace = &quot;Application/Critical&quot;
    value     = &quot;1&quot;
  }
}

# 비용 제어를 위한 X-Ray 샘플링
resource &quot;aws_xray_sampling_rule&quot; &quot;cost_optimized_sampling&quot; {
  rule_name      = &quot;CostOptimizedSampling&quot;
  priority       = 9000
  version        = 1
  reservoir_size = 1
  fixed_rate     = 0.05  # 일반 트래픽에 5% 샘플링
  url_path       = &quot;*&quot;
  host           = &quot;*&quot;
  http_method    = &quot;*&quot;
  service_type   = &quot;*&quot;
  service_name   = &quot;*&quot;
  resource_arn   = &quot;*&quot;

  tags = {
    Environment = &quot;production&quot;
    CostTier    = &quot;optimized&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고급 모니터링 패턴&lt;/span&gt;&lt;/h3&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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;합성 모니터링과 사용자 경험&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구현 전략에는 다음이 포함된다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;API 상태 검사&lt;/b&gt;: 중요한 API 엔드포인트의 자동화된 테스트&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;사용자 여정 시뮬레이션&lt;/b&gt;: 완전한 사용자 워크플로우 테스트&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;지리적 분산&lt;/b&gt;: 여러 글로벌 위치에서의 테스트&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;성능 기준선&lt;/b&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;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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;카오스 엔지니어링 통합&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현대 모니터링 시스템은 시스템 복원력과 모니터링 효율성을 검증하기 위해 카오스 엔지니어링 관행과 통합된다. 제어된 장애 주입은 모니터링 시스템의 응답성과 알림 정확도를 테스트한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2958&quot; data-origin-height=&quot;960&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Iivar/btsQCslSDIs/K2GyXdk06m5FnnAYmApPeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Iivar/btsQCslSDIs/K2GyXdk06m5FnnAYmApPeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Iivar/btsQCslSDIs/K2GyXdk06m5FnnAYmApPeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIivar%2FbtsQCslSDIs%2FK2GyXdk06m5FnnAYmApPeK%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;2958&quot; height=&quot;960&quot; data-origin-width=&quot;2958&quot; data-origin-height=&quot;960&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;&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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;머신러닝 강화 모니터링&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모니터링에서의 ML 응용&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;이상 징후 감지&lt;/b&gt;: 비정상적인 패턴 식별을 위한 통계적 분석&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예측적 스케일링&lt;/b&gt;: 기록 패턴을 기반으로 한 리소스 요구사항 예측&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;근본 원인 분석&lt;/b&gt;: 빠른 문제 식별을 위한 상관관계 분석&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;알림 최적화&lt;/b&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안과 컴플라이언스 모니터링&lt;/span&gt;&lt;/h3&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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 이벤트 상관관계&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;AWS 보안 서비스와의 통합은 포괄적인 위협 감지를 가능하게 한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GuardDuty 통합&lt;/b&gt;: 모니터링 상관관계를 통한 위협 감지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;CloudTrail 분석&lt;/b&gt;: API 활동 모니터링 및 이상 징후 감지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Config 준수&lt;/b&gt;: 구성 드리프트 감지 및 알림&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Security Hub&lt;/b&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;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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컴플라이언스와 감사 요구사항&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컴플라이언스 고려사항&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;데이터 보관&lt;/b&gt;: 감사 요구사항을 위한 장기 저장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;액세스 로깅&lt;/b&gt;: 포괄적인 액세스 추적 유지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;변경 추적&lt;/b&gt;: 구성 및 코드 변경 상관관계&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보고서 생성&lt;/b&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;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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 튜닝과 최적화&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모니터링 시스템 성능&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 최적화 영역&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;데이터 수집&lt;/b&gt;: 효율적인 에이전트 구성 및 샘플링 전략&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;처리 파이프라인&lt;/b&gt;: 실시간 분석을 위한 스트림 처리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;저장 최적화&lt;/b&gt;: 액세스 패턴을 기반으로 한 계층화된 저장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;쿼리 성능&lt;/b&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;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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;미래 트렌드와 발전&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드로서의 관찰가능성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모니터링 환경은 모니터링 구성, 대시보드, 알림 규칙이 버전 제어되고 CI/CD 파이프라인을 통해 배포되는 &quot;코드로서의 관찰가능성&quot; 방향으로 발전하고 있다. 이 접근법은 환경 간 일관된 모니터링을 가능하게 하고 모니터링 변경의 신속한 배포를 가능하게 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 개념&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;구성 관리&lt;/b&gt;: 버전 제어된 모니터링 구성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;대시보드 코드화&lt;/b&gt;: 프로그래밍적 대시보드 생성 및 유지보수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;알림 규칙 관리&lt;/b&gt;: 자동화된 알림 규칙 배포 및 테스트&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;모니터링 테스트&lt;/b&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;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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AI 기반 운영 (AIOps)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인공지능은 지능적 패턴 인식, 예측 분석, 자동화된 응답 시스템을 통해 모니터링 기능을 점점 더 향상시키고 있다. AIOps 플랫폼은 문제 감지 및 해결 속도를 향상시키면서 수동 개입을 줄인다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1666&quot; data-origin-height=&quot;916&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qCJyK/btsQD3MrnFI/0edEVJ3T0NoiCLcjwRfgck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qCJyK/btsQD3MrnFI/0edEVJ3T0NoiCLcjwRfgck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qCJyK/btsQD3MrnFI/0edEVJ3T0NoiCLcjwRfgck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqCJyK%2FbtsQD3MrnFI%2F0edEVJ3T0NoiCLcjwRfgck%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;1666&quot; height=&quot;916&quot; data-origin-width=&quot;1666&quot; data-origin-height=&quot;916&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS 모니터링 환경은 다양한 조직 요구사항을 충족하는 &lt;b&gt;포괄적인 관찰가능성 솔루션을 구축&lt;/b&gt;하기 위한 정교한 옵션을 제공한다. CloudWatch는 깊은 AWS 통합을 가진 기초적 모니터링을 제공하고, X-Ray는 복잡한 마이크로서비스 아키텍처를 위한 상세한 분산 추적을 가능하게 하며, 서드파티 솔루션은 특화된 기능과 멀티클라우드 지원을 제공한다.&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;color: #000000;&quot;&gt;모니터링 구현에서의 성공은 도구 선택을 넘어서는 &lt;b&gt;전략적 사고를 요구&lt;/b&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;color: #000000;&quot;&gt;모니터링 시스템이 애플리케이션 성장과 함께 확장됨에 따라 &lt;b&gt;비용 최적화는 중요한 고려사항&lt;/b&gt;으로 남아있다. 샘플링, 보관 정책, 기능 선택의 전략적 사용은 모니터링 효율성을 유지하면서 운영 비용을 상당히 줄일 수 있다. AWS 네이티브 도구와 서드파티 솔루션을 결합하는 하이브리드 접근법은 종종 최적의 비용 대비 성능 비율을 제공한다.&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;color: #000000;&quot;&gt;모니터링의 미래는 &lt;b&gt;AI 강화 기능, 엣지 컴퓨팅 지원, 코드로서의 관찰가능성 관행&lt;/b&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;color: #000000;&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;color: #000000;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/cloudwatch/&quot;&gt;Amazon CloudWatch 사용자 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/xray/&quot;&gt;AWS X-Ray 개발자 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/&quot;&gt;AWS Well-Architected Framework - 신뢰성 기둥&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://aws.amazon.com/cloudwatch/pricing/&quot;&gt;CloudWatch 가격 책정&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://aws.amazon.com/xray/pricing/&quot;&gt;X-Ray 가격 책정&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.datadoghq.com/integrations/amazon_web_services/&quot;&gt;Datadog AWS 통합 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.newrelic.com/docs/infrastructure/&quot;&gt;New Relic 인프라 모니터링&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://prometheus.io/docs/&quot;&gt;Prometheus 모니터링 시스템&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://grafana.com/docs/&quot;&gt;Grafana 문서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://aws-observability.github.io/observability-best-practices/&quot;&gt;AWS 관찰가능성 베스트 프랙티스&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://opentelemetry.io/docs/&quot;&gt;OpenTelemetry 문서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://sre.google/sre-book/table-of-contents/&quot;&gt;사이트 신뢰성 엔지니어링 - Google&lt;/a&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;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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>AWS</category>
      <category>3rdparty</category>
      <category>AWS</category>
      <category>CloudWatch</category>
      <category>monitoring</category>
      <category>X-RAY</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/465</guid>
      <comments>https://somaz.tistory.com/465#entry465comment</comments>
      <pubDate>Tue, 21 Apr 2026 00:00:05 +0900</pubDate>
    </item>
    <item>
      <title>Kubernetes 1.34.x gRPC etcd Warning 버그 상세 분석</title>
      <link>https://somaz.tistory.com/503</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes v1.34로 업그레이드한 후, kube-apiserver 로그에 아래와 같은 Warning이 30초마다 반복적으로 출력되는 현상이 보고되고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;W0407 09:18:02.032615  grpc: addrConn.createTransport failed to connect to 
{Addr: &quot;10.10.10.17:2379&quot;} Err: connection error: desc = &quot;transport: Error while 
dialing: dial tcp 10.10.10.17:2379: operation was canceled&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;이 로그만 보면 etcd 연결이 끊긴 것처럼 보이지만, 실제로는 클러스터 동작에 전혀 영향이 없는 무해한 Warning이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 포스팅에서는 이 Warning이 왜 발생하는지, v1.33에서는 왜 안 나왔는지, 그리고 언제 수정될 예정인지를 정리해본다.&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/kubernetes/kubernetes/issues/134080&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/kubernetes/kubernetes/issues/134080&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1775555379174&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;kube-apiserver log spammed with &amp;quot;failed to connect to etcd&amp;quot; &amp;middot; Issue #134080 &amp;middot; kubernetes/kubernetes&quot; data-og-description=&quot;What happened? Running 1.34.1 with talos 1.11.0 (etcd 3.6.4). It doesn't seem to be related to talos. All kube-apiserver logs are spammed every 15sec with grpc: addrConn.createTransport failed to c...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/kubernetes/kubernetes/issues/134080&quot; data-og-url=&quot;https://github.com/kubernetes/kubernetes/issues/134080&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cMHejr/dJMb88e1qQH/XHewUZZvK0wW89c9ebi9k1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/Rkb7h/dJMb8UHPU6F/kA9YGx9kZjg2Ruuuwfgcp1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/kubernetes/kubernetes/issues/134080&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/kubernetes/kubernetes/issues/134080&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cMHejr/dJMb88e1qQH/XHewUZZvK0wW89c9ebi9k1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/Rkb7h/dJMb8UHPU6F/kA9YGx9kZjg2Ruuuwfgcp1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;kube-apiserver log spammed with &quot;failed to connect to etcd&quot; &amp;middot; Issue #134080 &amp;middot; kubernetes/kubernetes&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;What happened? Running 1.34.1 with talos 1.11.0 (etcd 3.6.4). It doesn't seem to be related to talos. All kube-apiserver logs are spammed every 15sec with grpc: addrConn.createTransport failed to c...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.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;
&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;2420&quot; data-origin-height=&quot;1240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eePq3D/dJMcad2AQFe/gNJmnYUmosQU4h9OlaCsb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eePq3D/dJMcad2AQFe/gNJmnYUmosQU4h9OlaCsb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eePq3D/dJMcad2AQFe/gNJmnYUmosQU4h9OlaCsb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeePq3D%2FdJMcad2AQFe%2FgNJmnYUmosQU4h9OlaCsb0%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;2420&quot; height=&quot;1240&quot; data-origin-width=&quot;2420&quot; data-origin-height=&quot;1240&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 의존성 변경&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;K8s v1.34에서는 etcd와 gRPC 관련 핵심 의존성이 메이저 업그레이드되었다.&lt;/span&gt;&lt;/p&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구분&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.33&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.34&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd client&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v3.5.21&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v3.6.4&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;gRPC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.68.1&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.72.1&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;단순한 패치 업데이트가 아니라 &lt;b&gt;메이저 버전 변경&lt;/b&gt;이기 때문에, 내부 동작 방식이 크게 바뀌었다.&lt;/u&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;용어 설명&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;&lt;b&gt;gRPC&lt;/b&gt; &amp;mdash; Google이 만든 고성능 RPC(Remote Procedure Call) 프레임워크. Kubernetes에서 kube-apiserver와 etcd가 통신할 때 사용하는 프로토콜이다.&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;color: #000000;&quot;&gt;&lt;b&gt;balancer&lt;/b&gt; &amp;mdash; gRPC 내부에서 여러 서버(endpoint)에 요청을 분배하는 로직. 어떤 서버에 연결할지, 연결이 끊기면 어떻게 재시도할지를 결정한다.&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;color: #000000;&quot;&gt;&lt;b&gt;SubConn&lt;/b&gt; &amp;mdash; gRPC에서 하나의 서버 주소에 대한 물리적 연결 단위. balancer가 SubConn을 생성하고 관리한다.&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;color: #000000;&quot;&gt;&lt;b&gt;TLS handshake&lt;/b&gt; &amp;mdash; 암호화된 통신을 시작하기 전에 클라이언트와 서버가 인증서를 교환하고 암호화 방식을 합의하는 과정. etcd는 기본적으로 TLS를 사용하므로, 새 연결마다 이 과정이 필요하다.&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;color: #000000;&quot;&gt;&lt;b&gt;pickfirstleaf&lt;/b&gt; &amp;mdash; gRPC v1.72에서 새로 도입된 balancer 구현체. 이전의 `round_robin balancer` 를 대체한다.&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;color: #000000;&quot;&gt;&lt;b&gt;monitorCollector&lt;/b&gt; &amp;mdash; kube-apiserver 내부에서 etcd 스토리지 크기(`apiserver_storage_size_bytes`) 메트릭을 수집하는 컴포넌트.&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;원인 (Root Cause)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kube-apiserver의 `/metrics` 엔드포인트에는 `apiserver_storage_size_bytes` 메트릭을 수집하는 `monitorCollector` 가 있다. &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;color: #000000;&quot;&gt;이 컴포넌트는 메트릭을 수집할 때마다 다음과 같은 흐름을 거친다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;Prometheus가 /metrics 스크래핑 요청
  &amp;rarr; monitorCollector.CollectWithStability() 호출
    &amp;rarr; 새 etcd 클라이언트 생성
    &amp;rarr; client.Status() 호출 (gRPC 연결 2개 생성)
    &amp;rarr; 즉시 client.Close()&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;핵심은 &lt;b&gt;매 스크래핑마다 etcd 클라이언트를 새로 만들고 바로 닫는다&lt;/b&gt;는 것이다.&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;이 패턴 자체는 v1.33에도 동일하게 존재했다. 하지만 v1.33에서는 문제가 없었다.&lt;/u&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;&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;
&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;color: #000000;&quot;&gt;왜 v1.34에서만 문제인가&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;gRPC 내부의 balancer 구현이 완전히 바뀌었기 때문이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.33 (gRPC v1.68)&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;mipsasm&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;round_robin balancer
  └── base.NewBalancerBuilder 사용
  └── Close()가 no-op (아무것도 안 함)
  └── 연결 정리 중 Warning이 발생하지 않음&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;`round_robin balancer` 의 `Close()` 메서드가 사실상 아무 작업도 하지 않았기 때문에, etcd 클라이언트를 만들자마자 닫아도 깔끔하게 종료되었다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.34 (gRPC v1.72)&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;mipsasm&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;round_robin balancer (재작성됨)
  └── endpointsharding + pickfirstleaf 사용
  └── Close()가 SubConn 생명주기를 적극 관리
  └── 아직 진행 중인 TLS handshake가 cancel됨
  └── &quot;operation was canceled&quot; Warning 발생&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;새 구현에서는 `Close()` 가 모든 `SubConn` 의 상태를 추적하고 정리한다. &lt;/u&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;color: #000000;&quot;&gt;&lt;u&gt;문제는 `Close()` 가 호출되는 시점에 아직 TLS handshake가 진행 중인 `SubConn` 이 있을 수 있다는 것이다. 이때 진행 중인 연결이 강제로 cancel되면서 Warning이 출력된다.&lt;/u&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;color: #000000;&quot;&gt;&lt;u&gt;추가로 etcd client v3.6에서 resolver 업데이트 방식이 Addresses &amp;rarr; Endpoints로 변경되면서, 새로운 gRPC 코드 경로가 활성화된 것도 원인 중 하나이다.&lt;/u&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;&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;
&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;color: #000000;&quot;&gt;전체 흐름 정리&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;Prometheus --30초마다--&amp;gt; kube-apiserver /metrics 스크래핑
  │
  ▼
  새 etcd client 생성
  │
  ▼
  gRPC가 SubConn 열기 시작 (TLS handshake 진행 중...)
  │
  ▼
  즉시 Close() 호출
  │
  ▼
  gRPC pickfirstleaf가 아직 연결 중인 SubConn을 cancel
  │
  ▼
  &quot;operation was canceled&quot; Warning 출력
  │
  ▼
  실제 메트릭 수집은 기존 연결로 정상 동작&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;30초마다 Warning이 나오는 이유는 Prometheus의 기본 스크래핑 간격이 30초이기 때문이다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스크래핑할 때마다 새 etcd 클라이언트를 만들고 닫으면서 매번 같은 Warning이 발생하는 것이다.&lt;/span&gt;&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;&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;
&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;color: #000000;&quot;&gt;영향 범위&lt;/span&gt;&lt;/h3&gt;
&lt;div&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;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;영향&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클러스터 동작&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;전혀 영향 없음.&lt;/b&gt; 기존 ESTABLISHED 연결은 정상 동작&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd 데이터&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;영향 없음. 읽기/쓰기 정상&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로그&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;30초마다 Warning 1줄 출력 (스크래핑 간격과 동일)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;알림&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;KubeAPIErrorBudgetBurn 알림이 발생할 수 있음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;영향 없음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;span style=&quot;color: #000000;&quot;&gt;실제로 확인해보면 etcd는 정상 동작 중이다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# etcd 상태 확인
sudo systemctl status etcd
# Active: active (running) ✅

# etcd 포트 리스닝 확인
sudo ss -tlnp | grep 2379
# LISTEN 0 4096 10.10.10.17:2379 ✅&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;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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대응 방법&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지금 당장은?&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;무시해도 된다.&lt;/b&gt; 클러스터 동작에 전혀 영향이 없는 cosmetic한 Warning이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다만 모니터링 알림이 거슬린다면, `KubeAPIErrorBudgetBurn` 알림 규칙에서 이 패턴을 제외하거나 severity를 낮추는 것을 고려할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;근본 수정은?&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes 공식 이슈 &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/kubernetes/kubernetes/issues/138075&quot;&gt;kubernetes/kubernetes#138075&lt;/a&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;color: #000000;&quot;&gt;수정 방향은 `/metrics` 스크래핑 시 &lt;b&gt;etcd 클라이언트를 매번 새로 만들지 않고 기존 연결을 재사용&lt;/b&gt;하도록 변경하는 것이다. 이렇게 하면 매번 gRPC 연결을 열고 닫는 과정이 사라지므로 Warning도 발생하지 않는다.&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;color: #000000;&quot;&gt;다음 패치 릴리즈(v1.34.4 이후 또는 v1.35.x)에서 수정이 포함될 것으로 예상된다.&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;&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;
&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;color: #000000;&quot;&gt;비슷한 상황에서의 판단 기준&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드 후 etcd 관련 Warning이 보일 때, 실제 문제인지 아닌지 판단하는 기준을 정리한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;무해한 경우 (이번 케이스)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Warning이 일정 간격(30초)으로 규칙적으로 반복&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd가 active (running) 상태&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kubectl get nodes, kubectl get pods 등이 정상 동작&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd 포트(2379)가 리스닝 중&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실제 문제인 경우&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Error 레벨 로그가 출력됨 (Warning이 아니라 Error)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd 서비스가 죽어있거나 재시작을 반복&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kubectl 명령이 응답하지 않거나 타임아웃&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd 포트가 리스닝되지 않음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Pod 생성/삭제가 안 됨&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;&lt;span style=&quot;color: #000000;&quot;&gt;마무리: &quot;Warning은 항상 위험 신호는 아니다&quot;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes를 운영하다 보면 업그레이드 후 낯선 Warning 로그를 만나는 경우가 많다. 이번 케이스처럼 내부 의존성(gRPC, etcd client)의 메이저 업그레이드로 인해 이전에는 없던 로그가 새로 나타나기도 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중요한 것은 &lt;b&gt;Warning 자체가 아니라 실제 영향&lt;/b&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd가 정상이고, 클러스터가 정상 동작하고, 규칙적인 간격으로 나오는 Warning이라면 대부분 무해하다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;반면 불규칙하게 터지는 Error, 서비스 중단, 타임아웃이 동반된다면 즉시 대응이 필요하다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 버그는 이미 Kubernetes 커뮤니티에서 인지하고 있으며, 다음 패치에서 수정될 예정이다. 그 전까지는 안심하고 운영하면 된다.&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;&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;
&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/kubernetes/kubernetes/issues/138075&quot;&gt;kubernetes/kubernetes#138075 &amp;mdash; etcd client reuse for metrics&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/grpc/grpc-go/releases/tag/v1.72.0&quot;&gt;gRPC v1.72 Release Notes&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.6.md&quot;&gt;etcd client v3.6 Changelog&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.34.md&quot;&gt;Kubernetes v1.34 Release Notes&lt;/a&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Container Orchestration/Kubernetes</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/503</guid>
      <comments>https://somaz.tistory.com/503#entry503comment</comments>
      <pubDate>Mon, 20 Apr 2026 00:00:29 +0900</pubDate>
    </item>
    <item>
      <title>AWS Lambda vs ECS vs EKS 컨테이너 전략</title>
      <link>https://somaz.tistory.com/464</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라우드 네이티브 애플리케이션 개발에서 컨테이너 전략 선택은 시스템의 성능, 확장성, 비용 효율성을 결정하는 핵심 요소이다. AWS에서는 서버리스 Lambda부터 완전 관리형 Kubernetes인 EKS까지 다양한 컨테이너 실행 옵션을 제공하고 있다.&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;color: #000000;&quot;&gt;이 글에서는 AWS Lambda, ECS(Elastic Container Service), EKS(Elastic Kubernetes Service)의 특징과 각각의 스위트 스팟을 분석하고, 실무진에서 고려해야 할 마이그레이션 전략에 대해 살펴보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZrPU2/dJMcadHq2vk/xjMG6y2kTIcfnTKrpA87zK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZrPU2/dJMcadHq2vk/xjMG6y2kTIcfnTKrpA87zK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZrPU2/dJMcadHq2vk/xjMG6y2kTIcfnTKrpA87zK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZrPU2%2FdJMcadHq2vk%2FxjMG6y2kTIcfnTKrpA87zK%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;AWS&amp;nbsp;Lambda&amp;nbsp;vs&amp;nbsp;ECS&amp;nbsp;vs&amp;nbsp;EKS&amp;nbsp;컨테이너&amp;nbsp;전략&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS 컨테이너 서비스 비교&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스 특성 개요&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3098&quot; data-origin-height=&quot;794&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dFsKo2/btsQDF5oFGM/rgqLxWyrUOrU7kHiyqKekK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dFsKo2/btsQDF5oFGM/rgqLxWyrUOrU7kHiyqKekK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dFsKo2/btsQDF5oFGM/rgqLxWyrUOrU7kHiyqKekK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdFsKo2%2FbtsQDF5oFGM%2FrgqLxWyrUOrU7kHiyqKekK%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;3098&quot; height=&quot;794&quot; data-origin-width=&quot;3098&quot; data-origin-height=&quot;794&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 특징 비교표&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;항목&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS Lambda&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Amazon ECS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Amazon EKS&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;관리 수준&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완전 서버리스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;부분 관리형&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완전 관리형&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실행 시간 제한&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;15분&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한 없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한 없음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;콜드 스타트&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;있음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;없음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;확장성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동, 즉시&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동/수동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동/수동&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비용 모델&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;요청 기반&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인스턴스 기반&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인스턴스 기반&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;학습 곡선&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;컨테이너 크기&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10GB 제한&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한 없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한 없음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 서비스의 스위트 스팟&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2100&quot; data-origin-height=&quot;1136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GwHKr/btsQCPNPDFF/eEMpeyd1XKOYeV9IXpnDi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GwHKr/btsQCPNPDFF/eEMpeyd1XKOYeV9IXpnDi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GwHKr/btsQCPNPDFF/eEMpeyd1XKOYeV9IXpnDi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGwHKr%2FbtsQCPNPDFF%2FeEMpeyd1XKOYeV9IXpnDi0%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;2100&quot; height=&quot;1136&quot; data-origin-width=&quot;2100&quot; data-origin-height=&quot;1136&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS Lambda의 최적 사용 사례&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Lambda는 다음과 같은 워크로드에서 최고의 성능을 발휘한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;이벤트 기반 처리&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API Gateway와 연동한 RESTful API&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;S3 이벤트 트리거 기반 파일 처리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DynamoDB 스트림 기반 데이터 변환&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudWatch 이벤트 기반 스케줄링&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;마이크로서비스 아키텍처&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단순한 비즈니스 로직 처리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부 API 호출 및 데이터 변환&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인증 및 권한 부여 서비스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이메일/SMS 발송 서비스&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Amazon ECS의 최적 사용 사례&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ECS는 AWS 생태계 내에서 안정적인 컨테이너 운영이 필요한 경우에 적합하다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;웹 애플리케이션&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간 규모의 모놀리식 애플리케이션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마이크로서비스 클러스터&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배치 작업 처리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CI/CD 파이프라인&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;데이터 처리 워크로드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ETL 작업&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로그 분석 시스템&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실시간 데이터 스트리밍&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Amazon EKS의 최적 사용 사례&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EKS는 복잡한 컨테이너 오케스트레이션과 표준 Kubernetes 기능이 필요한 경우에 선택된다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;엔터프라이즈 애플리케이션&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대규모 마이크로서비스 아키텍처&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡한 배포 전략이 필요한 애플리케이션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;멀티 리전 배포&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;고급 운영 요구사항&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;세밀한 리소스 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;커스텀 네트워킹&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고급 모니터링 및 로깅&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GitOps 기반 배포&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마이그레이션 전략&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단계별 마이그레이션 접근법&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1310&quot; data-origin-height=&quot;1236&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ekMd2D/btsQD1NKg7R/prZ5wZx9YGm2clxcYoz9IK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ekMd2D/btsQD1NKg7R/prZ5wZx9YGm2clxcYoz9IK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ekMd2D/btsQD1NKg7R/prZ5wZx9YGm2clxcYoz9IK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FekMd2D%2FbtsQD1NKg7R%2FprZ5wZx9YGm2clxcYoz9IK%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;670&quot; height=&quot;632&quot; data-origin-width=&quot;1310&quot; data-origin-height=&quot;1236&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마이그레이션 의사결정 매트릭스&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;요소&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Lambda 선택&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ECS 선택&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;EKS 선택&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개발팀 규모&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;소규모 (1-5명)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간 (5-15명)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대규모 (15명+)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;애플리케이션 복잡도&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단순&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실행 시간&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;lt; 15분&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한 없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한 없음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;트래픽 패턴&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;간헐적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일정함&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다양함&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;운영 리소스&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최소&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;많음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Kubernetes 경험&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;불필요&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;불필요&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;필수&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실무 마이그레이션 가이드라인&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1단계: 현재 상태 평가&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;애플리케이션 아키텍처 분석&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 요구사항 정의&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;팀의 기술 역량 평가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;2단계: 파일럿 프로젝트 실행&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;작은 규모의 컴포넌트부터 시작&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 서비스별 POC 진행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 및 비용 데이터 수집&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;3단계: 점진적 마이그레이션&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Strangler Fig 패턴 적용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스별 단계적 이관&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모니터링 및 알람 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 전략&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스별 비용 구조&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Lambda 비용 최적화&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메모리 할당량 최적화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실행 시간 단축&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Provisioned Concurrency 활용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ARM 기반 Graviton2 사용&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ECS 비용 최적화&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate vs EC2 모드 선택&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스팟 인스턴스 활용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;적절한 인스턴스 크기 선택&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;EKS 비용 최적화&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클러스터 오토스케일러 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스팟 인스턴스 혼합 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네임스페이스별 리소스 할당&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;통합 모니터링 및 거버넌스&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1364&quot; data-origin-height=&quot;1376&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6PNDS/btsQDvawnw2/a41EmWaWbRkq7WmqNb19zK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6PNDS/btsQDvawnw2/a41EmWaWbRkq7WmqNb19zK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6PNDS/btsQDvawnw2/a41EmWaWbRkq7WmqNb19zK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6PNDS%2FbtsQDvawnw2%2Fa41EmWaWbRkq7WmqNb19zK%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;543&quot; height=&quot;548&quot; data-origin-width=&quot;1364&quot; data-origin-height=&quot;1376&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성공 사례 및 베스트 프랙티스&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하이브리드 접근법&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;전형적인 조합 패턴&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;API Gateway + Lambda + ECS&lt;/b&gt;: 간단한 API는 Lambda로, 복잡한 처리는 ECS로&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;EKS + Lambda&lt;/b&gt;: 메인 애플리케이션은 EKS에서, 이벤트 처리는 Lambda로&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;All-in-One EKS&lt;/b&gt;: 모든 워크로드를 EKS에서 통합 관리&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영 관점에서의 고려사항&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;보안 및 컴플라이언스&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IAM 역할 기반 권한 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPC 네트워킹 설계&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;암호화 및 시크릿 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개발자 경험&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CI/CD 파이프라인 통합&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로컬 개발 환경 구성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;디버깅 및 테스팅 도구&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;AWS의 컨테이너 서비스 선택은&lt;/b&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;color: #000000;&quot;&gt;&lt;b&gt;Lambda&lt;/b&gt;는 서버리스의 편의성과 비용 효율성을 제공하지만, 실행 시간 제한과 콜드 스타트 이슈가 있다. &lt;b&gt;ECS&lt;/b&gt;는 AWS 생태계와의 깊은 통합과 관리의 용이성을 제공하며, &lt;b&gt;EKS&lt;/b&gt;는 Kubernetes의 강력한 기능과 표준화된 접근법을 활용할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;앞으로는 &lt;b&gt;서버리스 컨테이너, 멀티 클라우드 환경, AI/ML 워크로드 최적화 등 새로운 트렌드에 맞춘 전략 수립&lt;/b&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;&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;
&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/lambda/&quot;&gt;AWS Lambda Developer Guide&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/ecs/&quot;&gt;Amazon ECS Developer Guide&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/eks/&quot;&gt;Amazon EKS User Guide&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://aws.amazon.com/architecture/well-architected/&quot;&gt;AWS Well-Architected Framework&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://aws.amazon.com/containers/&quot;&gt;AWS Container Services Overview&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubernetes.io/docs/&quot;&gt;Kubernetes Official Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://aws.amazon.com/aws-cost-management/aws-cost-optimization/&quot;&gt;AWS Cost Optimization Best Practices&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AWS</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/464</guid>
      <comments>https://somaz.tistory.com/464#entry464comment</comments>
      <pubDate>Tue, 14 Apr 2026 00:00:06 +0900</pubDate>
    </item>
    <item>
      <title>Kubernetes 클러스터 업그레이드하기 (kubespray 2026v.)</title>
      <link>https://somaz.tistory.com/502</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes 클러스터를 운영하다 보면 보안 패치, 새로운 기능, 인증서 갱신 등의 이유로 주기적인 업그레이드가 필요하다.&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;color: #000000;&quot;&gt;Kubespray는 upgrade-cluster.yml 플레이북을 통해 etcd &amp;rarr; Control Plane &amp;rarr; Worker 순서로 자동 업그레이드를 지원하며, 수동으로 각 노드에 접속하여 kubeadm upgrade를 실행할 필요 없이 Ansible 한 줄로 전체 클러스터를 업그레이드할 수 있다.&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;color: #000000;&quot;&gt;이번 포스팅에서는 다음의 내용을 중심으로 정리하였다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubespray &amp;harr; Kubernetes 버전 매핑 이해&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd 백업 및 복구&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubespray 버전 전환 (v2.28.0 &amp;rarr; v2.30.0)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;upgrade-cluster.yml을 이용한 Kubernetes 업그레이드 (v1.33.3 &amp;rarr; v1.34.3)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인증서 자동 갱신&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드 중 발생할 수 있는 에러와 대응 방법&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드 후 검증 및 inventory 동기화&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클러스터 설치 관련 내용은 이전 포스팅을 참고한다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/501&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2026.04.07 - [Container Orchestration/Kubernetes] - Kubernetes 클러스터 구축하기(kubespray 2026v.)&lt;/a&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/script-collection/tree/main/bash/k8s-script/kubespray&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/somaz94/script-collection/tree/main/bash/k8s-script/kubespray&lt;/a&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;&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;2382&quot; data-origin-height=&quot;1300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pa3gw/dJMcafGadJt/BnwuqdrQ2LC8RnKCSZd661/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pa3gw/dJMcafGadJt/BnwuqdrQ2LC8RnKCSZd661/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pa3gw/dJMcafGadJt/BnwuqdrQ2LC8RnKCSZd661/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fpa3gw%2FdJMcafGadJt%2FBnwuqdrQ2LC8RnKCSZd661%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;2382&quot; height=&quot;1300&quot; data-origin-width=&quot;2382&quot; data-origin-height=&quot;1300&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드 원칙&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubespray를 통한 Kubernetes 업그레이드에는 반드시 지켜야 할 원칙이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;원칙&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;한 번에 1 마이너 버전만&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.33 &amp;rarr; v1.34 ✅, v1.33 &amp;rarr; v1.35 ❌&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;패치 버전은 자유&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.33.3 &amp;rarr; v1.33.5 ✅&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;업그레이드 순서&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd &amp;rarr; Control Plane &amp;rarr; Worker (kubespray가 자동 처리)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Worker 업그레이드 방식&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;drain(Pod 퇴거) &amp;rarr; 업그레이드 &amp;rarr; uncordon(복귀)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;etcd 백업 필수&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드 전 반드시 스냅샷 생성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;staging 먼저&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가능하다면 테스트 환경에서 먼저 검증 후 production 적용&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubespray &amp;harr; Kubernetes 버전 매핑&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubespray 버전마다 지원하는 Kubernetes 버전 범위가 다르다. 업그레이드 전에 반드시 확인해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;br /&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubespray&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;K8s 지원 범위&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v2.25.x&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.29.x ~ v1.31.x&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v2.26.x&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.30.x ~ v1.32.x&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v2.27.x&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.31.x ~ v1.33.x&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v2.28.x&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.32.x ~ v1.34.x&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v2.30.0&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.32.x ~ v1.34.x&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정확한 매핑은 &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/kubernetes-sigs/kubespray/releases&quot;&gt;Kubespray Releases&lt;/a&gt;에서 확인하세요. 특정 태그의 지원 버전은 아래 명령어로도 확인 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;elixir&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;git show &amp;lt;tag&amp;gt;:roles/kubespray_defaults/defaults/main/main.yml | head -5&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;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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드 절차&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 1. 사전 준비 &amp;mdash; 현재 버전 확인&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;ssh somaz@10.10.10.17
cd ~/kubespray

# 현재 kubespray 버전 확인
git describe --tags

# 현재 K8s 버전 확인
kubectl get nodes -o wide

# 인증서 만료일 확인
sudo kubeadm certs check-expiration&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 2. etcd 백업 (필수)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드 전 etcd 스냅샷을 반드시 생성한다. 문제 발생 시 유일한 롤백 수단이다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;mel&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Control Plane에서 실행
sudo ETCDCTL_API=3 etcdctl snapshot save /tmp/etcd-backup-$(date +%Y%m%d).db \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/ssl/etcd/ssl/ca.pem \
  --cert=/etc/ssl/etcd/ssl/node-k8s-control-01.pem \
  --key=/etc/ssl/etcd/ssl/node-k8s-control-01-key.pem

# 백업 검증
sudo ETCDCTL_API=3 etcdctl snapshot status /tmp/etcd-backup-$(date +%Y%m%d).db --write-table&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;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 3. Kubespray 버전 전환&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes를 업그레이드하려면 먼저 Kubespray 자체를 해당 K8s 버전을 지원하는 태그로 전환해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# venv 활성화
source ~/kubespray/venv/bin/activate
cd ~/kubespray

# 최신 태그 목록 확인
git fetch --tags
git tag -l | sort -V | tail -20

# 변경사항이 있으면 stash
git stash

# 원하는 버전으로 전환
git checkout v2.30.0

# 의존성 업데이트
pip install -r requirements.txt&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 4. 설정 변경사항 확인 (Diff)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubespray 버전이 바뀌면 기본 설정값도 바뀔 수 있다. sample inventory와 내 inventory의 차이를 확인한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# sample과 내 inventory의 k8s-cluster.yml 비교
diff ~/kubespray/inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml \
     ~/kubespray/inventory/somaz-cluster/group_vars/k8s_cluster/k8s-cluster.yml

# sample과 내 inventory의 containerd.yml 비교
diff ~/kubespray/inventory/sample/group_vars/all/containerd.yml \
     ~/kubespray/inventory/somaz-cluster/group_vars/all/containerd.yml&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;v2.28.0 &amp;rarr; v2.30.0 주요 변경사항&lt;/b&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 133px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style11&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파일변경&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;내용&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;영향&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd.yml&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;삭제됨 (etcd 설정이 다른 곳으로 이동)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;커스텀 etcd 설정 없으면 영향 없음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;k8s-net-weave.yml&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;삭제됨 (Weave CNI deprecated)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cilium 사용 시 영향 없음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;k8s-net-cilium.yml&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kube_proxy_replacement: partial &amp;rarr; false, cilium_extra_values 추가&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본값이라 영향 없음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;k8s-cluster.yml&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kube_owner 주석에 Cilium 관련 안내 추가&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사소한 변경&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;containerd.yml&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;engine/root &amp;rarr; options.Root 구조 변경&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주석(예시)만 변경&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;addons.yml&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;local_path_provisioner_image_tag 제거&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 관리로 변경&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 5. kube_version 설정 (선택)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특정 K8s 버전을 지정하려면 아래 파일을 수정한다. 미설정 시 해당 Kubespray 태그의 기본 최신 버전이 적용된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;vi ~/kubespray/inventory/somaz-cluster/group_vars/k8s_cluster/k8s-cluster.yml&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 추가 또는 수정
kube_version: v1.34.3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 6. 업그레이드 실행&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;source ~/kubespray/venv/bin/activate
cd ~/kubespray

# Dry-run (변경사항 미리보기, 실제 변경 없음)
ansible-playbook -i inventory/somaz-cluster/inventory.ini \
  upgrade-cluster.yml \
  -b --become-user=root \
  --check --diff

# 실제 업그레이드 실행
ansible-playbook -i inventory/somaz-cluster/inventory.ini \
  upgrade-cluster.yml \
  -b --become-user=root&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`cluster.yml`이 아니라 `upgrade-cluster.yml` 을 사용해야 한다. `cluster.yml` 은 신규 설치용이다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;color: #000000;&quot;&gt;업그레이드는 보통 20~40분 소요되며, API server 10~30초 중단 + Worker drain 시 replica 1인 서비스는 잠시 중단될 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 7. 업그레이드 검증&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 모든 노드 버전 확인
kubectl get nodes -o wide

# 비정상 Pod 확인
kubectl get pods -A | grep -v Running | grep -v Completed

# 클러스터 정보
kubectl cluster-info

# 컴포넌트 상태
kubectl get --raw='/readyz?verbose'

# containerd insecure registry 설정 유지 확인
ssh somaz@10.10.10.18 &quot;cat /etc/containerd/certs.d/harbor.example.com/hosts.toml&quot;&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;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;color: #000000;&quot;&gt;업그레이드 자동화 스크립트&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아래의 github의 자동화 스크립트를 참고하면 위의 step의 과정들을 자동화 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/script-collection/tree/main/bash/k8s-script/kubespray&quot;&gt;https://github.com/somaz94/script-collection/tree/main/bash/k8s-script/kubespray&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1775531313450&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;script-collection/bash/k8s-script/kubespray at main &amp;middot; somaz94/script-collection&quot; data-og-description=&quot;Contribute to somaz94/script-collection development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/somaz94/script-collection/tree/main/bash/k8s-script/kubespray&quot; data-og-url=&quot;https://github.com/somaz94/script-collection/tree/main/bash/k8s-script/kubespray&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bfoUwP/dJMb83ktEWF/z5aDDNTDxvhXBMHCZJjaCK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/b7IEC6/dJMb8SpIHpI/ikZgorV8kAZk2T3JZOv7kK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/somaz94/script-collection/tree/main/bash/k8s-script/kubespray&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/somaz94/script-collection/tree/main/bash/k8s-script/kubespray&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bfoUwP/dJMb83ktEWF/z5aDDNTDxvhXBMHCZJjaCK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/b7IEC6/dJMb8SpIHpI/ikZgorV8kAZk2T3JZOv7kK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;script-collection/bash/k8s-script/kubespray at main &amp;middot; somaz94/script-collection&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to somaz94/script-collection development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인증서 자동 갱신&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kubespray로 `upgrade-cluster.yml` 을 실행하면 kubeadm이 인증서를 자동 갱신한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 갱신되는 인증서&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인증서&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;용도&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;갱신 여부&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;apiserver.crt&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API Server TLS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;apiserver-kubelet-client.crt&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API &amp;rarr; kubelet 통신&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;front-proxy-client.crt&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API aggregation&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd/server.crt&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd TLS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd/peer.crt&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd 피어 통신&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;admin.conf&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kubectl 접속&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&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;color: #000000;&quot;&gt;kubeadm은 업그레이드 시 만료 1년 미만인 인증서를 자동 갱신한다. 기본 유효기간은 1년이다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현재 인증서 만료일 확인&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;ebnf&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;sudo kubeadm certs check-expiration&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주의: 업그레이드 없이 1년 방치하면?&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인증서가 만료되어 클러스터가 먹통이 된다. 그때는 수동 갱신이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;sudo kubeadm certs renew all
sudo systemctl restart kubelet&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;권장: 1년 이내에 최소 1회 업그레이드를 수행하면 인증서가 자동 갱신되므로 별도 작업이 불필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;span style=&quot;color: #000000;&quot;&gt;아래의 스크립트를 사용해도 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/script-collection/blob/main/bash/k8s-script/k8s_certs_renew.sh&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/somaz94/script-collection/blob/main/bash/k8s-script/k8s_certs_renew.sh&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1775531417191&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;script-collection/bash/k8s-script/k8s_certs_renew.sh at main &amp;middot; somaz94/script-collection&quot; data-og-description=&quot;Contribute to somaz94/script-collection development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/somaz94/script-collection/blob/main/bash/k8s-script/k8s_certs_renew.sh&quot; data-og-url=&quot;https://github.com/somaz94/script-collection/blob/main/bash/k8s-script/k8s_certs_renew.sh&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bnWYfA/dJMb8VNv8uq/mV1NmOlLkOFVFX1TULpSGK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bq2LEM/dJMb9dHoRJG/OVwJd8Z04IaBOQkTsDXWt0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/somaz94/script-collection/blob/main/bash/k8s-script/k8s_certs_renew.sh&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/somaz94/script-collection/blob/main/bash/k8s-script/k8s_certs_renew.sh&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bnWYfA/dJMb8VNv8uq/mV1NmOlLkOFVFX1TULpSGK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bq2LEM/dJMb9dHoRJG/OVwJd8Z04IaBOQkTsDXWt0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;script-collection/bash/k8s-script/k8s_certs_renew.sh at main &amp;middot; somaz94/script-collection&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to somaz94/script-collection development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드 에러 대응&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;health-check Job 실패&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;[ERROR CreateJob]: Job &quot;upgrade-health-check-xxxxx&quot; in the namespace &quot;kube-system&quot; 
did not complete in 15s: no condition of type Complete&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;`kubeadm upgrade` 가 `health check Job` 을 생성했는데 15초 내에 완료되지 않을 때 발생한다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;확인&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 실패한 Job 확인
kubectl get jobs -n kube-system | grep upgrade-health
kubectl describe job &amp;lt;job-name&amp;gt; -n kube-system

# Pod 상태 확인
kubectl get pods -n kube-system | grep upgrade-health&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;해결&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Control Plane이 SchedulingDisabled 상태일 수 있으므로 먼저 uncordon
kubectl uncordon k8s-control-01

# 다시 실행
ansible-playbook -i inventory/somaz-cluster/inventory.ini \
  upgrade-cluster.yml -b --become-user=root&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;containerd insecure registry 설정 초기화&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드 시 containerd가 재설정되면서 직접 수정한 `hosts.toml` 이 덮어쓰여질 수 있다. kubespray inventory의 `containerd.yml` 에 설정이 포함되어 있으면 자동으로 유지된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;lsl&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 업그레이드 후 설정 유지 확인
for node in 10.10.10.17 10.10.10.18 10.10.10.19 10.10.10.22; do
  echo &quot;=== $node ===&quot;
  ssh somaz@$node &quot;cat /etc/containerd/certs.d/harbor.example.com/hosts.toml 2&amp;gt;/dev/null || echo 'NOT FOUND'&quot;
  echo &quot;&quot;
done&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;만약 설정이 날아갔다면 containerd 태그만 재실행하면 복구된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;ansible-playbook -i inventory/somaz-cluster/inventory.ini cluster.yml \
  --tags containerd -b --become-user=root&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중요: insecure registry 설정은 서버에 직접 수정하지 말고, 반드시 kubespray inventory(`containerd.yml`)에서 관리해야 업그레이드 시에도 안전하다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;롤백&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubespray는 자동 롤백을 지원하지 않는다. 업그레이드에 실패하면 Step 2에서 생성한 etcd 백업에서 복구해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# etcd 복구
sudo ETCDCTL_API=3 etcdctl snapshot restore /tmp/etcd-backup-YYYYMMDD.db \
  --data-dir=/var/lib/etcd-restore

# 이후 수동으로 etcd 데이터 디렉토리 교체 필요
# 참고: https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/#restoring-an-etcd-cluster&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;롤백은 복잡하고 위험한 작업이므로, 업그레이드 전 etcd 백업을 반드시 생성하고, 가능하면 staging 환경에서 먼저 테스트하는 것이 최선이다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;
&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;color: #000000;&quot;&gt;업그레이드 후 inventory 동기화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드가 완료되면 Control Plane의 inventory를 로컬(GitLab 등)에 백업해둔다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;elixir&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 로컬에서 실행
scp -r somaz@10.10.10.17:~/kubespray/inventory/somaz-cluster \
  ~/my-project/kubespray/inventory-somaz-cluster&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;버전 확인 스크립트를 만들어두면 업그레이드 전후 상태를 빠르게 비교할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;#!/bin/bash
# check-version.sh

echo &quot;=== K8s Version ===&quot;
kubectl get nodes -o wide

echo &quot;&quot;
echo &quot;=== Kubespray Version ===&quot;
cd ~/kubespray &amp;amp;&amp;amp; git describe --tags

echo &quot;&quot;
echo &quot;=== Containerd Version ===&quot;
containerd --version

echo &quot;&quot;
echo &quot;=== Cilium Version ===&quot;
kubectl get ds cilium -n kube-system -o=jsonpath='{.spec.template.spec.containers[0].image}'
echo &quot;&quot;

echo &quot;&quot;
echo &quot;=== Certificate Expiration ===&quot;
sudo kubeadm certs check-expiration 2&amp;gt;/dev/null | head -15&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;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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 업그레이드 사례: v1.33.3 &amp;rarr; v1.34.3&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2026.04.07에 실제로 수행한 업그레이드 과정을 기록한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;환경&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Before&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;After&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubespray&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v2.28.0&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v2.30.0&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.33.3&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.34.3&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cilium&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.17.3&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.19.1&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;containerd&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v2.1.3&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v2.2.1&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;과정&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd 백업 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;upgrade-kubespray.sh --diff-only로 설정 변경사항 확인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;upgrade-kubespray.sh --target v2.30.0으로 Kubespray 전환&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;upgrade-cluster.yml 실행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;health-check Job 실패로 1회 재실행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전체 노드 v1.34.3 업그레이드 완료 확인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;containerd insecure registry 설정 유지 확인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;inventory 로컬 동기화&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;발생한 이슈&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;health-check Job 15초 타임아웃&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;mipsasm&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;[ERROR CreateJob]: Job &quot;upgrade-health-check-1775526129268&quot; in the namespace &quot;kube-system&quot; 
did not complete in 15s&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;Control Plane은 이미 v1.34.3으로 업그레이드 완료되었지만 `SchedulingDisabled` 상태로 남아있었다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`kubectl uncordon k8s-control-01` 후 재실행하여 해결.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;소요 시간&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style10&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단계&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시간&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd 백업&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1분&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubespray 전환 (git checkout + pip install)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3분&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;upgrade-cluster.yml 1차 실행 (실패)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;11분&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;upgrade-cluster.yml 2차 실행 (성공)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~25분&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;검증&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5분&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;합계&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;~45분&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드 후 확인&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;lsl&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;k get nodes
NAME             STATUS   ROLES           AGE    VERSION
k8s-compute-01   Ready    &amp;lt;none&amp;gt;          252d   v1.34.3
k8s-compute-02   Ready    &amp;lt;none&amp;gt;          252d   v1.34.3
k8s-compute-03   Ready    &amp;lt;none&amp;gt;          245d   v1.34.3
k8s-control-01   Ready    control-plane   252d   v1.34.3&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;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;color: #000000;&quot;&gt;주의사항 정리&lt;/span&gt;&lt;/h3&gt;
&lt;div&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;style10&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd 백업&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드 전 &lt;b&gt;반드시&lt;/b&gt; 스냅샷 생성 &amp;mdash; 유일한 롤백 수단&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마이너 버전&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;한 번에 1 마이너 버전만 업그레이드 가능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플레이북&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`cluster.yml` 이 아니라 `&lt;b&gt;upgrade-cluster.yml`&lt;/b&gt; 사용&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;venv&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kubespray의 Python venv 활성화 확인 (`source venv/bin/activate`)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;StatefulSet&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DB 등 StatefulSet Pod은 drain 시 데이터 확인 필요&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PDB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PodDisruptionBudget 설정 확인 `&amp;mdash; drain` 이 차단될 수 있음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Replica&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스 무중단을 위해 Deployment replica 2개 이상 권장&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;insecure registry&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;inventory에서 관리해야 업그레이드 시에도 안전&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인증서&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1년 이내에 최소 1회 업그레이드하면 자동 갱신&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;피크 시간 회피&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가능하면 서비스 트래픽이 적은 시간대에 진행&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리: &quot;업그레이드는 선택이 아니라 운영의 일부&quot;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes 클러스터 업그레이드는 번거로운 작업처럼 느껴지지만, Kubespray를 사용하면 Ansible 한 줄로 전체 클러스터를 업그레이드할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 다음 사항을 기억하자.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;etcd 백업은 보험이다.&lt;/b&gt; 업그레이드 전 반드시 생성하고, 복구 절차를 미리 숙지해둔다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;인증서는 1년이다.&lt;/b&gt; 업그레이드를 1년 이상 미루면 인증서 만료로 클러스터가 먹통이 된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Diff를 확인하라.&lt;/b&gt; Kubespray 버전이 바뀌면 기본 설정값도 바뀐다. `--diff-only` 로 먼저 확인한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;containerd 설정은 inventory에서.&lt;/b&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;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;color: #000000;&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/kubernetes-sigs/kubespray&quot;&gt;Kubespray GitHub&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/kubernetes-sigs/kubespray/releases&quot;&gt;Kubespray Releases&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubespray.io/#/docs/upgrades&quot;&gt;Kubespray Upgrade Guide&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/&quot;&gt;etcd Backup/Restore&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/kubernetes-sigs/kubespray/blob/master/docs/operations/nodes.md&quot;&gt;Kubespray Node Management&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubespray.io/#/docs/CNI/cilium&quot;&gt;Cilium CNI Kubespray Docs&lt;/a&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;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;
&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;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Container Orchestration/Kubernetes</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/502</guid>
      <comments>https://somaz.tistory.com/502#entry502comment</comments>
      <pubDate>Mon, 13 Apr 2026 00:00:23 +0900</pubDate>
    </item>
    <item>
      <title>Kubernetes 클러스터 구축하기(kubespray 2026v.)</title>
      <link>https://somaz.tistory.com/501</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes 클러스터를 구축하는 방법은 여러 가지가 있지만, 온프레미스 환경에서 &lt;b&gt;반복 가능하고 자동화된 설치&lt;/b&gt;를 원한다면 Kubespray가 가장 강력한 선택지 중 하나이다.&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;color: #000000;&quot;&gt;Kubespray는 Ansible 기반의 프로비저닝 도구로, YAML 기반 인벤토리 파일만 정의하면 다양한 환경(GCP, AWS, 온프렘 등)에서 HA 구성을 포함한 쿠버네티스 클러스터를 유연하게 설치할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 포스팅에서는 다음의 내용을 중심으로 정리하였다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ubuntu 24.04 기반 온프레미스 환경에서 Kubespray를 이용한 Kubernetes v1.34 클러스터 구축&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cilium CNI, Helm, Metrics Server, Krew 등 주요 애드온 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;containerd insecure registry (Harbor) 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Worker Node 추가 (scale.yml) 및 제거 (remove-node.yml)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 구축 시 발생한 에러와 해결 방법&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2366&quot; data-origin-height=&quot;1176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBxKwv/dJMcajuZE1j/tfm5wZ3CdqkptKHmWMQEbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBxKwv/dJMcajuZE1j/tfm5wZ3CdqkptKHmWMQEbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBxKwv/dJMcajuZE1j/tfm5wZ3CdqkptKHmWMQEbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBxKwv%2FdJMcajuZE1j%2Ftfm5wZ3CdqkptKHmWMQEbK%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;2366&quot; height=&quot;1176&quot; data-origin-width=&quot;2366&quot; data-origin-height=&quot;1176&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시스템 구성&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2026.04.07 기준이다.&lt;/span&gt;&lt;/p&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;값&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ubuntu 24.04 LTS&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v1.34.3&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubespray&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;v2.30.0&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CNI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cilium v1.19.1&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Container Runtime&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;containerd v2.2.1&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cluster DNS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;somaz-cluster.local&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;color: #000000;&quot;&gt;노드 구성&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 87px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;역할&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;호스트명&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IP&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Memory&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Control Plane + etcd&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;k8s-control-01&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10.10.10.17&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;24GB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Worker&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;k8s-compute-01&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10.10.10.18&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;12&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;48GB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Worker&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;k8s-compute-02&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10.10.10.19&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;12&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;48GB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Worker&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;k8s-compute-03&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10.10.10.22&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;12&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;48GB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;k8s-compute-01 까지 먼저 설치한 뒤, scale.yml을 사용해서 k8s-compute-02, 03을 추가하는 방식으로 진행한다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사전 준비&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SSH 키 생성 및 복사&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 노드에 패스워드 없이 SSH 접속이 가능해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;lsl&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;ssh-keygen

# /etc/hosts 에 노드 등록
sudo vi /etc/hosts
10.10.10.17 k8s-control-01
10.10.10.18 k8s-compute-01
10.10.10.19 k8s-compute-02
10.10.10.22 k8s-compute-03

# SSH 키 복사
ssh-copy-id k8s-control-01
ssh-copy-id k8s-compute-01
ssh-copy-id k8s-compute-02

# 접속 확인
ssh k8s-control-01
ssh k8s-compute-01
ssh k8s-compute-02&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;패키지 설치 및 Kubespray 준비&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vim&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Python 3.10 및 필수 패키지 설치
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt-get -y update
sudo apt install -y python3.10 python3-pip git python3.10-venv

python3.10 --version

# Kubespray 클론
git clone https://github.com/kubernetes-sigs/kubespray.git
cd kubespray

# 원하는 버전으로 체크아웃
git checkout v2.30.0

# 인벤토리 복사
cp -rfp inventory/sample inventory/somaz-cluster

# Python 가상환경 생성 및 활성화
python3.10 -m venv venv
source venv/bin/activate

# 의존성 설치
pip install -U -r requirements.txt&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;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;color: #000000;&quot;&gt;인벤토리 설정&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;inventory.ini&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;`inventory/somaz-cluster/inventory.ini`&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처음에는 k8s-compute-01만 포함하여 설치한다. k8s-compute-02는 이후 `scale.yml` 로 추가한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;[kube_control_plane]
k8s-control-01 ansible_host=10.10.10.17 ip=10.10.10.17 etcd_member_name=etcd1

[etcd:children]
kube_control_plane

[kube_node]
k8s-compute-01&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;k8s-cluster.yml&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;`inventory/somaz-cluster/group_vars/k8s_cluster/k8s-cluster.yml`&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# CNI 플러그인 설정
kube_network_plugin: cilium

# 클러스터 도메인
cluster_name: somaz-cluster.local

# Cilium을 사용할 경우 kube_owner를 root로 설정해야 한다
# https://kubespray.io/#/docs/CNI/cilium?id=unprivileged-agent-configuration
kube_owner: root&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kube_owner: root를 설정하지 않으면 Cilium에서 /opt/cni/bin 권한 에러가 발생한다. 참고: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/cilium/cilium/issues/23838&quot;&gt;https://github.com/cilium/cilium/issues/23838&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;addons.yml&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;`inventory/somaz-cluster/group_vars/k8s_cluster/addons.yml`&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Helm 활성화
helm_enabled: true

# Metrics Server 활성화
metrics_server_enabled: true

# kubectl 플러그인 매니저 Krew 활성화
krew_enabled: true
krew_root_dir: &quot;/usr/local/krew&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;containerd.yml &amp;mdash; Insecure Registry 설정&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;`inventory/somaz-cluster/group_vars/all/containerd.yml`&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;color: #000000;&quot;&gt;프라이빗 레지스트리(Harbor 등)를 HTTP로 사용하는 경우, containerd에 insecure registry 설정을 추가해야 한다. 이 설정을 kubespray inventory에 넣어두면, 노드 추가나 업그레이드 시에도 자동으로 적용된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Harbor insecure registry 설정
containerd_registries_mirrors:
  - prefix: harbor.example.com
    mirrors:
      - host: http://harbor.example.com
        capabilities: [&quot;pull&quot;, &quot;resolve&quot;, &quot;push&quot;]
        skip_verify: true
        plain_http: true

# Harbor 인증 정보
containerd_registry_auth:
  - registry: harbor.example.com
    username: admin
    password: your-password&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;이 설정이 적용되면 각 노드의 `/etc/containerd/certs.d/harbor.example.com/hosts.toml` 파일이 자동 생성된다.&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;주의사항&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서버에 직접 `hosts.toml` 을 수정하면 kubespray 업그레이드 시 덮어쓸 위험이 있다. &lt;b&gt;반드시 inventory에서 관리&lt;/b&gt;하는 것을 권장한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드 후 설정이 유지되었는지 확인하려면 아래 명령어를 사용한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;ssh somaz@&amp;lt;node-ip&amp;gt; &quot;cat /etc/containerd/certs.d/harbor.example.com/hosts.toml&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;만약 설정이 날아갔다면 containerd 태그만 재실행하면 복구된다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;ansible-playbook -i inventory/somaz-cluster/inventory.ini cluster.yml \
  --tags containerd -b --become-user=root&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;color: #000000;&quot;&gt;클러스터 배포&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ansible 통신 확인&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배포 전에 모든 노드와 Ansible 통신이 가능한지 확인한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;apache&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 반드시 ~/kubespray 경로에서 실행
ansible all -i inventory/somaz-cluster/inventory.ini -m ping&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플레이북 실행&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 포그라운드 실행
ansible-playbook -i inventory/somaz-cluster/inventory.ini cluster.yml --become

# 백그라운드 실행 (시간이 오래 걸리므로 권장)
nohup ansible-playbook -i inventory/somaz-cluster/inventory.ini cluster.yml --become &amp;amp;

# 로그 확인
tail -f nohup.out&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kubectl 설정&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클러스터 배포 완료 후, Control Plane 노드에서 kubectl을 설정한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# kubeconfig 복사
mkdir ~/.kube
sudo cp /etc/kubernetes/admin.conf ~/.kube/config
sudo chown $USER:$USER ~/.kube/config

# 자동완성 및 alias 설정
echo '# kubectl completion and alias' &amp;gt;&amp;gt; ~/.bashrc
echo 'source &amp;lt;(kubectl completion bash)' &amp;gt;&amp;gt; ~/.bashrc
echo 'alias k=kubectl' &amp;gt;&amp;gt; ~/.bashrc
echo 'complete -F __start_kubectl k' &amp;gt;&amp;gt; ~/.bashrc
source ~/.bashrc&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설치 확인&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;k get nodes
NAME             STATUS   ROLES           AGE    VERSION
k8s-compute-01   Ready    &amp;lt;none&amp;gt;          2d4h   v1.34.3
k8s-control-01   Ready    control-plane   2d4h   v1.34.3

k version
Client Version: v1.34.3
Kustomize Version: v5.6.0
Server Version: v1.34.3

containerd --version
containerd github.com/containerd/containerd/v2 v2.2.1

# Cilium 버전 확인
k get ds cilium -n kube-system -o=jsonpath='{.spec.template.spec.containers[0].image}'
quay.io/cilium/cilium:v1.19.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;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;color: #000000;&quot;&gt;Cilium 권한 에러 해결&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cilium을 CNI로 사용할 때 `/opt/cni/bin` 디렉토리 권한 문제로 에러가 발생할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;증상&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Pod이 Init:CrashLoopBackOff 상태에 빠지거나, Cilium agent 로그에서 권한 관련 에러가 출력된다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해결 방법 1: 수동 권한 변경&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;groovy&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;chown -R root:root /opt/cni/bin&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해결 방법 2: kubespray 설정에서 근본 해결 (권장)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;`inventory/somaz-cluster/group_vars/k8s_cluster/k8s-cluster.yml`&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 기본값
# kube_owner: kube

# Cilium 사용 시 root로 변경
kube_owner: root&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubespray v2.30.0부터는 이 부분에 Cilium 관련 주석이 공식적으로 추가되었다. # Note: cilium needs to set kube_owner to root 참고: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/cilium/cilium/issues/23838&quot;&gt;https://github.com/cilium/cilium/issues/23838&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;Worker Node 추가 (Scale Up)&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 1. 사전 준비&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;accesslog&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# /etc/hosts에 새 노드 추가
sudo vi /etc/hosts
10.10.10.19 k8s-compute-02

# SSH 키 복사
ssh-copy-id k8s-compute-02&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 2. inventory.ini 수정&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;[kube_control_plane]
k8s-control-01 ansible_host=10.10.10.17 ip=10.10.10.17 etcd_member_name=etcd1

[etcd:children]
kube_control_plane

[kube_node]
k8s-compute-01
k8s-compute-02    # 새 노드 추가

[add_node]
k8s-compute-02    # scale.yml 대상 지정&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 3. facts 수집 (중요!)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 노드의 facts를 먼저 수집해야 한다. 이 단계를 생략하면 ipwrap 에러가 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;ansible-playbook -i inventory/somaz-cluster/inventory.ini playbooks/facts.yml --become&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;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 단계를 생략하면 아래 에러가 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;AnsibleFilterError: Unrecognized type for ipwrap filter&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/blockquote&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 4. scale.yml 실행&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# --limit add_node 으로 새 노드만 대상으로 실행
nohup ansible-playbook -i inventory/somaz-cluster/inventory.ini \
  scale.yml --limit add_node --become &amp;amp;

# 로그 확인
tail -f nohup.out&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 5. 검증 및 정리&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;lsl&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;k get nodes
NAME             STATUS   ROLES           AGE    VERSION
k8s-compute-01   Ready    &amp;lt;none&amp;gt;          2d5h   v1.34.3
k8s-compute-02   Ready    &amp;lt;none&amp;gt;          1m     v1.34.3
k8s-control-01   Ready    control-plane   2d5h   v1.34.3&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완료 후 `[add_node]` 섹션을 주석 처리하거나 제거한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# [add_node]
# k8s-compute-02  # Already added&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;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;color: #000000;&quot;&gt;Worker Node 제거 (Scale Down)&lt;/span&gt;&lt;/h3&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;color: #000000;&quot;&gt;노드위에 Pod 수와 PDB 영향을 확인한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778638127658&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get pods -A -o wide --field-selector spec.nodeName=k8s-compute-02 --no-headers | wc -l
kubectl get pdb -A&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;StatefulSet (DB 등) 이 그 노드에 있으면 데이터 이동/PV 재할당 계획 먼저 &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`replica=1` Deployment 가 있으면 옮길 곳 검토 (다른 노드 capacity)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;crmsh&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;cd ~/kubespray
source venv/bin/activate

ansible-playbook -i inventory/somaz-cluster/inventory.ini \
  remove-node.yml \
  -b --extra-vars='node=k8s-compute-02' \
  --extra-vars reset_nodes=true&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;완료 후 `inventory.ini` 에서 해당 노드를 제거한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;playbook&amp;nbsp;이&amp;nbsp;수행하는&amp;nbsp;것은 아래와 같다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778638199937&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1. `kubectl drain k8s-compute-02 --ignore-daemonsets --delete-emptydir-data` &amp;mdash; Pod evict
2. `kubectl delete node k8s-compute-02`
3. `reset_nodes=true` 일 때 &amp;mdash; 그 노드의 kubelet/CNI/etcd-data/containerd 데이터 정리 (재합류 가능 상태로 초기화)&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`reset_nodes=false`&amp;nbsp;로&amp;nbsp;호출하면&amp;nbsp;cluster&amp;nbsp;측&amp;nbsp;cleanup&amp;nbsp;만&amp;nbsp;함&amp;nbsp;(노드의&amp;nbsp;디스크는&amp;nbsp;그대로).&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드를&amp;nbsp;곧장&amp;nbsp;다른&amp;nbsp;용도로&amp;nbsp;재사용하지&amp;nbsp;않을&amp;nbsp;거면&amp;nbsp;`true`&amp;nbsp;권장.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;inventory를 정리한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778638293068&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;vi ~/kubespray/inventory/somaz-cluster/inventory.ini
# [kube_node] 에서 k8s-compute-02 라인 삭제&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;span style=&quot;color: #000000;&quot;&gt;아래와 같이 검증한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778638425904&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get nodes
# 제거된 노드가 더 이상 안 보여야 함

# (옵션) 남은 worker 에 Pod 가 자동 재스케줄됐는지
kubectl get pods -A -o wide --field-selector status.phase=Pending
# Pending 이 길게 남아있으면 &amp;mdash; capacity/affinity 문제&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;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;
&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;color: #000000;&quot;&gt;Control Plane Node 추가 (HA 전환)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단일 Control Plane으로 운영 중이던 클러스터에 control-02, control-03을 추가하여 HA 구성으로 전환한다. Worker 추가와는 절차가 다르므로 주의가 필요하다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;공식 가이드: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/kubernetes-sigs/kubespray/blob/master/docs/operations/nodes.md#adding-control-plane-nodes&quot;&gt;Adding control plane nodes&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1778637572859&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;kubespray/docs/operations/nodes.md at master &amp;middot; kubernetes-sigs/kubespray&quot; data-og-description=&quot;Deploy a Production Ready Kubernetes Cluster. Contribute to kubernetes-sigs/kubespray development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/kubernetes-sigs/kubespray/blob/master/docs/operations/nodes.md#adding-control-plane-nodes&quot; data-og-url=&quot;https://github.com/kubernetes-sigs/kubespray/blob/master/docs/operations/nodes.md&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/G6MRN/dJMb9fZz502/l82xknIn3W4c3RkkLKMgY0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/PTdZQ/dJMb9kmhsVU/r1mr7RVyX9F1qzafv4Keq1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/kubernetes-sigs/kubespray/blob/master/docs/operations/nodes.md#adding-control-plane-nodes&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/kubernetes-sigs/kubespray/blob/master/docs/operations/nodes.md#adding-control-plane-nodes&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/G6MRN/dJMb9fZz502/l82xknIn3W4c3RkkLKMgY0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/PTdZQ/dJMb9kmhsVU/r1mr7RVyX9F1qzafv4Keq1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;kubespray/docs/operations/nodes.md at master &amp;middot; kubernetes-sigs/kubespray&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Deploy a Production Ready Kubernetes Cluster. Contribute to kubernetes-sigs/kubespray development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Worker 추가와의 차이점&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Worker 추가&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Control Plane 추가&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실행 playbook&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;scale.yml&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;cluster.yml&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;--limit 옵션&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;--limit add_node&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용하지 않음 (전체 대상)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[add_node] 그룹&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용하지 않음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd 영향&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;member join + cert 재발급&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;후속 작업&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 worker의 nginx-proxy 재시작 필요&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;소요 시간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;30~60분&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;60~90분&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;&lt;span style=&quot;color: #000000;&quot;&gt;`cluster.yml`을 사용하는 이유는 `etcd member join`, 인증서 재발급, `nginx-proxy upstream` 갱신 등이 클러스터 전체에 걸쳐 일어나기 때문이다. `scale.yml` 은 worker 확장 전용이므로 control-plane 추가에는 사용할 수 없다.&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd Quorum 주의사항&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd는 합의 알고리즘(Raft) 기반으로 동작하므로 &lt;b&gt;홀수 멤버 + quorum 유지&lt;/b&gt;가 필수다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1 &amp;rarr; 3으로 한 번에 늘리기: OK&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1 &amp;rarr; 2로 늘리기: ❌ split-brain 위험 (짝수)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3 &amp;rarr; 5로 늘리기: OK&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;따라서 control-02와 control-03을 &lt;b&gt;동일한 cluster.yml 실행 안에서 함께 추가&lt;/b&gt;해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영 클러스터에서 실행 중 기존 etcd가 일시적으로 재시작될 수 있다. 짧은 시간 동안 API 호출이 실패할 수 있으므로 비업무 시간대에 진행을 권장한다. 실행 전 반드시 etcd 스냅샷 백업을 수행한다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&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;
&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;color: #000000;&quot;&gt;노드 구성&lt;/span&gt;&lt;/h3&gt;
&lt;div&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;style10&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;역할&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;호스트명&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IP&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Control Plane + etcd (기존)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;k8s-control-01&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10.10.10.17&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Control Plane + etcd (신규)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;k8s-control-02&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10.10.10.24&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Control Plane + etcd (신규)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;k8s-control-03&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10.10.10.25&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 1. 사전 준비&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Worker 추가와 동일하게 `/etc/hosts` 매핑과 SSH 키 등록을 진행한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;lsl&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# /etc/hosts에 새 노드 추가
sudo vi /etc/hosts
10.10.10.24 k8s-control-02
10.10.10.25 k8s-control-03

# SSH 키 복사
ssh-copy-id k8s-control-02
ssh-copy-id k8s-control-03

# 접속 확인
ssh k8s-control-02
ssh k8s-control-03&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 2. etcd 백업 (필수)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`cluster.yml` 실행 중 기존 etcd 멤버가 재시작되므로 사전 백업은 필수다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;mel&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;sudo ETCDCTL_API=3 etcdctl \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/ssl/etcd/ssl/ca.pem \
  --cert=/etc/ssl/etcd/ssl/admin-k8s-control-01.pem \
  --key=/etc/ssl/etcd/ssl/admin-k8s-control-01-key.pem \
  snapshot save /tmp/etcd-snapshot-$(date +%Y%m%d-%H%M%S).db&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 3. inventory.ini 수정&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`[kube_control_plane]` 그룹에 &lt;b&gt;반드시 끝에 append &lt;/b&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;[kube_control_plane]
k8s-control-01 ansible_host=10.10.10.17 ip=10.10.10.17 etcd_member_name=etcd1
k8s-control-02 ansible_host=10.10.10.24 ip=10.10.10.24 etcd_member_name=etcd2
k8s-control-03 ansible_host=10.10.10.25 ip=10.10.10.25 etcd_member_name=etcd3

[etcd:children]
kube_control_plane

[kube_node]
k8s-compute-01
k8s-compute-02
k8s-compute-03&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;첫 번째 위치의 노드(k8s-control-01)는 primary로 취급되므로 앞에 끼워넣으면 클러스터가 깨질 수 있다. Kubespray 공식 문서에서도 &quot;always append&quot;를 명시하고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;[add_node] 그룹은 worker 흐름 전용이므로 control-plane 추가에는 사용하지 않는다.&lt;/b&gt;&lt;/u&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 4. facts 수집&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Worker 추가 시와 동일한 이유(`ipwrap` 에러 방지)로 control-plane 추가에서도 facts 수집을 먼저 수행한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;ansible-playbook -i inventory/somaz-cluster/inventory.ini playbooks/facts.yml --become&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 5. cluster.yml 실행&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`scale.yml` 이 아닌 `cluster.yml` 을 `--limit` 없이 실행한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;nohup ansible-playbook -i inventory/somaz-cluster/inventory.ini \
  cluster.yml --become &amp;amp;

# 로그 확인
tail -f nohup.out&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;소요 시간은 약 60~90분이다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 6. 모든 Worker의 nginx-proxy 재시작 (필수)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubespray의 표준 구성은 각 worker에 nginx-proxy 컨테이너를 띄워 `localhost:6443` 을 control-plane 멤버들로 분배한다(별도 외부 LB 불필요). 새로 추가된 control-plane을 worker가 인식하려면 nginx-proxy 재시작이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 모든 worker에서 nginx-proxy 재시작 (ansible 한 줄 버전)
ansible -i inventory/somaz-cluster/inventory.ini kube_node -b -m shell \
  -a 'crictl ps | grep nginx-proxy | awk &quot;{print \$1}&quot; | xargs -r crictl stop'

# kubelet이 static pod를 자동 재기동함&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;nginx-proxy의 upstream 목록은 kubespray가 [kube_control_plane] 멤버 기준으로 템플릿 렌더하여 `/etc/nginx/nginx.conf`에 박는다. 컨테이너 재시작 = 새 멤버 인식. kubelet의 static pod 재기동이라 별도 `kubectl apply` 불필요.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 7. 검증&lt;/span&gt;&lt;/h4&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;7-1. 노드 상태&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;lsl&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;kubectl get nodes
# NAME             STATUS   ROLES           AGE    VERSION
# k8s-control-01   Ready    control-plane   2d6h   v1.34.3
# k8s-control-02   Ready    control-plane   5m     v1.34.3
# k8s-control-03   Ready    control-plane   5m     v1.34.3
# k8s-compute-01   Ready    &amp;lt;none&amp;gt;          2d6h   v1.34.3
# k8s-compute-02   Ready    &amp;lt;none&amp;gt;          1h     v1.34.3
# k8s-compute-03   Ready    &amp;lt;none&amp;gt;          1h     v1.34.3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ROLES 컬럼이 &amp;lt;none&amp;gt;으로 남는다면 inventory의 [kube_control_plane] 매핑이나 `cluster.yml` 실행 로그를 점검한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;7-2. etcd 멤버 및 Quorum&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;haml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# control-01에서 etcd member list 확인
sudo ETCDCTL_API=3 etcdctl \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/ssl/etcd/ssl/ca.pem \
  --cert=/etc/ssl/etcd/ssl/admin-k8s-control-01.pem \
  --key=/etc/ssl/etcd/ssl/admin-k8s-control-01-key.pem \
  member list

# 3개 멤버(etcd1, etcd2, etcd3)가 모두 started 상태여야 함

# endpoint status 확인 (LEADER + RAFT INDEX)
sudo ETCDCTL_API=3 etcdctl \
  --endpoints=https://10.10.10.17:2379,https://10.10.10.24:2379,https://10.10.10.25:2379 \
  --cacert=/etc/ssl/etcd/ssl/ca.pem \
  --cert=/etc/ssl/etcd/ssl/admin-k8s-control-01.pem \
  --key=/etc/ssl/etcd/ssl/admin-k8s-control-01-key.pem \
  endpoint status --cluster -w table&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;한 멤버가 `IS LEADER=true`, 나머지 둘은 `false`. `RAFT INDEX` 는 거의 동일해야 한다.&lt;/span&gt;&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;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;7-3. Control Plane Static Pod 분산 확인&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;gherkin&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;kubectl get pods -n kube-system -o wide | grep -E &quot;kube-apiserver|kube-controller|kube-scheduler|etcd&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;kube-apiserver, kube-controller-manager, kube-scheduler, etcd 각 컴포넌트가 control-01/02/03 세 노드에 모두 분산되어 있어야 한다.&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;7-4. nginx-proxy Upstream 검증&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 worker의 nginx-proxy가 &lt;b&gt;세 control-plane endpoint 모두&lt;/b&gt;를 upstream으로 가지고 있는지 확인한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# nginx 설정의 upstream 블록 확인
ansible -i inventory/somaz-cluster/inventory.ini kube_node -b -m shell -a '
  ID=$(crictl ps -q --name nginx-proxy | head -n1)
  echo &quot;--- $(hostname) ---&quot;
  crictl exec &quot;$ID&quot; cat /etc/nginx/nginx.conf | grep -E &quot;server .*:6443&quot;
'

# 기대 출력 (각 worker마다):
# --- k8s-compute-01 ---
#         server 10.10.10.17:6443;
#         server 10.10.10.24:6443;
#         server 10.10.10.25:6443;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3줄이 모두 출력되어야 한다. 하나만 보이는 worker가 있다면 해당 노드의 nginx-proxy만 다시 재시작한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;ada&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;ssh somaz@&amp;lt;문제-노드&amp;gt; 'sudo crictl ps -q --name nginx-proxy | xargs sudo crictl stop'&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;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;color: #000000;&quot;&gt;&lt;b&gt;7-5. localhost:6443 Health 확인&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;ansible -i inventory/somaz-cluster/inventory.ini kube_node -b -m shell \
  -a 'curl -kfsS --max-time 3 https://127.0.0.1:6443/healthz; echo'

# 각 노드에서 ok 출력&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Step 8. (선택) HA Failover 동작 확인&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영 환경에서 fault injection을 통해 HA 동작을 검증한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;livecodeserver&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# control-01의 kube-apiserver 잠시 정지
sudo systemctl stop kubelet  # 또는 /etc/kubernetes/manifests/kube-apiserver.yaml 임시 이동

# worker에서 다른 control-plane으로 자동 fallback 되는지 확인
kubectl get nodes  # 정상 응답이 와야 함

# 복구
sudo systemctl start kubelet&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영 클러스터에서는 비업무 시간대에 수행하고, 의도된 fault injection임을 팀에 사전 공지한다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;주의사항 정리&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&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;style10&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;playbook&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;scale.yml ❌ &amp;rarr; cluster.yml ⭕&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;--limit 옵션&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용하지 않음 (전체 노드 대상)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;inventory 순서&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 노드 뒤에 &lt;b&gt;append&lt;/b&gt; (앞 끼워넣기 금지)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd 멤버 수&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;홀수 유지 (1 &amp;rarr; 3 한번에 추가)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd 백업&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실행 전 반드시 스냅샷 생성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;facts.yml&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;cluster.yml 전에 먼저 실행 (ipwrap 에러 방지)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;nginx-proxy 재시작&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 worker에서 필수 (upstream 갱신)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실행 시간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;60~90분, nohup 권장&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Control Node 제거&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;etcd quorum 보호가 최우선이다.&lt;/b&gt;&amp;nbsp; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;i&gt;3 &amp;rarr; 1 (한 번에 두 개 제거) 또는 3 &amp;rarr; 2 (한 개 제거) 중 어느 케이스든&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3 &amp;rarr; 2: 짝수 quorum. 1 노드만 더 죽으면 cluster read-only. 단기 운영은 가능하지만 즉시 다른 member 추가 또는 3 &amp;rarr; 1 로 추가 감축 결정 필요 &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3 &amp;rarr; 1: 단일 SPOF 로 회귀. 의도된 다운스케일이면 OK &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;한 번에 여러 member 동시 제거 시 quorum 잃을 위험 &amp;rarr; 반드시 한 번에 한 노드씩&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. etcd 백업 (필수)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1778640275416&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ssh somaz@&amp;lt;server_ip&amp;gt;
sudo ETCDCTL_API=3 etcdctl snapshot save /tmp/etcd-pre-remove-$(date +%Y%m%d-%H%M%S).db \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/ssl/etcd/ssl/ca.pem \
  --cert=/etc/ssl/etcd/ssl/admin-k8s-control-01.pem \
  --key=/etc/ssl/etcd/ssl/admin-k8s-control-01-key.pem

# 워크스테이션으로 복사
scp somaz@&amp;lt;server_ip&amp;gt;:/tmp/etcd-pre-remove-*.db ./backup/&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. etcd member 수동 제거&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1778640316978&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo ETCDCTL_API=3 etcdctl member list -w table \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/ssl/etcd/ssl/ca.pem \
  --cert=/etc/ssl/etcd/ssl/admin-k8s-control-01.pem \
  --key=/etc/ssl/etcd/ssl/admin-k8s-control-01-key.pem

# 제거 대상 (예: etcd3 = f14b6f49ec2e7af4)
sudo ETCDCTL_API=3 etcdctl member remove f14b6f49ec2e7af4 \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/ssl/etcd/ssl/ca.pem \
  --cert=/etc/ssl/etcd/ssl/admin-k8s-control-01.pem \
  --key=/etc/ssl/etcd/ssl/admin-k8s-control-01-key.pem

# 확인 &amp;mdash; 2 member 만 남아야 함
sudo ETCDCTL_API=3 etcdctl member list -w table ...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이&amp;nbsp;시점에서&amp;nbsp;cluster&amp;nbsp;는&amp;nbsp;2-member&amp;nbsp;quorum&amp;nbsp;으로&amp;nbsp;운영&amp;nbsp;중.&amp;nbsp;write&amp;nbsp;가능하지만&amp;nbsp;1&amp;nbsp;member&amp;nbsp;더&amp;nbsp;잃으면&amp;nbsp;read-only.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. remove-node.yml 실행&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1778640358658&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd ~/kubespray
source venv/bin/activate

ansible-playbook -i inventory/somaz-cluster/inventory.ini \
  remove-node.yml \
  -b --extra-vars='node=k8s-control-03' \
  --extra-vars reset_nodes=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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;playbook&amp;nbsp;이&amp;nbsp;수행하는&amp;nbsp;것:&amp;nbsp;&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;`kubectl drain k8s-control-03 --ignore-daemonsets --delete-emptydir-data`&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`kubectl delete node k8s-control-03`&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대상 노드의 kubelet / CNI / etcd-data / containerd 정리&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;etcd member 제거 (Step 2) 를 건너뛰고 `remove-node.yml` 만 실행하면, etcd 클러스터에 stale member 가 남아 quorum 계산이 어긋날 수 있다. 반드시 etcd 먼저 실행한다.&lt;/b&gt;&lt;/u&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. inventory 정리&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1778640481949&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;vi ~/kubespray/inventory/somaz-cluster/inventory.ini

[kube_control_plane]
k8s-control-01 ansible_host=10.10.10.17 ip=10.10.10.17 etcd_member_name=etcd1
k8s-control-02 ansible_host=10.10.10.24 ip=10.10.10.24 etcd_member_name=etcd2
# k8s-control-03 라인 삭제 &amp;mdash; etcd_member_name=etcd3 까지 같이&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. nginx-proxy 재시작 (필수)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;남은 worker 의 nginx-proxy 가 옛 upstream (사라진 control-03 포함) 을 들고 있다. 재시작으로 갱신한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778640531777&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ansible -i inventory/somaz-cluster/inventory.ini kube_node -b -m shell \
  -a 'crictl ps | grep nginx-proxy | awk &quot;{print \$1}&quot; | xargs -r crictl stop'&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6. 검증&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1778640581491&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get nodes
# k8s-control-03 가 더 이상 안 보여야 함

# etcd 멤버 - 2 개로 정리됨
sudo ETCDCTL_API=3 etcdctl member list -w table ...

# nginx-proxy upstream &amp;mdash; 남은 두 endpoint 만 나와야 함
ansible -i inventory/somaz-cluster/inventory.ini kube_node -b -m shell -a '
  ID=$(crictl ps -q --name nginx-proxy | head -n1)
  echo &quot;--- $(hostname) ---&quot;
  crictl exec &quot;$ID&quot; cat /etc/nginx/nginx.conf | grep -E &quot;server .*:6443&quot;
'
# 기대: server 10.10.10.17:6443; / server 10.10.10.24:6443; 두 줄만&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트러블 슈팅&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;etcd&amp;nbsp;member&amp;nbsp;가&amp;nbsp;remove&amp;nbsp;됐는데&amp;nbsp;list&amp;nbsp;에&amp;nbsp;stale&amp;nbsp;로&amp;nbsp;남음&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778640642494&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Force list/health 재계산
sudo systemctl restart etcd     # 남은 한 member 에서 &amp;mdash; quorum 영향 주의&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;span style=&quot;color: #000000;&quot;&gt;또는&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778640651473&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 명시적으로 health endpoint 갱신
sudo ETCDCTL_API=3 etcdctl endpoint health --cluster ...&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;drain&amp;nbsp;이&amp;nbsp;PDB&amp;nbsp;위반으로&amp;nbsp;멈춤&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;error&amp;nbsp;when&amp;nbsp;evicting&amp;nbsp;pods:&amp;nbsp;Cannot&amp;nbsp;evict&amp;nbsp;pod&amp;nbsp;as&amp;nbsp;it&amp;nbsp;would&amp;nbsp;violate&amp;nbsp;the&amp;nbsp;pod's&amp;nbsp;disruption&amp;nbsp;budget.&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;원인&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PDB `minAvailable=N` 인데 다른 replica 가 모두 다른 노드에서 NotReady&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;replica=1 + PDB 설정&amp;nbsp;&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해결&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;다른 노드의 같은 Pod replica health 확인 후 회복 (보통 옳은 길)&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;임시로 PDB 완화 후 재시도 (자체 책임)&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`--disable-eviction` 으로 강제 drain &amp;mdash; Pod 직접 delete (마지막 수단)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;
&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;color: #000000;&quot;&gt;실무 운영 팁&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인벤토리 로컬 백업&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Control Plane의 inventory를 로컬에 백업해두면, 서버 장애 시 복구에 유용하다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;scp -r somaz@10.10.10.17:~/kubespray/inventory/somaz-cluster \
  ~/my-project/kubespray/inventory-somaz-cluster&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;버전 확인 스크립트&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클러스터 상태를 빠르게 확인할 수 있는 스크립트를 만들어두면 편리하다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;#!/bin/bash
echo &quot;=== K8s Version ===&quot;
kubectl get nodes -o wide

echo &quot;&quot;
echo &quot;=== Kubespray Version ===&quot;
cd ~/kubespray &amp;amp;&amp;amp; git describe --tags

echo &quot;&quot;
echo &quot;=== Containerd Version ===&quot;
containerd --version

echo &quot;&quot;
echo &quot;=== Cilium Version ===&quot;
kubectl get ds cilium -n kube-system -o=jsonpath='{.spec.template.spec.containers[0].image}'
echo &quot;&quot;

echo &quot;&quot;
echo &quot;=== Certificate Expiration ===&quot;
sudo kubeadm certs check-expiration 2&amp;gt;/dev/null | head -15&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주의사항 정리&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;venv&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kubespray의 Python venv 활성화를 반드시 확인 (`source venv/bin/activate`)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;경로&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 ansible-playbook 명령은 `~/kubespray` 디렉토리에서 실행&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;facts.yml&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 추가 시 반드시 먼저 실행 (ipwrap 에러 방지)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kube_owner&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cilium 사용 시 root로 설정 필수&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;insecure registry&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서버 직접 수정 대신 inventory에서 관리 권장&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd 백업&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드 전 반드시 스냅샷 생성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;StatefulSet&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;drain 시 데이터 확인 필요&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Replica&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스 무중단을 위해 Deployment replica 2개 이상 권장&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubespray는 단순 설치 자동화를 넘어 운영 환경 수준의 쿠버네티스 클러스터 구성을 가능하게 해준다. 특히 다음과 같은 경우에 유용하다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;온프레미스나 사설 클라우드에서 빠른 배포가 필요할 때&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HA 클러스터, MetalLB/Ingress 구성 자동화가 필요할 때&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Terraform + Ansible 연동을 통한 IaC 기반 인프라 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CI 환경에서 테스트 클러스터 생성 및 제거 반복&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ansible 기반 자동화 &amp;rarr; 클러스터 구축 &amp;rarr; GitOps 기반 앱 배포라는 흐름을 갖추면 운영 자동화 수준을 한 단계 끌어올릴 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다음 포스팅에서는 Kubespray를 이용한 &lt;b&gt;Kubernetes 클러스터 업그레이드&lt;/b&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;&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;
&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/kubernetes-sigs/kubespray&quot;&gt;Kubespray GitHub&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/kubernetes-sigs/kubespray/releases&quot;&gt;Kubespray Releases&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/kubernetes-sigs/kubespray/blob/master/docs/operations/nodes.md&quot;&gt;Kubespray Node Management&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/cilium/cilium/issues/23838&quot;&gt;Cilium CNI Issue #23838&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubespray.io/#/docs/CNI/cilium&quot;&gt;Kubespray Cilium Docs&lt;/a&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Container Orchestration/Kubernetes</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/501</guid>
      <comments>https://somaz.tistory.com/501#entry501comment</comments>
      <pubDate>Wed, 8 Apr 2026 00:00:56 +0900</pubDate>
    </item>
    <item>
      <title>GCP CDN 서비스 완전 가이드 - Cloud CDN vs Media CDN vs Firebase Hosting 구현 전략</title>
      <link>https://somaz.tistory.com/463</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;글로벌 콘텐츠 전송이 애플리케이션 성능과 사용자 경험의 핵심 요소로 자리잡으면서, Google Cloud Platform(GCP)의 세 가지 CDN 솔루션이 주목받고 있다. &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;color: #000000;&quot;&gt;Cloud CDN은 일반적인 웹 콘텐츠에, Media CDN은 스트리밍과 대용량 파일 전송에, Firebase Hosting은 정적 웹 애플리케이션에 최적화되어 있다. 각 서비스는 고유한 최적화 전략과 비용 구조로 특정 콘텐츠 전송 요구사항을 해결한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이러한 서비스들 간의 차이점을 이해하면 성능, 비용, 운영 복잡성의 균형을 맞춘 최적의 콘텐츠 전송 아키텍처를 설계할 수 있다. Cloud CDN은 동적 콘텐츠 가속을 위해 Google Cloud Load Balancing과 완벽하게 통합되며, Media CDN은 고급 캐싱 정책을 통한 고대역폭 미디어 스트리밍에 특화되어 있다. Firebase Hosting은 내장 CDN 기능과 완벽한 CI/CD 통합을 제공하는 완전한 정적 호스팅 솔루션이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현대적인 콘텐츠 전송은 단순한 파일 캐싱을 넘어선다. 엣지 컴퓨팅 기능, 실시간 콘텐츠 최적화, 지능형 라우팅 알고리즘이 사용자 경험 지표에 상당한 영향을 미친다. GCP의 CDN 서비스들은 Google의 글로벌 네트워크 인프라를 활용하여 다양한 지리적 지역과 네트워크 조건에서 일관된 성능을 제공한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 포괄적인 분석에서는 플랫폼 선택 기준, 구현 전략, 성능 최적화 기법, 그리고 프로덕션 환경에서 즉시 적용할 수 있는 비용 효율적인 설계 패턴을 살펴본다. 고급 캐싱 전략, 엣지 컴퓨팅 통합, 최적의 콘텐츠 전송 성능을 보장하는 모니터링 접근법도 다룬다.&lt;/span&gt;&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-origin-width=&quot;2350&quot; data-origin-height=&quot;2406&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buIqRk/btsQB63Wab6/usr9SjKP9lejkgh9aXvWb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buIqRk/btsQB63Wab6/usr9SjKP9lejkgh9aXvWb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buIqRk/btsQB63Wab6/usr9SjKP9lejkgh9aXvWb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuIqRk%2FbtsQB63Wab6%2Fusr9SjKP9lejkgh9aXvWb1%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;2350&quot; height=&quot;2406&quot; data-origin-width=&quot;2350&quot; data-origin-height=&quot;2406&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GCP&amp;nbsp;CDN&amp;nbsp;서비스&amp;nbsp;완전&amp;nbsp;가이드&lt;/span&gt;&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;&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;color: #000000;&quot;&gt;GCP CDN 서비스 비교 분석&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2278&quot; data-origin-height=&quot;1646&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eg1HDB/btsQCrzB8za/cme1AoxGh33yChuoZRkBT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eg1HDB/btsQCrzB8za/cme1AoxGh33yChuoZRkBT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eg1HDB/btsQCrzB8za/cme1AoxGh33yChuoZRkBT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Feg1HDB%2FbtsQCrzB8za%2Fcme1AoxGh33yChuoZRkBT1%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;814&quot; height=&quot;588&quot; data-origin-width=&quot;2278&quot; data-origin-height=&quot;1646&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;&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스 특성 및 선택 매트릭스&amp;nbsp;&lt;/span&gt;&lt;/h3&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 사용 사례&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;콘텐츠 타입&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;통합 복잡성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 구조&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 초점&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud CDN&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;웹 애플리케이션, API, 동적 콘텐츠&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정적/동적 혼합&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용량 기반&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;글로벌 가속&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Media CDN&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비디오 스트리밍, 대용량 다운로드, 소프트웨어 배포&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;미디어 파일, 대용량 자산&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음-중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대역폭 최적화&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스트리밍 성능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Firebase Hosting&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정적 웹사이트, SPA, JAMstack 애플리케이션&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정적 자산만&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;무료 티어 제공&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;개발자 경험&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud CDN: 동적 콘텐츠 가속화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특징 및 아키텍처 장점&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud CDN은 Google Cloud Load Balancing과 긴밀하게 통합되어 정적 및 동적 콘텐츠 전송을 모두 가속화한다. 이 서비스는 복잡한 웹 애플리케이션에서 정적 자산 전송과 동적 콘텐츠 가속화를 모두 필요로 하는 경우에 이상적인 오리진 쉴딩, 스마트 라우팅, 캐시 무효화 기능을 제공한다.&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;color: #000000;&quot;&gt;플랫폼은 요청 헤더, 쿼리 매개변수, 사용자 정의 캐시 키에 기반한 세밀한 캐시 동작 제어가 가능한 고급 캐싱 정책을 지원한다. 이러한 유연성은 개인화된 콘텐츠나 복잡한 라우팅 요구사항이 있는 애플리케이션에서 정교한 캐싱 전략을 가능하게 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1818&quot; data-origin-height=&quot;1568&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt1Maj/btsQBtLvKfJ/XJP4Fewb5ImyodsFQcnS1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt1Maj/btsQBtLvKfJ/XJP4Fewb5ImyodsFQcnS1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt1Maj/btsQBtLvKfJ/XJP4Fewb5ImyodsFQcnS1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt1Maj%2FbtsQBtLvKfJ%2FXJP4Fewb5ImyodsFQcnS1k%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;1818&quot; height=&quot;1568&quot; data-origin-width=&quot;1818&quot; data-origin-height=&quot;1568&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고급 캐싱 전략&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud CDN은 다양한 콘텐츠 타입과 사용자 접근 패턴에 최적화된 정교한 캐싱 구성을 지원한다:&lt;/span&gt;&lt;/p&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;콘텐츠 타입&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;캐시 전략&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TTL 구성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;캐시 키 정책&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정적 자산&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장기 캐싱&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1년 (버전 관리)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;URL + 쿼리 매개변수&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API 응답&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단기 캐싱&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5-30분&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;URL + 헤더 + 인증 컨텍스트&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동적 페이지&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선택적 캐싱&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1-60분&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;URL + 사용자 세그먼트&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;개인화된 콘텐츠&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;엣지 사이드 인클루드&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프래그먼트별 가변&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자 정의 캐시 키&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud CDN Terraform 구현&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 로드 밸런서와 Cloud CDN 통합
resource &quot;google_compute_global_address&quot; &quot;cdn_ip&quot; {
  name = &quot;cdn-global-ip&quot;
}

resource &quot;google_compute_managed_ssl_certificate&quot; &quot;cdn_ssl&quot; {
  name = &quot;cdn-ssl-cert&quot;
  
  managed {
    domains = [var.domain_name, &quot;www.${var.domain_name}&quot;]
  }
}

resource &quot;google_compute_backend_service&quot; &quot;web_backend&quot; {
  name                  = &quot;web-backend-service&quot;
  protocol              = &quot;HTTP&quot;
  timeout_sec          = 30
  enable_cdn           = true
  
  # CDN 구성
  cdn_policy {
    cache_mode                   = &quot;CACHE_ALL_STATIC&quot;
    default_ttl                 = 3600
    max_ttl                     = 86400
    client_ttl                  = 7200
    negative_caching            = true
    serve_while_stale           = 86400
    
    # 사용자 정의 캐시 키 정책
    cache_key_policy {
      include_host           = true
      include_protocol       = true
      include_query_string   = false
      query_string_whitelist = [&quot;version&quot;, &quot;lang&quot;]
      
      include_http_headers = [
        &quot;Accept-Encoding&quot;,
        &quot;Accept-Language&quot;
      ]
    }
    
    # 부정 캐싱 정책
    negative_caching_policy {
      code = 404
      ttl  = 120
    }
    
    negative_caching_policy {
      code = 410
      ttl  = 3600
    }
  }
  
  backend {
    group                        = google_compute_instance_group.web_servers.self_link
    balancing_mode              = &quot;UTILIZATION&quot;
    max_utilization             = 0.8
    capacity_scaler             = 1.0
  }
  
  health_checks = [google_compute_health_check.web_health.id]
  
  # 사용자 정의 요청/응답 헤더
  custom_request_headers = [
    &quot;X-Client-Region:{client_region}&quot;,
    &quot;X-Client-City:{client_city}&quot;
  ]
  
  # 보안 헤더
  custom_response_headers = [
    &quot;X-Cache-Status:{cdn_cache_status}&quot;,
    &quot;X-Cache-Id:{cdn_cache_id}&quot;
  ]
}

# 정적 자산용 백엔드 버킷
resource &quot;google_compute_backend_bucket&quot; &quot;static_assets&quot; {
  name        = &quot;static-assets-backend&quot;
  bucket_name = google_storage_bucket.static_assets.name
  enable_cdn  = true
  
  cdn_policy {
    cache_mode       = &quot;CACHE_ALL_STATIC&quot;
    default_ttl     = 31536000  # 1년
    max_ttl         = 31536000
    client_ttl      = 86400     # 1일
    
    # 정적 자산의 적극적 캐싱
    cache_key_policy {
      include_host         = false
      include_protocol     = false
      include_query_string = true
    }
    
    # CORS 구성
    bypass_cache_on_request_headers = [
      &quot;Authorization&quot;,
      &quot;Cookie&quot;
    ]
  }
}

# 라우팅용 URL 맵
resource &quot;google_compute_url_map&quot; &quot;cdn_url_map&quot; {
  name            = &quot;cdn-url-map&quot;
  default_service = google_compute_backend_service.web_backend.id
  
  host_rule {
    hosts        = [var.domain_name, &quot;www.${var.domain_name}&quot;]
    path_matcher = &quot;main-matcher&quot;
  }
  
  path_matcher {
    name            = &quot;main-matcher&quot;
    default_service = google_compute_backend_service.web_backend.id
    
    # 정적 자산 라우팅
    path_rule {
      paths   = [&quot;/static/*&quot;, &quot;/assets/*&quot;, &quot;/images/*&quot;]
      service = google_compute_backend_bucket.static_assets.id
    }
    
    # API 라우팅 (다른 캐싱 정책)
    path_rule {
      paths   = [&quot;/api/*&quot;]
      service = google_compute_backend_service.api_backend.id
    }
  }
}

# HTTPS 로드 밸런서
resource &quot;google_compute_target_https_proxy&quot; &quot;cdn_proxy&quot; {
  name             = &quot;cdn-https-proxy&quot;
  url_map          = google_compute_url_map.cdn_url_map.id
  ssl_certificates = [google_compute_managed_ssl_certificate.cdn_ssl.id]
  ssl_policy       = google_compute_ssl_policy.modern_ssl.id
}

resource &quot;google_compute_global_forwarding_rule&quot; &quot;cdn_https&quot; {
  name       = &quot;cdn-https-rule&quot;
  target     = google_compute_target_https_proxy.cdn_proxy.id
  port_range = &quot;443&quot;
  ip_address = google_compute_global_address.cdn_ip.id
}

# HTTP에서 HTTPS로 리다이렉트
resource &quot;google_compute_target_http_proxy&quot; &quot;cdn_http_proxy&quot; {
  name    = &quot;cdn-http-proxy&quot;
  url_map = google_compute_url_map.https_redirect.id
}

resource &quot;google_compute_url_map&quot; &quot;https_redirect&quot; {
  name = &quot;https-redirect&quot;
  
  default_url_redirect {
    https_redirect         = true
    redirect_response_code = &quot;MOVED_PERMANENTLY_DEFAULT&quot;
    strip_query           = false
  }
}

resource &quot;google_compute_global_forwarding_rule&quot; &quot;cdn_http&quot; {
  name       = &quot;cdn-http-rule&quot;
  target     = google_compute_target_http_proxy.cdn_http_proxy.id
  port_range = &quot;80&quot;
  ip_address = google_compute_global_address.cdn_ip.id
}

# 현대적 보안을 위한 SSL 정책
resource &quot;google_compute_ssl_policy&quot; &quot;modern_ssl&quot; {
  name            = &quot;modern-ssl-policy&quot;
  profile         = &quot;MODERN&quot;
  min_tls_version = &quot;TLS_1_2&quot;
}

# 정적 자산용 스토리지 버킷
resource &quot;google_storage_bucket&quot; &quot;static_assets&quot; {
  name          = &quot;${var.project_id}-static-assets&quot;
  location      = &quot;US&quot;
  storage_class = &quot;STANDARD&quot;
  
  website {
    main_page_suffix = &quot;index.html&quot;
    not_found_page   = &quot;404.html&quot;
  }
  
  cors {
    origin          = [&quot;*&quot;]
    method          = [&quot;GET&quot;, &quot;HEAD&quot;]
    response_header = [&quot;Content-Type&quot;, &quot;Cache-Control&quot;]
    max_age_seconds = 3600
  }
  
  lifecycle_rule {
    condition {
      age = 365
    }
    action {
      type = &quot;Delete&quot;
    }
  }
}

# 캐시 무효화 자동화
resource &quot;google_cloudfunctions_function&quot; &quot;cache_invalidation&quot; {
  name        = &quot;cache-invalidation&quot;
  runtime     = &quot;python39&quot;
  entry_point = &quot;invalidate_cache&quot;
  
  source_archive_bucket = google_storage_bucket.functions_source.name
  source_archive_object = google_storage_bucket_object.cache_function.name
  
  event_trigger {
    event_type = &quot;google.storage.object.finalize&quot;
    resource   = google_storage_bucket.static_assets.name
  }
  
  environment_variables = {
    CDN_URL_MAP = google_compute_url_map.cdn_url_map.name
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Media CDN: 스트리밍 및 대용량 파일 최적화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스트리밍 중심 아키텍처&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Media CDN은 비디오 스트리밍, 소프트웨어 배포, 대용량 파일 다운로드를 위한 최적화 기능을 갖춘 고대역폭 콘텐츠 전송을 위해 특별히 설계되었다. 이 서비스는 적응형 비트레이트 스트리밍 지원, 바이트 범위 요청 최적화, 미디어 콘텐츠를 위한 지능형 프리페칭과 같은 고급 기능을 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1846&quot; data-origin-height=&quot;1554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8eUcU/btsQBRL6Wve/2C2IpHRiS5WKwVSdAVwyO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8eUcU/btsQBRL6Wve/2C2IpHRiS5WKwVSdAVwyO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8eUcU/btsQBRL6Wve/2C2IpHRiS5WKwVSdAVwyO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8eUcU%2FbtsQBRL6Wve%2F2C2IpHRiS5WKwVSdAVwyO0%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;830&quot; height=&quot;699&quot; data-origin-width=&quot;1846&quot; data-origin-height=&quot;1554&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;&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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고급 미디어 전송 기능&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Media CDN은 표준 CDN이 제공할 수 없는 미디어 및 대용량 파일 전송을 위한 전문 기능을 제공한다:&lt;/span&gt;&lt;/p&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기능&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Media CDN&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud CDN&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용 사례&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;바이트 범위 캐싱&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네이티브 지원&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대용량 파일 스트리밍, 재개 가능한 다운로드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비디오 최적화&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;내장 트랜스코딩&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;패스스루&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;적응형 비트레이트 스트리밍&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;엣지 컴퓨팅&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비디오 처리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 변환&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실시간 비디오 조작&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오리진 쉴드&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다단계 캐싱&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단일 단계&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인기 콘텐츠의 오리진 부하 감소&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;분석&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;미디어 전용 지표&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일반 웹 지표&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스트리밍 품질 모니터링&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Media CDN 구현&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# Media CDN 서비스 구성
resource &quot;google_network_services_edge_cache_service&quot; &quot;media_cdn&quot; {
  name        = &quot;media-cdn-service&quot;
  description = &quot;비디오 스트리밍 및 대용량 파일 전송을 위한 Media CDN&quot;
  
  routing {
    host_rule {
      description  = &quot;비디오 스트리밍 호스트&quot;
      hosts        = [&quot;stream.${var.domain_name}&quot;, &quot;video.${var.domain_name}&quot;]
      path_matcher = &quot;video-matcher&quot;
    }
    
    host_rule {
      description  = &quot;다운로드 호스트&quot;
      hosts        = [&quot;download.${var.domain_name}&quot;, &quot;files.${var.domain_name}&quot;]
      path_matcher = &quot;download-matcher&quot;
    }
    
    # 비디오 스트리밍 경로 매처
    path_matcher {
      name = &quot;video-matcher&quot;
      
      route_rule {
        description = &quot;라이브 스트리밍&quot;
        priority    = 1
        
        match_rule {
          path_template_match = &quot;/live/{stream_id}/{segment}.ts&quot;
        }
        
        origin = google_network_services_edge_cache_origin.live_origin.name
        route_action {
          cdn_policy {
            cache_mode = &quot;CACHE_ALL_STATIC&quot;
            default_ttl = &quot;10s&quot;  # 라이브 콘텐츠용 짧은 TTL
            max_ttl     = &quot;60s&quot;
            
            # 라이브 스트리밍 최적화
            cache_key_policy {
              excluded_query_parameters = [&quot;timestamp&quot;, &quot;token&quot;]
              include_protocol         = false
              include_host            = true
            }
          }
        }
      }
      
      route_rule {
        description = &quot;VOD 콘텐츠&quot;
        priority    = 2
        
        match_rule {
          path_template_match = &quot;/vod/{video_id}/{quality}/{segment}.m4s&quot;
        }
        
        origin = google_network_services_edge_cache_origin.vod_origin.name
        route_action {
          cdn_policy {
            cache_mode   = &quot;CACHE_ALL_STATIC&quot;
            default_ttl = &quot;86400s&quot;  # VOD용 24시간
            max_ttl     = &quot;31536000s&quot;  # 1년
            
            # 비디오 세그먼트용 범위 요청 지원
            cache_key_policy {
              include_protocol = false
              include_host    = false
            }
            
            # 누락된 세그먼트의 부정 캐싱
            negative_caching_policy {
              code = 404
              ttl  = &quot;300s&quot;
            }
          }
        }
      }
    }
    
    # 대용량 파일 다운로드 경로 매처
    path_matcher {
      name = &quot;download-matcher&quot;
      
      route_rule {
        description = &quot;소프트웨어 다운로드&quot;
        priority    = 1
        
        match_rule {
          path_template_match = &quot;/downloads/{software}/{version}/{file}&quot;
        }
        
        origin = google_network_services_edge_cache_origin.download_origin.name
        route_action {
          cdn_policy {
            cache_mode  = &quot;CACHE_ALL_STATIC&quot;
            default_ttl = &quot;2592000s&quot;  # 30일
            
            # 대용량 파일 다운로드 최적화
            cache_key_policy {
              include_protocol      = false
              include_query_string = false
            }
            
            # 범위 요청 캐싱 활성화
            signed_request_mode = &quot;DISABLED&quot;
          }
        }
      }
    }
  }
}

# 라이브 스트리밍 오리진
resource &quot;google_network_services_edge_cache_origin&quot; &quot;live_origin&quot; {
  name                 = &quot;live-streaming-origin&quot;
  origin_address      = &quot;live-origin.${var.domain_name}&quot;
  protocol            = &quot;HTTPS&quot;
  port                = 443
  max_attempts        = 3
  
  # 라이브 콘텐츠용 오리진 쉴드
  origin_override_action {
    header_action {
      request_headers_to_add {
        header_name  = &quot;X-Origin-Shield&quot;
        header_value = &quot;enabled&quot;
      }
    }
  }
  
  # 라이브 스트리밍용 타임아웃 구성
  timeout {
    connect_timeout = &quot;10s&quot;
    read_timeout    = &quot;30s&quot;
  }
}

# VOD 콘텐츠 오리진
resource &quot;google_network_services_edge_cache_origin&quot; &quot;vod_origin&quot; {
  name           = &quot;vod-content-origin&quot;
  origin_address = google_storage_bucket.video_content.url
  protocol       = &quot;HTTPS&quot;
  port           = 443
  
  # 안정성 향상을 위한 재시도 구성
  retry_policy {
    retry_conditions = [&quot;5XX&quot;, &quot;GATEWAY_ERROR&quot;, &quot;CONNECT_FAILURE&quot;]
    num_retries     = 3
    per_try_timeout = &quot;30s&quot;
  }
}

# 대용량 파일 다운로드 오리진
resource &quot;google_network_services_edge_cache_origin&quot; &quot;download_origin&quot; {
  name           = &quot;download-origin&quot;
  origin_address = google_storage_bucket.software_downloads.url
  protocol       = &quot;HTTPS&quot;
  port           = 443
  
  # 범위 요청 지원
  aws_v4_authentication {
    access_key_id     = var.aws_access_key_id
    secret_access_key = var.aws_secret_access_key
    origin_region     = var.aws_origin_region
  }
}

# 비디오 콘텐츠 스토리지
resource &quot;google_storage_bucket&quot; &quot;video_content&quot; {
  name          = &quot;${var.project_id}-video-content&quot;
  location      = &quot;US&quot;
  storage_class = &quot;STANDARD&quot;
  
  # 비디오 콘텐츠 생명주기 관리
  lifecycle_rule {
    condition {
      age                   = 90
      matches_storage_class = [&quot;STANDARD&quot;]
    }
    action {
      type          = &quot;SetStorageClass&quot;
      storage_class = &quot;NEARLINE&quot;
    }
  }
  
  lifecycle_rule {
    condition {
      age                   = 365
      matches_storage_class = [&quot;NEARLINE&quot;]
    }
    action {
      type          = &quot;SetStorageClass&quot;
      storage_class = &quot;COLDLINE&quot;
    }
  }
  
  # 비디오 플레이어용 CORS
  cors {
    origin          = [&quot;*&quot;]
    method          = [&quot;GET&quot;, &quot;HEAD&quot;, &quot;OPTIONS&quot;]
    response_header = [&quot;Accept-Ranges&quot;, &quot;Content-Range&quot;, &quot;Content-Length&quot;]
    max_age_seconds = 3600
  }
}

# 소프트웨어 다운로드 스토리지
resource &quot;google_storage_bucket&quot; &quot;software_downloads&quot; {
  name          = &quot;${var.project_id}-software-downloads&quot;
  location      = &quot;US&quot;
  storage_class = &quot;STANDARD&quot;
  
  # 다운로드용 공개 읽기 권한
  uniform_bucket_level_access = true
}

# 분석 및 모니터링
resource &quot;google_monitoring_dashboard&quot; &quot;media_cdn_dashboard&quot; {
  dashboard_json = jsonencode({
    displayName = &quot;Media CDN 성능 대시보드&quot;
    mosaicLayout = {
      tiles = [
        {
          width = 6
          height = 4
          widget = {
            title = &quot;캐시 적중률&quot;
            xyChart = {
              dataSets = [{
                timeSeriesQuery = {
                  timeSeriesFilter = {
                    filter = &quot;resource.type=\&quot;edge_cache_service\&quot;&quot;
                    aggregation = {
                      alignmentPeriod = &quot;60s&quot;
                      perSeriesAligner = &quot;ALIGN_RATE&quot;
                    }
                  }
                }
                plotType = &quot;LINE&quot;
              }]
              yAxis = {
                label = &quot;적중률 %&quot;
                scale = &quot;LINEAR&quot;
              }
            }
          }
        },
        {
          width = 6
          height = 4
          xPos = 6
          widget = {
            title = &quot;대역폭 사용량&quot;
            xyChart = {
              dataSets = [{
                timeSeriesQuery = {
                  timeSeriesFilter = {
                    filter = &quot;resource.type=\&quot;edge_cache_service\&quot;&quot;
                    aggregation = {
                      alignmentPeriod = &quot;300s&quot;
                      perSeriesAligner = &quot;ALIGN_RATE&quot;
                    }
                  }
                }
                plotType = &quot;STACKED_AREA&quot;
              }]
              yAxis = {
                label = &quot;바이트/초&quot;
                scale = &quot;LINEAR&quot;
              }
            }
          }
        }
      ]
    }
  })
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Firebase Hosting: 정적 사이트 전문 솔루션&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완전한 정적 호스팅 솔루션&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Firebase Hosting은 내장 CDN, SSL 인증서, 완벽한 CI/CD 통합을 갖춘 정적 웹사이트와 단일 페이지 애플리케이션을 위한 통합 솔루션이다. 이 플랫폼은 미리보기 채널, 사용자 정의 도메인, 자동 HTTPS와 같은 기능으로 뛰어난 개발자 경험을 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2032&quot; data-origin-height=&quot;1558&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b16cmS/btsQCwub1iY/iB8C3CpqOextDagJDonmS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b16cmS/btsQCwub1iY/iB8C3CpqOextDagJDonmS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b16cmS/btsQCwub1iY/iB8C3CpqOextDagJDonmS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb16cmS%2FbtsQCwub1iY%2FiB8C3CpqOextDagJDonmS0%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;2032&quot; height=&quot;1558&quot; data-origin-width=&quot;2032&quot; data-origin-height=&quot;1558&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고급 Firebase Hosting 구성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Firebase Hosting은 firebase.json 구성을 통해 정교한 라우팅 및 캐싱 기능을 제공한다:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;json&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;{
  &quot;hosting&quot;: {
    &quot;public&quot;: &quot;dist&quot;,
    &quot;ignore&quot;: [
      &quot;firebase.json&quot;,
      &quot;**/.*&quot;,
      &quot;**/node_modules/**&quot;
    ],
    &quot;rewrites&quot;: [
      {
        &quot;source&quot;: &quot;/api/**&quot;,
        &quot;function&quot;: &quot;api&quot;
      },
      {
        &quot;source&quot;: &quot;/admin/**&quot;,
        &quot;destination&quot;: &quot;/admin.html&quot;
      },
      {
        &quot;source&quot;: &quot;**&quot;,
        &quot;destination&quot;: &quot;/index.html&quot;
      }
    ],
    &quot;redirects&quot;: [
      {
        &quot;source&quot;: &quot;/old-page&quot;,
        &quot;destination&quot;: &quot;/new-page&quot;,
        &quot;type&quot;: 301
      }
    ],
    &quot;headers&quot;: [
      {
        &quot;source&quot;: &quot;**/*.@(jpg|jpeg|gif|png|svg|webp)&quot;,
        &quot;headers&quot;: [
          {
            &quot;key&quot;: &quot;Cache-Control&quot;,
            &quot;value&quot;: &quot;max-age=31536000&quot;
          }
        ]
      },
      {
        &quot;source&quot;: &quot;**/*.@(js|css)&quot;,
        &quot;headers&quot;: [
          {
            &quot;key&quot;: &quot;Cache-Control&quot;,
            &quot;value&quot;: &quot;max-age=31536000&quot;
          }
        ]
      },
      {
        &quot;source&quot;: &quot;/sw.js&quot;,
        &quot;headers&quot;: [
          {
            &quot;key&quot;: &quot;Cache-Control&quot;,
            &quot;value&quot;: &quot;max-age=0&quot;
          }
        ]
      },
      {
        &quot;source&quot;: &quot;**&quot;,
        &quot;headers&quot;: [
          {
            &quot;key&quot;: &quot;X-Content-Type-Options&quot;,
            &quot;value&quot;: &quot;nosniff&quot;
          },
          {
            &quot;key&quot;: &quot;X-Frame-Options&quot;,
            &quot;value&quot;: &quot;DENY&quot;
          },
          {
            &quot;key&quot;: &quot;X-XSS-Protection&quot;,
            &quot;value&quot;: &quot;1; mode=block&quot;
          }
        ]
      }
    ],
    &quot;cleanUrls&quot;: true,
    &quot;trailingSlash&quot;: false
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GitHub Actions와 CI/CD 통합&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# .github/workflows/firebase-deploy.yml
name: Firebase Hosting에 배포

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    
    steps:
    - name: 코드 체크아웃
      uses: actions/checkout@v3
      
    - name: Node.js 설정
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'
        
    - name: 의존성 설치
      run: npm ci
      
    - name: 테스트 실행
      run: npm run test:ci
      
    - name: 애플리케이션 빌드
      run: npm run build
      env:
        NODE_ENV: production
        
    - name: Firebase Hosting 미리보기 배포
      if: github.event_name == 'pull_request'
      uses: FirebaseExtended/action-hosting-deploy@v0
      with:
        repoToken: '${{ secrets.GITHUB_TOKEN }}'
        firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT }}'
        projectId: '${{ secrets.FIREBASE_PROJECT_ID }}'
        expires: 7d
        
    - name: Firebase Hosting 프로덕션 배포
      if: github.ref == 'refs/heads/main'
      uses: FirebaseExtended/action-hosting-deploy@v0
      with:
        repoToken: '${{ secrets.GITHUB_TOKEN }}'
        firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT }}'
        projectId: '${{ secrets.FIREBASE_PROJECT_ID }}'
        channelId: live
        
    - name: 성능 감사
      if: github.ref == 'refs/heads/main'
      run: |
        npm install -g lighthouse
        lighthouse https://${{ secrets.FIREBASE_PROJECT_ID }}.web.app --output=json --output-path=./lighthouse-results.json
        
    - name: Lighthouse 결과 업로드
      if: github.ref == 'refs/heads/main'
      uses: actions/upload-artifact@v3
      with:
        name: lighthouse-results
        path: lighthouse-results.json
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Terraform과 Firebase Hosting&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# Firebase 프로젝트 구성
resource &quot;google_firebase_project&quot; &quot;default&quot; {
  provider = google-beta
  project  = var.project_id
}

resource &quot;google_firebase_web_app&quot; &quot;basic&quot; {
  provider     = google-beta
  project      = var.project_id
  display_name = var.app_display_name
  
  depends_on = [google_firebase_project.default]
}

# 사용자 정의 도메인 구성
resource &quot;google_firebase_hosting_site&quot; &quot;default&quot; {
  provider = google-beta
  project  = var.project_id
  site_id  = var.site_id
  
  depends_on = [google_firebase_project.default]
}

resource &quot;google_firebase_hosting_custom_domain&quot; &quot;default&quot; {
  provider    = google-beta
  project     = var.project_id
  site_id     = google_firebase_hosting_site.default.site_id
  custom_domain = var.custom_domain
  
  cert_preference = &quot;GROUPED_CERT&quot;
  
  depends_on = [
    google_firebase_hosting_site.default,
    google_dns_record_set.firebase_domain_verification
  ]
}

# 사용자 정의 도메인용 DNS 구성
resource &quot;google_dns_managed_zone&quot; &quot;firebase_zone&quot; {
  name     = &quot;firebase-zone&quot;
  dns_name = &quot;${var.custom_domain}.&quot;
}

resource &quot;google_dns_record_set&quot; &quot;firebase_domain_verification&quot; {
  name = google_dns_managed_zone.firebase_zone.dns_name
  type = &quot;TXT&quot;
  ttl  = 300
  
  managed_zone = google_dns_managed_zone.firebase_zone.name
  
  rrdatas = [google_firebase_hosting_custom_domain.default.required_dns_updates[0].required_txt_record]
}

resource &quot;google_dns_record_set&quot; &quot;firebase_a_record&quot; {
  name = google_dns_managed_zone.firebase_zone.dns_name
  type = &quot;A&quot;
  ttl  = 300
  
  managed_zone = google_dns_managed_zone.firebase_zone.name
  
  rrdatas = [&quot;199.36.158.100&quot;]  # Firebase Hosting IP
}

# Firebase용 보안 규칙
resource &quot;google_firebase_hosting_release&quot; &quot;default&quot; {
  provider = google-beta
  site_id  = google_firebase_hosting_site.default.site_id
  version_name = &quot;v${formatdate(&quot;YYYYMMDD-hhmmss&quot;, timestamp())}&quot;
  
  message = &quot;Terraform을 통해 배포됨&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정적 vs 동적 콘텐츠 캐싱 전략&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;콘텐츠 분류 및 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;효과적인 CDN 구현은 콘텐츠 특성을 이해하고 적절한 캐싱 전략을 적용하는 것에서 시작된다.&lt;/span&gt;&lt;/p&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;콘텐츠 타입&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;캐싱 전략&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;권장 TTL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;캐시 헤더&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최적화 기법&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정적 자산 (이미지, CSS, JS)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;버전 관리를 통한 적극적 캐싱&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1년&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cache-Control: max-age=31536000, immutable&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;압축, WebP 변환, 축소화&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HTML 페이지&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;검증을 통한 단기 캐싱&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5-15분&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cache-Control: max-age=900, must-revalidate&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ETag 검증, 서버 사이드 인클루드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API 응답&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;맥락별 캐싱&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1-30분&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cache-Control: max-age=1800, private&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;개인화 헤더, 조건부 요청&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동적 콘텐츠&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;엣지 사이드 인클루드&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가변&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Surrogate-Control with tags&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프래그먼트 캐싱, 선택적 무효화&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;미디어 스트리밍&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;세그먼트 기반 캐싱&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;24시간 - 1주&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cache-Control: max-age=604800&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;범위 요청, 적응형 비트레이트&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고급 캐싱 패턴 구현&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;nix&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 다단계 캐싱 전략
resource &quot;google_compute_region_backend_service&quot; &quot;api_backend&quot; {
  name                  = &quot;api-backend-service&quot;
  protocol              = &quot;HTTP&quot;
  timeout_sec          = 30
  load_balancing_scheme = &quot;EXTERNAL_MANAGED&quot;
  
  # API 전용 CDN 구성
  cdn_policy {
    cache_mode                   = &quot;USE_ORIGIN_HEADERS&quot;
    default_ttl                 = 0
    max_ttl                     = 3600
    client_ttl                  = 300
    negative_caching            = true
    serve_while_stale           = 86400
    
    # API 엔드포인트용 사용자 정의 캐시 키
    cache_key_policy {
      include_host             = true
      include_protocol         = true
      include_query_string     = true
      query_string_whitelist   = [&quot;userId&quot;, &quot;version&quot;, &quot;locale&quot;]
      
      include_http_headers = [
        &quot;Authorization&quot;,
        &quot;Accept-Language&quot;,
        &quot;User-Agent&quot;
      ]
    }
    
    # 인증된 요청의 캐시 우회
    bypass_cache_on_request_headers = [
      &quot;Authorization&quot;,
      &quot;Cookie&quot;
    ]
    
    # API 오류의 부정 캐싱
    negative_caching_policy {
      code = 404
      ttl  = 300
    }
    
    negative_caching_policy {
      code = 500
      ttl  = 0
    }
  }
  
  backend {
    group                        = google_compute_instance_group.api_servers.self_link
    balancing_mode              = &quot;RATE&quot;
    max_rate_per_instance       = 100
    capacity_scaler             = 1.0
  }
}

# 엣지 사이드 인클루드 구성
resource &quot;google_compute_backend_service&quot; &quot;esi_backend&quot; {
  name       = &quot;esi-backend-service&quot;
  protocol   = &quot;HTTP&quot;
  enable_cdn = true
  
  cdn_policy {
    cache_mode       = &quot;CACHE_ALL_STATIC&quot;
    default_ttl     = 1800  # 30분
    max_ttl         = 7200  # 2시간
    
    # ESI 구성
    cache_key_policy {
      include_host         = true
      include_protocol     = false
      include_query_string = false
      
      # 개인화를 위한 사용자 세그먼트 포함
      include_http_headers = [
        &quot;X-User-Segment&quot;,
        &quot;X-Geo-Country&quot;
      ]
    }
  }
  
  # ESI 처리용 사용자 정의 헤더
  custom_request_headers = [
    &quot;X-Edge-Cache: enabled&quot;,
    &quot;X-ESI-Enabled: true&quot;
  ]
}

# 서로게이트 키를 통한 프래그먼트 캐싱
resource &quot;google_compute_backend_service&quot; &quot;fragment_cache&quot; {
  name       = &quot;fragment-cache-service&quot;
  protocol   = &quot;HTTP&quot;
  enable_cdn = true
  
  cdn_policy {
    cache_mode   = &quot;USE_ORIGIN_HEADERS&quot;
    default_ttl = 3600
    
    # 서로게이트 키 무효화 지원
    signed_request_mode = &quot;DISABLED&quot;
    
    cache_key_policy {
      include_host         = true
      include_protocol     = false
      include_query_string = true
      
      # 프래그먼트 전용 캐시 키
      query_string_whitelist = [
        &quot;fragment&quot;,
        &quot;version&quot;,
        &quot;user_type&quot;
      ]
    }
  }
  
  # 프래그먼트 캐시 관리용 헤더
  custom_response_headers = [
    &quot;Surrogate-Key: {fragment_type}&quot;,
    &quot;Cache-Tag: {content_version}&quot;
  ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;엣지 캐싱 및 성능 모니터링&lt;/span&gt;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;글로벌 성능 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;엣지 캐싱 전략은 다양한 지리적 지역에서의 사용자 경험에 상당한 영향을 미친다. GCP의 CDN 서비스는 포괄적인 성능 모니터링 및 최적화 기능을 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1328&quot; data-origin-height=&quot;1612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wF9JZ/btsQBUoz9wD/odrvfjbjXQlZPUOrfA8co1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wF9JZ/btsQBUoz9wD/odrvfjbjXQlZPUOrfA8co1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wF9JZ/btsQBUoz9wD/odrvfjbjXQlZPUOrfA8co1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwF9JZ%2FbtsQBUoz9wD%2FodrvfjbjXQlZPUOrfA8co1%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;824&quot; data-origin-width=&quot;1328&quot; data-origin-height=&quot;1612&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;&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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;포괄적인 모니터링 구현&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# CDN 성능 대시보드
resource &quot;google_monitoring_dashboard&quot; &quot;cdn_performance&quot; {
  dashboard_json = jsonencode({
    displayName = &quot;CDN 성능 분석&quot;
    mosaicLayout = {
      tiles = [
        {
          width = 6
          height = 4
          widget = {
            title = &quot;지역별 캐시 적중률&quot;
            xyChart = {
              dataSets = [{
                timeSeriesQuery = {
                  timeSeriesFilter = {
                    filter = &quot;resource.type=\&quot;https_lb_rule\&quot; AND metric.type=\&quot;loadbalancing.googleapis.com/https/request_count\&quot;&quot;
                    aggregation = {
                      alignmentPeriod = &quot;60s&quot;
                      perSeriesAligner = &quot;ALIGN_RATE&quot;
                      crossSeriesReducer = &quot;REDUCE_SUM&quot;
                      groupByFields = [&quot;resource.label.forwarding_rule_name&quot;, &quot;metric.label.cache_result&quot;]
                    }
                  }
                }
                plotType = &quot;STACKED_BAR&quot;
              }]
              yAxis = {
                label = &quot;초당 요청 수&quot;
                scale = &quot;LINEAR&quot;
              }
            }
          }
        },
        {
          width = 6
          height = 4
          xPos = 6
          widget = {
            title = &quot;오리진 응답 시간&quot;
            xyChart = {
              dataSets = [{
                timeSeriesQuery = {
                  timeSeriesFilter = {
                    filter = &quot;resource.type=\&quot;https_lb_rule\&quot; AND metric.type=\&quot;loadbalancing.googleapis.com/https/backend_request_count\&quot;&quot;
                    aggregation = {
                      alignmentPeriod = &quot;300s&quot;
                      perSeriesAligner = &quot;ALIGN_MEAN&quot;
                      groupByFields = [&quot;resource.label.backend_service_name&quot;]
                    }
                  }
                }
                plotType = &quot;LINE&quot;
              }]
              yAxis = {
                label = &quot;응답 시간 (ms)&quot;
                scale = &quot;LINEAR&quot;
              }
            }
          }
        },
        {
          width = 12
          height = 4
          yPos = 4
          widget = {
            title = &quot;콘텐츠 타입별 대역폭 사용량&quot;
            xyChart = {
              dataSets = [{
                timeSeriesQuery = {
                  timeSeriesFilter = {
                    filter = &quot;resource.type=\&quot;https_lb_rule\&quot;&quot;
                    aggregation = {
                      alignmentPeriod = &quot;300s&quot;
                      perSeriesAligner = &quot;ALIGN_RATE&quot;
                      crossSeriesReducer = &quot;REDUCE_SUM&quot;
                      groupByFields = [&quot;metric.label.cache_result&quot;]
                    }
                  }
                }
                plotType = &quot;STACKED_AREA&quot;
              }]
              yAxis = {
                label = &quot;바이트/초&quot;
                scale = &quot;LINEAR&quot;
              }
            }
          }
        }
      ]
    }
  })
}

# CDN 성능 알림 정책
resource &quot;google_monitoring_alert_policy&quot; &quot;cache_hit_ratio_low&quot; {
  display_name = &quot;CDN 캐시 적중률 낮음&quot;
  combiner     = &quot;OR&quot;
  
  conditions {
    display_name = &quot;캐시 적중률이 80% 미만&quot;
    
    condition_threshold {
      filter          = &quot;resource.type=\&quot;https_lb_rule\&quot;&quot;
      comparison      = &quot;COMPARISON_LT&quot;
      threshold_value = 0.8
      duration        = &quot;300s&quot;
      
      aggregations {
        alignment_period     = &quot;300s&quot;
        per_series_aligner  = &quot;ALIGN_RATE&quot;
        cross_series_reducer = &quot;REDUCE_MEAN&quot;
        group_by_fields     = [&quot;resource.label.forwarding_rule_name&quot;]
      }
    }
  }
  
  notification_channels = [google_monitoring_notification_channel.email.id]
  
  alert_strategy {
    auto_close = &quot;1800s&quot;
  }
}

resource &quot;google_monitoring_alert_policy&quot; &quot;origin_response_time_high&quot; {
  display_name = &quot;오리진 응답 시간 높음&quot;
  combiner     = &quot;OR&quot;
  
  conditions {
    display_name = &quot;오리진 응답 시간이 2초 초과&quot;
    
    condition_threshold {
      filter          = &quot;resource.type=\&quot;https_lb_rule\&quot;&quot;
      comparison      = &quot;COMPARISON_GT&quot;
      threshold_value = 2000
      duration        = &quot;120s&quot;
      
      aggregations {
        alignment_period    = &quot;60s&quot;
        per_series_aligner = &quot;ALIGN_MEAN&quot;
      }
    }
  }
  
  notification_channels = [google_monitoring_notification_channel.slack.id]
}

# 고급 모니터링용 사용자 정의 지표
resource &quot;google_logging_metric&quot; &quot;cdn_performance_score&quot; {
  name   = &quot;cdn_performance_score&quot;
  filter = &quot;resource.type=\&quot;https_lb_rule\&quot; AND jsonPayload.performance_score &amp;gt; 0&quot;
  
  metric_descriptor {
    metric_kind = &quot;GAUGE&quot;
    value_type  = &quot;DOUBLE&quot;
    display_name = &quot;CDN 성능 점수&quot;
  }
  
  value_extractor = &quot;EXTRACT(jsonPayload.performance_score)&quot;
  
  label_extractors = {
    region       = &quot;EXTRACT(jsonPayload.edge_location)&quot;
    content_type = &quot;EXTRACT(jsonPayload.content_type)&quot;
    cache_status = &quot;EXTRACT(jsonPayload.cache_status)&quot;
  }
}

# 성능 최적화 자동화
resource &quot;google_cloudfunctions_function&quot; &quot;cdn_optimizer&quot; {
  name        = &quot;cdn-performance-optimizer&quot;
  runtime     = &quot;python39&quot;
  entry_point = &quot;optimize_cdn_performance&quot;
  
  source_archive_bucket = google_storage_bucket.functions_source.name
  source_archive_object = google_storage_bucket_object.optimizer_function.name
  
  event_trigger {
    event_type = &quot;google.pubsub.topic.publish&quot;
    resource   = google_pubsub_topic.cdn_metrics.name
  }
  
  environment_variables = {
    CDN_SERVICE_NAME = google_network_services_edge_cache_service.media_cdn.name
    THRESHOLD_HIT_RATIO = &quot;0.85&quot;
    OPTIMIZATION_ENABLED = &quot;true&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 및 운영 효율성&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 전략&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CDN 비용은 트래픽 패턴, 지리적 분포, 캐싱 효율성에 따라 크게 달라질 수 있다. 비용 효율적인 설계 패턴을 구현하면 최적의 ROI를 보장할 수 있다.&lt;/span&gt;&lt;/p&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 요소&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud CDN&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Media CDN&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Firebase Hosting&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최적화 전략&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 전송&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.08-0.20/GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.04-0.15/GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.15/GB (무료 티어 이후)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;캐시 적중률 최대화&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HTTP/HTTPS 요청&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.0075/10K 요청&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.0060/10K 요청&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.40/10K 요청&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;요청 빈도 감소&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;캐시 무효화&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.005/요청&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.005/요청&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;무료&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;무효화 일괄 처리&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오리진 대역폭&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;표준 이그레스 요금&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;표준 이그레스 요금&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해당 없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오리진 쉴드 구현&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다단계 비용 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3106&quot; data-origin-height=&quot;1454&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJxAEq/btsQCMctUp2/uy29pvm2auxIWQQRN7DgV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJxAEq/btsQCMctUp2/uy29pvm2auxIWQQRN7DgV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJxAEq/btsQCMctUp2/uy29pvm2auxIWQQRN7DgV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJxAEq%2FbtsQCMctUp2%2Fuy29pvm2auxIWQQRN7DgV1%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;3106&quot; height=&quot;1454&quot; data-origin-width=&quot;3106&quot; data-origin-height=&quot;1454&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;&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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 구현&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 비용 최적화를 위한 다중 서비스 CDN 아키텍처
resource &quot;google_storage_bucket&quot; &quot;cost_optimized_assets&quot; {
  name          = &quot;${var.project_id}-cost-optimized-assets&quot;
  location      = &quot;US&quot;
  storage_class = &quot;STANDARD&quot;
  
  # 비용 최적화를 위한 생명주기 관리
  lifecycle_rule {
    condition {
      age = 30
      matches_storage_class = [&quot;STANDARD&quot;]
    }
    action {
      type          = &quot;SetStorageClass&quot;
      storage_class = &quot;NEARLINE&quot;
    }
  }
  
  lifecycle_rule {
    condition {
      age = 365
      matches_storage_class = [&quot;NEARLINE&quot;]
    }
    action {
      type          = &quot;SetStorageClass&quot;
      storage_class = &quot;COLDLINE&quot;
    }
  }
  
  # 오래된 버전 자동 삭제
  lifecycle_rule {
    condition {
      age                        = 90
      matches_storage_class     = [&quot;STANDARD&quot;, &quot;NEARLINE&quot;]
      num_newer_versions        = 5
    }
    action {
      type = &quot;Delete&quot;
    }
  }
}

# 오리진 쉴드가 있는 비용 최적화 백엔드 서비스
resource &quot;google_compute_backend_service&quot; &quot;cost_optimized_backend&quot; {
  name       = &quot;cost-optimized-backend&quot;
  protocol   = &quot;HTTP&quot;
  enable_cdn = true
  
  cdn_policy {
    cache_mode                   = &quot;CACHE_ALL_STATIC&quot;
    default_ttl                 = 86400    # 24시간
    max_ttl                     = 2592000  # 30일
    client_ttl                  = 3600     # 1시간
    negative_caching            = true
    serve_while_stale           = 86400
    
    # 비용 절감을 위한 오리진 쉴드
    cache_key_policy {
      include_host         = false
      include_protocol     = false
      include_query_string = false
    }
    
    # 적극적인 압축
    signed_request_mode = &quot;DISABLED&quot;
  }
  
  # 오리진 쉴드 구성
  backend {
    group                        = google_compute_instance_group.origin_shield.self_link
    balancing_mode              = &quot;UTILIZATION&quot;
    max_utilization             = 0.9
    capacity_scaler             = 1.0
  }
  
  # 압축 설정
  compression_mode = &quot;AUTOMATIC&quot;
  
  custom_request_headers = [
    &quot;X-Origin-Shield: enabled&quot;,
    &quot;Accept-Encoding: gzip, br&quot;
  ]
}

# 비용 모니터링 및 알림
resource &quot;google_monitoring_alert_policy&quot; &quot;cdn_cost_alert&quot; {
  display_name = &quot;CDN 비용 임계값 알림&quot;
  combiner     = &quot;OR&quot;
  
  conditions {
    display_name = &quot;월간 CDN 비용이 예산 초과&quot;
    
    condition_threshold {
      filter          = &quot;resource.type=\&quot;global_load_balancer\&quot;&quot;
      comparison      = &quot;COMPARISON_GT&quot;
      threshold_value = var.monthly_cdn_budget
      duration        = &quot;3600s&quot;
      
      aggregations {
        alignment_period = &quot;3600s&quot;
        per_series_aligner = &quot;ALIGN_SUM&quot;
      }
    }
  }
  
  notification_channels = [google_monitoring_notification_channel.cost_alerts.id]
}

# 자동화된 비용 최적화
resource &quot;google_cloud_scheduler_job&quot; &quot;cost_optimization&quot; {
  name      = &quot;cdn-cost-optimization&quot;
  schedule  = &quot;0 */6 * * *&quot;  # 6시간마다
  time_zone = &quot;UTC&quot;
  
  http_target {
    http_method = &quot;POST&quot;
    uri         = google_cloudfunctions_function.cost_optimizer.https_trigger_url
    
    headers = {
      &quot;Content-Type&quot; = &quot;application/json&quot;
    }
    
    body = base64encode(jsonencode({
      action = &quot;optimize_cdn_costs&quot;
      threshold = var.cost_optimization_threshold
    }))
  }
}

# 예산 구성
resource &quot;google_billing_budget&quot; &quot;cdn_budget&quot; {
  billing_account = var.billing_account
  display_name    = &quot;CDN 서비스 예산&quot;
  
  budget_filter {
    projects = [&quot;projects/${var.project_id}&quot;]
    services = [
      &quot;services/95FF2D27-F988-46BA-B4C7-9A6588B11B9E&quot;,  # Cloud CDN
      &quot;services/A1E8-BE35-4EDC-9F00-1EA502E1B960&quot;       # Firebase Hosting
    ]
  }
  
  amount {
    specified_amount {
      currency_code = &quot;USD&quot;
      units         = tostring(var.monthly_cdn_budget)
    }
  }
  
  threshold_rules {
    threshold_percent = 1.0
    spend_basis      = &quot;FORECASTED_SPEND&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고급 통합 패턴&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다중 CDN 하이브리드 아키텍처&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;미션 크리티컬한 애플리케이션에서는 하이브리드 CDN 전략을 구현하여 중복성과 성능 최적화를 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2966&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oMD63/btsQBwBvdbv/E4AwJNb5iCq6Cmd7X2Nqo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oMD63/btsQBwBvdbv/E4AwJNb5iCq6Cmd7X2Nqo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oMD63/btsQBwBvdbv/E4AwJNb5iCq6Cmd7X2Nqo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoMD63%2FbtsQBwBvdbv%2FE4AwJNb5iCq6Cmd7X2Nqo0%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;2966&quot; height=&quot;1000&quot; data-origin-width=&quot;2966&quot; data-origin-height=&quot;1000&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;엣지 컴퓨팅 통합&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;nix&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# Cloud Functions를 활용한 엣지 컴퓨팅
resource &quot;google_cloudfunctions_function&quot; &quot;edge_processor&quot; {
  name        = &quot;edge-content-processor&quot;
  runtime     = &quot;python39&quot;
  entry_point = &quot;process_edge_request&quot;
  
  source_archive_bucket = google_storage_bucket.functions_source.name
  source_archive_object = google_storage_bucket_object.edge_function.name
  
  https_trigger {
    url = &quot;https://${var.region}-${var.project_id}.cloudfunctions.net/edge-content-processor&quot;
  }
  
  environment_variables = {
    CDN_CACHE_CONTROL = &quot;max-age=3600&quot;
    IMAGE_OPTIMIZATION = &quot;enabled&quot;
    COMPRESSION_LEVEL = &quot;6&quot;
  }
  
  # 엣지 컴퓨팅을 위한 지역별 배포
  region = var.region
}

# 엣지에서의 이미지 최적화
resource &quot;google_cloudfunctions_function&quot; &quot;image_optimizer&quot; {
  name        = &quot;edge-image-optimizer&quot;
  runtime     = &quot;python39&quot;
  entry_point = &quot;optimize_image&quot;
  
  source_archive_bucket = google_storage_bucket.functions_source.name
  source_archive_object = google_storage_bucket_object.image_optimizer.name
  
  https_trigger {
    url = &quot;https://${var.region}-${var.project_id}.cloudfunctions.net/optimize-image&quot;
  }
  
  environment_variables = {
    WEBP_QUALITY = &quot;85&quot;
    AVIF_QUALITY = &quot;80&quot;
    RESIZE_ALGORITHM = &quot;lanczos&quot;
    CACHE_TTL = &quot;31536000&quot;  # 최적화된 이미지용 1년
  }
}

# 실시간 콘텐츠 개인화
resource &quot;google_cloudfunctions_function&quot; &quot;content_personalizer&quot; {
  name        = &quot;edge-content-personalizer&quot;
  runtime     = &quot;nodejs18&quot;
  entry_point = &quot;personalizeContent&quot;
  
  source_archive_bucket = google_storage_bucket.functions_source.name
  source_archive_object = google_storage_bucket_object.personalizer_function.name
  
  https_trigger {
    url = &quot;https://${var.region}-${var.project_id}.cloudfunctions.net/personalize&quot;
  }
  
  environment_variables = {
    PERSONALIZATION_API = google_apikeys_key.personalization_api.key_string
    USER_SEGMENT_TTL = &quot;1800&quot;  # 30분
    CONTENT_CACHE_TTL = &quot;300&quot;  # 5분
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지능형 트래픽 라우팅&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 지능형 CDN 라우팅을 위한 Cloud Function
import json
import requests
from google.cloud import monitoring_v3
from google.cloud import dns

def intelligent_routing(request):
    &quot;&quot;&quot;실시간 성능을 기반으로 최적의 CDN으로 트래픽 라우팅&quot;&quot;&quot;
    
    request_json = request.get_json()
    user_location = request_json.get('location', {})
    content_type = request_json.get('content_type', 'web')
    
    # 현재 CDN 성능 지표 분석
    performance_metrics = get_cdn_performance_metrics()
    
    # 요청에 최적인 CDN 결정
    optimal_cdn = select_optimal_cdn(
        user_location, 
        content_type, 
        performance_metrics
    )
    
    # 라우팅 결정 생성
    routing_decision = {
        'cdn_service': optimal_cdn,
        'cache_policy': get_cache_policy(content_type),
        'routing_reason': f&quot;{user_location.get('country', 'unknown')}의 {content_type}에 최적&quot;
    }
    
    return json.dumps(routing_decision)

def get_cdn_performance_metrics():
    &quot;&quot;&quot;실시간 CDN 성능 지표 조회&quot;&quot;&quot;
    client = monitoring_v3.MetricServiceClient()
    project_name = f&quot;projects/{os.environ['GCP_PROJECT']}&quot;
    
    # 다양한 CDN 서비스 지표 쿼리
    metrics = {}
    
    # Cloud CDN 지표
    metrics['cloud_cdn'] = {
        'latency': query_latency_metric(client, project_name, 'cloud_cdn'),
        'hit_ratio': query_hit_ratio_metric(client, project_name, 'cloud_cdn'),
        'availability': query_availability_metric(client, project_name, 'cloud_cdn')
    }
    
    # Media CDN 지표
    metrics['media_cdn'] = {
        'latency': query_latency_metric(client, project_name, 'media_cdn'),
        'hit_ratio': query_hit_ratio_metric(client, project_name, 'media_cdn'),
        'availability': query_availability_metric(client, project_name, 'media_cdn')
    }
    
    # Firebase Hosting 지표
    metrics['firebase_hosting'] = {
        'latency': query_latency_metric(client, project_name, 'firebase'),
        'hit_ratio': 0.95,  # Firebase는 뛰어난 캐싱 성능을 보임
        'availability': 0.999
    }
    
    return metrics

def select_optimal_cdn(user_location, content_type, performance_metrics):
    &quot;&quot;&quot;콘텐츠 타입과 성능을 기반으로 최적의 CDN 선택&quot;&quot;&quot;
    
    # 콘텐츠 타입 라우팅 규칙
    if content_type in ['video', 'audio', 'large_file']:
        # Media CDN이 스트리밍 콘텐츠에 최적
        if performance_metrics['media_cdn']['availability'] &amp;gt; 0.99:
            return 'media_cdn'
    
    elif content_type in ['static', 'spa', 'jamstack']:
        # 정적 콘텐츠는 Firebase Hosting
        if performance_metrics['firebase_hosting']['availability'] &amp;gt; 0.99:
            return 'firebase_hosting'
    
    # 동적 콘텐츠는 기본적으로 Cloud CDN
    if performance_metrics['cloud_cdn']['availability'] &amp;gt; 0.99:
        return 'cloud_cdn'
    
    # 최고 성능을 기반으로 한 폴백 로직
    best_cdn = 'cloud_cdn'
    best_score = 0
    
    for cdn, metrics in performance_metrics.items():
        score = (
            metrics['availability'] * 0.4 +
            (1 - metrics['latency'] / 2000) * 0.4 +  # 지연시간 정규화
            metrics['hit_ratio'] * 0.2
        )
        
        if score &amp;gt; best_score:
            best_score = score
            best_cdn = cdn
    
    return best_cdn

def get_cache_policy(content_type):
    &quot;&quot;&quot;콘텐츠 타입에 따른 캐시 정책 반환&quot;&quot;&quot;
    cache_policies = {
        'static': {
            'ttl': 31536000,  # 1년
            'cache_control': 'public, max-age=31536000, immutable'
        },
        'dynamic': {
            'ttl': 900,  # 15분
            'cache_control': 'public, max-age=900, must-revalidate'
        },
        'video': {
            'ttl': 86400,  # 24시간
            'cache_control': 'public, max-age=86400'
        },
        'api': {
            'ttl': 300,  # 5분
            'cache_control': 'public, max-age=300, s-maxage=1800'
        }
    }
    
    return cache_policies.get(content_type, cache_policies['dynamic'])
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 및 컴플라이언스 고려사항&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CDN 보안 구현&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2128&quot; data-origin-height=&quot;1498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2iWOs/btsQCPUz40i/Ihldwknrmh0uHQ8aY2rVD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2iWOs/btsQCPUz40i/Ihldwknrmh0uHQ8aY2rVD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2iWOs/btsQCPUz40i/Ihldwknrmh0uHQ8aY2rVD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2iWOs%2FbtsQCPUz40i%2FIhldwknrmh0uHQ8aY2rVD0%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;2128&quot; height=&quot;1498&quot; data-origin-width=&quot;2128&quot; data-origin-height=&quot;1498&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 구성 구현&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# CDN용 Cloud Armor 보안 정책
resource &quot;google_compute_security_policy&quot; &quot;cdn_security&quot; {
  name = &quot;cdn-security-policy&quot;
  
  # 기본 규칙 - 모든 트래픽 허용
  rule {
    action   = &quot;allow&quot;
    priority = &quot;2147483647&quot;
    match {
      versioned_expr = &quot;SRC_IPS_V1&quot;
      config {
        src_ip_ranges = [&quot;*&quot;]
      }
    }
    description = &quot;기본 허용 규칙&quot;
  }
  
  # 요청 제한 규칙
  rule {
    action   = &quot;rate_based_ban&quot;
    priority = &quot;1000&quot;
    match {
      versioned_expr = &quot;SRC_IPS_V1&quot;
      config {
        src_ip_ranges = [&quot;*&quot;]
      }
    }
    rate_limit_options {
      conform_action = &quot;allow&quot;
      exceed_action  = &quot;deny(429)&quot;
      enforce_on_key = &quot;IP&quot;
      
      rate_limit_threshold {
        count        = 100
        interval_sec = 60
      }
      
      ban_threshold {
        count        = 1000
        interval_sec = 300
      }
      
      ban_duration_sec = 3600
    }
    description = &quot;요청 제한 규칙&quot;
  }
  
  # 지리적 차단 규칙
  rule {
    action   = &quot;deny(403)&quot;
    priority = &quot;1100&quot;
    match {
      expr {
        expression = &quot;origin.region_code == 'CN' || origin.region_code == 'RU'&quot;
      }
    }
    description = &quot;특정 지역 차단&quot;
  }
  
  # SQL 인젝션 보호
  rule {
    action   = &quot;deny(403)&quot;
    priority = &quot;1200&quot;
    match {
      expr {
        expression = &quot;evaluatePreconfiguredExpr('sqli-stable')&quot;
      }
    }
    description = &quot;SQL 인젝션 보호&quot;
  }
  
  # XSS 보호
  rule {
    action   = &quot;deny(403)&quot;
    priority = &quot;1300&quot;
    match {
      expr {
        expression = &quot;evaluatePreconfiguredExpr('xss-stable')&quot;
      }
    }
    description = &quot;XSS 보호&quot;
  }
}

# 백엔드 서비스에 보안 정책 적용
resource &quot;google_compute_backend_service&quot; &quot;secure_backend&quot; {
  name            = &quot;secure-backend-service&quot;
  protocol        = &quot;HTTP&quot;
  enable_cdn      = true
  security_policy = google_compute_security_policy.cdn_security.id
  
  cdn_policy {
    cache_mode       = &quot;CACHE_ALL_STATIC&quot;
    default_ttl     = 3600
    signed_url_cache_max_age_sec = 3600
    
    # 보안 캐시 키 정책
    cache_key_policy {
      include_host         = true
      include_protocol     = true
      include_query_string = false
      
      # 캐시 키에서 민감한 헤더 제외
      include_http_headers = []
    }
    
    # 보안을 위한 부정 캐싱
    negative_caching = true
    negative_caching_policy {
      code = 403
      ttl  = 120
    }
    negative_caching_policy {
      code = 404
      ttl  = 300
    }
  }
  
  # 보안 헤더
  custom_response_headers = [
    &quot;Strict-Transport-Security: max-age=31536000; includeSubDomains&quot;,
    &quot;X-Content-Type-Options: nosniff&quot;,
    &quot;X-Frame-Options: DENY&quot;,
    &quot;X-XSS-Protection: 1; mode=block&quot;,
    &quot;Referrer-Policy: strict-origin-when-cross-origin&quot;,
    &quot;Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'&quot;
  ]
}

# 보호된 콘텐츠용 서명된 URL 생성
resource &quot;google_storage_bucket&quot; &quot;protected_content&quot; {
  name          = &quot;${var.project_id}-protected-content&quot;
  location      = &quot;US&quot;
  storage_class = &quot;STANDARD&quot;
  
  # 공개 접근 방지
  uniform_bucket_level_access = true
  
  # 콘텐츠 무결성을 위한 버전 관리 활성화
  versioning {
    enabled = true
  }
  
  # 생명주기 관리
  lifecycle_rule {
    condition {
      age = 7
    }
    action {
      type = &quot;Delete&quot;
    }
  }
}

# 서명된 URL 생성용 IAM
resource &quot;google_service_account&quot; &quot;signed_url_generator&quot; {
  account_id   = &quot;signed-url-generator&quot;
  display_name = &quot;서명된 URL 생성기 서비스 계정&quot;
}

resource &quot;google_storage_bucket_iam_member&quot; &quot;signed_url_access&quot; {
  bucket = google_storage_bucket.protected_content.name
  role   = &quot;roles/storage.objectViewer&quot;
  member = &quot;serviceAccount:${google_service_account.signed_url_generator.email}&quot;
}

# 서명된 URL 생성용 Cloud Function
resource &quot;google_cloudfunctions_function&quot; &quot;signed_url_generator&quot; {
  name        = &quot;generate-signed-urls&quot;
  runtime     = &quot;python39&quot;
  entry_point = &quot;generate_signed_url&quot;
  
  source_archive_bucket = google_storage_bucket.functions_source.name
  source_archive_object = google_storage_bucket_object.signed_url_function.name
  
  https_trigger {
    url = &quot;https://${var.region}-${var.project_id}.cloudfunctions.net/generate-signed-url&quot;
  }
  
  service_account_email = google_service_account.signed_url_generator.email
  
  environment_variables = {
    BUCKET_NAME = google_storage_bucket.protected_content.name
    URL_EXPIRY_HOURS = &quot;24&quot;
    ALLOWED_IPS = var.allowed_ip_ranges
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 벤치마킹 및 테스팅&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;포괄적인 테스팅 프레임워크&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CDN 성능 테스팅은 지연시간, 처리량, 캐시 효율성, 글로벌 분산 효과성을 포함한 여러 차원에서 체계적인 평가가 필요하다.&lt;/span&gt;&lt;/p&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;테스트 카테고리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지표&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;도구&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;목표 성능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지연시간 테스팅&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TTFB, 왕복 시간, 엣지 응답 시간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Lighthouse, WebPageTest, 사용자 정의 모니터링&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;글로벌 P95 &amp;lt; 100ms&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처리량 테스팅&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대역폭 활용률, 동시 연결&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Apache Bench, JMeter, 부하 테스트 도구&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;엣지 위치당 &amp;gt; 10 Gbps&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;캐시 효율성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;적중률, 캐시 침투, 오리진 부하&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CDN 분석, 사용자 정의 대시보드&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;캐시 적중률 &amp;gt; 90%&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;글로벌 분산&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지리적 커버리지, 지역별 성능&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다중 지역 테스팅, 사용자 경험 모니터링&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전 세계 일관된 성능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동화된 성능 테스팅&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;nix&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 성능 테스팅을 위한 Cloud Build
resource &quot;google_cloudbuild_trigger&quot; &quot;performance_tests&quot; {
  name = &quot;cdn-performance-tests&quot;
  
  github {
    owner = var.github_owner
    name  = var.github_repo
    push {
      branch = &quot;^main$&quot;
    }
  }
  
  build {
    # Lighthouse 성능 감사
    step {
      name = &quot;gcr.io/cloud-builders/npm&quot;
      args = [
        &quot;install&quot;, &quot;-g&quot;, 
        &quot;lighthouse&quot;, 
        &quot;lighthouse-ci&quot;
      ]
    }
    
    step {
      name = &quot;gcr.io/cloud-builders/npm&quot;
      args = [
        &quot;run&quot;, 
        &quot;lighthouse:ci&quot;
      ]
      env = [
        &quot;LHCI_GITHUB_APP_TOKEN=${var.lighthouse_github_token}&quot;,
        &quot;LHCI_SERVER_BASE_URL=${var.lighthouse_server_url}&quot;
      ]
    }
    
    # Artillery를 사용한 부하 테스팅
    step {
      name = &quot;gcr.io/cloud-builders/npm&quot;
      args = [
        &quot;install&quot;, &quot;-g&quot;, 
        &quot;artillery&quot;
      ]
    }
    
    step {
      name = &quot;gcr.io/cloud-builders/npm&quot;
      args = [
        &quot;run&quot;,
        &quot;loadtest:cdn&quot;
      ]
      env = [
        &quot;CDN_BASE_URL=${var.cdn_base_url}&quot;,
        &quot;TEST_DURATION=300&quot;,  # 5분
        &quot;CONCURRENT_USERS=100&quot;
      ]
    }
    
    # 캐시 성능 검증
    step {
      name = &quot;gcr.io/cloud-builders/curl&quot;
      args = [
        &quot;-s&quot;, &quot;-w&quot;, 
        &quot;cache_status:%{http_code}\\nresponse_time:%{time_total}\\n&quot;,
        &quot;-H&quot;, &quot;Cache-Control: no-cache&quot;,
        &quot;${var.cdn_base_url}/test-endpoint&quot;
      ]
    }
    
    # 글로벌 성능 테스팅
    step {
      name = &quot;gcr.io/cloud-builders/gcloud&quot;
      args = [
        &quot;functions&quot;, &quot;call&quot;, &quot;global-performance-test&quot;,
        &quot;--region&quot;, var.region,
        &quot;--data&quot;, &quot;{\&quot;test_urls\&quot;:[\&quot;${var.cdn_base_url}\&quot;]}&quot;
      ]
    }
  }
  
  substitutions = {
    _CDN_BASE_URL = var.cdn_base_url
    _PERFORMANCE_THRESHOLD = &quot;90&quot;
  }
}

# 글로벌 성능 테스팅 함수
resource &quot;google_cloudfunctions_function&quot; &quot;global_performance_test&quot; {
  name        = &quot;global-performance-test&quot;
  runtime     = &quot;python39&quot;
  entry_point = &quot;run_global_performance_test&quot;
  
  source_archive_bucket = google_storage_bucket.functions_source.name
  source_archive_object = google_storage_bucket_object.perf_test_function.name
  
  https_trigger {
    url = &quot;https://${var.region}-${var.project_id}.cloudfunctions.net/global-performance-test&quot;
  }
  
  timeout = 540  # 9분
  
  environment_variables = {
    TEST_REGIONS = &quot;us-east1,europe-west1,asia-northeast1,australia-southeast1&quot;
    PERFORMANCE_THRESHOLD_MS = &quot;200&quot;
    CONCURRENT_REQUESTS = &quot;50&quot;
  }
}

# 성능 벤치마크 대시보드
resource &quot;google_monitoring_dashboard&quot; &quot;performance_benchmark&quot; {
  dashboard_json = jsonencode({
    displayName = &quot;CDN 성능 벤치마크 대시보드&quot;
    mosaicLayout = {
      tiles = [
        {
          width = 12
          height = 4
          widget = {
            title = &quot;글로벌 지연시간 히트맵&quot;
            xyChart = {
              dataSets = [{
                timeSeriesQuery = {
                  timeSeriesFilter = {
                    filter = &quot;resource.type=\&quot;global_load_balancer\&quot; AND metric.type=\&quot;loadbalancing.googleapis.com/https/total_latencies\&quot;&quot;
                    aggregation = {
                      alignmentPeriod = &quot;300s&quot;
                      perSeriesAligner = &quot;ALIGN_MEAN&quot;
                      crossSeriesReducer = &quot;REDUCE_MEAN&quot;
                      groupByFields = [&quot;resource.label.forwarding_rule_name&quot;, &quot;metric.label.client_country&quot;]
                    }
                  }
                }
                plotType = &quot;HEATMAP&quot;
              }]
              yAxis = {
                label = &quot;응답 시간 (ms)&quot;
                scale = &quot;LINEAR&quot;
              }
            }
          }
        },
        {
          width = 6
          height = 4
          yPos = 4
          widget = {
            title = &quot;캐시 적중률 추세&quot;
            xyChart = {
              dataSets = [{
                timeSeriesQuery = {
                  timeSeriesFilter = {
                    filter = &quot;resource.type=\&quot;https_lb_rule\&quot;&quot;
                    aggregation = {
                      alignmentPeriod = &quot;300s&quot;
                      perSeriesAligner = &quot;ALIGN_RATE&quot;
                      crossSeriesReducer = &quot;REDUCE_SUM&quot;
                      groupByFields = [&quot;metric.label.cache_result&quot;]
                    }
                  }
                }
                plotType = &quot;STACKED_AREA&quot;
              }]
            }
          }
        },
        {
          width = 6
          height = 4
          xPos = 6
          yPos = 4
          widget = {
            title = &quot;대역폭 활용률&quot;
            xyChart = {
              dataSets = [{
                timeSeriesQuery = {
                  timeSeriesFilter = {
                    filter = &quot;resource.type=\&quot;https_lb_rule\&quot;&quot;
                    aggregation = {
                      alignmentPeriod = &quot;60s&quot;
                      perSeriesAligner = &quot;ALIGN_RATE&quot;
                    }
                  }
                }
                plotType = &quot;LINE&quot;
              }]
              yAxis = {
                label = &quot;바이트/초&quot;
                scale = &quot;LINEAR&quot;
              }
            }
          }
        }
      ]
    }
  })
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google Cloud Platform의 CDN 서비스들은 현대적인 콘텐츠 전송 요구사항을 위한 포괄적인 솔루션을 제공하며, 각각이 최적화된 성능과 비용 특성으로 특정 사용 사례를 해결한다. &lt;b&gt;Cloud CDN, Media CDN, Firebase Hosting&lt;/b&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;color: #000000;&quot;&gt;&lt;b&gt;Cloud CDN&lt;/b&gt;은 Google Cloud Load Balancing과의 긴밀한 통합을 통해 동적 웹 애플리케이션 가속화에 뛰어나며, 정교한 캐싱 정책과 오리진 쉴딩 기능을 제공한다. 이 서비스의 강점은 지능적인 캐시 키 정책과 캐싱 동작에 대한 세밀한 제어를 통해 혼합 콘텐츠 타입을 처리하는 데 있다.&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;color: #000000;&quot;&gt;&lt;b&gt;Media CDN&lt;/b&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;color: #000000;&quot;&gt;&lt;b&gt;Firebase Hosting&lt;/b&gt;은 내장 CDN 기능과 완벽한 CI/CD 통합을 결합하여 정적 웹사이트와 단일 페이지 애플리케이션에 뛰어난 개발자 경험을 제공한다. 관대한 무료 티어와 자동 최적화 기능은 현대적인 웹 개발 워크플로우에 이상적이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전략적 구현 프레임워크&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;콘텐츠 기반 아키텍처&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: 기술적 선호도보다는 콘텐츠 특성을 중심으로 CDN 전략을 설계한다. 정적 자산은 Firebase Hosting의 단순함으로, 동적 콘텐츠는 Cloud CDN의 정교함으로, 미디어 콘텐츠는 Media CDN의 전문화된 기능을 활용한다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;하이브리드 접근법&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: 가장 성공적인 구현은 통합된 전송 아키텍처 내에서 특정 콘텐츠 타입에 대한 각 플랫폼의 강점을 활용하여 여러 CDN 서비스를 결합한다. 이 접근법은 다양한 트래픽 패턴에서 비용을 최적화하면서 성능을 극대화한다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;성능 우선 설계&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: 첫날부터 포괄적인 모니터링과 최적화를 구현한다. CDN 효과성은 적절한 캐시 구성, 지능형 라우팅, 실제 사용 패턴을 기반으로 한 지속적인 성능 튜닝에 크게 의존한다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비용 최적화&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: 전략적 캐시 정책, 오리진 쉴딩, 지능형 트래픽 라우팅을 통해 성능 요구사항과 비용 제약의 균형을 맞춘다. 다양한 CDN 기능의 비용 영향을 이해하면 정보에 입각한 아키텍처 결정을 내릴 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안 통합&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: 보안 고려사항을 나중에 추가하는 것이 아니라 CDN 설계에 구축한다. 적절한 SSL 종료, DDoS 보호, 접근 제어를 통해 보안 위협으로부터 보호하면서 안정적인 콘텐츠 전송을 보장한다.&lt;/span&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;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;color: #000000;&quot;&gt;콘텐츠 전송의 미래는 점점 더 엣지 컴퓨팅 기능, 실시간 최적화, 사용자 컨텍스트와 네트워크 조건을 기반으로 한 지능형 라우팅을 강조한다. GCP의 CDN 서비스는 프로덕션 배포에 필요한 단순성과 안정성을 유지하면서 이러한 고급 기능의 기반을 제공한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CDN 구현의 성공은 단일 서비스를 선택하는 것이 아니라 사용자 경험을 향상시키고 비즈니스 목표를 지원하는 효율적이고 안전하며 비용 효율적인 콘텐츠 전송 시스템을 만들기 위해 여러 플랫폼을 조율하는 데 있다.&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/cdn/docs&quot;&gt;Google Cloud CDN 문서&lt;/a&gt;&amp;nbsp;- 포괄적인 플랫폼 문서 및 구성 가이드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/media-cdn/docs&quot;&gt;Media CDN 문서&lt;/a&gt;&amp;nbsp;- 스트리밍 및 대용량 파일 전송 최적화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://firebase.google.com/docs/hosting&quot;&gt;Firebase Hosting 문서&lt;/a&gt;&amp;nbsp;- 정적 사이트 호스팅 및 배포 가이드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/content-delivery-network-best-practices&quot;&gt;CDN 성능 모범 사례&lt;/a&gt;&amp;nbsp;- 최적화 전략 및 구현 패턴&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/load-balancing/docs/https&quot;&gt;Cloud Load Balancing 통합&lt;/a&gt;&amp;nbsp;- 고급 트래픽 관리 및 라우팅&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/monitoring/docs&quot;&gt;CDN용 Cloud Monitoring&lt;/a&gt;&amp;nbsp;- 성능 모니터링 및 분석 구현&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://registry.terraform.io/providers/hashicorp/google/latest/docs&quot;&gt;Terraform Google Provider&lt;/a&gt;&amp;nbsp;- CDN 서비스용 Infrastructure as Code&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://web.dev/performance/&quot;&gt;웹 성능 최적화&lt;/a&gt;&amp;nbsp;- 현대적인 웹 성능 모범 사례&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP&quot;&gt;콘텐츠 보안 정책&lt;/a&gt;&amp;nbsp;- 보안 헤더 및 콘텐츠 보호&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://tools.ietf.org/html/rfc7234&quot;&gt;HTTP 캐싱 표준&lt;/a&gt;&amp;nbsp;- Cache-Control 및 HTTP 캐싱 사양&lt;/span&gt;&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;&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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>GCP</category>
      <category>CDN</category>
      <category>cloudcdn</category>
      <category>GCP</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/463</guid>
      <comments>https://somaz.tistory.com/463#entry463comment</comments>
      <pubDate>Tue, 7 Apr 2026 00:00:20 +0900</pubDate>
    </item>
    <item>
      <title>Kubernetes Probe (Liveness, Readiness, Startup)</title>
      <link>https://somaz.tistory.com/110</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&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 style=&quot;color: #000000;&quot;&gt;Kubernetes에서 애플리케이션의 안정적인 운영을 위해 중요한 개념 중 하나가 바로 &lt;b&gt;Probe&lt;/b&gt;이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클러스터를 구축하거나 배포 설정을 하다 보면 liveness, readiness, startup 같은 Probe 설정을 자주 마주하게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;422&quot; data-start=&quot;244&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Probe는 단순히 컨테이너가 살아 있는지뿐만 아니라, 서비스 요청을 받을 준비가 되었는지, 기동이 완료되었는지 등 다양한 상태를 세밀하게 감지해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;422&quot; data-start=&quot;244&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이러한 Probe를 적절히 구성하면 &lt;b&gt;장애 회복 속도 개선&lt;/b&gt;, &lt;b&gt;잘못된 트래픽 분산 방지&lt;/b&gt;, &lt;b&gt;무한 재시작 루프 방지&lt;/b&gt; 등의 효과를 얻을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;422&quot; data-start=&quot;244&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;495&quot; data-start=&quot;424&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;i&gt;이 글에서는 Kubernetes에서 지원하는 Probe의 개념과 종류, 각각의 용도와 동작 방식을 실무적 관점에서 정리해본다.&lt;/i&gt;&lt;/b&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;&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;1536&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjgSlJ/btsM3VSkXCv/YW3lmjl9XPVqWtF3vWnKU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjgSlJ/btsM3VSkXCv/YW3lmjl9XPVqWtF3vWnKU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjgSlJ/btsM3VSkXCv/YW3lmjl9XPVqWtF3vWnKU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjgSlJ%2FbtsM3VSkXCv%2FYW3lmjl9XPVqWtF3vWnKU1%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;521&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1024&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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 id=&quot;probe란&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Probe란?&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Probe는 컨테이너에서 kubelet에 의해 주기적으로 수행되는 진단이다.&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;color: #000000;&quot;&gt;이 Probe를 통해 쿠버네티스는 각 컨테이너의 상태를 주기적으로 체크한 후, 문제가 있는 컨테이너를 자동으로 재시작하거나 또는 문제가 있는 컨테이너를 서비스에서 제외할 수 있다.&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;color: #000000;&quot;&gt;kubelet은 컨테이너의 상태를 진단하기 위해 핸들러를 호출하는데 핸들러는 수행하는 작업의 분류에 따라서 ExecAction, TCPSocketAction, HttpGetAction로 나뉜다.&lt;/span&gt;&lt;/p&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 id=&quot;handler&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Handler&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너의 상태를 진단하기 위해 어떻게 진단할 것인지 명시한 것이 Handler이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ExecAction&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ExecAction은 컨테이너에서 지정된 명령어를 실행한다. 명령어를 실행했을 때 exit code가 0이면 성공, 이외의 값은 실패로 분류한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;exec:
   command:
   - cat
   - /etc/nginx/nginx.conf&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TCPAction&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TCPAction은 지정된 포트로 TCP 소켓 연결을 시도한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;tcpSocket:
    port: 8080
    initialDelaySeconds: 15
    periodSeconds: 20&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HttpGetAction&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지정된 포트와 url로 HTTP Get 요청을 전송하며, 응답 상태가 200 ~ 400 구간에 속하는 경우 성공, 이외에는 실패로 분류한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;  httpGet:
    path: /healthz
    port: liveness-port&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GRPCAction (Kubernetes 1.24+ GA)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;gRPC 기반 애플리케이션의 경우 gRPC Health Checking Protocol을 통해 Probe를 수행할 수 있다. Kubernetes 1.24부터 GA(정식)로 지원되며, gRPC 서버가 `grpc.health.v1.Health` 서비스를 구현하고 있어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;livenessProbe:
  grpc:
    port: 50051
    service: my-service  # 선택 사항. 생략 시 전체 서버 상태를 체크
  initialDelaySeconds: 10
  periodSeconds: 10&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;gRPC 게임 서버, 마이크로서비스 간 내부 통신 등에서 HTTP 엔드포인트 없이도 헬스 체크를 수행할 수 있어 유용하다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 HTTP 기반의 `/healthz` 엔드포인트를 별도로 만들 필요가 없으므로 gRPC 네이티브 환경에서는 이 방식이 더 자연스럽다.&lt;/span&gt;&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;&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;
&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 id=&quot;probe의-종류&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Probe의 종류&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kubelet은 실행 중인 컨테이너에 대해 세 가지 종류의 프로브를 지정할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Liveness probe&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;Pod은 정상적인 Running 상태이지만, 애플리케이션에 문제가 생겨서 접속이 안되는 경우를 감지한다. (메모리 오버플로우 등) 문제를 감지하면 Pod을 죽이고 재실행하여 애플리케이션의 문제를 해결한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Readiness probe&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너가 요청을 처리할 준비가 되었는지 확인하는 probe이다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Pod가 새로 배포되고 Running 상태여도 처음에 로딩하는 시간이 있기 때문에 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;Readiness probe는 어플리케이션이 구동되기 전까지 서비스와 연결되지 않게 해준다. (Readiness Probe가 실패할 때 엔드포인트 컨트롤러가 파드에 연관된 모든 서비스들의 엔드포인트에서 파드의 IP주소를 제거한다. ) &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;color: #000000;&quot;&gt;Liveness Probe와 비교했을 때 어떤 차이가 있냐면, Liveness Probe는 probe 핸들러 조건 아래 fail이 나면 pod을 재실행 시키지만 Readiness Probe는 pod을 서비스로부터 제외시킨다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Startup probe&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너 내의 애플리케이션이 시작되었는지를 나타낸다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;startup probe가 주어진 경우, 성공할 때 까지 다른 나머지 prob는 활성화 되지 않는다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;만약 startup probe가 실패하면, kubelet이 컨테이너를 죽이고, 컨테이너는 재시작 정책에 따라 처리된다.&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;&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;color: #000000;&quot;&gt;Probe 동작 순서&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너가 시작되면 Probe는 다음 순서로 동작한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;컨테이너 시작
    │
    ▼
┌──────────────┐
│ Startup Probe │ ◄── 설정된 경우, 성공할 때까지 반복
└──────┬───────┘
       │ 성공
       ▼
┌──────────────┐     ┌────────────────┐
│ Liveness     │     │ Readiness      │
│ Probe        │     │ Probe          │
│ (병렬 동작)   │     │ (병렬 동작)     │
└──────┬───────┘     └──────┬─────────┘
       │ 실패                │ 실패
       ▼                    ▼
  컨테이너 재시작        Endpoint에서 제거
                      (트래픽 차단)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;Startup Probe가 설정되어 있으면, 성공할 때까지 Liveness/Readiness Probe는 비활성 상태&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Startup Probe가 실패하면 컨테이너를 재시작 (restartPolicy에 따라)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Startup Probe 성공 이후 Liveness와 Readiness Probe가 &lt;b&gt;동시에&lt;/b&gt; 독립적으로 동작&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;color: #000000;&quot;&gt;Probe 실패 시 동작 비교&lt;/span&gt;&lt;/h3&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Probe&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실패 시 동작&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;영향 범위&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복구 방식&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Startup Probe&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너 재시작 (restartPolicy에 따라)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kubelet이 컨테이너를 kill 후 재시작&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Liveness Probe&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너 재시작&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kubelet이 컨테이너를 kill 후 재시작&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Readiness Probe&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Endpoint에서 Pod IP 제거&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스 트래픽&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Probe 재성공 시 자동으로 Endpoint 복귀&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&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;color: #000000;&quot;&gt;핵심 차이: Liveness 실패는 컨테이너를 죽이고, Readiness 실패는 트래픽만 차단한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Probe 설정 시 유의할 값들&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1849&quot; data-start=&quot;1580&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1662&quot; data-start=&quot;1580&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`initialDelaySeconds`: 컨테이너 시작 후 Probe를 시작할 때까지 대기 시간. 너무 짧으면 false positive 발생.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1724&quot; data-start=&quot;1663&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`timeoutSeconds`: 응답을 기다리는 최대 시간. 느린 I/O 작업이 있다면 충분히 확보 필요.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1784&quot; data-start=&quot;1725&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`failureThreshold`: 실패를 몇 번 반복해야 실패로 간주할 것인지. 민감도 조절에 핵심.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1849&quot; data-start=&quot;1785&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`periodSeconds`: Probe를 실행하는 주기. 지나치게 짧게 잡으면 시스템 부하가 늘어날 수 있음.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프레임워크별 권장 설정값 가이드&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;애플리케이션의 특성에 따라 Probe 값을 다르게 설정해야 한다. 아래는 실무에서 자주 사용하는 프레임워크별 권장 기준이다.&lt;/span&gt;&lt;/p&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프레임워크&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;initialDelaySeconds&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;periodSeconds&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;timeoutSeconds&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;failureThreshold&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Spring Boot&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;30~60&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Node.js (NestJS, Express)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5~10&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5~10&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Go (net/http)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3~5&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Python (Django, FastAPI)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10~20&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&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;color: #000000;&quot;&gt;Spring Boot는 JVM 워밍업과 Bean 초기화 시간 때문에 `initialDelaySeconds` 를 넉넉하게 잡아야 한다. Spring Boot Actuator의 `/actuator/health` 엔드포인트를 활용하면 좋다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Node.js는 기동이 빠르기 때문에 `initialDelaySeconds` 를 짧게 잡아도 된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Go 애플리케이션은 바이너리 기동이 매우 빠르므로 3~5초면 충분하다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기동 시간이 불규칙한 경우에는 `initialDelaySeconds` 를 늘리기보다 &lt;b&gt;Startup Probe를 별도로 설정&lt;/b&gt;하는 것이 더 안전하다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;terminationGracePeriodSeconds와 Probe의 관계&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Liveness Probe 실패 시 kubelet은 컨테이너에 SIGTERM을 보내고, `terminationGracePeriodSeconds`(기본값 30초) 동안 `graceful shutdown` 을 기다린 뒤 `SIGKILL` 로 강제 종료한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;Liveness Probe 실패 (failureThreshold 도달)
    │
    ▼
kubelet &amp;rarr; SIGTERM 전송
    │
    ▼
terminationGracePeriodSeconds 대기 (기본 30초)
    │
    ├── 앱이 종료됨 &amp;rarr; 정상 종료
    │
    └── 타임아웃 &amp;rarr; SIGKILL 강제 종료&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;주의할 점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;게임 서버처럼 진행 중인 세션 데이터를 저장해야 하는 경우, `terminationGracePeriodSeconds` 를 충분히 확보해야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;반대로 이 값이 너무 크면 장애 복구가 느려진다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`preStop` 훅과 함께 사용하면 `SIGTERM` 수신 전에 연결 정리 작업을 수행할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;spec:
  terminationGracePeriodSeconds: 60
  containers:
    - name: game-server
      lifecycle:
        preStop:
          exec:
            command: [&quot;/bin/sh&quot;, &quot;-c&quot;, &quot;sleep 5 &amp;amp;&amp;amp; kill -SIGTERM 1&quot;]&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;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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;각-probe를-언제-사용해야할까&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 probe를 언제 사용해야할까?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Liveness Probe&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사실 컨테이너 속 프로세스가 어떠한 이슈에 직면하거나 unhealty 상태가 되어(ex: out of memory) 프로세스가 중단된다면 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;원래는 kubelet이 파드의 restartPolicy에 따라서 올바른 대처를 자동으로 수행한다.&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;color: #000000;&quot;&gt;이와 같은 경우에는 Liveness Probe를 설정한다고 해서 큰 효과는 없고 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Readiness Probe&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;probe가 성공한 경우에만 파드에 트래픽 전송을 시작하려고 한다면 Readiness probe를 지정하면 된다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;혹은 컨테이너의 지속적인 유지 및 관리를 위해서 자체적으로 중단을 수행하는 경우는&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;pod을 죽이는 Liveness probe말고 Readiness probe를 사용할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Startup Probe&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스를 시작하는 데 오랜 시간이 걸리거나 불규칙적인 컨테이너에 설정하는 데 사용될 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(예를 들면 third party 에서 특정 데이터를 다운받는 등의 경우) startup probe가 성공하고 나서&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;color: #000000;&quot;&gt;liveness, readiness probe가 동작하기 때문에 기동시간이 불규칙적인 애플리케이션이 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;liveness probe에 의해 기동되기도 전에 재시작 되는 것을 방지할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(Readiness probe랑 비슷하지만 방금 말한 부분은 Readiness probe로 해결하기 어렵다.&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3개 Probe를 함께 설정한 전체 YAML 예시&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실무에서 기동 시간이 긴 애플리케이션에 3개 Probe를 모두 설정하는 예시이다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: app-with-probes
spec:
  terminationGracePeriodSeconds: 60
  containers:
    - name: app
      image: my-app:latest
      ports:
        - containerPort: 8080
      
      # 1. Startup Probe: 앱 기동 완료 확인 (최대 5분 대기)
      # 성공할 때까지 Liveness/Readiness Probe가 동작하지 않음
      startupProbe:
        httpGet:
          path: /healthz
          port: 8080
        initialDelaySeconds: 5
        periodSeconds: 10
        failureThreshold: 30    # 10초 &amp;times; 30회 = 최대 300초(5분) 대기
        timeoutSeconds: 3

      # 2. Liveness Probe: 앱 정상 동작 여부 확인
      # 실패 시 컨테이너 재시작
      livenessProbe:
        httpGet:
          path: /healthz
          port: 8080
        periodSeconds: 10
        failureThreshold: 3     # 3회 연속 실패 시 재시작
        timeoutSeconds: 3

      # 3. Readiness Probe: 트래픽 수신 준비 확인
      # 실패 시 서비스에서 제외 (재시작하지 않음)
      readinessProbe:
        httpGet:
          path: /ready
          port: 8080
        periodSeconds: 5
        failureThreshold: 3
        timeoutSeconds: 3&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;포인트&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`/healthz` 와 `/ready` 를 분리하는 것이 좋다. `/healthz` 는 앱 프로세스 생존 여부만 체크하고, /ready는 DB 연결, 캐시 연결 등 외부 의존성까지 포함한 준비 상태를 체크한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Startup Probe의 `failureThreshold` &amp;times; `periodSeconds` 가 앱의 최대 기동 시간보다 커야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Liveness Probe에 외부 의존성(DB, Redis 등) 체크를 넣지 않는 것이 좋다. 외부 서비스 장애 시 불필요한 재시작이 발생할 수 있다.&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실무에서 흔히 발생하는 Probe 관련 오해 및 문제 사례&lt;/span&gt;&lt;/h4&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 data-end=&quot;405&quot; data-start=&quot;303&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Readiness Probe만 설정한 경우, 컨테이너가 죽었는데도 Pod 자체는 Running 상태로 남아 트래픽은 차단되지만 모니터링 시스템에서는 장애로 인지되지 않을 수 있음.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;502&quot; data-start=&quot;406&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Liveness Probe만 설정한 경우, 애플리케이션이 일시적으로 느려지거나 외부 의존 서비스 문제로 실패해도 무조건 재시작되어 오히려 더 큰 장애로 이어질 수 있음.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;592&quot; data-start=&quot;503&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Startup Probe는 생략했지만 실제로 초기 부팅 시간이 긴 경우, liveness probe가 너무 빨리 시작되어 무한 재시작 루프에 빠질 수 있음.&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Helm 차트에서 Probe 설정하는 팁&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;내용:&lt;/b&gt; Helm 차트를 사용하는 경우 `values.yaml` 에서 probe 설정을 추상화하는 패턴을 자주 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1743564698658&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;livenessProbe:
  enabled: true
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 10
  periodSeconds: 5

readinessProbe:
  enabled: true
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 3&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이처럼 `enabled, initialDelaySeconds, periodSeconds` 값을 `values` 로 노출시키고 템플릿에 `{{- if .Values.livenessProbe.enabled }}` 식으로 조건부 렌더링을 걸면, 환경별로 쉽게 제어할 수 있다.&lt;/span&gt;&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;&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;
&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;color: #000000;&quot;&gt;모니터링 및 디버깅 팁&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;928&quot; data-start=&quot;667&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;737&quot; data-start=&quot;667&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`kubectl describe pod &amp;lt;pod-name&amp;gt;` 명령어로 Probe 상태와 최근 실패 이력을 확인할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;787&quot; data-start=&quot;738&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Events 섹션에서 Probe 실패 메시지를 통해 디버깅 힌트를 얻을 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;857&quot; data-start=&quot;788&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`kubectl get events --sort-by='.lastTimestamp'` 로 최근 이벤트 흐름을 파악해보자.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;928&quot; data-start=&quot;858&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Prometheus나 Grafana에서 Probe failure metrics를 수집해 장애 조기 감지에 활용할 수 있다.&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;547&quot; data-start=&quot;502&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리: &amp;ldquo;올바른 Probe 설정은 장애를 줄이고, 신뢰성을 높인다&amp;rdquo;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-end=&quot;677&quot; data-start=&quot;549&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes의 Probe는 단순한 헬스 체크 이상의 역할을 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;677&quot; data-start=&quot;549&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;677&quot; data-start=&quot;549&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;잘못된 설정은 오히려 &lt;b&gt;정상 동작 중인 애플리케이션을 재시작시키거나&lt;/b&gt;, 반대로 &lt;b&gt;장애가 난 서비스에 트래픽을 전달&lt;/b&gt;하게 만들 수도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;894&quot; data-start=&quot;679&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;757&quot; data-start=&quot;679&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Liveness Probe&lt;/b&gt;는 데드락 상태나 무한 루프처럼 정상적으로 종료되지 않는 문제를 감지하여 자동 복구할 수 있게 해준다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;830&quot; data-start=&quot;758&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Readiness Probe&lt;/b&gt;는 애플리케이션이 실제로 요청을 받을 준비가 되었는지를 판단하여 잘못된 라우팅을 막아준다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;894&quot; data-start=&quot;831&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Startup Probe&lt;/b&gt;는 기동 시간이 오래 걸리는 앱에 적절히 활용하여 불필요한 재시작을 방지한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1034&quot; data-start=&quot;896&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1034&quot; data-start=&quot;896&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1034&quot; data-start=&quot;896&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;모든 Probe를 무조건 사용하는 것보다, 애플리케이션 특성과 배포 목적에 따라 선별적이고 전략적으로 구성하는 것이 중요하다.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스 안정성과 자동 복구 능력을 높이기 위해 지금 사용하는 파드에 어떤 Probe가 필요한지 점검해보세요.&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-end=&quot;1057&quot; data-start=&quot;1041&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-end=&quot;1057&quot; data-start=&quot;1041&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1617&quot; data-start=&quot;1059&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1191&quot; data-start=&quot;1059&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; data-end=&quot;1191&quot; data-start=&quot;1061&quot;&gt;Kubernetes 공식 문서 - Probes&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1335&quot; data-start=&quot;1192&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; data-end=&quot;1335&quot; data-start=&quot;1194&quot;&gt;Kubernetes - Liveness vs Readiness vs Startup Probes 정리&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1487&quot; data-start=&quot;1336&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; data-end=&quot;1487&quot; data-start=&quot;1338&quot;&gt;Blog: Understand Kubernetes Probes Deeply&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1617&quot; data-start=&quot;1488&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; data-end=&quot;1617&quot; data-start=&quot;1490&quot;&gt;Kubernetes Docs - Configure Probes for containers&lt;/a&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;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>Container Orchestration/Kubernetes</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/110</guid>
      <comments>https://somaz.tistory.com/110#entry110comment</comments>
      <pubDate>Mon, 6 Apr 2026 16:39:03 +0900</pubDate>
    </item>
    <item>
      <title>GCP AI/ML 플랫폼 완벽 가이드: Vertex AI부터 실시간 추론까지</title>
      <link>https://somaz.tistory.com/462</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라우드 기반 머신러닝이 기업의 핵심 경쟁력으로 자리잡으면서, Google Cloud Platform(GCP)의 AI/ML 서비스들이 주목받고 있다. Vertex AI, AutoML, Custom Training부터 BigQuery ML까지, GCP는 다양한 수준의 ML 요구사항을 충족하는 통합된 플랫폼을 제공한다.&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;color: #000000;&quot;&gt;본 글에서는 각 서비스의 특징과 선택 기준, MLOps 파이프라인 구축 전략, 그리고 실무에서 바로 적용할 수 있는 아키텍처 패턴을 살펴본다. 특히 사전 훈련 모델과 커스텀 모델 개발의 트레이드오프, 모델 배포와 A/B 테스팅 자동화, 실시간 추론 시스템 구축까지 포괄적으로 다룬다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k1i4d/dJMcacu1OYF/a6Lu4vSKzg01PD7KUDqN20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k1i4d/dJMcacu1OYF/a6Lu4vSKzg01PD7KUDqN20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k1i4d/dJMcacu1OYF/a6Lu4vSKzg01PD7KUDqN20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk1i4d%2FdJMcacu1OYF%2Fa6Lu4vSKzg01PD7KUDqN20%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GCP&amp;nbsp;AI/ML&amp;nbsp;플랫폼&amp;nbsp;완벽&amp;nbsp;가이드&lt;/span&gt;&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;&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GCP AI/ML 플랫폼 비교 분석&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 서비스별 특징&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;서비스&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;적용 대상&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;개발 복잡도&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;커스터마이징 수준&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 효율성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;AutoML&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;도메인 전문가, 빠른 프로토타입&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음 (소규모)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Vertex AI&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ML 엔지니어, 통합 MLOps&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음 (중대규모)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Custom Training&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 사이언티스트, 연구 목적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최고&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;변동적&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;BigQuery ML&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 분석가, SQL 친화적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매우 높음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스 선택 의사결정 트리&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2284&quot; data-origin-height=&quot;1604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dzWRAd/btsQzKGN30J/6YbiIcYizPSdcYLzoN3pVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dzWRAd/btsQzKGN30J/6YbiIcYizPSdcYLzoN3pVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dzWRAd/btsQzKGN30J/6YbiIcYizPSdcYLzoN3pVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdzWRAd%2FbtsQzKGN30J%2F6YbiIcYizPSdcYLzoN3pVk%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;2284&quot; height=&quot;1604&quot; data-origin-width=&quot;2284&quot; data-origin-height=&quot;1604&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MLOps 파이프라인 구축 전략&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 데이터 파이프라인 설계&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;효과적인 MLOps는 안정적인 데이터 파이프라인에서 시작된다. GCP에서는 다음과 같은 아키텍처 패턴을 권장한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2912&quot; data-origin-height=&quot;268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NacmZ/btsQA6WCIhy/77A8J6JH2GdJ7vkpYYPql0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NacmZ/btsQA6WCIhy/77A8J6JH2GdJ7vkpYYPql0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NacmZ/btsQA6WCIhy/77A8J6JH2GdJ7vkpYYPql0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNacmZ%2FbtsQA6WCIhy%2F77A8J6JH2GdJ7vkpYYPql0%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;2912&quot; height=&quot;268&quot; data-origin-width=&quot;2912&quot; data-origin-height=&quot;268&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 구성 요소&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Cloud Storage&lt;/b&gt;: 원시 데이터 저장소&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Dataflow&lt;/b&gt;: 실시간/배치 데이터 처리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;BigQuery&lt;/b&gt;: 분석용 데이터 웨어하우스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Vertex AI Feature Store&lt;/b&gt;: 피처 관리 및 서빙&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Vertex AI Model Registry&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. CI/CD 통합 파이프라인&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;832&quot; data-origin-height=&quot;1662&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8hSAC/btsQClsaQ3S/TObWnea9x2jz5VtNHgioD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8hSAC/btsQClsaQ3S/TObWnea9x2jz5VtNHgioD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8hSAC/btsQClsaQ3S/TObWnea9x2jz5VtNHgioD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8hSAC%2FbtsQClsaQ3S%2FTObWnea9x2jz5VtNHgioD1%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;462&quot; height=&quot;923&quot; data-origin-width=&quot;832&quot; data-origin-height=&quot;1662&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;&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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 모니터링 및 자동화 전략&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;단계&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모니터링 지표&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동화 액션&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;데이터 품질&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스키마 드리프트, 누락값 비율&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;알림 발송, 파이프라인 중단&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;모델 성능&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정확도, 지연시간, 처리량&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모델 재훈련 트리거&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;인프라&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CPU/메모리 사용률, 비용&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 스케일링, 리소스 최적화&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비즈니스 지표&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전환율, 매출 영향&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;A/B 테스트 종료, 롤백&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사전 훈련 모델 vs 커스텀 모델 개발&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;의사결정 매트릭스&lt;/span&gt;&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 114px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;요소&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사전 훈련 모델&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;커스텀 모델&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개발 시간&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1-2주&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2-6개월&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;필요 데이터량&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1K-10K 샘플&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10K-1M+ 샘플&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;도메인 특화도&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최고&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;유지보수 비용&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;성능 상한선&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하이브리드 접근법&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 프로덕션 환경에서는 다음과 같은 단계적 접근이 효과적이다.&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Phase 1&lt;/b&gt;: 사전 훈련 모델로 MVP 구축&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Phase 2&lt;/b&gt;: 도메인 데이터로 파인튜닝&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Phase 3&lt;/b&gt;: 필요시 완전 커스텀 모델 개발&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3122&quot; data-origin-height=&quot;612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z2JOB/btsQBsSG3TP/G5foA6BfsvTfYae5tL0Sd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z2JOB/btsQBsSG3TP/G5foA6BfsvTfYae5tL0Sd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z2JOB/btsQBsSG3TP/G5foA6BfsvTfYae5tL0Sd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz2JOB%2FbtsQBsSG3TP%2FG5foA6BfsvTfYae5tL0Sd0%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;3122&quot; height=&quot;612&quot; data-origin-width=&quot;3122&quot; data-origin-height=&quot;612&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;&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모델 배포와 A/B 테스팅 자동화&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 카나리 배포 전략&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Vertex AI Endpoints를 활용한 점진적 배포 패턴이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;860&quot; data-origin-height=&quot;1638&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bENeYi/btsQArUu3oC/znQEVbkiajGCOm7c3SaZB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bENeYi/btsQArUu3oC/znQEVbkiajGCOm7c3SaZB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bENeYi/btsQArUu3oC/znQEVbkiajGCOm7c3SaZB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbENeYi%2FbtsQArUu3oC%2FznQEVbkiajGCOm7c3SaZB1%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;460&quot; height=&quot;876&quot; data-origin-width=&quot;860&quot; data-origin-height=&quot;1638&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;&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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. A/B 테스팅 프레임워크&lt;/span&gt;&lt;/h4&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;style10&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;구성 요소&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GCP 서비스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;역할&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;트래픽 분할&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Load Balancer&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자 그룹별 라우팅&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실험 관리&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Firebase A/B Testing&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실험 설정 및 관리&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;지표 수집&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Monitoring&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 지표 모니터링&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;통계 분석&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BigQuery + Looker&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실험 결과 분석&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 자동화된 의사결정 로직&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 예시: 자동 모델 승격 로직
def evaluate_ab_test_results(control_metrics, treatment_metrics):
    statistical_significance = calculate_significance(control_metrics, treatment_metrics)
    business_impact = calculate_business_impact(control_metrics, treatment_metrics)
    
    if statistical_significance &amp;gt; 0.95 and business_impact &amp;gt; 0.05:
        return &quot;PROMOTE_TO_PRODUCTION&quot;
    elif statistical_significance &amp;gt; 0.95 and business_impact &amp;lt; -0.02:
        return &quot;ROLLBACK_IMMEDIATELY&quot;
    else:
        return &quot;CONTINUE_TESTING&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BigQuery ML과 실시간 추론 아키텍처&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. BigQuery ML의 활용 시나리오&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BigQuery ML은 다음과 같은 상황에서 특히 유용하다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배치 예측이 주요 요구사항인 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터가 이미 BigQuery에 저장되어 있는 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SQL 기반 워크플로우를 선호하는 조직&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 하이브리드 추론 아키텍처&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1590&quot; data-origin-height=&quot;1614&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLJkPE/btsQBYRzfmA/KYcuq9spG58MfjwPccXR5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLJkPE/btsQBYRzfmA/KYcuq9spG58MfjwPccXR5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLJkPE/btsQBYRzfmA/KYcuq9spG58MfjwPccXR5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLJkPE%2FbtsQBYRzfmA%2FKYcuq9spG58MfjwPccXR5K%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;533&quot; height=&quot;541&quot; data-origin-width=&quot;1590&quot; data-origin-height=&quot;1614&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;&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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 성능 최적화 전략&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;추론 유형&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지연시간 목표&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;권장 아키텍처&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 방안&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실시간 (&amp;lt;100ms)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ultra-low&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Vertex AI Endpoints + 캐싱&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예측 캐싱, 모델 최적화&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;준실시간 (&amp;lt;1s)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Low&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Vertex AI Batch + Pub/Sub&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배치 크기 조정&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;배치 (분/시간)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;High&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BigQuery ML&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;슬롯 최적화, 스케줄링&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 실시간 추론 최적화 기법&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;모델 경량화&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;양자화(Quantization): 모델 크기 4배 감소&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프루닝(Pruning): 불필요한 파라미터 제거&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지식 증류(Knowledge Distillation): 작은 모델로 성능 전이&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;인프라 최적화&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPU vs CPU 인스턴스 선택 기준&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오토스케일링 정책 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 및 운영 효율성&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 리소스 관리 전략&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;워크로드 유형&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추천 인스턴스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 절감 방안&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;모델 훈련&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Preemptible GPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;체크포인트, 재시작 로직&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;배치 추론&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CPU 인스턴스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스케줄 기반 시작/종료&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실시간 추론&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;표준 인스턴스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오토스케일링, 캐싱&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 모니터링 대시보드 구성&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3136&quot; data-origin-height=&quot;1292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mtyZA/btsQzMq7Hh2/Wrx9gCgSapFBGcVoonUY01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mtyZA/btsQzMq7Hh2/Wrx9gCgSapFBGcVoonUY01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mtyZA/btsQzMq7Hh2/Wrx9gCgSapFBGcVoonUY01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmtyZA%2FbtsQzMq7Hh2%2FWrx9gCgSapFBGcVoonUY01%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;804&quot; height=&quot;331&quot; data-origin-width=&quot;3136&quot; data-origin-height=&quot;1292&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 구현 시 주의사항&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 보안 및 컴플라이언스&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;데이터 암호화&lt;/b&gt;: 전송 중/저장 시 암호화 필수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;IAM 정책&lt;/b&gt;: 최소 권한 원칙 적용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;감사 로깅&lt;/b&gt;: Cloud Audit Logs 활성화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;데이터 거버넌스&lt;/b&gt;: DLP API를 통한 민감정보 보호&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 성능 튜닝 체크리스트&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;모델 크기와 추론 속도의 균형점 찾기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배치 크기 최적화를 통한 처리량 개선&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;캐싱 전략으로 반복 요청 최적화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 운영 안정성 확보&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;장애 복구 계획(Disaster Recovery) 수립&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모델 성능 저하 시 자동 알림 시스템&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;버전 관리를 통한 빠른 롤백 체계&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GCP의 AI/ML 플랫폼은 조직의 성숙도와 요구사항에 따라 다양한 선택지를 제공한다. AutoML로 시작해서 점진적으로 Vertex AI와 Custom Training으로 발전시키는 단계적 접근이 실무에서 가장 효과적이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 MLOps 파이프라인 구축 시에는 완벽한 시스템을 처음부터 구축하려 하기보다는, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;모델 배포와 A/B 테스팅 자동화는 비즈니스 가치 창출의 핵심이며, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BigQuery ML과 실시간 추론의 하이브리드 아키텍처를 통해 다양한 사용 사례를 효율적으로 지원할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;Google Cloud. (2024). &quot;Vertex AI Documentation&quot;.&amp;nbsp;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/vertex-ai/docs&quot;&gt;https://cloud.google.com/vertex-ai/docs&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google Cloud. (2024). &quot;MLOps: Continuous delivery and automation pipelines in machine learning&quot;.&amp;nbsp;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/mlops-continuous-delivery-and-automation-pipelines-in-machine-learning&quot;&gt;https://cloud.google.com/architecture/mlops-continuous-delivery-and-automation-pipelines-in-machine-learning&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google Cloud. (2024). &quot;BigQuery ML Documentation&quot;.&amp;nbsp;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/bigquery-ml/docs&quot;&gt;https://cloud.google.com/bigquery-ml/docs&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Sculley, D., et al. (2015). &quot;Hidden Technical Debt in Machine Learning Systems&quot;. NIPS 2015.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google Cloud. (2024). &quot;Best practices for implementing machine learning on Google Cloud&quot;.&amp;nbsp;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/ml-on-gcp-best-practices&quot;&gt;https://cloud.google.com/architecture/ml-on-gcp-best-practices&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Paleyes, A., et al. (2022). &quot;Challenges in deploying machine learning: a survey of case studies&quot;. ACM Computing Surveys.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google Cloud. (2024). &quot;Cost optimization for machine learning workloads&quot;.&amp;nbsp;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/cost-optimization-for-ml-workloads&quot;&gt;https://cloud.google.com/architecture/cost-optimization-for-ml-workloads&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>GCP</category>
      <category>Ai</category>
      <category>Al</category>
      <category>GCP</category>
      <category>ML</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/462</guid>
      <comments>https://somaz.tistory.com/462#entry462comment</comments>
      <pubDate>Tue, 31 Mar 2026 00:00:51 +0900</pubDate>
    </item>
    <item>
      <title>GitLab Source Backup &amp;amp; Restore with rclone + Google Drive</title>
      <link>https://somaz.tistory.com/500</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GitLab 소스를 Google Drive 공유 드라이브에 자동 백업하고, 필요 시 리스토어하는 방법을 정리한다.&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;color: #000000;&quot;&gt;`git clone --mirror` 를 사용하여 모든 브랜치, 태그, 커밋 히스토리를 포함한 완전한 백업을 생성하고, `rclone` 을 통해 Google Drive에 업로드한다. 리스토어 시에는 `git push --mirror` 로 원본과 동일한 상태를 복원할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;[Backup Flow]
GitLab CI Pipeline (push / manual trigger)
  &amp;rarr; git clone --mirror (all branches + tags + history)
  &amp;rarr; tar compress
  &amp;rarr; rclone copy &amp;rarr; Google Drive (Shared Drive)

[Restore Flow]
Google Drive (Shared Drive)
  &amp;rarr; rclone copy &amp;rarr; local
  &amp;rarr; tar extract
  &amp;rarr; git push --mirror &amp;rarr; GitLab repo&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2496&quot; data-origin-height=&quot;1372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ux84t/dJMb99Z4Kop/oHHJXlU5Y7O4N5EUuDgyGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ux84t/dJMb99Z4Kop/oHHJXlU5Y7O4N5EUuDgyGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ux84t/dJMb99Z4Kop/oHHJXlU5Y7O4N5EUuDgyGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fux84t%2FdJMb99Z4Kop%2FoHHJXlU5Y7O4N5EUuDgyGK%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;2496&quot; height=&quot;1372&quot; data-origin-width=&quot;2496&quot; data-origin-height=&quot;1372&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;Prerequisites&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. rclone config&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;rclone config
# n (New remote)
# Name: Gitlab Backup
# Storage: drive (Google Drive)
# scope: drive (Full access)
# Configure this as a Shared Drive? &amp;rarr; y &amp;rarr; Select shared drive&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설정 완료 후 확인&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;rclone config show
rclone lsd &quot;Gitlab Backup:&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;rclone config 파일 1개에 remote를 여러 개 등록할 수 있다. remote 1개에 공유 드라이브(team drive) 1개가 연결되며, 같은 Google 계정이면 token을 공유할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# rclone.conf example

[Design Docs]
type = drive
team_drive = aaaa1111bbbb
scope = drive
token = {&quot;access_token&quot;:&quot;...&quot;,&quot;refresh_token&quot;:&quot;...&quot;}

[Gitlab Backup]
type = drive
team_drive = cccc2222dddd
scope = drive
token = {&quot;access_token&quot;:&quot;...&quot;,&quot;refresh_token&quot;:&quot;...&quot;}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;token의 `expires_in: 3599` (약 1시간)은 access_token 유효시간이다. rclone이 refresh_token으로 자동 갱신하므로 신경 쓸 필요 없다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Push rclone image to Harbor&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Copy multi-arch image to local
skopeo copy --all docker://rclone/rclone:latest dir:///tmp/rclone-latest

# Push to Harbor
skopeo copy --all --dest-tls-verify=false \
  dir:///tmp/rclone-latest docker://harbor.example.com/library/rclone/rclone:latest&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. GitLab CI/CD Variables&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style10&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Variable&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Type&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Description&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GITLAB_BACKUP_RCLONE_CONFIG&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;File&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;rclone config file&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;1616&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dmOkEh/dJMcaadA5EC/sWwLQsx4qlBKLyGEfpWxU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dmOkEh/dJMcaadA5EC/sWwLQsx4qlBKLyGEfpWxU0/img.png&quot; data-alt=&quot;rclone config show 값을 그대로 넣어주면 된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dmOkEh/dJMcaadA5EC/sWwLQsx4qlBKLyGEfpWxU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdmOkEh%2FdJMcaadA5EC%2FsWwLQsx4qlBKLyGEfpWxU0%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;385&quot; height=&quot;780&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;1616&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;rclone config show 값을 그대로 넣어주면 된다.&lt;/figcaption&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;rclone config file content&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;[Gitlab Backup]
type = drive
scope = drive
team_drive = &amp;lt;SHARED_DRIVE_ID&amp;gt;
token = {&quot;access_token&quot;:&quot;...&quot;,&quot;refresh_token&quot;:&quot;...&quot;,&quot;expiry&quot;:&quot;...&quot;}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;나머지 변수(`CI_JOB_TOKEN, CI_SERVER_HOST, CI_PROJECT_PATH, CI_PROJECT_NAME, CI_COMMIT_SHORT_SHA, CI_PIPELINE_SOURCE`)는 GitLab predefined 변수로 자동 제공된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.gitlab.com/ci/variables/predefined_variables/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.gitlab.com/ci/variables/predefined_variables/&lt;/a&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Backup (.gitlab-ci.yml)&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;stages:
  - source-backup

variables:
  CONFIG: $GITLAB_BACKUP_RCLONE_CONFIG

source-backup:
  stage: source-backup
  image: rclone/rclone:latest
  interruptible: true
  retry:
    max: 1
    when:
      - runner_system_failure
      - unknown_failure
      - data_integrity_failure
    exit_codes:
      - 137
  variables:
    GIT_STRATEGY: none
  before_script:
    - apk add --no-cache git
  script:
    - git clone --mirror http://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git repo.git
    - tar czf /tmp/${CI_PROJECT_NAME}_${CI_COMMIT_SHORT_SHA}_$(date +%Y%m%d_%H%M%S).tar.gz repo.git
    - rclone copy /tmp/*.tar.gz &quot;Gitlab Backup:${CI_PROJECT_NAME}/&quot; --progress --config $CONFIG
    # Clean up old backups (keep latest 10)
    - rclone lsf &quot;Gitlab Backup:${CI_PROJECT_NAME}/&quot; --config $CONFIG | sort | head -n -10 | while read f; do
        rclone deletefile &quot;Gitlab Backup:${CI_PROJECT_NAME}/$f&quot; --config $CONFIG;
      done
  tags:
    - build-image
  rules:
    - if: '$CI_PIPELINE_SOURCE == &quot;web&quot;'
    - if: '$CI_PIPELINE_SOURCE == &quot;push&quot;'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Key Points&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;`GIT_STRATEGY: none` &amp;mdash; CI 기본 clone(shallow)을 비활성화한다. CI 기본 clone은 `--depth 1` 로 현재 브랜치의 최신 커밋만 가져오기 때문에 전체 백업에 적합하지 않다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`git clone --mirror` &amp;mdash; 모든 브랜치 + 태그 + 전체 커밋 히스토리를 클론한다. push 안 된 로컬 브랜치는 포함되지 않는다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최근 10개 백업만 유지하고 나머지는 자동 삭제한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;백업할 리포마다 동일한 `.gitlab-ci.yml` 을 넣으면 `${CI_PROJECT_NAME}` 등 변수가 자동으로 해당 리포에 맞게 적용된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`rclone/rclone:latest` 이미지는 Alpine 기반으로 git이 포함되어 있지 않아 `before_script` 에서 `apk add --no-cache git` 으로 설치한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Backup file structure on Google Drive&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;Gitlab Backup (Shared Drive)
├── my-project/
│   ├── my-project_abc1234_20260320_120000.tar.gz
│   ├── my-project_def5678_20260321_150000.tar.gz
│   └── my-project_efc199d_20260323_072951.tar.gz
├── another-project/
│   └── another-project_ghi9012_20260323_080000.tar.gz
└── ...&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;Restore (gitlab-restore.sh)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리스토어 스크립트는 Google Drive에서 백업을 다운로드하고 압축 해제 후 로컬 또는 GitLab 리포로 복원한다. 원본 리포와의 비교 기능도 포함되어 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Script&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code_1774257327754&quot; data-ke-type=&quot;html&quot; data-source=&quot;&amp;lt;script src=&amp;quot;https://gist.github.com/somaz94/93b77f77289cf7182a81b6e8be8b9127.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&quot;&gt;
&lt;script src=&quot;https://gist.github.com/somaz94/93b77f77289cf7182a81b6e8be8b9127.js&quot;&gt;&lt;/script&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Usage&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Restore latest backup to local&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;stata&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;./gitlab-restore.sh my-project&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Restore latest backup to GitLab repo&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;./gitlab-restore.sh my-project git@gitlab.example.com:group/restore-repo.git&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GitLab에 빈 리포를 먼저 생성해야 한다. Protected Branch가 설정되어 있으면 Settings &amp;rarr; Repository &amp;rarr; Protected Branches에서 force push를 허용해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Select specific backup&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;stata&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;./gitlab-restore.sh -s my-project&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;[1/6] Listing backups
---
  1) my-project_abc1234_20260320_120000.tar.gz
  2) my-project_def5678_20260321_150000.tar.gz
  3) my-project_efc199d_20260323_072951.tar.gz
---
Select backup number to restore (1-3):&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Restore and compare with original repo&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;cmake&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;./gitlab-restore.sh -d ~/gitlab-project/my-project my-project&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;[6/6] Comparing with: ~/gitlab-project/my-project
---
  Commits:  IDENTICAL
  Branches: IDENTICAL
  Tags:     IDENTICAL
---&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Combined options&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Select + compare
./gitlab-restore.sh -s -d ~/gitlab-project/my-project my-project

# Select + restore to GitLab + compare
./gitlab-restore.sh -s -d ~/gitlab-project/my-project my-project git@gitlab.example.com:group/restore-repo.git

# Custom remote + config + work directory
./gitlab-restore.sh -r &quot;Gitlab Backup&quot; -c ~/.config/rclone/rclone.conf -w /tmp/restore my-project&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Options&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Option&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Description&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Default&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-s, --select&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Select backup from list&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Latest backup&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-d, --diff &amp;lt;path&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Compare with local repo after restore&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Disabled&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-r, --remote &amp;lt;name&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;rclone remote name&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gitlab Backup&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-w, --work-dir &amp;lt;path&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Working directory&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/tmp/gitlab-restore&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-c, --config &amp;lt;path&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;rclone config file path&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;rclone default&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-h, --help&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Show help&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;span style=&quot;color: #000000;&quot;&gt;환경변수로도 설정 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;basic&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;REMOTE=&quot;Gitlab Backup&quot; WORK_DIR=/tmp/restore ./gitlab-restore.sh my-project&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Execution Flow&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;[1/6] Listing backups        &amp;larr; Fetch backup list from Google Drive
[2/6] Downloading backup     &amp;larr; Download selected backup file
[3/6] Extracting archive     &amp;larr; Extract tar.gz + display branches/tags
[4/6] Restoring              &amp;larr; Local clone or git push --mirror to GitLab
[5/6] Restore complete
[6/6] Comparing              &amp;larr; (Optional) Compare with original repo&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Notes&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`refs/pipelines/*` 관련 에러는 GitLab 내부 파이프라인 메타데이터로 push가 거부되는 것이 정상이며 소스 복원에 영향 없다. 스크립트에서 자동으로 감지하고 무시한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`--mirror` 는 서버에 push 된 내용만 백업한다. push 안 된 로컬 브랜치는 포함되지 않으므로 비교 시 차이가 날 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;bare repo(`repo.git`)는 소스 파일이 직접 보이지 않는다. 로컬에서 작업하려면 `git clone repo.git` 으로 워킹 디렉토리를 생성해야 한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 구성으로 GitLab 소스의 자동 백업과 리스토어가 가능해진다. 백업은 CI 파이프라인에서 push마다 자동으로 실행되고, 리스토어는 스크립트 하나로 Google Drive에서 다운로드 &amp;rarr; 복원 &amp;rarr; 검증까지 처리할 수 있다.&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;color: #000000;&quot;&gt;백업할 리포가 여러 개라면 각 리포에 동일한 `.gitlab-ci.yml` 을 넣으면 된다. `${CI_PROJECT_NAME}` 등 predefined 변수가 자동으로 리포별 경로를 생성하기 때문에 별도 수정 없이 동작한다.&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;color: #000000;&quot;&gt;rclone의 Google Drive 연동은 한번 설정하면 token이 자동 갱신되므로 유지보수가 거의 필요 없다. 공유 드라이브를 사용하면 팀 단위로 백업을 관리할 수 있고, 필요 시 `rclone remote` 를 추가하여 다른 공유 드라이브로 확장할 수 있다.&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://rclone.org/drive/&quot;&gt;rclone Google Drive Configuration&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://rclone.org/drive/#shared-drives&quot;&gt;rclone Shared Drive (Team Drive)&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---mirror&quot;&gt;git clone --mirror Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://git-scm.com/docs/git-push#Documentation/git-push.txt---mirror&quot;&gt;git push --mirror Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.gitlab.com/ee/ci/variables/predefined_variables.html&quot;&gt;GitLab CI/CD Predefined Variables&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.gitlab.com/ee/user/project/protected_branches.html&quot;&gt;GitLab Protected Branches&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/containers/skopeo&quot;&gt;skopeo - Container Image Tool&lt;/a&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;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;
&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;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>IaC/CI CD Tool</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/500</guid>
      <comments>https://somaz.tistory.com/500#entry500comment</comments>
      <pubDate>Thu, 26 Mar 2026 00:00:23 +0900</pubDate>
    </item>
    <item>
      <title>GKE Autopilot vs Standard vs Cloud Run 컨테이너 전략 가이드</title>
      <link>https://somaz.tistory.com/461</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google Cloud에서 컨테이너 기반 애플리케이션을 운영할 때 선택할 수 있는 주요 플랫폼은 GKE Standard, GKE Autopilot, 그리고 Cloud Run이다. 각각은 서로 다른 운영 복잡도와 비용 구조를 가지고 있으며, 워크로드의 특성에 따라 최적의 선택이 달라진다.&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;color: #000000;&quot;&gt;GKE Standard는 전통적인 Kubernetes 클러스터로 최대한의 제어권을 제공하지만 운영 부담이 크다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Autopilot은 Google이 노드 관리를 대신해주는 서버리스 Kubernetes 솔루션이며, Cloud Run은 완전 관리형 서버리스 컨테이너 플랫폼이다. 이 글에서는 각 플랫폼의 특징과 적합한 사용 사례를 분석하여 최적의 컨테이너 전략 수립을 도와주겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpxPDy/dJMcagjTjbc/aKXywPqVgaaIo2tRoqK3Bk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpxPDy/dJMcagjTjbc/aKXywPqVgaaIo2tRoqK3Bk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpxPDy/dJMcagjTjbc/aKXywPqVgaaIo2tRoqK3Bk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpxPDy%2FdJMcagjTjbc%2FaKXywPqVgaaIo2tRoqK3Bk%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플랫폼 비교 개요&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1856&quot; data-origin-height=&quot;1628&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UoaYB/btsQBmkL0ed/pohfwmOFQtlQrQ9rKp1pq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UoaYB/btsQBmkL0ed/pohfwmOFQtlQrQ9rKp1pq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UoaYB/btsQBmkL0ed/pohfwmOFQtlQrQ9rKp1pq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUoaYB%2FbtsQBmkL0ed%2FpohfwmOFQtlQrQ9rKp1pq1%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;1856&quot; height=&quot;1628&quot; data-origin-width=&quot;1856&quot; data-origin-height=&quot;1628&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;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;플랫폼&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관리 수준&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영 복잡도&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 모델&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최적 사용 사례&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Cloud Run&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완전 관리형&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용량 기반&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;웹 API, 스테이트리스 앱&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GKE Autopilot&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 관리형&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파드 리소스 기반&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마이크로서비스, 일반 앱&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GKE Standard&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자 관리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 기반&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;엔터프라이즈, GPU 워크로드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Standard: 최대 제어권과 유연성&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특징 및 장점&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Standard는 완전한 Kubernetes 환경을 제공하는 관리형 서비스다. 사용자가 직접 노드 풀을 구성하고 클러스터의 모든 측면을 제어할 수 있다. 노드 타입, 스케일링 정책, 네트워킹 구성 등을 세밀하게 조정할 수 있어 복잡한 엔터프라이즈 워크로드에 적합하다.&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;color: #000000;&quot;&gt;특히 GPU 워크로드, 특수한 하드웨어 요구사항, 복잡한 네트워킹 구성이 필요한 경우 GKE Standard가 유일한 선택일 수 있다. 또한 기존 Kubernetes 생태계의 모든 도구와 완벽히 호환되며, 멀티클라우드 전략을 고려한다면 표준 Kubernetes API를 그대로 사용할 수 있다는 장점이 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영 복잡도와 비용&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Standard는 가장 높은 운영 복잡도를 요구한다. 클러스터 업그레이드, 노드 패치, 보안 설정, 모니터링 구성 등을 직접 관리해야 한다. 또한 노드가 항상 실행되고 있어야 하므로 리소스 사용률이 낮더라도 지속적인 비용이 발생한다.&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;color: #000000;&quot;&gt;비용 구조는 사용하는 노드의 컴퓨팅 리소스에 기반한다. 클러스터 관리 수수료는 무료이지만, &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;효율적인 리소스 활용을 위해서는 적절한 노드 스케일링과 파드 스케줄링 전략이 필요하다.&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Standard 테라폼 예시&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;nix&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# GKE Standard 클러스터 생성
resource &quot;google_container_cluster&quot; &quot;standard&quot; {
  name     = &quot;standard-cluster&quot;
  location = &quot;asia-northeast3-a&quot;
  
  # 초기 노드 풀 제거 후 별도 관리
  remove_default_node_pool = true
  initial_node_count       = 1
  
  # 네트워크 구성
  network    = &quot;default&quot;
  subnetwork = &quot;default&quot;
  
  # 마스터 인증된 네트워크
  master_authorized_networks_config {
    cidr_blocks {
      cidr_block   = &quot;10.0.0.0/8&quot;
      display_name = &quot;private-network&quot;
    }
  }
  
  # 워크로드 아이덴티티 활성화
  workload_identity_config {
    workload_pool = &quot;${var.project_id}.svc.id.goog&quot;
  }
  
  # 로깅 및 모니터링
  logging_service    = &quot;logging.googleapis.com/kubernetes&quot;
  monitoring_service = &quot;monitoring.googleapis.com/kubernetes&quot;
}

# 노드 풀 생성
resource &quot;google_container_node_pool&quot; &quot;standard_pool&quot; {
  name       = &quot;standard-node-pool&quot;
  location   = &quot;asia-northeast3-a&quot;
  cluster    = google_container_cluster.standard.name
  node_count = 2
  
  node_config {
    preemptible  = true
    machine_type = &quot;e2-medium&quot;
    
    # 서비스 계정
    service_account = google_service_account.gke_sa.email
    oauth_scopes = [
      &quot;https://www.googleapis.com/auth/cloud-platform&quot;
    ]
    
    # 메타데이터
    metadata = {
      disable-legacy-endpoints = &quot;true&quot;
    }
  }
  
  # 자동 스케일링
  autoscaling {
    min_node_count = 1
    max_node_count = 10
  }
  
  # 노드 관리 정책
  management {
    auto_repair  = true
    auto_upgrade = true
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Autopilot: 서버리스 Kubernetes의 균형점&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서버리스 Kubernetes 개념&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Autopilot은 Google이 노드 관리를 완전히 대신해주는 서버리스 Kubernetes 플랫폼이다. 사용자는 파드 리소스 요청량에 대해서만 비용을 지불하며, 노드 프로비저닝, 스케일링, 업그레이드 등은 Google이 자동으로 처리한다.&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;color: #000000;&quot;&gt;이는 Kubernetes의 유연성과 서버리스의 편의성을 결합한 접근법이다. 표준 Kubernetes API를 그대로 사용할 수 있지만, 인프라 관리 부담은 크게 줄어든다. 보안 모범 사례가 기본적으로 적용되어 있어 보안 설정에 대한 고민도 덜 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제약사항과 적용 사례&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Autopilot은 보안과 안정성을 위해 일부 제약사항을 두고 있다. 권한있는 컨테이너 실행이 제한되고, 특정 볼륨 타입 사용에 제약이 있으며, 노드에 직접 접근할 수 없다. 또한 DaemonSet 사용에 제한이 있어 모든 워크로드에 적합하지는 않다.&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;color: #000000;&quot;&gt;하지만 일반적인 웹 애플리케이션, 마이크로서비스, 배치 작업, CI/CD 파이프라인 등에는 매우 적합하다. 특히 개발팀이 Kubernetes에 익숙하지만 인프라 운영 부담을 줄이고 싶은 경우에 이상적인 선택이다. 트래픽 패턴이 불규칙하거나 개발 환경처럼 간헐적으로 사용되는 워크로드에서 비용 효율성이 높다.&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;&amp;nbsp;&lt;/p&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;기능&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Standard&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Autopilot&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제약사항&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;권한있는 컨테이너&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지원&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 정책 적용&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;DaemonSet&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완전 지원&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google 관리 제외&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;노드 접근&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SSH 가능&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;불가능&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완전 관리형&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;볼륨 타입&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 타입&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;승인된 타입만&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GPU 지원&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완전 지원&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지원&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특정 타입만&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Autopilot 테라폼 예시&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# GKE Autopilot 클러스터 생성
resource &quot;google_container_cluster&quot; &quot;autopilot&quot; {
  name     = &quot;autopilot-cluster&quot;
  location = &quot;asia-northeast3&quot;
  
  # Autopilot 모드 활성화
  enable_autopilot = true
  
  # 네트워크 구성
  network    = google_compute_network.vpc.self_link
  subnetwork = google_compute_subnetwork.subnet.self_link
  
  # IP 할당 정책
  ip_allocation_policy {
    cluster_secondary_range_name  = &quot;pods&quot;
    services_secondary_range_name = &quot;services&quot;
  }
  
  # 워크로드 아이덴티티
  workload_identity_config {
    workload_pool = &quot;${var.project_id}.svc.id.goog&quot;
  }
  
  # 프라이빗 클러스터 구성
  private_cluster_config {
    enable_private_nodes    = true
    enable_private_endpoint = false
    master_ipv4_cidr_block  = &quot;172.16.0.0/28&quot;
  }
  
  # 릴리스 채널
  release_channel {
    channel = &quot;STABLE&quot;
  }
}

# VPC 네트워크
resource &quot;google_compute_network&quot; &quot;vpc&quot; {
  name                    = &quot;autopilot-vpc&quot;
  auto_create_subnetworks = false
}

# 서브넷
resource &quot;google_compute_subnetwork&quot; &quot;subnet&quot; {
  name          = &quot;autopilot-subnet&quot;
  ip_cidr_range = &quot;10.0.0.0/16&quot;
  region        = &quot;asia-northeast3&quot;
  network       = google_compute_network.vpc.id
  
  secondary_ip_range {
    range_name    = &quot;pods&quot;
    ip_cidr_range = &quot;192.168.0.0/18&quot;
  }
  
  secondary_ip_range {
    range_name    = &quot;services&quot;
    ip_cidr_range = &quot;192.168.64.0/18&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Run: 완전 관리형 서버리스 컨테이너&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서버리스 컨테이너 플랫폼의 장점&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Run은 완전 관리형 서버리스 컨테이너 플랫폼으로, 코드를 컨테이너로 패키징하여 배포하면 나머지는 모두 Google이 관리한다. 요청이 없을 때는 인스턴스가 0으로 스케일다운되어 비용이 발생하지 않으며, 트래픽 증가 시 자동으로 스케일업된다.&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;color: #000000;&quot;&gt;HTTP/gRPC 기반의 스테이트리스 애플리케이션에 최적화되어 있으며, 콜드 스타트 시간이 매우 빠르다. 개발자는 애플리케이션 로직에만 집중할 수 있고, 인프라 관리는 전혀 필요하지 않다. CI/CD 파이프라인과의 통합도 간단하여 빠른 배포와 롤백이 가능하다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제약사항과 사용 사례&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Run은 요청-응답 패턴의 워크로드에 특화되어 있어 장시간 실행되는 배경 작업이나 복잡한 상태 관리가 필요한 애플리케이션에는 적합하지 않다. 또한 15분의 최대 실행 시간 제한이 있어 장시간 처리가 필요한 작업에는 부적절하다.&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;color: #000000;&quot;&gt;REST API, 웹 애플리케이션, 마이크로서비스, 이벤트 기반 처리 등에 이상적이다. 특히 트래픽이 불규칙하거나 스파이크가 있는 워크로드에서 비용 효율성이 뛰어나다. 스타트업이나 사이드 프로젝트처럼 초기 단계에서 운영 복잡도를 최소화하고 싶을 때도 좋은 선택이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Run 제약사항 및 한계&lt;/span&gt;&lt;/p&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;제약사항&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;값&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;최대 실행 시간&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;15분&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장시간 배치 작업 불가&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;최대 메모리&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;32GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메모리 집약적 워크로드 제한&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;최대 CPU&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;8 vCPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고성능 컴퓨팅 제한&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;동시 요청&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1000개/인스턴스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높은 동시성 제한&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;파일 시스템&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;읽기 전용&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;임시 파일만 /tmp에 저장&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Run 테라폼 예시&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# Cloud Run 서비스 배포
resource &quot;google_cloud_run_v2_service&quot; &quot;api_service&quot; {
  name     = &quot;api-service&quot;
  location = &quot;asia-northeast3&quot;
  
  template {
    # 스케일링 설정
    scaling {
      min_instance_count = 0
      max_instance_count = 100
    }
    
    containers {
      image = &quot;gcr.io/${var.project_id}/api-service:latest&quot;
      
      # 리소스 제한
      resources {
        limits = {
          cpu    = &quot;2&quot;
          memory = &quot;4Gi&quot;
        }
      }
      
      # 환경 변수
      env {
        name  = &quot;DATABASE_URL&quot;
        value = var.database_url
      }
      
      env {
        name = &quot;SECRET_KEY&quot;
        value_source {
          secret_key_ref {
            secret  = google_secret_manager_secret.api_secret.secret_id
            version = &quot;latest&quot;
          }
        }
      }
      
      # 포트 설정
      ports {
        container_port = 8080
      }
      
      # 헬스체크
      startup_probe {
        http_get {
          path = &quot;/health&quot;
        }
        initial_delay_seconds = 10
        timeout_seconds       = 5
        period_seconds        = 3
        failure_threshold     = 3
      }
    }
    
    # 서비스 계정
    service_account = google_service_account.cloud_run_sa.email
    
    # VPC 액세스
    vpc_access {
      connector = google_vpc_access_connector.connector.id
      egress    = &quot;ALL_TRAFFIC&quot;
    }
  }
  
  # 트래픽 설정
  traffic {
    percent = 100
    type    = &quot;TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST&quot;
  }
}

# IAM 설정
resource &quot;google_cloud_run_service_iam_member&quot; &quot;public_access&quot; {
  service  = google_cloud_run_v2_service.api_service.name
  location = google_cloud_run_v2_service.api_service.location
  role     = &quot;roles/run.invoker&quot;
  member   = &quot;allUsers&quot;
}

# VPC 커넥터
resource &quot;google_vpc_access_connector&quot; &quot;connector&quot; {
  name          = &quot;api-connector&quot;
  region        = &quot;asia-northeast3&quot;
  ip_cidr_range = &quot;10.8.0.0/28&quot;
  network       = &quot;default&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;워크로드별 최적 플랫폼 선택 가이드&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;워크로드의 특성에 따른 최적 플랫폼 선택을 위한 의사결정 플로우는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1662&quot; data-origin-height=&quot;1652&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Hbnwb/btsQCRxorHp/hAhNekUGk1hnKhSkpVUW40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Hbnwb/btsQCRxorHp/hAhNekUGk1hnKhSkpVUW40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hbnwb/btsQCRxorHp/hAhNekUGk1hnKhSkpVUW40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHbnwb%2FbtsQCRxorHp%2FhAhNekUGk1hnKhSkpVUW40%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;1662&quot; height=&quot;1652&quot; data-origin-width=&quot;1662&quot; data-origin-height=&quot;1652&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플랫폼별 적합 워크로드&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;워크로드 유형&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Run&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;GKE Autopilot&amp;nbsp;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Standard&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추천 이유&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;REST API&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;간편한 배포와 자동 스케일링&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;웹 애플리케이션&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트래픽 기반 스케일링 최적&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;마이크로서비스&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스 간 통신과 네트워킹&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;배치 처리&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장시간 실행과 리소스 제어&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실시간 처리&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;❌&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;WebSocket, 스트리밍 지원&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GPU 워크로드&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;❌&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특수 하드웨어 요구사항&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;레거시 앱&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;❌&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 구성 유지 필요&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개발/테스트&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮은 비용과 빠른 배포&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;웹 애플리케이션 및 API 서비스&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단순한 웹 애플리케이션이나 RESTful API의 경우 Cloud Run이 가장 적합하다. 개발과 배포가 간단하고 비용 효율적이며, 자동 스케일링으로 트래픽 변화에 유연하게 대응할 수 있다. 다만 복잡한 상태 관리나 백그라운드 작업이 필요하다면 GKE Autopilot을 고려해야 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마이크로서비스 아키텍처&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마이크로서비스 아키텍처에서는 서비스 간 복잡한 통신과 상태 관리가 필요할 수 있어 GKE Autopilot이 적합하다. Kubernetes의 풍부한 네트워킹 기능과 서비스 디스커버리를 활용하면서도 인프라 관리 부담을 줄일 수 있다. 각 서비스의 특성에 따라 일부는 Cloud Run으로, 일부는 GKE로 하이브리드 구성도 가능하다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배치 처리 및 데이터 파이프라인&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대용량 데이터 처리나 ETL 작업의 경우 GKE Autopilot이나 Standard가 적합하다. 장시간 실행되는 작업이 많고, GPU 리소스가 필요한 경우도 있기 때문이다. Cloud Run Jobs를 사용하면 단발성 배치 작업도 처리할 수 있지만, 복잡한 워크플로우에는 제한이 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;레거시 애플리케이션 마이그레이션&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 온프레미스나 VM 기반 애플리케이션을 컨테이너로 마이그레이션할 때는 GKE Standard가 적합할 수 있다. 기존 애플리케이션의 특수한 요구사항을 수용할 수 있는 유연성이 필요하기 때문이다. 점진적으로 애플리케이션을 현대화하면서 Autopilot이나 Cloud Run으로 이전할 수 있다.&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;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Knative와 Cloud Run의 서버리스 패턴&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Knative 서버리스 프레임워크&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Knative는 Kubernetes 위에서 동작하는 오픈소스 서버리스 프레임워크다. GKE에서 Knative를 사용하면 Kubernetes 환경에서도 서버리스 패턴을 구현할 수 있다.&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;color: #000000;&quot;&gt;이는 복잡한 워크로드를 서버리스로 실행하고 싶지만 Cloud Run의 제약사항에 부딪힐 때 유용한 대안이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Knative Serving은 자동 스케일링과 트래픽 기반 라우팅을 제공하고, Knative Eventing은 이벤트 기반 아키텍처를 구현할 수 있게 해준다. 하지만 설정과 관리가 복잡하여 상당한 Kubernetes 전문성이 필요하다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Run과의 비교 및 선택 기준&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Run은 Knative를 기반으로 구축된 완전 관리형 서비스다. 따라서 Knative의 핵심 기능을 더 간단하게 사용할 수 있지만, 커스터마이징 옵션은 제한적이다. 표준 HTTP/gRPC 워크로드라면 Cloud Run이 훨씬 편리하고, 복잡한 이벤트 처리나 커스텀 스케일링 로직이 필요하다면 GKE에서 Knative를 직접 사용하는 것을 고려해야 한다.&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;color: #000000;&quot;&gt;또한 멀티클라우드나 온프레미스 환경으로의 이식성을 고려한다면 Knative가 더 나은 선택일 수 있다. Cloud Run은 Google Cloud에 종속적이지만, Knative는 표준 Kubernetes 환경에서 실행할 수 있기 때문이다.&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;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 전략&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 효율성을 극대화하기 위한 플랫폼별 전략과 비교 분석이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2374&quot; data-origin-height=&quot;1634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kL5sC/btsQAO9zAcq/Ueu5LQzy83saZxr2wL7b81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kL5sC/btsQAO9zAcq/Ueu5LQzy83saZxr2wL7b81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kL5sC/btsQAO9zAcq/Ueu5LQzy83saZxr2wL7b81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkL5sC%2FbtsQAO9zAcq%2FUeu5LQzy83saZxr2wL7b81%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;2374&quot; height=&quot;1634&quot; data-origin-width=&quot;2374&quot; data-origin-height=&quot;1634&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플랫폼별 비용 구조 비교&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비용 요소&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Run&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Autopilot&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Standard&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;기본 과금&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용 시간 기반&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파드 리소스 요청&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 시간 기반&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;관리 수수료&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;없음 (100노드 초과시 유료)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;최소 비용&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0 (요청 없을 시)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0 (파드 없을 시)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 최소 개수 &amp;times; 시간&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스케일링&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 (0까지 가능)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 (파드 단위)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수동/자동 (노드 단위)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예약 할인&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지원 안함&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지원 안함&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지원 (1-3년)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Spot/Preemptible&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지원 안함&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지원 안함&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지원 (최대 80% 할인)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플랫폼별 비용 구조 이해&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 플랫폼의 비용 구조를 정확히 이해하는 것이 최적화의 첫걸음이다. GKE Standard는 노드 시간당 과금, Autopilot은 파드 리소스 요청량 기반 과금, Cloud Run은 실제 사용 시간과 리소스 기반 과금이다.&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;color: #000000;&quot;&gt;GKE Standard에서는 노드 사용률을 높이는 것이 핵심이다. Horizontal Pod Autoscaler와 Vertical Pod Autoscaler를 적절히 활용하고, 노드 어피니티 규칙을 통해 리소스 활용도를 극대화해야 한다. 또한 Spot VM을 사용하면 비용을 크게 절감할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 테라폼 설정&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;nix&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 비용 최적화된 GKE Standard 구성
resource &quot;google_container_node_pool&quot; &quot;cost_optimized_pool&quot; {
  name       = &quot;cost-optimized-pool&quot;
  location   = &quot;asia-northeast3-a&quot;
  cluster    = google_container_cluster.standard.name
  node_count = 1
  
  node_config {
    # Spot VM 사용으로 최대 80% 비용 절감
    spot         = true
    machine_type = &quot;e2-standard-2&quot;
    disk_size_gb = 50
    disk_type    = &quot;pd-standard&quot;
    
    # 리소스 효율성을 위한 라벨
    labels = {
      workload-type = &quot;batch&quot;
      cost-optimized = &quot;true&quot;
    }
    
    # 테인트 설정으로 특정 워크로드만 스케줄
    taint {
      key    = &quot;spot-instance&quot;
      value  = &quot;true&quot;
      effect = &quot;NO_SCHEDULE&quot;
    }
  }
  
  # 공격적인 스케일링 정책
  autoscaling {
    min_node_count = 0
    max_node_count = 20
  }
  
  # 빠른 스케일업을 위한 관리 정책
  management {
    auto_repair  = true
    auto_upgrade = false  # 비용 예측성을 위해 수동 관리
  }
}

# Cloud Run 비용 최적화 설정
resource &quot;google_cloud_run_v2_service&quot; &quot;cost_optimized_service&quot; {
  name     = &quot;cost-optimized-service&quot;
  location = &quot;asia-northeast3&quot;
  
  template {
    scaling {
      min_instance_count = 0  # 트래픽 없을 때 완전 스케일다운
      max_instance_count = 10
    }
    
    containers {
      image = &quot;gcr.io/${var.project_id}/app:latest&quot;
      
      # 최소 리소스로 시작하여 비용 절약
      resources {
        limits = {
          cpu    = &quot;1&quot;      # 필요에 따라 조정
          memory = &quot;512Mi&quot;  # 최소 메모리 설정
        }
      }
      
      # 동시성 최대화로 인스턴스 수 최소화
      env {
        name  = &quot;CONCURRENT_REQUESTS&quot;
        value = &quot;1000&quot;
      }
    }
    
    # 최대 실행 시간 설정으로 비용 제한
    timeout = &quot;300s&quot;
    
    # 서비스 계정 최소 권한 원칙
    service_account = google_service_account.minimal_sa.email
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;워크로드 특성에 따른 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트래픽 패턴이 불규칙한 워크로드는 Cloud Run이나 Autopilot이 비용 효율적이다. 반면 안정적이고 예측 가능한 트래픽을 가진 워크로드는 GKE Standard에서 예약 인스턴스나 약정 사용 할인을 활용하는 것이 유리할 수 있다.&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;color: #000000;&quot;&gt;배치 작업의 경우 Preemptible 인스턴스를 활용하여 비용을 대폭 절감할 수 있다. Cloud Run Jobs나 GKE의 Job 리소스를 사용하여 필요할 때만 리소스를 사용하도록 구성하는 것도 좋은 전략이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 시나리오별 전략&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;nix&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# GKE Standard - 예약 인스턴스 활용
resource &quot;google_compute_reservation&quot; &quot;production_reservation&quot; {
  name = &quot;production-reservation&quot;
  zone = &quot;asia-northeast3-a&quot;
  
  specific_reservation {
    count = 10
    instance_properties {
      machine_type = &quot;n2-standard-4&quot;
      min_cpu_platform = &quot;Intel Cascade Lake&quot;
      
      local_ssds {
        disk_size_gb = 375
        interface    = &quot;NVME&quot;
      }
    }
  }
}

# Autopilot - 리소스 요청 최적화 예시
resource &quot;kubernetes_manifest&quot; &quot;cost_optimized_deployment&quot; {
  manifest = {
    apiVersion = &quot;apps/v1&quot;
    kind       = &quot;Deployment&quot;
    
    metadata = {
      name      = &quot;web-app&quot;
      namespace = &quot;default&quot;
    }
    
    spec = {
      replicas = 3
      
      selector = {
        matchLabels = {
          app = &quot;web-app&quot;
        }
      }
      
      template = {
        metadata = {
          labels = {
            app = &quot;web-app&quot;
          }
        }
        
        spec = {
          containers = [{
            name  = &quot;web-app&quot;
            image = &quot;gcr.io/project/web-app:latest&quot;
            
            # Autopilot 비용 최적화를 위한 정확한 리소스 요청
            resources = {
              requests = {
                cpu    = &quot;250m&quot;     # 실제 필요량에 맞춤
                memory = &quot;512Mi&quot;    # 메모리 낭비 최소화
              }
              limits = {
                cpu    = &quot;500m&quot;
                memory = &quot;1Gi&quot;
              }
            }
            
            # 효율적인 헬스체크
            livenessProbe = {
              httpGet = {
                path = &quot;/health&quot;
                port = 8080
              }
              periodSeconds = 30    # 체크 주기 최적화
            }
          }]
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영 복잡도 관리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 플랫폼의 운영 복잡도와 관리 포인트를 체계적으로 분석해본다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1760&quot; data-origin-height=&quot;1484&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzDGc8/btsQzcpM1dG/B6lbx3ggHGiqzFElNk5sSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzDGc8/btsQzcpM1dG/B6lbx3ggHGiqzFElNk5sSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzDGc8/btsQzcpM1dG/B6lbx3ggHGiqzFElNk5sSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzDGc8%2FbtsQzcpM1dG%2FB6lbx3ggHGiqzFElNk5sSk%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;582&quot; height=&quot;491&quot; data-origin-width=&quot;1760&quot; data-origin-height=&quot;1484&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;&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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영 복잡도 비교표&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;운영 영역&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Run&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Autopilot&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Standard&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;인프라 관리&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드, 네트워크, 업데이트&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안 패치&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OS, 런타임 보안 업데이트&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;모니터링 설정&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 제공&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대부분 자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수동 구성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로그, 메트릭, 알림&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스케일링&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완전 자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파드 레벨 자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수동/반자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트래픽 기반 확장&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;네트워킹&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단순&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LB, 서비스메시, 보안&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;백업/복구&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;불필요&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;부분적 필요&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완전 수동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 지속성 관리&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;컴플라이언스&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 적용&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대부분 기본&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수동 설정&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모니터링 및 로깅&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 플랫폼마다 모니터링과 로깅 설정의 복잡도가 다르다. Cloud Run은 기본적으로 Cloud Logging과 Cloud Monitoring과 통합되어 있어 별도 설정이 거의 필요 없다. GKE Autopilot도 대부분의 모니터링이 자동 구성되지만, 커스텀 메트릭이 필요한 경우 추가 설정이 필요하다.&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;color: #000000;&quot;&gt;GKE Standard에서는 로깅 에이전트, 모니터링 에이전트 설치와 구성을 직접 관리해야 한다. 하지만 그만큼 세밀한 제어와 커스터마이징이 가능하다. Prometheus, Grafana 같은 오픈소스 도구를 자유롭게 사용할 수 있어 복잡한 모니터링 요구사항도 충족할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;통합 모니터링 테라폼 구성&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 모든 플랫폼을 위한 통합 모니터링 대시보드
resource &quot;google_monitoring_dashboard&quot; &quot;container_overview&quot; {
  dashboard_json = jsonencode({
    displayName = &quot;Container Platform Overview&quot;
    mosaicLayout = {
      tiles = [
        {
          width = 6
          height = 4
          widget = {
            title = &quot;Cloud Run Request Rate&quot;
            xyChart = {
              dataSets = [{
                timeSeriesQuery = {
                  timeSeriesFilter = {
                    filter = &quot;resource.type=\&quot;cloud_run_revision\&quot;&quot;
                    aggregation = {
                      alignmentPeriod = &quot;60s&quot;
                      perSeriesAligner = &quot;ALIGN_RATE&quot;
                    }
                  }
                }
              }]
            }
          }
        },
        {
          width = 6  
          height = 4
          widget = {
            title = &quot;GKE Pod CPU Usage&quot;
            xyChart = {
              dataSets = [{
                timeSeriesQuery = {
                  timeSeriesFilter = {
                    filter = &quot;resource.type=\&quot;k8s_pod\&quot;&quot;
                    aggregation = {
                      alignmentPeriod = &quot;60s&quot;
                      perSeriesAligner = &quot;ALIGN_MEAN&quot;
                    }
                  }
                }
              }]
            }
          }
        }
      ]
    }
  })
}

# 알림 정책 설정
resource &quot;google_monitoring_alert_policy&quot; &quot;high_error_rate&quot; {
  display_name = &quot;High Error Rate Alert&quot;
  combiner     = &quot;OR&quot;
  
  conditions {
    display_name = &quot;Cloud Run High Error Rate&quot;
    
    condition_threshold {
      filter          = &quot;resource.type=\&quot;cloud_run_revision\&quot;&quot;
      duration        = &quot;300s&quot;
      comparison      = &quot;COMPARISON_GREATER_THAN&quot;
      threshold_value = 0.1
      
      aggregations {
        alignment_period   = &quot;60s&quot;
        per_series_aligner = &quot;ALIGN_RATE&quot;
      }
    }
  }
  
  notification_channels = [
    google_monitoring_notification_channel.email.id
  ]
}

# 이메일 알림 채널
resource &quot;google_monitoring_notification_channel&quot; &quot;email&quot; {
  display_name = &quot;DevOps Team Email&quot;
  type         = &quot;email&quot;
  
  labels = {
    email_address = &quot;devops@company.com&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 및 컴플라이언스&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Run과 GKE Autopilot은 Google의 보안 모범 사례가 기본적으로 적용되어 있어 보안 설정 부담이 적다. 하지만 특수한 컴플라이언스 요구사항이 있다면 GKE Standard에서 세밀한 보안 정책을 구성해야 할 수 있다.&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;color: #000000;&quot;&gt;네트워크 보안, Pod Security Standards, RBAC 설정 등을 직접 관리해야 하는 복잡도가 있지만, 엔터프라이즈 환경에서 요구되는 엄격한 보안 요구사항을 충족할 수 있다. Binary Authorization, Policy Controller 같은 고급 보안 기능도 활용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 강화 테라폼 설정&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 통합 보안 정책
resource &quot;google_binary_authorization_policy&quot; &quot;container_policy&quot; {
  admission_whitelist_patterns {
    name_pattern = &quot;gcr.io/${var.project_id}/*&quot;
  }
  
  default_admission_rule {
    evaluation_mode  = &quot;REQUIRE_ATTESTATION&quot;
    enforcement_mode = &quot;ENFORCED_BLOCK_AND_AUDIT_LOG&quot;
    
    require_attestations_by = [
      google_binary_authorization_attestor.build_attestor.name
    ]
  }
  
  # Cloud Run 전용 규칙
  cluster_admission_rules {
    cluster                = &quot;projects/${var.project_id}/locations/*/cloudrun&quot;
    evaluation_mode        = &quot;REQUIRE_ATTESTATION&quot;
    enforcement_mode       = &quot;ENFORCED_BLOCK_AND_AUDIT_LOG&quot;
    require_attestations_by = [
      google_binary_authorization_attestor.build_attestor.name
    ]
  }
}

# 서비스 계정 최소 권한 설정
resource &quot;google_service_account&quot; &quot;secure_workload_sa&quot; {
  account_id   = &quot;secure-workload&quot;
  display_name = &quot;Secure Workload Service Account&quot;
}

# 필요한 최소 권한만 부여
resource &quot;google_project_iam_member&quot; &quot;workload_permissions&quot; {
  for_each = toset([
    &quot;roles/cloudsql.client&quot;,
    &quot;roles/secretmanager.secretAccessor&quot;
  ])
  
  project = var.project_id
  role    = each.value
  member  = &quot;serviceAccount:${google_service_account.secure_workload_sa.email}&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 구현 시나리오&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실무에서 활용할 수 있는 구체적인 구현 예시들을 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시나리오 1: 스타트업 MVP 구축&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1702&quot; data-origin-height=&quot;1608&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cLvJiK/btsQA5pGV5i/k3yHz30Dq5H5YLUxYMf5Nk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cLvJiK/btsQA5pGV5i/k3yHz30Dq5H5YLUxYMf5Nk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cLvJiK/btsQA5pGV5i/k3yHz30Dq5H5YLUxYMf5Nk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcLvJiK%2FbtsQA5pGV5i%2Fk3yHz30Dq5H5YLUxYMf5Nk%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;630&quot; height=&quot;595&quot; data-origin-width=&quot;1702&quot; data-origin-height=&quot;1608&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MVP를 위한 완전 서버리스 구성&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# API Gateway
resource &quot;google_cloud_run_v2_service&quot; &quot;api_gateway&quot; {
  name     = &quot;api-gateway&quot;
  location = &quot;asia-northeast3&quot;
  
  template {
    containers {
      image = &quot;gcr.io/${var.project_id}/api-gateway:latest&quot;
      
      env {
        name  = &quot;USER_SERVICE_URL&quot;
        value = google_cloud_run_v2_service.user_service.uri
      }
      
      env {
        name  = &quot;AUTH_SERVICE_URL&quot;
        value = google_cloud_run_v2_service.auth_service.uri
      }
    }
    
    scaling {
      min_instance_count = 0
      max_instance_count = 100
    }
  }
}

# User Service
resource &quot;google_cloud_run_v2_service&quot; &quot;user_service&quot; {
  name     = &quot;user-service&quot;
  location = &quot;asia-northeast3&quot;
  
  template {
    containers {
      image = &quot;gcr.io/${var.project_id}/user-service:latest&quot;
      
      env {
        name = &quot;DB_CONNECTION&quot;
        value_source {
          secret_key_ref {
            secret  = google_secret_manager_secret.db_connection.secret_id
            version = &quot;latest&quot;
          }
        }
      }
    }
    
    # 내부 서비스이므로 외부 접근 차단
    annotations = {
      &quot;run.googleapis.com/ingress&quot; = &quot;internal&quot;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시나리오 2: 엔터프라이즈 마이크로서비스&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2010&quot; data-origin-height=&quot;1088&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B1wCC/btsQB4KIY8u/KvHL3UtarFNYbzTEm57XvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B1wCC/btsQB4KIY8u/KvHL3UtarFNYbzTEm57XvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B1wCC/btsQB4KIY8u/KvHL3UtarFNYbzTEm57XvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB1wCC%2FbtsQB4KIY8u%2FKvHL3UtarFNYbzTEm57XvK%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;2010&quot; height=&quot;1088&quot; data-origin-width=&quot;2010&quot; data-origin-height=&quot;1088&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마이크로서비스를 위한 GKE Autopilot 구성&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# Istio 서비스 메시 활성화
resource &quot;google_container_cluster&quot; &quot;microservices_cluster&quot; {
  name     = &quot;microservices-cluster&quot;
  location = &quot;asia-northeast3&quot;
  
  enable_autopilot = true
  
  # Istio 서비스 메시 활성화
  service_external_ips_config {
    enabled = true
  }
  
  addons_config {
    istio_config {
      disabled = false
      auth     = &quot;AUTH_MUTUAL_TLS&quot;
    }
  }
  
  # 워크로드 아이덴티티
  workload_identity_config {
    workload_pool = &quot;${var.project_id}.svc.id.goog&quot;
  }
}

# 서비스메시 게이트웨이
resource &quot;kubernetes_manifest&quot; &quot;istio_gateway&quot; {
  manifest = {
    apiVersion = &quot;networking.istio.io/v1beta1&quot;
    kind       = &quot;Gateway&quot;
    
    metadata = {
      name      = &quot;microservices-gateway&quot;
      namespace = &quot;default&quot;
    }
    
    spec = {
      selector = {
        istio = &quot;ingressgateway&quot;
      }
      
      servers = [{
        port = {
          number   = 80
          name     = &quot;http&quot;
          protocol = &quot;HTTP&quot;
        }
        hosts = [&quot;api.company.com&quot;]
      }]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시나리오 3: 하이브리드 아키텍처&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대규모 엔터프라이즈에서는 각 서비스의 특성에 따라 다른 플랫폼을 조합하여 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1238&quot; data-origin-height=&quot;1598&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5JO8f/btsQBtcMQMl/dMEh5GP77KqzqKrKLc8avK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5JO8f/btsQBtcMQMl/dMEh5GP77KqzqKrKLc8avK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5JO8f/btsQBtcMQMl/dMEh5GP77KqzqKrKLc8avK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5JO8f%2FbtsQBtcMQMl%2FdMEh5GP77KqzqKrKLc8avK%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;1238&quot; height=&quot;1598&quot; data-origin-width=&quot;1238&quot; data-origin-height=&quot;1598&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하이브리드 구성 관리&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 프로젝트 수준 공통 설정
locals {
  common_labels = {
    environment = &quot;production&quot;
    team        = &quot;platform&quot;
    managed_by  = &quot;terraform&quot;
  }
}

# 공통 VPC
resource &quot;google_compute_network&quot; &quot;shared_vpc&quot; {
  name                    = &quot;shared-vpc&quot;
  auto_create_subnetworks = false
}

# Cloud Run을 위한 VPC 커넥터
resource &quot;google_vpc_access_connector&quot; &quot;cloud_run_connector&quot; {
  name          = &quot;cloud-run-connector&quot;
  region        = &quot;asia-northeast3&quot;
  network       = google_compute_network.shared_vpc.name
  ip_cidr_range = &quot;10.8.0.0/28&quot;
}

# GKE 클러스터용 서브넷
resource &quot;google_compute_subnetwork&quot; &quot;gke_subnet&quot; {
  name          = &quot;gke-subnet&quot;
  ip_cidr_range = &quot;10.0.0.0/16&quot;
  region        = &quot;asia-northeast3&quot;
  network       = google_compute_network.shared_vpc.id
  
  secondary_ip_range {
    range_name    = &quot;pods&quot;
    ip_cidr_range = &quot;192.168.0.0/18&quot;
  }
  
  secondary_ip_range {
    range_name    = &quot;services&quot;
    ip_cidr_range = &quot;192.168.64.0/18&quot;
  }
}

# 통합 로드 밸런서
resource &quot;google_compute_global_address&quot; &quot;main_ip&quot; {
  name = &quot;main-lb-ip&quot;
}

resource &quot;google_compute_managed_ssl_certificate&quot; &quot;main_cert&quot; {
  name = &quot;main-ssl-cert&quot;
  
  managed {
    domains = [&quot;api.company.com&quot;, &quot;app.company.com&quot;]
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google Cloud의 컨테이너 플랫폼 선택은 워크로드의 특성, 팀의 기술 역량, 비용 목표, 운영 복잡도 허용 수준을 종합적으로 고려해야 한다.&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;i&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Run은 간단한 웹 애플리케이션과 API에 최적화되어 있고, &lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Autopilot은 Kubernetes의 유연성과 서버리스의 편의성을 균형있게 제공한다. &lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Standard는 최대한의 제어권이 필요한 복잡한 엔터프라이즈 워크로드에 적합하다.&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플랫폼 선택 의사결정 매트릭스&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고려사항&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Run&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Autopilot&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Standard&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개발 속도&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매우 빠름&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;빠름&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보통&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;운영 부담&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매우 낮음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비용 예측성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;변동적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;확장성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수동/반자동&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;커스터마이징&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완전 자유&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;멀티클라우드&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;불가능&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;학습 곡선&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단계적 도입 전략&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2452&quot; data-origin-height=&quot;1448&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b584Sb/btsQA181XpN/kgcuTYG59acOJFjbRul0Nk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b584Sb/btsQA181XpN/kgcuTYG59acOJFjbRul0Nk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b584Sb/btsQA181XpN/kgcuTYG59acOJFjbRul0Nk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb584Sb%2FbtsQA181XpN%2FkgcuTYG59acOJFjbRul0Nk%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;2452&quot; height=&quot;1448&quot; data-origin-width=&quot;2452&quot; data-origin-height=&quot;1448&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;초기에는 Cloud Run으로 시작하여 빠르게 프로토타입을 구축하고, 복잡도가 증가하면 GKE Autopilot으로 마이그레이션하며, 특수한 요구사항이 생기면 GKE Standard로 확장하는 점진적 접근법을 권장한다.&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;color: #000000;&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;color: #000000;&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;color: #000000;&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;&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;
&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/kubernetes-engine/docs&quot;&gt;Google Kubernetes Engine Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/run/docs&quot;&gt;Cloud Run Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-overview&quot;&gt;GKE Autopilot vs Standard Comparison&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://knative.dev/docs/&quot;&gt;Knative Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/pricing&quot;&gt;Google Cloud Container Services Pricing&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/best-practices-for-containers&quot;&gt;Container Optimization Best Practices&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/kubernetes-engine/docs/how-to/cost-optimization&quot;&gt;Kubernetes Cost Optimization Guide&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://registry.terraform.io/providers/hashicorp/google/latest/docs&quot;&gt;Terraform Google Cloud Provider&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/service-mesh/docs&quot;&gt;Istio Service Mesh on GKE&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/binary-authorization/docs&quot;&gt;Binary Authorization for Container Security&lt;/a&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;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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>GCP</category>
      <category>Autopilot</category>
      <category>Cloud</category>
      <category>GCP</category>
      <category>GKE</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/461</guid>
      <comments>https://somaz.tistory.com/461#entry461comment</comments>
      <pubDate>Tue, 24 Mar 2026 00:00:51 +0900</pubDate>
    </item>
    <item>
      <title>누가 kubectl edit 했어? &amp;mdash; Kubernetes Cluster Drift 감지 도구 직접 만들기</title>
      <link>https://somaz.tistory.com/498</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes 클러스터를 운영하다 보면 &lt;b&gt;Git에 정의된 manifest와 실제 클러스터 상태가 달라지는 현상&lt;/b&gt;, 이른바 &lt;b&gt;Cluster Drift&lt;/b&gt;가 발생한다. 누군가 `kubectl edit` 으로 replicas를 수동 변경하거나, `kubectl scale` 로 급하게 스케일링했을 때, Git 소스와 클러스터 상태 사이에 괴리가 생긴다.&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;color: #000000;&quot;&gt;기존 `kubectl diff` 로도 비교가 가능하지만, YAML 파일만 지원하고, Helm/Kustomize를 직접 다룰 수 없으며, 출력이 raw unified diff라 가독성이 떨어진다.&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;&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;span style=&quot;color: #000000;&quot;&gt;이 글에서는 이런 문제를 해결하기 위해 직접 만든 두 가지 도구를 소개한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/kube-diff&quot;&gt;kube-diff&lt;/a&gt;&lt;/b&gt; &amp;mdash; Go로 작성한 CLI 도구. Plain YAML, Helm chart, Kustomize overlay를 클러스터와 비교&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/kube-diff-action&quot;&gt;kube-diff-action&lt;/a&gt;&lt;/b&gt; &amp;mdash; GitHub Actions에서 kube-diff를 사용할 수 있는 Composite Action&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;br /&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`kubectl diff`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`kube-diff`&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Input&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;YAML files only&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Helm / Kustomize / plain YAML&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Output&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Raw unified diff&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Per-resource colorized diff + summary&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;New resources&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Full content dump&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;NEW&lt;/b&gt; label&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Deleted detection&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Not supported&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Detects resources only in cluster&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;CI integration&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Exit code only&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;JSON / Markdown report output&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Filtering&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;None&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Namespace, kind, label selector filter&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;&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;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUufux/dJMcadH16hP/zwNblx17if3Jgq7SbcCKpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUufux/dJMcadH16hP/zwNblx17if3Jgq7SbcCKpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUufux/dJMcadH16hP/zwNblx17if3Jgq7SbcCKpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUufux%2FdJMcadH16hP%2FzwNblx17if3Jgq7SbcCKpK%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 프로젝트 구조&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kube-diff (CLI)&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;kube-diff/
├── cmd/
│   ├── main.go                # 엔트리포인트
│   └── cli/
│       ├── root.go            # Cobra root command
│       ├── file.go            # file subcommand
│       ├── helm.go            # helm subcommand
│       ├── kustomize.go       # kustomize subcommand
│       ├── version.go         # version subcommand
│       └── run.go             # 공유 비교 로직
├── internal/
│   ├── source/                # Manifest loaders (file, helm, kustomize)
│   ├── cluster/               # K8s dynamic client fetcher
│   ├── diff/                  # Normalization &amp;amp; unified diff
│   └── report/                # Color/JSON/Markdown output
├── examples/
│   ├── file/                  # Plain YAML 예제
│   ├── helm/                  # Helm chart 예제
│   └── kustomize/             # Kustomize overlay 예제
├── scripts/
│   ├── demo.sh                # 데모 스크립트
│   └── demo-clean.sh          # 데모 정리
├── .goreleaser.yml            # GoReleaser 설정
└── Makefile&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kube-diff-action (GitHub Action)&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;stata&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;kube-diff-action/
├── action.yml                 # Composite Action 정의
├── scripts/
│   ├── install.sh             # kube-diff 바이너리 설치
│   ├── run.sh                 # kube-diff 실행 &amp;amp; output 설정
│   └── comment.sh             # PR 코멘트 생성/업데이트
└── .github/workflows/
    ├── ci.yml                 # CI (ShellCheck, kind cluster 테스트)
    ├── release.yml            # 릴리스 자동화
    └── use-action.yml         # Smoke Test (릴리스된 액션 검증)&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;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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;2. 핵심 설계 포인트&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2.1 Kubernetes Dynamic Client&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특정 리소스 타입에 의존하지 않고, `unstructured.Unstructured` 를 사용하는 dynamic client로 &lt;b&gt;모든 종류의 Kubernetes 리소스&lt;/b&gt;를 다룬다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;stata&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;// internal/cluster/fetcher.go
func (f *Fetcher) Get(ctx context.Context, apiVersion, kind, namespace, name string) (*unstructured.Unstructured, error) {
    gvr, err := f.resolveGVR(apiVersion, kind)
    if err != nil {
        return nil, err
    }

    var resource *unstructured.Unstructured
    if namespace != &quot;&quot; {
        resource, err = f.client.Resource(gvr).Namespace(namespace).Get(ctx, name, metav1.GetOptions{})
    } else {
        resource, err = f.client.Resource(gvr).Get(ctx, name, metav1.GetOptions{})
    }
    return resource, err
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2.2 공유 비교 로직&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;file, helm, kustomize 세 가지 서브커맨드가 모두 동일한 `runDiff()`&amp;nbsp; 함수를 공유한다. Source 인터페이스만 다르게 주입하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;go&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;// cmd/cli/run.go &amp;mdash; 핵심 흐름
func runDiff(cmd *cobra.Command, src source.Source) error {
    // 1. 로컬 리소스 로드
    resources, err := src.Load()

    // 2. 필터링 (namespace, kind, label selector)
    // ...

    // 3. 클러스터에서 대응하는 리소스 조회
    fetcher, _ := cluster.NewFetcher(kubeconfig, kubeContext)
    for _, r := range resources {
        clusterObj, err := fetcher.Get(ctx, r.APIVersion, r.Kind, r.Namespace, r.Name)
        // 4. diff 비교
        result, _ := diff.Compare(r.Object, clusterObj)
        results = append(results, result)
    }

    // 5. 리포트 출력 (color, plain, json, markdown)
    summary := report.NewSummary(results)
    // ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2.3 Kubernetes 기본값 정규화&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클러스터는 리소스에 다양한 &lt;b&gt;기본값을 자동 추가&lt;/b&gt;한다. 이를 그대로 비교하면 false positive가 대량 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예를 들어, Deployment를 apply하면 클러스터가 자동으로 추가하는 필드들:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`spec.progressDeadlineSeconds: 600`&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`spec.revisionHistoryLimit: 10`&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`spec.strategy.type: RollingUpdate`&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`spec.template.spec.dnsPolicy: ClusterFirst`&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`spec.template.spec.restartPolicy: Always`&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Container의 `terminationMessagePath`, `terminationMessagePolicy`&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Container port의 `protocol: TCP`&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;이런 기본값들을 &lt;b&gt;Kind별로 정규화&lt;/b&gt;하여 제거한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;reasonml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;// internal/diff/normalize.go
func Normalize(obj *unstructured.Unstructured) *unstructured.Unstructured {
    // 공통 메타데이터 제거 (managedFields, uid, resourceVersion 등)
    // ...

    // Kind별 기본값 제거
    switch kind {
    case &quot;Deployment&quot;, &quot;StatefulSet&quot;:
        normalizeDeploymentSpec(spec)  // progressDeadlineSeconds, strategy 등
    case &quot;Service&quot;:
        normalizeServiceSpec(spec)     // clusterIP, sessionAffinity 등
    case &quot;Namespace&quot;:
        normalizeNamespaceSpec(obj)    // spec.finalizers 등
    case &quot;Pod&quot;:
        normalizePodSpec(spec)
    case &quot;Job&quot;:
        normalizeJobSpec(spec)
    case &quot;DaemonSet&quot;:
        normalizeDaemonSetSpec(spec)
    }
    return normalized
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;이 정규화 덕분에 실제로 의미 있는 차이만 diff에 표시된다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2.4 Exit Code 설계&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Code&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Meaning&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;No changes detected&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Changes detected&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Error occurred&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&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;color: #000000;&quot;&gt;CI에서 exit code 1은 &quot;drift 있음&quot;이지 에러가 아니므로, GitHub Action에서는 exit code 0과 1 모두 성공으로 처리하고, 2만 실패로 간주한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;3. 샘플 애플리케이션&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3.1 Plain YAML (file mode)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;Namespace&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# examples/file/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: kube-diff-demo&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ConfigMap&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# examples/file/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: demo-config
  namespace: kube-diff-demo
data:
  APP_ENV: production
  LOG_LEVEL: info
  MAX_CONNECTIONS: &quot;100&quot;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Deployment&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# examples/file/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
  namespace: kube-diff-demo
  labels:
    app: demo-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: demo-app
  template:
    metadata:
      labels:
        app: demo-app
    spec:
      containers:
        - name: app
          image: nginx:1.25
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 200m
              memory: 256Mi
          envFrom:
            - configMapRef:
                name: demo-config&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Service&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# examples/file/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: demo-app
  namespace: kube-diff-demo
spec:
  selector:
    app: demo-app
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: ClusterIP&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3.2 Helm Chart (helm mode)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;Chart.yaml&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# examples/helm/demo-chart/Chart.yaml
apiVersion: v2
name: demo-chart
description: Demo Helm chart for kube-diff examples
version: 0.1.0
type: application&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;values.yaml&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# examples/helm/demo-chart/values.yaml
replicaCount: 2
image: nginx:1.25
namespace: kube-diff-demo

config:
  APP_ENV: production
  LOG_LEVEL: info
  MAX_CONNECTIONS: &quot;100&quot;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;templates/deployment.yaml&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-app
  namespace: {{ .Values.namespace }}
  labels:
    app: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app: {{ .Release.Name }}
    spec:
      containers:
        - name: app
          image: {{ .Values.image }}
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 200m
              memory: 256Mi&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;templates/configmap.yaml&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;crystal&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-config
  namespace: {{ .Values.namespace }}
data:
  {{- range $key, $val := .Values.config }}
  {{ $key }}: {{ $val | quote }}
  {{- end }}&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;templates/service.yaml&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}-svc
  namespace: {{ .Values.namespace }}
spec:
  selector:
    app: {{ .Release.Name }}
  ports:
    - port: 80
      targetPort: 80
  type: ClusterIP&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;values-drift.yaml&lt;/b&gt; (의도적으로 다른 값)&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# examples/helm/values-drift.yaml
replicaCount: 3
image: nginx:1.26
namespace: kube-diff-demo

config:
  APP_ENV: staging
  LOG_LEVEL: debug
  MAX_CONNECTIONS: &quot;200&quot;
  NEW_KEY: &quot;added&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3.3 Kustomize (kustomize mode)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;base/kustomization.yaml&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;http&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: kube-diff-demo

resources:
  - configmap.yaml
  - deployment.yaml
  - service.yaml&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;overlays/dev/kustomization.yaml&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;http&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: kube-diff-demo

resources:
  - ../../base

patches:
  - target:
      kind: Deployment
      name: demo-app
    patch: |
      - op: replace
        path: /spec/replicas
        value: 3
      - op: replace
        path: /spec/template/spec/containers/0/image
        value: nginx:1.26

  - target:
      kind: ConfigMap
      name: demo-config
    patch: |
      - op: replace
        path: /data/LOG_LEVEL
        value: debug
      - op: add
        path: /data/NEW_KEY
        value: added&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;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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;4. CLI 사용법과 데모&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4.1 설치&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Homebrew
brew install somaz94/tap/kube-diff

# Krew (kubectl plugin)
kubectl krew install diff2

# Binary
curl -sL https://github.com/somaz94/kube-diff/releases/latest/download/kube-diff_linux_amd64.tar.gz | tar xz
sudo mv kube-diff /usr/local/bin/

# From source
go install github.com/somaz94/kube-diff/cmd@latest&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4.2 기본 사용법&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Plain YAML 비교
kube-diff file ./manifests/ -n production

# Helm chart 비교
kube-diff helm ./my-chart --values values-prod.yaml --release my-release -n production

# Kustomize overlay 비교
kube-diff kustomize ./overlays/production -n production&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4.3 필터링&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Kind 필터
kube-diff file ./manifests/ -n production -k Deployment,Service

# Label selector 필터
kube-diff file ./manifests/ -n production -l app=nginx,env=prod

# 조합
kube-diff file ./manifests/ -n production -k Deployment -l app=nginx&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4.4 출력 형식&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Colorized (기본)
kube-diff file ./manifests/ -n production

# JSON
kube-diff file ./manifests/ -n production -o json

# Markdown
kube-diff file ./manifests/ -n production -o markdown

# Summary only
kube-diff file ./manifests/ -n production -s&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4.5 데모 실행 결과&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`make demo-all` 명령으로 전체 데모를 실행할 수 있다. 아래는 주요 Phase별 결과이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Phase 2 &amp;mdash; Drift 없는 상태&lt;/b&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;color: #000000;&quot;&gt;클러스터에 manifest를 배포한 직후 비교하면 모든 리소스가 unchanged로 나온다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;maxima&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;✓ OK     ConfigMap/demo-config (namespace: kube-diff-demo)
✓ OK     Deployment/demo-app (namespace: kube-diff-demo)
✓ OK     Namespace/kube-diff-demo
✓ OK     Service/demo-app (namespace: kube-diff-demo)

Summary: 4 resources &amp;mdash; 4 unchanged&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Phase 3 &amp;mdash; 클러스터에 수동 변경 적용&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;maxima&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 수동으로 replicas 변경
kubectl scale deploy/demo-app --replicas=5 -n kube-diff-demo

# ConfigMap에 새 키 추가
kubectl patch configmap demo-config -n kube-diff-demo --type merge -p '{&quot;data&quot;:{&quot;DEBUG_MODE&quot;:&quot;true&quot;}}'&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Phase 4 &amp;mdash; Drift 감지&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;diff&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;~ CHANGED ConfigMap/demo-config (namespace: kube-diff-demo)
--- cluster
+++ local
@@ -1,7 +1,6 @@
 apiVersion: v1
 data:
     APP_ENV: production
-    DEBUG_MODE: &quot;true&quot;
     LOG_LEVEL: info
     MAX_CONNECTIONS: &quot;100&quot;

~ CHANGED Deployment/demo-app (namespace: kube-diff-demo)
--- cluster
+++ local
@@ -6,7 +6,7 @@
     name: demo-app
     namespace: kube-diff-demo
 spec:
-    replicas: 5
+    replicas: 2
     selector:

✓ OK     Namespace/kube-diff-demo
✓ OK     Service/demo-app (namespace: kube-diff-demo)

Summary: 4 resources &amp;mdash; 2 changed, 2 unchanged&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;클러스터에서 수동으로 추가한 `DEBUG_MODE` 와 변경한 `replicas: 5` 가 정확히 감지된다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Phase 7 &amp;mdash; JSON 출력&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;json&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;{
  &quot;total&quot;: 4,
  &quot;changed&quot;: 2,
  &quot;new&quot;: 0,
  &quot;deleted&quot;: 0,
  &quot;unchanged&quot;: 2,
  &quot;resources&quot;: [
    {
      &quot;kind&quot;: &quot;ConfigMap&quot;,
      &quot;name&quot;: &quot;demo-config&quot;,
      &quot;namespace&quot;: &quot;kube-diff-demo&quot;,
      &quot;status&quot;: &quot;changed&quot;
    },
    {
      &quot;kind&quot;: &quot;Deployment&quot;,
      &quot;name&quot;: &quot;demo-app&quot;,
      &quot;namespace&quot;: &quot;kube-diff-demo&quot;,
      &quot;status&quot;: &quot;changed&quot;
    },
    {
      &quot;kind&quot;: &quot;Namespace&quot;,
      &quot;name&quot;: &quot;kube-diff-demo&quot;,
      &quot;status&quot;: &quot;unchanged&quot;
    },
    {
      &quot;kind&quot;: &quot;Service&quot;,
      &quot;name&quot;: &quot;demo-app&quot;,
      &quot;namespace&quot;: &quot;kube-diff-demo&quot;,
      &quot;status&quot;: &quot;unchanged&quot;
    }
  ]
}&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Phase 7 &amp;mdash; Markdown 출력&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;gherkin&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;## kube-diff Report

**4** resources &amp;mdash; **2** changed, 2 unchanged

| Status | Resource | Namespace |
|--------|----------|-----------|
| CHANGED | ConfigMap/demo-config | kube-diff-demo |
| CHANGED | Deployment/demo-app | kube-diff-demo |
| OK | Namespace/kube-diff-demo | - |
| OK | Service/demo-app | kube-diff-demo |&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;5. GitHub Action 구현&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5.1 왜 Composite Action인가&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kube-diff-action은 Docker Action이 아닌 &lt;b&gt;Composite Action&lt;/b&gt;으로 구현했다. 이유는 단순하다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kube-diff 바이너리를 다운로드해서 실행하는 것이 전부&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Docker 이미지를 빌드하거나 유지할 필요 없음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Runner의 kubeconfig과 kubectl을 직접 사용 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5.2 action.yml&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;http&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;name: kube-diff Action
description: Compare local Kubernetes manifests against live cluster state and report drift
author: somaz94

inputs:
  source:
    description: 'Source type: file, helm, or kustomize'
    required: true
  path:
    description: 'Path to manifests, Helm chart, or Kustomize overlay'
    required: true
  values:
    description: 'Helm values files (comma-separated)'
    required: false
    default: ''
  release:
    description: 'Helm release name'
    required: false
    default: 'release'
  namespace:
    description: 'Filter by namespace'
    required: false
    default: ''
  kind:
    description: 'Filter by resource kind (comma-separated)'
    required: false
    default: ''
  selector:
    description: 'Filter by label selector (e.g., app=nginx,env=prod)'
    required: false
    default: ''
  output:
    description: 'Output format: color, plain, json, markdown'
    required: false
    default: 'markdown'
  summary-only:
    description: 'Show summary only without diff details'
    required: false
    default: 'false'
  comment:
    description: 'Post diff result as PR comment'
    required: false
    default: 'true'
  version:
    description: 'kube-diff version to install (e.g., v0.2.1). Default: latest'
    required: false
    default: 'latest'
  token:
    description: 'GitHub token for PR comments'
    required: false
    default: ${{ github.token }}

outputs:
  result:
    description: 'Diff output text'
    value: ${{ steps.diff.outputs.result }}
  exit-code:
    description: 'Exit code from kube-diff (0=no changes, 1=changes detected)'
    value: ${{ steps.diff.outputs.exit-code }}
  has-changes:
    description: 'Whether changes were detected (true/false)'
    value: ${{ steps.diff.outputs.has-changes }}

runs:
  using: composite
  steps:
    - name: Install kube-diff
      shell: bash
      env:
        VERSION: ${{ inputs.version }}
      run: ${{ github.action_path }}/scripts/install.sh

    - name: Run kube-diff
      id: diff
      shell: bash
      env:
        INPUT_SOURCE: ${{ inputs.source }}
        INPUT_PATH: ${{ inputs.path }}
        # ... (환경변수로 input 전달)
      run: ${{ github.action_path }}/scripts/run.sh

    - name: Comment on PR
      if: inputs.comment == 'true' &amp;amp;&amp;amp; github.event_name == 'pull_request'
      shell: bash
      env:
        GH_TOKEN: ${{ inputs.token }}
        DIFF_RESULT: ${{ steps.diff.outputs.result }}
        HAS_CHANGES: ${{ steps.diff.outputs.has-changes }}
      run: ${{ github.action_path }}/scripts/comment.sh&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5.3 install.sh &amp;mdash; 바이너리 설치&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OS/Arch를 자동 감지하고, GitHub Releases에서 최신 바이너리를 다운로드한다:&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;#!/usr/bin/env bash
set -euo pipefail

VERSION=&quot;${VERSION:-latest}&quot;

# OS/Arch 자동 감지
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)

case &quot;${ARCH}&quot; in
  x86_64)  ARCH=&quot;amd64&quot; ;;
  aarch64) ARCH=&quot;arm64&quot; ;;
  arm64)   ARCH=&quot;arm64&quot; ;;
  *)       echo &quot;::error::Unsupported architecture: ${ARCH}&quot;; exit 1 ;;
esac

# latest 버전 자동 해석
if [[ &quot;${VERSION}&quot; == &quot;latest&quot; ]]; then
  VERSION=$(curl -sL https://api.github.com/repos/somaz94/kube-diff/releases/latest \
    | grep '&quot;tag_name&quot;' | sed -E 's/.*&quot;([^&quot;]+)&quot;.*/\1/')
fi

# 다운로드 &amp;amp; 설치
VERSION_NUM=&quot;${VERSION#v}&quot;
FILENAME=&quot;kube-diff_${VERSION_NUM}_${OS}_${ARCH}.tar.gz&quot;
URL=&quot;https://github.com/somaz94/kube-diff/releases/download/${VERSION}/${FILENAME}&quot;

TMPDIR=$(mktemp -d)
trap 'rm -rf &quot;${TMPDIR}&quot;' EXIT

curl -sL -o &quot;${TMPDIR}/kube-diff.tar.gz&quot; &quot;${URL}&quot;
tar -xzf &quot;${TMPDIR}/kube-diff.tar.gz&quot; -C &quot;${TMPDIR}&quot;
chmod +x &quot;${TMPDIR}/kube-diff&quot;
sudo mv &quot;${TMPDIR}/kube-diff&quot; /usr/local/bin/kube-diff&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주의: `set -euo pipefail` 환경에서 `VERSION` 환경변수가 없으면 `unbound variable` 에러가 발생한다. `VERSION=&quot;${VERSION:-latest}&quot;` 기본값 설정이 반드시 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5.4 run.sh &amp;mdash; 실행 &amp;amp; Output 설정&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;#!/usr/bin/env bash
set -euo pipefail

# 커맨드 조합
CMD=&quot;kube-diff ${INPUT_SOURCE} ${INPUT_PATH}&quot;

# Helm 전용 플래그
if [[ &quot;${INPUT_SOURCE}&quot; == &quot;helm&quot; ]]; then
  [[ -n &quot;${INPUT_VALUES}&quot; ]] &amp;amp;&amp;amp; # values 파일 추가
  [[ -n &quot;${INPUT_RELEASE}&quot; ]] &amp;amp;&amp;amp; CMD+=&quot; -r ${INPUT_RELEASE}&quot;
fi

# 글로벌 플래그
[[ -n &quot;${INPUT_NAMESPACE}&quot; ]] &amp;amp;&amp;amp; CMD+=&quot; -n ${INPUT_NAMESPACE}&quot;
[[ -n &quot;${INPUT_KIND}&quot; ]] &amp;amp;&amp;amp; CMD+=&quot; -k ${INPUT_KIND}&quot;
[[ -n &quot;${INPUT_SELECTOR}&quot; ]] &amp;amp;&amp;amp; CMD+=&quot; -l ${INPUT_SELECTOR}&quot;

# 실행 &amp;amp; 결과 캡처
set +e
RESULT=$(eval &quot;${CMD}&quot; 2&amp;gt;&amp;amp;1)
EXIT_CODE=$?
set -e

# GitHub Output 설정 (multiline)
{
  echo &quot;result&amp;lt;&amp;lt;KUBE_DIFF_EOF&quot;
  echo &quot;${RESULT}&quot;
  echo &quot;KUBE_DIFF_EOF&quot;
} &amp;gt;&amp;gt; &quot;${GITHUB_OUTPUT}&quot;

# Exit code 0(변경 없음), 1(변경 있음) &amp;rarr; 성공 / 2(에러) &amp;rarr; 실패
if [[ ${EXIT_CODE} -eq 2 ]]; then
  exit 1
fi&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5.5 comment.sh &amp;mdash; PR 코멘트&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`&amp;lt;!-- kube-diff-action --&amp;gt;` 마커를 사용해 기존 코멘트가 있으면 업데이트, 없으면 새로 생성한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;#!/usr/bin/env bash
set -euo pipefail

MARKER=&quot;&amp;lt;!-- kube-diff-action --&amp;gt;&quot;

# 기존 코멘트 확인
EXISTING_COMMENT_ID=$(gh api &quot;repos/${REPO}/issues/${PR_NUMBER}/comments&quot; \
  --jq &quot;.[] | select(.body | contains(\&quot;${MARKER}\&quot;)) | .id&quot; | head -1 || true)

if [[ -n &quot;${EXISTING_COMMENT_ID}&quot; ]]; then
  # 업데이트
  gh api &quot;repos/${REPO}/issues/comments/${EXISTING_COMMENT_ID}&quot; \
    -X PATCH -f body=&quot;${BODY}&quot; &amp;gt; /dev/null
else
  # 새로 생성
  gh api &quot;repos/${REPO}/issues/${PR_NUMBER}/comments&quot; \
    -f body=&quot;${BODY}&quot; &amp;gt; /dev/null
fi&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5.6 kube-diff-action 사용 예시&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;- name: Check drift
  id: diff
  uses: somaz94/kube-diff-action@v1
  with:
    source: file
    path: ./manifests/
    namespace: production
    output: markdown

- name: Fail if drift
  if: steps.diff.outputs.has-changes == 'true'
  run: |
    echo &quot;::error::Drift detected &amp;mdash; review the PR comment for details&quot;
    exit 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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;6. CI/CD 파이프라인&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6.1 kube-diff CI&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# .github/workflows/ci.yml (발췌)
test-unit:
  steps:
    - uses: actions/checkout@v6
    - uses: actions/setup-go@v5
      with:
        go-version-file: go.mod
    - run: go test ./... -v -race -cover

e2e:
  steps:
    - uses: actions/checkout@v6
    - uses: actions/setup-go@v5
    - uses: helm/kind-action@v1      # kind cluster 생성
    - run: make build
    - run: make demo-all             # 전체 데모 실행&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6.2 kube-diff-action CI&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kind cluster를 활용해 실제 Kubernetes 환경에서 file/helm 모드를 테스트한다:&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# .github/workflows/ci.yml (발췌)
test-action-file:
  steps:
    - uses: actions/checkout@v4
    - name: Setup kind cluster
      uses: helm/kind-action@v1
    - name: Apply test manifests
      run: kubectl apply -f /tmp/test-manifests/
    - name: Run kube-diff action
      id: diff
      uses: ./                       # 로컬 action 테스트
      with:
        source: file
        path: /tmp/test-manifests/
        namespace: default
        comment: 'false'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6.3 Smoke Test (Released Action)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;릴리스 후 실제 `somaz94/kube-diff-action@v1` 으로 동작을 검증하는 워크플로우이다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# .github/workflows/use-action.yml
on:
  workflow_dispatch:
  workflow_run:
    workflows: [&quot;Create release&quot;]
    types: [completed]

jobs:
  smoke-test-file:
    steps:
      - uses: somaz94/kube-diff-action@v1  # 릴리스된 버전 사용
        with:
          source: file
          path: /tmp/test-manifests/
          namespace: default
          comment: '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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;7. 배포 &amp;mdash; GoReleaser, Homebrew, Krew&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;7.1 GoReleaser 설정&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# .goreleaser.yml
version: 2

builds:
  - main: ./cmd/main.go
    binary: kube-diff
    env:
      - CGO_ENABLED=0
    goos: [linux, darwin, windows]
    goarch: [amd64, arm64]
    ldflags:
      - -s -w
      - -X github.com/somaz94/kube-diff/cmd/cli.version={{.Version}}
      - -X github.com/somaz94/kube-diff/cmd/cli.commit={{.Commit}}
      - -X github.com/somaz94/kube-diff/cmd/cli.date={{.Date}}

brews:
  - repository:
      owner: somaz94
      name: homebrew-tap
    description: &quot;Compare local Kubernetes manifests against live cluster state&quot;

krews:
  - name: diff2
    repository:
      owner: somaz94
      name: krew-index
    short_description: &quot;Diff local K8s manifests vs cluster&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;tag를 push하면 GoReleaser가 자동으로&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;6개 플랫폼(linux/darwin/windows x amd64/arm64) 바이너리 빌드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GitHub Release 생성 및 바이너리 첨부&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Homebrew tap 업데이트 (somaz94/homebrew-tap)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Krew 플러그인 index 업데이트 (somaz94/krew-index)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;7.2 kube-diff-action 버전 관리&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`kube-diff-action` 은 `install.sh` 에서 &lt;b&gt;런타임에 최신 kube-diff 바이너리&lt;/b&gt;를 다운로드하므로, kube-diff가 업그레이드되면 action 사용자들은 다음 실행 시 자동으로 최신 버전을 받게 된다.&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;color: #000000;&quot;&gt;`major-tag-action` 을 사용해 v1 태그를 항상 최신 릴리스 커밋으로 갱신한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# .github/workflows/release.yml (발췌)
- name: &quot;Update major version tag&quot;
  uses: somaz94/major-tag-action@v1
  with:
    tag: ${{ github.ref_name }}
    github_token: ${{ secrets.EXAMPLE_PAT_TOKEN }}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;이렇게 하면 `somaz94/kube-diff-action@v1` 으로 항상 최신 패치 버전을 사용할 수 있다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;8. 실제 활용 시나리오&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CLI 활용&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시나리오&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;명령어&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배포 전 drift 확인&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kube-diff file ./manifests/ -n production&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인시던트 후 감사&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kube-diff file ./manifests/ -n production -o json &amp;gt; drift-report.json&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GitOps sync 검증&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kube-diff kustomize ./overlays/production -n production&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;멀티 클러스터 비교&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kube-diff file ./manifests/ --context prod-cluster -n app&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Helm 업그레이드 미리보기&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kube-diff helm ./chart/ -f values-prod.yaml -r my-release -n production&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GitHub Action 활용&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;PR Drift Gate&lt;/b&gt; &amp;mdash; manifest 변경 PR에서 자동으로 drift 체크&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;name: Drift Check
on:
  pull_request:
    paths: ['manifests/**']

jobs:
  check-drift:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v6
      - name: Setup kubeconfig
        run: echo &quot;${{ secrets.EXAMPLE_KUBECONFIG }}&quot; | base64 -d &amp;gt; /tmp/kubeconfig
        env:
          KUBECONFIG: /tmp/kubeconfig
      - name: Check drift
        uses: somaz94/kube-diff-action@v1
        with:
          source: file
          path: ./manifests/
          namespace: production&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스케줄 기반 Drift 모니터링&lt;/b&gt; &amp;mdash; 6시간마다 drift 체크 후 Slack 알림&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;name: Drift Monitor
on:
  schedule:
    - cron: '0 */6 * * *'

jobs:
  monitor:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Setup kubeconfig
        run: echo &quot;${{ secrets.EXAMPLE_KUBECONFIG }}&quot; | base64 -d &amp;gt; /tmp/kubeconfig
        env:
          KUBECONFIG: /tmp/kubeconfig
      - name: Check drift
        id: diff
        uses: somaz94/kube-diff-action@v1
        with:
          source: file
          path: ./manifests/
          namespace: production
          output: json
          comment: 'false'
      - name: Alert on drift
        if: steps.diff.outputs.has-changes == 'true'
        run: |
          curl -X POST &quot;${{ secrets.EXAMPLE_SLACK_WEBHOOK }}&quot; \
            -H 'Content-Type: application/json' \
            -d '{&quot;text&quot;: &quot;Cluster drift detected in production!&quot;}'&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;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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kube-diff를 만들면서 몇 가지 교훈을 얻었다.&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Kubernetes 기본값 정규화가 핵심이다&lt;/b&gt; &amp;mdash; 단순히 로컬과 클러스터를 비교하면 false positive가 대량 발생한다. `progressDeadlineSeconds`, `revisionHistoryLimit`, `dnsPolicy` 같은 기본값을 Kind별로 정확히 제거해야 의미 있는 diff가 나온다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Exit code 설계가 중요하다&lt;/b&gt; &amp;mdash; CI에서 &quot;변경 감지&quot;와 &quot;에러&quot;를 구분하지 않으면 워크플로우가 매번 실패로 처리된다. `exit code` 0/1/2 체계로 이를 분리했다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Composite Action은 가볍고 빠르다&lt;/b&gt; &amp;mdash; 기존 CLI 바이너리를 활용하는 경우, Docker Action보다 Composite Action이 훨씬 실용적이다. 빌드 시간 없이 바이너리만 다운로드하면 끝난다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;런타임 최신 버전 다운로드 전략&lt;/b&gt; &amp;mdash; kube-diff-action 은 kube-diff 바이너리를 런타임에 다운로드하므로, CLI만 업그레이드하면 Action 사용자도 자동으로 최신 기능을 사용하게 된다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현재 v0.2.1 기준으로 `file/helm/kustomize` 비교, `namespace/kind/label` 필터링, `color/plain/json/markdown` 출력을 지원한다. &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;color: #000000;&quot;&gt;Kubernetes 클러스터의 drift를 빠르게 감지하고, CI에서 자동으로 모니터링하고 싶다면 한번 사용해보길 바란다.&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;&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;
&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/kube-diff&quot;&gt;kube-diff GitHub Repository&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/kube-diff-action&quot;&gt;kube-diff-action GitHub Repository&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/kube-diff/tree/main/docs&quot;&gt;kube-diff Documentation&lt;/a&gt;&lt;/span&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/kube-diff/blob/main/docs/USAGE.md&quot;&gt;Usage Guide&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/kube-diff/blob/main/docs/CONFIGURATION.md&quot;&gt;Configuration&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/kube-diff/blob/main/docs/EXAMPLES.md&quot;&gt;Examples&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/somaz94/kube-diff/blob/main/docs/USE-CASES.md&quot;&gt;Use Cases&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://pkg.go.dev/k8s.io/client-go/dynamic&quot;&gt;Kubernetes Dynamic Client&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://goreleaser.com/&quot;&gt;GoReleaser&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/spf13/cobra&quot;&gt;Cobra CLI Framework&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-composite-action&quot;&gt;GitHub Composite Actions&lt;/a&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;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;
&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;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Container Orchestration/Kubernetes</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/498</guid>
      <comments>https://somaz.tistory.com/498#entry498comment</comments>
      <pubDate>Mon, 23 Mar 2026 00:00:44 +0900</pubDate>
    </item>
    <item>
      <title>GitLab CI/CD YAML 파일 최적화: 중복 제거와 재사용성 향상</title>
      <link>https://somaz.tistory.com/460</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GitLab CI/CD 파이프라인이 복잡해질수록 YAML 설정 파일에서 중복된 코드와 복잡한 구성이 늘어난다. 이는 유지보수를 어렵게 만들고 실수 가능성을 높입니다. GitLab은 이러한 문제를 해결하기 위해 YAML 재사용 기능들을 제공한다. 이번 글에서는 GitLab CI/CD YAML 파일을 최적화하는 세 가지 핵심 방법을 살펴보겠다.&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;color: #000000;&quot;&gt;GitLab CI/CD에서 제공하는 YAML 최적화 도구들은 크게 세 가지로 나눌 수 있다.&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;YAML 앵커(Anchors)&lt;/b&gt;: 전통적인 YAML 문법을 활용한 재사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;extends 키워드&lt;/b&gt;: GitLab에서 권장하는 구성 상속 방식&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;!reference 태그&lt;/b&gt;: 선택적 참조를 통한 유연한 재사용&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각각의 특징과 사용법을 자세히 알아보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pQfWQ/dJMcagYt0Xv/Rx5kugOvIbGMixNEpVWuJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pQfWQ/dJMcagYt0Xv/Rx5kugOvIbGMixNEpVWuJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pQfWQ/dJMcagYt0Xv/Rx5kugOvIbGMixNEpVWuJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpQfWQ%2FdJMcagYt0Xv%2FRx5kugOvIbGMixNEpVWuJ0%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. YAML 앵커 (Anchors): 기본적인 재사용 패턴&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;YAML 앵커는 표준 YAML 문법으로, `&amp;amp;` 로 앵커를 정의하고 `*` 로 참조하는 방식이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 사용법&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 앵커 정의
.job_template: &amp;amp;job_configuration
  image: ruby:2.6
  services:
    - postgres
    - redis

# 앵커 참조
test1:
  &amp;lt;&amp;lt;: *job_configuration  # 맵 병합
  script:
    - test1 project

test2:
  &amp;lt;&amp;lt;: *job_configuration
  script:
    - test2 project
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스크립트용 앵커 활용&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스크립트 섹션에서도 앵커를 유용하게 활용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;vim&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;.setup_script: &amp;amp;setup_script
  - echo &quot;환경 설정 시작&quot;
  - npm install

.test_script: &amp;amp;test_script
  - echo &quot;테스트 실행&quot;
  - npm test

job1:
  before_script:
    - *setup_script
  script:
    - *test_script
    - echo &quot;job1 전용 명령어&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;앵커의 제한사항&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;앵커는&amp;nbsp;&lt;b&gt;같은 파일 내에서만&lt;/b&gt;&amp;nbsp;작동합니다. include로 가져온 외부 파일의 앵커는 참조할 수 없다.&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. extends: GitLab이 권장하는 상속 방식&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;extends 키워드는 YAML 앵커보다 더 유연하고 가독성이 좋은 GitLab 전용 기능이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 상속&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;vim&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;.base_job:
  image: node:16
  stage: build
  tags:
    - docker

build_dev:
  extends: .base_job
  variables:
    NODE_ENV: development
  script:
    - npm run build:dev

build_prod:
  extends: .base_job
  variables:
    NODE_ENV: production
  script:
    - npm run build:prod
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다단계 상속&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최대 11단계까지 상속이 가능하지만, 복잡성을 고려해 3단계 이내를 권장합니다:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;vim&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;.tests:
  rules:
    - if: $CI_PIPELINE_SOURCE == &quot;push&quot;

.rspec:
  extends: .tests
  script: rake rspec

rspec_unit:
  extends: .rspec
  variables:
    TEST_TYPE: unit
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부 파일과의 조합&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;include와 extends를 함께 사용하면 강력한 재사용성을 구현할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;dts&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# templates.yml
.build_template:
  stage: build
  script:
    - echo &quot;빌드 시작&quot;

# .gitlab-ci.yml
include:
  - local: templates.yml

my_build:
  extends: .build_template
  variables:
    PROJECT_NAME: &quot;my-project&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;병합 규칙 이해하기&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;extends는 해시(객체)는 병합하지만 배열은&amp;nbsp;&lt;b&gt;완전 교체&lt;/b&gt;합니다:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;vim&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;.base:
  variables:
    VAR1: &quot;base&quot;
  script:
    - echo &quot;base script&quot;

job:
  extends: .base
  variables:
    VAR2: &quot;job&quot;     # VAR1과 VAR2 모두 유지
  script:
    - echo &quot;job script&quot;  # base script는 완전히 교체됨
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. `!reference` 태그: 선택적 참조의&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`!reference` 태그는 GitLab의 최신 기능으로, 다른 작업의 특정 부분만 선택적으로 재사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 사용법&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;vim&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# setup.yml
.setup:
  script:
    - echo &quot;환경 설정&quot;

# .gitlab-ci.yml
include:
  - local: setup.yml

.teardown:
  after_script:
    - echo &quot;정리 작업&quot;

test:
  script:
    - !reference [.setup, script]
    - echo &quot;테스트 실행&quot;
  after_script:
    - !reference [.teardown, after_script]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;변수의 선택적 참조&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전체 변수 그룹이나 특정 변수만 선택해서 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;dts&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;.common_vars:
  variables:
    API_URL: &quot;https://api.example.com&quot;
    DEBUG_MODE: &quot;false&quot;

test_all_vars:
  variables: !reference [.common_vars, variables]
  script:
    - printenv

test_specific_var:
  variables:
    MY_API_URL: !reference [.common_vars, variables, API_URL]
  script:
    - echo $MY_API_URL
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중첩 참조 활용&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최대 10단계까지 중첩된 참조가 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;vim&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;.scripts:
  basic:
    - echo &quot;기본 스크립트&quot;
  extended:
    - !reference [.scripts, basic]
    - echo &quot;확장 스크립트&quot;
  full:
    - !reference [.scripts, extended]
    - echo &quot;전체 스크립트&quot;

complex_job:
  script:
    - !reference [.scripts, full]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실전 활용: 통합 예제&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;세 가지 방법을 조합하여 효율적인 파이프라인을 구성해보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 공통 설정 (앵커 활용)
.common_config: &amp;amp;common_config
  interruptible: true
  retry:
    max: 2
    when:
      - runner_system_failure

# 기본 템플릿 (extends 활용)
.build_template:
  &amp;lt;&amp;lt;: *common_config
  stage: build
  image: node:16
  before_script:
    - npm ci

# 스크립트 조각 (!reference 활용)
.scripts:
  test:
    - npm run test
  lint:
    - npm run lint

# 실제 작업들
build_frontend:
  extends: .build_template
  script:
    - npm run build:frontend

test_and_lint:
  extends: .build_template
  script:
    - !reference [.scripts, test]
    - !reference [.scripts, lint]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IDE 지원 설정&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VS Code에서 `!reference` 태그의 문법 오류를 방지하려면 다음 설정을 추가해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;json&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;// settings.json
{
  &quot;yaml.customTags&quot;: [
    &quot;!reference sequence&quot;
  ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;언제 무엇을 사용할까?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;YAML 앵커를 사용하는 경우&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;같은 파일 내에서 간단한 재사용이 필요할 때&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스크립트 배열을 여러 작업에서 공유할 때&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 YAML 지식을 활용하고 싶을 때&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;extends를 사용하는 경우&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;작업 전체의 구성을 상속받고 싶을 때&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부 파일의 템플릿을 확장하고 싶을 때&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;!reference를 사용하는 경우&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;특정 키의 값만 선택적으로 재사용하고 싶을 때&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부 파일의 일부분만 필요할 때&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GitLab CI/CD YAML 파일 최적화는 단순히 코드를 줄이는 것을 넘어서 유지보수성과 가독성을 크게 향상시킨다. YAML 앵커의 기본적인 재사용부터 `extends` 의 강력한 상속 기능, 그리고 `!reference` 태그의 선택적 참조까지, 각 도구의 특성을 이해하고 적절히 조합하면 효율적이고 관리하기 쉬운 파이프라인을 구축할 수 있다.&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;color: #000000;&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;&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;
&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.gitlab.com/ee/ci/yaml/&quot;&gt;GitLab CI/CD YAML syntax reference&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.gitlab.com/ee/ci/yaml/yaml_optimization.html&quot;&gt;Optimize your YAML files - GitLab Docs&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.gitlab.com/ee/ci/yaml/includes.html&quot;&gt;Include examples - GitLab Docs&lt;/a&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;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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>IaC/CI CD Tool</category>
      <category>CICD</category>
      <category>gitlab</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/460</guid>
      <comments>https://somaz.tistory.com/460#entry460comment</comments>
      <pubDate>Tue, 17 Mar 2026 00:00:52 +0900</pubDate>
    </item>
    <item>
      <title>GCP 데이터베이스 선택 완전 가이드: Cloud SQL vs Spanner vs Firestore vs BigQuery</title>
      <link>https://somaz.tistory.com/459</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현대 애플리케이션의 데이터 요구사항은 그 어느 때보다 복잡하고 다양하다. Google Cloud Platform(GCP)은 이러한 다양한 요구사항을 충족하기 위해 관계형, NoSQL, 분석형 데이터베이스 서비스를 포괄적으로 제공한다. 각 데이터베이스는 고유한 강점과 적용 시나리오를 가지고 있어, 올바른 선택이 애플리케이션의 성능과 비용 효율성을 크게 좌우한다.&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;color: #000000;&quot;&gt;&lt;b&gt;Cloud SQL&lt;/b&gt;은 전통적인 관계형 데이터베이스의 완전 관리형 서비스로, MySQL, PostgreSQL, SQL Server를 지원하며 기존 애플리케이션의 클라우드 마이그레이션에 최적화되어 있다. &lt;b&gt;Cloud Spanner&lt;/b&gt;는 Google이 개발한 혁신적인 글로벌 분산 관계형 데이터베이스로, ACID 트랜잭션과 수평적 확장성을 동시에 제공하는 독특한 위치를 차지한다.&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;color: #000000;&quot;&gt;&lt;b&gt;Firestore&lt;/b&gt;는 서버리스 NoSQL 문서 데이터베이스로, 실시간 동기화와 자동 스케일링을 통해 모바일 및 웹 애플리케이션에 최적화되어 있다. &lt;b&gt;BigQuery&lt;/b&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;color: #000000;&quot;&gt;최근 데이터베이스 기술의 발전과 함께, 각 서비스는 더욱 정교한 기능들을 추가하고 있다. Cloud SQL의 고가용성과 읽기 복제본 최적화, Spanner의 멀티리전 강력한 일관성, Firestore의 오프라인 지원과 실시간 리스너, BigQuery의 실시간 스트리밍과 ML 통합 등이 그 예다.&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;color: #000000;&quot;&gt;이 글에서는 각 데이터베이스의 핵심 원리와 특성을 심층 분석하고, 비용과 성능, 일관성 간의 트레이드오프를 구체적으로 검토한다. 또한 실제 운영 환경에서의 적용 시나리오와 Terraform을 활용한 구현 예제, 그리고 OLTP와 분석 워크로드의 최적화 전략을 함께 제시한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt54n0/dJMcacV5LoC/51IwcPk9hMKxbaoNlZ6VMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt54n0/dJMcacV5LoC/51IwcPk9hMKxbaoNlZ6VMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt54n0/dJMcacV5LoC/51IwcPk9hMKxbaoNlZ6VMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt54n0%2FdJMcacV5LoC%2F51IwcPk9hMKxbaoNlZ6VMK%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터베이스 기초 개념과 분류&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관계형 데이터베이스의 원리&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관계형 데이터베이스는 Edgar F. Codd의 관계형 모델을 기반으로 하며, 데이터를 테이블 형태로 구조화하여 저장한다. ACID(Atomicity, Consistency, Isolation, Durability) 속성을 통해 데이터 무결성을 보장하며, SQL을 통한 복잡한 쿼리와 조인 연산을 지원한다.&lt;/span&gt;&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ACID 속성의 구현 원리&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;원자성(Atomicity)&lt;/b&gt;: 트랜잭션의 모든 연산이 완전히 수행되거나 전혀 수행되지 않음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;일관성(Consistency)&lt;/b&gt;: 트랜잭션 실행 전후에 데이터베이스가 일관된 상태 유지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;격리성(Isolation)&lt;/b&gt;: 동시 실행되는 트랜잭션들이 서로 영향을 주지 않음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;지속성(Durability)&lt;/b&gt;: 커밋된 트랜잭션의 결과가 영구적으로 저장됨&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NoSQL 데이터베이스의 특성&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NoSQL 데이터베이스는 CAP 정리(Consistency, Availability, Partition tolerance)에 따라 설계되며, 대규모 분산 환경에서의 확장성과 성능을 중시한다. 스키마가 유연하고 수평적 확장이 용이하다는 장점이 있다.&lt;/span&gt;&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CAP 정리의 실제 적용&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;일관성(Consistency)&lt;/b&gt;: 모든 노드가 동시에 같은 데이터를 볼 수 있음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;가용성(Availability)&lt;/b&gt;: 시스템이 지속적으로 운영됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;분할 내성(Partition tolerance)&lt;/b&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;분석형 데이터베이스의 구조&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;분석형 데이터베이스는 OLAP(Online Analytical Processing) 워크로드에 최적화되어 있으며, 컬럼 지향 저장과 대용량 데이터 처리를 위한 병렬 처리 엔진을 활용한다.&lt;/span&gt;&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;&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;&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;&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;&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud SQL 심층 분석&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud SQL의 아키텍처와 원리&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud SQL은 Google의 인프라 위에서 실행되는 완전 관리형 관계형 데이터베이스 서비스다. 자동 백업, 패치 관리, 고가용성을 제공하며 기존 애플리케이션과의 호환성을 보장한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고가용성 구성 원리&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud SQL의 고가용성은 동기식 복제를 통해 구현된다. 기본 인스턴스와 대기 인스턴스가 서로 다른 가용 영역에 배치되며, 자동 페일오버를 통해 RTO(Recovery Time Objective) 60초 이하를 달성한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# Cloud SQL MySQL 인스턴스 구성
resource &quot;google_sql_database_instance&quot; &quot;main&quot; {
  name             = &quot;main-instance&quot;
  database_version = &quot;MYSQL_8_0&quot;
  region          = &quot;us-central1&quot;
  
  settings {
    tier = &quot;db-n1-standard-2&quot;
    
    # 고가용성 구성
    availability_type = &quot;REGIONAL&quot;
    
    # 백업 구성
    backup_configuration {
      enabled                        = true
      start_time                    = &quot;02:00&quot;
      point_in_time_recovery_enabled = true
      transaction_log_retention_days = 7
      backup_retention_settings {
        retained_backups = 30
        retention_unit   = &quot;COUNT&quot;
      }
    }
    
    # IP 구성
    ip_configuration {
      ipv4_enabled    = true
      private_network = google_compute_network.private_network.id
      require_ssl     = true
      
      authorized_networks {
        name  = &quot;office-network&quot;
        value = &quot;203.0.113.0/24&quot;
      }
    }
    
    # 데이터베이스 플래그
    database_flags {
      name  = &quot;slow_query_log&quot;
      value = &quot;on&quot;
    }
    
    database_flags {
      name  = &quot;general_log&quot;
      value = &quot;on&quot;
    }
    
    # 디스크 구성
    disk_type    = &quot;PD_SSD&quot;
    disk_size    = 100
    disk_autoresize = true
    disk_autoresize_limit = 500
  }
  
  deletion_protection = true
}

# 읽기 복제본 구성
resource &quot;google_sql_database_instance&quot; &quot;read_replica&quot; {
  name                 = &quot;read-replica&quot;
  master_instance_name = google_sql_database_instance.main.name
  region              = &quot;us-east1&quot;
  database_version     = &quot;MYSQL_8_0&quot;
  
  replica_configuration {
    failover_target = false
  }
  
  settings {
    tier = &quot;db-n1-standard-1&quot;
    
    availability_type = &quot;ZONAL&quot;
    
    ip_configuration {
      ipv4_enabled    = true
      private_network = google_compute_network.private_network.id
      require_ssl     = true
    }
    
    disk_type = &quot;PD_SSD&quot;
    disk_size = 50
  }
}

# 데이터베이스 생성
resource &quot;google_sql_database&quot; &quot;database&quot; {
  name     = &quot;application_db&quot;
  instance = google_sql_database_instance.main.name
  charset  = &quot;utf8mb4&quot;
  collation = &quot;utf8mb4_unicode_ci&quot;
}

# 사용자 생성
resource &quot;google_sql_user&quot; &quot;app_user&quot; {
  name     = &quot;app_user&quot;
  instance = google_sql_database_instance.main.name
  password = var.db_password
  host     = &quot;%&quot;
}

# SSL 인증서 생성
resource &quot;google_sql_ssl_cert&quot; &quot;client_cert&quot; {
  common_name = &quot;client-cert&quot;
  instance    = google_sql_database_instance.main.name
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud SQL 성능 최적화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;연결 풀링과 캐싱 전략&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# Cloud SQL Proxy를 위한 서비스 어카운트
resource &quot;google_service_account&quot; &quot;sql_proxy&quot; {
  account_id   = &quot;sql-proxy&quot;
  display_name = &quot;Cloud SQL Proxy Service Account&quot;
}

# Cloud SQL 클라이언트 권한 부여
resource &quot;google_project_iam_member&quot; &quot;sql_proxy_client&quot; {
  project = var.project_id
  role    = &quot;roles/cloudsql.client&quot;
  member  = &quot;serviceAccount:${google_service_account.sql_proxy.email}&quot;
}

# GKE에서 Cloud SQL Proxy 사용
resource &quot;kubernetes_deployment&quot; &quot;app&quot; {
  metadata {
    name = &quot;web-app&quot;
  }
  
  spec {
    replicas = 3
    
    selector {
      match_labels = {
        app = &quot;web-app&quot;
      }
    }
    
    template {
      metadata {
        labels = {
          app = &quot;web-app&quot;
        }
      }
      
      spec {
        service_account_name = google_service_account.sql_proxy.email
        
        container {
          name  = &quot;web-app&quot;
          image = &quot;gcr.io/project/web-app:latest&quot;
          
          env {
            name  = &quot;DB_HOST&quot;
            value = &quot;127.0.0.1&quot;
          }
          
          env {
            name  = &quot;DB_PORT&quot;
            value = &quot;3306&quot;
          }
          
          env {
            name = &quot;DB_PASSWORD&quot;
            value_from {
              secret_key_ref {
                name = &quot;db-credentials&quot;
                key  = &quot;password&quot;
              }
            }
          }
        }
        
        # Cloud SQL Proxy 사이드카
        container {
          name  = &quot;cloudsql-proxy&quot;
          image = &quot;gcr.io/cloudsql-docker/gce-proxy:1.33.2&quot;
          
          command = [
            &quot;/cloud_sql_proxy&quot;,
            &quot;-instances=${google_sql_database_instance.main.connection_name}=tcp:3306&quot;
          ]
          
          security_context {
            run_as_non_root = true
          }
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Spanner 혁신적 아키텍처&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spanner의 글로벌 분산 원리&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Spanner는 Google의 TrueTime API를 활용하여 글로벌 분산 환경에서 강력한 일관성을 제공하는 혁신적인 데이터베이스다. 전통적인 CAP 정리의 한계를 넘어서는 독특한 아키텍처를 가지고 있다.&lt;/span&gt;&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;&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TrueTime과 외부 일관성&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TrueTime은 GPS와 원자시계를 활용한 글로벌 시간 동기화 시스템으로, 각 트랜잭션에 글로벌하게 유일한 타임스탬프를 할당한다. 이를 통해 외부 일관성(External Consistency)을 보장한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# Cloud Spanner 인스턴스 구성
resource &quot;google_spanner_instance&quot; &quot;main&quot; {
  config       = &quot;regional-us-central1&quot;
  display_name = &quot;Main Instance&quot;
  name         = &quot;main-instance&quot;
  num_nodes    = 3
  
  labels = {
    environment = &quot;production&quot;
    team       = &quot;backend&quot;
  }
}

# Spanner 데이터베이스 생성
resource &quot;google_spanner_database&quot; &quot;database&quot; {
  instance = google_spanner_instance.main.name
  name     = &quot;application_db&quot;
  
  ddl = [
    &quot;CREATE TABLE Users (UserId STRING(36) NOT NULL, Email STRING(MAX), Name STRING(MAX), CreatedAt TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)) PRIMARY KEY (UserId)&quot;,
    &quot;CREATE TABLE Orders (OrderId STRING(36) NOT NULL, UserId STRING(36) NOT NULL, Amount NUMERIC NOT NULL, Status STRING(20) NOT NULL, CreatedAt TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)) PRIMARY KEY (OrderId)&quot;,
    &quot;CREATE INDEX UserEmailIndex ON Users(Email)&quot;,
    &quot;CREATE INDEX UserOrdersIndex ON Orders(UserId, CreatedAt DESC)&quot;
  ]
  
  deletion_protection = true
}

# 멀티리전 구성
resource &quot;google_spanner_instance&quot; &quot;multi_region&quot; {
  config       = &quot;nam-eur-asia1&quot;  # 북미-유럽-아시아 멀티리전
  display_name = &quot;Multi-Region Instance&quot;
  name         = &quot;multi-region-instance&quot;
  num_nodes    = 9  # 각 리전당 3노드
  
  labels = {
    environment = &quot;production&quot;
    scope      = &quot;global&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spanner의 스키마 설계 최적화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핫스팟 방지를 위한 키 설계&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spanner에서는 순차적인 키로 인한 핫스팟을 방지하기 위해 키 설계가 중요하다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;-- 잘못된 설계 (순차적 키로 인한 핫스팟)
CREATE TABLE Orders (
  OrderId INT64 NOT NULL,  -- 자동 증가 키는 핫스팟 유발
  UserId STRING(36) NOT NULL,
  Amount NUMERIC NOT NULL,
  CreatedAt TIMESTAMP NOT NULL
) PRIMARY KEY (OrderId);

-- 올바른 설계 (UUID 또는 해시 기반 키)
CREATE TABLE Orders (
  OrderId STRING(36) NOT NULL,  -- UUID 사용
  UserId STRING(36) NOT NULL,
  Amount NUMERIC NOT NULL,
  CreatedAt TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)
) PRIMARY KEY (OrderId);

-- 또는 복합키를 통한 분산
CREATE TABLE UserOrders (
  UserId STRING(36) NOT NULL,
  OrderId STRING(36) NOT NULL,
  Amount NUMERIC NOT NULL,
  CreatedAt TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)
) PRIMARY KEY (UserId, OrderId);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Firestore 실시간 NoSQL 데이터베이스&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Firestore의 문서 기반 데이터 모델&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Firestore는 문서-컬렉션 계층 구조를 사용하는 NoSQL 데이터베이스로, 실시간 동기화와 오프라인 지원을 제공한다. 각 문서는 키-값 쌍으로 구성되며, 하위 컬렉션을 가질 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# Firestore 데이터베이스 생성
resource &quot;google_firestore_database&quot; &quot;database&quot; {
  project     = var.project_id
  name        = &quot;(default)&quot;
  location_id = &quot;us-central&quot;
  type        = &quot;FIRESTORE_NATIVE&quot;
  
  concurrency_mode = &quot;OPTIMISTIC&quot;
  app_engine_integration_mode = &quot;DISABLED&quot;
}

# 복합 인덱스 생성
resource &quot;google_firestore_index&quot; &quot;user_orders_index&quot; {
  project = var.project_id
  
  collection = &quot;orders&quot;
  
  fields {
    field_path = &quot;userId&quot;
    order      = &quot;ASCENDING&quot;
  }
  
  fields {
    field_path = &quot;createdAt&quot;
    order      = &quot;DESCENDING&quot;
  }
  
  fields {
    field_path = &quot;status&quot;
    order      = &quot;ASCENDING&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Firestore 보안 규칙&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;groovy&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;// Firestore 보안 규칙 예제
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // 사용자 프로필 접근 제어
    match /users/{userId} {
      allow read, write: if request.auth != null &amp;amp;&amp;amp; request.auth.uid == userId;
    }
    
    // 주문 정보 접근 제어
    match /orders/{orderId} {
      allow read, write: if request.auth != null 
        &amp;amp;&amp;amp; request.auth.uid == resource.data.userId;
      allow create: if request.auth != null 
        &amp;amp;&amp;amp; request.auth.uid == request.resource.data.userId;
    }
    
    // 공개 상품 정보
    match /products/{productId} {
      allow read: if true;
      allow write: if request.auth != null 
        &amp;amp;&amp;amp; 'admin' in request.auth.token.roles;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BigQuery 대규모 분석 플랫폼&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BigQuery의 컬럼 지향 저장 구조&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BigQuery는 Dremel 기술을 기반으로 한 완전 관리형 데이터 웨어하우스로, 컬럼 지향 저장과 대규모 병렬 처리를 통해 페타바이트 규모의 데이터 분석을 지원한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# BigQuery 데이터셋 생성
resource &quot;google_bigquery_dataset&quot; &quot;analytics&quot; {
  dataset_id  = &quot;analytics&quot;
  description = &quot;Analytics data warehouse&quot;
  location    = &quot;US&quot;
  
  default_table_expiration_ms = 3600000  # 1시간
  
  access {
    role          = &quot;OWNER&quot;
    user_by_email = google_service_account.bigquery_admin.email
  }
  
  access {
    role   = &quot;READER&quot;
    domain = &quot;example.com&quot;
  }
  
  labels = {
    environment = &quot;production&quot;
    team       = &quot;analytics&quot;
  }
}

# 파티션 테이블 생성
resource &quot;google_bigquery_table&quot; &quot;user_events&quot; {
  dataset_id = google_bigquery_dataset.analytics.dataset_id
  table_id   = &quot;user_events&quot;
  
  description = &quot;User events partitioned by date&quot;
  
  time_partitioning {
    type                     = &quot;DAY&quot;
    field                   = &quot;event_timestamp&quot;
    require_partition_filter = true
    expiration_ms           = 5184000000  # 60일
  }
  
  clustering = [&quot;user_id&quot;, &quot;event_type&quot;]
  
  schema = jsonencode([
    {
      name = &quot;event_id&quot;
      type = &quot;STRING&quot;
      mode = &quot;REQUIRED&quot;
    },
    {
      name = &quot;user_id&quot;
      type = &quot;STRING&quot;
      mode = &quot;REQUIRED&quot;
    },
    {
      name = &quot;event_type&quot;
      type = &quot;STRING&quot;
      mode = &quot;REQUIRED&quot;
    },
    {
      name = &quot;event_timestamp&quot;
      type = &quot;TIMESTAMP&quot;
      mode = &quot;REQUIRED&quot;
    },
    {
      name = &quot;properties&quot;
      type = &quot;JSON&quot;
      mode = &quot;NULLABLE&quot;
    }
  ])
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터베이스 선택 기준 및 비교 분석&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;워크로드별 데이터베이스 선택 매트릭스&lt;/span&gt;&lt;/h3&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud SQL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Spanner&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Firestore&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BigQuery&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;데이터 모델&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관계형 (테이블)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관계형 (스키마)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문서 기반 NoSQL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컬럼 지향 분석형&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;확장성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수직적 (최대 96vCPU)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수평적 (글로벌)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 수평적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;페타바이트 급&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;일관성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ACID 강력한 일관성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ACID 외부 일관성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최종 일관성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배치 일관성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;지연시간&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;lt; 10ms&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;lt; 10ms (리전 내)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;lt; 100ms&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;초-분 단위&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;쿼리 언어&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SQL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SQL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NoSQL 쿼리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SQL (분석 최적화)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실시간 기능&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트리거/복제&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;변경 스트림&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실시간 리스너&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스트리밍 삽입&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;글로벌 분산&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;읽기 복제본&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네이티브 지원&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;멀티리전 복제&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;글로벌 가용&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;오프라인 지원&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네이티브 지원&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;없음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;트랜잭션&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ACID&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ACID 분산&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배치&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;월 비용 (중간 규모)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$200-800&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$900-3000&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$100-500&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$100-1000&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;적용 시나리오&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 앱 마이그레이션&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;글로벌 OLTP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모바일/웹 앱&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 분석&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능과 비용 트레이드오프 분석&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처리량과 지연시간 비교&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# 성능 테스트를 위한 리소스 구성
locals {
  performance_scenarios = {
    oltp_high_throughput = {
      database_type = &quot;spanner&quot;
      config = {
        instance_config = &quot;regional-us-central1&quot;
        node_count     = 3
        expected_qps   = 10000
      }
    }
    
    oltp_cost_optimized = {
      database_type = &quot;cloud_sql&quot;
      config = {
        tier           = &quot;db-n1-standard-4&quot;
        replica_count  = 2
        expected_qps   = 2000
      }
    }
    
    mobile_app_backend = {
      database_type = &quot;firestore&quot;
      config = {
        location     = &quot;us-central&quot;
        read_units   = 100000
        write_units  = 50000
      }
    }
    
    analytics_workload = {
      database_type = &quot;bigquery&quot;
      config = {
        slot_capacity    = 500
        storage_tb      = 10
        query_frequency = &quot;hourly&quot;
      }
    }
  }
}

# 비용 계산 모듈
module &quot;cost_calculator&quot; {
  source = &quot;./modules/database-cost-calculator&quot;
  
  for_each = local.performance_scenarios
  
  scenario_name = each.key
  database_type = each.value.database_type
  config       = each.value.config
  
  region = var.region
  usage_pattern = {
    hours_per_day = 24
    days_per_month = 30
  }
}

output &quot;cost_analysis&quot; {
  value = {
    for scenario, config in local.performance_scenarios :
    scenario =&amp;gt; {
      database_type = config.database_type
      estimated_monthly_cost = module.cost_calculator[scenario].monthly_cost
      performance_tier = module.cost_calculator[scenario].performance_tier
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실시간 분석과 OLTP 워크로드 최적화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하이브리드 아키텍처 구성&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# OLTP + 실시간 분석 하이브리드 아키텍처
resource &quot;google_sql_database_instance&quot; &quot;oltp_primary&quot; {
  name             = &quot;oltp-primary&quot;
  database_version = &quot;POSTGRES_14&quot;
  region          = &quot;us-central1&quot;
  
  settings {
    tier = &quot;db-custom-4-16384&quot;  # 4 vCPU, 16GB RAM
    
    availability_type = &quot;REGIONAL&quot;
    
    backup_configuration {
      enabled = true
      start_time = &quot;02:00&quot;
      point_in_time_recovery_enabled = true
    }
    
    # 실시간 복제를 위한 설정
    database_flags {
      name  = &quot;cloudsql.logical_decoding&quot;
      value = &quot;on&quot;
    }
    
    database_flags {
      name  = &quot;max_replication_slots&quot;
      value = &quot;10&quot;
    }
  }
}

# 실시간 CDC를 위한 Dataflow 작업
resource &quot;google_dataflow_job&quot; &quot;cdc_to_bigquery&quot; {
  name              = &quot;postgres-cdc-to-bigquery&quot;
  template_gcs_path = &quot;gs://dataflow-templates/latest/Cloud_SQL_to_BigQuery_CDC&quot;
  temp_gcs_location = &quot;gs://${google_storage_bucket.temp.name}/temp&quot;
  
  parameters = {
    inputSubscription    = google_pubsub_subscription.cdc_subscription.id
    outputTableSpec     = &quot;${var.project_id}:${google_bigquery_dataset.realtime.dataset_id}.transactions&quot;
    outputDeadletterTable = &quot;${var.project_id}:${google_bigquery_dataset.realtime.dataset_id}.failed_records&quot;
  }
  
  depends_on = [google_sql_database_instance.oltp_primary]
}

# 실시간 대시보드를 위한 구체화된 뷰
resource &quot;google_bigquery_table&quot; &quot;realtime_metrics&quot; {
  dataset_id = google_bigquery_dataset.realtime.dataset_id
  table_id   = &quot;realtime_metrics&quot;
  
  description = &quot;Real-time business metrics&quot;
  
  materialized_view {
    query = &amp;lt;&amp;lt;-SQL
      SELECT
        DATETIME_TRUNC(transaction_timestamp, MINUTE) as minute,
        COUNT(*) as transaction_count,
        SUM(amount) as total_amount,
        AVG(amount) as avg_amount,
        COUNT(DISTINCT user_id) as unique_users
      FROM `${var.project_id}.${google_bigquery_dataset.realtime.dataset_id}.transactions`
      WHERE transaction_timestamp &amp;gt;= DATETIME_SUB(CURRENT_DATETIME(), INTERVAL 1 HOUR)
      GROUP BY minute
      ORDER BY minute DESC
    SQL
    
    enable_refresh = true
    refresh_interval_ms = 60000  # 1분마다 갱신
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 튜닝과 최적화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud SQL 성능 튜닝&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;-- Cloud SQL PostgreSQL 성능 최적화 예제

-- 1. 인덱스 최적화
CREATE INDEX CONCURRENTLY idx_orders_user_created 
ON orders (user_id, created_at DESC) 
WHERE status = 'active';

-- 2. 파티션 테이블 구성
CREATE TABLE orders_partitioned (
    order_id UUID PRIMARY KEY,
    user_id UUID NOT NULL,
    amount DECIMAL(10,2) NOT NULL,
    created_at TIMESTAMP NOT NULL,
    status VARCHAR(20) NOT NULL
) PARTITION BY RANGE (created_at);

-- 월별 파티션 생성
CREATE TABLE orders_2024_01 PARTITION OF orders_partitioned
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');

-- 3. 구체화된 뷰 활용
CREATE MATERIALIZED VIEW user_order_summary AS
SELECT 
    user_id,
    COUNT(*) as total_orders,
    SUM(amount) as total_amount,
    AVG(amount) as avg_amount,
    MAX(created_at) as last_order_date
FROM orders 
GROUP BY user_id;

-- 인덱스 추가
CREATE UNIQUE INDEX ON user_order_summary (user_id);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spanner 쿼리 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;sql&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;-- Spanner 성능 최적화 예제

-- 1. 인덱스 설계 (핫스팟 방지)
CREATE INDEX UserOrdersByTimestamp ON Orders(UserId, CreatedAt DESC);

-- 2. 인터리빙 테이블 활용
CREATE TABLE OrderItems (
    OrderId STRING(36) NOT NULL,
    ItemId STRING(36) NOT NULL,
    ProductId STRING(36) NOT NULL,
    Quantity INT64 NOT NULL,
    Price NUMERIC NOT NULL
) PRIMARY KEY (OrderId, ItemId),
  INTERLEAVE IN PARENT Orders ON DELETE CASCADE;

-- 3. 배치 쿼리 최적화
-- 올바른 방식 (인덱스 활용)
SELECT * FROM Orders@{FORCE_INDEX=UserOrdersByTimestamp} 
WHERE UserId = @user_id AND CreatedAt &amp;gt; @start_date;

-- 4. 뮤테이션 배칭
-- 단일 뮤테이션 대신 배치 처리
INSERT INTO Orders (OrderId, UserId, Amount, CreatedAt)
VALUES 
    ('order1', 'user1', 100.00, PENDING_COMMIT_TIMESTAMP()),
    ('order2', 'user2', 200.00, PENDING_COMMIT_TIMESTAMP()),
    ('order3', 'user3', 150.00, PENDING_COMMIT_TIMESTAMP());
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BigQuery 성능 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;sql&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;-- BigQuery 성능 최적화 예제

-- 1. 파티션과 클러스터링 활용
SELECT 
    user_id,
    COUNT(*) as event_count,
    SUM(revenue) as total_revenue
FROM `project.dataset.user_events`
WHERE _PARTITIONDATE = '2024-01-15'  -- 파티션 프루닝
  AND event_type = 'purchase'        -- 클러스터링 활용
GROUP BY user_id;

-- 2. 윈도우 함수 최적화
SELECT 
    user_id,
    event_timestamp,
    revenue,
    SUM(revenue) OVER (
        PARTITION BY user_id 
        ORDER BY event_timestamp 
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) as running_total
FROM `project.dataset.user_events`
WHERE _PARTITIONDATE BETWEEN '2024-01-01' AND '2024-01-31';

-- 3. 어근사 집계 함수 활용 (대용량 데이터)
SELECT 
    event_type,
    APPROX_COUNT_DISTINCT(user_id) as unique_users,
    APPROX_QUANTILES(revenue, 100)[OFFSET(50)] as median_revenue
FROM `project.dataset.user_events`
WHERE _PARTITIONDATE &amp;gt;= '2024-01-01'
GROUP BY event_type;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터베이스 마이그레이션 전략&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud SQL 마이그레이션&lt;/span&gt;&lt;/h4&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Database Migration Service 활용&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# Database Migration Service 구성
resource &quot;google_database_migration_service_connection_profile&quot; &quot;source&quot; {
  location              = &quot;us-central1&quot;
  connection_profile_id = &quot;source-mysql&quot;
  display_name         = &quot;Source MySQL Database&quot;
  
  mysql {
    host     = var.source_db_host
    port     = 3306
    username = var.source_db_user
    password = var.source_db_password
    
    ssl {
      ca_certificate = file(&quot;./ssl/ca-cert.pem&quot;)
    }
  }
}

resource &quot;google_database_migration_service_connection_profile&quot; &quot;destination&quot; {
  location              = &quot;us-central1&quot;
  connection_profile_id = &quot;destination-cloudsql&quot;
  display_name         = &quot;Destination Cloud SQL&quot;
  
  cloudsql {
    cloud_sql_id = google_sql_database_instance.target.connection_name
  }
}

resource &quot;google_database_migration_service_migration_job&quot; &quot;default&quot; {
  location         = &quot;us-central1&quot;
  migration_job_id = &quot;mysql-migration&quot;
  display_name     = &quot;MySQL to Cloud SQL Migration&quot;
  
  source          = google_database_migration_service_connection_profile.source.name
  destination     = google_database_migration_service_connection_profile.destination.name
  
  type = &quot;CONTINUOUS&quot;
  
  vpc_peering_connectivity {
    vpc = google_compute_network.migration_vpc.id
  }
  
  dump_path = &quot;gs://${google_storage_bucket.migration.name}/dump&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spanner 스키마 마이그레이션&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# Spanner 마이그레이션을 위한 Harbourbridge 구성
resource &quot;google_cloudbuild_trigger&quot; &quot;spanner_migration&quot; {
  name = &quot;spanner-migration&quot;
  
  github {
    owner = var.github_owner
    name  = var.github_repo
    
    push {
      branch = &quot;^main$&quot;
    }
  }
  
  build {
    step {
      name = &quot;gcr.io/cloud-spanner-pg-adapter/harbourbridge&quot;
      args = [
        &quot;-source=mysql&quot;,
        &quot;-source-profile=host=${var.source_host},user=${var.source_user},password=${var.source_password}&quot;,
        &quot;-target-profile=projects/${var.project_id}/instances/${google_spanner_instance.main.name}/databases/${google_spanner_database.database.name}&quot;,
        &quot;-schema-file=gs://${google_storage_bucket.migration.name}/schema.json&quot;
      ]
    }
    
    step {
      name = &quot;gcr.io/google.com/cloudsdktool/cloud-sdk&quot;
      args = [
        &quot;gcloud&quot;, &quot;spanner&quot;, &quot;databases&quot;, &quot;ddl&quot;, &quot;update&quot;,
        google_spanner_database.database.name,
        &quot;--instance=${google_spanner_instance.main.name}&quot;,
        &quot;--ddl-file=schema.sql&quot;
      ]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안과 규정 준수&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 암호화와 키 관리&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# Cloud KMS 키 관리
resource &quot;google_kms_key_ring&quot; &quot;database_keyring&quot; {
  name     = &quot;database-keyring&quot;
  location = &quot;global&quot;
}

resource &quot;google_kms_crypto_key&quot; &quot;database_key&quot; {
  name     = &quot;database-encryption-key&quot;
  key_ring = google_kms_key_ring.database_keyring.id
  
  rotation_period = &quot;2592000s&quot;  # 30일
  
  version_template {
    algorithm = &quot;GOOGLE_SYMMETRIC_ENCRYPTION&quot;
  }
}

# CMEK를 사용하는 Cloud SQL
resource &quot;google_sql_database_instance&quot; &quot;encrypted&quot; {
  name             = &quot;encrypted-instance&quot;
  database_version = &quot;POSTGRES_14&quot;
  region          = &quot;us-central1&quot;
  
  encryption_key_name = google_kms_crypto_key.database_key.id
  
  settings {
    tier = &quot;db-n1-standard-2&quot;
    
    ip_configuration {
      ipv4_enabled                                  = false
      private_network                              = google_compute_network.private_network.id
      enable_private_path_for_google_cloud_services = true
    }
  }
  
  depends_on = [google_kms_crypto_key_iam_member.sql_kms_binding]
}

# BigQuery 테이블 암호화
resource &quot;google_bigquery_table&quot; &quot;encrypted_table&quot; {
  dataset_id = google_bigquery_dataset.analytics.dataset_id
  table_id   = &quot;encrypted_user_data&quot;
  
  encryption_configuration {
    kms_key_name = google_kms_crypto_key.database_key.id
  }
  
  schema = jsonencode([
    {
      name = &quot;user_id&quot;
      type = &quot;STRING&quot;
      mode = &quot;REQUIRED&quot;
    },
    {
      name = &quot;encrypted_data&quot;
      type = &quot;BYTES&quot;
      mode = &quot;REQUIRED&quot;
    }
  ])
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;감사 로깅과 모니터링&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# Cloud Audit Logs 구성
resource &quot;google_project_iam_audit_config&quot; &quot;database_audit&quot; {
  project = var.project_id
  
  audit_log_config {
    log_type = &quot;ADMIN_READ&quot;
  }
  
  audit_log_config {
    log_type = &quot;DATA_READ&quot;
  }
  
  audit_log_config {
    log_type = &quot;DATA_WRITE&quot;
  }
  
  service = &quot;cloudsql.googleapis.com&quot;
}

resource &quot;google_project_iam_audit_config&quot; &quot;spanner_audit&quot; {
  project = var.project_id
  
  audit_log_config {
    log_type = &quot;ADMIN_READ&quot;
  }
  
  audit_log_config {
    log_type = &quot;DATA_READ&quot;
  }
  
  audit_log_config {
    log_type = &quot;DATA_WRITE&quot;
  }
  
  service = &quot;spanner.googleapis.com&quot;
}

# 로그 기반 메트릭
resource &quot;google_logging_metric&quot; &quot;database_access_metric&quot; {
  name   = &quot;database_access_count&quot;
  filter = &quot;resource.type=\&quot;cloudsql_database\&quot; AND protoPayload.methodName=\&quot;cloudsql.instances.query\&quot;&quot;
  
  metric_descriptor {
    metric_kind = &quot;DELTA&quot;
    value_type  = &quot;INT64&quot;
    display_name = &quot;Database Access Count&quot;
  }
  
  label_extractors = {
    &quot;user&quot; = &quot;EXTRACT(protoPayload.authenticationInfo.principalEmail)&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터베이스 모니터링과 운영&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 메트릭과 알림&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# 종합적인 데이터베이스 모니터링 대시보드
resource &quot;google_monitoring_dashboard&quot; &quot;database_overview&quot; {
  dashboard_json = jsonencode({
    displayName = &quot;Database Performance Overview&quot;
    
    gridLayout = {
      widgets = [
        {
          title = &quot;Cloud SQL CPU Utilization&quot;
          xyChart = {
            dataSets = [{
              timeSeriesQuery = {
                timeSeriesFilter = {
                  filter = &quot;resource.type=\&quot;cloudsql_database\&quot;&quot;
                  aggregation = {
                    alignmentPeriod = &quot;60s&quot;
                    perSeriesAligner = &quot;ALIGN_MEAN&quot;
                  }
                }
              }
            }]
            yAxis = { scale = &quot;LINEAR&quot; }
          }
        },
        {
          title = &quot;Spanner Query Latency&quot;
          xyChart = {
            dataSets = [{
              timeSeriesQuery = {
                timeSeriesFilter = {
                  filter = &quot;resource.type=\&quot;spanner_instance\&quot;&quot;
                  aggregation = {
                    alignmentPeriod = &quot;60s&quot;
                    perSeriesAligner = &quot;ALIGN_MEAN&quot;
                  }
                }
              }
            }]
          }
        },
        {
          title = &quot;Firestore Read/Write Operations&quot;
          xyChart = {
            dataSets = [{
              timeSeriesQuery = {
                timeSeriesFilter = {
                  filter = &quot;resource.type=\&quot;firestore_database\&quot;&quot;
                  aggregation = {
                    alignmentPeriod = &quot;60s&quot;
                    perSeriesAligner = &quot;ALIGN_RATE&quot;
                  }
                }
              }
            }]
          }
        },
        {
          title = &quot;BigQuery Slot Utilization&quot;
          xyChart = {
            dataSets = [{
              timeSeriesQuery = {
                timeSeriesFilter = {
                  filter = &quot;resource.type=\&quot;bigquery_project\&quot;&quot;
                  aggregation = {
                    alignmentPeriod = &quot;300s&quot;
                    perSeriesAligner = &quot;ALIGN_MEAN&quot;
                  }
                }
              }
            }]
          }
        }
      ]
    }
  })
}

# SLO 기반 알림 정책
resource &quot;google_monitoring_slo&quot; &quot;database_availability&quot; {
  service      = google_monitoring_service.database_service.service_id
  display_name = &quot;Database Availability SLO&quot;
  
  request_based_sli {
    good_total_ratio {
      total_service_filter = &quot;resource.type=\&quot;cloudsql_database\&quot;&quot;
      good_service_filter  = &quot;resource.type=\&quot;cloudsql_database\&quot; AND metric.type=\&quot;cloudsql.googleapis.com/database/up\&quot;&quot;
    }
  }
  
  goal {
    performance_goal = 0.995  # 99.5% 가용성
    rolling_period   = &quot;2592000s&quot;  # 30일
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동화된 백업과 복구&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# 크로스 리전 백업 전략
resource &quot;google_sql_backup_run&quot; &quot;automated_backup&quot; {
  instance = google_sql_database_instance.main.name
  
  description = &quot;Automated daily backup&quot;
  type        = &quot;ON_DEMAND&quot;
  location    = &quot;us-east1&quot;  # 다른 리전에 백업
}

# Spanner 백업 자동화
resource &quot;google_spanner_backup&quot; &quot;automated_backup&quot; {
  instance    = google_spanner_instance.main.name
  database    = google_spanner_database.database.name
  backup_id   = &quot;auto-backup-${formatdate(&quot;YYYY-MM-DD&quot;, timestamp())}&quot;
  expire_time = timeadd(timestamp(), &quot;2160h&quot;)  # 90일 후 만료
}

# Firestore 백업 자동화
resource &quot;google_cloud_scheduler_job&quot; &quot;firestore_backup&quot; {
  name      = &quot;firestore-backup&quot;
  schedule  = &quot;0 2 * * *&quot;  # 매일 오전 2시
  time_zone = &quot;UTC&quot;
  
  http_target {
    http_method = &quot;POST&quot;
    uri         = &quot;https://firestore.googleapis.com/v1/projects/${var.project_id}/databases/(default):exportDocuments&quot;
    
    headers = {
      &quot;Content-Type&quot; = &quot;application/json&quot;
    }
    
    body = base64encode(jsonencode({
      outputUriPrefix = &quot;gs://${google_storage_bucket.backups.name}/firestore-backup&quot;
    }))
    
    oauth_token {
      service_account_email = google_service_account.backup_service.email
    }
  }
}

# BigQuery 테이블 백업 스케줄링
resource &quot;google_bigquery_data_transfer_config&quot; &quot;table_backup&quot; {
  display_name   = &quot;BigQuery Table Backup&quot;
  location       = &quot;us&quot;
  data_source_id = &quot;scheduled_query&quot;
  schedule       = &quot;every day 03:00&quot;
  
  destination_dataset_id = google_bigquery_dataset.backup.dataset_id
  
  params = {
    query = &quot;CREATE OR REPLACE TABLE `${var.project_id}.${google_bigquery_dataset.backup.dataset_id}.user_events_backup` AS SELECT * FROM `${var.project_id}.${google_bigquery_dataset.analytics.dataset_id}.user_events`&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GCP의 데이터베이스 서비스들은 각각 독특한 강점과 적용 영역을 가지고 있어, 애플리케이션의 요구사항에 따른 신중한 선택이 필요하다. Cloud SQL은 기존 관계형 데이터베이스 워크로드의 클라우드 마이그레이션에 최적화되어 있으며, 완전 관리형 서비스의 편리함과 익숙한 SQL 인터페이스를 제공한다.&lt;/span&gt;&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;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Spanner는 글로벌 분산 애플리케이션에서 ACID 트랜잭션과 수평적 확장성을 동시에 요구하는 까다로운 요구사항을 해결하는 혁신적인 솔루션이다. TrueTime을 통한 외부 일관성 보장은 전통적인 분산 데이터베이스의 한계를 뛰어넘는 독특한 가치를 제공한다.&lt;/span&gt;&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;&lt;span style=&quot;color: #000000;&quot;&gt;Firestore는 모바일과 웹 애플리케이션의 실시간 협업과 오프라인 지원 요구사항에 특화되어 있으며, 서버리스 아키텍처와 자동 스케일링을 통해 개발 생산성을 크게 향상시킨다. BigQuery는 페타바이트 규모의 분석 워크로드에서 탁월한 성능을 보여주며, 머신러닝 통합을 통해 고급 분석 기능을 제공한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 선택 기준&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;워크로드 특성&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: OLTP에는 Cloud SQL이나 Spanner를, 실시간 협업에는 Firestore를, 분석 워크로드에는 BigQuery를 선택하는 것이 기본 원칙이다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;확장성 요구사항&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: 수직적 확장으로 충분하다면 Cloud SQL을, 글로벌 수평적 확장이 필요하다면 Spanner를, 자동 스케일링이 중요하다면 Firestore를 고려해야 한다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;일관성 요구사항&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: 강력한 일관성이 필요한 금융 애플리케이션에는 Spanner를, 최종 일관성으로 충분한 소셜 애플리케이션에는 Firestore가 적합하다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비용 최적화&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: 예측 가능한 워크로드에는 Cloud SQL이, 가변적인 트래픽에는 Firestore나 BigQuery의 온디맨드 모델이 경제적이다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;운영 복잡성&lt;/b&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&gt;&lt;/li&gt;
&lt;/ul&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;적절한 데이터베이스 선택과 최적화는 애플리케이션의 성능, 확장성, 그리고 운영 효율성을 결정하는 핵심 요소다. 이 가이드에서 제시한 비교 분석과 최적화 전략을 바탕으로, 각 조직의 요구사항에 가장 적합한 데이터베이스 아키텍처를 구축하시기 바란다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/sql/docs&quot;&gt;Cloud SQL Documentation&lt;/a&gt;&amp;nbsp;- 완전 관리형 관계형 데이터베이스 서비스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/spanner/docs&quot;&gt;Cloud Spanner Documentation&lt;/a&gt;&amp;nbsp;- 글로벌 분산 관계형 데이터베이스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/firestore/docs&quot;&gt;Firestore Documentation&lt;/a&gt;&amp;nbsp;- NoSQL 문서 데이터베이스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/bigquery/docs&quot;&gt;BigQuery Documentation&lt;/a&gt;&amp;nbsp;- 서버리스 데이터 웨어하우스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/database-migration/docs&quot;&gt;Database Migration Service&lt;/a&gt;&amp;nbsp;- 데이터베이스 마이그레이션 도구&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/database-design-patterns&quot;&gt;Database Design Patterns&lt;/a&gt;&amp;nbsp;- 데이터베이스 설계 패턴&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/architectures-for-high-availability-multi-region&quot;&gt;Multi-region Architecture&lt;/a&gt;&amp;nbsp;- 멀티리전 고가용성 아키텍처&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/data-lifecycle-cloud-platform&quot;&gt;Data Lifecycle Management&lt;/a&gt;&amp;nbsp;- 데이터 생명주기 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/microservices-architecture-on-gcp&quot;&gt;Microservices Data Architecture&lt;/a&gt;&amp;nbsp;- 마이크로서비스 데이터 아키텍처&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/real-time-stream-processing&quot;&gt;Real-time Analytics Architecture&lt;/a&gt;&amp;nbsp;- 실시간 분석 아키텍처&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/sql/docs/mysql/best-practices&quot;&gt;Cloud SQL Best Practices&lt;/a&gt;&amp;nbsp;- Cloud SQL 최적화 가이드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/spanner/docs/schema-design&quot;&gt;Spanner Schema Design&lt;/a&gt;&amp;nbsp;- Spanner 스키마 설계 가이드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://firebase.google.com/docs/firestore/security/get-started&quot;&gt;Firestore Security Rules&lt;/a&gt;&amp;nbsp;- Firestore 보안 규칙&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/bigquery/docs/best-practices-performance-overview&quot;&gt;BigQuery Query Optimization&lt;/a&gt;&amp;nbsp;- BigQuery 쿼리 최적화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/monitoring/api/metrics_gcp&quot;&gt;Database Performance Monitoring&lt;/a&gt;&amp;nbsp;- 데이터베이스 성능 모니터링&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/sql/pricing&quot;&gt;Cloud SQL Pricing&lt;/a&gt;&amp;nbsp;- Cloud SQL 요금 정보&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/spanner/pricing&quot;&gt;Spanner Pricing&lt;/a&gt;&amp;nbsp;- Spanner 요금 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://firebase.google.com/pricing&quot;&gt;Firestore Pricing&lt;/a&gt;&amp;nbsp;- Firestore 요금 정보&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/bigquery/pricing&quot;&gt;BigQuery Pricing&lt;/a&gt;&amp;nbsp;- BigQuery 요금 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/docs/enterprise/best-practices-for-enterprise-organizations&quot;&gt;Cost Optimization Best Practices&lt;/a&gt;&amp;nbsp;- 비용 최적화 방법&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/framework/cost-optimization&quot;&gt;Database Resource Planning&lt;/a&gt;&amp;nbsp;- 리소스 계획 및 비용 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/sql/docs/mysql/security&quot;&gt;Cloud SQL Security&lt;/a&gt;&amp;nbsp;- Cloud SQL 보안 가이드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/spanner/docs/iam&quot;&gt;Spanner IAM and Security&lt;/a&gt;&amp;nbsp;- Spanner 보안 및 접근 제어&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://firebase.google.com/docs/firestore/security/rules-conditions&quot;&gt;Firestore Security Best Practices&lt;/a&gt;&amp;nbsp;- Firestore 보안 모범 사례&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/bigquery/docs/data-governance&quot;&gt;BigQuery Data Governance&lt;/a&gt;&amp;nbsp;- BigQuery 데이터 거버넌스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/docs/security/encryption-at-rest&quot;&gt;Database Encryption&lt;/a&gt;&amp;nbsp;- 데이터베이스 암호화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/logging/docs/audit&quot;&gt;Audit Logging&lt;/a&gt;&amp;nbsp;- 감사 로깅 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/migrating-mysql-to-cloud-sql&quot;&gt;Database Migration Strategies&lt;/a&gt;&amp;nbsp;- 데이터베이스 마이그레이션 전략&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/spanner/docs/migration-overview&quot;&gt;Spanner Migration Tools&lt;/a&gt;&amp;nbsp;- Spanner 마이그레이션 도구&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/data-processing-patterns&quot;&gt;Data Integration Patterns&lt;/a&gt;&amp;nbsp;- 데이터 통합 패턴&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/performing-etl-from-relational-database-into-bigquery&quot;&gt;ETL/ELT Best Practices&lt;/a&gt;&amp;nbsp;- ETL/ELT 모범 사례&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://registry.terraform.io/providers/hashicorp/google/latest/docs&quot;&gt;Terraform Google Provider&lt;/a&gt;&amp;nbsp;- Terraform GCP 프로바이더&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/apis/docs/cloud-client-libraries&quot;&gt;Cloud Client Libraries&lt;/a&gt;&amp;nbsp;- 클라우드 클라이언트 라이브러리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://firebase.google.com/docs/web/setup&quot;&gt;Firebase SDKs&lt;/a&gt;&amp;nbsp;- Firebase 개발 도구&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/bigquery/docs/reference/libraries&quot;&gt;BigQuery Client Libraries&lt;/a&gt;&amp;nbsp;- BigQuery 클라이언트 라이브러리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/sql/docs/mysql/manage-connections&quot;&gt;Database Connection Pooling&lt;/a&gt;&amp;nbsp;- 연결 풀링 가이드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/monitoring/docs&quot;&gt;Cloud Monitoring&lt;/a&gt;&amp;nbsp;- 클라우드 모니터링 서비스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/error-reporting/docs&quot;&gt;Error Reporting&lt;/a&gt;&amp;nbsp;- 오류 보고 및 추적&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/logging/docs&quot;&gt;Cloud Logging&lt;/a&gt;&amp;nbsp;- 로그 관리 및 분석&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/stackdriver/docs/solutions/slo-monitoring&quot;&gt;SLO Monitoring&lt;/a&gt;&amp;nbsp;- SLO 모니터링 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/monitoring/support/notification-options&quot;&gt;Alerting Best Practices&lt;/a&gt;&amp;nbsp;- 알림 모범 사례&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/bigquery-ml/docs&quot;&gt;BigQuery ML&lt;/a&gt;&amp;nbsp;- BigQuery 머신러닝&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/vertex-ai/docs&quot;&gt;Vertex AI Integration&lt;/a&gt;&amp;nbsp;- Vertex AI 통합&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/real-time-analytics&quot;&gt;Real-time Analytics&lt;/a&gt;&amp;nbsp;- 실시간 분석 아키텍처&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/data-science-at-scale&quot;&gt;Data Science Workflows&lt;/a&gt;&amp;nbsp;- 데이터 사이언스 워크플로우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/dataflow/docs&quot;&gt;Stream Processing&lt;/a&gt;&amp;nbsp;- 스트림 데이터 처리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/solutions/financial-services&quot;&gt;Financial Services&lt;/a&gt;&amp;nbsp;- 금융 서비스 솔루션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/solutions/healthcare-life-sciences&quot;&gt;Healthcare and Life Sciences&lt;/a&gt;&amp;nbsp;- 헬스케어 솔루션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/solutions/retail&quot;&gt;Retail and E-commerce&lt;/a&gt;&amp;nbsp;- 리테일 솔루션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/solutions/gaming&quot;&gt;Gaming&lt;/a&gt;&amp;nbsp;- 게임 산업 솔루션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/solutions/media-entertainment&quot;&gt;Media and Entertainment&lt;/a&gt;&amp;nbsp;- 미디어 솔루션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/training&quot;&gt;Google Cloud Training&lt;/a&gt;&amp;nbsp;- 공식 교육 프로그램&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/certification/cloud-database-engineer&quot;&gt;Database Engineer Certification&lt;/a&gt;&amp;nbsp;- 데이터베이스 엔지니어 자격증&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/blog/topics/databases&quot;&gt;Cloud Blog - Databases&lt;/a&gt;&amp;nbsp;- 데이터베이스 관련 블로그&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://stackoverflow.com/questions/tagged/google-cloud-platform&quot;&gt;Stack Overflow - GCP&lt;/a&gt;&amp;nbsp;- 기술 질문 및 답변&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/GoogleCloudPlatform&quot;&gt;GitHub - GoogleCloudPlatform&lt;/a&gt;&amp;nbsp;- 샘플 코드 및 도구&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.googlecloudcommunity.com/&quot;&gt;Cloud Community&lt;/a&gt;&amp;nbsp;- 사용자 커뮤니티&lt;/span&gt;&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;&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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>GCP</category>
      <category>cloudspanner</category>
      <category>cloudsql</category>
      <category>database</category>
      <category>GCP</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/459</guid>
      <comments>https://somaz.tistory.com/459#entry459comment</comments>
      <pubDate>Tue, 10 Mar 2026 00:00:14 +0900</pubDate>
    </item>
    <item>
      <title>GCP 네트워크 연결 완전 가이드: VPC Peering vs Cloud Interconnect vs VPN</title>
      <link>https://somaz.tistory.com/458</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라우드 네트워킹에서 다양한 리소스 간의 안전하고 효율적인 연결은 현대 IT 인프라의 핵심이다. Google Cloud Platform(GCP)은 온프레미스 환경, 다른 클라우드 제공업체, 그리고 GCP 내부 리소스 간의 연결을 위한 다양한 네트워킹 옵션을 제공한다.&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;color: #000000;&quot;&gt;VPC Peering은 같은 조직 내 또는 서로 다른 조직의 VPC 간 프라이빗 연결을 제공하며, Cloud Interconnect는 온프레미스 네트워크와 GCP 간의 전용 연결을 통해 높은 대역폭과 낮은 지연시간을 보장한다. Cloud VPN은 인터넷을 통한 암호화된 터널을 제공하여 비용 효율적인 하이브리드 연결을 가능하게 한다.&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;color: #000000;&quot;&gt;최근 GCP의 네트워킹 서비스는 더욱 정교해졌다. Shared VPC를 통한 중앙집중식 네트워크 관리, Cloud Router의 BGP 라우팅 최적화, 그리고 Cross-Cloud Interconnect를 통한 멀티클라우드 연결까지 지원하고 있다. 특히 네트워크 보안과 성능을 동시에 고려한 아키텍처 설계가 중요해지고 있다.&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;color: #000000;&quot;&gt;이 글에서는 각 연결 방식의 원리와 특성을 심층 분석하고, 실제 운영 환경에서의 적용 시나리오, 비용 분석, 그리고 최적화 전략을 제시한다. 또한 Terraform을 활용한 실제 구현 예제와 하이브리드 클라우드 아키텍처 설계 패턴도 함께 다룬다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ISgD6/dJMcahb1Npp/c0Gg9pgSDKlb3sl2lBwlMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ISgD6/dJMcahb1Npp/c0Gg9pgSDKlb3sl2lBwlMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ISgD6/dJMcahb1Npp/c0Gg9pgSDKlb3sl2lBwlMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FISgD6%2FdJMcahb1Npp%2Fc0Gg9pgSDKlb3sl2lBwlMK%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPC 네트워킹 기초 개념&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPC(Virtual Private Cloud) 이해&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPC는 GCP에서 제공하는 가상 네트워크 환경으로, 물리적으로 격리된 클라우드 네트워크를 제공한다. 각 VPC는 독립적인 네트워크 공간을 가지며, 서브넷, 라우팅 테이블, 방화벽 규칙 등을 포함한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPC의 핵심 구성 요소&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;서브넷&lt;/b&gt;: 특정 리전 내의 IP 주소 범위&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;라우팅 테이블&lt;/b&gt;: 트래픽 경로 정의&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;방화벽 규칙&lt;/b&gt;: 네트워크 보안 제어&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;피어링 연결&lt;/b&gt;: 다른 VPC와의 연결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;게이트웨이&lt;/b&gt;: 외부 네트워크와의 연결점&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 기본 VPC 구성
resource &quot;google_compute_network&quot; &quot;main_vpc&quot; {
  name                    = &quot;main-vpc&quot;
  auto_create_subnetworks = false
  description             = &quot;Main VPC for production workloads&quot;
}

resource &quot;google_compute_subnetwork&quot; &quot;web_subnet&quot; {
  name          = &quot;web-subnet&quot;
  ip_cidr_range = &quot;10.0.1.0/24&quot;
  region        = &quot;us-central1&quot;
  network       = google_compute_network.main_vpc.id
  
  secondary_ip_range {
    range_name    = &quot;pods&quot;
    ip_cidr_range = &quot;10.1.0.0/16&quot;
  }
  
  secondary_ip_range {
    range_name    = &quot;services&quot;
    ip_cidr_range = &quot;10.2.0.0/16&quot;
  }
}

resource &quot;google_compute_subnetwork&quot; &quot;db_subnet&quot; {
  name          = &quot;db-subnet&quot;
  ip_cidr_range = &quot;10.0.2.0/24&quot;
  region        = &quot;us-central1&quot;
  network       = google_compute_network.main_vpc.id
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPC Peering vs Shared VPC 설계 패턴&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPC Peering 개념과 원리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPC Peering은 두 VPC 간의 네트워크 연결을 제공하여 프라이빗 IP 주소를 통한 통신을 가능하게 한다. 이는 소프트웨어 정의 네트워킹을 통해 구현되며, 두 VPC의 라우팅 테이블에 피어 VPC로의 경로를 자동으로 추가한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPC Peering의 동작 원리&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;피어링 요청&lt;/b&gt;: 한쪽 VPC에서 다른 VPC로 피어링 요청 전송&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;피어링 승인&lt;/b&gt;: 대상 VPC에서 요청 승인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;라우팅 설정&lt;/b&gt;: 양쪽 VPC의 라우팅 테이블 자동 업데이트&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;트래픽 전달&lt;/b&gt;: 프라이빗 IP를 통한 직접 통신&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# VPC Peering 구성
resource &quot;google_compute_network&quot; &quot;production_vpc&quot; {
  name                    = &quot;production-vpc&quot;
  auto_create_subnetworks = false
}

resource &quot;google_compute_network&quot; &quot;development_vpc&quot; {
  name                    = &quot;development-vpc&quot;
  auto_create_subnetworks = false
}

resource &quot;google_compute_network_peering&quot; &quot;prod_to_dev&quot; {
  name         = &quot;prod-to-dev-peering&quot;
  network      = google_compute_network.production_vpc.self_link
  peer_network = google_compute_network.development_vpc.self_link
  
  auto_create_routes = true
  
  # 커스텀 라우트 가져오기/내보내기 설정
  export_custom_routes = true
  import_custom_routes = true
}

resource &quot;google_compute_network_peering&quot; &quot;dev_to_prod&quot; {
  name         = &quot;dev-to-prod-peering&quot;
  network      = google_compute_network.development_vpc.self_link
  peer_network = google_compute_network.production_vpc.self_link
  
  auto_create_routes = true
  export_custom_routes = true
  import_custom_routes = true
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Shared VPC 개념과 설계&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Shared VPC는 조직 내에서 네트워크 리소스를 중앙집중식으로 관리할 수 있게 해주는 기능이다. 호스트 프로젝트에서 VPC를 관리하고, 서비스 프로젝트에서 해당 VPC의 서브넷을 사용할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Shared VPC의 장점&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;중앙집중식 네트워크 관리&lt;/b&gt;: 네트워크 정책과 보안 규칙의 일관성 유지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비용 효율성&lt;/b&gt;: 네트워크 리소스 공유로 비용 절감&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안 강화&lt;/b&gt;: 네트워크 관리 권한의 명확한 분리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;규정 준수&lt;/b&gt;: 엔터프라이즈 거버넌스 요구사항 충족&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# Shared VPC 구성
resource &quot;google_compute_shared_vpc_host_project&quot; &quot;host&quot; {
  project = var.host_project_id
}

resource &quot;google_compute_shared_vpc_service_project&quot; &quot;service1&quot; {
  host_project    = google_compute_shared_vpc_host_project.host.project
  service_project = var.service_project1_id
}

resource &quot;google_compute_shared_vpc_service_project&quot; &quot;service2&quot; {
  host_project    = google_compute_shared_vpc_host_project.host.project
  service_project = var.service_project2_id
}

# Shared VPC 네트워크
resource &quot;google_compute_network&quot; &quot;shared_vpc&quot; {
  name                    = &quot;shared-vpc&quot;
  auto_create_subnetworks = false
  project                 = var.host_project_id
  
  depends_on = [google_compute_shared_vpc_host_project.host]
}

# 서비스 프로젝트용 서브넷
resource &quot;google_compute_subnetwork&quot; &quot;service1_subnet&quot; {
  name          = &quot;service1-subnet&quot;
  ip_cidr_range = &quot;10.1.0.0/24&quot;
  region        = &quot;us-central1&quot;
  network       = google_compute_network.shared_vpc.id
  project       = var.host_project_id
}

resource &quot;google_compute_subnetwork&quot; &quot;service2_subnet&quot; {
  name          = &quot;service2-subnet&quot;
  ip_cidr_range = &quot;10.2.0.0/24&quot;
  region        = &quot;us-central1&quot;
  network       = google_compute_network.shared_vpc.id
  project       = var.host_project_id
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPC Peering vs Shared VPC 비교&lt;/span&gt;&lt;/h3&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;VPC Peering&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Shared VPC&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;관리 방식&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;분산형 관리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중앙집중식 관리&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;조직 구조&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;독립적인 프로젝트 간 연결&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;조직 내 프로젝트 통합&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;네트워크 정책&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 VPC별 개별 관리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;호스트 프로젝트에서 통합 관리&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비용&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 프로젝트별 과금&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;호스트 프로젝트 통합 과금&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안 관리&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;개별 VPC 보안 관리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중앙집중식 보안 관리&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;라우팅&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;피어링 기반 라우팅&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단일 VPC 내 라우팅&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;확장성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;피어링 제한 존재&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서브넷 기반 확장&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;적용 시나리오&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서로 다른 조직/팀 연결&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;같은 조직 내 리소스 공유&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Interconnect 심층 분석&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Interconnect 개념과 원리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Interconnect는 온프레미스 네트워크와 Google Cloud 간의 전용 네트워크 연결을 제공한다. 이는 인터넷을 경유하지 않는 프라이빗 연결로, 높은 대역폭과 낮은 지연시간, 안정적인 성능을 보장한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Interconnect의 동작 원리&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;물리적 연결&lt;/b&gt;: 온프레미스 라우터와 Google 네트워크 간 직접 연결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;BGP 세션&lt;/b&gt;: Border Gateway Protocol을 통한 라우팅 정보 교환&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;VLAN 태깅&lt;/b&gt;: 802.1Q VLAN을 통한 논리적 연결 분리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;라우팅 전파&lt;/b&gt;: Cloud Router를 통한 동적 라우팅&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Dedicated Interconnect&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Dedicated Interconnect는 고객의 온프레미스 네트워크와 Google 네트워크 간의 직접적인 물리적 연결을 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# Dedicated Interconnect 구성
resource &quot;google_compute_interconnect_attachment&quot; &quot;dedicated&quot; {
  name                     = &quot;dedicated-attachment&quot;
  interconnect            = var.interconnect_name
  description             = &quot;Dedicated interconnect attachment&quot;
  bandwidth               = &quot;BPS_10G&quot;
  
  candidate_subnets = [&quot;169.254.1.0/29&quot;]
  
  # VLAN 설정
  vlan_tag8021q = 100
}

# Cloud Router 구성
resource &quot;google_compute_router&quot; &quot;interconnect_router&quot; {
  name    = &quot;interconnect-router&quot;
  region  = &quot;us-central1&quot;
  network = google_compute_network.main_vpc.id
  
  bgp {
    asn            = 65000
    advertise_mode = &quot;CUSTOM&quot;
    
    advertised_groups = [&quot;ALL_SUBNETS&quot;]
    
    advertised_ip_ranges {
      range = &quot;10.0.0.0/16&quot;
      description = &quot;On-premises network&quot;
    }
  }
}

# BGP 피어 설정
resource &quot;google_compute_router_interface&quot; &quot;interconnect_interface&quot; {
  name       = &quot;interconnect-interface&quot;
  router     = google_compute_router.interconnect_router.name
  region     = google_compute_router.interconnect_router.region
  ip_range   = &quot;169.254.1.1/30&quot;
  vpn_tunnel = google_compute_interconnect_attachment.dedicated.id
}

resource &quot;google_compute_router_peer&quot; &quot;interconnect_peer&quot; {
  name                      = &quot;interconnect-peer&quot;
  router                    = google_compute_router.interconnect_router.name
  region                    = google_compute_router.interconnect_router.region
  peer_ip_address          = &quot;169.254.1.2&quot;
  peer_asn                 = 65001
  advertised_route_priority = 100
  interface                = google_compute_router_interface.interconnect_interface.name
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Partner Interconnect&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Partner Interconnect는 Google Cloud Partner를 통해 Google 네트워크에 연결하는 방식이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# Partner Interconnect 구성
resource &quot;google_compute_interconnect_attachment&quot; &quot;partner&quot; {
  name         = &quot;partner-attachment&quot;
  type         = &quot;PARTNER&quot;
  region       = &quot;us-central1&quot;
  description  = &quot;Partner interconnect attachment&quot;
  
  # Partner에서 제공하는 pairing key
  pairing_key = var.partner_pairing_key
  
  # 대역폭 설정
  bandwidth = &quot;BPS_1G&quot;
  
  candidate_subnets = [&quot;169.254.2.0/29&quot;]
  vlan_tag8021q    = 200
}

# Partner Interconnect용 Cloud Router
resource &quot;google_compute_router&quot; &quot;partner_router&quot; {
  name    = &quot;partner-router&quot;
  region  = &quot;us-central1&quot;
  network = google_compute_network.main_vpc.id
  
  bgp {
    asn = 16550
    advertise_mode = &quot;DEFAULT&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Dedicated vs Partner Interconnect 비교&lt;/span&gt;&lt;/h3&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Dedicated Interconnect&amp;nbsp;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Partner Interconnect&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;연결 방식&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;직접 물리 연결&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파트너 경유 연결&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;최소 대역폭&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10Gbps&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;50Mbps&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;최대 대역폭&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;200Gbps&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;50Gbps&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;월 비용 (10Gbps)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$1,650&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$250-500&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;데이터 전송 비용&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.02/GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.02/GB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;설치 시간&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2-4주&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1-2주&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;SLA&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;99.9%&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;99.9%&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;적용 시나리오&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대용량 트래픽&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중소 규모 연결&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud VPN 구성과 최적화&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud VPN 개념과 원리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud VPN은 IPsec VPN 터널을 통해 온프레미스 네트워크와 Google Cloud VPC를 안전하게 연결한다. 인터넷을 통한 암호화된 연결로 비용 효율적인 하이브리드 연결을 제공한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud VPN의 종류&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Classic VPN&lt;/b&gt;: 기본적인 IPsec VPN 연결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;HA VPN&lt;/b&gt;: 고가용성을 위한 이중화 VPN 연결&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# HA VPN 구성
resource &quot;google_compute_ha_vpn_gateway&quot; &quot;main&quot; {
  name    = &quot;main-ha-vpn-gateway&quot;
  region  = &quot;us-central1&quot;
  network = google_compute_network.main_vpc.id
}

# 외부 VPN 게이트웨이 (온프레미스)
resource &quot;google_compute_external_vpn_gateway&quot; &quot;onprem&quot; {
  name            = &quot;onprem-gateway&quot;
  redundancy_type = &quot;SINGLE_IP_INTERNALLY_REDUNDANT&quot;
  description     = &quot;On-premises VPN gateway&quot;

  interface {
    id         = 0
    ip_address = var.onprem_gateway_ip
  }
}

# VPN 터널 구성
resource &quot;google_compute_vpn_tunnel&quot; &quot;tunnel1&quot; {
  name                            = &quot;ha-vpn-tunnel1&quot;
  region                          = &quot;us-central1&quot;
  vpn_gateway                     = google_compute_ha_vpn_gateway.main.id
  vpn_gateway_interface          = 0
  peer_external_gateway          = google_compute_external_vpn_gateway.onprem.id
  peer_external_gateway_interface = 0
  shared_secret                   = var.shared_secret
  ike_version                     = 2
  
  router = google_compute_router.vpn_router.id
}

resource &quot;google_compute_vpn_tunnel&quot; &quot;tunnel2&quot; {
  name                            = &quot;ha-vpn-tunnel2&quot;
  region                          = &quot;us-central1&quot;
  vpn_gateway                     = google_compute_ha_vpn_gateway.main.id
  vpn_gateway_interface          = 1
  peer_external_gateway          = google_compute_external_vpn_gateway.onprem.id
  peer_external_gateway_interface = 0
  shared_secret                   = var.shared_secret_2
  ike_version                     = 2
  
  router = google_compute_router.vpn_router.id
}

# VPN용 Cloud Router
resource &quot;google_compute_router&quot; &quot;vpn_router&quot; {
  name    = &quot;vpn-router&quot;
  region  = &quot;us-central1&quot;
  network = google_compute_network.main_vpc.id
  
  bgp {
    asn = 64512
    advertise_mode = &quot;DEFAULT&quot;
  }
}

# BGP 세션 구성
resource &quot;google_compute_router_interface&quot; &quot;vpn_interface1&quot; {
  name       = &quot;vpn-interface1&quot;
  router     = google_compute_router.vpn_router.name
  region     = &quot;us-central1&quot;
  ip_range   = &quot;169.254.1.1/30&quot;
  vpn_tunnel = google_compute_vpn_tunnel.tunnel1.name
}

resource &quot;google_compute_router_peer&quot; &quot;vpn_peer1&quot; {
  name                      = &quot;vpn-peer1&quot;
  router                    = google_compute_router.vpn_router.name
  region                    = &quot;us-central1&quot;
  peer_ip_address          = &quot;169.254.1.2&quot;
  peer_asn                 = 65001
  advertised_route_priority = 100
  interface                = google_compute_router_interface.vpn_interface1.name
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Router와 BGP 라우팅 전략&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Router 개념과 역할&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Router는 Google Cloud에서 제공하는 완전 관리형 라우터 서비스로, BGP(Border Gateway Protocol)를 통해 동적 라우팅을 제공한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Router의 핵심 기능&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;동적 라우팅&lt;/b&gt;: BGP를 통한 자동 라우트 학습 및 광고&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고가용성&lt;/b&gt;: 다중 인터페이스 및 피어 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;라우트 필터링&lt;/b&gt;: 커스텀 라우트 정책 적용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;로드 밸런싱&lt;/b&gt;: ECMP(Equal Cost Multi-Path) 지원&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 고급 Cloud Router 구성
resource &quot;google_compute_router&quot; &quot;advanced_router&quot; {
  name    = &quot;advanced-router&quot;
  region  = &quot;us-central1&quot;
  network = google_compute_network.main_vpc.id
  
  bgp {
    asn            = 64512
    advertise_mode = &quot;CUSTOM&quot;
    
    # 특정 서브넷만 광고
    advertised_groups = []
    
    advertised_ip_ranges {
      range       = &quot;10.0.1.0/24&quot;
      description = &quot;Web tier subnet&quot;
    }
    
    advertised_ip_ranges {
      range       = &quot;10.0.2.0/24&quot;
      description = &quot;App tier subnet&quot;
    }
  }
}

# 라우트 정책 적용
resource &quot;google_compute_router_peer&quot; &quot;advanced_peer&quot; {
  name                      = &quot;advanced-peer&quot;
  router                    = google_compute_router.advanced_router.name
  region                    = &quot;us-central1&quot;
  peer_ip_address          = &quot;169.254.1.2&quot;
  peer_asn                 = 65001
  advertised_route_priority = 100
  interface                = google_compute_router_interface.advanced_interface.name
  
  # 커스텀 라우트 필터
  advertise_mode = &quot;CUSTOM&quot;
  
  advertised_groups = [&quot;ALL_SUBNETS&quot;]
  
  advertised_ip_ranges {
    range       = &quot;192.168.1.0/24&quot;
    description = &quot;Corporate network&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BGP 라우팅 최적화 전략&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 라우트 우선순위 설정&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 기본 연결과 백업 연결의 우선순위 차등 적용
resource &quot;google_compute_router_peer&quot; &quot;primary_peer&quot; {
  name                      = &quot;primary-peer&quot;
  router                    = google_compute_router.main_router.name
  region                    = &quot;us-central1&quot;
  peer_ip_address          = &quot;169.254.1.2&quot;
  peer_asn                 = 65001
  advertised_route_priority = 100  # 높은 우선순위
  interface                = google_compute_router_interface.primary_interface.name
}

resource &quot;google_compute_router_peer&quot; &quot;backup_peer&quot; {
  name                      = &quot;backup-peer&quot;
  router                    = google_compute_router.main_router.name
  region                    = &quot;us-central1&quot;
  peer_ip_address          = &quot;169.254.2.2&quot;
  peer_asn                 = 65002
  advertised_route_priority = 200  # 낮은 우선순위 (백업용)
  interface                = google_compute_router_interface.backup_interface.name
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 라우트 필터링&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 특정 라우트만 광고하는 정책
resource &quot;google_compute_router&quot; &quot;filtered_router&quot; {
  name    = &quot;filtered-router&quot;
  region  = &quot;us-central1&quot;
  network = google_compute_network.main_vpc.id
  
  bgp {
    asn            = 64512
    advertise_mode = &quot;CUSTOM&quot;
    
    # 기본 그룹 제외
    advertised_groups = []
    
    # 명시적 라우트만 광고
    advertised_ip_ranges {
      range       = &quot;10.0.0.0/16&quot;
      description = &quot;Internal network only&quot;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하이브리드 클라우드 네트워크 아키텍처&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다층 하이브리드 아키텍처&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현대의 엔터프라이즈 환경에서는 온프레미스, 퍼블릭 클라우드, 프라이빗 클라우드를 아우르는 하이브리드 아키텍처가 필수적이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 하이브리드 클라우드 아키텍처 구성
module &quot;hybrid_network&quot; {
  source = &quot;./modules/hybrid-network&quot;
  
  # 온프레미스 연결
  onprem_asn          = 65001
  onprem_gateway_ip   = var.onprem_gateway_ip
  onprem_networks     = [&quot;192.168.0.0/16&quot;, &quot;172.16.0.0/12&quot;]
  
  # 클라우드 네트워크
  cloud_asn           = 64512
  vpc_networks        = {
    production  = &quot;10.0.0.0/16&quot;
    development = &quot;10.1.0.0/16&quot;
    management  = &quot;10.2.0.0/16&quot;
  }
  
  # 연결 타입
  primary_connection   = &quot;interconnect&quot;
  backup_connection    = &quot;vpn&quot;
  
  # 보안 정책
  enable_private_google_access = true
  enable_flow_logs            = true
}

# Interconnect + VPN 이중화 구성
resource &quot;google_compute_router&quot; &quot;hybrid_router&quot; {
  name    = &quot;hybrid-router&quot;
  region  = &quot;us-central1&quot;
  network = google_compute_network.production_vpc.id
  
  bgp {
    asn            = 64512
    advertise_mode = &quot;CUSTOM&quot;
    
    advertised_groups = [&quot;ALL_SUBNETS&quot;]
    
    # 온프레미스 특정 서비스만 광고
    advertised_ip_ranges {
      range       = &quot;10.0.1.0/24&quot;
      description = &quot;Public services&quot;
    }
  }
}

# Primary: Dedicated Interconnect
resource &quot;google_compute_interconnect_attachment&quot; &quot;primary&quot; {
  name         = &quot;primary-interconnect&quot;
  interconnect = var.dedicated_interconnect_name
  bandwidth    = &quot;BPS_10G&quot;
  
  candidate_subnets = [&quot;169.254.1.0/29&quot;]
  vlan_tag8021q    = 100
}

# Backup: HA VPN
resource &quot;google_compute_ha_vpn_gateway&quot; &quot;backup&quot; {
  name    = &quot;backup-vpn-gateway&quot;
  region  = &quot;us-central1&quot;
  network = google_compute_network.production_vpc.id
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;멀티리전 하이브리드 연결&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 멀티리전 하이브리드 연결 구성
locals {
  regions = {
    primary   = &quot;us-central1&quot;
    secondary = &quot;us-east1&quot;
    disaster  = &quot;europe-west1&quot;
  }
}

# 각 리전별 VPN 게이트웨이
resource &quot;google_compute_ha_vpn_gateway&quot; &quot;regional&quot; {
  for_each = local.regions
  
  name    = &quot;${each.key}-vpn-gateway&quot;
  region  = each.value
  network = google_compute_network.global_vpc.id
}

# 각 리전별 Cloud Router
resource &quot;google_compute_router&quot; &quot;regional&quot; {
  for_each = local.regions
  
  name    = &quot;${each.key}-router&quot;
  region  = each.value
  network = google_compute_network.global_vpc.id
  
  bgp {
    asn            = 64512
    advertise_mode = &quot;CUSTOM&quot;
    
    advertised_groups = [&quot;ALL_SUBNETS&quot;]
    
    # 리전별 우선순위 차등 적용
    advertised_ip_ranges {
      range       = &quot;10.${index(keys(local.regions), each.key)}.0.0/16&quot;
      description = &quot;${each.key} region networks&quot;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 연결 방식 종합 비교&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;연결 방식별 특성 비교&lt;/span&gt;&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 150px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPC Peering&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Shared VPC&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Dedicated Interconnect&amp;nbsp;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Partner Interconnect&amp;nbsp;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud VPN&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;연결 대상&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPC 간&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로젝트 간&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;온프레미스&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;온프레미스&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;온프레미스&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;대역폭&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 한도&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 한도&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10-200Gbps&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;50Mbps-50Gbps&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최대 3Gbps&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;지연시간&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매우 낮음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매우 낮음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;설정 복잡도&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;월 비용&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;무료&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;무료&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$1,650+&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$250+&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$45+&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;SLA&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;99.9%&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;99.9%&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;99.9%&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;99.9%&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;99.9%&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프라이빗&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프라이빗&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전용 연결&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프라이빗&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IPsec 암호화&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 분석 및 최적화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Dedicated Interconnect 비용 모델&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nix&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 비용 계산을 위한 변수 정의
locals {
  # Dedicated Interconnect 비용 (10Gbps 기준)
  monthly_port_cost = 1650  # USD per month
  data_transfer_cost = 0.02  # USD per GB
  
  # 월간 예상 트래픽 (GB)
  monthly_traffic_gb = 10000
  
  # 총 월간 비용
  total_monthly_cost = local.monthly_port_cost + (local.monthly_traffic_gb * local.data_transfer_cost)
  
  # Partner Interconnect 비용 비교 (1Gbps)
  partner_monthly_cost = 400  # USD per month
  partner_total_cost = local.partner_monthly_cost + (local.monthly_traffic_gb * local.data_transfer_cost)
  
  # VPN 비용 비교
  vpn_gateway_cost = 45    # USD per month per gateway
  vpn_tunnel_cost = 36     # USD per month per tunnel
  vpn_total_cost = (local.vpn_gateway_cost * 2) + (local.vpn_tunnel_cost * 2) + (local.monthly_traffic_gb * 0.045)
}

# 비용 최적화를 위한 출력
output &quot;cost_comparison&quot; {
  value = {
    dedicated_interconnect = &quot;${local.total_monthly_cost} USD/month&quot;
    partner_interconnect   = &quot;${local.partner_total_cost} USD/month&quot;
    ha_vpn                = &quot;${local.vpn_total_cost} USD/month&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;연결 방식 선택 가이드&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;gams&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 트래픽 패턴에 따른 연결 방식 선택
variable &quot;requirements&quot; {
  description = &quot;Network requirements&quot;
  type = object({
    bandwidth_gbps     = number
    monthly_traffic_tb = number
    latency_sensitive  = bool
    budget_limit_usd   = number
    compliance_required = bool
  })
}

locals {
  # 요구사항에 따른 연결 방식 추천
  recommended_solution = (
    var.requirements.bandwidth_gbps &amp;gt; 10 ? &quot;dedicated_interconnect&quot; :
    var.requirements.monthly_traffic_tb &amp;gt; 5 ? &quot;partner_interconnect&quot; :
    var.requirements.latency_sensitive ? &quot;partner_interconnect&quot; :
    var.requirements.budget_limit_usd &amp;lt; 500 ? &quot;ha_vpn&quot; :
    &quot;partner_interconnect&quot;
  )
}

output &quot;recommended_solution&quot; {
  value = local.recommended_solution
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;고급 네트워크 보안 및 모니터링&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Private Google Access와 Private Service Connect&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Private Google Access 구성
resource &quot;google_compute_subnetwork&quot; &quot;private_subnet&quot; {
  name                     = &quot;private-subnet&quot;
  ip_cidr_range           = &quot;10.0.1.0/24&quot;
  region                  = &quot;us-central1&quot;
  network                 = google_compute_network.main_vpc.id
  private_ip_google_access = true
  
  # Flow Logs 활성화
  log_config {
    aggregation_interval = &quot;INTERVAL_10_MIN&quot;
    flow_sampling       = 0.5
    metadata           = &quot;INCLUDE_ALL_METADATA&quot;
  }
}

# Private Service Connect 엔드포인트
resource &quot;google_compute_global_address&quot; &quot;psc_endpoint&quot; {
  name          = &quot;psc-endpoint&quot;
  purpose       = &quot;PRIVATE_SERVICE_CONNECT&quot;
  network       = google_compute_network.main_vpc.id
  address_type  = &quot;INTERNAL&quot;
}

resource &quot;google_compute_global_forwarding_rule&quot; &quot;psc_forwarding_rule&quot; {
  name                  = &quot;psc-forwarding-rule&quot;
  target                = &quot;all-apis&quot;
  network               = google_compute_network.main_vpc.id
  ip_address           = google_compute_global_address.psc_endpoint.id
  load_balancing_scheme = &quot;&quot;
}&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 모니터링 및 로깅&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# VPC Flow Logs 구성
resource &quot;google_compute_subnetwork&quot; &quot;monitored_subnet&quot; {
  name          = &quot;monitored-subnet&quot;
  ip_cidr_range = &quot;10.0.2.0/24&quot;
  region        = &quot;us-central1&quot;
  network       = google_compute_network.main_vpc.id
  
  log_config {
    aggregation_interval = &quot;INTERVAL_5_MIN&quot;
    flow_sampling       = 1.0
    metadata           = &quot;INCLUDE_ALL_METADATA&quot;
    metadata_fields = [
      &quot;src_vpc&quot;,
      &quot;dest_vpc&quot;,
      &quot;src_gke_details&quot;,
      &quot;dest_gke_details&quot;
    ]
  }
}

# 네트워크 태그 기반 방화벽 규칙
resource &quot;google_compute_firewall&quot; &quot;web_tier&quot; {
  name    = &quot;allow-web-tier&quot;
  network = google_compute_network.main_vpc.name

  allow {
    protocol = &quot;tcp&quot;
    ports    = [&quot;80&quot;, &quot;443&quot;]
  }

  source_ranges = [&quot;0.0.0.0/0&quot;]
  target_tags   = [&quot;web-server&quot;]

  # 로깅 활성화
  log_config {
    metadata = &quot;INCLUDE_ALL_METADATA&quot;
  }
}

resource &quot;google_compute_firewall&quot; &quot;app_tier&quot; {
  name    = &quot;allow-app-tier&quot;
  network = google_compute_network.main_vpc.name

  allow {
    protocol = &quot;tcp&quot;
    ports    = [&quot;8080&quot;, &quot;8443&quot;]
  }

  source_tags = [&quot;web-server&quot;]
  target_tags = [&quot;app-server&quot;]

  log_config {
    metadata = &quot;INCLUDE_ALL_METADATA&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;네트워크 성능 최적화 전략&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지역별 트래픽 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 멀티리전 네트워크 최적화
resource &quot;google_compute_network&quot; &quot;global_network&quot; {
  name                    = &quot;global-network&quot;
  auto_create_subnetworks = false
  routing_mode           = &quot;GLOBAL&quot;
}

# 리전별 서브넷 구성
resource &quot;google_compute_subnetwork&quot; &quot;regional_subnets&quot; {
  for_each = {
    &quot;us-central1&quot; = &quot;10.1.0.0/16&quot;
    &quot;us-east1&quot;    = &quot;10.2.0.0/16&quot;
    &quot;europe-west1&quot; = &quot;10.3.0.0/16&quot;
    &quot;asia-east1&quot;   = &quot;10.4.0.0/16&quot;
  }

  name          = &quot;${each.key}-subnet&quot;
  ip_cidr_range = each.value
  region        = each.key
  network       = google_compute_network.global_network.id
  
  # 리전별 Private Google Access
  private_ip_google_access = true
  
  # 세컨더리 IP 범위 (GKE용)
  secondary_ip_range {
    range_name    = &quot;pods&quot;
    ip_cidr_range = cidrsubnet(each.value, 8, 1)
  }
  
  secondary_ip_range {
    range_name    = &quot;services&quot;
    ip_cidr_range = cidrsubnet(each.value, 8, 2)
  }
}

# 리전별 Cloud NAT
resource &quot;google_compute_router&quot; &quot;regional_routers&quot; {
  for_each = toset([&quot;us-central1&quot;, &quot;us-east1&quot;, &quot;europe-west1&quot;, &quot;asia-east1&quot;])
  
  name    = &quot;${each.key}-router&quot;
  region  = each.key
  network = google_compute_network.global_network.id
}

resource &quot;google_compute_router_nat&quot; &quot;regional_nat&quot; {
  for_each = google_compute_router.regional_routers
  
  name                               = &quot;${each.key}-nat&quot;
  router                            = each.value.name
  region                            = each.value.region
  nat_ip_allocate_option            = &quot;AUTO_ONLY&quot;
  source_subnetwork_ip_ranges_to_nat = &quot;ALL_SUBNETWORKS_ALL_IP_RANGES&quot;

  log_config {
    enable = true
    filter = &quot;ERRORS_ONLY&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대역폭 및 지연시간 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Premium 네트워크 티어 구성
resource &quot;google_compute_global_address&quot; &quot;premium_ip&quot; {
  name         = &quot;premium-global-ip&quot;
  address_type = &quot;EXTERNAL&quot;
  
  # Premium 티어 사용 (기본값)
  network_tier = &quot;PREMIUM&quot;
}

# 지역별 표준 티어 IP (비용 절약)
resource &quot;google_compute_address&quot; &quot;standard_ip&quot; {
  for_each = toset([&quot;us-central1&quot;, &quot;us-east1&quot;])
  
  name         = &quot;${each.key}-standard-ip&quot;
  address_type = &quot;EXTERNAL&quot;
  region       = each.key
  network_tier = &quot;STANDARD&quot;
}

# 전용 Interconnect 대역폭 모니터링
resource &quot;google_monitoring_alert_policy&quot; &quot;interconnect_utilization&quot; {
  display_name = &quot;Interconnect High Utilization&quot;
  combiner     = &quot;OR&quot;
  
  conditions {
    display_name = &quot;Interconnect utilization &amp;gt; 80%&quot;
    
    condition_threshold {
      filter          = &quot;resource.type=\&quot;gce_interconnect_attachment\&quot;&quot;
      comparison      = &quot;COMPARISON_GREATER_THAN&quot;
      threshold_value = 0.8
      duration        = &quot;300s&quot;
      
      aggregations {
        alignment_period   = &quot;300s&quot;
        per_series_aligner = &quot;ALIGN_MEAN&quot;
      }
    }
  }
  
  notification_channels = [var.notification_channel_id]
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;재해 복구 및 고가용성 설계&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;멀티리전 재해 복구 아키텍처&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 기본 리전과 재해 복구 리전 구성
variable &quot;regions&quot; {
  description = &quot;Primary and DR regions&quot;
  type = object({
    primary = string
    dr      = string
  })
  default = {
    primary = &quot;us-central1&quot;
    dr      = &quot;us-east1&quot;
  }
}

# 각 리전별 VPC 구성
resource &quot;google_compute_network&quot; &quot;regional_vpc&quot; {
  for_each = var.regions
  
  name                    = &quot;${each.key}-vpc&quot;
  auto_create_subnetworks = false
  routing_mode           = &quot;REGIONAL&quot;
}

# VPC Peering for DR
resource &quot;google_compute_network_peering&quot; &quot;primary_to_dr&quot; {
  name         = &quot;primary-to-dr&quot;
  network      = google_compute_network.regional_vpc[&quot;primary&quot;].self_link
  peer_network = google_compute_network.regional_vpc[&quot;dr&quot;].self_link
  
  auto_create_routes                = true
  export_custom_routes             = true
  import_custom_routes             = true
  export_subnet_routes_with_public_ip = false
  import_subnet_routes_with_public_ip = false
}

resource &quot;google_compute_network_peering&quot; &quot;dr_to_primary&quot; {
  name         = &quot;dr-to-primary&quot;
  network      = google_compute_network.regional_vpc[&quot;dr&quot;].self_link
  peer_network = google_compute_network.regional_vpc[&quot;primary&quot;].self_link
  
  auto_create_routes                = true
  export_custom_routes             = true
  import_custom_routes             = true
  export_subnet_routes_with_public_ip = false
  import_subnet_routes_with_public_ip = false
}

# 각 리전별 온프레미스 연결
resource &quot;google_compute_ha_vpn_gateway&quot; &quot;regional_gateways&quot; {
  for_each = var.regions
  
  name    = &quot;${each.key}-vpn-gateway&quot;
  region  = each.value
  network = google_compute_network.regional_vpc[each.key].id
}

# 자동 페일오버를 위한 Health Check
resource &quot;google_compute_health_check&quot; &quot;primary_health&quot; {
  name               = &quot;primary-region-health&quot;
  check_interval_sec = 10
  timeout_sec        = 3
  healthy_threshold  = 2
  unhealthy_threshold = 3

  tcp_health_check {
    port = &quot;80&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 자동화 및 IaC 관리&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nix&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 네트워크 구성 모듈화
module &quot;enterprise_network&quot; {
  source = &quot;./modules/enterprise-network&quot;
  
  # 기본 설정
  project_id = var.project_id
  regions    = var.regions
  
  # 네트워크 설정
  vpc_configs = {
    production = {
      cidr_range      = &quot;10.0.0.0/16&quot;
      enable_flow_logs = true
      subnets = {
        web = &quot;10.0.1.0/24&quot;
        app = &quot;10.0.2.0/24&quot;
        db  = &quot;10.0.3.0/24&quot;
      }
    }
    staging = {
      cidr_range      = &quot;10.1.0.0/16&quot;
      enable_flow_logs = false
      subnets = {
        web = &quot;10.1.1.0/24&quot;
        app = &quot;10.1.2.0/24&quot;
        db  = &quot;10.1.3.0/24&quot;
      }
    }
  }
  
  # 연결 설정
  interconnect_config = {
    type      = &quot;partner&quot;
    bandwidth = &quot;1Gbps&quot;
    vlan_tag  = 100
  }
  
  # 보안 설정
  firewall_rules = {
    allow_web = {
      ports        = [&quot;80&quot;, &quot;443&quot;]
      source_ranges = [&quot;0.0.0.0/0&quot;]
      target_tags   = [&quot;web-server&quot;]
    }
    allow_ssh = {
      ports        = [&quot;22&quot;]
      source_ranges = [var.admin_cidr]
      target_tags   = [&quot;admin-access&quot;]
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GCP의 네트워크 연결 옵션들은 각각 고유한 장점과 적용 시나리오를 가지고 있어, 조직의 요구사항에 맞는 최적의 선택이 중요하다. &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;color: #000000;&quot;&gt;VPC Peering은 간단하고 비용 효율적인 VPC 간 연결을 제공하며, Shared VPC는 대규모 조직의 중앙집중식 네트워크 관리를 가능하게 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Interconnect는 온프레미스와의 고성능 연결을 위한 최적의 선택이며, Dedicated Interconnect는 대용량 트래픽을, Partner Interconnect는 중소 규모의 연결을 효과적으로 처리한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud VPN은 가장 경제적인 하이브리드 연결 방식으로, 중간 규모의 트래픽과 백업 연결에 적합하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 선택 기준&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;비용 대비 성능&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: 트래픽 패턴과 예산을 고려한 연결 방식 선택이 중요하다. 월 10TB 이상의 트래픽이라면 Interconnect가, 그 이하라면 VPN이 비용 효율적이다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;지연시간 요구사항&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: 실시간 애플리케이션이나 고성능 컴퓨팅에는 Dedicated Interconnect를, 일반적인 엔터프라이즈 애플리케이션에는 Partner Interconnect나 HA VPN이 적합하다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안 및 규정 준수&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: 금융이나 의료 등 엄격한 규정이 있는 산업에서는 전용 연결인 Dedicated Interconnect를 권장한다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;확장성과 관리 편의성&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: Shared VPC는 대규모 조직의 네트워크 거버넌스를, VPC Peering은 독립적인 프로젝트 간 유연한 연결을 제공한다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;재해 복구&lt;/b&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&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud Router와 BGP를 통한 동적 라우팅은 네트워크의 자동화와 최적화에 핵심적인 역할을 한다. 특히 ECMP를 활용한 로드 밸런싱과 우선순위 기반 경로 선택을 통해 네트워크 성능을 극대화할 수 있다.&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;color: #000000;&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;&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;
&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;공식 Google Cloud 문서&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/vpc/docs&quot;&gt;GCP VPC Documentation&lt;/a&gt;&amp;nbsp;- VPC 네트워킹 기본 개념과 구성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/network-connectivity/docs/interconnect&quot;&gt;Cloud Interconnect Documentation&lt;/a&gt;&amp;nbsp;- 전용 연결 서비스 가이드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/network-connectivity/docs/vpn&quot;&gt;Cloud VPN Documentation&lt;/a&gt;&amp;nbsp;- IPsec VPN 터널 구성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/vpc/docs/vpc-peering&quot;&gt;VPC Peering Documentation&lt;/a&gt;&amp;nbsp;- VPC 간 피어링 연결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/vpc/docs/shared-vpc&quot;&gt;Shared VPC Documentation&lt;/a&gt;&amp;nbsp;- 공유 VPC 설정 및 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/network-connectivity/docs/router&quot;&gt;Cloud Router Documentation&lt;/a&gt;&amp;nbsp;- 동적 라우팅 구성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/network-connectivity/docs/router/concepts/best-practices&quot;&gt;BGP Routing Best Practices&lt;/a&gt;&amp;nbsp;- BGP 라우팅 최적화 방법&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 보안 및 고급 기능&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/security/products/network-security&quot;&gt;GCP Network Security Documentation&lt;/a&gt;&amp;nbsp;- 네트워크 보안 서비스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/vpc/docs/private-google-access&quot;&gt;Private Google Access Documentation&lt;/a&gt;&amp;nbsp;- 프라이빗 구글 액세스 구성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/vpc/docs/private-service-connect&quot;&gt;Private Service Connect Documentation&lt;/a&gt;&amp;nbsp;- 프라이빗 서비스 연결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/nat/docs&quot;&gt;Cloud NAT Documentation&lt;/a&gt;&amp;nbsp;- 클라우드 NAT 서비스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/vpc/docs/flow-logs&quot;&gt;VPC Flow Logs Documentation&lt;/a&gt;&amp;nbsp;- 네트워크 트래픽 로깅&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/armor/docs&quot;&gt;Cloud Armor Documentation&lt;/a&gt;&amp;nbsp;- DDoS 방어 및 WAF&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/network-intelligence-center/docs&quot;&gt;Network Intelligence Center&lt;/a&gt;&amp;nbsp;- 네트워크 모니터링 및 분석&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아키텍처 및 설계 가이드&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/framework&quot;&gt;GCP Architecture Framework&lt;/a&gt;&amp;nbsp;- 클라우드 아키텍처 설계 원칙&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/hybrid-and-multi-cloud-architecture-patterns&quot;&gt;Hybrid and Multi-cloud Architecture Patterns&lt;/a&gt;&amp;nbsp;- 하이브리드 클라우드 패턴&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/docs/security/infrastructure/design&quot;&gt;Network Security Design Patterns&lt;/a&gt;&amp;nbsp;- 네트워크 보안 설계 패턴&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/docs/enterprise&quot;&gt;Enterprise Networking on GCP&lt;/a&gt;&amp;nbsp;- 엔터프라이즈 네트워킹 가이드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/reference-patterns/multi-region&quot;&gt;Multi-region Architecture&lt;/a&gt;&amp;nbsp;- 멀티 리전 아키텍처 패턴&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Terraform 및 자동화&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://registry.terraform.io/providers/hashicorp/google/latest/docs&quot;&gt;Terraform Google Cloud Provider&lt;/a&gt;&amp;nbsp;- Terraform GCP 프로바이더&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://registry.terraform.io/modules/terraform-google-modules/network/google/latest&quot;&gt;Terraform Network Module&lt;/a&gt;&amp;nbsp;- 네트워크 모듈&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/foundation-toolkit&quot;&gt;Cloud Foundation Toolkit&lt;/a&gt;&amp;nbsp;- IaC 템플릿 및 모듈&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/config-connector/docs&quot;&gt;Config Connector&lt;/a&gt;&amp;nbsp;- Kubernetes 기반 리소스 관리&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 및 운영 최적화&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/vpc/network-pricing&quot;&gt;GCP Network Pricing&lt;/a&gt;&amp;nbsp;- 네트워크 서비스 요금&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/network-connectivity/docs/interconnect/pricing&quot;&gt;Cloud Interconnect Pricing&lt;/a&gt;&amp;nbsp;- 인터커넥트 요금 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/network-connectivity/docs/vpn/pricing&quot;&gt;Cloud VPN Pricing&lt;/a&gt;&amp;nbsp;- VPN 서비스 요금&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/docs/enterprise/best-practices-for-enterprise-organizations&quot;&gt;Cost Optimization Best Practices&lt;/a&gt;&amp;nbsp;- 비용 최적화 방법&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/compute/docs/networking/network-performance&quot;&gt;Network Performance Guide&lt;/a&gt;&amp;nbsp;- 네트워크 성능 튜닝&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모니터링 및 문제 해결&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/monitoring/docs&quot;&gt;Cloud Monitoring Documentation&lt;/a&gt;&amp;nbsp;- 모니터링 서비스 가이드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/logging/docs&quot;&gt;Cloud Logging Documentation&lt;/a&gt;&amp;nbsp;- 로깅 서비스 구성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/vpc/docs/troubleshooting&quot;&gt;Network Troubleshooting Guide&lt;/a&gt;&amp;nbsp;- 네트워크 문제 해결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/network-intelligence-center/docs/connectivity-tests&quot;&gt;Connectivity Tests&lt;/a&gt;&amp;nbsp;- 연결성 테스트 도구&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/network-intelligence-center/docs/performance-dashboard&quot;&gt;Performance Dashboard&lt;/a&gt;&amp;nbsp;- 성능 대시보드&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;규정 준수 및 보안&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/security-command-center/docs&quot;&gt;Security Command Center&lt;/a&gt;&amp;nbsp;- 보안 모니터링 센터&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/security/compliance&quot;&gt;Compliance Resource Center&lt;/a&gt;&amp;nbsp;- 규정 준수 가이드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/docs/geography-and-regions&quot;&gt;Data Residency Guide&lt;/a&gt;&amp;nbsp;- 데이터 주권 가이드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/privacy/gdpr&quot;&gt;GDPR Compliance&lt;/a&gt;&amp;nbsp;- GDPR 준수 방안&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/security/compliance/soc-2&quot;&gt;SOC 2 Type II Report&lt;/a&gt;&amp;nbsp;- SOC 2 인증 정보&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;커뮤니티 및 학습 리소스&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/certification/cloud-network-engineer&quot;&gt;Google Cloud Networking Specialist Certification&lt;/a&gt;&amp;nbsp;- 네트워킹 전문가 자격증&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloudonair.withgoogle.com/events/cloud-onboard&quot;&gt;Cloud OnBoard&lt;/a&gt;&amp;nbsp;- 무료 교육 프로그램&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/blog/topics/networking&quot;&gt;Google Cloud Blog - Networking&lt;/a&gt;&amp;nbsp;- 네트워킹 관련 블로그&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://stackoverflow.com/questions/tagged/google-cloud-platform&quot;&gt;Stack Overflow - Google Cloud Platform&lt;/a&gt;&amp;nbsp;- 기술 질문 및 답변&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.googlecloudcommunity.com&quot;&gt;Google Cloud Community&lt;/a&gt;&amp;nbsp;- 사용자 커뮤니티&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/GoogleCloudPlatform&quot;&gt;GitHub - GoogleCloudPlatform&lt;/a&gt;&amp;nbsp;- 샘플 코드 및 도구&lt;/span&gt;&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;&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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>GCP</category>
      <category>GCP</category>
      <category>Network</category>
      <category>VPC</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/458</guid>
      <comments>https://somaz.tistory.com/458#entry458comment</comments>
      <pubDate>Tue, 3 Mar 2026 00:00:09 +0900</pubDate>
    </item>
    <item>
      <title>Valkey - Redis의 오픈소스 대안, Kubernetes Helm Chart로 설치하기</title>
      <link>https://somaz.tistory.com/489</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis는 오랫동안 인메모리 데이터 스토어의 대명사였다. 캐싱, 세션 관리, 메시지 큐 등 다양한 워크로드에서 독보적인 성능을 보여주며 사실상 업계 표준으로 자리잡았다. &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;color: #000000;&quot;&gt;그러나 2024년 3월, Redis Inc.가 기존의 BSD 3-Clause 라이선스를 버리고 소스 어베일러블(Source-Available) 라이선스로 전환하면서 상황이 크게 달라졌다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이에 대한 응답으로 Linux Foundation의 주도 하에 AWS, Google Cloud, Oracle 등 주요 클라우드 벤더들의 지원을 받아 &lt;b&gt;Valkey&lt;/b&gt; 프로젝트가 탄생했다. Valkey는 Redis 7.2.4(마지막 오픈소스 버전)를 포크하여 시작된 프로젝트로, BSD 3-Clause 라이선스를 유지하며 진정한 오픈소스 인메모리 데이터 스토어를 지향한다.&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;color: #000000;&quot;&gt;이번 글에서는 Valkey의 개념, Redis와의 차이점, 라이선스 비교를 살펴보고, 공식 Helm Chart를 사용하여 Kubernetes 클러스터에 Valkey를 배포하는 방법을 정리한다.&lt;/span&gt;&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-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8yecA/dJMcafetpk3/7BjdZX6OvccczHK2S0PkZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8yecA/dJMcafetpk3/7BjdZX6OvccczHK2S0PkZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8yecA/dJMcafetpk3/7BjdZX6OvccczHK2S0PkZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8yecA%2FdJMcafetpk3%2F7BjdZX6OvccczHK2S0PkZK%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;1. Valkey란?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Valkey는 고성능 오픈소스 인메모리 Key-Value 데이터 스토어이다. Redis 7.2.4를 기반으로 포크되었으며, Linux Foundation이 관리하는 커뮤니티 주도 프로젝트이다. 캐싱, 메시지 큐, 세션 스토어 등 Redis가 담당하던 대부분의 워크로드를 그대로 수행할 수 있으며, Redis 7.2와 높은 호환성을 유지하고 있어 기존 Redis 클라이언트를 그대로 사용할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Valkey 8.0 이후부터는 독자적인 기술 방향을 본격적으로 추진하고 있다. Kyle Davis(Valkey 메인테이너)는 다음과 같이 말했다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;From this point forward, Redis and Valkey are two different pieces of software.&quot;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;span style=&quot;color: #000000;&quot;&gt;주요 지원 기업으로는 AWS, Google Cloud, Oracle, Ericsson, Snap Inc.(Snapchat 모회사) 등이 있으며, AWS ElastiCache와 MemoryDB에서도 Valkey를 공식 지원하고 있다.&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;&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;color: #000000;&quot;&gt;2. Redis vs Valkey 비교&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2.1 라이선스 차이&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;라이선스 변경은 Valkey가 탄생하게 된 가장 핵심적인 이유이다.&lt;/span&gt;&lt;/p&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Valkey&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;라이선스&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;RSALv2 / SSPLv1 / AGPLv3 (트리플 라이선스)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BSD 3-Clause&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;오픈소스 여부&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AGPLv3는 OSI 승인이지만 제약이 큼&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완전한 오픈소스&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;상업적 사용&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라우드 서비스 제공 시 제한 있음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한 없음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;거버넌스&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis Inc. 주도&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Linux Foundation 주도&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;코드 수정/재배포&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;라이선스에 따라 제약&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자유&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Redis의 라이선스 변천사&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;~2024년 2월&lt;/b&gt;: BSD 3-Clause (완전 오픈소스)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2024년 3월&lt;/b&gt;: RSALv2 / SSPLv1 (소스 어베일러블, 오픈소스 아님)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2025년 5월 (Redis 8.0)&lt;/b&gt;: AGPLv3 추가 (트리플 라이선스)&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;Redis가 AGPLv3를 추가하면서 다시 오픈소스 분류에 포함되었지만, AGPLv3의 카피레프트 조항(수정된 코드를 반드시 공개해야 함) 때문에 많은 기업에서 채택을 꺼리는 상황이다. &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;color: #000000;&quot;&gt;반면 Valkey의 BSD 3-Clause 라이선스는 상업적 사용, 수정, 재배포에 거의 제한이 없어 기업 환경에서 훨씬 유연하게 사용할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2.2 기술적 차이&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Valkey&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스레딩 모델&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단일 스레드 커맨드 실행 (I/O 멀티스레딩 일부 지원)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;향상된 I/O 멀티스레딩 (멀티코어 활용)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;메모리 효율성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 해시테이블 구조&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;재설계된 해시테이블로 메모리 오버헤드 감소&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;RDMA 지원&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;미지원&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실험적 지원 (Valkey 8.0+)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;벡터 검색&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis Query Engine 내장&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;미지원&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;JSON 지원&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네이티브 지원&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;미지원&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;TimeSeries&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;내장 지원&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;미지원&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;호환성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis 7.2와 높은 호환성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;&lt;span style=&quot;color: #000000;&quot;&gt;Valkey는 캐싱, 메시지 큐, 세션 스토어 등 전통적인 인메모리 데이터 스토어 워크로드에서 강점을 보인다. 특히 멀티스레딩 개선으로 높은 처리량(throughput)과 낮은 레이턴시를 달성하며, 메모리 효율성도 개선되었다.&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;color: #000000;&quot;&gt;반면 Redis는 벡터 검색, JSON, TimeSeries 등 고급 기능이 내장되어 있어 AI/ML 워크로드나 복합적인 데이터베이스 용도로는 Redis가 더 적합할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2.3 커뮤니티와 지원&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Valkey&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;커뮤니티&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis Inc. 중심&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Linux Foundation, AWS, Google Cloud 등&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;엔터프라이즈 지원&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis Enterprise (상용)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;커뮤니티 기반 (CSP에서 관리형 서비스 제공)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;관리형 서비스&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis Cloud&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS ElastiCache, Google Memorystore 등&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;원 개발자&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;antirez 복귀 (2024, 에반젤리스트)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis 핵심 커미터 다수 참여&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. Valkey Helm Chart로 Kubernetes에 설치하기&lt;/span&gt;&lt;/h3&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;color: #000000;&quot;&gt;Valkey 공식 Helm Chart(&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/valkey-io/valkey-helm&quot;&gt;valkey-io/valkey-helm&lt;/a&gt;)를 사용하여 Kubernetes에 Standalone 모드로 배포하는 방법을 정리한다. Helmfile을 활용한 선언적 배포 방식을 사용한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3.1 사전 요구사항&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;Kubernetes 클러스터가 구성되어 있어야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kubectl과 helm이 설치 및 설정되어 있어야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;helmfile이 설치되어 있어야 한다. (선택)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PersistentVolume을 프로비저닝할 StorageClass가 필요하다. (예: local-path)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3.2 Helm Repository 추가&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vim&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;helm repo add valkey https://valkey.io/valkey-helm/
helm repo update&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3.3 Values 파일 작성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`values/valkey.values.yaml` 파일을 아래와 같이 작성한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;global:
  imageRegistry: &quot;&quot;
  imagePullSecrets: []

image:
  registry: &quot;docker.io&quot;
  repository: valkey/valkey
  pullPolicy: IfNotPresent
  tag: &quot;&quot;

# 리소스 이름 오버라이드
nameOverride: &quot;valkey-redis&quot;
fullnameOverride: &quot;valkey-redis&quot;

# 클러스터 도메인 (환경에 맞게 수정)
clusterDomain: my-cluster.local

service:
  # NodePort로 외부 접근 허용
  type: NodePort
  port: 6379
  annotations: {}
  # NodePort 포트 번호 (30000-32767 범위)
  nodePort: 30500
  clusterIP: &quot;&quot;
  loadBalancerClass: &quot;&quot;
  appProtocol: &quot;&quot;

networkPolicy: {}

# 리소스 제한 설정
resources:
  limits:
    cpu: 500m
    memory: 1024Mi
  requests:
    cpu: 100m
    memory: 256Mi

# 영구 스토리지 설정 (Standalone 모드)
dataStorage:
  enabled: true
  persistentVolumeClaimName: &quot;&quot;
  subPath: &quot;&quot;
  volumeName: &quot;valkey-data&quot;
  requestedSize: &quot;5Gi&quot;
  # 환경에 맞는 StorageClass 지정
  className: &quot;local-path&quot;
  accessModes:
    - ReadWriteOnce
  keepPvc: false
  annotations: {}
  labels: {}
  hostPath: &quot;&quot;

# 인증 설정 (필요 시 enabled: true로 변경)
auth:
  enabled: false

# 레플리카 설정 (Standalone이므로 비활성화)
replica:
  enabled: false

# TLS 설정
tls:
  enabled: false

# Pod가 배치될 노드 선택
nodeSelector:
  local-path: enabled

# 로그 레벨 설정
valkeyLogLevel: &quot;notice&quot;

env: {}

# Prometheus 메트릭 수집 (필요 시 활성화)
metrics:
  enabled: 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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;주요 설정 설명&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;service.type: NodePort &amp;mdash; 클러스터 외부에서 NodePort(30500)를 통해 접근할 수 있도록 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;dataStorage.enabled: true &amp;mdash; PVC를 생성하여 데이터를 영구적으로 저장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;dataStorage.className: &quot;local-path&quot; &amp;mdash; 환경에 맞는 StorageClass를 지정 (Rancher Local Path Provisioner 등)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;replica.enabled: false &amp;mdash; Standalone 모드로 단일 인스턴스 배포&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;auth.enabled: false &amp;mdash; 인증 비활성화 (프로덕션에서는 활성화 권장)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3.4 Helmfile 작성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`helmfile.yaml` 파일을 작성한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;repositories:
  - name: valkey
    url: https://valkey.io/valkey-helm/

releases:
  - name: valkey-redis
    chart: valkey/valkey
    namespace: my-db-redis
    version: 0.9.3
    values:
      - values/valkey.values.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3.5 배포&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Helmfile을 사용한 배포
helmfile sync

# 또는 Helm 직접 사용
helm install valkey-redis valkey/valkey \
  --namespace my-db-redis \
  --create-namespace \
  --version 0.9.3 \
  -f values/valkey.values.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3.6 배포 확인&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Pod 상태 확인
kubectl get pods -n my-db-redis

# 출력 예시
# NAME                            READY   STATUS    RESTARTS   AGE
# valkey-redis-0                  1/1     Running   0          2m

# Service 확인
kubectl get svc -n my-db-redis

# 출력 예시
# NAME           TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
# valkey-redis   NodePort   10.96.xxx.xxx   &amp;lt;none&amp;gt;        6379:30500/TCP   2m&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3.7 접속 테스트&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;redis-cli를 사용하여 Valkey에 접속할 수 있다. Valkey는 Redis 프로토콜과 호환되므로 기존 Redis 클라이언트를 그대로 사용하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;avrasm&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# NodePort를 통한 접속 (노드 IP와 NodePort 사용)
redis-cli -h &amp;lt;NODE_IP&amp;gt; -p 30500&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# PING 테스트
&amp;lt;NODE_IP&amp;gt;:30500&amp;gt; PING
PONG

# 서버 정보 확인
&amp;lt;NODE_IP&amp;gt;:30500&amp;gt; INFO server
# Server
redis_version:7.2.4
server_name:valkey
valkey_version:9.0.1
...
server_mode:standalone
...
tcp_port:6379&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;`INFO server` 출력에서 `server_name:valkey` 와 `valkey_version:9.0.1` 을 통해 Valkey가 정상적으로 동작하고 있음을 확인할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`redis_version:7.2.4` 는 Redis 프로토콜 호환성을 위해 표시되는 값이다.&lt;/span&gt;&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;&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;color: #000000;&quot;&gt;4. 디렉토리 구조&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최종적인 프로젝트 디렉토리 구조는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;maxima&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;valkey/
├── helmfile.yaml
└── values/
    └── valkey.values.yaml&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;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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis의 라이선스 변경은 오픈소스 생태계에 큰 파장을 일으켰고, 그 결과 Valkey라는 강력한 대안이 등장했다. Valkey는 단순히 Redis의 포크를 넘어서 멀티스레딩 최적화, 메모리 효율성 개선, RDMA 지원 등 독자적인 기술 혁신을 추진하고 있다.&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;color: #000000;&quot;&gt;특히 BSD 3-Clause 라이선스를 유지하면서 Linux Foundation의 거버넌스 아래 운영되기 때문에, 라이선스 변경에 대한 불확실성 없이 안심하고 사용할 수 있다는 것이 가장 큰 장점이다. AWS ElastiCache, Google Memorystore 등 주요 클라우드 서비스에서도 Valkey를 공식 지원하고 있어, 클라우드 환경에서의 생태계도 빠르게 확장되고 있다.&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;color: #000000;&quot;&gt;캐싱, 세션 관리, 메시지 큐 등 전통적인 인메모리 데이터 스토어 워크로드라면 Valkey는 Redis를 대체할 수 있는 충분한 역량을 갖추고 있다. 다만 벡터 검색, JSON, TimeSeries 등 Redis의 고급 모듈이 필요한 경우에는 Redis를 선택하는 것이 더 적합할 수 있다.&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;color: #000000;&quot;&gt;새로운 프로젝트를 시작하거나, Redis 라이선스 문제로 대안을 찾고 있다면 Valkey를 적극 검토해볼 것을 권장한다.&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;&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;
&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://valkey.io/&quot;&gt;Valkey 공식 사이트&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/valkey-io/valkey&quot;&gt;Valkey GitHub Repository&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/valkey-io/valkey-helm&quot;&gt;Valkey Helm Chart GitHub&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://valkey.io/blog/valkey-helm-chart/&quot;&gt;Valkey Helm Chart Blog&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://betterstack.com/community/comparisons/redis-vs-valkey/&quot;&gt;Redis vs Valkey - Better Stack&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.percona.com/blog/choosing-the-right-key-value-store-redis-vs-valkey/&quot;&gt;Redis vs Valkey - Percona&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://aws.amazon.com/elasticache/redis/&quot;&gt;Redis vs Valkey - AWS&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.dragonflydb.io/blog/redis-8-0-vs-valkey-8-1-a-technical-comparison&quot;&gt;Redis 8.0 vs Valkey 8.1 Technical Comparison - DragonflyDB&lt;/a&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Database</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/489</guid>
      <comments>https://somaz.tistory.com/489#entry489comment</comments>
      <pubDate>Wed, 25 Feb 2026 00:00:37 +0900</pubDate>
    </item>
    <item>
      <title>AWS CDN: CloudFront vs Global Accelerator - 글로벌 콘텐츠 전송 최적화 완벽 가이드</title>
      <link>https://somaz.tistory.com/456</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;AWS는 이러한 요구사항을 충족하기 위해 CloudFront와 Global Accelerator라는 두 가지 주요 서비스를 제공&lt;/b&gt;&lt;/u&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;color: #000000;&quot;&gt;CloudFront는 전통적인 CDN(Content Delivery Network) 서비스로, 정적 및 동적 콘텐츠를 전 세계 엣지 로케이션에 캐싱하여 사용자에게 더 가까운 위치에서 콘텐츠를 제공한다. 반면 Global Accelerator는 네트워크 계층에서 작동하여 AWS의 글로벌 네트워크 인프라를 통해 트래픽을 최적화된 경로로 라우팅한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 글에서는 두 서비스의 특징, 성능 개선 전략, 그리고 비용 효율성을 상세히 분석하여 각각의 적절한 사용 사례를 제시하고자 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GfiLJ/dJMb99ZnEF3/aWj9KpXMdxQIRrDkNYgPfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GfiLJ/dJMb99ZnEF3/aWj9KpXMdxQIRrDkNYgPfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GfiLJ/dJMb99ZnEF3/aWj9KpXMdxQIRrDkNYgPfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGfiLJ%2FdJMb99ZnEF3%2FaWj9KpXMdxQIRrDkNYgPfK%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  관련 글&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/37&quot;&gt;2022.02.13 - [AWS] - AWS IAM (Identity and Access Management) 개요 및 설정 방법&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/30&quot;&gt;2022.02.07 - [AWS] - AWS EC2 인스턴스 생성&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/38&quot;&gt;2022.02.13 - [AWS] - AWS S3 (Simple Storage Service) 개요 및 활용 방법&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/183&quot;&gt;2023.03.30 - [AWS] - AWS Secrets Manager란?(OAuth, SSO)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/182&quot;&gt;2023.03.29 - [AWS] - AWS CLI 정리&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/181&quot;&gt;2023.03.28 - [AWS] - AWS IAM이란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/180&quot;&gt;2023.03.28 - [AWS] - AWS S3 권한이란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/179&quot;&gt;2023.03.28 - [AWS] - AWS S3란?(개념, 속성)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/184&quot;&gt;2023.03.30 - [AWS] - AWS Cloudfront란? / Canary 및 Blue-Green 배포&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/188&quot;&gt;2023.04.03 - [AWS] - AWS VPC란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/238&quot;&gt;2023.05.26 - [AWS] - AWS IRSA(IAM Roles for Service Accounts)란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/340&quot;&gt;2024.11.07 - [AWS] - AWS Ingress Annotations 정리&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/337&quot;&gt;2024.11.04 - [AWS] - AWS Assume Role이란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/349&quot;&gt;2024.11.16 - [AWS] - AWS Network ACL vs Security Group&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/354&quot;&gt;2024.11.21 - [AWS] - ALB access Log 활성화 &amp;rarr; S3 권한 설정 및 로그 저장&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/357&quot;&gt;2024.11.24 - [AWS] - EKS Pod Identity Addon&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/360&quot;&gt;2024.11.27 - [AWS] - AWS DynamoDB란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/364&quot;&gt;2025.01.03 - [AWS] - AWS DynamoDB Local 설치&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/447&quot;&gt;2025.09.02 - [AWS] - AWS EFS와 Kubernetes를 활용한 영구 스토리지 구축 가이드&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/452&quot;&gt;2025.09.05 - [AWS] - AWS CDN 구축 가이드: Kubernetes + AWS CloudFront로 API와 정적 파일 서빙 최적화&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/453&quot;&gt;2025.09.05 - [AWS] - AWS 네트워크 연결 방식 완전 비교: VPC Peering vs Transit Gateway vs VPN&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/451&quot;&gt;2025.09.04 - [AWS] - AWS Load Balancer 완전 비교 가이드&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/455&quot;&gt;2025.09.10 - [AWS] - EKS Fargate vs EC2 Node Groups 완전 분석 - Kubernetes 워커 노드 옵션&lt;/a&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS&amp;nbsp;CDN:&amp;nbsp;CloudFront&amp;nbsp;vs&amp;nbsp;Global&amp;nbsp;Accelerator&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3220&quot; data-origin-height=&quot;770&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cX28Kg/btsQt9yprrZ/NPJ60mZ6QHwZ7Ei2cvUCk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cX28Kg/btsQt9yprrZ/NPJ60mZ6QHwZ7Ei2cvUCk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cX28Kg/btsQt9yprrZ/NPJ60mZ6QHwZ7Ei2cvUCk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcX28Kg%2FbtsQt9yprrZ%2FNPJ60mZ6QHwZ7Ei2cvUCk1%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;3220&quot; height=&quot;770&quot; data-origin-width=&quot;3220&quot; data-origin-height=&quot;770&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront: 전통적인 CDN의 진화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 특징 및 작동 원리&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront는 AWS의 대표적인 CDN 서비스로, 전 세계 400개 이상의 엣지 로케이션과 13개의 리전별 엣지 캐시를 통해 콘텐츠를 배포한다. 사용자가 콘텐츠를 요청하면, CloudFront는 지리적으로 가장 가까운 엣지 로케이션에서 캐시된 콘텐츠를 제공하거나, 캐시에 없는 경우 오리진 서버에서 가져와 캐시한 후 제공한다.&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;color: #000000;&quot;&gt;CloudFront의 핵심 장점은 캐싱 메커니즘에 있다. HTTP 헤더, 쿠키, 쿼리 스트링 등을 기반으로 세밀한 캐싱 정책을 설정할 수 있으며, 이를 통해 오리진 서버의 부하를 현저히 줄일 수 있다. 또한 Lambda@Edge를 통해 엣지에서 직접 코드를 실행할 수 있어, 개인화된 콘텐츠 제공이나 실시간 이미지 리사이징 등의 고급 기능을 구현할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront의 성능 최적화 전략&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront의 성능을 극대화하기 위해서는 적절한 캐싱 전략 수립이 핵심이다. TTL(Time To Live) 설정을 통해 콘텐츠 유형별로 차별화된 캐싱 정책을 적용하는 것이 중요하다. 정적 자산의 경우 긴 TTL을, 동적 콘텐츠의 경우 짧은 TTL을 설정하여 최적의 성능과 콘텐츠 신선도를 보장할 수 있다.&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;color: #000000;&quot;&gt;압축 기능을 활성화하면 전송되는 데이터 크기를 줄여 대역폭 사용량을 최적화하고 로딩 속도를 개선할 수 있다. 특히 텍스트 기반 콘텐츠에 대해서는 Gzip 압축을 통해 70-80%의 크기 절감 효과를 얻을 수 있다.&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;color: #000000;&quot;&gt;Origin Request Policy와 Cache Policy를 통해 세밀한 캐싱 제어가 가능하다. 이를 통해 사용자의 위치, 디바이스 타입, 언어 설정 등에 따른 개인화된 캐싱 전략을 구현할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Content Delivery Flow&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1646&quot; data-origin-height=&quot;1620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGxSfz/btsQsmMsUGN/0xixs4KRVPgqeSt9lceqp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGxSfz/btsQsmMsUGN/0xixs4KRVPgqeSt9lceqp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGxSfz/btsQsmMsUGN/0xixs4KRVPgqeSt9lceqp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGxSfz%2FbtsQsmMsUGN%2F0xixs4KRVPgqeSt9lceqp1%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;1646&quot; height=&quot;1620&quot; data-origin-width=&quot;1646&quot; data-origin-height=&quot;1620&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;&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;
&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Accelerator: 네트워크 최적화의 새로운 접근&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 기능 및 작동 메커니즘&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Accelerator는 애플리케이션 성능을 개선하기 위해 AWS의 글로벌 네트워크 인프라를 활용하는 네트워크 서비스이다. 사용자 트래픽을 AWS의 글로벌 백본 네트워크로 빠르게 유입시켜, 공용 인터넷의 혼잡과 지연을 우회하는 방식으로 작동한다.&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;color: #000000;&quot;&gt;Global Accelerator는 두 개의 정적 Anycast IP 주소를 제공한다. 이 IP 주소들은 전 세계 어디서나 접근 가능하며, 사용자와 가장 가까운 AWS 엣지 로케이션으로 자동 라우팅된다. 이후 트래픽은 AWS의 고성능 네트워크를 통해 최종 목적지인 Application Load Balancer, Network Load Balancer, 또는 EC2 인스턴스로 전달된다.&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;color: #000000;&quot;&gt;특히 실시간 애플리케이션이나 TCP/UDP 기반 서비스에 최적화되어 있으며, 게임, VoIP, 스트리밍과 같은 지연 시간에 민감한 애플리케이션에서 뛰어난 성능을 발휘한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Accelerator의 성능 최적화 요소&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Accelerator의 가장 큰 장점은 AWS 글로벌 네트워크의 일관된 성능이다. 공용 인터넷을 통한 라우팅은 여러 ISP를 거치면서 예측 불가능한 지연과 패킷 손실을 경험할 수 있지만, Global Accelerator는 AWS의 사설 네트워크를 통해 안정적이고 예측 가능한 성능을 제공한다.&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;color: #000000;&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;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Network Acceleration Flow&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1338&quot; data-origin-height=&quot;1668&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DLAMi/btsQshK1PF3/0q39vkEgOeRj862JWQDRu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DLAMi/btsQshK1PF3/0q39vkEgOeRj862JWQDRu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DLAMi/btsQshK1PF3/0q39vkEgOeRj862JWQDRu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDLAMi%2FbtsQshK1PF3%2F0q39vkEgOeRj862JWQDRu0%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;1338&quot; height=&quot;1668&quot; data-origin-width=&quot;1338&quot; data-origin-height=&quot;1668&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 비교 분석&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지연 시간 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront는 캐싱을 통한 지연 시간 단축에 특화되어 있다. 캐시 적중률이 높은 콘텐츠의 경우 엣지에서 직접 응답하므로 매우 낮은 지연 시간을 제공한다. 반면 캐시 미스가 발생하면 오리진까지 왕복해야 하므로 상대적으로 높은 지연 시간을 경험할 수 있다.&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;color: #000000;&quot;&gt;Global Accelerator는 모든 요청이 AWS 글로벌 네트워크를 통과하므로 일관된 성능을 제공한다. 캐시 개념이 없기 때문에 모든 요청이 백엔드까지 전달되지만, 최적화된 네트워크 경로를 통해 일반적으로 공용 인터넷 대비 15-60%의 성능 개선을 달성한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처리량 및 동시 연결&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront는 HTTP/HTTPS 트래픽에 최적화되어 있으며, 캐싱을 통해 오리진 서버의 부하를 대폭 줄일 수 있다. 이는 특히 트래픽이 급증하는 상황에서 시스템 안정성을 보장하는 핵심 요소가 된다.&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;color: #000000;&quot;&gt;Global Accelerator는 TCP 및 UDP 트래픽을 모두 지원하며, 연결 재사용과 멀티플렉싱을 통해 네트워크 효율성을 높인다. 실시간 통신이나 게임과 같은 애플리케이션에서 특히 우수한 성능을 보인다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 효율성 분석&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront 비용 구조&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront의 비용은 주로 데이터 전송량과 요청 수를 기반으로 계산된다. 캐시 적중률이 높을수록 오리진으로의 요청이 줄어들어 비용 효율성이 증가한다. 특히 정적 콘텐츠가 많은 웹사이트의 경우 매우 경제적인 선택이 될 수 있다.&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;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Accelerator 비용 구조&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Accelerator는 고정 시간당 요금과 데이터 전송 요금으로 구성된다. 시간당 요금은 사용 여부와 관계없이 발생하므로, 트래픽이 적은 서비스에서는 상대적으로 높은 비용 부담이 될 수 있다.&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;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 전략&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;두 서비스를 함께 사용하는 하이브리드 접근 방식이 가장 효율적일 수 있다. 정적 콘텐츠는 CloudFront를 통해 제공하고, 동적 API나 실시간 통신은 Global Accelerator를 활용하는 방식으로 각 서비스의 장점을 최대화할 수 있다.&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;color: #000000;&quot;&gt;Reserved Capacity를 통해 예상 사용량에 대해 사전 약정하면 상당한 할인 혜택을 받을 수 있으며, 이는 안정적인 트래픽 패턴을 가진 서비스에서 유용한 전략이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 구현을 위한 Terraform 코드&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront 배포 코드&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# CloudFront Distribution 구성
resource &quot;aws_cloudfront_distribution&quot; &quot;main_distribution&quot; {
  origin {
    domain_name = aws_lb.main_alb.dns_name
    origin_id   = &quot;main-origin&quot;
    
    custom_origin_config {
      http_port              = 80
      https_port             = 443
      origin_protocol_policy = &quot;https-only&quot;
      origin_ssl_protocols   = [&quot;TLSv1.2&quot;]
    }
  }

  enabled             = true
  is_ipv6_enabled     = true
  comment             = &quot;Main CloudFront Distribution&quot;
  default_root_object = &quot;index.html&quot;

  # 캐싱 동작 설정
  default_cache_behavior {
    allowed_methods        = [&quot;DELETE&quot;, &quot;GET&quot;, &quot;HEAD&quot;, &quot;OPTIONS&quot;, &quot;PATCH&quot;, &quot;POST&quot;, &quot;PUT&quot;]
    cached_methods         = [&quot;GET&quot;, &quot;HEAD&quot;]
    target_origin_id       = &quot;main-origin&quot;
    compress               = true
    viewer_protocol_policy = &quot;redirect-to-https&quot;

    forwarded_values {
      query_string = false
      cookies {
        forward = &quot;none&quot;
      }
    }

    min_ttl     = 0
    default_ttl = 3600
    max_ttl     = 86400
  }

  # 추가 캐싱 동작 (API 엔드포인트용)
  ordered_cache_behavior {
    path_pattern           = &quot;/api/*&quot;
    allowed_methods        = [&quot;DELETE&quot;, &quot;GET&quot;, &quot;HEAD&quot;, &quot;OPTIONS&quot;, &quot;PATCH&quot;, &quot;POST&quot;, &quot;PUT&quot;]
    cached_methods         = [&quot;GET&quot;, &quot;HEAD&quot;, &quot;OPTIONS&quot;]
    target_origin_id       = &quot;main-origin&quot;
    compress               = true
    viewer_protocol_policy = &quot;redirect-to-https&quot;

    forwarded_values {
      query_string = true
      headers      = [&quot;Authorization&quot;, &quot;CloudFront-Forwarded-Proto&quot;]
      cookies {
        forward = &quot;all&quot;
      }
    }

    min_ttl     = 0
    default_ttl = 0
    max_ttl     = 0
  }

  # 지리적 제한 설정
  restrictions {
    geo_restriction {
      restriction_type = &quot;none&quot;
    }
  }

  # SSL 인증서 설정
  viewer_certificate {
    cloudfront_default_certificate = true
  }

  # 로깅 설정
  logging_config {
    include_cookies = false
    bucket          = aws_s3_bucket.cloudfront_logs.bucket_domain_name
    prefix          = &quot;cloudfront-logs/&quot;
  }

  tags = {
    Name        = &quot;main-cloudfront&quot;
    Environment = &quot;production&quot;
  }
}

# CloudFront 로그용 S3 버킷
resource &quot;aws_s3_bucket&quot; &quot;cloudfront_logs&quot; {
  bucket        = &quot;my-cloudfront-logs-${random_string.suffix.result}&quot;
  force_destroy = true

  tags = {
    Name        = &quot;CloudFront Logs&quot;
    Environment = &quot;production&quot;
  }
}

resource &quot;aws_s3_bucket_public_access_block&quot; &quot;cloudfront_logs&quot; {
  bucket = aws_s3_bucket.cloudfront_logs.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# Lambda@Edge 함수 (선택적)
resource &quot;aws_lambda_function&quot; &quot;edge_function&quot; {
  filename         = &quot;edge_function.zip&quot;
  function_name    = &quot;cloudfront-edge-function&quot;
  role            = aws_iam_role.lambda_edge_role.arn
  handler         = &quot;index.handler&quot;
  source_code_hash = filebase64sha256(&quot;edge_function.zip&quot;)
  runtime         = &quot;nodejs18.x&quot;
  publish         = true

  tags = {
    Environment = &quot;production&quot;
  }
}

# Lambda@Edge용 IAM 역할
resource &quot;aws_iam_role&quot; &quot;lambda_edge_role&quot; {
  name = &quot;lambda-edge-role&quot;

  assume_role_policy = jsonencode({
    Version = &quot;2012-10-17&quot;
    Statement = [
      {
        Action = &quot;sts:AssumeRole&quot;
        Effect = &quot;Allow&quot;
        Principal = {
          Service = [
            &quot;lambda.amazonaws.com&quot;,
            &quot;edgelambda.amazonaws.com&quot;
          ]
        }
      }
    ]
  })
}

resource &quot;aws_iam_role_policy_attachment&quot; &quot;lambda_edge_basic&quot; {
  policy_arn = &quot;arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole&quot;
  role       = aws_iam_role.lambda_edge_role.name
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Accelerator 배포 코드&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# Global Accelerator 구성
resource &quot;aws_globalaccelerator_accelerator&quot; &quot;main_accelerator&quot; {
  name            = &quot;main-global-accelerator&quot;
  ip_address_type = &quot;IPV4&quot;
  enabled         = true

  attributes {
    flow_logs_enabled   = true
    flow_logs_s3_bucket = aws_s3_bucket.accelerator_logs.bucket
    flow_logs_s3_prefix = &quot;flow-logs/&quot;
  }

  tags = {
    Name        = &quot;main-accelerator&quot;
    Environment = &quot;production&quot;
  }
}

# Global Accelerator 리스너 구성
resource &quot;aws_globalaccelerator_listener&quot; &quot;main_listener&quot; {
  accelerator_arn = aws_globalaccelerator_accelerator.main_accelerator.id
  client_affinity = &quot;SOURCE_IP&quot;
  protocol        = &quot;TCP&quot;

  port_range {
    from = 80
    to   = 80
  }

  port_range {
    from = 443
    to   = 443
  }
}

# 엔드포인트 그룹 구성 (주 리전)
resource &quot;aws_globalaccelerator_endpoint_group&quot; &quot;main_endpoint_group&quot; {
  listener_arn = aws_globalaccelerator_listener.main_listener.id

  endpoint_group_region = &quot;us-west-2&quot;
  traffic_dial_percentage = 100

  health_check_interval_seconds = 30
  health_check_path            = &quot;/health&quot;
  health_check_protocol        = &quot;HTTP&quot;
  health_check_port            = 80
  healthy_threshold_count      = 3
  unhealthy_threshold_count    = 3

  endpoint_configuration {
    endpoint_id = aws_lb.main_alb.arn
    weight      = 100
  }
}

# 백업 엔드포인트 그룹 구성 (보조 리전)
resource &quot;aws_globalaccelerator_endpoint_group&quot; &quot;backup_endpoint_group&quot; {
  listener_arn = aws_globalaccelerator_listener.main_listener.id

  endpoint_group_region = &quot;us-east-1&quot;
  traffic_dial_percentage = 0  # 평상시에는 비활성화

  health_check_interval_seconds = 30
  health_check_path            = &quot;/health&quot;
  health_check_protocol        = &quot;HTTP&quot;
  health_check_port            = 80
  healthy_threshold_count      = 3
  unhealthy_threshold_count    = 3

  endpoint_configuration {
    endpoint_id = aws_lb.backup_alb.arn
    weight      = 100
  }
}

# Global Accelerator 로그용 S3 버킷
resource &quot;aws_s3_bucket&quot; &quot;accelerator_logs&quot; {
  bucket        = &quot;my-accelerator-logs-${random_string.suffix.result}&quot;
  force_destroy = true

  tags = {
    Name        = &quot;Global Accelerator Logs&quot;
    Environment = &quot;production&quot;
  }
}

# Application Load Balancer (주 리전)
resource &quot;aws_lb&quot; &quot;main_alb&quot; {
  name               = &quot;main-alb&quot;
  internal           = false
  load_balancer_type = &quot;application&quot;
  security_groups    = [aws_security_group.alb_sg.id]
  subnets           = aws_subnet.public[*].id

  enable_deletion_protection = false

  access_logs {
    bucket  = aws_s3_bucket.alb_logs.bucket
    prefix  = &quot;main-alb&quot;
    enabled = true
  }

  tags = {
    Name        = &quot;main-alb&quot;
    Environment = &quot;production&quot;
  }
}

# 타겟 그룹 구성
resource &quot;aws_lb_target_group&quot; &quot;main_tg&quot; {
  name     = &quot;main-tg&quot;
  port     = 80
  protocol = &quot;HTTP&quot;
  vpc_id   = aws_vpc.main.id

  health_check {
    enabled             = true
    healthy_threshold   = 2
    interval            = 30
    matcher             = &quot;200&quot;
    path                = &quot;/health&quot;
    port                = &quot;traffic-port&quot;
    protocol            = &quot;HTTP&quot;
    timeout             = 5
    unhealthy_threshold = 2
  }

  tags = {
    Name        = &quot;main-tg&quot;
    Environment = &quot;production&quot;
  }
}

# ALB 리스너 구성
resource &quot;aws_lb_listener&quot; &quot;main_listener&quot; {
  load_balancer_arn = aws_lb.main_alb.arn
  port              = &quot;80&quot;
  protocol          = &quot;HTTP&quot;

  default_action {
    type             = &quot;forward&quot;
    target_group_arn = aws_lb_target_group.main_tg.arn
  }
}

# 보안 그룹 구성
resource &quot;aws_security_group&quot; &quot;alb_sg&quot; {
  name        = &quot;alb-security-group&quot;
  description = &quot;Security group for Application Load Balancer&quot;
  vpc_id      = aws_vpc.main.id

  ingress {
    description = &quot;HTTP&quot;
    from_port   = 80
    to_port     = 80
    protocol    = &quot;tcp&quot;
    cidr_blocks = [&quot;0.0.0.0/0&quot;]
  }

  ingress {
    description = &quot;HTTPS&quot;
    from_port   = 443
    to_port     = 443
    protocol    = &quot;tcp&quot;
    cidr_blocks = [&quot;0.0.0.0/0&quot;]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = &quot;-1&quot;
    cidr_blocks = [&quot;0.0.0.0/0&quot;]
  }

  tags = {
    Name        = &quot;alb-sg&quot;
    Environment = &quot;production&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하이브리드 구성 및 모니터링&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# CloudWatch 대시보드 구성
resource &quot;aws_cloudwatch_dashboard&quot; &quot;cdn_performance&quot; {
  dashboard_name = &quot;CDN-Performance-Dashboard&quot;

  dashboard_body = jsonencode({
    widgets = [
      {
        type   = &quot;metric&quot;
        x      = 0
        y      = 0
        width  = 12
        height = 6

        properties = {
          metrics = [
            [&quot;AWS/CloudFront&quot;, &quot;Requests&quot;, &quot;DistributionId&quot;, aws_cloudfront_distribution.main_distribution.id],
            [&quot;AWS/CloudFront&quot;, &quot;BytesDownloaded&quot;, &quot;DistributionId&quot;, aws_cloudfront_distribution.main_distribution.id],
            [&quot;AWS/CloudFront&quot;, &quot;CacheHitRate&quot;, &quot;DistributionId&quot;, aws_cloudfront_distribution.main_distribution.id]
          ]
          period = 300
          stat   = &quot;Sum&quot;
          region = &quot;us-east-1&quot;
          title  = &quot;CloudFront Performance Metrics&quot;
        }
      },
      {
        type   = &quot;metric&quot;
        x      = 0
        y      = 6
        width  = 12
        height = 6

        properties = {
          metrics = [
            [&quot;AWS/GlobalAccelerator&quot;, &quot;ProcessedBytesIn&quot;, &quot;Accelerator&quot;, aws_globalaccelerator_accelerator.main_accelerator.id],
            [&quot;AWS/GlobalAccelerator&quot;, &quot;ProcessedBytesOut&quot;, &quot;Accelerator&quot;, aws_globalaccelerator_accelerator.main_accelerator.id]
          ]
          period = 300
          stat   = &quot;Sum&quot;
          region = &quot;us-west-2&quot;
          title  = &quot;Global Accelerator Traffic Metrics&quot;
        }
      }
    ]
  })
}

# CloudWatch 경보 설정
resource &quot;aws_cloudwatch_metric_alarm&quot; &quot;cloudfront_error_rate&quot; {
  alarm_name          = &quot;cloudfront-high-error-rate&quot;
  comparison_operator = &quot;GreaterThanThreshold&quot;
  evaluation_periods  = &quot;2&quot;
  metric_name         = &quot;ErrorRate&quot;
  namespace           = &quot;AWS/CloudFront&quot;
  period              = &quot;300&quot;
  statistic           = &quot;Average&quot;
  threshold           = &quot;5&quot;
  alarm_description   = &quot;This metric monitors CloudFront error rate&quot;
  alarm_actions       = [aws_sns_topic.alerts.arn]

  dimensions = {
    DistributionId = aws_cloudfront_distribution.main_distribution.id
  }

  tags = {
    Environment = &quot;production&quot;
  }
}

# SNS 토픽 (알림용)
resource &quot;aws_sns_topic&quot; &quot;alerts&quot; {
  name = &quot;cdn-alerts&quot;

  tags = {
    Environment = &quot;production&quot;
  }
}

# 랜덤 문자열 생성 (버킷 이름 고유성 보장)
resource &quot;random_string&quot; &quot;suffix&quot; {
  length  = 8
  special = false
  upper   = false
}

# 출력값 정의
output &quot;cloudfront_domain_name&quot; {
  description = &quot;CloudFront Distribution domain name&quot;
  value       = aws_cloudfront_distribution.main_distribution.domain_name
}

output &quot;global_accelerator_dns_name&quot; {
  description = &quot;Global Accelerator DNS name&quot;
  value       = aws_globalaccelerator_accelerator.main_accelerator.dns_name
}

output &quot;global_accelerator_ips&quot; {
  description = &quot;Global Accelerator static IP addresses&quot;
  value       = aws_globalaccelerator_accelerator.main_accelerator.ip_sets[0].ip_addresses
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;적절한 사용 사례 및 선택 가이드&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront 최적 사용 사례&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront는 웹사이트, 이미지 갤러리, 동영상 스트리밍 서비스와 같이 캐싱 가능한 콘텐츠가 많은 서비스에 최적화되어 있다. 특히 정적 자산이 전체 트래픽의 상당 부분을 차지하는 경우 매우 높은 비용 효율성을 제공한다.&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;color: #000000;&quot;&gt;또한 Lambda@Edge를 활용한 엣지 컴퓨팅이 필요한 경우에도 CloudFront가 유일한 선택이다. 이미지 리사이징, A/B 테스팅, 보안 헤더 추가 등의 작업을 엣지에서 처리하여 오리진 서버의 부하를 줄이고 응답 속도를 개선할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Accelerator 최적 사용 사례&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Accelerator는 게임 서버, VoIP 애플리케이션, IoT 데이터 수집과 같이 실시간성이 중요하고 TCP/UDP 프로토콜을 사용하는 서비스에 적합하다. 또한 지역별로 복잡한 장애 조치 시나리오가 필요한 글로벌 서비스에서 그 진가를 발휘한다.&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;color: #000000;&quot;&gt;API 서비스의 경우 캐싱이 어려운 동적 콘텐츠가 주를 이루므로, Global Accelerator를 통한 네트워크 최적화가 더 효과적일 수 있다. 특히 데이터베이스 쿼리나 복잡한 비즈니스 로직이 포함된 API 호출에서 안정적인 성능 개선을 기대할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하이브리드 접근 방식&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;많은 현실적인 시나리오에서는 두 서비스를 함께 사용하는 것이 최적의 결과를 낳는다. 예를 들어, 웹 애플리케이션의 정적 자산(CSS, JavaScript, 이미지)은 CloudFront를 통해 전송하고, API 엔드포인트는 Global Accelerator를 통해 최적화하는 방식이다.&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;color: #000000;&quot;&gt;이러한 접근 방식은 각 서비스의 장점을 최대한 활용하면서도 전체적인 비용 효율성을 유지할 수 있는 균형잡힌 솔루션을 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2738&quot; data-origin-height=&quot;1666&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4naSw/btsQt2e3i6k/KzTrDlDIz0fhix4t9QkoPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4naSw/btsQt2e3i6k/KzTrDlDIz0fhix4t9QkoPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4naSw/btsQt2e3i6k/KzTrDlDIz0fhix4t9QkoPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4naSw%2FbtsQt2e3i6k%2FKzTrDlDIz0fhix4t9QkoPK%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;2738&quot; height=&quot;1666&quot; data-origin-width=&quot;2738&quot; data-origin-height=&quot;1666&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 측정 및 모니터링&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront 성능 지표&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront의 성능을 평가하기 위한 핵심 지표로는 캐시 적중률, 오리진 응답 시간, 엣지 응답 시간이 있다. 캐시 적중률이 높을수록 사용자 경험과 비용 효율성이 개선되므로, 이를 지속적으로 모니터링하고 최적화해야 한다.&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;color: #000000;&quot;&gt;Real User Monitoring(RUM)을 통해 실제 사용자가 경험하는 성능을 측정하는 것도 중요하다. CloudWatch RUM을 활용하면 페이지 로딩 시간, 자바스크립트 오류, 사용자 상호작용 등을 상세히 분석할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Accelerator 성능 지표&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Accelerator의 성능 측정에는 네트워크 지연 시간, 패킷 손실률, 연결 성공률이 핵심 지표가 된다. AWS CloudWatch를 통해 이러한 지표들을 실시간으로 모니터링할 수 있으며, 특히 지역별 성능 차이를 분석하여 최적화 포인트를 찾을 수 있다.&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;color: #000000;&quot;&gt;Flow Logs를 활성화하면 트래픽 패턴과 엔드포인트별 성능을 상세히 분석할 수 있다. 이를 통해 트래픽 분산 정책을 조정하고 장애 조치 시나리오를 개선할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;통합 모니터링 전략&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;두 서비스를 함께 사용하는 경우, 통합된 모니터링 대시보드를 구성하여 전체적인 성능 트렌드를 파악하는 것이 중요하다. CloudWatch 대시보드를 통해 CloudFront와 Global Accelerator의 주요 지표를 한 곳에서 확인할 수 있으며, 이를 통해 문제 발생 시 신속한 대응이 가능하다.&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;&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 고려사항&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront 보안 기능&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront는 다양한 보안 기능을 제공하여 콘텐츠와 애플리케이션을 보호한다. AWS WAF(Web Application Firewall)를 연동하여 SQL 인젝션, XSS 공격 등을 차단할 수 있으며, 지리적 제한을 통해 특정 국가나 지역에서의 접근을 제어할 수 있다.&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;color: #000000;&quot;&gt;Origin Access Control(OAC)을 통해 S3 버킷에 대한 직접 접근을 차단하고 CloudFront를 통해서만 콘텐츠에 접근할 수 있도록 설정할 수 있다. 또한 Signed URL과 Signed Cookie를 활용하여 프리미엄 콘텐츠에 대한 접근 제어를 구현할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Accelerator 보안 고려사항&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Accelerator는 네트워크 계층에서 작동하므로 DDoS 공격에 대한 기본적인 보호 기능을 제공한다. AWS Shield Standard가 자동으로 적용되며, 필요에 따라 Shield Advanced를 통해 고급 DDoS 보호 기능을 활용할 수 있다.&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;color: #000000;&quot;&gt;엔드포인트로 사용되는 Load Balancer나 EC2 인스턴스의 보안 그룹 설정을 통해 추가적인 네트워크 레벨 보안을 구현할 수 있다. 특히 Global Accelerator의 IP 주소 범위만 허용하도록 설정하여 보안을 강화할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마이그레이션 및 구현 전략&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단계적 마이그레이션 접근법&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 인프라에서 CloudFront나 Global Accelerator로 마이그레이션할 때는 단계적 접근법을 사용하는 것이 안전하다. 먼저 트래픽의 일부분만 새로운 서비스로 라우팅하고, 성능과 안정성을 확인한 후 점진적으로 비율을 늘려가는 방식을 권장한다.&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;color: #000000;&quot;&gt;DNS 가중치 기반 라우팅을 활용하면 트래픽을 단계적으로 이전할 수 있으며, 문제 발생 시 빠른 롤백이 가능하다. Route 53의 헬스 체크 기능과 연동하면 자동 장애 조치도 구현할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 테스트 및 검증&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;특히 캐싱 정책이나 TTL 설정과 같은 구성 요소들은 실제 운영 환경에서의 동작을 정확히 예측하기 어려우므로, 프로덕션과 유사한 환경에서의 테스트가 필수적이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;미래 발전 방향 및 신기술 동향&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Edge Computing의 확산&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront의 Lambda@Edge와 CloudFront Functions는 엣지 컴퓨팅의 새로운 가능성을 열어주고 있다. 앞으로는 더 복잡한 비즈니스 로직을 엣지에서 처리하여 지연 시간을 줄이고 사용자 경험을 개선하는 방향으로 발전할 것으로 예상된다.&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;color: #000000;&quot;&gt;특히 개인화 서비스, 실시간 이미지 처리, A/B 테스팅과 같은 기능들이 엣지에서 더욱 효율적으로 구현될 것이며, 이는 중앙 서버의 부하를 크게 줄이는 동시에 응답 속도를 향상시킬 것이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5G와 IoT 환경에서의 활용&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5G 네트워크의 확산과 IoT 디바이스의 급증은 CDN과 네트워크 가속화 서비스에 새로운 요구사항을 제시하고 있다. 초저지연 통신이 필요한 자율주행, 증강현실, 원격수술과 같은 애플리케이션에서 CloudFront와 Global Accelerator의 역할이 더욱 중요해질 것이다.&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;color: #000000;&quot;&gt;특히 Global Accelerator의 경우 TCP 및 UDP 트래픽 최적화 기능을 통해 IoT 디바이스 간의 실시간 통신을 효율적으로 지원할 수 있으며, 이는 스마트 시티나 인더스트리 4.0과 같은 대규모 IoT 생태계에서 핵심적인 역할을 할 것으로 전망된다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업계 사례 분석&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대규모 서비스 사례&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Netflix는 CloudFront와 자체 CDN을 조합하여 전 세계 사용자에게 고품질 스트리밍 서비스를 제공하고 있다. 특히 캐싱 최적화와 Lambda@Edge를 활용한 개인화 추천 시스템을 통해 사용자별 맞춤 콘텐츠를 효율적으로 전달하고 있다.&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;color: #000000;&quot;&gt;게임 업계에서는 Global Accelerator를 활용한 사례가 늘어나고 있다. 실시간 멀티플레이어 게임에서 지연 시간은 사용자 경험에 직접적인 영향을 미치므로, AWS 글로벌 네트워크를 통한 최적화된 라우팅이 핵심 경쟁 요소가 되고 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중소기업 적용 사례&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중소기업의 경우 비용 효율성이 매우 중요한 요소이다. CloudFront의 무료 티어를 활용하면 월 1TB의 데이터 전송과 1000만 건의 HTTP 요청을 무료로 처리할 수 있어, 스타트업이나 중소기업에서도 부담 없이 CDN 서비스를 시작할 수 있다.&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;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최적화 팁과 베스트 프랙티스&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront 최적화 전략&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HTTP/2와 HTTP/3 프로토콜을 활성화하면 다중화와 헤더 압축을 통해 성능을 크게 개선할 수 있다. 특히 많은 작은 파일을 전송하는 웹 애플리케이션에서 뚜렷한 성능 향상을 경험할 수 있다.&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;color: #000000;&quot;&gt;Origin Request Policy를 활용하여 불필요한 헤더나 쿠키를 제거하면 캐시 효율성을 높일 수 있다. 예를 들어, 정적 자산에 대해서는 인증 관련 헤더를 제거하여 캐시 적중률을 향상시킬 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Accelerator 최적화 방법&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;엔드포인트 그룹의 트래픽 다이얼 설정을 통해 단계적 배포나 A/B 테스팅을 안전하게 수행할 수 있다. 이를 통해 새로운 기능이나 성능 개선사항을 점진적으로 적용하면서 위험을 최소화할 수 있다.&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;color: #000000;&quot;&gt;클라이언트 어피니티 설정을 적절히 조정하면 세션 유지나 캐시 효율성을 개선할 수 있다. SOURCE_IP 설정을 통해 동일한 사용자의 요청을 일관된 엔드포인트로 라우팅할 수 있다.&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront와 Global Accelerator는 각각 고유한 강점과 적용 분야를 가진 보완적인 서비스이다. CloudFront는 캐싱을 통한 콘텐츠 전송 최적화에 특화되어 있어 웹사이트, 미디어 스트리밍, API 응답 캐싱 등에 탁월한 성능을 발휘한다. &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;color: #000000;&quot;&gt;반면 Global Accelerator는 네트워크 계층에서의 최적화를 통해 실시간 애플리케이션, 게임, IoT 서비스 등에 안정적이고 예측 가능한 성능을 제공한다.&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;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;글로벌 서비스의 성공을 위해서는 단순한 기술 도입을 넘어서 지속적인 모니터링, 최적화, 그리고 사용자 피드백 반영이 필요하다. CloudFront와 Global Accelerator는 이러한 요구사항을 충족하기 위한 강력한 도구이며, 적절한 구성과 운영을 통해 세계적 수준의 서비스 품질을 달성할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;AWS CloudFront Developer Guide -&amp;nbsp;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/cloudfront/&quot;&gt;https://docs.aws.amazon.com/cloudfront/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS Global Accelerator Developer Guide -&amp;nbsp;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/global-accelerator/&quot;&gt;https://docs.aws.amazon.com/global-accelerator/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS Well-Architected Framework - Performance Efficiency Pillar -&amp;nbsp;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/wellarchitected/latest/performance-efficiency-pillar/&quot;&gt;https://docs.aws.amazon.com/wellarchitected/latest/performance-efficiency-pillar/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;Content Delivery Networks: Web Caching and Beyond&quot; - Buyya et al., IEEE Internet Computing&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS re:Invent 2023 - NET301: Accelerate your applications with AWS Global Accelerator&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudFront Pricing -&amp;nbsp;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://aws.amazon.com/cloudfront/pricing/&quot;&gt;https://aws.amazon.com/cloudfront/pricing/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Accelerator Pricing -&amp;nbsp;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://aws.amazon.com/global-accelerator/pricing/&quot;&gt;https://aws.amazon.com/global-accelerator/pricing/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS CDN Performance Best Practices Whitepaper&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Terraform AWS Provider Documentation -&amp;nbsp;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs&quot;&gt;https://registry.terraform.io/providers/hashicorp/aws/latest/docs&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;High Performance Browser Networking&quot; - Ilya Grigorik, O'Reilly Media&lt;/span&gt;&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;&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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>AWS</category>
      <category>AWS</category>
      <category>CDN</category>
      <category>CloudFront</category>
      <category>Global Accelerator</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/456</guid>
      <comments>https://somaz.tistory.com/456#entry456comment</comments>
      <pubDate>Tue, 24 Feb 2026 00:00:48 +0900</pubDate>
    </item>
    <item>
      <title>EKS Fargate vs EC2 Node Groups 완전 분석 - Kubernetes 워커 노드 옵션</title>
      <link>https://somaz.tistory.com/455</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Amazon EKS에서 제공하는 두 가지 컴퓨팅 옵션의 기술적 차이점, 비용 구조, 운영 고려사항을 종합적으로 비교 분석한다.&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;color: #000000;&quot;&gt;컨테이너 오케스트레이션 영역에서 Amazon EKS는 기업들이 Kubernetes 클러스터를 관리하는 방식을 혁신적으로 변화시켰다. 특히 워커 노드를 운영하는 방식에서 두 가지 근본적으로 다른 접근법을 제시하며, 각각이 현대 클라우드 네이티브 아키텍처의 서로 다른 요구사항을 해결한다.&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;color: #000000;&quot;&gt;&lt;b&gt;Fargate&lt;/b&gt;는 서버리스 컨테이너 플랫폼으로서, 인프라 관리의 복잡성을 완전히 추상화한다. 개발자와 DevOps 엔지니어들이 애플리케이션 로직에만 집중할 수 있도록 하며, AWS가 모든 인프라 레이어를 투명하게 관리한다. 이는 특히 스타트업이나 개발 팀이 제한적인 운영 리소스로 복잡한 Kubernetes 환경을 구축해야 할 때 매력적인 옵션이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;반면 &lt;b&gt;EC2 Node Groups&lt;/b&gt;는 전통적이면서도 강력한 접근법으로, 엔터프라이즈급 애플리케이션이 요구하는 세밀한 제어와 최적화를 가능하게 한다. 이 방식은 특히 금융, 제조업, 대규모 e-커머스와 같이 성능 최적화와 비용 효율성이 핵심인 산업에서 선호된다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;이 분석에서는 실제 운영 환경에서의 경험을 바탕으로, 각 옵션의 기술적 세부사항부터 비즈니스 임팩트까지 포괄적으로 다룬다. 또한 단순한 기능 비교를 넘어서, 실무진이 직면하는 실제 의사결정 상황에서 고려해야 할 요소들을 구체적으로 제시한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QP1LR/dJMcadtSMN5/OkXrElAtfinqVh38d2ihC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QP1LR/dJMcadtSMN5/OkXrElAtfinqVh38d2ihC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QP1LR/dJMcadtSMN5/OkXrElAtfinqVh38d2ihC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQP1LR%2FdJMcadtSMN5%2FOkXrElAtfinqVh38d2ihC1%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  관련 글&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/37&quot;&gt;2022.02.13 - [AWS] - AWS IAM (Identity and Access Management) 개요 및 설정 방법&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/30&quot;&gt;2022.02.07 - [AWS] - AWS EC2 인스턴스 생성&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/38&quot;&gt;2022.02.13 - [AWS] - AWS S3 (Simple Storage Service) 개요 및 활용 방법&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/183&quot;&gt;2023.03.30 - [AWS] - AWS Secrets Manager란?(OAuth, SSO)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/182&quot;&gt;2023.03.29 - [AWS] - AWS CLI 정리&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/181&quot;&gt;2023.03.28 - [AWS] - AWS IAM이란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/180&quot;&gt;2023.03.28 - [AWS] - AWS S3 권한이란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/179&quot;&gt;2023.03.28 - [AWS] - AWS S3란?(개념, 속성)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/184&quot;&gt;2023.03.30 - [AWS] - AWS Cloudfront란? / Canary 및 Blue-Green 배포&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/188&quot;&gt;2023.04.03 - [AWS] - AWS VPC란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/238&quot;&gt;2023.05.26 - [AWS] - AWS IRSA(IAM Roles for Service Accounts)란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/340&quot;&gt;2024.11.07 - [AWS] - AWS Ingress Annotations 정리&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/337&quot;&gt;2024.11.04 - [AWS] - AWS Assume Role이란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/349&quot;&gt;2024.11.16 - [AWS] - AWS Network ACL vs Security Group&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/354&quot;&gt;2024.11.21 - [AWS] - ALB access Log 활성화 &amp;rarr; S3 권한 설정 및 로그 저장&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/357&quot;&gt;2024.11.24 - [AWS] - EKS Pod Identity Addon&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/360&quot;&gt;2024.11.27 - [AWS] - AWS DynamoDB란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/364&quot;&gt;2025.01.03 - [AWS] - AWS DynamoDB Local 설치&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/447&quot;&gt;2025.09.02 - [AWS] - AWS EFS와 Kubernetes를 활용한 영구 스토리지 구축 가이드&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/452&quot;&gt;2025.09.05 - [AWS] - AWS CDN 구축 가이드: Kubernetes + AWS CloudFront로 API와 정적 파일 서빙 최적화&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/453&quot;&gt;2025.09.05 - [AWS] - AWS 네트워크 연결 방식 완전 비교: VPC Peering vs Transit Gateway vs VPN&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/451&quot;&gt;2025.09.04 - [AWS] - AWS Load Balancer 완전 비교 가이드&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/455&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2025.09.10 - [AWS] - EKS Fargate vs EC2 Node Groups 완전 분석 - Kubernetes 워커 노드 옵션&lt;/a&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;&lt;span style=&quot;color: #000000;&quot;&gt;개요&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Amazon Elastic Kubernetes Service(EKS)는 Kubernetes 워크로드를 실행하기 위해 두 가지 주요 컴퓨팅 옵션을 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;b&gt;Fargate&lt;/b&gt;와 &lt;b&gt;EC2 Node Groups&lt;/b&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;color: #000000;&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;color: #000000;&quot;&gt;이 글에서는 두 옵션의 기술적 아키텍처, 비용 영향, 운영상 고려사항을 종합적으로 분석하여 최적의 Kubernetes 클러스터 설계 결정을 위한 가이드를 제공한다.&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;&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;color: #000000;&quot;&gt;EKS 컴퓨팅 아키텍처 개요&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate 아키텍처&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate는 서버리스 모델로 각 파드가 전용 컴퓨팅 인프라에서 실행되며, AWS가 완전히 관리한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;EKS Control Plane &amp;rarr; Fargate Profile &amp;rarr; Pod (서버리스 실행)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 Node Groups 아키텍처&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 Node Groups는 전통적인 접근 방식으로 EC2 인스턴스에서 여러 파드가 실행된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;EKS Control Plane &amp;rarr; Node Group &amp;rarr; EC2 Nodes &amp;rarr; Multiple Pods&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EKS Fargate 심층 분석&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 특징&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;서버리스 인프라&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 인스턴스 관리가 필요 없음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파드별 전용 컴퓨팅 리소스 제공&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안 격리&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파드 수준의 향상된 보안 격리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate profile 구성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate profile 은 어떤 파드가 Fargate 컴퓨팅에서 실행될지 결정한다. 네임스페이스와 라벨 선택자를 기반으로 파드 배치를 결정한다.&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_1757487427399&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Fargate 호환 배포 예시
apiVersion: apps/v1
kind: Deployment
metadata:
  name: fargate-app
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: fargate-app
  template:
    metadata:
      labels:
        app: fargate-app
        compute-type: fargate  # Fargate profile 선택자
    spec:
      containers:
      - name: app
        image: nginx:latest
        resources:
          requests:
            cpu: 250m
            memory: 512Mi
          limits:
            cpu: 500m
            memory: 1Gi&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한사항&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate는 EC2 노드 그룹 대비 몇 가지 운영 제약사항이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;DaemonSets 지원 안 함&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;권한이 있는 컨테이너 실행 불가&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;호스트 네트워킹 사용 불가&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스토리지 옵션 제한&lt;/b&gt; (임시 스토리지 및 EFS 볼륨만 지원)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Terraform 구현 예시&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# EKS 클러스터 (Fargate 포함)
resource &quot;aws_eks_cluster&quot; &quot;main&quot; {
  name     = &quot;main-cluster&quot;
  role_arn = aws_iam_role.eks_cluster.arn
  version  = &quot;1.29&quot;

  vpc_config {
    subnet_ids              = var.subnet_ids
    endpoint_private_access = true
    endpoint_public_access  = true
  }
}

# Fargate 프로필
resource &quot;aws_eks_fargate_profile&quot; &quot;main&quot; {
  cluster_name           = aws_eks_cluster.main.name
  fargate_profile_name   = &quot;main-fargate-profile&quot;
  pod_execution_role_arn = aws_iam_role.fargate_pod_execution_role.arn
  subnet_ids            = var.private_subnet_ids

  selector {
    namespace = &quot;default&quot;
    labels = {
      &quot;compute-type&quot; = &quot;fargate&quot;
    }
  }

  selector {
    namespace = &quot;kube-system&quot;
    labels = {
      &quot;k8s-app&quot; = &quot;kube-dns&quot;
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 Node Groups 종합 분석&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아키텍처 기반&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 Node Groups는 EKS 클러스터에 워커 노드로 참여하는 관리형 EC2 인스턴스에서 작동한다. AWS가 AMI 업데이트, 보안 패치, 노드 라이프사이클 관리를 처리하면서 기본 컴퓨팅 인프라에 대한 완전한 액세스를 제공한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 기능&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;완전한 Kubernetes 호환성&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DaemonSets를 포함한 모든 Kubernetes 기능 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPU 인스턴스를 포함한 다양한 EC2 인스턴스 유형 제공&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스토리지 옵션&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;영구 볼륨 지원을 위한 완전한 EBS 통합&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;호스트 네트워킹 및 권한이 있는 컨테이너 지원&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 그룹 유형&lt;/span&gt;&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 74px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 그룹 유형&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관리 수준&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;커스터마이징&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용 사례&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관리형 노드 그룹&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완전 관리형&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;표준 워크로드, 간소화된 운영&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자체 관리형 노드 그룹&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자 관리&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완전 제어&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;커스텀 AMI, 특정 요구사항&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스팟 노드 그룹&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스팟과 함께 관리&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화, 내결함성 워크로드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 스케일링 및 리소스 관리&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 노드 그룹은 Cluster Autoscaler와 통합되어 파드 리소스 요구사항에 따라 클러스터 용량을 자동으로 조정한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nix&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 관리형 노드 그룹
resource &quot;aws_eks_node_group&quot; &quot;main&quot; {
  cluster_name    = aws_eks_cluster.main.name
  node_group_name = &quot;main-node-group&quot;
  node_role_arn   = aws_iam_role.node_group.arn
  subnet_ids      = var.private_subnet_ids
  instance_types  = [&quot;t3.medium&quot;, &quot;t3.large&quot;]
  
  scaling_config {
    desired_size = 2
    max_size     = 5
    min_size     = 1
  }

  ami_type       = &quot;AL2_x86_64&quot;
  capacity_type  = &quot;ON_DEMAND&quot;
  disk_size      = 50

  labels = {
    &quot;node-type&quot; = &quot;managed&quot;
  }
}

# 비용 최적화를 위한 스팟 인스턴스 노드 그룹
resource &quot;aws_eks_node_group&quot; &quot;spot&quot; {
  cluster_name    = aws_eks_cluster.main.name
  node_group_name = &quot;spot-node-group&quot;
  node_role_arn   = aws_iam_role.node_group.arn
  subnet_ids      = var.private_subnet_ids
  instance_types  = [&quot;t3.medium&quot;, &quot;t3.large&quot;, &quot;t3.xlarge&quot;]
  
  scaling_config {
    desired_size = 0
    max_size     = 10
    min_size     = 0
  }

  capacity_type = &quot;SPOT&quot;
  
  taint {
    key    = &quot;node.kubernetes.io/spot&quot;
    value  = &quot;true&quot;
    effect = &quot;NO_SCHEDULE&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 분석&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate 비용 구조&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate는 파드에 할당된 vCPU 및 메모리 리소스를 기반으로 청구되며, 1분 최소 단위로 초당 계산된다.&lt;/span&gt;&lt;/p&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: 93px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 36px;&quot;&gt;
&lt;td style=&quot;height: 36px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리소스 유형&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 36px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 (USD/시간)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 36px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최소 단위&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 36px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비고&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;vCPU&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.04048&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0.25 vCPU&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;vCPU당 시간당&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메모리&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.004445&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0.5 GB&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GB당 시간당&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스토리지&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.000111&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1 GB&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;임시 스토리지 GB당 시간당&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 Node Groups 비용 모델&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 노드 그룹은 표준 EC2 가격을 따르며, EBS 스토리지 및 데이터 전송에 대한 추가 고려사항이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 68px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인스턴스 유형&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;온디맨드 (USD/시간)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스팟 (USD/시간)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;vCPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메모리 (GB)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;t3.medium&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.0416&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~$0.0125&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;t3.large&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.0832&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~$0.0250&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;8&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;m5.large&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.096&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~$0.0288&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;8&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;c5.xlarge&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.17&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~$0.051&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;8&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 비교 시나리오&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리소스 활용률 패턴이 Fargate와 EC2 노드 그룹 간의 비용 효율성에 크게 영향을 미친다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;낮은 활용률 시나리오 (10-30%)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate: $0.20/시간&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2: $0.50/시간&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결과: Fargate 승리&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;높은 활용률 시나리오 (70-90%)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate: $0.80/시간&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2: $0.50/시간&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결과: EC2 승리&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 특성 분석&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시작 시간 비교&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메트릭&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 Node Groups&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;영향&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파드 시작 시간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;30-60초&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5-15초&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;애플리케이션 응답성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;콜드 스타트 영향&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스케일링 응답성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리소스 가용성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;온디맨드&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사전 프로비저닝&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;즉시 스케줄링&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워킹 고려사항&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate의 네트워킹 제약사항&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate는 AWS VPC 내에서 작동하지만 몇 가지 네트워킹 제약사항이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Host 네트워킹 모드 비지원&lt;/b&gt;: 각 파드는 자체 ENI(Elastic Network Interface)를 갖습니다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;포트 매핑 제한&lt;/b&gt;: 동일한 포트에서 여러 서비스 실행 시 고려사항&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;로드 밸런서 통합&lt;/b&gt;: ALB/NLB와의 직접적인 통합이 간편함&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Fargate에서 ALB Ingress 사용 예시
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: fargate-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: fargate-service
            port:
              number: 80&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 Node Groups의 네트워킹 유연성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 노드 그룹은 완전한 네트워킹 제어를 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Host 네트워킹 지원&lt;/b&gt;: 성능이 중요한 애플리케이션에 유리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;포트 바인딩 자유도&lt;/b&gt;: 동일 노드에서 여러 서비스의 동일 포트 사용 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;CNI 플러그인 선택권&lt;/b&gt;: Calico, Weave 등 다양한 CNI 옵션&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스토리지 옵션 상세 비교&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate 스토리지 제한사항&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Fargate에서 EFS 사용 예시
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: efs-claim
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: efs-sc
  resources:
    requests:
      storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: fargate-efs-app
spec:
  template:
    spec:
      containers:
      - name: app
        image: nginx
        volumeMounts:
        - mountPath: &quot;/data&quot;
          name: efs-storage
      volumes:
      - name: efs-storage
        persistentVolumeClaim:
          claimName: efs-claim&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 Node Groups 스토리지 옵션&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;EBS 볼륨&lt;/b&gt;: 고성능 블록 스토리지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Instance Store&lt;/b&gt;: 임시 고성능 스토리지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;EFS&lt;/b&gt;: 네트워크 파일 시스템&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;FSx&lt;/b&gt;: 고성능 파일 시스템&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 아키텍처 심화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate 보안 모델&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Fargate에서 Pod Security Context
apiVersion: v1
kind: Pod
metadata:
  name: secure-fargate-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  containers:
  - name: app
    image: nginx:alpine
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
        - ALL&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 Node Groups 보안 강화&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nix&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 보안 그룹 설정
resource &quot;aws_security_group&quot; &quot;worker_nodes&quot; {
  name        = &quot;eks-worker-nodes&quot;
  description = &quot;Security group for EKS worker nodes&quot;
  vpc_id      = var.vpc_id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = &quot;tcp&quot;
    cidr_blocks = [var.admin_cidr]
  }

  ingress {
    from_port = 10250
    to_port   = 10250
    protocol  = &quot;tcp&quot;
    self      = true
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = &quot;-1&quot;
    cidr_blocks = [&quot;0.0.0.0/0&quot;]
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파드 스케줄링 전략&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate 스케줄링 메커니즘&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate는 프로필을 사용하여 파드 배치를 결정하며, 네임스페이스 및 라벨 선택자를 기반으로 스케줄링 결정을 내린다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 Node Group 스케줄링 전략&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 노드 그룹은 정확한 워크로드 배치를 위해 노드 선택자, 어피니티 규칙, 테인트/톨러레이션을 포함한 고급 스케줄링 기법을 지원한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 노드 어피니티를 사용한 고급 스케줄링
apiVersion: apps/v1
kind: Deployment
metadata:
  name: compute-intensive-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: compute-intensive-app
  template:
    metadata:
      labels:
        app: compute-intensive-app
    spec:
      nodeSelector:
        node-type: compute-optimized
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: instance-type
                operator: In
                values: [&quot;c5.large&quot;, &quot;c5.xlarge&quot;]
      tolerations:
      - key: &quot;high-compute&quot;
        operator: &quot;Equal&quot;
        value: &quot;true&quot;
        effect: &quot;NoSchedule&quot;
      containers:
      - name: app
        image: compute-app:latest
        resources:
          requests:
            cpu: 1
            memory: 2Gi
          limits:
            cpu: 2
            memory: 4Gi&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하이브리드 스케줄링 접근법&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;많은 조직에서 워크로드 특성과 요구사항에 따라 두 컴퓨팅 옵션을 결합한 하이브리드 전략을 구현한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 워크로드별 사용 사례&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마이크로서비스 아키텍처&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate에서의 마이크로서비스&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 독립적인 마이크로서비스 배포
apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service
  namespace: microservices
spec:
  replicas: 3
  selector:
    matchLabels:
      app: user-service
  template:
    metadata:
      labels:
        app: user-service
        compute-type: fargate
    spec:
      containers:
      - name: user-service
        image: user-service:1.2.3
        ports:
        - containerPort: 8080
        resources:
          requests:
            cpu: 200m
            memory: 256Mi
          limits:
            cpu: 500m
            memory: 512Mi
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: url&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2에서의 마이크로서비스&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 리소스 집약적인 마이크로서비스
apiVersion: apps/v1
kind: Deployment
metadata:
  name: analytics-service
spec:
  replicas: 2
  selector:
    matchLabels:
      app: analytics-service
  template:
    metadata:
      labels:
        app: analytics-service
    spec:
      nodeSelector:
        workload-type: compute-intensive
      containers:
      - name: analytics-service
        image: analytics-service:2.1.0
        resources:
          requests:
            cpu: 2
            memory: 4Gi
          limits:
            cpu: 4
            memory: 8Gi&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배치 처리 워크로드&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate Job 패턴&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Fargate에서 배치 작업
apiVersion: batch/v1
kind: Job
metadata:
  name: data-processing-job
spec:
  template:
    metadata:
      labels:
        compute-type: fargate
    spec:
      restartPolicy: Never
      containers:
      - name: data-processor
        image: data-processor:latest
        command: [&quot;python&quot;, &quot;process_data.py&quot;]
        resources:
          requests:
            cpu: 1
            memory: 2Gi
          limits:
            cpu: 2
            memory: 4Gi
        env:
        - name: S3_BUCKET
          value: &quot;data-processing-bucket&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ML/AI 워크로드 고려사항&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPU 지원 비교&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# EC2에서 GPU 워크로드
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ml-training
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ml-training
  template:
    metadata:
      labels:
        app: ml-training
    spec:
      nodeSelector:
        accelerator: nvidia-tesla-k80
      containers:
      - name: ml-trainer
        image: tensorflow/tensorflow:latest-gpu
        resources:
          limits:
            nvidia.com/gpu: 1
            cpu: 4
            memory: 16Gi&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모니터링 및 로깅 전략&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CloudWatch 통합&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate 모니터링&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Fargate에서 사이드카 패턴을 통한 로깅
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-with-logging
spec:
  template:
    spec:
      containers:
      - name: app
        image: my-app:latest
        volumeMounts:
        - name: log-volume
          mountPath: /var/log
      - name: log-shipper
        image: fluent/fluent-bit:latest
        volumeMounts:
        - name: log-volume
          mountPath: /var/log
        - name: fluent-bit-config
          mountPath: /fluent-bit/etc/
      volumes:
      - name: log-volume
        emptyDir: {}
      - name: fluent-bit-config
        configMap:
          name: fluent-bit-config&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 Node Groups 모니터링&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# DaemonSet을 통한 노드 레벨 모니터링
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostNetwork: true
      hostPID: true
      containers:
      - name: node-exporter
        image: prom/node-exporter:latest
        ports:
        - containerPort: 9100
          hostPort: 9100
        volumeMounts:
        - name: proc
          mountPath: /host/proc
          readOnly: true
        - name: sys
          mountPath: /host/sys
          readOnly: true
      volumes:
      - name: proc
        hostPath:
          path: /proc
      - name: sys
        hostPath:
          path: /sys&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 고급 전략&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate 비용 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리소스 요청 최적화&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 비용 분석 스크립트 예시
import boto3
import pandas as pd
from datetime import datetime, timedelta

def analyze_fargate_costs():
    &quot;&quot;&quot;Fargate 비용 분석 및 최적화 권장사항&quot;&quot;&quot;
    
    # CloudWatch 메트릭 수집
    cloudwatch = boto3.client('cloudwatch')
    
    # CPU 및 메모리 사용률 조회
    end_time = datetime.utcnow()
    start_time = end_time - timedelta(days=7)
    
    cpu_metrics = cloudwatch.get_metric_statistics(
        Namespace='AWS/ECS',
        MetricName='CPUUtilization',
        Dimensions=[
            {'Name': 'ServiceName', 'Value': 'my-fargate-service'}
        ],
        StartTime=start_time,
        EndTime=end_time,
        Period=3600,
        Statistics=['Average', 'Maximum']
    )
    
    # 비용 최적화 권장사항 생성
    avg_cpu = sum(d['Average'] for d in cpu_metrics['Datapoints']) / len(cpu_metrics['Datapoints'])
    
    if avg_cpu &amp;lt; 30:
        print(&quot;권장사항: CPU 요청을 25% 감소시킬 수 있습니다.&quot;)
    elif avg_cpu &amp;gt; 80:
        print(&quot;권장사항: CPU 요청을 증가시켜 성능을 개선하세요.&quot;)
    
    return cpu_metrics&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 Node Groups 비용 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스팟 인스턴스 활용 전략&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nix&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 혼합 인스턴스 정책
resource &quot;aws_eks_node_group&quot; &quot;mixed_instances&quot; {
  cluster_name    = aws_eks_cluster.main.name
  node_group_name = &quot;mixed-instance-group&quot;
  node_role_arn   = aws_iam_role.node_group.arn
  subnet_ids      = var.private_subnet_ids

  scaling_config {
    desired_size = 3
    max_size     = 10
    min_size     = 1
  }

  # 혼합 인스턴스 사용
  instance_types = [&quot;m5.large&quot;, &quot;m5a.large&quot;, &quot;m4.large&quot;]
  capacity_type  = &quot;SPOT&quot;

  # 스팟 인스턴스 중단 처리
  taint {
    key    = &quot;node.kubernetes.io/spot&quot;
    value  = &quot;true&quot;
    effect = &quot;NO_SCHEDULE&quot;
  }

  labels = {
    &quot;node-type&quot;     = &quot;spot&quot;
    &quot;instance-type&quot; = &quot;mixed&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;재해 복구 및 고가용성&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다중 AZ 배포 전략&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate 고가용성&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 다중 AZ에 걸친 Fargate 배포
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ha-fargate-app
spec:
  replicas: 6
  selector:
    matchLabels:
      app: ha-fargate-app
  template:
    metadata:
      labels:
        app: ha-fargate-app
        compute-type: fargate
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - ha-fargate-app
              topologyKey: topology.kubernetes.io/zone
      containers:
      - name: app
        image: my-app:latest
        resources:
          requests:
            cpu: 500m
            memory: 1Gi&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 Node Groups 고가용성&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nix&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 다중 AZ 노드 그룹 설정
resource &quot;aws_eks_node_group&quot; &quot;ha_nodes&quot; {
  cluster_name    = aws_eks_cluster.main.name
  node_group_name = &quot;ha-node-group&quot;
  node_role_arn   = aws_iam_role.node_group.arn
  
  # 다중 AZ 서브넷 지정
  subnet_ids = [
    var.private_subnet_1a,
    var.private_subnet_1b,
    var.private_subnet_1c
  ]

  scaling_config {
    desired_size = 6  # AZ당 2개씩
    max_size     = 15
    min_size     = 3   # AZ당 최소 1개
  }

  # 인스턴스 다양성 확보
  instance_types = [&quot;m5.large&quot;, &quot;m5a.large&quot;, &quot;m5n.large&quot;]
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영 고려사항&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관리 오버헤드&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영 작업&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 Node Groups&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;영향&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OS 패치&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS에서 관리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관리 필요&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 규정 준수&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;용량 계획&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수동 계획 필요&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리소스 효율성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 모니터링&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;필요 없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완전한 모니터링 필요&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영 복잡성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스케일링 관리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cluster Autoscaler 설정&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;응답성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 영향&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate는 파드 수준 격리를 통해 향상된 보안을 제공하는 반면, EC2 노드 그룹은 더 세분화된 보안 제어를 제공하지만 추가 구성이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모니터링 및 관찰 가능성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;두 컴퓨팅 옵션 모두 CloudWatch Container Insights와 통합되지만, EC2 노드 그룹은 추가적인 노드 수준 메트릭 및 모니터링 기능을 제공한 다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;의사결정 프레임워크&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fargate 최적 시나리오&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;배치 처리&lt;/b&gt;: 예측할 수 없는 리소스 요구사항을 가진 단기, 가변 워크로드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;마이크로서비스&lt;/b&gt;: 최소한의 리소스 요구사항을 가진 소규모 독립 서비스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개발/테스트&lt;/b&gt;: 신속한 프로비저닝 및 해체가 필요한 환경&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안 중요&lt;/b&gt;: 향상된 격리 및 규정 준수가 필요한 워크로드&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2 Node Groups 최적 시나리오&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;장시간 실행 애플리케이션&lt;/b&gt;: 일관된 리소스 활용률을 가진 지속적인 서비스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고성능 컴퓨팅&lt;/b&gt;: 전용 리소스가 필요한 CPU 또는 메모리 집약적 워크로드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;시스템 서비스&lt;/b&gt;: DaemonSets, 모니터링 에이전트 및 인프라 구성 요소&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비용 최적화&lt;/b&gt;: 리소스 활용률이 60-70%를 초과하는 환경&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하이브리드 아키텍처 장점&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대부분의 엔터프라이즈 환경은 두 컴퓨팅 옵션을 전략적으로 활용하는 하이브리드 접근법의 이점을 얻는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;하이브리드 EKS 아키텍처 예시&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;Fargate 워크로드:
- 배치 작업
- 개발 서비스  
- API 게이트웨이

EC2 Node Groups:
- 시스템 노드: 모니터링 스택, Ingress 컨트롤러
- 애플리케이션 노드: 데이터베이스, 캐싱 레이어
- 컴퓨팅 노드: ML 학습, GPU 워크로드&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모범 사례 및 권장사항&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리소스 최적화 전략&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;적정 크기 조정&lt;/b&gt;: 실제 워크로드 요구사항에 맞는 컴퓨팅 리소스 매칭&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;프로필 설계&lt;/b&gt;: 특정 워크로드 패턴을 위한 대상화된 Fargate 프로필 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;노드 다양화&lt;/b&gt;: 유연성을 위한 EC2 노드 그룹에서 여러 인스턴스 유형 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스팟 통합&lt;/b&gt;: 내결함성 워크로드를 위한 스팟 인스턴스 활용&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 관리 접근법&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;리소스 모니터링&lt;/b&gt;: 포괄적인 비용 추적 및 할당 구현&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스케줄링 최적화&lt;/b&gt;: 활용률 극대화를 위한 적절한 스케줄링 전략 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예약 용량&lt;/b&gt;: 예측 가능한 워크로드에 대한 예약 인스턴스 고려&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;자동 스케일링 구성&lt;/b&gt;: 비용 효율성을 위한 스케일링 매개변수 세밀 조정&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 강화&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Pod 보안 표준 구현
apiVersion: v1
kind: Namespace
metadata:
  name: secure-workloads
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: secure-workloads
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Amazon EKS에서 Fargate와 EC2 Node Groups 사이의 선택은 현대 클라우드 인프라 전략의 핵심적인 결정 중 하나이다. 이 글을 통해 살펴본 바와 같이, 각 옵션은 고유한 강점과 제약사항을 가지고 있으며, 최적의 선택은 조직의 구체적인 요구사항과 컨텍스트에 따라 달라진다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;운영의 단순성 vs 제어의 유연성&lt;/b&gt;이라는 근본적인 트레이드오프가 존재한다. Fargate는 인프라 관리의 복잡성을 제거하여 개발팀이 비즈니스 로직에 집중할 수 있게 하는 반면, EC2 Node Groups는 세밀한 최적화와 커스터마이제이션을 통해 최대 성능과 비용 효율성을 달성할 수 있게 한다.&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;color: #000000;&quot;&gt;클라우드 네이티브 생태계는 지속적으로 발전하고 있으며, 서버리스와 컨테이너 기술의 융합은 더욱 정교해지고 있다. Fargate는 서버리스 컴퓨팅의 미래를 보여주는 한편, EC2 Node Groups는 여전히 엔터프라이즈급 워크로드의 백본 역할을 수행하고 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;Kubernetes와 서버리스 기술의 지속적인 혁신을 고려할 때, 앞으로는 더욱 정교한 워크로드 배치 전략과 자동화된 최적화 도구들이 등장할 것으로 예상된다. 머신러닝 기반의 리소스 예측과 동적 스케줄링, 그리고 멀티 클라우드 환경에서의 워크로드 분산이 새로운 표준이 될 가능성이 높다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 분석을 바탕으로 조직에서 고려해야 할 구체적인 액션 아이템들을 제시한다.&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;현재 워크로드 프로파일링&lt;/b&gt;: 기존 애플리케이션들의 리소스 사용 패턴, 스케일링 요구사항, 보안 제약사항을 체계적으로 분석&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;파일럿 프로젝트 실행&lt;/b&gt;: 대표적인 워크로드를 선정하여 두 옵션 모두에서 테스트 실행 후 성능, 비용, 운영성 비교&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비용 모델링 구축&lt;/b&gt;: 실제 사용 패턴을 기반으로 한 정확한 TCO(Total Cost of Ownership) 계산&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;운영 프로세스 정의&lt;/b&gt;: 각 컴퓨팅 옵션에 맞는 모니터링, 배포, 문제 해결 프로세스 수립&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;팀 역량 개발&lt;/b&gt;: DevOps 팀의 Kubernetes 및 서버리스 기술 숙련도 향상을 위한 교육 계획 수립&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&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;color: #000000;&quot;&gt;클라우드 환경에서는 &quot;설정하고 잊어버리는&quot; 접근법이 통하지 않는다. 비즈니스 요구사항의 변화, 새로운 AWS 서비스의 출시, 그리고 애플리케이션 사용 패턴의 진화에 따라 컴퓨팅 전략을 지속적으로 재평가하고 조정해야 한다. 정기적인 비용 리뷰, 성능 벤치마킹, 그리고 보안 감사를 통해 최적의 상태를 유지하는 것이 핵심이다.&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;color: #000000;&quot;&gt;Kubernetes와 AWS 생태계는 활발한 오픈소스 커뮤니티에 의해 지원된다. 지속적인 학습과 커뮤니티 참여를 통해 새로운 베스트 프랙티스와 도구들을 파악하고 적용하는 것이 중요하다. CNCF(Cloud Native Computing Foundation)의 프로젝트들과 AWS의 새로운 서비스 발표를 주시하며, 조직의 기술 스택을 현대적으로 유지해야 한다.&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;&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;span style=&quot;color: #000000;&quot;&gt;결론적으로, EKS Fargate와 EC2 Node Groups는 상호 보완적인 기술로 이해되어야 한다. 성공적인 클라우드 네이티브 전환을 위해서는:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;단계적 접근&lt;/b&gt;: 복잡성이 낮은 워크로드부터 시작하여 점진적으로 확장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;데이터 기반 의사결정&lt;/b&gt;: 추측이 아닌 실제 메트릭과 비용 데이터를 기반으로 한 선택&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;지속적인 학습&lt;/b&gt;: 기술 발전에 따른 지속적인 역량 개발과 아키텍처 개선&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;문화적 변화&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이러한 접근을 통해 조직은 Kubernetes의 강력한 기능을 최대한 활용하면서도, 각자의 비즈니스 목표에 가장 적합한 컴퓨팅 전략을 구축할 수 있을 것이다. &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;color: #000000;&quot;&gt;클라우드 네이티브의 여정은 목적지가 아닌 지속적인 개선과 혁신의 과정임을 기억하며, 변화하는 비즈니스 환경에 유연하게 대응할 수 있는 기술적 기반을 마련하는 것이 무엇보다 중요하다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&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;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;
&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;&lt;a style=&quot;background-color: #e6f5ff; color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/&quot;&gt;Amazon EKS 사용자 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html&quot;&gt;AWS Fargate 사용자 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html&quot;&gt;EKS 노드 그룹 문서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubernetes.io/docs/home/&quot;&gt;Kubernetes 문서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://aws.amazon.com/eks/pricing/&quot;&gt;AWS 컨테이너 서비스 요금&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://aws.github.io/aws-eks-best-practices/&quot;&gt;EKS 모범 사례 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler&quot;&gt;Cluster Autoscaler 문서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://registry.terraform.io/modules/terraform-aws-modules/eks/aws/latest&quot;&gt;Terraform AWS EKS 모듈&lt;/a&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;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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>AWS</category>
      <category>AWS</category>
      <category>EKS</category>
      <category>eks fargate</category>
      <category>eks nodegroup</category>
      <category>Kubernetes</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/455</guid>
      <comments>https://somaz.tistory.com/455#entry455comment</comments>
      <pubDate>Tue, 17 Feb 2026 00:00:12 +0900</pubDate>
    </item>
    <item>
      <title>온프레미스 환경에서 Ollama + Open WebUI로 사내 LLM 구축하기</title>
      <link>https://somaz.tistory.com/488</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최근 AI 기술의 발전으로 ChatGPT, Claude 같은 상용 LLM 서비스가 대중화되었지만, 보안이 중요한 기업 환경에서는 민감한 데이터를 외부 API로 전송하기 어려운 경우가 많다. 이러한 상황에서 온프레미스 환경에 자체 LLM을 구축하면 데이터 보안을 유지하면서도 AI의 이점을 활용할 수 있다.&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;color: #000000;&quot;&gt;이번 글에서는 NVIDIA GPU가 장착된 물리 서버에 Ollama를 설치하고, Open WebUI를 통해 웹 인터페이스를 제공하는 사내 LLM 시스템을 구축하는 전체 과정을 다룬다. &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;color: #000000;&quot;&gt;NFS를 활용한 스토리지 관리와 Docker Compose를 이용한 컨테이너 오케스트레이션까지 포함하여 실무에 바로 적용 가능한 완전한 솔루션을 제시한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6UBk8/dJMcadAQ1Sx/NTGMKRteDjHlwUZUZ8kPK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6UBk8/dJMcadAQ1Sx/NTGMKRteDjHlwUZUZ8kPK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6UBk8/dJMcadAQ1Sx/NTGMKRteDjHlwUZUZ8kPK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6UBk8%2FdJMcadAQ1Sx%2FNTGMKRteDjHlwUZUZ8kPK0%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시스템 구성 및 사전 요구사항&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하드웨어 환경&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GPU 서버 (192.168.1.20)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CPU: Intel Xeon 6코어&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;RAM: 32GB&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPU: NVIDIA GeForce RTX 3060 12GB&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OS: Ubuntu 24.04 LTS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;용도: Ollama 서버&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;웹 서버 (192.168.1.21)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CPU: 4코어&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;RAM: 16GB&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OS: Ubuntu 24.04 LTS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;용도: Open WebUI&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스토리지 서버 (192.168.1.25)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NFS 서버: /storage/ai-data 공유&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPU 호환성 확인&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;먼저 설치된 GPU의 스펙을 확인한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;1c&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;lspci | grep -iE &quot;vga|display|3d&quot;
# 01:00.0 VGA compatible controller: NVIDIA Corporation GA106 [GeForce RTX 3060]&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;RTX 3060의 주요 스펙&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아키텍처: Ampere (GA106)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CUDA 코어: 3,584개&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VRAM: 12GB GDDR6&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CUDA Compute Capability: 8.6&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;권장 드라이버: 525+ (535 안정적)&lt;/span&gt;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;1단계: NVIDIA 드라이버 설치&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Secure Boot 상태 확인&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;mokutil --sb-state
# SecureBoot disabled 또는 SecureBoot enabled 확인&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;Secure Boot이 활성화되어 있으면 드라이버 설치 후 MOK(Machine Owner Key) 등록 과정이 필요하다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용 가능한 드라이버 버전 확인&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 저장소에서 사용 가능한 버전 확인
apt-cache search nvidia-driver

# 특정 버전의 상세 정보 확인
apt-cache show nvidia-driver-535 | grep Version
# Version: 535.288.01-0ubuntu0.24.04.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;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;color: #000000;&quot;&gt;또는 NVIDIA 공식 웹사이트에서 최신 버전 확인&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;URL: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.nvidia.com/Download/index.aspx&quot;&gt;https://www.nvidia.com/Download/index.aspx&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Product Type: GeForce&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Product Series: GeForce RTX 30 Series&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Product: GeForce RTX 3060&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Operating System: Linux 64-bit&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;드라이버 설치 및 확인&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 시스템 업데이트
sudo apt update

# NVIDIA 드라이버 설치
sudo apt install -y nvidia-driver-535

# 시스템 재부팅
sudo reboot&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;재부팅 후 Secure Boot이 활성화되어 있다면 파란색 MOK 관리 화면이 나타난다.&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;&quot;Enroll MOK&quot; 선택&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;Continue&quot; 선택&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설치 시 설정한 비밀번호 입력&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;Reboot&quot; 선택&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설치 확인&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;nvidia-smi

# 정상 설치 시 GPU 정보와 드라이버 버전이 출력된다.


Wed Feb  5 10:15:23 2026       
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.288.01             Driver Version: 535.288.01   CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|=========================================+======================+======================|
|   0  NVIDIA GeForce RTX 3060        Off | 00000000:01:00.0 Off |                  N/A |
|  0%   35C    P8              15W / 170W |      0MiB / 12288MiB |      0%      Default |
+-----------------------------------------+----------------------+----------------------+&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2단계: Docker 및 NVIDIA Container Toolkit 설치&lt;/span&gt;&lt;/h3&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Docker 설치&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Docker 설치 확인
docker --version

# 없을 경우 설치
sudo apt update
sudo apt install -y docker.io
sudo systemctl enable --now docker

# 현재 사용자를 docker 그룹에 추가 (선택사항)
sudo usermod -aG docker $USER&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NVIDIA Container Toolkit 설치&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Docker 컨테이너에서 GPU를 사용하기 위해 NVIDIA Container Toolkit이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# GPG 키 추가
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg

# 저장소 추가
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
  sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

# 패키지 설치
sudo apt update
sudo apt install -y nvidia-container-toolkit&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Docker 런타임 설정&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Docker에 NVIDIA 런타임 설정
sudo nvidia-ctk runtime configure --runtime=docker

# Docker 서비스 재시작
sudo systemctl restart docker&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPU 접근 테스트&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;정상적으로 GPU 정보가 출력되면 설정 완료이다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3단계: NFS 스토리지 구성&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 서버에서 모델 파일과 데이터를 공유하기 위해 NFS를 구성한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라이언트 설치 및 마운트&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;elixir&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# NFS 클라이언트 설치
sudo apt install -y nfs-common

# 마운트 포인트 생성
sudo mkdir -p /data/llm-models
sudo mkdir -p /data/webui-storage

# NFS 마운트
sudo mount -t nfs4 192.168.1.25:/storage/ai-data/models /data/llm-models
sudo mount -t nfs4 192.168.1.25:/storage/ai-data/webui /data/webui-storage

# 확인
df -h | grep nfs&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;영구 마운트 설정&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;재부팅 후에도 자동으로 마운트되도록 `/etc/fstab` 을 설정한다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;elixir&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;sudo nano /etc/fstab

# 다음 줄 추가
192.168.1.25:/storage/ai-data/models  /data/llm-models     nfs4  defaults,_netdev,rw  0  0
192.168.1.25:/storage/ai-data/webui   /data/webui-storage  nfs4  defaults,_netdev,rw  0  0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;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;color: #000000;&quot;&gt;설정 확인&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;sudo mount -a
df -h | grep nfs&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;권한 설정&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;haskell&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Ollama 데이터 디렉토리
sudo chown -R root:root /data/llm-models
sudo chmod 755 /data/llm-models

# Open WebUI 데이터 디렉토리
sudo chown -R root:root /data/webui-storage
sudo chmod 755 /data/webui-storage&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;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;
&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;color: #000000;&quot;&gt;4단계: Docker 네트워크 구성&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ollama와 Open WebUI가 통신할 수 있도록 공유 네트워크를 생성한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Docker 브리지 네트워크 생성
docker network create ai_network

# 확인
docker network ls
# NETWORK ID     NAME         DRIVER    SCOPE
# abc123def456   ai_network   bridge    local&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5단계: Ollama 서버 구축 (GPU 서버)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Docker Compose 파일 생성&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;cat &amp;gt; /opt/ollama/docker-compose.yml &amp;lt;&amp;lt; 'EOF'
version: '3.8'

services:
  ollama:
    image: ollama/ollama:0.15.4
    container_name: ollama-server
    restart: unless-stopped
    runtime: nvidia
    
    ports:
      - &quot;11434:11434&quot;
    
    volumes:
      - /data/llm-models:/root/.ollama
    
    environment:
      # 모델 메모리 유지 시간 설정
      # -1: 영구 유지 (언로드 안 함, 항상 메모리에 상주)
      # 0: 즉시 언로드 (사용 후 바로 메모리 해제)
      # 5m: 5분 후 언로드 (기본값)
      # 30m: 30분 후 언로드
      # 1h: 1시간 후 언로드
      # 
      # -1 설정 시:
      #   장점: 첫 응답 이후 매번 빠른 응답 (로딩 시간 없음)
      #   단점: VRAM 계속 점유 (qwen2.5-coder:14b = ~8GB 상시 사용)
      # 
      # 권장: 자주 사용하면 -1, 가끔 사용하면 30m
      - OLLAMA_KEEP_ALIVE=-1
      - NVIDIA_VISIBLE_DEVICES=all
      - OLLAMA_ORIGINS=*
    
    networks:
      - ai_network

networks:
  ai_network:
    name: ai_network
    external: true
EOF&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;환경변수 설명&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&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;color: #000000;&quot;&gt;OLLAMA_KEEP_ALIVE: 모델 메모리 유지 시간&lt;/span&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;color: #000000;&quot;&gt;-1: 영구 유지 (첫 로딩 후 항상 메모리에 상주)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5m: 5분 후 자동 언로드 (기본값)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;30m: 30분 후 언로드 (권장)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0: 즉시 언로드&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NVIDIA_VISIBLE_DEVICES=all: 모든 GPU 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OLLAMA_ORIGINS=*: CORS 허용 (선택사항)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;KEEP_ALIVE 설정 가이드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;자주 사용 (1일 10회 이상)&lt;/b&gt;: -1 (영구 유지) &amp;rarr; 빠른 응답&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;가끔 사용 (1일 3~10회)&lt;/b&gt;: 30m 또는 1h &amp;rarr; 균형&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;드물게 사용 (1일 1~2회)&lt;/b&gt;: 5m (기본값) &amp;rarr; 메모리 절약&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너 실행&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 디렉토리 이동
cd /opt/ollama

# 컨테이너 실행
docker-compose up -d

# 로그 확인
docker-compose logs -f

# 상태 확인
docker-compose ps&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPU 사용 확인&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;livescript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 컨테이너 내부에서 nvidia-smi 실행
docker exec -it ollama-server nvidia-smi

# NFS 마운트 확인
docker exec -it ollama-server df -h /root/.ollama&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LLM 모델 다운로드&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ollama는 &lt;a style=&quot;color: #000000;&quot; href=&quot;https://ollama.com/library&quot;&gt;https://ollama.com/library&lt;/a&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;color: #000000;&quot;&gt;RTX 3060 12GB 기준 권장 모델은 다음과 같다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1) DeepSeek-Coder-V2 16B (코딩 특화, 10GB)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;armasm&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;docker exec -it ollama-server ollama pull deepseek-coder-v2:16b&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2) Qwen2.5-Coder 14B (코딩, 9.7GB)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;docker exec -it ollama-server ollama pull qwen2.5-coder:14b&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;3) Qwen3 14B (범용, 11GB)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;docker exec -it ollama-server ollama pull qwen3:14b&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;4) Qwen2.5-Coder 32B (고성능 코딩, 21GB - CPU 오프로딩)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;docker exec -it ollama-server ollama pull qwen2.5-coder:32b&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모델 다운로드 확인&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;ls -lh /data/llm-models/models/&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모델 테스트&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# DeepSeek 16B 테스트
docker exec -it ollama-server ollama run deepseek-coder-v2:16b
&amp;gt;&amp;gt;&amp;gt; Write a Python function to reverse a string

# 종료: Ctrl+D 또는 /bye&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모델별 성능 비교 (RTX 3060 12GB 기준)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;DeepSeek-Coder-V2 16B (10GB)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;docker exec -it ollama-server ollama ps

NAME                     ID              SIZE     PROCESSOR    CONTEXT
deepseek-coder-v2:16b    63fb193b3a9b    10 GB    100% GPU     4096


## 메모리 사용량
|   0  NVIDIA GeForce RTX 3060        Off | 00000000:01:00.0 Off |                  N/A |
|  0%   49C    P2              26W / 170W |   9898MiB / 12288MiB |      0%      Default |&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Qwen2.5-Coder 14B (9.7GB)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;NAME                 ID              SIZE      PROCESSOR    CONTEXT
qwen2.5-coder:14b    9ec8897f747e    9.7 GB    100% GPU     4096


## 메모리 사용량:
|   0  NVIDIA GeForce RTX 3060        Off | 00000000:01:00.0 Off |                  N/A |
|  0%   50C    P2              44W / 170W |   9482MiB / 12288MiB |      0%      Default |&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Qwen2.5-Coder 32B (21GB - CPU 오프로딩)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;NAME                 ID              SIZE     PROCESSOR          CONTEXT
qwen2.5-coder:32b    b92d6a0bd47e    21 GB    45%/55% CPU/GPU    4096


## 메모리 사용량:
|   0  NVIDIA GeForce RTX 3060        Off | 00000000:01:00.0 Off |                  N/A |
|  0%   60C    P2              60W / 170W |  11476MiB / 12288MiB |     17%      Default |&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 분석 및 권장사항&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모델&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;크기&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VRAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처리 방식&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;속도추천&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;용도&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;DeepSeek 16B&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;9.9GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;100% GPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;★★★★★&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실시간 코딩 지원&lt;/b&gt; (가장 빠름)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Qwen2.5 14B&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;9.7GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;9.5GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;100% GPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;★★★★☆&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일반 코딩 작업&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Qwen3 14B&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;11GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;11GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;100% GPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;★★★★☆&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡한 추론/논리 작업&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Qwen2.5 32B&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;21GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;11.5GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;45% CPU&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;55% GPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;★★☆☆☆&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고품질 결과 필요 시&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(속도 5배 이상 느림)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;핵심 포인트&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VRAM 12GB 이하 모델 &amp;rarr; 100% GPU 처리 &amp;rarr; 빠른 응답&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VRAM 12GB 초과 모델 &amp;rarr; CPU 오프로딩 &amp;rarr; 매우 느린 응답&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실무 권장: DeepSeek 16B&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모델 관리 명령어&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;gauss&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 실행 중인 모델 확인
docker exec -it ollama-server ollama ps

# 모델 언로드 (메모리 확보)
docker exec -it ollama-server ollama stop deepseek-coder-v2:16b
docker exec -it ollama-server ollama stop qwen2.5-coder:32b

# 모델 삭제
docker exec -it ollama-server ollama rm qwen2.5-coder:32b

# 설치된 모든 모델 목록
docker exec -it ollama-server ollama list&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;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;color: #000000;&quot;&gt;6단계: Open WebUI 구축 (웹 서버)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Open WebUI는 ChatGPT와 유사한 웹 인터페이스를 제공하는 오픈소스 프로젝트다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Docker Compose 파일 생성&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vim&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;cat &amp;gt; /opt/open-webui/docker-compose.yml &amp;lt;&amp;lt; 'EOF'
version: '3.8'

services:
  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    container_name: open-webui
    restart: unless-stopped
    
    ports:
      - &quot;8080:8080&quot;
    
    volumes:
      - /data/webui-storage:/app/backend/data
    
    environment:
      - OLLAMA_BASE_URL=http://192.168.1.20:11434
      - WEBUI_SECRET_KEY=your-random-secret-key-change-this
      - WEBUI_NAME=Company AI Assistant
      - DEFAULT_MODELS=deepseek-coder-v2:16b,qwen2.5-coder:14b
    
    networks:
      - ai_network

networks:
  ai_network:
    name: ai_network
    external: true
EOF&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;환경변수 설명&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;OLLAMA_BASE_URL: Ollama 서버 주소 (컨테이너 간 통신 시 서비스명 또는 IP 사용)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;WEBUI_SECRET_KEY: 세션 암호화 키 (랜덤 문자열로 변경 필수)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;WEBUI_NAME: 웹 UI 타이틀&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DEFAULT_MODELS: 기본 표시 모델 목록&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;주의사항&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;같은 Docker 네트워크 내에서는 http://ollama-server:11434 형식으로 통신 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다른 물리 서버에 있다면 IP 주소 사용 (http://192.168.1.20:11434)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너 실행&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 디렉토리 이동
cd /opt/open-webui

# 실행
docker-compose up -d

# 로그 확인
docker-compose logs -f

# 상태 확인
docker-compose ps&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;웹 인터페이스 접속&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;브라우저에서 `http://192.168.1.21:8080` 접속한다.&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;color: #000000;&quot;&gt;&lt;b&gt;초기 설정&lt;/b&gt;&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;회원가입 (첫 사용자는 자동으로 관리자)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설정 &amp;rarr; 모델 &amp;rarr; Ollama 연결 확인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대화 시작&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3402&quot; data-origin-height=&quot;1422&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vICuz/dJMcagdmynt/yxIv1wBMNk46AiSKGQlUK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vICuz/dJMcagdmynt/yxIv1wBMNk46AiSKGQlUK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vICuz/dJMcagdmynt/yxIv1wBMNk46AiSKGQlUK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvICuz%2FdJMcagdmynt%2FyxIv1wBMNk46AiSKGQlUK0%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;3402&quot; height=&quot;1422&quot; data-origin-width=&quot;3402&quot; data-origin-height=&quot;1422&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;&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;
&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;color: #000000;&quot;&gt;7단계: API 연동 및 활용&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Open WebUI는 OpenAI 호환 API를 제공하여 프로그래밍 방식으로 접근할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API 키 발급&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;웹 UI 로그인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설정 &amp;rarr; Account &amp;rarr; API Keys&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;Create new secret key&quot; 클릭&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;생성된 키 복사 (예: sk-abc123def456...)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API 호출 예제&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;cURL 테스트&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;flix&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;curl -X POST http://192.168.1.21:8080/api/chat/completions \
  -H &quot;Authorization: Bearer sk-abc123def456...&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d '{
    &quot;model&quot;: &quot;deepseek-coder-v2:16b&quot;,
    &quot;messages&quot;: [
      {
        &quot;role&quot;: &quot;user&quot;,
        &quot;content&quot;: &quot;파이썬으로 피보나치 수열 함수를 작성해줘&quot;
      }
    ],
    &quot;stream&quot;: 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;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;color: #000000;&quot;&gt;&lt;b&gt;Python 예제&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;makefile&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;import requests
import json

API_URL = &quot;http://192.168.1.21:8080/api/chat/completions&quot;
API_KEY = &quot;sk-abc123def456...&quot;

headers = {
    &quot;Authorization&quot;: f&quot;Bearer {API_KEY}&quot;,
    &quot;Content-Type&quot;: &quot;application/json&quot;
}

payload = {
    &quot;model&quot;: &quot;deepseek-coder-v2:16b&quot;,
    &quot;messages&quot;: [
        {
            &quot;role&quot;: &quot;system&quot;,
            &quot;content&quot;: &quot;당신은 파이썬 전문 코딩 어시스턴트다.&quot;
        },
        {
            &quot;role&quot;: &quot;user&quot;,
            &quot;content&quot;: &quot;이진 탐색 알고리즘을 구현해줘&quot;
        }
    ],
    &quot;temperature&quot;: 0.7,
    &quot;max_tokens&quot;: 2000
}

response = requests.post(API_URL, headers=headers, json=payload)
result = response.json()

print(result['choices'][0]['message']['content'])&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;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;color: #000000;&quot;&gt;&lt;b&gt;스트리밍 응답 예제&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;import requests
import json

payload = {
    &quot;model&quot;: &quot;qwen2.5-coder:14b&quot;,
    &quot;messages&quot;: [
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;REST API란 무엇인지 설명해줘&quot;}
    ],
    &quot;stream&quot;: True
}

response = requests.post(
    API_URL, 
    headers=headers, 
    json=payload, 
    stream=True
)

for line in response.iter_lines():
    if line:
        decoded = line.decode('utf-8')
        if decoded.startswith('data: '):
            data = json.loads(decoded[6:])
            if 'choices' in data:
                content = data['choices'][0]['delta'].get('content', '')
                print(content, end='', flush=True)&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;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;color: #000000;&quot;&gt;8단계: 모니터링 및 유지보수&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPU 모니터링&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;실시간 GPU 사용량 확인&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;watch -n 1 nvidia-smi&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;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;color: #000000;&quot;&gt;로그 기반 모니터링&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;stata&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# GPU 사용률 로그
nvidia-smi --query-gpu=timestamp,name,temperature.gpu,utilization.gpu,utilization.memory,memory.used,memory.total \
  --format=csv -l 5 &amp;gt;&amp;gt; /var/log/gpu-usage.log

# 분석
tail -f /var/log/gpu-usage.log&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Docker 컨테이너 관리&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Ollama 재시작
cd /opt/ollama
docker-compose restart

# Open WebUI 재시작
cd /opt/open-webui
docker-compose restart

# 로그 확인 (최근 100줄)
docker-compose logs --tail 100 ollama
docker-compose logs --tail 100 open-webui

# 리소스 사용량 확인
docker stats&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;color: #000000;&quot;&gt;백업 전략&lt;/span&gt;&lt;/h3&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;모델 파일 백업&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;haskell&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# NFS 디렉토리 백업
sudo rsync -avz /data/llm-models/ /backup/llm-models-$(date +%Y%m%d)/&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Open WebUI 데이터 백업&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;haskell&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 사용자 설정 및 대화 내역
sudo rsync -avz /data/webui-storage/ /backup/webui-storage-$(date +%Y%m%d)/&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 백업 스크립트&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;cat &amp;gt; /usr/local/bin/backup-ai-system.sh &amp;lt;&amp;lt; 'EOF'
#!/bin/bash

BACKUP_DIR=&quot;/backup/ai-system&quot;
DATE=$(date +%Y%m%d_%H%M%S)

# 백업 디렉토리 생성
mkdir -p ${BACKUP_DIR}/${DATE}

# 모델 백업 (심볼릭 링크 사용)
ln -sf /data/llm-models ${BACKUP_DIR}/${DATE}/models

# WebUI 데이터 백업
rsync -az /data/webui-storage/ ${BACKUP_DIR}/${DATE}/webui/

# 7일 이상 된 백업 삭제
find ${BACKUP_DIR} -type d -mtime +7 -exec rm -rf {} +

echo &quot;Backup completed: ${BACKUP_DIR}/${DATE}&quot;
EOF

chmod +x /usr/local/bin/backup-ai-system.sh

# Cron 등록 (매일 새벽 2시)
(crontab -l 2&amp;gt;/dev/null; echo &quot;0 2 * * * /usr/local/bin/backup-ai-system.sh &amp;gt;&amp;gt; /var/log/ai-backup.log 2&amp;gt;&amp;amp;1&quot;) | crontab -&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;
&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;color: #000000;&quot;&gt;트러블슈팅&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPU 인식 안됨&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;증상:&lt;/b&gt; `docker exec -it ollama-server nvidia-smi` 실패&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;해결&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 드라이버 재설치
sudo apt purge -y nvidia-*
sudo apt install -y nvidia-driver-535
sudo reboot

# Container Toolkit 재설정
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ollama 응답 느림 (32B 모델)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;증상:&lt;/b&gt; 응답이 매우 느림, GPU 메모리 부족&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;color: #000000;&quot;&gt;&lt;b&gt;해결:&lt;/b&gt; 작은 모델 사용 또는 GPU 업그레이드&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;gauss&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 메모리 효율적인 모델로 전환
docker exec -it ollama-server ollama stop qwen2.5-coder:32b
docker exec -it ollama-server ollama run deepseek-coder-v2:16b&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NFS 마운트 실패&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;증상:&lt;/b&gt; mount.nfs4: Connection timed out&lt;b&gt;&lt;/b&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;color: #000000;&quot;&gt;&lt;b&gt;해결&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# NFS 서버 확인
showmount -e 192.168.1.25

# 방화벽 확인 (NFS 서버에서)
sudo ufw allow from 192.168.1.0/24 to any port nfs

# 재마운트
sudo umount /data/llm-models
sudo mount -a&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Open WebUI 연결 오류&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;증상:&lt;/b&gt; &quot;Failed to connect to Ollama&quot;&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;color: #000000;&quot;&gt;&lt;b&gt;해결&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# Ollama API 테스트
curl http://192.168.1.20:11434/api/tags

# 네트워크 확인
docker network inspect ai_network

# 환경변수 수정
cd /opt/open-webui
docker-compose down
# docker-compose.yml에서 OLLAMA_BASE_URL 수정 후
docker-compose up -d&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모델 로딩 시간 길어짐&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;증상:&lt;/b&gt; 첫 요청 시 응답까지 10~30초 소요&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;color: #000000;&quot;&gt;&lt;b&gt;해결:&lt;/b&gt; OLLAMA_KEEP_ALIVE 설정 조정&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# docker-compose.yml 수정
environment:
  - OLLAMA_KEEP_ALIVE=-1  # 영구 유지로 변경

# 재시작
cd /opt/ollama
docker-compose down
docker-compose up -d&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 고려사항&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리버스 프록시 설정 (Nginx)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부 접근 시 HTTPS 적용을 권장한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# /etc/nginx/sites-available/ai-assistant
server {
    listen 443 ssl http2;
    server_name ai.company.com;
    
    ssl_certificate /etc/letsencrypt/live/ai.company.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ai.company.com/privkey.pem;
    
    location / {
        proxy_pass http://192.168.1.21:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        
        # WebSocket 지원
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자 접근 제어&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Open WebUI 관리자 페이지에서 다음을 설정한다:&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;Settings &amp;rarr; Users &amp;rarr; User Permissions&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자별 모델 접근 권한 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일일 요청 제한 설정&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;
&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;color: #000000;&quot;&gt;성능 최적화 팁&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 모델 사전 로딩&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자주 사용하는 모델을 미리 메모리에 로드한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# systemd 서비스 생성
cat &amp;gt; /etc/systemd/system/ollama-preload.service &amp;lt;&amp;lt; 'EOF'
[Unit]
Description=Ollama Model Preloader
After=docker.service
Requires=docker.service

[Service]
Type=oneshot
ExecStart=/usr/bin/docker exec ollama-server ollama run deepseek-coder-v2:16b &quot;&quot;
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable ollama-preload
sudo systemctl start ollama-preload&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Context Window 조정&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;긴 대화 시 성능 저하를 방지한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;makefile&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# API 호출 시 max_tokens 제한
payload = {
    &quot;model&quot;: &quot;deepseek-coder-v2:16b&quot;,
    &quot;messages&quot;: messages,
    &quot;max_tokens&quot;: 1024,  # 적절한 값으로 제한
    &quot;temperature&quot;: 0.7
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 배치 처리&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 요청을 동시에 처리해야 할 경우 설정을 조정한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# docker-compose.yml에 추가
environment:
  - OLLAMA_NUM_PARALLEL=2
  - OLLAMA_MAX_LOADED_MODELS=2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. KEEP_ALIVE 최적화 전략&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;시나리오 1: 개발팀 전용 (하루 종일 사용)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;avrasm&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;environment:
  - OLLAMA_KEEP_ALIVE=-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;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;color: #000000;&quot;&gt;&lt;b&gt;시나리오 2: 부서 공유 (업무 시간만 사용)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;environment:
  - OLLAMA_KEEP_ALIVE=1h  # 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;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;color: #000000;&quot;&gt;&lt;b&gt;시나리오 3: 간헐적 사용 (가끔 필요)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;avrasm&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;environment:
  - OLLAMA_KEEP_ALIVE=5m  # 기본값&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;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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 글에서는 온프레미스 환경에서 Ollama와 Open WebUI를 활용한 사내 LLM 시스템을 구축하는 전체 과정을 다뤘다. NVIDIA GPU 드라이버 설치부터 Docker Compose를 이용한 컨테이너 오케스트레이션, NFS 스토리지 연동, 그리고 실제 운영에 필요한 모니터링과 백업 전략까지 실무에 바로 적용 가능한 내용으로 구성했다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;핵심 요약&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;RTX 3060 12GB 기준&lt;/b&gt;: DeepSeek 16B 모델이 속도와 성능 면에서 최적&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Docker Compose 활용&lt;/b&gt;: 컨테이너 관리를 선언적으로 정의하여 유지보수 용이&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;KEEP_ALIVE 설정&lt;/b&gt;: 사용 패턴에 맞춰 -1, 30m, 5m 중 선택&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;NFS 활용&lt;/b&gt;: 여러 서버 간 모델 파일 공유로 스토리지 효율 극대화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;API 연동&lt;/b&gt;: OpenAI 호환 API로 기존 워크플로우 통합 가능&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 보안이 중요한 금융, 헬스케어, 정부 기관 등에서는 데이터를 외부로 전송하지 않고도 AI의 이점을 활용할 수 있다는 점에서 온프레미스 LLM 구축이 큰 가치를 제공한다. 초기 구축 비용이 들지만 장기적으로는 API 사용료 절감과 데이터 주권 확보라는 두 마리 토끼를 잡을 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;향후에는 모델 파인튜닝, RAG(Retrieval-Augmented Generation) 시스템 통합, 그리고 Kubernetes 환경에서의 오케스트레이션 등 고급 주제로 시리즈를 이어가겠다.&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;&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;
&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;
&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;
&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;Ollama 공식 문서: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/ollama/ollama&quot;&gt;https://github.com/ollama/ollama&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Open WebUI 공식 저장소: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/open-webui/open-webui&quot;&gt;https://github.com/open-webui/open-webui&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NVIDIA Container Toolkit: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/&quot;&gt;https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/&lt;/a&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;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;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>AI/AI Tool</category>
      <category>Ai</category>
      <category>LLM</category>
      <category>ollama</category>
      <category>open-webui</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/488</guid>
      <comments>https://somaz.tistory.com/488#entry488comment</comments>
      <pubDate>Wed, 11 Feb 2026 00:00:44 +0900</pubDate>
    </item>
    <item>
      <title>Docker 이미지 최적화 실전 가이드</title>
      <link>https://somaz.tistory.com/450</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;개인적으로 이 주제를 깊이 파보고 싶었다. DevOps 엔지니어로 일하면서 비대한 Docker 이미지가 늘 골칫거리였기 때문이다. 특히 Python의 머신러닝 스택이나 Go의 개발 도구들이 포함된 이미지들은 종종 1GB를 넘어가곤 한다.&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;color: #000000;&quot;&gt;최근 개인 프로젝트로 다양한 최적화 기법들을 실험해 봤는데, 초기 이미지 크기가 너무 커서 로컬 개발 환경의 디스크 공간을 많이 차지하는 문제가 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;배포 시간&lt;/b&gt;: 긴 이미지 빌드 및 전송 시간&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개발 환경&lt;/b&gt;: 로컬 디스크 공간 부족&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안 취약점&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;몇 주간 다양한 최적화 기법을 실험한 결과, 개인 프로젝트의 Python FastAPI 서비스를 &lt;b&gt;1.96GB에서 305MB&lt;/b&gt;로, Go API 서버를 &lt;b&gt;1.54GB에서 30MB&lt;/b&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;color: #000000;&quot;&gt;이번 글에서는 개인적으로 검증해본 Docker 이미지 최적화 전략을 두 언어로 나누어 소개하겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HYiFr/dJMcaaYhIA7/gKBdEMqBKFgS1ATL0Fany0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HYiFr/dJMcaaYhIA7/gKBdEMqBKFgS1ATL0Fany0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HYiFr/dJMcaaYhIA7/gKBdEMqBKFgS1ATL0Fany0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHYiFr%2FdJMcaaYhIA7%2FgKBdEMqBKFgS1ATL0Fany0%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;Docker 이미지 최적화 실전 가이드&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;왜 이미지 크기가 중요한가?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 운영에서 마주친 문제들&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;배포 지연 문제&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1.2GB 이미지 &amp;rarr; 새 인스턴스 시작까지 8분 소요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오토스케일링 시 급격한 트래픽 증가에 대응 불가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;인프라 비용 폭증&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS ECR 비용: 월 $300 &amp;rarr; $1,200 (4배 증가)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EKS 노드 디스크 풀 문제로 인한 스케일 아웃 필요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 비용 증가 (이미지 pull 트래픽)&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안 위험 증대&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;불필요한 패키지로 인한 CVE 취약점 300개 이상&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너 스캔 시간 10분 &amp;rarr; CI/CD 속도 저하&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최종 결과 미리보기&lt;/span&gt;&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 171px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;언어&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단계&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이미지 크기&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;감소율&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;누적 감소율&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Python&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 (python:latest)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1.96GB&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;slim 버전&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;703MB&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;64%&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;64%&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;alpine 버전&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;352MB&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;50%&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;82%&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;멀티스테이지&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;305MB&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;13%&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;84%&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Go&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 (golang:latest)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1.54GB&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;alpine 버전&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;628MB&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;59%&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;59%&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;멀티스테이지&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;30MB&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;95%&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;98%&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;scratch 베이스&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;15.3MB&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;49%&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;99%&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;color: #000000;&quot;&gt;Python FastAPI 최적화 단계별 가이드&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2964&quot; data-origin-height=&quot;356&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d4CXPL/btsQt4xgSO3/SsE9GCy5zK0KtQH2r99Dc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d4CXPL/btsQt4xgSO3/SsE9GCy5zK0KtQH2r99Dc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d4CXPL/btsQt4xgSO3/SsE9GCy5zK0KtQH2r99Dc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd4CXPL%2FbtsQt4xgSO3%2FSsE9GCy5zK0KtQH2r99Dc0%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;2964&quot; height=&quot;356&quot; data-origin-width=&quot;2964&quot; data-origin-height=&quot;356&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예제 애플리케이션 준비&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 운영 환경과 유사한 FastAPI 애플리케이션을 만들어보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756878662758&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import pandas as pd
import numpy as np
from datetime import datetime
import uvicorn
import os

app = FastAPI(title=&quot;ML Prediction API&quot;, version=&quot;1.0.0&quot;)

# 데이터 모델
class PredictionRequest(BaseModel):
    features: list[float]
    model_name: str = &quot;linear&quot;

class PredictionResponse(BaseModel):
    prediction: float
    confidence: float
    timestamp: str

# 간단한 ML 모델 시뮬레이션
class SimpleModel:
    def __init__(self):
        # 실제로는 pickle로 로드된 모델일 것
        self.weights = np.random.randn(10)
        
    def predict(self, features):
        if len(features) != len(self.weights):
            raise ValueError(&quot;Feature dimension mismatch&quot;)
        
        prediction = np.dot(features, self.weights)
        confidence = min(0.95, abs(prediction) / 10)
        return prediction, confidence

model = SimpleModel()

@app.get(&quot;/&quot;)
async def root():
    return {
        &quot;service&quot;: &quot;ML Prediction API&quot;,
        &quot;status&quot;: &quot;healthy&quot;,
        &quot;timestamp&quot;: datetime.now().isoformat()
    }

@app.get(&quot;/health&quot;)
async def health_check():
    return {
        &quot;status&quot;: &quot;ok&quot;,
        &quot;memory_usage&quot;: pd.DataFrame({&quot;test&quot;: [1, 2, 3]}).memory_usage(deep=True).sum()
    }

@app.post(&quot;/predict&quot;, response_model=PredictionResponse)
async def predict(request: PredictionRequest):
    try:
        if len(request.features) != 10:
            raise HTTPException(status_code=400, detail=&quot;Expected 10 features&quot;)
            
        prediction, confidence = model.predict(request.features)
        
        return PredictionResponse(
            prediction=float(prediction),
            confidence=float(confidence),
            timestamp=datetime.now().isoformat()
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

if __name__ == &quot;__main__&quot;:
    port = int(os.getenv(&quot;PORT&quot;, 8000))
    uvicorn.run(app, host=&quot;0.0.0.0&quot;, port=port)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1756878801406&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# requirements.txt
fastapi==0.104.1
uvicorn[standard]==0.24.0
pandas==2.2.0  # Python 3.13 호환 버전
numpy==1.26.0   # 최신 버전
pydantic==2.5.0&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1단계: 기본 베이스라인 (1.42GB)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756878837843&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Dockerfile.step1
FROM python:3.12

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

EXPOSE 8000
CMD [&quot;python&quot;, &quot;main.py&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1756878845783&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker build -f Dockerfile.step1 -t ml-api:step1 .
docker images | grep ml-api
# ml-api    step1    1.96GB&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;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;문제점&lt;/b&gt;: 전체 Debian 시스템 + Python 개발 도구 + 컴파일러 모두 포함&lt;/i&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2단계: Slim 베이스 이미지 (703MB, 64% 감소)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756878886590&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Dockerfile.step2  
FROM python:3.12-slim

WORKDIR /app

# 시스템 의존성 최소화
RUN apt-get update &amp;amp;&amp;amp; apt-get install -y \
    --no-install-recommends \
    gcc \
    &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/*

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000
CMD [&quot;python&quot;, &quot;main.py&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1756879189347&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker build -f Dockerfile.step2 -t ml-api:step2 .
docker images | grep ml-api
# ml-api    step2    703MB&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;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;개선점&lt;/b&gt;: Debian 슬림 버전으로 불필요한 패키지 제거&lt;/i&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3단계: Alpine 베이스 (352MB, 추가 50% 감소)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756879102262&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Dockerfile.step3
FROM python:3.12-alpine

WORKDIR /app

# Alpine에 필요한 빌드 도구들
RUN apk add --no-cache \
    gcc \
    g++ \
    musl-dev \
    linux-headers \
    gfortran \ 
    openblas-dev 

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 빌드 도구 정리
RUN apk del gcc g++ musl-dev linux-headers gfortran openblas-dev

COPY . .

EXPOSE 8000
CMD [&quot;python&quot;, &quot;main.py&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1756879277737&quot; class=&quot;bash&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;docker build -f Dockerfile.step3 -t ml-api:step3 .
docker images | grep ml-api
# ml-api    step3    352MB&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;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;주의사항&lt;/b&gt;: pandas와 numpy는 Alpine에서 컴파일 시간이 오래 걸림&lt;/i&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4단계: 멀티스테이지 빌드 (305MB, 추가 13% 감소)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756879347250&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Dockerfile.step4
FROM python:3.12-alpine AS builder  

WORKDIR /app

RUN apk add --no-cache \
    gcc \
    g++ \
    musl-dev \
    linux-headers \
    gfortran \
    openblas-dev

COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt

# 런타임 스테이지
FROM python:3.12-alpine

WORKDIR /app

RUN apk add --no-cache libstdc++

COPY --from=builder /root/.local /root/.local
COPY . .

ENV PATH=/root/.local/bin:$PATH

EXPOSE 8000
CMD [&quot;python&quot;, &quot;main.py&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1756879351620&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker build -f Dockerfile.step4 -t ml-api:step4 .
docker images | grep ml-api
# ml-api    step4    305MB&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;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;최종 결과&lt;/b&gt;: 305MB는 실무에서 실용성과 최적화의 균형점. pandas/numpy가 포함된 ML 애플리케이션에서는 이 정도가 현실적인 최적값이다.&lt;/i&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;&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;
&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;color: #000000;&quot;&gt;Go API 서버 최적화 단계별 가이드&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2958&quot; data-origin-height=&quot;340&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dT4nAY/btsQsHv5Vz0/04QYY3dsl9NEvrGzVkSKk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dT4nAY/btsQsHv5Vz0/04QYY3dsl9NEvrGzVkSKk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dT4nAY/btsQsHv5Vz0/04QYY3dsl9NEvrGzVkSKk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdT4nAY%2FbtsQsHv5Vz0%2F04QYY3dsl9NEvrGzVkSKk1%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;2958&quot; height=&quot;340&quot; data-origin-width=&quot;2958&quot; data-origin-height=&quot;340&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예제 애플리케이션 준비&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 운영 환경에서 사용하는 Go REST API 서버를 만들어보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1756883530756&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// main.go
package main

import (
    &quot;encoding/json&quot;
    &quot;fmt&quot;
    &quot;log&quot;
    &quot;net/http&quot;
    &quot;os&quot;
    &quot;strconv&quot;
    &quot;time&quot;

    &quot;github.com/gorilla/mux&quot;
    &quot;github.com/prometheus/client_golang/prometheus&quot;
    &quot;github.com/prometheus/client_golang/prometheus/promhttp&quot;
)

type User struct {
    ID        int       `json:&quot;id&quot;`
    Name      string    `json:&quot;name&quot;`
    Email     string    `json:&quot;email&quot;`
    CreatedAt time.Time `json:&quot;created_at&quot;`
}

type APIResponse struct {
    Status  string      `json:&quot;status&quot;`
    Message string      `json:&quot;message,omitempty&quot;`
    Data    interface{} `json:&quot;data,omitempty&quot;`
}

// Prometheus metrics
var (
    httpRequestsTotal = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: &quot;http_requests_total&quot;,
            Help: &quot;Total number of HTTP requests&quot;,
        },
        []string{&quot;method&quot;, &quot;endpoint&quot;, &quot;status&quot;},
    )
    httpRequestDuration = prometheus.NewHistogramVec(
        prometheus.HistogramOpts{
            Name: &quot;http_request_duration_seconds&quot;,
            Help: &quot;HTTP request duration in seconds&quot;,
        },
        []string{&quot;method&quot;, &quot;endpoint&quot;},
    )
)

// Mock database
var users = []User{
    {ID: 1, Name: &quot;Alice&quot;, Email: &quot;alice@example.com&quot;, CreatedAt: time.Now()},
    {ID: 2, Name: &quot;Bob&quot;, Email: &quot;bob@example.com&quot;, CreatedAt: time.Now()},
}

func init() {
    prometheus.MustRegister(httpRequestsTotal)
    prometheus.MustRegister(httpRequestDuration)
}

func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        log.Printf(&quot;%s %s %s&quot;, r.Method, r.RequestURI, r.RemoteAddr)
        next.ServeHTTP(w, r)
        duration := time.Since(start)
        log.Printf(&quot;Request completed in %v&quot;, duration)
    })
}

func metricsMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        next.ServeHTTP(w, r)
        duration := time.Since(start).Seconds()
        
        httpRequestsTotal.WithLabelValues(r.Method, r.URL.Path, &quot;200&quot;).Inc()
        httpRequestDuration.WithLabelValues(r.Method, r.URL.Path).Observe(duration)
    })
}

func healthHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set(&quot;Content-Type&quot;, &quot;application/json&quot;)
    response := APIResponse{
        Status: &quot;healthy&quot;,
        Data: map[string]interface{}{
            &quot;timestamp&quot;: time.Now(),
            &quot;service&quot;:   &quot;User API&quot;,
            &quot;version&quot;:   &quot;1.0.0&quot;,
        },
    }
    json.NewEncoder(w).Encode(response)
}

func getUsersHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set(&quot;Content-Type&quot;, &quot;application/json&quot;)
    response := APIResponse{
        Status: &quot;success&quot;,
        Data:   users,
    }
    json.NewEncoder(w).Encode(response)
}

func getUserHandler(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)
    id, err := strconv.Atoi(vars[&quot;id&quot;])
    if err != nil {
        w.WriteHeader(http.StatusBadRequest)
        response := APIResponse{
            Status:  &quot;error&quot;,
            Message: &quot;Invalid user ID&quot;,
        }
        json.NewEncoder(w).Encode(response)
        return
    }

    for _, user := range users {
        if user.ID == id {
            w.Header().Set(&quot;Content-Type&quot;, &quot;application/json&quot;)
            response := APIResponse{
                Status: &quot;success&quot;,
                Data:   user,
            }
            json.NewEncoder(w).Encode(response)
            return
        }
    }

    w.WriteHeader(http.StatusNotFound)
    response := APIResponse{
        Status:  &quot;error&quot;,
        Message: &quot;User not found&quot;,
    }
    json.NewEncoder(w).Encode(response)
}

func createUserHandler(w http.ResponseWriter, r *http.Request) {
    var user User
    if err := json.NewDecoder(r.Body).Decode(&amp;amp;user); err != nil {
        w.WriteHeader(http.StatusBadRequest)
        response := APIResponse{
            Status:  &quot;error&quot;,
            Message: &quot;Invalid JSON&quot;,
        }
        json.NewEncoder(w).Encode(response)
        return
    }

    user.ID = len(users) + 1
    user.CreatedAt = time.Now()
    users = append(users, user)

    w.Header().Set(&quot;Content-Type&quot;, &quot;application/json&quot;)
    w.WriteHeader(http.StatusCreated)
    response := APIResponse{
        Status: &quot;success&quot;,
        Data:   user,
    }
    json.NewEncoder(w).Encode(response)
}

func main() {
    r := mux.NewRouter()
    
    // Middleware
    r.Use(loggingMiddleware)
    r.Use(metricsMiddleware)
    
    // Routes
    r.HandleFunc(&quot;/health&quot;, healthHandler).Methods(&quot;GET&quot;)
    r.HandleFunc(&quot;/users&quot;, getUsersHandler).Methods(&quot;GET&quot;)
    r.HandleFunc(&quot;/users/{id:[0-9]+}&quot;, getUserHandler).Methods(&quot;GET&quot;)
    r.HandleFunc(&quot;/users&quot;, createUserHandler).Methods(&quot;POST&quot;)
    r.Handle(&quot;/metrics&quot;, promhttp.Handler())

    port := os.Getenv(&quot;PORT&quot;)
    if port == &quot;&quot; {
        port = &quot;8080&quot;
    }

    log.Printf(&quot;Server starting on port %s&quot;, port)
    log.Fatal(http.ListenAndServe(fmt.Sprintf(&quot;:%s&quot;, port), r))
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1756883543168&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// go.mod
module user-api

go 1.21

require (
    github.com/gorilla/mux v1.8.1
    github.com/prometheus/client_golang v1.17.0
)&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`go.sum` 생성&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756883767615&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;go mod tidy&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1단계: 기본 베이스라인 (1.54GB)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756883562053&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Dockerfile.step1
FROM golang:1.24

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN go build -o main .

EXPOSE 8080
CMD [&quot;./main&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1756883572328&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker build -f Dockerfile.step1 -t user-api:step1 .
docker images | grep user-api
# user-api    step1    1.54GB&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;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;문제점&lt;/b&gt;: Go 개발 환경 전체 + 빌드 도구 + Git 등 불필요한 도구들 포함&lt;/i&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2단계: Alpine 베이스 (628MB, 59% 감소)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756883594745&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Dockerfile.step2
FROM golang:1.24-alpine

WORKDIR /app

# Git 설치 (go mod download에 필요할 수 있음)
RUN apk add --no-cache git

COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN go build -o main .

EXPOSE 8080
CMD [&quot;./main&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1756883601979&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker build -f Dockerfile.step2 -t user-api:step2 .
docker images | grep user-api
# user-api    step2    628MB&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;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;개선점&lt;/b&gt;: Alpine Linux로 기본 OS 크기 대폭 감소&lt;/i&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3단계: 멀티스테이지 빌드 (30MB, 92% 감소)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756883629087&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Dockerfile.step3
FROM golang:1.24-alpine AS builder

WORKDIR /app

# 의존성 캐싱을 위한 레이어 분리
COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags=&quot;-w -s&quot; -o main .

# 런타임 스테이지
FROM alpine:latest

WORKDIR /root/

# SSL 인증서와 타임존 정보 추가
RUN apk --no-cache add ca-certificates tzdata
COPY --from=builder /app/main .

EXPOSE 8080
CMD [&quot;./main&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1756883969393&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker build -f Dockerfile.step3 -t user-api:step3 .
docker images | grep user-api
# user-api    step3    30MB&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개선점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`CGO_ENABLED=0`: C 라이브러리 의존성 제거&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`-ldflags=&quot;-w -s&quot;`: 디버그 정보와 심볼 테이블 제거&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Alpine 런타임으로 최소한의 환경만 포함&lt;/span&gt;&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4단계: Scratch 베이스 (8.2MB, 71% 추가 감소)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756883807737&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Dockerfile.step4
FROM golang:1.24-alpine AS builder

WORKDIR /app

# Alpine에 필요한 패키지 설치
RUN apk --no-cache add ca-certificates tzdata

COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags=&quot;-w -s&quot; -o main .

# 최종 스테이지: scratch (빈 이미지)
FROM scratch

# SSL 인증서 복사 (HTTPS 요청을 위해 필요)
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

# 타임존 정보 복사 (Alpine의 경우)
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo

COPY --from=builder /app/main /main

EXPOSE 8080
ENTRYPOINT [&quot;/main&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1756883816965&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker build -f Dockerfile.step4 -t user-api:step4 .
docker images | grep user-api
# user-api    step4    15.3MB&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;최종 최적화&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;scratch: 완전히 빈 베이스 이미지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-a -installsuffix cgo: 완전한 정적 빌드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;필수 파일만 선별적 복사 (SSL 인증서, 타임존 정보)&lt;/span&gt;&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;&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;
&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;color: #000000;&quot;&gt;최적화 전략 비교 및 선택 가이드&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Python vs Go 최적화 특성&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Python&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Go&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최적화 한계&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;305MB (의존성 때문)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;15.3MB (정적 빌드)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡도&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간 (의존성 관리)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음 (간단한 빌드)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;빌드 시간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;길음 (numpy/pandas 컴파일)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;빠름 (네이티브 컴파일)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;디버깅 용이성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;좋음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적 (scratch 사용 시)&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실무 권장사항&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Python 프로젝트&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;멀티스테이지 Alpine (305MB)까지가 실용적&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ML 라이브러리가 없다면 더 작게 가능 (~50MB)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Distroless는 복잡성 대비 이득 적음&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Go 프로젝트&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Scratch 베이스 (15.3MB) 적극 권장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부 C 라이브러리 사용 시 Alpine 고려 (30MB)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;디버깅이 필요한 개발 환경에서는 Alpine 사용&lt;/span&gt;&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;&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;color: #000000;&quot;&gt;고급 최적화 기법&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`.dockerignore` 활용&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756884676213&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# .dockerignore
.git
.gitignore
README.md
Dockerfile*
.DS_Store
node_modules
npm-debug.log
coverage/
.nyc_output
*.log
.env.local
.env.development.local
.env.test.local
.env.production.local&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;결론&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Docker 이미지 최적화는 단순히 크기를 줄이는 것을 넘어, &lt;b&gt;배포 속도 개선&lt;/b&gt;, &lt;b&gt;로컬 개발 환경 효율 증대&lt;/b&gt;, &lt;b&gt;보안 강화&lt;/b&gt;라는 세 가지 핵심 가치를 동시에 달성하는 전략이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1852&quot; data-origin-height=&quot;1582&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ytuuj/btsQtUg7STV/ohdPXlSnpZJceqCLE4uGZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ytuuj/btsQtUg7STV/ohdPXlSnpZJceqCLE4uGZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ytuuj/btsQtUg7STV/ohdPXlSnpZJceqCLE4uGZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fytuuj%2FbtsQtUg7STV%2FohdPXlSnpZJceqCLE4uGZ0%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;1852&quot; height=&quot;1582&quot; data-origin-width=&quot;1852&quot; data-origin-height=&quot;1582&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 원칙&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;언어 특성에 맞는 접근&lt;/b&gt;: Python은 의존성 관리, Go는 정적 빌드가 핵심이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;단계적 최적화&lt;/b&gt;: 한 번에 모든 것을 바꾸려 하지 말고 단계별로 접근해야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실용성 우선&lt;/b&gt;: 복잡성 대비 효과를 고려하여 최적점을 찾는 것이 중요하다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;지속적 모니터링&lt;/b&gt;: CI/CD에 이미지 크기 체크를 자동화하는 것이 좋다.&lt;/span&gt;&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;span style=&quot;color: #000000;&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;color: #000000;&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;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.docker.com/develop/develop-images/dockerfile_best-practices/&quot;&gt;https://docs.docker.com/develop/develop-images/dockerfile_best-practices/&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/GoogleContainerTools/distroless&quot;&gt;https://github.com/GoogleContainerTools/distroless&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://hub.docker.com/_/python&quot;&gt;https://hub.docker.com/_/python&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://pythonspeed.com/articles/smaller-python-docker-images/&quot;&gt;https://pythonspeed.com/articles/smaller-python-docker-images/&lt;/a&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;&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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>IaC/Container</category>
      <category>Network</category>
      <category>topology</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/450</guid>
      <comments>https://somaz.tistory.com/450#entry450comment</comments>
      <pubDate>Tue, 10 Feb 2026 00:00:13 +0900</pubDate>
    </item>
    <item>
      <title>네트워크 토폴로지 모델 완전 가이드: 허브-스포크부터 메시까지</title>
      <link>https://somaz.tistory.com/454</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 토폴로지는 컴퓨터 네트워크에서 노드들 간의 물리적 또는 논리적 연결 구조를 의미한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;본 글에서는 현대 &lt;b&gt;네트워크 설계에서 핵심적인 토폴로지 모델들을 비교 분석&lt;/b&gt;하고, 각각의 특성과 적용 시나리오를 심층적으로 탐구한다. 특히 클라우드 환경에서 주목받는 &lt;b&gt;허브-스포크 모델을 중심&lt;/b&gt;으로 실무적 관점에서 살펴본다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1622&quot; data-origin-height=&quot;1052&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nhEEj/dJMcac9z4TN/nUyfgkFyihCtWz9C1a5Zi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nhEEj/dJMcac9z4TN/nUyfgkFyihCtWz9C1a5Zi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nhEEj/dJMcac9z4TN/nUyfgkFyihCtWz9C1a5Zi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnhEEj%2FdJMcac9z4TN%2FnUyfgkFyihCtWz9C1a5Zi1%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;1622&quot; height=&quot;1052&quot; data-origin-width=&quot;1622&quot; data-origin-height=&quot;1052&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;&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-origin-width=&quot;2326&quot; data-origin-height=&quot;998&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxz95V/btsQmq10f2T/MnEFbZNjVWVeYR6R1mDKc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxz95V/btsQmq10f2T/MnEFbZNjVWVeYR6R1mDKc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxz95V/btsQmq10f2T/MnEFbZNjVWVeYR6R1mDKc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbxz95V%2FbtsQmq10f2T%2FMnEFbZNjVWVeYR6R1mDKc1%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;2326&quot; height=&quot;998&quot; data-origin-width=&quot;2326&quot; data-origin-height=&quot;998&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크&amp;nbsp;토폴로지&amp;nbsp;모델&amp;nbsp;완전&amp;nbsp;가이드&lt;/span&gt;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;span style=&quot;color: #000000;&quot;&gt;허브-스포크부터&amp;nbsp;메시까지&lt;/span&gt;&lt;/i&gt;&lt;/u&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 토폴로지의 기본 이해&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;토폴로지 분류 체계&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;물리적 토폴로지 (Physical Topology)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 케이블과 장비의 물리적 배치&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하드웨어 연결 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;논리적 토폴로지 (Logical Topology)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 흐름과 통신 경로&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로토콜과 알고리즘에 의해 결정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;토폴로지 설계 원칙&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;효과적인 네트워크 토폴로지 설계를 위해서는 다음 원칙들을 고려해야 한다.&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;확장성 (Scalability)&lt;/b&gt;: 노드 추가 시 복잡성 증가율&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;신뢰성 (Reliability)&lt;/b&gt;: 장애 허용 능력과 복구 메커니즘&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;성능 (Performance)&lt;/b&gt;: 지연시간, 대역폭, 처리량&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비용 효율성 (Cost Efficiency)&lt;/b&gt;: 구축 및 운영 비용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;관리 복잡성 (Management Complexity)&lt;/b&gt;: 운영 및 유지보수 난이도&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;허브-스포크 모델 (Hub-and-Spoke Model)&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 구조와 개념&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;허브-스포크 모델은 중앙의 허브(Hub)를 통해 여러 스포크(Spoke)들이 연결되는 구조다. 이 모델은 자전거 바퀴의 중심축과 바퀴살 형태에서 이름을 따왔으며, 중앙집중식 네트워크 아키텍처의 대표적인 패턴이다.&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;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;핵심 특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 통신이 중앙 허브를 경유&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스포크 간 직접 통신 불가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중앙집중식 제어 및 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;허브-스포크의 수학적 분석&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;연결 복잡도&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;n개 노드 연결 시: n개의 링크 필요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시간 복잡도: O(n)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;공간 복잡도: O(n)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비교 분석&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;excel&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;메시 토폴로지: n(n-1)/2 = O(n&amp;sup2;)
허브-스포크: n = O(n)
&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예시로 10개의 노드를 연결할 경우&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메시 토폴로지: 45개의 연결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;허브-스포크: 10개의 연결&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;허브-스포크의 장점&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 확장성 우수&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;새로운 노드 추가 시 기존 연결에 영향 없이 허브에만 연결하면 된다. 이는 선형적 확장성을 제공하여 대규모 네트워크 구축에 유리하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 중앙집중식 관리&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 트래픽이 허브를 경유하므로 다음과 같은 이점을 제공한다:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;통합 보안 정책 적용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중앙화된 모니터링과 로깅&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일관된 라우팅 정책&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 비용 효율성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;연결 수의 선형적 증가로 인해 비용 예측이 용이하고, 중복 인프라를 제거할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 정책 일관성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;허브-스포크의 단점&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 단일 장애점 (Single Point of Failure)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;허브 장애 시 전체 네트워크가 마비될 수 있다. 이를 완화하기 위한 방법들:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;허브 이중화 구성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클러스터링을 통한 고가용성 확보&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 성능 병목&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 트래픽이 허브를 경유하므로 다음과 같은 성능 이슈가 발생할 수 있다:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;허브의 처리 능력에 의한 성능 제한&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추가 홉으로 인한 지연시간 증가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 확장성 제한&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메시 토폴로지 (Mesh Topology)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;풀 메시 (Full Mesh)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최대 신뢰성 제공&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최단 경로 통신 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단일 장애점 없음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높은 구축 비용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;연결 수 계산:&lt;/b&gt;&amp;nbsp;n개 노드의 풀 메시: n(n-1)/2개의 연결&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;&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;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;부분 메시 (Partial Mesh)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;풀 메시 대비 비용 절약&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중요한 경로는 직접 연결로 성능 보장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡한 라우팅 계획 필요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스타 토폴로지 (Star Topology)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 구조&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가장 간단한 중앙집중형 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중앙 노드를 통한 모든 통신&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쉬운 설치와 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장단점 분석&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;간단한 설치와 구성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쉬운 문제 해결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중앙집중식 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중앙 노드 의존성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;확장성 제한&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;링 토폴로지 (Ring Topology)&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구조와 동작 원리&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단방향 또는 양방향 데이터 전송&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;토큰 패싱 방식 주로 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예측 가능한 성능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;종류&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;단일 링&lt;/b&gt;: 한 방향으로만 데이터 전송&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;이중 링&lt;/b&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;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;
&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;버스 토폴로지 (Bus Topology)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 개념&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단순한 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 효율적&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쉬운 확장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;프로토콜&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CSMA/CD (Carrier Sense Multiple Access with Collision Detection)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트리 토폴로지 (Tree Topology)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;계층적 구조&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;계층적 관리 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;확장성과 관리성의 균형&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;부분적 단일 장애점&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하이브리드 토폴로지 (Hybrid Topology)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복합 구조의 필요성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;일반적인 조합&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스타-버스&lt;/b&gt;: LAN에서 스타, WAN에서 버스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스타-링&lt;/b&gt;: 백본은 링, 접근은 스타&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;메시-허브스포크&lt;/b&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라우드 환경에서의 토폴로지 구현&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS에서의 허브-스포크 구현&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS Transit Gateway를 활용한 허브-스포크 모델 구현&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 중앙 허브 역할의 Transit Gateway
resource &quot;aws_ec2_transit_gateway&quot; &quot;central_hub&quot; {
  description                     = &quot;Central Hub for Enterprise Network&quot;
  default_route_table_association = &quot;disable&quot;
  default_route_table_propagation = &quot;disable&quot;
  dns_support                     = &quot;enable&quot;
  vpn_ecmp_support               = &quot;enable&quot;
  
  tags = {
    Name = &quot;enterprise-hub-tgw&quot;
    Pattern = &quot;hub-spoke&quot;
  }
}

# 환경별 라우팅 테이블 생성
resource &quot;aws_ec2_transit_gateway_route_table&quot; &quot;production&quot; {
  transit_gateway_id = aws_ec2_transit_gateway.central_hub.id
  
  tags = {
    Name = &quot;production-route-table&quot;
    Environment = &quot;production&quot;
  }
}

resource &quot;aws_ec2_transit_gateway_route_table&quot; &quot;development&quot; {
  transit_gateway_id = aws_ec2_transit_gateway.central_hub.id
  
  tags = {
    Name = &quot;development-route-table&quot; 
    Environment = &quot;development&quot;
  }
}

resource &quot;aws_ec2_transit_gateway_route_table&quot; &quot;shared_services&quot; {
  transit_gateway_id = aws_ec2_transit_gateway.central_hub.id
  
  tags = {
    Name = &quot;shared-services-route-table&quot;
    Environment = &quot;shared&quot;
  }
}

# VPC 어태치먼트 (스포크 역할)
resource &quot;aws_ec2_transit_gateway_vpc_attachment&quot; &quot;production_spoke&quot; {
  subnet_ids                                      = [aws_subnet.prod_tgw.id]
  transit_gateway_id                              = aws_ec2_transit_gateway.central_hub.id
  vpc_id                                          = aws_vpc.production.id
  transit_gateway_default_route_table_association = false
  transit_gateway_default_route_table_propagation = false
  
  tags = {
    Name = &quot;production-spoke-attachment&quot;
    Role = &quot;spoke&quot;
  }
}

# 네트워크 세분화를 위한 라우팅 연결
resource &quot;aws_ec2_transit_gateway_route_table_association&quot; &quot;prod_association&quot; {
  transit_gateway_attachment_id  = aws_ec2_transit_gateway_vpc_attachment.production_spoke.id
  transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.production.id
}

# 선택적 통신을 위한 라우트 설정
resource &quot;aws_ec2_transit_gateway_route&quot; &quot;prod_to_shared_dns&quot; {
  destination_cidr_block         = &quot;10.100.0.0/24&quot;  # DNS 서브넷
  transit_gateway_attachment_id  = aws_ec2_transit_gateway_vpc_attachment.shared_services.id
  transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.production.id
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Azure에서의 허브-스포크 구현&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Azure Virtual WAN을 활용한 구현&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# Virtual WAN 생성 (허브 역할)
resource &quot;azurerm_virtual_wan&quot; &quot;enterprise_wan&quot; {
  name                = &quot;enterprise-vwan&quot;
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  type               = &quot;Standard&quot;
  
  tags = {
    Environment = &quot;production&quot;
    Pattern     = &quot;hub-spoke&quot;
  }
}

# Virtual Hub 생성
resource &quot;azurerm_virtual_hub&quot; &quot;main_hub&quot; {
  name                = &quot;main-hub&quot;
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  virtual_wan_id      = azurerm_virtual_wan.enterprise_wan.id
  address_prefix      = &quot;10.0.0.0/24&quot;
  
  tags = {
    Role = &quot;hub&quot;
  }
}

# 스포크 VNet 연결
resource &quot;azurerm_virtual_hub_connection&quot; &quot;spoke_connection&quot; {
  name                      = &quot;spoke-vnet-connection&quot;
  virtual_hub_id            = azurerm_virtual_hub.main_hub.id
  remote_virtual_network_id = azurerm_virtual_network.spoke_vnet.id
  
  routing {
    associated_route_table_id = azurerm_virtual_hub_route_table.custom.id
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;GCP에서의 허브-스포크 구현&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GCP Network Connectivity Center와 VPC Peering을 활용한 구현&lt;/p&gt;
&lt;pre id=&quot;code_1757054543464&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Network Connectivity Center Hub 생성 (허브 역할)
resource &quot;google_network_connectivity_hub&quot; &quot;enterprise_hub&quot; {
  name        = &quot;enterprise-hub&quot;
  description = &quot;Central hub for enterprise network connectivity&quot;
  project     = var.project_id
  
  labels = {
    environment = &quot;production&quot;
    pattern     = &quot;hub-spoke&quot;
  }
}

# 허브 VPC 네트워크 생성
resource &quot;google_compute_network&quot; &quot;hub_network&quot; {
  name                    = &quot;hub-network&quot;
  auto_create_subnetworks = false
  routing_mode           = &quot;GLOBAL&quot;
  project                = var.project_id
}

# 허브 서브넷 생성
resource &quot;google_compute_subnetwork&quot; &quot;hub_subnet&quot; {
  name          = &quot;hub-subnet&quot;
  ip_cidr_range = &quot;10.0.0.0/24&quot;
  region        = var.region
  network       = google_compute_network.hub_network.id
  project       = var.project_id
}

# Production 스포크 VPC 생성
resource &quot;google_compute_network&quot; &quot;production_spoke&quot; {
  name                    = &quot;production-spoke&quot;
  auto_create_subnetworks = false
  routing_mode           = &quot;REGIONAL&quot;
  project                = var.project_id
}

resource &quot;google_compute_subnetwork&quot; &quot;production_subnet&quot; {
  name          = &quot;production-subnet&quot;
  ip_cidr_range = &quot;10.1.0.0/16&quot;
  region        = var.region
  network       = google_compute_network.production_spoke.id
  project       = var.project_id
}

# Development 스포크 VPC 생성
resource &quot;google_compute_network&quot; &quot;development_spoke&quot; {
  name                    = &quot;development-spoke&quot;
  auto_create_subnetworks = false
  routing_mode           = &quot;REGIONAL&quot;
  project                = var.project_id
}

resource &quot;google_compute_subnetwork&quot; &quot;development_subnet&quot; {
  name          = &quot;development-subnet&quot;
  ip_cidr_range = &quot;10.2.0.0/16&quot;
  region        = var.region
  network       = google_compute_network.development_spoke.id
  project       = var.project_id
}

# 허브-스포크 VPC Peering 연결 (Production)
resource &quot;google_compute_network_peering&quot; &quot;hub_to_production&quot; {
  name         = &quot;hub-to-production&quot;
  network      = google_compute_network.hub_network.self_link
  peer_network = google_compute_network.production_spoke.self_link
  
  export_custom_routes = true
  import_custom_routes = true
  
  export_subnet_routes_with_public_ip = false
  import_subnet_routes_with_public_ip = false
}

resource &quot;google_compute_network_peering&quot; &quot;production_to_hub&quot; {
  name         = &quot;production-to-hub&quot;
  network      = google_compute_network.production_spoke.self_link
  peer_network = google_compute_network.hub_network.self_link
  
  export_custom_routes = true
  import_custom_routes = true
  
  export_subnet_routes_with_public_ip = false
  import_subnet_routes_with_public_ip = false
}

# 허브-스포크 VPC Peering 연결 (Development)
resource &quot;google_compute_network_peering&quot; &quot;hub_to_development&quot; {
  name         = &quot;hub-to-development&quot;
  network      = google_compute_network.hub_network.self_link
  peer_network = google_compute_network.development_spoke.self_link
  
  export_custom_routes = true
  import_custom_routes = false  # Development는 제한된 라우트만 허용
  
  export_subnet_routes_with_public_ip = false
  import_subnet_routes_with_public_ip = false
}

resource &quot;google_compute_network_peering&quot; &quot;development_to_hub&quot; {
  name         = &quot;development-to-hub&quot;
  network      = google_compute_network.development_spoke.self_link
  peer_network = google_compute_network.hub_network.self_link
  
  export_custom_routes = false  # Development에서 허브로의 라우트 내보내기 제한
  import_custom_routes = true
  
  export_subnet_routes_with_public_ip = false
  import_subnet_routes_with_public_ip = false
}

# Network Connectivity Center Spoke 등록
resource &quot;google_network_connectivity_spoke&quot; &quot;production_spoke_registration&quot; {
  name     = &quot;production-spoke&quot;
  location = &quot;global&quot;
  hub      = google_network_connectivity_hub.enterprise_hub.id
  
  linked_vpc_network {
    uri                              = google_compute_network.production_spoke.self_link
    exclude_export_ranges            = [&quot;10.2.0.0/16&quot;]  # Development 네트워크 제외
    include_export_ranges            = [&quot;10.1.0.0/16&quot;]  # Production 네트워크만 포함
  }
  
  labels = {
    environment = &quot;production&quot;
    role        = &quot;spoke&quot;
  }
}

resource &quot;google_network_connectivity_spoke&quot; &quot;development_spoke_registration&quot; {
  name     = &quot;development-spoke&quot;
  location = &quot;global&quot;
  hub      = google_network_connectivity_hub.enterprise_hub.id
  
  linked_vpc_network {
    uri                              = google_compute_network.development_spoke.self_link
    exclude_export_ranges            = [&quot;10.1.0.0/16&quot;]  # Production 네트워크 제외
    include_export_ranges            = [&quot;10.2.0.0/16&quot;]  # Development 네트워크만 포함
  }
  
  labels = {
    environment = &quot;development&quot;
    role        = &quot;spoke&quot;
  }
}

# 공유 서비스를 위한 별도 VPC (DNS, 모니터링 등)
resource &quot;google_compute_network&quot; &quot;shared_services&quot; {
  name                    = &quot;shared-services&quot;
  auto_create_subnetworks = false
  routing_mode           = &quot;GLOBAL&quot;
  project                = var.project_id
}

resource &quot;google_compute_subnetwork&quot; &quot;shared_services_subnet&quot; {
  name          = &quot;shared-services-subnet&quot;
  ip_cidr_range = &quot;10.100.0.0/24&quot;
  region        = var.region
  network       = google_compute_network.shared_services.id
  project       = var.project_id
}

# 공유 서비스 VPC와 허브 연결
resource &quot;google_compute_network_peering&quot; &quot;hub_to_shared&quot; {
  name         = &quot;hub-to-shared-services&quot;
  network      = google_compute_network.hub_network.self_link
  peer_network = google_compute_network.shared_services.self_link
  
  export_custom_routes = true
  import_custom_routes = true
}

resource &quot;google_compute_network_peering&quot; &quot;shared_to_hub&quot; {
  name         = &quot;shared-services-to-hub&quot;
  network      = google_compute_network.shared_services.self_link
  peer_network = google_compute_network.hub_network.self_link
  
  export_custom_routes = true
  import_custom_routes = true
}

# Cloud Router 및 Cloud NAT 설정 (아웃바운드 인터넷 접근)
resource &quot;google_compute_router&quot; &quot;hub_router&quot; {
  name    = &quot;hub-router&quot;
  region  = var.region
  network = google_compute_network.hub_network.id
  project = var.project_id
  
  bgp {
    asn = 64512
  }
}

resource &quot;google_compute_router_nat&quot; &quot;hub_nat&quot; {
  name                               = &quot;hub-nat&quot;
  router                            = google_compute_router.hub_router.name
  region                            = var.region
  nat_ip_allocate_option            = &quot;AUTO_ONLY&quot;
  source_subnetwork_ip_ranges_to_nat = &quot;ALL_SUBNETWORKS_ALL_IP_RANGES&quot;
  project                           = var.project_id
  
  log_config {
    enable = true
    filter = &quot;ERRORS_ONLY&quot;
  }
}

# 방화벽 규칙 - 환경별 트래픽 제어
resource &quot;google_compute_firewall&quot; &quot;allow_hub_to_spokes&quot; {
  name    = &quot;allow-hub-to-spokes&quot;
  network = google_compute_network.hub_network.name
  project = var.project_id
  
  allow {
    protocol = &quot;tcp&quot;
    ports    = [&quot;22&quot;, &quot;80&quot;, &quot;443&quot;]
  }
  
  allow {
    protocol = &quot;icmp&quot;
  }
  
  source_ranges = [&quot;10.0.0.0/24&quot;]  # 허브 서브넷
  target_tags   = [&quot;spoke-vm&quot;]
  
  description = &quot;Allow traffic from hub to spokes&quot;
}

resource &quot;google_compute_firewall&quot; &quot;deny_cross_spoke&quot; {
  name     = &quot;deny-cross-spoke-communication&quot;
  network  = google_compute_network.hub_network.name
  project  = var.project_id
  priority = 1000
  
  deny {
    protocol = &quot;all&quot;
  }
  
  source_ranges = [&quot;10.1.0.0/16&quot;, &quot;10.2.0.0/16&quot;]  # Production, Development
  target_tags   = [&quot;cross-spoke-deny&quot;]
  
  description = &quot;Deny direct communication between spokes&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 및 확장성 비교 분석&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정량적 비교 지표&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;토폴로지&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;연결 복잡도&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지연시간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;신뢰성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;확장성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;허브-스포크&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O(n)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;풀 메시&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O(n&amp;sup2;)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스타&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O(n)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;링&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O(n)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;버스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O(n)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트래픽 패턴에 따른 선택 기준&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;East-West 트래픽이 많은 경우&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메시 토폴로지 선호&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;North-South 트래픽이 주된 경우&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;허브-스포크 모델 적합&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;혼합 트래픽 패턴&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하이브리드 접근법&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 관점에서의 토폴로지 분석&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;허브-스포크의 보안 이점&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 중앙집중식 보안 제어&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단일 지점에서 모든 보안 정책 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일관된 보안 정책 적용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 네트워크 세분화 (Segmentation)&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;환경별 트래픽 격리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제로 트러스트 아키텍처 구현&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 트래픽 검사 및 필터링&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중앙 허브에서의 심층 패킷 검사&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;침입 탐지/방지 시스템 통합&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 손실 방지 (DLP) 적용&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 설계 패턴&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 보안 강화를 위한 허브-스포크 설계
resource &quot;aws_ec2_transit_gateway_route_table&quot; &quot;security_inspection&quot; {
  transit_gateway_id = aws_ec2_transit_gateway.central_hub.id
  
  tags = {
    Name = &quot;security-inspection-route-table&quot;
    Purpose = &quot;traffic-inspection&quot;
  }
}

# 보안 VPC (방화벽/IDS 포함)
resource &quot;aws_ec2_transit_gateway_vpc_attachment&quot; &quot;security_vpc&quot; {
  subnet_ids         = [aws_subnet.security_inspection.id]
  transit_gateway_id = aws_ec2_transit_gateway.central_hub.id
  vpc_id            = aws_vpc.security.id
  
  tags = {
    Name = &quot;security-inspection-attachment&quot;
    Role = &quot;security-hub&quot;
  }
}

# 트래픽을 보안 VPC로 라우팅
resource &quot;aws_ec2_transit_gateway_route&quot; &quot;inspect_traffic&quot; {
  destination_cidr_block         = &quot;0.0.0.0/0&quot;
  transit_gateway_attachment_id  = aws_ec2_transit_gateway_vpc_attachment.security_vpc.id
  transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.security_inspection.id
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모니터링 및 운영 전략&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 모니터링 지표&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 허브-스포크 모델&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;허브 성능 지표&lt;/b&gt;: CPU 사용률, 메모리 사용률, 처리량&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;네트워크 지표&lt;/b&gt;: 지연시간, 패킷 손실률, 대역폭 사용률&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;연결 상태&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 메시 토폴로지&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;링크별 성능&lt;/b&gt;: 각 직접 연결의 상태와 성능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;경로 최적화&lt;/b&gt;: 최단 경로 vs 실제 사용 경로&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;로드 밸런싱&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동화된 모니터링 구현&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# CloudWatch 메트릭을 활용한 허브-스포크 모니터링
import boto3
import json

def monitor_transit_gateway_performance():
    cloudwatch = boto3.client('cloudwatch')
    ec2 = boto3.client('ec2')
    
    # Transit Gateway 목록 조회
    tgws = ec2.describe_transit_gateways()
    
    for tgw in tgws['TransitGateways']:
        tgw_id = tgw['TransitGatewayId']
        
        # 데이터 처리량 메트릭 조회
        response = cloudwatch.get_metric_statistics(
            Namespace='AWS/TransitGateway',
            MetricName='BytesIn',
            Dimensions=[
                {
                    'Name': 'TransitGateway',
                    'Value': tgw_id
                }
            ],
            StartTime=datetime.now() - timedelta(hours=1),
            EndTime=datetime.now(),
            Period=300,
            Statistics=['Sum', 'Average']
        )
        
        # 임계값 체크 및 알림
        for datapoint in response['Datapoints']:
            if datapoint['Sum'] &amp;gt; THRESHOLD_BYTES:
                send_alert(f&quot;TGW {tgw_id} high traffic detected: {datapoint['Sum']} bytes&quot;)

def check_spoke_connectivity():
    &quot;&quot;&quot;스포크 연결 상태 확인&quot;&quot;&quot;
    ec2 = boto3.client('ec2')
    
    attachments = ec2.describe_transit_gateway_attachments()
    
    for attachment in attachments['TransitGatewayAttachments']:
        if attachment['State'] != 'available':
            send_alert(f&quot;Spoke attachment {attachment['TransitGatewayAttachmentId']} is {attachment['State']}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 전략&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;토폴로지별 비용 분석&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 허브-스포크 모델&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고정 비용&lt;/b&gt;: 허브 인프라 (Transit Gateway, Virtual WAN)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;변동 비용&lt;/b&gt;: 어태치먼트별 시간당 요금, 데이터 전송 비용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;최적화 방안&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 메시 토폴로지&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고정 비용&lt;/b&gt;: 다수의 직접 연결 (VPC Peering, Express Route)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;변동 비용&lt;/b&gt;: 연결별 데이터 전송 비용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;최적화 방안&lt;/b&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 모니터링 자동화&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;nix&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;# 비용 알림을 위한 CloudWatch 알람
resource &quot;aws_cloudwatch_metric_alarm&quot; &quot;tgw_cost_alarm&quot; {
  alarm_name          = &quot;transit-gateway-high-cost&quot;
  comparison_operator = &quot;GreaterThanThreshold&quot;
  evaluation_periods  = &quot;2&quot;
  metric_name         = &quot;EstimatedCharges&quot;
  namespace           = &quot;AWS/Billing&quot;
  period              = &quot;86400&quot;  # 24 hours
  statistic           = &quot;Maximum&quot;
  threshold           = &quot;1000&quot;   # $1000
  alarm_description   = &quot;This metric monitors Transit Gateway costs&quot;
  
  dimensions = {
    Currency = &quot;USD&quot;
    ServiceName = &quot;AmazonVPC&quot;
  }
  
  alarm_actions = [aws_sns_topic.cost_alerts.arn]
}

# 비용 최적화를 위한 Lambda 함수
resource &quot;aws_lambda_function&quot; &quot;cost_optimizer&quot; {
  filename         = &quot;cost_optimizer.zip&quot;
  function_name    = &quot;network-cost-optimizer&quot;
  role            = aws_iam_role.lambda_role.arn
  handler         = &quot;index.handler&quot;
  runtime         = &quot;python3.9&quot;
  
  environment {
    variables = {
      SNS_TOPIC_ARN = aws_sns_topic.cost_alerts.arn
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;미래 기술 동향과 토폴로지 진화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SD-WAN과 토폴로지&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Software-Defined WAN은 기존 토폴로지 개념을 혁신하고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;동적 경로 선택&lt;/b&gt;: 실시간 성능 기반 라우팅&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;하이브리드 연결&lt;/b&gt;: 다양한 연결 방식의 동적 조합&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;중앙집중식 정책 관리&lt;/b&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;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라우드 네이티브 아키텍처&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너와 마이크로서비스 환경에서의 토폴로지&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;서비스 메시&lt;/b&gt;: 애플리케이션 레벨의 네트워크 토폴로지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;CNI 기반 네트워킹&lt;/b&gt;: Kubernetes 네트워크 플러그인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;멀티 클라우드 연결&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5G와 엣지 컴퓨팅&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;차세대 네트워크 기술이 토폴로지에 미치는 영향&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;엣지-클라우드 하이브리드&lt;/b&gt;: 분산된 허브-스포크 모델&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;초저지연 요구사항&lt;/b&gt;: 새로운 토폴로지 패러다임 필요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;동적 네트워크 슬라이싱&lt;/b&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;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;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;토폴로지 선택 가이드라인&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;의사결정 프레임워크&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1단계: 요구사항 분석&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;트래픽 패턴 분석&lt;/b&gt;: East-West vs North-South&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;성능 요구사항&lt;/b&gt;: 지연시간, 대역폭, 가용성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안 요구사항&lt;/b&gt;: 격리 수준, 규정 준수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;확장 계획&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2단계: 제약사항 평가&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예산 제약&lt;/b&gt;: 구축 비용, 운영 비용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;기술적 제약&lt;/b&gt;: 기존 인프라, 기술 역량&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;시간적 제약&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3단계: 토폴로지 매칭&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;허브-스포크&lt;/b&gt;: 중앙집중식 관리, 확장성 중시&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;메시&lt;/b&gt;: 성능 최우선, 고가용성 요구&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;하이브리드&lt;/b&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;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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실무 적용 사례&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대기업 환경&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;asciidoc&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;요구사항: 글로벌 다중 사이트, 엄격한 보안, 중앙 관리
선택: 계층적 허브-스포크
- 리전별 허브 구성
- 글로벌 허브 간 메시 연결
- 사이트별 스포크 연결
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스타트업 환경&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;asciidoc&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;요구사항: 빠른 구축, 비용 최적화, 간단한 관리
선택: 단순 허브-스포크
- 클라우드 Transit Gateway 활용
- 최소 어태치먼트로 시작
- 성장에 따른 점진적 확장
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;금융 기관&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;asciidoc&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;요구사항: 최고 수준 보안, 규정 준수, 고가용성
선택: 보안 강화 하이브리드
- 중요 시스템 간 직접 메시 연결
- 일반 시스템은 보안 허브 경유
- 다중 백업 경로 구성
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 토폴로지는 단순한 연결 방식을 넘어서 전체 IT 인프라의 성능, 보안, 확장성을 결정하는 핵심 요소다. 허브-스포크 모델은 현대적인 클라우드 환경에서 확장성과 관리 효율성의 균형을 제공하는 강력한 아키텍처 패턴으로 자리잡고 있다.&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;color: #000000;&quot;&gt;효과적인 토폴로지 선택을 위해서는 비즈니스 요구사항과 기술적 제약사항을 종합적으로 고려해야 한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;color: #000000;&quot;&gt;미래의 네트워크는 더욱 동적이고 지능적인 형태로 진화할 것이며, 기존의 물리적 토폴로지 개념을 넘어서 소프트웨어 정의 네트워크와 AI 기반 자동화가 핵심 역할을 할 것이다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&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;
&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.cisco.com/c/en/us/solutions/enterprise-networks/what-is-network-topology.html&quot;&gt;Network Topology Types and Examples&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/vpc/latest/tgw/&quot;&gt;AWS Transit Gateway Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.microsoft.com/en-us/azure/virtual-wan/&quot;&gt;Azure Virtual WAN Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.microsoft.com/en-us/azure/architecture/reference-architectures/hybrid-networking/hub-spoke&quot;&gt;Hub and Spoke Network Topology&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.ciscopress.com/store/network-design-fundamentals-9781578701209&quot;&gt;Network Design Fundamentals&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://opennetworking.org/sdn-definition/&quot;&gt;Software Defined Networking (SDN) Architecture&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.cncf.io/reports/cloud-native-network-functions-cnf-whitepaper/&quot;&gt;Cloud Native Network Functions&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.3gpp.org/technologies/5g-system-overview&quot;&gt;5G Network Architecture and Design&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.juniper.net/us/en/research-topics/what-is-network-design.html&quot;&gt;Enterprise Network Design Best Practices&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs&quot;&gt;Terraform AWS Provider Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Network</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/454</guid>
      <comments>https://somaz.tistory.com/454#entry454comment</comments>
      <pubDate>Tue, 3 Feb 2026 00:00:10 +0900</pubDate>
    </item>
    <item>
      <title>AWS Load Balancer 완전 비교 가이드</title>
      <link>https://somaz.tistory.com/451</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS는 다양한 유형의 로드 밸런서를 제공하여 애플리케이션의 가용성, 확장성, 보안을 향상시킨다. 각 로드 밸런서는 고유한 특성과 최적화된 사용 사례를 가지고 있어, 올바른 선택이 시스템 성능과 비용에 큰 영향을 미친다.&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;color: #000000;&quot;&gt;본 가이드에서는 AWS의 4가지 주요 로드 밸런서(ALB, NLB, CLB, Gateway Load Balancer)의 특징, 성능, 사용 사례를 심층 분석하고, Terraform을 활용한 실제 구현 방법과 비용 최적화 전략을 제시한다. &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;color: #000000;&quot;&gt;이를 통해 여러분의 아키텍처에 가장 적합한 로드 밸런서를 선택하고 효율적으로 운영할 수 있는 실무 지식을 제공하겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2020&quot; data-origin-height=&quot;1092&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UitwR/dJMcagEdfqa/4jzLE0Te6cUVZmrNK0Q3Gk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UitwR/dJMcagEdfqa/4jzLE0Te6cUVZmrNK0Q3Gk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UitwR/dJMcagEdfqa/4jzLE0Te6cUVZmrNK0Q3Gk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUitwR%2FdJMcagEdfqa%2F4jzLE0Te6cUVZmrNK0Q3Gk%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;2020&quot; height=&quot;1092&quot; data-origin-width=&quot;2020&quot; data-origin-height=&quot;1092&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  관련 글&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/37&quot;&gt;2022.02.13 - [AWS] - AWS IAM (Identity and Access Management) 개요 및 설정 방법&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/30&quot;&gt;2022.02.07 - [AWS] - AWS EC2 인스턴스 생성&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/38&quot;&gt;2022.02.13 - [AWS] - AWS S3 (Simple Storage Service) 개요 및 활용 방법&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/183&quot;&gt;2023.03.30 - [AWS] - AWS Secrets Manager란?(OAuth, SSO)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/182&quot;&gt;2023.03.29 - [AWS] - AWS CLI 정리&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/181&quot;&gt;2023.03.28 - [AWS] - AWS IAM이란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/180&quot;&gt;2023.03.28 - [AWS] - AWS S3 권한이란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/179&quot;&gt;2023.03.28 - [AWS] - AWS S3란?(개념, 속성)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/184&quot;&gt;2023.03.30 - [AWS] - AWS Cloudfront란? / Canary 및 Blue-Green 배포&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/188&quot;&gt;2023.04.03 - [AWS] - AWS VPC란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/238&quot;&gt;2023.05.26 - [AWS] - AWS IRSA(IAM Roles for Service Accounts)란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/340&quot;&gt;2024.11.07 - [AWS] - AWS Ingress Annotations 정리&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/337&quot;&gt;2024.11.04 - [AWS] - AWS Assume Role이란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/349&quot;&gt;2024.11.16 - [AWS] - AWS Network ACL vs Security Group&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/354&quot;&gt;2024.11.21 - [AWS] - ALB access Log 활성화 &amp;rarr; S3 권한 설정 및 로그 저장&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/357&quot;&gt;2024.11.24 - [AWS] - EKS Pod Identity Addon&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/360&quot;&gt;2024.11.27 - [AWS] - AWS DynamoDB란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/364&quot;&gt;2025.01.03 - [AWS] - AWS DynamoDB Local 설치&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/447&quot;&gt;2025.09.02 - [AWS] - AWS EFS와 Kubernetes를 활용한 영구 스토리지 구축 가이드&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/452&quot;&gt;2025.09.05 - [AWS] - AWS CDN 구축 가이드: Kubernetes + AWS CloudFront로 API와 정적 파일 서빙 최적화&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/453&quot;&gt;2025.09.05 - [AWS] - AWS 네트워크 연결 방식 완전 비교: VPC Peering vs Transit Gateway vs VPN&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/451&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2025.09.04 - [AWS] - AWS Load Balancer 완전 비교 가이드&lt;/a&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;AWS&amp;nbsp;Load&amp;nbsp;Balancer&amp;nbsp;완전&amp;nbsp;비교&amp;nbsp;가이드&lt;/span&gt;&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;&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;color: #000000;&quot;&gt;1. AWS Load Balancer 종류별 특징&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Application Load Balancer (ALB)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;Layer 7 HTTP/HTTPS 트래픽을 위한 고급 로드 밸런서&lt;/b&gt;&lt;/i&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;핵심 특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HTTP/HTTPS 프로토콜 지원 (Layer 7)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;경로 기반, 호스트 기반 라우팅&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;웹소켓 및 HTTP/2 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너 및 람다 함수 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SSL/TLS 터미네이션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;WAF 통합 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;성능 특성&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처리량: 초당 수십만 요청 처리 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지연시간: 평균 1-5ms 추가 레이턴시&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Network Load Balancer (NLB)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;Layer 4 고성능 TCP/UDP 트래픽 로드 밸런서&lt;/b&gt;&lt;/i&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;핵심 특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TCP, UDP, TLS 프로토콜 지원 (Layer 4)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;초고성능 및 초저지연&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고정 IP 주소 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Preserve client IP&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cross-zone 로드 밸런싱&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PrivateLink 엔드포인트 지원&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;성능 특성&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처리량: 초당 수백만 요청 처리 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지연시간: 100 마이크로초 미만&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Classic Load Balancer (CLB)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;레거시 EC2-Classic을 위한 기본 로드 밸런서&lt;/b&gt;&lt;/i&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;핵심 특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Layer 4 (TCP) 및 Layer 7 (HTTP/HTTPS) 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EC2-Classic 및 VPC 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본적인 헬스체크&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SSL 터미네이션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;현재 상태&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS에서 사용 중단 권장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 워크로드 유지보수 목적으로만 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;신규 프로젝트에서는 ALB 또는 NLB 권장&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gateway Load Balancer (GWLB)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;네트워크 보안 어플라이언스를 위한 투명한 로드 밸런서&lt;/b&gt;&lt;/i&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;핵심 특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Layer 3 (IP) 레벨에서 동작&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GENEVE 프로토콜 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;투명한 네트워크 게이트웨이&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;써드파티 보안 어플라이언스 통합&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPC 엔드포인트 서비스 지원&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;성능 특성&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처리량: 수백만 패킷 처리 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지연시간: 극도로 낮은 레이턴시&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 사용 사례별 최적 선택 가이드&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ALB 최적 사용 사례&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;웹 애플리케이션 및 API 서비스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마이크로서비스 아키텍처&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너 기반 애플리케이션 (ECS, EKS)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서버리스 아키텍처 (Lambda)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;경로 기반 라우팅이 필요한 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고급 보안 기능 (WAF) 연동&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt; A/B 테스팅 및 카나리 배포&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실제 시나리오 예시&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전자상품몰에서 `/api/products` 는 상품 서비스로, `/api/users` 는 사용자 서비스로 라우팅&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;React 프론트엔드와 Node.js API 서버 간 로드 밸런싱&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NLB 최적 사용 사례&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;초고성능이 필요한 애플리케이션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;게임 서버 및 실시간 스트리밍&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IoT 및 센서 데이터 처리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고정 IP가 필요한 서비스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TCP/UDP 기반 애플리케이션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;온프레미스와의 VPN/DirectConnect 연결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실제 시나리오 예시&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;온라인 게임의 게임 서버 클러스터&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;금융 거래 시스템의 실시간 데이터 처리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gateway Load Balancer 최적 사용 사례&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;방화벽 어플라이언스 배포&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IDS/IPS 시스템 통합&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DDoS 보호 솔루션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 모니터링 및 분석&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;써드파티 보안 도구 통합&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실제 시나리오 예시&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Palo Alto Networks 방화벽을 통한 트래픽 검사&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fortinet 보안 어플라이언스 클러스터 운영&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;3. Terraform 구현 예제 및 Kubernetes 사용 시 구현 예제&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ALB Terraform 구현&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1756978594153&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Application Load Balancer
resource &quot;aws_lb&quot; &quot;main_alb&quot; {
  name               = &quot;main-alb&quot;
  internal           = false
  load_balancer_type = &quot;application&quot;
  security_groups    = [aws_security_group.alb_sg.id]
  subnets            = var.public_subnet_ids

  enable_deletion_protection = false
  
  access_logs {
    bucket  = aws_s3_bucket.alb_logs.id
    prefix  = &quot;alb-logs&quot;
    enabled = true
  }

  tags = {
    Environment = var.environment
    Name        = &quot;main-alb&quot;
  }
}

# Target Group
resource &quot;aws_lb_target_group&quot; &quot;web_tg&quot; {
  name     = &quot;web-tg&quot;
  port     = 80
  protocol = &quot;HTTP&quot;
  vpc_id   = var.vpc_id
  
  health_check {
    enabled             = true
    healthy_threshold   = 2
    interval            = 30
    matcher             = &quot;200&quot;
    path                = &quot;/health&quot;
    port                = &quot;traffic-port&quot;
    protocol            = &quot;HTTP&quot;
    timeout             = 5
    unhealthy_threshold = 2
  }
  
  target_type = &quot;instance&quot;
  
  tags = {
    Name = &quot;web-target-group&quot;
  }
}

# Listener
resource &quot;aws_lb_listener&quot; &quot;web_listener&quot; {
  load_balancer_arn = aws_lb.main_alb.arn
  port              = &quot;443&quot;
  protocol          = &quot;HTTPS&quot;
  ssl_policy        = &quot;ELBSecurityPolicy-TLS-1-2-2017-01&quot;
  certificate_arn   = var.ssl_certificate_arn

  default_action {
    type             = &quot;forward&quot;
    target_group_arn = aws_lb_target_group.web_tg.arn
  }
}

# Path-based routing
resource &quot;aws_lb_listener_rule&quot; &quot;api_rule&quot; {
  listener_arn = aws_lb_listener.web_listener.arn
  priority     = 100

  action {
    type             = &quot;forward&quot;
    target_group_arn = aws_lb_target_group.api_tg.arn
  }

  condition {
    path_pattern {
      values = [&quot;/api/*&quot;]
    }
  }
}

# Security Group
resource &quot;aws_security_group&quot; &quot;alb_sg&quot; {
  name_prefix = &quot;alb-sg&quot;
  vpc_id      = var.vpc_id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = &quot;tcp&quot;
    cidr_blocks = [&quot;0.0.0.0/0&quot;]
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = &quot;tcp&quot;
    cidr_blocks = [&quot;0.0.0.0/0&quot;]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = &quot;-1&quot;
    cidr_blocks = [&quot;0.0.0.0/0&quot;]
  }

  tags = {
    Name = &quot;alb-security-group&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NLB Terraform 구현&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756978640043&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Network Load Balancer
resource &quot;aws_lb&quot; &quot;main_nlb&quot; {
  name               = &quot;main-nlb&quot;
  internal           = false
  load_balancer_type = &quot;network&quot;
  subnets            = var.public_subnet_ids

  enable_deletion_protection = false
  
  # Static IP allocation
  subnet_mapping {
    subnet_id     = var.public_subnet_ids[0]
    allocation_id = aws_eip.nlb_eip_1.id
  }
  
  subnet_mapping {
    subnet_id     = var.public_subnet_ids[1]
    allocation_id = aws_eip.nlb_eip_2.id
  }

  tags = {
    Environment = var.environment
    Name        = &quot;main-nlb&quot;
  }
}

# Elastic IPs for static IPs
resource &quot;aws_eip&quot; &quot;nlb_eip_1&quot; {
  vpc = true
  tags = {
    Name = &quot;nlb-eip-1&quot;
  }
}

resource &quot;aws_eip&quot; &quot;nlb_eip_2&quot; {
  vpc = true
  tags = {
    Name = &quot;nlb-eip-2&quot;
  }
}

# Target Group for TCP
resource &quot;aws_lb_target_group&quot; &quot;tcp_tg&quot; {
  name     = &quot;tcp-tg&quot;
  port     = 8080
  protocol = &quot;TCP&quot;
  vpc_id   = var.vpc_id
  
  health_check {
    enabled             = true
    healthy_threshold   = 2
    interval            = 30
    port                = &quot;traffic-port&quot;
    protocol            = &quot;TCP&quot;
    timeout             = 6
    unhealthy_threshold = 2
  }
  
  target_type = &quot;instance&quot;
  
  # Preserve client IP
  preserve_client_ip = true
  
  tags = {
    Name = &quot;tcp-target-group&quot;
  }
}

# Listener for TCP
resource &quot;aws_lb_listener&quot; &quot;tcp_listener&quot; {
  load_balancer_arn = aws_lb.main_nlb.arn
  port              = &quot;80&quot;
  protocol          = &quot;TCP&quot;

  default_action {
    type             = &quot;forward&quot;
    target_group_arn = aws_lb_target_group.tcp_tg.arn
  }
}&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gateway Load Balancer Terraform 구현&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756978660453&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Gateway Load Balancer
resource &quot;aws_lb&quot; &quot;gateway_lb&quot; {
  name               = &quot;gateway-lb&quot;
  load_balancer_type = &quot;gateway&quot;
  subnets            = var.private_subnet_ids

  enable_deletion_protection = false

  tags = {
    Name = &quot;gateway-load-balancer&quot;
  }
}

# Target Group for GWLB
resource &quot;aws_lb_target_group&quot; &quot;gwlb_tg&quot; {
  name     = &quot;gwlb-tg&quot;
  port     = 6081
  protocol = &quot;GENEVE&quot;
  vpc_id   = var.vpc_id
  
  health_check {
    enabled             = true
    healthy_threshold   = 2
    interval            = 30
    port                = &quot;80&quot;
    protocol            = &quot;HTTP&quot;
    path                = &quot;/health&quot;
    timeout             = 5
    unhealthy_threshold = 2
  }
  
  target_type = &quot;instance&quot;
  
  tags = {
    Name = &quot;gwlb-target-group&quot;
  }
}

# GWLB Listener
resource &quot;aws_lb_listener&quot; &quot;gwlb_listener&quot; {
  load_balancer_arn = aws_lb.gateway_lb.arn

  default_action {
    type             = &quot;forward&quot;
    target_group_arn = aws_lb_target_group.gwlb_tg.arn
  }
}

# VPC Endpoint Service
resource &quot;aws_vpc_endpoint_service&quot; &quot;gwlb_endpoint_service&quot; {
  acceptance_required        = false
  gateway_load_balancer_arns = [aws_lb.gateway_lb.arn]
  
  tags = {
    Name = &quot;gwlb-endpoint-service&quot;
  }
}

# VPC Endpoint
resource &quot;aws_vpc_endpoint&quot; &quot;gwlb_endpoint&quot; {
  vpc_id              = var.vpc_id
  service_name        = aws_vpc_endpoint_service.gwlb_endpoint_service.service_name
  vpc_endpoint_type   = &quot;GatewayLoadBalancer&quot;
  subnet_ids          = var.private_subnet_ids

  tags = {
    Name = &quot;gwlb-endpoint&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고급 ALB 구성 예제 (컨테이너 환경)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756978871458&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# ECS Service용 ALB 타겟 그룹
resource &quot;aws_lb_target_group&quot; &quot;ecs_tg&quot; {
  name                 = &quot;ecs-service-tg&quot;
  port                 = 80
  protocol             = &quot;HTTP&quot;
  vpc_id               = var.vpc_id
  target_type          = &quot;ip&quot;
  deregistration_delay = 30
  
  health_check {
    enabled             = true
    healthy_threshold   = 2
    interval            = 15
    matcher             = &quot;200,404&quot;
    path                = &quot;/health&quot;
    port                = &quot;traffic-port&quot;
    protocol            = &quot;HTTP&quot;
    timeout             = 5
    unhealthy_threshold = 3
  }
  
  tags = {
    Name = &quot;ecs-target-group&quot;
  }
}

# Lambda 함수용 타겟 그룹
resource &quot;aws_lb_target_group&quot; &quot;lambda_tg&quot; {
  name        = &quot;lambda-tg&quot;
  target_type = &quot;lambda&quot;
  
  health_check {
    enabled             = true
    healthy_threshold   = 2
    interval            = 30
    matcher             = &quot;200&quot;
    path                = &quot;/health&quot;
    timeout             = 5
    unhealthy_threshold = 2
  }
}

# Lambda 권한
resource &quot;aws_lambda_permission&quot; &quot;allow_alb&quot; {
  statement_id  = &quot;AllowExecutionFromALB&quot;
  action        = &quot;lambda:InvokeFunction&quot;
  function_name = var.lambda_function_name
  principal     = &quot;elasticloadbalancing.amazonaws.com&quot;
  source_arn    = aws_lb_target_group.lambda_tg.arn
}&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes Ingress 사용하여 구현&lt;/span&gt;&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS Load Balancer Controller 설치&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756979046425&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Helm을 통한 AWS Load Balancer Controller 설치
helm repo add eks https://aws.github.io/eks-charts
helm repo update

helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=your-cluster-name \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 Ingress 구성 예제&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756979063552&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-app-ingress
  namespace: default
  annotations:
    # ALB 생성 지정
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    
    # SSL/HTTPS 설정
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:123456789012:certificate/your-cert-arn
    alb.ingress.kubernetes.io/listen-ports: '[{&quot;HTTP&quot;: 80}, {&quot;HTTPS&quot;: 443}]'
    alb.ingress.kubernetes.io/ssl-redirect: &quot;443&quot;
    
    # 로드 밸런서 이름 지정
    alb.ingress.kubernetes.io/load-balancer-name: web-app-alb
    
    # 헬스체크 설정
    alb.ingress.kubernetes.io/healthcheck-path: /health
    alb.ingress.kubernetes.io/healthcheck-interval-seconds: &quot;30&quot;
    alb.ingress.kubernetes.io/healthcheck-timeout-seconds: &quot;5&quot;
    alb.ingress.kubernetes.io/healthy-threshold-count: &quot;2&quot;
    alb.ingress.kubernetes.io/unhealthy-threshold-count: &quot;3&quot;
    
    # External DNS 통합
    external-dns.alpha.kubernetes.io/hostname: webapp.example.com
  labels:
    app: web-app
spec:
  ingressClassName: alb
  rules:
  - host: webapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-app-service
            port:
              number: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web-app-service
  namespace: default
spec:
  selector:
    app: web-app
  ports:
  - port: 80
    targetPort: 8080
  type: ClusterIP&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다중 서비스 라우팅 예제&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756979083928&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: microservices-ingress
  namespace: production
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:123456789012:certificate/your-cert-arn
    alb.ingress.kubernetes.io/listen-ports: '[{&quot;HTTP&quot;: 80}, {&quot;HTTPS&quot;: 443}]'
    alb.ingress.kubernetes.io/ssl-redirect: &quot;443&quot;
    alb.ingress.kubernetes.io/load-balancer-name: microservices-alb
    
    # WAF 연결
    alb.ingress.kubernetes.io/wafv2-acl-arn: arn:aws:wafv2:us-west-2:123456789012:regional/webacl/your-waf/12345
    
    # 태그 지정
    alb.ingress.kubernetes.io/tags: Environment=production,Team=backend
  labels:
    app: microservices
spec:
  ingressClassName: alb
  rules:
  - host: api.example.com
    http:
      paths:
      # 사용자 서비스
      - path: /api/users
        pathType: Prefix
        backend:
          service:
            name: user-service
            port:
              number: 80
      # 상품 서비스
      - path: /api/products
        pathType: Prefix
        backend:
          service:
            name: product-service
            port:
              number: 80
      # 주문 서비스
      - path: /api/orders
        pathType: Prefix
        backend:
          service:
            name: order-service
            port:
              number: 80
      # 기본 경로
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend-service
            port:
              number: 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;&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;공유 ALB 사용 예제 (제공해주신 파일 기반)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756979102575&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 첫 번째 애플리케이션
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: alpha-game-app
  namespace: gameservice
  annotations:
    # 공유 ALB 그룹 설정
    alb.ingress.kubernetes.io/group.name: luckyday-shared-alb
    alb.ingress.kubernetes.io/group.order: &quot;10&quot;
    
    # 기본 ALB 설정
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/load-balancer-name: luckyday-shared-alb-loadbalancer
    
    # SSL/HTTPS 설정
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:eu-central-1:010339071704:certificate/14eeaf2b-e34e-416d-a1bb-fbfb18c9f59b
    alb.ingress.kubernetes.io/listen-ports: '[{&quot;HTTP&quot;: 80}, {&quot;HTTPS&quot;: 443}]'
    alb.ingress.kubernetes.io/ssl-redirect: &quot;443&quot;
    
    # External DNS
    external-dns.alpha.kubernetes.io/hostname: alpha-game.luckyday.soulssvc.com
    
    # ArgoCD 추적
    argocd.argoproj.io/tracking-id: alpha-luckyday-game:networking.k8s.io/Ingress:luckyday/alpha-luckyday-game
  labels:
    app.kubernetes.io/instance: alpha-luckyday-game
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: alpha-luckyday-game
    app.kubernetes.io/version: 1.16.0
    helm.sh/chart: base-aws-0.1.0
spec:
  ingressClassName: alb
  rules:
  - host: alpha-game.luckyday.soulssvc.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: alpha-luckyday-game
            port:
              number: 80

---
# 두 번째 애플리케이션 (같은 ALB 공유)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: beta-game-app
  namespace: gameservice
  annotations:
    # 동일한 ALB 그룹 사용
    alb.ingress.kubernetes.io/group.name: luckyday-shared-alb
    alb.ingress.kubernetes.io/group.order: &quot;20&quot;
    
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/load-balancer-name: luckyday-shared-alb-loadbalancer
    
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:eu-central-1:010339071704:certificate/14eeaf2b-e34e-416d-a1bb-fbfb18c9f59b
    alb.ingress.kubernetes.io/listen-ports: '[{&quot;HTTP&quot;: 80}, {&quot;HTTPS&quot;: 443}]'
    alb.ingress.kubernetes.io/ssl-redirect: &quot;443&quot;
    
    external-dns.alpha.kubernetes.io/hostname: beta-game.luckyday.soulssvc.com
spec:
  ingressClassName: alb
  rules:
  - host: beta-game.luckyday.soulssvc.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: beta-luckyday-game
            port:
              number: 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;&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고급 설정 예제 (실제 운영 환경)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756979122167&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: production-app-ingress
  namespace: production
  annotations:
    # 기본 ALB 설정
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/load-balancer-name: production-app-alb
    
    # SSL/보안 설정
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:123456789012:certificate/your-cert-arn
    alb.ingress.kubernetes.io/listen-ports: '[{&quot;HTTP&quot;: 80}, {&quot;HTTPS&quot;: 443}]'
    alb.ingress.kubernetes.io/ssl-redirect: &quot;443&quot;
    alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS-1-2-2017-01
    
    # 헬스체크 커스터마이징
    alb.ingress.kubernetes.io/healthcheck-path: /api/health
    alb.ingress.kubernetes.io/healthcheck-protocol: HTTPS
    alb.ingress.kubernetes.io/healthcheck-interval-seconds: &quot;15&quot;
    alb.ingress.kubernetes.io/healthcheck-timeout-seconds: &quot;5&quot;
    alb.ingress.kubernetes.io/healthy-threshold-count: &quot;2&quot;
    alb.ingress.kubernetes.io/unhealthy-threshold-count: &quot;3&quot;
    
    # 성능 및 연결 설정
    alb.ingress.kubernetes.io/target-group-attributes: |
      deregistration_delay.timeout_seconds=30,
      slow_start.duration_seconds=60,
      stickiness.enabled=true,
      stickiness.lb_cookie.duration_seconds=86400
    
    # WAF 및 보안
    alb.ingress.kubernetes.io/wafv2-acl-arn: arn:aws:wafv2:us-west-2:123456789012:regional/webacl/production-waf/12345
    alb.ingress.kubernetes.io/security-groups: sg-12345678,sg-87654321
    
    # 서브넷 및 네트워크 설정
    alb.ingress.kubernetes.io/subnets: subnet-12345678,subnet-87654321
    
    # 로깅 및 모니터링
    alb.ingress.kubernetes.io/load-balancer-attributes: |
      access_logs.s3.enabled=true,
      access_logs.s3.bucket=my-alb-logs-bucket,
      access_logs.s3.prefix=production-app,
      deletion_protection.enabled=true
    
    # 태깅
    alb.ingress.kubernetes.io/tags: |
      Environment=production,
      Application=main-app,
      Team=platform,
      CostCenter=engineering
    
    # External DNS
    external-dns.alpha.kubernetes.io/hostname: app.example.com,www.example.com
  labels:
    app: production-app
    environment: production
spec:
  ingressClassName: alb
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: production-app-service
            port:
              number: 80
  - host: www.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: production-app-service
            port:
              number: 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;&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;External DNS로 CDN 도메인도 관리&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756979889897&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: cdn-integrated-ingress
  namespace: production
  annotations:
    # ALB 설정
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/load-balancer-name: cdn-origin-alb
    
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:123456789012:certificate/your-cert-arn
    alb.ingress.kubernetes.io/listen-ports: '[{&quot;HTTP&quot;: 80}, {&quot;HTTPS&quot;: 443}]'
    alb.ingress.kubernetes.io/ssl-redirect: &quot;443&quot;
    
    # External DNS - 여러 도메인 관리
    external-dns.alpha.kubernetes.io/hostname: |
      origin.example.com,
      cdn.example.com
    
    # CDN 친화적 헤더 설정
    alb.ingress.kubernetes.io/load-balancer-attributes: |
      routing.http2.enabled=true,
      idle_timeout.timeout_seconds=60
    
    # Origin용 캐시 헤더 설정을 위한 커스텀 응답 헤더
    nginx.ingress.kubernetes.io/configuration-snippet: |
      more_set_headers &quot;Cache-Control: public, max-age=31536000&quot; if ($uri ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$);
      more_set_headers &quot;Cache-Control: no-cache&quot; if ($uri !~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$);
spec:
  ingressClassName: alb
  rules:
  - host: origin.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: webapp-service
            port:
              number: 80
  - host: cdn.example.com  # CDN 도메인도 같은 ALB로 처리 (CDN 없이 직접 접근 시)
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: webapp-service
            port:
              number: 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;&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;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CDN + External DNS를 위한 완전한 설정&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756979913928&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 1. Origin 전용 Ingress (CDN에서 사용)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: origin-ingress
  namespace: production
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/load-balancer-name: origin-alb
    
    # Origin 전용 인증서
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:123456789012:certificate/origin-cert
    alb.ingress.kubernetes.io/listen-ports: '[{&quot;HTTPS&quot;: 443}]'
    
    # Origin 도메인 - External DNS로 자동 생성
    external-dns.alpha.kubernetes.io/hostname: origin-api.example.com
    
    # CDN 최적화 설정
    alb.ingress.kubernetes.io/target-group-attributes: |
      deregistration_delay.timeout_seconds=10,
      stickiness.enabled=false
    
    # Origin 식별을 위한 태그
    alb.ingress.kubernetes.io/tags: &quot;Purpose=CDN-Origin,Environment=production&quot;
spec:
  ingressClassName: alb
  rules:
  - host: origin-api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 80

---
# 2. CDN Distribution (Terraform으로 생성되지만 참조용)
# terraform에서 다음과 같이 생성:
# resource &quot;aws_cloudfront_distribution&quot; &quot;main&quot; {
#   origin {
#     domain_name = &quot;origin-api.example.com&quot;  # 위 Ingress에서 생성된 도메인
#     origin_id   = &quot;ALB-Origin&quot;
#   }
#   aliases = [&quot;api.example.com&quot;, &quot;www.api.example.com&quot;]
# }

---
# 3. CDN 도메인을 위한 External DNS 설정 (별도 관리)
apiVersion: v1
kind: Service
metadata:
  name: cdn-external-dns
  namespace: production
  annotations:
    # CloudFront Distribution 도메인을 External DNS로 관리
    external-dns.alpha.kubernetes.io/hostname: api.example.com
    external-dns.alpha.kubernetes.io/cloudfront-distribution-id: E1234567890123
spec:
  type: ExternalName
  externalName: d123456789.cloudfront.net  # CloudFront 도메인&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;4. 성능 비교 및 벤치마크&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처리량 비교&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로드 밸런서&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최대 RPS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동시 연결&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대역폭&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ALB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~100,000 RPS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~25,000&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~25 Gbps&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NLB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~3,000,000 RPS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수백만&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~100 Gbps&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CLB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~10,000 RPS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~55,000&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~10 Gbps&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GWLB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;패킷 기준&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수백만&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~100 Gbps&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지연시간 비교&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로드 밸런서&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;P50 지연시간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;P99 지연시간&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추가 홉&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ALB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1-3ms&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5-10ms&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1 홉&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NLB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0.1ms&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0.5ms&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;투명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CLB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2-5ms&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10-15ms&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1 홉&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GWLB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0.1ms&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0.3ms&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;투명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기능 비교 매트릭스&lt;/span&gt;&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 170px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ALB&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NLB&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CLB&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GWLB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Layer 7 라우팅&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고정 IP&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;WebSocket&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HTTP/2&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SNI&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;WAF 통합&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Lambda 지원&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cross-zone LB&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본값&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;옵션&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;옵션&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본값&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. 비용 최적화 전략&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5.1 비용 구조 이해&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;ALB 비용 구성요소&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시간당 요금: $0.0225/시간&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LCU(Load Balancer Capacity Unit): $0.008/LCU&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 전송: 표준 EC2 요금&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;NLB 비용 구성요소&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시간당 요금: $0.0225/시간&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NLCU(Network Load Balancer Capacity Unit): $0.006/NLCU&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 전송: 표준 EC2 요금&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GWLB 비용 구성요소&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시간당 요금: $0.0225/시간&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GWLCU(Gateway Load Balancer Capacity Unit): $0.004/GWLCU&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPC 엔드포인트: $0.01/시간&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5.2 비용 최적화 기법&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 적절한 로드 밸런서 선택&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756979366112&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 비용 효율적인 선택 로직
locals {
  # 트래픽이 적고 HTTP만 사용하는 경우 ALB
  use_alb = var.avg_requests_per_second &amp;lt; 1000 &amp;amp;&amp;amp; var.protocol == &quot;HTTP&quot;
  
  # 고성능이 필요한 TCP 트래픽의 경우 NLB
  use_nlb = var.avg_requests_per_second &amp;gt; 10000 || var.protocol == &quot;TCP&quot;
  
  # 보안 어플라이언스 통합이 필요한 경우 GWLB
  use_gwlb = var.security_appliance_required
}&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Cross-Zone 로드 밸런싱 최적화&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# NLB에서 Cross-zone 로드 밸런싱 비용 고려
resource &quot;aws_lb&quot; &quot;cost_optimized_nlb&quot; {
  name               = &quot;cost-optimized-nlb&quot;
  load_balancer_type = &quot;network&quot;
  
  # Cross-zone 로드 밸런싱 비활성화로 데이터 전송 비용 절약
  # (단, 고가용성 고려 필요)
  enable_cross_zone_load_balancing = false
  
  subnets = var.subnet_ids
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 타겟 그룹 최적화&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 효율적인 헬스체크 설정
resource &quot;aws_lb_target_group&quot; &quot;optimized_tg&quot; {
  name     = &quot;optimized-tg&quot;
  port     = 80
  protocol = &quot;HTTP&quot;
  vpc_id   = var.vpc_id
  
  health_check {
    enabled             = true
    healthy_threshold   = 2
    interval            = 30  # 기본값, 더 짧게 하면 비용 증가
    matcher             = &quot;200&quot;
    path                = &quot;/health&quot;
    timeout             = 5
    unhealthy_threshold = 3
  }
  
  # 빠른 연결 해제로 비용 절약
  deregistration_delay = 30
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 로그 및 모니터링 최적화&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 선택적 로그 활성화
resource &quot;aws_lb&quot; &quot;log_optimized_alb&quot; {
  name               = &quot;log-optimized-alb&quot;
  load_balancer_type = &quot;application&quot;
  subnets            = var.subnet_ids
  
  # 로그를 필요한 경우에만 활성화
  access_logs {
    bucket  = var.enable_access_logs ? aws_s3_bucket.alb_logs[0].id : &quot;&quot;
    enabled = var.enable_access_logs
  }
}

# S3 버킷 라이프사이클 정책으로 로그 비용 관리
resource &quot;aws_s3_bucket_lifecycle_configuration&quot; &quot;alb_logs_lifecycle&quot; {
  count  = var.enable_access_logs ? 1 : 0
  bucket = aws_s3_bucket.alb_logs[0].id

  rule {
    id     = &quot;log_retention&quot;
    status = &quot;Enabled&quot;

    expiration {
      days = 30  # 30일 후 삭제
    }

    transition {
      days          = 7
      storage_class = &quot;STANDARD_IA&quot;
    }

    transition {
      days          = 14
      storage_class = &quot;GLACIER&quot;
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5.3 비용 모니터링 및 알람&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nix&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# CloudWatch 비용 알람
resource &quot;aws_cloudwatch_metric_alarm&quot; &quot;lb_cost_alarm&quot; {
  alarm_name          = &quot;lb-monthly-cost-alarm&quot;
  comparison_operator = &quot;GreaterThanThreshold&quot;
  evaluation_periods  = &quot;2&quot;
  metric_name         = &quot;EstimatedCharges&quot;
  namespace           = &quot;AWS/Billing&quot;
  period              = &quot;86400&quot;  # 1일
  statistic           = &quot;Maximum&quot;
  threshold           = var.monthly_cost_threshold
  alarm_description   = &quot;This metric monitors lb monthly charges&quot;
  alarm_actions       = [var.sns_topic_arn]

  dimensions = {
    Currency = &quot;USD&quot;
    ServiceName = &quot;AmazonEC2&quot;  # 로드 밸런서는 EC2 서비스에 포함
  }
}

# LCU 사용량 모니터링
resource &quot;aws_cloudwatch_metric_alarm&quot; &quot;alb_lcu_alarm&quot; {
  alarm_name          = &quot;alb-lcu-usage-high&quot;
  comparison_operator = &quot;GreaterThanThreshold&quot;
  evaluation_periods  = &quot;2&quot;
  metric_name         = &quot;ConsumedLCUs&quot;
  namespace           = &quot;AWS/ApplicationELB&quot;
  period              = &quot;300&quot;
  statistic           = &quot;Average&quot;
  threshold           = var.lcu_threshold
  alarm_description   = &quot;ALB LCU usage is too high&quot;
  
  dimensions = {
    LoadBalancer = aws_lb.main_alb.arn_suffix
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5.4 예상 비용 계산 도구&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 변수 정의
variable &quot;monthly_requests&quot; {
  description = &quot;Monthly request count&quot;
  type        = number
  default     = 1000000
}

variable &quot;avg_request_size&quot; {
  description = &quot;Average request size in KB&quot;
  type        = number
  default     = 10
}

variable &quot;avg_response_size&quot; {
  description = &quot;Average response size in KB&quot;
  type        = number
  default     = 50
}

# 비용 계산 로컬 값
locals {
  # ALB 비용 계산
  alb_hourly_cost = 0.0225
  alb_monthly_hours = 24 * 30
  alb_base_cost = local.alb_hourly_cost * local.alb_monthly_hours
  
  # LCU 계산 (4가지 차원 중 최대값)
  new_connections_per_second = var.monthly_requests / (30 * 24 * 3600)
  requests_per_second = local.new_connections_per_second
  bandwidth_mbps = (var.avg_request_size + var.avg_response_size) * local.requests_per_second / 1024
  rule_evaluations_per_second = local.requests_per_second * 2  # 평균 2개 룰 평가
  
  max_lcu = max(
    local.new_connections_per_second / 25,    # 25 new connections/sec per LCU
    local.requests_per_second / 1000,         # 1000 requests/sec per LCU
    local.bandwidth_mbps / 1,                 # 1 Mbps per LCU
    local.rule_evaluations_per_second / 1000  # 1000 rule evaluations/sec per LCU
  )
  
  lcu_cost = local.max_lcu * 0.008 * local.alb_monthly_hours
  total_alb_cost = local.alb_base_cost + local.lcu_cost
}

# 비용 출력
output &quot;estimated_monthly_cost&quot; {
  value = {
    alb_base_cost = local.alb_base_cost
    lcu_cost = local.lcu_cost
    total_cost = local.total_alb_cost
    estimated_lcu = local.max_lcu
  }
}&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;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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6. 모니터링 및 트러블슈팅&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6.1 핵심 메트릭 모니터링&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# ALB 핵심 메트릭 대시보드
resource &quot;aws_cloudwatch_dashboard&quot; &quot;alb_dashboard&quot; {
  dashboard_name = &quot;ALB-Monitoring-Dashboard&quot;

  dashboard_body = jsonencode({
    widgets = [
      {
        type   = &quot;metric&quot;
        x      = 0
        y      = 0
        width  = 12
        height = 6

        properties = {
          metrics = [
            [&quot;AWS/ApplicationELB&quot;, &quot;RequestCount&quot;, &quot;LoadBalancer&quot;, aws_lb.main_alb.arn_suffix],
            [&quot;.&quot;, &quot;TargetResponseTime&quot;, &quot;.&quot;, &quot;.&quot;],
            [&quot;.&quot;, &quot;HTTPCode_Target_2XX_Count&quot;, &quot;.&quot;, &quot;.&quot;],
            [&quot;.&quot;, &quot;HTTPCode_Target_4XX_Count&quot;, &quot;.&quot;, &quot;.&quot;],
            [&quot;.&quot;, &quot;HTTPCode_Target_5XX_Count&quot;, &quot;.&quot;, &quot;.&quot;],
            [&quot;.&quot;, &quot;HealthyHostCount&quot;, &quot;TargetGroup&quot;, aws_lb_target_group.web_tg.arn_suffix],
            [&quot;.&quot;, &quot;UnHealthyHostCount&quot;, &quot;.&quot;, &quot;.&quot;]
          ]
          period = 300
          stat   = &quot;Sum&quot;
          region = var.aws_region
          title  = &quot;ALB Key Metrics&quot;
        }
      }
    ]
  })
}

# 중요 알람 설정
resource &quot;aws_cloudwatch_metric_alarm&quot; &quot;high_response_time&quot; {
  alarm_name          = &quot;alb-high-response-time&quot;
  comparison_operator = &quot;GreaterThanThreshold&quot;
  evaluation_periods  = &quot;2&quot;
  metric_name         = &quot;TargetResponseTime&quot;
  namespace           = &quot;AWS/ApplicationELB&quot;
  period              = &quot;60&quot;
  statistic           = &quot;Average&quot;
  threshold           = &quot;1.0&quot;  # 1초
  alarm_description   = &quot;ALB response time is too high&quot;
  alarm_actions       = [var.sns_topic_arn]

  dimensions = {
    LoadBalancer = aws_lb.main_alb.arn_suffix
  }
}

resource &quot;aws_cloudwatch_metric_alarm&quot; &quot;high_error_rate&quot; {
  alarm_name          = &quot;alb-high-5xx-error-rate&quot;
  comparison_operator = &quot;GreaterThanThreshold&quot;
  evaluation_periods  = &quot;2&quot;
  metric_name         = &quot;HTTPCode_Target_5XX_Count&quot;
  namespace           = &quot;AWS/ApplicationELB&quot;
  period              = &quot;300&quot;
  statistic           = &quot;Sum&quot;&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;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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 선택 기준 요약 &lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;Application Load Balancer (ALB)는 HTTP/HTTPS 기반 웹 애플리케이션과 마이크로서비스에 최적화되어 있으며, 경로 기반 라우팅과 고급 보안 기능이 필요한 경우 최고의 선택이다. Kubernetes 환경에서 Ingress Controller를 통한 통합도 매우 원활하다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Network Load Balancer (NLB)는 극도의 성능과 낮은 지연시간이 요구되는 TCP/UDP 애플리케이션에 이상적입니다. 게임 서버, 실시간 스트리밍, IoT 환경에서 탁월한 성능을 발휘한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gateway Load Balancer (GWLB)는 네트워크 보안 어플라이언스의 투명한 통합을 위한 특수 목적 로드 밸런서로, 엔터프라이즈 보안 환경에서 필수적인 역할을 한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성공적인 구현을 위한 권장사항 &lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;아키텍처 설계 단계에서는 트래픽 패턴, 성능 요구사항, 보안 정책을 충분히 분석하여 적절한 로드 밸런서를 선택하고, Terraform과 같은 IaC 도구를 활용하여 일관되고 재현 가능한 인프라를 구축하자.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비용 최적화&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;는 지속적인 모니터링과 조정을 통해 달성할 수 있습니다. LCU/NLCU 사용량을 정기적으로 검토하고, 불필요한 기능은 비활성화하며, 적절한 헬스체크 간격을 설정하여 비용을 절감하자.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;운영 관리&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;에서는 CloudWatch 메트릭과 알람을 통한 proactive 모니터링을 구축하고, 액세스 로그 분석을 통해 트래픽 패턴을 이해하며, 정기적인 성능 검토를 통해 지속적으로 최적화하자.&lt;/span&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;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;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt; AWS 로드 밸런서는 단순한 트래픽 분산 도구를 넘어 현대적 애플리케이션 아키텍처의 핵심 구성 요소이다. 이 가이드의 모범 사례를 적용하여 안정적이고 확장 가능한 시스템을 구축하시기 바란다.&lt;/b&gt;&lt;/i&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;div&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;color: #000000;&quot;&gt;&lt;b&gt;AWS Application Load Balancer 사용자 가이드&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/elasticloadbalancing/latest/application/&quot;&gt;https://docs.aws.amazon.com/elasticloadbalancing/latest/application/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&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;color: #000000;&quot;&gt;&lt;b&gt;AWS Network Load Balancer 사용자 가이드&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/elasticloadbalancing/latest/network/&quot;&gt;https://docs.aws.amazon.com/elasticloadbalancing/latest/network/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&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;color: #000000;&quot;&gt;&lt;b&gt;AWS Gateway Load Balancer 사용자 가이드&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/elasticloadbalancing/latest/gateway/&quot;&gt;https://docs.aws.amazon.com/elasticloadbalancing/latest/gateway/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&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;color: #000000;&quot;&gt;&lt;b&gt;Elastic Load Balancing 요금&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://aws.amazon.com/elasticloadbalancing/pricing/&quot;&gt;https://aws.amazon.com/elasticloadbalancing/pricing/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;AWS Load Balancer Controller 공식 가이드&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubernetes-sigs.github.io/aws-load-balancer-controller/&quot;&gt;https://kubernetes-sigs.github.io/aws-load-balancer-controller/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;EKS 사용자 가이드 - Application Load Balancing&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/alb-ingress.html&quot;&gt;https://docs.aws.amazon.com/eks/latest/userguide/alb-ingress.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;AWS Load Balancer Controller Annotations&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/ingress/annotations/&quot;&gt;https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/ingress/annotations/&lt;/a&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;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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Terraform AWS Provider - ALB 리소스&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb&quot;&gt;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Terraform AWS Provider - ALB Target Group&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group&quot;&gt;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Terraform AWS Load Balancer 예제&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/terraform-aws-modules/terraform-aws-alb&quot;&gt;https://github.com/terraform-aws-modules/terraform-aws-alb&lt;/a&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;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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;CloudWatch 메트릭 - Application Load Balancer&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html&quot;&gt;https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ALB 액세스 로그&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html&quot;&gt;https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;로드 밸런서 성능 최적화 가이드&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://aws.amazon.com/premiumsupport/knowledge-center/elb-latency-troubleshooting/&quot;&gt;https://aws.amazon.com/premiumsupport/knowledge-center/elb-latency-troubleshooting/&lt;/a&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;WAF와 ALB 통합&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-associating-aws-resource.html&quot;&gt;https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-associating-aws-resource.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ALB 보안 정책&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies&quot;&gt;https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies&lt;/a&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>AWS</category>
      <category>AWS</category>
      <category>aws loadbalancer</category>
      <category>loadbalancer</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/451</guid>
      <comments>https://somaz.tistory.com/451#entry451comment</comments>
      <pubDate>Tue, 27 Jan 2026 00:00:18 +0900</pubDate>
    </item>
    <item>
      <title>Jenkins 서버 정전 후 복구 - 플러그인 버전 불일치 해결 가이드</title>
      <link>https://somaz.tistory.com/486</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;갑작스러운 서버 정전은 Jenkins 환경에 예상치 못한 문제를 일으킬 수 있다. 특히 정전 전에 개발자가 플러그인을 업데이트한 경우, 재시작 후 플러그인 버전 불일치로 인해 Jenkins가 정상적으로 작동하지 않을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 글에서는 서버 정전 후 Jenkins가 깨져서 Job이 보이지 않는 문제를 Jenkins 업그레이드를 통해 해결한 경험을 공유하겠다. macOS, Linux, Docker 컨테이너, Kubernetes 환경 등 다양한 플랫폼별 해결 방법을 다룬다.&lt;/span&gt;&lt;/p&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tFg6D/dJMcaiBXthY/eSFQ4kIy6ynKpdb1eLgEGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tFg6D/dJMcaiBXthY/eSFQ4kIy6ynKpdb1eLgEGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tFg6D/dJMcaiBXthY/eSFQ4kIy6ynKpdb1eLgEGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtFg6D%2FdJMcaiBXthY%2FeSFQ4kIy6ynKpdb1eLgEGk%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제 상황&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;발생한 문제&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;갑작스러운 서버 정전&lt;/b&gt;으로 Jenkins가 비정상 종료&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정전 전 개발자가 &lt;b&gt;플러그인을 업데이트&lt;/b&gt;했고, 재시작 과정에서 플러그인 버전이 상승&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Jenkins 재시작 후 &lt;b&gt;UI가 깨지면서 Job 목록이 전혀 보이지 않음&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플러그인 버전 불일치로 인한 호환성 문제 발생&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;증상&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;Jenkins 웹 UI 접속은 가능하지만 Job 리스트가 표시되지 않음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플러그인 관리 페이지에서 경고 메시지 발생&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&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;color: #000000;&quot;&gt;해결 방법&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. Jenkins 백업 (필수!)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;문제 해결을 시도하기 전에 반드시 현재 상태를 백업해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Jenkins 전체 백업
tar -czf ~/jenkins-backup-$(date +%Y%m%d).tar.gz ~/.jenkins

# 또는 중요한 설정만 백업
cd ~/.jenkins
tar -czf ~/jenkins-config-backup.tar.gz \
  config.xml \
  jobs/ \
  credentials.xml \
  secrets/ \
  users/&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Homebrew로 설치한 경우 (권장)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;macOS에서 Homebrew로 Jenkins를 설치한 경우 다음 절차를 따른다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 1. Jenkins 중지
brew services stop jenkins-lts

# 2. Java 21 설치 (의존성)
brew install openjdk@21

# 3. Homebrew 업데이트
brew update

# 4. Jenkins 업그레이드
brew upgrade jenkins-lts

# 5. Jenkins 시작
brew services start jenkins-lts

# 6. 버전 확인
brew info jenkins-lts&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;간소화된 버전&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Jenkins 중지
brew services stop jenkins-lts

# Homebrew 업데이트
brew update

# Jenkins 업그레이드
brew upgrade jenkins-lts

# Jenkins 재시작
brew services start jenkins-lts

# 버전 확인
brew info jenkins-lts&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. WAR 파일로 직접 설치한 경우&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;WAR 파일을 직접 다운로드하여 실행하는 경우&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 현재 Jenkins 중지 (실행 중인 터미널에서 Ctrl+C)

# 기존 WAR 파일 백업
cd ~/jenkins  # 또는 jenkins.war가 있는 디렉토리
mv jenkins.war jenkins.war.backup

# 최신 LTS 버전 다운로드
wget https://updates.jenkins.io/download/war/2.528.3/jenkins.war

# 또는 curl 사용
curl -L https://updates.jenkins.io/download/war/2.528.3/jenkins.war -o jenkins.war

# Jenkins 재시작
java -jar jenkins.war --httpPort=8080&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. Installer(.pkg)로 설치한 경우&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;macOS Installer 패키지로 설치한 경우&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;gauss&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 최신 Jenkins LTS Installer 다운로드
curl -L https://www.jenkins.io/download/thank-you-downloading-osx-installer-stable/ -o jenkins-installer.pkg

# 설치 (기존 버전 위에 덮어씀)
sudo installer -pkg jenkins-installer.pkg -target /

# Jenkins 재시작
sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist
sudo launchctl load /Library/LaunchDaemons/org.jenkins-ci.plist&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. Linux - 패키지 관리자로 설치한 경우&lt;/span&gt;&lt;/h4&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;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Ubuntu/Debian&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;crystal&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 1. 현재 Jenkins 백업
sudo tar -czf /backup/jenkins-backup-$(date +%Y%m%d).tar.gz /var/lib/jenkins

# 2. Jenkins 중지
sudo systemctl stop jenkins

# 3. APT 업데이트
sudo apt update

# 4. Jenkins 업그레이드
sudo apt upgrade jenkins -y

# 5. Jenkins 시작
sudo systemctl start jenkins

# 6. 상태 확인
sudo systemctl status jenkins

# 7. 버전 확인
jenkins --version&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;CentOS/RHEL&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;crystal&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 1. 현재 Jenkins 백업
sudo tar -czf /backup/jenkins-backup-$(date +%Y%m%d).tar.gz /var/lib/jenkins

# 2. Jenkins 중지
sudo systemctl stop jenkins

# 3. YUM 업데이트
sudo yum update

# 4. Jenkins 업그레이드
sudo yum upgrade jenkins -y

# 5. Jenkins 시작
sudo systemctl start jenkins

# 6. 상태 확인
sudo systemctl status jenkins

# 7. 버전 확인
rpm -qa | grep jenkins&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6. Docker 컨테이너 환경&lt;/span&gt;&lt;/h4&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;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;단일 Docker 컨테이너&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 1. 현재 컨테이너 상태 확인
docker ps -a | grep jenkins

# 2. Jenkins 데이터 백업 (볼륨 백업)
docker run --rm \
  -v jenkins_home:/source \
  -v $(pwd):/backup \
  alpine tar -czf /backup/jenkins-backup-$(date +%Y%m%d).tar.gz -C /source .

# 3. 현재 컨테이너 중지 및 제거
docker stop jenkins
docker rm jenkins

# 4. 최신 Jenkins 이미지 Pull
docker pull jenkins/jenkins:lts

# 5. 새 컨테이너로 재시작 (기존 볼륨 재사용)
docker run -d \
  --name jenkins \
  -p 8080:8080 -p 50000:50000 \
  -v jenkins_home:/var/jenkins_home \
  jenkins/jenkins:lts

# 6. 로그 확인
docker logs -f jenkins&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Docker Compose 사용&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;`docker-compose.yml` 업데이트&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;http&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;version: '3.8'

services:
  jenkins:
    image: jenkins/jenkins:lts  # 또는 jenkins/jenkins:2.528.3
    container_name: jenkins
    privileged: true
    user: root
    ports:
      - &quot;8080:8080&quot;
      - &quot;50000:50000&quot;
    volumes:
      - jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - JAVA_OPTS=-Djenkins.install.runSetupWizard=false
    restart: unless-stopped

volumes:
  jenkins_home:
    driver: local&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;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;color: #000000;&quot;&gt;&lt;b&gt;업그레이드 실행&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 1. Jenkins 데이터 백업
docker run --rm \
  -v jenkins_home:/source \
  -v $(pwd):/backup \
  alpine tar -czf /backup/jenkins-backup-$(date +%Y%m%d).tar.gz -C /source .

# 2. 현재 컨테이너 중지
docker-compose down

# 3. 최신 이미지 Pull
docker-compose pull

# 4. 새 버전으로 재시작
docker-compose up -d

# 5. 로그 확인
docker-compose logs -f jenkins&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;7. Kubernetes 환경&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Helm Chart 사용&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 1. 현재 Jenkins 상태 확인
kubectl get pods -n jenkins
helm list -n jenkins

# 2. Jenkins PVC 백업
kubectl get pvc -n jenkins
JENKINS_POD=$(kubectl get pod -n jenkins -l app.kubernetes.io/component=jenkins-controller -o jsonpath='{.items[0].metadata.name}')

# PVC 데이터를 로컬로 백업
kubectl exec -n jenkins $JENKINS_POD -- tar czf /tmp/jenkins-backup.tar.gz -C /var/jenkins_home .
kubectl cp jenkins/$JENKINS_POD:/tmp/jenkins-backup.tar.gz ./jenkins-backup-$(date +%Y%m%d).tar.gz

# 3. Helm Repository 업데이트
helm repo update

# 4. 현재 values.yaml 백업
helm get values jenkins -n jenkins &amp;gt; jenkins-values-backup.yaml

# 5. Jenkins Chart 업그레이드
helm upgrade jenkins jenkins/jenkins \
  -n jenkins \
  -f jenkins-values-backup.yaml \
  --version 5.1.0  # 최신 Chart 버전 지정

# 6. Rollout 상태 확인
kubectl rollout status statefulset/jenkins -n jenkins

# 7. Pod 상태 확인
kubectl get pods -n jenkins
kubectl logs -f $JENKINS_POD -n jenkins&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;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;color: #000000;&quot;&gt;&lt;b&gt;`values.yaml` 예시 (이미지 버전 업데이트)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;controller:
  image:
    repository: jenkins/jenkins
    tag: &quot;2.528.3-lts&quot;  # 최신 LTS 버전으로 업데이트
  
  # 리소스 설정
  resources:
    requests:
      cpu: &quot;500m&quot;
      memory: &quot;2Gi&quot;
    limits:
      cpu: &quot;2000m&quot;
      memory: &quot;4Gi&quot;
  
  # 백업 설정
  backup:
    enabled: true
    schedule: &quot;0 2 * * *&quot;
  
  # JVM 옵션
  javaOpts: &quot;-Xmx2048m -Xms512m&quot;
  
persistence:
  enabled: true
  size: 20Gi
  storageClass: &quot;gp3&quot;  # 환경에 맞게 수정&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes Manifest 사용&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1. Deployment 업데이트&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# jenkins-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: jenkins
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jenkins
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      containers:
      - name: jenkins
        image: jenkins/jenkins:2.528.3-lts  # 최신 버전으로 업데이트
        ports:
        - containerPort: 8080
        - containerPort: 50000
        volumeMounts:
        - name: jenkins-home
          mountPath: /var/jenkins_home
        resources:
          requests:
            memory: &quot;2Gi&quot;
            cpu: &quot;500m&quot;
          limits:
            memory: &quot;4Gi&quot;
            cpu: &quot;2000m&quot;
      volumes:
      - name: jenkins-home
        persistentVolumeClaim:
          claimName: jenkins-pvc&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;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;color: #000000;&quot;&gt;&lt;b&gt;2. 업그레이드 실행&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;reasonml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 1. 현재 PVC 백업
JENKINS_POD=$(kubectl get pod -n jenkins -l app=jenkins -o jsonpath='{.items[0].metadata.name}')
kubectl exec -n jenkins $JENKINS_POD -- tar czf /tmp/jenkins-backup.tar.gz -C /var/jenkins_home .
kubectl cp jenkins/$JENKINS_POD:/tmp/jenkins-backup.tar.gz ./jenkins-backup-$(date +%Y%m%d).tar.gz

# 2. Deployment 업데이트 적용
kubectl apply -f jenkins-deployment.yaml

# 3. Rollout 상태 모니터링
kubectl rollout status deployment/jenkins -n jenkins

# 4. 새 Pod 확인
kubectl get pods -n jenkins

# 5. 로그 확인
NEW_POD=$(kubectl get pod -n jenkins -l app=jenkins -o jsonpath='{.items[0].metadata.name}')
kubectl logs -f $NEW_POD -n jenkins&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;StatefulSet으로 운영하는 경우&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 1. 현재 StatefulSet 백업
kubectl get statefulset jenkins -n jenkins -o yaml &amp;gt; jenkins-statefulset-backup.yaml

# 2. PVC 백업
JENKINS_POD=$(kubectl get pod -n jenkins -l app=jenkins -o jsonpath='{.items[0].metadata.name}')
kubectl exec -n jenkins $JENKINS_POD -- tar czf /tmp/jenkins-backup.tar.gz -C /var/jenkins_home .
kubectl cp jenkins/$JENKINS_POD:/tmp/jenkins-backup.tar.gz ./jenkins-backup-$(date +%Y%m%d).tar.gz

# 3. StatefulSet 이미지 업데이트
kubectl set image statefulset/jenkins jenkins=jenkins/jenkins:2.528.3-lts -n jenkins

# 또는 직접 편집
kubectl edit statefulset jenkins -n jenkins

# 4. Rollout 상태 확인
kubectl rollout status statefulset/jenkins -n jenkins

# 5. Pod 재시작 확인
kubectl get pods -n jenkins -w&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드 후 확인 사항&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&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;&lt;span style=&quot;color: #000000;&quot;&gt;1. Jenkins 접속 확인&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;브라우저에서 Jenkins URL에 접속하여 정상 작동을 확인한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;각 환경별 기본 URL&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;macOS/Linux: `http://localhost:8080`&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Docker: `http://localhost:8080`&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes: Service/Ingress에 설정된 URL&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Job 목록 확인&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;Dashboard에서 모든 Job이 정상적으로 표시되는지 확인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 Job의 설정이 유지되었는지 점검&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 플러그인 업데이트&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Jenkins가 정상적으로 작동하면 모든 플러그인을 최신 버전으로 업데이트한다.&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;color: #000000;&quot;&gt;&lt;b&gt;플러그인 업데이트 절차&lt;/b&gt;&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;Jenkins 관리 &amp;rarr; Plugin Manager 접속&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;Updates&quot; 탭에서 업데이트 가능한 플러그인 확인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;Select All&quot; 선택 후 &quot;Download now and install after restart&quot; 클릭&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;재시작 체크박스 선택하여 자동 재시작&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 최종 검증&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;macOS/Linux&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Jenkins 로그 확인
# Homebrew 설치
tail -f /opt/homebrew/var/log/jenkins-lts/jenkins.log

# Linux systemd
sudo journalctl -u jenkins -f

# Linux 전통 방식
tail -f /var/log/jenkins/jenkins.log&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Docker&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 컨테이너 로그 확인
docker logs -f jenkins

# Docker Compose
docker-compose logs -f jenkins&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;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;color: #000000;&quot;&gt;&lt;b&gt;Kubernetes&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Pod 로그 확인
kubectl logs -f &amp;lt;jenkins-pod-name&amp;gt; -n jenkins

# 실시간 이벤트 모니터링
kubectl get events -n jenkins --watch

# Pod 상태 확인
kubectl describe pod &amp;lt;jenkins-pod-name&amp;gt; -n jenkins&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;color: #000000;&quot;&gt;문제 해결 팁&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플러그인 버전 불일치 방지&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;정기적인 Jenkins 및 플러그인 업데이트&lt;/b&gt;: 최신 버전을 유지하여 호환성 문제 예방&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;업데이트 전 백업&lt;/b&gt;: 모든 업데이트 전에 백업 수행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;점진적 업데이트&lt;/b&gt;: 한 번에 모든 플러그인을 업데이트하지 말고 중요도에 따라 단계적으로 진행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;테스트 환경 활용&lt;/b&gt;: 가능하면 프로덕션 환경 적용 전 테스트 환경에서 먼저 검증&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서버 정전 대비&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인프라 레벨&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;UPS(무정전 전원 공급 장치) 사용&lt;/b&gt;: 갑작스러운 정전으로부터 보호&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;클라우드 환경 활용&lt;/b&gt;: AWS/GCP/Azure 등의 고가용성 인프라 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Multi-AZ 배포&lt;/b&gt;: Kubernetes 환경에서 여러 가용 영역에 분산 배치&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;애플리케이션 레벨&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;정기적인 백업 자동화&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;crystal&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Cron job으로 일일 백업 설정 (Linux)
0 2 * * * tar -czf ~/jenkins-backups/jenkins-$(date +\%Y\%m\%d).tar.gz /var/lib/jenkins&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Kubernetes CronJob을 이용한 백업&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;apiVersion: batch/v1
kind: CronJob
metadata:
  name: jenkins-backup
  namespace: jenkins
spec:
  schedule: &quot;0 2 * * *&quot;  # 매일 새벽 2시
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: alpine
            command:
            - /bin/sh
            - -c
            - |
              tar czf /backup/jenkins-$(date +%Y%m%d).tar.gz -C /var/jenkins_home .
              # S3나 다른 스토리지로 업로드하는 로직 추가 가능
            volumeMounts:
            - name: jenkins-home
              mountPath: /var/jenkins_home
            - name: backup
              mountPath: /backup
          restartPolicy: OnFailure
          volumes:
          - name: jenkins-home
            persistentVolumeClaim:
              claimName: jenkins-pvc
          - name: backup
            persistentVolumeClaim:
              claimName: jenkins-backup-pvc&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Jenkins Configuration as Code (JCasC) 사용&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# jenkins.yaml
jenkins:
  systemMessage: &quot;Jenkins configured automatically by JCasC&quot;
  numExecutors: 5
  mode: NORMAL
  securityRealm:
    local:
      allowsSignup: false
  authorizationStrategy:
    loggedInUsersCanDoAnything:
      allowAnonymousRead: false
  
  crumbIssuer:
    standard:
      excludeClientIPFromCrumb: false

unclassified:
  location:
    url: &quot;https://jenkins.yourdomain.com&quot;
    adminAddress: &quot;admin@yourdomain.com&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;
&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;color: #000000;&quot;&gt;컨테이너 환경 특화 팁&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Docker&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Named Volume 사용&lt;/b&gt;: 데이터 영속성 보장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Health Check 설정&lt;/b&gt;: 컨테이너 상태 모니터링&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;services:
  jenkins:
    image: jenkins/jenkins:lts
    healthcheck:
      test: [&quot;CMD-SHELL&quot;, &quot;curl -f http://localhost:8080/login || exit 1&quot;]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 60s&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;PersistentVolume 백업&lt;/b&gt;: 정기적인 스냅샷 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ReadinessProbe/LivenessProbe 설정&lt;/b&gt;: 자동 복구 기능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;StorageClass 선택&lt;/b&gt;: 백업/스냅샷 기능을 지원하는 스토리지 사용 (AWS EBS, GCP PD 등)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;livenessProbe:
  httpGet:
    path: /login
    port: 8080
  initialDelaySeconds: 90
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 5

readinessProbe:
  httpGet:
    path: /login
    port: 8080
  initialDelaySeconds: 60
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 3&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&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 style=&quot;color: #000000;&quot;&gt;Jenkins는 DevOps 파이프라인의 핵심 도구이지만, 갑작스러운 장애 상황에서 취약할 수 있다. 특히 서버 정전과 같은 예기치 않은 상황에서는 플러그인 버전 불일치로 인한 심각한 문제가 발생할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 트러블슈팅에서 핵심은 &lt;b&gt;Jenkins 자체를 최신 버전으로 업그레이드&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;교훈&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항상 백업을 우선시하세요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Jenkins와 플러그인을 최신 상태로 유지하세요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정전과 같은 장애 상황에 대비한 예방책을 마련하세요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제 발생 시 단계적으로 접근하세요 (백업 &amp;rarr; 업그레이드 &amp;rarr; 플러그인 업데이트)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;플랫폼별 권장사항&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;macOS&lt;/b&gt;: Homebrew를 통한 관리로 의존성 자동 해결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Linux&lt;/b&gt;: 패키지 관리자를 활용한 안정적인 업데이트&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Docker&lt;/b&gt;: 이미지 버전 관리와 볼륨 백업 전략 수립&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Kubernetes&lt;/b&gt;: Helm Chart 사용과 자동화된 백업 CronJob 구성&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Jenkins 환경을 안정적으로 운영하기 위해서는 정기적인 유지보수와 백업 전략이 필수적이다. 특히 컨테이너 오케스트레이션 환경에서는 선언적 구성 관리(IaC)와 자동화된 백업 시스템이 더욱 중요하다. 이번 경험이 비슷한 문제를 겪는 분들께 도움이 되기를 바란다.&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;&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.jenkins.io/doc/&quot;&gt;Jenkins Official Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.jenkins.io/changelog-stable/&quot;&gt;Jenkins LTS Changelog&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://plugins.jenkins.io/&quot;&gt;Jenkins Plugin Manager&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.jenkins.io/doc/book/system-administration/backing-up/&quot;&gt;Jenkins Backup and Restore&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://formulae.brew.sh/formula/jenkins-lts&quot;&gt;Homebrew Jenkins Formula&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/jenkinsci/configuration-as-code-plugin&quot;&gt;Jenkins Configuration as Code&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://hub.docker.com/r/jenkins/jenkins&quot;&gt;Jenkins Docker Hub&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/jenkinsci/helm-charts&quot;&gt;Jenkins Helm Chart&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/&quot;&gt;Kubernetes StatefulSets&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.docker.com/compose/&quot;&gt;Docker Compose Documentation&lt;/a&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;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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>Trouble Shooting</category>
      <category>CICD</category>
      <category>Jenkins</category>
      <category>trouble Shooting</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/486</guid>
      <comments>https://somaz.tistory.com/486#entry486comment</comments>
      <pubDate>Fri, 23 Jan 2026 00:00:03 +0900</pubDate>
    </item>
    <item>
      <title>Supermicro 서버 IPMI 설정 및 팬 제어 가이드</title>
      <link>https://somaz.tistory.com/449</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&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 style=&quot;color: #000000;&quot;&gt;서버 관리에서 하드웨어 모니터링과 원격 관리는 필수적인 요소다. 특히 Supermicro 서버의 경우 IPMI(Intelligent Platform Management Interface)를 통해 강력한 하드웨어 관리 기능을 제공한다. &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;color: #000000;&quot;&gt;이번 글에서는 실제 서버 환경에서 IPMI 설정과 팬 제어를 시도했던 과정을 단계별로 살펴보고, 각 단계에서 마주친 문제점과 해결 방법을 공유하겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1878&quot; data-origin-height=&quot;2380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2kvVK/btsQjks9TG6/dDahBehlIodMffF6XoL8vK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2kvVK/btsQjks9TG6/dDahBehlIodMffF6XoL8vK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2kvVK/btsQjks9TG6/dDahBehlIodMffF6XoL8vK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2kvVK%2FbtsQjks9TG6%2FdDahBehlIodMffF6XoL8vK%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;726&quot; height=&quot;920&quot; data-origin-width=&quot;1878&quot; data-origin-height=&quot;2380&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Supermicro 서버 IPMI 설정 및 팬 제어 가이드&lt;/span&gt;&lt;/h2&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;color: #000000;&quot;&gt;서버 환경 확인&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;먼저 서버의 기본 정보를 확인해보았다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756864071876&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sensors
... (정상적인 온도 출력) ...

sensors | grep -i fan
# 아무런 결과도 나오지 않음

sudo pwmconfig
# pwmconfig version 3.6.0
...
/usr/sbin/pwmconfig: There are no pwm-capable sensor modules installed&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;sensors가 팬 속도 정보를 보여주지 않았고, pwmconfig는 &quot;pwm-capable sensor modules이 없다&quot;는 메시지를 반환했다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이는 운영체제(소프트웨어)가 팬을 직접 제어할 수 있는 하드웨어 인터페이스를 찾지 못했다는 의미이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대부분의 엔터프라이즈 서버는 &lt;b&gt;BMC(Baseboard Management Controller)&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; 칩을 통해 팬, 전원, 온도 등을 관리하며, 이 BMC는 IPMI 프로토콜을 사용한다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IPMI를 통한 하드웨어 정보 확인&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서버급 하드웨어에서는 IPMI를 통해 더 정확한 하드웨어 정보를 얻을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756864193337&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo ipmitool sdr list | grep -i fan
...
FAN1             | no reading        | ns
FAN2             | 3360 RPM          | ok
FANA             | 2240 RPM          | ok
FANB             | 2100 RPM          | ok
FANC             | no reading        | ns

sudo ipmitool sensor list | grep -i fan
...
FAN1             | na         |            | na    | na        | na        | na        | na        | na        | na        
FAN2             | 3220.000   | RPM        | ok    | na        | 420.000   | na        | na        | na        | na        
FANA             | 2240.000   | RPM        | ok    | na        | 420.000   | na        | na        | na        | na        
FANB             | 2100.000   | RPM        | ok    | na        | 420.000   | na        | na        | na        | na        
FANC             | na         |            | na    | na        | na        | na        | na        | na        | na&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IPMI를 통해 확인한 팬 정보는 다음과 같았다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;FAN1: 측정값 없음 (no reading)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;FAN2: 약 2800-3220 RPM&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;FANA: 약 1400-2240 RPM&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;FANB: 약 1400-2100 RPM&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;FANC: 측정값 없음 (no reading)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IPMI 네트워크 설정 및 웹 접근 활성화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IPMI 네트워크 정보 확인&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756864264857&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo ipmitool lan print 1
...
Set in Progress         : Set Complete
Auth Type Support       : NONE MD2 MD5 PASSWORD 
Auth Type Enable        : Callback : MD2 MD5 PASSWORD 
                        : User     : MD2 MD5 PASSWORD 
                        : Operator : MD2 MD5 PASSWORD 
                        : Admin    : MD2 MD5 PASSWORD 
                        : OEM      : MD2 MD5 PASSWORD 
IP Address Source       : Static Address
IP Address              : 10.10.10.14
Subnet Mask             : 255.255.255.0
MAC Address             : 90:5a:08:74:a9:13
SNMP Community String   : public
IP Header               : TTL=0x00 Flags=0x00 Precedence=0x00 TOS=0x00
BMC ARP Control         : ARP Responses Enabled, Gratuitous ARP Disabled
Default Gateway IP      : 10.10.10.1
Default Gateway MAC     : 00:00:00:00:00:00
Backup Gateway IP       : 0.0.0.0
Backup Gateway MAC      : 00:00:00:00:00:00
802.1q VLAN ID          : Disabled
802.1q VLAN Priority    : 0
RMCP+ Cipher Suites     : 3,17
Cipher Suite Priv Max   : aaXXXXXXXXXXXXX
                        :     X=Cipher Suite Unused
                        :     c=CALLBACK
                        :     u=USER
                        :     o=OPERATOR
                        :     a=ADMIN
                        :     O=OEM
Bad Password Threshold  : 3
Invalid password disable: yes
Attempt Count Reset Int.: 300
User Lockout Interval   : 300&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;span style=&quot;color: #000000;&quot;&gt;서버의 BMC는 다음과 같이 설정되어 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IP 주소: 10.10.10.14&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서브넷 마스크: 255.255.255.0&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MAC 주소: 90:5a:08:74:a9:13&lt;/span&gt;&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;&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;color: #000000;&quot;&gt;사용자 계정 웹 접근 활성화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IPMI 웹 인터페이스에 접근하기 위해 기존 계정들의 웹 접근을 활성화했다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756864322408&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo ipmitool user list 1
ID  Name             Callin  Link Auth  IPMI Msg   Channel Priv Limit
1                    true    false      false      Unknown (0x00)
2   ADMIN            false   false      true       ADMINISTRATOR
3   somazxc          true    false      true       ADMINISTRATOR
4   fwupd            true    false      false      Unknown (0x00)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1756864337079&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# ADMIN 계정의 웹 접근 활성화
sudo ipmitool channel setaccess 1 2 link=on ipmi=on callin=on privilege=4

# somazxc 계정의 웹 접근도 활성화
sudo ipmitool channel setaccess 1 3 link=on ipmi=on callin=on privilege=4&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;span style=&quot;color: #000000;&quot;&gt;확인해본다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756864365797&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo ipmitool user list 1
ID  Name             Callin  Link Auth  IPMI Msg   Channel Priv Limit
1                    true    false      false      Unknown (0x00)
2   ADMIN            true    true       true       ADMINISTRATOR
3   somazxc          true    true       true       ADMINISTRATOR
4   fwupd            true    false      false      Unknown (0x00)&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BMC 재시작과 안정성 문제&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BMC 재시작 시도&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설정 변경사항을 적용하기 위해 BMC를 재시작했다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756864406343&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo ipmitool mc reset warm&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;재시작 후 불안정성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;팬 속도를 조절하기 위해 몇 가지 IPMI 명령어를 시도했지만, `Unable to send RAW command` 와 같은 오류가 발생했다. 이는 IPMI 컨트롤러 자체에 일시적인 문제가 있거나 통신이 원활하지 않다는 신호였다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756864537730&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo ipmitool mc info
Get Device ID command failed: Unspecified error&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;span style=&quot;color: #000000;&quot;&gt;`mc reset warm` 명령어로 컨트롤러를 재시작했지만 문제가 해결되지 않았다. 그러다가 IPMI 통신을 초기화하는 &lt;b&gt;raw 명령어&lt;/b&gt;를 발견하고 실행했다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756864580562&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo ipmitool raw 0x06 0x02
sudo ipmitool mc info
Device ID          : 32
...
Device ID                 : 32
Device Revision           : 1
Firmware Revision         : 1.03
IPMI Version              : 2.0
Manufacturer ID           : 10876
Manufacturer Name         : Supermicro
Product ID                : 7290 (0x1c7a)
Product Name              : Unknown (0x1C7A)
Device Available          : yes
Provides Device SDRs      : no
Additional Device Support :
    Sensor Device
    SDR Repository Device
    SEL Device
    FRU Inventory Device
    IPMB Event Receiver
    IPMB Event Generator
    Chassis Device
Aux Firmware Rev Info     : 
    0x05
    0x03
    0x00
    0x00&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;명령어를 실행한 후 IPMI 컨트롤러가 정상적으로 응답하기 시작했다. Supermicro 서버의 경우, 이 raw 명령어가 내부 통신 문제를 해결하는 데 효과적이었던 것으로 보인다.&lt;/span&gt;&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;&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;color: #000000;&quot;&gt;최종 결과: 팬 소음의 감소&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IPMI 컨트롤러와의 통신을 정상화한 후 다시 팬 상태를 확인했다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756864627438&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo ipmitool sdr list | grep -i fan
FAN1             | no reading      | ns
FAN2             | 2800 RPM        | ok
FANA             | 1400 RPM        | ok
FANB             | 1400 RPM        | ok
FANC             | no reading      | ns&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;txc-textbox&quot; style=&quot;background-color: #ffffff; border: #cbcbcb 3px double; padding: 10px;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;놀랍게도 FAN2, FANA, FANB의 RPM이 초기 상태보다 훨씬 낮아진 것을 확인할 수 있었다. 팬 소음은 즉시 확연히 줄어들었다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;이는 IPMI 컨트롤러가 통신 문제 해결 후&amp;nbsp;&lt;/span&gt;&lt;b&gt;자동 모드&lt;/b&gt;&lt;span style=&quot;text-align: start;&quot;&gt;로 돌아가서, 현재 시스템 온도에 맞춰&amp;nbsp;&lt;/span&gt;&lt;b&gt;필요한 만큼만 팬 속도를 조절&lt;/b&gt;하기 시작했기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;센서 오류로 인한 팬 제어 문제 해결&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제 발견: 이중 온도 센서의 모순&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IPMI 통신을 정상화한 후에도 팬 소음이 계속 지속되는 상황이 발생했다. 온도를 다시 확인해보니 흥미로운 사실을 발견할 수 있었다.&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;&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Linux sensors 출력&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;sensors
nct6798-isa-0a30
Adapter: ISA adapter
...
CPUTIN:                +127.5&amp;deg;C  (high = +80.0&amp;deg;C, hyst = +75.0&amp;deg;C)  ALARM  sensor = CPU diode
...

coretemp-isa-0000
Adapter: ISA adapter
Package id 0:  +30.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 0:        +28.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 1:        +26.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)&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;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IPMI 센서 출력&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;sudo ipmitool sdr type temperature
CPU Temp         | 01h | ok  |  3.1 | 29 degrees C
PCH Temp         | 0Ah | ok  |  7.1 | 38 degrees C
System Temp      | 0Bh | ok  |  7.2 | 27 degrees C&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;두 시스템이 완전히 다른 CPU 온도를 보고하고 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;nct6798 센서&lt;/b&gt;: 127.5&amp;deg;C (과열 상태)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;IPMI 센서&lt;/b&gt;: 29&amp;deg;C (정상 상태)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;coretemp 센서&lt;/b&gt;: 26-30&amp;deg;C (정상 상태)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제 분석&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이는 &lt;b&gt;메인보드의 nct6798 센서 칩이 CPU 온도를 잘못 읽고 있는 상황&lt;/b&gt;이었다. 시스템의 팬 제어 로직이 이 잘못된 127.5&amp;deg;C 값을 기준으로 작동하여 팬을 최대 속도로 돌리고 있었던 것이다.&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;color: #000000;&quot;&gt;실제로는&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CPU 온도: 정상 (26-30&amp;deg;C)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시스템 부하: 낮음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해결 방법 1: 센서 설정 파일로 무시&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;가장 깔끔한 해결책은 잘못된 센서를 무시하도록 설정하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;sudo nano /etc/sensors.d/supermicro.conf&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;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;color: #000000;&quot;&gt;설정 파일에 다음 내용을 추가한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;chip &quot;nct6798-*&quot;
    # CPUTIN 센서 무시 (잘못된 127.5&amp;deg;C 값 출력)
    ignore temp2
    
    # 필요시 다른 문제 센서도 무시
    ignore temp1&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설정을 적용한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;ebnf&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;sudo sensors -s&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해결 방법 2: 모듈 완전 비활성화&lt;/span&gt;&lt;/h4&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;더 확실한 방법은 문제가 있는 센서 모듈을 아예 비활성화하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;sudo nano /etc/modprobe.d/blacklist-sensors.conf&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;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;color: #000000;&quot;&gt;다음 내용을 추가한다&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;gcode&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# nct6798 센서 모듈 비활성화 (잘못된 온도 값 출력)
blacklist nct6798&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;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;color: #000000;&quot;&gt;현재 로드된 모듈을 제거한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;gcode&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;sudo modprobe -r nct6798&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결과 확인&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설정 적용 후 sensors 명령어를 다시 실행하면&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;sensors
# nct6798 섹션에서 CPUTIN: +127.5&amp;deg;C 라인이 사라짐
# 또는 nct6798 섹션 전체가 사라짐 (모듈 비활성화 시)

coretemp-isa-0000
Adapter: ISA adapter
Package id 0:  +30.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
# 정상적인 온도만 표시됨&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;팬 상태 재확인&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;coq&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;sudo ipmitool sdr type fan
FAN1             | 41h | ns  | 29.1 | No Reading
FAN2             | 42h | ok  | 29.2 | 2800 RPM  # 이전 3360 RPM에서 감소
FANA             | 47h | ok  | 29.7 | 1400 RPM  # 이전 2100 RPM에서 감소  
FANB             | 48h | ok  | 29.8 | 1400 RPM  # 이전 2100 RPM에서 감소
FANC             | 49h | ns  | 29.9 | No Reading&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결과&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;이중 센서 시스템&lt;/b&gt;: 최신 서버는 여러 온도 센서를 가지고 있으며, 각각 다른 값을 보고할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;센서 우선순위&lt;/b&gt;: 시스템이 어떤 센서를 팬 제어 기준으로 사용하는지 파악하는 것이 중요하다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;하드웨어 vs 소프트웨어&lt;/b&gt;: IPMI(하드웨어)와 lm-sensors(소프트웨어)가 서로 다른 센서에서 정보를 가져올 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;선택적 비활성화&lt;/b&gt;: 잘못된 센서는 무시하고 정확한 센서만 사용하도록 설정할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;추가 내용&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Fan Mode 변경&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;sensors-detect가 &lt;b&gt;Nuvoton NCT6798D Super IO Sensors&lt;/b&gt;를 찾았음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;pre id=&quot;code_1756950157213&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo sensors-detect
# sensors-detect version 3.6.0
# System: Supermicro Super Server [0123456789]
# Board: Supermicro X13SRA-TF
# Kernel: 5.15.0-153-generic x86_64
# Processor: Intel(R) Xeon(R) w5-2465X (6/143/8)

This program will help you determine which kernel modules you need
to load to use lm_sensors most effectively. It is generally safe
and recommended to accept the default answers to all questions,
unless you know what you're doing.

Some south bridges, CPUs or memory controllers contain embedded sensors.
Do you want to scan for them? This is totally safe. (YES/no):  yes  
Module cpuid loaded successfully.
Silicon Integrated Systems SIS5595...                       No
VIA VT82C686 Integrated Sensors...                          No
VIA VT8231 Integrated Sensors...                            No
AMD K8 thermal sensors...                                   No
AMD Family 10h thermal sensors...                           No
AMD Family 11h thermal sensors...                           No
AMD Family 12h and 14h thermal sensors...                   No
AMD Family 15h thermal sensors...                           No
AMD Family 16h thermal sensors...                           No
AMD Family 17h thermal sensors...                           No
AMD Family 15h power sensors...                             No
AMD Family 16h power sensors...                             No
Hygon Family 18h thermal sensors...                         No
Intel digital thermal sensor...                             Success!
    (driver `coretemp')
Intel AMB FB-DIMM thermal sensor...                         No
Intel 5500/5520/X58 thermal sensor...                       No
VIA C7 thermal sensor...                                    No
VIA Nano thermal sensor...                                  No

Some Super I/O chips contain embedded sensors. We have to write to
standard I/O ports to probe them. This is usually safe.
Do you want to scan for Super I/O sensors? (YES/no): yes
Probing for Super-I/O at 0x2e/0x2f
Trying family `National Semiconductor/ITE'...               No
Trying family `SMSC'...                                     No
Trying family `VIA/Winbond/Nuvoton/Fintek'...               Yes
Found `Nuvoton NCT6798D Super IO Sensors'                   Success!
    (address 0xa30, driver `nct6775')&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;span style=&quot;color: #000000;&quot;&gt;Module을 로드한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756950214777&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo modprobe nct6775
sudo modprobe coretemp&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;span style=&quot;color: #000000;&quot;&gt;Sensors 명령어로 확인해본다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756950266186&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sensors

nct6798-isa-0a30
Adapter: ISA adapter
in0:                     1.83 V  (min =  +0.00 V, max =  +1.74 V)  ALARM
in1:                     1.25 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in2:                     3.34 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in3:                     3.36 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in4:                     1.80 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in5:                   1000.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM
in6:                     1.81 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in7:                     3.34 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in8:                     3.04 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in9:                   496.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM
in10:                  896.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM
in11:                  576.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM
in12:                    1.06 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in13:                    1.08 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in14:                    1.06 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
fan1:                     0 RPM  (min =    0 RPM)
fan2:                     0 RPM  (min =    0 RPM)
fan3:                     0 RPM  (min =    0 RPM)
fan4:                     0 RPM  (min =    0 RPM)
fan5:                     0 RPM  (min =    0 RPM)
fan7:                     0 RPM  (min =    0 RPM)
SYSTIN:                 +29.0&amp;deg;C  (high = +80.0&amp;deg;C, hyst = +75.0&amp;deg;C)  sensor = thermistor
CPUTIN:                +127.5&amp;deg;C  (high = +80.0&amp;deg;C, hyst = +75.0&amp;deg;C)  ALARM  sensor = CPU diode
AUXTIN0:                -23.5&amp;deg;C    sensor = thermistor
AUXTIN1:                -23.0&amp;deg;C    sensor = thermistor
AUXTIN2:                +18.0&amp;deg;C    sensor = thermistor
AUXTIN3:                +23.0&amp;deg;C    sensor = thermistor
PCH_CHIP_CPU_MAX_TEMP:   +0.0&amp;deg;C  
PCH_CHIP_TEMP:           +0.0&amp;deg;C  
PCH_CPU_TEMP:            +0.0&amp;deg;C  
PCH_MCH_TEMP:            +0.0&amp;deg;C  
intrusion0:            ALARM
intrusion1:            ALARM
beep_enable:           disabled

eno2-pci-0500
Adapter: PCI adapter
PHY Temperature:  +43.0&amp;deg;C  
MAC Temperature:  +43.0&amp;deg;C  

coretemp-isa-0000
Adapter: ISA adapter
Package id 0:  +30.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 0:        +27.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 1:        +26.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 2:        +30.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 3:        +26.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 4:        +26.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 5:        +28.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 6:        +28.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 7:        +26.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 8:        +27.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 9:        +25.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 10:       +28.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 11:       +27.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 12:       +25.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 13:       +27.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 14:       +28.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)
Core 15:       +28.0&amp;deg;C  (high = +87.0&amp;deg;C, crit = +95.0&amp;deg;C)&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;span style=&quot;color: #000000;&quot;&gt;IPMI 팬 모드 변경한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756950284094&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo ipmitool raw 0x30 0x45 0x00
02

sudo ipmitool raw 0x30 0x45 0x01 0x00

sudo ipmitool raw 0x30 0x45 0x00
00&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`0x02 (Optimal)` 에서 `0x00 (Standard)` 로 성공적으로 변경됨&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현재 상태 분석할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756953570543&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo ipmitool raw 0x30 0x70 0x66 0x00  # 결과: 2f
sudo ipmitool raw 0x30 0x45 0x00        # 결과: 00&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;&lt;span style=&quot;color: #000000;&quot;&gt;`0x2f` (47 decimal) = 현재 팬 속도가 약 **18%**로 설정되어 있음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`0x00` = Standard 자동 모드가 아직 활성화되어 있다.&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;또는 수동 모드로 변경도 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756953359929&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 12% 속도 (0x20 = 32 decimal)
sudo ipmitool raw 0x30 0x70 0x66 0x01 0x00 0x20

# 20% 속도 (0x33 = 51 decimal)
sudo ipmitool raw 0x30 0x70 0x66 0x01 0x00 0x33

# 25% 속도 (0x40 = 64 decimal) 
sudo ipmitool raw 0x30 0x70 0x66 0x01 0x00 0x40

# 30% 속도 (0x4D = 77 decimal)
sudo ipmitool raw 0x30 0x70 0x66 0x01 0x00 0x4D&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;span style=&quot;color: #000000;&quot;&gt;다시 자동모드로 변경하는 방법은 아래와 같다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756953401112&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 자동 팬 제어 모드로 복원
sudo ipmitool raw 0x30 0x30 0x01 0x01

# 그 다음 Standard 모드로 설정
sudo ipmitool raw 0x30 0x45 0x01 0x00

# 현재 모드 확인
sudo ipmitool raw 0x30 0x45 0x00&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리: 하드웨어 관리의 중요성&lt;/span&gt;&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 style=&quot;color: #000000;&quot;&gt;`lm-sensors` 나 `fancontrol` 로 해결되지 않는 팬 소음은 대부분 하드웨어 레벨의 문제이며, 이럴 땐&lt;b&gt; IPMI(또는 벤더사에서 제공하는 관리 도구)&lt;/b&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;color: #000000;&quot;&gt;이 경험을 통해 얻은 교훈은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;IPMI 우선&lt;/b&gt;: 서버 팬 제어는 소프트웨어보다 IPMI를 통한 하드웨어 제어가 기본 방식일 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;IPMI 통신 점검&lt;/b&gt;: `ipmitool` 을 사용해 `mc info` 가 정상 작동하는지 확인하고, 문제가 있다면 초기화 명령어를 시도하자.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;팬 속도 자동 조절&lt;/b&gt;: IPMI 통신이 정상화되면 대부분의 BMC는 시스템 부하에 따라 팬 속도를 자동으로 최적화한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;&lt;span style=&quot;color: #000000;&quot;&gt;최종적으로 잘못된 nct6798 센서를 비활성화한 후&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;팬 소음이 현저히 감소&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CPU 온도 모니터링은 정확한 IPMI와 coretemp 센서로 유지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시스템 안정성과 사용자 경험 모두 개선&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서버 환경에서는 이처럼 하드웨어와 소프트웨어가 복합적으로 작용하는 문제들이 자주 발생한다. 각 컴포넌트의 역할을 정확히 파악하고 문제의 근본 원인을 찾아 해결하는 것이 효과적인 서버 관리의 핵심이다.&lt;/span&gt;&lt;/p&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.supermicro.com/en/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.supermicro.com/en/&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.intel.com/content/www/us/en/servers/ipmi/ipmi-second-gen-interface-spec-v2-rev1-1.html&quot;&gt;https://www.intel.com/content/www/us/en/servers/ipmi/ipmi-second-gen-interface-spec-v2-rev1-1.html&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://linux.die.net/man/1/ipmitool&quot;&gt;https://linux.die.net/man/1/ipmitool&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://hwmon.wiki.kernel.org/lm_sensors&quot;&gt;https://hwmon.wiki.kernel.org/lm_sensors&lt;/a&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;&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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>Trouble Shooting</category>
      <category>Linux</category>
      <category>server</category>
      <category>supermicro</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/449</guid>
      <comments>https://somaz.tistory.com/449#entry449comment</comments>
      <pubDate>Tue, 20 Jan 2026 00:07:09 +0900</pubDate>
    </item>
    <item>
      <title>Claude 4.5 Sonnet vs Gemini 3 Pro 비교: 2026년 최신 AI 모델 대결</title>
      <link>https://somaz.tistory.com/485</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2025년 말부터 2026년 초까지, AI 업계에서 가장 주목받는 두 모델이 등장했다. Anthropic의 Claude 4.5 Sonnet과 Google의 Gemini 3 Pro는 각각 2025년 9월과 11월에 출시되어 AI 모델의 새로운 기준을 제시하고 있다. 개발자 관점에서 이 두 모델을 심층 비교해보겠다.&lt;/span&gt;&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-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1lUPM/dJMcaaRvseq/GIDqlADODAFTl73SCwtHR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1lUPM/dJMcaaRvseq/GIDqlADODAFTl73SCwtHR1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1lUPM/dJMcaaRvseq/GIDqlADODAFTl73SCwtHR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1lUPM%2FdJMcaaRvseq%2FGIDqlADODAFTl73SCwtHR1%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;680&quot; height=&quot;371&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 기본 스펙 비교&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude 4.5 Sonnet&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;출시일&lt;/b&gt;: 2025년 9월 29일&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;학습 데이터 기준&lt;/b&gt;: 2025년 4월&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;컨텍스트 윈도우&lt;/b&gt;: 200K 토큰 (기본), 1M 토큰 (베타)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;가격&lt;/b&gt;: 입력 $3/M 토큰, 출력 $15/M 토큰&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gemini 3 Pro&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;출시일&lt;/b&gt;: 2025년 11월 18일&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;학습 데이터 기준&lt;/b&gt;: 2025년 1월&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;컨텍스트 윈도우&lt;/b&gt;: 1M 토큰 (기본), 출력 64K 토큰&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;가격&lt;/b&gt;: 입력 $127/M 토큰, 출력 $12/M 토큰 (약 42배 비쌈)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&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;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;
&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;color: #000000;&quot;&gt;2. 코딩 성능: 실전 벤치마크 분석&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SWE-bench Verified (실제 GitHub 이슈 해결)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;Claude 4.5 Sonnet: 77.2%&lt;/b&gt; (역대 최고 점수)&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 오픈소스 프로젝트의 버그 수정 능력 측정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드베이스 이해, 버그 재현, 수정 구현, 테스트 통과 필요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Replit 내부 벤치마크에서 0% 에러율 달성&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Gemini 3 Pro: 76.2%&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude와 거의 대등한 성능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1%p 차이는 실무에서 큰 차이는 아님&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개발자 관점&lt;/b&gt;: 실제 코드 수정 작업에서는 두 모델 모두 우수하나, Claude가 약간 앞선다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LiveCodeBench Pro (알고리즘 코딩)&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Gemini 3 Pro: 2,439 Elo&lt;/b&gt; (압도적 우위)&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Codeforces 스타일의 경쟁 프로그래밍&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPT-5.1(2,243 Elo)보다 196점 높음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Claude 4.5 Sonnet: 1,418 Elo&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gemini보다 1,000점 이상 낮음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;개발자 관점&lt;/b&gt;: 알고리즘 문제 해결이나 코딩 테스트 준비에는 Gemini가 월등히 우수하다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Terminal-Bench 2.0 (터미널 에이전트 코딩)&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Claude 4.5 Sonnet: 61.3%&lt;/b&gt; (Extended Thinking 모드)&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최초로 60% 돌파&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Gemini 3 Pro: 54.2%&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선방했지만 Claude에 밀림&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개발자 관점&lt;/b&gt;: CLI 기반 워크플로우나 자동화 스크립트 작성에는 Claude가 더 적합하다.&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;3. 에이전트 성능 비교&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장시간 자율 작업&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Claude 4.5 Sonnet&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;30시간 이상 자율 작업 실증&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;멀티스텝 추론과 코드 실행 유지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Computer Use 기능: OSWorld 벤치마크 61.4% (최고 기록)&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Gemini 3 Pro&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;tau;2-bench: 85.4% (Claude 84.7%)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Vending-Bench 2: $5,478.16 (Claude $3,838.74)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개발자 관점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡한 자동화 워크플로우: Claude (Computer Use 우수)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장기 실행 에이전트: Gemini (더 높은 안정성)&lt;/span&gt;&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 멀티모달 능력&lt;/span&gt;&lt;/h3&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Gemini 3 Pro의 압승&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MMMU-Pro: 81% (Claude 68%)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Video-MMMU: 87.6% (Claude 77.8%)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ScreenSpot-Pro: 72.7% (Claude 36.2%)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;Claude 4.5 Sonnet&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주로 텍스트와 이미지에 집중&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개발자 관점&lt;/b&gt;: UI/UX 관련 작업, 비디오 분석, 멀티모달 데이터 처리는 Gemini가 필수이다.&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;&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;
&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;color: #000000;&quot;&gt;5. 추론 및 수학 능력&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Humanity's Last Exam (PhD 수준 추론)&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Gemini 3 Pro: 37.5%&lt;/b&gt; (도구 미사용)&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Deep Think 모드: 41.0%&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Claude 4.5 Sonnet: 13.7%&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gemini 대비 약 3배 낮은 점수&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPQA Diamond (전문가 수준 과학)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;Gemini 3 Pro: 91.9%&lt;/b&gt; (인간 전문가 ~89.8% 초과)&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Deep Think: 93.8%&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Claude 4.5 Sonnet: 83.4%&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MathArena Apex (최고난도 수학)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;Gemini 3 Pro: 23.4%&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Claude 4.5 Sonnet: 1.6%&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GPT-5.1: 1.0%&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개발자 관점&lt;/b&gt;: 과학 계산, 복잡한 수학 문제, 연구 수준 추론이 필요하면 Gemini를 선택해야 한다.&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6. 프론트엔드 개발&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude 4.5 Sonnet&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;기능적이고 실용적인 디자인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;빠른 반복 편집에 적합&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IDE 스타일 워크플로우에 최적화&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gemini 3 Pro&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;시각적으로 세련되고 상호작용적인 출력&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡한 UI 애니메이션과 WebGL 작업 우수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Figma 목업에서 HTML/CSS 변환 탁월&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실제 사례&lt;/b&gt;: Gemini는 레이 트레이싱 씬, 인터랙티브 비주얼라이제이션 등 창의적 작업에서 압도적 우위&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;color: #000000;&quot;&gt;&lt;b&gt;개발자 관점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 CRUD 앱, 내부 툴: Claude (빠르고 실용적)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고급 UI, 마케팅 사이트, 인터랙티브 경험: Gemini (시각적 품질)&lt;/span&gt;&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;&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;
&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;color: #000000;&quot;&gt;7. 가격 대비 성능&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude 4.5 Sonnet&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;입력&lt;/b&gt;: $3/M 토큰&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;출력&lt;/b&gt;: $15/M 토큰&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Opus 4.1의 1/5 가격으로 동등 이상 성능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gemini 3 Pro&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;입력&lt;/b&gt;: $127/M 토큰 (Claude의 42배)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;출력&lt;/b&gt;: $12/M 토큰 (Claude의 0.8배)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;100M 토큰/월 사용 시 비용 비교&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude: 입력 $300 + 출력 $1,500 = &lt;b&gt;$1,800&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gemini: 입력 $12,700 + 출력 $1,200 = &lt;b&gt;$13,900&lt;/b&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;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;color: #000000;&quot;&gt;&lt;b&gt;개발자 관점&lt;/b&gt;: 예산이 제한적이거나 대규모 서비스라면 Claude가 압도적으로 유리하다.&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;&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;
&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;color: #000000;&quot;&gt;8. 컨텍스트 윈도우 및 속도&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨텍스트 윈도우&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;Gemini 3 Pro&lt;/b&gt;: 1M 토큰 기본 제공 (입력), 64K 토큰 (출력)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Claude 4.5 Sonnet&lt;/b&gt;: 200K 토큰 기본, 1M 토큰 베타&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;활용 사례&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전체 코드베이스 분석: Gemini (1M 기본)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대용량 PDF, 내부 위키: Gemini&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일반 개발 작업: Claude (200K로 충분)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;응답 속도&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;Claude: 상대적으로 빠른 응답&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gemini: 복잡한 추론 시 지연 발생 가능 (Deep Think 모드는 더 느림)&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;9. 안전성 및 정렬&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude 4.5 Sonnet&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;유해 응답률: 1.29% &amp;rarr; 0.71% 개선&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;과도한 거부율: 0.15% &amp;rarr; 0.02% (7.5배 감소)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ASL-3 보안 수준 (CBRN 위험 자동 차단)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;가장 정렬된 프론티어 모델&quot;&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gemini 3 Pro&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;강력한 안전 필터 적용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&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;color: #000000;&quot;&gt;10. 실제 사용 사례별 추천&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude 4.5 Sonnet을 선택해야 하는 경우&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;실무 코딩 어시스턴트 (IDE 통합)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CI/CD 파이프라인, 인프라 자동화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;버그 수정, 리팩토링, 코드 리뷰&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CLI 기반 워크플로우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 효율적인 대규모 서비스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;30시간 이상 장시간 자율 작업&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gemini 3 Pro를 선택해야 하는 경우&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;알고리즘 경진 대회, 코딩 테스트 준비&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡한 수학, 과학 연구&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PhD 수준 추론이 필요한 작업&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;멀티모달 데이터 처리 (비디오, 오디오)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고급 UI/UX 개발&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전체 코드베이스 분석 (1M 토큰)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비주얼 디자인에서 코드 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하이브리드 전략&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;많은 개발자들이 실제로 두 모델을 병행 사용하고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;계획 및 아키텍처 설계&lt;/b&gt;: Claude (논리적 사고)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;알고리즘 최적화&lt;/b&gt;: Gemini (알고리즘 강점)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;일반 코딩&lt;/b&gt;: Claude (비용 효율)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;UI/비주얼 작업&lt;/b&gt;: Gemini (디자인 품질)&lt;/span&gt;&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;&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;
&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;color: #000000;&quot;&gt;11. 2026년 전망&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude의 과제&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;알고리즘 코딩 능력 개선 필요 (LiveCodeBench)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;멀티모달 능력 강화 필요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨텍스트 윈도우 1M 정식 출시 필요&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gemini의 과제&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;응답 속도 개선 (특히 반복 작업)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실무 코딩에서 Claude 수준으로 개선&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업계 트렌드&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;에이전트 중심 개발&lt;/b&gt;: 두 모델 모두 에이전트 워크플로우에 집중&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;멀티모달 표준화&lt;/b&gt;: 텍스트+이미지+비디오+코드 통합이 기본이 될 전망&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;가격 경쟁&lt;/b&gt;: 고성능 모델의 가격 하락 압력 증가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특화 vs 범용&lt;/b&gt;: Claude는 코딩 특화, Gemini는 범용 전략&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2026년 초 현재, &lt;b&gt;Claude 4.5 Sonnet과 Gemini 3 Pro는 서로 다른 강점을 가진 최고 수준의 모델&lt;/b&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DevOps 엔지니어 관점에서의 최종 추천&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실무 개발 환경에서는 Claude 4.5 Sonnet&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;SWE-bench에서 최고 점수 (77.2%)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 효율성 (42배 저렴)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;터미널 작업에 강점&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장시간 자율 작업 능력&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;연구, 알고리즘, 멀티모달 작업에는 Gemini 3 Pro&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;알고리즘 코딩 압도적 우위 (LiveCodeBench 2,439 Elo)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PhD 수준 추론 능력&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;멀티모달 작업에서 타의 추종 불허&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1M 토큰 기본 제공&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개인적 경험을 토대로 한 조언&lt;/b&gt;: Kubernetes 클러스터 관리, CI/CD 파이프라인 구축, 인프라 자동화 같은 DevOps 작업에는 &lt;b&gt;Claude 4.5 Sonnet&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;반면, 복잡한 알고리즘 최적화나 멀티모달 데이터를 다루는 특수한 경우에는 &lt;b&gt;Gemini 3 Pro&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결론&lt;/b&gt;: 대부분의 실무 개발자에게는 &lt;b&gt;Claude 4.5 Sonnet&lt;/b&gt;이 현재 최선의 선택이며, 특정 도메인(알고리즘, 멀티모달)에서 필요할 때만 Gemini 3 Pro를 활용하는 전략이 가장 합리적이다.&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;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;Anthropic. (2025). &quot;Introducing Claude Sonnet 4.5&quot;. &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.anthropic.com/news/claude-sonnet-4-5&quot;&gt;https://www.anthropic.com/news/claude-sonnet-4-5&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google DeepMind. (2025). &quot;Gemini 3: Introducing the latest Gemini AI model&quot;. &lt;a style=&quot;color: #000000;&quot; href=&quot;https://blog.google/products/gemini/gemini-3/&quot;&gt;https://blog.google/products/gemini/gemini-3/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Caylent. (2025). &quot;Claude Sonnet 4.5: Highest-Scoring Claude Model Yet on SWE-bench&quot;. &lt;a style=&quot;color: #000000;&quot; href=&quot;https://caylent.com/blog/claude-sonnet-4-5-highest-scoring-claude-model-yet-on-swe-bench&quot;&gt;https://caylent.com/blog/claude-sonnet-4-5-highest-scoring-claude-model-yet-on-swe-bench&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DataCamp. (2025). &quot;Gemini 3: Google's Most Powerful LLM&quot;. &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.datacamp.com/blog/gemini-3&quot;&gt;https://www.datacamp.com/blog/gemini-3&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Simon Willison. (2025). &quot;Trying out Gemini 3 Pro with audio transcription and a new pelican benchmark&quot;. &lt;a style=&quot;color: #000000;&quot; href=&quot;https://simonwillison.net/2025/Nov/18/gemini-3/&quot;&gt;https://simonwillison.net/2025/Nov/18/gemini-3/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Vellum AI. (2025). &quot;Google Gemini 3 Benchmarks (Explained)&quot;. &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.vellum.ai/blog/google-gemini-3-benchmarks&quot;&gt;https://www.vellum.ai/blog/google-gemini-3-benchmarks&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AceCloud. (2025). &quot;Claude Opus 4.5 Vs Gemini 3 Pro Vs Sonnet 4.5 Comparison Guide&quot;. &lt;a style=&quot;color: #000000;&quot; href=&quot;https://acecloud.ai/blog/claude-opus-4-5-vs-gemini-3-pro-vs-sonnet-4-5/&quot;&gt;https://acecloud.ai/blog/claude-opus-4-5-vs-gemini-3-pro-vs-sonnet-4-5/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CometAPI. (2025). &quot;Gemini 3 Pro vs Claude 4.5 Sonnet for Coding: Which is Better in 2025&quot;. &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.cometapi.com/gemini-3-pro-vs-claude-4-5-sonnet-for-coding/&quot;&gt;https://www.cometapi.com/gemini-3-pro-vs-claude-4-5-sonnet-for-coding/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;InfoQ. (2025). &quot;Claude Sonnet 4.5 Tops SWE-Bench Verified, Extends Coding Focus beyond 30 Hours&quot;. &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.infoq.com/news/2025/10/claude-sonnet-4-5/&quot;&gt;https://www.infoq.com/news/2025/10/claude-sonnet-4-5/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VentureBeat. (2025). &quot;Google unveils Gemini 3 claiming the lead in math, science, multimodal, and agentic AI benchmarks&quot;. &lt;a style=&quot;color: #000000;&quot; href=&quot;https://venturebeat.com/ai/google-unveils-gemini-3-claiming-the-lead-in-math-science-multimodal-and&quot;&gt;https://venturebeat.com/ai/google-unveils-gemini-3-claiming-the-lead-in-math-science-multimodal-and&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;JDuncan.io. (2025). &quot;Gemini 3 Pro vs Claude Sonnet 4.5: Antigravity IDE Review&quot;. &lt;a style=&quot;color: #000000;&quot; href=&quot;https://jduncan.io/blog/2025-11-20-google-antigravity-gemini-3-first-impressions/&quot;&gt;https://jduncan.io/blog/2025-11-20-google-antigravity-gemini-3-first-impressions/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SWE-bench Official Leaderboard. &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.swebench.com/&quot;&gt;https://www.swebench.com/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LiveCodeBench Leaderboard. &lt;a style=&quot;color: #000000;&quot; href=&quot;https://livecodebench.github.io/leaderboard.html&quot;&gt;https://livecodebench.github.io/leaderboard.html&lt;/a&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;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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>AI/AI Tool</category>
      <category>Ai</category>
      <category>AI model</category>
      <category>ChatGPT</category>
      <category>claude</category>
      <category>gemini</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/485</guid>
      <comments>https://somaz.tistory.com/485#entry485comment</comments>
      <pubDate>Sat, 17 Jan 2026 00:00:49 +0900</pubDate>
    </item>
    <item>
      <title>Claude Code 완벽 가이드: Mac에서 시작하기</title>
      <link>https://somaz.tistory.com/482</link>
      <description>&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;터미널에서 바로 AI와 코딩하는 시대가 왔다. Claude Code는 Anthropic에서 만든 CLI 기반 에이전틱 코딩 도구로, IDE를 벗어나 터미널에서 직접 Claude와 대화하며 코드를 작성하고, 수정하고, 디버깅할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4r5kv/dJMcadN7O1h/HCTg1DxNbSKJzLOhhbGzoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4r5kv/dJMcadN7O1h/HCTg1DxNbSKJzLOhhbGzoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4r5kv/dJMcadN7O1h/HCTg1DxNbSKJzLOhhbGzoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4r5kv%2FdJMcadN7O1h%2FHCTg1DxNbSKJzLOhhbGzoK%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;733&quot; height=&quot;400&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;/&gt;&lt;/span&gt;&lt;/figure&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code란?&lt;/span&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code는 단순한 코드 자동완성 도구가 아니다. 터미널에서 실행되는 에이전트로, 프로젝트의 컨텍스트를 이해하고 파일을 직접 읽고 쓰며, 쉘 명령어까지 실행할 수 있다. 개발자가 자연어로 지시하면 Claude가 알아서 코드를 수정하고 테스트까지 돌려준다.&lt;/span&gt;&lt;/p&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설치 방법&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사전 요구사항&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;macOS 10.15 이상&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Node.js 18 이상&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;Node.js가 없다면 먼저 설치한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;crmsh&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Homebrew로 Node.js 설치
brew install node

# 버전 확인
node --version&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code 설치&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;npm install -g @anthropic-ai/claude-code&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;설치가 완료되면 claude 명령어를 사용할 수 있다.&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트러블 슈팅&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;만약 npm registry를 offical로 사용하고 있지 않다면 아래의 명령어를 사용해서 변경해준다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1766991641358&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm config get registry&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;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;공식 npm 레지스트리로 변경&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;arduino&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;npm config set registry https://registry.npmjs.org/&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;또는 일시적으로 레지스트리 지정해서 설치할 수도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;npm install -g @anthropic-ai/claude-code --registry https://registry.npmjs.org/&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;이렇게 하면 기존 설정 건드리지 않고 설치 가능하다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시작하기&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인증&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Pro 요금제를 사용 중이라면 별도의 API 키 없이 Anthropic 계정으로 바로 인증할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 프로젝트 디렉토리로 이동
cd ~/projects/my-app

# Claude Code 실행
claude&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1458&quot; data-origin-height=&quot;1426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6jWxO/dJMcaiaTtza/SuG2862cuKiV6ReKwutlSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6jWxO/dJMcaiaTtza/SuG2862cuKiV6ReKwutlSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6jWxO/dJMcaiaTtza/SuG2862cuKiV6ReKwutlSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6jWxO%2FdJMcaiaTtza%2FSuG2862cuKiV6ReKwutlSk%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;690&quot; height=&quot;675&quot; data-origin-width=&quot;1458&quot; data-origin-height=&quot;1426&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&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;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 사용법&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code는 크게 세 가지 방식으로 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 1. 대화형 REPL 모드
claude

# 2. 일회성 질문
claude &quot;이 프로젝트의 구조를 설명해줘&quot;

# 3. 이전 대화 이어서 계속
claude -c&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 명령어 정리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;터미널 명령어&lt;/span&gt;&lt;/h4&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;명령어&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;claude&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대화형 REPL 모드 시작&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;claude &quot;질문&quot;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;한 번만 질문하고 종료&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;claude -c&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마지막 대화 이어서 계속&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;claude -p &quot;질문&quot;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파이프라인 모드 (스크립트 연동용)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;claude config&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설정 메뉴 열기&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;claude update&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최신 버전으로 업데이트&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;REPL 모드 슬래시 명령어&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대화형 모드에서 사용할 수 있는 명령어들이다.&lt;/span&gt;&lt;/p&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;명령어&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/help&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전체 도움말 보기&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/clear&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대화 내역 초기화&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/compact&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨텍스트 압축 (토큰 절약)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/cost&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현재 세션 토큰 사용량 확인&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/doctor&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설치 및 환경 진단&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/init&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로젝트 설정 파일 생성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/quit&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;종료 (Ctrl+C 두 번도 가능)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/model&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모델 변경&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2222&quot; data-origin-height=&quot;868&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rHOtr/dJMcac2MdYr/PJqaGNswcrs5IV8FOjRKk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rHOtr/dJMcac2MdYr/PJqaGNswcrs5IV8FOjRKk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rHOtr/dJMcac2MdYr/PJqaGNswcrs5IV8FOjRKk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrHOtr%2FdJMcac2MdYr%2FPJqaGNswcrs5IV8FOjRKk1%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;2222&quot; height=&quot;868&quot; data-origin-width=&quot;2222&quot; data-origin-height=&quot;868&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2766&quot; data-origin-height=&quot;1232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nNAQZ/dJMcabixuXl/09cHS39dDVyPGVhSwCiZg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nNAQZ/dJMcabixuXl/09cHS39dDVyPGVhSwCiZg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nNAQZ/dJMcabixuXl/09cHS39dDVyPGVhSwCiZg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnNAQZ%2FdJMcabixuXl%2F09cHS39dDVyPGVhSwCiZg1%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;2766&quot; height=&quot;1232&quot; data-origin-width=&quot;2766&quot; data-origin-height=&quot;1232&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;web console 사용량을 공유한다.&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2666&quot; data-origin-height=&quot;916&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bebFyy/dJMcafysHVK/Ts4hRVSc7muqmDkTUPp1P1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bebFyy/dJMcafysHVK/Ts4hRVSc7muqmDkTUPp1P1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bebFyy/dJMcafysHVK/Ts4hRVSc7muqmDkTUPp1P1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbebFyy%2FdJMcafysHVK%2FTs4hRVSc7muqmDkTUPp1P1%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;2666&quot; height=&quot;916&quot; data-origin-width=&quot;2666&quot; data-origin-height=&quot;916&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실전 활용 예시&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드 이해 및 설명&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;claude &quot;src/api/auth.ts 파일이 어떤 역할을 하는지 설명해줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;버그 수정&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;claude &quot;npm run build 하면 타입 에러가 나. 고쳐줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리팩토링&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;claude &quot;이 함수를 더 읽기 쉽게 리팩토링해줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;테스트 작성&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;claude &quot;UserService 클래스에 대한 Jest 테스트 코드 만들어줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Git 작업&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;claude &quot;변경사항 확인하고 적절한 커밋 메시지로 커밋해줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문서화&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;claude &quot;이 프로젝트의 README.md를 작성해줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로젝트 설정&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로젝트 루트에 CLAUDE.md 파일을 만들어두면 Claude가 프로젝트 컨텍스트를 더 잘 이해한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;claude /init&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`CLAUDE.md` 에 담으면 좋은 내용은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로젝트 개요 및 기술 스택&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 디렉토리 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;빌드 및 실행 방법&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코딩 컨벤션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자주 쓰는 명령어&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Pro 요금제 사용 팁&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Pro 플랜은 월간 사용량 제한이 있다. 효율적으로 사용하려면 다음을 참고하자.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`/cost` 명령어로 현재 세션의 토큰 사용량을 수시로 확인한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`/compact` 명령어로 긴 대화의 컨텍스트를 압축해 토큰을 절약한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단순한 질문은 웹 버전 Claude를 활용하고, 코드 작업이 필요할 때 Claude Code를 사용한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용량이 많아지면 일시적으로 속도 제한이 걸릴 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제 해결&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설치나 실행에 문제가 있다면 진단 명령어를 실행해본다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;claude /doctor&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자주 발생하는 문제와 해결법은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;permission denied 에러&lt;/b&gt;: `sudo npm install -g @anthropic-ai/claude-code` 또는 npm 권한 설정 확인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Node.js 버전 문제&lt;/b&gt;: `node --version` 으로 18 이상인지 확인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;인증 실패&lt;/b&gt;: `claude config` 에서 계정 다시 연결&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code 활용&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code는 단순히 코드를 작성하는 것 이상으로, 개발 워크플로우 전반에 걸쳐 활용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드베이스 이해하기&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;새로운 프로젝트에 투입되었을 때 가장 먼저 해야 할 일은 코드베이스를 파악하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1766992118171&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 프로젝트 전체 구조 파악
claude &quot;이 프로젝트의 아키텍처를 설명해줘&quot;

# 특정 파일의 역할 이해
claude &quot;src/services/payment.ts가 어떤 로직을 처리하는지 알려줘&quot;

# 함수 간 의존관계 분석
claude &quot;handleCheckout 함수가 호출하는 다른 함수들을 다이어그램으로 보여줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드 작성 및 수정&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자연어로 원하는 기능을 설명하면 Claude가 직접 파일을 생성하거나 수정한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 새 기능 구현
claude &quot;사용자 프로필 이미지 업로드 API를 만들어줘. S3에 저장하고 URL을 반환해야 해&quot;

# 기존 코드 개선
claude &quot;이 함수에 에러 핸들링 추가해줘&quot;

# 타입 정의 생성
claude &quot;API 응답에 맞는 TypeScript 인터페이스 만들어줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;디버깅 및 문제 해결&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에러 메시지를 복사해서 붙여넣으면 원인 분석부터 해결까지 도와준다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 에러 분석
claude &quot;이 에러 메시지가 왜 나오는 거야? [에러 내용 붙여넣기]&quot;

# 로그 분석
claude &quot;이 로그에서 문제가 되는 부분을 찾아줘&quot;

# 성능 이슈 진단
claude &quot;이 쿼리가 왜 느린지 분석해줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;테스트 및 품질 관리&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;테스트 코드 작성부터 코드 리뷰까지 자동화할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 단위 테스트 생성
claude &quot;UserService에 대한 테스트 코드 작성해줘&quot;

# 테스트 커버리지 개선
claude &quot;커버리지가 낮은 부분에 테스트 추가해줘&quot;

# 코드 리뷰
claude &quot;이 PR의 변경사항을 리뷰해줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Git 워크플로우 자동화&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;커밋, 브랜치 관리, PR 생성까지 터미널에서 처리할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 커밋 메시지 자동 생성
claude &quot;변경사항 보고 커밋 메시지 작성해서 커밋해줘&quot;

# PR 설명 작성
claude &quot;이 브랜치의 변경사항으로 PR 설명을 작성해줘&quot;

# 충돌 해결
claude &quot;merge conflict 해결해줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Infrastructure as Code 작업&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DevOps 작업에도 유용하게 활용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# Terraform 코드 작성
claude &quot;AWS EKS 클러스터를 생성하는 Terraform 코드 만들어줘&quot;

# Kubernetes 매니페스트 생성
claude &quot;이 애플리케이션을 위한 Deployment와 Service YAML 만들어줘&quot;

# CI/CD 파이프라인 구성
claude &quot;GitHub Actions로 빌드, 테스트, 배포 파이프라인 만들어줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로젝트 관리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code는 프로젝트별로 컨텍스트를 관리할 수 있어 여러 프로젝트를 효율적으로 다룰 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CLAUDE.md 설정&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로젝트 루트에 `CLAUDE.md` 파일을 생성하면 Claude가 프로젝트 컨텍스트를 자동으로 인식한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 자동 생성
claude /init

# 또는 직접 생성
touch CLAUDE.md&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CLAUDE.md 예시&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;markdown&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 프로젝트: MyApp API Server

## 기술 스택
- Node.js 20 + TypeScript
- Express.js
- PostgreSQL + Prisma ORM
- Jest for testing

## 디렉토리 구조
- src/controllers: API 엔드포인트 핸들러
- src/services: 비즈니스 로직
- src/repositories: 데이터 접근 계층
- src/middlewares: 인증, 로깅 등 미들웨어

## 명령어
- npm run dev: 개발 서버 실행
- npm run build: 프로덕션 빌드
- npm run test: 테스트 실행
- npm run migrate: DB 마이그레이션

## 컨벤션
- 커밋 메시지는 Conventional Commits 형식 사용
- 함수명은 camelCase, 클래스명은 PascalCase
- API 응답은 { success, data, error } 형식 통일&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로젝트별 설정 관리&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 프로젝트를 오가며 작업할 때는 각 프로젝트 디렉토리에서 Claude Code를 실행하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 프로젝트 A 작업
cd ~/projects/frontend-app
claude

# 프로젝트 B로 전환
cd ~/projects/backend-api
claude&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;각 디렉토리의 `CLAUDE.md` 를 읽어 해당 프로젝트에 맞는 컨텍스트로 동작한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대화 히스토리 관리&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# 이전 대화 이어서 작업
claude -c

# 새로운 대화 시작 (기존 컨텍스트 초기화)
claude

# REPL 모드에서 대화 초기화
/clear

# 컨텍스트가 너무 길어졌을 때 압축
/compact&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;팀 프로젝트에서 활용&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`CLAUDE.md` 를 Git에 커밋해두면 팀원 모두 동일한 컨텍스트로 Claude Code를 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;# .gitignore에 추가하지 않음
git add CLAUDE.md
git commit -m &quot;docs: add CLAUDE.md for AI-assisted development&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;color: #000000;&quot;&gt;팀 컨벤션, 자주 쓰는 명령어, 프로젝트 특이사항 등을 문서화해두면 온보딩에도 도움이 된다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code는 터미널 기반 개발 워크플로우를 완전히 바꿔놓을 도구다. 기존에 IDE 플러그인 형태로 제공되던 AI 코딩 도구들과 달리, CLI에서 직접 동작하기 때문에 SSH로 접속한 원격 서버에서도, CI/CD 파이프라인에서도, 심지어 Vim이나 Neovim만 쓰는 환경에서도 활용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 DevOps 엔지니어 입장에서 보면 Terraform 코드 작성, Kubernetes 매니페스트 수정, 쉘 스크립트 디버깅 같은 작업을 터미널을 벗어나지 않고 처리할 수 있다는 점이 매력적이다. `kubectl get pods` 결과를 보면서 바로 &quot;이 에러 원인이 뭐야?&quot;라고 물어볼 수 있고, Claude가 직접 YAML 파일을 수정해주기도 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아직 발전 중인 도구라 가끔 불안정할 수 있지만, 터미널 중심으로 작업하는 개발자라면 한 번쯤 도입을 고려해볼 만하다. Pro 요금제를 이미 사용 중이라면 추가 비용 없이 바로 시작할 수 있으니, 오늘 설치해서 직접 경험해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.anthropic.com/en/docs/claude-code&quot;&gt;Claude Code 공식 문서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/anthropics/claude-code&quot;&gt;Claude Code GitHub&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.anthropic.com/claude-code&quot;&gt;Anthropic 공식 블로그 - Claude Code 소개&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.npmjs.com/package/@anthropic-ai/claude-code&quot;&gt;npm - @anthropic-ai/claude-code&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;/div&gt;</description>
      <category>AI/AI Tool</category>
      <category>claude</category>
      <category>claude code</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/482</guid>
      <comments>https://somaz.tistory.com/482#entry482comment</comments>
      <pubDate>Thu, 15 Jan 2026 00:00:16 +0900</pubDate>
    </item>
    <item>
      <title>Kubernetes Redis 클러스터 장애 처리 및 복구 가이드</title>
      <link>https://somaz.tistory.com/448</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis 클러스터는 고가용성과 확장성을 제공하는 강력한 분산 캐시 솔루션이다. 하지만 Kubernetes 환경에서 운영하다 보면 네트워크 분할, 노드 재시작, 설정 문제 등으로 인해 클러스터 상태가 불안정해질 수 있다.&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;color: #000000;&quot;&gt;본 글에서는 Redis 클러스터에서 자주 발생하는 &quot;ClusterAllFailedError&quot;와 &quot;Cluster state changed: fail&quot; 문제를 진단하고 해결하는 실무적인 방법을 다룬다. &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;color: #000000;&quot;&gt;특히 `slots cache` 갱신 실패 문제부터 클러스터 완전 복구까지의 단계별 접근법을 상세히 알아보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baTfb7/dJMcabCShSj/7BfyREjxVyObNFzi9hVHQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baTfb7/dJMcabCShSj/7BfyREjxVyObNFzi9hVHQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baTfb7/dJMcabCShSj/7BfyREjxVyObNFzi9hVHQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaTfb7%2FdJMcabCShSj%2F7BfyREjxVyObNFzi9hVHQ1%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;1408&quot; height=&quot;768&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&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;&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;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  관련 글&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/149&quot;&gt;2022.09.26 - [Open Source Software] - Redis(Remote Dictionary Server)란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/410&quot;&gt;2025.04.02 - [CS 지식] - [CS 지식20.] OS 캐시와 디스크 I/O: MySQL, Redis 퍼포먼스 분석&lt;/a&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;span style=&quot;color: #000000;&quot;&gt;장애 증상 분석&lt;/span&gt;&lt;/h2&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;color: #000000;&quot;&gt;애플리케이션 레벨 에러&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis 클라이언트(ioredis)에서 다음과 같은 에러가 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756798297573&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[ioredis] Unhandled error event: ClusterAllFailedError: Failed to refresh slots cache.
    at tryNode (/app/node_modules/.pnpm/ioredis@5.7.0/node_modules/ioredis/built/cluster/index.js:323:31)
    at /app/node_modules/.pnpm/ioredis@5.7.0/node_modules/ioredis/built/cluster/index.js:340:21
    at Timeout.&amp;lt;anonymous&amp;gt; (/app/node_modules/.pnpm/ioredis@5.7.0/node_modules/ioredis/built/cluster/index.js:699:24)&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;span style=&quot;color: #000000;&quot;&gt;이 에러는 다음을 의미한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라이언트가 Redis 클러스터의 slots 정보를 갱신할 수 없음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 클러스터 노드에 대한 연결이 실패&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;Redis 서버 레벨 증상&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 Redis 노드의 로그에서 확인되는 패턴&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756798326367&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 초기 시작 시
1:M 02 Sep 2025 05:58:10.944 * Cluster state changed: ok

# 몇 초 후 상태 변화
1:M 02 Sep 2025 05:58:26.645 # Cluster state changed: fail&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;정상 시작 후 실패로 전환되는 원인&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클러스터 노드 간 네트워크 통신 문제&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 검색 실패 (node discovery)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;slots 할당 불일치&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;단계별 진단 및 해결&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1단계: 클러스터 상태 진단&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;먼저 현재 클러스터 상태를 정확히 파악한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756798366757&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 기본 클러스터 정보 확인
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli cluster info

# 노드 구성 및 상태 확인
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli cluster nodes

# 각 노드별 상태 확인
kubectl exec -it -n gameserver-cache redis-main-1 -- redis-cli cluster info
kubectl exec -it -n gameserver-cache redis-main-2 -- redis-cli cluster info&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;주요 확인 포인트:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`cluster_state`: ok/fail 상태&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`cluster_slots_assigned`: 16384개 slots 할당 상태&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`cluster_known_nodes`: 인식된 노드 수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`cluster_size`: 실제 클러스터 크기&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2단계: 네트워크 연결성 검증&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클러스터 노드 간 통신이 정상적인지 확인한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756798410445&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 노드 간 ping 테스트
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli ping
kubectl exec -it -n gameserver-cache redis-main-1 -- redis-cli ping
kubectl exec -it -n gameserver-cache redis-main-2 -- redis-cli ping

# 서비스 DNS 해상도 확인
kubectl exec -it -n gameserver-cache redis-main-0 -- nslookup redis-main-1.redis-main.gameserver-cache.svc.cluster.local
kubectl exec -it -n gameserver-cache redis-main-0 -- nslookup redis-main-2.redis-main.gameserver-cache.svc.cluster.local

# 클러스터 버스 포트 연결 테스트 (Redis 포트 + 10000)
kubectl exec -it -n gameserver-cache redis-main-0 -- nc -zv redis-main-1.redis-main.gameserver-cache.svc.cluster.local 16379
kubectl exec -it -n gameserver-cache redis-main-0 -- nc -zv redis-main-2.redis-main.gameserver-cache.svc.cluster.local 16379&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3단계: Slots 할당 상태 점검&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis 클러스터의 핵심인 해시 슬롯 분배 상태를 확인한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756798448916&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 각 노드의 slots 할당 정보 확인
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli cluster slots

# 할당되지 않은 slots 확인
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli cluster check redis-main-0.redis-main.gameserver-cache.svc.cluster.local:6379&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;일반적인 slots 문제&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중복 할당된 slots&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;할당되지 않은 slots&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 간 slots 정보 불일치&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4단계: 클러스터 복구 실행&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;소프트 리셋을 통한 복구&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클러스터 구성 정보만 리셋하고 데이터는 유지한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756798492370&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 모든 노드에서 소프트 리셋 실행
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli cluster reset soft
kubectl exec -it -n gameserver-cache redis-main-1 -- redis-cli cluster reset soft
kubectl exec -it -n gameserver-cache redis-main-2 -- redis-cli cluster reset soft&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클러스터 재생성&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756798505651&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 클러스터 재구성 (replicas 없는 3-master 구성)
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli --cluster create \
  redis-main-0.redis-main.gameserver-cache.svc.cluster.local:6379 \
  redis-main-1.redis-main.gameserver-cache.svc.cluster.local:6379 \
  redis-main-2.redis-main.gameserver-cache.svc.cluster.local:6379 \
  --cluster-replicas 0 --cluster-yes&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성공 시 예상 출력은 아래와 같다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756798520142&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[OK] All nodes agree about slots configuration.
&amp;gt;&amp;gt;&amp;gt; Check for open slots...
&amp;gt;&amp;gt;&amp;gt; Check slots coverage...
[OK] All 16384 slots covered.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5단계: 복구 검증&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클러스터 복구 후 반드시 기능 검증을 수행한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756798607640&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 클러스터 상태 재확인
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli cluster info

# 데이터 읽기/쓰기 테스트
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli set test-key &quot;recovery-test&quot;
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli get test-key

# 다른 노드에서도 데이터 접근 확인
kubectl exec -it -n gameserver-cache redis-main-1 -- redis-cli get test-key
kubectl exec -it -n gameserver-cache redis-main-2 -- redis-cli get test-key

# 클러스터 키 분산 확인
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli set key1 &quot;value1&quot;
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli set key2 &quot;value2&quot; 
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli set key3 &quot;value3&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;&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;
&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;color: #000000;&quot;&gt;고급 문제 해결&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;부분 노드 장애 시 복구&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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_1756798631283&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 문제 노드 식별
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli cluster nodes | grep fail

# 해당 노드를 클러스터에서 제거
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli cluster forget &amp;lt;NODE-ID&amp;gt;

# 새 노드로 교체 후 클러스터에 추가
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli cluster meet redis-main-X.redis-main.gameserver-cache.svc.cluster.local 6379&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Slots 재분배&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 추가/제거 후 slots 균등 분배&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756798647724&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 자동 리밸런싱
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli --cluster rebalance redis-main-0.redis-main.gameserver-cache.svc.cluster.local:6379

# 수동 slots 이동
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli --cluster reshard redis-main-0.redis-main.gameserver-cache.svc.cluster.local:6379&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 일관성 검증&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756798664784&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 모든 노드의 키 개수 확인
for i in {0..2}; do
  echo &quot;Node redis-main-$i:&quot;
  kubectl exec -it -n gameserver-cache redis-main-$i -- redis-cli dbsize
done

# 클러스터 전체 키 검증
kubectl exec -it -n gameserver-cache redis-main-0 -- redis-cli --cluster check redis-main-0.redis-main.gameserver-cache.svc.cluster.local:6379 --cluster-search-multiple-owners&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;&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;color: #000000;&quot;&gt;예방 및 모니터링&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;헬스체크 설정&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis 클러스터 상태 모니터링을 위한 헬스체크 구성한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756798688941&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# redis-healthcheck.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-healthcheck
  namespace: gameserver-cache
data:
  healthcheck.sh: |
    #!/bin/bash
    # 클러스터 상태 확인
    CLUSTER_STATE=$(redis-cli cluster info | grep cluster_state | cut -d: -f2)
    if [ &quot;$CLUSTER_STATE&quot; != &quot;ok&quot; ]; then
      echo &quot;Cluster state is not ok: $CLUSTER_STATE&quot;
      exit 1
    fi
    
    # 기본 ping 응답 확인
    redis-cli ping | grep -q PONG
    if [ $? -ne 0 ]; then
      echo &quot;Redis ping failed&quot;
      exit 1
    fi
    
    echo &quot;Redis cluster is healthy&quot;
    exit 0&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로메테우스 메트릭 수집&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis 클러스터 상태를 지속적으로 모니터링&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_1756798706446&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# redis-exporter.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-exporter
  namespace: gameserver-cache
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis-exporter
  template:
    metadata:
      labels:
        app: redis-exporter
    spec:
      containers:
      - name: redis-exporter
        image: oliver006/redis_exporter:latest
        env:
        - name: REDIS_ADDR
          value: &quot;redis://redis-main-0.redis-main.gameserver-cache.svc.cluster.local:6379&quot;
        - name: REDIS_IS_CLUSTER
          value: &quot;true&quot;
        ports:
        - containerPort: 9121&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;알림 규칙 설정&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중요한 메트릭에 대한 알림 구성&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756798725926&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# redis-alerts.yaml
groups:
- name: redis-cluster
  rules:
  - alert: RedisClusterDown
    expr: redis_up == 0
    for: 1m
    labels:
      severity: critical
    annotations:
      summary: &quot;Redis cluster node is down&quot;
      
  - alert: RedisClusterSlotsFail
    expr: redis_cluster_slots_fail &amp;gt; 0
    for: 30s
    labels:
      severity: warning
    annotations:
      summary: &quot;Redis cluster has failed slots&quot;
      
  - alert: RedisClusterStateNotOK
    expr: redis_cluster_state != 1
    for: 30s
    labels:
      severity: critical
    annotations:
      summary: &quot;Redis cluster state is not OK&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;&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;
&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;color: #000000;&quot;&gt;성능 최적화 고려사항&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 설정&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756798748933&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# redis-statefulset.yaml 최적화
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-main
  namespace: gameserver-cache
spec:
  template:
    spec:
      containers:
      - name: redis
        # 네트워크 버퍼 크기 조정
        command:
        - redis-server
        - /etc/redis/redis.conf
        - --tcp-keepalive
        - &quot;60&quot;
        - --tcp-backlog
        - &quot;511&quot;
        # 클러스터 통신 최적화
        - --cluster-node-timeout
        - &quot;5000&quot;
        - --cluster-announce-bus-port
        - &quot;16379&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메모리 및 디스크 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1756798765359&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;resources:
  requests:
    cpu: 200m
    memory: 512Mi
  limits:
    cpu: 1000m
    memory: 2Gi
    
# 영구 볼륨 설정
volumeClaimTemplates:
- metadata:
    name: data
  spec:
    accessModes: [&quot;ReadWriteOnce&quot;]
    storageClassName: fast-ssd
    resources:
      requests:
        storage: 20Gi&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis 클러스터 장애는 분산 시스템의 특성상 완전히 피하기는 어렵지만, 체계적인 진단과 복구 절차를 통해 신속하게 해결할 수 있다. 본 글에서 소개한 단계별 접근법을 통해 다음과 같은 효과를 얻을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 성과&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;장애 발생 시 평균 복구 시간(MTTR) 단축&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 손실 없는 안전한 클러스터 복구&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영 노하우&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;정기적인 클러스터 상태 점검으로 잠재적 문제 조기 발견&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;백업 및 복구 절차의 정기적 테스트 실시&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis 클러스터는 올바르게 구성하고 모니터링한다면 안정적이고 확장 가능한 캐시 솔루션으로 활용할 수 있다. 장애 발생 시 당황하지 말고 본 가이드의 절차를 차근차근 따라 실행하면, 대부분의 클러스터 문제를 효과적으로 해결할 수 있을 것이다.&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;color: #000000;&quot;&gt;무엇보다 중요한 것은 장애 발생 전 미리 모니터링 체계를 구축하고, 복구 절차를 숙지하여 신속한 대응이 가능하도록 준비하는 것이다. 이를 통해 서비스 중단 시간을 최소화하고 사용자 경험을 보호할 수 있다.&lt;/span&gt;&lt;/p&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&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;&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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>Trouble Shooting</category>
      <category>Kubernetes</category>
      <category>redis</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/448</guid>
      <comments>https://somaz.tistory.com/448#entry448comment</comments>
      <pubDate>Tue, 13 Jan 2026 00:00:39 +0900</pubDate>
    </item>
    <item>
      <title>Claude와 Claude Code: AI 기반 개발 환경의 새로운 패러다임</title>
      <link>https://somaz.tistory.com/483</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AI 기술이 소프트웨어 개발 프로세스를 혁신하고 있는 가운데, Anthropic의 Claude는 단순한 챗봇을 넘어 실질적인 개발 파트너로 자리잡고 있다. 특히 최근 출시된 Claude Code는 커맨드라인 환경에서 직접 코딩 작업을 위임할 수 있는 에이전트 도구로, DevOps 엔지니어와 개발자들에게 새로운 가능성을 제시하고 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 글에서는 Claude의 최신 모델 패밀리인 Claude 4 시리즈와 터미널 기반의 AI 코딩 어시스턴트인 Claude Code의 특징, 활용 방법, 그리고 실무에서의 적용 사례를 살펴보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/V6nXd/dJMcadm5iq9/93nlpVNAsk5bxMmHH7mFN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/V6nXd/dJMcadm5iq9/93nlpVNAsk5bxMmHH7mFN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/V6nXd/dJMcadm5iq9/93nlpVNAsk5bxMmHH7mFN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FV6nXd%2FdJMcadm5iq9%2F93nlpVNAsk5bxMmHH7mFN1%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;697&quot; height=&quot;380&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&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;color: #000000;&quot;&gt;Claude 4 모델 패밀리 소개&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현재 제공되는 모델&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude 4 패밀리는 현재 다음과 같은 모델들로 구성되어 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Claude Opus 4.5&lt;/b&gt;: 가장 강력한 성능의 모델&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Claude Sonnet 4.5&lt;/b&gt;: 일상적인 사용에 최적화된 가장 스마트한 모델&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Claude Haiku 4.5&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Opus의 성능이 어마무시하지만, 토큰을 많이 잡아먹는 이슈가 있다. 간단한 코딩은 Sonnet으로도 충분하다!&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Sonnet 4.5의 특징&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Sonnet 4.5는 성능과 효율성의 균형이 뛰어나 다음과 같은 작업에 적합하다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡한 코드 리뷰 및 리팩토링&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인프라 설정 파일 작성 (Kubernetes, Terraform 등)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기술 문서 작성 및 번역&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;디버깅 및 문제 해결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API 설계 및 구현&lt;/span&gt;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude 접근 방법&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude는 다양한 채널을 통해 접근할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 웹 인터페이스 (claude.ai)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;브라우저를 통해 직접 접속하여 대화형 방식으로 사용할 수 있다. 다음과 같은 기능을 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Artifacts&lt;/b&gt;: 코드, 문서 등을 별도 패널에서 실시간으로 확인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Web Search&lt;/b&gt;: 최신 정보 검색 기능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Code Execution and File Creation&lt;/b&gt;: 코드 실행 및 파일 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Search and Reference Past Chats&lt;/b&gt;: 이전 대화 검색 및 참조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Memory Generation&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 모바일 및 데스크톱 앱&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;iOS, Android, macOS, Windows 등 다양한 플랫폼에서 네이티브 앱을 통해 사용 가능하다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. API 및 개발자 플랫폼&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로그래밍 방식으로 Claude를 통합할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;import anthropic

client = anthropic.Anthropic(api_key=&quot;your-api-key&quot;)

message = client.messages.create(
    model=&quot;claude-sonnet-4-5-20250929&quot;,
    max_tokens=1024,
    messages=[
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;Kubernetes Deployment YAML 예제를 작성해줘&quot;}
    ]
)

print(message.content)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;color: #000000;&quot;&gt;4. Claude Code&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;터미널에서 직접 코딩 작업을 위임할 수 있는 커맨드라인 도구이다.&lt;/span&gt;&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-origin-width=&quot;2264&quot; data-origin-height=&quot;852&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YVKtK/dJMb99ZlNuv/5SFuu5TjshJo1KknCL79l1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YVKtK/dJMb99ZlNuv/5SFuu5TjshJo1KknCL79l1/img.png&quot; data-alt=&quot;상당히 귀염뽀짝하다?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YVKtK/dJMb99ZlNuv/5SFuu5TjshJo1KknCL79l1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYVKtK%2FdJMb99ZlNuv%2F5SFuu5TjshJo1KknCL79l1%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;2264&quot; height=&quot;852&quot; data-origin-width=&quot;2264&quot; data-origin-height=&quot;852&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;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;
&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;color: #000000;&quot;&gt;Claude Code: 터미널 기반 AI 코딩 어시스턴트&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code란?&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code는 개발자가 터미널에서 직접 Claude에게 코딩 작업을 위임할 수 있는 에이전트 도구이다. 파일 생성, 코드 수정, 디버깅, 테스트 작성 등의 작업을 자연어 명령으로 수행할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 특징&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1. 컨텍스트 인식&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현재 작업 중인 프로젝트의 구조를 이해&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 코드베이스와 일관된 스타일로 코드 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Git 히스토리 및 변경사항 추적&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2. 멀티스텝 작업 수행&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡한 리팩토링 작업을 단계별로 진행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 파일에 걸친 변경사항을 일관되게 처리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;3. 대화형 워크플로우&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;작업 진행 중 추가 질문 및 확인 요청&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;변경사항에 대한 설명 제공&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자세한 내용은 아래의 글을 참고하길 바란다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/482&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2025.12.29 - [AI/AI Tool] - Claude Code 완벽 가이드: Mac에서 시작하기&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude vs 다른 AI 모델 비교&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AI 코딩 어시스턴트 시장에는 여러 경쟁자들이 있다. 각 모델의 특징과 Claude의 차별점을 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 AI 모델 비교표&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특징&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Sonnet 4.5&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPT-4o&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gemini 2.0 Flash&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GitHub Copilot&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;컨텍스트 윈도우&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;200K 토큰&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;128K 토큰&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1M 토큰&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;코드 생성 품질&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매우 우수&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우수&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우수&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우수&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;추론 능력&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매우 우수&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우수&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우수&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보통&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;터미널 통합&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VS Code 중심&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;DevOps 특화&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;강함&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보통&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보통&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;약함&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;가격 (API)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$3/1M 입력 토큰&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$2.5/1M 입력 토큰&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$0.075/1M 입력 토큰&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;$10/월 구독&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;한국어 지원&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우수&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우수&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우수&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;벤치마크 비교&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;HumanEval (Python 코딩 테스트)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Sonnet 4.5: 92%&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPT-4o: 90.2%&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gemini 2.0 Flash: 88.5%&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPT-3.5: 48.1%&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;SWE-bench (실제 GitHub 이슈 해결)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Sonnet 4.5: 49.0%&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GPT-4o: 38.4%&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gemini Pro: 34.2%&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 벤치마크는 Claude가 실제 소프트웨어 엔지니어링 작업에서 우위를 보인다는 것을 시사한다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최신 벤치마크 결과는 각 모델 제공사의 공식 문서를 참고하길 바란다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.anthropic.com/research&quot;&gt;Anthropic 벤치마크&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://openai.com/research&quot;&gt;OpenAI 벤치마크&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://ai.google/research&quot;&gt;Google AI 벤치마크&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude와 Claude Code는 단순한 AI 도구를 넘어 DevOps 엔지니어의 강력한 파트너로 자리잡고 있다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;반복적인 작업의 자동화, 복잡한 설정의 간소화, 빠른 프로토타이핑이 가능하며, 무엇보다 자연어로 의도를 표현하는 것만으로 전문적인 인프라 코드와 설정을 생성할 수 있다는 점이 혁신적이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 Claude Code는 터미널에서 직접 작업을 위임할 수 있어 기존 워크플로우에 자연스럽게 통합된다. Kubernetes 매니페스트 작성, Terraform 모듈 개발, CI/CD 파이프라인 구성 등 복잡한 DevOps 작업을 대화형으로 수행할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하지만 AI는 도구일 뿐이며, 최종 책임과 판단은 엔지니어의 몫이다. 생성된 코드와 설정을 항상 검토하고, 보안 및 성능 측면에서 검증하는 습관을 유지해야 한다. Claude를 효과적으로 활용하면 더 높은 수준의 아키텍처와 전략적 의사결정에 집중할 수 있는 시간을 확보할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;앞으로 AI 기반 개발 도구는 계속 진화할 것이며, Claude는 그 선두에서 DevOps 워크플로우의 패러다임을 바꾸고 있다. 여러분의 일상적인 개발 작업에 Claude를 통합하여 생산성을 높이고, 더 창의적이고 전략적인 업무에 집중해보시기 바란다.&lt;/span&gt;&lt;/p&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;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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.anthropic.com&quot;&gt;Anthropic 공식 웹사이트&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://claude.ai&quot;&gt;Claude 사용 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.anthropic.com&quot;&gt;Claude API 문서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/overview&quot;&gt;Claude 프롬프트 엔지니어링 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://support.claude.com&quot;&gt;Claude 지원 센터&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://console.anthropic.com&quot;&gt;Anthropic Developer Platform&lt;/a&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;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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>AI/AI Tool</category>
      <category>claude</category>
      <category>claude code</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/483</guid>
      <comments>https://somaz.tistory.com/483#entry483comment</comments>
      <pubDate>Sat, 10 Jan 2026 00:00:45 +0900</pubDate>
    </item>
    <item>
      <title>GCP Load Balancer 완전 비교 가이드</title>
      <link>https://somaz.tistory.com/457</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라우드 환경에서 로드밸런서는 애플리케이션의 가용성과 성능을 보장하는 핵심 구성 요소이다. Google Cloud Platform(GCP)은 다양한 로드밸런싱 솔루션을 제공하여 각기 다른 요구사항과 아키텍처에 최적화된 선택지를 제공한다.&lt;/span&gt;&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 data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최근 몇 년간 GCP의 로드밸런서 서비스들은 크게 발전했다. 특히 HTTP(S) Load Balancer의 경우 Certificate Manager를 통한 여러 도메인 지원이 강화되었고, SSL 인증서 관리 방식도 다양해졌다. Certificate Map 기능을 통해 도메인별로 다른 인증서를 할당할 수 있게 되어, 과거의 제약이 크게 완화되었다.&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;color: #000000;&quot;&gt;하지만 GKE 환경에서는 여전히 중요한 제약사항이 있습니다. GKE ManagedCertificate는 하나의 인증서당 하나의 도메인만 지원하며, AWS ALB Ingress Group과 같은 기능이 없어 하나의 Ingress가 하나의 Load Balancer를 생성한다.&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;color: #000000;&quot;&gt;이 글에서는 GCP의 주요 로드밸런서 유형들을 심층 분석하고, 각각의 특성과 적절한 사용 사례를 살펴보겠습니다. 또한 실제 운영 환경에서 활용할 수 있는 Terraform 코드와 GKE Ingress 구성 예제, 그리고 최적화 전략도 함께 제시하겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pmImg/dJMcagRIHsO/bMkeckypGAUCk1QbibiKf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pmImg/dJMcagRIHsO/bMkeckypGAUCk1QbibiKf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pmImg/dJMcagRIHsO/bMkeckypGAUCk1QbibiKf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpmImg%2FdJMcagRIHsO%2FbMkeckypGAUCk1QbibiKf0%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;1408&quot; height=&quot;768&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&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;&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;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  관련 글&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/194&quot;&gt;2023.04.06 - [GCP] - GCP란? - 서비스 계정 &amp;amp; Project 생성 / SDK(gcloud) 설치&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/195&quot;&gt;2023.04.06 - [GCP] - GCP IAM이란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/197&quot;&gt;2023.04.12 - [GCP] - GCP - SDK(gcloud) 계정 2개 등록하기&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/218&quot;&gt;2023.05.05 - [GCP] - GCP vs AWS 리소스 비교&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/231&quot;&gt;2023.05.19 - [GCP] - GCP BigQuery란? &amp;amp; Data Warehouse&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/249&quot;&gt;2023.09.23 - [GCP] - BigQuery와 DataFlow를 활용한 Data ETL(GCP)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: left;&quot; href=&quot;https://somaz.tistory.com/253&quot;&gt;2023.10.03 - [GCP] - Shared VPC를 사용하여 GKE 클러스터 생성시 IAM 설정&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/264&quot;&gt;2023.12.18 - [GCP] - GCP를 활용한 데이터 자동화(MongoDB, CloudSQL, GA, Dune)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: left;&quot; href=&quot;https://somaz.tistory.com/279&quot;&gt;2024.01.20 - [GCP] - Terraform 으로 GCS 생성후 Cloud CDN 생성(GCP)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/291&quot;&gt;2024.03.04 - [GCP] - GCP에서 딥러닝을 위한 GPU VM 서버 만들기(GCP)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/306&quot;&gt;2024.04.24 - [Migration] - AWS에서 GCP로 마이그레이션하는 방법 및 고려사항&lt;/a&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GCP Load Balancer 유형별 특성 분석&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HTTP(S) Load Balancer&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HTTP(S) Load Balancer는 GCP의 가장 강력하고 유연한 로드밸런싱 솔루션이다. 글로벌 범위에서 동작하며, 레이어 7(애플리케이션 계층)에서 트래픽을 처리한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 특징&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;글로벌 애니캐스트 IP&lt;/b&gt;: 전 세계 어디서나 가장 가까운 백엔드로 라우팅&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Cloud CDN 통합&lt;/b&gt;: 정적 콘텐츠 캐싱으로 성능 향상&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;URL 기반 라우팅&lt;/b&gt;: 경로, 헤더, 쿠키에 따른 정교한 트래픽 분산&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;SSL 터미네이션&lt;/b&gt;: Google-managed 또는 사용자 관리 인증서 지원&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SSL 인증서 관리 옵션&lt;/span&gt;&lt;/h4&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. Certificate Manager (권장 - 여러 도메인 가능)&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# Certificate Manager를 통한 Google 관리형 인증서 (여러 도메인 지원)
resource &quot;google_certificate_manager_certificate&quot; &quot;default&quot; {
  name        = &quot;example-cert&quot;
  description = &quot;Multi-domain certificate&quot;
  scope       = &quot;DEFAULT&quot;

  managed {
    domains = [
      &quot;example.com&quot;,
      &quot;www.example.com&quot;, 
      &quot;api.example.com&quot;
    ]
    dns_authorizations = [
      google_certificate_manager_dns_authorization.example.id,
      google_certificate_manager_dns_authorization.www.id,
      google_certificate_manager_dns_authorization.api.id
    ]
  }
}

# DNS 승인 (각 도메인별)
resource &quot;google_certificate_manager_dns_authorization&quot; &quot;example&quot; {
  name   = &quot;example-dns-auth&quot;
  domain = &quot;example.com&quot;
}

resource &quot;google_certificate_manager_dns_authorization&quot; &quot;www&quot; {
  name   = &quot;www-dns-auth&quot;
  domain = &quot;www.example.com&quot;
}

resource &quot;google_certificate_manager_dns_authorization&quot; &quot;api&quot; {
  name   = &quot;api-dns-auth&quot;
  domain = &quot;api.example.com&quot;
}

# Certificate Map
resource &quot;google_certificate_manager_certificate_map&quot; &quot;default&quot; {
  name        = &quot;cert-map&quot;
  description = &quot;Multi-domain certificate mapping&quot;
}

resource &quot;google_certificate_manager_certificate_map_entry&quot; &quot;default&quot; {
  name         = &quot;cert-map-entry&quot;
  map          = google_certificate_manager_certificate_map.default.name
  certificates = [google_certificate_manager_certificate.default.id]
  hostname     = &quot;example.com&quot;
}
&lt;/code&gt;&lt;/pre&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;&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Compute Engine Managed SSL (여러 도메인 가능)&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;resource &quot;google_compute_managed_ssl_certificate&quot; &quot;default&quot; {
  name = &quot;example-cert&quot;
  managed {
    domains = [
      &quot;example.com&quot;,
      &quot;www.example.com&quot;,
      &quot;api.example.com&quot;
    ]
  }
}
&lt;/code&gt;&lt;/pre&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;&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. GKE ManagedCertificate (도메인당 하나씩 제한)&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# 각 도메인마다 별도의 ManagedCertificate 필요
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: main-cert
spec:
  domains:
    - example.com

---
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: api-cert
spec:
  domains:
    - api.example.com
&lt;/code&gt;&lt;/pre&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;&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 data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. GKE에서 Certificate Manager 사용 (새로운 방식)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Certificate Manager는 GKE에서도 사용할 수 있으며, 더 유연한 인증서 관리를 제공한다.&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;color: #000000;&quot;&gt;&lt;b&gt;Certificate Manager 기반 GKE 인프라&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1757569008443&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# GKE용 Certificate Manager 인증서 생성
resource &quot;google_certificate_manager_certificate&quot; &quot;gke_cert&quot; {
  name        = &quot;gke-certificate&quot;
  description = &quot;Certificate for GKE services&quot;
  scope       = &quot;DEFAULT&quot;

  managed {
    domains = [
      &quot;example.com&quot;,
      &quot;api.example.com&quot;,
      &quot;admin.example.com&quot;
    ]
    dns_authorizations = [
      google_certificate_manager_dns_authorization.example.id,
      google_certificate_manager_dns_authorization.api.id,
      google_certificate_manager_dns_authorization.admin.id
    ]
  }
}

# Certificate Map 생성
resource &quot;google_certificate_manager_certificate_map&quot; &quot;gke_cert_map&quot; {
  name        = &quot;gke-cert-map&quot;
  description = &quot;Certificate map for GKE&quot;
}

# Certificate Map Entry
resource &quot;google_certificate_manager_certificate_map_entry&quot; &quot;main_entry&quot; {
  name         = &quot;main-cert-entry&quot;
  map          = google_certificate_manager_certificate_map.gke_cert_map.name
  certificates = [google_certificate_manager_certificate.gke_cert.id]
  hostname     = &quot;example.com&quot;
}

resource &quot;google_certificate_manager_certificate_map_entry&quot; &quot;api_entry&quot; {
  name         = &quot;api-cert-entry&quot;
  map          = google_certificate_manager_certificate_map.gke_cert_map.name
  certificates = [google_certificate_manager_certificate.gke_cert.id]
  hostname     = &quot;api.example.com&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;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GKE Ingress에서 Certificate Manager 사용&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1757569035126&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: cert-manager-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: &quot;gke-static-ip&quot;
    kubernetes.io/ingress.class: &quot;gce&quot;
    # Certificate Manager 사용 (ManagedCertificate 대신)
    networking.gke.io/certificate-map: &quot;gke-cert-map&quot;
    networking.gke.io/v1beta1.FrontendConfig: &quot;frontend-config&quot;
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
      - path: /static/*
        pathType: Prefix
        backend:
          service:
            name: static-service
            port:
              number: 80
  - host: api.example.com
    http:
      paths:
      - path: /v1/*
        pathType: Prefix
        backend:
          service:
            name: api-v1-service
            port:
              number: 8080
      - path: /v2/*
        pathType: Prefix
        backend:
          service:
            name: api-v2-service
            port:
              number: 8080&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. GKE Ingress에서 기존 ManagedCertificate 사용&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1757569054116&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    networking.gke.io/managed-certificates: &quot;main-cert,api-cert&quot;
spec:
  rules:
  - host: example.com
    # 웹사이트 라우팅
  - host: api.example.com
    # API 라우팅&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인증서 관리 방식 비교&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;방식&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;도메인 수&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인증 방법&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관리 방식&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;권장 사용처&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Certificate Manager&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 도메인&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DNS 승인&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Certificate Map&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡한 도메인 구성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Compute Engine Managed SSL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 도메인&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HTTP 승인&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Terraform&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Compute Engine 환경&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE ManagedCertificate&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;도메인당 1개&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HTTP 승인&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단순한 GKE 환경&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;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;
&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Network Load Balancer (TCP/UDP)&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Network Load Balancer는 레이어 4에서 동작하는 고성능 로드밸런서로, TCP 및 UDP 트래픽을 처리한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 특징&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;초고성능&lt;/b&gt;: 레이어 4 처리로 낮은 지연시간 제공&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;원본 IP 보존&lt;/b&gt;: 클라이언트의 실제 IP 주소를 백엔드에 전달&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;프로토콜 지원&lt;/b&gt;: TCP, UDP, ESP, GRE, ICMP 등 다양한 프로토콜&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;지역적 로드밸런싱&lt;/b&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;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;적합한 사용 사례&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;게임 서버&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IoT 디바이스 통신&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPN 게이트웨이&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Internal Load Balancer&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Internal Load Balancer는 VPC 내부 트래픽을 위한 로드밸런서로, 외부에서 직접 접근할 수 없는 내부 서비스들 간의 통신을 담당한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 특징&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;내부 전용&lt;/b&gt;: VPC 내부에서만 접근 가능한 프라이빗 IP 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;마이크로서비스 아키텍처 지원&lt;/b&gt;: 서비스 간 통신 최적화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고가용성&lt;/b&gt;: 여러 가용 영역에 걸친 백엔드 분산&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비용 효율성&lt;/b&gt;: 외부 IP 사용료 없음&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE와 GCP Load Balancer의 차이점&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GCP에는 두 가지 주요 로드밸런싱 환경이 있다.&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Compute Engine 기반 Load Balancer&lt;/b&gt;: Terraform으로 직접 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GKE Ingress&lt;/b&gt;: Kubernetes 리소스로 관리되며 내부적으로 GCP Load Balancer 생성&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중요한 제약사항&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;GKE ManagedCertificate&lt;/b&gt;: 하나의 인증서당 하나의 도메인만 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;AWS ALB Ingress Group과 같은 기능은 GKE에 없음&lt;/b&gt;: 하나의 Ingress = 하나의 Load Balancer&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;여러 서비스를 하나의 Load Balancer로 처리하려면&lt;/b&gt;: 하나의 Ingress에서 여러 rule 정의 필요&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Ingress 실전 예제&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 운영 환경에서의 GKE Ingress 구성&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;bash&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 1. 각 도메인별 ManagedCertificate 생성
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: somaz-main-cert
spec:
  domains:
    - somaz.link

---
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: somaz-api-cert
spec:
  domains:
    - api.somaz.link

---
# 2. FrontendConfig (선택적 - 보안 헤더, 리다이렉트 등)
apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
  name: somaz-frontend-config
spec:
  redirectToHttps:
    enabled: true
    responseCodeName: MOVED_PERMANENTLY_DEFAULT
  sslPolicy: somaz-ssl-policy

---
# 3. 통합 Ingress 구성
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: somaz-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: &quot;somaz-gke-lb-ip&quot;
    networking.gke.io/managed-certificates: &quot;somaz-main-cert,somaz-api-cert&quot;
    kubernetes.io/ingress.class: &quot;gce&quot;
    networking.gke.io/v1beta1.FrontendConfig: &quot;somaz-frontend-config&quot;
    cloud.google.com/backend-config: '{&quot;default&quot;: &quot;somaz-backend-config&quot;}'
spec:
  rules:
  # 메인 웹사이트
  - host: somaz.link
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend-service
            port:
              number: 80
      - path: /static/*
        pathType: Prefix
        backend:
          service:
            name: static-service
            port:
              number: 80
  
  # API 서비스
  - host: api.somaz.link
    http:
      paths:
      - path: /v1/*
        pathType: Prefix
        backend:
          service:
            name: api-v1-service
            port:
              number: 8080
      - path: /v2/*
        pathType: Prefix
        backend:
          service:
            name: api-v2-service
            port:
              number: 8080
      - path: /health
        pathType: Exact
        backend:
          service:
            name: health-service
            port:
              number: 8080

---
# 4. BackendConfig for CDN and optimization
apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: somaz-backend-config
spec:
  cdn:
    enabled: true
    cachePolicy:
      includeHost: true
      includeProtocol: true
      includeQueryString: false
    negativeCaching: true
    negativeCachingPolicy:
    - code: 404
      ttl: 120
  connectionDraining:
    drainingTimeoutSec: 60
  healthCheck:
    checkIntervalSec: 10
    timeoutSec: 5
    healthyThreshold: 2
    unhealthyThreshold: 3
    type: HTTP
    requestPath: /health
    port: 8080&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Terraform으로 구현하는 GKE 지원 인프라&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Ingress를 위한 기반 인프라 구성&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# GKE Ingress에서 사용할 글로벌 정적 IP
resource &quot;google_compute_global_address&quot; &quot;gke_ingress_ip&quot; {
  name = &quot;somaz-gke-lb-ip&quot;
}

# SSL Policy 정의 (TLS 버전 및 암호화 설정)
resource &quot;google_compute_ssl_policy&quot; &quot;modern_tls&quot; {
  name    = &quot;somaz-ssl-policy&quot;
  profile = &quot;MODERN&quot;
  min_tls_version = &quot;TLS_1_2&quot;
}

# 출력 값으로 Kubernetes에서 사용할 정보 제공
output &quot;gke_ingress_ip&quot; {
  description = &quot;Static IP for GKE Ingress&quot;
  value       = google_compute_global_address.gke_ingress_ip.address
}

output &quot;ssl_policy_name&quot; {
  description = &quot;SSL Policy name for FrontendConfig&quot;
  value       = google_compute_ssl_policy.modern_tls.name
}
&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Compute Engine 기반 완전한 Load Balancer 구현&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;bash&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 글로벌 IP 주소
resource &quot;google_compute_global_address&quot; &quot;main_lb_ip&quot; {
  name = &quot;main-lb-global-ip&quot;
}

# SSL 인증서 (여러 도메인 지원)
resource &quot;google_compute_managed_ssl_certificate&quot; &quot;main_ssl_cert&quot; {
  name = &quot;main-ssl-certificate&quot;
  managed {
    domains = [
      &quot;example.com&quot;,
      &quot;www.example.com&quot;,
      &quot;api.example.com&quot;,
      &quot;admin.example.com&quot;
    ]
  }
}

# 인스턴스 그룹
resource &quot;google_compute_instance_group&quot; &quot;web_servers&quot; {
  name        = &quot;web-server-group&quot;
  description = &quot;Instance Group for web servers&quot;
  zone        = &quot;${var.region}-a&quot;
  instances   = [google_compute_instance.web_server.self_link]

  named_port {
    name = &quot;http&quot;
    port = 80
  }

  named_port {
    name = &quot;https&quot;
    port = 443
  }

  named_port {
    name = &quot;api&quot;
    port = 8080
  }
}

# Health Check for Web Service
resource &quot;google_compute_health_check&quot; &quot;web_health_check&quot; {
  name               = &quot;web-service-health-check&quot;
  check_interval_sec = 5
  timeout_sec        = 3
  healthy_threshold  = 2
  unhealthy_threshold = 3

  http_health_check {
    port         = 80
    request_path = &quot;/health&quot;
  }
}

# Health Check for API Service
resource &quot;google_compute_health_check&quot; &quot;api_health_check&quot; {
  name               = &quot;api-service-health-check&quot;
  check_interval_sec = 5
  timeout_sec        = 3
  healthy_threshold  = 2
  unhealthy_threshold = 3

  http_health_check {
    port         = 8080
    request_path = &quot;/api/health&quot;
  }
}

# Backend Service for Web
resource &quot;google_compute_backend_service&quot; &quot;web_backend_service&quot; {
  name        = &quot;web-backend-service&quot;
  description = &quot;Backend Service for Web Application&quot;
  protocol    = &quot;HTTP&quot;
  port_name   = &quot;http&quot;
  timeout_sec = 30

  backend {
    group = google_compute_instance_group.web_servers.self_link
  }

  health_checks = [google_compute_health_check.web_health_check.self_link]

  # CDN 활성화 (정적 콘텐츠용)
  enable_cdn = true
  cdn_policy {
    cache_mode  = &quot;CACHE_ALL_STATIC&quot;
    default_ttl = 3600
    max_ttl     = 86400
  }
}

# Backend Service for API
resource &quot;google_compute_backend_service&quot; &quot;api_backend_service&quot; {
  name        = &quot;api-backend-service&quot;
  description = &quot;Backend Service for API&quot;
  protocol    = &quot;HTTP&quot;
  port_name   = &quot;api&quot;
  timeout_sec = 30

  backend {
    group = google_compute_instance_group.web_servers.self_link
  }

  health_checks = [google_compute_health_check.api_health_check.self_link]

  # API는 CDN 비활성화
  enable_cdn = false
}

# URL Map (메인 라우팅 설정)
resource &quot;google_compute_url_map&quot; &quot;main_url_map&quot; {
  name            = &quot;main-url-map&quot;
  description     = &quot;Main URL map for multi-domain routing&quot;
  default_service = google_compute_backend_service.web_backend_service.self_link

  # API 도메인 라우팅
  host_rule {
    hosts        = [&quot;api.example.com&quot;]
    path_matcher = &quot;api-matcher&quot;
  }

  path_matcher {
    name            = &quot;api-matcher&quot;
    default_service = google_compute_backend_service.api_backend_service.self_link

    path_rule {
      paths   = [&quot;/v1/*&quot;]
      service = google_compute_backend_service.api_backend_service.self_link
    }

    path_rule {
      paths   = [&quot;/v2/*&quot;]
      service = google_compute_backend_service.api_backend_service.self_link
    }
  }

  # Admin 도메인 라우팅
  host_rule {
    hosts        = [&quot;admin.example.com&quot;]
    path_matcher = &quot;admin-matcher&quot;
  }

  path_matcher {
    name            = &quot;admin-matcher&quot;
    default_service = google_compute_backend_service.web_backend_service.self_link
  }

  depends_on = [
    google_compute_backend_service.web_backend_service,
    google_compute_backend_service.api_backend_service
  ]
}

# HTTPS Target Proxy
resource &quot;google_compute_target_https_proxy&quot; &quot;main_https_proxy&quot; {
  name             = &quot;main-https-proxy&quot;
  description      = &quot;HTTPS proxy for main load balancer&quot;
  url_map          = google_compute_url_map.main_url_map.self_link
  ssl_certificates = [google_compute_managed_ssl_certificate.main_ssl_cert.self_link]
}

# HTTPS Global Forwarding Rule
resource &quot;google_compute_global_forwarding_rule&quot; &quot;main_https_forwarding_rule&quot; {
  name       = &quot;main-https-forwarding-rule&quot;
  target     = google_compute_target_https_proxy.main_https_proxy.self_link
  ip_address = google_compute_global_address.main_lb_ip.address
  port_range = &quot;443&quot;
}

# HTTP to HTTPS Redirect URL Map
resource &quot;google_compute_url_map&quot; &quot;http_to_https_redirect&quot; {
  name = &quot;http-to-https-redirect&quot;
  
  default_url_redirect {
    https_redirect         = true
    redirect_response_code = &quot;MOVED_PERMANENTLY_DEFAULT&quot;
    strip_query           = false
  }
}

# HTTP Target Proxy
resource &quot;google_compute_target_http_proxy&quot; &quot;main_http_proxy&quot; {
  name    = &quot;main-http-proxy&quot;
  url_map = google_compute_url_map.http_to_https_redirect.self_link
}

# HTTP Global Forwarding Rule (리다이렉트용)
resource &quot;google_compute_global_forwarding_rule&quot; &quot;main_http_forwarding_rule&quot; {
  name       = &quot;main-http-forwarding-rule&quot;
  target     = google_compute_target_http_proxy.main_http_proxy.self_link
  ip_address = google_compute_global_address.main_lb_ip.address
  port_range = &quot;80&quot;
}

# 출력값
output &quot;load_balancer_ip&quot; {
  description = &quot;Load Balancer Global IP Address&quot;
  value       = google_compute_global_address.main_lb_ip.address
}

output &quot;ssl_certificate_status&quot; {
  description = &quot;SSL Certificate Status&quot;
  value       = google_compute_managed_ssl_certificate.main_ssl_cert.managed
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트러블슈팅 가이드&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 일반적인 문제와 해결책&lt;/span&gt;&lt;/h4&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 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ManagedCertificate가 Provisioning 상태에서 멈춤&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;vala&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# 문제 진단
kubectl describe managedcertificate &amp;lt;cert-name&amp;gt;

# 일반적인 원인:
# 1. DNS가 Load Balancer IP를 가리키지 않음
# 2. 도메인 소유권 확인 실패
# 3. Ingress에서 올바르게 참조되지 않음

# 해결:
# 1. DNS 설정 확인
nslookup your-domain.com

# 2. Ingress 어노테이션 확인
kubectl get ingress -o yaml
&lt;/code&gt;&lt;/pre&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Load Balancer가 생성되지 않음&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;vala&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# 이벤트 확인
kubectl describe ingress &amp;lt;ingress-name&amp;gt;

# 일반적인 원인:
# 1. 정적 IP가 다른 리소스에서 사용 중
# 2. 백엔드 서비스가 정상적이지 않음
# 3. Health Check 실패

# 해결:
# 1. 정적 IP 상태 확인
gcloud compute addresses list --global

# 2. 백엔드 서비스 상태 확인
kubectl get services
&lt;/code&gt;&lt;/pre&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Health Check 실패&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# Pod 상태 확인
kubectl get pods -o wide

# 서비스 상태 확인
kubectl describe service &amp;lt;service-name&amp;gt;

# Health Check 경로 테스트
kubectl exec -it &amp;lt;pod-name&amp;gt; -- curl localhost:8080/health
&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 성능 튜닝 팁&lt;/span&gt;&lt;/h4&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 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BackendConfig 최적화&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: performance-backend-config
spec:
  timeoutSec: 30
  connectionDraining:
    drainingTimeoutSec: 300
  sessionAffinity:
    affinityType: &quot;CLIENT_IP&quot;
    affinityCookieTtlSec: 3600
  healthCheck:
    checkIntervalSec: 5
    timeoutSec: 3
    healthyThreshold: 2
    unhealthyThreshold: 2
    type: HTTP
    requestPath: /health
    port: 8080
&lt;/code&gt;&lt;/pre&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CDN 캐시 최적화&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: cdn-optimized-config
spec:
  cdn:
    enabled: true
    cachePolicy:
      includeHost: true
      includeProtocol: true
      includeQueryString: false
      queryStringBlacklist: [&quot;utm_source&quot;, &quot;utm_medium&quot;, &quot;utm_campaign&quot;]
    negativeCaching: true
    negativeCachingPolicy:
    - code: 404
      ttl: 300
    - code: 500
      ttl: 60
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 전략&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GKE Ingress 비용 구조&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;Global Load Balancer: $18/월 (첫 5개 규칙)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추가 규칙: $7/월당&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 처리: $0.008/GB&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최적화 방법&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;# 하나의 Ingress에 여러 서비스 통합
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: unified-ingress
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /api/v1
        pathType: Prefix
        backend:
          service:
            name: api-v1-service
            port:
              number: 8080
      - path: /api/v2
        pathType: Prefix
        backend:
          service:
            name: api-v2-service
            port:
              number: 8080
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global vs Regional 로드밸런싱 전략&lt;/span&gt;&lt;/h3&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Global Load Balancing&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;글로벌 로드밸런싱은 전 세계 사용자에게 최적의 성능을 제공하기 위한 전략이다.&lt;/span&gt;&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;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;지연시간 최소화&lt;/b&gt;: 사용자와 가장 가까운 백엔드로 자동 라우팅&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;장애 조치&lt;/b&gt;: 리전 장애 시 자동으로 다른 리전으로 트래픽 전환&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스케일링&lt;/b&gt;: 글로벌 트래픽 증가에 유연하게 대응&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Regional Load Balancing&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리전별 로드밸런싱은 특정 지역에 집중된 사용자나 규정 준수 요구사항이 있는 경우에 적합하다.&lt;/span&gt;&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;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;적용 시나리오&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 주권 요구사항&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지역별 서비스 제공&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화 (특정 리전만 사용)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;내부 서비스 통신&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud CDN 통합 및 성능 최적화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud CDN 설정&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cloud CDN을 HTTP(S) Load Balancer와 연동하면 정적 콘텐츠의 전송 속도를 크게 향상시킬 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;nix&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;resource &quot;google_compute_backend_service&quot; &quot;website&quot; {
  name        = &quot;website-backend&quot;
  protocol    = &quot;HTTP&quot;
  timeout_sec = 10

  backend {
    group = google_compute_instance_group.web.id
  }

  health_checks = [google_compute_http_health_check.default.id]

  # Cloud CDN 활성화
  enable_cdn = true

  cdn_policy {
    cache_mode                   = &quot;CACHE_ALL_STATIC&quot;
    default_ttl                 = 3600
    max_ttl                     = 86400
    negative_caching            = true
    negative_caching_policy {
      code = 404
      ttl  = 120
    }
    
    # 캐시 키 설정
    cache_key_policy {
      include_host         = true
      include_protocol     = true
      include_query_string = false
      query_string_whitelist = [&quot;version&quot;, &quot;locale&quot;]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GCP의 로드밸런서는 각각 고유한 특성과 장점을 가지고 있어, 적절한 선택과 구성이 매우 중요하다. 특히 SSL 인증서 관리에서는 다음과 같은 선택지가 있다.&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Certificate Manager&lt;/b&gt;: 최신 방식으로 여러 도메인을 하나의 인증서에 포함 가능하며, DNS 승인을 통한 자동화된 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Compute Engine Managed SSL&lt;/b&gt;: Terraform으로 관리하기 쉽고 여러 도메인 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GKE ManagedCertificate&lt;/b&gt;: GKE 환경에서 간단하지만 도메인당 별도 인증서 필요&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 포인트&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;인증서 관리 전략:&lt;/b&gt; Certificate Manager를 활용하면 여러 도메인을 효율적으로 관리할 수 있으며, GKE에서는 도메인별 ManagedCertificate를 사용하거나 Certificate Manager를 통한 Certificate Map 방식을 선택할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;목적에 맞는 선택&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: 웹 애플리케이션에는 HTTP(S) Load Balancer, 고성능 TCP/UDP 서비스에는 Network Load Balancer, 내부 서비스 통신에는 Internal Load Balancer를 선택하자.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;글로벌 vs 리전별 전략&lt;/b&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&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Cloud CDN 활용&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: 정적 콘텐츠가 많은 서비스라면 Cloud CDN을 적극 활용하여 성능과 비용을 동시에 최적화하자.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;지속적인 모니터링&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: Cloud Monitoring을 통해 성능 지표를 추적하고, 임계값 기반 알림을 설정하여 문제를 사전에 예방하자.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비용 최적화&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: 백엔드 서비스 구성과 CDN 캐시 정책을 최적화하여 불필요한 비용을 절감하자.&lt;/span&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;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;color: #000000;&quot;&gt;GCP의 로드밸런서는 AWS와 달리 Ingress Group 같은 기능이 없어 하나의 Ingress가 하나의 Load Balancer를 생성하지만, Certificate Manager와 Certificate Map을 통해 복잡한 도메인 관리가 가능하다.&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;color: #000000;&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;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/load-balancing/docs&quot;&gt;GCP Load Balancing Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/certificate-manager/docs&quot;&gt;Certificate Manager Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/kubernetes-engine/docs/concepts/ingress&quot;&gt;GKE Ingress Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/cdn/docs&quot;&gt;Cloud CDN Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/architecture/best-practices-for-networking&quot;&gt;GCP Networking Best Practices&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://registry.terraform.io/providers/hashicorp/google/latest/docs&quot;&gt;Terraform Google Cloud Provider&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/kubernetes-engine/docs/how-to/managed-certs&quot;&gt;GKE ManagedCertificate Guide&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/monitoring/docs&quot;&gt;Cloud Monitoring Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/load-balancing/pricing&quot;&gt;GCP Load Balancer Pricing&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cloud.google.com/certificate-manager/docs/dns-authorizations&quot;&gt;Certificate Manager DNS Authorization Guide&lt;/a&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;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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>GCP</category>
      <category>GCP</category>
      <category>gcp loadbalancer</category>
      <category>gcp network</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/457</guid>
      <comments>https://somaz.tistory.com/457#entry457comment</comments>
      <pubDate>Thu, 8 Jan 2026 00:00:10 +0900</pubDate>
    </item>
    <item>
      <title>AWS EFS와 Kubernetes를 활용한 영구 스토리지 구축 가이드</title>
      <link>https://somaz.tistory.com/447</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS Elastic File System(EFS)은 확장 가능하고 완전 관리형 NFS 파일 시스템으로, 여러 EC2 인스턴스에서 동시에 접근할 수 있는 공유 스토리지를 제공한다. 특히 Kubernetes 환경에서는 여러 Pod가 동일한 데이터를 공유해야 하는 경우에 매우 유용하다.&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;color: #000000;&quot;&gt;본 글에서는 Terraform을 사용하여 EFS를 구성하고, Kubernetes에서 이를 활용하여 영구 스토리지를 구현하는 방법을 상세히 알아보겠다.&lt;/span&gt;&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-origin-width=&quot;2012&quot; data-origin-height=&quot;1098&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b60rKK/dJMcai21rbW/KFHSbTFPwTmJmgCTPIwVxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b60rKK/dJMcai21rbW/KFHSbTFPwTmJmgCTPIwVxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b60rKK/dJMcai21rbW/KFHSbTFPwTmJmgCTPIwVxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb60rKK%2FdJMcai21rbW%2FKFHSbTFPwTmJmgCTPIwVxk%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;2012&quot; height=&quot;1098&quot; data-origin-width=&quot;2012&quot; data-origin-height=&quot;1098&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  관련 글&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/37&quot;&gt;2022.02.13 - [AWS] - AWS IAM (Identity and Access Management) 개요 및 설정 방법&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/30&quot;&gt;2022.02.07 - [AWS] - AWS EC2 인스턴스 생성&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/38&quot;&gt;2022.02.13 - [AWS] - AWS S3 (Simple Storage Service) 개요 및 활용 방법&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/183&quot;&gt;2023.03.30 - [AWS] - AWS Secrets Manager란?(OAuth, SSO)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/182&quot;&gt;2023.03.29 - [AWS] - AWS CLI 정리&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/181&quot;&gt;2023.03.28 - [AWS] - AWS IAM이란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/180&quot;&gt;2023.03.28 - [AWS] - AWS S3 권한이란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/179&quot;&gt;2023.03.28 - [AWS] - AWS S3란?(개념, 속성)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/184&quot;&gt;2023.03.30 - [AWS] - AWS Cloudfront란? / Canary 및 Blue-Green 배포&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/188&quot;&gt;2023.04.03 - [AWS] - AWS VPC란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/238&quot;&gt;2023.05.26 - [AWS] - AWS IRSA(IAM Roles for Service Accounts)란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/340&quot;&gt;2024.11.07 - [AWS] - AWS Ingress Annotations 정리&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/337&quot;&gt;2024.11.04 - [AWS] - AWS Assume Role이란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/349&quot;&gt;2024.11.16 - [AWS] - AWS Network ACL vs Security Group&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/354&quot;&gt;2024.11.21 - [AWS] - ALB access Log 활성화 &amp;rarr; S3 권한 설정 및 로그 저장&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/357&quot;&gt;2024.11.24 - [AWS] - EKS Pod Identity Addon&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/360&quot;&gt;2024.11.27 - [AWS] - AWS DynamoDB란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/364&quot;&gt;2025.01.03 - [AWS] - AWS DynamoDB Local 설치&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000; text-align: start;&quot; href=&quot;https://somaz.tistory.com/447&quot;&gt;2025.09.02 - [AWS] - AWS EFS와 Kubernetes를 활용한 영구 스토리지 구축 가이드&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/452&quot;&gt;2025.09.05 - [AWS] - AWS CDN 구축 가이드: Kubernetes + AWS CloudFront로 API와 정적 파일 서빙 최적화&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/453&quot;&gt;2025.09.05 - [AWS] - AWS 네트워크 연결 방식 완전 비교: VPC Peering vs Transit Gateway vs VPN&lt;/a&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EFS란?&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Amazon Elastic File System(EFS)은 AWS에서 제공하는 완전 관리형 NFS(Network File System) 서비스이다. 전통적인 온프레미스 환경에서 사용되던 네트워크 스토리지의 클라우드 버전으로 이해할 수 있다.&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;&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;color: #000000;&quot;&gt;EFS vs 다른 AWS 스토리지 서비스&lt;/span&gt;&lt;/h3&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EFS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EBS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;S3&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;접근 방식&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 파일 시스템&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;블록 스토리지&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;객체 스토리지&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동시 접근&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다중 인스턴스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단일 인스턴스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API 기반&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용 사례&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;공유 파일 스토리지&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영체제, 데이터베이스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;백업, 아카이브, 웹 자산&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;확장성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 확장&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수동 확장&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;언제 EFS를 사용해야 할까?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;적합한 사용 사례&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;컨테이너 환경&lt;/b&gt;: 여러 Pod/Container가 동일한 설정 파일이나 데이터를 공유해야 하는 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;콘텐츠 관리&lt;/b&gt;: 웹 서버들이 공통의 미디어 파일이나 정적 콘텐츠를 서빙하는 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;데이터 분석&lt;/b&gt;: 여러 분석 작업자가 동일한 데이터셋에 동시 접근이 필요한 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;백업 및 아카이빙&lt;/b&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;부적합한 사용 사례&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;고성능 데이터베이스&lt;/b&gt;: 낮은 지연시간이 중요한 OLTP 데이터베이스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;임시 스토리지&lt;/b&gt;: 인스턴스 생명주기와 함께하는 임시 데이터&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;단일 접근 워크로드&lt;/b&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;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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EFS와 Access Point의 이해&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;EFS의 주요 특징&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;확장성&lt;/b&gt;: 자동으로 용량이 확장되며, 페타바이트 규모까지 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고가용성&lt;/b&gt;: 여러 가용 영역에 걸쳐 자동으로 복제&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안&lt;/b&gt;: KMS를 통한 저장 데이터 암호화 및 전송 중 암호화 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;성능&lt;/b&gt;: General Purpose와 Max I/O 성능 모드 제공&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Access Point의 역할&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Access Point는 EFS 파일 시스템에 대한 애플리케이션별 진입점을 제공한다. &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;color: #000000;&quot;&gt;각 Access Point는&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특정 디렉토리 경로를 루트로 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;POSIX 사용자 및 그룹 권한 적용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&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;color: #000000;&quot;&gt;Terraform을 이용한 EFS 구성&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다음은 게임 서버 환경을 위한 EFS 구성 예시이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756790452286&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# KMS 키 생성 (EFS 저장 데이터 암호화용)
resource &quot;aws_kms_key&quot; &quot;gameserver_efs_key&quot; {
  description             = &quot;KMS key for beta-gameserver-efs encryption&quot;
  deletion_window_in_days = 7

  tags = {
    Environment = var.environment
    Terraform   = var.terraform
  }
}

resource &quot;aws_kms_alias&quot; &quot;gameserver_efs_key_alias&quot; {
  name          = &quot;alias/beta-gameserver-efs&quot;
  target_key_id = aws_kms_key.gameserver_efs_key.id
}

# EFS 파일 시스템 생성
module &quot;beta_gameserver_efs&quot; {
  source = &quot;terraform-aws-modules/efs/aws&quot;

  # File system
  name           = var.beta_gameserver_efs
  creation_token = &quot;beta-gameserver-efs-token&quot;
  encrypted      = true
  kms_key_arn    = aws_kms_key.gameserver_efs_key.arn

  # 성능 및 처리량 모드
  performance_mode = &quot;generalPurpose&quot;
  throughput_mode  = &quot;provisioned&quot;
  provisioned_throughput_in_mibps = 100

  # 파일 시스템 정책
  attach_policy                      = true
  bypass_policy_lockout_safety_check = false
  policy_statements = [
    {
      sid = &quot;BetaGameServerAccess&quot;
      actions = [
        &quot;elasticfilesystem:ClientMount&quot;,
        &quot;elasticfilesystem:ClientWrite&quot;,
        &quot;elasticfilesystem:ClientRootAccess&quot;
      ]
      principals = [
        {
          type        = &quot;AWS&quot;
          identifiers = [&quot;arn:aws:iam::${data.aws_caller_identity.current.account_id}:root&quot;]
        }
      ]
    }
  ]

  # 마운트 타겟 - 다중 가용 영역 구성
  mount_targets = {
    &quot;ap-northeast-2a&quot; = {
      subnet_id       = &quot;subnet-0a1b2c3d4e5f6789a&quot;
      security_groups = [&quot;sg-0123456789abcdef0&quot;]
    }
    &quot;ap-northeast-2b&quot; = {
      subnet_id       = &quot;subnet-0b2c3d4e5f6789abc&quot;
      security_groups = [&quot;sg-0123456789abcdef0&quot;]
    }
    &quot;ap-northeast-2c&quot; = {
      subnet_id       = &quot;subnet-0c3d4e5f6789abcde&quot;
      security_groups = [&quot;sg-0123456789abcdef0&quot;]
    }
  }

  # Access Points 구성
  access_points = {
    # 서버 설정 파일용 Access Point
    server_config = {
      name = &quot;beta-gameserver-config&quot;
      posix_user = {
        gid = 2000
        uid = 2000
      }
      root_directory = {
        path = &quot;/server/config&quot;
        creation_info = {
          owner_gid   = 2000
          owner_uid   = 2000
          permissions = &quot;755&quot;
        }
      }
      tags = {
        Purpose     = &quot;Server configuration directory&quot;
        Component   = &quot;server-config&quot;
        Environment = var.environment
      }
    }
    
    # 게임 자산 파일용 Access Point
    game_assets = {
      name = &quot;beta-gameserver-assets&quot;
      posix_user = {
        gid = 2000
        uid = 2000
      }
      root_directory = {
        path = &quot;/server/assets&quot;
        creation_info = {
          owner_gid   = 2000
          owner_uid   = 2000
          permissions = &quot;755&quot;
        }
      }
      tags = {
        Purpose     = &quot;Game assets directory&quot;
        Component   = &quot;game-assets&quot;
        Environment = var.environment
      }
    }
    
    # 플레이어 데이터용 Access Point
    player_data = {
      name = &quot;beta-gameserver-playerdata&quot;
      posix_user = {
        gid = 2000
        uid = 2000
      }
      root_directory = {
        path = &quot;/server/playerdata&quot;
        creation_info = {
          owner_gid   = 2000
          owner_uid   = 2000
          permissions = &quot;750&quot;
        }
      }
      tags = {
        Purpose     = &quot;Player data directory&quot;
        Component   = &quot;player-data&quot;
        Environment = var.environment
      }
    }
  }

  # 백업 정책 활성화
  enable_backup_policy = true

  tags = {
    Environment = var.environment
    Project     = var.project
    Terraform   = var.terraform
    Name        = var.beta_gameserver_efs
  }
}&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;&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;
&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;color: #000000;&quot;&gt;Kubernetes에서 EFS 사용하기&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PersistentVolume과 PersistentVolumeClaim 구성&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1756790489805&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: PersistentVolume
metadata:
  name: beta-gameserver-mysql-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: efs-sc
  csi:
    driver: efs.csi.aws.com
    volumeHandle: fs-0e63cfa4272bcd819::fsap-0a1b2c3d4e5f67890
    volumeAttributes:
      path: &quot;/mysql-data&quot;
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: beta-gameserver-mysql-pvc
  namespace: gameserver
spec:
  storageClassName: efs-sc
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  volumeName: beta-gameserver-mysql-pv&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MySQL Deployment 예시&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1756790508219&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Service
metadata:
  name: beta-gameserver-mysql
  namespace: gameserver
spec:
  type: ClusterIP
  ports:
  - port: 3306
    targetPort: 3306
    protocol: TCP
  selector:
    app: beta-gameserver-mysql
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: beta-gameserver-mysql
  namespace: gameserver
  labels:
    app: beta-gameserver-mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: beta-gameserver-mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: beta-gameserver-mysql
    spec:
      nodeSelector:
        eks.amazonaws.com/nodegroup: GameServerNodeGroup-MainNodes
      containers:
        - image: mysql:8.0
          name: mysql
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secrets
                  key: root-password
            - name: MYSQL_DATABASE
              value: gameserver_db
          ports:
            - containerPort: 3306
              protocol: TCP
              name: mysql
          resources:
            requests:
              cpu: 200m
              memory: 512Mi
            limits:
              cpu: 1000m
              memory: 2048Mi
          volumeMounts:
            - name: mysql-storage
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-storage
          persistentVolumeClaim:
            claimName: beta-gameserver-mysql-pvc&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&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;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;color: #000000;&quot;&gt;volumeAttributes.path와 Access Point 활용&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;volumeHandle 구성 방식&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;volumeHandle은 다음과 같은 형태로 구성된다.&lt;/span&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;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;기본 형태&lt;/b&gt;: `fs-xxxxxxxxx`&lt;/span&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;color: #000000;&quot;&gt;EFS 파일 시스템 ID만 지정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파일 시스템의 루트 디렉토리에 접근&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Access Point 사용&lt;/b&gt;: `fs-xxxxxxxxx::fsap-yyyyyyyy`&lt;/span&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;color: #000000;&quot;&gt;EFS 파일 시스템 ID와 Access Point ID를 함께 지정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Access Point에서 정의한 특정 디렉토리로 루트 경로가 제한됨&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;volumeAttributes.path의 역할&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`volumeAttributes.path` 는 EFS 파일 시스템 내에서 마운트할 특정 경로를 지정&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756790903920&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;csi:
  driver: efs.csi.aws.com
  volumeHandle: fs-0e63cfa4272bcd819  
  volumeAttributes:
    path: &quot;/mysql-data&quot;  # EFS 내의 /mysql-data 디렉토리를 마운트&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Access Point vs volumeAttributes.path&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;Access Point 사용 시&lt;/b&gt;: 보다 강력한 보안 및 권한 제어 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;volumeAttributes.path 사용 시&lt;/b&gt;: 단순한 경로 지정, 유연성 높음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;조합 사용&lt;/b&gt;: Access Point로 기본 권한 설정 후, path로 세부 디렉토리 지정&lt;/span&gt;&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;&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;color: #000000;&quot;&gt;실제 사용 예시&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1756791020729&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Access Point를 활용한 보안 강화 방식
apiVersion: v1
kind: PersistentVolume
metadata:
  name: secure-data-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteMany
  csi:
    driver: efs.csi.aws.com
    volumeHandle: fs-0e63cfa4272bcd819::fsap-0a1b2c3d4e5f67890  # Access Point 사용
    # volumeAttributes.path는 생략 (Access Point에서 경로 제어)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1756791836039&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 단순 경로 지정 방식
apiVersion: v1
kind: PersistentVolume
metadata:
  name: shared-logs-pv
spec:
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteMany
  csi:
    driver: efs.csi.aws.com
    volumeHandle: fs-0e63cfa4272bcd819  # 파일 시스템 ID만 사용
    volumeAttributes:
      path: &quot;/shared/logs&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 및 최적화 고려사항&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 설정&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;KMS를 통한 저장 데이터 암호화 활성화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전송 중 암호화(TLS) 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IAM 정책을 통한 세밀한 접근 제어&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Security Group을 통한 네트워크 접근 제한&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 최적화&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;적절한 성능 모드 선택 (General Purpose vs Max I/O)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Throughput 모드 설정 (Bursting vs Provisioned)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비용 최적화&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;Storage Class 설정 (Standard vs Infrequent Access)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;백업 정책 적절한 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용하지 않는 Access Point 정리&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AWS EFS와 Kubernetes를 함께 활용하면 확장 가능하고 안정적인 영구 스토리지 솔루션을 구축할 수 있다. 특히 Access Point 기능을 활용하면 애플리케이션별로 격리된 환경을 제공하면서도 강력한 보안 제어가 가능하다.&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;color: #000000;&quot;&gt;본 글에서 소개한 구성을 통해 여러분의 Kubernetes 환경에서도 안정적이고 확장 가능한 스토리지 인프라를 구축하시기 바란다.&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;color: #000000;&quot;&gt;`volumeAttributes.path` 와 Access Point의 적절한 조합을 통해 보안과 유연성을 모두 확보할 수 있을 것이다.&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;color: #000000;&quot;&gt;EFS는 단순한 파일 공유를 넘어서, 현대적인 컨테이너 환경에서 필수적인 데이터 관리 솔루션으로 자리잡고 있습니다. 지속적인 모니터링과 최적화를 통해 더욱 효율적인 운영이 가능할 것이다.&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/efs/latest/ug/whatisefs.html&quot;&gt;Amazon EFS 사용 설명서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/efs-csi.html&quot;&gt;Amazon EFS CSI 드라이버&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/efs/latest/ug/performance.html&quot;&gt;EFS 성능 모드 선택 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.aws.amazon.com/efs/latest/ug/security-considerations.html&quot;&gt;EFS 보안 모범 사례&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_file_system&quot;&gt;AWS Provider - EFS Resource&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_access_point&quot;&gt;AWS Provider - EFS Access Point&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_mount_target&quot;&gt;AWS Provider - EFS Mount Target&lt;/a&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>AWS</category>
      <category>AWS</category>
      <category>AWS EFS</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/447</guid>
      <comments>https://somaz.tistory.com/447#entry447comment</comments>
      <pubDate>Tue, 6 Jan 2026 00:00:01 +0900</pubDate>
    </item>
    <item>
      <title>Python TypeVar와 제네릭, 제대로 알고 쓰자</title>
      <link>https://somaz.tistory.com/472</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Python 코드를 작성하다 보면 `TypeVar('T')` 나 `Generic[T]` 를 사용하게 된다.&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;color: #000000;&quot;&gt;코드를 복사해서 쓰긴 하는데, 정확히 뭘 하는 건지 모르겠다면?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 글에서 TypeVar와 제네릭의 개념부터 실전 활용까지 완벽하게 정리한다.&lt;/span&gt;&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-origin-width=&quot;2238&quot; data-origin-height=&quot;1272&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/G8HOF/dJMb9PGp0Hf/Hi2tGbNkbMUWUDLj0euMJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/G8HOF/dJMb9PGp0Hf/Hi2tGbNkbMUWUDLj0euMJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/G8HOF/dJMb9PGp0Hf/Hi2tGbNkbMUWUDLj0euMJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FG8HOF%2FdJMb9PGp0Hf%2FHi2tGbNkbMUWUDLj0euMJK%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;2238&quot; height=&quot;1272&quot; data-origin-width=&quot;2238&quot; data-origin-height=&quot;1272&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;color: #000000;&quot;&gt;TypeVar란 무엇인가?&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 개념&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;julia&quot;&gt;&lt;code&gt;from typing import TypeVar

T = TypeVar('T')
&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;TypeVar는 &quot;제네릭 타입 변수&quot;를 선언하는 것이다.&lt;/b&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;color: #000000;&quot;&gt;쉽게 말하면&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;T는 &quot;어떤 타입이든 될 수 있는&quot; 플레이스홀더&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용할 때 구체적인 타입이 결정됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;제네릭이 필요한 이유&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제 상황: 타입이 불명확한 코드&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 제네릭 없이
class ProcessResult:
    def __init__(self, data, success: bool):
        self.data = data  # 타입이 뭔지 모름
        self.success = success

result = ProcessResult([1, 2, 3], True)
# IDE가 result.data의 타입을 알 수 없음
# 자동완성 안됨, 타입 체크 불가능&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;문제점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;data가 무슨 타입인지 알 수 없음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IDE 자동완성 지원 안됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해결책: 제네릭 사용&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 제네릭 사용
from typing import Generic, TypeVar

T = TypeVar('T')

class ProcessResult(Generic[T]):
    def __init__(self, data: T, success: bool):
        self.data: T = data
        self.success = success

# 사용 시 타입 지정
result: ProcessResult[list[int]] = ProcessResult([1, 2, 3], True)
# IDE가 result.data가 list[int]인 걸 인식!
# 자동완성 지원, 타입 체크 가능&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;타입 안정성 확보&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IDE 자동완성 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드 가독성 향상&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;실전 활용 예시&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 기본 사용법&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;from typing import Generic, TypeVar

T = TypeVar('T')

class Box(Generic[T]):
    def __init__(self, content: T):
        self.content: T = content
    
    def get(self) -&amp;gt; T:
        return self.content

# 사용 예시
int_box: Box[int] = Box(123)
str_box: Box[str] = Box(&quot;Hello&quot;)
list_box: Box[list[str]] = Box([&quot;a&quot;, &quot;b&quot;, &quot;c&quot;])

print(int_box.get())  # 123 (타입: int)
print(str_box.get())  # &quot;Hello&quot; (타입: str)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 여러 타입 변수 사용&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;from typing import Generic, TypeVar

K = TypeVar('K')
V = TypeVar('V')

class KeyValuePair(Generic[K, V]):
    def __init__(self, key: K, value: V):
        self.key = key
        self.value = value

# 사용 예시
pair1: KeyValuePair[str, int] = KeyValuePair(&quot;age&quot;, 25)
pair2: KeyValuePair[int, list[str]] = KeyValuePair(1, [&quot;a&quot;, &quot;b&quot;])
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 제약이 있는 TypeVar&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;from typing import TypeVar

# 숫자 타입만 허용
T = TypeVar('T', int, float)

def add(a: T, b: T) -&amp;gt; T:
    return a + b

result1 = add(1, 2)        # ✅ OK (int)
result2 = add(1.5, 2.5)    # ✅ OK (float)
# result3 = add(&quot;a&quot;, &quot;b&quot;)  # ❌ 에러 (str은 허용 안됨)
&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;&lt;/h2&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;color: #000000;&quot;&gt;비교 분석: Any vs Generic&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시나리오 1: Any 사용&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;from typing import Any

class Container:
    def __init__(self, value: Any):
        self.value = value
    
    def get(self) -&amp;gt; Any:
        return self.value

container = Container(123)
result = container.get()
# IDE: result의 타입을 알 수 없음 (Any)
# result.upper()  # 런타임 에러!
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시나리오 2: Generic 사용&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;from typing import Generic, TypeVar

T = TypeVar('T')

class Container(Generic[T]):
    def __init__(self, value: T):
        self.value = value
    
    def get(self) -&amp;gt; T:
        return self.value

container: Container[int] = Container(123)
result = container.get()
# IDE: result가 int임을 정확히 인식
# result.upper()  # IDE가 미리 경고!
&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비교표&lt;/b&gt;&lt;/span&gt;&lt;/p&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Any&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Generic[T]&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;타입 안정성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;강력함&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IDE 자동완성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;불가능&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완벽 지원&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;타입 체크&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;불가능&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;유연성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매우 높음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제한적&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;권장 용도&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;레거시 코드&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;신규 코드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;흔한 실수와 해결법&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실수 1: TypeVar 선언만 하고 활용 안함&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 잘못된 사용
T = TypeVar('T')

class ProcessResult:  # Generic[T] 빠짐!
    def __init__(self, data: T, success: bool):
        self.data = data
        self.success = success

# 제네릭이 작동 안함!&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;올바른 사용&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 올바른 사용
T = TypeVar('T')

class ProcessResult(Generic[T]):  # Generic[T] 상속!
    def __init__(self, data: T, success: bool):
        self.data: T = data
        self.success = success&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실수 2: 타입 힌트 생략&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 타입 힌트 없음
def process(data):
    result = ProcessResult(data, True)
    return result

# 타입 힌트 명시
def process(data: T) -&amp;gt; ProcessResult[T]:
    result = ProcessResult(data, True)
    return result&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실수 3: 여러 TypeVar를 섞어서 사용&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 잘못된 사용
T = TypeVar('T')
U = TypeVar('U')

class Wrong(Generic[T]):
    def method(self, value: U) -&amp;gt; U:  # U는 클래스 레벨에 없음!
        return value

# 올바른 사용
class Correct(Generic[T, U]):
    def method(self, value: U) -&amp;gt; U:
        return value&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;&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;
&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;color: #000000;&quot;&gt;실무 활용 사례&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API 응답 래퍼&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;from typing import Generic, TypeVar, Optional

T = TypeVar('T')

class ApiResponse(Generic[T]):
    def __init__(
        self,
        data: Optional[T] = None,
        error: Optional[str] = None,
        status_code: int = 200
    ):
        self.data = data
        self.error = error
        self.status_code = status_code
    
    def is_success(self) -&amp;gt; bool:
        return self.error is None and self.data is not None

# 사용 예시
class User:
    def __init__(self, id: int, name: str):
        self.id = id
        self.name = name

def get_user(user_id: int) -&amp;gt; ApiResponse[User]:
    # API 호출
    user = User(user_id, &quot;홍길동&quot;)
    return ApiResponse(data=user, status_code=200)

response = get_user(123)
if response.is_success():
    user = response.data  # 타입: Optional[User]
    print(user.name)  # IDE가 User 타입임을 인식!
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 캐시 구현&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;from typing import Generic, TypeVar, Dict, Optional
from datetime import datetime, timedelta

K = TypeVar('K')
V = TypeVar('V')

class Cache(Generic[K, V]):
    def __init__(self, ttl_seconds: int = 300):
        self._cache: Dict[K, tuple[V, datetime]] = {}
        self._ttl = timedelta(seconds=ttl_seconds)
    
    def set(self, key: K, value: V) -&amp;gt; None:
        self._cache[key] = (value, datetime.now())
    
    def get(self, key: K) -&amp;gt; Optional[V]:
        if key not in self._cache:
            return None
        
        value, timestamp = self._cache[key]
        if datetime.now() - timestamp &amp;gt; self._ttl:
            del self._cache[key]
            return None
        
        return value

# 사용 예시
user_cache: Cache[int, User] = Cache(ttl_seconds=600)
user_cache.set(123, User(123, &quot;홍길동&quot;))

user = user_cache.get(123)  # 타입: Optional[User]
if user:
    print(user.name)
&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;&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;
&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;color: #000000;&quot;&gt;TypeVar 고급 기능&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. bound 파라미터&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;from typing import TypeVar

# T는 반드시 Number의 서브클래스여야 함
class Number:
    def __init__(self, value: float):
        self.value = value

T = TypeVar('T', bound=Number)

def double(n: T) -&amp;gt; T:
    n.value *= 2
    return n
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. covariant와 contravariant&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;from typing import TypeVar

# covariant: 서브타입 관계 유지
T_co = TypeVar('T_co', covariant=True)

# contravariant: 서브타입 관계 역전
T_contra = TypeVar('T_contra', contravariant=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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;요약 및 체크리스트&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 요약&amp;nbsp;&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;T&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;어떤 타입이든 될 수 있는&quot; 플레이스홀더&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TypeVar('T')&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;제네릭 타입 변수 선언&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Generic[T]&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클래스를 제네릭으로 만듦&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;목적&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;타입 안정성 + 재사용성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;효과&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IDE 자동완성, 타입 체크&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용 전 체크리스트&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;TypeVar를 선언했는가?&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;T = TypeVar('T')
&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;span style=&quot;color: #000000;&quot;&gt;Generic[T]를 상속했는가?&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;class MyClass(Generic[T]):
&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;span style=&quot;color: #000000;&quot;&gt;타입 힌트를 명시했는가?&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;def __init__(self, data: T):
    self.data: T = data
&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;span style=&quot;color: #000000;&quot;&gt;사용 시 타입을 지정했는가?&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;isbl&quot;&gt;&lt;code&gt;result: MyClass[int] = MyClass(123)
&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;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결론&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TypeVar와 제네릭은 Python의 타입 시스템을 강력하게 만드는 핵심 도구이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;언제 사용해야 하나?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 타입을 다루는 컨테이너 클래스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;API 응답 래퍼&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;캐시, 큐 등 자료구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;사용의 이점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;타입 안정성 확보&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IDE 지원 최대화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드 가독성 향상&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.python.org/3/library/typing.html&quot;&gt;https://docs.python.org/3/library/typing.html&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://typing.python.org/en/latest/reference/generics.html&quot;&gt;https://typing.python.org/en/latest/reference/generics.html&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://mypy.readthedocs.io/en/stable/generics.html&quot;&gt;https://mypy.readthedocs.io/en/stable/generics.html&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://medium.com/pythoneers/understanding-typevar-in-python-f78e5108471d&quot;&gt;https://medium.com/pythoneers/understanding-typevar-in-python-f78e5108471d&lt;/a&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;&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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>Launguage</category>
      <category>Python</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/472</guid>
      <comments>https://somaz.tistory.com/472#entry472comment</comments>
      <pubDate>Fri, 2 Jan 2026 00:00:29 +0900</pubDate>
    </item>
    <item>
      <title>Apache Spark: 대용량 데이터를 위한 분산 처리 프레임워크</title>
      <link>https://somaz.tistory.com/433</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오늘날 기업과 서비스는 &lt;b&gt;초당 수천~수백만 건의 로그, 이벤트, 거래 데이터&lt;/b&gt;를 실시간으로 처리하고 분석해야 한다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이런 대용량 데이터를 기존 방식으로 처리하는 데에는 &lt;b&gt;속도, 유연성, 통합성의 한계&lt;/b&gt;가 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;305&quot; data-start=&quot;266&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 문제를 해결하고자 등장한 것이 &lt;b&gt;Apache Spark&lt;/b&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;475&quot; data-start=&quot;307&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Apache Spark는 대용량 데이터를 &lt;b&gt;메모리 기반으로 빠르게 처리&lt;/b&gt;할 수 있도록 설계된 &lt;b&gt;오픈소스 분산 처리 프레임워크&lt;/b&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;475&quot; data-start=&quot;307&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;475&quot; data-start=&quot;307&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단순히 배치 처리에 그치지 않고, &lt;b&gt;실시간 스트리밍, 머신러닝, SQL 분석까지 하나의 플랫폼에서 통합적으로&lt;/b&gt; 처리할 수 있는 것이 가장 큰 장점이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;475&quot; data-start=&quot;307&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;543&quot; data-start=&quot;477&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 글에서는 Spark의 개념부터 아키텍처, 실습 환경, Hadoop과의 비교, 실전 활용 사례까지 폭넓게 소개한다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-end=&quot;590&quot; data-start=&quot;545&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;590&quot; data-start=&quot;547&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;ldquo;데이터가 많다고 느껴지는 순간, Spark는 분명 도움이 되는 도구이다.&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m0Ou0/dJMcaioreKc/IiASqLUdWFBXK7s7HfOR51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m0Ou0/dJMcaioreKc/IiASqLUdWFBXK7s7HfOR51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m0Ou0/dJMcaioreKc/IiASqLUdWFBXK7s7HfOR51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm0Ou0%2FdJMcaioreKc%2FIiASqLUdWFBXK7s7HfOR51%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;331&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;225&quot; data-start=&quot;205&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Apache Spark란?&lt;/span&gt;&lt;/h2&gt;
&lt;p data-end=&quot;374&quot; data-start=&quot;227&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Apache Spark는 &lt;b&gt;대용량 데이터를 빠르게 처리하기 위한 오픈소스 분산 처리 프레임워크&lt;/b&gt;이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 Hadoop MapReduce보다 &lt;b&gt;메모리 기반 처리(in-memory computation)&lt;/b&gt; 방식으로 훨씬 빠르고 유연한 분석이 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-end=&quot;446&quot; data-start=&quot;376&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;446&quot; data-start=&quot;378&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;ldquo;데이터를 나누고 동시에 처리한다&amp;rdquo;는 분산 처리의 핵심을 유지하면서도, 훨씬 더 직관적인 API와 높은 성능을 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;
&lt;h2 data-end=&quot;473&quot; data-start=&quot;453&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spark의 핵심 구성요소&lt;/span&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;890&quot; data-start=&quot;475&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컴포넌트&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;603&quot; data-start=&quot;521&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;563&quot; data-start=&quot;521&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;RDD (Resilient Distributed Dataset)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;603&quot; data-start=&quot;563&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;불변(immutable)한 분산 컬렉션. Spark의 기본 단위.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;673&quot; data-start=&quot;604&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;630&quot; data-start=&quot;604&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;DataFrame / Dataset&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;673&quot; data-start=&quot;630&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;RDD보다 더 높은 추상화. SQL처럼 다룰 수 있고 최적화도 잘 됨.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;726&quot; data-start=&quot;674&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;690&quot; data-start=&quot;674&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Spark SQL&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;726&quot; data-start=&quot;690&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SQL 문법으로 데이터 분석 가능. Hive 연동도 지원.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;787&quot; data-start=&quot;727&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;749&quot; data-start=&quot;727&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Spark Streaming&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;787&quot; data-start=&quot;749&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실시간 데이터 스트리밍 처리. Kafka와 자주 함께 사용됨.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;825&quot; data-start=&quot;788&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;800&quot; data-start=&quot;788&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;MLlib&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;825&quot; data-start=&quot;800&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;머신러닝 라이브러리. 분산 학습 지원.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;890&quot; data-start=&quot;826&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;839&quot; data-start=&quot;826&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GraphX&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;890&quot; data-start=&quot;839&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래프 처리용 API. Social Graph, Recommendation 등에 활용&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;&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;color: #000000;&quot;&gt;Spark 아키텍처 이해&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spark 애플리케이션은 &lt;b&gt;Driver&lt;/b&gt;와 여러 &lt;b&gt;Executor&lt;/b&gt;로 구성된다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1211&quot; data-start=&quot;1062&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1103&quot; data-start=&quot;1062&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Driver&lt;/b&gt;: 애플리케이션의 실행 계획(DAG)을 생성하고 관리&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1138&quot; data-start=&quot;1104&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Executor&lt;/b&gt;: 실제 데이터를 계산하는 워커 노드&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1211&quot; data-start=&quot;1139&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Cluster Manager&lt;/b&gt;: 자원 할당을 담당 (YARN, Mesos, Standalone, Kubernetes 등)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-end=&quot;1292&quot; data-start=&quot;1213&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;1292&quot; data-start=&quot;1215&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spark는 Lazy Evaluation을 통해 최적화된 DAG를 구성한 뒤 실행하므로 불필요한 작업을 줄이고 성능을 향상시킨다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;
&lt;h2 data-end=&quot;1332&quot; data-start=&quot;1299&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spark vs Hadoop: 왜 Spark인가?&lt;/span&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;1608&quot; data-start=&quot;1334&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Hadoop MapReduce&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Apache Spark&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1455&quot; data-start=&quot;1418&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1426&quot; data-start=&quot;1418&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처리 방식&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1440&quot; data-start=&quot;1426&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;디스크 기반 (느림)&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1455&quot; data-start=&quot;1440&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메모리 기반 (빠름)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1517&quot; data-start=&quot;1456&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1465&quot; data-start=&quot;1456&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드 복잡도&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1485&quot; data-start=&quot;1465&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Map, Reduce 직접 구현&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1517&quot; data-start=&quot;1485&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SQL, DataFrame, 함수 기반 간결한 코드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1568&quot; data-start=&quot;1518&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1528&quot; data-start=&quot;1518&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스트리밍 지원&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1540&quot; data-start=&quot;1528&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부 시스템 필요&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1568&quot; data-start=&quot;1540&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;내장된 Structured Streaming&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1608&quot; data-start=&quot;1569&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1579&quot; data-start=&quot;1569&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;머신러닝 지원&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1596&quot; data-start=&quot;1579&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Mahout 등 외부 연동&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1608&quot; data-start=&quot;1596&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MLlib 내장&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&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;
&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spark 실습 환경&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로컬 설치&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1750387625477&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Spark 설치 및 실행
wget https://downloads.apache.org/spark/spark-4.0.0/spark-4.0.0-bin-hadoop3.tgz
tar -xzf spark-4.0.0-bin-hadoop3.tgz
cd spark-4.0.0-bin-hadoop3
./bin/spark-shell&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라우드 환경&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;Databricks&lt;/b&gt;: 가장 인기 있는 Spark 관리형 서비스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;AWS EMR&lt;/b&gt;: Amazon의 Hadoop/Spark 클러스터 서비스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Google Dataproc&lt;/b&gt;: Google Cloud의 Spark 서비스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Azure HDInsight&lt;/b&gt;: Microsoft의 빅데이터 플랫폼&lt;/span&gt;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spark 실전 코드 예제&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PySpark 기본 예제&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1755579978568&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from pyspark.sql import SparkSession
from pyspark.sql.functions import col, count, avg

# SparkSession 생성
spark = SparkSession.builder \
    .appName(&quot;DataAnalysis&quot;) \
    .config(&quot;spark.sql.adaptive.enabled&quot;, &quot;true&quot;) \
    .getOrCreate()

# 데이터 읽기
df = spark.read.option(&quot;header&quot;, &quot;true&quot;).csv(&quot;sales_data.csv&quot;)

# 기본 분석
df.select(&quot;product_category&quot;, &quot;sales_amount&quot;) \
  .groupBy(&quot;product_category&quot;) \
  .agg(count(&quot;*&quot;).alias(&quot;count&quot;), avg(&quot;sales_amount&quot;).alias(&quot;avg_sales&quot;)) \
  .orderBy(col(&quot;avg_sales&quot;).desc()) \
  .show()

# SQL 사용
df.createOrReplaceTempView(&quot;sales&quot;)
result = spark.sql(&quot;&quot;&quot;
    SELECT product_category, 
           COUNT(*) as total_orders,
           AVG(sales_amount) as avg_amount
    FROM sales 
    WHERE sales_amount &amp;gt; 100
    GROUP BY product_category
    ORDER BY avg_amount DESC
&quot;&quot;&quot;)
result.show()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&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;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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실시간 스트리밍 예제&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755579994439&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Kafka에서 실시간 데이터 처리
streaming_df = spark \
    .readStream \
    .format(&quot;kafka&quot;) \
    .option(&quot;kafka.bootstrap.servers&quot;, &quot;localhost:9092&quot;) \
    .option(&quot;subscribe&quot;, &quot;user-events&quot;) \
    .load()

# JSON 파싱 및 집계
from pyspark.sql.functions import from_json, window
from pyspark.sql.types import StructType, StringType, TimestampType

schema = StructType() \
    .add(&quot;user_id&quot;, StringType()) \
    .add(&quot;event_type&quot;, StringType()) \
    .add(&quot;timestamp&quot;, TimestampType())

processed_stream = streaming_df \
    .select(from_json(col(&quot;value&quot;).cast(&quot;string&quot;), schema).alias(&quot;data&quot;)) \
    .select(&quot;data.*&quot;) \
    .groupBy(window(col(&quot;timestamp&quot;), &quot;10 minutes&quot;), col(&quot;event_type&quot;)) \
    .count()

query = processed_stream \
    .writeStream \
    .outputMode(&quot;update&quot;) \
    .format(&quot;console&quot;) \
    .start()

query.awaitTermination()&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 최적화 핵심 팁&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 파티셔닝 전략&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580016608&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 적절한 파티션 수 설정
spark.conf.set(&quot;spark.sql.adaptive.coalescePartitions.enabled&quot;, &quot;true&quot;)
spark.conf.set(&quot;spark.sql.adaptive.advisoryPartitionSizeInBytes&quot;, &quot;128MB&quot;)

# 데이터 저장 시 파티셔닝
df.write \
  .partitionBy(&quot;year&quot;, &quot;month&quot;) \
  .mode(&quot;overwrite&quot;) \
  .parquet(&quot;partitioned_data&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 캐싱 활용&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580034747&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 반복 사용되는 DataFrame 캐싱
df_cached = df.filter(col(&quot;status&quot;) == &quot;active&quot;).cache()
df_cached.count()  # 캐시에 저장
df_cached.groupBy(&quot;category&quot;).count().show()  # 캐시에서 읽기&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 브로드캐스트 조인&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580051030&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from pyspark.sql.functions import broadcast

# 작은 테이블을 브로드캐스트하여 조인 성능 향상
large_df.join(broadcast(small_df), &quot;key&quot;).show()&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;&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;
&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;color: #000000;&quot;&gt;실전 활용 사례&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 로그 분석 시스템&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580074965&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 웹 로그 실시간 분석
log_schema = StructType() \
    .add(&quot;timestamp&quot;, TimestampType()) \
    .add(&quot;ip&quot;, StringType()) \
    .add(&quot;url&quot;, StringType()) \
    .add(&quot;status_code&quot;, StringType())

# 실시간 이상 탐지
anomaly_detection = log_df \
    .groupBy(window(col(&quot;timestamp&quot;), &quot;5 minutes&quot;), col(&quot;ip&quot;)) \
    .count() \
    .filter(col(&quot;count&quot;) &amp;gt; 1000)  # 5분간 1000건 이상 요청

anomaly_detection.writeStream \
    .outputMode(&quot;append&quot;) \
    .format(&quot;delta&quot;) \
    .option(&quot;path&quot;, &quot;/alerts/anomalies&quot;) \
    .start()&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 추천 시스템 데이터 준비&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580093469&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from pyspark.ml.recommendation import ALS
from pyspark.ml.evaluation import RegressionEvaluator

# 사용자-상품 평점 데이터 준비
ratings = spark.read.csv(&quot;ratings.csv&quot;, header=True, inferSchema=True)

# ALS 모델 학습
als = ALS(userCol=&quot;user_id&quot;, itemCol=&quot;product_id&quot;, ratingCol=&quot;rating&quot;)
model = als.fit(ratings)

# 추천 생성
user_recs = model.recommendForAllUsers(10)
user_recs.show()&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. ETL 파이프라인&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580111644&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def extract_transform_load():
    # Extract: 다양한 소스에서 데이터 추출
    sales_df = spark.read.jdbc(url=&quot;jdbc:mysql://...&quot;, table=&quot;sales&quot;)
    users_df = spark.read.json(&quot;s3://bucket/users/&quot;)
    
    # Transform: 데이터 정제 및 변환
    cleaned_sales = sales_df \
        .filter(col(&quot;amount&quot;) &amp;gt; 0) \
        .withColumn(&quot;date&quot;, to_date(col(&quot;sale_timestamp&quot;)))
    
    result = cleaned_sales.join(users_df, &quot;user_id&quot;) \
        .groupBy(&quot;date&quot;, &quot;user_segment&quot;) \
        .agg(
            sum(&quot;amount&quot;).alias(&quot;total_sales&quot;),
            countDistinct(&quot;user_id&quot;).alias(&quot;unique_users&quot;)
        )
    
    # Load: 결과 저장
    result.write \
        .mode(&quot;overwrite&quot;) \
        .option(&quot;path&quot;, &quot;s3://warehouse/daily_sales/&quot;) \
        .saveAsTable(&quot;analytics.daily_sales&quot;)

# 스케줄링과 함께 실행
extract_transform_load()&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;클러스터 설정 및 배포&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Standalone 클러스터 구성&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1755580137090&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Master 노드 시작
./sbin/start-master.sh

# Worker 노드 시작
./sbin/start-slave.sh spark://master-node:7077

# 애플리케이션 제출
./bin/spark-submit \
    --class org.example.SparkApp \
    --master spark://master-node:7077 \
    --deploy-mode cluster \
    --executor-memory 4g \
    --total-executor-cores 8 \
    app.jar&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;YARN 클러스터에서 실행&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1755580155436&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# YARN에서 Spark 실행
./bin/spark-submit \
    --master yarn \
    --deploy-mode cluster \
    --num-executors 10 \
    --executor-memory 4g \
    --executor-cores 2 \
    --driver-memory 2g \
    --conf spark.sql.adaptive.enabled=true \
    --conf spark.sql.adaptive.coalescePartitions.enabled=true \
    my_app.py&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모니터링 및 디버깅&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. Spark UI 활용&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1755580176559&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 애플리케이션 실행 중 Spark UI 접근
# http://driver-node:4040

# 주요 확인 사항:
# - Jobs 탭: 작업 실행 상태 및 시간
# - Stages 탭: 각 스테이지별 세부 정보
# - Storage 탭: 캐시된 RDD/DataFrame 정보
# - Executors 탭: 익스큐터 리소스 사용량&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 로그 레벨 설정&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580273794&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 로그 레벨 조정
spark.sparkContext.setLogLevel(&quot;WARN&quot;)

# 상세한 실행 계획 확인
df.explain(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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 성능 메트릭 수집&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580319731&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 메트릭 활성화
spark.conf.set(&quot;spark.sql.adaptive.enabled&quot;, &quot;true&quot;)
spark.conf.set(&quot;spark.eventLog.enabled&quot;, &quot;true&quot;)
spark.conf.set(&quot;spark.eventLog.dir&quot;, &quot;/tmp/spark-events&quot;)

# 실행 시간 측정
import time
start_time = time.time()
result = df.count()
end_time = time.time()
print(f&quot;실행 시간: {end_time - start_time:.2f}초&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 포맷별 처리 방법&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Parquet (추천 포맷)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580344807&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Parquet 읽기/쓰기 - 컬럼형 저장으로 성능 최적
df.write.mode(&quot;overwrite&quot;).parquet(&quot;data.parquet&quot;)
df_parquet = spark.read.parquet(&quot;data.parquet&quot;)

# 파티션 프루닝 자동 적용
df_parquet.filter(col(&quot;year&quot;) == 2024).show()&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Delta Lake (ACID 트랜잭션 지원)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580360016&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Delta 테이블 생성
df.write.format(&quot;delta&quot;).mode(&quot;overwrite&quot;).save(&quot;delta-table&quot;)

# ACID 트랜잭션으로 업데이트
from delta.tables import DeltaTable
deltaTable = DeltaTable.forPath(spark, &quot;delta-table&quot;)
deltaTable.update(
    condition = col(&quot;status&quot;) == &quot;pending&quot;,
    set = {&quot;status&quot;: lit(&quot;processed&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;JSON 데이터 처리&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580375169&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 중첩된 JSON 구조 처리
from pyspark.sql.functions import explode, col

json_df = spark.read.json(&quot;nested_data.json&quot;)
flattened_df = json_df \
    .select(&quot;id&quot;, explode(&quot;items&quot;).alias(&quot;item&quot;)) \
    .select(&quot;id&quot;, &quot;item.name&quot;, &quot;item.price&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 설정&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 인증 및 암호화&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580411951&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Kerberos 인증 설정
spark = SparkSession.builder \
    .appName(&quot;SecureApp&quot;) \
    .config(&quot;spark.sql.adaptive.enabled&quot;, &quot;true&quot;) \
    .config(&quot;spark.authenticate&quot;, &quot;true&quot;) \
    .config(&quot;spark.network.crypto.enabled&quot;, &quot;true&quot;) \
    .getOrCreate()&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 데이터 마스킹&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580472435&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from pyspark.sql.functions import regexp_replace

# 개인정보 마스킹
masked_df = df.withColumn(
    &quot;phone&quot;, 
    regexp_replace(col(&quot;phone&quot;), r&quot;(\d{3})-(\d{4})-(\d{4})&quot;, r&quot;$1-****-$3&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;&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;
&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;color: #000000;&quot;&gt;자주 발생하는 문제와 해결책&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. OutOfMemoryError&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580500435&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 해결 방법: 파티션 수 조정 및 메모리 설정
spark.conf.set(&quot;spark.sql.adaptive.enabled&quot;, &quot;true&quot;)
spark.conf.set(&quot;spark.sql.adaptive.coalescePartitions.enabled&quot;, &quot;true&quot;)
df.repartition(200).write.parquet(&quot;output&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 데이터 스큐 문제&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580516253&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 해결 방법: 솔트 키 추가로 데이터 분산
from pyspark.sql.functions import rand, concat, lit

# 스큐된 키에 랜덤 솔트 추가
df_salted = df.withColumn(&quot;salted_key&quot;, concat(col(&quot;skewed_key&quot;), lit(&quot;_&quot;), (rand() * 10).cast(&quot;int&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 셔플 성능 이슈&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1755580533492&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 해결 방법: 브로드캐스트 조인 또는 버킷팅 사용
# 버킷팅으로 사전 정렬
df.write \
  .bucketBy(10, &quot;join_key&quot;) \
  .mode(&quot;overwrite&quot;) \
  .saveAsTable(&quot;bucketed_table&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Apache Spark는 현대 빅데이터 처리의 핵심 기술로 자리잡았다. &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;color: #000000;&quot;&gt;기존 Hadoop 생태계의 복잡함과 성능 제약을 해결하면서도, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 &lt;b&gt;메모리 기반 처리&lt;/b&gt;로 인한 성능 향상과 &lt;b&gt;직관적인 API&lt;/b&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;color: #000000;&quot;&gt;SQL을 아는 사람이라면 Spark SQL로, Python을 다루는 사람이라면 PySpark로, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Scala 개발자라면 네이티브 Spark API로 각자에게 맞는 방식으로 접근할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;앞으로 실시간 데이터 처리 needs가 더욱 증가할 것이고, 클라우드 네이티브 환경에서의 Spark 활용도 확대될 전망이다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Kubernetes 지원 강화, Delta Lake와의 통합, MLflow를 통한 &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ML 파이프라인 자동화&lt;/b&gt; 등이 Spark 생태계를 더욱 풍부하게 만들고 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;큰 데이터를 다루기 시작했다면, Spark는 선택이 아닌 필수가 될 것이다.&quot; 이제 시작해보자.&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;&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;
&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;
&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Apache Spark 공식 문서&lt;/b&gt;: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://spark.apache.org/docs/latest/&quot;&gt;https://spark.apache.org/docs/latest/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Spark SQL 가이드&lt;/b&gt;: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://spark.apache.org/docs/latest/sql-programming-guide.html&quot;&gt;https://spark.apache.org/docs/latest/sql-programming-guide.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;MLlib 공식 문서&lt;/b&gt;: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://spark.apache.org/docs/latest/ml-guide.html&quot;&gt;https://spark.apache.org/docs/latest/ml-guide.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Spark Streaming 가이드&lt;/b&gt;: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://spark.apache.org/docs/latest/streaming-programming-guide.html&quot;&gt;https://spark.apache.org/docs/latest/streaming-programming-guide.html&lt;/a&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;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;i&gt;&lt;b&gt;Somaz&amp;nbsp;|&amp;nbsp;DevOps&amp;nbsp;Engineer&amp;nbsp;|&amp;nbsp;Kubernetes&amp;nbsp;&amp;amp;&amp;nbsp;Cloud&amp;nbsp;Infrastructure&amp;nbsp;Specialist&lt;/b&gt; &lt;/i&gt;&lt;/p&gt;</description>
      <category>Data Engineering</category>
      <category>Apache Spark</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/433</guid>
      <comments>https://somaz.tistory.com/433#entry433comment</comments>
      <pubDate>Thu, 1 Jan 2026 00:18:01 +0900</pubDate>
    </item>
    <item>
      <title>Raft 합의 알고리즘 완전 가이드</title>
      <link>https://somaz.tistory.com/446</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 가이드는 분산 시스템의 핵심 기술인 &lt;b&gt;Raft 합의 알고리즘&lt;/b&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;&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;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  관련 글&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/149&quot;&gt;2022.09.26 - [Open Source Software] - Redis(Remote Dictionary Server)란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/410&quot;&gt;2025.04.02 - [CS 지식] - [CS 지식20.] OS 캐시와 디스크 I/O: MySQL, Redis 퍼포먼스 분석&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/445&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2025.08.12 - [Container Orchestration/Kubernetes] - Kubernetes 환경에서 Redis Redlock 구현하기: 분산 락의 완전한 이해&lt;/a&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;학습 목표&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 가이드를 통해 다음을 습득할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Raft 알고리즘의 동작 원리&lt;/b&gt;와 핵심 개념 완전 이해&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;분산 시스템에서 합의가 필요한 이유&lt;/b&gt;와 해결 방법&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;리더 선출, 로그 복제, 장애 처리&lt;/b&gt; 등 핵심 메커니즘&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실제 구현 방법&lt;/b&gt;과 코드 예시 (Go 언어)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;운영 환경에서의 최적화 기법&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가이드 구성&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;기초 개념&lt;/b&gt;: Raft란 무엇이며 왜 필요한가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;핵심 구조&lt;/b&gt;: 노드 상태, Term 개념, 기본 아키텍처&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;동작 원리&lt;/b&gt;: 리더 선출과 로그 복제 과정 상세 분석&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;안전성&lt;/b&gt;: 데이터 일관성과 장애 허용 메커니즘&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실전 활용&lt;/b&gt;: 구현 예시, 실제 사용 사례, 최적화 기법&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대상 독자&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;백엔드 개발자&lt;/b&gt;: 분산 시스템 설계에 관심 있는 개발자&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;시스템 엔지니어&lt;/b&gt;: Kubernetes, etcd, Consul 등을 다루는 엔지니어&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;아키텍트&lt;/b&gt;: 고가용성 시스템 설계를 담당하는 아키텍트&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;학습자&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 포인트 미리보기&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;이해하기 쉬운 설계&lt;/b&gt;: Paxos보다 훨씬 간단하고 직관적&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;강력한 리더 기반&lt;/b&gt;: 중앙 집권적 접근으로 복잡성 해결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;수학적 안전성&lt;/b&gt;: 엄밀하게 증명된 일관성 보장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실전 검증&lt;/b&gt;: etcd, Consul, TiDB 등에서 프로덕션 사용&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Raft란 무엇인가?&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Raft(Reliable, Replicated, Redundant, And Fault-Tolerant)는 분산 시스템에서 &lt;b&gt;합의(Consensus)&lt;/b&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;color: #000000;&quot;&gt; 2013년 Diego Ongaro와 John Ousterhout이 Stanford에서 개발했으며, 기존의 Paxos 알고리즘보다 이해하기 쉽고 구현하기 간단하다는 것이 가장 큰 장점이다.&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;&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;
&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;color: #000000;&quot;&gt;왜 합의 알고리즘이 필요한가?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;분산 시스템의 근본적 문제&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;분산 시스템에서는 여러 노드가 같은 상태를 유지해야 한다. 하지만 현실에서는&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;네트워크 지연/파티션&lt;/b&gt;: 메시지가 늦게 도착하거나 아예 전달되지 않음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;노드 장애&lt;/b&gt;: 서버가 갑자기 죽거나 재시작됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;동시성 문제&lt;/b&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;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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;합의가 필요한 상황들&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;상황 1: 분산 데이터베이스&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 A: &quot;계좌 잔액 = 1000원&quot;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 B: &quot;계좌 잔액 = 500원&quot;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 C: &quot;계좌 잔액 = 1500원&quot; &amp;rarr; 어떤 값이 정답인가?&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;상황 2: 분산 락&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 A: &quot;리소스 X는 내가 사용 중&quot;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 B: &quot;리소스 X는 내가 사용 중&quot; &amp;rarr; 누가 실제로 사용해야 하는가?&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;상황 3: 리더 선택&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 A: &quot;내가 리더다&quot;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 B: &quot;내가 리더다&quot; &amp;rarr; 실제 리더는 누구인가?&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;Raft는 이런 상황에서 모든 노드가 같은 결론에 도달하도록 보장한다.&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;&lt;span style=&quot;color: #000000;&quot;&gt;Raft의 핵심 구성 요소&lt;/span&gt;&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;&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;color: #000000;&quot;&gt;1. 노드의 3가지 상태&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Raft에서 각 노드는 다음 3가지 상태 중 하나를 가진다.&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Leader (리더)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;역할&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 클라이언트 요청을 처리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로그 엔트리를 다른 노드들에게 복제&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Heartbeat를 통해 자신의 리더십 유지&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클러스터에 최대 1개만 존재&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Follower (팔로워)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;역할&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리더의 요청에 응답&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로그 엔트리를 수신하고 저장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리더의 Heartbeat를 기다림&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대부분의 노드가 이 상태&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Candidate (후보자)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;역할&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리더 선거를 시작&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다른 노드들에게 투표 요청&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일시적인 상태 (선거 기간 동안만)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Leader 또는 Follower로 전환&lt;/span&gt;&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;&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;
&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;color: #000000;&quot;&gt;2. Term (임기) 개념&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Term이란?&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;논리적 시간 개념&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 Term마다 최대 1명의 Leader 존재&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Leader 선거가 일어날 때마다 Term 증가&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1754985671938&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Term 0: [Leader A]
Term 1: [Leader B] 
Term 2: [Leader C]
Term 3: [선거 실패]
Term 4: [Leader A]&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Raft 동작 원리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Raft의 동작은 크게 2단계로 나뉜다.&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;&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;color: #000000;&quot;&gt;1단계: Leader Election (리더 선출)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선거 시작 조건&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;클러스터 시작 시 (모든 노드가 Follower)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Follower가 리더의 Heartbeat를 받지 못할 때&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Candidate가 선거에서 승리하지 못할 때&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선거 과정&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1214&quot; data-origin-height=&quot;1634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/odiTa/btsPQxmBBF4/YBmpC2htDZ9zuCdoKuUfNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/odiTa/btsPQxmBBF4/YBmpC2htDZ9zuCdoKuUfNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/odiTa/btsPQxmBBF4/YBmpC2htDZ9zuCdoKuUfNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FodiTa%2FbtsPQxmBBF4%2FYBmpC2htDZ9zuCdoKuUfNk%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;620&quot; height=&quot;834&quot; data-origin-width=&quot;1214&quot; data-origin-height=&quot;1634&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;투표 규칙&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;Term 조건&lt;/b&gt;: 후보자의 Term이 자신의 Term보다 크거나 같아야 함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;최신성 조건&lt;/b&gt;: 후보자의 로그가 자신의 로그만큼 최신이어야 함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1표 원칙&lt;/b&gt;: 같은 Term에서는 최대 1번만 투표&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선거 결과&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;Case 1&lt;/b&gt;: 과반수 득표 &amp;rarr; Leader 당선&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Case 2&lt;/b&gt;: 과반수 실패 &amp;rarr; 새로운 Term으로 재선거&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Case 3&lt;/b&gt;: 동시 후보 &amp;rarr; Split Vote, 재선거&lt;/span&gt;&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;&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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2단계: Log Replication (로그 복제)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라이언트 요청 처리 과정&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1776&quot; data-origin-height=&quot;1636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MEAg9/btsPRGpHKLn/VFYoC6qsSUJ0kLFa8TKpfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MEAg9/btsPRGpHKLn/VFYoC6qsSUJ0kLFa8TKpfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MEAg9/btsPRGpHKLn/VFYoC6qsSUJ0kLFa8TKpfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMEAg9%2FbtsPRGpHKLn%2FVFYoC6qsSUJ0kLFa8TKpfK%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;724&quot; height=&quot;667&quot; data-origin-width=&quot;1776&quot; data-origin-height=&quot;1636&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로그 구조&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;각 로그 엔트리 구성&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Index&lt;/b&gt;: 로그 내 위치&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Term&lt;/b&gt;: 엔트리가 생성된 Term&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Command&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예시&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754985844683&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Index: 1  Term: 1  Command: &quot;SET a=10&quot;
Index: 2  Term: 1  Command: &quot;SET b=20&quot;  
Index: 3  Term: 2  Command: &quot;SET c=30&quot;
Index: 4  Term: 2  Command: &quot;SET d=40&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;복제 과정 상세&lt;/b&gt;&lt;/span&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;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Leader가 로그 엔트리 생성&lt;/b&gt;&lt;/span&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;color: #000000;&quot;&gt;새로운 요청이 오면:&lt;/span&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;color: #000000;&quot;&gt;로그에 새 엔트리 추가 (uncommitted 상태)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 Follower에게 AppendEntries RPC 전송&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Follower가 로그 엔트리 검증&lt;/b&gt;&lt;/span&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;color: #000000;&quot;&gt;받은 엔트리를 검증:&lt;/span&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;color: #000000;&quot;&gt;이전 엔트리와 연결성 확인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Term 일치성 확인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;충돌 시 로그 덮어쓰기&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;과반수 복제 후 Commit&lt;/b&gt;&lt;/span&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;color: #000000;&quot;&gt;과반수 노드가 응답하면:&lt;/span&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;color: #000000;&quot;&gt;Leader가 엔트리를 committed로 표시&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다음 Heartbeat에서 Follower들에게 commit 알림&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 노드가 해당 엔트리 적용&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Raft의 안전성 보장&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. Leader Election Safety&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;각 Term에서 최대 1명의 Leader만 선출된다&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보장 방법&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;과반수 투표 요구&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;같은 Term에서 노드당 최대 1표&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Split Vote 시 재선거&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Log Matching Property&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;같은 Index와 Term을 가진 엔트리는 같은 내용이다.&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보장 방법&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Leader가 특정 Index에 하나의 엔트리만 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. Leader Completeness&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;이전 Term에서 committed된 엔트리는 새 Leader의 로그에 반드시 존재한다.&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보장 방법&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선거 시 로그 최신성 검증&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;4. State Machine Safety&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;모든 노드가 같은 Index에 같은 명령을 적용한다.&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보장 방법&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Leader Completeness&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Log Matching Property&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장애 상황별 처리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. Leader 장애&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;상황&lt;/b&gt;: Leader가 갑자기 죽음&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;color: #000000;&quot;&gt;&lt;b&gt;처리 과정&lt;/b&gt;&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;Follower들이 Heartbeat 타임아웃 감지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;새로운 Term으로 리더 선거 시작&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가장 최신 로그를 가진 노드가 새 Leader&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;새 Leader가 미완료 로그 복제 재개&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결과&lt;/b&gt;: 새로운 Leader 선출, 서비스 계속&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Follower 장애&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;상황&lt;/b&gt;: Follower 하나가 죽음&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;color: #000000;&quot;&gt;&lt;b&gt;처리 과정&lt;/b&gt;&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;Leader가 해당 Follower에게 복제 실패 감지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;나머지 노드들로 과반수 확보 가능하면 계속 진행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장애 노드가 복구되면 누락된 로그 자동 동기화&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결과&lt;/b&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 네트워크 파티션&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;상황&lt;/b&gt;: 5노드 클러스터가 3+2로 분할&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;파티션 A (3노드)&lt;/b&gt;: 과반수 &amp;rarr; 정상 동작 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;파티션 B (2노드)&lt;/b&gt;: 소수 &amp;rarr; 읽기 전용 모드&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;처리:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파티션 A: 새 Leader 선출, 쓰기 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파티션 B: Leader 선출 불가, 읽기만 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. Split Brain 방지&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;핵심 원리&lt;/b&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;color: #000000;&quot;&gt;&lt;b&gt;예시 (5노드)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정상: 5노드 중 3노드 이상 동의 필요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파티션: 3+2 분할 시, 3노드 그룹만 동작&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보장: 동시에 2개 Leader 불가능&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;수학적 증명&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;N개 노드에서 과반수 = N/2 + 1&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;두 그룹이 모두 과반수를 가질 수 없음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;따라서 Split Brain 불가능&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 구현 예시&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 구조 (Go 언어)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754986808060&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type RaftNode struct {
    // 상태 정보
    currentTerm int
    votedFor    *int
    log         []LogEntry
    
    // 휘발성 상태
    commitIndex int
    lastApplied int
    
    // Leader 전용 (선거 후 초기화)
    nextIndex   []int
    matchIndex  []int
    
    // 노드 정보
    id    int
    peers []int
    state NodeState
}

type LogEntry struct {
    Term    int
    Index   int
    Command interface{}
}

type NodeState int
const (
    Follower NodeState = iota
    Candidate  
    Leader
)&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;RequestVote RPC&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754986823556&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type RequestVoteArgs struct {
    Term         int // 후보자의 Term
    CandidateID  int // 후보자 ID
    LastLogIndex int // 후보자의 마지막 로그 인덱스
    LastLogTerm  int // 후보자의 마지막 로그 Term
}

type RequestVoteReply struct {
    Term        int  // 현재 Term (후보자 업데이트용)
    VoteGranted bool // 투표 결과
}

func (rf *RaftNode) RequestVote(args *RequestVoteArgs, reply *RequestVoteReply) {
    rf.mu.Lock()
    defer rf.mu.Unlock()
    
    reply.Term = rf.currentTerm
    reply.VoteGranted = false
    
    // Term 조건 확인
    if args.Term &amp;lt; rf.currentTerm {
        return
    }
    
    if args.Term &amp;gt; rf.currentTerm {
        rf.currentTerm = args.Term
        rf.votedFor = nil
        rf.state = Follower
    }
    
    // 투표 조건 확인
    if (rf.votedFor == nil || *rf.votedFor == args.CandidateID) &amp;amp;&amp;amp;
       rf.isLogUpToDate(args.LastLogIndex, args.LastLogTerm) {
        rf.votedFor = &amp;amp;args.CandidateID
        reply.VoteGranted = true
        rf.resetElectionTimeout()
    }
}

func (rf *RaftNode) isLogUpToDate(index, term int) bool {
    lastIndex, lastTerm := rf.getLastLogInfo()
    
    // 더 높은 Term을 가지거나, 같은 Term에서 더 긴 로그
    return term &amp;gt; lastTerm || (term == lastTerm &amp;amp;&amp;amp; index &amp;gt;= lastIndex)
}&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AppendEntries RPC&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754986839127&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type AppendEntriesArgs struct {
    Term         int        // Leader의 Term
    LeaderID     int        // Leader ID
    PrevLogIndex int        // 새 엔트리 직전 로그 인덱스
    PrevLogTerm  int        // PrevLogIndex의 Term
    Entries      []LogEntry // 복제할 엔트리들
    LeaderCommit int        // Leader의 commitIndex
}

type AppendEntriesReply struct {
    Term    int  // 현재 Term
    Success bool // 복제 성공 여부
}

func (rf *RaftNode) AppendEntries(args *AppendEntriesArgs, reply *AppendEntriesReply) {
    rf.mu.Lock()
    defer rf.mu.Unlock()
    
    reply.Term = rf.currentTerm
    reply.Success = false
    
    // Term 확인
    if args.Term &amp;lt; rf.currentTerm {
        return
    }
    
    rf.resetElectionTimeout()
    
    if args.Term &amp;gt; rf.currentTerm {
        rf.currentTerm = args.Term
        rf.votedFor = nil
    }
    rf.state = Follower
    
    // 로그 일치성 확인
    if args.PrevLogIndex &amp;gt; 0 {
        if len(rf.log) &amp;lt; args.PrevLogIndex ||
           rf.log[args.PrevLogIndex-1].Term != args.PrevLogTerm {
            return
        }
    }
    
    // 엔트리 추가
    if len(args.Entries) &amp;gt; 0 {
        rf.log = rf.log[:args.PrevLogIndex]
        rf.log = append(rf.log, args.Entries...)
    }
    
    // Commit 업데이트
    if args.LeaderCommit &amp;gt; rf.commitIndex {
        rf.commitIndex = min(args.LeaderCommit, len(rf.log))
    }
    
    reply.Success = 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;&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;
&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;color: #000000;&quot;&gt;실제 사용 사례&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. etcd (Kubernetes)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;용도&lt;/b&gt;: Kubernetes 클러스터 상태 저장 &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;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 K8s 설정이 etcd에 저장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Raft로 고가용성 보장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일반적으로 3-5개 노드 구성&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예시 구성&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd-0 (Leader)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd-1 (Follower)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;etcd-2 (Follower)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Consul (HashiCorp)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;용도&lt;/b&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;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;분산 서비스 메쉬의 중앙 저장소&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Raft로 데이터 일관성 보장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Multi-Datacenter 지원&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예시 구성&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;consul-server-0 (Leader)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;consul-server-1 (Follower)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;consul-server-2 (Follower)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. TiKV (TiDB)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;용도&lt;/b&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;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Region별로 Raft 그룹 구성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수천 개의 Raft 그룹이 동시 실행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. CockroachDB&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;용도&lt;/b&gt;: 분산 SQL 데이터베이스 &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;color: #000000;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Range별 Raft 복제&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;강력한 일관성 보장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&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;color: #000000;&quot;&gt;Raft vs 다른 합의 알고리즘&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;vs. Paxos&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;항목&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Raft&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Paxos&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이해도&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쉬움&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;어려움&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구현 복잡도&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단순&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;검증&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;상대적 최신&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오랜 검증&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리더십&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;강한 리더&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;vs. PBFT (Practical Byzantine Fault Tolerance)&lt;/span&gt;&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-style=&quot;style8&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;항목&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Raft&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;PBFT&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장애 모델&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Crash Fault&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Byzantine Fault&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡도&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단순&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매우 복잡&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;노드 수 요구&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2f+1&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3f+1&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용 케이스&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일반 분산 시스템&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Raft 최적화 기법&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 배치 처리 (Batching)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754987142543&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 여러 요청을 한 번에 처리
func (rf *RaftNode) batchAppend() {
    entries := []LogEntry{}
    
    // 여러 클라이언트 요청을 수집
    for i := 0; i &amp;lt; batchSize &amp;amp;&amp;amp; len(rf.pendingRequests) &amp;gt; 0; i++ {
        req := &amp;lt;-rf.pendingRequests
        entry := LogEntry{
            Term:    rf.currentTerm,
            Index:   rf.getNextIndex(),
            Command: req.Command,
        }
        entries = append(entries, entry)
    }
    
    // 한 번에 복제
    rf.replicateEntries(entries)
}&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 파이프라이닝 (Pipelining)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754987157487&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 이전 복제 완료를 기다리지 않고 다음 복제 시작
func (rf *RaftNode) pipelineReplication() {
    for _, peer := range rf.peers {
        go func(peerID int) {
            for {
                // 다음 전송할 엔트리 확인
                entries := rf.getNextEntries(peerID)
                if len(entries) &amp;gt; 0 {
                    rf.sendAppendEntries(peerID, entries)
                }
                time.Sleep(10 * time.Millisecond)
            }
        }(peer)
    }
}&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 로그 압축 (Log Compaction)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754987172021&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 오래된 로그를 스냅샷으로 압축
func (rf *RaftNode) createSnapshot() {
    snapshot := rf.stateMachine.CreateSnapshot()
    
    // 스냅샷 이전의 로그 제거
    rf.log = rf.log[rf.lastSnapshotIndex:]
    rf.lastSnapshotIndex = rf.commitIndex
    rf.lastSnapshotTerm = rf.currentTerm
    
    rf.saveSnapshot(snapshot)
}&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영 시 주의사항&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 클러스터 크기 선택&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;권장 크기:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;3노드&lt;/b&gt;: 1개 장애 허용 (개발/테스트)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;5노드&lt;/b&gt;: 2개 장애 허용 (프로덕션)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;7노드&lt;/b&gt;: 3개 장애 허용 (고가용성)&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;주의사항:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;홀수 개 노드 사용 (Split Vote 방지)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;너무 많으면 성능 저하&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 타임아웃 설정&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754987207696&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 일반적인 타임아웃 설정
const (
    ElectionTimeoutMin = 150 * time.Millisecond
    ElectionTimeoutMax = 300 * time.Millisecond
    HeartbeatInterval  = 50 * time.Millisecond
    RPCTimeout        = 100 * time.Millisecond
)

// 네트워크 환경에 따른 조정
if rf.networkLatency &amp;gt; 50*time.Millisecond {
    ElectionTimeoutMin *= 2
    ElectionTimeoutMax *= 2
    HeartbeatInterval *= 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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 모니터링 메트릭&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754987245943&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 모니터링해야 할 핵심 지표
- raft_leader_elections_total
- raft_leader_last_contact_seconds
- raft_log_entries_total
- raft_log_commits_total  
- raft_rpc_duration_seconds
- raft_cluster_size
- raft_nodes_health&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 백업 및 복구&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754987260925&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# etcd 백업 예시
etcdctl snapshot save backup.db

# 복구
etcdctl snapshot restore backup.db \
  --name m1 \
  --initial-cluster m1=http://host1:2380 \
  --initial-cluster-token etcd-cluster-1&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;&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Raft는 분산 시스템에서 이해하기 쉽고 구현하기 간단한 합의 알고리즘이다. 강력한 Leader 기반의 접근 방식으로 복잡한 분산 문제를 우아하게 해결한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 포인트&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;단순함&lt;/b&gt;: Paxos보다 훨씬 이해하기 쉬운 설계&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;안전성&lt;/b&gt;: 수학적으로 증명된 안전성 보장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실용성&lt;/b&gt;: 많은 프로덕션 시스템에서 검증됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;확장성&lt;/b&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선택 기준&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;일반적인 분산 시스템&lt;/b&gt;: Raft 추천&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;매우 높은 성능 요구&lt;/b&gt;: 최적화된 Paxos 고려&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비잔틴 장애 대응&lt;/b&gt;: PBFT 계열 알고리즘 필요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;단순한 요구사항&lt;/b&gt;: 단순한 Master-Slave 복제도 고려&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Raft를 이해하면 현대 분산 시스템의 핵심 동작 원리를 파악할 수 있고, etcd, Consul 같은 도구들의 내부 동작도 명확하게 이해할 수 있게 된다.&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;&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;원본 논문 및 학술 자료&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;[Raft 원본 논문]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://raft.github.io/raft.pdf&quot;&gt;In Search of an Understandable Consensus Algorithm&lt;/a&gt; (Diego Ongaro, John Ousterhout, 2014)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[Raft 박사논문]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/ongardie/dissertation&quot;&gt;Consensus: Bridging Theory and Practice&lt;/a&gt; (Diego Ongaro, 2014)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[Raft 공식 웹사이트]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://raft.github.io/&quot;&gt;https://raft.github.io/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[Raft 시각화]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;http://thesecretlivesofdata.com/raft/&quot;&gt;http://thesecretlivesofdata.com/raft/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 구현체&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;[etcd]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/etcd-io/etcd&quot;&gt;https://github.com/etcd-io/etcd&lt;/a&gt; (Go)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[Consul]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/hashicorp/consul&quot;&gt;https://github.com/hashicorp/consul&lt;/a&gt; (Go)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[TiKV]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/tikv/tikv&quot;&gt;https://github.com/tikv/tikv&lt;/a&gt; (Rust)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[Sofa-JRaft]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/sofastack/sofa-jraft&quot;&gt;https://github.com/sofastack/sofa-jraft&lt;/a&gt; (Java)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[LogCabin]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/logcabin/logcabin&quot;&gt;https://github.com/logcabin/logcabin&lt;/a&gt; (C++)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;학습 자료&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;[Raft Playground]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://raft.github.io/raftscope/index.html&quot;&gt;https://raft.github.io/raftscope/index.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[MIT 6.824 강의]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://pdos.csail.mit.edu/6.824/&quot;&gt;https://pdos.csail.mit.edu/6.824/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[Raft 사용자 가이드 (etcd)]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://etcd.io/docs/&quot;&gt;https://etcd.io/docs/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동영상 강의&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;[Raft 알고리즘 소개 (John Ousterhout)]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.youtube.com/watch?v=YbZ3zDzDnrw&quot;&gt;YouTube&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[분산 시스템 강의 (MIT 6.824)]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.youtube.com/playlist?list=PLrw6a1wE39_tb2fErI4-WkMbsvGQk9_UB&quot;&gt;YouTube Playlist&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;도구 및 라이브러리&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;[Raft.js]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/kanaka/raft.js&quot;&gt;https://github.com/kanaka/raft.js&lt;/a&gt; (JavaScript 시뮬레이션)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[go-raft]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/goraft/raft&quot;&gt;https://github.com/goraft/raft&lt;/a&gt; (Go 라이브러리)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[python-raft]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/zhebrak/raft-algorithm&quot;&gt;https://github.com/zhebrak/raft-algorithm&lt;/a&gt; (Python 구현)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;벤치마크 및 성능 분석&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;[Raft vs Paxos 성능 비교]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://ramcloud.stanford.edu/~ongaro/userstudy/&quot;&gt;Performance Analysis Paper&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[etcd 성능 벤치마크]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://etcd.io/docs/v3.4/op-guide/performance/&quot;&gt;https://etcd.io/docs/v3.4/op-guide/performance/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로덕션 사용 사례&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;[Kubernetes + etcd]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubernetes.io/docs/concepts/overview/components/#etcd&quot;&gt;https://kubernetes.io/docs/concepts/overview/components/#etcd&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[HashiCorp 스택]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.hashicorp.com/resources/raft-consul-consensus-protocol&quot;&gt;https://www.hashicorp.com/resources/raft-consul-consensus-protocol&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[CockroachDB 아키텍처]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.cockroachlabs.com/docs/stable/architecture/replication-layer.html&quot;&gt;https://www.cockroachlabs.com/docs/stable/architecture/replication-layer.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추가 읽을거리&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;[CAP 정리]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://en.wikipedia.org/wiki/CAP_theorem&quot;&gt;https://en.wikipedia.org/wiki/CAP_theorem&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[분산 시스템 설계 패턴]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://martinfowler.com/articles/patterns-of-distributed-systems/&quot;&gt;https://martinfowler.com/articles/patterns-of-distributed-systems/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[Jepsen 테스트 (분산 시스템 검증)]&lt;/b&gt; - &lt;a style=&quot;color: #000000;&quot; href=&quot;https://jepsen.io/&quot;&gt;https://jepsen.io/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Algorithm</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/446</guid>
      <comments>https://somaz.tistory.com/446#entry446comment</comments>
      <pubDate>Wed, 31 Dec 2025 07:34:26 +0900</pubDate>
    </item>
    <item>
      <title>구글의 끝판왕 AI, 'Google AI Pro' 소개</title>
      <link>https://somaz.tistory.com/481</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구글이 작정하고 내놓은 'Google AI Pro' 요금제가 엄청난 할인 혜택으로 찾아왔다. 기존 정가 연 348,000원에서 무려 20만 원 이상 할인된 &lt;b&gt;연 140,000원(첫해 59% 할인)&lt;/b&gt;에 이용할 수 있는 기회이다. 월 구독도 첫 3개월간 9,500원이라는 파격적인 가격이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 요금제는 단순한 챗봇 사용을 넘어선다. 영화급 영상을 만드는 Veo, 초고품질 이미지를 그리는 Nano Banana Pro, 그리고 개발자를 위한 Jules와 Antigravity까지. 크리에이터와 개발자라면 놓칠 수 없는 올인원 패키지이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;경쟁사 대비 가성비&lt;/b&gt;를 살펴보면&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ChatGPT Plus: 월 $20 (약 27,000원) = 연 324,000원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Pro: 월 $20 (약 27,000원) = 연 324,000원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google AI Pro (할인가): 연 140,000원 &amp;rarr; &lt;b&gt;2배 이상 저렴!&lt;/b&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;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;어떤 괴물 같은 기능들이 들어있는지 상세히 뜯어보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;738&quot; data-origin-height=&quot;1350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmUEry/dJMcachrbKA/5F2mqKW9EGF4gk1NJrlNBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmUEry/dJMcachrbKA/5F2mqKW9EGF4gk1NJrlNBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmUEry/dJMcachrbKA/5F2mqKW9EGF4gk1NJrlNBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmUEry%2FdJMcachrbKA%2F5F2mqKW9EGF4gk1NJrlNBk%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;597&quot; height=&quot;1092&quot; data-origin-width=&quot;738&quot; data-origin-height=&quot;1350&quot;/&gt;&lt;/span&gt;&lt;/figure&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;9&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google AI Pro 핵심 기능 완벽 해부&lt;/span&gt;&lt;/h3&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;h4 data-path-to-node=&quot;10&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;① 차원이 다른 생성형 AI 모델 (Gemini 앱)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-path-to-node=&quot;11&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가장 강력한 최신 모델들을 제한 없이 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;12&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,0,0&quot;&gt;Gemini 3 Pro &amp;amp; Deep Research:&lt;/b&gt; 복잡한 연구와 심층 분석에 특화된 최고 성능 모델이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,1,0&quot;&gt;Nano Banana Pro:&lt;/b&gt; 앞서 언급된 바로 그 모델! 텍스트 묘사력이 뛰어난 최상급 이미지 생성 기능을 제공한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,2,0&quot;&gt;Veo 3.1:&lt;/b&gt; 텍스트만으로 고퀄리티 동영상을 생성하는 최신 비디오 모델에 액세스할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1766987873619&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;무료 사용자:
- Gemini 2.5 Flash: 무제한
- Gemini 3 Pro (사고 모드): 하루 5회
- Nano Banana: 하루 100회

AI Pro 구독자:
- Gemini 3 Pro: 하루 100회 (20배 증가!)
- Nano Banana Pro: 무제한에 가까운 높은 한도
- Veo 3.1 Fast: 제한적 액세스
- 1백만 토큰 컨텍스트 윈도우 (1,500페이지 또는 30,000줄 코드)&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;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;② 크리에이터를 위한 AI 스튜디오 (Flow &amp;amp; Whisk)&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;영상 제작자가 꿈꾸던 기능이 현실이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Flow - AI 영화 제작 도구&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Veo 3.1 기반&lt;/b&gt; 영화 같은 장면과 스토리 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Text to Video: 텍스트만으로 영상 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ingredients to Video: 재료(요소)를 조합해 영상 제작&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Frames to Video: 프레임을 이어붙여 완성도 높은 영상 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;AI Pro 한도&lt;/b&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;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Whisk - 이미지-비디오 변환 도구&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정적 이미지 &amp;rarr; 생동감 넘치는 동영상 변환&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Whisk Animate&lt;/b&gt;: Veo 3을 활용한 애니메이션 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;AI 크레딧 시스템&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #abb2bf; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;월간 AI 크레딧 1,000 제공 (AI Pro)
- Flow와 Whisk에서 고성능 작업 수행 시 사용
- 크레딧은 생성당 차감 (요청당이 아님)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Google 포토 통합&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;사진으로 동영상 만들기&lt;/b&gt;: AI가 사진에 애니메이션 적용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;리믹스&lt;/b&gt;: 기존 사진을 AI로 재해석하여 새로운 스타일로 변환&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AI Pro 사용자는 더 많은 사진 변환 가능 (미국 내 Android/iOS)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;③ 개발자를 위한 프로페셔널 도구 (Dev Tools)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Google Antigravity - 에이전트 개발 플랫폼&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;ldif&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;무료 사용자: 기본 한도
AI Pro: 5배 높은 AI 에이전트 할당량
AI Ultra: 최고 한도 + 우선 성능

특징:
- Gemini 3 Pro 기반 자율 AI 에이전트 관리
- 편집기, 터미널, 브라우저 전반의 복잡한 코딩 작업 자동화
- 5시간마다 사용량 한도 새로고침
- Claude 4.5 Sonnet, GPT-OSS 등 다른 모델도 사용 가능
- 실험 모델 우선 액세스&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Jules - 비동기 코딩 에이전트&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;asciidoc&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;기능:
- Gemini 3 Pro 기반
- 코드 읽기 및 사용자 의도 파악
- 여러 작업을 한 번에 처리
- 기능 구현, 버그 수정, 테스트 실행 자동화

한도:
- 무료: 기본 한도
- AI Pro: 5배 높은 한도 (일일 코딩 작업에 이상적)
- AI Ultra: 20배 높은 한도 (대규모 멀티 에이전트 워크플로우)&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Gemini Code Assist &amp;amp; CLI&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;asciidoc&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;- IDE에서 코딩 도와주는 어시스턴트
- AI Pro: 더 높은 일일 모델 요청 한도
- AI Ultra: 최고 일일 요청 한도
- Pro 모델 기반으로 더 정확한 코드 제안&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Firebase Studio&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;작업공간 30개까지 지원 (개발자 프로그램 가입 시)&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;④ 학습과 업무 효율의 극대화&lt;/span&gt;&lt;/h4&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;NotebookLM - AI 연구 파트너&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;asciidoc&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;무료 vs Pro 비교:

무료 사용자:
- 기본 노트북 개수
- 기본 쿼리 한도
- 노트북당 소스 제한

AI Pro:
- 5배 더 많은 노트북, 쿼리, 소스
- 노트북당 최대 300개 소스 (대폭 증가)
- AI 오디오 오버뷰 생성
- 비디오 오버뷰 생성
- 퀴즈 자동 출제
- 주요 핵심 기능 우선 이용 권한
- 모바일(iOS/Android) 지원&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;기능 상세&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단순 텍스트 요약을 넘어 AI가 자료를 분석해 &lt;b&gt;오디오/동영상 오버뷰&lt;/b&gt; 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;학습 자료로 &lt;b&gt;퀴즈 자동 출제&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구글 연구 파트너 수준의 액세스 권한&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;Google 검색 통합 - Deep Search&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;haml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;AI 모드에서 사용 가능:
- 더욱 정교한 질문에 대한 심층 답변
- 수백 건의 검색을 자동 수행
- 분산된 정보를 종합하여 완전한 인용이 포함된 보고서 생성
- 응답까지 몇 분 소요 (Deep Research와 유사)
- AI Pro: &quot;Higher&quot; 사용 한도&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;AI 기반 전화 (미국 전용)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지역 비즈니스에 가격과 재고 확인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google 검색에서 AI가 자동으로 전화 연결&lt;/span&gt;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Google Earth 통합&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Gemini와 채팅하여 지형공간 분석&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AI Pro: 더 높은 한도로 빠른 분석&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Workspace 통합&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Gmail, Docs, Sheets, Slides, Vids&lt;/b&gt; 등에서 Gemini 바로 호출&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이메일 작성, 문서 요약, 데이터 분석, 프레젠테이션 제작 자동화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;&lt;b&gt;Google Vids - AI 영상 제작 앱&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;asciidoc&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;기능:
- AI 기반 비디오 생성, 작성, 편집
- 프레젠테이션 스타일 영상 특화
- 학교, 비즈니스, 개인 용도
- 팀 협업 및 공유 기능&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;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;color: #000000;&quot;&gt;&lt;b&gt;Google Meet 통합&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;더 긴 통화 시간&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주변 소음 제거 (방해 요소 없는 오디오)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중요한 대화 저장 및 재생&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Premium 요금제 이상에서 사용 가능&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Google Calendar 고급 기능&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다양한 약속 유형 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 리마인더&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일정 관리 스트레스 해소&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Premium 요금제 이상&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;21&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⑤ 든든한 기반: 2TB 스토리지&lt;/span&gt;&lt;/h4&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 모든 고화질 영상과 방대한 코드를 저장할 공간도 잊지 않았다. &lt;b data-index-in-node=&quot;39&quot; data-path-to-node=&quot;22&quot;&gt;Google 포토, Drive, Gmail에서 공유 가능한 2TB 대용량 스토리지&lt;/b&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;&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;color: #000000;&quot;&gt;추가 혜택 및 기능&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가족 공유 (Family Sharing)&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;asciidoc&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;최대 6명까지 공유 (본인 포함):
- 2TB 스토리지 공유
- AI 혜택 및 기능 모두 공유 (추가 비용 없음)
- 가족 그룹 생성 및 관리
- 일부 혜택은 요금제 관리자 전용&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google 개발자 프로그램 연동&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;haml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;Standard 플랜 ($24.99/월):
- Google AI Pro 1개월 포함
- $45 상당 생성형 AI &amp;amp; Cloud 월별 크레딧
- $500 상당 보너스 크레딧
- Gemini Code Assist Standard

Expert 플랜 ($299/년):
- Google AI Pro 3개월 포함
- $550 상당 연간 크레딧
- Google Cloud 자격증 쿠폰
- 무제한 Google Skills&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Project Mariner (사전 체험판, 미국 전용)&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;haml&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;브라우저 에이전트 연구 프로토타입:
- 동시에 10개 작업 수행
- 리서치, 쇼핑, 여행 예약 자동화
- AI Ultra 전용 ($149.99/월 상당)&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;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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google AI Pro는 2025년 생성형 AI 시장에서 &lt;b&gt;가성비 킹&lt;/b&gt;으로 자리매김하고 있다. 연 140,000원으로 최첨단 AI 모델, 영상/이미지 생성, 개발자 도구, 2TB 스토리지까지 모두 누릴 수 있는 기회는 흔치 않다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 &lt;b&gt;가족 공유 기능&lt;/b&gt;을 활용하면 6명이 1인당 연 23,333원(월 1,944원)만으로 모든 혜택을 나눌 수 있어, 경쟁사 대비 압도적인 가격 경쟁력을 자랑한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;크리에이터, 개발자, 학생 모두에게 올인원 솔루션을 제공하는 Google AI Pro, 할인 기간을 놓치지 말자.&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;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://one.google.com/intl/ko_kr/about/google-ai-plans/&quot;&gt;Google One 공식 사이트&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://gemini.google/kr/subscriptions/&quot;&gt;Gemini 구독 페이지&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://9to5google.com/2025/12/24/google-ai-pro-ultra-features/&quot;&gt;9to5Google - AI Pro vs Ultra 비교&lt;/a&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/481</guid>
      <comments>https://somaz.tistory.com/481#entry481comment</comments>
      <pubDate>Wed, 31 Dec 2025 00:00:44 +0900</pubDate>
    </item>
    <item>
      <title>Kubernetes 환경에서 Redis Redlock 구현하기: 분산 락의 완전한 이해</title>
      <link>https://somaz.tistory.com/445</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;분산 시스템에서 동시성 제어는 항상 까다로운 문제다. 여러 인스턴스가 동시에 같은 리소스에 접근하려 할 때, 데이터 일관성을 보장하고 race condition을 방지하기 위해서는 적절한 락(Lock) 메커니즘이 필요하다.&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;color: #000000;&quot;&gt;Redis를 사용한 분산 락 구현 시, 단순한 SET NX 명령어만으로는 네트워크 파티션이나 Redis 인스턴스 장애 상황에서 안전성을 보장하기 어렵다. 이런 문제를 해결하기 위해 Redis 창시자 Salvatore Sanfilippo가 제안한 것이 바로 &lt;b&gt;Redlock 알고리즘&lt;/b&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;color: #000000;&quot;&gt;이 글에서는 Redlock의 동작 원리부터 Kubernetes 환경에서의 실제 구현 방법, 그리고 운영 시 주의사항까지 상세히 알아본다. 특히 많은 개발자들이 놓치기 쉬운 Kubernetes StatefulSet 환경에서의 함정과 이를 해결하는 방법을 중점적으로 다룬다.&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;&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;2568&quot; data-origin-height=&quot;1632&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GIVH6/btsPQC2EHMK/4KeAYX7e9votl9MGsBuKpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GIVH6/btsPQC2EHMK/4KeAYX7e9votl9MGsBuKpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GIVH6/btsPQC2EHMK/4KeAYX7e9votl9MGsBuKpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGIVH6%2FbtsPQC2EHMK%2F4KeAYX7e9votl9MGsBuKpk%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;2568&quot; height=&quot;1632&quot; data-origin-width=&quot;2568&quot; data-origin-height=&quot;1632&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  관련 글&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/149&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.09.26 - [Open Source Software] - Redis(Remote Dictionary Server)란?&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/410&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2025.04.02 - [CS 지식] - [CS 지식20.] OS 캐시와 디스크 I/O: MySQL, Redis 퍼포먼스 분석&lt;/a&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redlock 알고리즘이란?&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 개념&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redlock은 &lt;b&gt;여러 독립적인 Redis 인스턴스&lt;/b&gt;를 사용하여 분산 환경에서 안전하고 신뢰할 수 있는 락을 구현하는 알고리즘이다. 핵심 아이디어는 간단하다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라이언트가 락을 획득하려면 N개의 독립적인 Redis 인스턴스 중 과반수(N/2 + 1) 이상에서 락을 성공적으로 획득해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;color: #000000;&quot;&gt;왜 여러 인스턴스가 필요한가?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단일 Redis 인스턴스를 사용할 경우 발생할 수 있는 문제들&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Single Point of Failure&lt;/b&gt;: Redis 서버 장애 시 전체 락 시스템 마비&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;네트워크 파티션&lt;/b&gt;: 클라이언트와 Redis 간 연결 문제 시 잘못된 락 상태&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;클럭 드리프트&lt;/b&gt;: 서버 시간 차이로 인한 TTL 오차&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redlock은 이런 문제들을 &lt;b&gt;분산과 과반수 합의&lt;/b&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redlock 동작 원리 심화&lt;/span&gt;&lt;/h2&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;color: #000000;&quot;&gt;1. 락 획득 과정&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redlock의 락 획득 과정을 단계별로 살펴보자&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754983908127&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def acquire_lock(resource_name, ttl):
    start_time = current_time()
    successful_locks = 0
    unique_value = generate_unique_id()
    
    # 모든 Redis 인스턴스에 동시에 락 요청
    for redis_instance in redis_instances:
        if redis_instance.set(resource_name, unique_value, px=ttl, nx=True):
            successful_locks += 1
    
    elapsed_time = current_time() - start_time
    drift = (ttl * 0.01) + 2  # 클럭 드리프트 보정
    
    # 성공 조건: 과반수 + 유효 시간 남음
    if successful_locks &amp;gt;= (len(redis_instances) / 2 + 1):
        validity_time = ttl - elapsed_time - drift
        if validity_time &amp;gt; 0:
            return True, validity_time
    
    # 실패 시 모든 인스턴스에서 락 해제
    release_lock(resource_name, unique_value)
    return False, 0&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;&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;color: #000000;&quot;&gt;2. 성공 조건&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;락 획득이 성공으로 간주되려면 두 조건을 모두 만족해야 한다.&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;과반수 합의&lt;/b&gt;: N/2 + 1 개 이상의 인스턴스에서 락 획득 성공&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;유효 시간&lt;/b&gt;: TTL에서 소요 시간과 클럭 드리프트를 뺀 값이 양수&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 락 해제 과정&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;락 해제는 &lt;b&gt;원자적(Atomic)&lt;/b&gt;으로 수행되어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754983949399&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- Lua 스크립트로 원자적 해제
if redis.call(&quot;get&quot;, KEYS[1]) == ARGV[1] then
    return redis.call(&quot;del&quot;, KEYS[1])
else
    return 0
end&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;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;Kubernetes 환경에서 흔한 실수&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;많은 개발자들이 Kubernetes에서 Redis를 StatefulSet으로 배포하면서 Redlock이 자동으로 동작할 것이라고 생각한다. 하지만 현실은 다르다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제 상황&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754984003071&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 이런 구성으로는 Redlock이 제대로 동작하지 않는다
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-cluster
spec:
  replicas: 3  # 3개 Pod가 생성되지만...

---
apiVersion: v1
kind: Service
metadata:
  name: redis-service
spec:
  clusterIP: None   # Headless Service
  selector:
    app: redis-cluster&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_1754984020524&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 이 코드는 실제로는 1개 연결만 생성한다!
const redis = new Redis({host: 'redis-service', port: 6379});
const redlock = new Redlock([redis]);  // ❌ 단일 연결!&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;왜 동작하지 않는가?&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Headless Service 한계&lt;/b&gt;: DNS는 여러 IP를 반환하지만, 대부분의 Redis 클라이언트는 첫 번째 IP만 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;독립성 부족&lt;/b&gt;: 같은 클러스터 내 Pod들은 동일한 네트워크 환경을 공유&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;클라이언트 인식&lt;/b&gt;: Redis 클라이언트가 여러 인스턴스를 개별적으로 인식하지 못함&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;올바른 해결 방법들&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;방법 1: 개별 Service 생성 (권장)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가장 확실한 방법은 각 Redis Pod에 대해 개별 Service를 생성하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754984074187&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Pod별 개별 Service
apiVersion: v1
kind: Service
metadata:
  name: redis-0
spec:
  selector:
    app: redis-cluster
    statefulset.kubernetes.io/pod-name: redis-cluster-0
  ports:
    - port: 6379
      targetPort: 6379

---
apiVersion: v1
kind: Service
metadata:
  name: redis-1
spec:
  selector:
    app: redis-cluster
    statefulset.kubernetes.io/pod-name: redis-cluster-1
  ports:
    - port: 6379
      targetPort: 6379

---
apiVersion: v1
kind: Service
metadata:
  name: redis-2
spec:
  selector:
    app: redis-cluster
    statefulset.kubernetes.io/pod-name: redis-cluster-2
  ports:
    - port: 6379
      targetPort: 6379&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;방법 2: Pod Anti-Affinity 적용&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서로 다른 노드에 Pod를 배치하여 진정한 독립성을 확보한다&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754984108407&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: StatefulSet
metadata:
  name: redis-cluster
spec:
  template:
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - redis-cluster
            topologyKey: kubernetes.io/hostname&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;방법 3: DNS 기반 동적 접근&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;더 고급 방법으로는 DNS SRV 레코드를 활용한 동적 인스턴스 발견이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754984129936&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const dns = require('dns').promises;

async function getRedisInstances() {
  const addresses = await dns.lookup('redis-service', { all: true });
  return addresses.map(addr =&amp;gt; ({
    host: addr.address,
    port: 6379
  }));
}

async function createRedlock() {
  const instances = await getRedisInstances();
  return new Redlock(instances.map(config =&amp;gt; new Redis(config)));
}&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;실제 구현 예시&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Node.js 구현&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754984155362&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const Redis = require('ioredis');
const Redlock = require('redlock');

class RedlockService {
  constructor() {
    // 개별 Service들을 사용한 연결
    this.redisClients = [
      new Redis({
        host: 'redis-0.default.svc.cluster.local',
        port: 6379,
        retryDelayOnFailover: 100,
        maxRetriesPerRequest: 3
      }),
      new Redis({
        host: 'redis-1.default.svc.cluster.local',
        port: 6379,
        retryDelayOnFailover: 100,
        maxRetriesPerRequest: 3
      }),
      new Redis({
        host: 'redis-2.default.svc.cluster.local',
        port: 6379,
        retryDelayOnFailover: 100,
        maxRetriesPerRequest: 3
      })
    ];

    this.redlock = new Redlock(this.redisClients, {
      retryCount: 3,
      retryDelay: 200,
      retryJitter: 200,
      driftFactor: 0.01,
      clockDriftMs: 2
    });

    this.setupEventHandlers();
  }

  setupEventHandlers() {
    this.redisClients.forEach((client, index) =&amp;gt; {
      client.on('connect', () =&amp;gt; {
        console.log(`Redis-${index} 연결 성공`);
      });
      
      client.on('error', (err) =&amp;gt; {
        console.error(`Redis-${index} 오류:`, err.message);
      });
    });

    this.redlock.on('clientError', (err) =&amp;gt; {
      console.error('Redlock 클라이언트 오류:', err);
    });
  }

  async acquireLock(resource, ttl = 10000) {
    try {
      console.log(`락 획득 시도: ${resource}`);
      const lock = await this.redlock.acquire([resource], ttl);
      console.log(`락 획득 성공: ${resource}`);
      return lock;
    } catch (error) {
      console.error(`락 획득 실패: ${resource}`, error.message);
      throw error;
    }
  }

  async releaseLock(lock) {
    try {
      await lock.release();
      console.log(`락 해제 성공: ${lock.resources}`);
    } catch (error) {
      console.error(`락 해제 실패:`, error.message);
      throw error;
    }
  }
}

// 사용 예시
async function criticalSection() {
  const redlockService = new RedlockService();
  
  try {
    const lock = await redlockService.acquireLock('user-action-123', 15000);
    
    try {
      // 임계 영역에서 수행할 작업
      console.log('중요한 작업 수행 중...');
      await performCriticalOperation();
      console.log('작업 완료');
    } finally {
      await redlockService.releaseLock(lock);
    }
  } catch (error) {
    console.error('작업 실패:', error.message);
  }
}&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;&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;color: #000000;&quot;&gt;Java 구현 (Redisson 사용)&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1754984206266&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

@Service
public class RedlockService {
    
    private final RedissonClient redissonClient;
    
    public RedlockService() {
        Config config = new Config();
        config.useReplicatedServers()
            .addNodeAddress(&quot;redis://redis-0.default.svc.cluster.local:6379&quot;)
            .addNodeAddress(&quot;redis://redis-1.default.svc.cluster.local:6379&quot;)
            .addNodeAddress(&quot;redis://redis-2.default.svc.cluster.local:6379&quot;);
        
        this.redissonClient = Redisson.create(config);
    }
    
    public boolean executeWithLock(String lockName, int ttlSeconds, Runnable task) {
        RLock lock = redissonClient.getLock(lockName);
        
        try {
            if (lock.tryLock(10, ttlSeconds, TimeUnit.SECONDS)) {
                try {
                    log.info(&quot;락 획득 성공: {}&quot;, lockName);
                    task.run();
                    return true;
                } finally {
                    lock.unlock();
                    log.info(&quot;락 해제 완료: {}&quot;, lockName);
                }
            } else {
                log.warn(&quot;락 획득 실패: {}&quot;, lockName);
                return false;
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error(&quot;락 획득 중 인터럽트: {}&quot;, lockName, e);
            return 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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;운영 시 주의사항&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 클럭 동기화&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redlock의 핵심은 시간 기반 TTL이므로 서버 간 시간 동기화가 매우 중요하다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754984261939&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# NTP 동기화 상태 확인
chrony sources -v

# 클럭 드리프트 최소화 설정
echo &quot;server time.google.com iburst&quot; &amp;gt;&amp;gt; /etc/chrony.conf
systemctl restart chronyd&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 적절한 TTL 설정&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TTL은 예상 작업 시간의 2-3배로 설정하는 것이 안전하다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754984284737&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const expectedWorkTime = 5000;  // 5초
const safetyMargin = 2;
const ttl = expectedWorkTime * safetyMargin;  // 10초&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 네트워크 타임아웃 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754984302085&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const redisOptions = {
  connectTimeout: 100,    // 100ms
  commandTimeout: 200,    // 200ms
  retryDelayOnFailover: 100,
  maxRetriesPerRequest: 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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 모니터링 메트릭&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로덕션 환경에서는 다음 메트릭들을 모니터링해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754984324511&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Prometheus 메트릭 예시
- redlock_acquire_success_total
- redlock_acquire_failure_total  
- redlock_acquire_duration_seconds
- redlock_validity_time_remaining
- redis_connection_failures_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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. 장애 시나리오 대비&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754984405783&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 락 연장 로직
async function extendLockIfNeeded(lock, workTimeRemaining) {
  if (lock.validity &amp;lt; workTimeRemaining + 1000) {  // 1초 여유
    try {
      const extendedLock = await lock.extend(10000);
      console.log('락 연장 성공');
      return extendedLock;
    } catch (error) {
      console.error('락 연장 실패:', error.message);
      throw new Error('작업 시간 부족으로 중단');
    }
  }
  return lock;
}&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;대안 솔루션과의 비교&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;vs. Database-based Locking&lt;/span&gt;&lt;/h4&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redlock&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Database Lock&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;성능&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매우 빠름&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;상대적으로 느림&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;복잡성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단순함&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;일관성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Eventually Consistent&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Strongly Consistent&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;장애 복구&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 TTL&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;vs. Consul/etcd Locking&lt;/span&gt;&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 95px;&quot; border=&quot;1&quot; data-ke-style=&quot;style8&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redlock&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Database Lock&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;인프라 복잡성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;성능&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매우 빠름&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;빠름&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;합의 알고리즘&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;과반수 투표&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Raft&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;생태계&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redis 중심&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;Raft&lt;/b&gt;(Reliable, Replicated, Redundant, And Fault-Tolerant)는 분산 시스템에서 &lt;b&gt;합의(Consensus)&lt;/b&gt;를 달성하기 위한 알고리즘이다. 2013년 Diego Ongaro와 John Ousterhout이 Stanford에서 개발했으며, 기존의 Paxos 알고리즘보다 &lt;b&gt;이해하기 쉽고 구현하기 간단하다&lt;/b&gt;는 것이 가장 큰 장점이다.&lt;/i&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;&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;
&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;color: #000000;&quot;&gt;언제 Redlock을 사용해야 할까?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redlock이 적합한 경우&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;높은 처리량&lt;/b&gt;이 필요한 환경&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;짧은 지연시간&lt;/b&gt;이 중요한 실시간 시스템&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이미 &lt;b&gt;Redis 인프라&lt;/b&gt;가 구축된 환경&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;단순한 락&lt;/b&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redlock을 피해야 할 경우&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;강한 일관성&lt;/b&gt;이 절대적으로 필요한 금융 시스템&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;네트워크 파티션&lt;/b&gt;이 빈번한 환경&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;클럭 동기화&lt;/b&gt;가 어려운 환경&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;복잡한 분산 합의&lt;/b&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;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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Redlock은 분산 환경에서 락을 구현하는 좋은 솔루션이지만, 올바른 구현이 중요하다. 특히 Kubernetes 환경에서는 단순히 StatefulSet을 배포하는 것만으로는 충분하지 않으며, 각 Redis 인스턴스에 대한 독립적인 접근 경로를 확보해야 한다.&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;color: #000000;&quot;&gt;핵심은 &lt;b&gt;진정한 독립성&lt;/b&gt;을 확보하는 것이다. 서로 다른 노드에 배치된 Redis 인스턴스들에 개별적으로 접근할 수 있는 구조를 만들고, 적절한 클럭 동기화와 모니터링을 통해 안정성을 확보해야 한다.&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;color: #000000;&quot;&gt;또한 Redlock이 만능 해결책은 아님을 인식해야 한다. 요구사항에 따라 데이터베이스 기반 락이나 Consul/etcd 같은 대안이 더 적합할 수 있다. 중요한 것은 각 솔루션의 특성을 이해하고, 상황에 맞는 최적의 선택을 하는 것이다.&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;color: #000000;&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;&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;
&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;
&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://redis.io/docs/reference/patterns/distributed-locks/&quot;&gt;Redis Redlock 공식 문서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html&quot;&gt;Redlock 논란에 대한 Martin Kleppmann의 분석&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/&quot;&gt;Kubernetes StatefulSet 공식 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://redis.io/docs/reference/cluster-spec/&quot;&gt;Redis 클러스터링 베스트 프랙티스&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Container Orchestration/Kubernetes</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/445</guid>
      <comments>https://somaz.tistory.com/445#entry445comment</comments>
      <pubDate>Wed, 24 Dec 2025 07:48:09 +0900</pubDate>
    </item>
    <item>
      <title>Python 예외 처리와 컨텍스트 매니저 완벽 가이드</title>
      <link>https://somaz.tistory.com/471</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예외 처리(Exception Handling)와 컨텍스트 매니저(Context Manager)는 견고하고 안전한 Python 코드를 작성하는 핵심 기능이다. 오류를 우아하게 처리하고, 리소스를 안전하게 관리하는 방법을 알아보자.&lt;/span&gt;&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-origin-width=&quot;2134&quot; data-origin-height=&quot;2402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yvIr9/dJMb9LxdJ5H/AC0LBEIzeHDFzeKxu7Xf30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yvIr9/dJMb9LxdJ5H/AC0LBEIzeHDFzeKxu7Xf30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yvIr9/dJMb9LxdJ5H/AC0LBEIzeHDFzeKxu7Xf30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyvIr9%2FdJMb9LxdJ5H%2FAC0LBEIzeHDFzeKxu7Xf30%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;2134&quot; height=&quot;2402&quot; data-origin-width=&quot;2134&quot; data-origin-height=&quot;2402&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;1. 예외 처리 기본&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;try-except 기본 구조&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;nimrod&quot;&gt;&lt;code&gt;try:
    # 예외가 발생할 수 있는 코드
    result = 10 / 0
except ZeroDivisionError:
    # 예외 처리
    print(&quot;0으로 나눌 수 없습니다!&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 예외 처리하기&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;def safe_divide(a, b):
    try:
        result = a / b
        return result
    except ZeroDivisionError:
        print(&quot;0으로 나눌 수 없습니다!&quot;)
        return None
    except TypeError:
        print(&quot;숫자만 입력 가능합니다!&quot;)
        return None

print(safe_divide(10, 2))     # 5.0
print(safe_divide(10, 0))     # 0으로 나눌 수 없습니다! None
print(safe_divide(10, &quot;a&quot;))   # 숫자만 입력 가능합니다! None
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 예외를 한 번에 처리&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;try:
    value = int(input(&quot;숫자 입력: &quot;))
    result = 100 / value
except (ValueError, ZeroDivisionError) as e:
    print(f&quot;오류 발생: {e}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 예외 객체 활용&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예외 정보 얻기&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;try:
    with open(&quot;없는파일.txt&quot;, &quot;r&quot;) as f:
        content = f.read()
except FileNotFoundError as e:
    print(f&quot;파일을 찾을 수 없습니다: {e}&quot;)
    print(f&quot;예외 타입: {type(e)}&quot;)
    print(f&quot;예외 메시지: {str(e)}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 예외 잡기 (비권장)&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;try:
    # 위험한 코드
    risky_operation()
except Exception as e:
    print(f&quot;예상치 못한 오류: {e}&quot;)
    # 하지만 가능하면 구체적인 예외를 잡는 게 좋음!
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. else와 finally&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;else: 예외가 발생하지 않았을 때&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;def read_file(filename):
    try:
        f = open(filename, 'r')
    except FileNotFoundError:
        print(&quot;파일이 없습니다.&quot;)
    else:
        # try 블록이 성공했을 때만 실행
        content = f.read()
        f.close()
        return content

print(read_file(&quot;data.txt&quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;finally: 항상 실행&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;def process_file(filename):
    f = None
    try:
        f = open(filename, 'r')
        data = f.read()
        return data
    except FileNotFoundError:
        print(&quot;파일을 찾을 수 없습니다.&quot;)
        return None
    finally:
        # 예외 발생 여부와 관계없이 항상 실행
        if f:
            f.close()
            print(&quot;파일을 닫았습니다.&quot;)

process_file(&quot;test.txt&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;완전한 구조&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;nimrod&quot;&gt;&lt;code&gt;try:
    # 예외가 발생할 수 있는 코드
    result = dangerous_operation()
except SomeException as e:
    # 예외 처리
    handle_error(e)
else:
    # 예외가 발생하지 않았을 때
    print(&quot;성공!&quot;)
finally:
    # 항상 실행 (정리 작업)
    cleanup()
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 예외 발생시키기 (raise)&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 예외 발생&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;isbl&quot;&gt;&lt;code&gt;def validate_age(age):
    if age &amp;lt; 0:
        raise ValueError(&quot;나이는 음수일 수 없습니다!&quot;)
    if age &amp;gt; 150:
        raise ValueError(&quot;나이가 너무 많습니다!&quot;)
    return True

try:
    validate_age(-5)
except ValueError as e:
    print(f&quot;유효성 검사 실패: {e}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예외 다시 발생시키기&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;def process_data(data):
    try:
        # 데이터 처리
        result = complex_operation(data)
    except Exception as e:
        print(f&quot;로그: 오류 발생 - {e}&quot;)
        raise  # 예외를 다시 발생시켜 상위로 전파

try:
    process_data(None)
except Exception:
    print(&quot;상위에서 예외 처리&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. 커스텀 예외 만들기&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자 정의 예외&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;class InsufficientFundsError(Exception):
    &quot;&quot;&quot;잔액 부족 예외&quot;&quot;&quot;
    def __init__(self, balance, amount):
        self.balance = balance
        self.amount = amount
        message = f&quot;잔액 부족: {balance}원 있음, {amount}원 필요&quot;
        super().__init__(message)

class BankAccount:
    def __init__(self, balance):
        self.balance = balance
    
    def withdraw(self, amount):
        if amount &amp;gt; self.balance:
            raise InsufficientFundsError(self.balance, amount)
        self.balance -= amount
        return self.balance

# 사용
account = BankAccount(10000)
try:
    account.withdraw(15000)
except InsufficientFundsError as e:
    print(f&quot;출금 실패: {e}&quot;)
    print(f&quot;현재 잔액: {e.balance}원&quot;)
    print(f&quot;필요 금액: {e.amount}원&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예외 계층 구조&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;class ValidationError(Exception):
    &quot;&quot;&quot;기본 검증 오류&quot;&quot;&quot;
    pass

class EmailValidationError(ValidationError):
    &quot;&quot;&quot;이메일 검증 오류&quot;&quot;&quot;
    pass

class PasswordValidationError(ValidationError):
    &quot;&quot;&quot;비밀번호 검증 오류&quot;&quot;&quot;
    pass

def validate_user(email, password):
    if &quot;@&quot; not in email:
        raise EmailValidationError(&quot;유효하지 않은 이메일 형식&quot;)
    if len(password) &amp;lt; 8:
        raise PasswordValidationError(&quot;비밀번호는 8자 이상이어야 합니다&quot;)

try:
    validate_user(&quot;test&quot;, &quot;123&quot;)
except EmailValidationError as e:
    print(f&quot;이메일 오류: {e}&quot;)
except PasswordValidationError as e:
    print(f&quot;비밀번호 오류: {e}&quot;)
except ValidationError as e:
    # 모든 검증 오류를 잡음
    print(f&quot;검증 오류: {e}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6. 컨텍스트 매니저 (Context Manager)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨텍스트 매니저는 with 문과 함께 사용하여 리소스를 안전하게 관리한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;with 문 기본&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;# 나쁜 예: 파일을 닫지 않을 수 있음
f = open(&quot;data.txt&quot;, &quot;r&quot;)
data = f.read()
f.close()  # 예외 발생 시 실행 안 됨!

# 좋은 예: 자동으로 파일 닫힘
with open(&quot;data.txt&quot;, &quot;r&quot;) as f:
    data = f.read()
# 여기서 자동으로 f.close() 호출됨
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 리소스 관리&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;with open(&quot;input.txt&quot;, &quot;r&quot;) as infile, open(&quot;output.txt&quot;, &quot;w&quot;) as outfile:
    content = infile.read()
    outfile.write(content.upper())
# 두 파일 모두 자동으로 닫힘
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;7. 커스텀 컨텍스트 매니저 만들기&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클래스 기반 컨텍스트 매니저&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;class DatabaseConnection:
    def __init__(self, db_name):
        self.db_name = db_name
        self.connection = None
    
    def __enter__(self):
        print(f&quot;{self.db_name} 연결 중...&quot;)
        self.connection = f&quot;Connection to {self.db_name}&quot;
        return self.connection
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print(f&quot;{self.db_name} 연결 종료&quot;)
        if exc_type is not None:
            print(f&quot;예외 발생: {exc_type.__name__}: {exc_val}&quot;)
        # False 반환 시 예외가 전파됨
        # True 반환 시 예외를 억제
        return False

# 사용
with DatabaseConnection(&quot;mydb&quot;) as conn:
    print(f&quot;연결됨: {conn}&quot;)
    # 작업 수행
# 자동으로 연결 종료
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예외 처리가 있는 컨텍스트 매니저&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;class FileManager:
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode
        self.file = None
    
    def __enter__(self):
        try:
            self.file = open(self.filename, self.mode)
            return self.file
        except FileNotFoundError:
            print(f&quot;파일을 찾을 수 없습니다: {self.filename}&quot;)
            raise
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.file:
            self.file.close()
            print(&quot;파일이 안전하게 닫혔습니다.&quot;)
        
        if exc_type is IOError:
            print(&quot;IO 오류가 발생했지만 처리했습니다.&quot;)
            return True  # 예외를 억제
        return False

# 사용
try:
    with FileManager(&quot;test.txt&quot;, &quot;r&quot;) as f:
        content = f.read()
except FileNotFoundError:
    print(&quot;파일 처리 실패&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;8. @contextmanager 데코레이터&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;더 간단하게 컨텍스트 매니저를 만들 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;from contextlib import contextmanager

@contextmanager
def timer(name):
    import time
    print(f&quot;{name} 시작&quot;)
    start = time.time()
    try:
        yield  # with 블록이 실행되는 지점
    finally:
        end = time.time()
        print(f&quot;{name} 완료: {end - start:.4f}초&quot;)

# 사용
with timer(&quot;데이터 처리&quot;):
    # 시간을 측정할 작업
    total = sum(range(1000000))
    print(f&quot;합계: {total}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;값을 반환하는 컨텍스트 매니저&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;from contextlib import contextmanager

@contextmanager
def temporary_setting(setting_name, new_value):
    import os
    old_value = os.environ.get(setting_name)
    
    # 설정 변경
    os.environ[setting_name] = new_value
    print(f&quot;{setting_name} 변경: {old_value} &amp;rarr; {new_value}&quot;)
    
    try:
        yield new_value  # with 문에 값 전달
    finally:
        # 원래 설정으로 복구
        if old_value is None:
            os.environ.pop(setting_name, None)
        else:
            os.environ[setting_name] = old_value
        print(f&quot;{setting_name} 복구: {new_value} &amp;rarr; {old_value}&quot;)

# 사용
with temporary_setting(&quot;DEBUG&quot;, &quot;true&quot;) as debug:
    print(f&quot;디버그 모드: {debug}&quot;)
    # 디버그 환경에서 작업
# 자동으로 원래 설정으로 복구
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;9. 실전 예제: 파일 처리 시스템&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;from contextlib import contextmanager
import json
import logging

# 로깅 설정
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class FileProcessingError(Exception):
    &quot;&quot;&quot;파일 처리 오류&quot;&quot;&quot;
    pass

@contextmanager
def safe_file_operation(filename, mode='r'):
    &quot;&quot;&quot;안전한 파일 작업을 위한 컨텍스트 매니저&quot;&quot;&quot;
    file_obj = None
    try:
        logger.info(f&quot;파일 열기: {filename} (모드: {mode})&quot;)
        file_obj = open(filename, mode, encoding='utf-8')
        yield file_obj
    except FileNotFoundError:
        logger.error(f&quot;파일을 찾을 수 없습니다: {filename}&quot;)
        raise FileProcessingError(f&quot;파일 없음: {filename}&quot;)
    except PermissionError:
        logger.error(f&quot;파일 접근 권한이 없습니다: {filename}&quot;)
        raise FileProcessingError(f&quot;권한 없음: {filename}&quot;)
    except Exception as e:
        logger.error(f&quot;예상치 못한 오류: {e}&quot;)
        raise
    finally:
        if file_obj:
            file_obj.close()
            logger.info(f&quot;파일 닫기: {filename}&quot;)

class DataProcessor:
    def __init__(self, input_file, output_file):
        self.input_file = input_file
        self.output_file = output_file
    
    def process(self):
        &quot;&quot;&quot;데이터 처리 메인 로직&quot;&quot;&quot;
        try:
            data = self._read_data()
            processed_data = self._transform_data(data)
            self._write_data(processed_data)
            logger.info(&quot;데이터 처리 완료&quot;)
            return True
        except FileProcessingError as e:
            logger.error(f&quot;파일 처리 실패: {e}&quot;)
            return False
        except json.JSONDecodeError as e:
            logger.error(f&quot;JSON 파싱 실패: {e}&quot;)
            return False
        except Exception as e:
            logger.error(f&quot;처리 중 오류 발생: {e}&quot;)
            return False
    
    def _read_data(self):
        &quot;&quot;&quot;파일에서 데이터 읽기&quot;&quot;&quot;
        with safe_file_operation(self.input_file, 'r') as f:
            return json.load(f)
    
    def _transform_data(self, data):
        &quot;&quot;&quot;데이터 변환&quot;&quot;&quot;
        if not isinstance(data, list):
            raise ValueError(&quot;데이터는 리스트 형식이어야 합니다&quot;)
        
        processed = []
        for item in data:
            if 'name' not in item or 'value' not in item:
                logger.warning(f&quot;잘못된 데이터 형식: {item}&quot;)
                continue
            
            processed.append({
                'name': item['name'].upper(),
                'value': item['value'] * 2,
                'processed': True
            })
        
        return processed
    
    def _write_data(self, data):
        &quot;&quot;&quot;파일에 데이터 쓰기&quot;&quot;&quot;
        with safe_file_operation(self.output_file, 'w') as f:
            json.dump(data, f, indent=2, ensure_ascii=False)

# 사용 예시
if __name__ == &quot;__main__&quot;:
    processor = DataProcessor(&quot;input.json&quot;, &quot;output.json&quot;)
    
    # 입력 파일 생성 (테스트용)
    with safe_file_operation(&quot;input.json&quot;, &quot;w&quot;) as f:
        json.dump([
            {&quot;name&quot;: &quot;apple&quot;, &quot;value&quot;: 10},
            {&quot;name&quot;: &quot;banana&quot;, &quot;value&quot;: 20},
            {&quot;name&quot;: &quot;cherry&quot;, &quot;value&quot;: 15}
        ], f)
    
    # 데이터 처리
    success = processor.process()
    if success:
        print(&quot;✅ 처리 성공!&quot;)
    else:
        print(&quot;❌ 처리 실패!&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10. 주요 내장 예외&lt;/span&gt;&lt;/h3&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예외&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;발생 상황&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ValueError&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;잘못된 값&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TypeError&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;잘못된 타입&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;KeyError&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;딕셔너리 키 없음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IndexError&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인덱스 범위 초과&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;FileNotFoundError&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파일 없음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ZeroDivisionError&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0으로 나눔&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AttributeError&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;속성 없음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ImportError&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;임포트 실패&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;RuntimeError&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일반적 실행 오류&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;StopIteration&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;반복자 종료&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;핵심 요약&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예외 처리 베스트 프랙티스&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;구체적인 예외를 잡아라&lt;/b&gt;: except Exception보다는 except ValueError&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예외를 무시하지 마라&lt;/b&gt;: 최소한 로그라도 남겨라&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;finally로 정리하라&lt;/b&gt;: 리소스는 항상 정리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;커스텀 예외를 만들어라&lt;/b&gt;: 도메인에 맞는 예외 정의&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;컨텍스트 매니저를 사용하라&lt;/b&gt;: with로 안전하게&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨텍스트 매니저 베스트 프랙티스&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;리소스 관리에 사용&lt;/b&gt;: 파일, 데이터베이스, 네트워크 연결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;임시 상태 관리&lt;/b&gt;: 설정 변경, 트랜잭션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;시간 측정, 로깅&lt;/b&gt;: 성능 모니터링&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;@contextmanager 활용&lt;/b&gt;: 간단한 경우 데코레이터 사용&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;&lt;span style=&quot;color: #000000;&quot;&gt;결론&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예외 처리와 컨텍스트 매니저를 잘 활용하면&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예상치 못한 오류에 대응 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리소스 누수 방지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드의 안정성과 신뢰성 향상&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&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;&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;
&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;Python Errors and Exceptions: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.python.org/3/tutorial/errors.html&quot;&gt;https://docs.python.org/3/tutorial/errors.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Built-in Exceptions: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.python.org/3/library/exceptions.html&quot;&gt;https://docs.python.org/3/library/exceptions.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;contextlib: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.python.org/3/library/contextlib.html&quot;&gt;https://docs.python.org/3/library/contextlib.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;color: #000000;&quot;&gt;Python Tips: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://book.pythontips.com/en/latest/context_managers.html&quot;&gt;https://book.pythontips.com/en/latest/context_managers.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Python Engineer: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.python-engineer.com/courses/advancedpython/21-contextmanagers/&quot;&gt;https://www.python-engineer.com/courses/advancedpython/21-contextmanagers/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Earthly Blog: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://earthly.dev/blog/python-with-statement/&quot;&gt;https://earthly.dev/blog/python-with-statement/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Siv Scripts: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://alysivji.com/managing-resources-with-context-managers-pythonic.html&quot;&gt;https://alysivji.com/managing-resources-with-context-managers-pythonic.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Launguage</category>
      <category>Python</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/471</guid>
      <comments>https://somaz.tistory.com/471#entry471comment</comments>
      <pubDate>Fri, 19 Dec 2025 00:00:03 +0900</pubDate>
    </item>
    <item>
      <title>Kubernetes Local Storage Solutions: OpenEBS vs Longhorn vs Rook Ceph 완전 비교 가이드</title>
      <link>https://somaz.tistory.com/444</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes 환경에서 상태를 가진 애플리케이션(Stateful Applications)을 운영할 때, 적절한 스토리지 솔루션 선택은 매우 중요하다. 기존의 NFS나 클라우드 기반 스토리지의 한계를 극복하고자 많은 조직들이 local storage 기반의 분산 블록 스토리지 솔루션을 도입하고 있다.&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;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CNCF 샌드박스 프로젝트로, Container Attached Storage(CAS) 개념을 도입한 클라우드 네이티브 스토리지 솔루션이다. 다양한 스토리지 엔진을 제공하여 다양한 워크로드 요구사항을 충족한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Longhorn&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rancher에서 개발한 분산 블록 스토리지로, 단순함과 사용 편의성에 중점을 둔 솔루션이다. 직관적인 웹 UI와 강력한 백업/복원 기능을 제공한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rook Ceph&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Kubernetes 환경에서 Ceph 클러스터를 자동화하여 관리하는 솔루션입니다. 엔터프라이즈급 성능과 안정성을 제공하며, Object, Block, File 스토리지를 모두 지원한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  관련 글&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/289&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.02.20 - [Open Source Software] - Rook-Ceph란?&lt;/a&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;아키텍처 비교&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS 아키텍처&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2564&quot; data-origin-height=&quot;1644&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dkd4Tz/btsPNDuNztG/yUJKO43GoomQtCEJRbJvkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dkd4Tz/btsPNDuNztG/yUJKO43GoomQtCEJRbJvkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dkd4Tz/btsPNDuNztG/yUJKO43GoomQtCEJRbJvkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdkd4Tz%2FbtsPNDuNztG%2FyUJKO43GoomQtCEJRbJvkK%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;2564&quot; height=&quot;1644&quot; data-origin-width=&quot;2564&quot; data-origin-height=&quot;1644&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특징&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;멀티 엔진 아키텍처&lt;/b&gt;: 워크로드별 최적화된 엔진 선택 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Container Attached Storage&lt;/b&gt;: 각 볼륨마다 전용 컨트롤러 파드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;마이크로서비스 기반&lt;/b&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;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;
&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;color: #000000;&quot;&gt;Longhorn 아키텍처&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3138&quot; data-origin-height=&quot;1298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biQxMa/btsPO4kDVyg/tyvo405MeKF30Kp9HOO2K0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biQxMa/btsPO4kDVyg/tyvo405MeKF30Kp9HOO2K0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biQxMa/btsPO4kDVyg/tyvo405MeKF30Kp9HOO2K0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiQxMa%2FbtsPO4kDVyg%2Ftyvo405MeKF30Kp9HOO2K0%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;3138&quot; height=&quot;1298&quot; data-origin-width=&quot;3138&quot; data-origin-height=&quot;1298&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특징&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;단순한 아키텍처&lt;/b&gt;: 이해하기 쉬운 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;iSCSI 기반&lt;/b&gt;: 표준 블록 스토리지 프로토콜 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;볼륨별 엔진&lt;/b&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;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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rook Ceph 아키텍처&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1148&quot; data-origin-height=&quot;1618&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vkuDR/btsPPJOmV3Z/szgC6VIWVnt9wCqwNeCPk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vkuDR/btsPPJOmV3Z/szgC6VIWVnt9wCqwNeCPk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vkuDR/btsPPJOmV3Z/szgC6VIWVnt9wCqwNeCPk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvkuDR%2FbtsPPJOmV3Z%2FszgC6VIWVnt9wCqwNeCPk1%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;1148&quot; height=&quot;1618&quot; data-origin-width=&quot;1148&quot; data-origin-height=&quot;1618&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특징&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;엔터프라이즈급 아키텍처&lt;/b&gt;: 검증된 Ceph 기반&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;다중 스토리지 타입&lt;/b&gt;: Block, Object, File 모두 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고도로 분산된 구조&lt;/b&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;상세 기능 비교&lt;/span&gt;&lt;/h2&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;color: #000000;&quot;&gt;스토리지 엔진 및 기능&lt;/span&gt;&lt;/h3&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Longhorn&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rook Ceph&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스토리지 엔진&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LocalPV, Jiva, cStor, Mayastor&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단일 엔진&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ceph RBD, CephFS, RGW&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복제 방식&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동기/비동기 선택 가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동기식 복제&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동기식 복제&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스냅샷&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅ (엔진별 상이)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;백업&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅ (S3, NFS)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅ (Multiple backends)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;암호화&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;압축&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅ (cStor, Mayastor)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;❌&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;씬 프로비저닝&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;❌&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QoS&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;❌&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 비교&lt;/span&gt;&lt;/h3&gt;
&lt;table style=&quot;color: #333333; text-align: start; border-collapse: collapse; width: 100%; height: 161px;&quot; border=&quot;1&quot; data-ke-style=&quot;style8&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Longhorn&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rook Ceph&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지연시간(Latency)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음-중간 (엔진별)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처리량(Throughput)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음 (Mayastor)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매우 높음&lt;/span&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;&lt;span style=&quot;color: #000000;&quot;&gt;IOPS&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음 (LocalPV)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매우 높음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오버헤드&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음-중간&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간-높음&lt;/span&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;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 사용량&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관리 및 운영&lt;/span&gt;&lt;/h3&gt;
&lt;table style=&quot;color: #333333; text-align: start; border-collapse: collapse; width: 100%; height: 148px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Longhorn&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rook Ceph&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설치 복잡도&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;웹 UI&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅ (기본적)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅ (풍부한 기능)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅ (Ceph Dashboard)&lt;/span&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;&lt;span style=&quot;color: #000000;&quot;&gt;모니터링&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Prometheus/Grafana&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;내장 + Prometheus&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;풍부한 메트릭&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로그 관리&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본적&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;상세함&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매우 상세함&lt;/span&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;&lt;span style=&quot;color: #000000;&quot;&gt;업그레이드&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;간단&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복잡&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제 해결&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쉬움&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;어려움&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문서화&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;양호&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우수&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;워크로드별 성능 분석&lt;/span&gt;&lt;/h2&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;color: #000000;&quot;&gt;데이터베이스 워크로드&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 순위(랜덤 I/O 집약적 워크로드)&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS (Mayastor/LocalPV): 8.5/10&lt;/span&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;color: #000000;&quot;&gt;NVMe 최적화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮은 지연시간&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rook Ceph: 8.0/10&lt;/span&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;color: #000000;&quot;&gt;BlueStore 최적화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;높은 IOPS&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Longhorn: 7.0/10&lt;/span&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;color: #000000;&quot;&gt;안정적이지만 상대적으로 낮은 성능&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;빅데이터/분석 워크로드(순차 I/O 집약적 워크로드)&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 순위&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rook Ceph: 9.0/10&lt;/span&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;color: #000000;&quot;&gt;뛰어난 처리량&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;병렬 처리 최적화&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS (cStor): 8.0/10&lt;/span&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;color: #000000;&quot;&gt;ZFS 기반 최적화&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Longhorn: 7.5/10&lt;/span&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;color: #000000;&quot;&gt;간단하지만 제한적 성능&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;웹 애플리케이션(혼합 I/O 패턴)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 순위&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS (LocalPV): 9.0/10&lt;/span&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;color: #000000;&quot;&gt;로컬 스토리지 성능&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Longhorn: 8.5/10&lt;/span&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;color: #000000;&quot;&gt;균형 잡힌 성능&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rook Ceph: 8.0/10&lt;/span&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;color: #000000;&quot;&gt;안정적이지만 오버헤드 존재&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;
&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;color: #000000;&quot;&gt;실제 구현 사례&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS 구현 예시&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754970875103&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# StorageClass for Database
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: openebs-mayastor-nvme
provisioner: io.openebs.csi-mayastor
parameters:
  repl: &quot;3&quot;
  protocol: &quot;nvmf&quot;
  fsType: &quot;ext4&quot;
allowVolumeExpansion: true
volumeBindingMode: Immediate

---
# PVC for High-Performance Database
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-data
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: openebs-mayastor-nvme
  resources:
    requests:
      storage: 100Gi&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Longhorn 구현 예시&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754970951772&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# StorageClass for General Purpose
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: longhorn-ssd
provisioner: driver.longhorn.io
allowVolumeExpansion: true
reclaimPolicy: Retain
parameters:
  numberOfReplicas: &quot;2&quot;
  staleReplicaTimeout: &quot;30&quot;
  fromBackup: &quot;&quot;
  fsType: &quot;ext4&quot;

---
# PVC with Backup Policy
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-data
  annotations:
    longhorn.io/recurring-jobs: |
      [
        {
          &quot;name&quot;: &quot;backup&quot;,
          &quot;task&quot;: &quot;backup&quot;,
          &quot;cron&quot;: &quot;0 2 * * *&quot;,
          &quot;retain&quot;: 7
        }
      ]
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn-ssd
  resources:
    requests:
      storage: 50Gi&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rook Ceph 구현 예시&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754971003641&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# CephCluster Configuration
apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
  name: rook-ceph
  namespace: rook-ceph
spec:
  cephVersion:
    image: quay.io/ceph/ceph:v17.2.6
  dataDirHostPath: /var/lib/rook
  mon:
    count: 3
    allowMultiplePerNode: false
  mgr:
    count: 2
  dashboard:
    enabled: true
    ssl: true
  storage:
    useAllNodes: true
    useAllDevices: true
    config:
      osdsPerDevice: &quot;1&quot;

---
# StorageClass for Enterprise Workload  
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: rook-ceph-block-ssd
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
  clusterID: rook-ceph
  pool: replicapool
  imageFormat: &quot;2&quot;
  imageFeatures: layering
  csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
  csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
allowVolumeExpansion: 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;&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;
&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;color: #000000;&quot;&gt;총 소유 비용(TCO) 분석&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하드웨어 요구사항&lt;/span&gt;&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 76px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;솔루션&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최소 노드 수&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CPU 요구사항&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메모리 요구사항&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예상 비용&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2-4 코어/노드&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4-8GB/노드&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1Gbps&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Longhorn&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1-2 코어/노드&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2-4GB/노드&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1Gbps&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rook Ceph&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3-5&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4-8 코어/노드&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;8-16GB/노드&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10Gbps&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용 사례별 추천 가이드&lt;/span&gt;&lt;/h2&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;color: #000000;&quot;&gt;스타트업/중소기업 (10-50 노드)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추천: Longhorn&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;이유&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;낮은 학습 곡선&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최소한의 운영 인력&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;충분한 성능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;적합한 워크로드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;웹 애플리케이션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;소규모 데이터베이스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CI/CD 파이프라인&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;중견기업 (50-200 노드)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추천: OpenEBS&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;이유&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다양한 워크로드 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 최적화 옵션&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;적당한 복잡도&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;적합한 워크로드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마이크로서비스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중규모 데이터베이스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실시간 분석&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;대기업/엔터프라이즈 (200+ 노드)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추천: Rook Ceph&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;이유&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;엔터프라이즈급 성능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;뛰어난 확장성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다양한 스토리지 타입&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;적합한 워크로드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대규모 데이터베이스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;빅데이터 분석&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AI/ML 워크로드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;특수 환경별 추천&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;엣지 컴퓨팅&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;추천: OpenEBS LocalPV&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최소한의 리소스 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;멀티클라우드&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;추천: Longhorn&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라우드 간 이식성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고성능 컴퓨팅(HPC)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;추천: Rook Ceph&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;병렬 I/O 최적화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결론 및 권장사항&lt;/span&gt;&lt;/h2&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;color: #000000;&quot;&gt;최종 추천 매트릭스&lt;/span&gt;&lt;/h3&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시나리오&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1순위&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2순위&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3순위&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;소규모 환경&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Longhorn&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS LocalPV&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS Jiva&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;중간 규모 환경&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Longhorn&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rook Ceph&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;대규모 엔터프라이즈&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rook Ceph&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Longhorn&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고성능 요구&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS Mayastor&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rook Ceph&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Longhorn&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;단순함 우선&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Longhorn&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS LocalPV&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS Jiva&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;다양한 워크로드&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenEBS&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rook Ceph&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Longhorn&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;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;color: #000000;&quot;&gt;핵심 결론&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Longhorn&lt;/b&gt;: 단순함과 사용 편의성을 중시하는 환경에 최적. 중소규모 조직과 Kubernetes 초보자에게 강력 추천.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;OpenEBS&lt;/b&gt;: 다양한 워크로드와 성능 요구사항을 가진 환경에 최적. 유연성과 확장성을 동시에 원하는 조직에 적합.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Rook Ceph&lt;/b&gt;: 엔터프라이즈급 성능과 안정성이 필요한 대규모 환경에 최적. 복잡하지만 가장 강력한 기능 제공.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성공적인 도입을 위해선?&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;단계적 접근&lt;/b&gt;: 파일럿 프로젝트부터 시작하여 점진적으로 확대&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;충분한 테스트&lt;/b&gt;: 프로덕션 적용 전 다양한 시나리오에서 충분한 테스트 수행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;모니터링 강화&lt;/b&gt;: 초기 단계에서 상세한 모니터링 구축&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;백업 전략&lt;/b&gt;: 마이그레이션 전 반드시 백업 계획 수립&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;팀 역량&lt;/b&gt;: 선택한 솔루션에 대한 팀의 이해도와 역량 개발&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;span style=&quot;color: #000000;&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;&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;공식 문서&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://openebs.io/docs&quot;&gt;OpenEBS Official Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://longhorn.io/docs&quot;&gt;Longhorn Official Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://rook.io/docs/rook/latest/&quot;&gt;Rook Ceph Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/&quot;&gt;Kubernetes Storage Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아키텍처 및 설계 가이드&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/openebs/openebs/blob/master/contribute/design/README.md&quot;&gt;OpenEBS Architecture Guide&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://longhorn.io/docs/latest/concepts/&quot;&gt;Longhorn Architecture&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.ceph.com/en/latest/architecture/&quot;&gt;Ceph Architecture Overview&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/container-storage-interface/spec&quot;&gt;Container Storage Interface (CSI) Specification&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Container Orchestration/Kubernetes</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/444</guid>
      <comments>https://somaz.tistory.com/444#entry444comment</comments>
      <pubDate>Wed, 17 Dec 2025 07:29:48 +0900</pubDate>
    </item>
    <item>
      <title>GitLab VM 장애 복구: NBD 마운트와 백업 복원으로 서비스 재구축하기</title>
      <link>https://somaz.tistory.com/443</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&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 style=&quot;color: #000000;&quot;&gt;GitLab VM이 갑작스럽게 rescue 모드로 돌입하면서 서비스가 중단되는 치명적인 장애가 발생했다. GRUB 복구도 불가능한 상황에서, 다행히 중요한 데이터들은 NFS에 저장되어 있어 완전한 데이터 손실은 피할 수 있었다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 포스팅에서는 NBD(Network Block Device)를 활용해 손상된 VM의 qcow2 디스크를 마운트하고, 백업 데이터를 추출한 후 새로운 환경에서 GitLab을 복구하는 전체 과정을 다룬다. 또한 복구 과정에서 발생한 Prometheus 권한 문제와 GitLab 버전 다운그레이드 방법도 함께 소개한다.&lt;/span&gt;&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-origin-width=&quot;1612&quot; data-origin-height=&quot;1194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Wkcow/btsPI8AI0sK/faDbiHRqTfHcqWTmQOf9e1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Wkcow/btsPI8AI0sK/faDbiHRqTfHcqWTmQOf9e1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Wkcow/btsPI8AI0sK/faDbiHRqTfHcqWTmQOf9e1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWkcow%2FbtsPI8AI0sK%2FfaDbiHRqTfHcqWTmQOf9e1%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;1612&quot; height=&quot;1194&quot; data-origin-width=&quot;1612&quot; data-origin-height=&quot;1194&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제 상황 분석&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 증상&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;GitLab VM이 rescue 모드로 부팅됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GRUB 복구 시도 실패&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;긍정적 요소&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;핵심 데이터가 NFS에 안전하게 보관됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VM 디스크 파일(qcow2)에 접근 가능&lt;/span&gt;&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복구 과정&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. NBD를 이용한 GitLab VM 디스크 마운트&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;손상된 VM에 직접 접근할 수 없는 상황에서 NBD(Network Block Device)를 활용해 qcow2 디스크 이미지를 마운트했다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754459375564&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# NBD 모듈 로드
modprobe nbd max_part=8

# GitLab VM의 qcow2 디스크를 NBD 디바이스로 연결
qemu-nbd --connect=/dev/nbd0 /path/to/gitlab-vm.qcow2&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 파티션 확인 및 마운트&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754459390539&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 연결된 디스크의 파티션 확인
fdisk -l /dev/nbd0

# GitLab 루트 파티션 마운트 (보통 /dev/nbd0p1)
mkdir -p /mnt/gitlab-root
mount /dev/nbd0p1 /mnt/gitlab-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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 백업 데이터 추출&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마운트된 디스크에서 GitLab 관련 중요 데이터들을 체계적으로 추출했다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1754459410383&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# GitLab 설정 백업 (8.7M)
cp -r /mnt/gitlab-root/etc/gitlab /tmp/gitlab-config-backup

# GitLab 데이터 백업 (1.6G) - 주요 데이터베이스와 리포지토리
cp -r /mnt/gitlab-root/var/opt/gitlab /tmp/gitlab-data-backup

# 홈 디렉토리 백업 (88K)
cp -r /mnt/gitlab-root/home /tmp/home-backup&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추출된 데이터 구성 예시&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;gitlab-config-backup (8.7M)&lt;/b&gt;: `/etc/gitlab/` - GitLab 설정 파일들&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;gitlab-data-backup (1.6G)&lt;/b&gt;: `/var/opt/gitlab/` - 데이터베이스, 리포지토리, 로그 등&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;home-backup (88K)&lt;/b&gt;: `/home/` - 사용자 홈 디렉토리&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 마운트 해제 및 정리&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1754459461021&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 마운트 해제
umount /mnt/gitlab-root

# NBD 연결 해제
qemu-nbd --disconnect /dev/nbd0&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. GitLab 백업 복원&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;새로운 환경에서 추출한 백업을 활용해 GitLab을 복원했다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754459514005&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo gitlab-backup restore BACKUP=1754284731_2025_08_04_18.1.1&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6. Prometheus 권한 문제 해결&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복구 과정에서 Prometheus 서비스가 다음과 같은 권한 오류로 실패했다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754459534597&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;caller=query_logger.go:114 level=error component=activeQueryTracker 
msg=&quot;Error opening query log file&quot; 
file=/mnt/nfs/gitlab/prometheus/data/queries.active 
err=&quot;open /mnt/nfs/gitlab/prometheus/data/queries.active: permission denied&quot;
panic: Unable to create mmap-ed active query log&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;span style=&quot;color: #000000;&quot;&gt;이 문제는 NFS 마운트된 디렉토리의 소유권 문제로 발생했으며, 다음 명령으로 해결했다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754459558387&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo chown -R gitlab-prometheus:gitlab-prometheus /mnt/nfs/gitlab/prometheus/&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;7. GitLab 다운그레이드&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존버전이 18.1.1 이였고, 최신버전이 18.2.1 이였는데 생각없이 최신버전으로 다운받았다가 백업이 동작하지 않아서 GitLab 버전을 다운그레이드해야 했다. 자동 백업을 건너뛰고 특정 버전으로 강제 다운그레이드를 수행했다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754459633116&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 자동 백업 스킵 설정
touch /etc/gitlab/skip-auto-backup

# 특정 버전으로 다운그레이드
sudo apt-get install -y gitlab-ce=18.1.1-ce.0 --allow-downgrades&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;
&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;color: #000000;&quot;&gt;교훈과 개선 사항&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 모니터링 강화&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;Prometheus와 같은 모니터링 서비스의 상태를 더욱 면밀히 관찰&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NFS 권한 문제에 대한 사전 점검 체계 구축&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 백업 전략 개선&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;정기적인 전체 시스템 백업 외에 설정 파일 별도 백업&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 버전 관리 정책&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;GitLab 업그레이드 전 충분한 테스트 환경 검증&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 인프라 아키텍처&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;단일 VM 의존도 감소를 위한 고가용성 구성 검토&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&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;
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 GitLab 장애는 예상치 못한 시스템 실패 상황에서 NBD를 활용한 디스크 마운트 기법의 유용성을 확인할 수 있는 사례였다. GRUB 복구가 불가능한 극한 상황에서도 qcow2 디스크에서 직접 데이터를 추출할 수 있다는 점은 가상화 환경의 큰 장점 중 하나다.&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;color: #000000;&quot;&gt;특히 NFS에 데이터를 분산 저장한 아키텍처 덕분에 완전한 데이터 손실을 피할 수 있었지만, 동시에 권한 관리의 복잡성도 경험했다. Prometheus 권한 문제처럼 세밀한 부분까지 고려한 운영 절차가 필요함을 다시 한번 깨달았다.&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;color: #000000;&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NFS 권한 문제 관련 자료&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://serverfault.com/questions/240897/how-to-properly-set-permissions-for-nfs-folder-permission-denied-on-mounting-en&quot;&gt;How to properly set permissions for NFS folder? Permission denied on mounting end - Server Fault&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://unix.stackexchange.com/questions/252812/user-permissions-in-nfs-mounted-directory&quot;&gt;User permissions in NFS mounted directory - Unix &amp;amp; Linux Stack Exchange&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.suse.com/support/kb/doc/?id=000019272&quot;&gt;NFS clients getting 'permission denied', even when ownership and permissions are correct - SUSE Support&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Prometheus NFS 권한 문제 관련 자료&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/prometheus/prometheus/issues/5976&quot;&gt;err=&quot;open /prometheus/queries.active: permission denied&quot; - Prometheus GitHub Issue&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://stackoverflow.com/questions/64578730/permission-denied-on-etc-prometheus-prometheus-yml-cannot-deploy-prom-promethe&quot;&gt;Permission denied on /etc/prometheus/prometheus.yml; cannot deploy prom/prometheus container - Stack Overflow&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://access.redhat.com/solutions/5670841&quot;&gt;Prometheus pods not able to mount NFS volumes after upgrading the cluster - Red Hat Customer Portal&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GitLab 관련 공식 문서&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.gitlab.com/ee/administration/backup_restore/&quot;&gt;GitLab Backup and Restore - Official Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.gitlab.com/ee/administration/monitoring/prometheus/&quot;&gt;GitLab Prometheus Monitoring - Official Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NBD와 qcow2 관련 자료&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://qemu.readthedocs.io/en/latest/tools/qemu-nbd.html&quot;&gt;QEMU NBD Documentation&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://nbd.sourceforge.io/&quot;&gt;Linux NBD - Network Block Device&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Trouble Shooting</category>
      <category>backup</category>
      <category>gitlab</category>
      <category>Restore</category>
      <category>Troubleshooting</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/443</guid>
      <comments>https://somaz.tistory.com/443#entry443comment</comments>
      <pubDate>Wed, 10 Dec 2025 06:58:41 +0900</pubDate>
    </item>
    <item>
      <title>Python 상속과 다형성 완벽 가이드</title>
      <link>https://somaz.tistory.com/470</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;상속(Inheritance)과 다형성(Polymorphism)은 객체지향 프로그래밍의 핵심 개념이다. 코드 재사용성을 높이고, 유지보수를 쉽게 만들며, 확장 가능한 구조를 설계할 수 있게 해준다.&lt;/span&gt;&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-origin-width=&quot;2146&quot; data-origin-height=&quot;2018&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JEOLF/dJMb87trvND/Iw0GJTwMkctlBpqxS2lrb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JEOLF/dJMb87trvND/Iw0GJTwMkctlBpqxS2lrb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JEOLF/dJMb87trvND/Iw0GJTwMkctlBpqxS2lrb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJEOLF%2FdJMb87trvND%2FIw0GJTwMkctlBpqxS2lrb0%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;2146&quot; height=&quot;2018&quot; data-origin-width=&quot;2146&quot; data-origin-height=&quot;2018&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;color: #000000;&quot;&gt;1. 상속 기본 개념&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 상속 구조&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        return &quot;동물이 소리를 냅니다&quot;
    
    def move(self):
        return f&quot;{self.name}이(가) 움직입니다&quot;

class Dog(Animal):  # Animal을 상속
    def speak(self):  # 메서드 오버라이딩
        return &quot;멍멍!&quot;

class Cat(Animal):
    def speak(self):
        return &quot;야옹!&quot;

# 사용
dog = Dog(&quot;바둑이&quot;)
cat = Cat(&quot;나비&quot;)

print(dog.name)      # 바둑이 (상속받은 속성)
print(dog.speak())   # 멍멍! (오버라이딩된 메서드)
print(dog.move())    # 바둑이이(가) 움직입니다 (상속받은 메서드)
print(cat.speak())   # 야옹!
&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;용어 정리&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;부모 클래스(Parent Class)&lt;/b&gt; / 슈퍼 클래스(Super Class) / 베이스 클래스(Base Class): Animal&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;자식 클래스(Child Class)&lt;/b&gt; / 서브 클래스(Sub Class) / 파생 클래스(Derived Class): Dog, Cat&lt;/span&gt;&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. super() 함수&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`super()` 는 부모 클래스의 메서드를 호출할 때 사용한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;super()로 부모 클래스 초기화&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def introduce(self):
        return f&quot;안녕하세요, {self.name}입니다. {self.age}살입니다.&quot;

class Student(Person):
    def __init__(self, name, age, student_id):
        super().__init__(name, age)  # 부모 클래스의 __init__ 호출
        self.student_id = student_id
    
    def introduce(self):
        parent_intro = super().introduce()  # 부모의 introduce() 호출
        return f&quot;{parent_intro} 학번: {self.student_id}&quot;

student = Student(&quot;김철수&quot;, 20, &quot;2024001&quot;)
print(student.introduce())
# 안녕하세요, 김철수입니다. 20살입니다. 학번: 2024001
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;super() vs 직접 호출&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;class Parent:
    def method(self):
        return &quot;부모 메서드&quot;

class Child(Parent):
    def method(self):
        # 방법 1: super() 사용 (권장)
        return super().method() + &quot; + 자식 메서드&quot;
    
    def method_old_style(self):
        # 방법 2: 직접 호출 (비권장)
        return Parent.method(self) + &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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;`super()` 를 사용하는 이유&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다중 상속에서 올바른 MRO를 따름&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드 유지보수가 쉬움&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;3. 메서드 오버라이딩 (Method Overriding)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자식 클래스가 부모 클래스의 메서드를 재정의하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;class Shape:
    def __init__(self, color):
        self.color = color
    
    def area(self):
        raise NotImplementedError(&quot;서브클래스에서 구현해야 합니다&quot;)
    
    def describe(self):
        return f&quot;{self.color} 도형&quot;

class Circle(Shape):
    def __init__(self, color, radius):
        super().__init__(color)
        self.radius = radius
    
    def area(self):  # 오버라이딩
        return 3.14159 * self.radius ** 2
    
    def describe(self):  # 오버라이딩
        return f&quot;{super().describe()}: 원 (반지름: {self.radius})&quot;

class Rectangle(Shape):
    def __init__(self, color, width, height):
        super().__init__(color)
        self.width = width
        self.height = height
    
    def area(self):  # 오버라이딩
        return self.width * self.height
    
    def describe(self):
        return f&quot;{super().describe()}: 직사각형 ({self.width}x{self.height})&quot;

circle = Circle(&quot;빨강&quot;, 5)
rectangle = Rectangle(&quot;파랑&quot;, 4, 6)

print(circle.area())       # 78.53975
print(circle.describe())   # 빨강 도형: 원 (반지름: 5)
print(rectangle.area())    # 24
print(rectangle.describe()) # 파랑 도형: 직사각형 (4x6)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;4. 다형성 (Polymorphism)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다형성은 같은 인터페이스로 다른 동작을 수행하는 것을 의미한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;class Bird:
    def fly(self):
        return &quot;새가 하늘을 납니다&quot;

class Airplane:
    def fly(self):
        return &quot;비행기가 하늘을 납니다&quot;

class Butterfly:
    def fly(self):
        return &quot;나비가 하늘을 날아다닙니다&quot;

# 다형성: 같은 메서드 이름, 다른 동작
def make_it_fly(flying_object):
    print(flying_object.fly())

bird = Bird()
plane = Airplane()
butterfly = Butterfly()

make_it_fly(bird)       # 새가 하늘을 납니다
make_it_fly(plane)      # 비행기가 하늘을 납니다
make_it_fly(butterfly)  # 나비가 하늘을 날아다닙니다
&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;덕 타이핑 (Duck Typing):&lt;/b&gt; Python은 &quot;오리처럼 걷고, 오리처럼 꽥꽥거리면, 그것은 오리다&quot;라는 철학을 따른다. 타입보다는 동작이 중요하다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;# 상속 관계가 없어도 같은 메서드만 있으면 OK!
class Dog:
    def speak(self):
        return &quot;멍멍!&quot;

class Cat:
    def speak(self):
        return &quot;야옹!&quot;

class Robot:
    def speak(self):
        return &quot;삐빅!&quot;

def animal_sound(obj):
    print(obj.speak())  # 어떤 타입이든 speak()만 있으면 됨

animal_sound(Dog())    # 멍멍!
animal_sound(Cat())    # 야옹!
animal_sound(Robot())  # 삐빅!
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;5. 추상 클래스 (Abstract Base Class)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추상 클래스는 인스턴스를 생성할 수 없으며, 자식 클래스에서 반드시 구현해야 하는 메서드를 정의한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;from abc import ABC, abstractmethod

class Vehicle(ABC):  # ABC를 상속
    def __init__(self, brand):
        self.brand = brand
    
    @abstractmethod
    def start_engine(self):
        &quot;&quot;&quot;서브클래스에서 반드시 구현해야 함&quot;&quot;&quot;
        pass
    
    @abstractmethod
    def stop_engine(self):
        &quot;&quot;&quot;서브클래스에서 반드시 구현해야 함&quot;&quot;&quot;
        pass
    
    def honk(self):
        return f&quot;{self.brand} 경적: 빵빵!&quot;

class Car(Vehicle):
    def start_engine(self):
        return f&quot;{self.brand} 자동차 시동을 켭니다&quot;
    
    def stop_engine(self):
        return f&quot;{self.brand} 자동차 시동을 끕니다&quot;

class Motorcycle(Vehicle):
    def start_engine(self):
        return f&quot;{self.brand} 오토바이 시동을 켭니다&quot;
    
    def stop_engine(self):
        return f&quot;{self.brand} 오토바이 시동을 끕니다&quot;

# vehicle = Vehicle(&quot;현대&quot;)  # 에러! 추상 클래스는 인스턴스 생성 불가
car = Car(&quot;현대&quot;)
motorcycle = Motorcycle(&quot;혼다&quot;)

print(car.start_engine())       # 현대 자동차 시동을 켭니다
print(car.honk())               # 현대 경적: 빵빵!
print(motorcycle.start_engine()) # 혼다 오토바이 시동을 켭니다
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;6. 다중 상속 (Multiple Inheritance)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Python은 여러 부모 클래스로부터 상속받을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;class Flyable:
    def fly(self):
        return &quot;날 수 있습니다&quot;

class Swimmable:
    def swim(self):
        return &quot;헤엄칠 수 있습니다&quot;

class Duck(Flyable, Swimmable):
    def __init__(self, name):
        self.name = name
    
    def quack(self):
        return &quot;꽥꽥!&quot;

duck = Duck(&quot;도널드&quot;)
print(duck.fly())    # 날 수 있습니다
print(duck.swim())   # 헤엄칠 수 있습니다
print(duck.quack())  # 꽥꽥!
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MRO (Method Resolution Order)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다중 상속에서 메서드 탐색 순서를 나타낸다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;class A:
    def method(self):
        return &quot;A&quot;

class B(A):
    def method(self):
        return &quot;B&quot;

class C(A):
    def method(self):
        return &quot;C&quot;

class D(B, C):
    pass

d = D()
print(d.method())     # B
print(D.mro())        # MRO 확인
# [&amp;lt;class '__main__.D'&amp;gt;, &amp;lt;class '__main__.B'&amp;gt;, 
#  &amp;lt;class '__main__.C'&amp;gt;, &amp;lt;class '__main__.A'&amp;gt;, &amp;lt;class 'object'&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;MRO 규칙&lt;/b&gt;&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;자식 클래스가 먼저&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;부모 클래스는 선언 순서대로&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;같은 부모는 한 번만&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최상위는 항상 object&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;7. 실전 예제: 직원 관리 시스템&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 개념을 활용한 완전한 예제다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;from abc import ABC, abstractmethod
from datetime import datetime

class Employee(ABC):
    &quot;&quot;&quot;직원 추상 클래스&quot;&quot;&quot;
    
    employee_count = 0
    
    def __init__(self, name, employee_id):
        self.name = name
        self.employee_id = employee_id
        self.hire_date = datetime.now()
        Employee.employee_count += 1
    
    @abstractmethod
    def calculate_salary(self):
        &quot;&quot;&quot;급여 계산 - 서브클래스에서 구현 필수&quot;&quot;&quot;
        pass
    
    @abstractmethod
    def get_role(self):
        &quot;&quot;&quot;직책 반환 - 서브클래스에서 구현 필수&quot;&quot;&quot;
        pass
    
    def get_info(self):
        return f&quot;[{self.employee_id}] {self.name} - {self.get_role()}&quot;
    
    @classmethod
    def get_employee_count(cls):
        return cls.employee_count

class Developer(Employee):
    &quot;&quot;&quot;개발자 클래스&quot;&quot;&quot;
    
    def __init__(self, name, employee_id, programming_languages, level):
        super().__init__(name, employee_id)
        self.programming_languages = programming_languages
        self.level = level  # junior, senior, lead
    
    def calculate_salary(self):
        base_salary = 3000000
        level_bonus = {
            'junior': 0,
            'senior': 1000000,
            'lead': 2000000
        }
        return base_salary + level_bonus.get(self.level, 0)
    
    def get_role(self):
        return f&quot;{self.level.capitalize()} Developer&quot;
    
    def write_code(self, language):
        if language in self.programming_languages:
            return f&quot;{self.name}이(가) {language}로 코드를 작성합니다&quot;
        return f&quot;{self.name}은(는) {language}를 모릅니다&quot;

class Designer(Employee):
    &quot;&quot;&quot;디자이너 클래스&quot;&quot;&quot;
    
    def __init__(self, name, employee_id, specialty):
        super().__init__(name, employee_id)
        self.specialty = specialty  # UI/UX, Graphic, etc.
    
    def calculate_salary(self):
        return 3500000
    
    def get_role(self):
        return f&quot;{self.specialty} Designer&quot;
    
    def create_design(self, project):
        return f&quot;{self.name}이(가) {project}의 디자인을 작성합니다&quot;

class Manager(Employee):
    &quot;&quot;&quot;매니저 클래스&quot;&quot;&quot;
    
    def __init__(self, name, employee_id, team_size):
        super().__init__(name, employee_id)
        self.team_size = team_size
        self.team_members = []
    
    def calculate_salary(self):
        base_salary = 5000000
        team_bonus = self.team_size * 100000
        return base_salary + team_bonus
    
    def get_role(self):
        return f&quot;Manager (팀원 {self.team_size}명)&quot;
    
    def add_team_member(self, employee):
        self.team_members.append(employee)
        self.team_size = len(self.team_members)
    
    def get_team_info(self):
        team_info = [f&quot;\n{self.name}의 팀:&quot;]
        for member in self.team_members:
            team_info.append(f&quot;  - {member.get_info()}&quot;)
        return &quot;\n&quot;.join(team_info)

# 다형성을 활용한 급여 계산
def print_salary_info(employees):
    print(&quot;=== 급여 명세서 ===&quot;)
    total = 0
    for emp in employees:
        salary = emp.calculate_salary()
        total += salary
        print(f&quot;{emp.get_info()}: {salary:,}원&quot;)
    print(f&quot;\n총 급여: {total:,}원&quot;)
    print(f&quot;총 직원 수: {Employee.get_employee_count()}명&quot;)

# 사용 예시
dev1 = Developer(&quot;김개발&quot;, &quot;DEV001&quot;, [&quot;Python&quot;, &quot;JavaScript&quot;], &quot;senior&quot;)
dev2 = Developer(&quot;이코드&quot;, &quot;DEV002&quot;, [&quot;Java&quot;, &quot;Kotlin&quot;], &quot;junior&quot;)
designer = Designer(&quot;박디자인&quot;, &quot;DES001&quot;, &quot;UI/UX&quot;)
manager = Manager(&quot;최매니저&quot;, &quot;MGR001&quot;, 0)

# 팀 구성
manager.add_team_member(dev1)
manager.add_team_member(dev2)
manager.add_team_member(designer)

# 직원 목록
employees = [dev1, dev2, designer, manager]

# 다형성: 모든 직원 타입에 동일한 함수 적용
print_salary_info(employees)

print(manager.get_team_info())

print(f&quot;\n{dev1.write_code('Python')}&quot;)
print(designer.create_design(&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;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;출력&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;=== 급여 명세서 ===
[DEV001] 김개발 - Senior Developer: 4,000,000원
[DEV002] 이코드 - Junior Developer: 3,000,000원
[DES001] 박디자인 - UI/UX Designer: 3,500,000원
[MGR001] 최매니저 - Manager (팀원 3명): 5,300,000원

총 급여: 15,800,000원
총 직원 수: 4명

최매니저의 팀:
  - [DEV001] 김개발 - Senior Developer
  - [DEV002] 이코드 - Junior Developer
  - [DES001] 박디자인 - UI/UX Designer

김개발이(가) Python로 코드를 작성합니다
박디자인이(가) 쇼핑몰 앱의 디자인을 작성합니다
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;color: #000000;&quot;&gt;8. 상속 vs 컴포지션 (Composition)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항상 상속이 답은 아니다. &quot;is-a&quot; 관계일 때는 상속, &quot;has-a&quot; 관계일 때는 컴포지션을 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;# 상속 (is-a): 자동차는 차량이다
class Vehicle:
    pass

class Car(Vehicle):  # Car is a Vehicle
    pass

# 컴포지션 (has-a): 자동차는 엔진을 가지고 있다
class Engine:
    def start(self):
        return &quot;엔진 시동&quot;

class Car:
    def __init__(self):
        self.engine = Engine()  # Car has an Engine
    
    def start(self):
        return self.engine.start()
&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;언제 컴포지션을 사용할까?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;상속 계층이 너무 깊어질 때&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 기능을 유연하게 조합해야 할 때&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;has-a&quot; 관계가 더 명확할 때&lt;/span&gt;&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;&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;color: #000000;&quot;&gt;핵심 요약&lt;/span&gt;&lt;/h3&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;개념&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;언제 사용?&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;상속&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;부모 클래스의 기능을 물려받음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;is-a 관계, 코드 재사용&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;오버라이딩&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;부모 메서드를 재정의&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동작을 변경해야 할 때&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;super()&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;부모 클래스 메서드 호출&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;부모 기능 확장&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;다형성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;같은 인터페이스, 다른 동작&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;유연한 코드 설계&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;추상 클래스&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구현을 강제하는 템플릿&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인터페이스 정의&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;다중 상속&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 부모로부터 상속&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 기능 조합&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;컴포지션&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;객체를 포함&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;has-a 관계&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;
&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;&lt;span style=&quot;color: #000000;&quot;&gt;결론&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;상속과 다형성을 잘 활용하면&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드 재사용성이 높아진다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;유지보수가 쉬워진다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;확장 가능한 구조를 만들 수 있다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&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;&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;
&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;Python ABC: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.python.org/3/library/abc.html&quot;&gt;https://docs.python.org/3/library/abc.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Python MRO: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.python.org/3/howto/mro.html&quot;&gt;https://docs.python.org/3/howto/mro.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;color: #000000;&quot;&gt;GeeksforGeeks - MRO: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.geeksforgeeks.org/python/method-resolution-order-in-python-inheritance/&quot;&gt;https://www.geeksforgeeks.org/python/method-resolution-order-in-python-inheritance/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DataCamp - Inheritance: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.datacamp.com/tutorial/python-inheritance&quot;&gt;https://www.datacamp.com/tutorial/python-inheritance&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;AlmaBetter: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.almabetter.com/bytes/tutorials/python/python-inheritance-and-polymorphism&quot;&gt;https://www.almabetter.com/bytes/tutorials/python/python-inheritance-and-polymorphism&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DataFlair: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://data-flair.training/blogs/python-multiple-inheritance/&quot;&gt;https://data-flair.training/blogs/python-multiple-inheritance/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CoderzColumn: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://coderzcolumn.com/blogs/python/method-resolution-order-in-python-while-using-multiple-inheritance&quot;&gt;https://coderzcolumn.com/blogs/python/method-resolution-order-in-python-while-using-multiple-inheritance&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Launguage</category>
      <category>Python</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/470</guid>
      <comments>https://somaz.tistory.com/470#entry470comment</comments>
      <pubDate>Fri, 5 Dec 2025 00:00:51 +0900</pubDate>
    </item>
    <item>
      <title>KVM과 Cockpit을 활용한 가상화 환경 구축 가이드</title>
      <link>https://somaz.tistory.com/441</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;현대 IT 환경에서 가상화 기술은 서버 자원의 효율적 활용과 운영 비용 절감을 위한 필수 요소가 되었다. 특히 Linux 환경에서 KVM(Kernel-based Virtual Machine)은 높은 성능과 안정성을 제공하는 하이퍼바이저로 널리 사용되고 있다.&lt;/i&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 가이드에서는 Ubuntu/Debian 기반 시스템에서 KVM을 설치하고, 웹 기반 관리 도구인 Cockpit을 통해 직관적인 가상머신 관리 환경을 구축하는 방법을 상세히 알아보겠다. Cockpit을 활용하면 복잡한 명령어 없이도 브라우저를 통해 가상머신을 손쉽게 생성, 관리, 모니터링할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;4900&quot; data-origin-height=&quot;2558&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NvCCP/btsPEF5Gkry/h4aVkXrwywb84CPgbhqkkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NvCCP/btsPEF5Gkry/h4aVkXrwywb84CPgbhqkkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NvCCP/btsPEF5Gkry/h4aVkXrwywb84CPgbhqkkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNvCCP%2FbtsPEF5Gkry%2Fh4aVkXrwywb84CPgbhqkkk%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;4900&quot; height=&quot;2558&quot; data-origin-width=&quot;4900&quot; data-origin-height=&quot;2558&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1. 시스템 업데이트 및 사전 준비&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;먼저 패키지 목록을 최신화한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753859037987&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt update&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2. KVM 필수 패키지 설치&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;KVM 가상화 환경 구축에 필요한 핵심 패키지들을 설치한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1753859054146&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt install -y cpu-checker
sudo apt install -y qemu-kvm libvirt-daemon-system bridge-utils libguestfs-tools virt-manager&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&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;color: #000000;&quot;&gt;&lt;b&gt;cpu-checker: CPU 가상화 지원 여부 확인 도구&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;qemu-kvm: KVM 하이퍼바이저 핵심 패키지&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;libvirt-daemon-system: 가상머신 관리 데몬&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;bridge-utils: 네트워크 브리지 관리 도구&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;libguestfs-tools: 가상머신 디스크 이미지 조작 도구&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;virt-manager: GUI 기반 가상머신 관리 도구&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&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;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;color: #000000;&quot;&gt;&lt;b&gt;3. KVM 설치 확인&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;CPU 가상화 지원 확인&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753859081047&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo kvm-ok&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;정상적으로 설치되었다면 다음과 같은 메시지가 출력된다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753859095382&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;INFO: /dev/kvm exists
KVM acceleration can be used&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;자세한 내용은 아래의 글을 참고하길 바란다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/139&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.09.02 - [Understand different OS Concepts/Virtualization] - KVM 중첩 가상화 완벽 가이드: VT-x 설정부터 virsh, EPT, VPID까지 실무 적용법&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1753859116718&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;KVM 중첩 가상화 완벽 가이드: VT-x 설정부터 virsh, EPT, VPID까지 실무 적용법&quot; data-og-description=&quot;OverviewKVM(Kernel-based Virtual Machine)에서 중첩 가상화(Nested Virtualization)는 가상 머신(VM) 내부에서 또 다른 VM을 실행할 수 있게 해주는 기능이다. 이는 가상화 환경을 테스트하거나 CI/CD, 클라우드 플랫&quot; data-og-host=&quot;somaz.tistory.com&quot; data-og-source-url=&quot;https://somaz.tistory.com/139&quot; data-og-url=&quot;https://somaz.tistory.com/139&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cY5eGz/hyZqZmSQOK/wYbaPlVqqnj4Db22Ulmbk0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/MyExe/hyZqSnM8Ds/RWiapkv1cmT7gbq4eM21M0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/hszyK/hyZrqYN1R7/FjiyiHdGnMvu3AiPDTIYwk/img.png?width=600&amp;amp;height=600&amp;amp;face=0_0_600_600&quot;&gt;&lt;a href=&quot;https://somaz.tistory.com/139&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://somaz.tistory.com/139&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cY5eGz/hyZqZmSQOK/wYbaPlVqqnj4Db22Ulmbk0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/MyExe/hyZqSnM8Ds/RWiapkv1cmT7gbq4eM21M0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/hszyK/hyZrqYN1R7/FjiyiHdGnMvu3AiPDTIYwk/img.png?width=600&amp;amp;height=600&amp;amp;face=0_0_600_600');&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;KVM 중첩 가상화 완벽 가이드: VT-x 설정부터 virsh, EPT, VPID까지 실무 적용법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;OverviewKVM(Kernel-based Virtual Machine)에서 중첩 가상화(Nested Virtualization)는 가상 머신(VM) 내부에서 또 다른 VM을 실행할 수 있게 해주는 기능이다. 이는 가상화 환경을 테스트하거나 CI/CD, 클라우드 플랫&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;somaz.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;
&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;libvirt 버전 확인&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753859130535&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo virsh version&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;&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;color: #000000;&quot;&gt;&lt;b&gt;4. libvirt 서비스 활성화&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;libvirt 데몬의 상태를 확인하고 자동 시작을 설정한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753859152646&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo systemctl status libvirtd
sudo systemctl enable libvirtd&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;&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;color: #000000;&quot;&gt;&lt;b&gt;5. Cockpit 설치&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;웹 기반 시스템 관리 도구인 Cockpit과 가상머신 관리 플러그인을 설치한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753859171937&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt install -y cockpit cockpit-machines&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;6. Cockpit 보안 설정&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안상의 이유로 root 사용자의 Cockpit 접근을 제한한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753859198408&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo vi /etc/cockpit/disallowed-users&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;파일에 다음 내용을 추가한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753859211996&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;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;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;설정 변경 후 Cockpit 서비스를 재시작한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753859226425&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo systemctl restart cockpit&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;&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;color: #000000;&quot;&gt;&lt;b&gt;7. Cockpit 웹 인터페이스 접근&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;웹 브라우저를 통해 다음 URL로 접근한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753859246897&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;http://&amp;lt;서버_IP&amp;gt;:9090&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;시스템 사용자 계정으로 로그인하면 직관적인 웹 인터페이스를 통해 가상머신을 관리할 수 있다.&lt;/b&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;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;color: #000000;&quot;&gt;&lt;b&gt;8. VM 생성 후 Network 설정&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;color: #000000;&quot;&gt;&lt;b&gt;먼저 Cloud Image를 다운로드 한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753859360691&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Ubuntu 22.04 (jammy) Cloud Image
wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img

# Ubuntu 24.02 (Noble) Cloud Image
wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;아래는 생성 예시이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;1754&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxsDCA/btsPDaFxII0/U1opDKqkYFje6hLBHFpYs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxsDCA/btsPDaFxII0/U1opDKqkYFje6hLBHFpYs1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxsDCA/btsPDaFxII0/U1opDKqkYFje6hLBHFpYs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxsDCA%2FbtsPDaFxII0%2FU1opDKqkYFje6hLBHFpYs1%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;1672&quot; height=&quot;1754&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;1754&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;&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;네트워크 관련 문제는 아래의 글을 참고하길 바란다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;a style=&quot;background-color: #e6f5ff; color: #000000;&quot; href=&quot;https://somaz.tistory.com/436&quot;&gt;2025.07.25 - [Trouble Shooting] - Cockpit에서 VM 간 네트워크 통신 문제 해결하기&lt;/a&gt;&lt;/b&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&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;
&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;color: #000000;&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;이번 가이드를 통해 KVM과 Cockpit을 활용한 완전한 가상화 환경을 성공적으로 구축했습니다. 이제 다음과 같은 이점을 누릴 수 있다.&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;핵심 장점&lt;/b&gt;&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;사용자 친화적 관리: 복잡한 명령어 대신 직관적인 웹 인터페이스로 가상머신 관리&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실시간 모니터링: 시스템 자원 사용량과 가상머신 상태를 실시간으로 모니터링&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;원격 접근: 네트워크를 통해 어디서든 가상화 환경 관리 가능&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비용 효율성: 오픈소스 솔루션으로 라이선스 비용 절약&lt;/b&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안 권장사항&lt;/b&gt;&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;&lt;b&gt;정기적인 시스템 업데이트를 통한 보안 패치 적용&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;방화벽 설정을 통한 9090 포트 접근 제한&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;강력한 패스워드 정책 적용&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;SSL/TLS 인증서 적용을 통한 안전한 웹 접근&lt;/b&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;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;color: #000000;&quot;&gt;&lt;b&gt;KVM과 Cockpit의 조합은 개발 환경 구축부터 프로덕션 서버 운영까지 &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;다양한 용도로 활용할 수 있는 강력하고 안정적인 가상화 솔루션이다. &lt;/b&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;color: #000000;&quot;&gt;&lt;b&gt;이제 효율적인 가상화 환경에서 다양한 운영체제와 애플리케이션을 테스트하고 운영해보시기 바란다.&lt;/b&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;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&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;span style=&quot;color: #000000;&quot;&gt;KVM 공식 홈페이지: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.linux-kvm.org/&quot;&gt;https://www.linux-kvm.org/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;libvirt 공식 문서: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://libvirt.org/&quot;&gt;https://libvirt.org/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cockpit 프로젝트: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://cockpit-project.org/&quot;&gt;https://cockpit-project.org/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ubuntu KVM 가이드: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://ubuntu.com/server/docs/virtualization-libvirt&quot;&gt;https://ubuntu.com/server/docs/virtualization-libvirt&lt;/a&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Red Hat 가상화 가이드: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_and_managing_virtualization/&quot;&gt;https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_and_managing_virtualization/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QEMU 문서: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.qemu.org/documentation/&quot;&gt;https://www.qemu.org/documentation/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;libvirt Python API: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://libvirt.org/python.html&quot;&gt;https://libvirt.org/python.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;KVM 네트워킹 가이드: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://wiki.libvirt.org/page/Networking&quot;&gt;https://wiki.libvirt.org/page/Networking&lt;/a&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;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;span style=&quot;color: #000000;&quot;&gt;ibvirt 메일링 리스트: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://libvirt.org/contact.html&quot;&gt;https://libvirt.org/contact.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cockpit GitHub 저장소: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/cockpit-project/cockpit&quot;&gt;https://github.com/cockpit-project/cockpit&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;KVM Forum: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://events.linuxfoundation.org/kvm-forum/&quot;&gt;https://events.linuxfoundation.org/kvm-forum/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Stack Overflow KVM 태그: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://stackoverflow.com/questions/tagged/kvm&quot;&gt;https://stackoverflow.com/questions/tagged/kvm&lt;/a&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;virt-install 매뉴얼: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://linux.die.net/man/1/virt-install&quot;&gt;https://linux.die.net/man/1/virt-install&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cockpit Machines 플러그인: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/cockpit-project/cockpit-machines&quot;&gt;https://github.com/cockpit-project/cockpit-machines&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;libguestfs 도구: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://libguestfs.org/&quot;&gt;https://libguestfs.org/&lt;/a&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;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>Virtualization</category>
      <category>cockpit</category>
      <category>KVM</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/441</guid>
      <comments>https://somaz.tistory.com/441#entry441comment</comments>
      <pubDate>Wed, 3 Dec 2025 07:13:38 +0900</pubDate>
    </item>
    <item>
      <title>Containerd v3에서 Insecure Registry 설정 방식 변경</title>
      <link>https://somaz.tistory.com/439</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;containerd가 v2에서 v3로 업그레이드되면서 insecure registry 설정 방법이 크게 변경되었다. 기존의 `config.toml` 파일 내 설정 방식에서 별도 디렉토리 구조를 사용하는 방식으로 변경되었다.&lt;/span&gt;&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-origin-width=&quot;2902&quot; data-origin-height=&quot;1530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czluDz/btsPCSynmBZ/8a2sY7QdXnWBBi744ml031/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czluDz/btsPCSynmBZ/8a2sY7QdXnWBBi744ml031/img.png&quot; data-alt=&quot;출처 : https://github.com/containerd/containerd/releases&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czluDz/btsPCSynmBZ/8a2sY7QdXnWBBi744ml031/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczluDz%2FbtsPCSynmBZ%2F8a2sY7QdXnWBBi744ml031%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;2902&quot; height=&quot;1530&quot; data-origin-width=&quot;2902&quot; data-origin-height=&quot;1530&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : https://github.com/containerd/containerd/releases&lt;/figcaption&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 변경사항&lt;/span&gt;&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;&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;color: #000000;&quot;&gt;containerd v2 (기존 방식)&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1753855388547&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# /etc/containerd/config.toml
version = 2
[plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry]
  [plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry.mirrors]
    [plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry.mirrors.&quot;harbor.somaz.link&quot;]
      endpoint = [&quot;http://harbor.somaz.link&quot;]
  [plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry.configs]
    [plugins.&quot;io.containerd.grpc.v1.cri&quot;.registry.configs.&quot;harbor.somaz.link&quot;.tls]
      insecure_skip_verify = 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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;containerd v3 (새로운 방식)&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1753855411210&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# /etc/containerd/config.toml
version = 3
[plugins.&quot;io.containerd.cri.v1.images&quot;.registry]
  config_path = &quot;/etc/containerd/certs.d&quot;&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_1753855439303&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# /etc/containerd/certs.d/harbor.somaz.link/hosts.toml
server = &quot;https://harbor.somaz.link&quot;
[host.&quot;http://harbor.somaz.link&quot;]
  capabilities = [&quot;pull&quot;, &quot;resolve&quot;, &quot;push&quot;]
  skip_verify = true
  plain_http = 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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&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;
&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;color: #000000;&quot;&gt;kubespray를 통한 설정&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설정 파일 수정&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753855489834&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# inventory/mycluster/group_vars/all/containerd.yml
containerd_registries_mirrors:
  - prefix: harbor.somaz.link
    mirrors:
      - host: http://harbor.somaz.link
        capabilities: [&quot;pull&quot;, &quot;resolve&quot;, &quot;push&quot;]
        skip_verify: true
        plain_http: true

# registry 인증 정보 별도 설정
containerd_registry_auth:
  - registry: harbor.somaz.link
    username: admin
    password: somaz123!&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;kubespray 적용&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1753855527061&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# containerd 설정만 적용
nohup ansible-playbook -i inventory/somaz-cluster/inventory.ini \
  cluster.yml --become --tags=containerd &amp;amp;

# 로그 확인
tail -f nohup.out&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수동 설정 방법&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 디렉토리 생성&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753855624281&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo mkdir -p /etc/containerd/certs.d/harbor.somaz.link&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. `hosts.toml` 파일 생성&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753855652792&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo tee /etc/containerd/certs.d/harbor.somaz.link/hosts.toml &amp;lt;&amp;lt;EOF
server = &quot;http://harbor.somaz.link&quot;
[host.&quot;http://harbor.somaz.link&quot;]
  capabilities = [&quot;pull&quot;, &quot;resolve&quot;, &quot;push&quot;]
  skip_verify = true
  plain_http = true
EOF&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 권한 설정 및 재시작&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753855680003&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo chmod 644 /etc/containerd/certs.d/harbor.concrit.us/hosts.toml
sudo systemctl restart containerd&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;&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;color: #000000;&quot;&gt;설정 확인 방법&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;containerd v2에서의 확인&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753855706815&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# config.toml에서 registry 설정 확인
sudo containerd config dump | grep -A 20 &quot;harbor.somaz.link&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;&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;containerd v3에서의 확인&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753855734606&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# hosts.toml 파일 확인 (v3에서는 config dump에 나타나지 않음)
sudo cat /etc/containerd/certs.d/harbor.somaz.link/hosts.toml

# 실제 이미지 pull 테스트로 확인
sudo crictl pull harbor.somaz.link/library/alpine:latest&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;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&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;
&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;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;containerd v3에서는 registry 설정이 별도 디렉토리 구조로 분리되어 더욱 체계적으로 관리할 수 있게 되었다. &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;color: #000000;&quot;&gt;kubespray를 사용하는 환경에서는 `containerd_registries_mirrors` 변수를 통해 쉽게 설정할 수 있으며, 수동 설정 시에는 `/etc/containerd/certs.d/` 디렉토리 하위에 registry별 설정 파일을 생성하면 된다.&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;color: #000000;&quot;&gt;중요한 점은 v3에서는 `containerd config dump` 명령어로 registry 설정을 확인할 수 없으므로, 실제 이미지 pull 테스트나 `hosts.toml` 파일을 직접 확인하는 방법을 사용해야 한다는 것이다.&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;&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;span style=&quot;color: #000000;&quot;&gt;마지막으로 아래의 글을 확인하면 imagetools를 이용해 dockerhub 이미지를 손쉽게 harbor나 다른 private registry로 옮기는 방법을 참고할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://somaz.tistory.com/419&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2025.05.29 - [IaC/Container] - 도커 이미지 복사 자동화: buildx imagetools vs skopeo 실전 비교&lt;/a&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/containerd/containerd/discussions/6468&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/containerd/containerd/discussions/6468&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.reddit.com/r/kubernetes/comments/187kbgn/kubespray_changing_containerd_config/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.reddit.com/r/kubernetes/comments/187kbgn/kubespray_changing_containerd_config/&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Container Orchestration/Kubernetes</category>
      <category>containerd</category>
      <category>insecure registry</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/439</guid>
      <comments>https://somaz.tistory.com/439#entry439comment</comments>
      <pubDate>Wed, 26 Nov 2025 07:14:18 +0900</pubDate>
    </item>
    <item>
      <title>Python 클래스 데코레이터 완벽 가이드</title>
      <link>https://somaz.tistory.com/468</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데코레이터는 Python의 강력한 기능 중 하나로, 코드를 간결하고 우아하게 만들어준다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클래스에서 사용하는 주요 데코레이터들을 알아보자.&lt;/span&gt;&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-origin-width=&quot;1948&quot; data-origin-height=&quot;1920&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHjO9U/dJMb9XxzCpu/shtAVakj9fTdDKDmr1tDzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHjO9U/dJMb9XxzCpu/shtAVakj9fTdDKDmr1tDzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHjO9U/dJMb9XxzCpu/shtAVakj9fTdDKDmr1tDzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHjO9U%2FdJMb9XxzCpu%2FshtAVakj9fTdDKDmr1tDzk%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;770&quot; height=&quot;759&quot; data-origin-width=&quot;1948&quot; data-origin-height=&quot;1920&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. @property: Getter 만들기&lt;/span&gt;&lt;/h3&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;color: #000000;&quot;&gt;`@property` 는 메서드를 속성처럼 사용할 수 있게 해준다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;class Circle:
    def __init__(self, radius):
        self._radius = radius
    
    @property
    def radius(self):
        &quot;&quot;&quot;반지름 getter&quot;&quot;&quot;
        return self._radius
    
    @property
    def diameter(self):
        &quot;&quot;&quot;지름 계산&quot;&quot;&quot;
        return self._radius * 2
    
    @property
    def area(self):
        &quot;&quot;&quot;넓이 계산&quot;&quot;&quot;
        return 3.14159 * self._radius ** 2

# 사용
circle = Circle(5)
print(circle.radius)    # 5 - 메서드처럼 ()가 필요 없음!
print(circle.diameter)  # 10
print(circle.area)      # 78.53975
&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드를 속성처럼 깔끔하게 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;계산된 값을 속성처럼 접근 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. @property.setter: Setter 만들기&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;속성 값을 설정할 때 유효성 검사나 추가 로직을 넣을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ruby&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;class Person:
    def __init__(self, name, age):
        self._name = name
        self._age = age
    
    @property
    def age(self):
        return self._age
    
    @age.setter
    def age(self, value):
        if value &amp;lt; 0:
            raise ValueError(&quot;나이는 0보다 작을 수 없습니다!&quot;)
        if value &amp;gt; 150:
            raise ValueError(&quot;나이가 너무 많습니다!&quot;)
        self._age = value
    
    @property
    def name(self):
        return self._name
    
    @name.setter
    def name(self, value):
        if not value or not value.strip():
            raise ValueError(&quot;이름은 비어있을 수 없습니다!&quot;)
        self._name = value.strip()

# 사용
person = Person(&quot;철수&quot;, 25)
print(person.age)  # 25

person.age = 30    # setter 호출
print(person.age)  # 30

person.age = -5    # ValueError: 나이는 0보다 작을 수 없습니다!
&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;왜 사용하나요?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 유효성 검사&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;값 변경 시 추가 작업 수행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. @property.deleter: Deleter 만들기&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;속성 삭제 시 동작을 정의한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ruby&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;class BankAccount:
    def __init__(self, balance):
        self._balance = balance
    
    @property
    def balance(self):
        return self._balance
    
    @balance.setter
    def balance(self, value):
        if value &amp;lt; 0:
            raise ValueError(&quot;잔액은 음수일 수 없습니다!&quot;)
        self._balance = value
    
    @balance.deleter
    def balance(self):
        print(&quot;계좌를 초기화합니다.&quot;)
        self._balance = 0

# 사용
account = BankAccount(10000)
print(account.balance)  # 10000

del account.balance  # 계좌를 초기화합니다.
print(account.balance)  # 0
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. @dataclass: 자동으로 클래스 생성&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Python 3.7+에서 도입된 `@dataclass` 는 보일러플레이트 코드를 줄여준다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ruby&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;from dataclasses import dataclass, field
from typing import List

# 일반 클래스
class PersonOld:
    def __init__(self, name, age, email):
        self.name = name
        self.age = age
        self.email = email
    
    def __repr__(self):
        return f&quot;Person(name={self.name}, age={self.age}, email={self.email})&quot;
    
    def __eq__(self, other):
        return (self.name == other.name and 
                self.age == other.age and 
                self.email == other.email)

# @dataclass 사용
@dataclass
class Person:
    name: str
    age: int
    email: str
    hobbies: List[str] = field(default_factory=list)  # 기본값

# 사용
person1 = Person(&quot;철수&quot;, 25, &quot;chulsoo@email.com&quot;)
person2 = Person(&quot;철수&quot;, 25, &quot;chulsoo@email.com&quot;)

print(person1)  # Person(name='철수', age=25, email='chulsoo@email.com', hobbies=[])
print(person1 == person2)  # True - __eq__ 자동 생성!
&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;@dataclass 옵션&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;@dataclass(
    frozen=True,      # 불변 객체로 만들기
    order=True,       # &amp;lt;, &amp;gt;, &amp;lt;=, &amp;gt;= 비교 연산자 추가
    eq=True,          # == 연산자 (기본값 True)
    repr=True         # __repr__ 자동 생성 (기본값 True)
)
class Product:
    name: str
    price: int
    stock: int = 0  # 기본값
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. 클래스 데코레이터: 클래스 자체를 수정&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클래스 전체에 데코레이터를 적용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;def singleton(cls):
    &quot;&quot;&quot;싱글톤 패턴 데코레이터&quot;&quot;&quot;
    instances = {}
    
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    
    return get_instance

@singleton
class Database:
    def __init__(self):
        print(&quot;데이터베이스 연결 생성!&quot;)
        self.connection = &quot;Connected&quot;

# 사용
db1 = Database()  # 데이터베이스 연결 생성!
db2 = Database()  # 출력 없음 - 같은 인스턴스 반환
print(db1 is db2)  # True
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6. 메서드 데코레이터: 성능 측정&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;import time
from functools import wraps

def timer(func):
    &quot;&quot;&quot;함수 실행 시간을 측정하는 데코레이터&quot;&quot;&quot;
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f&quot;{func.__name__} 실행 시간: {end - start:.4f}초&quot;)
        return result
    return wrapper

class DataProcessor:
    @timer
    def process_large_data(self, data_size):
        &quot;&quot;&quot;대용량 데이터 처리 시뮬레이션&quot;&quot;&quot;
        total = 0
        for i in range(data_size):
            total += i
        return total

# 사용
processor = DataProcessor()
result = processor.process_large_data(1000000)
# process_large_data 실행 시간: 0.0234초
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;7. 실전 예제: 모든 데코레이터 활용&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;from dataclasses import dataclass
from functools import wraps

def validate_positive(func):
    &quot;&quot;&quot;양수 검증 데코레이터&quot;&quot;&quot;
    @wraps(func)
    def wrapper(self, value):
        if value &amp;lt;= 0:
            raise ValueError(f&quot;{func.__name__}: 양수만 가능합니다!&quot;)
        return func(self, value)
    return wrapper

class Product:
    def __init__(self, name, price, stock):
        self._name = name
        self._price = price
        self._stock = stock
    
    @property
    def name(self):
        return self._name
    
    @property
    def price(self):
        return self._price
    
    @price.setter
    @validate_positive
    def price(self, value):
        self._price = value
    
    @property
    def stock(self):
        return self._stock
    
    @stock.setter
    @validate_positive
    def stock(self, value):
        self._stock = value
    
    @property
    def total_value(self):
        &quot;&quot;&quot;재고 총액 계산&quot;&quot;&quot;
        return self._price * self._stock
    
    @staticmethod
    def apply_tax(price, tax_rate=0.1):
        &quot;&quot;&quot;세금 계산&quot;&quot;&quot;
        return price * (1 + tax_rate)
    
    @classmethod
    def create_bundle(cls, name, items):
        &quot;&quot;&quot;묶음 상품 생성&quot;&quot;&quot;
        total_price = sum(item.price for item in items)
        total_stock = min(item.stock for item in items)
        return cls(name, total_price, total_stock)

# 사용
laptop = Product(&quot;노트북&quot;, 1000000, 50)
print(laptop.total_value)  # 50000000

laptop.price = 1200000  # setter로 가격 변경
print(laptop.total_value)  # 60000000

print(Product.apply_tax(laptop.price))  # 1320000.0

laptop.price = -100  # ValueError: price: 양수만 가능합니다!
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데코레이터 비교 정리&lt;/span&gt;&lt;/h3&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데코레이터&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;용도&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;적용 대상&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`@property`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Getter 만들기&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`@속성.setter`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Setter 만들기&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`@속성.deleter`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Deleter 만들기&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`@staticmethod`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정적 메서드&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`@classmethod`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클래스 메서드&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`@dataclass`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동 클래스 생성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클래스&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;커스텀 데코레이터&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;원하는 기능 추가&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클래스/메서드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결론&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데코레이터를 잘 활용하면&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드가 간결하고 읽기 쉬워진다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;반복되는 로직을 재사용할 수 있다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관심사를 분리하여 유지보수가 쉬워진다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&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;&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;
&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;Python Official Docs - dataclasses: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.python.org/3/library/dataclasses.html&quot;&gt;https://docs.python.org/3/library/dataclasses.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Python Official Docs - Built-in Functions (property, classmethod, staticmethod): &lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.python.org/3/library/functions.html&quot;&gt;https://docs.python.org/3/library/functions.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;튜토리얼 &amp;amp; 가이드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Real Python - Properties: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://python101.pythonlibrary.org/chapter25_decorators.html&quot;&gt;https://python101.pythonlibrary.org/chapter25_decorators.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Florimond Manca - Reconciling Dataclasses and Properties: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://florimond.dev/en/posts/2018/10/reconciling-dataclasses-and-properties-in-python/&quot;&gt;https://florimond.dev/en/posts/2018/10/reconciling-dataclasses-and-properties-in-python/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Machine Learning Plus - Method Decorators: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.machinelearningplus.com/python/python-method-decorators-classmethod-vs-staticmethod-vs-property/&quot;&gt;https://www.machinelearningplus.com/python/python-method-decorators-classmethod-vs-staticmethod-vs-property/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Better Programming - Magical Decorators: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://betterprogramming.pub/how-to-use-the-magical-staticmethod-classmethod-and-property-decorators-in-python-e42dd74e51e7&quot;&gt;https://betterprogramming.pub/how-to-use-the-magical-staticmethod-classmethod-and-property-decorators-in-python-e42dd74e51e7&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;심화 자료&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Stack Overflow - Dataclasses and Property: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://stackoverflow.com/questions/51079503/dataclasses-and-property-decorator&quot;&gt;https://stackoverflow.com/questions/51079503/dataclasses-and-property-decorator&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TutorialsTeacher - Static Method Decorator: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.tutorialsteacher.com/python/staticmethod-decorator&quot;&gt;https://www.tutorialsteacher.com/python/staticmethod-decorator&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Launguage</category>
      <category>Decorator</category>
      <category>Python</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/468</guid>
      <comments>https://somaz.tistory.com/468#entry468comment</comments>
      <pubDate>Fri, 21 Nov 2025 00:00:17 +0900</pubDate>
    </item>
    <item>
      <title>가상화 네트워킹 핵심 개념: Linux, KVM, libvirt</title>
      <link>https://somaz.tistory.com/437</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가상화 환경에서 네트워킹을 이해하려면 다양한 기술과 용어들을 알아야 한다. 특히 KVM/QEMU 기반의 가상화 환경에서는 &lt;b&gt;물리 네트워크와 가상 네트워크가 어떻게 연결되고 상호작용하는지&lt;/b&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;color: #000000;&quot;&gt;이 글에서는 가상화 네트워킹의 핵심 개념들을 실제 사례와 함께 설명하며, Cockpit을 통한 VM 관리 시 마주치는 네트워크 용어들을 체계적으로 정리해보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다룰 주요 개념들&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;가상화 네트워킹 기본 구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;libvirt 네트워크 모드와 특징&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Linux 브리지와 가상 인터페이스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;macvtap과 veth의 차이점&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 가상화 기술들&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KI1Zd/dJMcajnkvSB/tOUEk2GofjknkJRHWKtEoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KI1Zd/dJMcajnkvSB/tOUEk2GofjknkJRHWKtEoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KI1Zd/dJMcajnkvSB/tOUEk2GofjknkJRHWKtEoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKI1Zd%2FdJMcajnkvSB%2FtOUEk2GofjknkJRHWKtEoK%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 가상화 네트워킹 기본 구조&lt;/span&gt;&lt;/h2&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;color: #000000;&quot;&gt;물리 네트워크 vs 가상 네트워크&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;물리 네트워크 계층&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753413992160&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Internet &amp;larr;&amp;rarr; Physical Switch &amp;larr;&amp;rarr; Physical NIC (eno1) &amp;larr;&amp;rarr; Host OS
                     &amp;darr;
            [Physical Network Layer]&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가상 네트워크 계층&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414010652&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;VM1 &amp;larr;&amp;rarr; Virtual NIC &amp;larr;&amp;rarr; Virtual Switch &amp;larr;&amp;rarr; Physical NIC &amp;larr;&amp;rarr; Physical Switch
VM2 &amp;larr;&amp;rarr; Virtual NIC &amp;larr;&amp;rarr;      &amp;uarr;        &amp;larr;&amp;rarr;      &amp;uarr;      &amp;larr;&amp;rarr;       &amp;uarr;
VM3 &amp;larr;&amp;rarr; Virtual NIC &amp;larr;&amp;rarr; [Virtual Layer] [Bridge Layer] [Physical Layer]&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;&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;color: #000000;&quot;&gt;네트워크 스택의 이해&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전체 네트워크 스택&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414033280&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│   VM1 (Guest)   │ │   VM2 (Guest)   │ │   VM3 (Guest)   │
│   eth0/enp1s0   │ │   eth0/enp1s0   │ │   eth0/enp1s0   │
└─────────────────┘ └─────────────────┘ └─────────────────┘
         │                   │                   │
         ▼                   ▼                   ▼
┌─────────────────────────────────────────────────────────┐
│              Virtual Network Layer                      │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐       │
│  │  vnet1  │ │  vnet2  │ │  vnet3  │ │ virbr0  │       │
│  │(tap/tun)│ │(tap/tun)│ │(tap/tun)│ │(bridge) │       │
│  └─────────┘ └─────────┘ └─────────┘ └─────────┘       │
└─────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────┐
│                 Host OS Network                         │
│              eno1 (Physical NIC)                        │
└─────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────┐
│              Physical Network                           │
│            (Switch, Router, Internet)                   │
└─────────────────────────────────────────────────────────┘&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;&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;span style=&quot;color: #000000;&quot;&gt;2. libvirt 네트워크 모드 완전 분석&lt;/span&gt;&lt;/h2&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;color: #000000;&quot;&gt;NAT 모드 (Network Address Translation)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 개념&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;VM들이 사설 네트워크(192.168.122.0/24)를 사용한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부 통신 시 호스트의 IP로 NAT 변환된다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 구조&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414066905&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Internet (Public) &amp;larr;&amp;rarr; Host (10.10.10.15) &amp;larr;&amp;rarr; virbr0 (192.168.122.1) &amp;larr;&amp;rarr; VM (192.168.122.17)
                                    &amp;uarr;                              &amp;uarr;
                               [NAT Gateway]                  [Private Network]&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특징&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;VM 간 통신 가능하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부 접근 시 포트 포워딩이 필요하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안성이 높다 (내부 네트워크 숨김)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;libvirt XML 설정&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414100635&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;network&amp;gt;
  &amp;lt;name&amp;gt;default&amp;lt;/name&amp;gt;
  &amp;lt;forward mode='nat'/&amp;gt;
  &amp;lt;bridge name='virbr0' stp='on' delay='0'/&amp;gt;
  &amp;lt;ip address='192.168.122.1' netmask='255.255.255.0'&amp;gt;
    &amp;lt;dhcp&amp;gt;
      &amp;lt;range start='192.168.122.2' end='192.168.122.254'/&amp;gt;
    &amp;lt;/dhcp&amp;gt;
  &amp;lt;/ip&amp;gt;
&amp;lt;/network&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;&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;color: #000000;&quot;&gt;Bridge 모드 (브리지)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 개념&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;VM들이 물리 네트워크에 직접 연결된 것처럼 동작한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;같은 네트워크 세그먼트에서 IP를 할당받는다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;L2 레벨에서 투명한 연결을 제공한다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 구조&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414169176&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Physical Switch &amp;larr;&amp;rarr; br0 (Linux Bridge) &amp;larr;&amp;rarr; eno1 (Physical NIC)
       &amp;uarr;                    &amp;darr;
   [L2 Domain]         ┌─────────┐
                       │  VM1    │ 10.10.10.17
                       │  VM2    │ 10.10.10.18  
                       │  VM3    │ 10.10.10.19
                       └─────────┘&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특징&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;VM들이 물리 네트워크의 일부처럼 동작한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부에서 직접 접근이 가능하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능이 우수하다 (NAT 오버헤드 없음)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;❌ IP 주소 관리가 필요하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;libvirt XML 설정&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414198033&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;network&amp;gt;
  &amp;lt;name&amp;gt;br0-network&amp;lt;/name&amp;gt;
  &amp;lt;forward mode='bridge'/&amp;gt;
  &amp;lt;bridge name='br0'/&amp;gt;
&amp;lt;/network&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;&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;
&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;color: #000000;&quot;&gt;Route 모드 (라우팅)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 개념&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;호스트가 라우터 역할을 수행한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VM들은 별도 서브넷을 사용한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 구조&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414224057&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;External Network (10.10.10.0/24) &amp;larr;&amp;rarr; Host Router &amp;larr;&amp;rarr; VM Network (192.168.100.0/24)
                                         &amp;uarr;
                                   [Routing Table]
                               192.168.100.0/24 &amp;rarr; virbr1&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특징&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;네트워크 분리와 제어가 가능하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다중 서브넷 관리가 용이하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;❌ 라우팅 설정이 복잡하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&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;color: #000000;&quot;&gt;Isolated 모드 (격리)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 개념&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;VM들끼리만 통신이 가능하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부 네트워크와 완전히 차단된다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 구조&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414264428&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Internet ✗ Host ✗ Isolated Bridge &amp;larr;&amp;rarr; VM1, VM2, VM3
                        &amp;uarr;
                [Internal Only]&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특징&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;완전한 네트워크 격리가 가능하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안 테스트에 적합하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;❌ 외부 접근이 불가능하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&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;&lt;span style=&quot;color: #000000;&quot;&gt;3. 가상 네트워크 인터페이스 심화&lt;/span&gt;&lt;/h2&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;color: #000000;&quot;&gt;TAP/TUN 인터페이스&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TUN (Network Tunnel)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;L3 (Network Layer) 인터페이스다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IP 패킷 단위로 동작한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VPN에서 주로 사용된다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TAP (Network Tap)&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;L2 (Data Link Layer) 인터페이스다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ethernet 프레임 단위로 동작한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VM 네트워킹에서 주로 사용된다&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;동작 방식&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414316126&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# TAP 인터페이스 생성 예시
sudo ip tuntap add dev tap0 mode tap
sudo ip link set tap0 up
sudo ip addr add 192.168.100.1/24 dev tap0

# VM에서 TAP 사용
qemu-system-x86_64 -netdev tap,id=net0,ifname=tap0,script=no \
                   -device virtio-net,netdev=net0 [other options]&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;&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;color: #000000;&quot;&gt;veth (Virtual Ethernet) 쌍&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 개념&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;가상 이더넷 케이블과 같은 역할을 한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항상 쌍으로 생성된다 (veth0 &amp;harr; veth1)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;생성과 사용&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414355760&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# veth 쌍 생성
sudo ip link add veth0 type veth peer name veth1

# 네임스페이스 연결 예시
sudo ip netns add ns1
sudo ip link set veth1 netns ns1
sudo ip netns exec ns1 ip addr add 192.168.1.2/24 dev veth1
sudo ip netns exec ns1 ip link set veth1 up&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;&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;color: #000000;&quot;&gt;macvtap 심화 분석&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;macvtap 모드별 상세 특징&lt;/span&gt;&lt;/h4&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. VEPA (Virtual Ethernet Port Aggregator) 모드&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753414386565&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;VM1 &amp;rarr; macvtap1 &amp;rarr; Physical NIC &amp;rarr; External Switch &amp;rarr; Physical NIC &amp;rarr; macvtap2 &amp;rarr; VM2
                        &amp;uarr;                              &amp;uarr;
                   [Hair-pin 필요]              [External Switching]&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;&lt;span style=&quot;color: #000000;&quot;&gt;모든 트래픽이 외부 스위치를 거쳐야 한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스위치가 hair-pin 모드를 지원해야 VM 간 통신이 가능하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Bridge 모드&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753414411904&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;VM1 &amp;rarr; macvtap1 ↘
              &amp;rarr; Internal Switch &amp;rarr; External Network
VM2 &amp;rarr; macvtap2 ↗&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;&lt;span style=&quot;color: #000000;&quot;&gt;VM 간 직접 통신이 가능하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;호스트와는 통신이 불가능하다 (보안 격리)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. Private 모드&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753414435357&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;VM1 &amp;rarr; macvtap1 &amp;rarr; Physical NIC &amp;rarr; External Network
VM2 &amp;rarr; macvtap2 &amp;rarr; Physical NIC &amp;rarr; External Network
     &amp;uarr;                    ↗
   [Isolated]        [No Inter-VM Communication]&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;&lt;span style=&quot;color: #000000;&quot;&gt;VM 간 완전히 격리된다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 VM이 독립적으로 외부 통신한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. Passthrough 모드&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753414455880&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;VM &amp;rarr; Direct Hardware Control &amp;rarr; Physical NIC
            &amp;uarr;
    [Exclusive Access]&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;&lt;span style=&quot;color: #000000;&quot;&gt;VM이 물리 NIC를 독점 사용한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최고 성능과 하드웨어 기능을 완전히 활용한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;한 번에 하나의 VM만 사용 가능하다&lt;/span&gt;&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;&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;color: #000000;&quot;&gt;macvlan vs macvtap 비교&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;macvlan&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;커널 기능으로 네트워크 네임스페이스와 함께 사용된다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨테이너에서 주로 활용된다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 MAC 주소를 하나의 물리 인터페이스에 할당한다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;macvtap&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;macvlan + TAP 기능이 결합되어 있다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VM에서 직접 사용이 가능하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QEMU/KVM에 최적화되어 있다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1753414491509&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# macvlan 생성 예시
sudo ip link add macvlan0 link eno1 type macvlan mode bridge
sudo ip addr add 10.10.10.100/24 dev macvlan0

# macvtap 확인
ip link show type macvtap
ls /dev/tap*&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. Linux 브리지 네트워킹 심화&lt;/span&gt;&lt;/h2&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;color: #000000;&quot;&gt;브리지 동작 원리&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MAC 주소 학습&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VM1이 패킷을 전송한다 &amp;rarr; 브리지가 MAC 주소를 학습한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;브리지 FDB (Forwarding Database)에 저장한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이후 해당 MAC으로 오는 패킷을 정확한 포트로 전달한다&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;브리지 테이블 확인&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414553714&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# FDB (Forwarding Database) 확인
bridge fdb show br br0

# MAC 주소 테이블
brctl showmacs br0

# 브리지 통계
cat /sys/class/net/br0/statistics/rx_packets
cat /sys/class/net/br0/statistics/tx_packets&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;&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;color: #000000;&quot;&gt;STP (Spanning Tree Protocol)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;STP의 역할&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;루프를 방지한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중복 경로를 관리한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;STP 상태&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414598651&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# STP 정보 확인
brctl showstp br0

# 포트별 STP 상태
# Disabled, Blocking, Listening, Learning, Forwarding&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;STP 설정&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414615838&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# STP 활성화/비활성화
sudo brctl stp br0 on
sudo brctl stp br0 off

# 브리지 우선순위 설정 (낮을수록 루트 브리지)
sudo brctl setbridgeprio br0 4096

# 포트 우선순위 설정
sudo brctl setportprio br0 eno1 10&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VLAN과 브리지&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VLAN 태깅&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414635541&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# VLAN 인터페이스 생성
sudo ip link add link eno1 name eno1.100 type vlan id 100
sudo ip link set eno1.100 up

# 브리지에 VLAN 인터페이스 추가
sudo brctl addif br0 eno1.100&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;브리지 VLAN 필터링&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414653480&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# VLAN 인식 브리지 생성
sudo ip link add name br-vlan type bridge vlan_filtering 1

# VLAN 설정
bridge vlan add vid 100 dev eno1 master
bridge vlan add vid 100 dev vnet1 master&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;&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. 네트워크 가상화 고급 개념&lt;/span&gt;&lt;/h2&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;color: #000000;&quot;&gt;SR-IOV (Single Root I/O Virtualization)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 개념&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;물리 NIC를 여러 가상 기능(VF)으로 분할한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;VM이 하드웨어에 직접 접근한다 (Passthrough)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구조&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414702315&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Physical NIC (PF: Physical Function)
    ├── VF1 &amp;rarr; VM1 (Direct Hardware Access)
    ├── VF2 &amp;rarr; VM2 (Direct Hardware Access)  
    ├── VF3 &amp;rarr; VM3 (Direct Hardware Access)
    └── VF4 &amp;rarr; VM4 (Direct Hardware Access)&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설정 예시&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414716718&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# SR-IOV 지원 확인
lspci | grep -i ethernet
cat /sys/class/net/eno1/device/sriov_totalvfs

# VF 생성
echo 4 &amp;gt; /sys/class/net/eno1/device/sriov_numvfs

# VF 확인
ip link show
lspci | grep &quot;Virtual Function&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;&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;
&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;color: #000000;&quot;&gt;DPDK (Data Plane Development Kit)&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특징&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;유저스페이스 네트워킹이다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;커널 바이패스로 극한 성능을 제공한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;패킷 처리 전용 CPU 코어를 할당한다&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;vs 전통적 네트워킹&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414744980&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Traditional: Hardware &amp;rarr; Kernel &amp;rarr; Userspace Application
DPDK:       Hardware &amp;rarr; Userspace Application (Direct)&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;&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;color: #000000;&quot;&gt;OVS (Open vSwitch)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기능&lt;/span&gt;&lt;/h4&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;color: #000000;&quot;&gt;프로그래밍 가능한 가상 스위치다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OpenFlow 프로토콜을 지원한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SDN (Software Defined Networking)을 구현한다&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;libvirt와 OVS&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414778785&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;network&amp;gt;
  &amp;lt;name&amp;gt;ovs-network&amp;lt;/name&amp;gt;
  &amp;lt;forward mode='bridge'/&amp;gt;
  &amp;lt;bridge name='ovsbr0'/&amp;gt;
  &amp;lt;virtualport type='openvswitch'/&amp;gt;
&amp;lt;/network&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OVS 명령어&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414795931&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 브리지 생성
sudo ovs-vsctl add-br ovsbr0

# 포트 추가
sudo ovs-vsctl add-port ovsbr0 eno1

# Flow 규칙 확인
sudo ovs-ofctl dump-flows ovsbr0&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;&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;
&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;&lt;span style=&quot;color: #000000;&quot;&gt;6. 네트워크 성능과 최적화&lt;/span&gt;&lt;/h2&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;color: #000000;&quot;&gt;성능 측정 도구&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;iperf3 - 대역폭 측정&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414826223&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iperf3 -s -B 10.10.10.17

# 클라이언트 모드 (다양한 테스트)
iperf3 -c 10.10.10.17 -t 30 -P 4    # 30초, 4개 병렬 스트림
iperf3 -c 10.10.10.17 -u -b 1G      # UDP, 1Gbps 테스트
iperf3 -c 10.10.10.17 -R             # 역방향 테스트&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;hping3 - 지연시간 측정&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414840561&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# ICMP 지연시간
sudo hping3 -c 100 -i u1000 10.10.10.17

# TCP 지연시간
sudo hping3 -c 100 -S -p 80 -i u1000 10.10.10.17&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;netperf - 종합 네트워크 성능&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414857137&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# TCP 스트림 테스트
netperf -H 10.10.10.17 -t TCP_STREAM

# UDP 스트림 테스트  
netperf -H 10.10.10.17 -t UDP_STREAM

# 요청-응답 테스트
netperf -H 10.10.10.17 -t TCP_RR&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;성능 최적화 기법&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. CPU 친화성 (CPU Affinity)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414878096&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 네트워크 인터럽트를 특정 CPU에 바인딩
echo 2 &amp;gt; /proc/irq/24/smp_affinity

# VM의 vCPU를 특정 물리 CPU에 고정
virsh vcpupin vm-name 0 1
virsh vcpupin vm-name 1 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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 큐 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414895089&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 네트워크 인터페이스 큐 수 확인
ethtool -l eno1

# 큐 수 조정
ethtool -L eno1 combined 4

# 링 버퍼 크기 조정
ethtool -G eno1 rx 4096 tx 4096&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 가상 네트워크 최적화&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414909884&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- VM XML에서 멀티큐 활성화 --&amp;gt;
&amp;lt;interface type='bridge'&amp;gt;
  &amp;lt;source bridge='br0'/&amp;gt;
  &amp;lt;model type='virtio'/&amp;gt;
  &amp;lt;driver name='vhost' queues='4'/&amp;gt;
&amp;lt;/interface&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;&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;
&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;&lt;span style=&quot;color: #000000;&quot;&gt;7. 보안과 네트워크 정책&lt;/span&gt;&lt;/h2&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;color: #000000;&quot;&gt;iptables와 가상화&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;브리지 트래픽 제어&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414935199&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 브리지 트래픽이 iptables를 거치도록 설정
echo 1 &amp;gt; /proc/sys/net/bridge/bridge-nf-call-iptables

# VM 간 통신 차단
iptables -I FORWARD -i br0 -o br0 -j DROP

# 특정 VM만 허용
iptables -I FORWARD -s 10.10.10.17 -d 10.10.10.18 -j ACCEPT&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;libvirt 네트워크 필터&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414950759&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;interface type='bridge'&amp;gt;
  &amp;lt;source bridge='br0'/&amp;gt;
  &amp;lt;filterref filter='clean-traffic'/&amp;gt;
&amp;lt;/interface&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;&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네트워크 네임스페이스와 격리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네임스페이스 생성과 관리&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753414972798&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 네트워크 네임스페이스 생성
sudo ip netns add secure-ns

# 인터페이스를 네임스페이스로 이동
sudo ip link set veth1 netns secure-ns

# 네임스페이스 내에서 명령 실행
sudo ip netns exec secure-ns ip addr show
sudo ip netns exec secure-ns ping 8.8.8.8&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;8. 모니터링과 트러블슈팅&lt;/span&gt;&lt;/h2&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;color: #000000;&quot;&gt;네트워크 상태 모니터링&lt;/span&gt;&lt;/h3&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실시간 트래픽 모니터링&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753415001730&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 인터페이스별 트래픽
watch -n1 &quot;cat /proc/net/dev&quot;

# iftop - 실시간 대역폭 사용량
sudo iftop -i br0

# vnstat - 네트워크 통계
vnstat -i br0 -l    # 실시간
vnstat -i br0 -d    # 일별 통계&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;패킷 캡처와 분석&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753415018054&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# tcpdump - 패킷 캡처
sudo tcpdump -i br0 -w capture.pcap
sudo tcpdump -i br0 host 10.10.10.17

# Wireshark용 캡처
sudo dumpcap -i br0 -w wireshark.pcapng&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;&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;color: #000000;&quot;&gt;일반적인 문제 진단&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;연결 테스트 순서&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753415037334&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 1. 물리적 연결 확인
ethtool eno1 | grep &quot;Link detected&quot;

# 2. IP 설정 확인  
ip addr show br0

# 3. 라우팅 테이블 확인
ip route show

# 4. DNS 해결 확인
nslookup google.com

# 5. 방화벽 확인
iptables -L -n -v&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;브리지 문제 진단&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1753415052117&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 브리지 연결 상태
brctl show

# MAC 학습 확인
brctl showmacs br0

# STP 상태 (문제 시)
brctl showstp br0&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&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;
&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가상화 네트워킹은 &lt;b&gt;물리 네트워크의 확장&lt;/b&gt;이면서 동시에 &lt;b&gt;완전히 새로운 추상화 계층&lt;/b&gt;이다. 이해해야 할 개념들이 많지만, 각각의 기술이 어떤 문제를 해결하기 위해 만들어졌는지 파악하면 전체적인 그림을 그릴 수 있다.&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;핵심 정리&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;계층적 이해&lt;/b&gt;: Physical &amp;rarr; Virtual &amp;rarr; Application 순으로 네트워크 스택을 이해해야 한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;모드별 특징&lt;/b&gt;: NAT(보안), Bridge(성능), Route(제어), Isolated(격리)의 용도를 구분해야 한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;인터페이스 타입&lt;/b&gt;: tap/tun, veth, macvtap의 차이점과 사용 사례를 알아야 한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;성능 고려&lt;/b&gt;: SR-IOV, DPDK 등 고성능 기술의 필요성과 트레이드오프를 고려해야 한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안과 격리&lt;/b&gt;: 네트워크 정책과 방화벽의 중요성을 인식해야 한다&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;학습 순서 권장&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;기초&lt;/b&gt;: Linux 네트워킹 기본 (ip, route, iptables)을 익혀야 한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;가상화&lt;/b&gt;: KVM/QEMU 기본과 libvirt 네트워크를 학습해야 한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실습&lt;/b&gt;: Cockpit으로 다양한 네트워크 모드를 테스트해봐야 한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고급&lt;/b&gt;: OVS, SR-IOV 등 고급 기술을 탐구해야 한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;자동화&lt;/b&gt;: Ansible, Terraform 등으로 네트워크 인프라를 코드화해야 한다&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;span style=&quot;color: #000000;&quot;&gt;이러한 개념들을 체계적으로 이해하면, &lt;b&gt;단순한 VM 관리를 넘어서 복잡한 클라우드 인프라를 설계하고 운영&lt;/b&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;&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;
&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;
&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.linux-kvm.org/page/Documents&quot;&gt;KVM 공식 문서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://wiki.qemu.org/Documentation/Networking&quot;&gt;QEMU 네트워킹 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://libvirt.org/formatnetwork.html&quot;&gt;libvirt 네트워킹 문서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://cockpit-project.org/guide/latest/machines&quot;&gt;Red Hat Cockpit 가상화 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://netplan.io/reference/&quot;&gt;Ubuntu Netplan 설정&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://wiki.linuxfoundation.org/networking/bridge&quot;&gt;Linux Bridge 관리&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://man7.org/linux/man-pages/man8/ip-netns.8.html&quot;&gt;Linux 네트워크 네임스페이스&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://wiki.linuxfoundation.org/networking/iproute2&quot;&gt;iproute2 사용법&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://netfilter.org/documentation/HOWTO/packet-filtering-HOWTO.html&quot;&gt;iptables 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.kernel.org/doc/Documentation/networking/tuntap.txt&quot;&gt;TAP/TUN 인터페이스 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking&quot;&gt;macvlan vs macvtap 비교&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://man7.org/linux/man-pages/man4/veth.4.html&quot;&gt;veth 쌍 사용법&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://doc.dpdk.org/guides/nics/overview.html&quot;&gt;SR-IOV 기술 개요&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.openvswitch.org/&quot;&gt;Open vSwitch 공식 문서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://doc.dpdk.org/guides/prog_guide/&quot;&gt;DPDK 프로그래밍 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/virtualization_deployment_and_administration_guide/sect-sr_iov&quot;&gt;SR-IOV 설정 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.kernel.org/doc/Documentation/networking/vlan.txt&quot;&gt;VLAN 태깅과 트렁킹&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://access.redhat.com/sites/default/files/attachments/20150325_network_performance_tuning.pdf&quot;&gt;Linux 네트워크 성능 튜닝&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://wiki.libvirt.org/page/Virtio&quot;&gt;virtio 네트워크 최적화&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/performance_tuning_guide/s-cpu-irq&quot;&gt;CPU 친화성 설정&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://iperf.fr/iperf-doc.php&quot;&gt;iperf3 사용법&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.tcpdump.org/manpages/tcpdump.1.html&quot;&gt;tcpdump 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.wireshark.org/docs/&quot;&gt;Wireshark 문서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://humdi.net/vnstat/&quot;&gt;vnstat 네트워크 모니터링&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://libvirt.org/security.html&quot;&gt;libvirt 보안 가이드&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://libvirt.org/formatnwfilter.html&quot;&gt;네트워크 필터링&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://wiki.libvirt.org/page/Net.bridge.bridge-nf-call_and_sysctl.conf&quot;&gt;브리지 방화벽 설정&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://wiki.archlinux.org/title/KVM#Networking&quot;&gt;KVM 네트워킹 튜토리얼&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://jamielinux.com/docs/libvirt-networking-handbook/&quot;&gt;libvirt 네트워크 예제&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.docker.com/network/drivers/bridge/&quot;&gt;Linux 컨테이너 네트워킹&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://standards.ieee.org/ieee/802.1Q/6844/&quot;&gt;IEEE 802.1Q VLAN 표준&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.ieee802.org/1/pages/802.1D.html&quot;&gt;STP RFC 802.1D&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://opennetworking.org/software-defined-standards/specifications/&quot;&gt;OpenFlow 프로토콜&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://libvirt.org/contact.html#email&quot;&gt;libvirt 메일링 리스트&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.linux-kvm.org/page/KvmForum&quot;&gt;KVM 포럼&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://wiki.qemu.org/&quot;&gt;QEMU 위키&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://stackoverflow.com/questions/tagged/kvm&quot;&gt;Stack Overflow KVM 태그&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Network</category>
      <category>KVM</category>
      <category>libvirt</category>
      <category>Linux</category>
      <category>qemu</category>
      <category>가상화</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/437</guid>
      <comments>https://somaz.tistory.com/437#entry437comment</comments>
      <pubDate>Wed, 19 Nov 2025 06:46:31 +0900</pubDate>
    </item>
    <item>
      <title>GitLab CI로 Google Drive에 자동 업로드하기</title>
      <link>https://somaz.tistory.com/435</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지속적인 통합(Continuous Integration, CI)은 단순한 빌드와 테스트를 넘어, 다양한 업무를 자동화하는 강력한 도구이다. 그 중 하나가 바로 &lt;b&gt;GitLab CI를 활용해 Google Drive에 파일을 자동 업로드&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;338&quot; data-start=&quot;314&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 방법은 다음과 같은 상황에서 유용하다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;433&quot; data-start=&quot;340&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;375&quot; data-start=&quot;340&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;빌드 결과물을 팀 공유용 Google Drive에 자동 저장&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;404&quot; data-start=&quot;376&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;테스트 리포트나 로그 파일을 백업 용도로 업로드&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;433&quot; data-start=&quot;405&quot;&gt;&lt;span style=&quot;color: #000000;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;505&quot; data-start=&quot;435&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 글에서는 &lt;b&gt;GitLab CI에서 rclone을 활용하여 회사의 Google Workspace 공유 계정의 Google Drive에 파일을 업로드&lt;/b&gt;하는 방법을 소개한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;505&quot; data-start=&quot;435&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;505&quot; data-start=&quot;435&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 디자인 문서나 산출물을 팀 Drive에 자동으로 올려야 하는 프로젝트에 매우 적합한 방식이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9NfLy/dJMcabQpYsW/yybUPZsRummTwCM1B1X05K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9NfLy/dJMcabQpYsW/yybUPZsRummTwCM1B1X05K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9NfLy/dJMcabQpYsW/yybUPZsRummTwCM1B1X05K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9NfLy%2FdJMcabQpYsW%2FyybUPZsRummTwCM1B1X05K%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;2816&quot; height=&quot;1536&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&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;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;534&quot; data-start=&quot;519&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. rclone 설정&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;586&quot; data-start=&quot;536&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우선, rclone을 로컬에서 설정하고, 설정 파일을 GitLab에 업로드해야 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;619&quot; data-start=&quot;588&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google Workspace 공유 계정 준비&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;782&quot; data-start=&quot;621&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;658&quot; data-start=&quot;621&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;회사에서 사용하는 Google Workspace 계정으로 로그인&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;699&quot; data-start=&quot;659&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Google Drive 내 &lt;b&gt;공유 드라이브 또는 특정 폴더 생성&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;747&quot; data-start=&quot;700&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;rclone 인증을 위한 서비스 계정 또는 OAuth 인증을 마치고 토큰 저장&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;rclone 설치&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1752723212776&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Linux
curl https://rclone.org/install.sh | sudo bash

# Mac
brew install rclone&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;rclone 설정 예시&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1752723185313&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;rclone config

No remotes found - make a new one
n) New remote
s) Set configuration password
q) Quit config
n/s/q&amp;gt; n

...
name&amp;gt; somaz
Type of storage to configure.
Enter a string value. Press Enter for the default (&quot;&quot;).
Choose a number from below, or type in your own value

...
1 / 1Fichier
   \ &quot;fichier&quot;
 2 / Alias for an existing remote
   \ &quot;alias&quot;
 3 / Amazon Drive
   \ &quot;amazon cloud drive&quot;
(...)
15 / Google Drive
   \ &quot;drive&quot;
(...)
Storage&amp;gt; drive

...
Google Application Client Id
Setting your own is recommended.
See https://rclone.org/drive/#making-your-own-client-id for how to create your own.
If you leave this blank, it will use an internal key which is low performance.
Enter a string value. Press Enter for the default (&quot;&quot;).
client_id&amp;gt; 

...
OAuth Client Secret
Leave blank normally.
Enter a string value. Press Enter for the default (&quot;&quot;).
client_secret&amp;gt; 

...

Scope that rclone should use when requesting access from drive.
Enter a string value. Press Enter for the default (&quot;&quot;).
Choose a number from below, or type in your own value
 1 / Full access all files, excluding Application Data Folder.
   \ &quot;drive&quot;
 2 / Read-only access to file metadata and file contents.
   \ &quot;drive.readonly&quot;
   / Access to files created by rclone only.
 3 | These are visible in the drive website.
   | File authorization is revoked when the user deauthorizes the app.
   \ &quot;drive.file&quot;
   / Allows read and write access to the Application Data folder.
 4 | This is not visible in the drive website.
   \ &quot;drive.appfolder&quot;
   / Allows read-only access to file metadata but
 5 | does not allow any access to read or download file content.
   \ &quot;drive.metadata.readonly&quot;
scope&amp;gt; drive

...
Enter a string value. Press Enter for the default (&quot;&quot;).
root_folder_id&amp;gt; 
Service Account Credentials JSON file path 
Leave blank normally.
Needed only if you want use SA instead of interactive login.

Leading `~` will be expanded in the file name as will environment variables such as `${RCLONE_CONFIG_DIR}`.

...
Enter a string value. Press Enter for the default (&quot;&quot;).
service_account_file&amp;gt; 
Edit advanced config? (y/n)
y) Yes
n) No (default)
y/n&amp;gt;

...
Remote config
Use auto config?
 * Say Y if not sure
 * Say N if you are working on a remote or headless machine
y) Yes (default)
n) No
y/n&amp;gt; y

...
Configure this as a team drive?
y) Yes
n) No (default)
y/n&amp;gt; y
--------------------
[gdrive]
type = drive
scope = drive
token = {&quot;access_token&quot;: 토큰값&quot;}
--------------------
y) Yes this is OK (default)
e) Edit this remote
d) Delete this remote
y/e/d&amp;gt; y&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;API를 이용하실 분들은&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;http://cloud.google.com&quot;&gt;http://cloud.google.com&lt;/a&gt;&amp;nbsp;접속해서 발급하시면 된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;공유 드라이브를 사용하려면 team drive 설정 할때 y 눌러야 한다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;804&quot; data-start=&quot;784&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`rclone.conf` 예시&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1752723145860&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[Name]
type = drive
scope = drive
token = {&quot;access_token&quot;:&quot;ya29.a...&quot;,&quot;expiry&quot;:&quot;2025-07-08T16:48:22.410283+09:00&quot;,&quot;expires_in&quot;:3599}
team_drive = 0AH...
root_folder_id =&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-end=&quot;1125&quot; data-start=&quot;1059&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;1125&quot; data-start=&quot;1061&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;team_drive 값은 공유 드라이브를 사용할 때 필요하다. 개인 My Drive만 사용할 경우 생략한다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;OAuth 인증 등 안내에 따라 Google 계정 연동을 마치면 `~/.config/rclone/rclone.conf` 파일이 생성된다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;1150&quot; data-start=&quot;1132&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. GitLab CI 설정&lt;/span&gt;&lt;/h3&gt;
&lt;p data-end=&quot;1226&quot; data-start=&quot;1152&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이제 위에서 생성한 rclone.conf 파일을 GitLab에 등록하고 `.gitlab-ci.yml` 에 업로드 작업을 정의합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1226&quot; data-start=&quot;1152&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1226&quot; data-start=&quot;1152&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1226&quot; data-start=&quot;1152&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1226&quot; data-start=&quot;1152&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;1246&quot; data-start=&quot;1228&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GitLab 변수 등록&lt;/span&gt;&lt;/h4&gt;
&lt;p data-end=&quot;1295&quot; data-start=&quot;1248&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Settings &amp;gt; CI/CD &amp;gt; Variables 에서 다음과 같이 등록한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1456&quot; data-start=&quot;1297&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1323&quot; data-start=&quot;1297&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Key&lt;/b&gt;: RCLONE_CONFIG&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1340&quot; data-start=&quot;1324&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Type&lt;/b&gt;: File&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1377&quot; data-start=&quot;1341&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Value&lt;/b&gt;: `rclone.conf` 파일 내용 업로드&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1456&quot; data-start=&quot;1378&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Flags&lt;/b&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1456&quot; data-start=&quot;1393&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1417&quot; data-start=&quot;1393&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Mask variable (선택)&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1456&quot; data-start=&quot;1420&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Expand variable reference (필수)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`gitlab-ci.yml` 예시&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1752723580100&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;stages:
  - gdrive-upload

variables:
  CONFIG: $RCLONE_CONFIG

.change_files: &amp;amp;change_files
  changes:
    - SomazDocs/**/*
    - &quot;!.gitlab-ci.yml&quot;
    - &quot;!.gitignore&quot;

gdrive-upload:
  stage: gdrive-upload
  image: rclone/rclone:latest
  script:
    - rclone config show --config $CONFIG
    - rclone copy ./SomazDocs &quot;Somaz:SomazDocs&quot; --progress --config $CONFIG
  tags:
    - build-image
  rules:
    - if: '$CI_PIPELINE_SOURCE == &quot;web&quot;'
    - if: '$CI_PIPELINE_SOURCE == &quot;push&quot;'
      &amp;lt;&amp;lt;: *change_files&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2376&quot; data-start=&quot;2128&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2215&quot; data-start=&quot;2128&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;rclone copy 명령어는 로컬의 SomazDocs 폴더를 Google Drive 내의 동일한 이름 폴더에 업로드한다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2265&quot; data-start=&quot;2216&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Somaz는 `rclone.conf` 에 정의된 remote 이름이다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2325&quot; data-start=&quot;2266&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;CONFIG 변수는 GitLab에서 파일 타입으로 등록된 `RCLONE_CONFIG` 를 참조한다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2376&quot; data-start=&quot;2326&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;rules 블록은 웹 UI 실행 또는 특정 폴더 변경 시에만 동작하도록 제어한다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2376&quot; data-start=&quot;2326&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;copy 말고 sync 명령어를 사용하면 완전 동기화가 된다. (주의: 파일 삭제도 됨)&lt;/span&gt;&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&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;
&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;
&lt;h2 data-end=&quot;2389&quot; data-start=&quot;2383&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-end=&quot;2518&quot; data-start=&quot;2391&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;rclone은 다양한 클라우드 스토리지를 지원하며, 특히 Google Drive와의 연동이 강력하고 안정적이다. GitLab CI와 연동하면, 파일 업로드를 자동화하여 협업의 효율성과 기록 관리를 동시에 챙길 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2518&quot; data-start=&quot;2391&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2694&quot; data-start=&quot;2520&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 Google Workspace의 공유 드라이브를 사용하는 경우, team_drive 옵션을 통해 전체 팀이 파일을 실시간으로 확인할 수 있어 더욱 유용하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2694&quot; data-start=&quot;2520&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;작업자 입장에서는 &lt;b&gt;업로드를 신경 쓸 필요 없이 커밋만 하면 Drive에 자동 저장&lt;/b&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;&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://rclone.org/drive/?utm_source=chatgpt.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://rclone.org/drive/?utm_source=chatgpt.com&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.youtube.com/watch?v=n7yB1x2vhKw&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=n7yB1x2vhKw&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>IaC/CI CD Tool</category>
      <category>gitlab</category>
      <category>Google Drive</category>
      <category>rclone</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/435</guid>
      <comments>https://somaz.tistory.com/435#entry435comment</comments>
      <pubDate>Wed, 12 Nov 2025 07:44:19 +0900</pubDate>
    </item>
    <item>
      <title>Python 매직 메서드 완벽 가이드</title>
      <link>https://somaz.tistory.com/469</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Overview&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매직 메서드(Magic Methods)는 Python 클래스에 특별한 기능을 부여하는 메서드다. ` __init__`, `__str__`&amp;nbsp; 처럼 앞뒤로 언더스코어 두 개(__)가 붙어서 &lt;b&gt;던더(Dunder) 메서드&lt;/b&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;color: #000000;&quot;&gt;매직 메서드를 사용하면 클래스가 Python의 내장 함수나 연산자와 자연스럽게 동작하게 만들 수 있다.&lt;/span&gt;&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-origin-width=&quot;2158&quot; data-origin-height=&quot;1720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckPuhQ/dJMb88lz6XA/TcHQVmqR3oKBxkmkLbrXB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckPuhQ/dJMb88lz6XA/TcHQVmqR3oKBxkmkLbrXB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckPuhQ/dJMb88lz6XA/TcHQVmqR3oKBxkmkLbrXB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckPuhQ%2FdJMb88lz6XA%2FTcHQVmqR3oKBxkmkLbrXB0%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;2158&quot; height=&quot;1720&quot; data-origin-width=&quot;2158&quot; data-origin-height=&quot;1720&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 객체 생성과 초기화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__init__`: 생성자&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가장 많이 사용하는 매직 메서드로, 객체가 생성될 때 자동으로 호출된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;ruby&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print(f&quot;{name} 객체가 생성되었습니다!&quot;)

person = Person(&quot;철수&quot;, 25)
# 출력: 철수 객체가 생성되었습니다!&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__new__`: 인스턴스 생성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__init__` 보다 먼저 호출되며, 실제로 객체를 생성하는 메서드다. 싱글톤 패턴 등에서 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;class Singleton:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

s1 = Singleton()
s2 = Singleton()
print(s1 is s2)  # True - 같은 객체!&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 문자열 표현&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__str__`: 사용자 친화적 문자열&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`print()` 함수나 `str()` 로 객체를 출력할 때 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;ruby&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author
    
    def __str__(self):
        return f&quot;'{self.title}' by {self.author}&quot;

book = Book(&quot;파이썬 완벽 가이드&quot;, &quot;홍길동&quot;)
print(book)  # '파이썬 완벽 가이드' by 홍길동&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__repr__`: 개발자용 문자열&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;디버깅할 때 유용하며, `repr()` 함수나 인터프리터에서 객체를 직접 입력했을 때 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __repr__(self):
        return f&quot;Point(x={self.x}, y={self.y})&quot;
    
    def __str__(self):
        return f&quot;({self.x}, {self.y})&quot;

point = Point(3, 4)
print(point)        # (3, 4) - __str__ 사용
print(repr(point))  # Point(x=3, y=4) - __repr__ 사용&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;차이점&lt;/b&gt;: `__str__` 은 일반 사용자용, `__repr__` 은 개발자용으로 더 자세한 정보를 담는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 비교 연산자&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 비교 연산자 구현하기&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;class Money:
    def __init__(self, amount):
        self.amount = amount
    
    def __eq__(self, other):
        &quot;&quot;&quot;==&quot;&quot;&quot;
        return self.amount == other.amount
    
    def __ne__(self, other):
        &quot;&quot;&quot;!=&quot;&quot;&quot;
        return self.amount != other.amount
    
    def __lt__(self, other):
        &quot;&quot;&quot;&amp;lt;&quot;&quot;&quot;
        return self.amount &amp;lt; other.amount
    
    def __le__(self, other):
        &quot;&quot;&quot;&amp;lt;=&quot;&quot;&quot;
        return self.amount &amp;lt;= other.amount
    
    def __gt__(self, other):
        &quot;&quot;&quot;&amp;gt;&quot;&quot;&quot;
        return self.amount &amp;gt; other.amount
    
    def __ge__(self, other):
        &quot;&quot;&quot;&amp;gt;=&quot;&quot;&quot;
        return self.amount &amp;gt;= other.amount

money1 = Money(1000)
money2 = Money(2000)

print(money1 &amp;lt; money2)   # True
print(money1 == money2)  # False
print(money1 &amp;gt;= money2)  # False&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;팁&lt;/b&gt;: `functools.total_ordering` 데코레이터를 사용하면 `__eq__` 와 `__lt__` 만 구현해도 나머지가 자동 생성된다!&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;ruby&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;from functools import total_ordering

@total_ordering
class Money:
    def __init__(self, amount):
        self.amount = amount
    
    def __eq__(self, other):
        return self.amount == other.amount
    
    def __lt__(self, other):
        return self.amount &amp;lt; other.amount
    
    # 이제 &amp;gt;, &amp;lt;=, &amp;gt;= 도 자동으로 사용 가능!&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 산술 연산자&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본 산술 연산&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __add__(self, other):
        &quot;&quot;&quot;+&quot;&quot;&quot;
        return Vector(self.x + other.x, self.y + other.y)
    
    def __sub__(self, other):
        &quot;&quot;&quot;-&quot;&quot;&quot;
        return Vector(self.x - other.x, self.y - other.y)
    
    def __mul__(self, scalar):
        &quot;&quot;&quot;*&quot;&quot;&quot;
        return Vector(self.x * scalar, self.y * scalar)
    
    def __truediv__(self, scalar):
        &quot;&quot;&quot;/&quot;&quot;&quot;
        return Vector(self.x / scalar, self.y / scalar)
    
    def __repr__(self):
        return f&quot;Vector({self.x}, {self.y})&quot;

v1 = Vector(2, 3)
v2 = Vector(1, 1)

print(v1 + v2)      # Vector(3, 4)
print(v1 - v2)      # Vector(1, 2)
print(v1 * 2)       # Vector(4, 6)
print(v1 / 2)       # Vector(1.0, 1.5)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;복합 할당 연산자&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;class Counter:
    def __init__(self, value=0):
        self.value = value
    
    def __iadd__(self, other):
        &quot;&quot;&quot;+=&quot;&quot;&quot;
        self.value += other
        return self
    
    def __isub__(self, other):
        &quot;&quot;&quot;-=&quot;&quot;&quot;
        self.value -= other
        return self

counter = Counter(10)
counter += 5
print(counter.value)  # 15
counter -= 3
print(counter.value)  # 12&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. 컨테이너 매직 메서드&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리스트처럼 동작하는 클래스 만들기&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;class CustomList:
    def __init__(self):
        self._items = []
    
    def __len__(self):
        &quot;&quot;&quot;len() 함수&quot;&quot;&quot;
        return len(self._items)
    
    def __getitem__(self, index):
        &quot;&quot;&quot;obj[index]&quot;&quot;&quot;
        return self._items[index]
    
    def __setitem__(self, index, value):
        &quot;&quot;&quot;obj[index] = value&quot;&quot;&quot;
        self._items[index] = value
    
    def __delitem__(self, index):
        &quot;&quot;&quot;del obj[index]&quot;&quot;&quot;
        del self._items[index]
    
    def __contains__(self, item):
        &quot;&quot;&quot;item in obj&quot;&quot;&quot;
        return item in self._items
    
    def append(self, item):
        self._items.append(item)

my_list = CustomList()
my_list.append(1)
my_list.append(2)
my_list.append(3)

print(len(my_list))        # 3
print(my_list[0])          # 1
print(2 in my_list)        # True
my_list[1] = 10
print(my_list[1])          # 10&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6. 호출 가능한 객체&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__call__`: 객체를 함수처럼 호출&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;ruby&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;class Multiplier:
    def __init__(self, factor):
        self.factor = factor
    
    def __call__(self, x):
        return x * self.factor

double = Multiplier(2)
triple = Multiplier(3)

print(double(5))   # 10
print(triple(5))   # 15

# 객체를 함수처럼 사용 가능!&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실전 예제: 데코레이터를 클래스로 구현&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;ruby&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;class CountCalls:
    def __init__(self, func):
        self.func = func
        self.count = 0
    
    def __call__(self, *args, **kwargs):
        self.count += 1
        print(f&quot;{self.func.__name__} 호출 횟수: {self.count}&quot;)
        return self.func(*args, **kwargs)

@CountCalls
def say_hello():
    print(&quot;Hello!&quot;)

say_hello()  # say_hello 호출 횟수: 1, Hello!
say_hello()  # say_hello 호출 횟수: 2, Hello!
say_hello()  # say_hello 호출 횟수: 3, Hello!&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;7. 컨텍스트 매니저&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__enter__` 와 `__exit__: with `문 지원&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;ruby&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;class FileManager:
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode
        self.file = None
    
    def __enter__(self):
        print(f&quot;파일 열기: {self.filename}&quot;)
        self.file = open(self.filename, self.mode)
        return self.file
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print(&quot;파일 닫기&quot;)
        if self.file:
            self.file.close()

# with 문과 함께 사용
with FileManager('test.txt', 'w') as f:
    f.write(&quot;Hello, World!&quot;)
# 자동으로 파일이 닫힘!&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;8. 실전 예제: 좌표 클래스&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 개념을 활용한 완전한 예제다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #abb2bf; text-align: left;&quot;&gt;&lt;code&gt;from functools import total_ordering
import math

@total_ordering
class Point:
    &quot;&quot;&quot;2D 좌표를 표현하는 클래스&quot;&quot;&quot;
    
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    # 문자열 표현
    def __str__(self):
        return f&quot;({self.x}, {self.y})&quot;
    
    def __repr__(self):
        return f&quot;Point(x={self.x}, y={self.y})&quot;
    
    # 비교 연산
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y
    
    def __lt__(self, other):
        # 원점으로부터의 거리로 비교
        return self.distance_from_origin() &amp;lt; other.distance_from_origin()
    
    # 산술 연산
    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)
    
    def __sub__(self, other):
        return Point(self.x - other.x, self.y - other.y)
    
    def __mul__(self, scalar):
        return Point(self.x * scalar, self.y * scalar)
    
    # 기타 유용한 메서드
    def __abs__(self):
        &quot;&quot;&quot;abs(point) - 원점으로부터의 거리&quot;&quot;&quot;
        return self.distance_from_origin()
    
    def __bool__(self):
        &quot;&quot;&quot;bool(point) - 원점이 아니면 True&quot;&quot;&quot;
        return self.x != 0 or self.y != 0
    
    def distance_from_origin(self):
        return math.sqrt(self.x**2 + self.y**2)

# 사용 예시
p1 = Point(3, 4)
p2 = Point(1, 2)

print(p1)                    # (3, 4)
print(repr(p1))              # Point(x=3, y=4)
print(p1 + p2)               # (4, 6)
print(p1 - p2)               # (2, 2)
print(p1 * 2)                # (6, 8)
print(p1 == p2)              # False
print(p1 &amp;gt; p2)               # True
print(abs(p1))               # 5.0
print(bool(Point(0, 0)))     # False
print(bool(p1))              # True&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 매직 메서드 정리&lt;/span&gt;&lt;/h3&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;카테고리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;생성/소멸&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__init__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;객체 초기화&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__new__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;객체 생성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__del__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;객체 소멸 시&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;문자열&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__str__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;str(), print()&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__repr__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;repr(), 인터프리터&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비교&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__eq__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;==&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__ne__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;!=&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__lt__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__le_`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__gt__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__ge__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;산술&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__add__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;+&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__sub__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__mul__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;*&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__truediv__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__floordiv__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;//&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__mod__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;%&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__pow__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;**&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;컨테이너&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__len__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;len()&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__getitem__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;obj[key]&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__setitem__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;obj[key] = val&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__delitem__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;del obj[key]&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__contains__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;item in obj&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;기타&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__call__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;obj()&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__enter__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;with 문 진입&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__exit__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;with 문 종료&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__bool__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;bool()&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;`__hash__`&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;color: #000000;&quot;&gt;hash()&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결론&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매직 메서드를 활용하면&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클래스를 Python의 내장 타입처럼 자연스럽게 사용 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;연산자 오버로딩으로 직관적인 코드 작성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;더 Pythonic하고 읽기 쉬운 코드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&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;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;color: #000000;&quot;&gt;매직 메서드는 Python의 객체지향 프로그래밍을 한 단계 업그레이드시켜주는 핵심 기능이다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;&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;
&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Reference&lt;/span&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;color: #000000;&quot;&gt;Python Official Docs - Data Model (Special Methods): &lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.python.org/3/reference/datamodel.html&quot;&gt;https://docs.python.org/3/reference/datamodel.html&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;튜토리얼 &amp;amp; 가이드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Real Python - Magic Methods: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://realpython.com/python-magic-methods/&quot;&gt;https://realpython.com/python-magic-methods/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GeeksforGeeks - Dunder Methods: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.geeksforgeeks.org/python/dunder-magic-methods-python/&quot;&gt;https://www.geeksforgeeks.org/python/dunder-magic-methods-python/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rafe Kettler - Magic Methods Guide: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://rszalski.github.io/magicmethods/&quot;&gt;https://rszalski.github.io/magicmethods/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;dbader.org - Dunder Methods: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://dbader.org/blog/python-dunder-methods&quot;&gt;https://dbader.org/blog/python-dunder-methods&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Python Morsels - Every Dunder Method: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.pythonmorsels.com/every-dunder-method/&quot;&gt;https://www.pythonmorsels.com/every-dunder-method/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TutorialsTeacher - Magic Methods: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.tutorialsteacher.com/python/magic-methods-in-python&quot;&gt;https://www.tutorialsteacher.com/python/magic-methods-in-python&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Built In - Dunder Methods: &lt;a style=&quot;color: #000000;&quot; href=&quot;https://builtin.com/data-science/dunder-methods-python&quot;&gt;https://builtin.com/data-science/dunder-methods-python&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Launguage</category>
      <category>Method</category>
      <category>Python</category>
      <author>Somaz</author>
      <guid isPermaLink="true">https://somaz.tistory.com/469</guid>
      <comments>https://somaz.tistory.com/469#entry469comment</comments>
      <pubDate>Fri, 7 Nov 2025 00:00:05 +0900</pubDate>
    </item>
  </channel>
</rss>