바이브코딩으로 앱 10개 만들면, 서버도 10개 필요할까?
AI 덕분에 앱은 쉽게 만들지만, 서비스가 늘어날수록 서버 운영은 복잡해집니다. 맥 미니, Docker, k3s, 쿠버네티스로 공통 운영 환경을 구성하면서 고민한 문제와 기술 선택의 이유, 얻은 점과 아직 해결하지 못한 과제를 초보자 눈높이에서 정리했습니다.
바이브코딩으로 앱은 쉽게 만들었는데, 운영은 왜 점점 어려워질까?
맥 미니, Docker, k3s, 쿠버네티스까지. 여러 서비스를 운영하면서 서버 구조를 다시 고민한 이야기
요즘 바이브코딩을 하면서 가장 크게 달라진 건 앱을 만드는 속도입니다.
예전에는 아이디어 하나를 실제 서비스로 만드는 데 많은 시간과 인력이 필요했습니다. 지금은 Claude Code나 Codex 같은 AI에게 요구사항을 설명하고, 코드를 만들고, 테스트까지 진행할 수 있습니다.
저도 그렇게 여러 앱과 서비스를 만들고 운영하고 있습니다.
그런데 서비스가 하나둘 늘어나면서 예상하지 못했던 문제가 생겼습니다.
앱 하나를 만들면 서버가 필요합니다. 데이터베이스도 연결해야 하고, 도메인과 보안 설정도 해야 합니다. 새로운 기능을 배포하다가 문제가 생기면 복구해야 하고, 업데이트와 백업도 신경 써야 합니다.
앱이 하나일 때는 괜찮습니다. 그런데 5개, 10개로 늘어나면 같은 일을 계속 반복하게 됩니다.
장애 · 백업
이대로라면 AI가 코딩하는 시간보다 제가 서버를 관리하는 시간이 더 많아질 수도 있겠다는 생각이 들었습니다.
그래서 최근 운영 환경을 다시 구성하기 시작했습니다.
앞으로 어떤 앱을 만들든, 서버 구성부터 다시 고민하지 않고 공통된 환경에서 안전하게 운영할 수 있도록 만들자.
이번 글은 그 과정에서 왜 Docker와 k3s 같은 기술을 선택했는지, 어떤 문제를 해결하려 했는지, 아직 무엇이 부족한지에 대한 이야기입니다.
1. 앱마다 서버가 필요한 걸까?
먼저 앱을 실행하는 환경부터 생각해 봤습니다.
앱 A는 특정 버전의 프로그램이 필요하고, 앱 B는 다른 버전이 필요할 수 있습니다. 같은 서버에 프로그램을 직접 설치하다 보면 서로 충돌할 수도 있습니다.
예를 들어 한 앱 때문에 프로그램 버전을 올렸는데 다른 앱이 작동하지 않는 상황입니다.
이런 문제를 줄이기 위해 사용하는 기술이 Docker(도커)입니다.
Docker는 앱마다 독립된 작업 공간을 만들어 줍니다
여러 사람이 하나의 주방을 함께 사용한다고 생각해 보겠습니다.
모두 같은 조리대에서 요리하면 재료나 도구가 섞일 수 있습니다. 그런데 각자 필요한 도구와 재료를 별도의 작업 공간에 두면 서로 간섭할 일이 줄어듭니다.
Docker의 컨테이너도 비슷합니다.
컨테이너 A에서 사용하는 프로그램 버전을 변경해도 컨테이너 B에 설치된 라이브러리가 함께 변경되지는 않습니다.
그 이유는 컨테이너마다 파일 시스템과 프로세스 등의 실행 환경을 구분하기 때문입니다. 리눅스에서는 네임스페이스 같은 기능이 이런 격리에 사용됩니다.
하지만 여기서 오해하면 안 되는 부분이 있습니다.
컨테이너가 독립적이라는 것은 서버 자원을 완전히 따로 사용한다는 뜻이 아닙니다.
CPU와 메모리는 여전히 같은 서버의 자원을 나눠 씁니다.
그래서 컨테이너별로 메모리와 CPU 사용량에 제한을 두는 것이 중요합니다. 리눅스의 cgroups 같은 기능이 자원 사용을 관리하는 데 활용됩니다.
물론 이런 격리는 가상머신처럼 완전히 별도의 운영체제를 실행하는 방식과는 다릅니다. 컨테이너는 호스트의 커널을 공유하므로 모든 장애나 보안 문제에서 완전히 독립적인 것은 아닙니다.
2. 그런데 서버 자체가 고장 나면?
Docker로 여러 앱을 정리해 놓으니 다음 문제가 보였습니다.
서버 한 대에서 앱 10개가 잘 돌아간다고 가정해 보겠습니다.
그런데 그 서버가 갑자기 고장 나면 어떻게 될까요?
컨테이너를 아무리 잘 분리해 놓아도 같은 서버에서 실행하던 앱들은 영향을 받습니다.
Docker는 앱의 실행 환경을 분리하는 데 유용하지만, 서버 자체의 고장까지 해결해 주지는 않습니다.
저도 서비스를 운영하면서 장애와 복구 문제를 겪었습니다. 백업을 해두는 것과 서비스가 계속 살아 있도록 만드는 것은 다른 문제였습니다.
그래서 여러 서버가 서로 역할을 나눠서 앱을 운영하는 방법을 고민했습니다.
쿠버네티스는 여러 서버를 관리하는 관리자입니다
식당 하나에 직원이 여러 명 있다고 생각해 보겠습니다.
한 직원이 일을 못 하게 되면 다른 직원에게 업무를 배분할 수 있습니다. 다만 누가 어떤 일을 하고 있고, 다른 직원에게 여유가 있는지 파악하는 관리자가 필요합니다.
쿠버네티스(Kubernetes)가 하는 일이 이와 비슷합니다.
여러 서버의 상태를 확인하고, 어떤 서버에서 앱을 실행할지 결정하고, 실행 중인 앱에 문제가 생기면 다시 실행하도록 관리합니다.
저는 그중 비교적 가볍게 구성할 수 있는 k3s를 선택했습니다.
k3s는 쿠버네티스와 완전히 다른 기술이 아닙니다. 쿠버네티스를 작은 규모의 환경에서도 비교적 간편하게 운영할 수 있도록 만든 배포판입니다.
쿠버네티스에서는 이런 서버를 노드(Node)라고 부릅니다.
앱은 보통 파드(Pod)라는 단위로 실행됩니다. 파드에는 하나 이상의 컨테이너가 들어갈 수 있습니다.
이렇게 여러 서버를 하나의 운영 환경으로 관리하면 앱이 늘어나도 배포 방식을 통일하기가 쉬워집니다.
서버가 죽어도 정말 자동 복구될까?
여기서 한 가지 주의할 점이 있습니다.
쿠버네티스를 설치했다고 자동으로 무중단 서비스가 되는 건 아닙니다.
예를 들어 앱을 하나만 실행하고 있었다면 그 앱이 실행되던 서버가 고장 났을 때 다른 서버에서 새로 실행되기까지 시간이 필요합니다.
그 사이에는 서비스가 중단될 수 있습니다.
여기서 또 하나의 문제가 있습니다.
앱은 다른 서버에서 실행할 수 있어도 데이터베이스나 파일이 고장 난 서버에만 있다면 정상적으로 작동하지 못할 수 있습니다.
결국 쿠버네티스는 무중단을 위한 도구이지, 무중단을 보장하는 마법 같은 기술은 아닙니다.
3. 왜 맥 미니와 AMD 서버를 함께 사용할까?
이번에는 서로 다른 종류의 컴퓨터도 함께 활용하고 있습니다.
맥 미니에 들어가는 Apple Silicon은 ARM 계열이고, 일반적인 AMD 서버는 x86 계열입니다.
초보자라면 이렇게 생각하면 됩니다.
둘 다 컴퓨터지만 사용하는 프로세서의 구조가 다릅니다. 그래서 어떤 프로그램은 양쪽에서 모두 실행되고, 어떤 프로그램은 한쪽 환경에 맞게 만들어야 합니다.
예를 들어 스마트폰 앱이 윈도우 PC에서 그대로 실행되지 않는 것처럼, 서버 프로그램도 실행 환경에 맞는 버전이 필요할 수 있습니다.
그렇다고 모든 앱을 같은 종류의 서버에서 실행할 필요는 없습니다.
서버가 여러 종류라는 건 관리가 복잡해질 수 있다는 뜻이기도 합니다.
하지만 앱을 실행할 때 필요한 CPU 구조와 자원 사용량을 명확하게 구분하면 장비를 더 효율적으로 활용할 수 있습니다.
제가 중요하게 생각한 건 최고 사양의 서버를 구매하는 것이 아니었습니다.
이미 가진 장비를 최대한 활용하고, 꼭 필요한 곳에만 추가 비용을 쓰는 구조를 만드는 것이었습니다.
4. AI가 만든 코드를 바로 운영 서버에 올려도 될까?
바이브코딩을 하다 보면 AI에게 기능을 수정해 달라고 요청하는 일이 많습니다.
AI가 수정했다고 해서 기존 기능까지 모두 정상이라는 보장은 없습니다.
버튼 하나를 수정했는데 다른 페이지에서 오류가 발생할 수도 있고, 데이터베이스 구조를 변경하면서 기존 데이터에 영향을 줄 수도 있습니다.
그런데 실제 사용자가 있는 서비스에 이런 변경 사항을 바로 반영하면 어떻게 될까요?
사용자가 장애를 먼저 발견하는 상황이 생길 수도 있습니다.
그래서 이번에는 앱을 기본적으로 세 단계로 나누는 방향을 잡았습니다.
AI 코드 수정
자유로운 실험
오류 확인
배포 전 점검
검증된 버전
안정성 우선
개발 환경은 새로운 기능을 만들고 수정하는 곳입니다.
테스트 환경은 실제 운영에 반영하기 전에 기능이 제대로 동작하는지 확인하는 곳입니다.
운영 환경은 사용자가 실제로 접속하는 서비스입니다.
이렇게 구분하면 개발 중인 코드가 곧바로 운영 서비스에 영향을 주는 위험을 줄일 수 있습니다.
물론 세 환경을 만들었다고 모든 오류를 막을 수는 없습니다. 테스트가 부실하면 여전히 문제가 생깁니다.
중요한 건 앱을 만들 때마다 이 과정을 처음부터 새로 구성하지 않는 것입니다.
5. 앱이 늘어나도 반복 작업은 줄이고 싶다
앱을 운영하다 보면 비슷한 일을 계속 반복하게 됩니다.
새로운 코드를 배포하고, 업데이트를 적용하고, 환경변수를 설정하고, 정상 작동 여부를 확인해야 합니다.
앱 하나라면 직접 처리해도 괜찮습니다.
그런데 앱이 10개라면 같은 작업을 10번 반복할 수도 있습니다.
그래서 배포와 설정 관리도 가능한 한 공통화하려고 했습니다.
여기서 등장하는 기술이 CI/CD와 GitOps입니다.
CI/CD는 코드를 변경했을 때 테스트하고 배포하는 과정을 자동화하는 방식입니다.
GitOps는 Git에 기록된 설정을 기준으로 실제 운영 환경을 맞춰 가는 방식입니다.
쉽게 말해 사람이 서버에 접속해서 매번 같은 명령어를 입력하는 대신, 정해진 절차에 따라 변경 사항을 적용하는 겁니다.
다만 자동화도 무조건 많이 한다고 좋은 것은 아닙니다.
여러 프로젝트의 라이브러리 업데이트를 중앙에서 관리하면 편리하지만, 변경 요청이 너무 많이 쌓이는 문제가 생길 수 있습니다.
AI로 검토한다면 토큰 비용도 무시할 수 없습니다.
잘못된 설정을 자동화하면 잘못된 작업도 빠르게 반복됩니다.
그래서 자동화의 목적은 모든 판단을 AI에게 맡기는 것이 아니라, 사람이 반복할 필요가 없는 작업을 줄이는 데 있다고 생각합니다.
6. 가장 어려운 건 앱이 아니라 데이터였다
여러 서버에 앱을 배포하고, 장애가 발생하면 다른 서버에서 실행하게 만드는 구조를 생각하다 보니 또 다른 문제가 보였습니다.
바로 데이터베이스입니다.
웹사이트 프로그램은 다른 서버에서 다시 실행할 수 있습니다.
하지만 사용자의 회원정보, 게시글, 주문 내역 같은 데이터는 어떻게 해야 할까요?
데이터베이스가 특정 서버에만 저장돼 있다면 그 서버가 고장 났을 때 다른 서버에서 앱을 실행하더라도 필요한 데이터를 읽지 못할 수 있습니다.
이 문제는 단순히 데이터베이스 프로그램을 두 개 실행한다고 해결되지 않습니다.
어느 데이터베이스가 쓰기 작업을 처리할지, 변경된 데이터를 다른 서버에 어떻게 전달할지, 장애가 발생하면 어떤 서버가 이어받을지 결정해야 합니다.
잘못 구성하면 서비스 중단보다 더 심각한 데이터 손실이나 불일치가 발생할 수도 있습니다.
파일 저장소도 마찬가지입니다.
사용자가 올린 이미지나 첨부파일이 특정 서버에만 있다면 앱이 다른 서버에서 실행될 때 파일을 읽지 못할 수 있습니다.
그래서 여러 서버가 접근할 수 있는 저장소나 별도의 객체 스토리지 같은 방식도 고려하게 됩니다.
백업은 또 다른 문제입니다.
데이터가 여러 서버에 복제돼 있어도 실수로 삭제한 데이터가 모든 서버에 함께 반영될 수 있습니다.
따라서 복제와 백업은 목적이 다릅니다.
이 부분은 이번 구성에서도 계속 검증하고 개선해야 할 과제입니다.
7. 그래서 무엇이 좋아졌을까?
이번 작업의 목표는 서버를 몇 대 연결하는 것이 아니었습니다.
앞으로 새로운 서비스를 만들 때마다 반복하던 고민을 줄이는 것이었습니다.
예전에는 앱을 만들고 나면 어디에 배포할지, 어떤 서버를 사용할지, 데이터베이스는 어떻게 연결할지, 장애가 발생하면 어떻게 복구할지를 개별적으로 고민해야 했습니다.
이제는 이런 문제를 공통된 운영 구조 안에서 해결하는 방향으로 바꾸고 있습니다.
얻으려는 효과는 크게 세 가지입니다.
- 배포 방식의 표준화: 앱이 늘어나도 같은 방식으로 운영 환경을 구성합니다.
- 자원의 효율적인 활용: 여러 앱이 서버 자원을 공유하되 사용량을 관리합니다.
- 반복 작업의 감소: 업데이트와 배포, 장애 대응 절차를 가능한 한 자동화합니다.
하지만 아직 모든 서비스의 이전과 검증이 끝난 것은 아닙니다.
실제로 운영 시간이 얼마나 줄었는지, 장애 대응이 얼마나 개선됐는지, 비용을 얼마나 절감했는지는 충분한 운영 데이터가 쌓인 뒤 판단해야 합니다.
구조를 만들었다는 것과 그 구조가 실제로 더 효율적이라는 것은 다른 이야기니까요.
8. 초보 바이브코더도 쿠버네티스를 배워야 할까?
제 생각은 아직은 아닙니다.
처음 앱을 만드는 사람에게 쿠버네티스부터 공부하라고 권하고 싶지는 않습니다.
앱 하나를 만들고 처음 배포하는 단계라면 훨씬 간단한 방법도 많습니다.
관리형 호스팅 서비스를 사용하면 서버를 직접 운영하지 않고도 서비스를 공개할 수 있습니다.
Docker도 처음부터 반드시 알아야 하는 건 아닙니다.
중요한 건 지금 해결해야 하는 문제가 무엇인지 아는 것입니다.
앱 하나를 운영하는 사람과 여러 서비스를 직접 운영하는 사람에게 필요한 기술은 다릅니다.
사용자가 거의 없는 개인 프로젝트와 실제 사용자가 지속적으로 이용하는 서비스의 운영 기준도 다를 수밖에 없습니다.
저 역시 처음부터 지금 같은 구조를 만들려고 했던 건 아닙니다.
여러 서비스를 만들고 운영하면서 반복되는 문제가 생겼고, 그 문제를 해결하기 위해 하나씩 기술을 도입하게 됐습니다.
기술을 먼저 정하고 거기에 서비스를 맞추는 것보다, 해결해야 할 문제에 맞춰 기술을 선택하는 편이 낫다고 생각합니다.
9. 결국 바꾸고 싶었던 건 서버가 아니라 일하는 방식이었다
바이브코딩 덕분에 앱을 만드는 데 필요한 시간과 비용이 크게 줄었습니다.
혼자서도 여러 서비스를 만들고 실험할 수 있는 환경이 됐습니다.
하지만 앱을 만드는 속도가 빨라졌다고 운영까지 쉬워지는 건 아닙니다.
앱이 늘어날수록 업데이트, 보안, 장애, 데이터 관리처럼 사람이 책임져야 하는 일도 늘어납니다.
저는 이 부분이 앞으로 바이브코딩을 하는 사람들에게 점점 더 중요한 문제가 될 거라고 생각합니다.
AI가 앱을 빠르게 만들어 주는데, 정작 사람은 만들어 놓은 앱을 관리하느라 새로운 아이디어를 시도하지 못한다면 아쉬운 일입니다.
그래서 이번에는 새로운 기능을 만드는 대신, 앞으로 만들 서비스들이 공통으로 사용할 운영 기반을 정비하는 데 시간을 쓰고 있습니다.
물론 이런 구성이 모든 사람에게 필요한 건 아닙니다.
오히려 처음에는 단순하게 시작하고, 실제 문제가 생겼을 때 필요한 기술을 도입하는 편이 좋습니다.
저도 이번에 구성한 환경이 얼마나 효과적인지는 앞으로 운영하면서 계속 확인하고 개선해야 합니다.
앞으로는 이번 구성에서 사용한 기술들을 하나씩 자세히 다뤄보려고 합니다.
Docker는 왜 필요한지, Docker만으로 충분한데 왜 k3s까지 도입했는지, ARM과 AMD 서버를 어떻게 함께 사용하는지, 데이터베이스를 무중단으로 운영하는 게 왜 어려운지 등입니다.
설치 명령어를 나열하기보다는 제가 왜 그 기술을 선택했고, 실제로 어떤 문제를 해결하려 했는지 중심으로 정리해 보겠습니다.
저처럼 바이브코딩으로 서비스를 하나둘 만들다 보면 언젠가 비슷한 고민을 하게 될 수도 있으니까요.