본문으로 건너뛰기

흩어진 정책을 모으다, 횡단 관심사 - 두 개의 아키텍처 정의서 ep.05

가장 위험한 정책은 모두의 일이면서 아무의 일도 아닌 정책이다.

기능은 보통 자기 자리가 있습니다. 검색은 검색 모듈에, 저장은 저장 모듈에 있습니다. 그런데 어디에도 자기 자리가 없는 것들이 있습니다. 보안, 인증, 로깅 같은 것들입니다. 이번 편은 그 횡단 관심사(cross-cutting concerns) 를 한자리에 모읍니다.


한 컴포넌트에 속하지 않는 것들

횡단 관심사는 정의상 여러 컴포넌트에 걸칩니다. 로깅은 프론트엔드에도, API에도, 워커에도 필요합니다. 인증은 거의 모든 진입점에 필요합니다.

기능과 횡단 관심사의 차이를 보여주는 그림. SPA, API 백엔드, 요약 워커, PostgreSQL 네 개의 컴포넌트 열이 있다. 가운데 API 백엔드 열 안에 틸색으로 채워진 박스 '기능 — 예: 검색 로직'이 한 컴포넌트 안에 담겨 있다. 그 아래에는 네 컴포넌트 열을 모두 가로지르는 앰버색 띠 '횡단 관심사 — 예: 로깅 · 인증 · 보안'이 있다. 캡션은 기능은 보통 한 컴포넌트 안에 모여 위치가 분명하지만, 횡단 관심사는 거의 모든 컴포넌트에 걸쳐 흩어 두면 빠지고 모아 두어야 일관된다고 설명한다.

문제는 이것들을 컴포넌트마다 따로 구현하면, 컴포넌트마다 조금씩 달라진다는 점입니다. 한 곳에서는 로그를 남기고 다른 곳에서는 안 남깁니다. 한 곳에서는 권한을 확인하고 다른 곳에서는 빠뜨립니다. 그 빠진 한 곳이 사고가 됩니다. 그래서 정의서에 별도 섹션으로 모읍니다.


스폿의 횡단 관심사

스폿에서 모아야 할 관심사는 여섯 가지입니다. 인증·인가, 보안, 관측성, 에러 처리, 캐싱, 트랜잭션입니다. 각각이 어느 컴포넌트에 걸치는지를 매트릭스로 보면 “횡단”의 의미가 분명해집니다.

횡단 관심사와 컴포넌트의 적용 관계를 보여주는 매트릭스. 행은 인증·인가, 보안(위치), 관측성, 에러 처리, 캐싱, 트랜잭션 여섯 관심사이고, 열은 SPA, API, 워커, 큐, DB, 외부 API 여섯 컴포넌트다. 채워진 원은 강하게 적용, 빈 원은 부분 적용을 뜻한다. 인증·인가는 API와 DB와 외부 API에 강하게, SPA와 워커에 부분 적용된다. 보안은 API와 DB와 외부 API에 강하게, SPA와 워커와 큐에 부분 적용된다. 관측성은 SPA·API·워커·큐에 강하게, DB와 외부 API에 부분 적용된다. 에러 처리는 API·워커·큐와 외부 API에 강하게, SPA에 부분 적용된다. 캐싱은 API와 외부 API에 강하게, SPA에 부분 적용된다. 트랜잭션은 API·워커·DB에 강하게, 큐에 부분 적용된다. 거의 모든 행이 여러 컴포넌트에 걸친다.

매트릭스의 거의 모든 행이 여러 열에 표시됩니다. 이것이 횡단의 의미입니다. 한 행을 한 컴포넌트 문서에만 적으면, 다른 컴포넌트를 만지는 사람은 그 정책을 모릅니다.


같은 외부 의존, 다른 에러 전략

횡단 관심사 중 에러 처리가 스폿에서 특히 흥미롭습니다. 외부 API가 둘인데, 하나는 동기 핵심 경로이고 하나는 비동기 부가 경로라, 같은 “외부 호출 실패”인데 전혀 다른 전략을 씁니다.

동기 경로와 비동기 경로의 에러 처리 전략을 좌우로 비교하는 그림. 왼쪽 동기 핵심 경로(지도 API)는 API에서 서킷 브레이커로 내려가고, 서킷 브레이커는 정상이면 지도 API로 통과하지만 연속 실패로 open 상태가 되면 캐시 폴백으로 내려간다. 캡션은 실패를 빨리 끊고 캐시로 답해 사용자 대기를 막는다고 설명한다. 오른쪽 비동기 부가 경로(LLM API)는 메시지 큐에서 요약 워커로 내려가고, 워커는 LLM API로 요약을 요청하며 실패 시 지수 백오프로 재시도하는 루프가 있고, N회를 초과하면 데드레터 큐로 보낸다. 캡션은 사용자를 막지 않고 재시도로 버티다 안 되면 DLQ로 보낸다고 설명한다.

동기 경로에서는 사용자가 응답을 기다리므로, 실패를 빨리 끊는 것이 최우선입니다. 서킷 브레이커로 연속 실패를 차단하고 캐시로 폴백합니다. 비동기 경로에서는 사용자가 이미 떠났으므로, 시간을 들여 재시도할 여유가 있습니다. 지수 백오프로 재시도하고, 끝내 안 되면 데드레터 큐에 모아 둡니다. 같은 관심사가 경로의 성격에 따라 다른 모습이 됩니다.


보안: 위치는 민감정보다

여섯 관심사 중 스폿에서 가장 무거운 것은 보안입니다. 사용자의 위치 기록은 개인정보이고, 그중 비공개 기록은 민감정보에 가깝습니다.

그래서 보안은 한 줄로 적을 수 없고, 결정으로 풀어야 합니다. 인증은 자체 구현하지 않고 OAuth에 위임합니다(ADR-005). 비공개 기록은 소유자만 조회할 수 있도록 행 수준 접근 통제를 둡니다. 전송 구간과 저장 시점 모두 암호화합니다. 이런 정책들은 특정 컴포넌트의 일이 아니라 시스템 전체의 일이라, 횡단 관심사 섹션에 모여야 빠지지 않습니다.


두 문서에서의 횡단 관심사

내부 공유용SI 납품용
형태개념별로 “이렇게 처리한다”를 서술보안·개인정보 항목을 규정·법규에 매핑
보안위협과 대응을 결정과 함께 적음개인정보 처리방침·준수 증빙으로 정리
관측성로그·메트릭·트레이스 운영 합의감사 로그 보존 요건 충족을 명시

내부용에서 횡단 관심사는 “우리 팀이 합의한 공통 규칙”입니다. 새 컴포넌트를 만들 때 따라야 할 체크리스트에 가깝습니다. 납품용에서는 같은 내용이 규정 준수의 언어로 바뀝니다. 개인정보를 어떻게 다루는지, 감사 로그를 얼마나 보존하는지가 법규와 계약 요건에 매핑됩니다. 같은 보안 정책이 한쪽에서는 팀 규칙이고 다른 쪽에서는 준수 증빙입니다.


참고 자료

  • arc42. arc42 Documentation Template — Section 8 Cross-cutting Concepts. https://arc42.org
  • Michael T. Nygard. Release It! Design and Deploy Production-Ready Software. (서킷 브레이커, 안정성 패턴)

다음 편 예고

ep.06 - 내부 공유용 정의서, 거짓말하지 않는 문서 만들기

지금까지 모은 재료로 첫 번째 결과물을 완성합니다. 내부 공유용 정의서입니다. 핵심 과제는 하나입니다. 두 번째 죽음, 거짓말을 막는 것. 다음 편에서는 거짓말할 수 없는 구조로 문서를 설계합니다.