pile·
백엔드·마켓컬리마켓컬리 Hello World·

nginx 설정 없이 우아하게 서비스 점검하기 (上)

컬리 배송 팀이 DB 점검 중 특정 기능(적치 워크플로우) 접근을 막아야 했는데, nginx 라우팅 설정을 바꿀 권한이 없었다. 그래서 nginx 없이 애플리케이션 레벨에서 접근을 차단하는 AccessBlock 을 만들었다. 초기엔 MySQL 테이블로 차단 URL 을 관리하다가, 점검(=DB 장애) 중에도 동작하도록 Redis 캐시 기반 v2 로 발전시켰다.

핵심 포인트
  • 문제: DB 점검 창에서 적치 등 특정 기능 접근을 막아야 하나 nginx 설정 변경 권한이 없어 앱 레벨 해법이 필요했다.
  • 초기 설계: access_block(차단 URL 경로)과 access_block_group(그룹) 테이블을 두고 페이지 라우팅마다 차단 여부 API 를 호출했다.
  • 차단 판정: 요청 URL 을 등록된 경로와 비교해 boolean 을 반환하고 true 면 점검 안내 페이지로 리다이렉트한다.
  • v2 전환: 메타데이터를 Redis 로 옮겨 DB 장애 중에도 차단 상태를 조회할 수 있게 했다.
  • 부수 효과: 라우팅마다 API 를 타면서 만료된 토큰을 즉시 잡아 자동 로그아웃을 유도한다.
  • 한계: 메타데이터 등록은 여전히 RDBMS 가 필요해 완전한 DB 독립은 미해결로 남았다.
상세 정리
  • 배경: 배송 시스템 DB 점검 시 사용자가 작업 중인 기능에 계속 접근하면 문제가 생겨, 점검 구간 동안 특정 기능만 막아야 했다.
  • 제약: 개발 팀이 nginx 라우팅 설정을 직접 수정할 권한이 없어 인프라 대신 애플리케이션에서 차단을 구현했다.
  • 초기 구조: MySQL 에 access_block(예: /user/list 같은 차단 경로)과 access_block_group(경로 묶음) 두 테이블로 차단 대상을 관리했다.
  • 동작: 프론트 각 페이지가 라우팅할 때마다 차단 여부 확인 API 를 호출하고, API 는 요청 URL 을 등록된 차단 경로와 대조했다.
  • 리다이렉트: true 응답이면 점검 안내 페이지로 보내 사용자가 해당 기능에 들어가지 못하게 막았다.
  • v2 동기: DB 점검 자체가 차단이 필요한 시점인데 차단 메타데이터를 DB 에서 읽으면 점검 중 조회가 막히는 모순이 있어 Redis 캐시로 옮겼다.
  • Redis 키: ACCESS_BLOCK, ACCESS_BLOCK_GROUP 에 설정을, BLOCKED_...ID_LIST 에 활성 차단 상태를 저장했다.
  • 캐시 갱신: 메타데이터 변경 즉시 캐싱하고 주기적(API 호출 100회마다)으로 재캐싱해 최신 상태를 유지했다.
  • 토글: 차단 on/off 는 이제 Redis 만 수정하고 DB 는 건드리지 않는다.
  • 트레이드오프: 페이지 라우팅마다 네트워크 홉이 한 단계 늘지만 성능 영향은 미미하다고 판단했다.
  • 남은 과제: 메타데이터 등록은 여전히 RDBMS 를 거쳐야 해 DB 전면 장애 중 설정 변경은 불가하며, 완전한 DB 독립은 아직 이루지 못했다.
왜 읽나nginx/인프라 권한 없이 애플리케이션 레벨로 점검 중 기능 차단을 구현해야 하는 백엔드 개발자에게 실전 설계 사례.
마켓컬리
마켓컬리 Hello World 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 백엔드·github-engGitHub Engineering·

    조기 종료를 없애야 벡터화된다 — 메모리 속도 소스 코드 케이스 폴딩

    GitHub의 코드 검색 엔진 Blackbird는 480TB 이상의 소스 코드를 인덱싱하기 전 모든 바이트에 case folding을 적용한다. 이 글은 Rust로 구현한 case folding을 메모리 대역폭 한계(45+ GiB/s)까지 끌어올린 두 가지 반직관적 최적화를 상세히 다룬다. 핵심은 루프 조기 종료(break) 제거로 LLVM 벡터화를 유도하고, UTF-8을 디코딩하지 않고 바이트 공간 산술만으로 fold를 수행하는 것이다.

    #rust#unicode#simd+2
  2. 백엔드·여기어때 (GC컴퍼니)여기어때 (GC컴퍼니)·

    트랜잭션 스크립트에서 숙소 메타 + 가격 계산 모듈로 — 전시 아키텍처 개선기 (2/3)

    여기어때 전시개발팀이 숙소 상세(PDP) API를 해부한 결과, 코드상으로는 DB 호출 3번처럼 보이던 요청이 실제로는 MongoDB $lookup 체인으로 컬렉션을 19회 접근하는 구조였다. 이 트랜잭션 스크립트 방식의 핵심 문제는 "aggregation이 I/O를 가린다"는 점으로, 독립적인 쿼리 10개가 단일 파이프라인에 직렬화되어 병렬화 기회를 잃고, 가격 때문에 거의 안 바뀌는 이미지까지 매 요청마다 읽어야 하는 읽기 증폭이 발생했다. V3에서는 "조회 시점 조립"을 "쓰기 시점 사전 조립"으로 전환하고, 화면별로 복제되던 가격 계산 로직을 goodsprice 단일 모듈로 수렴했다. 4개 API(PLP/PDP/RDP/ILP)의 반복 마이그레이션은 Claude Code skill로 절차를 고정하고 쉐도잉 + 동일성 검증으로 안전망을 마련하는 방식으로 진행됐다.

    #architecture#migration#caching+2