Skip to content

fix: project_file 레거시 컬럼 제거로 파일 업로드 복구 - #139

Merged
chazy-d merged 1 commit into
developfrom
fix/project-file-legacy-columns
Aug 7, 2026
Merged

fix: project_file 레거시 컬럼 제거로 파일 업로드 복구#139
chazy-d merged 1 commit into
developfrom
fix/project-file-legacy-columns

Conversation

@chazy-d

@chazy-d chazy-d commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

🔗 관련 이슈 (Related Issue)

  • 운영 장애 복구 작업으로 별도 이슈 없이 진행했습니다.

📝 작업 내용

운영에서 프로젝트 파일 업로드가 100% 실패하고 있습니다. project_file 테이블에 엔티티가 더 이상 사용하지 않는 컬럼 두 개가 NOT NULL 제약과 함께 남아 있어 모든 INSERT가 거부되는 상태입니다. 해당 컬럼을 제거하는 마이그레이션을 추가했습니다. 문제 내용은 ssh 접속하여 로그를 확인하였습니다!

주요 검토 파일

마이그레이션

  • src/main/resources/db/migration/V012__project_file_drop_legacy_columns.sql - project_filefile_url, is_pinned 컬럼 제거

1. 장애 현상

POST /api/v1/projects/{projectId}/files

요청이 전건 COMMON500으로 실패합니다.

JpaSystemException: could not execute statement
[Field 'file_url' doesn't have a default value]
[insert into project_file (content_type,created_at,deleted_at,description,file_name,
 file_size,is_final,pinned_at,project_id,storage_key,updated_at,uploader_id)
 values (?,?,?,?,?,?,?,?,?,?,?,?)]
at com.slatto.domain.project.service.ProjectFileService.uploadProjectFile(ProjectFileService.java:124)

이 업로드가 막혀 있어 파일 수정, 삭제, 다운로드, 고정, 고정 해제와 영상 참조 파일 연결, 연결 제거까지 후속 API 검증이 함께 막혀 있었습니다.


2. 원인

refactor: 프로젝트 파일 도메인 모델 정리(a833792)에서 ProjectFile 엔티티의 모델을 다음과 같이 변경했으나, 대응하는 마이그레이션을 작성하지 않았습니다.

  • file_urlstorage_key
  • isPinned(boolean) → pinnedAt(nullable)

운영 DB는 해당 커밋 이전에 ddl-auto=update로 생성된 상태였습니다. Hibernate의 update 모드는 컬럼을 추가만 하고 삭제하지 않으므로, 신규 컬럼인 storage_key만 추가되고 구 컬럼 두 개가 NOT NULL, DEFAULT 없음 상태로 그대로 남았습니다.

현재 INSERT 문은 두 컬럼을 포함하지 않으므로 MySQL이 모든 INSERT를 거부합니다.

ddl-auto=validate가 이 상태를 잡아내지 못한 이유는, validate가 엔티티에 있는데 DB에 없는 컬럼만 검사하고 그 반대 방향은 보지 않기 때문입니다.


3. 변경 내용

ALTER TABLE project_file
    DROP COLUMN file_url,
    DROP COLUMN is_pinned;
  • 두 컬럼을 한 문장으로 함께 제거합니다. file_url만 제거하면 다음 업로드에서 is_pinned로 동일하게 실패합니다.
  • 단일 문장이라 원자적으로 처리되며, 명시한 두 컬럼 외에는 어떤 컬럼도 변경하지 않습니다.
  • 삭제 시점 기준 project_file은 0건이라 데이터 손실이 없습니다.

버전 번호

V011은 d5191f6에서 활동 로그 인덱스용으로 사용됐다가 f1e99f0에서 삭제된 이력이 있어 재사용하지 않았습니다. 운영 DB의 flyway_schema_history에 V011 기록이 없고 실패 이력도 없음을 확인했으나(8 → 009 → 010, 전부 성공), 번호를 비워도 Flyway 동작에는 영향이 없어 안전한 쪽을 택했습니다.


4. 배포 시 함께 필요한 작업 (코드 변경 아님)

별건으로, 조회 응답의 일부 시각이 실제보다 9시간 이르게 반환되는 문제가 있습니다. 이번 PR에는 포함되지 않지만 배포와 함께 처리하면 한 번에 반영됩니다.

  • DB에 저장된 값은 UTC로 정상입니다. 데이터 오염이 없어 별도 복구가 필요하지 않습니다.
  • RDS의 time_zoneUTC이고 컨테이너 JVM도 UTC인데, JDBC URL에만 serverTimezone=Asia/Seoul이 지정되어 있습니다. 조회 시 드라이버가 UTC 값을 서울 시각으로 해석한 뒤 되돌리면서 9시간 차이가 발생합니다.
  • EC2의 환경 변수 파일에서 DB_URLserverTimezoneUTC로 변경하면 세 계층이 모두 UTC로 일치합니다. 서버 전용 파일이라 이 PR에는 포함할 수 없습니다.

엔드포인트가 달라지는거 아닌가? 라고 생각할 수 있으나 시간만 변경되기에 문제 없습니다.


5. 테스트 및 검증

./gradlew compileJava
./gradlew test

두 명령 모두 통과했습니다. 마이그레이션 파일 추가만 있어 코드 변경은 없습니다.

현재 테스트 환경은 H2 기반이고 Flyway가 비활성화되어 있어, 마이그레이션 자체는 테스트로 검증되지 않습니다. 대신 배포 전 운영 DB에서 다음을 직접 확인했습니다.

  • project_filefile_url, is_pinned 컬럼이 NOT NULL, DEFAULT 없음 상태로 존재
  • project_file 행 수 0건
  • 두 컬럼이 포함된 인덱스 없음
  • flyway_schema_history에 실패 이력 및 V011 기록 없음

✅ PR 체크리스트

  • PR 제목은 커밋 컨벤션을 따랐습니다.
  • 관련 이슈가 없는 작업임을 본문에 명시했습니다.
  • ./gradlew compileJava로 컴파일을 확인했습니다.
  • ./gradlew test로 단위 및 통합 테스트를 확인했습니다.
  • 마이그레이션이 MySQL 8.4에서 유효한 문법만 사용했는지 확인했습니다.
  • 배포 전 운영 DB의 실제 스키마 상태를 확인했습니다.

Summary by CodeRabbit

  • 개선 사항
    • 프로젝트 파일 데이터베이스에서 더 이상 사용되지 않는 레거시 파일 URL 및 고정 상태 정보가 제거되었습니다.
    • 관련 데이터 구조가 간소화되어 향후 프로젝트 파일 관리가 일관되게 처리됩니다.

파일 업로드가 운영에서 전건 500으로 실패했다.

  JpaSystemException: could not execute statement
  [Field 'file_url' doesn't have a default value]
  at ProjectFileService.uploadProjectFile(ProjectFileService.java:124)

a833792 에서 ProjectFile 의 file_url 을 storage_key 로, isPinned(boolean) 을
pinnedAt(nullable) 로 바꾸면서 대응 마이그레이션을 만들지 않았다. 운영 DB 는
ddl-auto=update 로 생성돼 신규 컬럼만 추가되고 구 컬럼 file_url, is_pinned 가
NOT NULL / DEFAULT 없음 상태로 남았다. 현재 INSERT 문은 두 컬럼을 포함하지 않으므로
모든 INSERT 가 거부된다.

ddl-auto=validate 는 엔티티에 있는데 DB 에 없는 컬럼만 검사하고 그 반대는 보지 않아
이 상태를 잡아내지 못했다. 운영 DB 전체 컬럼을 엔티티와 대조해 같은 유형의 고아 컬럼이
project_file 두 건뿐임을 확인했다.

file_url 만 제거하면 다음 업로드에서 is_pinned 로 동일하게 실패하므로 함께 제거한다.
삭제 시점 기준 project_file 은 0건이라 데이터 손실이 없다.

V011 은 d5191f6 에서 쓰였다가 f1e99f0 에서 삭제된 이력이 있어 재사용하지 않는다.
@chazy-d chazy-d self-assigned this Aug 6, 2026
@chazy-d chazy-d added the fix 버그 수정 label Aug 6, 2026
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 08092305-06c1-4b31-bbd5-3b1dbba8613b

📥 Commits

Reviewing files that changed from the base of the PR and between 2f1afb5 and bc1379c.

📒 Files selected for processing (1)
  • src/main/resources/db/migration/V012__project_file_drop_legacy_columns.sql

📝 Walkthrough

Walkthrough

project_file 테이블에서 레거시 컬럼 file_urlis_pinned을 삭제하는 Flyway 마이그레이션을 추가했습니다. MySQL 8.4의 DROP COLUMN IF EXISTS 미지원 사항과 관련 데이터 상태를 주석으로 기록했습니다.

Changes

project_file 스키마 정리

Layer / File(s) Summary
레거시 컬럼 제거 마이그레이션
src/main/resources/db/migration/V012__project_file_drop_legacy_columns.sql
project_file 테이블에서 file_urlis_pinned을 삭제합니다. 마이그레이션 배경과 사전 수동 삭제 금지 사항을 주석으로 명시합니다.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: sangwon02, guingguing, young0206, kohseoyoung

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 프로젝트 파일 업로드 장애의 원인인 레거시 컬럼 제거와 복구 목적을 명확하고 간결하게 설명합니다.
Description check ✅ Passed 변경 내용, 장애 원인, 검증 결과, 관련 이슈 부재와 체크리스트를 구체적으로 설명합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chazy-d
chazy-d merged commit 17dff55 into develop Aug 7, 2026
2 checks passed
@guingguing
guingguing deleted the fix/project-file-legacy-columns branch August 11, 2026 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix 버그 수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant