본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 01. 02:02

Atom이면 충분합니다: 코드베이스를 의존성 그래프가 아닌 Atom Map으로 읽기

요약

기존의 의존성 그래프 중심 분석을 넘어, 코드의 최소 의미 단위인 'Atom'을 추출하여 아키텍처를 분석하는 새로운 방법론을 제안합니다. 이를 위해 대수적 구조를 활용한 ArchSig 도구를 통해 설계 압력과 의미론적 결합을 파악할 수 있습니다.

핵심 포인트

  • 의존성 그래프 대신 Atom Map을 통한 아키텍처 분석 제안
  • AI 에이전트 시대에 코드베이스의 설계 품질 유지의 중요성 강조
  • ArchSig 도구를 활용한 설계 압력 및 의미론적 결합 분석 가능
  • 단순한 정적 분석을 넘어선 고차원적 아키텍처 관찰 단위 필요

요약 (TL;DR)

AI 시대의 아키텍처 분석은 코드를 파일, 함수, 임포트(import), 그리고 의존성 그래프(dependency graphs)로 읽는 것에 머물러서는 안 됩니다.

우리는 아키텍처적 의미를 담고 있는 가장 작은 단위들을 관찰해야 합니다. 저는 이 단위들을 Atom이라고 부릅니다.

코드베이스에서 Atom을 추출하고 이들이 생성하는 대수적 구조(algebraic structure)를 읽음으로써, 우리는 일반적인 의존성 관계를 넘어 아키텍처를 분석할 수 있습니다.

워크플로우는 다음과 같습니다:

codebase
  -> Atom 관찰 (Atom observations)
  -> ArchMap
...

이를 통해 일반적인 린팅(linting), 정적 분석(static analysis), 의존성 그래프가 놓치기 쉬운 설계 압력(design pressure), 의미론적 결합(semantic coupling), 누락된 증거(missing evidence), 그리고 리뷰 집중 포인트(review focus)를 볼 수 있습니다.

우리는 이 워크플로우를 위한 새로운 도구인 ArchSig를 구축했습니다.

해당 리포지토리는 공개되어 있으며 MIT 라이선스가 적용되므로, 여러분의 코드베이스에 직접 시도해 볼 수 있습니다.

핵심 아이디어는 간단합니다:

아키텍처 분석에는 더 거대한 자연어 요약이 필요한 것이 아닙니다.

적절한 관찰 단위(unit of observation)가 필요할 뿐입니다.

왜 아키텍처 분석기가 필요한가

AI 에이전트는 코드를 빠르게 작성할 수 있습니다.

하지만 코드를 빠르게 작성하는 것이 시스템을 잘 진화시키는 것과 같지는 않습니다.

AI 에이전트에게 코드베이스는 가장 거대한 프롬프트(prompt)입니다.

만약 기존 코드베이스에 지름길(shortcuts)이 포함되어 있다면, 그 지름길들은 예시가 됩니다.
만약 경계(boundaries)가 모호하다면, 새로운 코드는 자연스럽게 모호한 곳에 자리 잡게 됩니다.
만약 책임(responsibilities)이 뒤섞여 있다면, 그 뒤섞임은 다음 구현 컨텍스트(implementation context)의 일부가 됩니다.

전통적인 도구들은 종종 코드의 현재 형태를 살펴봅니다:

  • 임포트 그래프 (import graphs)
  • 의존성 사이클 (dependency cycles)
  • 레이어 위반 (layer violations)
  • 린트 규칙 (lint rules)
  • 복잡도 지표 (complexity metrics)
  • 테스트 커버리지 (test coverage)
  • 보안 규칙 (security rules)

이 모든 것들은 중요합니다.

하지만 AI 시대의 아키텍처 리뷰에서, 우리는 종종 더 깊은 질문을 던지고 싶어 합니다.

사용자가 입력 데이터를 선택하고, 자동화된 처리 또는 생성을 실행하며, 결과를 영속화(persist)하고, 외부 시스템으로부터 이벤트를 수신하며, 비동기 작업(async jobs)을 실행하고, 외부 제공자(external providers)를 호출하며, 생성된 아티팩트(artifacts)를 다시 비즈니스 상태(business state)에 저장하는 비즈니스 백엔드를 상상해 보십시오.

중요한 질문은 단지 다음과 같은 것만이 아닙니다:

의존성(dependencies)이 올바른 방향을 가리키고 있는가?

우리는 또한 다음을 알고 싶어 합니다:

  • 어떤 작업(operation)을 위해 어떤 입력을 사용하는 것이 허용되는가?
  • 생성된 출력(output)이 어떤 검증 경로(validation path)를 통해 영속화된 상태(persisted state)가 되는가?
  • 외부 제공자의 실패가 어디에 내구성이 있는 상태(durable state)로 기록되는가?
  • 동일한 아티팩트를 생성하는 두 워크플로(workflows)가 실제로 동일한 효과 순서(effect order)를 갖는가?
  • 엔트리포인트(entrypoint) 수준의 권한이 의도된 비즈니스 범위(business scope)와 일치하는가?
  • 권한이 부여된 작업(privileged operations)이 일반적인 워크플로 권한(ordinary workflow authority)과 분리되어 있는가?

이러한 것들은 의존성 그래프(dependency graph)만으로는 읽어내기 어렵습니다.

우리는 코드를 단순히 파일과 함수의 집합이 아니라, 아키텍처적 의미를 담고 있는 관찰(observations)의 집합으로 읽어야 합니다.

그 단위가 바로 Atom입니다.

Atom: 아키텍처적 의미의 최소 단위

Atom은 제가 아키텍처를 읽을 때 사용하고자 하는 가장 작은 관찰 단위입니다.

이것은 반드시 함수, 클래스, 모듈 또는 파일일 필요는 없습니다.

실제로, 리뷰 중에 무언가를 가리키며 다음과 같이 말할 때의 그것입니다:

이것은 경계(boundary)입니다.

이것은 상태(state)입니다.

이것은 효과(effect)입니다.

이것은 계약(contract)입니다.

이곳은 신뢰(trust)가 변하는 지점입니다.

Atom 계열의 예시는 다음과 같습니다:

Atom 계열의 예시는 다음과 같습니다:

  • component atom: 아키텍처 단위(architectural unit)가 존재함
  • relation atom: 두 단위 또는 Atom이 서로 관계를 맺음
  • capability atom: 단위가 특정 기능(capability)을 제공함
  • state atom: 무언가가 상태(state)로서 유지되거나 영속화(persisted)됨
  • effect atom: 외부 호출(external call) 또는 부수 효과(side effect)가 발생함
  • authority atom: 누군가 특정 행위를 할 권한(allowed)이 있음
  • trust relation atom: 특정 출력물이나 제공자(provider)가 경계(boundary)까지 신뢰됨
  • contract atom: 입력(inputs), 출력(outputs), 전제 조건(preconditions) 또는 실패 동작(failure behavior)이 약속됨
  • semantic atom: 무언가가 코드 위치를 넘어 아키텍처적 의미를 가짐

중요한 점은 Atom이 구문론적(syntactic) 의미에서 작은 것이 아니라는 점입니다.

Atom은 아키텍처적(architectural) 의미에서 작습니다.

예를 들어, 다음과 같은 관찰(observation)을 생각해 봅시다:

권한이 있는 행위자(authorized actor)만이 이 리소스를 업데이트할 수 있습니다.

이 관찰은 여러 파일을 가로지를 수 있습니다.

또한 다음과 같은 관찰도 있습니다:

생성된 출력물은 영속화(persistence)되기 전에 서비스 수준의 계약(service-level contract)을 통과해야 합니다.

이 관찰은 라우트(route), 서비스(service), 검증 계층(validation layer), 작업 상태(job state), 그리고 리포지토리(repository)를 가로지를 수 있습니다.

그럼에도 불구하고, 각 관찰은 아키텍처 리뷰(architecture review)에서 하나의 의미 있는 단위입니다.

그것이 바로 Atom이 기록하는 것입니다.

작은 코드 예시

아주 작은 함수라도 여러 개의 Atom을 포함할 수 있습니다.

def publish_artifact(actor, artifact_id, repository, gateway):
    artifact = repository.load_for_actor(actor.id, artifact_id)
    gateway.publish(artifact.payload)
...

만약 우리가 단지 "이것은 하나의 함수이다"라고만 말한다면, 아키텍처적 내용의 대부분을 놓치게 됩니다.

Atom으로 읽는다면, 적어도 다음과 같은 것들을 관찰할 수 있습니다:

  • component (구성 요소): repository (저장소)와 gateway (게이트웨이)는 아키텍처 단위이다
  • relation (관계): 핸들러 (handler)가 repositorygateway 모두로 흐른다
  • capability (역량): repository는 로드/저장 (load/save)을 제공하고, gateway는 발행 (publish)을 제공한다
  • state (상태): 아티팩트 (artifact)의 발행된 상태가 영속화된다
  • effect (영향): gateway.publish는 외부 상태를 변경한다
  • authority (권한): 액터 (actor)는 이 아티팩트를 발행할 수 있는 허가를 받아야 한다
  • trust_relation (신뢰 관계): gateway의 응답 및 실패 동작은 오직 경계 (boundary)를 통해서만 신뢰되어야 한다
  • contract (계약): 발행 성공, 저장 실패, 그리고 재시도 (retry) 동작은 명시적인 약속 (promises)이 필요하다
  • semantic (의미론): '발행됨 (published)'은 단순한 플래그가 아니다; 이는 외부에서 가시적임을 의미한다

이 아홉 가지 Atom 스키마 (schemas)는 원시적인 아키텍처 사실들을 아키텍처 객체의 생성기로 취급하기 위한 기본 어휘이다.

ArchMap: 코드베이스를 Atom Map으로 전환하기

ArchMap은 이러한 관찰 결과들의 지도이다.

이것은 코드베이스의 완전한 복사본이 아니다.
이것은 AST 덤프 (AST dump)가 아니다.
이것은 단순한 의존성 그래프 (dependency graph)도 아니다.

이것은 소스에 근거한 아키텍처 관찰의 지도이다.

소스 코드 (source code)
  관찰된 형태
Atom / Molecule / Semantic 관찰
...

하나의 Atom이 하나의 관찰이라면, Molecule (분자)은 하나의 책임 경계 (responsibility boundary)로 작동하는 Atom들의 유한한 구성체이다.

예를 들어, 백엔드의 ArchMap에는 다음과 같은 Molecule들이 포함될 수 있다:

  • 인증된 요청 경계 (authenticated request boundary)
  • 자격 증명 생명주기 (credential lifecycle)
  • 저장소 트랜잭션 경계 (repository transaction boundary)
  • 대화형 처리 워크플로우 (interactive processing workflow)
  • 입력-아티팩트 파이프라인 (input-to-artifact pipeline)
  • 외부 통합 인그레스 (external integration ingress)
  • 작업 관리 생성 표면 (job-managed generation surface)
  • 입력 기반 아티팩트 경계 (input-backed artifact boundary)
  • 에지 정책 및 관측 가능성 경계 (edge policy and observability boundary)
  • 특권 거버넌스 경계 (privileged governance boundary)

중요한 점은 코드베이스에 api, services, repositories, models와 같은 폴더가 있다는 것이 아니다.

중요한 점은 아키텍처적 의미가 해당 폴더들 위에 자리 잡고 있다는 것이다:

  • 권한 (authority)
  • 생성 (generation)
  • 외부 영향 (external effect)
  • 영속적 상태 (durable state)
  • 아티팩트 생명주기 (artifact lifecycle)
  • 의미론적 계약 (semantic contract)

ArchMap은 그 의미를 기계가 읽을 수 있는 형태로 기록합니다.

AAT: Atom Map으로부터 구조 읽기

ArchMap을 확보하고 나면, 우리는 다른 종류의 질문을 던질 수 있습니다:

이 아키텍처 객체는 어떤 법칙(laws) 하에서 압력(pressure)을 받는가?

대수적 아키텍처 이론 (AAT, Algebraic Architecture Theory)은 소프트웨어 아키텍처를 Atom으로부터 생성된 대수적 구조 (algebraic structure)로 읽습니다.

AAT는 객체 (objects), 연산 (operations), 법칙 (laws), 불변량 (invariants), 장애 (obstructions), 그리고 시그니처 축 (signature axes)을 통해 아키텍처를 연구합니다.

상세한 이론은 Algebraic Architecture Theory에 맡겨두겠습니다.

이 글에서는 직관만으로도 충분합니다:

  • law (법칙): 우리가 보존하고자 하는 설계 속성 (design property)
  • witness (증거): 해당 속성과 관련된 관찰된 증거
  • obstruction (장애): 법칙을 가로막는 구조
  • signature axis (시그니처 축): 압력이 나타나는 방향
  • operation (연산): 분리 (split), 이동 (move), 보호 (protect), 또는 리팩터링 (refactor)과 같은 설계 연산
  • path / homotopy (경로 / 호모토피): 두 변경 경로가 동일한 구조를 보존하는지 여부
  • curvature / holonomy (곡률 / 홀로노미): 국소적으로는 자연스러워 보이지만 루프를 따라 돌았을 때 불일치가 발생하는 경우

일반적인 리뷰에서 엔지니어들은 종종 이러한 아이디어들을 머릿속으로 처리합니다:

이 책임(responsibility)이 섞여 있네요.

이 외부 호출 (external call)은 트랜잭션 (transaction) 내부에 있으면 안 됩니다.

이 두 가지 작업 상태 (job statuses)는 같아 보이지만, 실패 경로 (failure paths)가 다릅니다.

이 생성된 출력물은 도메인 상태 (domain state)가 되기 전에 반드시 검증되어야 합니다.

AAT는 이러한 리뷰 어휘를 우리가 계산할 수 있는 무언가로 옮기고자 시도합니다.

중요한 단계는 Atom을 단순한 라벨 (labels)이 아니라, 아키텍처 객체를 생성하는 원시 사실 (primitive facts)로 취급하는 것입니다.

Atom이 관계 (relation), 상태 (state), 효과 (effect), 계약 (contract), 그리고 의미론적 축 (semantic axes)을 담게 되면, 의존성 그래프 (dependency graph)가 보여줄 수 없는 것들을 볼 수 있습니다:

  • 다른 경로를 통해 효과의 순서 (effect order)를 바꾸는, 국소적으로는 자연스러운 변경
  • 복잡성을 다른 경계 (boundary)로 이동시키는 분리 (split)
  • 정적으로는 유사해 보이지만 의미론적 계약 (semantic contract) 하에서 서로 다른 두 워크플로 (workflows)

이것들은 결코 사소하지 않은 아키텍처 읽기입니다.

이것들은 단지 시니어 엔지니어의 직관 속에만 머물러서는 안 됩니다.

이것들은 선택된 법칙 우주 (law universe) 및 선택된 증인 (witnesses) 세트와 결합되어야 합니다.

그것이 바로 AAT의 역할입니다.

ArchSig: ArchMap + LawPolicy로부터 구조 읽기

ArchSig는 ArchMap과 LawPolicy를 가져와 AAT 스타일의 분석 패킷 (analysis packet)을 생성합니다.

ArchMap
  + LawPolicy
  -> ArchSig
...

LawPolicy는 해석 프로필 (interpretation profile)입니다.

이는 분석을 위한 법칙 우주 (law universe), 증인 규칙 (witness rules), 시그니처 축 (signature axes), 측정 정책 (measurement policy), 그리고 커버리지 요구사항 (coverage requirements)을 선택합니다.

동일한 ArchMap이라도 무엇을 중요하게 여기느냐에 따라 서로 다른 방식으로 읽힐 수 있습니다:

  • 권한 경계 (authority boundaries)
  • 상태/효과 일관성 (state/effect consistency)
  • 생성된 출력 중재 (generated output mediation)
  • 도메인 응집도 (domain cohesion)
  • 권한 커버리지 (permission coverage)
  • 복구 전제 조건 (repair preconditions)

ArchSig는 이 모든 것을 하나의 "좋음 / 나쁨" 점수로 축약하지 않습니다.

대신 서로 다른 축을 따라 발생하는 압력 (pressure)과 의미론적 결합 (semantic coupling)을 보고합니다.

출력에는 다음과 같은 판독 결과가 포함될 수 있습니다:

  • 법칙 축에 따른 비제로 압력 (nonzero pressure by law axis)
  • 워크플로 위험 (workflow risk)
  • 전송 브리지 압력 (transfer bridge pressure)
  • 상태/효과 화해 압력 (state/effect reconciliation pressure)
  • 연산 사각형 (operation squares)
  • 축별 모노드로미 결함 (axis-wise monodromy defects)
  • 아키텍처 구멍 (architectural holes)
  • 경계 홀로노미 (boundary holonomy)
  • 복구 전제 조건 차단 요소 (repair precondition blockers)
  • 리뷰 초점 (review focus)

이것은 코드 품질 점수가 아닙니다.

설계 압력 (design pressure)과 의미론적 결합 (semantic coupling)이 어디에서 나타나는지를 읽기 위한 측정 표면 (measurement surface)입니다.

사례 연구: 백엔드 리포지토리 분석하기

지금까지의 논의는 개념적이었습니다.

이제 ArchSig를 통해 하나의 백엔드 리포지토리 (backend repository)의 형태를 살펴보겠습니다.

이 리포지토리는 다수의 사용자, 권한 경계, 비즈니스 데이터, 외부 효과, 비동기 작업 (async jobs), 그리고 생성된 출력물을 가지고 있습니다.

사용자는 입력 데이터를 선택하고 분석, 생성, 추출 또는 변환 워크플로 (workflows)를 실행합니다.
외부 시스템은 이벤트를 전송합니다.
비동기 작업은 프로바이더 (providers)를 호출합니다.
결과는 비즈니스 아티팩트 (business artifacts)로 영속화됩니다.

ArchMap으로부터 ArchSig는 다음과 같은 구조들을 읽어낼 수 있습니다:

  • API, service, repository, model, schema, 그리고 task 레이어로 분리된 백엔드
  • 사용자(users), 조직(organizations), 리소스(resources) 전반에 걸친 권한 경계 (authority boundaries)
  • 여러 아티팩트가 입력 데이터로부터 파생되는 도메인 모델 (domain model)
  • 서비스 계약 (service contracts) 및 작업 상태 (job state)에 의해 매개되는 생성된 출력 (generated output)
  • 영속적인 작업 상태 (durable job state)와 쌍을 이루는 외부 제공자 효과 (external provider effects)
  • 일반적인 워크플로 (workflows)와 분리된 특권 작업 (privileged operations)

이는 이미 의존성 그래프 (dependency graph)와는 다릅니다.

ArchSig는 리포지토리를 권한 경계, 생성된 출력, 외부 효과, 그리고 영속적인 상태를 가진 비즈니스 백엔드로 읽어냅니다.

그것이 발견한 설계 압력 (Design Pressure)

가장 강력한 압력은 권한 (authority)과 생성 (generation)의 교차점에서 나타났습니다.

시스템은 단순히 다음과 같이 말하는 것이 아닙:

인증된 행위자 (authenticated actor)는 생성을 실행할 수 있다.

진정한 아키텍처 질문은 다음과 같습니다:

누가 어떤 리소스를 입력으로 사용할 수 있으며, 어떤 생성된 출력이 어떤 도메인 상태 (domain state)가 될 수 있는가?

이것이 핵심적인 경계입니다.

인가 (authorization)만을 검토하는 것으로는 충분하지 않습니다.
생성 작업 (generation job)만을 검토하는 것으로도 충분하지 않습니다.
두 경계는 서로 연결되어 있습니다.

다음으로 큰 압력은 상태/효과 조정 (state/effect reconciliation)이었습니다.

리포지토리에는 외부 제공자 (external providers), 비동기 작업 (async jobs), 이벤트 핸들러 (event handlers), 재시도 (retries), 라운드트립 (roundtrips), 그리고 보상 경로 (compensation paths)가 존재합니다.

이러한 종류의 시스템에서는 모든 것이 하나의 트랜잭션 (transaction) 안에 머무를 수 없습니다.

아키텍처에는 영속적인 중간 상태 (durable intermediate state), 외부 효과 복구 (external effect recovery), 명시적인 실패 종결 (explicit failure finalization), 그리고 재시도 가능한 경로 (retryable paths)가 필요합니다.

ArchSig는 상태 아톰 (state atoms)과 효과 아톰 (effect atoms) 사이의 관계를 통해 이를 읽어냅니다.

세 번째 압력은 생성된 출력 매개 (generated output mediation)였습니다.

생성된 출력은 유용하지만, 매개 (mediation) 없이 도메인 상태가 되어서는 안 됩니다.

입력 구성 (input construction), 구조화된 출력 (structured output), 필터링 (filtering), 검증 (validation), 작업 실패 처리 (job failure handling), 그리고 영속성 게이트 (persistence gates)가 필요합니다.

이 리포지토리에서 매개는 여러 워크플로에 걸쳐 나타났습니다:

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0