Slack

14 개의 포스트

slack.engineering

태그로 필터

slack5분 읽기큐레이션 요약

Shipyard: Slack의 차세대 EC2 플랫폼을 구축한 방법

Slack은 장기 실행 EC2 인스턴스를 지속적으로 수정하는 기존 운영 방식의 한계를 해결하기 위해 차세대 EC2 플랫폼인 Shipyard를 구축했다. Shipyard는 EC2를 계속 변경되는 서버가 아니라 빌드·배포 가능한 불변 아티팩트로 다루며, 점진적 배포와 메트릭 기반 자동 중단·롤백을 지원한다. 이를 통해 컨테이너로 전환하기 어려운 워크로드에도 현대적인 배포 안정성과 예측 가능성을 제공한다. ## 기존 EC2 운영 방식의 한계 - Chef 기반으로 장기간 실행되는 인스턴스를 계속 업데이트하는 방식은 다음 문제를 낳았다. - 서비스 단위 배포가 복잡함 - 인프라 드리프트가 시간이 지날수록 누적됨 - 여러 계층의 변경 사항을 조율해야 함 - 수동 변경과 자동 설정 적용이 충돌할 수 있음 - Slack은 기존 Chef 환경을 다중 스택, 버전 관리, 분리된 프로덕션 환경, 신호 기반 실행 등으로 개선했지만 근본적인 구조적 한계는 남아 있었다. - 컨테이너가 일부 문제를 해결했지만 인프라 컴포넌트, Kubernetes 워커 노드, egress 네트워크 스택 등은 쉽게 컨테이너화하기 어려웠다. ## Shipyard의 핵심 방향 - 인스턴스를 지속적으로 수정하는 대신 이미지와 배포 산출물을 중심으로 운영한다. - 서비스 단위 배포 기능을 제공해 애플리케이션 배포와 유사한 방식으로 EC2 인프라를 관리한다. - 빌드 파이프라인, 배포 오케스트레이션, 자동 안전 장치를 긴밀하게 연동한다. - 인프라 변경을 불변성, 점진적 롤아웃, 자동화된 안전 검증을 갖춘 배포 과정으로 전환한다. ## 멀티 아키텍처와 멀티 운영체제 - AMD64와 ARM 기반 AWS Graviton 인스턴스를 모두 지원한다. - Ubuntu, RHEL, Amazon Linux 등 여러 운영체제를 사용할 수 있다. - 비용, 성능, 호환성에 따라 서비스별 실행 환경을 선택할 수 있다. - 컨테이너 전환이 어려운 다양한 EC2 워크로드를 동일한 플랫폼에서 운영할 수 있다. ## 메트릭 기반 점진적 배포 - Shipyard는 Slack의 배포 오케스트레이션 시스템인 Gondola와 통합된다. - 배포 과정에서 서비스 상태 지표를 기반으로 자동 안전 검사를 수행한다. - 오류율, 성능 저하 등 서비스 헬스 신호가 나빠지면 배포를 자동으로 중단할 수 있다. - 문제가 발생하면 이전의 정상 버전으로 자동 롤백할 수 있다. - 따라서 배포 실패의 영향 범위를 줄이고, 운영자의 수동 판단 의존도를 낮춘다. ## 계층형 이미지와 빠른 프로비저닝 - 컨테이너 이미지와 유사한 계층형 이미지 구조를 사용한다. - 공통 인프라 요소를 포함한 골든 베이스 이미지를 먼저 만들고, 그 위에 서비스별 이미지를 쌓는다. - 인스턴스 시작 시 수행해야 할 작업을 줄여 리전 간에도 빠르고 예측 가능한 프로비저닝이 가능하다. - 실행 시점에 많은 설정을 적용하던 기존 방식보다 부팅 과정의 변동성이 작다. ## 설정 관리 방식의 변화 - 기존에는 실행 중인 인스턴스가 주기적으로 Chef 작업을 실행해 설정을 확인하고 원하는 상태로 되돌렸다. - Shipyard에서는 이미지 생성과 초기 프로비저닝 같은 명확한 수명 주기 단계에서 설정을 적용한다. - 설정 관리 도구는 시스템 전체를 계속 수정하기보다 서비스 배포에 집중한다. - 이 방식의 장점은 다음과 같다. - 백그라운드 작업 부하 감소 - 수동 변경의 의도치 않은 덮어쓰기 방지 - 시간이 지나면서 인스턴스 상태가 달라지는 현상 감소 - 시스템 동작과 장애 원인 분석의 단순화 ## Peekaboo 기반 실시간 인벤토리 - Shipyard는 EC2 플릿을 거의 실시간으로 확인하기 위한 인벤토리 시스템 Peekaboo를 제공한다. - 기존처럼 Chef Server를 단일 정보 원천으로 사용하지 않고 AWS 이벤트와 인스턴스 메타데이터를 직접 활용한다. - Shipyard로 배포되지 않은 인스턴스도 추적해 전체 EC2 플릿을 한곳에서 확인할 수 있다. - AWS EventBridge, OpenSearch, Lambda를 기반으로 구축되었다. - UI, API, CLI를 제공해 다음 작업을 지원한다. - 전체 인스턴스 상태 탐색 - 다른 시스템과의 통합 - 명령줄에서 빠른 상태 확인 - 중앙화된 가시성을 통해 어떤 인스턴스가 어디에 있고 어떤 상태인지 파악하기 쉬워진다. ## 짧은 수명의 불변 인스턴스 - 각 EC2 인스턴스에 제한된 수명을 부여하고 정기적으로 자동 교체한다. - 인스턴스를 직접 수정해 오래 유지하기보다 새 이미지를 배포해 교체하는 방식을 채택한다. - 보안 취약점이 노출된 채 남아 있는 시간을 줄일 수 있다. - 운영팀은 개별 서버를 고치는 대신 최신 이미지를 기반으로 인스턴스를 재생성하는 데 집중한다. - 결과적으로 EC2 플릿의 상태를 지속적으로 신선하게 유지할 수 있다. ## Golden Base Image인 slack-zero - Shipyard의 기반에는 Slack Compute Platform Team이 관리하는 공통 이미지 `slack-zero`가 있다. - 보안 및 모니터링 팀과 협력해 표준화된 기반 환경을 유지한다. - 포함 내용: - 운영체제 기본 설정과 보안 강화 - 네트워크 및 서비스 디스커버리 설정 - 모니터링·보안 에이전트 - 공통 도구와 기반 시스템 설정 - 서비스는 `slack-zero`를 기반으로 필요한 런타임과 애플리케이션 요소를 추가한다. - 기반 이미지는 불변이지만 영구적으로 유지하지는 않는다. - 보안 패치, 모니터링 업데이트, 네트워크 개선이 필요하면 새 이미지를 생성한다. - 서비스 이미지는 최신 `slack-zero`를 기반으로 다시 빌드해 변경 사항을 상속한다. ## AWS Image Builder 활용 - Slack은 기존 Packer 대신 AWS Image Builder를 사용해 `slack-zero`를 생성한다. - AWS Image Builder의 장점으로 다음이 언급된다. - 수명 주기 정책을 통한 오래된 AMI 자동 정리 - AMI 저장 비용 절감 - 새 이미지가 생성될 때 SSM Parameter에 최신 AMI 정보를 게시 - 이를 통해 서비스 이미지 빌드와 인스턴스 교체 과정에서 최신 기반 이미지를 일관되게 참조할 수 있다. Shipyard의 핵심은 EC2를 수동으로 계속 관리하는 서버가 아니라, 버전이 지정된 이미지로 빌드하고 안전하게 교체하는 배포 대상으로 바꾸는 데 있다. EC2를 계속 사용해야 하지만 컨테이너의 불변성, 계층형 이미지, 점진적 배포, 자동 롤백의 이점을 원하는 조직이라면 이와 같은 플랫폼 접근이 효과적이다.

원문 읽기(새 탭에서 열림)
slack4분 읽기큐레이션 요약

에이전트 기반 테스트: E2E 테스트 스택에서 에이전트가 적합한 위치

에이전트 기반 E2E 테스트는 기존의 결정적 테스트를 대체하기보다, 사용자의 목표 달성 여부를 탐색적으로 검증하는 별도의 계층으로 활용해야 한다. 200회 이상 실험한 결과 Playwright MCP 기반 에이전트가 복잡한 흐름에서도 가장 안정적이었고, 생성된 Playwright 테스트는 단순한 흐름에서는 빠르지만 복잡도가 높아질수록 실패율이 크게 증가했다. 따라서 전통적 테스트는 핵심 회귀 검증에, 에이전트 테스트는 유연한 탐색과 목표 중심 검증에 배치하는 것이 적절하다. ## 여정 검증에서 목표 검증으로 - 전통적인 E2E 테스트는 `클릭 → 클릭 → 입력 → 검증`처럼 미리 정해진 UI 경로를 검증한다. - 에이전트 기반 테스트는 “스레드 메시지를 보내라”처럼 목표를 제시하고, 에이전트가 현재 UI 상태에 따라 경로를 선택하게 한다. - 동일한 결과에 도달하더라도 다음과 같은 차이가 발생했다. - 검색 제안 클릭 또는 Enter 키 사용 - 검색 화면을 다시 열거나 기존 상태 재사용 - 중간 클릭, 스냅샷 확인 등의 추가·생략 - 에이전트는 중간 단계도 검증할 수 있지만, 경로의 유연성 때문에 실행 시간·비용·신뢰성 관리가 필요하다. ## 실험 구성과 비교 대상 - 200회 이상의 자동 실행으로 신뢰성, 속도, 비용을 비교했다. - 비교한 실행 방식은 세 가지다. - **에이전트 + Playwright MCP**: 브라우저 액션과 DOM 상태·로그를 지속적인 컨텍스트로 사용 - **에이전트 + Playwright CLI**: 셸에서 명령을 한 단계씩 실행하고 매번 UI 상태를 바탕으로 다음 행동 결정 - **생성된 Playwright 테스트**: 자연어 설명으로 결정적 테스트 코드를 생성한 뒤 실행·수정 - Claude Sonnet 4.5와 Opus 4.6을 사용했으며, 비운영 데이터가 있는 테스트 워크스페이스에서 실행했다. - 입력 형식은 다음 두 가지였다. - 자연어 지시: 사람이 읽기 쉬운 단계별 설명 - 구조화된 YAML: 단계, 액션, 대상, 기대 결과를 명시 - 각 설정은 20회씩 실행했다. ## 테스트한 사용자 흐름 - **Thread Reply** - 약 15~20단계의 단순한 흐름 - 채널 생성, 메시지 전송, 스레드 답글 작성, 스레드 상태 확인 - **Search Discovery** - 약 25~30단계의 중간 복잡도 흐름 - 검색어 입력, 검색 결과 탐색, 채널·스레드·검색 화면 간 이동, 결과 검증 ## 측정 결과 | 방식 | Thread Reply 실패율 | Search Discovery 실패율 | 평균 실행 시간 | |---|---:|---:|---:| | 에이전트 + Playwright MCP | 0% | 약 12% | 약 5~8분 | | 에이전트 + Playwright CLI | 약 12% | 약 20% | 약 9~11분 | | 생성된 Playwright 테스트 | 약 8% | 약 48% | 약 3분 | - 에이전트 테스트는 실행당 15~30달러가 들고 10분 이상 걸릴 수 있어, 일반적인 빠른 회귀 테스트를 그대로 대체하기에는 부담이 있다. - 그러나 전통적 테스트와 목적이 다르므로 단순한 실패율만으로 비교해서는 안 된다. ## 복잡도가 높아질수록 벌어지는 신뢰성 차이 - Playwright MCP는 단순한 시나리오에서 거의 실패하지 않았고, 복잡한 흐름에서도 실패율이 0~12% 수준이었다. - Playwright CLI는 인증 처리, 탐색 타이밍, 세션 불안정 등 실행 환경 문제로 약 12~20%의 실패율을 보였다. - 생성된 Playwright 테스트는 단순한 흐름에서는 약 8% 실패했지만, 복잡한 검색 흐름에서는 약 48%까지 악화됐다. - 생성 테스트는 대체로 전체 흐름의 70~80%까지 진행한 뒤 마지막 상호작용이나 assertion에서 실패했다. - 주요 원인은 다음과 같다. - UI 상태의 변동성 - 자연어 명세와 실제 요소 선택 간의 추상화 불일치 - 기존 Page Object 추상화가 복잡한 상황에서 정확한 요소 지정을 방해 - MCP는 애플리케이션의 실시간 상태를 안정적으로 유지하는 반면, CLI는 단계마다 스냅샷을 다시 구성한다. - 긴 흐름에서는 상태 해석과 타이밍의 작은 차이가 누적되어 CLI 방식의 실패 가능성이 커질 수 있다. ## 테스트 스택에서의 적절한 역할 - 전통적인 결정적 Playwright 테스트는 빠르고 반복 가능하므로 핵심 회귀 테스트와 CI의 기본 검증에 적합하다. - 에이전트 기반 테스트는 특정 클릭 순서가 아니라 “사용자가 목표를 달성할 수 있는가”를 검증하는 데 적합하다. - 특히 다음 영역에서 활용 가치가 있다. - 다양한 UI 경로를 허용해야 하는 사용자 여정 - 사전에 모든 경로를 코드로 작성하기 어려운 탐색적 테스트 - 복잡한 화면 상태와 실제 사용자 행동에 가까운 검증 - 에이전트 방식 중에서는 실시간 브라우저 컨텍스트를 유지하는 Playwright MCP가 복잡한 시나리오에 더 적합한 것으로 나타났다. - 다만 높은 비용과 긴 실행 시간을 고려해 모든 커밋에서 실행하기보다는, 야간 테스트나 릴리스 전 검증 등 별도 계층에 배치하는 것이 현실적이다. 에이전트 기반 E2E 테스트는 결정적 테스트의 대체재가 아니라 보완재로 도입하는 것이 좋다. 빠르고 안정적인 핵심 회귀 검증은 기존 Playwright 테스트로 유지하고, MCP 기반 에이전트 테스트를 목표 중심·탐색적 검증에 제한적으로 추가하는 구성이 가장 실용적이다.

원문 읽기(새 탭에서 열림)
slack4분 읽기큐레이션 요약

Slack AI: 멀티 클라우드로 가는 길

Slack AI는 초기 SageMaker 기반 운영에서 출발해 Amazon Bedrock으로 이전하며, 수동적인 GPU·용량 관리에서 관리형·다중 클라우드 오케스트레이션으로 발전했다. 이 과정의 목표는 단순히 최신 LLM을 도입하는 것이 아니라, GPU 부족과 지역 장애에도 견디면서 엔터프라이즈 수준의 보안·성능·신뢰성을 유지하는 것이었다. 특히 부하 테스트, 품질 비교, 점진적 트래픽 전환을 통해 고객 영향 없이 마이그레이션을 완료한 점이 핵심이다. ## SageMaker 기반 초기 아키텍처 - 2023년 초 Slack은 AWS SageMaker를 LLM 서빙의 출발점으로 선택했다. - SageMaker는 다음 요구사항을 충족했다. - 보안성과 FedRAMP 준수 - 모델 가용성과 제어권 - Escrow VPC를 활용한 제로 지식 환경 - Slack의 데이터는 외부에 노출되지 않았고, 모델 제공업체의 비공개 가중치에도 Slack이 접근할 수 없었다. - 글로벌 가용성을 위해 여러 AWS 리전에 컨테이너를 배포했다. - 운영팀은 리전 간 IAM 역할, 모델 엔드포인트 라우팅, 용량 계획, 자동 확장을 직접 관리해야 했다. ## 자체 운영에서 발생한 비용 - **확장 지연** - 인스턴스 초기화 시간이 길어 즉각적인 확장이 어려웠다. - **GPU 부족** - A100, H100 같은 고성능 NVIDIA GPU를 필요한 시점에 확보하기 어려웠다. - **과잉 프로비저닝** - 피크 시간대 SLA를 맞추기 위해 유휴 리소스를 미리 확보해야 했다. - 2024년 초에는 On-Demand Capacity Reservations와 cron 기반 사전 확장으로 문제를 완화했지만, 엔지니어링 리소스가 인프라 조정 업무에 과도하게 투입됐다. - 결국 Slack은 수동 조정이 아니라 자동화된 용량 확보가 필요하다고 판단했다. ## SageMaker의 모델 출시 지연 - AWS가 관리형 LLM 서비스인 Bedrock을 우선적으로 발전시키면서, SageMaker 기반 커스텀 서빙 환경은 최신 모델 도입에서 뒤처지기 시작했다. - Escrow VPC에서 Anthropic 모델을 호스팅하는 방식은 Bedrock보다 모델 업데이트와 최적화 적용이 수주에서 수개월 늦었다. - AI 기능 품질이 경쟁력과 직결되는 Slack에는 이러한 지연이 큰 문제가 됐다. ## Amazon Bedrock으로의 전환 - 2024년 중반 Slack은 FedRAMP Moderate 인증과 필요한 보안 수준을 갖춘 Bedrock으로 이전했다. - 전환의 주요 이점은 다음과 같다. - 개별 GPU 인스턴스와 엔드포인트를 직접 확장하지 않아도 되는 운영 단순화 - 최신 모델을 공개 직후 빠르게 사용 가능 - 사용 패턴에 따른 비용·용량 최적화 - 예측 가능하고 지연 시간에 민감한 채널 요약에는 **Provisioned Throughput(PT)**를 사용했다. - 간헐적이고 예약 실행되는 Recap 작업에는 **On-Demand(OD)**를 사용해 유휴 용량 비용을 줄였다. ## Model Unit 기반 용량 관리 - Bedrock의 용량은 GPU 인스턴스가 아니라 **Model Unit(MU)**로 측정된다. - 각 MU는 분당 토큰 수로 표현되는 일정한 처리량을 제공한다. - Slack은 하드웨어 세부사항 대신 필요한 토큰 처리량에 집중할 수 있게 됐다. - 마이그레이션 위험을 줄이기 위해 먼저 Provisioned Throughput 환경을 이전하고, On-Demand 환경은 후속 단계로 진행했다. ## 무중단 마이그레이션 전략 - **규정 준수 검토** - Legal, Security, FedRAMP 승인을 받은 뒤 운영 트래픽을 전환했다. - **용량 검증** - 다양한 트래픽 패턴에서 SageMaker와 동일한 성능을 내는 MU 수를 부하 테스트로 산정했다. - **품질 비교** - A/B 테스트와 평가 프레임워크로 모델 출력 품질과 지연 시간을 나란히 비교했다. - **점진적 롤아웃** - 기능 플래그를 사용해 트래픽을 단계적으로 이동했다. - 문제가 발생하면 즉시 이전 환경으로 롤백할 수 있도록 구성했다. - 대규모 부하 테스트와 shadow request를 통해 기존 환경과의 성능 패리티를 확인했고, 고객에게 영향을 주는 장애 없이 전환을 완료했다. ## Bedrock 도입 이후의 운영 개선 - 엔지니어들은 GPU 수명주기, 엔드포인트 관리, 용량 예약 대신 모델 성능과 기능 품질에 집중할 수 있게 됐다. - 최신 모델을 더 빨리 적용하면서 AI Search에 고도화된 추론 모델을 신속히 도입했고, 더 정교하고 맥락에 맞는 답변을 제공할 수 있었다. - 인프라 운영은 다음과 같이 단순화됐다. - Slack이 필요한 quota를 요청 - AWS가 MU를 프로비저닝 - Slack이 해당 용량으로 트래픽을 처리 - 수요가 발생한 뒤 대응하는 방식에서, 몇 주 앞을 내다보고 용량을 예약하는 전략적 예측 방식으로 전환했다. - Slack이 강조한 운영 원칙은 **먼저 측정하고, 점진적으로 이전하며, 지속적으로 모니터링하는 것**이다. ## 남은 효율성 문제 - Provisioned Throughput은 안정적이고 예측 가능한 워크로드에는 효과적이었지만 모든 트래픽에 최적은 아니었다. - 미국 동부·서부 지역의 업무 시작 시간처럼 특정 시간대에 AI 요약과 검색 요청이 급증하는 패턴을 처리하려면 높은 MU 기본 용량을 유지해야 했다. - 그 결과 피크 시간대 성능을 보장하는 대신, 사용량이 낮은 시간에는 일부 용량이 유휴 상태로 남는 과잉 프로비저닝 문제가 여전히 존재했다. ## 실용적인 결론 LLM 인프라를 확장할 때는 직접 GPU를 운영하는 것보다 관리형 서비스가 모델 접근성과 운영 효율을 크게 높일 수 있다. 다만 서비스 이전은 단순한 엔드포인트 교체가 아니라, 부하·품질·규정 준수 검증과 점진적 롤백 체계를 포함한 통제된 마이그레이션으로 진행해야 한다.

원문 읽기(새 탭에서 열림)
slack4분 읽기큐레이션 요약

SSH에서 REST로: Slack EMR 데이터 파이프라인의 보안 주도 현대화

Slack은 700개가 넘는 EMR 데이터 파이프라인을 직접 SSH로 실행하던 구조에서 REST 기반 작업 제출 방식으로 전환했다. SSH는 보안 공격 표면, 키 관리, 장애 복구, 작업 관측성 측면에서 한계가 있었고 Spark on Kubernetes와 AWS 계정 분리 같은 현대화도 가로막았다. Slack은 YARN REST API와 YARN Distributed Shell을 활용해 8개 데이터 리전의 작업을 중단 없이 마이그레이션하고 SSH를 완전히 제거했다. ## SSH 기반 파이프라인의 확산 - 2017년경 Airflow가 EMR 마스터 노드에 SSH로 접속해 명령을 실행하는 방식으로 데이터 파이프라인을 구축했다. - 단순한 `SSHOperator` 패턴이 확산되면서 다음과 같은 작업까지 SSH로 실행됐다. - Spark 및 MapReduce 작업 - AWS CLI 명령 - 사용자 정의 Python 스크립트 - 2024년에는 700개 이상의 운영 작업이 SSH 기반으로 실행되고 있었다. - 검색 인덱싱, 분석, 비즈니스 인텔리전스 등 핵심 데이터 처리도 이 구조에 의존했다. ## SSH의 보안 및 운영상 문제 - **보안 위험** - 오케스트레이션 워커가 EMR 클러스터에 직접 SSH 접속해야 해 공격 표면이 커졌다. - SSH 키를 여러 워커에 배포하고 주기적으로 교체해야 했다. - 세밀한 감사 추적을 위해 여러 시스템의 로그를 상호 연관해야 했다. - 보안 그룹과 사용자 권한 설정이 복잡해졌다. - **운영 장애** - 작업이 EMR 마스터 노드에서 직접 실행되어 리소스 경쟁이 발생했다. - Kubernetes Pod가 재시작되면 SSH 연결이 끊겨 작업이 실패했다. - 연결이 끊긴 뒤에도 작업이 계속 실행되는 ‘좀비 작업’이 남을 수 있었다. - 연결 단절 후 작업의 성공·실패 상태를 안정적으로 확인하기 어려웠다. - **인프라 현대화 차단** - Spark on Kubernetes와 EMR on EKS 도입을 시작할 수 없었다. - 메인 AWS 계정의 EMR 클러스터를 자식 계정으로 이전하는 Whitecastle 프로젝트가 지연됐다. - 신뢰할 수 있는 작업 모니터링과 관측성을 구현하기 어려웠다. ## REST 기반 작업 제출의 장점 - SSH는 클라이언트와 서버 사이의 상태ful 연결을 유지해야 한다. - REST 방식에서는 작업의 생명주기를 서버가 관리한다. - `POST`: 작업을 제출하고 작업 ID를 받음 - `GET`: 작업 ID로 실행·완료·실패 상태를 조회 - `DELETE`: 필요할 때 작업을 취소 - Airflow나 Kubernetes Pod가 재시작되어도 작업 자체는 서버에서 계속 실행될 수 있다. - 클라이언트가 작업 상태를 다시 조회할 수 있어 연결 단절에 강하다. - 작업 취소, 리소스 관리, 로그 확인 등도 실행 엔진의 표준 기능으로 처리할 수 있다. ## YARN Distributed Shell을 활용한 해결책 - Spark는 Livy REST API, Hive는 HiveServer2를 사용할 수 있어 상대적으로 이전이 쉬웠다. - 반면 MapReduce와 `aws s3 sync`, `hadoop distcp` 같은 300개 이상의 임의 CLI 작업은 바로 사용할 REST API가 없었다. - 검토한 대안은 다음과 같았다. - 원격 명령 실행용 커스텀 래퍼 서비스 - Ansible이나 Salt 같은 원격 실행 프레임워크 - YARN에 새로운 작업 유형을 직접 개발 - 이러한 방법은 별도 보안 계층과 운영 인프라를 구축·유지해야 해 복잡도가 높았다. - YARN의 **Distributed Shell**은 임의의 셸 스크립트를 YARN 컨테이너에서 실행할 수 있도록 했다. - 기존 YARN REST API를 그대로 사용 - YARN의 인증·인가 체계 활용 - 별도 보안 서비스 불필요 - 오픈소스 표준 기반 - 컨테이너 리소스와 작업 생명주기 관리 지원 ## Distributed Shell의 실행 흐름 - 실행할 셸 스크립트를 S3에 업로드한다. - 예: `s3://bucket/command.sh` - 스크립트는 `aws s3 sync` 같은 임의 명령을 포함할 수 있다. - YARN REST 요청에 Distributed Shell의 `ApplicationMaster`와 스크립트 위치를 지정한다. - YARN이 컨테이너를 할당하고 S3에서 스크립트를 내려받아 실행한다. - 실행 과정에서 YARN이 다음을 담당한다. - 메모리와 vCore 등 리소스 제한 - 컨테이너 격리 - 재시도와 장애 복구 - 정상적인 작업 취소 - YARN UI를 통한 로그 및 상태 확인 ## 마이그레이션의 의미 - YARN Distributed Shell을 통해 REST API가 없던 CLI·MapReduce 작업까지 동일한 실행 모델로 통합할 수 있었다. - 작업 제출과 실행을 SSH 연결에서 분리해 클라이언트 재시작과 네트워크 단절에 대한 안정성을 높였다. - 700개 이상의 작업을 8개 데이터 리전에 걸쳐 중단 없이 이전하면서 SSH 의존성을 제거했다. - 결과적으로 보안 강화뿐 아니라 Kubernetes 기반 실행 환경, AWS 계정 분리, 표준화된 모니터링으로 나아갈 기반을 마련했다. 실용적으로는 원격 서버에 직접 접속해 명령을 실행하기보다, 작업 ID·상태 조회·취소를 제공하는 서버 측 실행 모델을 사용하는 것이 바람직하다. 특히 기존 작업이 단순 CLI 스크립트라면 복잡한 신규 실행 서비스를 만들기 전에 YARN Distributed Shell처럼 기존 플랫폼의 표준 기능을 우선 검토할 수 있다.

원문 읽기(새 탭에서 열림)
slack4분 읽기큐레이션 요약

장기 실행 에이전트 애플리케이션의 컨텍스트 관리

장시간 실행되는 멀티 에이전트 시스템은 모든 대화 기록을 그대로 누적하면 컨텍스트 윈도우 한계와 응답 품질 저하에 직면한다. Slack은 이를 해결하기 위해 Director의 구조화된 Journal, Critic의 신뢰도 주석 Review, 시간순 Timeline이라는 세 가지 컨텍스트 채널을 분리해 사용한다. 각 에이전트에 필요한 맥락만 제공함으로써 팀 전체의 일관성을 유지하면서도 과도한 정보 공유로 인한 창의성 저하와 확증편향을 줄이는 것이 핵심이다. ## 장시간 에이전트 시스템의 컨텍스트 문제 - 언어 모델 API는 상태가 없으므로, 호출 간 연속성을 유지하려면 전체 메시지 이력을 매번 전달해야 한다. - 에이전트 프레임워크는 일반적으로 메시지 기록을 누적하지만, 기록이 길어질수록 컨텍스트 윈도우가 빠르게 소진된다. - 컨텍스트 한도에 도달하기 전부터 응답 품질과 추론 능력이 저하될 수 있다. - 보안 조사처럼 수백 번의 추론 요청과 수 MB의 결과를 생성하는 작업에서는 단순한 대화 기록 누적만으로는 부족하다. - 멀티 에이전트 환경에서는 모든 정보를 공유하면: - 각 에이전트의 역할과 집중력이 흐려지고 - 기존 결론에 끌리는 확증편향이 커지며 - 독립적인 탐색과 창의적 추론이 억제될 수 있다. - 반대로 공유 정보가 너무 적으면 각 에이전트가 전체 조사 방향을 이해하지 못해 결과가 단절된다. ## 세 가지 컨텍스트 채널 Slack의 보안 조사 시스템은 Director가 조사 전체를 조율하고, 여러 Expert가 증거를 수집하며, Critic이 결과를 검토하는 구조다. - **Director’s Journal** - Director의 구조화된 작업 메모이자 장기 기억이다. - 조사 중 결정, 관찰, 사실, 가설, 미해결 질문 등을 기록한다. - **Critic’s Review** - Expert의 발견 사항을 검토하고 주석을 추가한 보고서다. - 각 결과의 신뢰도 점수를 포함해 어떤 증거를 얼마나 믿을지 판단하게 한다. - **Critic’s Timeline** - 여러 결과를 시간순으로 통합한 기록이다. - 사건의 진행 순서와 인과관계를 파악하도록 돕고, 신뢰도 점수도 함께 제공한다. - 세 채널은 서로 다른 목적을 가지며, 에이전트가 전체 메시지 이력 대신 역할에 맞는 맥락을 사용하도록 한다. ## Director’s Journal의 역할 Director는 어떤 질문을 던질지, 어떤 Expert를 호출할지, 언제 조사를 종료할지를 결정한다. 여러 단계와 라운드에 걸쳐 일관된 결정을 내리려면 이전에 무엇을 발견하고 판단했는지 기억해야 한다. - Journal은 Director가 사용하는 전용 journaling tool을 통해 업데이트된다. - 시스템 프롬프트는 Director가 Journal을 자주 갱신하고 짧은 메모 형태로 기록하도록 유도한다. - 기록의 목적은 완성된 보고서를 작성하는 것이 아니라, Director의 현재 사고 과정과 조사 상태를 유지하는 것이다. - 모든 에이전트는 현재 Journal 내용을 시간순으로 프롬프트에서 전달받는다. - 각 에이전트의 시스템 프롬프트에는 다음 내용이 설명된다. - Director의 역할 - 자신과 Director의 관계 - Journal의 목적 - Journal에 기록된 내용을 해석하는 방법 ## Journal의 기록 유형 Journal은 메모를 여섯 가지 유형으로 구분한다. - **decision**: 전략적 선택 - 예: 네트워크 활동보다 인증 이상 징후에 집중하기로 결정 - **observation**: 관찰된 패턴 - 예: 성공적인 인증 전에 여러 번의 로그인 실패가 발생 - **finding**: 확인된 사실 - 예: 사용자가 기존 이력에 없는 IP에서 인증 - **question**: 아직 해결되지 않은 질문 - 예: 의심스러운 활동 전후 중 언제 VPN 연결이 성립했는가 - **action**: 수행했거나 수행할 조치 - 예: Cloud Expert에게 EC2 인스턴스 활동 조사 요청 - **hypothesis**: 현재 검토 중인 가설 - 예: 계정 탈취보다 자격 증명 대입 공격에 가까운 패턴 추가로 각 항목에는 다음 정보를 포함할 수 있다. - 우선순위 - 후속 조치 목록 - 관련 증거 자료에 대한 인용 또는 참조 - 조사 단계(phase) - 라운드 번호 - 기록 시각 Journaling tool 자체는 복잡한 추론을 수행하지 않고 항목을 누적하는 역할만 담당한다. ## Journal을 통한 팀 정렬 Journal은 Director가 조사 방향을 유지하고 필요할 때 전략을 수정하도록 돕는다. - 조사 진행 상황을 관찰하고 측정할 수 있다. - 더 이상 유용하지 않은 조사 경로나 막다른 길을 식별할 수 있다. - 새 증거에 따라 가설과 조사 우선순위를 수정할 수 있다. - 다른 에이전트에게 공통된 조사 서사를 제공해 각자의 결과가 전체 조사와 연결되게 한다. - Director가 내린 결정과 아직 남은 질문을 명시적으로 전달해, Expert들이 중복되거나 무관한 작업을 수행하는 것을 줄인다. ## 실제 Journal 기록의 특징 글의 예시에서는 커널 모듈 로딩으로 탐지된 보안 알림을 조사한다. 실제로는 개발자가 개발 환경에서 패키지를 설치하던 중 발생한 오탐이었다. - 이벤트가 직접적인 `modprobe` 실행이 아니라 패키지 설치 과정의 스크립트였다는 점을 기록한다. - 관련 Expert 영역으로 엔드포인트 텔레메트리, 사용자 권한, 호스트 설정, 사용자 행동 패턴을 지정한다. - 개인 개발자 워크스테이션과 사용자 세션으로 보이는 단서를 정리한다. - 탐지 규칙이 실제 모듈 로딩이 아니라 스크립트 경로의 `"kmod"` 문자열에 반응했을 가능성을 제시한다. - 개발 환경에서 root 권한이 의도적으로 허용된다는 사실을 확인한다. - 프로세스 부모 관계, 엔드포인트 쿼리, SSH 인증서 로그 등을 추가로 검증할 대상으로 남긴다. - 조사 중간 결론으로 해당 이벤트가 정상적인 시스템 관리 활동에 의한 오탐일 가능성을 기록한다. 실무적으로는 전체 대화 로그를 무제한 보존하기보다, 역할별로 필요한 정보를 구조화하고 요약하는 방식이 적합하다. 특히 Director의 Journal에는 결정·근거·미해결 질문을 명시하고, Critic의 결과에는 신뢰도와 시간 순서를 함께 관리하면 장기 실행 에이전트의 일관성과 독립적인 탐색을 동시에 확보할 수 있다.

원문 읽기(새 탭에서 열림)
slack3분 읽기큐레이션 요약

커스텀에서 오픈으로: Prometheus를 활용한 확장 가능한 네트워크 프로빙 및 HTTP/3 준비성

Slack은 HTTP/3 도입 과정에서 기존 모니터링 도구가 QUIC/UDP 기반 엔드포인트를 측정하지 못하는 관측성 공백을 발견했다. 이를 해결하기 위해 Prometheus Blackbox Exporter에 `quic-go` 기반 HTTP/3 프로빙 기능을 추가하고 오픈소스로 공개했다. 그 결과 HTTP/1.1, HTTP/2, HTTP/3를 Grafana에서 통합 관찰하고 더 정확한 알림과 장애 분석이 가능해졌다. ### 기존 모니터링 도구의 한계 - Slack은 AWS Availability Zone 간 내부 트래픽과 인터넷에서 인프라로 유입되는 외부 트래픽을 상용 SaaS 및 자체 도구로 측정해 왔다. - HTTP/3는 TCP 대신 UDP 기반의 QUIC 프로토콜을 사용한다. - 기존 SaaS 관측성 도구 대부분은 HTTP/3 프로빙을 기본 지원하지 않았다. - 핵심 모니터링 도구인 Prometheus Blackbox Exporter(BBE)에도 QUIC 네이티브 지원이 없었다. - 수십만 개의 HTTP/3 엔드포인트를 측정할 수 없어 HTTP/2로의 회귀, 실제 왕복 시간(RTT), 클라이언트 관점의 성능 변화를 파악하기 어려웠다. ### `quic-go` 기반 HTTP/3 프로브 구현 - 인턴 Sebastian Feliciano가 BBE에 QUIC 지원을 구현하고 오픈소스로 기여했다. - Go용 QUIC 라이브러리로 널리 사용되는 `quic-go`를 선택했다. - HTTP/3 전송 계층을 다음과 같이 구성해 기존 HTTP 클라이언트에 연결했다. ```go http3Transport := &http3.Transport{ TLSClientConfig: tlsConfig, QUICConfig: &quic.Config{}, } client = &http.Client{ Transport: http3Transport, } ``` - BBE의 기존 설정 방식과 아키텍처를 유지해 새로운 프로브도 기존 기능과 조합할 수 있도록 설계했다. - 이를 통해 HTTP/3 엔드포인트에 대해 설정 가능한 Prometheus 프로브가 제공됐다. ### 오픈소스 기여와 사내 통합 - 새로운 기능을 Prometheus BBE에 upstream 기여해 다른 조직도 사용할 수 있게 했다. - 오픈소스 PR의 병합을 기다리는 동안, Slack은 새 기능을 활용하는 사내 프로빙 시스템도 별도로 설계했다. - 결과적으로 외부 공개 기능과 Slack 인프라에 맞춘 운영 시스템을 함께 확보했다. ### 통합 관측성과 운영 개선 - Grafana에서 HTTP/1.1, HTTP/2, HTTP/3 지표를 하나의 화면에서 확인할 수 있게 됐다. - 프로토콜별 성능을 비교하고 다른 텔레메트리와 상관관계를 분석하기 쉬워졌다. - HTTP/3 엔드포인트의 상태와 성능을 기반으로 더 정확하고 신뢰성 높은 알림을 만들 수 있게 됐다. - 장애 발생 시 관련 지표를 한곳에서 확인해 원인 분석과 디버깅 속도를 높였다. ### 향후 확장 방향 - **SNI 라우팅 테스트** - 공유 IP를 사용하는 CDN이나 멀티테넌트 로드밸런서에서 요청한 호스트명이 올바른 백엔드로 라우팅되는지 검증한다. - 올바른 TLS 인증서가 반환되는지도 확인해 잘못된 라우팅을 방지할 수 있다. - **종단 간 네트워크 경로 시각화** - 단순한 성공/실패 확인을 넘어 모니터링 에이전트부터 서비스까지의 네트워크 홉을 시각화한다. - 지연 증가나 패킷 손실이 어느 구간에서 발생했는지 파악할 수 있다. ### 실무적인 시사점 - 새로운 프로토콜이나 인프라로 마이그레이션하기 전에 먼저 관측성을 확보해야 한다. - 기존 도구에 기능이 없을 때 직접 구현하고 오픈소스로 공유하면 조직과 커뮤니티 모두의 비용을 줄일 수 있다. - HTTP/3 도입을 검토하는 팀이라면 Prometheus Blackbox Exporter의 QUIC 프로브를 활용해 마이그레이션 전후 성능과 장애를 지속적으로 비교하는 것이 좋다.

원문 읽기(새 탭에서 열림)
slack3분 읽기큐레이션 요약

슬랙이 알림 기능을 어떻게 다시 만들었나 📣

Slack은 알림이 많아서가 아니라 사용자가 알림 설정을 이해하고 통제하기 어려워서 “소음”을 느낀다고 진단했다. 이에 데스크톱과 모바일의 서로 다른 설정 체계를 하나의 모델로 통합하고, 활동 알림과 푸시 알림을 분리했다. 레거시 호환성과 롤백 가능성을 고려한 읽기 시점 마이그레이션, 자동 저장, 클라이언트 간 상태 동기화를 통해 더 예측 가능하고 차분한 알림 경험을 구축했다. ## 알림 소음의 근본 원인 - Slack에서 알림 과부하는 고객 불만의 주요 원인이며, 고객 경험 관련 문의의 상위 3개 요인에 포함됐다. - 참여한 채널 수가 많을수록 사용자는 알림 동작을 더 혼란스럽고 압도적으로 느꼈다. - 문제는 단순히 알림의 양이 아니라, 여러 해에 걸쳐 누적된 레거시 아키텍처에도 있었다. - 데스크톱과 모바일이 서로 다른 선호도 모델을 사용했다. - 모바일의 `nothing`과 데스크톱의 `Off`가 같은 의미가 아니었다. - 설정을 바꿔도 실제 결과를 예측하기 어려웠다. - 알림 대상과 전달 방식이 강하게 결합되어 있었다. - 푸시 알림을 줄이면 인앱 활동 확인까지 포기해야 했다. - 클라이언트 간 설정 동기화가 불안정해 데스크톱과 모바일에서 서로 다른 알림이 발생하거나 설정을 반복해야 했다. - 고급 기능이 여러 메뉴에 흩어져 있어 파워 유저도 전체 설정 구조를 파악하기 어려웠다. ## 하나의 알림 모델로 통합 Slack은 UI만 개편하지 않고 알림의 동작 방식 자체를 재설계했다. - 채널 알림을 세 가지 선택지로 단순화했다. - 모든 새 게시물 - 멘션 - 음소거 - 데스크톱과 모바일의 푸시 알림을 독립적인 켜기/끄기 옵션으로 통합했다. - 모바일에도 “모든 읽지 않은 항목 배지 표시” 같은 고급 제어 기능을 제공했다. - 데스크톱과 모바일의 전역 설정 구조와 문구를 일관되게 정비했다. - 단순화된 선호도 로직을 사용해 여러 클라이언트에서 동일한 상태를 유지하도록 개선했다. ## 선호도 데이터 마이그레이션 기존에는 데스크톱과 모바일 설정이 각각 알림 대상과 푸시 전달을 함께 결정했다. ```text 기존 desktop: everything | mentions | nothing mobile: everything | mentions | nothing ``` 새 모델에서는 활동과 푸시를 분리했다. ```text 변경 후 desktop: everything | mentions desktop_push_enabled: true | false mobile: everything | mentions | nothing ``` - 데스크톱의 `desktop_push_enabled`를 새로 도입해 푸시 알림만 별도로 제어했다. - 기존 사용자의 데이터베이스 값을 일괄적으로 직접 변경하지 않았다. - 잘못된 마이그레이션이나 롤백 문제를 피하기 위한 선택이다. - 새 설정을 기존 값에 기반해 백필했다. - 읽기 시점에 레거시 `Off`를 새로운 의미의 `Mentions + 푸시 비활성화`로 해석했다. - 사용자는 기존과 동일한 경험을 유지하면서도 새로운 분리형 알림 구조를 사용할 수 있었다. - 결과적으로 인앱 배지와 활동 알림은 계속 확인할 수 있고, 실제 방해가 되는 푸시만 별도로 끌 수 있게 됐다. ## 자동 저장과 “무엇을 받을지”와 “어떻게 받을지”의 분리 기존 알림 모달은 변경할 때마다 사용자가 `Save` 버튼을 눌러야 했다. - 저장을 잊으면 설정이 적용되지 않아 사용자가 알림 시스템이 고장 났다고 오해할 수 있었다. - 새 모달은 자동 저장을 적용해 변경 즉시 설정이 반영된다. - 알림 설정을 다음 두 축으로 분리했다. - 어떤 활동을 받을 것인가 - 어떤 방식으로 전달받을 것인가 - 예를 들어 모든 활동을 인앱에서 확인하되, 푸시는 멘션에 대해서만 받는 구성이 가능해졌다. - 데스크톱과 모바일 UI에는 재사용 가능한 React 컴포넌트를 활용해 일관성을 높였다. - 기존 모바일 전용 레거시 UI 코드도 대체해 플랫폼별 동작 차이를 줄였다. ## 크로스플랫폼 일관성 - 프로젝트는 수백 개의 댓글이 달린 기술 논의와 제품·디자인·프론트엔드·백엔드·모바일 팀 간 조율을 필요로 했다. - 핵심 목표는 단순히 같은 화면을 만드는 것이 아니라, 어떤 클라이언트에서 설정해도 동일한 상태와 의미를 갖게 하는 것이었다. - 이 구조를 통해 사용자는 데스크톱에서 바꾼 설정이 모바일에서 다르게 동작하는 문제를 덜 겪게 됐다. Slack의 접근 방식은 알림을 무조건 줄이는 대신, 활동 알림과 푸시 알림을 분리하고 설정 의미를 명확히 하는 데 초점을 둔다. 비슷한 시스템을 설계할 때도 레거시 값을 즉시 덮어쓰기보다 읽기 시점 호환성, 점진적 백필, 독립적인 설정 축, 자동 저장을 활용하는 것이 안전하고 사용자 혼란도 줄일 수 있다.

원문 읽기(새 탭에서 열림)
slack5분 읽기큐레이션 요약

에이전트를 활용한

Slack 보안 엔지니어링 팀은 수십억 건의 이벤트를 처리하는 보안 탐지 시스템의 알림 조사를 AI 에이전트로 효율화했다. 단일 프롬프트에 복잡한 조사 절차를 모두 맡기는 대신, 목적과 출력 형식이 명확한 여러 모델 호출을 연결해 조사 과정을 통제하는 구조를 택했다. Director·Expert·Critic 에이전트가 협력하고 서로의 결과를 검증함으로써 조사 품질의 일관성, 근거 교차검증, 환각 완화를 달성하려는 접근이다. ## 단일 프롬프트 프로토타입의 한계 - 초기 프로토타입은 약 300단어의 프롬프트와 MCP 서버, 코딩 에이전트 CLI를 실행 환경으로 사용했다. - 프롬프트는 다음 다섯 부분으로 구성됐다. - **Orientation**: 보안 분석가 역할 정의 - **Manifest**: 사용할 데이터 소스 설명 - **Methodology**: 조사 절차 지시 - **Formatting**: 조사 결과를 Markdown 보고서로 출력 - **Classification**: 대응 등급 분류 - MCP의 stdio 모드 서버를 통해 일부 보안 데이터 소스를 안전하게 도구 호출 방식으로 노출했다. - 어떤 경우에는 여러 데이터 소스의 증거를 훌륭하게 연결했지만, 다른 경우에는 충분한 검증 없이 편리하거나 잘못된 결론으로 빠르게 진행했다. - “가정을 의심하라”, “여러 출처로 검증하라”와 같은 지침을 프롬프트에 추가했지만, 프롬프트는 가이드라인일 뿐 세부적인 실행 흐름을 강제하기에는 한계가 있었다. ## 단계별 모델 호출과 구조화된 출력 - 복잡한 조사 전체를 하나의 프롬프트로 처리하지 않고, 조사 과정을 여러 개의 단순한 작업으로 분해했다. - 각 작업은 다음 요소를 갖는다. - 명확하게 정의된 단일 목적 - 애플리케이션이 해석하기 쉬운 구조화된 출력 - 다음 단계로 전달할 제한된 컨텍스트 - 각 모델 호출 결과는 JSON 스키마로 제한할 수 있는 구조화된 출력 형식으로 생성된다. - 구조화된 출력은 작업 간 계약 역할을 하므로, “증거를 의심하라” 같은 추상적인 지침도 독립적인 검토 작업으로 분리할 수 있다. - 다만 구조화된 출력에도 주의점이 있다. - 스키마가 지나치게 복잡하면 모델 실행 자체가 실패할 수 있다. - 모델이 형식을 형식적으로만 충족하거나, 여전히 환각을 포함할 수 있다. - 이 방식의 핵심 효과는 모델의 행동을 프롬프트 수준이 아니라 애플리케이션의 워크플로 수준에서 통제할 수 있다는 점이다. ## 페르소나 기반 조사 설계 - Slack은 메타 프롬프트와 다중 페르소나 자기협업 관련 연구, 보안 테이블톱 훈련에서 설계 아이디어를 얻었다. - 하나의 모델 호출 안에서 여러 페르소나를 연기하게 하는 대신, 각 페르소나를 독립적인 모델 호출로 구현했다. - 각 에이전트와 작업의 조합은 별도의 구조화된 출력 형식을 가지며, 애플리케이션이 호출 순서와 컨텍스트 전달을 orchestration한다. - 독립 호출 구조에서는 에이전트별로 모델 버전, 프롬프트, 지시사항, 도구, 출력 형식을 다르게 설정할 수 있다. ## Director·Expert·Critic 협업 구조 ### Director 에이전트 - 조사 전체를 시작부터 끝까지 진행하는 조사 책임자다. - 조사에 필요한 질문을 만들고 이를 도메인 전문가에게 전달한다. - 조사 진행 상황을 계획하고 정리하기 위해 저널링 도구를 사용한다. - 전문가의 결과와 Critic의 평가를 바탕으로 다음 조사 단계를 결정한다. ### Expert 에이전트 - 특정 도메인 지식과 데이터 소스를 담당한다. - Director의 질문에 답하기 위해 관련 도구를 호출하고 조사 결과를 생성한다. - 현재 네 종류의 전문가가 있다. - **Access**: 인증, 권한 부여, 경계 보안 서비스 - **Cloud**: 인프라, 컴퓨트, 오케스트레이션, 네트워킹 - **Code**: 소스 코드 및 구성 관리 분석 - **Threat**: 위협 분석과 위협 인텔리전스 데이터 - 각 전문가는 자신에게 필요한 데이터 소스에 집중하므로, 하나의 에이전트가 모든 영역을 무분별하게 조사하는 문제를 줄인다. ### Critic 에이전트 - 전문가 결과를 검토하는 메타 전문가다. - 사전에 정의한 평가 기준에 따라 각 발견 사항의 품질을 평가하고 정량화한다. - 전문가의 주장에 분석 내용을 추가하고, 각 발견 사항에 신뢰도 점수를 부여한다. - 가장 신뢰할 수 있는 결과를 바탕으로 타임라인을 구성해 Director에게 전달한다. - 전문가 그룹과 약한 적대적 관계를 형성함으로써 증거 해석의 편차와 환각을 완화한다. ## 반복형 조사 루프 - Director가 조사 질문을 제시한다. - 관련 Expert들이 각자의 데이터 소스를 조사해 발견 사항을 생성한다. - Critic이 발견 사항을 검토하고 신뢰도와 품질을 평가한다. - Critic은 중요한 결과를 선별하고 신뢰할 수 있는 증거를 이용해 사건 타임라인을 만든다. - Director는 검증된 발견 사항과 타임라인을 이용해 추가 조사가 필요한지, 다음 질문은 무엇인지 결정한다. - 이 루프를 통해 한 번의 응답으로 결론을 내리기보다, 질문·조사·검증·진행 결정이 반복되는 조사 프로세스를 구현한다. ## 지식 피라미드와 모델 비용 최적화 - 하위 단계에서는 도메인 전문가가 복잡한 데이터 소스를 직접 조회한다. - 이 과정은 도구 호출이 많고 반환된 데이터를 분석하는 데 많은 토큰이 필요하므로 상대적으로 비용이 높을 수 있다. - Critic은 전문가가 생성한 많은 결과를 검토해 중요하고 신뢰할 만한 발견 사항을 추린다. - 이후 상위 단계의 에이전트는 정제된 결과와 타임라인만 전달받아 더 높은 수준의 판단을 수행한다. - 이를 통해 모든 단계에서 가장 크고 비싼 모델을 사용하는 대신, 조사 단계별 요구 사항에 맞춰 모델을 선택할 수 있다. - 즉, 많은 원시 데이터를 처리하는 단계와 최종 판단을 내리는 단계를 분리해 비용과 성능을 함께 조정하는 구조다. ## 실용적인 설계 시사점 - 복잡한 보안 조사를 하나의 거대한 프롬프트에 담기보다, 목적이 명확한 작업과 구조화된 출력으로 분해하는 것이 안정적이다. - 에이전트 간 역할을 분리하고 독립적인 검토자를 두면 증거 검증과 환각 완화에 도움이 된다. - 데이터 소스별 전문 에이전트를 두면 각 모델이 불필요한 도구를 사용하거나 모든 영역을 피상적으로 조사하는 문제를 줄일 수 있다. - 모델 호출을 독립적으로 설계하면 작업별로 모델 크기, 도구, 프롬프트, 출력 스키마를 최적화할 수 있다. - 다만 구조화된 출력만으로 정확성이 보장되지는 않으므로, 다중 출처 검증과 별도 Critic 단계, 신뢰도 평가를 함께 구성하는 것이 중요하다.

원문 읽기(새 탭에서 열림)
slack4분 읽기큐레이션 요약

안드로이드 VPAT 여정

Slack은 2024년 대규모 UI 개편 이후 제3자 VPAT 평가를 진행하며 Android 전반의 접근성 문제를 발견했다. 단순한 색상 대비·이미지 라벨 문제뿐 아니라 오류 안내, 제목 구조, 입력 필드 라벨, 목록 개수, 드래그 앤 드롭 등 반복적인 문제가 확인되었고, 이를 공통 컴포넌트와 TalkBack 지원 개선으로 해결했다. 특히 시각적 UI를 추가하는 데 그치지 않고, 스크린 리더 사용자가 동일한 기능을 수행할 수 있도록 의미 구조와 대체 조작 방식을 제공하는 데 중점을 두었다. ## VPAT 평가와 Android 접근성 문제의 분류 - VPAT(Voluntary Product Accessibility Template)는 제품이 접근성 표준을 얼마나 충족하는지 설명해 고객의 구매 판단을 돕는 문서다. - Slack은 IA4 UI 개편 이후 2024년에 외부 접근성 전문 업체를 통해 VPAT 평가를 실시했다. - Android, iOS, 데스크톱에서 문제가 발견되었으며, Android에서는 다음과 같은 유형이 주요 이슈로 나타났다. - 오류 메시지가 스크린 리더에 전달되지 않음 - 제목이 제목 요소로 식별되지 않음 - 입력 필드에 영구적인 접근성 라벨이 없음 - 목록 항목 수가 잘못 안내됨 - 워크스페이스 순서 변경 기능이 드래그 앤 드롭에 의존함 - 취소선 정보가 스크린 리더에 전달되지 않음 - 오류를 색상만으로 표시함 - 키보드 탐색과 포커스 문제는 다수 보고되었지만, Android의 대형 화면 지원이 아직 제한적이어서 후속 과제로 남겼다. ## 오류 메시지의 스크린 리더 전달 - 잘못된 값을 입력한 뒤 “Next” 또는 제출을 누르면 오류가 화면에 표시되지만, TalkBack에는 오류 상태와 원인이 전달되지 않았다. - 오류 표시 방식은 크게 두 가지였다. - `OutlinedTextField` 바로 아래에 오류 메시지를 표시 - `SKBanner`를 이용해 오류 배너를 표시 - 두 경우 모두 TalkBack이 오류를 자동으로 읽지 않아 사용자가 화면을 직접 탐색해야 했다. - 해결 방법: - `OutlinedTextField`를 수정해 입력 필드에 포커스가 갔을 때 오류 상태와 메시지를 안내하도록 변경 - 오류 유형의 `SKBanner`도 오류 발생 시 스크린 리더가 내용을 읽도록 수정 ## 제목 구조와 페이지 탐색 개선 - 제목이 시맨틱하게 식별되지 않으면 스크린 리더 사용자가 페이지의 구조를 빠르게 파악하거나 제목 단위로 이동하기 어렵다. - Preferences와 같은 목록 내부에서 누락된 제목 요소를 찾아 수정했다. - 외부 업체는 상단 앱 바의 제목도 heading으로 지정할 것을 제안했지만, 다른 Android 앱과 표준 동작을 비교한 결과 일관된 Android 관행이 아니라고 판단해 해당 티켓은 종료했다. ## 입력 필드의 영구 라벨 문제 - 일부 입력 필드는 placeholder만 라벨로 사용했다. - 사용자가 텍스트를 입력하면 placeholder가 사라지므로, 인지적 어려움이 있는 사용자는 필드의 목적을 잊을 수 있다. - 메시지 입력 영역(AMI)은 공간 제약 때문에 이상적인 해결책을 적용하지 못했다. - 검색 필드에는 돋보기 아이콘을 추가했다. - 입력 전후에도 해당 필드가 검색용이라는 시각적 단서를 제공한다. - 작은 디자인 변경으로 입력 필드의 목적을 더 명확하게 만들었다. - 이 문제는 접근성 개선이 반드시 복잡한 기술적 변경을 요구하지 않으며, 적절한 시각적·의미적 단서만으로도 사용성을 크게 높일 수 있음을 보여준다. ## 목록 항목 수를 정확히 안내 - TalkBack의 “항상 목록 항목 수 말하기” 설정이 켜져 있으면 목록의 전체 항목 수가 안내된다. - Slack의 구형 Slack Kit(SK) Bottom sheet에서는 장식용 divider까지 목록 항목으로 계산됐다. - 실제 행이 5개이고 divider가 2개면 TalkBack이 “7개 항목이 있는 목록”이라고 안내했다. - 해결을 위해 `SKListAdapter`에 새로운 `SKListAccessibilityDelegate`를 도입했다. - 이 delegate는 접근성용 `CollectionInfo`를 덮어써 실제 의미 있는 목록 항목 수만 전달한다. ## 드래그 앤 드롭을 대체하는 워크스페이스 이동 방식 - 워크스페이스 전환기에서는 워크스페이스를 선택한 뒤 드래그해 순서를 변경해야 했다. - 손의 움직임이나 정교한 조작이 어려운 사용자는 이 기능을 수행하기 힘들거나 사용할 수 없었다. - 해결 방법: - 워크스페이스 전환기에 `Edit` 모드를 추가했다. - 편집 모드에서는 각 행에 6점 모양의 드래그 핸들을 표시해 이동 가능한 요소임을 명확히 했다. - TalkBack 사용자를 위해 사용자 지정 접근성 동작인 “앞으로 이동(Move before)”과 “뒤로 이동(Move after)”을 추가했다. - TalkBack 컨텍스트 메뉴의 세 손가락 탭 또는 `L`, `r` 제스처로 항목을 이동할 수 있게 했다. - 정렬이 끝나면 우측 상단의 “Done” 버튼을 눌러 편집 모드를 종료한다. - 시각적 드래그 UI와 스크린 리더용 명령형 조작을 함께 제공해 동일한 기능에 여러 접근 경로를 마련했다. ## 남은 접근성 개선 과제 - 취소선 정보가 스크린 리더에 전달되지 않는 문제와 오류를 색상만으로 표시하는 문제도 주요 이슈로 분류되었다. - 키보드 탐색과 포커스는 Android 태블릿 등 대형 폼 팩터에서 특히 중요하지만, Slack Android의 대형 화면 지원이 충분하지 않아 추가 검토 과제로 남았다. - 접근성 문제는 개별 화면의 수정만으로 끝나지 않고 공통 UI 컴포넌트와 접근성 메타데이터 처리 계층까지 개선해야 반복을 줄일 수 있다. 접근성을 개선할 때는 시각적 표시만 추가하지 말고, TalkBack이 오류·제목·목록 구조·상태 변화를 정확히 인식하는지 함께 검증해야 한다. 또한 드래그처럼 정밀한 동작이 필요한 기능에는 접근성 사용자 지정 동작이나 명시적인 편집 모드를 제공하는 것이 효과적이다.

원문 읽기(새 탭에서 열림)
slack4분 읽기큐레이션 요약

더 나은 소프트웨어를 만들기

빌드가 60분씩 걸리면 코드 변경에 대한 피드백이 늦어져 개발 생산성이 크게 떨어진다. Slack은 Bazel과 전통적인 성능 최적화 원칙인 캐싱·병렬화를 결합해 빌드 시간을 개선했다. 핵심은 빌드를 명확한 입력·출력 단위의 그래프로 모델링하고, 재사용 가능하고 병렬 실행 가능한 작은 작업으로 나누는 것이다. ## 빌드를 방향성 비순환 그래프로 모델링 - 백엔드와 프런트엔드는 서로 독립적으로 개발·배포될 수 있으며, 각각 필요한 소스 파일에만 의존한다. - 빌드 구성 요소와 배포 산출물 사이의 의존성은 방향성 비순환 그래프(DAG)로 표현된다. - 특정 Python 파일이 변경되면 백엔드만 다시 빌드하고, TypeScript 파일 변경 때문에 백엔드까지 재빌드하지 않도록 의존성을 정확히 정의할 수 있다. - 그래프로 빌드를 표현하면 애플리케이션 코드와 동일하게 다음 최적화를 적용할 수 있다. - 이미 수행한 작업의 결과를 저장해 다시 계산하지 않기 - 여러 컴퓨팅 자원에 작업을 분산해 동시에 처리하기 ## 캐싱을 통한 불필요한 작업 제거 - 캐시는 입력값과 결과값을 연결해 동일한 입력에 대한 작업을 한 번만 수행하도록 한다. - 예를 들어 `factorial(n)`은 입력 `n`에 따라 결과가 항상 같으므로 `functools.cache`를 적용할 수 있다. - 빌드 캐싱이 올바르게 작동하려면 작업이 다음 조건을 만족해야 한다. - **Hermetic**: 명시적으로 전달된 입력만 사용해 결과를 생성해야 한다. - **Idempotent**: 동일한 입력에 대해 항상 동일한 결과를 내야 한다. - 캐시 성능은 전체 호출 중 캐시에서 결과를 가져오는 비율인 캐시 적중률(hit rate)에 좌우된다. ## 작업 단위를 작게 나눠 캐시 적중률 높이기 - 이미지 목록 전체와 변환 목록 전체를 입력으로 받는 `process_images()`에 캐시를 적용하면, 이미지 하나만 추가돼도 전체 입력이 바뀐 것으로 간주된다. - 이 방식은 캐시 키가 지나치게 크고 거칠어, 작은 변경에도 모든 작업을 처음부터 다시 수행해야 한다. - 대신 이미지 하나에 변환 하나를 적용하는 `process_image(image, transform)`처럼 더 작은 단위에 캐시를 적용할 수 있다. - 그러면 새로 추가되거나 변경된 이미지·변환 조합만 처리하고, 이미 계산한 조합은 캐시에서 재사용할 수 있다. - 상위 수준 API는 유지하면서 내부 작업 단위만 세분화하는 방식이 성능과 재사용성을 높인다. ## 병렬화를 통한 작업 분산 - 이미지 처리처럼 서로 독립적인 작업은 여러 CPU 코어나 프로세스, 네트워크상의 다른 컴퓨팅 노드로 분산할 수 있다. - 병렬 실행을 위해서는 다음 조건이 필요하다. - 작업의 입력과 출력이 명확하게 정의되어야 한다. - 입력과 출력을 스레드·프로세스·네트워크 경계 너머로 전달할 수 있어야 한다. - 작업이 어떤 순서로 완료되거나 실패할지 보장할 수 없으므로 결과 처리 규칙을 명확히 해야 한다. - 예시의 스레드 기반 구현은 이미지 결과가 입력 순서와 다르게 반환될 수 있다. - 결과 순서 보장 여부는 API 계약의 일부이며, 사용자가 허용할 수 있는 동작인지 사전에 결정해야 한다. ## 병렬화에서도 작업 단위의 크기가 중요 - 작업 수가 적고 각각의 작업이 너무 크면 사용 가능한 컴퓨팅 자원에 충분히 분산하지 못한다. - 반대로 작업을 지나치게 잘게 나누면 작업 전달·관리 오버헤드가 커질 수 있다. - 적절한 작업 크기와 개수의 균형은 문제마다 다르므로 API와 빌드 단위를 설계할 때 함께 고려해야 한다. - 캐싱과 병렬화 모두 입력·출력이 명확하고 독립적인 작은 작업 단위를 필요로 한다. ## Bazel 빌드로 원칙 확장 - Bazel은 빌드를 방향성 비순환 그래프 형태의 **타깃(target)** 으로 정의한다. - 각 타깃에는 다음 세 가지 핵심 요소가 있다. - 빌드 단계의 입력이 되는 의존 파일 - 빌드 단계가 생성하는 출력 파일 - 입력을 출력으로 변환하는 명령어 - 이러한 명시적 정의를 바탕으로 변경된 타깃만 다시 빌드하고, 결과를 캐시하며, 서로 독립적인 타깃을 병렬 실행할 수 있다. - 따라서 빌드 시스템의 성능 개선은 단순히 더 빠른 도구를 도입하는 문제가 아니라, 코드 성능 최적화와 마찬가지로 작업의 경계와 의존성을 설계하는 문제다. 빌드 시간을 줄이려면 먼저 의존성과 입출력을 명확히 정의하고, 변경 범위가 작은 작업 단위로 빌드를 나누는 것이 좋다. 그 위에 hermetic·idempotent한 작업을 캐시하고 독립 작업을 병렬화하면, 대규모 프로젝트에서도 불필요한 재빌드를 줄이고 개발자 피드백 속도를 높일 수 있다.

원문 읽기(새 탭에서 열림)
slack3분 읽기큐레이션 요약

셰프 인프라 개선: 방해받지 않는 안전

Slack은 Chef Policyfiles로 전환하는 대신, 기존 cookbook과 role을 유지하면서 EC2 프로비저닝 구조를 개선하는 방식을 선택했다. 단일 프로덕션 환경을 `prod-1`부터 `prod-6`까지 분리하고, 카나리와 단계적 릴리스 트레인을 도입해 잘못된 변경의 영향 범위를 줄였다. 그 결과 대규모 확장이나 배포 중에도 문제를 조기에 발견하고 안전하게 롤백·수정할 수 있는 경로를 마련했다. ## Policyfiles 대신 기존 구조 개선 - Policyfiles를 도입하면 roles와 environments를 대체하고 여러 팀의 cookbook을 수정해야 했다. - 장기적으로는 안전성이 높아질 수 있지만, 단기적으로는 수십 개 팀의 대규모 작업과 새로운 변경 위험이 발생했다. - Slack은 기존 cookbook과 role을 변경하지 않고 EC2 프레임워크를 보강하는 방향을 택했다. ## 단일 프로덕션 환경의 위험 - 기존에는 모든 인스턴스가 하나의 `production` Chef environment를 공유했다. - 인스턴스별 cron 작업을 가용 영역(AZ)마다 분산해 Chef 실행 시점을 staggered 방식으로 조정했다. - 이 방식은 잘못된 변경이 전체 노드에 동시에 적용되는 것을 막아 주었지만, 새로 생성된 노드는 즉시 최신 변경을 가져갔다. - 따라서 대규모 scale-out 중 잘못된 cookbook 버전이 수십~수백 개의 새 노드에 한꺼번에 적용될 수 있었다. ## `prod-1`~`prod-6` 환경 분리 - 단일 production environment를 다음과 같이 6개 bucket으로 나눴다. - `prod-1` - `prod-2` - `prod-3` - `prod-4` - `prod-5` - `prod-6` - 서비스 팀은 계속 인스턴스를 “prod”로 실행하지만, 실제 Chef environment는 인스턴스의 AZ에 따라 결정된다. - 노드가 여러 환경에 균등하게 분산되므로 하나의 변경이 전체 프로덕션에 미치는 blast radius가 줄어든다. - 각 environment를 독립적으로 업데이트할 수 있어 특정 AZ 그룹만 대상으로 변경을 검증할 수 있다. ## Poptart Bootstrap의 역할 - Slack의 기본 AMI에는 부팅 시 실행되는 `Poptart Bootstrap` 도구가 포함되어 있다. - 주요 역할은 다음과 같다. - Chef node object 생성 - 필요한 DNS 레코드 설정 - 부팅 성공·실패 결과를 Slack 채널에 알림 - 환경 분리를 위해 노드의 AZ ID를 검사하고 해당 노드를 `prod-1`~`prod-6` 중 하나에 자동 배정하도록 확장했다. - 서비스 팀이 별도의 프로비저닝 방식을 학습하거나 cookbook을 수정하지 않아도 인프라 구조 변경을 적용할 수 있었다. ## 카나리 환경 `prod-1` - `prod-1`은 카나리 프로덕션 환경으로 사용된다. - 새 cookbook 변경이 있으면 매시간 최신 버전을 배포한다. - sandbox와 dev를 거친 변경을 실제 프로덕션 환경에서 작은 규모로 먼저 실행한다. - 모든 production 환경을 통과한 뒤에야 테스트하는 방식보다, 변경이 도입된 시점과 장애 발생 시점의 거리가 짧아 원인 추적이 쉽다. - 누적된 대규모 변경이 아니라 비교적 작은 단위의 artifact를 검증할 수 있다. ## `prod-2`~`prod-6`의 릴리스 트레인 - `prod-2`부터 `prod-6`까지는 순차적인 release train 방식으로 업데이트된다. - 새 버전을 `prod-2`에 배포하기 전, 기존 버전이 `prod-2`에서 `prod-6`까지 성공적으로 진행됐는지 확인한다. - 각 환경의 배포가 완료되어야 다음 단계가 진행되므로 회귀 문제가 전체 프로덕션으로 확산되는 것을 방지한다. - 여러 production environment가 항상 일정한 버전 순서를 유지하도록 설계되어 있다. ## 시간 기반 배포 흐름 - 매시 정각에 최신 cookbook 변경을 sandbox에 반영한다. - 이후 Kubernetes CronJob이 dev 환경으로 변경을 진행한다. - 매시 30분부터 production rollout이 시작된다. - 예를 들어 artifact A가 생성되면: - 정각: sandbox와 dev가 A로 업데이트 - 30분: `prod-1`이 A를 받아 카나리 테스트 - 이후: `prod-2`부터 `prod-6`까지 단계적으로 A를 적용 - 그 사이 새 변경으로 artifact B, C가 생성되더라도 기존 릴리스 트레인의 진행 상태를 고려해 순차적으로 배포한다. 실용적으로는 기존 배포 시스템을 전면 교체하기보다, 환경 분리·카나리·단계적 rollout처럼 변경의 영향 범위를 줄이는 장치를 먼저 도입하는 것이 효과적이다. 특히 대규모 인프라에서는 새 노드가 어떤 버전을 자동으로 받는지와, 실패한 변경이 어디까지 확산될 수 있는지를 별도로 통제해야 한다.

원문 읽기(새 탭에서 열림)
slack4분 읽기큐레이션 요약

안전한 배포: 변경

Slack은 고객 영향의 대부분(73%)이 배포를 비롯한 Slack 내부 변경에서 발생한다는 분석을 바탕으로 Deploy Safety Program을 시작했다. 이 프로그램은 자동 감지·복구, 영향 범위 제한, 안전장치와 문화 개선을 통해 고객 영향 시간을 줄이는 것을 목표로 했으며, 2025년 1월에는 정점 대비 고객 영향 시간이 90% 감소했다. 핵심은 특정 배포 시스템만 엄격하게 관리하는 대신, 모든 배포 방식에 반복 적용 가능한 안전 패턴을 구축하면서 개발 속도도 유지하는 것이다. ## 변화가 안정성에 미치는 영향 - Slack이 고객 업무에서 더욱 중요한 제품이 되면서 안정성에 대한 기대 수준이 높아졌다. - 고객 대상 장애의 73%가 Slack 내부 변경으로 발생했으며, 특히 코드 배포가 주요 원인이었다. - 장애 영향은 시스템마다 달랐고, 고객이 사용하는 기능에 따라 피해 정도도 달라졌다. - Slack에는 수백 개의 내부 서비스와 여러 배포 시스템이 있어, 단일한 배포 방식만 개선해서는 문제를 해결하기 어려웠다. - 기존에는 개별 서비스나 배포 시스템에 수동 절차를 추가하는 방식이 많았지만, 이는 개발 속도와 엔지니어링 사기를 떨어뜨렸다. - 고객은 약 10분을 넘는 중단을 단순한 “일시적 문제”가 아닌 심각한 장애로 인식하는 경향이 있었다. ## Deploy Safety의 목표 초기에는 중요도가 높은 서비스 전체를 대상으로 다음과 같은 North Star 목표를 세웠다. - 배포로 인한 영향 시간 단축 - 자동 감지 및 복구: 10분 이내 - 수동 감지 및 복구: 20분 이내 - 영향 심각도 감소 - 전체 플릿의 10%에 도달하기 전에 문제가 있는 배포 감지 - 개발 속도 유지 - 안정성을 높이되 변화와 혁신의 속도를 희생하지 않음 이 목표는 이후 모든 배포 시스템과 프로세스에 적용되는 Deploy Safety Manifesto로 확장됐다. 단순한 운영 절차가 아니라 자동화, 배포 안전장치, 조직 문화의 변화를 함께 추진한 것이 특징이다. ## 고객 영향 시간을 측정하는 지표 Slack은 프로그램의 성과를 측정하기 위해 다음 지표를 정의했다. - **고심각도 및 일부 중간 심각도 변경 유발 장애로 인한 고객 영향 시간** - 장애 심각도는 현재 또는 예상되는 고객 영향을 나타내지만, 실제 최종 영향과 항상 일치하지는 않는다. - 따라서 중간 심각도 장애는 실제 고객 영향 수준을 기준으로 별도 선별해야 했다. - 이 지표는 고객 감정을 직접 측정하는 값이 아니라, 고객 경험을 추정하는 실용적인 대리 지표다. Slack은 다음 세 요소 사이의 연결이 완벽하지 않다는 점도 인정한다. - 고객의 실제 만족도 - Deploy Safety 프로그램 지표 - 개별 프로젝트 지표 따라서 지표를 설계할 때 결과를 측정할 수 있는지, 무엇을 측정하는지 명확한지, 주관적 판단이 일관적인지, 실제 고객 피드백과 계속 비교되는지를 중요하게 봤다. ## 투자할 프로젝트를 고르는 방법 프로그램 초기에는 어떤 프로젝트가 가장 큰 효과를 낼지, 효과가 언제 나타날지 알기 어려웠다. 장애 데이터는 과거 결과를 보여주는 후행 데이터였지만 고객은 이미 현재 문제를 겪고 있었기 때문이다. 이에 따라 Slack은 다음과 같은 투자 전략을 사용했다. - 초기에는 여러 영역에 폭넓게 투자하고 빠르게 실행 - 이미 고객 피해가 확인된 영역을 우선 개선 - 성과가 확인된 프로젝트와 패턴에 추가 투자 - 효과가 낮은 영역의 투자는 축소 - 결과에 따라 바뀔 수 있는 짧고 유연한 로드맵 운영 프로젝트는 주로 다음 중 하나 이상의 목표에 기여하도록 설계했다. - 배포 과정에서 문제를 더 일찍 감지 - 자동 복구 시간 단축 - 수동 복구 시간 단축 - 격리 경계를 설계해 장애의 확산 범위와 심각도 축소 ## Webapp 배포 개선 사례 변경 유발 장애의 가장 큰 원인으로 Webapp backend가 지목되면서 단계적인 개선이 진행됐다. - 자동 메트릭 모니터링 구축 - 자동 알림과 수동 롤백으로 고객 영향 여부 검증 - 자동 배포 및 자동 롤백 도입 - 자동 롤백을 통해 고객 영향 시간을 10분 이하로 유지하는 성과 확인 - 추가 메트릭 모니터링과 수동 롤백 최적화 - Frontend 수동 롤백 기능 추가 - 중앙 집중식 배포 오케스트레이션 시스템으로 패턴 확대 - Slack Bedrock과 Kubernetes를 넘어 여러 배포 시스템에 메트릭 기반 배포와 자동 복구 적용 이 과정을 통해 Webapp backend와 frontend, 일부 인프라 배포가 훨씬 안전해졌으며 분기별로 계속 개선되는 결과를 보였다. ## 반복 가능한 안전 패턴 Slack의 접근 방식은 처음부터 완벽한 시스템을 설계하는 것이 아니었다. - 문제를 해결할 수 있는 작은 프로젝트를 먼저 시도 - 실제 고객 영향과 지표 변화를 통해 효과 검증 - 성공한 방식을 다른 서비스와 배포 시스템에 복제 - 결과가 낮은 영역은 투자를 줄이고 새로운 접근을 시도 즉, Deploy Safety는 하나의 도구나 배포 시스템을 도입하는 프로젝트가 아니라, 측정과 실험을 반복해 조직 전체에 안전한 변경 방식을 확산하는 프로그램이다. 실무적으로는 모든 배포를 수동 승인으로 막기보다, 고객 영향과 직접 연결된 메트릭을 기반으로 조기 감지·자동 롤백·영향 범위 제한을 구축하는 것이 효과적이다. 또한 안정성 지표를 정기적으로 실제 고객 피드백과 비교하고, 효과가 입증된 안전 패턴을 다른 시스템에 재사용해야 개발 속도와 안정성을 함께 확보할 수 있다.

원문 읽기(새 탭에서 열림)
slack4분 읽기큐레이션 요약

슬랙의 이상 이벤트 대응 체

Slack은 탐지에 그치지 않고 의심스러운 사용자 행동이 발생한 즉시 세션을 종료하는 **Anomaly Event Response(AER)**를 구축했다. AER는 실시간 분석과 자동 대응을 결합해 침해 탐지부터 대응까지의 시간을 며칠 또는 몇 시간에서 수분으로 줄이고, 데이터 유출이나 공격 체인의 진행을 조기에 차단한다. Enterprise Grid 고객은 별도 보안 도구나 인력 없이 기본 기능으로 사용할 수 있으며, 필요하면 기존 보안 시스템과 함께 운영할 수 있다. ## 탐지와 대응 사이의 공백 - Slack은 매주 수천만 명이 사용하고 매일 수십억 건의 상호작용이 발생하는 협업 플랫폼이다. - Enterprise 고객에게는 사용자의 플랫폼 활동을 기록하는 감사 로그를 제공한다. - `anomaly` 감사 로그는 다음과 같은 비정상 행위를 고급 분석으로 식별한다. - 비정상적인 로그인 - 악성 코드 업로드 - 예상치 못한 데이터 전송 - 기타 워크스페이스별 이상 활동 - 기존 감사 로그는 위협을 알려주는 조기 경보 역할을 하지만, 실제 대응을 위해서는 보안 담당자의 검토나 제3자 보안 솔루션 연동이 필요하다. - AER는 이 탐지-대응 간극을 자동화해, 고객이 이상 징후를 확인하기 전에 관련 사용자 세션을 종료한다. ## AER의 설계 철학 AER는 모든 유형의 위협을 다루기보다 여러 조직에서 공통적으로 발생할 가능성이 높은 이상 행위에 우선순위를 두었다. - Tor 출구 노드를 통한 Slack 접속 - 데이터 유출을 암시할 수 있는 과도한 다운로드 - Slack 기본 기능이 아닌 자동화 도구를 이용한 데이터 스크래핑 - 세션 지문(session fingerprint) 불일치 - 비정상적인 API 호출량 또는 호출 패턴 - 표준적이지 않거나 가상 환경을 나타내는 예상 밖의 사용자 에이전트 조직마다 정상적인 사용 패턴과 위험 수준이 다르므로, 고객은 탐지 유형별로 대응 방식을 선택할 수 있다. - 특정 이상 이벤트가 발생하면 사용자 세션을 종료 - 이벤트는 기록하되 자동 대응은 하지 않음 - 알림 수신 여부와 수신 대상 설정 - 조직 기본 소유자 - 보안 관리자 - 이메일 및 Slack 알림 설정은 **Tools and Settings → Organization settings → Security → Security Settings → Anomaly Event Response Settings**에서 변경한다. ## AER의 전체 아키텍처 AER는 실시간 탐지, 비동기 작업 처리, 알림 전달을 분리한 다중 계층 구조로 설계됐다. - **탐지 엔진** - Slack에서 발생하는 하루 수십억 건의 이벤트를 감시한다. - 규칙 기반 휴리스틱과 동적 임계값을 함께 사용한다. - **의사결정 프레임워크** - 의심스러운 행동이 감지될 때 생성된 감사 이벤트의 페이로드를 검증한다. - 해당 이벤트가 지원 대상 이상 유형인지, 고객 설정상 자동 대응해야 하는지 판단한다. - **응답 오케스트레이터** - 조건을 충족한 사용자 세션을 종료한다. - 대응 결과를 감사 로그에 남긴다. - 고객이 설정한 경우 조직 담당자에게 알림을 보낸다. 전체 흐름은 다음과 같다. 1. 의심스러운 사용자 활동 발생 2. 활동 분석 3. 이상 이벤트 생성 4. AER 컨트롤러가 지원 대상 여부와 대응 조건 확인 5. 조건 충족 시 사용자 세션 종료 6. 항상 감사 로그 기록 7. 설정된 경우 고객에게 알림 ## 조직별 기준을 적용하는 탐지 엔진 - 동일한 활동이라도 조직의 업무 특성에 따라 정상 또는 비정상일 수 있다. - 예를 들어 한 조직에서 대량 다운로드가 일상적이라면, 고정된 전역 기준을 적용할 경우 오탐이 많이 발생할 수 있다. - AER는 각 Enterprise 조직의 과거 사용 데이터를 기반으로 임계값을 계산한다. - 조직별 기준선을 사용하면 다음 효과가 있다. - 오탐 감소 - 탐지 민감도 조정 - 탐지 효과의 지속적인 검증과 개선 - 즉, 단순히 “특정 횟수 이상이면 공격”으로 판단하지 않고, 각 조직의 평소 사용 패턴에서 벗어났는지를 기준으로 판단한다. ## 자동 세션 종료를 통한 즉각 대응 - 이상 행위가 높은 신뢰도로 식별되면 관련 사용자 세션을 자동으로 종료한다. - 이를 통해 공격자가 계정을 계속 사용하거나 데이터를 추가로 추출하는 시간을 줄인다. - 기존의 사후 대응처럼 피해 규모를 조사한 뒤 조치하는 대신, 공격 체인이 완전히 실행되기 전에 개입한다. - 자동 대응 결과는 감사 로그에 남아 사후 조사와 보안 검토에 활용된다. - 고객은 조직의 위험 허용 수준에 따라 특정 탐지 항목만 세션 종료 대상으로 지정할 수 있다. ## 고객 보안 체계와의 역할 분담 - Slack은 플랫폼 자체의 탐지와 기본 대응 기능을 제공한다. - 고객은 감사 로그와 AER 설정을 활용해 조직별 보안 정책을 구성할 수 있다. - 보안 역량과 인력이 제한적인 고객은 AER를 별도 연동 없이 사용할 수 있다. - 고급 보안 조직은 AER를 SIEM, SOAR 또는 자체 탐지 체계와 결합해 더 세밀한 대응 정책을 추가할 수 있다. - 이는 Slack과 고객이 함께 보안을 책임지는 **공동 책임(shared responsibility)** 모델에 해당한다. 조직별 정상 패턴을 반영할 수 있는 자동 탐지와 즉시 세션 종료를 결합한 AER는, 감사 로그를 사람이 확인한 뒤 대응하는 방식보다 빠르고 실용적이다. 다만 자동 종료는 업무 중단을 일으킬 수 있으므로 처음에는 이벤트를 기록만 하며 오탐을 검증한 뒤, 위험도가 높은 탐지부터 단계적으로 자동 대응을 활성화하는 것이 바람직하다.

원문 읽기(새 탭에서 열림)
slack3분 읽기큐레이션 요약

E2E 파이프라인

Slack은 E2E 테스트 파이프라인에서 프론트엔드 변경이 없어도 매번 프론트엔드를 빌드하는 비효율을 발견했다. Git 변경 감지와 기존 빌드 산출물 재사용을 도입해 프론트엔드 빌드 횟수를 60% 줄이고, 전체 파이프라인 시간을 약 10분에서 2분으로 단축했다. 그 결과 개발자 대기 시간과 AWS S3 저장 비용을 줄였을 뿐 아니라 E2E 테스트의 플래키함도 개선됐다. ## 프론트엔드 빌드가 병목이 된 이유 - Slack의 대규모 모노레포에서는 병합 전 전체 스택을 검증하기 위해 E2E 테스트를 실행했다. - 기존 파이프라인은 다음 순서로 동작했다. - 코드 변경 후 브랜치 푸시 - 프론트엔드 빌드: 약 5분 - QA 환경 배포 - 200개 이상의 E2E 테스트: 약 5분 - 프론트엔드와 무관한 백엔드·데이터베이스·서비스 변경에도 프론트엔드를 새로 빌드했다. - 매주 수천 번의 빌드가 발생했고, 빌드 하나당 AWS S3에 약 1GB의 데이터가 저장됐다. - 이 중 절반가량은 실제 프론트엔드 변경이 없어 중복 산출물에 해당했다. ## Git diff를 이용한 조건부 빌드 - 현재 브랜치와 `main`의 최신 공통 커밋을 기준으로 `git diff`의 3-dot 표기법을 사용했다. - 변경 내역에 프론트엔드 관련 파일이 포함된 경우에만 새 프론트엔드 빌드 작업을 실행했다. - 프론트엔드 변경이 없으면 빌드를 완전히 건너뛰고 기존 산출물을 사용했다. - 추적 파일이 10만 개가 넘는 모노레포에서도 Git의 변경 감지는 약 몇 초 안에 완료됐다. ## 기존 빌드 산출물과 내부 CDN 재사용 - 새 빌드가 필요하지 않은 경우 AWS S3에 저장된 기존 프론트엔드 빌드를 탐색했다. - 현재 Production에서 사용 중인 비교적 최신 빌드를 선택해 테스트에 활용했다. - 내부 CDN이 해당 프론트엔드 정적 파일을 제공하도록 구성했다. - 이를 통해 PR마다 새 빌드를 생성하지 않으면서도 최신 상태에 가까운 프론트엔드 자산으로 E2E 테스트를 수행했다. ## 대규모 환경에서의 자산 관리 - 수백 개의 PR이 매일 병합되므로 재사용할 빌드가 충분히 최신인지 판단해야 했다. - S3의 파일명 규칙과 저장 구조를 활용해 빌드 산출물의 최신성, 일관성, 검색 성능을 관리했다. - 변경 여부 판단과 적절한 빌드 산출물 탐색을 평균 3초 이내에 처리했다. - 결과적으로 전체 테스트 흐름에서 프론트엔드 빌드 단계를 효율적으로 제거할 수 있었다. ## 성능과 비용 개선 - 불필요한 프론트엔드 빌드 빈도를 60% 줄였다. - AWS S3 중복 저장 데이터를 매월 수 테라바이트 규모로 절감했다. - 클라우드 컴퓨팅 비용과 개발자의 파이프라인 대기 시간을 줄였다. - 기존 Webpack 개선으로 평균 빌드 시간이 10분에서 5분으로 줄어든 데 이어, 이번 최적화로 약 2분까지 단축했다. - 전체 E2E 파이프라인 시간은 평균 10분에서 2분으로 감소했다. ## 예상하지 못한 효과 - 프론트엔드 빌드 과정과 자산 전달 방식이 단순해지고 일관되면서 E2E 테스트의 플래키함이 감소했다. - 월별 측정 결과 테스트 실패의 불안정성이 가장 낮은 수준까지 개선됐다. - 오래된 여러 시스템의 레거시 코드를 조사하는 과정에서 기존 동작을 재발견하고 향후 개선 과제도 발굴했다. ## 실용적인 결론 CI/CD 파이프라인에서는 모든 단계를 무조건 실행하기보다 실제 변경 범위와 필요한 검증 수준을 기준으로 조건부 실행을 설계하는 것이 효과적이다. 특히 Git 변경 감지, 빌드 산출물 캐싱, CDN 재사용을 결합하면 빌드 시간과 클라우드 비용을 동시에 줄일 수 있다.

원문 읽기(새 탭에서 열림)