Skip to content

Conversation

@ose0221
Copy link
Contributor

@ose0221 ose0221 commented Feb 5, 2026

🚀 PR 요약

목적이 무엇인가요? - 지우고 작성

✨ PR 상세 내용

어떤 부분이 어떻게 변경이 되었나요? - 지우고 작성

🚨 주의 사항

주의할 부분이 무엇인가요? - 지우고 작성

✅ 체크 리스트

  • 리뷰어 설정했나요?
  • Label 설정했나요?
  • 제목 양식 맞췄나요? (ex. feat: 기능 추가)
  • 변경 사항에 대한 테스트를 진행했나요?

Summary by CodeRabbit

Release Notes

  • New Features
    • Added article metadata extraction (title and thumbnail) during article creation
    • Implemented automatic thumbnail image upload and storage
    • Added batch migration tool to retrieve missing metadata for existing articles
    • Introduced new API endpoint for enhanced article creation workflow

@coderabbitai
Copy link

coderabbitai bot commented Feb 5, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

This PR introduces article metadata extraction and storage functionality. It adds JSoup-based HTML parsing to extract article titles and thumbnails from URLs, stores these in the Article domain model, uploads thumbnails to S3, and provides async batch migration for enriching existing articles with metadata.

Changes

Cohort / File(s) Summary
Dependencies & Configuration
api/build.gradle, infrastructure/build.gradle, api/src/main/resources/application.yml, shared/src/main/java/com/pinback/shared/constant/ExceptionCode.java
Added JSoup dependency for HTML parsing, DEFAULT_THUMBNAIL configuration property, and two new exception codes (INVALID_URL, ARTICLE_TILE_NOT_FOUND) for metadata extraction error handling.
API Layer
api/src/main/java/com/pinback/api/PinbackApiApplication.java, api/src/main/java/com/pinback/api/article/controller/ArticleControllerV3.java
Enabled Spring async support via @EnableAsync and added ArticleControllerV3 REST endpoint exposing POST /api/v3/articles (article creation) and POST /api/v3/articles/metadata (batch metadata migration).
Application Layer
application/src/main/java/com/pinback/application/article/dto/response/ArticleMetadataResponse.java, application/src/main/java/com/pinback/application/article/port/in/CreateArticlePort.java, application/src/main/java/com/pinback/application/test/port/out/ArticleMetadataPort.java, application/src/main/java/com/pinback/application/article/usecase/command/CreateArticleUsecase.java
Added ArticleMetadataPort abstraction for metadata extraction, ArticleMetadataResponse DTO, and createArticleV3 flow in CreateArticleUsecase that retrieves and stores metadata alongside article creation.
Domain Model
domain/src/main/java/com/pinback/domain/article/entity/Article.java, domain/src/main/java/com/pinback/domain/article/exception/ArticleTitleNotFoundException.java, domain/src/main/java/com/pinback/domain/article/exception/InvalidUrlException.java
Added title and thumbnail persisted fields to Article entity with createWithMetaData factory method and updateMetadata method; introduced new exception classes for missing titles and invalid URLs.
Infrastructure Services
infrastructure/src/main/java/com/pinback/infrastructure/article/repository/ArticleRepository.java, infrastructure/src/main/java/com/pinback/infrastructure/article/service/ArticleMetadataAdapter.java, infrastructure/src/main/java/com/pinback/infrastructure/article/service/ArticleUpdateService.java, infrastructure/src/main/java/com/pinback/infrastructure/s3/service/S3StorageService.java
Implemented ArticleMetadataAdapter for JSoup-based HTML metadata extraction with S3 thumbnail upload, added ArticleUpdateService for async batch metadata migration, extended ArticleRepository with findByTitleIsNull query, and added uploadArticleThumbnail method to S3StorageService with URL hashing and duplicate detection.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Controller as ArticleControllerV3
    participant Usecase as CreateArticleUsecase
    participant Adapter as ArticleMetadataAdapter
    participant S3 as S3StorageService
    participant Repo as ArticleRepository
    participant DB as Database

    Client->>Controller: POST /api/v3/articles
    Controller->>Usecase: createArticleV3(user, command)
    Usecase->>Adapter: extractMetadata(url)
    Adapter->>Adapter: parseHTML with Jsoup
    Adapter->>Adapter: extractTitle & ogImage
    alt Image exists
        Adapter->>S3: uploadArticleThumbnail(image)
        S3->>S3: hashUrl, checkExists
        S3->>Repo: upload to S3
        S3-->>Adapter: thumbnail S3 URL
    else No image
        Adapter->>Adapter: use DEFAULT_THUMBNAIL
    end
    Adapter-->>Usecase: ArticleMetadataResponse
    Usecase->>Repo: save Article with metadata
    Repo->>DB: INSERT article
    DB-->>Repo: success
    Repo-->>Usecase: saved Article
    Usecase-->>Controller: success
    Controller-->>Client: ResponseDto<Void>
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

  • 2차 스프린트 prod 업데이트 #122 — Both PRs extend S3StorageService with new upload methods (uploadArticleThumbnail in this PR vs. uploadProfileImage in referenced PR) and share similar S3 integration patterns.

Suggested labels

feat

Suggested reviewers

  • rootTiket

Poem

🐰 Hoppity-hop, metadata's found!
Jsoup parses, S3 uploads round,
Titles and thumbnails now stored with care,
Articles enriched everywhere!

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

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 and usage tips.

@ose0221 ose0221 merged commit 13bc306 into main Feb 5, 2026
4 of 5 checks passed
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