Skip to content

모듈 구조

truloop-core는 Hexagonal Architecture에 따라 7개의 Gradle 모듈로 구성됩니다.


모듈 계층도

settings.gradle.kts
├── :common                    # Layer 0: 순수 유틸리티
├── :domain                    # Layer 1: Enterprise Business Rules
├── :application               # Layer 2: Application Business Rules
├── :adapter:persistence       # Layer 3: DB 어댑터
├── :adapter:external          # Layer 3: 외부 서비스 어댑터
├── :adapter:web               # Layer 3: HTTP 어댑터
└── :bootstrap                 # Layer 4: 진입점 & 조립

모듈별 상세

:common — 공유 유틸리티

외부 의존성이 없는 leaf 모듈입니다. 다른 모든 모듈에서 사용할 수 있습니다.

co.butbeautiful.truloop.common/
├── config/          # 공통 설정 인터페이스
├── datetime/        # 날짜/시간 유틸리티
├── eid/             # TSID 기반 External ID 생성기
├── exception/       # InfrastructureException 계층
├── hashing/         # 해시 유틸리티
├── locale/          # 로케일 처리
├── phone/           # 전화번호 파싱/검증
├── security/        # 보안 유틸리티
├── util/            # 범용 유틸리티
└── validation/      # 검증 로직

허용 의존성: Kotlin 표준 라이브러리 + kotlinx-datetime, kotlinx-serialization-json, tsid-creator, libphonenumber

:domain — 도메인 계층

엔티티, Value Object, 도메인 이벤트를 정의합니다. 프레임워크에 완전히 독립적입니다.

co.butbeautiful.truloop.domain/
├── appversion/          # 앱 버전
├── auth/                # 인증 도메인
├── block/               # 차단
├── chat/                # 채팅
├── contact/             # 연락처
├── contenttemplate/      # 콘텐츠 템플릿
├── coverselection/      # 커버 선택
├── covertemplate/       # 커버 템플릿
├── device/              # 디바이스
├── eta/                 # ETA (예상 도착 시간)
├── event/               # 도메인 이벤트 정의
├── health/              # 헬스체크
├── liveactivity/        # Live Activity
├── loop/                # 룹 (핵심 엔티티)
├── loopcomment/         # 룹 댓글
├── loopguestparticipant/ # 비회원 참여자 (내부명: GuestParticipant)
├── loopinvitation/      # 룹 초대
├── loopmedia/           # 룹 미디어
├── mission/             # 미션
├── notificationcenter/  # 알림 센터
├── report/              # 신고
├── sampleloop/          # 샘플 룹
├── secretary/           # AI 비서
├── shared/              # 공유 VO (UserInfo, LoopInfo, Location)
├── shortform/           # 숏폼 (미사용/폐기 예정)
├── story/               # 리캡 (내부명: Story)
├── user/                # 사용자
└── verification/        # 인증(전화번호)

허용 의존성: :common만 허용

:application — 애플리케이션 계층

Use Case와 Port 인터페이스를 정의합니다. 비즈니스 로직을 오케스트레이션합니다.

co.butbeautiful.truloop.application/
├── appversion/
├── assistant/
├── auth/
│   ├── port/            # AuthRepository, AuthQueries
│   └── usecase/         # LoginUseCase, RefreshTokenUseCase
├── block/
├── chat/
├── contact/
├── contenttemplate/
├── coverselection/
├── covertemplate/
├── dashboard/           # 관리자 대시보드
│   ├── port/            # DashboardStatsQueries
│   └── usecase/         # GetDashboardSummaryUseCase, GetDashboardTimeSeriesUseCase
├── device/
├── eta/
├── liveactivity/
├── loop/
│   ├── port/            # LoopRepository, LoopQueries
│   └── usecase/         # CreateLoopUseCase, JoinLoopUseCase
├── loopcomment/
├── loopguestparticipant/ # 비회원 참여자 (내부명: GuestParticipant)
├── loopinvitation/
├── loopmedia/           # 이미지 그룹핑 포트/UseCase 포함 (ImageGroupingPort, GroupingJobPublisherPort 등)
├── loopparticipant/
├── mission/
├── notification/
├── notificationcenter/
├── profile/
├── recommendation/
├── report/
├── sampleloop/         # 샘플 룹 (유스케이스 7개, SampleLoopGuard 포함)
│   ├── port/           # SampleLoopRepository, SampleLoopQueries
│   └── usecase/        # RegisterSampleLoopUseCase, GetSampleLoopsForUserUseCase 등
├── secretary/
├── shared/
│   ├── config/          # Policy 설정 (AuthTokenPolicy, WebLinkPolicy 등)
│   ├── dto/             # 공유 DTO
│   ├── error/           # 공통 에러 정의
│   ├── exception/       # 공통 예외 정의
│   └── port/            # 공통 Port 인터페이스 (12개)
├── story/               # 리캡 (내부명: Story)
├── user/
│   ├── port/            # UserRepository, UserQueries
│   └── usecase/
└── verification/

허용 의존성: :domain, :common

정보

공통 Port 인터페이스 (shared/port/)에는 UnitOfWork, EventPublisher, CachePort, FileStoragePort, AnalyticsPort, DeepLinkPort, EnvironmentPort, ErrorReportingPort, HttpMetricsPort, MessageSourcePort, RevenueCatPort, SmsMessageSourcePort 등 모든 도메인에서 공유하는 인프라 추상화가 위치합니다.

:adapter:persistence — DB 어댑터

Exposed 기반의 Repository 구현체를 제공합니다. 도메인별로 패키지가 분리되어 있으며, 33개의 Adapter가 등록되어 있습니다.

co.butbeautiful.truloop.adapter.persistence/
├── auth/           # ExposedAuthAdapter, AuthTable
├── block/
├── contact/
├── contenttemplate/
├── coverselection/
├── covertemplate/
├── dashboard/      # ExposedDashboardStatsAdapter
├── device/
├── eta/
├── health/
├── loop/           # ExposedLoopAdapter, LoopsTable
├── loopcomment/
├── loopguestparticipant/ # 비회원 참여자 (내부명: GuestParticipant)
├── loopinvitation/
├── loopmedia/      # ExposedLoopGroupingAdapter, ExposedGroupRepresentativeAdapter 포함
├── mission/
├── notification/
├── report/
├── sampleloop/    # ExposedSampleLoopAdapter, SampleLoopsTable
├── secretary/
├── shared/         # ExposedUnitOfWork
├── story/          # 리캡 (내부명: Story)
├── user/           # ExposedUserAdapter, UsersTable
└── verification/

허용 의존성: :application, :domain, :common

:adapter:external — 외부 서비스 어댑터

AWS, Firebase, Sendbird 등 외부 서비스에 대한 19개 패키지로 Port 구현체를 제공합니다.

co.butbeautiful.truloop.adapter.external/
├── ai/              # AI 서비스 연동
├── assistant/       # Assistant 서비스 연동
├── aws/             # S3FileStorageAdapter
├── covertemplate/   # 커버 템플릿 외부 서비스
├── deeplink/        # Branch 딥링크
├── fcm/             # FcmNotificationAdapter
├── imagegrouping/   # HttpImageGroupingAdapter, NoOpImageGroupingAdapter
├── jwt/             # JWT 토큰 발급/검증
├── liveactivity/    # Live Activity 외부 연동
├── loop/            # 룹 관련 외부 서비스
├── message/         # 메시지 서비스
├── poster/          # 포스터 생성 외부 연동
├── redis/           # LettuceRedisAdapter (CachePort 구현)
├── revenuecat/      # RevenueCat 구독 관리
├── segment/         # Segment 분석
├── sendbird/        # SendbirdChatAdapter
├── sms/             # NHN SMS 발송
├── sqs/             # SQS 메시지 발행 (Story큐, Grouping큐 Publisher 포함)
└── story/           # 리캡 외부 연동 (내부명: Story)

허용 의존성: :application, :common

:adapter:web — HTTP 어댑터

Ktor 라우트, DTO, Controller/Handler를 정의합니다.

co.butbeautiful.truloop.adapter.web/
├── RouteRegistry.kt    # 전체 라우트 등록 (진입점)
├── admin/              # Admin API (Google Workspace OIDC 인증)
├── dashboard/          # 관리자 대시보드 (Admin API)
├── appversion/
├── auth/
├── block/
├── chat/
├── common/             # 공통 웹 유틸리티
├── contact/
├── contenttemplate/
├── coverselection/
├── covertemplate/
├── device/
├── error/              # StatusPages 설정
├── eta/
├── health/
├── liveactivity/
├── loop/
├── loopcomment/
├── loopguestparticipant/ # 비회원 참여자 (내부명: GuestParticipant)
├── loopinvitation/
├── loopmedia/
├── loopparticipant/
├── mission/
├── monitoring/
├── notificationcenter/
├── profile/
├── report/
├── sampleloop/         # 샘플 룹 Admin API (라우트/컨트롤러/DTO)
├── secretary/
├── security/
├── shared/             # 공유 웹 유틸리티 (BasePath 플러그인 포함)
├── shortform/          # 숏폼 (미사용/폐기 예정)
├── story/              # 리캡 (내부명: Story)
├── user/
└── verification/

허용 의존성: :application, :domain, :common

:bootstrap — 진입점

애플리케이션의 Composition Root입니다. 모든 모듈을 조합하고 실행합니다.

co.butbeautiful.truloop.bootstrap/
├── Application.kt       # main() 진입점
├── appversion/
├── config/              # AppConfig + 19개 설정 로더
├── di/                  # Koin 모듈 정의
├── event/               # EventBus, EventHandlerRegistry
│   └── handler/         # 도메인별 이벤트 핸들러
├── external/            # AWS 클라이언트 관리, SQS Consumer
├── health/
├── i18n/
├── logging/
├── monitoring/          # MetricsRegistry
├── plugins/             # 13개 Ktor 플러그인 설정
├── referral/
└── sentry/

허용 의존성: 모든 모듈


DI 모듈 구성

Bootstrap에서 Koin에 등록하는 모듈 목록:

Koin 모듈역할등록 방식
infrastructureModuleAppConfig, Database, EidGenerator, Json, Policy 등 싱글턴DSL
externalServicesModuleJWT, S3, FCM, Sendbird 등 외부 어댑터 (조건부)DSL
persistenceModuleUnitOfWork, Health CheckDSL
eventModuleEventBus, EventHandlerRegistry, EventPublisherDSL
PersistenceScanModulePersistence Adapter 스캔 (@Single)Annotation
ApplicationScanModuleUse Case 스캔 (@Factory) — 27개 도메인별 하위 모듈 포함Annotation
WebScanModuleController/Handler 스캔 (@Factory)Annotation
BootstrapEventHandlerScanModuleEventHandler 스캔 (@Single)Annotation

모듈 간 규칙 요약

위험

절대 위반 금지 규칙

  • Domain 모듈에서 프레임워크 import 금지 (Ktor, Exposed, AWS SDK)
  • Adapter에서 다른 Adapter 직접 참조 금지
  • Route 파일에서 UseCase.execute() 직접 호출 금지 (Controller/Handler를 통해야 함)
  • 순환 의존성 금지

변경 이력

날짜내용
2026-03-16SampleLoop 모듈 추가 — domain, application(유스케이스 7개 + SampleLoopGuard), persistence(SampleLoopsTable), web(Admin API 5개 엔드포인트). Persistence Adapter 32→33개
2026-03-12이미지 그룹핑 모듈 추가 — external에 imagegrouping 패키지, sqs에 GroupingJobPublisher, persistence/loopmedia에 Grouping/Representative Adapter 추가, Persistence Adapter 30→32개, External 패키지 18→19개
2026-03-11Dashboard 모듈 추가 (application, persistence, web), Persistence Adapter 29→30개
2026-03-10Domain에 shortform 추가, Web에 admin/shortform 추가, common에 config 설명 보완, shared/port 전체 목록 반영, application/shared 하위 구조 상세화, 외부 어댑터 18개 패키지로 수정, Bootstrap config loaders 19개/plugins 13개로 교정, DI 모듈에 BootstrapEventHandlerScanModule 추가