Skip to content

[FIX] 기록 이미지 업로드 관련 버그 수정 및 이미지만으로 기록 작성 허용 - #374

Merged
JiwonLee42 merged 12 commits into
develop-demofrom
fix/record-image-upload-and-content-length
Sep 20, 2026
Merged

JiwonLee42 merged 12 commits into
develop-demofrom
fix/record-image-upload-and-content-length

Conversation

@JiwonLee42

@JiwonLee42 JiwonLee42 commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor

📄 작업 내용 요약

사진 업로드로 독서 기록을 작성할 때 오래 걸리고 가끔 실패하던 문제를 k6 부하테스트로 재현하고, 원인이 된 서버 버그를 수정했습니다.

  • 기록 content가 검증은 1000자인데 DB 컬럼은 VARCHAR(255)라 255자 초과 시 INSERT 실패(409 "이미 존재하는 데이터") → 컬럼 확장 + Flyway 마이그레이션
  • 기록 수정 시 기존 이미지 키를 그대로 보내면 이미지가 2배로 중복 생성 → 신규/삭제/유지를 구분하는 diff 방식으로 동기화 (순서만 바뀌면 orderIndex만 갱신)
  • 텍스트 없이 이미지만으로도 기록 작성·수정 허용 (내용·이미지가 모두 없으면 RECORD-400)
  • 타임라인 기록 preview를 100자로 제한 (저장 시 / 목록·요약 조회 시, 상세 본문은 전체 유지)
  • 닉네임 길이 2~10자로 변경 (마이페이지, DEV 가입·로그인 DTO, 온보딩과 통일)
  • DataIntegrityViolationException 로그에 스택트레이스 포함, form 로그인 및 UserDetailsServiceAutoConfiguration 비활성화
  • k6 record-image-upload 시나리오와 리포트 비교 HTML 스크립트 추가

📎 Issue 번호

  • 관련 이슈 없음

✅ 작업 목록

  • 기능 구현
  • 코드 리뷰 반영
  • 테스트 코드 작성
  • 문서 업데이트 (user.adoc 닉네임 규칙)

📝 기타 참고사항

DB 마이그레이션: V20260916_000000__widen_records_content_column.sql (records.content → VARCHAR(1000)). 컬럼 타입 확장이라 기존 데이터 재작성 없이 적용됩니다.

확인이 필요한 부분

  • 프론트가 기록 content를 필수로 검증하고 있다면 이미지만 올리는 경우를 막을 수 있습니다. 또한 이미지만 있는 기록은 타임라인 상세·서재 목록 응답의 content가 null로 내려갑니다.
  • V20260904_120000__expand_record_content_length.sql이 다른 브랜치에 있는 것으로 확인됩니다(목적 동일). 그쪽이 머지되면 컬럼 확장이 중복될 수 있어 조율이 필요합니다.
  • 조사 과정에서 확인한 사실: 100명 동시 업로드 시 느려지는 부분은 이미지 PUT(로컬 노트북 업로드 대역폭)이며 서버 문제가 아니었습니다. 별개로 Hikari 풀이 기본값(10)이라 동시 접속이 몰리면 커넥션 대기가 생기는 것은 확인되었으나 이번 PR에서는 다루지 않았습니다.

검증: ./gradlew test 전체 통과, scripts/validate-flyway-migrations.sh 통과

Summary by CodeRabbit

  • 새로운 기능

    • 내용 없이 이미지로 기록을 생성하거나 수정할 수 있습니다.
    • 기록 이미지 순서를 유지하고 변경할 수 있습니다.
    • 타임라인 기록 미리보기가 최대 100자로 표시됩니다.
  • 변경 사항

    • 내용과 이미지가 모두 없는 기록은 저장할 수 없습니다.
    • 기록 내용은 최대 1,000자까지 입력할 수 있습니다.
    • 닉네임 허용 길이가 2~10자로 변경되었습니다.
    • 닉네임에 공백을 포함할 수 있습니다.
  • 성능 테스트

    • 기록 생성부터 이미지 업로드까지의 전체 흐름을 측정하는 시나리오가 추가되었습니다.
    • 테스트 결과를 비교하는 HTML 리포트를 생성할 수 있습니다.

@Length(max=1000)으로 검증은 통과하지만 DB 컬럼이 VARCHAR(255)라
255자 초과 기록 생성 시 INSERT가 실패해 409로 응답되던 문제를 수정한다.
수정 요청의 이미지 키를 전부 새로 insert하던 방식을 바꿔
신규 키만 추가하고, 요청에서 빠진 키만 삭제하며, 유지되는 키는 orderIndex만 갱신한다.
실제 원인 쿼리/호출 위치를 추적할 수 있도록 예외 객체를 함께 로깅한다.
JWT 기반 인증만 사용하므로 form 로그인을 끄고,
기동 시 임의 비밀번호를 생성/로깅하는 UserDetailsServiceAutoConfiguration을 제외한다.
업로드 URL 발급, R2 이미지 PUT, 기록 생성을 단계별로 측정하고
VUS, IMAGE_COUNT, CONTENT_LENGTH, PUT_MODE로 조건을 바꿔 1명/100명 등을 비교한다.
여러 실행의 report JSON을 받아 종단 소요 시간, 성공률, 단계별 응답 시간을 나란히 비교한다.
기록 생성·수정 DTO의 content @notblank를 제거하고, 내용과 이미지가 모두 비어 있는
경우에만 RECORD-400으로 거부한다. 공백 내용은 null로 저장하며 타임라인 preview는
기존 fallback("N개의 이미지")을 그대로 사용한다.
기록 수정 시 신규 이미지를 record.images에도 반영하고, 이에 맞춰 수정/중복 방지 테스트를 갱신한다.
마이페이지 닉네임/프로필 수정과 DEV 가입·로그인 DTO의 닉네임 규칙을 온보딩(최대 10자)과 맞춘다.
검증 메시지, REST Docs 설명, user.adoc 문구를 함께 갱신하고 10자/11자 경계 테스트를 추가한다.
서로게이트 문자(이모지)를 글자 단위로 세어 중간에서 깨지지 않게 자른다.
본문 전체를 preview로 저장하던 것을 앞 100자로 제한한다.
501자 이상 기록이 preview_text(VARCHAR(500)) 초과로 저장 실패하던 문제도 함께 해소된다.
조회 시 기록 본문으로 다시 계산하는 preview를 100자로 자른다.
상세 조회의 본문(content)은 자르지 않고 전체를 반환한다.
@coderabbitai

coderabbitai Bot commented Sep 20, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 7f4b7d29-62b6-4b8f-9bac-4a109a0f8956

📥 Commits

Reviewing files that changed from the base of the PR and between 4c8d6d0 and 27cd10a.

📒 Files selected for processing (30)
  • performance/k6/config/profiles.js
  • performance/k6/lib/data.js
  • performance/k6/lib/images.js
  • performance/k6/scenarios/record-image-upload.js
  • performance/k6/scripts/compare-reports.sh
  • performance/k6/scripts/run-k6.sh
  • performance/k6/scripts/verify-options.sh
  • performance/k6/scripts/verify-runner.sh
  • src/docs/asciidoc/user.adoc
  • src/main/java/app/nook/NookApplication.java
  • src/main/java/app/nook/global/config/WebSecurityConfig.java
  • src/main/java/app/nook/global/exception/ExceptionAdvice.java
  • src/main/java/app/nook/record/domain/Record.java
  • src/main/java/app/nook/record/domain/RecordImage.java
  • src/main/java/app/nook/record/dto/RecordRequestDto.java
  • src/main/java/app/nook/record/dto/RecordUpdateRequestDto.java
  • src/main/java/app/nook/record/exception/RecordErrorCode.java
  • src/main/java/app/nook/record/service/RecordCommandService.java
  • src/main/java/app/nook/timeline/service/TimelineCommandService.java
  • src/main/java/app/nook/timeline/service/TimelineQueryService.java
  • src/main/java/app/nook/timeline/util/TimelinePreviewText.java
  • src/main/java/app/nook/user/dto/UserDTO.java
  • src/main/java/app/nook/user/dto/UserProfileDto.java
  • src/main/resources/db/migration/V20260916_000000__widen_records_content_column.sql
  • src/test/java/app/nook/controller/record/RecordControllerTest.java
  • src/test/java/app/nook/controller/user/UserControllerTest.java
  • src/test/java/app/nook/record/service/RecordServiceTest.java
  • src/test/java/app/nook/timeline/service/TimelineCommandServiceTest.java
  • src/test/java/app/nook/timeline/service/TimelineQueryServiceTest.java
  • src/test/java/app/nook/timeline/util/TimelinePreviewTextTest.java
 _________________________________________________________________
< Granted, I'm not human, but I still know when your code is bad. >
 -----------------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

@JiwonLee42 JiwonLee42 self-assigned this Sep 20, 2026
@github-actions

Copy link
Copy Markdown
Overall Project 79.75% -0.02% 🍏
Files changed 98.24% 🍏

File Coverage
TimelinePreviewText.java 100% 🍏
RecordImage.java 100% 🍏
Record.java 100% 🍏
TimelineCommandService.java 98.21% 🍏
TimelineQueryService.java 97.19% 🍏
RecordCommandService.java 96.9% -0.71% 🍏

@JiwonLee42
JiwonLee42 merged commit e0616a8 into develop-demo Sep 20, 2026
1 of 2 checks passed
@kjhyeon0620 kjhyeon0620 mentioned this pull request Sep 21, 2026
4 tasks done
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