Skip to main content

바이브코딩 백엔드, Go?



사이드 프로젝트를 만들 때는 주로 Firebase, Supabase 같은 서비스를 사용했습니다. 인증, DB, 파일 저장 등의 기능을 직접 구현하지 않아도 되기 때문에 프론트엔드 개발자 입장에서 빠르게 서비스를 만들기 좋았습니다.

하지만 여러 프로젝트를 진행해보면서 처음에는 크게 느끼지 못했던 단점들이 보이기 시작했습니다. 원하는 방식으로 데이터를 조회하거나 서비스 로직을 관리할 때 불편한 부분이 있었고, 프로젝트를 추가할 때마다 비용이 늘어나다 보니 새로운 아이디어가 있어도 선뜻 프로젝트를 시작하기 어려웠습니다.

그래서 앞으로는 백엔드를 직접 구현해보려고 합니다. AI의 도움을 받아 빠르게 학습하고 기능을 적용해보면서, 학습과 개발에 드는 시간과 공수도 줄일 수 있을 것 같습니다.

현재 운영하는 서비스들은 대부분 트래픽이 거의 없는 상태입니다. 이를 고려해 우선 한 서버에서 모든 서비스를 함께 운영하고, 트래픽이 늘어나거나 자원이 부족해지는 시점에 필요한 서비스부터 분리하기로 했습니다.

결론부터 말하면, 새롭게 시작하는 사이드 프로젝트에서는 백엔드에 Go를 사용해보려고 합니다. 이번 글에서는 서버와 언어를 선택한 이유, 그리고 앞으로의 구성 방향을 정리해보았습니다.


백엔드를 직접 구성하려는 이유​

Firebase, Supabase를 사용하면 서버를 직접 관리할 일이 줄어듭니다. 작은 서비스를 빠르게 만들거나, 프론트엔드 작업에 집중하고 싶을 때는 여전히 편한 선택입니다. 다만 서비스를 계속 만들다 보니 데이터 구조와 조회 방식, 비용에서 아쉬운 부분이 있었습니다.

Firebase에서 사용한 Cloud Firestore는 문서와 컬렉션으로 데이터를 저장하는 NoSQL 데이터베이스입니다. 관계형 DB처럼 테이블을 조인해서 조회하는 방식과는 달라서, 서로 연관된 데이터를 다루거나 조회 조건이 복잡해질 때 데이터 구조와 조회 방식을 별도로 고민해야 했습니다.

Firestore의 커서 기반 페이지네이션도 아쉬웠습니다. 10페이지로 바로 이동하려면 9페이지의 마지막 커서가 필요하고, 이를 저장해두지 않았다면 앞선 데이터부터 조회해야 합니다. 이전·다음 페이지 방식이나 무한 스크롤에는 적합하지만, 원하는 페이지로 바로 이동하기에는 비효율적이라고 느꼈습니다.

Supabase는 PostgreSQL 기반의 관계형 DB를 제공하고, SQL로 데이터를 조회할 수 있다는 점이 좋았습니다. 다만 여러 프로젝트를 운영하려다 보니 프로젝트별로 추가되는 비용이 부담이었습니다. 유료 플랜을 사용하더라도 프로젝트를 하나 추가할 때마다 별도의 고정비가 늘어납니다. 트래픽이 거의 없는 프로젝트도 마찬가지라, 새로운 아이디어를 가볍게 시도하기에는 부담이 있었습니다.

비용을 줄이기 위해 Supabase 프로젝트 하나에서 스키마나 테이블을 나눠 여러 서비스를 운영하는 사례도 있었습니다. 다만 프로젝트 공통 인증 설정을 바꾸면 여러 서비스에 함께 영향을 줄 수 있고, Auth를 공유하는 만큼 서비스별 권한 검사를 잘못 구성하면 한 서비스의 로그인으로 다른 서비스의 데이터까지 접근할 수 있어 주의가 필요했습니다. 나중에 서비스를 별도 프로젝트로 옮길 때도 해당 서비스의 데이터뿐 아니라 공유하던 Auth 사용자와 인증 설정까지 분리해 이전해야 한다는 점을 고려해야 했습니다.

서버는 AWS Lightsail 사용하기​

백엔드 언어를 정하는 것보다 운영 비용이 더 중요해서, 먼저 여러 서비스를 운영할 서버를 정했습니다.

처음에는 남는 맥북을 집에서 서버로 사용해 비용을 아끼려 했지만, 네트워크 장애에 직접 대응하며 가용성을 챙겨야 하는 부담과 현재 사용하는 LG 비대칭 회선의 낮은 업로드 속도 때문에 제외했습니다.

직접 운영하는 대신, 서울 리전이 있는 VPS를 비교한 끝에 AWS Lightsail을 선택했습니다. 가장 큰 이유는 퍼블릭 IPv4, CPU, 메모리, SSD, 일정량의 데이터 전송량을 묶은 정액제 플랜으로 비용을 예상하기 쉽다는 점이었습니다. 이후 필요에 따라 EC2, RDS, 로드 밸런서 등 AWS 생태계 안에서 이전하거나 확장할 수 있다는 점도 고려했습니다.

DB도 초기에는 RDS를 사용하는 대신 같은 서버에서 PostgreSQL을 직접 운영해 비용을 줄이려고 합니다. 대신 백업과 복구는 직접 챙겨야 합니다. 서버 안에만 백업을 보관하면 인스턴스 삭제나 데이터 손상으로 원본과 함께 잃을 수 있어, 주기적으로 백업을 만들고 별도 클라우드 저장소에도 보관할 계획입니다. 실제로 백업과 복구가 잘 되는지 확인해보고 진행할 예정입니다.

백엔드 언어로 Go 선택하기​

서버를 정한 다음에는 작은 서버에서 여러 서비스와 DB를 함께 실행할 수 있는 백엔드 기술를 고민했습니다. 후보는 Spring Boot, NestJS, Rust, Go였습니다.

이번에는 트래픽이 거의 없는 프로젝트도 여러 개 실행해둘 예정이라, 요청을 처리할 때의 성능뿐만 아니라 각 애플리케이션이 상시 사용하는 메모리도 중요했습니다. 여기에 AI가 작성한 코드를 직접 읽고 검토하기 쉬운지, 배포 과정이 단순한지도 함께 고려해 Go를 선택했습니다.

후보선택할 때 고민한 부분
Spring Boot생태계와 레퍼런스가 풍부하고, 취업에도 가장 유리하다고 생각했습니다. 다만 프로젝트마다 실행되는 JVM의 메모리가 부담이었습니다. 네이티브 이미지로 줄일 수 있지만 빌드 설정과 라이브러리 호환성을 고려해야 하고, 여러 서비스를 운영하기에는 여전히 메모리가 부담될 것으로 예상했습니다.
NestJSTypeScript 기반이라 프론트엔드 개발자인 저에게는 가장 친숙한 선택지였습니다. 메모리 부담이 적은 편이지만, 서버 한 대에 좀 더 많은 서비스를 올리고 싶어 더 가벼운 Go를 선택했습니다.
Rust성능과 메모리 효율은 매력적이지만, 소유권과 라이프타임 같은 개념을 익히는 데 시간이 꽤 걸릴 것 같았습니다. 여러 서비스를 빠르게 만들고 AI가 작성한 코드를 직접 이해하고 수정하려는 목적에는 Go가 더 적합하다고 생각했습니다.
Go · Gin정적 타입 컴파일 언어로, 문법이 비교적 단순하고 코드 포맷을 통일할 수 있어 AI가 작성한 코드를 읽고 검토하기 좋겠다고 생각했습니다. 메모리를 자동으로 관리하고 고루틴으로 여러 작업을 동시에 처리할 수 있으며, 단일 실행 파일로 배포할 수 있다는 점도 좋았습니다.

실제로 서버 한 대에 얼마나 많은 프로젝트를 올릴 수 있는지는 직접 운영해보면서 확인하고, 그에 맞춰 계획을 수정할 예정입니다.

파일 저장은 Cloudflare R2 사용하기​

같은 AWS 생태계의 S3도 고려했지만, 무료 제공량이 있고 외부 데이터 전송 요금이 없는 Cloudflare R2를 선택했습니다. 공개 파일은 커스텀 도메인을 연결해 Cloudflare CDN으로 캐시해 제공할 계획입니다.

서버에서 파일까지 저장하고 제공하는 것보다 서버의 저장 공간과 전송 부담을 줄일 수 있고, 나중에 서버를 옮길 때도 파일을 함께 이전할 필요가 적어 이 방식이 더 적합하다고 생각했습니다. 구체적인 구성은 실제로 적용해보면서 달라질 수 있을 것 같습니다.

일단 해보기​

아직 트래픽이 거의 없는 단계에서 프로젝트마다 인프라를 따로 구성하기보다는, 작은 비용으로 새로운 아이디어를 계속 시도할 수 있는 환경을 먼저 만들고 싶었습니다. AI 덕분에 백엔드 학습과 구현의 부담이 줄어든 만큼, 이번에는 직접 만들고 운영하는 경험까지 해보려고 합니다.

서버를 직접 운영하면 보안 업데이트, 백업, 장애 대응을 직접 챙겨야 하고, 한 서버의 문제가 여러 서비스에 영향을 줄 수도 있습니다. 하지만 아직 트래픽이 거의 없는 여러 개인 서비스를 운영하려는 현재 상황에서는 이 구성이 가장 나은 선택지인 것 같아 보입니다.

이번 글은 직접 운영해보기 전에 자료를 찾아보며 정리한 내용이라, 실제와 다른 부분이 있을 수 있습니다. 메모리 사용량이나 한 서버에서 운영할 수 있는 서비스 수는 직접 시도해보며 확인하고, 운영해보면서 예상과 달랐던 부분은 추후 새 글로 정리해보겠습니다.