컬리 배송 팀이 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/인프라 권한 없이 애플리케이션 레벨로 점검 중 기능 차단을 구현해야 하는 백엔드 개발자에게 실전 설계 사례.