본문으로 건너뛰기

애플리케이션 아키텍처 (AA)

2026-08-17 기록. 현재 문서와 내용이 다를 수 있다. 아래 내용은 당시 상태를 보존하며 수정하지 않는다.

코드와 애플리케이션의 책임을 어떻게 나눌 것인가?

무엇이 무엇을 책임지는가를 그린다. 여기서 처음으로 기술 이름이 나온다.

  • 집중하는 것 — Application / Module / Domain
  • 담는 것 — Frontend, Backend, Agent, STT 등의 책임과 내부 모듈
  • 빼는 것 — EC2 · ECS · Subnet 같은 인프라
  • 구체성 — 중간

애플리케이션과 모듈까지만 내려간다. 모듈 하나가 어떤 클래스로 갈리고 엔드포인트가 어떤 경로를 갖는지는 이 층의 관심이 아니다.

한 장에 다 그리지 않는다. 그림 하나는 질문 하나에 답한다. 한 그림이 두 질문에 답하기 시작하면 선이 교차하고, 하나를 이해하려고 나머지 서른 개를 봐야 하게 된다.

그림답하는 질문
§1애플리케이션은 몇 개이고 무엇에 기대나
§2서버 모듈은 무엇이고 누가 부르나
§3ai 모듈은 무엇이고 무엇에 붙나

1. 전체 — 애플리케이션은 몇 개이고 무엇에 기대나

10초 안에 읽혀야 하는 것은 셋이다 — 애플리케이션이 셋이라는 것, 비동기로 갈린 자리가 있다는 것, 그리고 데이터의 주인이 갈려 있다는 것.

그림이 말하는 것무엇
비동기 경계가 있다회의 종료 뒤의 일을 요청 처리와 떼어 놨다. 구현 방식이 아니라 책임 분리다 — 떼어 놨기 때문에 ai 가 죽어도 회의가 안 끊기고, 실패한 것을 다시 태울 수 있다
수단은 SQS 다런타임 경계를 넘는 곳에만 넣는다. 같은 프로세스 안의 일은 DB 행으로 남는다
ai 만 되부르는 방향이 점선이다서버가 맡기고 ai 가 되묻는다. 그 방향이 있는 이유는 §5
브라우저에서 ai 로 가는 선이 없다도달 수단 자체가 없다

⚠️ 한 저장소 상자 안에 주인이 둘이다. PostgreSQL 인스턴스는 하나인데 heymoa 는 서버가, heymoa_ai 는 ai 가 소유하고 그 둘을 조인하지 않는다§4.


2. heymoa-server — 모듈과 부르는 쪽

부르는 쪽과 모듈 사이는 한 줄씩 긋는다. 어느 책임이 어느 모듈을 부르는지가 이 그림이 답하는 것이고, 거기서 빠진 선은 만들 것에서도 빠진다.

인증을 상자로 그리지 않는다. 모든 요청이 지나므로 그려 봐야 아는 게 늘지 않고, 모든 선을 그 상자로 몰면 어느 책임이 어느 모듈을 부르는지가 도리어 안 보인다.

그림이 말하는 것무엇
agentcontext 만 브라우저에서 오는 화살표가 없다들어오는 것이 heymoa-ai 쪽뿐이다. 사람이 아니라 에이전트가 쓰는 표면이다
회의 진행이 모듈 넷을 부른다오디오는 transcription, 시작·중지·재개는 note, 종료는 analysis, 회의 중 질의는 agentchat
채팅으로 들어가는 문이 둘이다회의 밖 채팅은 범위를 고르고 회의록을 고칠 수 있고, 회의 중 질의는 지금까지의 전사만 본다
analysis 만 비동기 경계 양쪽에 있다종료를 받아 발행하고, 나중에 결과를 받아 쓴다. 한 모듈이 동기와 비동기를 다 지는 자리
초대 수락만 로그인 앞에 선다세션이 없는 상태에서 시작하므로 다른 책임과 들어오는 길이 다르다

모듈이 무엇을 지나

모듈무엇을 책임지나실리는 실행 단위
auth · user로그인 · 세션 · 계정api
workspace · project조직과 멤버, 초대, 회의록을 묶는 단위api
note회의록과 참가자, 회의 상태 전이api
transcription전사 세션과 세그먼트, 오디오 중계realtime
analysis회의 종료, 분석 잡, 회의 항목과 근거, 분리 제출과 화자 결과 수용, 기계 매핑api
agentchat채팅과 메시지, 도구 승인 기록api · realtime
agentcontextheymoa-ai 에게 회의 맥락을 준다. 화면이 없는 유일한 모듈api
integration외부 도구 연결과 토큰 보관api
notification알림 생성과 읽음 처리api
common예외 처리 · 보안 설정 · 요청 로깅전부

모듈은 presentation · application · domain · infra 넷으로 나뉜다. 자기 상태가 없는 agentcontext 에는 domain 이 없고, 횡단 관심사만 드는 common 에는 application 이 없다.

⚠️ 모듈과 실행 단위는 1:1 이 아니다. agentchat 은 채팅 API 를 api 에서 받고 응답 스트림 중계를 realtime 에서 하며, transcription 은 세션 관리를 realtime 에서 하되 그 결과를 api 가 읽는다. 이 어긋남이 SA에서 실행 단위를 가르는 근거가 된다.

worker 가 오른쪽 열에서 사라졌다. 조립이 Spring 밖의 함수로 나갔기 때문이다 → SA. 그래서 이 표에 조립 함수 열이 없다. 그건 Kotlin 코드가 아니고 아무도 import 하지 않는다 — AA 의 단위가 아니다. analysis 는 그 함수를 부르는 쪽으로만 남는다.


3. heymoa-ai — 모듈과 바깥

그림이 말하는 것무엇
들어오는 문이 셋이다채팅은 런타임으로, 분석은 두 갈래로 — 서버가 직접 맡기는 길과 비동기 경계를 지나는 길이 따로 있다
맥락은 갖고 있지 않고 되묻는다그래서 맥락을 복제하지 않아도 된다
Redis · S3 · 메일로 가는 선이 없다ai 는 그것들을 쓰지 않는다. 없다고 확인한 것이다
도구 실행만 승인을 기다린다쓰기 도구는 사람 승인을 거친다 → 에이전트 채팅

의존 방향이 CI 에 걸려 있다 — 웹 표면은 조립을 모르고, 안쪽 계층은 프레임워크를 모르며, 외부 호출 계층은 에이전트 프레임워크를 모른다. 셋 중 하나라도 어기면 빌드가 깨진다.


4. 소유 규칙

한 데이터를 두 곳에서 쓰지 않는다. 두 곳이 쓰면 순서와 잠금을 코드가 관리해야 하고, 그건 실행 단위를 늘릴수록 지킬 수 없는 약속이 된다.

무엇쓰는 곳
전사 세션 · 세그먼트transcription오디오를 받는 쪽이 그대로 쓴다
회의 상태note종료·중지의 조건부 갱신이 한 곳에 모여야 한다
화자 결과와 매핑analysis벤더 결과를 받는 쪽이 쓴다
조립 잡의 진행 상태analysis조립 함수는 DB 를 안 본다. 발행과 완료 수용이 둘 다 api 쪽이다
회의록 간 관계analysisheymoa 안의 테이블이다. 어느 모듈이 질지는 노드·엣지 타입이 정해져야 정한다
분석 결과 · 임베딩 · 체크포인트heymoa-ai자기 데이터베이스를 따로 갖는다
그 밖의 업무 데이터 전부api

⚠️ 업무 데이터베이스와 에이전트 데이터베이스는 다른 것이다. 같은 인스턴스 안에 있어도 한 쿼리로 두 쪽을 조인하지 않는다. 조인이 생기는 순간 두 애플리케이션이 스키마 하나를 공유하게 되고 따로 배포할 수 없게 된다.


5. 의존 방향

서버와 AI 만 서로를 부른다. 브라우저는 heymoa-ai 의 주소를 알지 못하고, 그 규칙을 실제로 강제하는 것은 문서가 아니라 CA의 보안그룹이다.

AI 가 서버를 되부르는 방향은 의도된 것이다 — 에이전트는 회의 맥락을 갖고 있지 않고 권한 판단도 하지 않는다. 필요한 것을 그때그때 물어보게 두면 맥락을 복제하지 않아도 된다.

실행 단위를 가르는 방법이 스프링 프로필에서 빌드 단위로 바뀌면서, "realtime 이 인증 모듈을 부르지 않는다" 같은 약속이 적지 않으면 컴파일이 안 되는 것이 된다. 리뷰로 지키던 것을 빌드가 지킨다.


6. 아직 책임자가 없는 것

제품이 요구하는데 어느 모듈도 지지 않는 것들이다. 화면을 먼저 그려도 그 아래가 서 있지 않으면 만들 수 없다.

무엇무엇이 먼저인가
회의 관리 매니저 — 종료 임박 · 주제 이탈 · 결정 충돌 · 개입 설정넷 중 셋이 담을 자리부터 없다 → 회의 중 에이전트
회의 중 항목 갱신 — 안건·결정·액션이 회의 중에 자란다갱신 시점과 저장 자리 → 회의 중 에이전트
프로젝트 페이지 — 타임라인 · 회의록 간 의존 · 전역 액션과 결정무엇을 관계로 볼지가 안 정해졌다
화자 확인 화면종료 후 흐름이 요구하는데 IA 트리에 그 화면이 없다
그래프 투영을 어느 모듈이 지나위가 정해져야 정할 수 있다. 지금은 어느 모듈에도 없다
요약 완료 알림을 어느 모듈이 만드나analysisnotification 을 부르는 의존이 없다
회의 전 구간 — 안건 · 맥락 · 일정담을 자리가 없다
요약 항목의 담당자와 마감일 · 전사에 화자 표시
온보딩과 녹음 약관 동의 · 회원 탈퇴 · MCP · 알림 설정