Skip to content

핵심 개념

SSOT (Single Source of Truth)

**단일 진실 원천(SSOT)**은 Q-Framework의 가장 핵심적인 설계 원칙입니다.

동일한 의미의 정보는 시스템 내 단 하나의 기준 정의에서만 관리되어야 한다.

Q-Framework에서 SSOT는 어노테이션 기반 선언입니다.

java
@QfEntity(appKey = "app", name = @QfI18n(defaultMessage = "User"))
public class UserEntity {

    @QfCreateAttribute(requiredOn = @QfRequiredOn(always = true))  // <- 이것이 SSOT
    @QfCrypto                                                        // <- 이것이 SSOT
    @QfDisplayLabel(text = "Email")                                  // <- 이것이 SSOT
    private String email;
}

이 선언 하나에서 다음이 모두 파생됩니다:

  • API 요청 시 필수값 검증
  • 저장 시 자동 암호화 / 조회 시 자동 복호화
  • 프론트엔드 폼 검증 규칙
  • Swagger 문서의 제약 조건 표시

같은 내용을 여러 곳에 중복 작성하지 않습니다.

SSOT가 아닌 것들

항목SSOT 여부이유
어노테이션 선언✅ SSOT권위 있는 유일한 정의
생성된 메타데이터 JSON❌ 아님어노테이션에서 파생된 복사본
application.yml 설정❌ 아님런타임 환경 설정
훅(Hook) 구현❌ 아님비즈니스 로직, 선언이 아님
API 응답 데이터❌ 아님런타임 상태

메타데이터 기반 계약

Q-Framework는 계약(Contract) 기반으로 동작합니다.

어노테이션 선언
    ↓ (컴파일 시점 APT 처리)
메타데이터 JSON 생성
    ↓ (런타임 로딩)
레지스트리 초기화

API / UI 자동 처리

개발자가 작성하는 어노테이션은 의미와 계약만 표현합니다. "어떻게 실행할 것인가"는 프레임워크에 위임합니다.

계약의 강제

계약 위반(잘못된 어노테이션 조합, 필수 속성 누락 등)은 컴파일 시점에 오류로 처리됩니다. 런타임까지 가지 않습니다.


3단계 생명주기

Q-Framework는 3단계 생명주기를 통해 동작합니다.

1단계: 작성 시점 (Authoring Time)

개발자가 어노테이션으로 도메인을 선언하는 단계입니다.

java
// 개발자가 선언
@QfEntity(appKey = "app", name = @QfI18n(defaultMessage = "Order"))
@QfCapability(key = "order_management")
public class OrderEntity {
    @QfCreateAttribute(requiredOn = @QfRequiredOn(always = true))
    @QfDisplayLabel(text = "Customer ID")
    private String customerId;
}

이 단계에서 Q-Framework의 역할:

  • 어노테이션 정의 제공
  • IDE 코드 완성 지원

2단계: 컴파일 시점 (Compile-time)

APT(Annotation Processing Tool, JSR-269)가 동작하는 단계입니다.

Q-Framework가 자동으로 수행:

  1. 어노테이션 파싱 및 의미 분석
  2. 계약 위반 검사 (Fail-Fast)
  3. 메타데이터 JSON 파일 생성
  4. 레지스트리 인덱스 생성

컴파일 시점에 감지되는 오류 예시:

ERROR: @QfCrypto와 @QfSearch는 동시에 사용할 수 없습니다.
       암호화된 필드는 서버 사이드 검색이 불가합니다.
       → UserEntity.email

ERROR: organizationPolicy가 @QfEntity에 선언되었지만
       organization provider가 설정되지 않았습니다.
       → OrderEntity

3단계: 실행환경 (Runtime)

컴파일된 메타데이터를 기반으로 실제 요청을 처리하는 단계입니다.

런타임 초기화:

애플리케이션 시작

메타데이터 JSON 파일 로딩

엔티티 레지스트리 구성

Capability / Privilege 레지스트리 구성

API 라우팅 자동 등록

준비 완료

요청 처리 흐름:

HTTP 요청

인증 / 인가 확인

메타데이터 기반 검증

조직 범위 데이터 필터링

훅(Hook) 실행

데이터 처리 (암호화 포함)

응답 반환

클라이언트 앱 / Capability / Privilege / Role 관계

클라이언트 앱 (Client App)

논리적으로 독립된 서비스 단위입니다.

하나의 백엔드 애플리케이션
    ├── app (일반 사용자 앱)
    ├── admin (관리자 앱)
    └── mdm (마스터데이터 관리 앱)
java
@QfClientApp(key = "app")
public class AppConfig { }

@QfClientApp(key = "admin")
public class AdminConfig { }

Capability (업무 기능 영역)

메뉴를 통해 실행되는 논리적 기능 단위입니다.

java
@QfCapability(
    key = "user-management",
    name = @QfI18n(defaultMessage = "User Management", texts = { @QfI18nText(locale = "ko", message = "사용자 관리") }),
    entities = { UserEntity.class },
    privileges = {
        @QfPrivilege(key = "user-management__create"),
        @QfPrivilege(key = "user-management__update"),
        @QfPrivilege(key = "user-management__delete"),
        @QfPrivilege(key = "user-management__view-list")
    }
)
public final class UserManagementCapability {
}

Privilege (권한)

허용되는 행위 또는 접근을 표현하는 정책 단위입니다.

  • 사람 단위가 아닌 행위 단위로 정의
  • 키가 SSOT 기준 정의가 됨

예: user-management__create

Role (역할)

여러 Privilege를 묶은 집합입니다.

ROLE_ADMIN
    ├── user_management__create_user
    ├── user_management__delete_user
    └── order_management__view_all

ROLE_ORDER_MANAGER
    ├── order_management__create_order
    └── order_management__view_own

관계 다이어그램

Client App
    └── Capability (업무 기능 영역)
            └── Privilege (권한)
                    └── Role = Set<Privilege>
                            └── User (런타임 할당)

조직 모델 개요

Q-Framework는 계층적 조직 구조 기반의 데이터 접근 제어를 지원합니다.

본사
  ├── 서울 지점
  │     ├── 영업팀
  │     └── 지원팀
  └── 부산 지점
        └── 영업팀

엔티티에 조직 정책(organizationPolicy)을 선언하면:

  • 사용자의 소속 조직 범위에 따라 데이터가 자동 필터링됩니다.
  • 별도의 WHERE 절 작성이 필요 없습니다.
  • SaaS 멀티 테넌트 환경도 동일한 방식으로 처리됩니다.

자세한 내용은 조직 모델 가이드를 참고하세요.


다음 단계

Released under the Apache 2.0 License.