AI 기반 아키텍처 탐색: 어떻게 작동하는가 - Archyl Blog

코드베이스를 읽고 아키텍처 다이어그램을 생성하는 AI 시스템을 만들었습니다. 기술, 도전 과제, 그리고 왜 이것이 마법이 아닌지에 대해 배운 것을 공유합니다.

AI 기반 아키텍처 탐색: 어떻게 작동하는가

작년에 문서가 전혀 없는 코드베이스를 물려받았습니다. 15개 서비스에 걸쳐 200,000줄의 코드가 있었고, 이미 떠난 팀이 작성한 것이었습니다. 제 임무는 새로운 결제 통합을 추가할 수 있을 만큼 시스템을 충분히 이해하는 것이었습니다. 회사는 아키텍처를 파악하는 데만 2-3주가 걸릴 것으로 예상했습니다.

그 경험이 바로 Archyl의 AI 탐색 기능을 만든 이유입니다. 이제 대규모 언어 모델로 코드를 분석하는 데 몇 달을 보낸 후, 실제로 무엇이 효과가 있고, 무엇이 효과가 없으며, AI 기반 아키텍처 탐색이 강력하지만 마법은 아닌 이유를 공유하고 싶습니다.

수동 탐색의 문제점

AI에 들어가기 전에, 왜 이것이 필요한지 먼저 인정합시다.

문서화되지 않은 코드베이스에 직면했을 때, 제 탐색 과정은 이랬습니다:

1주차: 코드에서 키워드를 grep으로 검색. 주요 진입점 찾기. 화이트보드에 몇 개의 상자 그리기. 서비스 경계를 잘못 이해했다는 것을 깨닫기. 지우고 다시 그리기.

2주차: 어느 정도 역사를 기억할 만큼 오래 근무한 유일한 엔지니어 인터뷰. 그가 말하는 것의 절반은 코드에서 발견한 것과 모순됨. 알고 보니 변경사항이 있었지만 아무도 그의 멘탈 모델을 업데이트하지 않았던 것.

3주차: 마침내 변경할 수 있을 만큼 시스템을 이해했다고 느낌. 반드시 최신 상태로 유지하겠다고 맹세하며 문서 작성. (스포일러: 유지하지 않았습니다.)

이 과정은 느리고, 오류가 발생하기 쉬우며, 확장되지 않습니다. 모든 새 팀원이 같은 고통스러운 탐색을 겪습니다. 문서는 몇 달 안에 구식이 됩니다.

AI 탐색이 실제로 어떻게 작동하는가

저장소를 Archyl에 연결하고 탐색을 실행하면, 내부에서 이런 일이 일어납니다:

1단계: 저장소 스캔

먼저, 코드베이스의 지도를 구축합니다. 이것은 아직 AI가 아닙니다 — 단순한 파일 시스템 탐색입니다:

  • 모든 파일과 디렉토리 나열
  • 설정 파일 식별 (package.json, go.mod, docker-compose.yml)
  • 진입점 찾기 (main 함수, index 파일, API 라우트)
  • import에서 의존성 그래프 구축

이것으로 골격을 얻습니다. 어떤 파일이 존재하고 서로 어떻게 참조하는지 알 수 있습니다. 하지만 아직 그것들이 무엇을 _하는지_는 이해하지 못합니다.

2단계: 청크 분석

여기서 LLM이 등장하며, 동시에 까다로워지는 부분이기도 합니다.

현대 언어 모델에는 컨텍스트 제한이 있습니다. GPT-4는 약 128K 토큰을, Claude는 200K를 처리할 수 있습니다. 많아 보이지만, 중간 크기의 코드베이스도 쉽게 이를 초과합니다. 따라서 전체 코드베이스를 프롬프트에 넣고 "이게 뭐야?"라고 물을 수는 없습니다.

대신, 코드베이스를 소화 가능한 조각으로 나눕니다:

  1. 디렉토리나 모듈별로 파일 그룹화
  2. 각 청크를 프로젝트 내 위치에 대한 컨텍스트와 함께 LLM에 전송
  3. 모델에게 질문: 이 코드는 무엇을 담당하는가? 어떤 패턴을 사용하는가? 어떤 외부 시스템과 상호작용하는가?

응답은 구조화된 데이터로 돌아옵니다 — 시스템, 컨테이너, 컴포넌트와 그 관계를 설명하는 JSON.

3단계: 집계 및 조정

이것이 가장 어려운 부분이며, 개발 시간의 대부분을 보낸 곳입니다.

각 청크 분석은 부분적인 뷰를 제공합니다. 사용자 서비스 청크는 사용자 데이터베이스에 대해 알고 있습니다. 결제 청크는 Stripe에 대해 알고 있습니다. 하지만 어느 것도 전체 그림을 알지 못합니다.

이러한 부분적인 뷰를 조정해야 합니다:

  • 중복 엔티티 병합 ("UserDB"와 "users_database"는 같은 것인가?)
  • 청크 간 관계 추론 (주문 서비스가 사용자 서비스를 호출하지만, 별도로 분석되었음)
  • 충돌 해결 (한 청크는 PostgreSQL을 사용한다고 하고, 다른 청크는 MySQL이라고 함 — 어느 것이 맞는가?)

이 조정은 또 다른 LLM 분석과 일반적인 패턴에 기반한 휴리스틱을 사용합니다. 불완전합니다. 때때로 AI가 틀립니다. 그래서 탐색은 인간이 검토하는 _제안_을 생성하지, 최종 문서가 아닙니다.

4단계: C4 모델 생성

마지막으로, 발견된 엔티티를 C4 모델 요소에 매핑합니다:

  • 외부 시스템 (서드파티 API, 관리하지 않는 데이터베이스)
  • 컨테이너 (배포 가능한 단위)
  • 컴포넌트 (컨테이너 내 주요 모듈)
  • 관계 (누가 누구를 호출하는지, 어떤 데이터가 어디로 흐르는지)

결과는 AI가 아키텍처를 이해한 것을 포착한 C4 다이어그램 초안 세트입니다.

AI가 잘하는 것

개발 중 수십 개의 코드베이스에서 탐색을 실행한 후, 인상적이었던 것은 다음과 같습니다:

기술 스택 감지

LLM은 프로젝트가 어떤 기술을 사용하는지 식별하는 데 놀라울 정도로 뛰어납니다. 프레임워크 패턴, 라이브러리 관용구, 설정 파일 형식을 인식합니다. GPT가 @Controller 어노테이션을 보면 Spring을 사용하고 있다는 것을 압니다. fiber.New()를 보면 Go Fiber를 사용하고 있다는 것을 압니다.

서비스 경계 감지

마이크로서비스 아키텍처에서 AI는 서비스 경계를 안정적으로 식별합니다. /services/user/에 있는 코드가 /services/order/와는 별개의 서비스일 가능성이 높다는 것을 이해합니다. Docker Compose 파일을 서비스 토폴로지의 지표로 인식합니다.

일반적인 패턴 인식

AI는 훈련 데이터에서 수백만 개의 코드베이스를 보았습니다. 저장소 패턴, MVC 구조, 이벤트 기반 아키텍처, API 게이트웨이 설정을 인식합니다. 코드가 일반적인 패턴을 따를 때, AI는 이를 빠르게 식별합니다.

외부 통합 발견

모든 API 키 상수, 웹훅 URL, SDK import는 외부 통합에 대한 단서입니다. AI는 이들 대부분을 포착하여, 시스템이 의존하는 서드파티 서비스의 그림을 구축합니다.

AI가 틀리는 것

여기서 현실적인 기대를 설정해야 했습니다:

커스텀 도메인 로직

AI는 비즈니스 도메인을 이해하지 못합니다. processOrder 함수가 있다는 것은 알 수 있지만, 특정 비즈니스 맥락에서 "주문 처리"가 무엇을 의미하는지는 모릅니다. 도메인별 컴포넌트의 목적을 잘못 식별할 수 있습니다.

비정형 아키텍처

아키텍처가 일반적인 패턴을 따르지 않으면, AI는 어려움을 겪습니다. 커스텀 플러그인 시스템, 비전통적인 폴더 구조, 자체 제작 프레임워크는 혼란을 줍니다. AI는 Rails 앱이 Rails 앱처럼 보이기를 기대합니다.

숨겨진 의존성

모든 의존성이 코드에서 명시적인 것은 아닙니다. 서비스가 프로덕션에만 존재하는 특정 버전의 Redis를 필요로 할 수 있습니다. AI가 볼 수 없는 사이드카 컨테이너가 있을 수 있습니다. 런타임 의존성은 정적 분석에 종종 보이지 않습니다.

오래된 코드 경로

AI는 어떤 코드가 활발히 사용되는지와 아무도 수년간 건드리지 않은 레거시인지 구분하지 못합니다. 코드베이스에는 여전히 있지만 더 이상 배포되지 않는 폐기된 서비스를 두드러지게 표시할 수 있습니다.

AI 탐색의 정확도 향상

시행착오를 통해 탐색 정확도를 향상시키는 방법을 찾았습니다:

컨텍스트 제공

탐색을 실행하기 전에, 시스템에 대해 AI에게 알려주세요. "이것은 결제 처리가 있는 이커머스 플랫폼입니다"는 모델에게 참조 프레임을 제공합니다. 컨텍스트 없이는 맹목적으로 추측하는 것입니다.

구조부터 시작

기존 문서가 있다면 — 대략적인 아키텍처 스케치가 있는 README라도 — 제공하세요. AI는 이것을 분석을 안내하는 사전 정보로 사용합니다.

점진적으로 검토

전체 코드베이스에 대해 한 번에 탐색을 실행하지 마세요. 하나의 서비스부터 시작하세요. 결과를 검토하고 수정하세요. 그런 다음 다음 서비스로 확장하세요. 수정 사항이 향후 분석에 반영됩니다.

신뢰하되 검증하기

AI 제안을 출발점으로 취급하세요, 최종 답변이 아닙니다. AI의 정확도가 80%일 수 있습니다. 나머지 20%를 검증해야 합니다. 소스 코드 링크를 클릭하고, 관계가 합리적인지 확인하고, 실수를 수정하세요.

기술적 세부사항

구현에 대해 궁금한 분들을 위해:

청킹 전략

고정 크기 청크 대신 시맨틱 청킹을 사용합니다. 청크는 일반적으로 하나의 모듈, 하나의 서비스 또는 하나의 디렉토리 트리입니다. 이것은 관련 코드를 함께 유지하여 AI의 이해를 향상시킵니다.

프롬프트 엔지니어링

프롬프트는 상당히 진화했습니다. 초기 버전은 장황한 서술적 설명을 생성했습니다. 현재 프롬프트는 특정 필드가 있는 구조화된 출력을 요구합니다. 예상 형식을 보여주기 위해 few-shot 예제를 사용합니다.

동시성

큰 코드베이스에는 수천 개의 파일이 있습니다. 순차적으로 처리하면 영원히 걸릴 것입니다. API 속도 제한을 피하기 위해 구성 가능한 동시성 제한으로 청크를 병렬로 분석합니다.

모델 선택

다른 모델은 다른 강점을 가지고 있습니다. GPT-4는 더 정확한 분석을 생성하지만 비용이 더 높습니다. Claude는 구조화된 출력 요구사항을 따르는 데 더 뛰어납니다. 코드를 외부 API로 보낼 수 없는 팀을 위해 Ollama를 통한 로컬 모델도 지원합니다.

AI 기반 탐색의 미래

현재 가지고 있는 것은 버전 1입니다. 다음은 제가 목표로 하는 것입니다:

지속적 탐색

일회성 분석 대신, 코드베이스를 지속적으로 모니터링합니다. 코드가 변경되면 관련 다이어그램을 자동으로 업데이트합니다. 아키텍처 드리프트가 문제가 되기 전에 감지합니다.

더 깊은 이해

현재 분석은 주로 구조적입니다. 미래 버전은 동작을 이해할 수 있습니다: "이 엔드포인트는 입력을 검증하고, 결제 서비스를 호출한 다음, 확인 이메일을 보냅니다." 코드에서 생성된 시퀀스 다이어그램.

교차 저장소 분석

대부분의 조직은 여러 저장소를 가지고 있습니다. 탐색은 저장소가 어떻게 연결되는지 이해해야 합니다 — 저장소 A의 어떤 서비스가 저장소 B의 서비스를 호출하는지.

신뢰도 점수

모든 발견이 동일하게 확실한 것은 아닙니다. 어떤 제안을 더 신중하게 검토해야 하는지 알 수 있도록 신뢰도 점수를 추가하고 있습니다.

결론

AI 기반 아키텍처 탐색은 마법이 아닙니다. 코드베이스를 이해하는 지루한 부분을 가속화하면서도 미묘한 부분에 대해서는 여전히 인간의 판단이 필요한 도구입니다.

오늘 그 200K 줄 코드베이스에서 탐색을 실행하면, 3주 대신 10분 만에 아키텍처 다이어그램 초안을 얻습니다. 완벽하지는 않습니다 — 여전히 검토하고 수정해야 합니다. 하지만 빈 화이트보드보다 극적으로 더 나은 출발점입니다.

문서화되지 않은 코드에 파묻혀 있다면, AI 탐색을 시도해 보세요. 현실적인 기대를 가지고 접근하세요: 비즈니스 도메인을 이해하지 못하고, 비정형 패턴을 놓칠 수 있으며, 반드시 인간 검토가 필요합니다. 하지만 시간의 일부분으로 80%까지 도달하게 해줄 것입니다.


더 알고 싶으신가요? AI 탐색이 생성하는 C4 모델 소개를 확인하거나, 왜 아키텍처 문서화가 중요한지에 대해 읽어보세요.