소프트웨어 아키텍처

Software Architecture

개념

시스템을 어떤 덩어리로 자르고 덩어리끼리 어떻게 말을 걸게 할지 코드를 쓰기 전에 정해 두는 설계입니다.

등장 배경

페이지덱의 첫 서비스는 파일 몇 개가 전부였습니다. 문서를 저장하는 코드, 댓글을 다는 코드, 알림 메일을 보내는 코드가 한자리에 섞여 있었고 만드는 사람이 셋이던 시절에는 그게 제일 빨랐습니다. 누가 어디를 고치는지 말로 확인하면 됐고, 고친 것은 그날 저녁에 그대로 올라갔습니다.

구성원이 마흔다섯 명이 되자 같은 구조가 다르게 굴기 시작했습니다. 태오가 알림 메일 발송 부분을 고쳤는데 다음 날 아침에 문서 저장이 멈췄습니다. 두 기능은 아무 관계도 없어 보였지만 안에서 같은 설정값을 읽고 있었고, 그 사실을 아는 사람은 그 코드를 처음 쓴 사람뿐이었습니다. 원인을 찾는 데 반나절, 되돌리는 데 한 시간이 들었습니다.

이런 일이 몇 번 반복되면 팀의 말투가 바뀝니다. "이거 건드려도 돼요?" 라는 질문이 하루에도 몇 번씩 오가고, 아무도 확답을 못 하니 결국 손대지 않는 쪽으로 굳습니다. 고치면 나아질 것을 알면서도 옆에서 무엇이 깨질지 몰라 그냥 두는 코드가 늘어납니다. 기능 하나를 붙이는 데 처음에는 이틀이 들었는데 1년 뒤에는 같은 크기의 일에 2주가 듭니다.

문제는 코드가 틀린 것이 아니라 무엇이 무엇에 닿아도 되는지를 아무도 정해 두지 않았다는 데 있었습니다. 선이 없으면 선을 넘었는지도 알 수 없습니다. 급할 때마다 옆 기능의 속을 직접 들여다보는 지름길이 하나씩 생기고, 그 지름길은 지도에 표시되지 않으니 다음 사람은 밟기 전까지 있는 줄도 모릅니다. 새로 들어온 사람에게는 이 지름길이 전부 함정입니다. 코드 자체는 사흘이면 읽지만 어느 부분이 어디에 닿는지는 두어 달을 겪어야 알게 되고, 그동안 나오는 실수는 대개 같은 자리에서 반복됩니다.

소프트웨어 아키텍처는 그 선을 짓기 전에 미리 긋자는 제안입니다. 결제와 알림과 문서 저장을 한 덩어리에 넣을지 셋으로 나눌지, 나눈다면 서로 무엇을 어떤 창구로 주고받을지를 코드를 쓰기 전에 정합니다. 기능 하나를 고치는 데는 하루가 들지만 덩어리를 다시 자르는 데는 분기가 들기 때문에, 이 결정은 미룰수록 값이 올라갑니다.

분야 구성

아래 묶인 용어는 네 갈래로 나뉩니다. 어떤 모양으로 자를지를 고르는 구조, 잘 잘랐는지 재는 눈금인 품질 속성, 잘못 잘랐을 때 생기는 위험, 그리고 자르는 법을 앞사람들이 정리해 둔 설계 지식입니다. 앞의 하나가 선택지이고 나머지 셋은 그 선택을 판단하고 보완하는 자리입니다.

구조 갈래에는 일곱 개가 있고 두 질문으로 다시 갈립니다. 하나는 배포 단위를 몇 덩어리로 둘지이고, 다른 하나는 한 덩어리 안을 어떻게 층으로 나눌지입니다. 배포 단위란 한 번에 서버에 올리는 묶음을 말합니다.

  1. 모놀리스 — 전부를 한 덩어리에 담아 한 번에 올립니다. 결제도 알림도 문서 저장도 같은 프로그램 안에 있어서 내부끼리 함수를 바로 부를 수 있고, 처음 만들 때 가장 빠릅니다. 대신 알림 코드 한 줄을 고쳐도 결제까지 함께 다시 올라갑니다.
  2. 마이크로서비스 — 기능별로 잘라 각자 따로 올립니다. 결제 서비스와 알림 서비스가 다른 프로그램으로 돌고 네트워크를 통해 말을 겁니다. 알림만 고쳐서 알림만 올릴 수 있고 트래픽이 몰리는 쪽만 골라 늘릴 수 있지만, 서비스 다섯 개를 굴리려면 배포와 감시도 다섯 벌이 필요합니다.
  3. 모듈러 모놀리스 — 올리는 것은 한 덩어리로 두되 안을 모듈로 갈라 놓고 모듈끼리는 정해진 창구로만 부르게 막습니다. 알림 모듈이 문서 모듈의 내부 데이터를 직접 읽으면 코드 단계에서 걸립니다. 구성원 마흔다섯 명 규모에서 자주 고르는 중간 지점입니다.
  4. 서버리스 — 서버를 직접 빌리고 관리하는 대신 함수 단위로 코드를 올려 두고 요청이 올 때만 돌게 하는 방식입니다. 쓴 만큼만 돈을 내는 것이 장점이고, 한동안 호출이 없다가 첫 요청이 들어오면 준비하는 데 잠깐 시간이 걸리는 것이 단점입니다.
  5. 계층형 아키텍처 — 한 덩어리 안을 표현·업무·데이터 세 층으로 쌓고 위층만 아래층을 부르게 합니다. 화면에서 온 요청이 업무 규칙을 거쳐 데이터베이스로 내려가는 한 방향입니다. 가장 오래되고 가장 많이 쓰이는 배치입니다.
  6. 헥사고날 아키텍처 — 업무 규칙을 한가운데 두고 데이터베이스나 결제 대행사 같은 바깥 기술을 갈아 끼울 수 있는 부품으로 밀어냅니다. 결제 대행사를 바꿔도 할인 계산 규칙은 손대지 않는 상태를 노립니다.
  7. 이벤트 기반 아키텍처 — 덩어리끼리 직접 부르는 대신 "문서가 저장됐다" 같은 사건을 던져 두고 관심 있는 쪽이 알아서 받아 갑니다. 알림 기능이 잠깐 멈춰도 문서 저장은 그대로 끝나고, 나중에 새 기능이 같은 사건을 하나 더 받아 가도 던지는 쪽 코드는 그대로입니다.

품질 속성 갈래는 고른 구조가 잘 서 있는지 재는 눈금 셋입니다. 눈금이 있어야 취향 싸움이 아니라 근거를 두고 이야기할 수 있습니다.

  1. 결합도 — 구성 요소가 서로에게 얽혀 있는 정도입니다. 알림 코드가 문서 저장 쪽 내부 구조를 직접 들여다보고 있으면 결합도가 높고, 정해진 창구 하나로만 주고받으면 낮습니다. 낮을수록 한쪽을 고칠 때 다른 쪽이 덜 깨집니다.
  2. 응집도 — 한 모듈 안의 코드가 한 가지 일에 모여 있는 정도입니다. 결제 모듈 안에 결제 계산과 마케팅 메일 발송이 함께 들어 있으면 응집도가 낮습니다. 높을수록 무엇을 고치려면 어디를 열어야 하는지가 분명해집니다.
  3. 확장성 — 쓰는 사람이 늘어도 감당할 수 있게 키울 수 있는 성질입니다. 동시 접속이 100명에서 1만 명이 됐을 때 서버 대수만 늘려 버티면 확장성이 있는 것이고, 코드를 다시 짜야 한다면 없는 것입니다.

위험 갈래에는 단일 장애점 하나가 있습니다. 그것 하나가 멈추면 전체가 멈추는 지점을 가리킵니다. 서비스를 다섯 덩어리로 나눠 놓고도 다섯 모두가 같은 데이터베이스 한 대를 보고 있으면 그 한 대가 곧 단일 장애점입니다. 나눴다는 사실만으로 안전해지지 않고, 어디가 혼자 짊어지고 있는지를 따로 찾아 두어야 합니다.

설계 지식 갈래는 앞사람들이 겪고 정리해 둔 셋입니다. 매번 처음부터 고민하지 않게 해 주는 재료입니다.

  1. 디자인 패턴 — 자주 나오는 설계 문제에 이름과 정해진 해법을 붙여 둔 것입니다. 같은 값을 프로그램 전체에서 하나만 두고 싶을 때 쓰는 방식처럼, 이름만 대면 서로 같은 그림을 떠올리게 하는 것이 실제 쓸모입니다.
  2. SOLID 원칙 — 객체 지향 설계에서 지키면 좋은 다섯 가지 규칙입니다. 한 덩어리는 한 가지 이유로만 바뀌어야 한다는 것처럼, 앞의 결합도와 응집도를 코드 단위에서 지키는 방법을 다섯 문장으로 줄여 둔 것입니다.
  3. 도메인 주도 설계 — 기술이 아니라 업무의 말로 경계를 긋는 방법입니다. 결제와 문서를 나눌 때 데이터베이스 표 모양이 아니라 업무에서 둘을 다르게 부르는지를 기준으로 삼습니다. 덩어리를 어디서 자를지에 답을 주기 때문에 구조 갈래와 붙어 다닙니다.

네 갈래는 한 번에 하나씩 정하는 목록이 아니라 서로를 되먹입니다. 모놀리스로 시작해 결합도가 올라가면 모듈로 가르게 되고, 모듈 경계를 어디에 그을지는 도메인 주도 설계가 답하고, 가른 뒤에 남은 공용 데이터베이스가 단일 장애점으로 드러나면 그 부분만 다시 자릅니다. 고르는 순서도 대개 정해져 있습니다. 팀이 몇 명이고 한 주에 몇 번 배포하는지를 먼저 보고 배포 단위를 정한 다음, 한 덩어리 안의 층을 정합니다. 반대로 층부터 굳히면 나중에 덩어리를 자를 때 층이 전부 어긋납니다.

실무 용례

"이건 아키텍처 결정이라 이번 스프린트에서 정하기는 어렵고, 다음 주에 따로 자리를 잡죠."

코드 몇 줄을 고치는 판단이 아니라 되돌리는 값이 큰 판단이니 시간을 따로 쓰자는 뜻입니다.

"지금 구조로는 결제 쪽만 따로 늘리지 못해요. 트래픽 몰리면 전부 같이 올려야 합니다."

배포 단위가 하나라서 부하가 걸린 부분만 골라 키울 수 없다는 지적입니다.

"그건 결합도 문제예요. 알림 쪽이 문서 저장 쪽 내부를 직접 들여다보고 있어서 그렇습니다."

증상은 버그로 보이지만 원인은 두 덩어리 사이에 창구가 없는 것이라는 진단입니다.

페이지덱에서 이 말이 가장 자주 오간 자리는 기업 고객용 기능을 붙이기로 한 분기였습니다. 계약 고객마다 다른 권한 규칙이 필요했는데, 그 규칙을 문서 저장 코드 안에 조건문으로 넣으면 두 주 만에 끝나고 따로 떼어 내면 여섯 주가 걸리는 상황이었습니다. 태오는 조건문으로 넣으면 다음 고객이 올 때마다 같은 자리에 조건문이 하나씩 붙어 반년 뒤에는 아무도 그 부분을 못 고치게 된다고 봤습니다.

규원은 두 안을 놓고 되돌리는 값을 물었습니다. 두 주짜리 안은 나중에 떼어 내려면 여섯 주가 아니라 석 달이 걸린다는 답이 나왔고, 결정은 여섯 주 쪽으로 갔습니다. 지현은 이 논의를 문서에 남겨 두었습니다. 넉 달 뒤 비슷한 요청이 들어왔을 때 같은 이야기를 처음부터 다시 하지 않기 위해서였습니다.

흔한 오해

가장 흔한 오해는 아키텍처를 기술을 고르는 일과 같다고 보는 것입니다. 어떤 언어를 쓰고 어떤 데이터베이스를 붙일지가 첫 회의에서 제일 먼저 나오는 화제이니 그렇게 읽히기 쉽습니다. 하지만 아키텍처가 답하는 질문은 무엇을 쓰느냐가 아니라 어디서 자르고 어떻게 잇느냐입니다. 같은 언어와 같은 데이터베이스로도 한 덩어리를 만들 수도 있고 다섯 덩어리를 만들 수도 있습니다. 이 둘을 같은 것으로 보면 팀은 유행하는 도구를 고르는 데 시간을 쓰고 정작 경계는 아무도 긋지 않은 채 코드를 시작합니다. 그러면 반년 뒤에 새 도구로 만든 옛 문제가 그대로 돌아옵니다.

두 번째는 마이크로서비스를 더 발전된 형태로 읽는 것입니다. 큰 회사들이 그렇게 쓴다는 이야기가 많이 돌아서 모놀리스는 거쳐 가는 단계처럼 보입니다. 실제로는 둘이 위아래가 아니라 맞바꿈 관계입니다. 잘게 나누면 각자 따로 올릴 수 있는 대신, 한 번에 끝나던 함수 호출이 네트워크를 건너게 되고 다섯 덩어리를 감시하고 배포할 사람과 도구가 필요해집니다. 열 명짜리 팀이 서비스를 열두 개로 나누면 기능을 만드는 시간보다 서비스 사이를 맞추는 시간이 더 들고, 장애가 나면 어느 덩어리에서 시작됐는지 찾는 데만 한나절이 갑니다. 고르는 기준은 유행이 아니라 지금 팀이 감당할 수 있는 운영의 양입니다. 나눌지 말지보다 먼저 답할 질문은 지금 무엇이 아픈가입니다. 배포할 때마다 관계없는 기능이 함께 올라가는 것이 무서우면 모듈 경계를 긋는 것으로 대부분 풀리고, 특정 기능만 부하를 못 버티는 것이 문제라면 그 하나만 떼어 내면 됩니다.

자주 헷갈리는 용어

용어무엇을 정하는가소프트웨어 아키텍처와의 차이
디자인 패턴자주 나오는 설계 문제의 정형화된 해법다루는 크기가 다릅니다. 패턴은 클래스 몇 개 범위의 해법이고 이쪽은 시스템 전체를 어떤 덩어리로 자를지의 결정입니다
정보 구조내용을 어떻게 나누고 이름 붙이고 연결할지자르는 대상이 다릅니다. 정보 구조는 사용자가 보는 메뉴와 화면의 뼈대를 다루고 이쪽은 화면 뒤 코드와 서버의 뼈대를 다룹니다

같이 보면 좋은 페이지

  • 엔지니어링

    아키텍처가 열세 갈래 가운데 어디에 놓이고 배포·품질·운영과 어떻게 이어지는지 위에서 한 번 봅니다

  • 모놀리스

    거의 모든 서비스가 여기서 시작하므로, 이 구조의 장점과 한계를 알면 나머지 여섯 구조가 무엇을 바꾸려 한 것인지 읽힙니다

하위 용어

마지막 업데이트 2026-09-16