개주 훈련일지/📚 코살대 교본 학습

전통적인 설계 원리

lshfood2 2026. 2. 1. 15:36

[ 전통적인 설계 원리 ]

소프트웨어 설계에서

기능 요구를 만족시키는 것만으로는

좋은 설계가 되지 않는다.

 

같은 기능이라도 설계 품질에 따라 이해 난이도,

변경 비용, 장애 전파 범위가 크게 달라진다.

 

전통적인 설계 원리는 이런 설계 품질을

확보하기 위한 기본 원리들을 묶어서 설명한다.

 

이 글은 전통적으로 중요하게 보는 설계 원리인

단순성, 효율성, 분할과 계층화,

추상화, 캡슐화, 모듈화,

그리고 결합과 응집을 한 흐름으로 정리한다.


전통적인 설계 원리 한 장 요약

전통적인 설계 원리를

핵심 문장으로만 정리하면 아래 5개다.

원리 핵심 의미 설계자가 해야 할 일
단순성 복잡함을 최소화해
이해와 변경을 쉽게 만든다
불필요한 단계, 분기, 의존을 줄인다
효율성 시간과 자원을 적정하고
효과적으로 사용한다
병목을 제거하고 자원 사용을 통제한다
분할, 계층화 큰 문제를 다루기 쉬운
덩어리로 나눈다
책임 단위로 쪼개고 계층을 만든다
추상화 목적에 필요한 정보만 남기고
나머지는 숨긴다
인터페이스 중심으로 동작을 정의한다
모듈화 독립적인 구성 요소로
나누어 관리한다
낮은 결합, 높은 응집 구조를 만든다

1. 효율성

효율성은 시스템이 사용하는 자원이

적정하고 효과적임을 의미한다.

 

전통적으로 효율성에서 다루는

핵심 자원은 두 가지다.

  • 처리 시간
  • 기억 공간

초기의 컴퓨터 시스템에서는

CPU와 메모리 비용이 높아 효율성이

설계의 최우선 관심사였다.

 

현재는 하드웨어 비용이 상대적으로 낮아져

모든 시스템이 효율성만을 최우선으로 두지는 않는다.

 

다만 실행 시간 제약이 엄격한 실시간 시스템에서는

여전히 효율성이 최상위 설계 목표가 된다.

 

효율성을 설계 항목으로 바꾸는 관점은 아래처럼 잡는다.

  • 무엇이 병목인지 정의한다
    : CPU, 메모리, 디스크 I/O, 네트워크, DB 쿼리
  • 어떤 기준으로 측정할지 정한다
    : 평균 응답시간, p95, 처리량, 동시 사용자, 메모리 상한
  • 어떤 전략을 쓸지 정한다
    : 캐시, 비동기, 인덱스, 페이징, 배치, 압축, 큐

효율성은 감각이 아니라

설계 제약으로 명시될 때 관리가 된다.


2. 단순성

단순성은 설계 품질의 핵심 평가 기준으로 취급된다.

소프트웨어의 유지보수는 비용이 많이 드는 작업이며,

유지보수의 첫 단계는 시스템 이해이기 때문이다.

 

단순성이 유지보수성을

끌어올리는 흐름은 다음과 같다.

  • 단순한 구조 → 이해가 빠름
  • 이해가 빠름 → 변경 영향 분석이 쉬움
  • 변경 영향 분석이 쉬움 → 수정 범위가 줄어듦
  • 수정 범위가 줄어듦 → 결함 유입이 줄어듦

단순성을 확보하는 대표적인 설계 습관은

아래처럼 정리할 수 있다.

  • 한 요소가 하는 일을 한 문장으로 설명 가능하게 만든다
  • 한 화면, 한 기능 흐름이 불필요하게 분기하지 않게 만든다
  • 데이터의 소유권과 변경 책임을 분명히 한다
  • 모듈 간 통신 규칙을 단순하게 유지한다

단순성은 코드가 짧다는 의미가 아니라,

구조를 이해하는 비용이 낮다는 의미다.


3. 분할과 계층화

단순하고 효율적인 설계를 만들려면

큰 문제를 한 번에 구현하려 하면 안 된다.

여기서 등장하는 원리가 분할과 계층화다.

  • 분할
    : 복잡한 시스템을 구성 요소로 자르는 과정
  • 계층화
    : 잘린 구성 요소를 상위-하위 구조로 정리하는 과정

분할을 적용하는 전형적인 방식이

단계적 분할(stepwise refinement)이다.

 

상위 수준의 목표를 먼저 잡고,

이를 점점 더 구체적인 하위 단계로

내려가며 설계를 다듬는다.

 

단계적 분할의 기본 흐름은 아래처럼 잡을 수 있다.

  • 1단계: 시스템이 제공해야 할 큰 기능 덩어리 정의
  • 2단계: 기능 덩어리를 책임 단위로 분해
  • 3단계: 책임 단위를 모듈, 인터페이스, 데이터 흐름으로 정리
  • 4단계: 각 모듈의 내부 알고리즘과 데이터 구조 구체화

이 과정을 거치면 설계는

자연스럽게 계층을 갖게 된다.

 

계층화는 구조를 읽기 쉽게 만들고

변경 범위를 제한하는 역할을 한다.


4. 추상화

추상화는 모든 엔지니어링 작업에서 유용한 개념이다.

구현의 상세를 보지 않고 추상적인 수준에서

컴포넌트를 다루게 해준다.

 

추상화의 핵심 정의는 단순하다.

  • 특정 목적과 관련된 정보에 집중하고 나머지는 무시한다

예를 들어 자동차를 추상화하면,

내부 메커니즘 대신 아래처럼 동작 관점으로 정의할 수 있다.

  • 가속하면 속도가 올라간다
  • 브레이크를 밟으면 멈춘다

소프트웨어에서 추상화는

대표적으로 두 방식으로 나타난다.

 

1) 자료 추상화

  • 데이터의 구조만으로 대상을 정의한다
  • 내부 저장 방식과 구현은 뒤로 미룬다

2) 절차, 동작 추상화

  • 내부 구현 대신 외부에서
    관찰 가능한 절차로 대상을 정의한다

절차 추상화 예시는 아래처럼 정리할 수 있다.

 

send를 추상적으로 정의한 절차 예시

(= client, server, message)

단계 설명
1 클라이언트가 서버 상태를 탐색한다
2 TCP/IP 커넥션을 오픈한다
3 메시지를 보내고 응답을 기다린다
4 커넥션을 닫는다

 

추상화가 중요한 이유는 복잡성을 줄여

설계와 구현을 가능하게 만들기 때문이다.

 

또한 유지보수 단계에서도 추상화는 중요하다.

이미 구현된 상세 속에서 서브시스템과

컴포넌트의 핵심 동작을 찾아내야

전체 시스템을 이해할 수 있기 때문이다.


5. 캡슐화와 정보 은닉

캡슐화는 추상화된 대상이 제공하는 서비스를

쉽게 접근하게 하는 원리다.

 

서비스에 필요한 핵심만 노출하고, 내부 구현은 숨긴다.

이 내부 숨김을 정보 은닉(information hiding)이라고 한다.

 

캡슐화의 설계 효과는 다음으로 정리된다.

  • 외부는 인터페이스만 알면 된다
  • 내부 구현이 바뀌어도 외부 영향이 줄어든다
  • 변경 요구에 탄력적으로 대처할 수 있다

TV를 리모컨 관점으로 추상화했다고 가정하면,

공중파 신호 디코딩이나 화면 렌더링 같은 내부 구현은

굳이 외부에 드러낼 필요가 없다.

대신 외부에서 필요한 것은 인터페이스와 상태다.

  • 핵심 데이터
    : 채널, 볼륨, 전원 상태
  • 핵심 오퍼레이션
    : 채널 변경, 볼륨 변경, 음소거, 전원 켜기/끄기

객체지향 언어를 쓰면

접근 제어자를 통해 정보 은닉을 구현하기 쉬워진다.

 

하지만 캡슐화는 객체지향에만 국한된 원리가 아니라

설계 전반에서 적용되는 전통적 원리다.


6. 모듈화

모듈화는 문제를 소프트웨어의 구성 요소가

될 만한 수준으로 분할하는 과정이다.

 

복잡한 시스템을 세분화된 구성 요소로 정의하면

개발자와 고객 모두 더 쉽게 이해할 수 있고,

다루기 쉬운 구조가 된다.

 

모듈화의 이점은 크게 세 가지로 정리된다.

  • 개발과 테스트가 쉬워진다: 독립적으로 개발 가능
  • 변경 영향이 제한된다: 수정이 특정 모듈에 국한
  • 디버깅이 쉬워진다: 문제 범위를 좁히기 쉬움

하지만 단점도 있다.

  • 모듈이 지나치게 많아지면 상호작용 이해가 어려워진다
  • 모듈 경계가 과도하면 오히려 복잡도가 증가한다

그래서 모듈화는 무조건 잘게 쪼개는 것이 아니라,

적절한 수준을 선택하는 것이 핵심이다.

 

모듈화 수준을 판단할 때는 아래 두 축이 자주 충돌한다.

  • 사용 용이성
    : 작게 나누면 개별 이해는 쉬움
  • 재사용 가능성
    : 작게 나누면 재사용 가능성이 늘 수 있음
  • 상호작용 복잡도
    : 너무 작으면 연결이 많아져 전체 이해가 어려움

즉 모듈의 크기는 이해, 유지, 확장이 쉬운 균형점에서 정해야 한다.


7. 추상화, 캡슐화, 모듈화의 관계

세 원리는 따로 노는 개념이 아니라

한 흐름으로 이어진다.

  • 추상화
    : 큰 시스템을 핵심 특성 중심으로 나누는 기준을 만든다
  • 캡슐화
    : 나뉜 요소에서 핵심만 노출하고 내부 변경 영향을 줄인다
  • 모듈화
    : 결과적으로 독립적인 모듈 구조를 완성한다

흐름도로 정리

통째로 구성된 시스템
↓ (추상화: 핵심 특성 중심으로 분할)
인터페이스 중심의 구성 요소들
↓ (캡슐화: 내부 구현 은닉, 접근 통제)
구현 교체가 가능한 구성 요소들
↓ (모듈화: 독립적인 모듈로 정리)
모듈화된 시스템

여기서 중요한 관점이 하나 더 있다.

  • 인터페이스는 사용자의 뷰
  • 구현은 개발자의 뷰

추상화 원칙에 따라 설계되면 사용자는

내부 구현을 몰라도 사용 가능하고,

개발자는 외부에 알리지 않고 구현을 바꿀 수 있다.


8. 결합

결합(coupling)은 모듈 간에 서로 의존하는 정도다.

좋은 소프트웨어는 낮은 결합을 가진다.

결합이 강해지면 문제가 생기는 이유는 다음과 같다.

  • 이해가 어렵다
    : 모듈 하나를 보려면 다른 모듈까지 따라가야 함
  • 변경 파급이 크다
    : 한 모듈 수정이 연쇄 변경으로 이어짐
  • 오류 전파가 쉽다
    : 한 모듈의 결함이 다른 모듈로 확산됨

결합 정도를 결정하는 요소는 두 가지다.

  • 모듈 간 인터페이스 수
  • 각 인터페이스의 복잡성(통신 유형에 따라 결정)

결합도 5단계 분류

종류 의미 특징
내용 결합 다른 모듈의 내부 내용을
(=문장, 로컬 데이터)
직접 참조하거나 내부로 분기
최악 수준, 내부 변경에
바로 깨짐
공통 결합 전역 변수를 통해
데이터를 교환
숨은 의존이 생기고
추적이 어려움
제어 결합 제어 정보를 넘겨
상대 모듈의 흐름을 결정
호출자가 피호출자
흐름에 개입
스탬프 결합 복합 구조를 넘기되
일부 필드만 사용
불필요한 데이터 의존이 생김
데이터 결합 단순 타입 데이터만
매개변수로 전달
가장 바람직한 결합 형태

9. 결합을 낮추는 방법

결합을 낮추려면 두 가지를 줄여야 한다.

  • 인터페이스 수를 줄인다
  • 인터페이스 복잡도를 낮춘다

결합에 영향을 주는 요소

요소 낮음 높음
인터페이스 복잡도 단순하고 명확 복잡하고 불투명
연결 형태 이름으로 모듈에 연결 내부 요소에 직접 연결
커뮤니케이션 내용 데이터 제어 정보, 복합(데이터+제어 정보)

 

실전 체크리스트로 바꾸면 이렇게 된다.

  • 다른 모듈의 내부 데이터에 직접 접근하지 않는다
  • 전역 변수로 상태를 공유하지 않는다
  • 제어 플래그로 상대 모듈의 내부 흐름을 조종하지 않는다
  • 복합 객체를 통째로 넘기기보다 필요한 데이터만 넘긴다
  • 공개 API를 작고 명확하게 유지한다

특히 제어 정보를 넘기는 순간, 이해 난이도가 급격히 올라간다.

데이터만 주고받을 때가 가장 최소 수준의 결합이다.


10. 응집

응집(cohesion)은 하나의 모듈 안에서

수행되는 작업들이 서로 관련된 정도다.

 

모듈이 특정 작업을 수행하기 위해

필요한 것들만 잘 모여 있는지를 보는 기준이다.

 

응집이 높을수록 좋은 이유는 다음과 같다.

  • 재사용이 쉽다
  • 이해가 쉽다
  • 수정 영향이 줄어든다

응집은 일반적으로 높은 쪽에서

낮은 쪽으로 아래 순서로 나열한다.

응집 종류 의미 핵심 포인트
정보적 응집
Informational
여러 오퍼레이션이 같은
데이터에 대해 실행됨
데이터 중심,
객체 설계와 잘 맞음
기능적 응집
Functional
하나의 기능을 위해
필요한 요소만 모임
단일 기능에 모두 기여
교환적 응집
Communicational
동일한 데이터를
조작하는 작업들이 모임
같은 레코드나 구조를 중심
절차적 응집
Procedural
수행 순서가 묶는 기준 단계 순서 중심
시간적 응집
Temporal
같은 시점에 실행되는 작업이 모임 초기화, 종료 처리 같은 경우
논리적 응집
Logical
같은 범주의 작업이라 묶임 입력 처리처럼 범주만 동일
우연적 응집
Coincidental
의미적으로 관계 없는
요소가 한데 모임
최악, 정리 대상

 

객체지향 패러다임에서는

정보적 응집이 자연스럽게 나오기 쉽다.

 

객체가 자신이 가진 데이터를 중심으로

동작을 제공하기 때문이다.


11. 높은 응집과 낮은 결합

설계 품질에서 자주 같이 묶어 말하는 결론이 있다.

  • 높은 응집이 좋다
  • 낮은 결합이 좋다

요지는 간단하다.

  • 높은 응집
    : 관련 있는 것들을 한곳에 모아 유지한다
  • 낮은 결합
    : 관련 없는 것들은 가능한 많이 분리해 낸다

이 둘이 동시에 충족되면 변경이 쉽고,

오류가 국지화되며, 테스트와 재사용이 좋아진다.


12. 응집을 높이는 방법

응집을 높이는 핵심 원칙은 하나다.

  • 모듈 안에 여러 책임을 지우지 않는다

즉 단일 책임을 갖도록 만들면

대부분 기능적 응집 이상으로 올라간다.

 

모듈의 기능을 한마디로 요약할 수 없다면

응집이 낮다고 볼 수 있다.

 

응집 판단을 빠르게 하는 기준을

문장 패턴으로 정리하면 아래처럼 된다.

모듈 기능을 정의한 문장 특징 판단되는 응집 경향
복문, 쉼표, 하나 이상의 동사 순차적 또는 교환적 응집 가능
시간 관련 단어 포함(처음, 다음, 이후 등) 순차적 또는 시간적 응집
동사 앞에 단일 특정 객체가 아님 논리적 응집
초기화, 모두 삭제 같은 표현 시간적 응집

 

이 기준을 실제 설계에 적용하면

이런 결론으로 이어진다.

  • 이미지 처리와 사운드 처리가
    한 모듈에 같이 있으면 응집이 낮다
  • 자료 보관 모듈과 처리 모듈을
    분리하면 응집이 올라간다
  • 모듈이 담당하는 대상(단일 객체)이
    분명할수록 응집이 올라간다

[ 마무리 ]

전통적인 설계 원리는 결국 한 문장으로 수렴한다.

단순하게 만들고, 필요한 만큼만 효율화하고,
잘 나누고, 핵심만 드러내고, 결합을 낮추고, 응집을 높인다

 

설계 단계에서 이 원리를 실전 항목으로 바꾸려면

아래 순서가 안정적이다.

  • 시스템을 분할하고 계층을 잡는다
  • 각 구성 요소의 추상(인터페이스)을 먼저 정의한다
  • 내부 구현은 캡슐화로 숨기고 변경 가능하게 만든다
  • 모듈 경계를 정리하며 결합을 낮춘다
  • 모듈 책임을 정리하며 응집을 높인다

이 흐름대로 설계를 진행하면,

기능 구현 이후에 유지보수성과 확장성 문제로

구조를 갈아엎는 상황을 크게 줄일 수 있다.

'개주 훈련일지 > 📚 코살대 교본 학습' 카테고리의 다른 글

객체지향 설계 원리  (1) 2026.02.06
SQL) 그룹 함수  (0) 2026.02.02
품질 목표  (0) 2026.01.31
설계 원리와 설계 기본 개념  (0) 2026.01.26
SQL) 서브쿼리  (0) 2026.01.25