1. 왜 시작했냐?

처음 Plex 프로젝트는 Vue2 + Options API로 시작했음.
문제는 팀 구성이었는데, 대부분이 SI 업체에서 오신 분들..!!이라 프론트엔드 폴더 아키텍처나 코드 구조에 대한 개념 자체가 거의 없었음.
그래서 코드가 그냥 되는 대로 짜여 있었고, 점점 이런 문제들이 터짐 정말 힘든 싸움이었음.. 멱살잡고 끌고가는 수 밖에 없다는 판단이 섰음.. :

  • API 호출, 상태 관리, 유틸 함수가 여기저기 흩어져서 중복
  • 어디에 무슨 로직 넣어야 하는지 기준 없음 → 사람마다 다 다르게 짬
  • 새로운 기능 붙일 때 사이드 이펙트 대폭발
  • 코드리뷰마다 “이건 어디다 넣는 게 맞냐” 싸움 반복

한마디로 아키텍처 자체가 없으니 팀워크도 안 돌아가는 상황이었음.


2. 그래서 내가 뭘 했냐?

이대로는 답이 없겠다 싶어서 내가 Vue3 Composition API + DDD 구조를 제안하고 직접 셋업했음.

Vue3로 갈아탄 이유

  • 로직 분리가 깔끔해지고 composable로 공통화하기 쉬움
  • 신규 투입되는 사람도 구조만 보면 이해 가능
  • Options API보다 유지보수성이 훨씬 나음

DDD 아키텍처 적용

폴더 구조를 내가 직접 src/domains/{도메인}/application | domain | infrastructure로 재정리함.

  • application: 유스케이스 (ex: getConnector, sendChatMessage)
  • domain: 순수 비즈니스 로직, 엔티티/밸류
  • infrastructure: API 통신, 외부 연동

이걸 기준으로 잡으니까:

  • 로직이 흩어지지 않고, “이건 infra”, “이건 domain”이라고 명확히 나눌 수 있었음
  • 팀 내 쓸데없는 논쟁도 사라짐
  • UI랑 비즈니스 로직이 완전히 분리돼서 협업 구조가 좋아짐
  • 테스트하기도 훨씬 편해짐

폴더 아키텍처를 구성한 이유(DDD+애자일 결합)

  • 유비쿼터스 언어로, 챗, 메시지 와 같은 이름이 그대로 코드에 박혀서 기획 - 개발 qa 오해가 줄고 재작업 감소 목적
  • 경계가 명확해저서 팀원들간 작업시 맥락을 쪼개서 병렬 개발이 가능 → 충돌/ 의존성 감소됨 병목을 해소를 위한 목적
  • 테스트가 빠름 → 초고속 단위테스트 가능, 버그 조기 검출, QA 사이클 단축
  • 컨텍스트 안에서만 영향이 가서 리스크 최소화
  • 변경 친화적 규칙은 도메인 외부연동은 Infrastructure API 변경 돼도 도메인 안전, 리팩토링 비용이 감소함
  • 온보딩 쉬움 폴더 흐름으로 유추가능 ( views → application → domain → infra). 신규 투입 속도 빨라짐
  • 확장성이 좋아짐 필요 할 때만 컨텍스트 분리 * (레포/패키지)로 단계적 확장 가능함

 

폴더 구조: 기존 → 변경 매핑

  • src/config → src/shared/config (공용 설정 통합: endpoints.ts, env.ts)
  • src/mixins/* → 도메인/애플리케이션 훅로 흡수 (src/domains/*/application)
  • src/views/page/* & src/views/questionAnswer/* → 기능별 화면 유지 단 도메인 로직은 domains로 이동
  • src/views/component / src/component → 공용은 src/shared/component, 특정 기능은 해당 도메인 presentation(뷰)로 배치 가능
  • 네트워크 레이어: 흩어져있던 호출 → src/shared/http/*(+ 도메인별 infrastructure API 모듈)로 변경함
  • 채팅 관련 스크립트/믹스인 → src/domains/chat/{application,domain,infrastructure}로 분리함
  • 채팅 등 인프라 세부 → src/domains/chat/infrastructure/* 세분화시킴

아키텍처 개요(DDD 계층)

의존성 규칙(강제):

  • views → application만 호출 (가능하면 domain 직접 접근 금지)
  • application → domain + infrastructure 사용 가능
  • domain → shared/http 사용 금지, 외부 의존성 없음(순수)
  • infrastructure → shared/http 사용, domain 타입만 참조(비즈니스 로직 금지)
  • shared → 어디서든 참조 가능(단, 도메인 규칙 침범 금지)

변경 포인트 핵심

  • 네트워크 일원화: src/shared/http/httpClient.ts + tokens.ts로 인증/에러 처리 공통화
  • 도메인 분리: chat 예시처럼 application/domain/infrastructure로 책임 분리
  • 팩토리 도입: domain/factory/*로 생성 규칙/불변성 보장
  • 설정/상수 정리: shared/config, shared/constants로 분리 (런타임/빌드 시 분리 가능)
  • 공용 UI: src/shared/component로 재사용 컴포넌트 집약

폴더별 역할(샘플)

  • src/domains/chat/application/*: useChat.js, chatService.js, orchestration/유스케이스
  • src/domains/chat/domain/*: entities, valueObjects, factory/chatFactory.js, createChat.js
  • src/domains/chat/infrastructure/: chatApi.js (HTTP 호출만)
  • src/shared/http/*: httpClient.ts(인터셉터/재시도/토큰), tokens.ts
  • src/shared/config/*: env.ts, endpoints.ts(베이스 URL 등)
  • src/shared/constants/*: 공용 상수
  • src/views/*: 화면/라우팅/상태 최소화, 로직은 application에 위임

코드 합의(품질/확장)

  • Vue3, <script setup>, Node 18
  • 타입은 JS/TS 혼용 가능하되 lang= ts는 금지 → ts는 .ts 모듈에서만 사용 합니다.
  • 도메인 순수성 유지: 계산/검증/정책은 domain, 흐름은 application, 외부연동은 Infrastructure
  • 명명 규칙: usexx(훅), xxService(유스케이스), xxApi(인프라), createxx(팩토리)

핵심 의존성 관계는 다음과 같습니다.

Views 는

  • A(application) 의존
  • sc (Shared/Component) 에 의존

A(애플리케이션)는

  • D(도메인)에 의존
  • I (Infrastructure)에 의존

I (Infrastructure)에 의존 H(Shared/HTTp)에 의존

H(Share/HTTP)는 C(shared/config) 에 의존

위에 내용은 confluence 에 팀원들이 보라고 직접만든 부분이다.

 

테스트/Jest 도입 포인트

  • Domain 테스트 우선: I/O 없이 순수 로직이라 단위 테스트 효율이 좋습니다.
  • Application 테스트: 인프라 목킹으로 유스케이스 흐름 검증가능
  • Infrastructure 테스트: httpClient 인터셉터/에러 경로 테스트 가능
  • 구조가 분리되어 Jest + Vue Test Utils 도입이 쉬움(레이어별 독립 테스트 가능)

3. 바꾸고 나서

  • 팀원 간 정리: “이건 infra로 내려야지”라는 기준 생김 → 더이상 애매하게 끼워넣기 안 함
  • 가독성 상승: 신규 합류한 사람도 구조만 보면 금방 이해 가능
  • 확장성 확보: Chat 도메인에 SSE 붙일 때 infra에 네트워크 코드만 추가하면 끝 → 손쉽게 기능 확장
  • 중복 코드 제거: httpClient, 포맷터 같은 거 infra/application에서 불러다 쓰니 코드 정리됨

4. 결론

Vue3 + DDD 도입은 단순히 최신 기술 써본 게 아니라, 아키텍처 개념이 없던 팀에 기준을 세운 일이었음.
아무도 모르는 상태에서 내가 직접 끌고 와서 구조를 잡아주니까, 코드만 깔끔해진 게 아니라 팀 내 갈등도 줄고 협업 효율도 올라감.
결국 Plex 프로젝트는 그 덕분에 안정성 + 확장성 + 팀워크까지 챙길 수 있었음.

+ Recent posts