태그 보관물: AST

REST와 gRPC가 사라진다면? AST 레벨에서 런타임을 브릿징하는 파격적 상상

대표 이미지

REST와 gRPC가 사라진다면? AST 레벨에서 런타임을 브릿징하는 파격적 상상

API 컨트롤러와 인터페이스 정의 없이, 원격 메서드를 로컬 함수처럼 호출하는 '런타임 브릿징'의 가능성과 한계

가끔 코딩하다 보면 이런 생각 들 때 없으세요? “아니, 그냥 옆에 있는 함수 하나 호출하는 건데 왜 이렇게 할 일이 많지?” REST 컨트롤러를 만들고, proto 인터페이스를 정의하고, HTTP 상태 코드를 일일이 매핑하는 그 모든 ‘통합을 위한 코드’들 말이에요. 만약 이 모든 과정을 완전히 걷어내고, 오직 public 메서드 호출만으로 원격 실행이 가능하다면 어떨까요? [1]

사실 제가 하고 싶은 말은 이거예요. 통신 프로토콜을 정의하는 지루한 코드 대신, AST(추상 구문 트리) 레벨에서 개발자의 의도를 가로채 원격 런타임으로 바로 전달한다면 어떨까요? 네트워크 투명성을 극대화해서 통합 비용을 제로로 만들 수 있을지도 모른다는 상상이죠.

우리는 왜 여전히 ‘통신을 위한 코드’를 쓰는가

우리가 흔히 쓰는 REST나 gRPC, 정말 편리하죠. 하지만 시니어 입장에서 보면 이 방식들이 주는 피로감이 상당합니다. 비즈니스 로직은 정작 몇 줄 안 되는데, 그걸 외부에 노출하기 위해 작성하는 ‘껍데기 코드’가 너무 많거든요. REST 컨트롤러를 만들고, 라우팅을 설정하고, 에러 상황마다 적절한 HTTP 상태 코드를 매핑하는 작업들. 이거 다 비즈니스 로직과는 상관없는 ‘통합 전략’을 위한 부가 코드들입니다 [1].

클라이언트 쪽은 더 심해요. 서버가 만든 엔드포인트를 호출하기 위해 전용 클라이언트 코드를 또 중복해서 구현해야 하죠. 제가 예전에 .NET Nuget 라이브러리를 쓸 때를 생각해보면, 그냥 메서드 호출하고 예외 처리만 하면 끝이었거든요. 그런데 이걸 원격으로 옮기는 순간 갑자기 복잡한 인터페이스 계층이 강제됩니다.

“Why if I want to use it remotely I should expose the same method via REST, map it to routes, strange parameters, http codes and next call that on other end?” [1]

(왜 원격으로 사용하고 싶을 때 똑같은 메서드를 REST로 노출하고, 경로와 이상한 파라미터, HTTP 코드에 매핑한 뒤 반대편에서 호출해야 하는 걸까요?)

결국 우리는 ‘통신’이라는 물리적 제약을 해결하기 위해 너무 많은 시간을 낭비하고 있는 셈입니다.

런타임 브릿징: AST 레벨에서 의도를 가로채다

그럼 여기서 ‘런타임 브릿징’이라는 파격적인 아이디어를 던져볼게요. 핵심은 코드가 실제로 실행되기 전, AST(Abstract Syntax Tree, 추상 구문 트리) 단계에서 개발자의 의도를 인터셉트하는 겁니다 [1, 8].

쉽게 설명하자면 이렇습니다. 개발자가 remoteService.unzip(file)이라는 코드를 썼을 때, 컴파일러나 런타임이 “아, 이건 로컬 실행이 아니라 원격 런타임으로 보내야 하는 의도구나!”라고 가로채는 거죠. 그리고 이 ‘의도’ 자체를 네트워크를 통해 원격 런타임으로 쏴주고, 거기서 실행된 결과값만 다시 받아오는 방식입니다 [1, 8].

“intercepting developer intention at abstract syntax tree so when you perform operation in code before it gets executed and just send it to the remote runtime fulfill job there and return result.” [1]

(추상 구문 트리에서 개발자의 의도를 가로채어, 코드가 실행되기 전에 원격 런타임으로 보내 작업을 수행하고 결과를 반환받는 방식입니다.)

이게 가능하려면 네이티브 레벨에서 런타임끼리 브릿징이 되어야 합니다. 그러면 기술 스택이 다르든, 메모리 위치가 로컬이든 원격이든 상관없이 그냥 메서드 호출만으로 모든 게 해결됩니다. 정적 메서드는 상태 없이(Stateless) 처리하고, 인스턴스 메서드는 스티키 세션(Sticky Session)을 통해 상태를 유지(Stateful)하는 식으로 구현할 수 있겠죠.

이런 개념을 코드로 상상해본다면 아마 이런 모습일 겁니다. 실제로는 런타임 엔진이 이 작업을 수행하겠지만, 개발자가 느끼는 경험은 이렇겠죠.

# 런타임 브릿징 설정 예시 (가상의 설정 파일)
runtime_bridge:
  services:
    - name: "FileProcessor"
      remote_node: "10.0.0.5" # 원격 노드 주소
      binding: "native"       # AST 레벨 브릿징 사용
      session_strategy: "sticky" # 인스턴스 메서드 상태 유지를 위해 설정
  transport:
    channel: "http2"          # DevOps가 코드 수정 없이 여기서 채널 변경 가능
    timeout: "500ms"          # 네트워크 타임아웃 설정

위 설정이 적용되어 있다면, 개발자는 더 이상 HttpClientgRPC Stub를 만들 필요가 없습니다. 그냥 FileProcessor 객체의 메서드를 호출하면, 런타임이 알아서 설정된 remote_node로 의도를 전달하고 결과를 가져옵니다.

이 상상이 실현되었을 때의 DX 혁신

만약 이게 정말 실현된다면, 개발자 경험(DX)은 그야말로 혁명적인 수준으로 바뀔 겁니다. 우선 코드베이스가 극단적으로 깨끗해지겠죠. 통신을 위해 억지로 끼워 넣었던 보일러플레이트 코드들이 완전히 사라지니까요.

더 흥미로운 건, 우리가 설계 단계에서 그렸던 UML 다이어그램과 실제 구현 코드가 완벽하게 일치하게 된다는 점입니다 [1]. 추상화 계층이라는 이름의 ‘가짜 벽’ 없이, 도메인 모델 그대로 원격 호출을 할 수 있게 되니까요.

유지보수 측면에서도 이득이 큽니다. 인터페이스 파일(.proto 등)을 관리하거나 매핑 코드를 수정할 필요가 없으니, 사람이 실수할 확률이 줄어들고 AI가 코드를 생성할 때 쓰는 토큰 소모량까지 줄어들 겁니다. 인프라 유연성도 엄청나게 좋아집니다. 개발자는 그냥 메서드 호출 코드만 짜고, 실제 전송 채널을 WebSocket으로 할지 TCP/IP로 할지는 DevOps 엔지니어가 설정 파일 하나로 결정할 수 있게 되거든요 [1].

현실적인 장벽: 투명성의 함정과 분산 시스템의 난제

물론, 시니어로서 여기서 “와, 대박이다!” 하고 끝낼 수는 없습니다. 분산 시스템에는 절대 변하지 않는 물리적 법칙이 있거든요. 가장 큰 문제는 ‘네트워크 투명성(Network Transparency)’의 함정입니다.

로컬 함수 호출은 나노초 단위로 끝나지만, 원격 호출은 밀리초 단위가 걸립니다. 그런데 이걸 로컬 호출처럼 똑같이 보이게 만들면, 개발자는 이 호출이 원격이라는 사실을 잊고 루프 안에서 수천 번 호출하는 실수를 저지를 수 있습니다. 그러면 시스템 성능은 예측 불가능하게 곤두박질치겠죠 [6].

또한 ‘부분 실패(Partial Failure)’라는 무서운 놈이 있습니다. 로컬 호출은 프로세스가 죽으면 다 같이 죽는 ‘운명 공동체’지만, 원격 호출은 서버만 죽거나, 네트워크만 끊기거나, 응답만 늦게 오는 등 아주 다양한 실패 시나리오가 존재합니다 [6].

“3 properties of distributed computing that make achieving RPC transparency difficult: Partial failures, Latency, Memory access” [6]

(RPC 투명성을 달성하기 어렵게 만드는 분산 컴퓨팅의 세 가지 특성: 부분 실패, 지연 시간, 메모리 접근 방식입니다.)

보안 문제도 빼놓을 수 없죠. 서로 신뢰하지 않는 두 런타임 사이에서 타입 안전성(Type Safety)을 보장하려면 결국 엄격한 직렬화와 검증 과정이 필요한데, 이 과정에서 발생하는 오버헤드가 ‘단순한 메서드 호출’이 주는 성능 이점을 다 깎아먹을 가능성이 큽니다 [2].

짚고 넘어갈 한계와 안티패턴

여기서 우리가 경계해야 할 안티패턴이 하나 있습니다. 바로 “네트워크를 숨기려는 욕심”입니다. 로컬 호출처럼 보이게 만드는 투명성은 언뜻 달콤해 보이지만, 실제로는 네트워크 지연과 부분 실패라는 분산 시스템의 본질을 무시하게 만들어 시스템을 훨씬 더 취약하게 만듭니다 [6].

또한, 타입 안전한 언어 환경에서 서로 다른 런타임을 브릿징하려면 결국 복잡한 직렬화(Serialization) 과정이 필수적입니다 [10]. “그냥 호출만 하면 된다”는 마법 같은 말 뒤에는, 사실 엄청난 양의 데이터 변환과 무결성 검증이라는 비용이 숨어 있다는 점을 잊어서는 안 됩니다 [2, 10].

핵심 요약

  • 통합 보일러플레이트 제거는 모든 개발자의 꿈이지만, 네트워크의 물리적 실체(Latency, Failure)를 완전히 지울 수는 없습니다.
  • AST 인터셉션 기반의 런타임 브릿징은 DX를 비약적으로 높여주지만, 명시적인 계약(Contract)이 사라졌을 때의 버전 관리 리스크를 동반합니다.
  • 분산 시스템을 설계할 때는 ‘투명성(Transparency)’으로 편해질 것인가, ‘명시성(Explicitness)’으로 안전할 것인가 사이의 트레이드오프를 항상 고민해야 합니다.
  • 이런 접근법은 내부망(Internal Mesh)처럼 서로 신뢰하는 환경에서는 혁신적일 수 있지만, 외부 공개 API에서는 여전히 엄격한 계약이 필요합니다.

기술적 ‘마법’이 주는 유혹은 정말 강렬합니다. 하지만 시니어 엔지니어라면 그 마법 뒤에 숨겨진 비용을 계산할 줄 알아야 하죠. 그렇다고 이 상상이 무의미한 건 아닙니다. 이런 파격적인 상상들이 모여 결국 gRPC나 REST 같은 표준을 만들어냈으니까요. 런타임 브릿징의 시도가 언젠가 차세대 통신 패러다임의 씨앗이 되길 기대해 봅니다.


참고 자료 (References)

1. [reddit.com] Is it the end of REST, gRPC, Thrift, SignalR and GraalVM? — https://www.reddit.com/r/programming/comments/1u8nxc7/is_it_the_end_of_rest_grpc_thrift_signalr_and/ 2. [cs.cornell.edu] Security versus Performance Tradeoffs in RPC Implementations for Safe Language Systems — https://www.cs.cornell.edu/info/people/chichao/ew98-1.pdf 6. [cs.ubc.ca] 416 Distributed Systems – RPC overview — https://www.cs.ubc.ca/~bestchai/teaching/cs416_2021w2/lectures/lecture-jan18.pdf 8. [wikipedia.org] Abstract syntax tree — https://en.wikipedia.org/wiki/Abstract_syntax_tree 10. [wikipedia.org] Serialization — https://en.wikipedia.org/wiki/Serialization

관련 글 추천

  • https://infobuza.com/2026/06/18/20260618-3vdwjx/
  • https://infobuza.com/2026/06/18/20260618-xnub2z/

FAQ

런타임 브릿징이란 무엇인가요?

코드가 실행되기 전 AST(추상 구문 트리) 단계에서 개발자의 의도를 가로채어, 로컬 함수 호출처럼 보이지만 실제로는 원격 런타임으로 전달해 실행하고 결과값만 받아오는 방식입니다.

런타임 브릿징이 실현되면 개발자 경험(DX) 측면에서 어떤 이점이 있나요?

REST 컨트롤러나 gRPC Stub 같은 통신용 보일러플레이트 코드가 사라져 코드베이스가 깨끗해지며, UML 다이어그램과 실제 구현 코드가 일치하게 됩니다. 또한 전송 채널 설정을 DevOps 엔지니어가 설정 파일만으로 변경할 수 있어 인프라 유연성이 높아집니다.

런타임 브릿징의 핵심 기술적 구현 아이디어는 무엇인가요?

AST 레벨에서 의도를 인터셉트하여 네이티브 레벨에서 런타임끼리 브릿징하는 것입니다. 정적 메서드는 상태 없이(Stateless) 처리하고, 인스턴스 메서드는 스티키 세션(Sticky Session)을 통해 상태를 유지(Stateful)하는 방식으로 구현할 수 있습니다.

런타임 브릿징을 구현할 때 직면하게 되는 현실적인 장벽은 무엇인가요?

로컬 호출과 원격 호출의 지연 시간(Latency) 차이로 인한 성능 예측 불가능성, 서버 다운이나 네트워크 단절 같은 '부분 실패(Partial Failure)' 문제, 그리고 서로 다른 런타임 간의 타입 안전성 보장을 위한 직렬화 오버헤드 등이 있습니다.

분산 시스템에서 '네트워크 투명성'을 추구할 때 주의해야 할 점은 무엇인가요?

네트워크를 완전히 숨기려는 욕심은 개발자가 원격 호출의 특성(지연 및 실패 가능성)을 무시하게 만들어 시스템을 더 취약하게 만들 수 있습니다. 따라서 투명성으로 인한 편의성과 명시성으로 인한 안전성 사이의 트레이드오프를 고려해야 합니다.

보조 이미지 1

보조 이미지 2