Skip to content

feat: principal 감사와 배너 poster URL 지원 - #687

Merged
Whale0928 merged 2 commits into
mainfrom
feat/principal-audit-banner-poster
Jul 31, 2026
Merged

feat: principal 감사와 배너 poster URL 지원#687
Whale0928 merged 2 commits into
mainfrom
feat/principal-audit-banner-poster

Conversation

@bottlenote-app

@bottlenote-app bottlenote-app Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

개요

감사 주체를 문자열 이메일 하나가 아닌 id·type·email snapshot으로 기록할 수 있도록 공통 JPA auditing 모델을 확장합니다. 같은 migration에 포함된 배너 동영상 대표 이미지 URL 계약도 Product/Admin API에 연결합니다.

변경 내용

principal 감사 기록

  • git.environment-variables 포인터를 9c896cb3bc6a4f452e3c19c11181dba220f22b34로 변경했습니다.
  • AuditPrincipalAuditPrincipalType을 추가했습니다.
    • 타입: USER, ADMIN, AGENT, SYSTEM, ANONYMOUS
    • 저장값: principal ID, principal type, email snapshot
  • BaseTimeEntity가 생성·수정 시각과 생성·수정 principal을 함께 관리하도록 변경했습니다.
  • BaseEntity는 기존 상속 호환용 공통 클래스로 유지합니다.
  • AuditorAwareImpl이 Product 사용자와 Admin 사용자를 구분해 감사 주체를 생성합니다.
  • 큐레이션 만료 batch native SQL을 rename된 감사 컬럼에 맞추고 실행 주체를 SYSTEM으로 기록합니다.
    • 이전 USER/ADMIN 감사 ID가 남지 않도록 last_modify_principal_idNULL로 초기화합니다.

배너 poster URL

  • banners.poster_url VARCHAR(500) NULL 매핑을 추가했습니다.
  • Admin 배너 생성·수정 요청에서 선택값 posterUrl을 받고 최대 500자로 검증합니다.
  • Admin 목록·상세 응답과 Product 활성 배너 응답에 posterUrl을 포함합니다.
  • QueryDSL projection, 서비스 매핑, InMemory repository, REST Docs를 함께 갱신했습니다.

응답 형태 예시

{
  "imageUrl": "https://cdn.bottle-note.com/banners/event.mp4",
  "posterUrl": "https://cdn.bottle-note.com/banners/event-poster.jpg",
  "mediaType": "VIDEO"
}

posterUrl은 기존 배너와 이미지 배너의 호환성을 위해 nullable입니다.

migration 영향

  • 기존 create_by, last_modify_by 값은 각각 create_principal_email, last_modify_principal_email로 rename되어 보존됩니다.
  • 기존 BaseEntity 대상 테이블에는 principal ID/type 컬럼이 추가됩니다.
  • BaseTimeEntity 직접 상속 대상 테이블에는 principal ID/type/email 컬럼이 추가됩니다.
  • banners에 nullable poster_url 컬럼이 추가됩니다.
  • batch 모듈은 migration을 패키징하지 않으며, 변경된 스키마의 컬럼명만 사용합니다.

검증

  • ./gradlew :bottlenote-mono:test --tests app.bottlenote.banner.service.AdminBannerServiceTest --tests app.bottlenote.banner.service.BannerQueryServiceTest
  • ./gradlew :bottlenote-product-api:test --tests app.bottlenote.global.config.JpaAuditingTest
  • ./gradlew :bottlenote-product-api:test --tests app.docs.banner.RestBannerQueryControllerTest :bottlenote-admin-api:test --tests app.docs.banner.AdminBannerControllerDocsTest
  • ./gradlew :bottlenote-batch:test --tests app.batch.bottlenote.curation.CurationExpirationStatusJobTest
  • ./gradlew :bottlenote-product-api:unit_test :bottlenote-admin-api:unit_test
  • ./gradlew classes testClasses
  • git diff --check

미검증 / 로컬 제약

  • Product 통합 테스트와 전체 unit_test 중 Testcontainers/MinIO 의존 테스트는 로컬 Docker provider를 찾지 못해 컨테이너 기동 전에 중단됐습니다.
  • 실패 원인은 DockerClientProviderStrategy 초기화이며, 코드 assertion 또는 migration validation 실패는 확인되지 않았습니다.

관련 이슈 및 PR

@bottlenote-noa bottlenote-noa Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

감사 주체 정책과 배포 호환성에 대해 두 가지 확인 요청을 남깁니다. role은 감사 필드에 저장하지 않고 id/type/email snapshot을 사용하는 방향이 맞습니다.

public Optional<AuditPrincipal> getCurrentAuditor() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return Optional.empty();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SYSTEM은 인증 정보가 없다는 이유로 기본 반환하지 않고, scheduler·batch·내부 자동화처럼 시스템 작업임이 명시된 실행 경로에서만 주입하는 정책으로 맞춰주세요. 일반 미인증 context는 현재처럼 자동으로 SYSTEM 처리하지 않아야 합니다. 명시적 automation → SYSTEM, 일반 미인증 → empty를 각각 검증하는 테스트도 필요합니다.

"UPDATE curation "
+ "SET is_active = false, last_modify_at = NOW(), last_modify_by = 'batch-curation-expiration' "
+ "SET is_active = false, last_modify_at = NOW(), "
+ "last_modify_principal_email = 'batch-curation-expiration', "

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

배포 호환성 확인이 필요합니다. V5가 last_modify_by를 즉시 rename하지만 표준 backend release는 Product/Admin 이미지만 갱신하고 batch 이미지는 함께 배포하지 않습니다. 따라서 migration 적용 후 기존 batch가 구 컬럼으로 실행되어 실패하며, 기본 RollingUpdate 중인 기존 Product/Admin pod도 같은 영향을 받을 수 있습니다. V5에서는 신규 principal 컬럼을 추가하되 구 컬럼을 유지하고, Product/Admin/Batch 전환 후 후속 migration에서 구 컬럼을 제거하는 expand-contract 방식을 권장합니다.

@Whale0928
Whale0928 merged commit 77c18b2 into main Jul 31, 2026
8 checks passed
@Whale0928
Whale0928 deleted the feat/principal-audit-banner-poster branch July 31, 2026 12:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant