스테이징 환경을 분리하며 판단한 것들
무엇을 나누고 무엇을 나누지 않았는가
개발기 환경은 대체로 불안정하다
개발기는 개발자들이 실험적으로 사용하는 서버이다. 하루에도 여러 번 배포되고, 버그가 포함된 코드가 올라가기도 하고, 올라간 뒤에 문제가 발견되면 롤백이 되기도 한다. 이런 작업들은 개발 환경이 고장 난 상태가 아니라, 개발 환경이 제 역할을 하고 있는 상태라는 의미다. 문제는 그 환경에 개발자만 접근하지 않을 때 생긴다.
필자가 다니던 회사는 병원 운영에 들어가는 제품을 만들었고, 환경은 로컬 개발(개발자의 노트북) → 개발기(사내 서버) → 운영기(각 병원) 구조였다. 겉으로 보면 부족할 게 없어 보인다. 로컬에서 만들고, 개발기에서 확인하고, 운영기로 나간다. 흔한 구성이다.
그런데 이 구성에는 하나의 문제가 있었다. 로컬과 운영기 사이에 있는 환경이 개발기 하나뿐이었다는 점. 그 하나에 다양한 목적으로 개발기를 이용하는 사람들이 생기면서 목적들이 충돌하기 시작했다.
개발기에 대한 기존의 세 가지 목적
사내 개발기를 쓰는 주체는 개발자, QA담당자, 시연 담당자 셋이었다.
개발자
- 개발자는 본인이 개발한 사항을 자주 배포하기를 원했다. 만들다 만 것을 올리기도 하고, 동작이 안 되면 되돌리고, 다시 올렸다.
- 원래 개발자들에게 개발기는 빌드가 깨져도 되는 곳이다.
QA 담당자
- QA담당자는 기능 개발이 완료된 후 QA 진행했다. 실제 사용자 시나리오에 맞춰 처음부터 끝까지 기능을 이용해본다.
- 이 경우에는 시나리오 중간에 배포가 일어나 화면이 바뀌거나, 롤백이 일어나 방금까지 되던 게 안 되면 그 테스트는 무효가 된다.
- 이 사람에게 개발기는 최소한 검증하는 동안에는 아무 변화가 일어나면 안 되는 곳이었다.
시연 담당자
- 회사에선 대상 병원에 제품을 소개하기 위한 외부 시연이 있었다.
- 시연 또한 안정적인 서버 환경에서 해야 하니 그동안 개발 배포를 멈춰야 했다.
각기 다른 목적으로 개발기를 사용하는 사람들이 생겼지만, 이 목적들은 서로 충돌할 수밖에 없었다. 개발자가 원하는 상태와 QA가 원하는 상태가 반대이고, 시연이 원하는 상태는 그보다 더 엄격했다. 한 환경이 동시에 만족시킬 수 없는 요구를 받고 있다 보니 업무 프로세스에 병목이 발생했다.
특히 시연 때 배포를 멈춰야 했던 것이 이걸 가장 잘 보여준다. 개발기의 주사용자는 개발자인데, 시연이 잡히면 그 우선순위가 뒤집혔다. 이는 본질적으로 충돌했던 목적을 분리할 필요가 있음을 방증했다.
그래서 필자는 개발기와 별개인 서버 환경인 ‘스테이징’ 환경 분리를 수행하였다.
스테이징 환경의 목적
스테이징 환경을 분리하는 목적은 두 가지였다.
- QA 담당자가 QA를 수행하기 좋은 환경을 만드는 것
- 외부 시연과 개발 진행 사이의 의존성을 끊는 것
개발기는 개발자의 것으로 확정했고, 스테이징은 QA와 시연의 것으로 정했다.
스테이징 구축을 위한 두 개의 목적도 충돌 가능성은 분명 있었다. QA용과 시연용은 원리적으로는 충돌한다. 시연을 준비하는 동안 스테이징을 고정해두면 그 기간에는 QA를 못 할 수 있다. 그러면 원래 개발기에서 겪던 문제가 스테이징으로 옮겨간 것 아닌가 하는 의문이 남는다.
그러나 실제로는 문제가 되지 않았다. 왜냐하면,
- QA와 시연을 같은 사람이 담당했다. 기획자가 QA와 외부 시연을 함께 맡고 있었기 때문에 두 작업은 애초에 동시에 일어날 수 없었다.
- 두 용도가 환경에 요구하는 성질이 같았다. 앞에서 쓴 대로 QA 환경과 시연 환경은 고정되어 있는 환경을 원했다. 성질이 같은 두 용도라면 굳이 환경을 나눌 이유가 없었다.
게다가 환경을 늘리는 비용 자체도 적지 않았다. 스테이징 하나를 분리하는 것도 큰 작업이었기 때문에, 더 이상 쪼개지 않는 편이 ROI가 높다고 판단했다.
새로 정립한 배포 흐름
스테이징 환경을 구축하면서 배포 프로세스도 다시 정의했다.
렌더링 중...
- 개발기는
develop브랜치를 배포했고, 스테이징과 운영기는 둘 다main브랜치를 배포하되 환경변수 세트를 다르게 하여 배포했다. 스테이징에는 사내용 환경변수와 별도 서비스 DB가 붙었고, 운영기는 병원별 환경변수가 붙었다.
이전에는 develop 브랜치에서 직접 운영기로 배포했기 때문에 main 브랜치가 방치되고 있었는데, 이 또한 목적에 따라 사용을 하게 되었다. - 운영 배포는 주기가 정해져 있었고, 주기마다 배포 담당 개발자를 정했다. 담당자가 그 주기 동안 개발된 내용을 확인하고, 운영기 배포 며칠 전에 스테이징에 배포한다. 스테이징 배포 후 QA 담당자에게 알리면 담당자가 QA를 진행했다.
QA 이후 이상이 없으면 예정된 일정에 운영기로 나가고, 문제가 발견되면 원인을 진단해서 추가 대응을 하거나 롤백하거나 배포 일자를 미룬다. 이런 결정은 담당 개발자 혼자 내리는 게 아니어서, 팀 안에 합의된 룰이 있었다.
이 흐름을 정리하고 나서야 스테이징이 실제로 무엇이었는지가 분명해졌다. 며칠 동안 고정해둘 수 있는 환경이었기 때문이다. 원칙적으로 개발기에선 불가했던 QA를 보다 안정적으로 할 수 있었다.
또한, QA와 시연이 왜 한 환경에 들어갈 수 있었는지도 설명된다. 두 용도는 서로 다른 일이지만, 환경에 요구하는 성질은 같았다. 둘 다 정해진 기간 동안 변하지 않는 환경을 원했다.
다만 이 방식은 운영 배포 주기가 짧지 않았기 때문에 가능했던 방식이다. 스테이징 환경을 며칠 동안 그대로 둬도 개발 쪽이 감당할 수 있는 주기였다는 뜻이다. 배포가 더 잦은 조직이라면 같은 구조를 그대로 가져가기는 어려울 것이다.
스테이징으로 분리할 때 고려했던 인프라 요소
환경을 분리한다는 것은 인프라도 그만큼 동일한 구조로 만들어야 한다는 것이다. 다만 여기에서 실제로 인프라를 나눌 수 있던 것과 아닌 것이 존재했고 이를 고민할 수밖에 없었다.
첫 번째 고민 포인트는 쿠버네티스 클러스터 분리 문제였다. 매니지드 K8S를 이용하고 있었기 때문에 스테이징을 구축한다는 건 동일한 클러스터를 하나 더 띄워야 한다는 의미였다. 당연히 비용 문제까지 고려해야 했다.
다만 비용이 늘어나는 건 분명했지만, 시연 때문에 개발 배포를 멈추는 시간이 사라지는 것과 QA가 안정적으로 돌아가는 것을 감안하면 그만한 값어치가 있다고 판단했다.
두 번째 고민 포인트는 데이터 분리 문제였다. 이 부분은 쿠버네티스보다 분리 결정하기 어려웠다. 우리 제품에서 다루는 데이터는 성격이 둘로 나뉘었다.
- 서비스 DB: 애플리케이션에 직접 붙어 있는 데이터
- ETL로 적재된 데이터: 제품에서 가장 중요한 데이터 표준이자, 서비스 안에서 이를 이용하여 추출해 써야 하는, 일종의 소스 데이터
서비스 DB는 환경별로 분리할 수 있어서 문제가 아니었다. 문제는 후자였다. ETL 결과 데이터는 복제본을 하나 더 두는 게 부담스러운 규모였다. (사내 개발기 데이터임에도 TB 규모) 이 또한 매니지드 데이터베이스를 쓰고 있었기 때문에 그 규모가 그대로 비용으로 이어졌다.
결국 이러한 문제로 ETL 데이터는 분리하지 않고 개발기와 같은 것을 쓰기로 했다. 적어도 DB가 완전하게 분리되지 않았기 때문에 DB 단에서 커넥션 풀 등의 문제가 생길 수 있음을 예상했으나, 실제로 그로 인한 문제를 인지한 적은 없었다.
마치며
데이터를 완전히 분리하지 못한 건 아쉬운 점이지만, 비용을 보고 선택한 타협에 가깝다. 대신 이 상황을 겪으며 필자에게 남는 건 ‘전체를 분리하느냐 vs 일부라도 분리하느냐, 그에 따라 어떤 기준으로 어떤 판단을 해야 하는가’ 였다.
인프라와 서비스 DB는 분리해도 소스 데이터는 분리하지 않은 것처럼 환경 분리는 전부 하거나 아예 안 하거나의 문제가 아니라 각각 레이어로 나눠 따로 결정되는 일이었다. 환경을 나눠야 한다면 나눌 수 있는 것부터 나누고, 나누지 못한 부분은 무엇을 감수하는지 알고 안고 가는 편이 낫다.
결론적으론 이 작업의 결과로, 오랜 숙원의 숙제였던 사용 목적들의 의존성은 해소됐다. QA는 개발 배포에 흔들리지 않게 됐고, 외부 시연 때문에 개발을 멈출 일도 없어졌다. 이렇듯 여러 목적이 충돌하는 이런 상황에서는 기준을 정해 환경을 분리하는 것을 고려해야 한다는 것을 체감했던 작업이었다.