1. 먼저 무엇을 이전하는지 구분하기
Codex Cloud로 이동하는 것은 WSL2 Ubuntu의 디스크 전체를 업로드하는 작업과 다르다. GitHub의 소스·프로젝트 설정을 바탕으로 새 클라우드 실행 환경을 재구성하는 과정이다.
이번에 사용한 구성은 다음과 같다.
| 구분 | 실제 구성 |
|---|---|
| 소스 관리 | GitHub Private 저장소 7개 |
| 클라우드 개발 | Codex Cloud 통합 환경 |
| 웹 빌드 | Node.js 24.21.0, npm 11.19.0 |
| Android JDK | Temurin 17 |
| Android SDK | Platform 36, Build Tools 36.0.0 |
| Android 빌드 | 프로젝트의 Gradle 설정 사용 |
| 웹 배포 | GitHub → Cloudflare Git 연동 |
| 자동 검증 | GitHub Actions의 PR 빌드 검증(별도 시험) |
기존 WSL 환경을 구축한 경험은 JDK·SDK·Node.js 요구사항을 이미 파악했다는 점에서 도움이 됐다. 하지만 처음부터 클라우드 개발 환경을 구성하는 것도 가능하다.
개발환경을 분리하기로 한 계기는 실제 WSL2 메모리 부족 장애였다. 이 글은 그때 확인한 구성 절차와 검증 범위에 집중한다.
2. WSL2 OOM 증거 확인하기
WSL이 갑자기 중단됐다고 무조건 메모리 부족이라고 판단해서는 안 된다. 로그를 확인한다.
현재 메모리·Swap 상태를 점검한다.
free -h
top
커널 로그에서 메모리 부족 및 종료 기록을 찾는다.
sudo dmesg -T | grep -Ei 'out of memory|oom|killed process'
이전 부팅의 journal이 보존돼 있다면 다음 명령도 사용할 수 있다.
journalctl -k -b -1 --no-pager | grep -Ei 'out of memory|oom|killed process'
WSL 설정에 따라 이전 부팅 로그가 없을 수 있다. 결과가 비어 있어도 OOM이 없었다는 증거는 아니다.
이번 사례에서는 oom-killer, Out of memory, Swap 0kB, Chrome OOM 종료, 이어진 프로세스 강제 종료 기록을 확인했다. 메모리 부족은 확인됐지만 WSL의 최종 재시작 주체까지는 확정되지 않았다.
우선 불필요한 서버·브라우저·빌드 프로세스를 중복 실행하고 있지 않은지 확인한다. 환경을 클라우드로 옮겨도 과도한 병렬 실행 문제를 그대로 가져가서는 안 된다.
3. GitHub에 남겨 둘 개발 환경 정보
코드만 복제해서는 동일한 빌드를 보장할 수 없다. 저장소에서 다음을 확인할 수 있어야 한다.
AGENTS.md, README의 프로젝트 규칙과 작업 범위- Node.js 버전 파일(예:
.nvmrc)과 패키지 잠금 파일 - Android의 Gradle Wrapper, JDK·SDK 요구사항
- 실제 빌드·테스트 명령 및 산출물 경로
- 추적 파일과 생성 파일의 구분,
.gitignore적용 여부
비밀번호, API Token, 실제 문자 내용, Android Release 서명키는 저장소나 초기 환경 스크립트에 넣지 않는다.
기본적인 WSL2 설치와 GitHub 연동 과정을 먼저 살펴보고 싶다면 WSL2·GitHub·Cloudflare 개발 환경 구축 가이드를 참고하면 된다. 이 글은 그 다음 단계인 별도의 클라우드 실행 환경 구성에 집중한다.
4. Codex Cloud에서 여러 저장소 선택
Codex Cloud 환경 생성 화면에서 GitHub 저장소를 연결했다.
실제 선택한 저장소는 BLOG, HOME, INVEST, TOOL, CART, FLOW, ONSEMO Connect로 총 7개다. Connect의 GitHub 저장소 식별자는 onsemo/sms-forwarder지만, 이 글에서는 실제 제품명을 Connect로 표기한다.
여러 저장소를 하나의 환경에 연결해도 Git 저장소가 합쳐지는 것은 아니다. 각 작업은 대상 저장소를 명시하고, 해당 저장소의 AGENTS.md를 먼저 확인하도록 한다.
설정 단계에서의 작업 범위는 읽기·설치·빌드·로컬 검증으로 제한했다. Git 추적 파일 변경, Commit, Push, Cloudflare 직접 배포는 허용하지 않았다.
인터넷 연결은 필요한 패키지 관리자 중심으로 제한했다. Node.js 배포 호스트 nodejs.org 접근은 실제 HTTP 200 응답을 확인했고, 그 환경에서 추가 도메인 허용은 필요하지 않았다.
다른 환경에서는 도메인별 허용 정책이 다를 수 있다. 다운로드가 실패하면 비밀키를 새로 만들기보다 프록시·네트워크·인증 문제부터 구분한다.
5. Node.js와 BLOG 빌드 검증
BLOG 저장소의 .nvmrc에 맞춰 Node.js 24.21.0을 사용했다.
node --version
npm --version
다운로드할 때는 공식 배포 파일의 SHA-256과 제공된 체크섬을 대조하도록 설정했다. Connect 웹/PWA 등 npm 기반 프로젝트는 기존 잠금 파일을 기준으로 필요한 의존성을 준비했다.
BLOG에는 실제로 npm run build 명령이 있다.
npm run build
일부 프로젝트에서는 빌드 과정이 Git 추적 HTML·인덱스·사이트맵을 다시 쓸 수 있다. 따라서 이번 초기 검증은 원본 저장소가 아닌 임시 복사본에서 실행했다.
빌드 산출물 검증에는 다음 명령을 사용할 수 있다.
test -s public/index.html
test -s public/ko/index.html
test -s public/ko/knowledge/index.html
test -s public/content-index.json
이 파일 경로는 ONSEMO BLOG의 산출물 예시다. 다른 프로젝트라면 실제 빌드 구조를 확인해야 한다.
6. Connect Android 개발 도구 구성
Connect는 웹/PWA·Cloudflare Worker와 Android 앱이 함께 있는 프로젝트다. 클라우드에서 Android 테스트를 수행하려면 추가 개발 도구가 필요하다.
| 도구 | 적용한 버전·방법 |
|---|---|
| JDK | Temurin 17 |
| Android 명령줄 도구 | 공식 배포 도구 |
| SDK Platform | API 36 |
| Build Tools | 36.0.0 |
| Gradle | 기존 프로젝트 설정 및 캐시 활용 |
설치 스크립트에는 파일 무결성 검증을 넣었다. JDK 다운로드 파일은 체크섬 파일과 비교하고, Android 명령줄 도구는 공식 저장소 메타데이터의 SHA-1 값과 다운로드 파일을 대조했다. 사용자가 직접 다른 버전으로 바꾼다면 공식 자료와 프로젝트 요구사항을 다시 확인해야 한다.
Android 검증은 프로젝트의 기존 테스트·Debug 빌드 절차를 사용했다. 새 프로젝트에서 명령 이름을 무조건 복사하지 말고 기존 Gradle 설정부터 확인해야 한다.
클라우드에서 성공했다고 확인한 범위는 Android 컴파일, 단위 테스트, Debug APK 빌드다.
다음 항목은 확인하지 않았다.
- 실제 Galaxy에서 SMS 수신 및 권한 동작
- 실제 단말 간 메시지 전달
- Web Push 알림의 실제 단말 수신
- 기존 Release 서명 APK의 생성·업데이트 호환성
Debug APK는 개발용 검증 산출물이다. 사용자에게 배포하는 Connect 설치 파일을 별도 Debug APK로 대체하지 않는다. 기존 Release 서명키도 클라우드 환경에 넣지 않았다.
7. 설치 스크립트와 시작 지침 분리
초기 자동 구성에서는 여러 저장소의 서버를 모두 시작하는 도구가 준비됐다. 하지만 일상적인 개발 작업에서 모든 서버를 항상 실행할 이유는 없다.
환경 지침을 수정해 현재 작업에 필요한 프로젝트만 실행하도록 했다. 7개 전체 실행용 start.py는 기본 사용에서 제외했다.
설치 스크립트와 시작 지침의 역할도 나눴다.
| 단계 | 역할 |
|---|---|
| 설치 스크립트 | JDK·SDK·Node.js·의존성 준비 |
| 시작 지침 | 어떤 저장소를 확인하고 어떤 서버만 실행할지 결정 |
| 빌드 검증 | 개별 프로젝트에서 명시적으로 실행 |
| GitHub Actions | PR의 빌드·테스트를 자동 실행하도록 별도 구성 |
설치 스크립트가 wrangler deploy 같은 직접 배포 명령을 실행하지 않는지 확인했다. 외부 배포·비밀정보 출력 로직은 검토한 보조 파일 5개에서 발견되지 않았다는 결과를 받았다.
서버를 적게 실행한다고 무조건 좋은 것은 아니다. 여러 서비스를 연동 테스트해야 한다면 그때 필요한 서비스들을 명시적으로 실행하면 된다.
8. Publish 전후의 실제 검증 결과
첫 환경 설정에서 보고받은 자동 테스트 수는 다음과 같았다.
| 프로젝트 | 자동 테스트 결과 |
|---|---|
| CART | 22개 통과 |
| Connect 웹/PWA | 42개 통과 |
| Connect Worker | 32개 통과 |
| Connect Android | 190개 통과 |
| Android Debug APK | 빌드 성공 |
총 286개 자동 테스트 통과라는 보고를 받았으며, 7개 저장소의 빌드·로컬 HTTP 응답도 확인됐다고 보고됐다.
이후 설치 스크립트와 시작 지침을 검토하고 환경을 Publish했다.
기존 클라우드 환경에 연결된 후속 작업에서 BLOG 빌드를 다시 실행했을 때 Node.js 24.21.0, npm 11.19.0, 보조 파일과 캐시가 존재했다. 도구 재설치 없이 빌드가 성공했고 게시글 21개가 생성됐다.
보고된 실행 시간은 환경 준비 0.22초, 빌드 0.30초였다. 이는 기존 환경 내부에서 측정한 시간이지 새 클라우드 컴퓨터의 전체 부팅·복원 시간은 아니다.
완전히 새로운 인스턴스에서 설치 환경과 보조 파일이 재사용되는지는 아직 별도 검증하지 않았다. 이 결과를 생략한 채 복원까지 검증됐다고 표현해서는 안 된다.
9. Codex Cloud, GitHub Actions, Cloudflare의 역할
Codex Cloud는 코드 개발과 복잡한 문제 해결을 맡고, GitHub Actions는 지정된 빌드·테스트를 독립적으로 반복한다.
BLOG에서는 PR을 만들 때 npm run build와 주요 산출물을 확인하는 GitHub Actions 워크플로를 별도로 시험해 성공을 확인했다. 하지만 모든 프로젝트에 같은 자동 검증이 적용된 것은 아니다.
Cloudflare는 기존 Git 기반 배포 구조를 유지한다. 클라우드 개발 환경의 wrangler deploy로 운영 사이트를 직접 갱신하는 방식으로 바꾸지 않았다.
이번 접근의 핵심은 한 도구가 모든 일을 하는 구조를 피하는 것이다.
10. 다음 작업에서 확인할 항목
아래 순서로 재현성을 검증한다.
- 기존 채팅과 구분되는 새 Codex Cloud 인스턴스를 시작한다.
- 게시된 설정과 보조 스크립트가 존재하는지 확인한다.
- 필요한 프로젝트 하나에서 도구 버전과 의존성을 확인한다.
- 해당 프로젝트의 빌드와 최소 테스트를 실행한다.
git status --short로 의도하지 않은 추적 파일 변경이 없는지 확인한다.
새 인스턴스의 복원 검증을 하기 전에는 기존 환경에 접속한 뒤의 빠른 재빌드 결과를 전체 클라우드 설정 시간으로 소개하지 않는 것이 중요하다.
마무리
기존 WSL2 Ubuntu에서 개발해 본 경험은 클라우드 환경 구성을 빠르게 이해하는 데 도움이 됐다. 그러나 WSL 설치 자체가 Codex Cloud의 필수 선행 조건은 아니다.
웹/PWA 위주 프로젝트라면 클라우드에서 시작해도 된다. 실제 Android 기기 테스트와 기존 Release 서명이 필요한 프로젝트에서는 로컬 환경을 함께 유지하는 편이 현실적이다.
무엇보다 중요한 것은 하나의 컴퓨터가 멈추더라도 설정과 검증 절차를 기반으로 개발을 이어갈 수 있도록 만드는 것이다.
이 클라우드 이전을 계기로 WSL2와 GitHub Actions까지 역할을 분리한 후속 운영 구조는 다음 Story: 개발환경 이중화와 실제 비용에서 확인할 수 있다.