CPN 한국어 자습서 · Claude Certified Developer — Foundations Prep
5-7 · 신뢰 경계
Multi-component apps and trust boundaries
앞선 레슨에서 다룬 가속기와 여러 배포 방식, 그리고 그 사이의 선택(트레이드오프)이 이제 하나의 앱 안에서 만납니다. 구성요소를 연결할 때마다 신원과 비밀값, 신뢰할 수 없는 입력이 서로 넘나들 수 있는 자리가 함께 늘어납니다. 이 레슨에서는 무언가를 잇기 전에 경계가 어디에 생기는지 먼저 짚어 두는 방법과, 이음매마다 어떤 장치를 두면 좋은지 살펴봅니다.
이 장에서 배우는 것What you'll learn
약 19분여러 구성요소를 잇기 전에 각자 무슨 일을 맡는지 정리하는 법
신뢰 경계 — 데이터·지시가 실행 환경을 넘어가는 지점
가져온 콘텐츠를 지시가 아니라 데이터로 다루는 장치
앱 전체에 적용되는 최소 권한과 가장 약한 이음매
규제 검토를 앞두고 확인해 두는 항목
아무도 경계로 표시하지 않은 이음매 — 자주 놓치는 실패
여러 구성요소로 이뤄진 앱은 Claude의 기능 여러 개를 하나의 작업 흐름으로 엮은 것입니다. 예를 들어 API 요청이 Claude Code 작업을 부르고, 그 작업이 다시 MCP 서버Claude가 고객 시스템 같은 외부 시스템에 연결해 데이터를 읽거나 작업을 수행하도록 이어 주는 구성요소.를 거쳐 고객 시스템에 닿는 식입니다. 구성요소마다 다른 구성요소에는 없는 기능을 하나씩 맡습니다.
여기서 짚어 둘 부분은, 구성요소를 잇는 연결 하나하나가 신원과 비밀값, 신뢰할 수 없는 입력이 넘나들 수 있는 자리가 된다는 점입니다. 그래서 무언가를 연결하기 전에 어느 구성요소가 무슨 일을 맡는지부터 정리해 두는 것이 좋습니다. 이 레슨에서 다지는 원칙은 단순합니다 — 잇기 전에 모든 경계를 먼저 찾아 두는 것입니다.
구성요소 하나하나가 잘 동작하는지 보는 것도 중요하지만, 구성요소끼리 맞닿는 자리에서 무엇이 오가는지도 함께 살펴봐야 앱 전체가 안전해집니다.
신뢰 경계는 데이터나 지시가 한 실행 환경에서 다른 실행 환경으로 넘어가는 지점입니다. 앞 모듈에서 다룬 인젝션 대비와 접근 제어가 바로 이 자리에 적용됩니다.
예를 들어 Claude Code 작업이 웹에서 가져온 콘텐츠는, 다음 구성요소에 도착하는 순간부터 신뢰할 수 없는 입력으로 봅니다. 받는 쪽 구성요소는 그 콘텐츠를 지시가 아니라 데이터로 다루는 것이 좋습니다. 보안 모듈 내내 지켜 온 원칙과 같습니다. 여기서 핵심이 되는 규율은, 모든 이음매를 하나의 경계로 보는 것입니다. 어떤 구성요소가 혼자 돌아갈 때 제대로 작동했다는 사실만으로 그 구성요소를 곧바로 믿어도 된다고 보기는 어렵습니다.
집에 방이 여러 개 있다고 생각하면, 방과 방 사이의 문이 신뢰 경계입니다. 방 하나하나가 튼튼해도 문을 잠가 두지 않으면, 한 방에서 다른 방으로 아무나 넘어갈 수 있습니다.
신원과 최소 권한 — 각 구성요소에 그 일에 필요한 만큼의 접근 권한만 주는 것 — 은 앱 전체에 적용됩니다. 구성요소는 저마다 하나의 신원으로 움직입니다.
앱이 얼마나 잘 막혀 있는지는 가장 권한이 넓은 이음매가 결정합니다. 다른 구성요소를 아무리 촘촘하게 좁혀 두어도, 한 구성요소의 권한이 지나치게 넓으면 거기가 약한 고리가 됩니다. 그래서 각 구성요소를, 작업 흐름에서 맡은 역할에 필요한 최소 권한으로 좁혀 둡니다. 이렇게 해 두면 조종당한 구성요소가 원래 맡은 일의 범위를 넘어서지 못하게 됩니다.
앱이 얼마나 안전한지는 가장 헐겁게 열려 있는 구성요소 하나가 좌우합니다. 나머지를 잘 좁혀 두어도, 한 곳이 넓게 열려 있으면 결국 거기가 뚫립니다.
지금까지의 내용을 하나로 모으면, 세 구성요소가 각각 무엇을 내놓고, 그 이음매에 어떤 경계가 생기며, 무엇으로 그 경계를 지키는지 한눈에 정리할 수 있습니다.
INTEGRATION MAP — 구성요소별 이음매와 장치
| 구성요소 | 맡는 일 | 이음매에 생기는 신뢰 경계 | 그 경계를 지키는 장치 |
|---|---|---|---|
| 자사 APIFirst-party API | 작업 흐름 전체를 지휘하고, 바깥과 만나는 입구를 맡습니다. | 바깥에서 앱으로 들어오는 요청. | 입력 검증, 그리고 그 호출이 어떤 신원으로 실행되는지. |
| Claude Code 작업Claude Code task | 에이전트 방식의 작업을 수행하고, 외부 콘텐츠를 가져오기도 합니다. | 가져온 콘텐츠. 다음 단계에서는 신뢰할 수 없는 입력입니다. | 다음 이음매에서 가져온 콘텐츠를 데이터로 다룹니다. |
| MCP 서버MCP server | 고객 시스템에 연결해 데이터를 읽거나 작업을 수행합니다. | 앱을 대신해 갖고 있는 시스템 접근 권한. | 서버를 최소 권한으로 좁히고, 그 접근을 기록으로 남깁니다. |
규제를 받는 배포를 검토할 때는, 앱 전체에 걸쳐 감사 로깅누가 언제 무엇을 했는지 순서대로 남겨 두는 기록. 나중에 되짚어 볼 수 있게 한다., 데이터가 어느 지역에 저장되는지에 대한 결정, 권한 제어를 하나하나 근거를 들어 설명할 수 있어야 하는 경우가 많습니다.
규제 대상 배포에서는 보통 Amazon Bedrock과 Google Vertex AI(둘 다 클라우드에서 Claude 모델을 쓰는 플랫폼)가 지역별 데이터 레지던시data residency — 데이터가 물리적으로 어느 지역·국가에 저장되는지에 대한 규칙. 요건을 충족하는 플랫폼입니다. 범위를 정하기 전에, 각 구성요소가 ZDRZero Data Retention — 요청·응답 데이터를 보관하지 않는 설정.과 HIPAA BAA미국 의료정보보호법(HIPAA)에 따라 맺는 업무 협약(Business Associate Agreement). 조건에 해당하는지 Anthropic Trust Center와 platform.claude.com에서 먼저 확인해 두는 것이 좋습니다.
TRADE-OFFS — 이 접근의 득과 실
| 잘 맞을 때 | 모든 이음매에 경계라는 이름을 붙이고 각 구성요소를 최소 권한으로 좁혀 두면, 여러 구성요소로 이뤄진 앱도 검토를 통과해 배포할 수 있는 상태가 됩니다. |
|---|---|
| 비용·복잡도가 늘 때 | 이음매를 그리고, 각 지점에 장치를 걸고, 경계를 넘는 순간을 기록으로 남기는 일은 통합할 때마다 설계와 감사 작업을 더합니다. |
| 다른 방법을 쓸 때 | 어떤 이음매를 도무지 안전하게 만들 수 없다면, 그대로 우회해서 내보내기보다 사람 담당자에게 넘겨 판단을 받는 편이 낫습니다. |
각자 자기 테스트를 통과한 구성요소들을 연결했다고 해 봅시다. 부분들은 이미 검사를 마쳤고, 검증된 것끼리 잇는 일은 안전하게 느껴집니다. 하지만 신뢰할 수 있는 두 부분 사이의 이음매까지 저절로 믿을 수 있게 되는 것은 아닙니다.
아래는 페어 프로그래밍(둘이 함께 코드를 보며 작업하는 방식) 중에 오간 짧은 대화입니다. 표시되지 않았던 이음매를 알아차리는 순간에서 멈춥니다.
PAIRING SESSION — 페어링 중 오간 대화
| 개발자 A | 세 구성요소 다 각자 테스트를 통과해서, 방금 그냥 이어 붙였어요. |
|---|---|
| 개발자 B | Claude Code 작업이 가져온 건 어디로 보내요? |
| 개발자 A | 다음 호출에 프롬프트의 일부로 바로 넣죠. 고객 페이지에서 가져온 콘텐츠일 뿐이잖아요. |
| 개발자 B | 그 콘텐츠는 신뢰할 수 없어요. 안에 지시가 들어 있으면 다음 구성요소가 그걸 그대로 실행해 버립니다. 그 이음매를 경계로 표시한 적이 없으니까요. |
| 개발자 A | 그래도 구성요소는 각자 신뢰할 수 있는 것들이었는데요. |
| 개발자 B | 맞아요, 그런데 그 사이의 이음매는 아니었죠. 아무도 경계로 다루지 않은 게 바로 거기라, 가져온 콘텐츠가 지시가 되어 넘어가는 겁니다. |
각 구성요소가 자기 테스트를 통과했다는 사실은, 그 사이의 이음매에 대해서는 아무것도 말해 주지 않습니다. 가져온 콘텐츠는 Claude Code 작업을 떠나는 순간 이미 신뢰할 수 없는 입력이었습니다. 혼자서는 잘 작동하던 구성요소에서 나왔지만, 다음 호출에는 신뢰할 수 있는 지시처럼 넘어갔습니다. 경계는 데이터가 흐르는 길목에 이미 있었습니다. 다만 표시되지 않아서, 그 지점을 살피는 장치도 없었습니다.
자기 테스트를 통과한 구성요소 안에는 이음매 단위의 장치가 들어 있지 않습니다. 데이터가 한 실행 환경에서 다른 실행 환경으로 넘어가는 지점마다, 각 구성요소가 혼자서 어떻게 작동하든 별개로, 그 경계에 걸어 둘 장치가 따로 필요한 경우가 많습니다.
ZDR·HIPAA BAA 조건을 구성요소별로 확인해 둡니다.직접 해 볼 차례입니다. 아래 앱은 이미 세 구성요소로 연결돼 있고, 빈칸이 두 개 남아 있습니다. 신뢰할 수 없는 가져온 콘텐츠를 받는 이음매에 놓을 장치 하나와, 가장 권한이 큰 구성요소에 줄 신원 범위 하나를 고르면 됩니다.
PARTIAL APP — 빈칸 두 개가 남은 설정
# 연결된 구성요소: API -> Claude Code 작업 -> MCP 서버 fetched = code_task.run(fetch_url=customer_page) # 빈칸 1: 신뢰할 수 없는 '가져온 콘텐츠'를 받는 이음매의 장치 next_call(input=[ 빈칸 1 ](fetched)) # MCP 서버가 고객 시스템에 닿는다 (가장 권한이 큰 구성요소) mcp_server = MCPServer( system=customer_db, scope=[ 빈칸 2 ], # 빈칸 2: 신원 범위 )
고를 수 있는 토큰은 네 개이고, 그중 두 개는 함정입니다 — treat_as_data, least_privilege_read_only, run_as_instructions, full_access. 정답을 먼저 떠올려 본 뒤 골라 보세요. 맞히면 설명이 나옵니다.
Q1빈칸 1 — 신뢰할 수 없는 '가져온 콘텐츠'를 받는 이음매에 놓을 장치는 무엇일까요?
빈칸 1은 가져온 콘텐츠를 감싸서, 다음 구성요소가 그것을 지시가 아니라 데이터로 다루게 합니다. 이렇게 하면 인젝션이 넘어오던 이음매가 닫힙니다. run_as_instructions는 오히려 콘텐츠를 지시로 실행하게 만들고, full_access·least_privilege_read_only는 권한 범위를 정하는 토큰이라 이 자리에는 맞지 않습니다.
Q2빈칸 2 — 가장 권한이 큰 구성요소(MCP 서버)에 줄 신원 범위는 무엇일까요?
빈칸 2는 가장 권한이 큰 구성요소를 최소 권한으로 좁힙니다. 그래야 조종당한 동작이 원래 맡은 일의 범위를 넘어서지 못합니다. full_access는 정반대로 권한을 활짝 열어 두고, treat_as_data·run_as_instructions는 콘텐츠를 다루는 방식에 대한 토큰이라 신원 범위 자리에는 맞지 않습니다.
Q3세 구성요소가 각자 자기 테스트를 통과했습니다. 그렇다면 그 사이의 이음매도 믿을 수 있다고 볼 수 있을까요?
신뢰할 수 있는 두 부분 사이의 이음매까지 저절로 믿을 수 있게 되는 것은 아닙니다. 가져온 콘텐츠는 그 구성요소를 떠나는 순간 이미 신뢰할 수 없는 입력이고, 경계는 데이터가 흐르는 길목에 이미 있습니다. 표시해 두지 않으면 어떤 장치도 그 지점을 살피지 않습니다.
FILLED — 두 빈칸을 채운 설정
# 연결된 구성요소: API -> Claude Code 작업 -> MCP 서버 fetched = code_task.run(fetch_url=customer_page) # 빈칸 1: 신뢰할 수 없는 '가져온 콘텐츠'를 받는 이음매의 장치 next_call(input=treat_as_data(fetched)) # MCP 서버가 고객 시스템에 닿는다 (가장 권한이 큰 구성요소) mcp_server = MCPServer( system=customer_db, scope=least_privilege_read_only, # 빈칸 2: 신원 범위 )
빈칸 1은 가져온 콘텐츠를 감싸서, 다음 구성요소가 그것을 지시가 아니라 데이터로 다루게 하고, 이렇게 인젝션 이음매가 닫힙니다. 빈칸 2는 가장 권한이 큰 구성요소를 최소 권한으로 좁혀, 조종당한 동작이 자기 일의 범위를 넘지 못하게 합니다. 두 장치가 함께 걸리면 두 경계 모두 검토를 통과할 수 있는 상태로 유지됩니다.
다음 장은 모듈 5에서 배운 내용을 하나로 모아 실제 과제로 풀어 보는 누적 과제입니다. → 누적 과제로 이어집니다
전 코스는 계속 무료입니다. 등록하면 이 코스의 남은 38개 레슨을 끝까지 읽을 수 있습니다.
이미 등록하셨다면 그때 쓰신 이메일을 넣어 주세요.