Skip to main content
te
Sofrware Engineer
View all authors

오픈 소스 워게임 시뮬레이션 환경 c2z 회고

· 11 min read
te
Sofrware Engineer

title

KT Cloud TECHUP 사이버 보안 과정의 첫 팀 프로젝트로 CVE 기반 취약점 재현 환경을 위한 오픈 소스 시뮬레이션 환경을 개발했습니다.

프로젝트 개요

결과 링크:

팀 구성:

  • 5인으로 이루어진 팀이며, 제가 리드 역할을 맡았습니다.
  • 1명의 컴퓨터 관련 전공자와 저를 포함한 4명의 비전공자로 구성됐습니다.
    • 팀원 다수가 레드팀/모의해킹 분야를 희망하였습니다.
  • 1달 동안의 프로젝트 기간을 2개의 스프린트로 나누어 수행하였습니다.
  • 각 스프린트 동안 서브 팀을 구성하여, 팀원들이 다양한 역할을 맡아 기여할 수 있도록 조직했습니다.
  • 프로젝트에서 각 팀원들의 작업이 서로 협업할 수 있도록 리드했습니다.
    • 각자 맡은 역할이 서로 선행되어야 진행될 수 있도록 태스크를 분배하여, 팀원 간 서로 맡은 작업을 이해할 수 있도록 하였습니다.
    • 각자 맡은 작업을 완료한 뒤, 보고서 및 문서화를 강조하여 서로 어떤 작업을 수행했는지 이해할 수 있도록 하였습니다.
    • 매일, 매주, 매 스프린트마다 회고를 진행하여 팀원 각자 어떤 노력을 했고, 기술적 성장을 이루었는지 공유했습니다.

프로젝트 기간:

  • 총 5주
  • Sprint 1 : 2025/12/08 ~ 2025/12/19
  • Sprint 2 : 2025/12/22 ~ 2026/01/07

역할

각 팀원의 관심사와 목표에 따라 스프린트 별로 내부 팀을 나누었습니다.

  • Sprint 1: 재현환경 개발팀 / 공격 설계팀
  • Sprint 2: 블루팀 / 레드팀

저는 각각의 스프린트에서 재현환경 개발팀-블루팀에 속하였으나,
팀 리드로서 팀 서포트 및 협업을 수행했습니다.


c2z 오픈소스 CVE 재현 환경 시뮬레이터

소개

c2z-pj

c2z(Container to Zone)는 Kubernetes 네이티브 환경에서 동작하는 자동화된 CVE 재현 환경 시뮬레이터입니다.

  • Helm Chart를 통해 배포되며, GitHub Pages를 통해 퍼블릭 Helm Repository로 제공됩니다.
  • 보안 연구자와 학습자가 실전적인 취약점 분석 환경을 빠르게 구축할 수 있습니다.
  • k3d(macOS) 및 k3s(Linux)를 지원하여 로컬 환경에서 손쉽게 실행 가능합니다.
  • 컨테이너 기반으로 가상머신 대비 현저히 낮은 리소스 점유율을 자랑합니다.
  • CVE별 Docker 이미지를 GHCR(GitHub Container Registry)에 배포하여 재현 환경을 표준화했습니다.
  • Cloudflare Tunnel을 활용한 외부 접근 자동화 스크립트를 제공합니다.

기여

각 스프린트 별로는 다음과 같은 작업을 수행했습니다:

  • 스프린트 1 :
    • 재현환경 개발팀에 속하여 공격 설계팀이 조사 내용을 바탕으로 재현 환경에 필요한 Docker 이미지와 Kubernetes 매니페스트를 개발하였습니다.
    • 쿠버네티스 클러스터 구축을 위한 Helm 차트를 개발했습니다. /simulation/monitoring PodService를 구성하였습니다.
  • 스프린트 2 :
    • 블루팀에 속하여 재현 환경이 정상적으로 실행되지 않을 때 디버깅하였고, 포트포워딩 및 구축 환경에 필요한 스크립트를 개발하였습니다.
    • 레드팀이 침투에 성공한 환경을 버전 패치하고, 추가 재현 환경을 위한 Pod를 개발했습니다.

구체적으로 c2z를 개발하면서 제가 기여한 부분은 다음과 같습니다:

  • 프로젝트 전체 아키텍처 설계 및 Kubernetes 리소스 구조 설계
  • 5개 CVE 재현 환경 개발 (Docker 이미지 빌드 및 K8s 매니페스트 작성)
    • CVE-2025-55182: Next.js 16 (React2Shell)
    • CVE-2025-66205: Frappe (Frappe/ Redis / MySQL)
    • CVE-2025-56749: Academy LMS (Apache/ PHP / MySQL)
    • CVE-2025-63531: Blood Bank (Apache/ PHP / MariaDB)
    • CVE-2025-63689: Money POS (Apache/ PHP / MySQL)
  • Helm Chart 개발 및 GitHub Pages 기반 Helm Repository 구축
  • 멀티 플랫폼(linux/amd64, linux/arm64) Docker 이미지 빌드 자동화
  • install.sh 자동 설치 스크립트 개발
  • Cloudflare Tunnel 기반 외부 노출 자동화 스크립트 (expose_simulation_tunnel.py)
  • CI/CD 배포 파이프라인 개발 및 유지보수

시스템 설계 및 동작 원리

c2z는 Kubernetes를 기반으로 한 컨테이너 오케스트레이션 환경에서 동작합니다.

k8s

전체 시스템은 크게 세 가지 계층으로 구성됩니다:

1. 배포 계층 (Deployment Layer) 사용자는 install.sh 스크립트를 실행하여 환경을 자동으로 구축합니다. 스크립트는 다음을 수행합니다:

  • Python 가상환경 설정 및 의존성 설치
  • 시스템 요구사항 검증 (RAM, Docker 등)
  • Kubernetes 클러스터 설치 (macOS는 k3d, Linux는 k3s)
  • Helm 설치 및 c2z Chart 배포
  • GHCR 인증을 위한 Secret 생성 및 복제

2. 런타임 계층 (Runtime Layer) Kubernetes 클러스터 내에서 CVE 재현 환경이 Pod로 실행됩니다.

  • 각 CVE는 독립된 Pod와 Service로 격리되어 실행
  • simulation 네임스페이스에서 모든 취약점 환경 관리
  • GHCR에서 프라이빗 이미지를 Pull하여 컨테이너 실행
  • 멀티 컨테이너 Pod 지원 (예: 웹 서버 + 데이터베이스)

3. 외부 노출 계층 (Exposure Layer) 로컬 클러스터의 서비스를 외부에서 접근 가능하도록 만듭니다.

  • kubectl port-forward로 로컬 포트 바인딩
  • Cloudflare Tunnel(cloudflared)을 통해 공개 URL 생성
  • Python 스크립트로 전체 프로세스 자동화

이러한 구조를 통해 한 번의 설치로 여러 CVE 환경을 동시에 실행할 수 있으며,
각 환경은 독립적으로 관리되어 서로 영향을 주지 않도록 작업했습니다.


CVE 재현 작업

프로젝트 기간 동안 총 5개의 CVE 재현 환경을 개발했습니다. 각 CVE마다 고유한 기술 스택과 환경 설정이 필요했기에, 다양한 학습과 트러블 슈팅을 경험할 수 있었습니다.

CVE-2025-55182: Next.js 16 취약점

Next.js 16.0.6Next.js 16.0.10
c2z-nextjs-16.0.6c2z-nextjs-16.0.10
React Server Component + Next.js (No API route)Next.js 16.0.6 → 16.0.10 패치 + API route 엔드포인트 개발

Next.js 16 버전의 SSR 관련 취약점을 재현하는 환경입니다. 이 작업에서는 Node.js 기반 애플리케이션을 컨테이너화하는 과정을 학습했습니다.

작업 내용:

  • Next.js 16 애플리케이션 Docker 이미지 빌드
  • 멀티 스테이지 빌드를 통한 이미지 크기 최적화
  • Kubernetes Pod 및 Service 매니페스트 작성
  • GHCR 프라이빗 레지스트리 배포 자동화

CVE-2025-66205: Frappe Framework

c2z-frappe

Frappe는 Python 기반 풀스택 프레임워크로, 상당히 복잡한 설정이 필요했습니다.
특히 초기화 컨테이너(Init Container) 패턴을 처음 적용해본 작업이었습니다.

작업 내용:

  • Frappe 취약 버전 기본 이미지(frappe/base:v15.85.1) 기반 커스텀 이미지 빌드
  • MariaDB 연동을 위한 멀티 컨테이너 Pod 구성
  • Init Container를 통한 데이터베이스 초기화 자동화
  • bench 명령어를 활용한 Frappe 애플리케이션 설정

이 과정에서 Init Container가 메인 컨테이너보다 먼저 실행되어
사전 작업(DB 마이그레이션, 설정 초기화 등)을 수행하는 패턴을 익혔습니다.

CVE-2025-63531: Blood Bank 시스템

c2z-bb

PHP 기반 레거시 애플리케이션으로, 데이터베이스 연동이 핵심이었습니다.

작업 내용:

  • Apache + PHP 환경 Docker 이미지 구성
  • MariaDB 컨테이너와의 네트워크 연결 설정
  • 환경 변수를 통한 DB 크레덴셜 관리
  • Pod 내 볼륨 마운트를 통한 초기 SQL 스크립트 개발

레거시 PHP 애플리케이션을 컨테이너화하면서,
기존 코드 수정 없이 환경 변수만으로 설정을 주입하는 방법을 배웠습니다.

CVE-2025-63689: Money POS

Java Spring Boot 기반의 복잡한 엔터프라이즈 애플리케이션이었습니다.
여러 의존성 서비스를 조율하는 작업이 가장 도전적이었습니다.

작업 내용:

  • MySQL, Redis, XXL-Job-Admin, Money-App-Biz 4개 컴포넌트 통합
  • 각 컴포넌트별 Docker 이미지 빌드
  • Kubernetes Deployment 및 Service 리소스 작성
  • 컴포넌트 간 네트워크 통신 검증

이 작업을 통해 마이크로서비스 아키텍처를 Kubernetes로 구현하는 실전 경험을 쌓을 수 있었습니다.

CVE-2025-56749: Academy LMS

PHP 기반 학습 관리 시스템으로, 권한 상승 BAC 취약점을 재현하는 환경이었습니다.

작업 내용:

  • Apache + PHP + MySQL 스택 구성
  • 볼륨 마운트를 통한 영구 데이터 저장
  • 파일 업로드 디렉토리 권한 설정

Kubernetes 및 Helm 기술 스택

Kubernetes 네이티브 환경 구축

이전에는 가상머신 기반으로 보안 랩을 구성했었는데,
이번 프로젝트에서는 Kubernetes를 선택했습니다.

Kubernetes를 선택한 이유:

  • 컨테이너 기반으로 리소스 효율성이 높음
  • 선언적 설정(YAML)으로 환경 재현이 용이
  • Pod, Service, Namespace 등으로 명확한 격리 가능
  • Helm을 통한 패키징 및 배포 자동화
  • OpenStack 환경 설치 용이성을 고려

c2z 또한 오픈소스를 감안하여 작업하였기애, 누구나 git clone으로 쉽게 설치할 수 있도록 install.sh 스크립트를 작성했습니다.
macOS와 Linux 환경 모두 지원하기 위해:

  • macOS: k3d (Docker Desktop 위에서 실행되는 경량 Kubernetes)
  • Linux: k3s (네이티브 경량 Kubernetes)

를 각각 지원하도록 install.sh 스크립트를 작성했습니다.

특히 k3d 클러스터 생성 시 로드밸런서를 통한 포트 포워딩 설정이 중요했습니다:

k3d cluster create c2z \
--api-port 6443 \
--port "80:80@loadbalancer" \
--port "443:443@loadbalancer" \
--port "3000-3005:3000-3005@loadbalancer" \
--agents 1 \
--k3s-arg "--disable=traefik@server:*"

이 설정으로 호스트의 특정 포트를 클러스터 내부 서비스로 직접 연결할 수 있었습니다.

Helm Chart 개발

Kubernetes 매니페스트를 직접 관리하는 것은 복잡하고 오류가 발생하기 쉽습니다.
이에 Helm을 도입하여 패키징, 버전 관리, 배포를 표준화했습니다.

Helm Chart 구조:

charts/c2z/
├── Chart.yaml # Chart 메타데이터
├── values.yaml # 기본 설정 값
└── templates/
├── namespaces.yaml
├── simulation/ # CVE 재현 환경 템플릿
│ ├── cve-2025-55182.yaml
│ ├── cve-2025-55182-service.yaml
│ ├── cve-2025-66205.yaml
│ └── ...
└── monitoring/ # 모니터링 스택 (구현 예정)

Helm을 통해 얻은 이점:

  • 템플릿화: 공통 패턴을 재사용하여 코드 중복 제거
  • 값 주입: values.yaml로 환경별 설정 관리
  • 원클릭 배포: helm install 한 번으로 전체 환경 구축
  • 버전 관리: Chart 버전으로 릴리스 추적

Helm Repository (GitHub Pages)

c2z-helm

Helm Chart를 누구나 사용할 수 있도록 퍼블릭 Repository로 배포했습니다.
GitHub Pages를 활용하여 Helm Repository 또한 연동하였고, CI/CD 파이프라인에 통합했습니다.

구현 내용:

  1. GitHub Actions 워크플로우 작성 (.github/workflows/deploy.yml)
  2. main 브랜치에 푸시 시 자동으로 Chart 패키징
  3. helm repo indexindex.yaml 생성 및 업데이트
  4. GitHub Pages에 배포

사용자는 다음 명령어로 c2z를 설치할 수 있습니다:

helm repo add c2z https://s2n0n.github.io/c2z/
helm repo update
helm install c2z c2z/c2z

이를 통해 오픈소스 프로젝트로서의 접근성을 크게 높일 수 있었습니다.

Cloudflare Tunnel을 활용한 외부 노출

c2z-tunnel

로컬 Kubernetes 클러스터의 서비스를 외부에서 접근 가능하게 만들어야 했습니다.
ngrok도 고려했지만, 최종적으로 Cloudflare Tunnel을 선택했습니다.

Cloudflare Tunnel의 장점:

  • 무료로 무제한 터널 생성 가능
  • HTTPS 자동 적용
  • Docker 이미지로 제공되어 쉽게 실행 가능
  • 안정적인 연결 유지

자동화 스크립트 (expose_simulation_tunnel.py) 동작 원리:

  1. kubectl get svc -n simulation으로 서비스 목록 조회
  2. 각 서비스마다 사용 가능한 로컬 포트 찾기
  3. kubectl port-forward로 서비스를 로컬 포트에 바인딩
  4. cloudflared tunnel로 해당 로컬 포트를 공개 URL로 노출
  5. 생성된 URL 목록 출력

이 스크립트 하나로 모든 CVE 환경을 동시에 외부 접근 가능하게 만들 수 있었습니다.


인프라 자동화 및 배포 파이프라인

GHCR Secret 관리 자동화

프라이빗 이미지를 Kubernetes에서 Pull하려면 ImagePullSecret이 필요합니다.
처음에는 수동으로 Secret을 생성했는데, 여러 네임스페이스에 복제하는 과정이 번거로웠습니다.

install.sh 스크립트에 자동화 로직 추가:

  1. .env.local 파일에서 GitHub 인증 정보 로드
  2. c2z-system 네임스페이스에 ghcr-secret 생성
  3. simulation 네임스페이스로 Secret 복제
  4. 모든 Pod 템플릿에 imagePullSecrets 자동 적용

이 자동화를 통해 사용자는 한 번의 설정으로 모든 CVE 환경을 배포할 수 있게 되었습니다.

원클릭 설치 스크립트 (install.sh)

초기에는 Kubernetes 설치, Helm 설치, Chart 배포를 모두 수동으로 진행했습니다.
하지만 팀원들과 사용자들이 쉽게 환경을 구축할 수 있도록 자동화 스크립트를 개발했습니다.

install.sh의 주요 기능:

  • Python 가상환경 자동 생성 및 의존성 설치
  • 시스템 요구사항 검증 (RAM, Docker 등)
  • OS 감지 및 적절한 Kubernetes 배포 (k3d/k3s)
  • Helm 자동 설치
  • GHCR Secret 대화형 생성
  • c2z Helm Chart 자동 배포
  • CLI 래퍼 스크립트 생성

사용자는 단 두 줄의 명령어로 전체 환경을 구축할 수 있습니다:

chmod +x install.sh
./install.sh

이 스크립트를 작성하면서 **사용자 경험(UX)**의 중요성을 다시 한번 느꼈습니다.


트러블 슈팅 및 기술적 도전

c2z 프로젝트는 s2n보다 훨씬 다양한 기술 스택을 다루었기에,
더 많은 트러블 슈팅과 학습이 필요했습니다.

ImagePullBackOff 해결

Kubernetes 초보자가 가장 흔히 마주치는 에러 중 하나입니다.
처음 CVE Pod를 배포했을 때, 모든 Pod가 ImagePullBackOff 상태였습니다.

원인 분석:

  • GHCR 프라이빗 레지스트리에서 이미지를 Pull하려면 인증 필요
  • imagePullSecrets가 Pod 스펙에 정의되지 않음
  • Secret이 잘못된 네임스페이스에 생성됨

해결 방법:

  1. kubectl create secret docker-registry로 Secret 생성
  2. Pod 템플릿에 imagePullSecrets 추가
  3. install.sh에서 Secret을 필요한 모든 네임스페이스에 복제하도록 자동화

이 경험을 통해 Kubernetes의 네임스페이스 격리Secret 관리의 중요성을 배웠습니다.

Init Container CrashLoopBackOff

Frappe CVE 환경을 배포할 때, Pod는 생성되지만 Init:CrashLoopBackOff 상태였습니다.

원인 분석:

  • Init Container가 데이터베이스 초기화 수행
  • 하지만 MariaDB 컨테이너가 아직 준비되지 않아 연결 실패
  • Init Container가 재시작을 반복

해결 방법:

  • Init Container에 재시도 로직 추가
  • sleepfor 루프로 DB가 준비될 때까지 대기
  • MariaDB의 readinessProbe 설정으로 준비 상태 명확히 정의

Kubernetes의 컨테이너 생명주기 관리에 대해 깊이 이해할 수 있었습니다.

Port Forwarding 충돌 해결

여러 서비스를 동시에 port-forward하면 포트 충돌이 발생했습니다.
expose_simulation_tunnel.py 스크립트에 동적 포트 할당 로직을 구현했습니다.

구현 내용:

  • 8000번 포트부터 순차적으로 사용 가능한 포트 탐색
  • socket.connect_ex()로 포트 사용 여부 확인
  • 이미 사용한 포트를 set으로 추적하여 중복 방지

이를 통해 수십 개의 서비스도 자동으로 포트를 할당받아 동시에 실행할 수 있게 되었습니다.

Cloudflare Tunnel URL 파싱

cloudflared는 터널 URL을 stdout 또는 stderr에 출력하는데,
출력 포맷이 일정하지 않아 파싱이 어려웠습니다.

해결 방법:

  • 정규표현식으로 *.trycloudflare.com 패턴 추출
  • 타임아웃(30초) 설정하여 무한 대기 방지
  • 백그라운드 스레드로 나머지 출력 소비하여 버퍼 블로킹 방지

정규표현식과 멀티스레딩을 활용한 파싱 로직 작성이 좋은 학습 경험이었습니다.


회고 및 배운 점

Kubernetes 생태계에 대한 이해

이번 프로젝트를 통해 Kubernetes의 핵심 개념을 실전에서 익혔습니다:

  • Pod, Service, Namespace, Secret 등 리소스 관리
  • Init Container, Sidecar Container 패턴
  • ImagePullSecrets, ConfigMap, Volume 활용
  • Readiness Probe, Liveness Probe 설정

단순히 튜토리얼을 따라하는 것과,
실제 문제를 해결하며 배우는 것은 확실히 다르다는 것을 느꼈습니다.

Infrastructure as Code의 가치

모든 설정을 YAML 파일로 관리하면서,
재현 가능한 인프라의 중요성을 체감했습니다.

Git으로 버전 관리되는 YAML 파일 하나면,
언제든지 동일한 환경을 다시 만들 수 있습니다.
이는 협업과 문서화 측면에서 엄청난 이점이었습니다.

자동화의 힘

install.sh, expose_simulation_tunnel.py 같은 스크립트를 작성하면서,
반복 작업을 자동화하는 것이 얼마나 중요한지 깨달았습니다.

처음에는 스크립트 작성이 시간이 걸리더라도,
장기적으로는 엄청난 시간 절약과 오류 감소 효과가 있었습니다.

오픈소스 프로젝트 운영 경험

Helm Repository를 GitHub Pages로 배포하고,
Docker 이미지를 GHCR에 퍼블리싱하면서,
오픈소스 프로젝트를 운영하는 과정을 경험했습니다.

사용자 입장에서 얼마나 쉽게 설치하고 사용할 수 있는지가
프로젝트의 성공을 좌우한다는 것을 배웠습니다.


긴 글 읽어주셔서 감사합니다!
힘든 상황에서도 함께 힘써주신 팀원 여러분, 영운, 민욱, 민재, 서원님께도 감사드립니다!

오픈 소스 라이브러리 s2n 회고

· 7 min read
te
Sofrware Engineer

title

KT Cloud TECHUP 사이버 보안 과정의 첫 팀 프로젝트로 오픈 소스 파이썬 라이브러리를 개발했습니다.

프로젝트 개요

결과 링크:

팀 구성:

  • 5인으로 이루어진 팀이며, 제가 리드 역할을 맡았습니다.
  • 2명의 컴퓨터 관련 전공자와 저를 포함한 3명의 비전공자로 구성됐습니다.
    • 비전공자 팀원 두 분에겐 첫 개발 프로젝트였습니다.

프로젝트 기간:

  • 총 5주
  • Sprint 1 : 2025/11/03 ~ 2025/11/16
  • Sprint 2 : 2025/11/17 ~ 2025/12/01

역할

각 팀원의 관심사와 목표에 따라 스프린트 별로 내부 팀을 나누었습니다.

  • Sprint 1: 인프라팀 / 코어팀
  • Sprint 2: 라이브러리팀 / 클라우드팀

저는 인프라-라이브러리 팀에 속하였으나,
팀 리드로서 팀 서포트 및 여러 일을 맡았습니다.


s2n 취약점 스캐너 라이브러리

소개

s2n-cli

s2n은 파이썬 오픈소스 취약점 스캐너입니다.

  • PyPi에 등록 및 배포가 되어있어, 파이썬 환경에서 패키지를 다운받아 실행할 수 있습니다.
  • CLI 기능을 제공하여 파이썬과 여러 환경에서 실행 가능합니다.
    • Docker 이미지 또한 배포되어 있어, 컨테이너 환경에서도 실행할 수 있습니다.
  • XSS, CSRF, SQL Injection 등 7종의 주요 공격 기법 취약성을 스캔할 수 있습니다.
  • 타겟 URL을 입력하여 취약점을 스캔합니다.
    • DAST 방식으로 런타임 취약점을 점검합니다.
  • 스캔 대상에 실질적인 피해를 주지 않는 안전한 방식을 고려했습니다.
  • 스캔 결과를 JSON, HTML로 Export하거나 콘솔을 출력할 수 있습니다.

기여

s2n을 개발하면서 제가 기여한 부분은 다음과 같습니다:

  • 시스템 설계 및 주요 인터페이스 개발
  • CSRF 플러그인 개발 및 플러그인 전반 코드 컨벤션 적용하여 리팩터링
  • 스캔 엔진 인증 모듈, CLI 인터페이스 개선 및 유지보수
  • 플러그인 전반의 Pytest 작성 및 conftest로 공용 모킹 모듈 작성
  • 배포 파이프라인에 테스트 적용 및 유지보수
  • CI/CD 배포 파이프라인 개발 및 유지보수
  • Docker Image 개발 및 자동 배포 환경 구축
    • dev : Github Container Registry 배포 (s2n:dev)
    • main : Docker Hub 퍼블릭 레지스트리 배포 (opens2n/s2n-docker:latest)

작업 PR

시스템 설계 및 동작 원리

s2n-system

위 설계도는 s2n의 전체 구조를 한눈에 보여주는 시스템 아키텍처입니다.

  1. 사용자가 CLI 혹은 코드 레벨에서 Scanner 객체를 호출하여 인자를 입력하고
  2. 스캐너가 입력을 받아 플러그인을 통해 분석을 수행한 뒤
  3. 리포트를 출력하기까지의 흐름을 중심으로 구성했습니다.
  • 코드 레벨과 CI/CD 환경에서 실행될 수 있도록 CLI 인터페이스까지 설계 단계에서 고려했습니다.
  • 동적 분석(DAST)을 기반으로, 실행 흐름에서 생성되는 request 인스턴스를 공용 모듈이 중앙에서 관리하도록 설계했습니다. 이를 통해 세션과 인증을 일관되게 처리할 수 있도록 구조를 정리했습니다.

가장 바깥에는 사용자가 진입하는 Entry Point가 있습니다. CLI에서 URL과 설정, 플러그인을 직접 지정하거나, Python 패키지로 Scanner 클래스를 불러와 사용할 수 있습니다.

입력된 요청은 Core System을 통해 처리됩니다. 코어 영역은 스캐너의 핵심 로직이 모여 있는 부분으로, 설정 관리, 인증 처리, 로깅, HTTP 요청 관리, 크롤링, 세션 유지 등
실제 스캐닝 과정에 필요한 공통 기능이 모두 이 계층에 포함됩니다. 스캔 과정 중 발생하는 집계, 에러, 인증, 세션 관리 등의 처리가 이 코어 시스템을 통해 조율됩니다.

실제 취약점 탐지는 Plugin System에서 이루어집니다.

플러그인 매니저가 필요한 플러그인을 로드하고 실행 파이프라인을 구성하면, SQL Injection, XSS, CSRF 등을 포함한 다양한 플러그인이 타겟 URL에 대해 검사를 수행합니다. 설계 초기부터 확장 가능한 구조를 염두하여,새로운 플러그인을 추가하는 것이 가능하게끔 개발했습니다.

스캔 과정에서 발생할 수 있는 오류들은 Error Handling 시스템에서 통합적으로 다룹니다. 네트워크 오류, 인증 문제, 플러그인 실행 오류 등을 분류하고 적절히 대응하여 스캐너 전체가 중단되지 않고 동작하도록 했습니다.

최종적으로 결과는 Reporting System에서 다양한 형식으로 출력됩니다. JSON, HTML, 콘솔 출력, CSV 등 사용 목적에 맞추어 결과를 가공하며, 특히 HTML 리포트는 대시보드 형태로 시각적 확인이 가능합니다.


팀 협업

sprint-teams

팀원 과반이 프로젝트 경험이 부족하였기에, 자연스럽게 리드를 맡게 되었습니다.
사실 어떤 직함이나 역할을 갖고 리드 역할을 한 것은 처음이었기에, 꽤 도전적인 경험이었습니다.
(프로젝트를 진행하면서, 전직장에서 FE 챕터 리드님이 고생하시던 모습이 자주 떠올랐습니다.)

팀을 리드하면서 스스로 지키자고 세웠던 원칙은 다음과 같습니다:

  • 경험이 더 있다고 팀원들에게 오만하게 굴지 말것
  • 과정과 결과를 기록할 것
  • 누구든 자유롭게 의견을 낼 수 있도록 할 것
  • 나를 포함한 한 사람의 의견에 프로젝트가 좌우되게 하지 않을 것
  • 팀 전원이 하고 싶은 일을 하도록 조율할 것
  • 모르는 부분이 있으면 누구나 질문하고, 성실히 답할 것
  • 즐거운 분위기를 유지할 것

혼자서 오랫동안 취업 준비를 해서 그런지, 다양한 배경의 팀원들과 함께하여 무척 즐거웠습니다.
이번 프로젝트를 통해 개발을 처음 시작할 때의 열정이 떠올라 보람찼습니다.

노션 기록과 문서화

s2n-notion

현직에 있을 때도 결과와 과정의 문서화를 중시하던 편이라,
팀원 모두에게 문서 기반으로 작업하도록 요청하였습니다.

Github PR

pr-s2n

오픈 소스를 만드는 프로젝트이기에, GitGithub 활용이 중요했습니다. 이번 기회에 깃 관련 경험이 적은 팀원들 위해 매뉴얼 작성과 간단한 세션을 진행했습니다.
결과적으로, 팀원 전원이 PR을 1회 이상 작성하였고, 브랜치를 병합했습니다.

바쁘게 작업을 하다보면 일일히 회고를 작성하기 어렵습니다.
PR 단위로 작업을 한 뒤, 문서를 작성하여 작업 이력을 활용할 수 있습니다.
팀 규칙으로 PR 작성을 ruleset으로 정하였고, PR 템플릿을 작성했습니다.

s2n-git-1 s2n-git-2

프로젝트 초기에 브랜치 전략을 실제 업무 현장처럼 다소 복잡하게 구성했는데,
추후 4시간동안 꼬인 커밋을 리베이스로 정리하면서 후회도 했습니다.
하지만 고생한만큼 반복하여 발생하던 깃 충돌 문제를 해결할 수 있었습니다.
이후 깃 브랜치 전략을 main - dev - 작업 브랜치 3단계로 단순화하였습니다.


트러블 슈팅 및 기술적 도전

Github s2n PR 리스트

작업의 모든 과정을 PR로 기록했습니다.
pull_request_template.md를 작성하여 팀원 전원이 자신이 올린 PR을 설명하도록 팀 규칙을 정했습니다. 개발 과정에서 기억에 남고 학습이 되었던 PR 내용을 간략히 설명하면 다음과 같습니다.

일관된 개발 환경 구축

파이썬 경험도 많지 않고, 도커 또한 경험이 많지 않았기에 서툴렀던 점이 많았습니다.
스스로 학습도 해가며, 팀원들에게 도움이 되도록 PR문서에 매뉴얼도 함께 작성했습니다.

  1. Python 버전 및 .venv 통합 (PR #43) 팀원별 Python 버전이 달라 실행 오류가 발생하던 문제를 해결하기 위해 Python 3.11.14 + 통일된 가상환경(.venv) 기반의 개발 환경을 표준화했습니다.
  • 모든 팀원이 pyenv로 동일한 버전을 설치하도록 매뉴얼화
  • setup_venv 스크립트를 통해 한 번에 .venv 생성 및 활성화
  • 코드 에디터(vscode, PyCharm 등)의 프로젝트 전역 Python 경로를 .envs/python/.venv로 통합
  • .gitignore를 정리하고 불필요한 항목 제거, 환경 관련 폴더만 정확히 제외하도록 구조 개선
  • 추가로 학습 내용에 대해 글 작성 뒤 팀원들에게 공유 : venv 학습 문서

팀 리드로서 프로젝트 초반에 신경써야할 부분이었지만, 뒤늦게라도 작업하여 반복된 (주로 린트) 문제를 해결할 수 있었습니다.

  1. 로컬 DVWA 환경 구축 (PR #4) 보안 스캐너를 테스트하기 위한 DVWA(Local Damn Vulnerable Web App) 환경을 직접 구성했습니다. Docker 기반으로 누구나 동일한 환경에서 취약점 스캔 실험을 할 수 있도록 설계했습니다.
  • .envs/dev 경로에 DVWA용 docker-compose.yml, Dockerfile 작성
  • 실행/중지를 위한 스크립트(run_dvwa.sh, stop_dvwa.sh)를 개발
  • .env.dev 파일을 이용해 팀원 간 환경 변수를 통일
  • 팀원들은 bash run_dvwa.sh 한 번으로 DVWA를 실행하고, 동일 주소에서 테스트 가능

이 작업을 통해 팀 전체가 동일한 취약점 테스트 환경을 공유할 수 있게 되었습니다.

Docker Image 멀티 플랫폼

title 이미지 배포 이후, Vagrantlinux debian을 실행하였는데, 다음과 같은 에러가 났습니다.

PR-93 링크

에러 원인을 확인해보니, 컨테이너 이미지를 단일 아키텍처(ARM)에서만 제공할 경우, AMD에서 실행할 수 없다는 문제가 있었습니다. 이를 해결하기 위해서 배포 스크립트의 docker 이미지 빌드 단계를 수정했습니다. (자세한 내용은 위의 PR 링크에 기록했습니다.) docker buildx를 활용하여 멀티 플랫폼 이미지를 자동으로 빌드하도록 CI/CD 파이프라인을 개선하는 작업이었습니다.

기여한 내용은 다음과 같습니다:

  • GitHub Actions 워크플로우에 setup-buildx-action을 추가하여 멀티 아키텍처 빌드 환경 구성
  • linux/amd64, linux/arm64 대상 이미지 빌드 및 Docker Hub로 자동 푸시 설정
  • Dockerfile을 멀티 스테이지로 개선하여 이미지 크기 최적화
  • 이미지 실행 시 Python 의존성이 정상적으로 동작하도록 런타임 환경 검증

이 과정을 통해 팀원들 모두 M1/M2 환경에서도 문제 없이 s2n을 실행할 수 있게 되었고, 프로젝트의 배포 범위와 활용성을 크게 늘린 의미 있는 작업이었습니다.

신경쓰지 못한 부분이었는데, 실제 사용을 해보면서 알 수 있어 좋았습니다.

Pytest

PR-83 링크

프로젝트가 커질수록 수동 테스트만으로는 기능 안정성을 보장하기 어려웠습니다. 이에 pytest 기반의 자동 테스트 환경을 구축하여 플러그인 동작과 핵심 스캐너 로직을 검증할 수 있도록 했습니다. 이 과정에서 코드 전반에 일정한 패턴을 적용하도록 리팩터링을 함께 진행했습니다.

주요 작업 내용은 다음과 같습니다:

  • 프로젝트 구조에 맞춰 tests/ 디렉토리 구성 및 기본 테스트 스켈레톤 작성
  • 스캐너 핵심 엔진, 유틸리티 함수, 플러그인 로딩 로직 테스트 케이스 구현
  • Mocking을 활용해 HTTP 요청/응답을 가짜 객체로 처리하여 안전하게 테스트하도록 구성
  • CLI 실행 결과를 캡처하여 정상적으로 출력되는지 검증하는 테스트 추가
  • GitHub Actions에서 pytest가 자동 실행되도록 CI 통합

긴 글 읽어주셔서 감사합니다!

AWS Github CICD 배포 파이프라인 설계

· 6 min read
te
Sofrware Engineer

이 문서는 팀 프로젝트에서 AWS 협업 과정을 기록하기 위해 작성했습니다.

  • AWS 클라우드 환경을 IaC 기반으로 구축하기 위한 CI/CD 파이프라인을 설계를 다룹니다.

프로젝트 개요 Project Overview

AWS 클라우드 구축: EC2 서버앱 + RDS + S3 + Cloudformation

두번째 스프린트에서 프로젝트 목적은 클라우드 보안 체계 및 시스템 수립이었습니다.
프로젝트 기간이 많이 남지 않아 Web Socket을 이용한 간단한 실시간 채팅앱을 MVP로 목표했으며,
학습 목적을 고려해 (채팅앱에는 일반적이진 않은) 여러 AWS 기능을 구성했습니다.

  • Region : 서울 Seoul (ap-northeast-2)
  • IAM: 1개의 루트 계정과 각 팀원들에게 적절한 IAM 권한을 설정했습니다. (MFA를 사용합니다.)
  • VPC: Public SubnetPrivate Subnet으로 나누어 외부에 노출되어선 안될 기능을 프라이빗 서브넷에 두었습니다.
    • ACL: 보안을 위한 적절한 ACLAccess Control List과 보안 그룹 Security Group(sg)을 설정했습니다.
  • Route 53: DNS로 상용 중인 AWS 인스턴스를 라우팅하기 위해 사용했습니다.
  • EC2: t3.micro, Python/Flask로 빌드된 서버앱을 배포하기 위해 사용했습니다.
    • Docker: 브랜치 병합 시 Github Actions 환경의 CI 단계에서 파이썬 앱을 도커 이미지로 빌드한 뒤, Github Container Registry에 배포합니다.
    • EC2-Runner: 이미지 배포가 끝난 뒤, 새 버전의 이미지를 pull하여 새로운 컨테이너로 교체합니다.
  • RDS: MySQL 데이터베이스로 채팅 메타데이터, 세션 등을 저장합니다.
    • AWS 튜토리얼에도 명시되었듯이, 일반적으로 실시간 기능에는 DynamoDB, Lambda, Firehose 등을 조합하여 사용합니다. 이번 프로젝트에선 파이썬 Flask을 학습하고, EC2에서 컨테이너를 활용하기 위해 사용했습니다.
  • Application Load Balancer: 분산할 만큼 큰 트래픽은 없지만, 학습 목적을 위해 추가했습니다. Cloudwatch, S3와 연동하여 로그 수집을 하고 있습니다.
  • Cloudformation: Cloudwatch 기능으로부터 AWS 경고 이벤트 알람 기능과 S3 로그 저장 및 다양한 기능을 코드Infra As Code로 관리하기 위해 사용했습니다.
  • Cloudwatch: 로그 수집, 실시간 보안 및 장애 이벤트에 대응하기 위해 사용했습니다.
  • S3: 웹앱의 프론트엔드 배포와 로그를 수집하여 저장하기 위해 사용했습니다.

현재 구성된 AWS의 간략한 유저 플로우와 기능들을 다이어그램으로 표현하면 다음과 같습니다.

시스템 다이어그램 System Diagram


배포 파이프라인 설계

클라우드 구성과 웹앱/DB 등 배포를 진행하면서 여러 작업자들이 영향도Effect가 있는 작업을 진행하면서, 간단한 프로젝트임에도 복잡도가 크게 상승하는 것이 느껴졌습니다.

이러한 문제 상황의 근본 원인은 Git과 같은 형상 관리 없이, AWS 웹 콘솔 대시보드에서 작업이 분산되고 트래킹 없기 때문이 아닐까 생각이 들었습니다.

이에 대한 해결책으로 Github Repo와 클라우드 구성을 코드로 연동하자고 제안하였습니다.
사실 저를 포함한 팀원 다수가 AWS에 대해 경험이 부족한 상태였고, 제가 그나마 기여할 수 있는 것이 Github ActionsCI/CD 파이프라인을 개발하는 것이라는 생각이 들어, 이 작업을 담당하게 되었습니다.

팀원들의 이해를 돕기 위해, 현재 프로젝트 레포와 AWS를 연동하기 위한 배포 파이프라인 설계도를 먼저 작성했습니다.

Github Project Repo 구성

aws-web-app
├── backend // 파이썬 백엔드 앱
├── cloudformation // cloudwatch 구성 yaml
├── db_schema // rds 스키마
├── frontend // s3에 배포될 프론트엔드 코드
│ ├── public
│ └── src
├── lambda // 파이썬 코드로 이루어진 람다 함수
└── scripts // aws ec2에서 실행되는 쉘 스크립트

Github Actions

AWS 설정을 코드로 관리하기 위한 Github Actions CI/CD 파이프라인의 순서도를 작성했습니다.

해당 배포 파이프라인은 팀원과 협업으로 이룰 수 있었습니다. 이 과정에서 코드 리뷰를 진행하였고, 팀원들 모두 학습할 수 있도록 협업하였습니다.

code-review.png

성과 Accomplishment

새롭게 배운 내용과 협업에서 느낀 점이 많았습니다. 간단히 정리하자면 다음과 같습니다:

  • AWS 배포 파이프라인 설계 및 개발과 IaC의 필요성을 절감할 수 있었습니다.
    • 여러 작업자가 Session Manager, 웹 UI 대시보드, ssh 연결 등으로 작업하면서 변동사항의 트래킹이 어려운 점을 절감했습니다.
    • 설정 오류 등으로 장애 발생 시 원인을 파악하는 것이 무척 까다롭게 느껴졌기 때문에, Github과 연동을 신경썼습니다.
  • 문서화의 중요성을 느꼈습니다. 코드의 형상 관리 차원과 함께, 추상적이고 난이도가 높을 수 있는 클라우드 개발을 협업하는데 있어 문서와 아키텍처 설계도가 큰 도움이 되었습니다.

Vagrant로 VM Linux 실행하기

· 2 min read
te
Sofrware Engineer

VMware Fusion의 GUI로 매번 칼리 리눅스를 실행하는게 번거로워,
Vagrant를 통해 CLI로 칼리 리눅스를 실행해보고자 합니다.

Mac M3 Sequoia 최신 버전을 기준으로 작성했습니다.

Vagrant

Vagrant는 가상 머신(VM)을 생성하고 관리하는 하이퍼바이저Hypervisor를 사용하여 개발 환경을 자동화 및 관리해주는 도구입니다. 관련 글
VM 실행 환경을 Ruby 파일로 설정하고, vagrant ssh로 vm 환경과 터미널로 연결하여 사용할 수 있습니다. 사용 목적은 개인적으로 Kali Linux에서 거의 대부분 작업을 CLI로 하고 있어 번거롭게 느껴진 부분이 많았기 때문입니다.

Steps

1단계

사전 준비

VMware Fusion 설치: VMWare Fusion을 다운로드 받아 설치합니다.

  • Rosetta 설치 (Mac ARM 환경): M1/M2/M3 등 ARM 기반 Mac의 경우, Rosetta를 먼저 설치해야 합니다.
/usr/sbin/softwareupdate --install-rosetta --agree-to-license
  • Vagrant 설치: Homebrew를 사용하여 Vagrant를 설치합니다.
brew install vagrant
  • vagrant-vmware-utility: vmware fusion을 vagrant에서 실행하기 위해 필요합니다.
  • Vagrant-vmware-desktop 플러그인 설치: VagrantVMware를 연결하기 위한 플러그인을 설치합니다.
brew install --cask vagrant-vmware-utility
vagrant plugin install vagrant-vmware-desktop

2단계

Vagrant 설정 및 실행

VMware Fusion 실행: 처음 실행 시 시스템 설정에서 VMware를 허용해야 할 수 있습니다.

Vagrantfile 생성: Vagrantfile은 가상 머신의 설정 파일로, Ruby로 작성됩니다. 프로젝트 디렉토리에서 vagrant init 명령어로 생성합니다. 아래 명령어로 Kali Linux 전용의 Vagrantfile을 생성합니다.

vagrant init kalilinux/rolling
vagrantfile

Box 지정: Vagrantfile에서 사용할 운영체제 이미지를 지정합니다. 가상 머신 생성 및 실행: vagrant up 명령어를 실행하여 가상 머신을 생성하고 시작합니다. 이후 SSH 접속 vagrant ssh 명령어로 생성된 가상 머신에 접속할 수 있습니다

vagrantfile
vagrant up
vagrant ssh
vagrantfile

vagrant up으로 kalilinux/vagrant.box를 받는 것이 생각보다 오래 걸립니다. vagrant 실행이 완료되면, VM Fusion이 열립니다.

Kali Linux에 devilbox 설치 및 local DB 연결하기

· 4 min read
te
Sofrware Engineer

XAMPPHeidiSQL를 사용해야 하는 강의를 들었는데, VM 리눅스 환경과 호환이 좋지 않았습니다. 여러 차례 vm 재설치, 리눅스 재설치 등 삽질을 좀 했습니다. 실습 환경을 그대로 재현하는 건 빠르게 포기하고, debian-linux에서 강의에서 봤던 것과 유사한
AMP 웹 서버 환경 구성과 데이터베이스 관리 툴 dbeaver 을 사용하는 방법을 기록합니다.

❓LAMP Stack (Linux + Apache + MySQL + PHP)

LAMP 스택은 개발자가 웹 사이트와 웹 애플리케이션을 빌드하는 데 사용하는 4가지 소프트웨어 기술의 번들입니다. LAMP는 Linux(운영 체제), Apache(웹 서버), MySQL(데이터베이스 서버), PHP(프로그래밍 언어)의 두문자어입니다. 이 4가지 기술 모두 오픈 소스이므로 커뮤니티에서 유지 관리되며 누구나 무료로 사용할 수 있습니다. 개발자는 LAMP 스택을 사용하여 웹 콘텐츠를 생성, 호스팅 및 유지 관리합니다. LAMP 스택은 오늘날 일반적으로 사용하는 많은 웹 사이트를 지원하는 널리 사용되는 솔루션입니다.

https://aws.amazon.com/ko/what-is/lamp-stack/


Environment

VM : VMware Fusion OS : Kali Linux debian-12-arm

uname -a
Linux kali-blue 6.12.38+kali-arm64
#1 SMP Kali 6.12.38-1kali1 (2025-08-12) aarch64 GNU/Linux

1. install devilbox

xampp를 대체할 오픈 소스 프로젝트 devilbox 를 VM에 설치했습니다. 설치 방법은 레포 README에 잘 설명되어 있습니다.

https://github.com/cytopia/devilbox

# devilbox kali linux에 설치
git clone https://github.com/cytopia/devilbox
cd devilbox
cp env-example .env # 환경 변수는 공유하면 안됩니다

devilbox는 도커 컴포즈에서 실행됩니다.

칼리 리눅스에 dockerdocker-compose를 우선 설치해야 합니다.

sudo apt install docker.io

dockerdocker compose 를 모두 설치했다고 가정하고,
devilbox 를 실행합니다:

docker compose up httpd php mysql

file_pwOFWhod5vNEdNr3Xm

devilbox 를 사용한 이유는 :

  1. xampp 를 대체할 만한 오픈 소스를 찾고 있었고,

  2. devilboxLAMP 개발 환경을 만들어보고 싶었고,

  3. (칼리) 리눅스와 도커를 익히기에도 좋을 것 같았습니다.

  4. 격리된 컨테이너 단위로 취약점 테스트를 수행하는 것이 좋지 않을까 싶었습니다.

file_QUMzluLEUUfHr5ZrWqfile_JesE4pNLPtLSMa0hg7

패키지 설치 도중에 VM 디스크 공간이 부족해
시스템 부하가 걸린 순간이 몇번 있었는데, 용량을 늘려 gparted로 할당도 해보고
df -h , du -sh /* 로 용량도 확인하면서 리눅스 fs를 여러 면으로 탐색했습니다.


VM에서 메모리가 부족하여 docker compose up 을 했더니

도커 이미지 pulling과정에서 시스템이 다운되었습니다 😅

file_pYJ9vUtsCRr4CUKvfk로컬호스트에 설치된 devilbox를 확인할 수 있습니다.

다음으로 dbeaver 를 설치하도록 하겠습니다. snap 패키지 설치 이후 다음 명령어로 쉽게 다운받을 수 있습니다.

sudo snap install dbeaver-ce

.deb 인스톨러 설치 방법은 아래와 같습니다.

https://dbeaver.io/download/

.deb 파일이 다운됩니다. 이 파일에 적절한 권한 설정을 해준 뒤 루트 권한으로 설치파일을 apt 대신 dpkg로 실행합니다. 이 부분을 잘 몰라서 시간 소요가 조금 있었습니다.

sudo chmod +x ./dbeaver-{version}-installer.deb
dpkg -i ./dbeaver-{v}-installer.deb

dpkg

dpkgapt 차이가 궁금해서 검색한 내용을 정리합니다.

  • dpkg: .deb 파일을 직접 설치/삭제하는 저수준(low-level) 패키지 관리 도구

    • .deb 파일을 설치 및 삭제하는 기본 도구
    • 로컬에 있는 .deb 파일만 설치 가능
    • 의존성 문제 자동으로 해결하지 못함
  • apt: dpkg의 기능을 활용하며 의존성 문제를 자동으로 해결하고 원격 저장소에서 패키지를 다운로드하는 고수준(high-level) 도구

    • dpkg를 기반으로 작동하는 고수준 도구
    • 원격 저장소에서 패키지를 자동으로 다운로드 및 설치 가능
    • 의존성 문제 자동으로 해결함
  • 일반적으로 더 편리한 apt를 사용하고, dpkg는 특정 상황에서 사용

npm vs yarn 같은 패키지 매니저 비교로 이해하니 한결 수월합니다. 개인적으로 apt , dpkg 명령어를 잘 모르고 사용하면서 의존성 문제가 많이 생겼던 것 같습니다.


다운로드 완료 이후, 명령어dbeaver 를 입력하면, 브라우저로 DBeaver 웹 UI가 실행됩니다.

file_VPl2o4CDq4pNqsNh40xamppp 의 데이터베이스 조회/조작과 거의 동일한 기능을 제공합니다.

이제 상단의 메뉴바에서 Database > Connect를 실행하여 로컬 MySQL과 연결합니다.

file_GX1v0xTsQdPR0azREofile_KDHlpTEFzloM0WzXzK

file_s4hm3mFvwRMnRmrRfwfile_kCKfk5fLBlRPMWxqf5

사실 devilbox 에도 myAdminPHP 웹 UI를 제공합니다. 여기에서 데이터베이스를 조회/조작할 수 있습니다.

file_zva15F9cg8goHJThSI

Apple silicon 맥북에 VM으로 Windows OS 설치하기

· 3 min read
te
Sofrware Engineer

file_f6ZO0497NcTFYzukm1

file_QFTapskg5XV6I29XmO

Macbook M3를 기준으로 작성했습니다.

맥북에 윈도우를 실행하기 위해, LLM을 사용하며 질의응답한 내용을 문서로 정리하여 공유드립니다.

1. Windows ARM ISO 얻기

하단의 링크에서 윈도우 iso 파일을 준비합니다. Microsoft Windows OS ARM64

2. UTM 설치

https://mac.getutm.app/

  1. UTM 공식 사이트(또는 Mac App Store/공식 릴리스)에서 UTM 앱 다운로드 → 애플리케이션 폴더로 드래그.
  2. UTM 실행(보안 경고 나오면 시스템 환경설정 → 보안 및 개인 정보 → 허용).

3. 새 VM 만들기 — 권장 설정 (Step-by-step)

  1. UTM 열고 + Create a New Virtual Machine 클릭.
  2. Virtualize 선택 (에뮬레이션 대신 가상화; Apple Hypervisor 사용).
    • 이유: 성능 향상. M3에서는 Virtualize → ARM64 타입으로 진행해야 함.
  3. Operating System: Windows 선택.
  4. Boot ISO: 앞서 받은 Windows 11 ARM64 ISO 파일을 지정(Attach).
  5. System / CPU & Memory
    • CPU: 4 vCPU 이상 권장 (M3이면 4~8 할당 가능).
    • Memory: 8 GB 권장(가능하면 16GB).
  6. Drives / Storage
    • New Drive → Disk type: qcow2 또는 raw (qcow2는 스냅샷·공간 효율에서 유리).
    • Size: 최소 64 GB 권장 (개발/툴 설치 고려).
    • 부팅 순서(Boot Order): **CD/DVD(ISO)**가 하드 디스크보다 먼저 오도록 설정(설치 미디어로 부팅해야 하므로).
  7. Display
    • Display device: VirtIO GPU (또는 SPICE 관련 드라이버 옵션) 선택.
    • Enable SPICE/Display 기능(UTM UI에 따라 Display 추가).
    • 이 항목을 빠뜨리면 “Display output is not active” 같은 메시지가 뜰 수 있음 — 반드시 추가.
  8. Network
    • NIC: virtio-net-pci (Shared Network / NAT) 선택 — 인터넷 연결 위해.
  9. Sound / USB: 필요하면 추가(선택).
  10. Advanced: QEMU arguments나 기타를 건들 필요는 없음(고급 사용자용).

저장 후 VM 생성 완료.


4. VM 시작 및 Windows 설치

  1. 생성한 VM 선택 → ▶ Start.
  2. 부팅 시 Windows 설치 화면이 뜨면 평소대로 파티션 선택 → Windows 설치 진행.
    • 설치 중 드라이버 오류가 나면 UTM에서 virtio 드라이버/guest tools를 마운트해서 설치해야 함(아래 참고).
  3. 설치가 끝나고 재부팅되면 Windows ARM 환경으로 진입.

5. 필수 게스트 도구(성능/통합 향상)

설치 직후 아래 항목을 설치하면 그래픽, 네트워크, 커서/클립보드 공유 등이 정상 동작한다.

  1. SPICE Guest Tools (Windows용)
    • SPICE 툴은 클립보드 공유, 개선된 그래픽/커서, 드래그 앤 드롭 등을 도와줌.
    • UTM에서는 보통 Spice Guest Tools 또는 SPICE 패키지를 mounting 옵션으로 제공하거나, 외부에서 설치 파일을 얻어 VM 내부에서 실행.
  2. QEMU Guest Agent / VirtIO 드라이버
    • 네트워크(virtio-net), 블록 드라이버(virtio-blk), GPU(virtio-gpu) 등 드라이버가 빠지면 네트워크 안 되거나 성능 저하 발생.
    • UTM에서 제공하는 virtio ISO를 VM에 마운트한 다음 Windows에서 드라이버 설치(장치관리자 → 드라이버 업데이트 → ISO 경로 지정)하여 적용.

네트워크(virtio-net), 블록 드라이버(virtio-blk), GPU(virtio-gpu) 등 드라이버가 빠지면 네트워크 안 되거나 성능 저하 발생.

설치 방법: UTM VM 설정 → Drives → New Drive → Import 또는 Attach에서 SPICE/virtio ISO 선택 → Windows 내부 탐색기에서 실행(.exe) / 장치관리자에서 수동 설치.

6. 권장 리소스/설정 (성능·안정성)

  • CPU: min 4 vCPU, 권장 6~8(여유 메모리 대비)
  • Memory: 8~16 GB
  • Disk: 64GB 이상, 가능하면 qcow2
  • Network: Shared (NAT)으로 설정 후 내부 Windows에서 인터넷 작동 여부 확인
  • 스냅샷: 중요한 변경 전 스냅샷(또는 VM 파일 백업) 권장

7. 라이선스 & Windows 업데이트

  • Insider Preview는 제한된 기간 동안 무료로 사용 가능하지만, 정식 라이선스 정책은 MS 정책 따름.
  • Windows Update 통해 최신 드라이버·보안 업데이트 적용.