Architecture & Design/Software Architecture

Foundations - 01. 아키텍처란 무엇인가

코드를 짜는 순간, 아키텍처는 이미 정해져 있다

집을 지을 때 거실에서 영화를 보고 주방에서 요리하고 침실에서 잔다는 방의 용도가 같아도, 골조를 목조로 세울지 철골 콘크리트로 세울지는 다른 문제다. 지진이 오거나 3층을 증축하려 할 때 결과를 갈라놓는 건 방의 용도가 아니라 이 골조다. 소프트웨어도 비슷하다. 코드가 "무엇을 하는가"를 정하면, 아키텍처는 그 코드가 "어떤 구조로 세워졌는가"를 결정한다. 그리고 벽돌을 쌓는 순간 골조는 이미 정해진다 — "우린 스타트업이라 아키텍처 같은 건 안 한다"는 말이 성립하지 않는다.

아키텍처는 부정할 수 없다

소프트웨어 아키텍처 분야의 고전 에서 Bass·Clements·Kazman은 아키텍처를 "시스템에 대해 추론할 때 필요한 구조들의 집합"이라 정의한다. 요소, 요소의 속성, 요소 사이의 관계로 이루어진 구조. 시스템이 어떤 덩어리로 쪼개져 있고, 그 덩어리들이 어떻게 이어지는가를 다루는 영역이다.

이 구조는 코드를 쓰는 순간 생긴다. Foote와 Yoder가 이름 붙인 큰 진흙 덩어리(Big Ball of Mud) — 모든 모듈이 모든 모듈을 직접 부르는 카오스 — 에도 아키텍처는 있다. "모든 것이 모든 것에 의존한다"가 곧 그 시스템의 구조다. 이 덩어리가 상당히 성공적인 시스템에서 자주 나타나는 이유는, 그 구조가 초기엔 빠른 변경을 허용했기 때문이다.

그래서 "아키텍처를 하느냐"는 잘못된 질문이다. 의도적이냐 우발적이냐만 남는다. 설계하지 않으면 수많은 작은 결정이 쌓여 어쩌다 생긴 아키텍처가 되고, 그것이 팀을 짓누른다.

같은 시스템을 여러 구조로 동시에 볼 수 있다. Bass 등이 잡은 세 축은 모듈 구조(코드가 어떤 단위로 나뉘고 의존하는가, 정적), 컴포넌트-커넥터(실행 시간에 무엇이 무엇을 호출하는가, 동적), 할당 구조(소프트웨어가 하드웨어·팀·파일시스템에 어떻게 배치되는가)다. 세 축으로 같은 시스템을 그리면 그림이 다르다 — 모듈 구조에선 깔끔해 보여도 컴포넌트-커넥터에선 동기 호출 체인이 뒤엉켜 보일 수 있다. 아키텍처를 논할 땐 "어떤 구조를 보고 있나"부터 맞춰야 같은 말이 된다.

되돌리기 비용이 아키텍처와 설계를 가른다

아키텍처와 일반 '설계'의 경계는 명확하지 않다. 스펙트럼이다. 다만 선을 긋는 잣대는 하나로 충분하다 — 바꾸는 데 비용이 드는가. 벽지를 바꾸거나 식탁 위치를 옮기는 건 하루면 된다. 골조를 허물고 다시 세우는 건 집을 거의 다시 짓는 일이다. Mark Richards와 Neal Ford는 에서 아키텍처를 "중요하면서도 변경이 어려운 결정들의 모음"으로 잡는다. 함수 이름, 변수 타입, 루프 하나는 틀려도 금방 고친다. 반면 아래 결정은 한 번 적용되면 되돌리기 비싸다.

  • 주문 처리를 단일 프로세스에서 할까, 마이크로서비스로 쪼갤까
  • 서비스 간 통신을 동기로 할까, 이벤트로 할까
  • 모든 서비스가 공유 DB를 쓸까, 따로 둘까

되돌림 비용은 결정마다 다르다. 같은 '결정'이라도 차이가 극심하다.

결정 되돌림 비용
함수·변수 이름 변경 매우 낮음 (IDE 리팩터링 한 번)
타입 변경(int → long) 낮음 (컴파일러가 검증)
라이브러리 교체 중간 (호출부 수정 + 재테스트)
동기 → 비동기 전환 높음 (장애 전파·일관성·재시도·순서까지 재설계)
모놀리스 → 마이크로서비스 매우 높음 (데이터 분리·네트워크·관측성·배포 전면 개편)
RDBMS → NoSQL 매우 높음 (데이터 모델·트랜잭션·쿼리·일관성 가정 재정의)

인테리어 수준의 결정에 일주일을 쓰는 건 과잉이고, 골조 수준의 결정을 "나중에 생각하자"로 미루는 건 비용이 크다.

Richards와 Ford가 단언하는 제1법칙은 소프트웨어 아키텍처의 모든 것이 트레이드오프라는 것이다. "마이크로서비스가 무조건 좋다"는 말은 트레이드오프를 인정하지 않는다는 점에서 아키텍처적 발언이 아니다. 철골은 내진에 유리하지만 비싸고, 목조는 싸지만 화재에 취약하다 — 어느 한쪽이 전부 이기는 구조는 없다.

기능이 아니라 품질 속성이 구조를 갈라놓는다

같은 기능을 가진 두 시스템이 완전히 다른 아키텍처를 가질 수 있다. 차이를 만드는 건 기능이 아니라 품질 속성(quality attributes)이다. 기능적 요구사항은 "무엇을 하는가"다 — 주문을 받고, 결제하고, 재고를 깎는다. 두 시스템이 이걸 똑같이 잘해도 아키텍처는 전혀 다를 수 있다. 부여된 품질 속성이 다를 수 있기 때문이다.

  • 하루 1만 건인가, 1억 건인가 (확장성)
  • 결제 서비스가 멈춰도 주문은 받아야 하나 (가용성)
  • 같은 재고를 두 사람이 동시에 못 사게 해야 하나 (일관성)
  • 장애 뒤 데이터를 잃지 않아야 하나 (신뢰성)

Bass 등은 이 " ~ 성"들을 품질 속성이라 부르고, 아키텍처를 이끄는 요소(architectural drivers)로 분류한다. 아키텍처는 기능이 아니라 품질 속성에 의해 결정된다. 내진 설계가 필요한 집과 그렇지 않은 집이 골조를 다르게 해야 하는 것과 같다.

품질 속성은 "빠르게 동작해야 한다"처럼 적어놓으면 다루기 어렵다. Bass 등은 품질 속성을 시나리오로 구체화해야 한다고 본다 — 자극·환경·응답·측정의 네 요소로. "결제 시스템은 고가용성이어야 한다"는 설계를 이끌지 못하지만, "결제 노드 1대가 장애를 일으키면(자극) 정상 영업 시간에(환경) 다른 노드로 요청을 우회시키고(응답) 복구 시간 30초 이내·가동률 99.95%(측정)를 유지한다"는 즉시 헬스체크와 자동 우회, 멀티 노드 배치로 이어진다. 측정 가능한 품질 속성만이 아키텍처를 움직인다.

품질 속성 자극 환경 응답/측정 기준
확장성 주문 트래픽 피크 블랙프라이데이 p99 응답 500ms 이하, 수평 확장으로 흡수
가용성 결제 서비스 장애 정상 영업 시간 주문은 계속 수용, 결제는 큐 적체 후 복구
일관성 같은 재고 동시 주문 동시성 초과 주문(오버셀) 0건, 잔여 재고 정확

역사 박스 — 아키텍처가 프로그래밍과 구분된 학문으로 선 건 1990년대다. Perry·Wolf(1992)와 Shaw·Garlan의 (1996)가 구조와 스타일을 학문 대상으로 정립했다. 2000년대엔 UML과 표기법 위주의 "다이어그램 = 아키텍처" 시대가 왔다 갔다. 오늘날 "되돌리기 비싼 결정을 다루는 일"이라는 시선은 그 흐름의 결과다.

같은 기능, 두 구조 — 장애 앞에서 벌어지는 차이

같은 주문 처리를 두 구조로 짜고, 결제 서비스가 느려지는 상황을 넣어본다.

아키텍처 A — 동기식 모놀리스.

// 결제·재고·배송을 순차 동기 호출
class OrderService {
    void placeOrder(Order order) {
        inventory.reserve(order);
        payment.charge(order);        // 외부 PG사, 지연 폭발 지점
        shipping.dispatch(order);
    }
}

결제가 3초 걸리면 placeOrder는 3초 블록된다. 요청이 몰리면 스레드 풀이 고갈되고 주문 시스템 전체가 응답 불능에 빠진다. 결제 하나가 느려졌을 뿐인데 회사는 주문을 못 받는다. 이 현상을 장애 전파(failure cascading)라 부른다.

아키텍처 B — 이벤트 기반.

// 주문을 저장하고 이벤트만 발행
class OrderService {
    void placeOrder(Order order) {
        orders.save(order);
        events.publish(new OrderPlaced(order.id()));
    }
}
class PaymentOnOrderPlaced {
    void on(OrderPlaced e) { payment.charge(orders.find(e.id())); }
}

결제가 느려도 주문은 계속 받힌다. 이벤트가 큐에 쌓이고, 결제 서비스가 따라잡으면 처리한다. 가용성은 지켜진다. 대가가 있다 — "결제까지 완료됐나"를 즉시 알 수 없다(최종 일관성). 디버깅은 어려워지고, 메시지 브로커라는 새 의존성이 생긴다.

flowchart TD
    subgraph A["A: 동기식 모놀리스"]
        OA[OrderService] -->|동기 호출| PA[Payment]
        OA -->|동기 호출| IA[Inventory]
        OA -->|동기 호출| SA[Shipping]
    end
    subgraph B["B: 이벤트 기반"]
        OB[OrderService] -->|이벤트 발행| Q[(메시지 큐)]
        Q --> PB[Payment 구독]
        Q --> IB[Inventory 구독]
        Q --> SB[Shipping 구독]
    end
    PA -. 결제 지연 시 전체 블록 .-> X1[주문 불능]
    PB -. 결제 지연 시 큐 적체 .-> X2[주문은 가능, 결제 지연]
품질 속성 A: 동기식 모놀리스 B: 이벤트 기반
가용성 (부분 장애) 의존 서비스 장애 시 전체 블록 큐가 버퍼 역할
응답성 결제 지연이 주문 지연으로 즉시 전파 결제 지연이 주문에 즉시 영향 없음
일관성 (결제 완료 시점) 강함 — 주문 완료 = 결제 완료 약함 — 최종 일관성, 중간 상태 노출
단순함/디버깅 호출 스택 한 줄로 추적 용이 메시지 추적 부담
확장 비용 전체가 함께 커짐 서비스별 독립 확장

A가 약한 품질 속성이 있고 B가 약한 품질 속성이 있다. 어느 쪽도 전부 이기지 못한다. 트레이드오프를 명시적으로 놓고 고르는 것이 아키텍처 작업이지, "더 좋은 쪽"을 찾는 것은 아키텍처 작업이 아니다.

다이어그램은 아키텍처가 아니다

아키텍처를 상자와 화살표 그림으로 요약하려는 시도가 흔하다. 그림은 아키텍처를 설명하는 부정확한 사본일 뿐, 아키텍처 그 자체가 아니다. 아키텍처는 시스템에 실재하는 구조다 — 실제로 어떤 프로세스가 어떤 프로세스를 부르는지, 실제로 어떤 서비스가 어떤 DB를 쓰는지. 팀이 "아키텍처 문서"라며 멋진 그림을 그려놓고 코드를 전혀 다르게 짜는 일이 흔한데, 그 그림은 실제 시스템과 다른 도면이다. 그림이 코드와 어긋나면 어느 쪽이 진짜인지 따져야지, 그림을 예쁘게 다시 칠할 일이 아니다. 한 시스템을 여러 관점에서 그려야 하는 이유가 여기에 있다 — Kruchten의 4+1 뷰나 Simon Brown의 C4 같은 접근은 같은 시스템을 다른 청중·다른 상세도로 보여주기 위한 장치다.

언제, 어떻게 결정하는가

"아키텍처는 일찍 결정해야 한다"는 말은 반은 맞고 반은 위험하다. 되돌리기 비싼 결정은 일찍 신중하게 내리는 게 유리하다 — 골조를 나중에 뒤집으면 그 위에 쌓은 게 다 흔들린다. 하지만 "시작에 모든 결정을 확정하라"는 극단적 해석은 문제가 있다. 시작 시점엔 요구사항이 가장 불확실하다. 그때 전부 얼려버리면 나중에 드러나는 정보에 적응하지 못하는 딱딱한 구조가 된다.

현대 담론은 진화적 아키텍처로 기운다 — Ford·Parsons·Kua가 에서 편 접근이다. 되돌림 비용이 큰 결정은 일찍 신중하게, 되돌릴 수 있는 결정은 뒤로 미루며, 구조가 요구사항 변화에 맞춰 진화하도록 짠다.

아키텍처는 기술만의 문제도 아니다. Melvin Conway의 1968년 관찰 — "시스템을 설계하는 조직은 자기 의사소통 구조를 복제한 구조를 만든다" — 이 아키텍처와 조직이 떼어 쓸 수 없음을 가리킨다.

아키텍트는 안내자다

"아키텍트 = 위에서 구조를 명령하는 설계자" 모델은 거의 작동하지 않는다. 한 사람이 모든 결정을 내리고 개발자가 따르기만 하면, 코드와 구상이 급격히 어긋난다 — 실제 시스템과 다른 도면이 쌓이는 것이다. 마틴 파울러와 랄프 존슨이 제안한 더 현실적인 모델은 아키텍트를 안내자로 본다. 구조적 결정을 독점하는 게 아니라, 개발자가 올바른 결정을 내릴 수 있게 공유된 원칙과 템플릿을 깔고, 되돌리기 비싼 결정에 직접 개입하며, 팀 전체의 아키텍처적 판단력을 키운다. 이 모델에서 아키텍트의 핵심 산출물은 그림이 아니라 결정과 원칙의 기록이다 — 그래서 아키텍처 결정 기록(ADR)이 떠오른다.

아키텍트의 일은 되돌리기 비싼 결정을 식별하고, 트레이드오프를 명시적으로 만들고, 기록에 남겨 팀이 따를 수 있게 하는 것이다. "무엇을 포기했나"를 드러내는 것이 아키텍트의 말투다.

설계 사례 — 스타트업에서 성장하는 아키텍처 진화

한 스타트업이 주문 서비스를 시작한다. 처음엔 모놀리스 — OrderService 하나에 결제·재고·배송 로직이 전부 들어간다. 출시 속도가 생명이고, 트래픽은 하루 수백 건이다. 이 단계에서 모놀리스는 합리적 선택이다 — 진입 장벽이 낮고 배포가 한 번에 끝난다.

트래픽이 하루 10만 건을 넘으면서 문제가 시작된다. 피크 시간에 결제 API가 3초 걸리면, 동기 호출 체인 때문에 주문 전체가 멈춘다. 블랙프라이데이에 2시간 장애가 난다. 품질 속성 요구가 바뀐 것이다 — "가용성"이 "출시 속도"를 앞지른 시점이다.

flowchart LR
    S1["1단계: 모놀리스<br/>(출시 속도 우선)"] --> S2["2단계: 결제 분리<br/>(가용성 문제 해결)"]
    S2 --> S3["3단계: 이벤트 기반<br/>(확장성 + 독립 배포)"]

2단계에서 결제 서비스를 별도로 분리한다. 이때 아키텍처 결정을 ADR로 남긴다:

ADR-001: 결제 서비스를 별도 프로세스로 분리한다

상태

수락됨 (2026-03-15)

맥락

블랙프라이데이 피크 시 결제 API 지연(3초)이 주문 전체를 블록.
동기식 모놀리스에서 결제 장애 시 주문 수용 불가.

결정

결제 로직을 별도 서비스로 분리. 주문은 결제 API를 동기 호출하되,
타임아웃(2초) + 폴백(결제 대기 상태)으로 장애 전파 차단.

결과

  • 얻는 것: 결제 장애 시 주문은 '결제 대기'로 수용 가능.
  • 잃는 것: 분산 시스템 복잡성 증가, 배포 파이프라인 2배.
  • 후속: 3단계에서 결제를 비동기 이벤트로 전환 검토(ADR-003).

3단계로 가면 결제를 동기 호출이 아니라 이벤트로 보낸다. 주문은 "접수됨" 상태로 끝내고, 결제는 별도로 처리한다. 이 전환의 되돌림 비용은 크다 — 데이터 일관성 모델이 바뀌고(강일관성 → 최종 일관성), 클라이언트가 "결제 대기 중" 상태를 처리해야 한다. 하지만 하루 100만 건을 넘기려면 이 선택이 필요하다.

이 진화에서 주목할 점은 — 각 단계에서의 아키텍처가 "틀린" 게 아니라는 것이다. 1단계 모놀리스는 그 시점의 품질 속성(출시 속도)에 맞는 정답이었고, 3단계 이벤트 기반은 새 품질 속성(확장성·가용성)에 맞는 정답이다. 아키텍처는 고정이 아니라 요구사항과 품질 속성이 변함에 따라 진화하는 것이다. 중요한 것은 각 전환을 ADR로 기록해, "왜 그때 모놀리스였고 왜 지금 분리했는가"를 미래의 팀이 이해할 수 있게 하는 것이다.

골조는 이미 있다

아키텍처가 시스템에 있다는 건 사실이 아니라 전제다. 코드를 쓰는 순간 골조는 이미 세워진다. 의미 있는 질문은 그 골조가 의도적으로 세워진 것인지 어쩌다 세워진 것인지다. 주말마다 서버를 꺼느라 바쁜 상황이라면, 골조를 "안 다뤄서"가 아니라 수많은 작은 결정을 검토 없이 쌓아둔 탓일 가능성이 높다. 아키텍처를 다루기 시작한다는 건, 그 결정들을 끌어모아 빛 아래에 놓고 "이게 정말 우리가 원하는 골조인가"를 묻는 일에서 출발한다. 철골이 좋은지 목조가 좋은지는, 그 집이 지진 다발 지역인지·증축 계획이 있는지·예산이 얼마인지에 달려 있다 — 소프트웨어도 마찬가지로, 정답이 아니라 그 시스템이 처한 상황에 맞는 골조를 고르는 일이다.


참고

  • Bass, Clements, Kazman — (4th ed, Addison-Wesley, 2021), Ch.1·2·4 — 접근 2026-07-15
  • Richards, Ford — (O'Reilly, 2020), Ch.1 (제1법칙: 모든 것은 트레이드오프)
  • Fowler — "Who Needs an Architect?" (IEEE Software, 2003), https://martinfowler.com/ieeeSoftware/whoNeedsArchitect/index.pdf — 접근 2026-07-15
  • Foote, Yoder — "Big Ball of Mud" (1999), http://www.laputan.org/mud/ — 접근 2026-07-15
  • Ford, Parsons, Kua — (O'Reilly, 2017)
  • Conway — "How Do Committees Invent?" (Datamation, 1968)