Story · 개발 경험

개발하던 Ubuntu가 멈췄다. 그래서 개발 환경을 클라우드로 옮기기로 했다

WSL2 메모리 부족에서 시작된 ONSEMO 개발 방식의 변화

WSL2 Ubuntu의 OOM 로그를 확인한 뒤 Codex Cloud에 ONSEMO의 7개 GitHub 저장소와 Android 개발 도구를 구성한 과정, 그리고 로컬 의존성을 줄이게 된 이유를 기록한다.

잘 사용하던 Ubuntu가 멈췄다

ONSEMO를 개발하면서 Windows PC의 WSL2 Ubuntu를 주 개발 환경으로 사용해 왔다. Ubuntu에서 Codex와 개발 도구를 실행하고, GitHub에 변경 이력을 남긴 뒤, Cloudflare의 Git 연동으로 웹서비스를 배포하는 방식이었다.

스마트폰에서 Codex Remote를 이용하면 PC 앞에 앉아 있지 않아도 개발을 계속할 수 있었다. 그래서 처음에는 이 구성으로 충분하다고 생각했다.

그러던 중 개발 작업 도중 WSL 환경이 중단됐다. 작업하던 Codex 연결이 끊겼고, 진행 중이던 작업을 다시 확인해야 했다.

로그를 살펴보니 oom-killer, Out of memory 기록이 있었다. Swap 여유 공간도 0이었다. 여러 브라우저·개발 도구 프로세스가 메모리를 사용하던 중 Chrome 프로세스가 OOM으로 종료됐고, 이후 다른 프로세스가 강제로 종료된 기록도 확인됐다.

이 로그는 당시 실제 메모리 부족이 발생했다는 증거였다. 다만 Windows가 WSL을 직접 재시작시켰는지, 별도의 조작이 있었는지까지 단정할 수는 없었다. 확인한 사실과 알 수 없는 부분을 구분해 기록하고 싶었다.

이후의 변화: 개발·빌드 환경까지 나누다

이 글은 ONSEMO 개발환경 변화의 두 번째 기록이다. 당시에는 OOM 원인을 확인하고 Codex Cloud에서 다시 개발할 수 있도록 환경을 구성하는 데 집중했다.

그 후에는 Codex Cloud를 주 개발환경으로, WSL2를 보조 개발·APK 빌드 환경으로 유지하고, GitHub Actions를 별도의 빌드·검증 경로로 추가했다. 실제로 어떤 구조가 되었는지와 운영비는 다음 Story: 노트북 한 대에서 시작한 개발, 클라우드 이중화까지에서 정리했다.

클라우드 환경의 준비 과정과 확인한 명령·도구는 관련 Knowledge: WSL2 OOM 이후 Codex Cloud 개발 환경 구성하기에서 따로 볼 수 있다.

아래는 이중화에 이르기 전, Ubuntu가 멈춘 당시부터 클라우드 이전을 결정하고 검증했던 과정이다.

Remote라고 해서 클라우드 개발은 아니었다

처음에 사용했던 Codex Remote는 개발을 원격으로 조작하는 데 유용했다. 하지만 실행되는 컴퓨터는 내 PC의 Ubuntu였다. WSL이나 PC가 멈추면 Remote도 그 개발 환경에 접근할 수 없었다.

스마트폰으로 내 컴퓨터를 조작하는 것과, 내 컴퓨터가 없어도 개발을 계속하는 것은 다른 문제였다.

이전에는 GitHub에 소스와 변경 이력을 보관하는 방법을 고민했다. 이제는 그 생각을 실제 개발환경의 독립성까지 확장할 차례였다.

GitHub에 코드가 있어도 실행 환경까지 있는 건 아니다

ONSEMO의 프로젝트는 이미 GitHub의 독립 저장소로 관리하고 있었다. BLOG, HOME, INVEST, TOOL, CART, FLOW, 그리고 ONSEMO Connect까지 총 7개 저장소였다.

GitHub 저장소를 복제하면 코드와 Git에 기록된 설정을 가져올 수 있다. 하지만 Node.js나 Android SDK가 저절로 설치되는 것은 아니다. 설치된 버전이 달라지면 같은 코드도 정상 빌드되지 않을 수 있다.

여기서 기존 WSL 개발 경험이 도움이 됐다. 프로젝트마다 AGENTS.md, 의존성 파일, 빌드 명령과 테스트 방법을 어느 정도 정리해 둔 상태였다. Android 앱인 Connect에는 웹/PWA·Cloudflare Worker 외에도 JDK와 Gradle, Android SDK가 필요하다는 사실을 이미 알고 있었다.

이번 이전은 WSL 파일 시스템을 통째로 복사한 작업이 아니었다. GitHub에 보관된 코드와 검증해 온 설정을 활용해 새로운 Linux 실행 환경을 구성한 것이었다.

일곱 저장소를 하나의 Codex Cloud 환경으로

처음에는 BLOG만 연결해 보려고 했다. 그러다 클라우드 환경 생성 화면에서 여러 저장소를 선택할 수 있다는 것을 확인했다.

개별 Git 저장소는 독립적으로 두고, 필요한 개발 도구를 준비하는 환경만 하나로 관리하면 어떨까? 그렇게 ONSEMO의 7개 저장소를 통합 환경에 연결했다.

Codex는 각 프로젝트의 설정을 확인해 Node.js와 Android 개발 도구를 준비했다. 자동 테스트와 로컬 HTTP 응답 검사도 실행했다.

처음 환경 구성 작업에서 보고된 결과는 다음과 같았다.

검증 대상보고된 결과
연결된 저장소7개
CART테스트 22개 통과
Connect 웹/PWA테스트 42개 통과
Connect Worker테스트 32개 통과
Connect Android테스트 190개 통과
Android Debug APK빌드 성공

총 286개의 자동 테스트가 통과했다는 보고였다. 내가 직접 단말에서 모든 기능을 확인했다는 의미는 아니며, 어디까지나 클라우드 개발 환경의 자동 검증 결과다.

실제 Galaxy SMS 송수신과 Web Push 전달은 검증하지 않았다. 기존 서명으로 업데이트할 Release APK도 이 과정에서 만들지 않았다.

그래도 WSL을 켜지 않고 Android 코드를 빌드하고 테스트할 수 있다는 점은 충분히 의미가 있었다.

모든 서버를 실행하는 것이 더 좋은 환경일까?

환경을 검토하면서 예상 밖으로 눈에 들어온 부분이 있었다. 처음 작성된 시작 지침에는 7개 서비스의 서버를 한꺼번에 실행하는 도구가 포함되어 있었다.

개발 도구가 많이 준비돼 있다는 사실과 그 도구를 늘 모두 실행해야 한다는 것은 다르다. BLOG 문장 하나를 고치려고 Android 프로젝트와 다른 웹서버를 모두 시작할 필요는 없었다.

특히 메모리 부족을 겪은 뒤였으므로 이 문제를 그냥 넘기고 싶지 않았다.

그래서 시작 지침을 수정했다.

현재 작업에 필요한 프로젝트만 실행한다.

전체 실행 도구는 필요할 때 사용할 수 있도록 남겼지만 기본 동작에서는 제외했다. 개발 환경을 옮기면서 단순히 설치에 성공하는 것뿐 아니라, 어떤 작업에 어떤 자원을 사용할지 다시 생각하게 됐다.

Publish를 눌렀다고 검증이 끝나는 건 아니다

설치 스크립트와 시작 지침을 검토한 다음 환경을 Publish했다. 보조 파일에서 직접 배포하거나 비밀정보를 출력하는 로직이 발견되지 않았다는 점도 확인했다.

이후 기존 클라우드 환경에 연결된 상태에서 BLOG 빌드를 다시 실행했다. Node.js와 npm, 기존 도구와 캐시를 재설치하지 않고 재사용했고, BLOG 게시글 21개를 생성하는 빌드가 성공했다.

하지만 이 결과만으로 완전히 새 인스턴스에서 환경이 자동 복원된다고 단정하지는 않았다. 기존 환경에 연결된 테스트였기 때문이다.

성공한 것과 아직 검증하지 못한 것을 구분해 두는 습관은 앞으로도 계속 유지하려고 한다.

클라우드 개발환경 구성 과정과 OOM 확인 방법은 위에서 소개한 별도의 Knowledge로 정리했다.

하나의 컴퓨터가 아니라, 이어갈 수 있는 개발 구조

그렇다고 WSL을 더 이상 사용하지 않으려는 것은 아니다.

실제 Galaxy에서 SMS를 테스트하거나 기존 서명키로 Android Release APK를 만드는 과정에는 로컬 환경이 필요할 수 있다. 반면 코드 수정과 자동 테스트는 클라우드에서도 수행할 수 있다.

당시에는 Codex Cloud를 개발 중심으로 삼고 GitHub Actions에서 독립적인 빌드를 검증하며 Cloudflare의 Git 기반 배포는 그대로 유지하는 방향을 생각했다. 이후의 실제 구성은 글 앞부분에서 연결한 다음 Story에 정리했다.

개발 환경이 멈춘 경험은 불편했지만 새로운 질문을 남겼다.

개발하던 컴퓨터가 멈춰도 다음 작업을 이어갈 수 있을까?

내가 원하는 것은 언제나 멈추지 않는 컴퓨터가 아니라, 문제가 생겨도 다시 시작할 수 있는 개발 구조다.