feat: OCR 모듈 구성, 화면 및 기능 연동#72
Conversation
# Conflicts: # gradle/libs.versions.toml
…Proxy) InputImage는 mlkit 패키지에 종속되어 있어 호출부에서 ML Kit 의존성이 생김, 이를 방지하기 위해 TextAnalyzer 인터페이스는 ImageProxy를 직접 받도록 변경하고, 내부에서 InputImage로 변환
… @AssistedFactory 로 변경 동적으로 변하는 함수 파라미터(런타입 콜백 파라미터)가 있는 객체는 Hilt가 자동 생성할 수 없기 때문
WalkthroughOCR(Optical Character Recognition) 기능을 위한 새로운 core:ocr 모듈이 추가되었습니다. ML Kit의 텍스트 인식(Korean) 라이브러리와 CameraX 의존성이 도입되었으며, OCR 분석기, DI 모듈, UI 상태 및 이벤트 모델, 프레젠터, Compose UI 컴포넌트가 구현되었습니다. 앱과 record feature에 OCR 모듈이 통합되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant OcrUi
participant CameraX
participant LiveTextAnalyzer
participant MLKit
participant OcrPresenter
participant Navigator
User->>OcrUi: 앱에서 OCR 화면 진입
OcrUi->>CameraX: 카메라 프리뷰 시작
CameraX->>LiveTextAnalyzer: 프레임 전달
LiveTextAnalyzer->>MLKit: 텍스트 인식 요청
MLKit-->>LiveTextAnalyzer: 인식 결과 반환
LiveTextAnalyzer-->>OcrPresenter: 결과 콜백 전달
OcrPresenter-->>OcrUi: UI 상태 갱신(텍스트, 문장 리스트 등)
User->>OcrUi: 문장 선택/확인
OcrUi->>OcrPresenter: 이벤트 전달
OcrPresenter->>Navigator: 선택 문장 결과 반환 및 화면 종료
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Assessment against linked issues
Suggested reviewers
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 10
🧹 Nitpick comments (10)
core/ocr/src/main/kotlin/com/ninecraft/booket/core/ocr/analyzer/TextAnalyzer.kt (1)
5-7: 인터페이스에 사용 책임 명시 필요
analyze()내부에서ImageProxy.close()호출 책임이 구현체에 있다는 점이 인터페이스 시그니처만으로는 드러나지 않습니다.
간단한 KDoc 혹은@WorkerThread·@AnyThread같은 어노테이션을 추가해 호출-스레드 규약과ImageProxy해제 책임을 명확히 적어 두면 유지보수성이 높아집니다.+/** + * CameraX `ImageAnalysis` 콜백에서 호출되는 OCR 분석기. + * + * 구현체는 분석 완료 후 반드시 `imageProxy.close()` 를 호출해야 한다. + */ interface TextAnalyzer { fun analyze(imageProxy: ImageProxy) }feature/record/build.gradle.kts (1)
19-27: 카메라 라이브러리 버전 일관성 확인
core.ocr모듈에서도 CameraX(core) 의존성을 가지고 있을 가능성이 높습니다.
feature 모듈에서 별도로camera2,lifecycle,view를 선언할 때 버전이 맞지 않으면 그래들 충돌 경고가 발생할 수 있으니,libs.versions.toml의 동일 coordinates 를 사용하고 있는지 확인해 주세요. 필요하다면 CameraX BOM(camera-bom) 사용을 고려해도 좋습니다.core/ocr/src/main/kotlin/com/ninecraft/booket/core/ocr/di/OcrModule.kt (1)
12-20: OCR 모듈 구현 완료, 리소스 생명주기 관리 고려 필요Dagger Hilt를 사용한 OCR 모듈 구성이 올바르게 되어 있습니다. 한국어 텍스트 인식을 위한 적절한 설정과 싱글톤 스코프 적용이 잘 되어 있습니다.
다만 ML Kit TextRecognizer는 리소스를 사용하는 객체이므로 앱 종료 시 또는 더 이상 사용하지 않을 때 적절한 정리가 필요할 수 있습니다. 현재 구현에서는 앱 생명주기와 함께 관리되므로 큰 문제는 없지만, 향후 메모리 사용량을 모니터링해보시기 바랍니다.
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/component/CameraFrame.kt (1)
34-80: 접근성 개선을 위한 contentDescription 구체화 필요모든 코너 마커가 동일한 contentDescription을 사용하고 있어 스크린 리더 사용자가 구분하기 어려울 수 있습니다.
다음 중 하나의 방법을 고려해주세요:
- 각 코너별로 구체적인 설명 제공 (예: "상단 좌측 프레임 마커")
- 장식적 요소라면
contentDescription = null사용// 옵션 1: 구체적인 설명 - contentDescription = "Frame Marker", + contentDescription = "상단 좌측 프레임 마커", // 옵션 2: 장식적 요소로 처리 - contentDescription = "Frame Marker", + contentDescription = null,core/ocr/src/main/kotlin/com/ninecraft/booket/core/ocr/analyzer/LiveTextAnalyzer.kt (1)
60-60: 프레임 처리 지연으로 인한 성능 문제현재 구현은 각 프레임 처리 후 1초의 지연을 추가하고 있습니다. 이는 실시간 분석에는 너무 긴 지연일 수 있습니다.
사용자 경험을 개선하기 위해 지연 시간을 줄이거나 동적으로 조정하는 것을 고려해보세요:
- const val THROTTLE_TIMEOUT_MS = 1_000L // 프레임 처리 간 인터벌 + const val THROTTLE_TIMEOUT_MS = 300L // 프레임 처리 간 인터벌feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrUi.kt (1)
145-145: 중복된 배경색 설정
ReedCloseTopAppBar에 이미isDark = true를 전달하고 있는데, 추가로background(color = Color.Black)을 설정하고 있습니다.중복된 배경색 설정을 제거하세요:
- modifier = Modifier.background(color = Color.Black), + modifier = Modifier,feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrPresenter.kt (2)
67-68: 한국어 텍스트 병합 시 공백 처리를 개선해보세요.한국어는 문장 간 공백이 영어와 다르게 처리됩니다. 현재 공백으로 연결하는 방식이 자연스러운지 검토가 필요합니다.
- mergedSentence = selectedIndices - .sorted().joinToString(" ") { sentenceList[it] } + mergedSentence = selectedIndices + .sorted().joinToString("") { sentenceList[it] }
109-122: 문장 파싱 로직이 잘 구현되어 있으나 한국어 구두점 지원을 확장할 수 있습니다.현재 구현은 기본적인 구두점 처리가 잘되어 있습니다. 한국어에서 사용되는 추가 구두점들도 고려해보세요.
- val containsPunctuation = text.contains(Regex("[.!?]")) + val containsPunctuation = text.contains(Regex("[.!?。!?]"))- .split(Regex("(?<=[.!?])\\s+")) + .split(Regex("(?<=[.!?。!?])\\s+"))feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt (2)
30-35: 텍스트 교체 로직을 개선하고 UX를 검토해보세요.현재 구현은 다음과 같은 개선점이 있습니다:
- 텍스트 교체 로직이 장황합니다 -
replace(0, length, "")+append()대신 더 간단한 방법을 사용할 수 있습니다.- 기존 텍스트를 완전히 교체하는 것이 최적의 UX인지 검토가 필요합니다. 사용자가 OCR 결과를 기존 텍스트에 추가하거나 특정 위치에 삽입하고 싶을 수도 있습니다.
텍스트 교체 로직을 단순화할 수 있습니다:
- recordSentenceState.edit { - replace(0, length, "") - append(result.sentence) - } + recordSentenceState.setTextAndPlaceCursorAtEnd(result.sentence)
30-35: OCR 결과 처리 로직을 검토해주세요.현재 구현은 OCR 결과를 받으면 기존 문장을 완전히 대체합니다. 사용자 경험 관점에서 다음을 고려해보세요:
- 기존 텍스트가 있을 때 사용자에게 확인을 요청할지
- 텍스트를 대체할지 추가할지 선택권을 제공할지
더 간단한 구현을 고려해볼 수 있습니다:
- recordSentenceState.edit { - replace(0, length, "") - append(result.sentence) - } + recordSentenceState.edit { + replace(0, length, result.sentence) + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
feature/record/src/main/res/drawable/img_frame_marker.pngis excluded by!**/*.png
📒 Files selected for processing (23)
app/build.gradle.kts(1 hunks)app/src/main/AndroidManifest.xml(1 hunks)core/ocr/.gitignore(1 hunks)core/ocr/build.gradle.kts(1 hunks)core/ocr/src/main/kotlin/com/ninecraft/booket/core/ocr/analyzer/LiveTextAnalyzer.kt(1 hunks)core/ocr/src/main/kotlin/com/ninecraft/booket/core/ocr/analyzer/StillTextAnalyzer.kt(1 hunks)core/ocr/src/main/kotlin/com/ninecraft/booket/core/ocr/analyzer/TextAnalyzer.kt(1 hunks)core/ocr/src/main/kotlin/com/ninecraft/booket/core/ocr/di/OcrModule.kt(1 hunks)core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/ReedTopAppBar.kt(6 hunks)feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/component/LibraryBookItem.kt(1 hunks)feature/record/build.gradle.kts(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrPresenter.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrUi.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrUiState.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/component/CameraFrame.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/component/SentenceBox.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt(3 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterUi.kt(1 hunks)feature/record/src/main/res/values/strings.xml(1 hunks)feature/screens/src/main/kotlin/com/ninecraft/booket/feature/screens/Screens.kt(2 hunks)feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/BookItem.kt(1 hunks)gradle/libs.versions.toml(5 hunks)settings.gradle.kts(1 hunks)
🧰 Additional context used
🧠 Learnings (12)
📓 Common learnings
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#46
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/InfiniteLazyColumn.kt:83-95
Timestamp: 2025-07-14T00:46:03.843Z
Learning: seoyoon513과 팀은 한국어 주석을 선호하며, 한국어 주석을 영어로 번역하라는 제안을 하지 않아야 함
settings.gradle.kts (1)
Learnt from: easyhooon
PR: #61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 booket.android.feature convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
core/ocr/build.gradle.kts (1)
Learnt from: easyhooon
PR: #61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 booket.android.feature convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/BookItem.kt (1)
Learnt from: easyhooon
PR: #61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 booket.android.feature convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
app/src/main/AndroidManifest.xml (1)
Learnt from: easyhooon
PR: #61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 booket.android.feature convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterUi.kt (1)
Learnt from: seoyoon513
PR: #35
File: feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/TermsAgreementScreen.kt:127-127
Timestamp: 2025-07-09T01:14:29.836Z
Learning: In the Reed-Android project's TermsAgreementScreen.kt, the OnTermDetailClick event is intentionally passed an empty string for the URL parameter because the actual URLs for terms detail pages haven't been decided yet. This is a temporary implementation that will be updated once the URLs are finalized.
app/build.gradle.kts (1)
Learnt from: easyhooon
PR: #61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 booket.android.feature convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt (2)
Learnt from: easyhooon
PR: #52
File: feature/main/src/main/kotlin/com/ninecraft/booket/feature/main/screens/DelegatingNavigator.kt:0-0
Timestamp: 2025-07-16T15:54:19.322Z
Learning: In the Reed-Android project using Circuit architecture, DelegatingNavigator was restored because NavigableCircuitContent can only inject a single navigator, but the dual-navigator architecture (childNavigator for bottom navigation screens, rootNavigator for full-screen screens) requires a delegating component to work within Circuit's constraint.
Learnt from: easyhooon
PR: #61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 booket.android.feature convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
feature/screens/src/main/kotlin/com/ninecraft/booket/feature/screens/Screens.kt (2)
Learnt from: easyhooon
PR: #61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 booket.android.feature convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
Learnt from: seoyoon513
PR: #35
File: feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/TermsAgreementScreen.kt:127-127
Timestamp: 2025-07-09T01:14:29.836Z
Learning: In the Reed-Android project's TermsAgreementScreen.kt, the OnTermDetailClick event is intentionally passed an empty string for the URL parameter because the actual URLs for terms detail pages haven't been decided yet. This is a temporary implementation that will be updated once the URLs are finalized.
feature/record/build.gradle.kts (1)
Learnt from: easyhooon
PR: #61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 booket.android.feature convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/ReedTopAppBar.kt (4)
Learnt from: seoyoon513
PR: #32
File: core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt:15-21
Timestamp: 2025-07-08T03:21:24.693Z
Learning: Reed Android 프로젝트에서는 다크모드/라이트모드 대응 계획이 없고 기본 테마 값만 사용할 예정이다.
Learnt from: seoyoon513
PR: #45
File: core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/appbar/ReedTopAppBar.kt:65-65
Timestamp: 2025-07-12T01:33:57.101Z
Learning: Reed Android 프로젝트에서 타이포그래피 사용 규칙: 톱 앱바(Top App Bar)에서는 headline2SemiBold를 사용하고, 바텀시트(Bottom Sheet)에서는 heading2SemiBold를 사용한다. 이는 의도적인 디자인 시스템 차별화이다.
Learnt from: easyhooon
PR: #55
File: core/designsystem/src/main/res/drawable/ic_x_circle.xml:6-11
Timestamp: 2025-07-17T23:41:33.929Z
Learning: Reed Android 프로젝트에서는 SVG에서 vector drawable로 변환시 색상 매핑 대신 모드별 별도 아이콘 파일을 사용하는 방식을 선호한다. Figma에서 SVG export한 형태를 그대로 사용하며, 다크모드 대응이 필요할 경우 drawable-night 폴더에 별도 아이콘을 배치하는 방식을 사용한다.
Learnt from: seoyoon513
PR: #35
File: feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/TermsAgreementScreen.kt:127-127
Timestamp: 2025-07-09T01:14:29.836Z
Learning: In the Reed-Android project's TermsAgreementScreen.kt, the OnTermDetailClick event is intentionally passed an empty string for the URL parameter because the actual URLs for terms detail pages haven't been decided yet. This is a temporary implementation that will be updated once the URLs are finalized.
gradle/libs.versions.toml (1)
Learnt from: easyhooon
PR: #61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 booket.android.feature convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
🧬 Code Graph Analysis (1)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/component/CameraFrame.kt (1)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
ReedTheme(14-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: ci-build
🔇 Additional comments (44)
feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/BookItem.kt (1)
54-54: UI 일관성 개선이 잘 적용되었습니다.
Column에서 end 패딩을 제거하여LibraryBookItem과 일관된 레이아웃을 유지하게 되었습니다. 이 변경으로 책 아이템 컴포넌트들 간의 통일성이 향상되었습니다.feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/component/LibraryBookItem.kt (1)
56-56: UI 일관성 개선이 적절하게 적용되었습니다.
Column에서 end 패딩을 제거하여 검색 화면의BookItem과 동일한 레이아웃 구조를 유지하게 되었습니다. 이로써 앱 전반에 걸쳐 책 아이템 컴포넌트들의 시각적 일관성이 향상되었습니다.settings.gradle.kts (1)
36-36: OCR 모듈 추가가 적절히 구성되었습니다.새로운
:core:ocr모듈이 다른 core 모듈들과 함께 올바른 위치에 추가되었습니다.gradle/libs.versions.toml (2)
81-84: 필요한 OCR 의존성들이 올바르게 추가되었습니다.Camera와 ML Kit 라이브러리들이 적절히 구성되어 OCR 기능 구현을 지원합니다.
Also applies to: 134-135
12-12: 버전 검증 완료: 추가된 Camera(1.4.2) 및 ML Kit Text Recognition(16.0.1) 라이브러리 버전이 최신 안정화 버전입니다.모든 Camera 모듈(camera-core, camera-camera2, camera-lifecycle, camera-view)은 최신 안정화 버전인 1.4.2이고, ML Kit Text Recognition은 16.0.1로 확인되었습니다.
따라서 현재 추가된 버전은 최신이며 보안상 안전합니다.core/ocr/.gitignore (1)
1-1: 표준적인 .gitignore 설정이 적절합니다.새로운 OCR 모듈의 빌드 디렉토리를 올바르게 무시하도록 설정되었습니다.
core/ocr/build.gradle.kts (2)
3-6: Convention plugin이 적절히 사용되었습니다.프로젝트의 표준 convention plugin을 올바르게 활용하여 OCR 모듈을 구성했습니다.
12-19: OCR 기능에 필요한 의존성들이 올바르게 구성되었습니다.로깅, 카메라, 한국어 텍스트 인식을 위한 필수 라이브러리들이 적절히 포함되었습니다.
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterUi.kt (1)
151-153: OCR 기능과의 연동이 올바르게 구현되었습니다.문장 스캔 버튼이 실제 OCR 이벤트를 발생시키도록 변경되어 새로운 OCR 기능과 적절히 연결되었습니다.
app/build.gradle.kts (1)
49-50: OCR 모듈 의존성 추가 확인
projects.core.ocr를 앱 모듈에도 직접 끼워 넣어 두셨는데, 실제로 앱 레이어에서 OCR API 를 호출하는 경우가 없다면 feature 모듈(예: record) 쪽 의존성만으로 충분합니다.
중복 포함이 문제 되지는 않지만, 그래들 구성 최소화를 위해 필요 여부 한 번 더 점검해 주세요.app/src/main/AndroidManifest.xml (1)
5-11: 카메라 권한 런타임 요청 여부 확인카메라 퍼미션과 하드웨어 선언이 추가되었습니다. UI 계층에서
ActivityResultContracts.RequestPermission등을 통해 런타임 퍼미션 플로우가 완비되어 있는지 다시 한 번 확인 부탁드립니다.
권한이 거부된 상태에서도 OCR 진입 시 앱이 크래시 없이 graceful 한 안내를 제공해야 합니다.feature/record/src/main/res/values/strings.xml (1)
15-23: 문자열 리소스 네이밍 👍OCR 관련 신규 문자열들이 명확히 이름 지어져 있어 재사용·검색이 용이합니다. 줄바꿈을 위한
\n사용도 적절합니다.feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt (8)
9-9: OCR 기능 통합을 위한 적절한 import 추가OCR 화면 네비게이션과 결과 처리를 위한 필수 import들이 올바르게 추가되었습니다.
Also applies to: 12-12
30-35: OCR 결과 처리 시 기존 입력 내용 완전 대체에 대한 검토 필요OCR 네비게이터 구현은 올바르게 되어 있지만,
recordSentenceState의 기존 내용을 완전히 대체합니다. 사용자가 이미 입력한 내용이 있을 경우 예상치 못한 동작일 수 있습니다.사용자 경험을 고려하여 다음 중 하나를 검토해주세요:
- 기존 내용 유지 후 OCR 결과 추가
- 사용자에게 기존 내용 대체 여부 확인
- 현재 동작이 의도된 것이라면 UX 문서화
55-57: OCR 화면으로의 네비게이션 구현 완료문장 스캔 버튼 클릭 시 OCR 화면으로 네비게이션하는 로직이 올바르게 구현되었습니다. Circuit 네비게이션 패턴을 잘 따르고 있습니다.
55-57: OCR 화면 네비게이션이 올바르게 구현되었습니다.이벤트 핸들러가
ocrNavigator를 사용하여 OCR 화면으로 정확히 네비게이션하고 있습니다.
9-9: 필요한 import가 올바르게 추가되었습니다.OCR 기능 통합을 위한 적절한 import들이 추가되었습니다.
Also applies to: 12-12
9-9: OCR 스크린 import가 올바르게 추가되었습니다.Circuit 아키텍처 패턴에 맞게 OCR 스크린이 적절히 import되었습니다.
12-12: answering navigator import가 적절합니다.Circuit의 결과 기반 네비게이션을 위한
rememberAnsweringNavigatorimport가 올바르게 추가되었습니다.
55-57: OCR 네비게이션 구현이 올바릅니다.Circuit의 answering navigator 패턴을 올바르게 사용하여 OCR 스크린으로 네비게이션하고 있습니다.
feature/screens/src/main/kotlin/com/ninecraft/booket/feature/screens/Screens.kt (8)
3-3: OCR 결과 반환을 위한 PopResult import 추가OCR 화면에서 결과를 반환하기 위한 필수 import가 올바르게 추가되었습니다.
36-36: RecordScreen 이름 변경 확인 필요RecordScreen의 이름이 "Record()"에서 "Record"로 변경되었습니다. 이 변경이 의도된 것인지, 그리고 다른 화면들과의 일관성을 유지하는지 확인해주세요.
38-42: OCR 화면 및 결과 타입 정의 완료OCR 화면과 결과 반환을 위한 데이터 클래스가 올바르게 정의되었습니다. 기존 화면들과 일관된 패턴을 따르고 있으며, PopResult 인터페이스 구현도 적절합니다.
38-42: OCR 화면과 결과 계약이 올바르게 정의되었습니다.
OcrScreen이 프로젝트의 화면 정의 패턴을 따르고 있으며,OcrResult데이터 클래스가PopResult인터페이스를 적절히 구현하여 OCR 결과를 호출 화면에 전달할 수 있도록 구성되었습니다.
36-36: 화면 이름 단순화가 일관성을 개선합니다.
RecordScreen의 이름에서 불필요한 괄호를 제거하여 다른 화면들과의 일관성을 높였습니다.
3-3: PopResult import가 올바르게 추가되었습니다.OCR 결과를 위한 PopResult 인터페이스 import가 적절히 추가되었습니다.
36-36: RecordScreen 이름 변경을 확인해주세요.RecordScreen의 이름이
"Record()"에서"Record"로 변경되었습니다. 이 변경이 의도된 것인지, 다른 스크린들과의 일관성에 영향을 주지 않는지 확인해주세요.
38-42: OCR 스크린 구현이 우수합니다.OCR 스크린과 결과 데이터 클래스가 올바르게 구현되었습니다:
@Parcelize어노테이션으로 상태 보존PopResult인터페이스 구현으로 결과 전달- 기존 스크린 패턴과 일관성 유지
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/component/CameraFrame.kt (3)
84-90: 프리뷰 구현 완료컴포넌트 프리뷰가 적절하게 구현되어 디자인 타임에서 확인 가능합니다.
21-43: 카메라 프레임 구현 검토 완료 및 리소스 확인됨카메라 프레임 컴포저블 구현이 전반적으로 적절하며 Compose 모범 사례를 준수합니다.
feature/record/src/main/res/drawable/img_frame_marker.png리소스가 정상적으로 존재함을 확인했습니다.
84-90: 프리뷰 함수가 적절하게 구현되었습니다.개발 시 미리보기를 위한 프리뷰 함수가 올바르게 구현되어 있습니다.
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/component/SentenceBox.kt (6)
19-57: 선택 가능한 문장 박스 컴포넌트 구현 완료선택 상태에 따른 조건부 스타일링이 잘 구현되어 있고, ReedTheme 디자인 토큰을 일관성 있게 사용하고 있습니다. 사용자 경험을 고려한 적절한 색상 조합과 레이아웃이 적용되었습니다.
43-45: 중복 클릭 방지가 적용된 안정적인 클릭 처리
clickableSingle확장 함수를 사용하여 중복 클릭을 방지하고 있어 OCR 결과 선택 시 안정적인 동작을 보장합니다.
59-68: 적절한 한국어 샘플 텍스트로 구성된 프리뷰한국어 텍스트를 사용한 프리뷰가 적절하게 구현되어 있어, OCR 기능의 실제 사용 상황을 잘 반영하고 있습니다.
19-57: SentenceBox 컴포넌트가 잘 구현되었습니다.다음과 같은 좋은 패턴들이 사용되었습니다:
- 선택 상태에 따른 조건부 스타일링으로 명확한 시각적 피드백 제공
- ReedTheme 디자인 시스템의 일관된 사용
clickableSingle확장 함수로 중복 클릭 방지- 적절한 모디파이어 체인과 재사용 가능한 컴포넌트 설계
19-57: 우수한 선택 가능한 문장 박스 컴포넌트 구현입니다.잘 구현된 UI 컴포넌트입니다:
- 상태 기반 스타일링으로 선택 여부를 시각적으로 표현
- ReedTheme 시스템과 일관된 통합
clickableSingle확장 함수로 안전한 클릭 처리- 접근성을 고려한 구현
- 단일 책임 원칙을 따르는 깔끔한 설계
59-68: 현실적인 한국어 텍스트로 구성된 프리뷰입니다.개발 시 실제 사용 사례를 잘 보여주는 한국어 텍스트가 포함된 프리뷰 함수입니다.
core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/ReedTopAppBar.kt (1)
31-31: 다크모드 구현이 프로젝트 가이드라인과 상충됨검색된 학습 내용에 따르면 Reed Android 프로젝트는 다크모드/라이트모드 대응 계획이 없고 기본 테마 값만 사용할 예정입니다. 하지만 이 변경사항은
isDark파라미터를 추가하여 다크모드를 지원하고 있습니다.OCR 기능을 위한 특별한 요구사항이 있다면 명시해 주시고, 그렇지 않다면 프로젝트 가이드라인에 맞춰 다크모드 관련 로직을 제거하는 것을 고려해 주세요.
Also applies to: 44-44, 56-56, 77-77
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrUi.kt (1)
127-133: 권한 처리 개선 필요현재
LaunchedEffect(Unit)을 사용하여 권한을 확인하고 있는데, 이는 컴포지션이 재생성될 때마다 실행될 수 있습니다.다음과 같이 개선하세요:
- LaunchedEffect(Unit) { + LaunchedEffect(permission) { val granted = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED if (!granted) { launcher.launch(permission) } else { hasPermission = true } }Likely an incorrect or invalid review comment.
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrPresenter.kt (3)
19-22: 클래스 구조와 의존성 주입이 올바르게 구현되었습니다.Circuit 패턴과 Dagger/Hilt를 활용한 의존성 주입이 적절히 설계되어 있습니다.
24-33: 상태 관리가 Compose 모범 사례를 잘 따르고 있습니다.
rememberRetained를 사용한 상태 보존과 불변 컬렉션 활용이 적절합니다.
19-107: 전반적으로 잘 구조화된 OCR Presenter입니다.Circuit 패턴을 올바르게 활용하고, 상태 관리와 이벤트 처리가 체계적으로 구현되어 있습니다. 성능 최적화와 오류 처리 부분을 개선하면 더욱 견고한 코드가 될 것입니다.
core/ocr/src/main/kotlin/com/ninecraft/booket/core/ocr/di/OcrModule.kt (2)
12-20: OCR 모듈이 올바르게 구현되었습니다.Dagger Hilt 모듈이 적절히 구성되어 있으며, ML Kit의 한국어 텍스트 인식기를 싱글톤으로 제공하고 있습니다. 이는 PR 목표에서 언급된 한국어 텍스트 인식 요구사항과 일치합니다.
12-20: 우수한 의존성 주입 모듈 구현입니다.OCR 모듈이 올바르게 구현되었습니다:
- Dagger Hilt 어노테이션 적절 사용
- SingletonComponent 스코프로 적절한 생명주기 관리
- 한국어 텍스트 인식을 위한 올바른 설정
- 단일 책임 원칙을 따르는 깔끔한 모듈 구조
| recognizedText = text | ||
| }, | ||
| ) | ||
| analyzer.analyze(event.imageProxy) |
There was a problem hiding this comment.
🛠️ Refactor suggestion
ML Kit 분석 작업에 대한 오류 처리가 누락되었습니다.
analyzer.analyze() 호출 시 발생할 수 있는 예외에 대한 처리가 필요합니다.
- analyzer.analyze(event.imageProxy)
+ try {
+ analyzer.analyze(event.imageProxy)
+ } catch (e: Exception) {
+ // 로깅 또는 사용자에게 오류 표시
+ isTextDetectionFailed = true
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| analyzer.analyze(event.imageProxy) | |
| try { | |
| analyzer.analyze(event.imageProxy) | |
| } catch (e: Exception) { | |
| // 로깅 또는 사용자에게 오류 표시 | |
| isTextDetectionFailed = true | |
| } |
🤖 Prompt for AI Agents
In
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrPresenter.kt
at line 46, the call to analyzer.analyze(event.imageProxy) lacks error handling
for exceptions that may occur during ML Kit analysis. Wrap this call in a
try-catch block to catch potential exceptions and handle them appropriately,
such as logging the error or notifying the user, to prevent crashes and improve
robustness.
There was a problem hiding this comment.
이건 LiveTextAnalyzer에서 addOnFailureListener, invokeOnCompletion에서 실패 및 예외를 콜백으로 처리 안해줘서 그런거야?
There was a problem hiding this comment.
🧩 Analysis chain
@seoyoon513, LiveTextAnalyzer의 구현을 확인해보겠습니다.
맞습니다! LiveTextAnalyzer를 확인해보니 이미 충분한 에러 처리가 구현되어 있네요:
- ML Kit 레벨:
addOnFailureListener로 ML Kit 실패 처리 - 코루틴 레벨:
suspendCoroutine주변의 try-catch 블록 - 리소스 관리:
invokeOnCompletion과 finally 블록으로imageProxy정리 - 콜백 처리: 성공 시에만
onTextDetected호출, 실패는 내부에서 로그 처리
제가 제안한 presenter 레벨의 try-catch는 불필요했습니다. LiveTextAnalyzer가 모든 예외를 내부적으로 처리하고 있어서 presenter에서 추가 예외 처리가 필요하지 않습니다.
🏁 Script executed:
#!/bin/bash
# LiveTextAnalyzer의 에러 처리 구현 확인
cat core/ocr/src/main/kotlin/com/ninecraft/booket/core/ocr/analyzer/LiveTextAnalyzer.kt
Length of output: 2755
@seoyoon513, 실제 구현을 확인하니 부분적으로 맞습니다!
LiveTextAnalyzer에서 ML Kit의 에러 처리는 되고 있습니다:
addOnFailureListener로 ML Kit 실패 처리 ✅invokeOnCompletion으로 코루틴 완료/취소 처리 ✅- SupervisorJob으로 프레임별 실패 격리 ✅
하지만 한 가지 문제가 있습니다:
현재 addOnFailureListener에서는 에러를 로그로만 남기고, presenter의 isTextDetectionFailed 상태를 업데이트할 방법이 없습니다.
.addOnFailureListener { exception ->
Logger.e(exception.message ?: "Unknown error") // 로그만 남김
}더 나은 해결책:
- LiveTextAnalyzer 팩토리에 실패 콜백 추가:
val analyzer = liveTextAnalyzer.create(
onTextDetected = { text -> recognizedText = text },
onFailure = { isTextDetectionFailed = true }
)- 또는 StillTextAnalyzer처럼 실패 콜백을 지원하도록 수정
제가 제안한 try-catch는 예외 처리용이 아니라 실패 상태 관리를 위한 것이었는데, 더 좋은 방법은 LiveTextAnalyzer 자체에 실패 콜백을 추가하는 것이겠네요.
✏️ Learnings added
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#72
File: feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrPresenter.kt:70-70
Timestamp: 2025-07-28T18:22:00.590Z
Learning: LiveTextAnalyzer 클래스는 ML Kit 텍스트 인식의 에러 처리를 완전히 내부적으로 처리하며, addOnFailureListener, try-catch, invokeOnCompletion을 통해 모든 예외 상황을 다루므로 presenter 레벨에서 추가 에러 처리가 불필요함
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#72
File: feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrPresenter.kt:70-70
Timestamp: 2025-07-28T18:22:00.590Z
Learning: LiveTextAnalyzer는 ML Kit 에러를 addOnFailureListener로 처리하지만 로그만 남기고 presenter에 실패를 알리지 않아서, UI에서 텍스트 인식 실패 상태를 표시할 수 없는 문제가 있음. StillTextAnalyzer처럼 실패 콜백을 추가하는 것이 더 나은 해결책임
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#46
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/InfiniteLazyColumn.kt:83-95
Timestamp: 2025-07-14T00:46:03.843Z
Learning: seoyoon513과 팀은 한국어 주석을 선호하며, 한국어 주석을 영어로 번역하라는 제안을 하지 않아야 함
There was a problem hiding this comment.
에러 처리는 디테일한 정책 수정이 논의되면 그때 진행할게
There was a problem hiding this comment.
@seoyoon513, 네, 이해했습니다! 현재는 기본 OCR 기능 구현에 집중하고, 에러 처리 정책은 향후 논의 후에 개선하는 것이 좋겠네요.
현재 구현된 LiveTextAnalyzer의 기본적인 에러 처리로도 충분히 동작하고 있으니, 우선은 이대로 진행하시면 될 것 같습니다.
🧠 Learnings used
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#72
File: feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrPresenter.kt:70-70
Timestamp: 2025-07-28T18:22:00.590Z
Learning: LiveTextAnalyzer는 ML Kit 에러를 addOnFailureListener로 처리하지만 로그만 남기고 presenter에 실패를 알리지 않아서, UI에서 텍스트 인식 실패 상태를 표시할 수 없는 문제가 있음. StillTextAnalyzer처럼 실패 콜백을 추가하는 것이 더 나은 해결책임
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#72
File: feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrPresenter.kt:70-70
Timestamp: 2025-07-28T18:22:00.590Z
Learning: LiveTextAnalyzer 클래스는 ML Kit 텍스트 인식의 에러 처리를 완전히 내부적으로 처리하며, addOnFailureListener, try-catch, invokeOnCompletion을 통해 모든 예외 상황을 다루므로 presenter 레벨에서 추가 에러 처리가 불필요함
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#46
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/InfiniteLazyColumn.kt:83-95
Timestamp: 2025-07-14T00:46:03.843Z
Learning: seoyoon513과 팀은 한국어 주석을 선호하며, 한국어 주석을 영어로 번역하라는 제안을 하지 않아야 함
|
still이 정적이라는 의미도 있군여 |
|
토끼가 리뷰를 너무 잘해줘서 일단 토끼가 해준 리뷰들만 다 반영하고 넘어가도 될것같은 +_+ |
…추어 DisposableEffect로 관리하도록 수정
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrPresenter.kt (1)
69-71: ML Kit 분석 작업에 대한 오류 처리가 누락되었습니다.이전 리뷰에서 언급된 것처럼
analyzer.analyze()호출 시 발생할 수 있는 예외에 대한 처리가 여전히 필요합니다.is OcrUiEvent.OnFrameReceived -> { - analyzer.analyze(event.imageProxy) + try { + analyzer.analyze(event.imageProxy) + } catch (e: Exception) { + // 로깅 또는 사용자에게 오류 표시 + isTextDetectionFailed = true + } }
🧹 Nitpick comments (2)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrPresenter.kt (1)
135-148: 한국어 텍스트 처리 개선을 고려해보세요.현재 구현은 기본적인 문장 분리 기능을 제공하지만, 한국어 특성을 고려한 개선이 가능합니다.
fun parseSentences(text: String): List<String> { - val containsPunctuation = text.contains(Regex("[.!?]")) + val containsPunctuation = text.contains(Regex("[.!?。!?]")) return if (containsPunctuation) { text.replace("\n", " ") - .split(Regex("(?<=[.!?])\\s+")) + .split(Regex("(?<=[.!?。!?])\\s*")) .map { it.trim() } .filter { it.isNotEmpty() } } else { text.split("\n") .map { it.trim() } .filter { it.isNotEmpty() } } }한국어 문장부호(。!?)를 추가하고, 공백 처리를 더 유연하게 만들었습니다.
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrUi.kt (1)
144-156: 시스템 UI 상태 관리 개선을 고려해보세요.다크 테마 상태 복원 시 더 정확한 처리가 필요할 수 있습니다.
DisposableEffect(systemUiController) { systemUiController.setSystemBarsColor( color = Neutral950, isNavigationBarContrastEnforced = false, ) onDispose { systemUiController.setSystemBarsColor( - color = White, - darkIcons = !isDarkTheme, + color = if (isDarkTheme) Neutral950 else White, + darkIcons = !isDarkTheme, isNavigationBarContrastEnforced = false, ) } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
core/ocr/src/main/kotlin/com/ninecraft/booket/core/ocr/analyzer/LiveTextAnalyzer.kt(1 hunks)core/ocr/src/main/kotlin/com/ninecraft/booket/core/ocr/analyzer/StillTextAnalyzer.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrPresenter.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrUi.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrUiState.kt(1 hunks)feature/record/src/main/res/values/strings.xml(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- feature/record/src/main/res/values/strings.xml
- feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrUiState.kt
- core/ocr/src/main/kotlin/com/ninecraft/booket/core/ocr/analyzer/LiveTextAnalyzer.kt
- core/ocr/src/main/kotlin/com/ninecraft/booket/core/ocr/analyzer/StillTextAnalyzer.kt
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#46
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/InfiniteLazyColumn.kt:83-95
Timestamp: 2025-07-14T00:46:03.843Z
Learning: seoyoon513과 팀은 한국어 주석을 선호하며, 한국어 주석을 영어로 번역하라는 제안을 하지 않아야 함
🔇 Additional comments (7)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrPresenter.kt (2)
37-43: 성능 최적화가 적용되었습니다!이전 리뷰에서 제기된 매 프레임마다 새로운 analyzer 생성 문제가
rememberRetained를 사용하여 적절히 해결되었습니다.
45-49: 적절한 리소스 정리가 구현되었습니다.
DisposableEffect를 사용하여 analyzer의 생명주기를 올바르게 관리하고 있습니다.feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrUi.kt (5)
70-82: 깔끔한 라우팅 구조입니다.상태에 따른 화면 전환 로직이 명확하고 잘 구현되었습니다.
132-142: 카메라 생명주기 관리가 개선되었습니다!이전 리뷰에서 제기된 카메라 바인딩 문제가
DisposableEffect를 사용하여 적절히 해결되었습니다. 재구성 시 여러 번 바인딩되는 문제가 해결되었습니다.
123-130: 권한 처리 로직이 잘 구현되었습니다.앱 시작 시 권한 상태를 확인하고 필요에 따라 권한 요청을 하는 로직이 적절합니다.
260-337: 텍스트 스캔 결과 화면이 잘 구현되었습니다.문장 선택 기능, 버튼 상태 관리, 다이얼로그 처리가 모두 적절하게 구현되었습니다. LazyColumn 사용으로 성능도 고려되었습니다.
339-361: 프리뷰 컴포저블이 적절히 제공되었습니다.개발 및 디자인 검토를 위한 프리뷰 함수들이 잘 구현되어 있습니다.
# Conflicts: # feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt # feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterUi.kt # feature/record/src/main/res/values/strings.xml
샘플앱에서도 Live, Still 이라는 표현을 썼더라구요! |
easyhooon
left a comment
There was a problem hiding this comment.
일단 이후 API 연동을 위해 approve!
| @Composable | ||
| override fun present(): OcrUiState { | ||
| var currentUi by rememberRetained { mutableStateOf(OcrUi.CAMERA) } | ||
| var hasPermission by rememberRetained { mutableStateOf(false) } |
There was a problem hiding this comment.
이렇게 hasPermission이라는 변수를 통해 권한 허용 여부를 관리하는 경우(메모리 저장방식이나, 디스크 저장방식이나) 실제 OS에서 관리하는 권한 허용 여부와 싱크가 맞지않을 수 있어, 개인적으론 지양하는 방식입니다.
현재 권한 허용 요청 커스텀 팝업이 떠 있는 상태에서, 홈 버튼을 눌러 밖으로 나간 후 설정 화면에가서 카메라 권한을 허용하고 돌아와도, 권한 허용 요청 커스텀 팝업이 닫히지 않는 문제가 발생하는듯함니다.
재현 조건: 문장 스캔을 통해 OCR 화면 진입 -> 카메라 권한 OS 팝업 노출 -> 허용 안함 선택 -> 커스텀 카메라 권한 팝업 노출 -> 홈버튼을 통해 앱 밖으로 나감 -> 설정에서 카메라 권한 허용함 -> 앱으로 다시 진입해도 커스텀 카메라 권한 팝업이 닫히지않음
이후 API 연동하면서 해당 방식 수정해보면 좋을듯하네여.
문제 상황)
https://github.com/user-attachments/assets/ddfe3a73-4fd7-4450-bdb9-f94cefcfa045
재현 조건)
https://github.com/user-attachments/assets/10e08ecd-c472-4929-9378-97f427b44b19
There was a problem hiding this comment.
요 부분 다음번에 같이 수정해보겠습니다!! 재현해주셔서 감사해요 👍
🔗 관련 이슈
📙 작업 설명
🧪 테스트 내역
📸 스크린샷 또는 시연 영상
Reed_OCR_.mp4
💬 추가 설명 or 리뷰 포인트
LiveTextAnalyzer,StillTextAnalyzer각각 라이브 분석, 정적 이미지 분석 객체를 만들었는데 2차 UT 테스트 전까지 정확도가 더 높은 쪽으로 사용하려고 만들어 뒀습니다.Summary by CodeRabbit
신규 기능
UI 개선
문구 및 안내
권한 및 설정
기타