Home [주니어 백엔드 개발자가 반드시 알아야 할 실무 지식] 11장 자주 쓰는 서버 구조와 설계 패턴
Post
Cancel

[주니어 백엔드 개발자가 반드시 알아야 할 실무 지식] 11장 자주 쓰는 서버 구조와 설계 패턴

  • 💡해당 게시글은 최범균님의 ‘주니어 백엔드 개발자가 반드시 알아야 할 실무 지식’을 개인 공부목적으로 메모하였습니다.



11장에서 다루는 내용

  • MVC 패턴 (Model-View-Controller)
  • 계층형 아키텍처 (Layered Architecture)
  • DDD와 전술 패턴 (Domain-Driven Design)
  • 마이크로서비스 아키텍처 (Microservices Architecture)
  • 이벤트 기반 아키텍처 (Event-Driven Architecture)
  • CQRS 패턴 (Command Query Responsibility Segregation)



MVC 패턴 (Model-View-Controller)

개념

  • 서버 애플리케이션을 Model, View, Controller 3가지 구조로 분리하는 패턴
  • Node.js의 Express.js, Spring MVC 등이 대표적인 MVC 패턴 사용 예

구조 및 역할

MVC 패턴

  • 모델(Model)
    • 데이터 관리, 비즈니스 로직 처리
  • 뷰(View)
    • 사용자에게 보여질 결과물 생성, 사용자 요청 응답
  • 컨트롤러(Controller)
    • 사용자 입력 처리 및 모델 제어

특징

  • 컨트롤러는 사용자의 요청을 해석하여 모델을 실행하고 결과를 컨트롤러에 리턴
  • 모델은 처리된 결과를 컨트롤러에 전달
  • 사용자가 요청한 기능을 처리하기 위한 요청을 받아 모델이 제공하는 기능을 실행하고, 그 결과를 뷰를 통해 응답함



계층형 아키텍처 (Layered Architecture)

개념

  • 오래된 패턴으로 많은 곳에서 사용됨
  • 각 계층마다 특정 역할을 수행하고, 하위에 위치한 계층에만 의존하는 특징

구조

계층형 아키텍처 구조

특징

  • 계층형 아키텍처에서 하위 계층은 상위 계층에 대한 의존을 갖지 않음
  • 모든 계층이 단방향으로 의존하도록 강제하는 경우도 있음
  • 계층 1이 계층 2에만 의존하고 계층 3에는 의존하지 못함
  • 비슷하게 계층 3은 계층 2와 계층 1에 의존하지 않음

웹 애플리케이션의 계층형 구조 예시

웹 애플리케이션 계층형 구조

  • 표현/UI 계층
    • 사용자의 요청 처리 담당
  • 응용 계층
    • 사용 케이스 정의
  • 도메인/모델 계층
    • 도메인 로직 구현 (주문 취소, 사용자 비밀번호 변경, 결제 상태 변경 등)
  • 인프라/영속 계층
    • DB 연동이나 문자 발송 같은 구현 기술을 지원



DDD와 전술 패턴 (Domain-Driven Design)

개념

  • 복잡성이 높은 도메인을 구현할 때 사용하는 설계 패턴
  • DDD에서 소개하는 전술 패턴을 사용하면 도메인 영역에 도메인 로직을 집중시키는 데 도움이 됨

DDD의 도메인 모델 구성 요소

  • 엔티티 (Entity)
    • 고유의 식별자를 갖는 객체
    • 내부 상태가 바뀌어도 식별자는 유지됨 (예: 주문번호가 다른 주문 엔티티)
  • 밸류 (Value)
    • 식별자 없이 개념적인 값으로 표현
    • 금액, 배송 주소 등 (Value Object 권장)
  • 애그리거트 (Aggregate)
    • 연관된 객체들을 묶은 개념적 단위
    • 도메인 모델의 관리 단위
  • 리포지토리 (Repository)
    • 도메인 객체 저장 및 조회 인터페이스
    • 애그리거트 단위로 관리
  • 도메인 서비스 (Domain Service)
    • 특정 애그리거트에 속하지 않는 로직 구현
    • 외부 연동 로직 등 처리
  • 도메인 이벤트 (Domain Event)
    • 도메인 상태 변경 시 발생하는 이벤트
    • 다른 구성요소에 변경 전파 용도

DDD 활용의 장점

  • 복잡한 도메인을 애그리거트 단위로 분산 관리 가능
  • 관련 로직을 모아 응집도를 높임
  • 복잡한 도메인의 유지보수 용이

DAO 중심 구현의 한계

  • 요구사항 및 쿼리
    • status가 ‘ACTIVE’인 경우에만 ‘BLOCKED’로 변경해야 함
    1
    2
    
      // MemberDao.updateStatus(id)의 쿼리
      update member set status = 'BLOCKED' where member_id = ? and status = 'ACTIVE'
    
  • 일반적인 구현 방식 (DAO 중심)
    • 단순히 쿼리 실행 결과(변경 행 개수)만 확인하여 성공 여부 판단
    1
    2
    3
    4
    5
    
      int cnt = mdao.updateMemberStatus(id);
      if (cnt == 0) {
          // 변경 건이 없으므로 변경 실패 처리
          // 예외를 던지거나 함
      }
    
  • 문제점 (도메인 로직 부재)
    • 비즈니스 규칙이 SQL(쿼리)에 숨어있음
    • 코드는 단순히 데이터베이스 처리 결과만 확인할 뿐 도메인 의도를 드러내지 못함



마이크로서비스 아키텍처

개념

  • 서비스를 작은 단위로 분리하고 각 서비스가 연동되는 구조
  • 기존 모놀리식(Monolithic)은 하나의 애플리케이션에 모든 기능 구현

구조

모놀리식 vs 마이크로서비스 구조

모놀리식과 마이크로서비스 장단점 비교

구분 모놀리식 마이크로서비스
장점 • 배포 단순
• 코드 관리 용이
• 구조 비교적 단순
• 테스트/디버깅 쉬움
• 독립적/지속적 배포 용이
• 성능 확장 유리
• 기술 선택 유연성
• 개발자 만족도 높음
단점 • 규모 증가 시 개발 속도 저하
• 부분 장애가 전체 영향
• 기술 스택 변경 어려움
• 작은 변경에도 전체 재배포 필요
• 테스트/디버깅 어려움
• 인프라 복잡도 증가
• 커뮤니케이션 비용 증가
• 분산 모놀리식 위험

마이크로서비스 아키텍처 구축의 주요 개념

  • 독립적 배포
    • 개별 서비스의 변경, 배포, 출시가 독립적으로 가능해야 함
  • 도메인을 중심으로 모델링
    • 도메인 기준으로 서비스 구분
    • 기능 분산 시 응집도 저하 발생
  • 자신의 상태를 가짐
    • DB 공유 금지
    • 타 서비스 데이터는 API 등을 통해 접근
  • 크기
    • 정해진 기준 없음
    • 조직이 감당 가능한 수준과 경계 정의에 집중
  • 유연함
    • 비용 투입 대비 유연성(기술, 확장, 견고함) 확보 필요
  • 아키텍처 조율을 맞춤
    • 조직 구조가 아키텍처에 영향을 줌
    • 비즈니스 도메인이 주도하는 아키텍처 지향
  • MSA가 무조건 정답은 아니며, 모놀리식이 잘못된 아키텍처도 아님
  • 코드 품질이 낮은 상태에서 무리하게 MSA로 분리하면 오히려 복잡도만 증가할 수 있음
  • 모놀리식도 모듈 간 결합도를 낮추고 컴포넌트를 잘 나누면 충분히 확장 가능함



이벤트 기반 아키텍처 (Event-Driven Architecture)

개념

  • 시스템 간 통신에 이벤트를 사용
  • 이벤트
    • 과거에 발생한 사실
    • ex) ‘주문 수행함’, ‘인증 실패함’

구조 및 구성 요소

이벤트 기반 아키텍처 구조

  • 이벤트 생산자
    • 이벤트를 생성하여 브로커에 전달
  • 이벤트 소비자
    • 이벤트를 받아 적절히 반응
  • 이벤트 브로커(또는 라우터)
    • 변경된 데이터를 다른 시스템에 전달하는 중개자 역할

이벤트 브로커와 단일 전달 공급원

  • 이벤트 브로커를 단일 전달 공급원으로 사용 가능

  • 카프카의 메시지 영구 저장 특징 활용
  • 이벤트 기록만으로 시스템 상태 변화 추적 가능 (이벤트 소싱 패턴)

특징

  • 이벤트는 메시지의 한 형태
  • 대표적인 브로커 기술은 Kafka, RabbitMQ
  • 생산자와 소비자 간 결합도 감소함



CQRS 패턴 (Command Query Responsibility Segregation)

개념

  • 명령(Command) 모델과 조회(Query) 모델을 분리
  • 각 기능에 최적화된 모델 구현 가능
  • 상호 영향 최소화

CQRS 구조

CQRS 패턴 구조

주요 특징

  • 조회와 명령의 분리
    • 복잡한 시스템에서는 상태 변경과 조회의 모델이 달라짐
    • 단일 모델로는 복잡도 증가 및 유지보수 어려움
    • ex) 주문 생성 시 여러 참조 데이터 필요
  • 모델의 차이
    • 독립적인 조회 성능 향상 가능
    • 조회 전용 캐시나 DB 활용 용이
  • 단점
    • 구현해야 할 코드량 증가
    • 단순 모델 적용 시 이점보다 작업량이 클 수 있음
    • 모델이 복잡할수록 효과적
  • 적용 시기
    • 구현 기술 복잡도 증가 고려
    • 조회 전용 DB 도입 시 데이터 동기화 이슈 해결 필요



배운 점

  • MVC 패턴
    • Model-View-Controller로 책임을 분리하여 유지보수성 향상
  • 계층형 아키텍처
    • 각 계층이 특정 역할을 수행하며 하위 계층에만 의존하여 결합도 감소
  • DDD와 전술 패턴
    • 도메인 로직을 체계적으로 구현하여 비즈니스 복잡성 관리
  • 마이크로서비스 아키텍처
    • 서비스를 작은 단위로 분리하여 독립적인 배포와 확장 가능
  • 이벤트 기반 아키텍처
    • 이벤트를 통한 시스템 간 비동기 통신으로 결합도 최소화
  • CQRS 패턴
    • 명령과 조회 모델을 분리하여 각각의 성능과 확장성 최적화



적용 방안

  • 아키텍처 선택 기준
    • 프로젝트 규모, 팀 구성, 비즈니스 요구사항에 따라 적절한 패턴 선택해야함
    • 초기에는 모놀리식으로 시작하고 필요시 마이크로서비스로 전환 고려하는 것도 괜찮음
  • 도메인 로직 강화
    • 비즈니스 로직은 도메인 계층에 집중시켜 응집도 높임
    • 서비스 계층은 도메인 객체 간의 흐름만 제어하도록 설계
  • 이벤트 활용
    • 시스템 간 강결합을 피하기 위해 이벤트 기반 통신 도입 고려
    • Kafka 등의 메시지 브로커를 활용하여 안정적인 메시지 처리
  • 성능 최적화
    • 조회 성능이 중요한 경우 CQRS 도입 검토
    • 캐싱 전략과 읽기 전용 DB 활용



Reference

Contents

[김영한의 스프링 MVC 2편 백엔드 웹 개발 활용 기술] 타임리프 기본 기능

Kotlin val과 Data Class