Skip to content

[NDGL-137] 콘텐츠 추천 화면 UI/UX 제작#1

Merged
mj010504 merged 5 commits into
developfrom
NDGL-131
May 14, 2026
Merged

[NDGL-137] 콘텐츠 추천 화면 UI/UX 제작#1
mj010504 merged 5 commits into
developfrom
NDGL-131

Conversation

@mj010504

@mj010504 mj010504 commented May 13, 2026

Copy link
Copy Markdown

개요

  • 콘텐츠 추천 화면 UI/UX 제작

연관 문서

디자인

스크린샷

bandicam.2026-05-13.23-57-29-100.mp4

변경사항

  • 기존 설정 화면에 콘텐츠 추천 링크 넣기 기능 변경(임시 진입점)
  • 콘텐츠 추천 화면 UI/UX 제작
  • Youtube Oembed API 연동

참고사항

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능
    • 여행 콘텐츠 추천 기능 추가: YouTube 영상 URL 입력, 여행 테마 선택(음식, 카페, 힐링 등), 추천 이유 작성이 가능합니다.
    • 설정 메뉴에서 "콘텐츠 추천" 옵션 추가로 쉬운 접근성 제공
    • YouTube 영상 메타데이터(제목, 채널명, 썸네일)자동 미리보기

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2dfce5d2-fe3e-4d4b-a78e-b300e5cb3e13

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

개요

YouTube oEmbed API를 통한 메타데이터 조회, MVI 패턴 기반 상태 관리, Compose UI 화면, 홈 설정 메뉴 통합을 포함하는 새로운 콘텐츠 추천 기능이 구현되었습니다.

변경 사항

콘텐츠 추천 기능

계층 / 파일 설명
YouTube 메타데이터 API 및 저장소
data/travel/src/main/java/com/yapp/ndgl/data/travel/api/YoutubeOembedApi.kt, data/travel/src/main/java/com/yapp/ndgl/data/travel/model/YoutubeOembedResponse.kt, data/travel/src/main/java/com/yapp/ndgl/data/travel/repository/ContentMetadataRepository.kt, data/travel/src/main/java/com/yapp/ndgl/data/travel/di/TravelNetworkModule.kt, data/core/src/main/java/com/yapp/ndgl/data/core/di/NetworkModule.kt
YouTube oEmbed API를 통해 동영상의 제목, 채널명, 썸네일 URL을 조회합니다. @YoutubeOembedClient 한정자를 통해 별도의 Retrofit 인스턴스와 OkHttpClient를 Hilt DI로 설정합니다.
기능 모듈 설정 및 MVI 계약
feature/content-recommendation/build.gradle.kts, feature/content-recommendation/src/main/AndroidManifest.xml, feature/content-recommendation/src/main/res/values/strings.xml, feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/ContentRecommendationContract.kt, feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/model/TravelTheme.kt
:feature:content-recommendation 모듈을 생성하고, 상태(URL, 메타데이터, 테마, 사유), 인텐트(URL 업데이트, 테마 토글, 사유 입력, 제출), 사이드이펙트를 정의합니다. 8개의 여행 테마 enum을 추가합니다.
UI 및 뷰모델 구현
feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/ContentRecommendationViewModel.kt, feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/ContentRecommendationScreen.kt, feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/ContentLinkSection.kt, feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/HeaderSection.kt, feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/ReasonSection.kt, feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/TravelThemeSection.kt, feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/navigation/ContentRecommendationEntry.kt
URL 검증, 비동기 메타데이터 조회, 테마 선택, 추천 사유 입력(200자 제한)을 구현합니다. 로딩/성공/오류 상태의 시각적 피드백을 Compose로 제공합니다.
앱 레벨 통합
navigation/src/main/java/com/yapp/ndgl/navigation/Route.kt, feature/home/src/main/java/com/yapp/ndgl/feature/home/navigation/HomeEntry.kt, feature/home/src/main/java/com/yapp/ndgl/feature/home/settings/SettingsContract.kt, feature/home/src/main/java/com/yapp/ndgl/feature/home/settings/SettingsScreen.kt, feature/home/src/main/java/com/yapp/ndgl/feature/home/settings/SettingsViewModel.kt, app/src/main/java/com/yapp/ndgl/ui/NDGLApp.kt, app/build.gradle.kts, settings.gradle.kts
새로운 Route.ContentRecommendation 라우트를 추가합니다. 홈 설정 메뉴에 콘텐츠 추천 항목을 추가하고, 클릭 시 새 화면으로 네비게이션하는 인텐트와 사이드이펙트를 정의합니다. 앱과 모듈 빌드 파일에서 의존성을 설정합니다.

추정 코드 리뷰 시간

🎯 4 (복잡함) | ⏱️ ~45분

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 주요 변경사항을 명확하게 반영하고 있습니다. 콘텐츠 추천 화면의 UI/UX 제작이 이 PR의 핵심 목표이며, 제목이 이를 정확히 설명합니다.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch NDGL-131

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@data/travel/src/main/java/com/yapp/ndgl/data/travel/di/TravelNetworkModule.kt`:
- Around line 15-16: Remove the locally declared qualifier and its import so the
module uses the shared core qualifier: delete the local `@Qualifier` annotation
declaration (the local YoutubeOembedClient qualifier) and the unnecessary
javax.inject.Qualifier import in TravelNetworkModule, keep the import of
com.yapp.ndgl.data.core.di.YoutubeOembedClient, and ensure any provider methods
that bind the OkHttpClient in TravelNetworkModule are annotated with the core
YoutubeOembedClient qualifier (the one from the core module) so Hilt injects the
same qualifier type across modules.

In `@feature/content-recommendation/build.gradle.kts`:
- Around line 10-12: 현재 val localProperties = Properties().apply {
load(rootProject.file("local.properties").bufferedReader()) } 는 파일이 없으면 즉시 실패하므로
빌드가 깨질 수 있습니다; 수정 방법은 localProperties를 로드하기 전에
rootProject.file("local.properties")의 존재 여부를 확인하고 존재할 때만 load를 호출하거나 존재하지 않을 경우
빈 Properties를 사용하도록 변경하는 것입니다(예: check file.exists() 또는 takeIf { it.exists() }
패턴을 사용하고, 필요하면 예외 방지를 위해 try/catch로 감쌉니다); 참조 대상: localProperties 변수와
load(rootProject.file("local.properties").bufferedReader()) 호출을 찾아 조건부 로딩으로
바꿉니다.

In
`@feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/ContentRecommendationViewModel.kt`:
- Around line 30-43: updateUrl currently fires fetchMetadata on every valid URL
and doesn't cancel prior requests, causing stale/late responses to overwrite
newer state; fix by debouncing input and canceling any in-flight metadata job
before starting a new one in updateUrl: introduce a Job/Coroutine reference
(e.g., metadataJob) at the ViewModel level, cancel metadataJob when starting a
new fetch, debounce rapid calls (e.g., delay before calling fetchMetadata) and
include a response guard inside fetchMetadata that verifies the response
corresponds to the current contentUrl (or a request token) before calling reduce
to update metadataState; reference updateUrl, fetchMetadata, isYoutubeUrl,
MetadataState and ensure isSubmitEnabled is set only after the guarded, latest
response is applied.
- Around line 84-85: The current isYoutubeUrl(url: String) uses String.contains
and can be bypassed by query params; change it to parse the URL and validate the
host instead: in isYoutubeUrl, parse the input with java.net.URI or
java.net.URL, extract the host (handle nulls and lowercase/trim), and return
true only if host equals "youtu.be" or equals "youtube.com" or endsWith
".youtube.com" (to allow subdomains like "m.youtube.com" or "www.youtube.com");
catch exceptions (MalformedURLException/URISyntaxException) and return false for
invalid inputs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6143dd2c-cc8e-49d9-9ff0-df06fd418a8d

📥 Commits

Reviewing files that changed from the base of the PR and between c2428ac and a1c0b4c.

📒 Files selected for processing (33)
  • .gitignore
  • app/build.gradle.kts
  • app/src/main/java/com/yapp/ndgl/ui/NDGLApp.kt
  • core/ui/src/main/res/drawable/ic_24_alert.xml
  • core/ui/src/main/res/drawable/ic_24_asterisk.xml
  • core/ui/src/main/res/drawable/ic_24_youtube.xml
  • data/core/src/main/java/com/yapp/ndgl/data/core/di/NetworkModule.kt
  • data/travel/src/main/java/com/yapp/ndgl/data/travel/api/YoutubeOembedApi.kt
  • data/travel/src/main/java/com/yapp/ndgl/data/travel/di/TravelNetworkModule.kt
  • data/travel/src/main/java/com/yapp/ndgl/data/travel/model/YoutubeOembedResponse.kt
  • data/travel/src/main/java/com/yapp/ndgl/data/travel/repository/ContentMetadataRepository.kt
  • feature/content-recommendation/.gitignore
  • feature/content-recommendation/build.gradle.kts
  • feature/content-recommendation/consumer-rules.pro
  • feature/content-recommendation/proguard-rules.pro
  • feature/content-recommendation/src/main/AndroidManifest.xml
  • feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/ContentLinkSection.kt
  • feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/ContentRecommendationContract.kt
  • feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/ContentRecommendationScreen.kt
  • feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/ContentRecommendationViewModel.kt
  • feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/HeaderSection.kt
  • feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/ReasonSection.kt
  • feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/TravelThemeSection.kt
  • feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/model/TravelTheme.kt
  • feature/content-recommendation/src/main/java/com/yapp/ndgl/feature/contentrecommendation/navigation/ContentRecommendationEntry.kt
  • feature/content-recommendation/src/main/res/values/strings.xml
  • feature/home/src/main/java/com/yapp/ndgl/feature/home/navigation/HomeEntry.kt
  • feature/home/src/main/java/com/yapp/ndgl/feature/home/settings/SettingsContract.kt
  • feature/home/src/main/java/com/yapp/ndgl/feature/home/settings/SettingsScreen.kt
  • feature/home/src/main/java/com/yapp/ndgl/feature/home/settings/SettingsViewModel.kt
  • gradle/libs.versions.toml
  • navigation/src/main/java/com/yapp/ndgl/navigation/Route.kt
  • settings.gradle.kts

Comment thread feature/content-recommendation/build.gradle.kts
@NDGL-official NDGL-official deleted a comment from coderabbitai Bot May 13, 2026
@mj010504 mj010504 merged commit 11f32a2 into develop May 14, 2026
4 checks passed
@mj010504 mj010504 deleted the NDGL-131 branch May 14, 2026 00:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant