OIDC로 CI 시크릿 없애기: 클라우드 키리스 인증
CI 파이프라인이 클라우드에 배포하려면 인증이 필요하다. 가장 흔한 방식은 콘솔에서 장기 액세스 키를 발급받아 CI 시크릿 저장소에 넣어두는 것이다. 처음엔 간단하지만, 시간이 지나면 “누가 언제 …
CI 파이프라인이 클라우드에 배포하려면 인증이 필요하다. 가장 흔한 방식은 콘솔에서 장기 액세스 키를 발급받아 CI 시크릿 저장소에 넣어두는 것이다. 처음엔 간단하지만, 시간이 지나면 “누가 언제 …
쿠버네티스의 기본 Deployment 는 롤링 업데이트를 제공하지만, 실무에서 배포를 두려워하게 만드는 문제는 여기서 시작된다. 롤링 업데이트는 새 버전 파드를 순차 교체할 뿐 “새 버전이 정말 건…
배포 자동화를 도입하면 코드가 병합되는 순간부터 프로덕션까지 사람 손을 거치지 않고 흘러갑니다. 대부분의 변경에는 이것이 바람직하지만, 결제 로직이나 데이터 마이그레이션처럼 실수의 대가가 큰 배포에…
왜 실행 시간이 문제가 되는가 CI는 병합 속도의 상한을 결정한다. 파이프라인이 느리면 개발자는 컨텍스트를 잃고, 여러 PR이 큐에 쌓이며, 실패한 잡이 러너를 붙잡아 다른 잡의 대기 시간까지 늘린…
왜 "배포 성공 = 정상"이 아닌가 CI가 초록불이고 파드가 Running이어도 서비스가 정상이라는 보장은 없다. 새 버전이 뜬 직후에는 커넥션 풀 워밍업, JIT 컴파일, 캐시 미스, 다운스트림 …
왜 스테이지 순차 실행이 문제인가 GitLab CI의 기본 모델은 스테이지 단위로 파이프라인을 진행한다. build → test → deploy 순서라면, build 스테이지의 모든 잡이 끝나야 t…
왜 캐시 키가 문제인가 모노레포에서 Bazel, Nx, Turborepo 같은 빌드 시스템은 이미 만든 결과물을 다시 만들지 않으려고 원격 캐시를 쓴다. 이 캐시의 정확성은 전적으로 "키"에 달려 …
왜 중복 이벤트가 문제인가 GitHub, GitLab, Docker Registry 같은 서비스는 웹훅을 최소 1회(at-least-once) 전달을 보장한다. 즉 같은 이벤트가 두 번 이상 도착할…
왜 드레이닝이 필요한가 Blue-Green 배포는 신규(Green) 환경을 띄운 뒤 트래픽을 한 번에 전환하는 방식이다. 문제는 전환 순간에 Blue로 향하던 기존 커넥션이다. 로드밸런서 타깃에서 …
왜 태그 기반 배포가 위험한가 myapp:1.4.0 같은 태그는 사람이 붙이는 라벨일 뿐, 특정 이미지를 영구히 가리키지 않는다. 같은 태그를 다시 push하면 레지스트리의 태그 포인터가 새 이미지…
왜 마이그레이션이 배포를 멈추는가 PostgreSQL이나 MySQL에서 ALTER TABLE 같은 DDL은 대상 테이블에 ACCESS EXCLUSIVE (PG) 혹은 메타데이터 락(MySQL)을 요…
왜 렌더링 사고가 반복되는가 Helm 차트는 결국 문자열 템플릿이다. values.yaml 의 작은 오타나 조건 분기 실수는 배포 시점에야 드러난다. helm install 이 성공해도 실제로는 r…
몇 년 전만 해도 도커 이미지는 사실상 amd64(x86_64) 하나면 충분했다. 하지만 이제 개발자 노트북은 arm64로 바뀌었고 클라우드에서도 arm64 인스턴스가 같은 성능을 더 싼 값에 제공…
왜 라이선스 검사가 문제가 되는가 오픈소스 의존성은 프로젝트당 수백 개에 이르고, 각 패키지는 저마다 다른 라이선스를 가진다. 문제는 대부분의 팀이 이를 코드 리뷰에서 육안으로 확인하지 못한다는 점…
왜 GitOps에서 시크릿이 문제가 되는가 GitOps는 Git을 단일 진실 공급원(single source of truth)으로 삼는다. 매니페스트를 커밋하면 Argo CD나 Flux가 클러스터 …
왜 스모크 테스트 게이트가 필요한가 단위 테스트와 통합 테스트를 모두 통과해도 실제 배포 환경에서는 다른 문제가 터진다. 환경변수 누락, DB 커넥션 실패, 잘못된 시크릿, 이미지 태그 불일치 같은…
왜 환경 분리가 문제가 되는가 dev, staging, prod를 하나의 테라폼 코드로 관리할 때 가장 흔한 사고는 잘못된 환경에 apply 하는 것이다. 상태 파일(state)이 섞이거나, 프로덕…
왜 단순 샤딩은 느린가 CI에서 테스트를 N개 러너로 나눌 때 가장 흔한 방식은 파일 개수나 알파벳 순으로 균등 분할하는 것이다. 하지만 테스트 파일마다 실행 시간은 수십 ms에서 수 분까지 편차가…
왜 다중 클러스터에서 배포 관리가 무너지는가 클러스터가 dev, staging, prod-us, prod-eu로 늘어나면 각 클러스터마다 Application 리소스를 따로 만들어 관리하게 된다. …
왜 배포 순서가 문제인가 ArgoCD는 기본적으로 Application에 속한 모든 매니페스트를 한 번에 클러스터에 적용한다. 대부분의 경우 Kubernetes 컨트롤러가 알아서 재조정(reconc…
왜 로컬과 CI의 린트가 어긋나는가 많은 팀이 CI 파이프라인에서 black , ruff , eslint 같은 린터를 돌린다. 하지만 개발자 로컬에서는 각자 다른 버전의 도구를 설치해 쓰거나, 아예…
왜 순수 Terraform은 멀티환경에서 무너지는가 dev, staging, prod를 나누다 보면 대부분 디렉터리를 통째로 복사한다. 모듈 호출, backend 설정, provider 블록, 변수…
왜 장수명 브랜치가 문제인가 Git Flow처럼 feature , develop , release 브랜치를 오래 유지하는 방식은 규모가 커질수록 병합 지옥을 만든다. 브랜치가 며칠~몇 주 살아 있으…
왜 이미지 스캔이 필요한가 컨테이너 이미지는 애플리케이션 코드뿐 아니라 베이스 이미지의 OS 패키지, 언어 런타임, 설치된 라이브러리까지 통째로 배포된다. 문제는 이 계층 대부분을 개발자가 직접 관…
왜 PR 폭주가 문제인가 Renovate를 기본 설정으로 켜면 의존성 하나당 PR이 하나씩 생성된다. 모노레포나 프론트엔드 프로젝트처럼 패키지 수가 수백 개인 환경에서는 매주 수십 개의 PR이 쏟아…
배포할 때마다 누군가 손으로 버전을 올리고, 체인지로그를 정리하고, 태그를 붙이고, 릴리스 노트를 작성하는 팀이 여전히 많다. 이 과정은 지루할 뿐 아니라 실수가 잦다. 어떤 릴리스는 버전이 갑자기…
왜 단일 잡(job) 테스트가 병목이 되는가 테스트 스위트가 커질수록 CI 파이프라인의 총 실행 시간은 선형으로 늘어난다. 하나의 잡에서 수천 개의 테스트를 순차 실행하면, PR 하나를 검증하는 데…
CI 파이프라인이 느려지는 과정은 대개 조용하다. 처음엔 3분이던 빌드가 어느 날 8분이 되고, 머지 큐가 밀리는 시점이 되어서야 문제가 드러난다. 이때 흔히 저지르는 실수는 감으로 최적화하는 것이…
왜 CI 스토리지가 조용히 새는가 CI 아티팩트는 빌드 산출물, 테스트 리포트, 커버리지 데이터, 컨테이너 이미지 레이어, 캐시로 구성된다. 문제는 이들 대부분이 기본 보존 기간이 길거나 무제한 이…
왜 CI 실패 분류가 필요한가 파이프라인이 커질수록 실패의 원인은 다양해진다. 코드 버그, 플래키 테스트, 인프라 타임아웃, 의존성 설치 실패, 시크릿 만료 등이 한데 섞여 "빨간 X"로만 표시된다…
왜 feature flag가 기술부채가 되는가 Feature flag는 배포와 릴리스를 분리하고 점진적 롤아웃을 가능하게 하지만, 대부분의 팀에서 '켜는' 코드는 열심히 짜도 '지우는' 과정은 방치…
컨테이너 이미지를 레지스트리에 올리는 순간, 우리는 암묵적으로 “이 태그로 pull 한 이미지가 내가 빌드한 그 이미지일 것이다”라고 믿습니다. 하지만 태그는 언제든 다른 다이제스트를 가리키도록 덮…
왜 성능 회귀는 늦게 발견되는가 기능 버그는 테스트가 빨간불로 잡아준다. 하지만 응답 지연이 20% 늘거나 메모리 할당이 두 배가 되는 회귀는 대부분 통과한다. 단위 테스트는 "맞는가"만 검증하지 …
왜 태그 참조가 위험한가 대부분의 워크플로는 uses: actions/checkout@v4 처럼 태그나 브랜치로 액션을 참조한다. 그런데 Git 태그는 이동 가능한 포인터일 뿐이다. 액션 저장소가 …
왜 로컬 빌드는 한계에 부딪히는가 모노레포가 커지면 전체 빌드 그래프의 액션 수는 수만~수십만 개로 늘어난다. 개발자 노트북이나 단일 CI 러너의 코어 수는 고정되어 있으므로, 병렬화 이득은 코어 …
환경마다 YAML을 복사하면 생기는 문제 쿠버네티스를 운영하다 보면 dev, staging, prod가 거의 같은 Deployment를 쓴다. 차이라곤 replicas 수, 이미지 태그, 리소스 l…
기능 브랜치에서 UI를 고쳤는데 리뷰어가 그 변화를 확인하려고 브랜치를 체크아웃해 로컬에 띄워봐야 한다면 리뷰의 마찰이 크게 늘어난다. 코드 diff만 보고 “버튼 정렬이 실제로 어떻게 보이는지”,…
왜 모듈 버저닝이 문제가 되는가 여러 팀이 공용 모듈을 쓰기 시작하면 곧 문제가 드러난다. 모듈 소스를 Git 브랜치로 참조하면, 모듈 저장소에 머지된 변경이 참조하는 모든 스택에 즉시 반영된다. …
왜 배포 순서가 문제가 되는가 모노레포에서는 여러 서비스와 라이브러리가 한 저장소에 모여 있다. 문제는 이들이 서로를 참조한다는 점이다. 공용 라이브러리 core 가 바뀌면 이를 쓰는 api 와 w…
왜 스테이징만으로는 부족한가 스테이징 환경은 합성 트래픽과 소량의 시드 데이터로 돌아간다. 문제는 장애 대부분이 프로덕션 특유의 조건 에서 터진다는 점이다. 실제 사용자 요청의 분포(특정 파라미터 …
왜 비주얼 회귀 테스트가 필요한가 단위 테스트와 E2E 테스트는 "기능이 동작하는가"를 검증하지만, 화면이 실제로 어떻게 보이는가는 거의 다루지 못한다. CSS 리팩터링, 디자인 토큰 변경, 폰트 …
쿠버네티스에 애플리케이션을 배포하다 보면 매니페스트가 순식간에 수십 개로 불어난다. Deployment, Service, ConfigMap, Ingress, HPA가 환경마다 조금씩 다르고, 이미지…
왜 통합 테스트만으로는 부족한가 마이크로서비스가 늘어나면 서비스 A(소비자)가 서비스 B(제공자)의 API를 호출하는 관계가 얽힙니다. B 팀이 응답 필드 이름을 바꾸거나 필수 필드를 제거하면, B…
왜 마이그레이션이 배포의 약한 고리인가 애플리케이션 코드는 롤백이 쉽다. 이전 이미지로 되돌리면 끝이다. 하지만 DB 스키마는 상태를 가진다. ALTER TABLE 로 컬럼을 드롭한 뒤 문제를 발견…
왜 배포 프리즈가 필요한가 연말 쇼핑 시즌, 대규모 마케팅 이벤트, 규제 심사 기간처럼 장애 비용이 급증하는 구간이 있다. 이때는 평소라면 무해했을 배포도 리스크가 된다. 롤백 인력이 부족한 새벽·…
왜 수동 리뷰어 지정이 문제인가 PR을 올릴 때마다 "이 코드는 누가 봐야 하지?"를 고민하는 팀이 많다. 결정이 사람에게 맡겨지면 리뷰어가 특정 인원에게 몰리고, 도메인 담당자가 빠진 채 병합되며…
대부분의 CI 도구는 쿠버네티스 바깥 에 살면서 클러스터를 원격으로 조종한다. Jenkins 마스터, GitLab 러너, GitHub Actions 워커가 kubectl apply 나 헬름 명령을 …
왜 전체 커버리지 게이트는 실패하는가 많은 팀이 "전체 커버리지 80% 유지" 같은 게이트를 CI에 건다. 하지만 레거시 코드가 많은 저장소에서 이 방식은 두 가지로 실패한다. 첫째, 이미 72%인…
왜 시크릿 유출이 치명적인가 API 키, DB 비밀번호, 클라우드 액세스 키가 Git 히스토리에 한 번 커밋되면, 이후 커밋에서 삭제하더라도 히스토리에는 영원히 남는다. 공개 저장소라면 자동화된 봇…
왜 멀티아키텍처가 문제가 되는가 M1/M2 맥(arm64)에서 docker build 로 만든 이미지를 amd64 EC2에 배포하면 exec format error 가 발생한다. 반대의 경우도 마찬…
애플리케이션 하나를 빌드하면 직접 작성한 코드는 전체의 5~10%에 불과하고 나머지는 오픈소스 의존성이다. 그 의존성은 또 다른 의존성을 끌어오고, 이 전이(transitive) 관계는 수백 단계까…
왜 중복 배포가 문제인가 같은 브랜치에 짧은 간격으로 여러 커밋이 푸시되면 배포 워크플로가 각각 실행된다. 문제는 이들이 서로 다른 시점의 아티팩트를 같은 환경에 밀어넣는다는 점이다. 커밋 A와 B…
왜 환경별 values 파일이 문제가 되는가 가장 흔한 시작점은 values-dev.yaml , values-staging.yaml , values-prod.yaml 을 각각 통째로 복제하는 방식이…
왜 모노레포 버저닝이 문제가 되는가 여러 패키지를 한 저장소에 두면 코드 공유와 통합 테스트는 쉬워지지만, 배포 시점에 "무엇을 어떤 버전으로 올릴 것인가"가 골칫거리가 된다. 흔한 실패 패턴은 두…
수동 버전 관리가 무너지는 지점 버전 번호를 사람이 손으로 올리면 두 가지가 반드시 어긋난다. 첫째, 버그 픽스만 있는데 마이너를 올리거나, 호환성이 깨지는 변경을 냈는데 패치만 올리는 판단 오류가…
배포와 릴리스는 같은 일이 아니다 많은 팀이 "배포(deploy)"와 "릴리스(release)"를 한 단어처럼 쓴다. 그러나 둘은 다른 사건이다. 배포는 새 코드를 프로덕션 서버에 올려두는 기술적 …
왜 워크플로 중복이 문제인가 마이크로서비스나 모노레포를 운영하다 보면 각 서비스마다 build → test → lint → docker push 파이프라인이 거의 똑같이 반복된다. 처음엔 복사·붙여…
왜 "그린한 PR"이 메인을 깨뜨리는가 PR이 통과했다는 것은 그 시점의 메인 과 병합한 결과가 통과했다는 뜻이다. 여러 PR이 동시에 그린 상태로 대기하다 순차 머지되면, 각 PR은 서로의 변경을…
프로젝트가 오래될수록 의존성은 조용히 낡아간다. 보안 취약점 알림을 받고 나서야 여러 버전을 한꺼번에 올리려다 빌드가 무너지는 경험은 대부분의 팀이 겪는다. 이 “한 번에 몰아서 업데이트”의 고통을…
초록불을 유지하던 CI가 어느 날부터 같은 커밋을 두 번 돌리면 한 번은 통과하고 한 번은 실패하기 시작하면, 팀은 조용히 위험한 습관을 들인다. 바로 “일단 재시도(retry) 버튼을 누른다” 는…
왜 수동 승인만으로는 부족한가 많은 조직이 프로덕션 배포 전 관리자 승인을 요구한다. 하지만 승인이 슬랙 메시지나 이메일, 티켓 코멘트에 흩어져 있으면 몇 가지 문제가 생긴다. 첫째, 누가 무엇을 …
왜 장기 자격증명이 문제인가 대부분의 CI 파이프라인은 클라우드에 접근하기 위해 액세스 키를 시크릿으로 저장한다. 하지만 정적 키는 한 번 만들면 만료되지 않고, 저장소·로그·포크된 PR을 통해 유…
왜 전체 빌드가 문제가 되는가 모노레포가 커지면 하나의 커밋이 수십 개 프로젝트를 담은 저장소 전체를 건드리는 것처럼 보인다. 실제로는 문서 한 줄만 고쳤는데도 CI가 모든 서비스의 빌드·테스트·이…
오래 굴러온 Jenkins 파이프라인은 대개 하나의 거대한 생명체처럼 자라 있다. 수십 개의 Jenkinsfile , 손으로 설치한 플러그인 더미, 특정 노드에만 존재하는 도구 버전, 아무도 전체를…
왜 수동 롤백은 늦는가 새 버전을 100%로 한 번에 배포하면 장애가 전체 트래픽을 덮친다. 카나리 배포는 소수 트래픽(예: 5%)만 신 버전으로 보내 위험을 격리한다. 하지만 사람이 대시보드를 보…
왜 의존성 설치가 병목이 되는가 CI 파이프라인의 러너는 대부분 매 실행마다 깨끗한 환경에서 시작한다. 그래서 npm install , pip install , go mod download 같은 명…
명령형 배포가 만드는 문제 많은 팀이 kubectl apply 나 스크립트로 클러스터를 직접 변경한다. 문제는 클러스터의 실제 상태가 코드 저장소 어디에도 남지 않는다는 점이다. 누가 언제 무엇을 …
라이브러리나 CLI 도구를 만들다 보면 “이게 Python 3.9에서도 돌아가나?”, “Windows에서는 경로 처리가 깨지지 않나?” 같은 질문이 계속 쌓인다. 이걸 손으로 하나씩 확인하는 건 현…
쿠버네티스 배포는 대개 kubectl apply 나 CI 파이프라인에서 매니페스트를 클러스터로 직접 밀어넣는 푸시(push) 방식 에서 출발한다. 처음엔 잘 돌아가지만 서비스와 환경이 늘면 문제가 …
배포는 새 기능을 세상에 내보내는 순간이지만, 동시에 장애가 가장 많이 발생하는 순간이기도 합니다. 아무리 테스트를 촘촘히 짜도 프로덕션 트래픽과 실데이터 앞에서는 예상치 못한 문제가 튀어나옵니다.…
배포(deploy)와 릴리스(release)를 같은 것으로 취급하면, 코드를 프로덕션에 올리는 순간이 곧 사용자에게 기능이 노출되는 순간이 됩니다. 이 결합은 릴리스 타이밍을 배포 파이프라인에 묶어…
CI 파이프라인에서 가장 자주 손보게 되는 곳이 컨테이너 이미지 빌드입니다. 매번 몇 분씩 걸리는 docker build 는 개발 피드백 루프를 갉아먹고, CI 청구서도 불립니다. 다행히 Docke…
GitHub Actions를 쓰다 보면 두 갈림길을 만납니다. GitHub이 제공하는 호스티드 러너를 계속 쓸 것인가, 아니면 셀프호스티드 러너 를 직접 운영할 것인가. 빌드가 느려서, 요금이 부담…
모노레포가 커질수록 CI는 “매번 전부 빌드하고 전부 테스트하는” 관성 때문에 느려집니다. 패키지가 30개인데 하나만 고쳐도 30개를 전부 도는 파이프라인은 개발자 대기 시간을 잡아먹고 러너 비용을…
같은 커밋을 아무것도 안 바꾸고 다시 돌렸는데 이번엔 초록불이 뜬다. 어제까지 멀쩡하던 테스트가 오늘 아침 PR에서 빨간불을 내고, “재시도(Re-run)” 버튼을 한 번 누르면 통과한다. 팀 채널…
CI/CD 파이프라인이 성숙해질수록 반드시 마주치는 문제가 시크릿 관리입니다. DB 비밀번호, API 키, TLS 인증서, 클라우드 자격 증명 — 이런 값들을 어떻게 저장하고, 어떻게 배포 시점에 …
기능 브랜치를 만들고 며칠, 길게는 몇 주씩 작업하다 메인 브랜치에 합치려는 순간, 지옥이 시작된다. 그 사이 다른 사람들이 올린 수십 개의 커밋과 충돌하고, 충돌을 해결하고 나면 테스트가 깨지고,…
GitLab CI 파이프라인을 처음 구성할 때는 잘 동작하다가, 프로젝트가 커지고 잡(job)이 늘어나면 어느 순간 빌드 시간이 10분을 넘어가기 시작한다. 원인을 들여다보면 대부분 매 잡마다 의존…
개발팀이 빠르게 움직이려면 코드를 푸시한 후 “이 변경이 시스템을 망가뜨리지 않는다”는 확신을 최대한 빨리 얻어야 합니다. 그 확신을 주는 것이 CI 테스트이고, 그 확신을 얻는 데 걸리는 시간이 …
운영 중인 서비스를 중단 없이 새 버전으로 바꾸는 일은 쉬워 보이지만, 실제로는 수백만 원짜리 장애를 유발하는 가장 흔한 원인 중 하나입니다. 블루-그린, 카나리, 롤링 업데이트—세 전략은 각각 뚜…
GitHub Actions를 도입하고 얼마 지나지 않아 많은 팀이 같은 벽에 부딪힙니다. PR을 올릴 때마다 20~30분씩 기다리는 CI 실행 시간. 코드 몇 줄 고쳤을 뿐인데 의존성 수천 개를 처…
팀이 커지고 코드베이스가 복잡해질수록 가장 먼저 고통받는 것은 CI/CD 파이프라인 입니다. 처음에는 5분이던 빌드가 어느 순간 40분을 넘기고, 개발자들은 PR 하나를 머지하기 위해 점심시간을 통…