Skip to main content
Summary

배포는 코드를 서버에 올리는 일이 아니다

배포는 작성한 코드를 실제 사용자가 쓰는 환경으로 안전하게 전달하는 과정이다. 단순히 파일을 복사하거나 서버를 재시작하는 일이 아니다. 새 코드가 기존 데이터와 맞는지, 설정값이 올바른지, 외부 API 연결이 살아 있는지, 문제가 생겼을 때 되돌릴 수 있는지까지 포함한다.

로컬에서 잘 동작하던 기능이 운영 환경에서 실패하는 이유는 대부분 코드 자체만의 문제가 아니다. 운영 서버에는 다른 운영체제, 다른 환경 변수, 다른 데이터 규모, 다른 네트워크 규칙, 다른 권한이 있다. 개발자는 이제 "내 컴퓨터에서는 됐다"에서 멈출 수 없다. 코드가 실행될 환경까지 함께 이해해야 한다.

DevOps는 개발자와 운영자가 같은 사람이 되어야 한다는 뜻이 아니다. 개발, 테스트, 배포, 운영의 경계를 줄이고 자동화와 관측을 통해 더 자주, 더 안전하게 변경하자는 사고방식이다. 좋은 DevOps 문화에서는 배포가 특별한 이벤트가 아니라 반복 가능한 일상 작업이 된다.

배포, 클라우드, DevOps 실무 감각AI 생성 이미지

환경은 분리하고 설정은 코드와 분리한다

대부분의 서비스는 최소한 세 가지 환경을 가진다.

  • 개발 환경: 개발자가 기능을 만들고 빠르게 실험하는 환경

  • 스테이징 환경: 운영과 비슷한 조건에서 배포 전 검증하는 환경

  • 운영 환경: 실제 사용자가 접속하는 환경

환경을 나누는 이유는 위험을 분리하기 위해서다. 개발 중인 코드가 실제 사용자 데이터에 영향을 주면 안 된다. 반대로 운영에서만 발생하는 문제를 로컬 환경만 보고 판단해서도 안 된다. 스테이징은 운영과 완전히 같을 수는 없지만, 데이터베이스 종류, 외부 서비스 연결 방식, 인증 설정, 캐시 사용 여부처럼 중요한 조건은 최대한 비슷하게 맞추는 것이 좋다.

설정값은 코드와 분리해야 한다. 데이터베이스 주소, API 키, 토큰, 로그 레벨, 기능 플래그 같은 값은 환경마다 다르다. 이런 값을 코드에 직접 적으면 배포할 때마다 코드를 수정해야 하고, 비밀값이 Git 저장소에 남을 위험도 있다.

일반적으로는 환경 변수를 사용한다. 예를 들어 서버는 DATABASE_URL, REDIS_HOST, LOG_LEVEL, PAYMENT_API_KEY 같은 값을 실행 시점에 읽는다. 코드는 "어떤 설정이 필요한지"만 알고, 실제 값은 배포 환경이 제공한다.

중요한 원칙은 다음과 같다.

  • 비밀번호, 토큰, 인증서 같은 시크릿은 코드와 저장소에 넣지 않는다.

  • 운영과 개발의 설정값을 명확히 분리한다.

  • 기본값이 위험한 동작을 만들지 않게 한다. 예를 들어 설정이 없을 때 운영 데이터베이스에 연결되면 안 된다.

  • 설정 변경도 배포와 마찬가지로 기록되고 검토되어야 한다.

설정은 사소해 보이지만 장애의 흔한 원인이다. 잘못된 데이터베이스 주소, 만료된 인증서, 누락된 환경 변수 하나가 전체 서비스를 멈출 수 있다.

CI/CD는 배포를 반복 가능한 절차로 만든다

CI는 Continuous Integration, 지속적 통합이다. 개발자가 코드를 자주 합치고, 그때마다 자동으로 검사하는 방식이다. CD는 Continuous Delivery 또는 Continuous Deployment로 쓰인다. 전자는 언제든 배포 가능한 상태를 유지하는 데 초점을 두고, 후자는 조건을 통과한 변경을 자동으로 운영까지 배포하는 데 더 가깝다.

CI/CD 파이프라인은 보통 다음 흐름을 가진다.

  1. 코드가 저장소에 push되거나 Pull Request가 생성된다.

  2. 의존성을 설치한다.

  3. 린트, 타입 검사, 단위 테스트, 통합 테스트를 실행한다.

  4. 애플리케이션을 빌드한다.

  5. Docker 이미지나 배포 패키지를 만든다.

  6. 스테이징 환경에 배포하고 추가 검증을 수행한다.

  7. 승인 또는 자동 조건에 따라 운영 환경에 배포한다.

  8. 문제가 생기면 이전 버전으로 롤백한다.

자동화의 목적은 사람을 배제하는 것이 아니다. 사람이 반복 작업에서 실수하지 않도록 돕는 것이다. 매번 터미널에서 수동으로 명령을 입력해 배포하면 누락과 순서 오류가 생기기 쉽다. 반면 파이프라인으로 정의된 배포는 같은 입력에 대해 같은 절차를 실행한다.

좋은 파이프라인은 빠르면서도 필요한 검사를 놓치지 않는다. 모든 테스트를 매번 오래 실행하면 개발 속도가 떨어진다. 반대로 너무 적은 검사만 통과시키면 배포 위험이 커진다. 그래서 PR 단계에서는 빠른 테스트를 실행하고, 운영 배포 전에는 통합 테스트나 스모크 테스트를 추가하는 식으로 균형을 잡는다.

여기서 스모크 테스트는 배포 후 서비스의 핵심 기능이 최소한 살아 있는지 확인하는 짧은 검사다. 예를 들어 /health API가 성공하는지, 로그인 페이지가 열리는지, 주요 API가 200 응답을 반환하는지 확인한다.

컨테이너는 실행 환경 차이를 줄인다

컨테이너는 애플리케이션과 실행에 필요한 파일, 라이브러리, 런타임 설정을 하나의 단위로 묶어 실행하는 기술이다. Docker는 컨테이너를 만들고 실행하는 대표적인 도구다.

컨테이너가 필요한 이유는 환경 차이를 줄이기 위해서다. 어떤 서버에는 Node.js 20이 설치되어 있고, 다른 서버에는 Node.js 18이 설치되어 있을 수 있다. Python 패키지 버전이나 시스템 라이브러리 차이도 문제를 만든다. 컨테이너 이미지를 사용하면 "이 애플리케이션은 어떤 환경에서 실행되어야 하는가"를 이미지 안에 명확히 담을 수 있다.

이미지는 실행 가능한 템플릿이고, 컨테이너는 그 이미지를 실제로 실행한 인스턴스다. 클래스와 객체의 관계를 떠올리면 이해하기 쉽다. 하나의 이미지로 여러 컨테이너를 만들 수 있다.

좋은 Docker 이미지에는 몇 가지 원칙이 있다.

  • 필요한 파일만 포함한다. 테스트 파일, 로컬 캐시, 임시 파일을 무심코 넣지 않는다.

  • 이미지 크기를 줄인다. 크기가 작을수록 빌드, 전송, 배포가 빨라진다.

  • 의존성 버전을 명확히 고정한다. 매번 다른 패키지가 설치되면 재현성이 떨어진다.

  • 빌드 단계와 실행 단계를 분리한다. 빌드 도구는 최종 실행 이미지에 필요 없을 수 있다.

  • 컨테이너 안에 영구 데이터를 저장하지 않는다. 컨테이너는 언제든 교체될 수 있다고 생각해야 한다.

컨테이너는 만능이 아니다. 잘못된 설정, 비효율적인 애플리케이션 구조, 부족한 모니터링을 자동으로 해결해 주지는 않는다. 다만 실행 환경을 표준화해 배포와 확장을 더 예측 가능하게 만든다.

클라우드는 자원 대여가 아니라 운영 책임의 선택이다

클라우드를 사용하면 서버, 디스크, 네트워크, 데이터베이스 같은 자원을 필요할 때 빌려 쓸 수 있다. 하지만 핵심은 단순한 대여가 아니다. 어떤 책임을 직접 지고, 어떤 책임을 클라우드 서비스에 맡길지 선택하는 것이다.

가장 기본은 컴퓨팅 서비스다. 가상 머신은 익숙하고 자유도가 높다. 직접 운영체제를 설정하고 웹 서버, 런타임, 배포 스크립트를 구성할 수 있다. 대신 보안 패치, 용량 관리, 장애 대응 책임도 크다. 컨테이너 실행 서비스나 서버리스 환경은 운영 부담을 줄일 수 있지만, 플랫폼의 제약과 비용 구조를 이해해야 한다.

스토리지는 파일, 이미지, 백업, 로그 같은 데이터를 저장하는 데 쓰인다. 애플리케이션 서버의 로컬 디스크에 사용자 업로드 파일을 저장하면 서버를 교체할 때 데이터가 사라질 수 있다. 그래서 보통 객체 스토리지 같은 외부 저장소를 사용한다. 객체 스토리지는 대량 파일 저장에 적합하고, 접근 권한과 수명 주기 정책을 함께 설계해야 한다.

네트워크 서비스는 사용자의 요청이 애플리케이션까지 안전하게 도달하도록 돕는다. 로드 밸런서는 여러 서버로 요청을 나누고, 방화벽 규칙은 허용된 트래픽만 통과시킨다. CDN은 정적 파일을 사용자와 가까운 위치에서 제공해 지연 시간을 줄인다.

관리형 데이터베이스는 데이터베이스 설치, 백업, 복제, 패치, 장애 조치의 일부를 클라우드가 대신 처리한다. 직접 운영하는 것보다 편하지만 비용이 더 높을 수 있고, 세부 튜닝이나 버전 선택에 제약이 있을 수 있다. 중요한 것은 "관리형이면 신경 쓰지 않아도 된다"가 아니다. 스키마 설계, 인덱스, 느린 쿼리, 백업 복구 검증은 여전히 개발팀의 책임이다.

클라우드 비용은 사용한 만큼 늘어난다. 서버를 켜 둔 시간, 저장한 데이터 양, 네트워크 전송량, 로그 보관 기간, 데이터베이스 인스턴스 크기가 모두 비용이 된다. 따라서 클라우드 설계에는 성능뿐 아니라 비용 관측도 포함되어야 한다.

무중단 배포는 실패를 전제로 설계한다

운영 서비스에서는 배포 중에도 사용자가 접속한다. 그래서 배포 전략은 "문제가 없을 것이다"가 아니라 "문제가 생기면 어떻게 영향을 줄이고 되돌릴 것인가"에서 출발해야 한다.

가장 기본은 롤링 배포다. 여러 서버 중 일부를 새 버전으로 교체하고, 정상 동작을 확인하며 나머지를 순차적으로 바꾼다. 전체를 한 번에 내리지 않아도 되지만, 잠시 동안 구버전과 신버전이 함께 동작한다. 이때 API 응답 형식이나 데이터베이스 스키마 변경이 서로 호환되어야 한다.

Blue-Green 배포는 두 개의 환경을 준비하는 방식이다. Blue가 현재 운영 중인 환경이고, Green이 새 버전이 배포된 환경이라고 하자. Green에서 검증을 마친 뒤 트래픽을 Green으로 전환한다. 문제가 생기면 다시 Blue로 돌릴 수 있다. 롤백이 빠르다는 장점이 있지만, 두 환경을 유지하는 비용이 든다.

Canary 배포는 새 버전을 일부 사용자나 일부 트래픽에만 먼저 노출한다. 예를 들어 전체 요청의 5%만 새 버전으로 보내고 오류율, 응답 시간, 주요 비즈니스 지표를 본다. 이상이 없으면 25%, 50%, 100%로 점차 확대한다. 위험을 작게 시작할 수 있지만, 지표와 라우팅 제어가 준비되어 있어야 한다.

무중단 배포에서 헬스 체크는 필수다. 헬스 체크는 서버가 요청을 받을 준비가 되었는지 확인하는 신호다. 단순히 프로세스가 살아 있는지만 보는 것은 부족할 수 있다. 애플리케이션이 시작되었는지, 필수 설정이 로드되었는지, 데이터베이스 연결이 가능한지 등을 상황에 맞게 확인해야 한다.

다만 헬스 체크가 너무 무거워도 문제다. 매초 데이터베이스에 복잡한 쿼리를 날리면 헬스 체크 자체가 부하가 된다. 보통은 가벼운 생존 확인과 주요 의존성 확인을 구분해 설계한다.

롤백 전략도 미리 정해야 한다. 코드만 이전 버전으로 되돌리면 되는 경우는 비교적 쉽다. 어려운 것은 데이터베이스 마이그레이션이 포함된 배포다. 새 코드가 새 컬럼을 쓰기 시작한 뒤 이전 코드로 되돌리면 오류가 날 수 있다. 그래서 안전한 배포에서는 스키마 변경을 여러 단계로 나눈다. 먼저 새 컬럼을 추가하고, 코드가 양쪽을 모두 처리하게 만든 뒤, 충분히 확인한 다음 오래된 컬럼을 제거한다.

운영 감각은 작은 체크리스트에서 시작된다

배포와 운영은 거창한 인프라 지식만으로 이루어지지 않는다. 실무에서는 작은 습관이 장애를 줄인다.

배포 전에는 무엇이 바뀌는지 확인한다. 코드 변경, 설정 변경, 데이터베이스 변경, 외부 API 변경을 구분한다. 실패했을 때 사용자에게 어떤 영향이 있는지도 예상한다. 배포 중에는 로그, 오류율, 응답 시간, 주요 기능 동작을 본다. 배포 후에는 문제가 없는지 일정 시간 관찰한다.

다음 질문에 답할 수 있으면 기본적인 운영 감각이 생긴 것이다.

  • 이 서비스는 어떤 환경 변수 없이는 실행될 수 없는가?

  • 새 버전이 배포되었는지 어떻게 확인하는가?

  • 배포 후 오류율이 증가하면 어디를 먼저 보는가?

  • 현재 버전을 이전 버전으로 되돌리는 방법은 무엇인가?

  • 데이터베이스 변경은 이전 코드와 호환되는가?

  • 서버가 죽었을 때 자동으로 다시 시작되는가?

  • 사용자가 올린 파일은 서버 교체 후에도 남아 있는가?

  • 비용이 갑자기 증가하면 어떤 지표를 확인할 것인가?

개발자는 모든 인프라를 직접 운영할 필요는 없다. 그러나 자신이 만든 코드가 어떤 환경 변수에 의존하는지, 어떤 포트에서 실행되는지, 어떤 데이터베이스와 연결되는지, 어떻게 배포되고 어떻게 되돌릴 수 있는지는 알아야 한다.

배포, 클라우드, DevOps의 핵심은 도구 이름을 많이 아는 것이 아니다. 변경을 작게 만들고, 자동화하고, 관측하고, 실패했을 때 빠르게 되돌릴 수 있게 만드는 것이다. 코드는 저장소에 있을 때보다 운영 환경에서 더 많은 현실을 만난다. 그 현실을 이해하는 개발자가 더 안정적인 서비스를 만든다.

책 목록

개발자에게 필요한 필수 지식 정리

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기