LLM이 만든 사용자 확장, 웹앱은 어디까지 권한을 줄까
LLM은 맞춤 기능의 작성 문턱을 낮추지만 권한과 상태의 경계까지 정해 주지는 않는다. 좁은 작업 권한, 실행 환경의 재사용, 생성·초기화 비용을 함께 살펴 확장형 웹앱의 도입 조건을 정리한다.
고객지원 화면에 “이 티켓을 요약하는 버튼”을 LLM으로 붙였다고 가정하자. 버튼은 금방 만들었지만, 그 코드에 전체 고객 조회 API와 자유로운 외부 통신까지 열어 줬다면 작은 기능에 비해 권한이 너무 크다. 사용자마다 필요한 기능을 직접 만들 수 있게 된 뒤에는, 코드를 얼마나 쉽게 생성하는가보다 제품이 어디까지 실행을 허용하는가가 중요해진다.
Jeremy Morrell의 확장형 소프트웨어에 관한 글은 2026년 8월 18일 작성됐고, GeekNews에는 11월 9일 오전 6시 24분, 한국 시각으로 등록됐다. 당일 출시 소식은 아니다. Cloudflare에 재직하는 저자의 제안을 현재 공식 문서와 대조해 읽은 분석이며, 데모나 샌드박스를 실행해 검증한 결과는 아니다.
기능을 열어 주는 일은 제품의 책임을 늘린다
원문의 출발점은 모든 사용자의 요구를 기본 기능으로 넣을 수 없다는 문제다. 소수에게 필요한 기능도 기본 화면을 복잡하게 만든다. 반대로 웹훅으로 해결하려면 사용자가 별도 서비스를 배포하고 운영해야 한다. 저자는 안정된 코어에 확장 지점을 두고 LLM이 사용자별 코드를 작성하게 하는 모델을 제안한다. 원문의 가설
이 방향은 고객별 분류 규칙이나 사내 도구의 맞춤 화면처럼 요구가 자주 갈리는 곳에서 검토할 만하다. 다만 작성 비용이 줄었다는 주장으로 배포와 유지보수 비용까지 사라졌다고 볼 수는 없다. 어떤 이벤트에서 실행하는지, 어떤 데이터를 전달하는지, 확장 API를 바꿀 때 기존 코드를 어떻게 지원하는지는 제품이 정해야 한다.
내가 주목한 부분은 맞춤 기능의 위치다. 기본 제품에 모든 기능을 넣는 대신 확장으로 옮겨도, 그 기능을 지원할 책임은 남는다. 설정 가능한 규칙 몇 개로 충분한 서비스라면 임의 코드 실행보다 규칙 편집기가 단순할 수 있다. 이미 운영 중인 웹훅이 요구를 충족한다면 그 경로를 유지하는 것도 대안이다.
키를 숨기는 것보다 허용할 작업을 좁힌다
원문은 확장에 범용 API 키를 주는 대신 capability를 전달하자고 제안한다. 여기서 capability는 특정 자원이나 동작에 접근할 수 있는 참조다. 앞의 사례라면 전체 고객을 검색하는 클라이언트보다, 승인된 티켓 하나의 필요한 필드만 읽는 함수를 제공하는 식이다. 실제 자격 증명과 데이터 조회 구현은 신뢰하는 플랫폼 쪽에 둔다. 권한 모델 설명
이 구조에도 실행 경계가 필요하다. 같은 프로세스에서 함수 이름만 제한하고 전역 네트워크나 환경 변수 접근을 그대로 두면 우회 경로가 남는다. Cloudflare의 외부 통신 문서는 Dynamic Worker에 globalOutbound: null을 설정하면 fetch()와 connect()가 예외를 내고, 제공한 바인딩으로 특정 자원에 접근하는 방식은 유지할 수 있다고 설명한다. 바인딩은 실행 환경에 연결해 주는 서비스나 자원이다.
중요한 것은 비밀 키가 보이지 않는다는 사실과 권한이 좁다는 사실이 다르다는 점이다. 키를 대신 붙여 주는 게이트웨이가 모든 고객 조회를 허용하면 과도한 권한은 그대로다. 공식 인가 문서도 확장 실행 전의 경로 검사와, 실제 데이터를 읽는 플랫폼 함수 안의 권한 검사를 함께 요구한다. 로그인 여부만 확인해서는 다른 사용자의 자료를 읽는 일을 막을 수 없다.
나는 티켓 식별자를 확장 코드가 보내더라도, 그 티켓을 현재 사용자가 읽을 수 있는지는 플랫폼에서 다시 확인하겠다. 외부 전송이 필요하면 목적지뿐 아니라 허용할 작업과 데이터 범위도 정한다. 요약 결과나 로그로 민감한 정보가 나가는 경로까지 살펴야 하므로, 네트워크 차단 하나를 유출 방지의 완성으로 보지는 않는다.
실행 환경을 재사용하면 데이터도 남을 수 있다
권한이 좁은 함수를 매번 전달해도 이전 실행의 상태까지 초기화되는 것은 아니다. 공식 문서는 캐시된 Dynamic Worker가 반환받은 데이터를 요청 사이에 메모리로 유지할 수 있다고 경고한다. 다른 사용자의 capability를 새로 전달해도 이미 보관한 자료가 지워지지는 않는다.
따라서 같은 회사의 사용자라는 이유만으로 실행 환경을 모두 공유하면 안 될 수 있다. 사용자별로 조회 권한이 다른 지원 도구라면, 같은 테넌트 안에서도 이전 사용자의 데이터가 다음 호출에 보이는지 따져야 한다. 테넌트는 서비스를 함께 쓰는 고객 조직 등의 구분 단위다. 문서는 앱 코드를 믿지 않고 격리를 유지해야 할 때 요청마다 load()로 새 Worker를 만들거나 사용자별 캐시 ID를 쓰고, 저장소 범위도 맞추도록 안내한다. 상태와 권한의 경계
이 선택은 비용에도 연결된다. 현재 가격 문서에 따르면 Dynamic Workers는 Workers 유료 플랜에서 제공되며, 요청과 CPU 외에 ID와 코드로 구분한 Worker의 일일 생성량을 집계한다. 같은 ID·코드의 반복 호출과 달리 load()는 호출마다 새 생성으로 센다. CPU 과금에는 코드 초기화 시간도 들어간다.
나는 재사용 범위를 먼저 비용으로 결정하지 않겠다. 어떤 사용자 사이에서 상태를 공유해도 되는지 정한 뒤 그 범위 안에서 재사용하겠다. 요청별 새 실행이 필요하다면 늘어나는 생성·초기화 비용을 맞춤 기능의 운영비에 넣는다. 캐시 키는 성능 설정인 동시에 데이터 격리 설계의 일부라고 본다.
첫 확장은 결과를 제안하는 데서 시작한다
도입을 검토한다면 처음부터 외부 발송이나 데이터 변경 권한을 열기보다, 제한된 입력을 받아 분류나 요약 결과를 반환하는 확장부터 시작하겠다. 이 결과를 플랫폼이 검증하고 사용자가 확인한 뒤 적용하면, 생성 코드의 오류가 곧바로 되돌리기 어려운 작업으로 이어지는 범위를 줄일 수 있다.
실행 자원도 제한해야 한다. Dynamic Workers는 호출별 CPU 시간과 하위 요청 수를 더 낮게 설정할 수 있고, 한도에 도달하면 예외를 낸다. 자원 제한 문서 이 두 설정이 로그 양이나 출력 크기까지 모두 통제해 주는 것은 아니므로, 제품이 전달받고 보관하는 데이터의 한도도 따로 정하겠다.
첫 적용에서 확인할 순서는 다음과 같다.
- 다른 사용자 자료의 식별자와 허용하지 않은 외부 주소를 넣어, 플랫폼이 접근을 거절하는지 확인한다.
- 반복 실행과 사용자 전환 뒤에 이전 입력이 노출되지 않는지 살피고, 무한 반복·과도한 호출에서는 확장만 중단되는지 확인한다.
- 코드와 권한 정책을 같은 버전으로 기록하고, 문제가 생긴 확장을 끄거나 이전 버전으로 되돌릴 경로를 마련한다.
코드와 경로 정책을 함께 배포하라는 것은 공식 문서의 권고이기도 하다. 이 기록이 있어야 어떤 코드가 어떤 권한으로 실행됐는지 추적할 수 있다.
LLM이 맞춤 기능을 만들기 쉽게 했다는 이유만으로 모든 웹앱을 플랫폼으로 바꿀 필요는 없다. 반복되는 사용자 요구가 있고, 좁은 권한과 실행 상태의 경계를 설명할 수 있으며, 그 API를 계속 지원할 여력이 있을 때 확장 모델이 의미를 갖는다. 첫 버튼이 동작하는 시점보다, 그 버튼이 해서는 안 되는 일을 막을 수 있는 시점을 도입 기준으로 삼겠다.
참고 자료
이 이야기가 도움이 되었나요?