개요
OpenCode를 알게 된 후부터 계속 어떻게 활용할 수 있을까를 고민하게 된다.
번뜩 떠오르는 무언가가 있는 것은 아니지만, 일상적인 부분에서 아이디어를 얻곤 한다. 이번에는 지난번 글의 마지막쯤 언급했던, Slack에서 OpenCode를 사용할 수 있도록 시스템을 구성해본 후기를 기록해보고자 한다.
무엇을 하는가 ?
이 아이디어는 클로드 코드의 사용 형태를 보고, 비슷하게 구성해볼 수 있지 않을까 하는 생각에서 출발했다.

클로드 코드의 Remote Control 기능은 데스크탑에서 실행 중인 클로드 코드 세션을 웹이나 모바일에서 원격으로 제어할 수 있는 기능이다. 즉, A 위치에서 시작한 작업을 B 위치에서 이어서 할 수 있는 형태다. 그렇다면 Slack + Local + OpenCode를 조합해 별도의 웹이나 모바일 환경을 새롭게 만들기보다는, 평소 사용하는 Slack을 인터페이스로 활용해보면 어떨까 하는 생각이 들었다.
Slack Bot을 통해 명령을 내리고, 이를 집에 있는 PC의 OpenCode로 전달한다면 클로드 코드의 Remote Control과 비슷한 형태의 환경을 만들어볼 수 있지 않을까 하는 아이디어다.
필요한 것들
이러한 아이디어를 구현하기 위해 필요한 것들은 도식에 드러냈듯이 다음과 같은 구성 요소가 필요하다.
각각의 구성요소에 대한 설명과 함께 어떤 셋팅이 필요했는지 키워드로 정리했고 해당 내용을 풀어보고자 한다.
- Slack Bot : Socket Mode와 App Token
- Listener Server : Antigravity로 뚝딱 만들기
- OpenCode : OpenCode는 API 찾아보기
Slack Bot : Socket Mode & App Token
Slack을 통해 입력을 하게 되는 경우 해당 처리를 해줄 Slack Bot이 필요하다. Slack Bot은 Slack 안에서 자동으로 메시지를 보내거나, 사용자의 명령을 받아 특정 작업을 수행하는 역할을 한다. 과거에는 특정 이벤트를 캐치하는 용도로 사용하곤 했다.
Slack Bot에 대한 세팅은 기존처럼 토큰을 발급받고 필요한 권한을 부여하는 식으로 하면 되지 않을까 싶었다. 그런데 한 가지 걸리는 부분이 있었다. Slack 명령어를 통해 Bot을 사용하고 Listener Server에서 해당 요청을 처리하려면, Slack에서 내 로컬 환경으로 요청을 전달할 수 있어야 했다. 문제는 Listener Server가 로컬 PC에서 실행되고 있다는 점이다. 그렇다면 외부에 서버를 노출하지 않고도 Slack과 로컬 환경을 연결할 수 있는 방법이 필요했다.
이 문제에 대한 해결책으로 ngrok을 통해 임시로 외부에서 접근할 수 있는 주소를 활성화히는 방법을 떠올렸다. 다만 실행할 때마다 주소가 변경되는 것도 번거롭고, Static Domain을 사용하는 것도 로컬에서 사용하는 것치고는 조금 거추장스럽다는 생각이 들었다.

그래서 다른 형태로 사용할 수 있는 방법이 없을까 찾아보다가 Slack의 Socket Mode를 알게 됐다. Socket Mode는 기존처럼 외부에 Request URL을 구성하는 대신, 로컬 애플리케이션이 Slack과 WebSocket 연결을 유지하면서 이벤트를 전달받는 방식이었다. 덕분에 Listener Server를 외부에 공개하지 않아도 됐다.


다만 기존의 Bot Token과 별도로 App Token이 필요했고, Slack App에서 Socket Mode를 활성화하는 설정도 추가로 필요했다.
지금까지의 내용을 표로 정리하면 아래와 같다.
| Events API | Socket Mode | |
| 연결 방식 | Slack → 내 서버 | 내 서버 → Slack |
| HTTP Endpoint | 필요 | 불필요 |
| WebSocket | 불필요 | 필요 |
| App Token | ❌ | ✅ |
| Bot Token | ✅ | ✅ |
| 로컬 개발 | 번거로움 | 편함 |
| 외부 서버 | 적합 | 가능 |
Listener Server : Antigravity로 뚝딱 만들기
Listener Server는 로컬 PC에서 돌아가는 간단한 Python Server다.
이 Server의 역할은 단순히 Slack Bot으로 전달된 명령을 내 PC에서 실행해주는 것이다. 이는 Antigravity로 뚝딱 만들었다. Antigravity가 이 Listener Server를 만드는 과정에서 OpenCode에 연결 요청을 하지 못하는 현상이 있었고, 이를 해결해야 했는데 이는 후술할 내용에서 다루려고 한다.
Slack Bot을 통해 전달한 명령어가 내 PC에서 실행된다는 것은 생각보다 편리함을 제공했다. 예를 들어 다음과 같이 맥북을 잠자기 모드로 전환해달라고 하니 알아서 명령을 실행하고 잠자기 모드로 전환해준다.

더 나아가서는 여러 접근 가능한 데이터 소스들을 준비해두고, OpenCode에게 찾아가는 방법을 일러두면 이러한 작업이 가능하다는 것을 의미하는 듯싶다. 뭔가 여러 가지를 해볼 수 있을 것 같은데, 아직 떠오르는 아이디어는 딱히 없다. 일상생활에서 불편하다고 생각되는 부분들을 자주 캐치하고, 이를 발전시켜봐야겠다.
OpenCode : OpenCode는 API 찾아보기
Listener Server는 Slack Bot과 Socket Mode(WebSocket)를 통해 연결되어 데이터를 송수신하기 때문에 문제없다. 그렇다면 Listener Server와 OpenCode가 데이터를 주고받기 위해서는 어떤 방식이 필요할까?
이 질문에 대한 답을 찾다가 OpenCode에는 serve라는 명령어를 통해 로컬에 간단한 Server를 띄워주는 기능이 존재한다는 것을 알게 됐다.
╭─jako@prompt-pro ~/
╰─$ opencode serve
Warning: OPENCODE_SERVER_PASSWORD is not set; server is unsecured.
opencode server listening on <http://127.0.0.1:50078>
이 기능을 사용하면 브라우저에서 OpenCode에 프롬프트를 입력할 수 있는 UI를 제공한다.

그런데 지금 하려고 하는 것은 Listener Server와 OpenCode 간 프로그래밍 방식의 연결이다. 즉, OpenCode에 데이터를 코드상에서 입력할 수 있는 방법이 필요했다.
잠깐 Gemini를 들여다보자. Gemini는 다음과 같이 curl 명령어를 통해 API를 제공한다.
curl "<https://generativelanguage.googleapis.com/v1beta/models/gemini-flash-latest:generateContent>" \
-H 'Content-Type: application/json' \
-X POST \
-d '{...}'
아쉽게도 OpenCode는 이와 같은 Chat Completions 형태의 API를 제공하지 않았다. 더 파보던 중 OpenCode는 server로 띄운 주소에 /doc를 입력하면 Swagger 형식으로 API 문서를 확인할 수 있다는 사실을 알게 됐다.

이 JSON을 Swagger Editor에 넣고 분석해보니 OpenCode 역시 여러 API를 제공하고 있다는 것을 알 수 있었다. 문서를 살펴보니 Listener Server에서 OpenCode에 프로그래밍 방식으로 입력을 전달하는 방법을 확인할 수 있었다.
OpenCode에서는 POST /session을 통해 세션을 생성하고, 이후 발급받은 session_id를 기준으로 메시지를 전달하는 구조이다.
이 내용을 정리해 Antigravity에 Listener Server에서 OpenCode와의 연결방식을 조정해달라하니 이내 프로그래밍 방식의 연결에 성공했다.
마치며
복잡해 보이는 구성을 만지면서도, 한편으로는 클로드 코드 썼으면 편리하게 해결될 일인데라는 생각이 든다. 이미 잘 만들어진 기능을 그대로 사용하면 훨씬 간단하게 해결할 수 있는 문제를 굳이 돌아가고 있는 셈이다.
그러나 나 같은 poor man은 가지고 있는 도구와 스킬셋을 활용해서 비슷한 결과를 만들어내는 것에 재미를 느끼는 듯 싶다. Slack에서 명령을 보내고, 이를 Listener Server가 받아서 로컬 PC에서 실행하고, 다시 OpenCode와 연결하는 과정을 직접 구성해보면서 각각의 기술이 어떻게 연결되는지도 조금 더 이해할 수 있었다.
결국 결과만 놓고 보면 클로드 코드의 Remote Control을 사용하는 것이 훨씬 편리하겠지만, 직접 비슷한 것을 만들어보는 과정에서 얻는 경험은 또 다른 것 같다. 당장 실용적인 결과물을 만든 것보다, “이런 것도 연결해서 만들 수 있구나”라는 점에서 나름대로 의미 있는 작업이었다.
또한 Antigravity가 OpenCode의 API를 사용방법을 찾지 못해 직접 사용사례를 일러주는 부분도 흥미로웠다. 어쩌면 앞으로는 AI가 생성해놓은 결과물에서 이상하게 동작하거나 안되는 동작들을 감지하고 해당 사용사례를 찾아서 일러주는 역량이 중요해지 않을까라는 후문이 남는다.
'개발 노트' 카테고리의 다른 글
| [Arduino] WeMos D1&R2 (0) | 2022.07.27 |
|---|---|
| MQTT, Message Queuing Telemetry Trasnport (0) | 2022.07.17 |
| [Postman] Cookie header 자동 셋업 끄기 (0) | 2022.05.15 |
| React && DJango 파일 업로드 (0) | 2020.12.14 |
| DRF&React로 REST API 체험기 (0) | 2020.11.18 |