8P by GN⁺ 2일전 | ★ favorite | 댓글 2개
  • 최근 AI 에이전트의 도입이 증가하면서, Go 언어 기반의 하이브리드 스택 활용이 늘어나는 추세임
  • 에이전트는 긴 실행 시간높은 비용, 그리고 입출력 대기가 잦은 특성을 가짐
  • Go는 경량 고루틴, 중앙집중적 취소 메커니즘, 채널 기반 메시징고성능 동시성 모델을 제공함
  • 표준 라이브러리가 방대하며, 프로파일링 도구(pprof)로 메모리 및 스레드 누수 추적이 용이함
  • 단, Go는 머신러닝 생태계 부족썩 뛰어나지 않은 최고 성능, 타 언어 대비 낮은 서드파티 지원 등의 한계도 존재함

에이전트란 무엇인가

  • 에이전트는 반복 루프에서 실행되며, 다음 실행 단계를 스스로 결정할 수 있는 프로세스를 의미함
  • 워크플로우처럼 미리 정의된 경로가 아니라, 조건(예: “테스트 통과”)이나 최대 반복 횟수 등으로 종료 여부를 판단함
  • 실제 서비스 시, 에이전트는 수 초~수 시간에 걸쳐 장시간 실행되고, LLM 호출·브라우저 조작 등으로 비용이 높음
  • 사용자의 입력(또는 다른 에이전트의 입력)을 처리해야 하므로, 입출력(I/O) 대기 시간이 많음

Go 언어가 에이전트에 적합한 이유

고성능 동시성

  • Go의 고루틴은 2KB의 메모리만으로 수천~수만 개의 경량 스레드를 동시 실행 가능
  • 각 고루틴은 멀티코어를 활용해 병렬 처리하며, I/O 및 대기 상태의 에이전트도 부담 없이 운영 가능
  • 채널(Channel) 기반 통신을 통해 메모리 공유 대신 메시지 전달로 동기화 구현 (Mutex 사용 최소화)
  • 에이전트가 비동기로 메시지를 주고받으며 상태를 관리하기에 적합

중앙집중적 취소 메커니즘

  • Go의 context.Context 활용 시, 대부분의 라이브러리·API가 취소 신호를 지원하므로 실행 중단이 매우 쉬움
  • Node.js나 Python은 여러 취소 패턴이 혼재해 있지만, Go는 일관된 방식으로 안전하게 취소 및 자원 회수 가능

풍부한 표준 라이브러리

  • Go는 표준 라이브러리가 방대하며, HTTP/웹, 파일, 네트워크 I/O 등 거의 모든 영역 지원
  • 모든 I/O는 고루틴 내에서 블로킹 동작을 가정하여 비즈니스 로직을 직선형(스트레이트라인)으로 작성 가능
  • Python은 asyncio, 스레딩, 프로세스 등 다양한 동시성 패턴이 혼재해 복잡함

프로파일링 및 진단 도구

  • Go의 pprof 등 내장 도구로 메모리 누수, 고루틴(스레드) 누수를 실시간 추적 가능
  • 장시간·동시 실행되는 에이전트에서 발생할 수 있는 누수 문제 진단에 강점

LLM 코딩 지원 우수

  • Go는 단순한 문법과 풍부한 표준 라이브러리 덕분에 LLM이 고유의 Go 스타일 코드를 잘 작성함
  • 프레임워크 의존성이 낮아 LLM이 버전이나 패턴에 신경 쓸 필요가 적음

Go의 한계점

  • 서드파티 라이브러리 및 생태계가 Python, TypeScript 대비 부족
  • 머신러닝 직접 구현에는 적합하지 않음 (성능과 지원이 한계)
  • 최고 성능이 필요한 경우 Rust, C++이 더 나음
  • 에러 핸들링에 관대한 개발자에게는 다소 불편할 수 있음

자바보다는 고 고보다는 러스트 :)

Hacker News 의견
  • 대부분의 에이전트 시스템에서 가장 큰 지연 요소는 결국 LLM 호출임을 강조함. 기사에서 언급한 장점들은 특정 언어에 유리하지 않으며, 대부분 장시간 기다림과 비싼 리소스 사용, 사용자 또는 다른 에이전트로부터의 입력, 그리고 I/O 대기 시간이 크다는 것임. 이런 특성상 서버 실행 속도나 효율성보다는, 오히려 Python 같은 언어가 가진 방대한 AI 라이브러리와 지원이 더 중요한 장점임을 주장함. Python에서 asyncio나 멀티스레딩 라이브러리를 고민해야 한다는 지적도 있으나, 실제로 에이전트 개발은 그리 어렵지 않고 이미 누군가 관련 워크플로우를 개발한 경험이 있기 때문에 쉽게 시작할 수 있다고 생각함

    • Go로 에이전트를 구축할 때는 동시성과 백프레셔 관리 패턴이 잘 정립되어 있다는 점이 큰 장점임을 경험함. 에이전트는 대부분 느린 외부 서비스와의 트랜잭션이 포함되고 이런 작업에 Go의 동시성 패턴이 매우 유용함. 물론 언어는 크게 상관없고, JavaScript가 가장 많이 사용되는 듯함. 단, 코드 생성이라면 Go와 LLM의 조합에 좋은 시너지가 있다고 느낌

    • Go는 뛰어난 동시성 처리가 가능하고, 배포도 쉽다는 점에서 Python과 차별점이 있음. Go는 스태틱 바이너리만 배포하면 되기 때문에 Python의 환경 및 의존성 문제에서 자유로움

    • 에이전트는 오케스트레이션 계층 역할을 하는데 Go, Erlang, Node가 특히 적합하다고 생각함. 대량의 AI 관련 라이브러리가 꼭 필요한 건 아니고, IO가 많은 작업은 도메인별 툴 인터페이스 뒤에 추상화해서 필요한 언어로 서브시스템을 만들면 된다는 점을 강조함

  • Go는 이런 종류의 워크로드에서 크게 이점이 없는 편이고, 대부분 시간을 IO 대기에 할애함. Go의 타입 시스템이 제한적이며, 최신 언어에서는 기본 제공되는 많은 기능들을 Go에서는 우회해야 함. TypeScript는 AI 용도로 우수한 글루 언어이며, Python과 함께 라이브러리 지원이 매우 좋음. 내가 Python보다 TypeScript를 선호하는 이유는 타입 시스템이 훨씬 더 강력하고 성숙했기 때문임. Python도 빠르게 개선되고 있음. Node.js와 Python에서 롱런닝 작업 중단이 매우 어렵다는 주장은 확적한 근거가 없다고 봄. 대부분의 도구가 이 기능을 이미 지원하고 있고 주요 언어는 Python과 JS임

    • 성능이 정말 필요하다면 V8보다 빠른 C++이나 Rust로 네이티브 모듈을 작성하는 방식을 선호함. Go까지 갈 필요가 없음
  • Elixir와 BEAM 기반 에이전트 프레임워크를 실험해 봤는데, BEAM과 SQLite 조합이 현시점에서 에이전트에게 가장 이상적이라고 생각함. 에이전트를 어플리케이션 재배포 없이 안전하게 교체할 수 있고, BEAM의 동시성은 이 작업에 충분히 여유로움. 상태 기반이나 임시 에이전트 구현도 매우 쉬움. 앞으로 Python, Typescript, Rust로 베이스 에이전트를 구축하고 각 언어 선호도에 따라 복잡한 에이전트 개발이 가능하도록 MCP 서버도 만들 예정임

    • Extism 프로젝트와 Elixir SDK를 추천함. 이 조합을 활용하면, Elixir로 코어 서비스·라우팅·메시지 패싱을 만든 뒤, BEAM/OTP의 이점을 살릴 수 있고, 다른 언어로 작성된 작고 경량적인 Wasm 모듈 형태의 에이전트도 플러그인처럼 임베딩 가능함
      Extism
      Elixir SDK

    • BEAM의 내장 데이터 스토어인 mnesia 대신 SQLite를 선택한 이유가 있는지 궁금함
      mnesia docs

  • 에이전트의 대부분 시간은 LLM 응답 대기 및 외부 서비스(API, DB) 호출에 쓰임. 언어 런타임의 성능 영향이 실제론 거의 없음. 에이전트 성능과 확장성에 진짜 중요한 언어 기능이라면, JSON 직렬화와 역직렬화 성능이 될 것임

    • 그래서 네이티브로 JSON을 다루는 TypeScript 같은 언어를 쓰는 게 낫다고 생각함. TypeScript 타입 시스템은 Go보다도 훨씬 강력함

    • 경험상 LLM 호출 이외에 에이전트에서 가장 비용이 많이 드는 것은 비동기 편집(merge, diff, patch) 충돌 해결임. 이 작업도 저수준 라이브러리로 위임할 수 있지만, 직렬화만큼이나 최적화가 어려운 문제임

  • ampcode.com의 에이전트 구축 가이드가 떠오름. Python은 동적 언어 특성 덕분에 데코레이터로 메소드를 툴 호출로 바로 변환하거나, 툴 함수 반복으로 리스트 생성, JSON 스키마로 빠르게 변환하는 등 활용이 자연스러움. 반면, 여러 외부 트리거(예: 유저 입력, Gmail 메일, Slack 메시지 등)로 새로운 에이전트 실행을 유발하는 구조는, Go의 채널과 switch for loop 활용이 훨씬 직관적이었음. Python에선 여러 큐와 스레딩을 따로 만들어야 해서 복잡함

  • 기사 논리를 따진다면 Elixir는 에이전트에 이상적임

  • Go의 제한적이고 부족한 타입 시스템은 거의 모든 애플리케이션에 부적합함. 실제로 Go의 가장 큰 단점은 언어 자체라고 평가함. 언어 외적인 부분이 오히려 Go를 용납하게 만든 요인임

    • 몇 년간 Go로 프로그래밍을 했지만 타입 시스템 문제가 많다는 데 동의함. LLM 분야 사람들은 거의 Python이나 JavaScript만 쓰는 것 같음. 모두 최신 언어로 이동해야 한다고 생각하지만, Go가 Python/JavaScript의 난잡한 임포트와 패키지 문제에 비해 그나마 나은 선택일 수 있음

    • Go 타입 시스템의 한계가 에이전트 제작에 어떻게 걸림돌이 되는지 구체적으로 듣고 싶음

    • 실상 Go에 정적 타입 시스템이 들어간 건, 성능 요구를 달성할 방법을 찾지 못했기 때문임. 실제로 동적 타이핑 언어처럼 쓰인다고 보는 게 맞고, 언어 설계 목적을 잘못 이해한 결과임. 동적 타이핑 언어가 전반적으로 부적합하다고 주장할 수 있지만, 실제로 Python, Erlang, Elixir 등 동적 타이핑 언어가 활발히 쓰이는 점에서 오히려 동적 타이핑이 문제 도메인에 더 적합함

    • 여러 리턴값이 합성되지 않고, 에러 지원은 익셉션보다 낫지만 매우 장황하며, 채널은 실수하기 쉽고, enum 타입은 실망스럽다고 느낌. 그럼에도 불구하고 인터페이스는 의외로 잘 작동하고, 패키징 시스템은 꽤나 매끄러움. Rust를 배우면서 file structure가 Go보다 훨씬 복잡하다는 점을 알게 됨. 심지어 언어가 단순하다 보니 다양한 린터/코드 생성 도구를 만들기에도 수월함. Go 코드 장기 유지보수는 Python/JS 대비 걱정이 적음

    • 만약 Go로 컴파일되는 LISP/Scheme 방언이 잘 유지된다면 정말 좋겠음

  • 오래 기다리는, 실행 비용이 높은 프로세스에서는 프로세스가 죽으면 모든 작업을 잃는다는 점이 단점임. 기다리는 동안 상태를 데이터베이스에 직렬화하는 게 더 안전할 수 있지만, 이걸 쉽게 구현하는 언어는 없는 것 같음. 체크포인트 기반 상태 머신 작성이 쉽지 않음

    • 체크포인트 기반 상태 머신은 Hatchet(hatchet.run), Temporal(temporal.io) 같은 플랫폼이 제공하는 핵심 기능임을 설명함. 워크플로우 내 함수 실행 이력을 저장하고, 인터럽트 발생 시 자동으로 이력을 재생함. 메모리 싱크보다 아웃풋 단위 진행 이력이 훨씬 효율적임을 주장함. (Hatchet 창업자)

    • goroutine, 스레드, 장기 실행 체인은 결국 atomic한 작업 단위로 쪼개고, 상태 직렬화가 필수임. 실패 복구, 에러 추적, 결과 재참조, 멀티 노드 분산 등의 요구를 충족함. Oban(github.com/oban-bg/oban) 프레임워크(Elixir)가 이 방식이고, 비동기 작업 영속화의 중요성을 강조한 Oban 기사도 추천함. (Oban 저자)

    • golang 기반 에이전트 라이브러리를 개발 중인데, 충분한 로깅만 있으면 언제든 에이전트 상태를 복원할 수 있다는 생각이 들었음. 타임스탬프와 부모 실행(run)만 알면 자식/분기 실행 트리를 쌓을 수 있음. 맵과 DB를 함께 활용해서 세션을 관리하고 필요시 재구축 가능함. 개별 오브젝트를 들고 있지 않고, stateless 오브젝트는 맵에서 id로 찾아써서 이전 액션, 스텝, 컨텍스트를 상태 오브젝트에 두는 구조임. 에이전트/워크플로우 일관성 역시 결과를 해시로 관리해 해결. 아직은 기본적인 에이전트/툴만 구현했고, 로깅과 복원, 취소 로직은 미개발 상태임

    • Temporal은 장기 프로세스 체크포인팅에 꽤 유용하고, 언어에도 중립적임

    • 나도 작업 큐를 고민하다가, Postgres에 rudimentary queue를 만들까 고민 중임. 장점은 서버간 워크로드 분산, 프로세스 종료 후 태스크 손실 방지, 더 나은 가시성 확보임. 대신 코드 복잡성이 크게 증가할 수 있어서 아키텍처를 쉽게 설계하는 게 어렵다고 느낌

  • AI 엔지니어들은 JavaScript 사용을 극도로 꺼림. TensorFlow for Swift가 중단된 것이 AI 언어 다양성의 종말이었음

    • JavaScript 기피는 AI 엔지니어에게만 해당하는 일이 아니라고 생각함. 30년 넘게 JS 코딩해 본 사람 입장에서도 동감함

    • JS는 언어로서 매우 형편없고, 백엔드에 갖고온 건 실수라고 생각함. TypeScript도 결국 기반에 깔린 JS의 문제를 해결하지 못함. JS나 TS를 쓰는 일은 피하고 Go, Rust, Python, Ruby, Elixir, F# 등 다른 대안을 선호함

    • JS가 에이전트에 특별히 좋은 이유가 궁금함

  • ML 분야에서 더 나은 동시성 모델이 필요하다고 느낌. Go로 ML을 시도해봤지만 라이브러리 지원 부족과 외부 gRPC 호출 또는 래퍼에 의존해야 해서 사실상 불가능함. Python은 한계가 있고 C++는 장황해서 생산성 저하 요인이 많음