노트북에서 돌리던 AI 코딩 에이전트를, 지하철에서 휴대폰 브라우저로 열어 이어서 조작해본 적이 있는가. 편리하다. 그런데 그 순간 질문 하나가 따라온다. 노트북 앞에서 내가 눌렀던 "이 명령은 허용, 이건 확인질문"이라는 결정이, 휴대폰 화면 너머에서도 똑같이 지켜지고 있는가. 지켜지지 않는다면 그건 편의 기능이 아니라 구멍이다.

로컬 세션 하나짜리 에이전트는 문이 하나다. 그 문 앞에 서 있는 사람과 명령을 내리는 사람이 항상 같다. 그런데 세션을 원격으로 열어주는 순간 문이 하나 더 생긴다. 두 번째 문으로 들어온 요청이 첫 번째 문에서 정한 규칙을 그대로 따르는지, 아니면 슬쩍 우회하는지는 설계자가 직접 확인해야 하는 문제다. 이 글은 그 "두 번째 문"을 안전하게 다는 원칙을 다룬다. 특정 제품의 내부 구조 대신, 세션 신원·재인증·권한 범위 축소·감사 흐름이라는 일반화된 아키텍처 개념으로 풀어본다.

문 하나가 새로 생기면 자물쇠도 새로 달아야 한다

비유로 시작하자. 집에 현관문 하나만 있을 때는 그 문 앞에 있는 사람이 곧 집주인이라고 믿어도 된다. 그런데 뒷마당에 문을 하나 더 달았다고 하자. 뒷문에도 현관문과 똑같은 열쇠 규칙을 적용하고 있는가, 아니면 급하게 다느라 자물쇠를 깜빡했는가. AI 에이전트를 원격으로 열어준다는 건 이 뒷문을 다는 일과 같다.

로컬 터미널에서만 돌아가는 에이전트는 "지금 화면 앞에 있는 사람"과 "명령을 내리는 사람"이 물리적으로 같다. 확인질문 팝업이 뜨면 그 사람이 바로 답한다. 그런데 원격 접속을 붙이면 이 등식이 깨진다. 명령을 내리는 곳(휴대폰 브라우저)과 실제로 파일이 지워지고 코드가 실행되는 곳(집에 켜둔 노트북)이 물리적으로 분리된다. 요청이 오가는 통로, 즉 로컬과 원격을 잇는 중계 지점(브리지)이 새로 생긴다.

이 통로는 단순한 화면 전송이 아니다. 명령, 실행 결과, 첨부 파일, 그리고 앞서 다룬 적 있는 "이 작업 해도 될까요"라는 확인질문까지 이 통로를 타고 오간다. 확인질문 하나가 이 통로를 통과한다는 게 핵심이다. 승인 여부를 묻고 답하는 절차 자체가 네트워크 밖으로 나갔다가 다시 들어온다는 뜻이다. 통로 설계가 허술하면, 원래는 사람에게 물어야 했던 위험한 명령이 누군가의 답 없이도 통과해버릴 수 있다.

로컬 터미널과 원격 브라우저 사이에 새로 생긴 중계 통로를 통해 명령·실행결과·승인요청이 오가는 구조를 보여주는 다이어그램
직접 생성한 오리지널 다이어그램.

원격 요청이 어느 세션 것인지부터 확인한다

원격 접속을 설계할 때 가장 먼저 걸리는 질문은 "이 요청이 어느 세션 것인가"다. 당연해 보이지만 놓치기 쉽다. 노트북에서 A 프로젝트 세션을 켜두고, 휴대폰에서는 B 프로젝트 세션을 열었다고 하자. 두 요청이 뒤섞이면 어떻게 될까. B 프로젝트를 보려던 사람이 실수로 A 프로젝트 파일을 지우는 명령을 승인해버릴 수 있다.

그래서 원격 요청 하나하나에는 반드시 꼬리표가 붙어야 한다. "이 요청은 어느 로컬 세션에서 시작됐고, 어느 작업 폴더에 묶여 있는가"를 밝히는 식별자다. 이 식별자가 없으면 브리지는 그냥 파이프일 뿐이다. 무슨 요청이든 실어 나르지만, 그게 누구 것인지는 모른다. 반대로 식별자가 확실하면, 여러 세션이 동시에 원격으로 열려 있어도 요청과 승인이 엉키지 않는다.

세션 신원 확인은 한 번 하고 끝나는 일이 아니다. 접속이 유지되는 동안 계속 유효해야 한다. 중간에 세션이 끊겼다가 다시 붙었을 때, 이전 요청이 새 세션에 잘못 이어 붙는 일이 없어야 한다. 이건 원격 기능을 처음 설계할 때부터 세션 경계를 명확히 그어두지 않으면 나중에 고치기 어려운 부분이다.

연결이 새로 열릴 때마다 신원을 다시 묻는다

세션 식별만으로는 부족하다. 그 요청을 보낸 게 진짜 나인지도 확인해야 한다. 로컬 터미널은 애초에 그 컴퓨터에 로그인할 수 있는 사람만 만질 수 있다는 전제가 깔려 있다. 하지만 원격 접속은 이 전제가 사라진다. 인터넷 어딘가에서 접속을 시도하는 게 나인지, 아니면 내 접속 정보를 훔친 다른 사람인지 브리지는 구분하지 못한다.

그래서 원격 연결이 새로 열릴 때는 로컬에서 쓰던 신원 확인을 그대로 재사용하면 안 된다. 새 연결마다 별도의 인증 절차를 다시 거쳐야 한다. 여기서 중요한 설계 원칙 하나가 등장한다. 원격 접속에 쓰이는 인증 정보(토큰)는 로컬 세션 전체를 다 열어주는 만능키가 아니라, 딱 그 연결 하나에만 쓸 수 있는 범위로 제한돼야 한다는 것이다. 이걸 세션 토큰 범위 제한(scoped session token)이라고 부른다. 호텔 카드키가 내 방 하나만 열리고 옆방은 안 열리는 것과 같은 원리다.

범위가 제한된 토큰은 두 가지를 동시에 해결한다. 첫째, 토큰 하나가 유출돼도 피해가 그 연결 하나로 끝난다. 둘째, 연결을 끊으면 그 토큰도 같이 무효가 되므로, 오래된 접속이 좀비처럼 남아 계속 명령을 실행하는 일을 막는다. 반대로 토큰 범위를 좁히지 않고 로컬 신원을 통째로 복사해 넘기면, 원격 접속 하나가 뚫렸을 때 로컬 세션 전체가 함께 뚫린다.

스마트폰 화면에서 원격 접속 시 별도의 인증 코드를 입력해 세션 신원을 재확인하는 모습
새 연결이 열릴 때마다 신원을 다시 확인하는 과정을 표현한 이미지.

로컬에서 괜찮던 권한도 원격에서는 좁혀야 한다

여기서 흔한 착각이 하나 있다. "로컬에서 이미 허용된 명령이니 원격에서도 그대로 허용하면 되지 않나"라는 생각이다. 아니다. 로컬 환경은 화면 앞에 있는 사람이 실시간으로 상황을 보면서 판단할 수 있다는 전제가 있다. 원격 환경은 그 전제가 약해진다. 접속이 끊겼는지, 화면이 잠깐 안 보이는 사이 뭔가 실행됐는지 사람이 놓치기 쉽다.

그래서 같은 작업이라도 원격 접속 지점에서는 로컬보다 보수적으로 판정하는 게 맞다. 비유하면, 집 안에서는 손님에게 냉장고를 자유롭게 열게 해줄 수 있어도, 초인종으로 연결된 택배 기사에게는 현관까지만 들여보내는 것과 같다. 같은 사람이라도 어느 문으로 들어왔는지에 따라 허용 범위가 달라질 수 있다는 뜻이다.

실무적으로는 두 가지를 점검한다. 첫째, 원격 경로로 들어온 요청에 한해 확인질문 문턱을 낮출지 결정한다. 로컬에서는 자동 허용됐던 명령도, 원격에서는 한 번 더 확인을 거치게 할 수 있다. 둘째, 원격 접속 자체가 로컬에만 있던 기능(파일 시스템 직접 접근, 시스템 명령 실행 같은 것)까지 그대로 노출하고 있는 건 아닌지 확인한다. 로컬 전용으로 설계했던 기능이 네트워크 표면으로 슬쩍 새어 나가는 경우가 실제로 자주 있다. 처음 설계할 때는 로컬만 생각하고 만든 기능인데, 나중에 원격 계층을 얹으면서 그 기능도 덩달아 원격에서 접근 가능해지는 식이다.

결국 원격 브리지는 로컬 권한 판정 위에 별도의 축소 계층을 하나 더 얹는 구조가 돼야 한다. 로컬에서 허용, 거부, 확인질문으로 갈리던 판정이 있다면, 원격 경로에서는 그 판정 결과에 "이건 네트워크 너머에서 온 요청"이라는 조건을 한 번 더 곱해야 한다. 곱한 결과가 원래보다 관대해지는 일은 없어야 한다.

요청한 곳과 실행된 곳, 둘 다 기록에 남긴다

로컬 한 대에서만 돌아갈 때는 로그가 단순하다. 어떤 명령이 언제 실행됐는지만 남기면 됐다. 원격이 끼면 로그에 한 칸이 더 필요하다. "이 명령이 어디서 요청됐고 어디서 실행됐는가"라는 두 지점을 같이 남겨야 한다.

왜 두 지점이 다 필요할까. 사고가 났을 때 되짚어야 할 질문이 늘어나기 때문이다. 실행된 결과만 보면 "무슨 일이 일어났는지"는 알 수 있다. 하지만 "누가 그걸 시켰는지" "그 사람이 정말 원격에서 정당하게 접속한 사람이었는지"는 별도로 확인해야 한다. 요청 위치, 실행 위치, 그리고 승인이 이뤄진 위치까지 세 지점을 모두 기록해두면, 나중에 "이 명령이 왜 통과됐지"라는 질문에 정확히 답할 수 있다. 이 중 하나라도 빠지면 사고 조사는 추측에 의존하게 된다.

여기서 실용적인 팁 하나. 원격 기능을 처음 붙일 때는 이 로그부터 먼저 설계하는 게 낫다. 기능을 다 만들고 나서 로그를 나중에 끼워 넣으려 하면, 이미 통로가 여러 갈래로 갈라져 있어서 빠뜨리는 지점이 생긴다. 문을 달 때 자물쇠와 CCTV를 같이 설치하는 것과 같은 이치다.

요청 위치, 실행 위치, 승인 위치 세 지점이 하나의 감사 로그로 연결되어 사고 발생 시 역추적 가능한 구조를 보여주는 다이어그램
직접 생성한 오리지널 다이어그램.

이렇게 뜯어보고 나니 생각이 하나 정리됐다. 원격 접속은 "같은 세션을 다른 화면으로 보여주는 기능"이 아니라 "권한 경계가 하나 늘어나는 사건"에 가깝다. 편의 기능처럼 보이지만 실제로는 보안 설계를 새로 한 번 더 해야 하는 지점이다. 세션 신원, 재인증, 권한 축소, 양쪽 로그. 이 네 가지 중 하나라도 로컬 설계를 그대로 복사해 쓰면, 편리함을 얻는 대신 로컬에서 애써 만든 권한 경계가 원격 접속 지점에서 조용히 무너진다.

브리지를 설계할 때 점검할 것

비슷한 원격 확장 기능을 설계하거나 리뷰할 일이 생기면, 아래 표로 지점마다 뭘 확인해야 하는지 정리해뒀다.

확인 지점 답하는 질문 놓치기 쉬운 지점
세션 신원 확인 이 요청이 어느 로컬 세션 것인가 여러 세션이 동시에 원격으로 열렸을 때 요청이 뒤섞이는 경우
연결별 재인증 이 접속을 시도한 게 정말 그 사람인가 로컬 신원을 그대로 복사해 원격에 재사용하는 설계
토큰 범위 제한 이 인증 정보로 어디까지 할 수 있는가 연결 하나용 토큰이 세션 전체를 여는 만능키가 되는 경우
원격 권한 축소 같은 명령이 원격에서도 똑같이 안전한가 로컬 전용 기능이 원격 계층을 얹으며 그대로 노출되는 경우
양방향 감사 로그 어디서 요청되고 어디서 실행됐는가 실행 위치만 남기고 요청·승인 위치는 안 남기는 경우

이 표를 체크리스트로 바꾸면 이렇다.

  • 원격 요청마다 로컬 세션 식별자가 붙어 있는가.
  • 새 연결이 열릴 때마다 별도의 인증 절차를 다시 거치는가.
  • 원격 접속용 인증 정보가 연결 하나로 범위가 좁혀져 있는가.
  • 로컬 전용으로 설계된 기능이 원격 계층에서도 그대로 열려 있지 않은가.
  • 같은 명령이라도 원격 경로에서는 확인질문 문턱을 더 낮췄는가.
  • 요청 위치·실행 위치·승인 위치가 모두 로그에 남는가.

이 원칙은 코딩 에이전트에만 해당하지 않는다. AI 에이전트에게 일을 맡기기 전에 계약을 정하는 법에서 다룬 "무엇을 자동으로 허용할지 미리 정해두는 것"과 이 글의 원격 확장 원칙은 같은 뿌리다. 다만 이번엔 그 계약이 네트워크 너머까지 그대로 지켜지는지를 따진다는 점이 다르다. 문을 하나 더 달았다면, 그 문에도 처음 문과 똑같은 무게의 자물쇠를 달아야 한다.