본문으로 건너뛰기
가이드

Core 식별자를 외래키로 참조하기

허용된 Core FK 대상과 마이그레이션 작성, 저장 전 권한 검사를 확인합니다.

Core 식별자를 외래키로 참조하기

앱 테이블에서 일부 Core 식별자를 외래키로 참조할 수 있습니다. 외래키는 대상의 존재를 보장할 뿐 Core 테이블 조회나 해당 레코드 사용 권한을 부여하지 않습니다. 빠른 시작으로 앱 실행을 마친 상태에서 진행하세요. 파일 경로는 앱 루트 기준입니다.

참조 대상 선택

대상 테이블참조 컬럼PostgreSQL 타입의미
public.legal_entitiesidbigint법인
public.operating_unitsidbigint운영조직
public.partiesidbigint사람·조직의 공통 식별자
public.sitesidbigint사업장
public.usersidbigint테넌트 사용자

현재 허용 목록은 위 컬럼뿐입니다. 각 테이블의 public_id UUID는 외부 식별자이며 FK 허용 대상이 아닙니다. Party는 직원 레코드가 아니고, 모든 사람이 User인 것도 아닙니다. 다른 앱 테이블이나 목록에 없는 Core 테이블까지 참조할 수 있다고 가정하지 마세요.

필요한 관계저장·사용 방식
같은 앱이 소유한 테이블앱 내부 FK와 인덱스
위 목록의 Core 식별자Backend에서 해당 SDK 계약으로 해석한 숫자 키
다른 앱의 업무 레코드고정 App 키·Resource 키·공개 레코드 식별자와 인가된 Resource Reference. 테이블을 직접 join하지 않음

플랫폼은 앱 migration 실행 계정에 REFERENCES를 부여합니다. Core 테이블의 SELECT·INSERT·UPDATE·DELETE 권한은 부여하지 않습니다. Composer와 격리 앱 실행 모두 같은 목록을 사용합니다. 앱 개발자가 DB 인증정보를 받거나 GRANT를 실행할 필요는 없습니다. 현재 공개 CLI에는 nexia db references와 nexia db reset이 없습니다.

마이그레이션 작성

Workshop Note에 선택 입력인 사업장 참조를 추가하는 예제입니다. 생성된 앱의 실제 테이블 접두사를 사용하고 이미 있는 소유자 컬럼을 중복 추가하지 마세요. Note 생성 마이그레이션보다 뒤의 새 파일 database/migrations/tenant/2026_10_04_120000_add_site_to_wsp_notes.php를 만듭니다.

코드 예시
PHP
<?php

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::table('wsp_notes', function (Blueprint $table): void {
            $table->unsignedBigInteger('site_id')->nullable();
            $table->index('site_id');
            $table->foreign('site_id')->references('id')
                ->on('public.sites')->restrictOnDelete();
        });
    }

    public function down(): void
    {
        Schema::table('wsp_notes', function (Blueprint $table): void {
            $table->dropForeign(['site_id']);
            $table->dropIndex(['site_id']);
            $table->dropColumn('site_id');
        });
    }
};

앱 테이블은 할당된 스키마를 사용하고 Core 참조 대상에만 public을 붙입니다. 앱 테이블을 public에 생성하거나 할당 스키마 이름을 코드에 고정하지 마세요. 참조가 허용돼도 FK와 참조 컬럼의 인덱스는 자동 생성되지 않습니다. 삭제 규칙은 업무에 맞춰 정하며, 위 예제는 참조 중인 사업장의 삭제를 차단합니다. down()은 컬럼 데이터를 지우므로 일반 오류 복구용으로 실행하지 않습니다.

저장 전 식별자 해석과 권한 검사

API에서는 공개 식별자를 받습니다. 생성된 Resource Policy와 조직 대상 검사를 유지한 뒤, 허용된 법인의 사업장인지 해석하세요. 다음은 인가를 마친 Controller 내부 발췌입니다. $legalEntityKey는 검증된 저장 소유자에서 가져오며 요청의 숫자 ID를 그대로 쓰지 않습니다.

코드 예시
PHP
use Nexia\Organization\Contracts\SiteDirectory;

$data = $request->validate(['site_public_id' => ['required', 'uuid']]);
$site = app(SiteDirectory::class)->findByPublicIdForLegalEntity(
    $data['site_public_id'],
    $legalEntityKey,
);
abort_if($site === null, 422);
$record->site_id = $site->key;
$record->save();

이 발췌는 값이 있는 경우의 지정만 보여 줍니다. 선택 입력에서는 필드 생략은 기존 값 유지, 명시적 null은 비우기로 따로 처리하세요. 모델 응답에서 site_id를 숨기고 허용된 공개 식별자를 반환합니다. 폼·응답 타입 연결은 데이터 모델과 마이그레이션을 따릅니다.

법인·운영조직은 OrganizationDirectory, 사업장은 SiteDirectory, Party는 Nexia\Laravel\Identity\Contracts\PartyDirectory를 사용합니다. 식별자 해석만으로 권한이나 업무상 사용 가능 여부가 검증되지는 않습니다. public.sites 직접 조회, Core Eloquent 모델 import, exists:sites,id 검증으로 권한 처리를 대체하지 마세요. FK만으로는 법인 소속·활성 상태·soft delete·사용자 권한까지 보장하지 않습니다.

적용하고 확인하기

nexia dev가 새 마이그레이션 동기화를 마칠 때까지 기다린 뒤 Ctrl+C로 감시를 종료합니다. 앱 폴더에서 실행하세요.

코드 예시
Shell
nexia db migrate
nexia db status

completed를 확인하고 nexia dev를 다시 실행합니다. 허용된 사업장을 저장하고 새로고침해 유지되는지, 사용 불가·범위 밖 대상은 거부되는지, 사업장이 없는 기존 Note도 수정 가능한지 확인하세요. 제약 위반 확인에는 별도 테스트 데이터를 사용합니다.

증상다음 조치
Core FK 대상에 권한 오류위의 정확한 테이블·컬럼과 앱 migration 실행 여부 확인. 계속 실패하면 작업 ID로 지원 요청. 직접 권한을 넓히지 않음
타입 불일치Core id는 bigint. FK 컬럼에 UUID를 저장하지 않음
FK 위반같은 테넌트의 식별자인지 해석하고 삭제·동시 변경을 처리. 잘못된 값을 저장하려고 제약을 제거하지 않음
queued·running·needs_review데이터 모델과 마이그레이션의 복구 절차 확인. 접수는 완료가 아니며 초기화로 복구하지 않음
원본 위치: docs/developers/content/ko/building-apps/core-database-references.md