특정 조직이나 개인의 사례를 재현하지 않기 위해 여러 경험을 섞고 기술적 세부를 바꾸어 썼다.
어느 날 공통 프로필 API에 관한 질문이 왔다.
여러 화면에서 사용자 상태를 확인하려고 호출하는 API인데, 응답에는 주소와 연락처, 외부 계정 연결 정보처럼 목적에 비해 많은 데이터가 들어 있었다. 질문은 짧았다.
- 이 응답은 어디까지 필요한가
- 용도에 따라 더 작게 나눌 수 있는가
- 서버에서 호출하면 더 안전해지는가
처음 보면 코드 검색 몇 번으로 답할 수 있을 것 같다. 하지만 세 문장은 각각 다른 종류의 일이다.
질문은 세 줄이었고, 일은 세 갈래였다
첫 번째는 사용처 감사다. 문자열 검색만으로는 부족하다. 공통 Provider나 hook 뒤에 숨은 호출을 찾고, 여러 애플리케이션에서 실제로 마운트되는지 확인해야 한다. 직접 호출과 간접 호출, 최초 진입과 클라이언트 이동도 구분해야 한다.
두 번째는 데이터 계약 분석이다. 타입에 선언된 필드와 실제 화면이 소비하는 필드는 다르다. 화면에서는 쓰지 않지만 다른 요청을 만드는 데 사용될 수도 있고, 공통 상태에 담긴 뒤 분석이나 오류 추적 도구로 흘러갈 수도 있다. “화면에 표시하지 않는다”는 것만으로 미사용이라고 단정할 수 없다.
세 번째는 아키텍처 의사결정이다. 브라우저 호출을 서버 호출로 바꾸는 일은 함수 위치를 옮기는 정도가 아니다. 인증 쿠키 전달, 토큰 갱신, 캐시 격리, 정적 렌더링 포기 여부, 클라이언트 전환 후의 동기화까지 함께 결정해야 한다.
그러니 이것은 사실 확인 하나가 아니었다. 여러 애플리케이션을 가로지르는 조사와 개인정보 최소화 검토, 렌더링 정책 판단이 묶인 작은 기술 프로젝트였다.
모두가 알고 있던 API
더 어려운 점은 문제가 새롭지 않았다는 것이다.
오래된 시스템에는 누구나 “응답이 너무 크다”고 알고 있는 API가 있다. 주문서 하나를 그리기 위해 회원, 배송, 할인, 결제, 약관 데이터가 한 응답에 얽혀 있기도 한다. 당장 화면을 완성하기에는 편하지만, 시간이 지나면 어느 필드가 누구의 책임인지 알기 어려워진다. 한 필드의 변경이 전체 계약의 검증 범위를 키우고, 사용하지 않는 정보까지 모든 호출자에게 전달된다.
OWASP는 클라이언트가 필요로 하는 것보다 더 많은 데이터를 API가 반환하는 상황을 Excessive Data Exposure로 설명한다. 클라이언트가 응답을 받아 필요한 필드만 골라 쓴다고 해서, 전달된 나머지 데이터가 사라지는 것은 아니다.
서버에서 대신 호출하면 모든 문제가 해결된다는 설명도 충분하지 않다. 전체 응답을 다시 브라우저에 직렬화하면 노출 범위는 크게 달라지지 않는다. 서버 안에서 필요한 값만 추려 내려보낼 때 비로소 경계가 줄어든다. 호출 위치보다 중요한 것은 서버의 인증·인가와 용도에 맞는 최소 응답 계약이다.
CSR을 없애는 것과 API를 잘 나누는 것은 다른 일이다
이런 문제가 발견되면 종종 “브라우저에서 직접 호출하지 말고 서버에서 호출하자”는 해결책이 먼저 나온다. 브라우저 개발자 도구에서 응답이 보이지 않게 되니 더 안전해진 것처럼 느껴지기 때문이다.
여기서 흔히 CSR이라고 뭉뚱그려 부르는 브라우저의 직접 API 호출은 데이터 조회 위치에 관한 선택이지, 그 자체로 보안 취약점은 아니다. 로그인한 사용자에게 자기 주소를 보여줘야 한다면 그 주소는 어떤 방식으로든 브라우저에 도착한다. 반대로 SSR로 전체 프로필을 받은 뒤 그대로 클라이언트 상태에 넣으면 전달 경로만 하나 늘었을 뿐이다. 서버 호출이 의미를 가지는 경우는 비밀 값이나 내부 로직을 서버 안에 남기고, 브라우저에는 필요한 결과만 내려보낼 때다.
거대한 API를 나누는 기준도 CSR과 SSR이 아니라 사용 목적과 데이터 수명이어야 한다. 예를 들어 여러 화면에서 공통으로 필요한 로그인 상태와 회원번호는 가벼운 세션 API로, 이름과 연락처는 프로필 화면에서, 주소는 배송지나 회원정보 수정 화면에서, 외부 계정 연결 정보는 계정 관리 화면에서 따로 조회할 수 있다.
이렇게 나누면 효과가 단순해진다.
- 자주 호출되는 API의 개인정보 범위가 작아진다.
- 한 기능의 변경이 다른 화면의 응답 계약을 흔들지 않는다.
- 캐시와 재조회 주기를 데이터 성격에 맞게 정할 수 있다.
- 어떤 화면이 어떤 개인정보를 필요로 하는지 설명할 수 있다.
서버 호출은 그다음 선택이다. 초기 화면 속도가 중요한지, 요청별 렌더링 비용을 감당할 수 있는지, 로그인 전환 뒤 데이터를 어떻게 다시 맞출지를 보고 결정하면 된다. 큰 API를 작게 만드는 일과 호출 위치를 옮기는 일을 같은 보안 대책으로 묶지 않는 것이 출발점이다.
문제는 이렇게 이미 알려진 구조를 확인하는 비용이 공식적인 일이 되지 않는 순간 생긴다.
공개된 질문과 투명한 일은 다르다
여러 사람이 보는 채널에 질문을 올리면 상황은 투명해 보인다. 누군가 답하고, 대화 기록도 남는다. 하지만 다음이 없다면 보이는 것은 질문뿐이다.
- 어디까지 조사해야 하는가
- 현황 파악과 실제 개선 중 무엇을 원하는가
- 누가 결정을 내리는가
- 조사에 얼마의 시간을 써도 되는가
- 결과를 어디에 남기고 누가 후속 작업을 맡는가
이 항목들이 비어 있으면 질문에 먼저 반응한 사람이 범위를 해석하고, 코드를 추적하고, 배경을 설명하고, 관련 팀과 조율하는 일까지 맡는다. 공개된 요청이 업무를 투명하게 만든 것이 아니라 조정 비용을 한 사람에게 조용히 이전한 것이다.
질문한 사람이 나쁜 의도를 가졌다는 뜻은 아니다. 오히려 조직 안에 일을 받아내는 형식이 없을수록 누구나 질문 형태로 일을 시작하게 된다. 문제는 개인의 태도보다, 질문이 일이 되는 순간을 포착하지 못하는 운영 방식에 있다.
담당자는 사람으로 된 캐시가 된다
이 구조에서 가장 먼저 지치는 사람은 해당 시스템을 가장 잘 아는 사람이다.
그 사람은 코드를 읽는 시간보다 “왜 이게 간단한 확인이 아닌지” 설명하는 데 더 많은 에너지를 쓴다. 설명을 마치고 나면 API는 그대로고, 다음 질문이 오면 같은 배경을 다시 꺼내야 한다. 조사 결과가 문서나 결정으로 남지 않았기 때문이다.
Google SRE는 수동적이고 반복적이며 반응적으로 발생하고, 끝난 뒤에도 시스템에 지속적인 가치를 남기지 않는 일을 toil이라고 부른다. 같은 시스템의 맥락을 사람이 매번 복원해야 하는 일도 비슷하게 증가한다. 시스템이 커질수록 질문이 늘고, 질문마다 같은 전문가의 시간이 선형으로 든다.
결국 담당자는 시스템을 개선하는 사람이 아니라 시스템의 역사와 예외를 대신 기억해 주는 사람으로 된 캐시가 된다. 캐시는 빠르지만, 한 사람의 집중력과 감정으로 유지되는 캐시는 확장되지 않는다.
질문을 일로 바꾸는 최소한의 형식
거창한 프로세스가 필요한 것은 아니다. 질문이 여러 시스템을 가로지르기 시작했다면 다음 정도만 명시해도 달라진다.
| 항목 | 확인할 내용 |
|---|---|
| 목적 | 단순 현황 파악인가, 변경 여부를 결정하려는가 |
| 범위 | 특정 API 하나인가, 공통 인증과 개인정보 API 전반인가 |
| 산출물 | 답글인가, 사용처 목록인가, 의사결정 문서인가 |
| 결정권자 | 조사 결과를 보고 유지·분리·폐기를 결정할 사람은 누구인가 |
| 시간 | 즉시 답변인가, 시간을 확보한 조사 업무인가 |
| 후속 처리 | 발견한 부채를 어느 백로그에 넣고 누가 우선순위를 정하는가 |
이 형식의 목적은 질문을 어렵게 만드는 것이 아니다. 이미 어려운 일을 쉬운 질문처럼 보이지 않게 하는 것이다.
조사 결과도 답글 하나로 끝내지 않아야 한다. 전역에서 필요한 인증 정보와 특정 화면에서만 필요한 상세 프로필을 분리할지, 서버가 데이터를 축소할지, 기존 계약을 언제까지 유지할지를 결정 가능한 형태로 남겨야 한다. 그래야 다음 사람은 처음부터 다시 검색하지 않는다.
Martin Fowler는 기술 부채라는 표현에서 중요한 것은 무엇을 부채로 분류할지보다, 그 은유가 설계 문제를 이해하고 다루는 데 도움이 되는지라고 설명한다. Technical Debt Quadrant 부채라는 이름을 붙였다면 발견했다는 기록만이 아니라, 이자를 누가 내고 언제 어떤 방식으로 갚을지도 보여야 한다.
투명성은 비용까지 보일 때 생긴다
예전에 책임이 둥둥 뜨면 버그가 된다고 썼다. 기술 부채도 비슷하다. 모두가 문제를 알고 있다는 상태는 공동 소유가 아니다. 책임자가 없다는 뜻일 수도 있다.
일정만 보이고 기술적 비용이 보이지 않을 때 생기는 문제는 일정은 관리됐지만 기술은 관리되지 않았다에서도 다뤘다. 질문 역시 마찬가지다. 채널에 공개됐다는 사실만으로는 부족하다. 조사 비용, 범위, 결정권, 후속 우선순위까지 보여야 한다.
기술 부채는 누군가가 발견했다고 줄어들지 않는다. 담당자를 찾아 질문을 전달했다고 상환되는 것도 아니다. 질문을 실제 업무로 인정하고, 그 결과를 다음 사람이 다시 사용할 수 있는 결정과 구조로 남길 때 비로소 조금씩 줄어든다.
공개된 질문은 가시성을 만든다. 비용과 책임, 남길 결과까지 공개된 일이 투명성을 만든다.