Skip to content

[FIX/#65] 디자인 수정 사항 반영#68

Merged
nhyeonii merged 20 commits intodevelopfrom
fix/#65-calendar-view-design
Jan 18, 2026
Merged

[FIX/#65] 디자인 수정 사항 반영#68
nhyeonii merged 20 commits intodevelopfrom
fix/#65-calendar-view-design

Conversation

@nhyeonii
Copy link
Copy Markdown
Contributor

@nhyeonii nhyeonii commented Jan 15, 2026

Related issue 🛠

Work Description ✏️

  • 카드 상, 하단의 그라데이션을 적용했어요.
  • 엠티뷰 이미지를 추가했어요.

Screenshot 📸

Screen_Recording_20260116_002737_Cherrish.mp4

Uncompleted Tasks 😅

  • N/A

To Reviewers 📢

캘린더 뷰 찐 최종 ~~~

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 절차 일정 카드에 애니메이션 효과가 추가되었습니다.
    • 빈 상태 표시가 개선되었습니다.
  • 개선 사항

    • 절차 목록의 레이아웃 구조가 개선되었습니다.
    • UI 시각화 요소가 최적화되었습니다.

✏️ Tip: You can customize this high-level summary in your review settings.

@nhyeonii nhyeonii self-assigned this Jan 15, 2026
@nhyeonii nhyeonii requested a review from a team as a code owner January 15, 2026 15:32
@nhyeonii nhyeonii added FIX🐛 오류 및 버그 수정 나현🍒 나현 담당 labels Jan 15, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 15, 2026

Walkthrough

사용자 ID를 DataStore에 저장하고 관리하는 TokenManager 인터페이스와 구현체를 추가하고, OkHttp의 AuthInterceptor와 TokenAuthenticator를 통해 요청에 사용자 ID를 자동으로 포함시키고 인증 실패(401) 시 처리하도록 통합한 변경사항입니다.

Changes

Cohort / File(s) 요약
토큰/ID 관리 인터페이스
app/src/main/java/com/cherrish/android/core/local/TokenManager.kt
사용자 ID를 저장, 조회, 삭제하는 3개의 suspend 함수를 정의한 새로운 인터페이스 추가
토큰/ID 관리 구현체
app/src/main/java/com/cherrish/android/core/local/TokenManagerImpl.kt
DataStore 기반의 TokenManager 구현체로, 메모리 캐시와 DataStore를 함께 사용하여 ID 영속성 제공
DataStore 설정 및 모델
app/src/main/java/com/cherrish/android/core/local/constant/DataStoreConstant.kt, app/src/main/java/com/cherrish/android/core/local/model/UserPreferences.kt
DataStore 상수 정의 및 사용자 정보 모델 추가
의존성 주입 모듈
app/src/main/java/com/cherrish/android/core/local/di/DataStoreModule.kt
PreferencesDataStore에서 TokenManager 인터페이스로 전환하고, 명명된 DataStore(userInfoDataStore) 적용
네트워크 인증 계층
app/src/main/java/com/cherrish/android/core/network/AuthInterceptor.kt, app/src/main/java/com/cherrish/android/core/network/TokenAuthenticator.kt, app/src/main/java/com/cherrish/android/core/network/NetworkModule.kt
OkHttp 요청에 X-User-Id 헤더를 추가하는 AuthInterceptor, 401 응답 처리용 TokenAuthenticator, 그리고 이들을 OkHttpClient에 연결하는 NetworkModule 업데이트
UI 컴포넌트
app/src/main/java/com/cherrish/android/presentation/calendar/component/ProcedureScheduleCard.kt
LazyColumn 기반의 스크롤 가능한 구조로 재구성하고, 상하단 그래디언트 애니메이션 추가, 빈 상태에 이미지 추가

Sequence Diagrams

sequenceDiagram
    participant Client as 클라이언트 코드
    participant AuthInt as AuthInterceptor
    participant TokenMgr as TokenManager
    participant DataStore as DataStore
    participant OkHttp as OkHttp Chain
    participant Server as 서버

    Client->>AuthInt: HTTP 요청
    AuthInt->>TokenMgr: getId() (blocking)
    TokenMgr->>DataStore: 캐시 확인 또는 DataStore 읽기
    DataStore-->>TokenMgr: 사용자 ID 반환
    TokenMgr-->>AuthInt: ID 반환
    
    alt ID가 존재하는 경우
        AuthInt->>OkHttp: X-User-Id 헤더 추가된 요청
    else ID가 없는 경우
        AuthInt->>OkHttp: 원본 요청 전달
    end
    
    OkHttp->>Server: 수정된 요청 전송
    Server-->>OkHttp: 응답 (200 또는 401)
    
    alt 401 Unauthorized 응답
        OkHttp->>TokenAuthenticator: 인증 처리 필요
        TokenAuthenticator->>TokenMgr: clearId() (runBlocking)
        TokenMgr->>DataStore: 저장된 ID 삭제
        DataStore-->>TokenMgr: 완료
        TokenMgr-->>TokenAuthenticator: 완료
        TokenAuthenticator-->>OkHttp: null 반환 (재시도 없음)
    end
    
    OkHttp-->>Client: 최종 응답
Loading
sequenceDiagram
    participant App as 애플리케이션
    participant TokenMgr as TokenManagerImpl
    participant Cache as 메모리 캐시
    participant DataStore as DataStore<Preferences>

    App->>TokenMgr: saveId(12345)
    TokenMgr->>Cache: ID 저장
    TokenMgr->>DataStore: 저장 작업 실행
    DataStore-->>TokenMgr: 완료
    
    App->>TokenMgr: getId()
    TokenMgr->>Cache: 캐시 확인
    
    alt 캐시에 존재
        Cache-->>TokenMgr: 12345 반환
    else 캐시에 없음
        TokenMgr->>DataStore: 읽기 작업 실행
        DataStore-->>TokenMgr: 12345 반환
        TokenMgr->>Cache: 캐시 업데이트
    end
    
    TokenMgr-->>App: ID 반환
    
    App->>TokenMgr: clearId()
    TokenMgr->>Cache: 캐시 초기화
    TokenMgr->>DataStore: 키 삭제 작업 실행
    DataStore-->>TokenMgr: 완료
    TokenMgr-->>App: 완료
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 분

Possibly related PRs

Suggested reviewers

  • sohee6989
  • hyeminililo
  • usuuhyn
🚥 Pre-merge checks | ✅ 2 | ❌ 3
❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning PR은 캘린더 뷰 디자인 수정이지만, 실제 코드 변경에는 TokenManager, AuthInterceptor, TokenAuthenticator 등 인증/토큰 관리 기능이 포함되어 있으며, 이는 #65 이슈의 범위를 벗어납니다. TokenManager, AuthInterceptor, TokenAuthenticator 관련 변경사항들은 별도 PR로 분리하거나, 연결된 이슈 범위를 명확히 수정해야 합니다.
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.
Linked Issues check ❓ Inconclusive 연결된 이슈 #65에서 구체적인 코딩 요구사항이 명시되지 않았으며, 체크리스트만 있고 세부 항목이 없어 코드 변경사항의 완전성을 검증하기 어렵습니다. 이슈 #65의 요구사항을 더 구체적으로 정의하거나, PR이 해결하려는 디자인 변경의 구체적 기준을 명확히 하기를 권장합니다.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 변경사항의 핵심을 명확히 반영합니다: 디자인 수정 사항(그라데이션, 이미지 추가)을 반영한 내용이 제목에 잘 표현되어 있습니다.
Description check ✅ Passed PR 설명이 저장소의 템플릿을 따르고 있으며, 관련 이슈, 작업 내용, 스크린샷, 미완료 작업, 검토자 메모가 모두 포함되어 있습니다.

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

✨ Finishing touches
  • 📝 Generate docstrings

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.

@nhyeonii nhyeonii marked this pull request as draft January 15, 2026 15:34
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 Fix all issues with AI agents
In `@app/src/main/java/com/cherrish/android/core/local/model/UserPreferences.kt`:
- Around line 1-5: Remove the unused data class UserPreferences: delete the
UserPreferences declaration (data class UserPreferences) since TokenManagerImpl
uses DataStore<Preferences> with longPreferencesKey("user_id") directly; ensure
no other references to UserPreferences remain and run a project-wide search for
"UserPreferences" to confirm safe removal.

In `@app/src/main/java/com/cherrish/android/core/network/AuthInterceptor.kt`:
- Around line 16-17: Logging the raw user ID via Timber.d("User ID: $id")
exposes PII; update the AuthInterceptor where you call runBlocking {
tokenManager.getId() } and Timber.d to either (1) only log in debug builds by
checking BuildConfig.DEBUG before calling Timber.d, or (2) mask the id (e.g.,
show only last 4 chars or a hash) before logging so the full identifier is never
written to logs; apply the chosen approach consistently where
tokenManager.getId() is used.

In
`@app/src/main/java/com/cherrish/android/data/repositoryimpl/CalendarRepositoryImpl.kt`:
- Around line 18-20: The current use of the non-null assertion data!!.toModel()
inside runCatching risks an NPE and hides a clear error; change the block in
calendarDataSource.getCalendarMonthly to explicitly check response.data and
either map it or throw a clear exception (e.g. val resp =
calendarDataSource.getCalendarMonthly(year, month); val model =
resp.data?.toModel() ?: throw IllegalStateException("getCalendarMonthly returned
null data for year=$year month=$month")) so runCatching surfaces a meaningful
error; apply the same pattern to calendarDataSource.getCalendarDaily and
calendarDataSource.getCalendarEventDowntime, replacing data!!.toModel() with a
null-safe check that throws a descriptive exception when data is null.

In
`@app/src/main/java/com/cherrish/android/presentation/calendar/CalendarViewModel.kt`:
- Around line 36-67: OnDateClick currently launches a coroutine inside
_uiState.updateSuccess (anti-pattern) causing async state races; remove
viewModelScope.launch from inside updateSuccess and perform synchronous state
changes first then start the coroutine. Specifically: in onDateClick, when
current mode is CalendarDisplayMode.Downtime, call _uiState.updateSuccess
synchronously to set selectedDate (and keep currentState or set a temporary
transitional state), then outside that update start viewModelScope.launch to
call calendarRepository.getCalendarDaily(date.toString()) and in its onSuccess
call _uiState.updateSuccess to set calendarDisplayMode to Normal and populate
procedureInfoList (using ProcedureInfoModel and formatProcedureDay as before);
keep loadDailyCalendar usage for the non-downtime branch. Use the same symbols:
onDateClick, _uiState.updateSuccess, viewModelScope.launch,
calendarRepository.getCalendarDaily, loadDailyCalendar, ProcedureInfoModel.
- Around line 79-96: The updateSuccess block in onEventClick must not call the
asynchronous loadDowntimeDetail(procedureId) because that creates a race;
instead, only perform synchronous state transformations inside
_uiState.updateSuccess (set calendarDisplayMode to CalendarDisplayMode.Downtime
with selectedProcedureId or to Normal as before), then after updateSuccess
completes call loadDowntimeDetail(procedureId) from the caller context (e.g.,
launch it in viewModelScope or the existing coroutine scope) so the async work
runs outside the updateSuccess block; reference symbols: onEventClick,
_uiState.updateSuccess, loadDowntimeDetail, CalendarDisplayMode.Downtime,
CalendarDisplayMode.Normal, cachedProcedureCountByDate, selectedProcedureId.
🧹 Nitpick comments (9)
app/src/main/java/com/cherrish/android/presentation/calendar/component/ProcedureScheduleCard.kt (1)

237-241: 접근성(Accessibility) 고려 권장

contentDescription = null은 순수 장식용 이미지에 적합하지만, 이 이미지가 "일정이 없음" 상태를 시각적으로 전달한다면 스크린 리더 사용자를 위해 의미 있는 설명을 추가하는 것이 좋습니다.

♻️ 접근성 개선 제안
 Image(
     painter = painterResource(id = R.drawable.img_calendar_empty_view),
-    contentDescription = null,
+    contentDescription = "일정 없음 이미지",
     modifier = Modifier.padding(8.dp)
 )
app/src/main/java/com/cherrish/android/presentation/calendar/util/CalendarCalculator.kt (1)

8-14: 날짜 파싱 실패 시 예외 처리를 고려하세요.

LocalDateTime.parse(scheduledAt)는 유효하지 않은 형식의 문자열이 들어올 경우 DateTimeParseException을 발생시킵니다. 서버 응답 형식이 항상 ISO-8601을 보장한다면 괜찮지만, 방어적 코딩을 위해 예외 처리나 형식 검증을 추가하는 것을 권장합니다.

♻️ 예외 처리 추가 제안
+import java.time.format.DateTimeParseException
+
 fun formatProcedureDay(scheduledAt: String): String {
-    val dateTime = LocalDateTime.parse(scheduledAt)
+    val dateTime = try {
+        LocalDateTime.parse(scheduledAt)
+    } catch (e: DateTimeParseException) {
+        return scheduledAt // fallback to original string
+    }
     val month = dateTime.month.value
     val day = dateTime.dayOfMonth
     val dayOfWeek = dateTime.dayOfWeek.toKoreanName()
     return "${month}월 ${day}일 $dayOfWeek"
 }
app/src/main/java/com/cherrish/android/presentation/calendar/CalendarUiState.kt (1)

17-18: cachedProcedureCountByDateImmutableMap 사용을 권장합니다.

@Immutable 어노테이션이 적용된 data class에서 procedureInfoListImmutableList를 사용하지만, cachedProcedureCountByDate는 표준 Map을 사용하고 있습니다. Compose의 안정성(stability) 추론과 불필요한 recomposition 방지를 위해 kotlinx.collections.immutable.ImmutableMap을 사용하는 것이 일관성 있습니다.

♻️ 권장 수정안
 import kotlinx.collections.immutable.ImmutableList
+import kotlinx.collections.immutable.ImmutableMap
 import kotlinx.collections.immutable.persistentListOf
+import kotlinx.collections.immutable.persistentMapOf

 `@Immutable`
 data class CalendarUiState(
     val selectedYearMonth: YearMonth = YearMonth.now(),
     val calendarDisplayMode: CalendarDisplayMode = CalendarDisplayMode.Normal(),
     val selectedDate: LocalDate? = LocalDate.now(),
     val procedureInfoList: ImmutableList<ProcedureInfoModel> = persistentListOf(),
-    val cachedProcedureCountByDate: Map<LocalDate, Int> = emptyMap()
+    val cachedProcedureCountByDate: ImmutableMap<LocalDate, Int> = persistentMapOf()
 )
app/src/main/java/com/cherrish/android/core/network/TokenAuthenticator.kt (1)

21-23: runBlocking 사용 시 주의

OkHttp의 authenticate()는 dispatcher 스레드에서 호출되므로 runBlocking 사용이 해당 스레드를 블로킹합니다. 현재 clearId()가 간단한 DataStore 작업이라면 큰 문제는 없지만, 네트워크 호출이 추가되면 데드락 위험이 있습니다.

app/src/main/java/com/cherrish/android/core/local/TokenManagerImpl.kt (1)

25-31: 캐시 업데이트 시 잠재적 race condition

cachedId가 null일 때 여러 코루틴이 동시에 getId()를 호출하면, 모두 DataStore를 읽게 됩니다. 동일 값을 읽으므로 기능적으로는 문제없지만, 불필요한 I/O가 발생할 수 있습니다.

현재 사용 패턴에서 동시 접근이 드물다면 괜찮지만, 빈번한 동시 접근이 예상된다면 Mutex를 사용한 동기화를 고려해보세요.

♻️ Mutex를 사용한 개선 예시
+import kotlinx.coroutines.sync.Mutex
+import kotlinx.coroutines.sync.withLock

 class TokenManagerImpl `@Inject` constructor(
     private val dataStore: DataStore<Preferences>
 ) : TokenManager {

+    private val mutex = Mutex()
+
     `@Volatile`
     private var cachedId: Long? = null

     override suspend fun getId(): Long? {
-        return cachedId ?: dataStore.data.map { preferences ->
-            preferences[KEY_USER_ID]
-        }.first().also {
-            cachedId = it
-        }
+        cachedId?.let { return it }
+        return mutex.withLock {
+            cachedId ?: dataStore.data.map { preferences ->
+                preferences[KEY_USER_ID]
+            }.first().also {
+                cachedId = it
+            }
+        }
     }
app/src/main/java/com/cherrish/android/core/network/AuthInterceptor.kt (1)

15-17: runBlocking 사용에 대한 고려사항

인터셉터에서 runBlocking은 OkHttp의 디스패처 스레드를 차단합니다. 현재 구현은 동작하지만, 고부하 상황에서 스레드 풀 고갈 가능성이 있습니다.

ID를 메모리에 캐싱하거나, @Volatile 변수와 함께 비동기 업데이트 패턴을 고려해볼 수 있습니다.

app/src/main/java/com/cherrish/android/presentation/calendar/component/ProcedureInfoItem.kt (1)

104-128: ProcedureScheduleInfodownTimeDuration 타입이 nullable로 남아있습니다.

ProcedureInfoItem의 공개 파라미터는 Int(Line 33)로 변경되었지만, 내부 컴포저블 ProcedureScheduleInfo의 파라미터는 여전히 Int?(Line 108)입니다. 일관성을 위해 non-nullable Int로 변경하는 것이 좋습니다.

♻️ 제안하는 수정
 `@Composable`
 private fun ProcedureScheduleInfo(
     colors: ProcedureColors,
     procedureDay: String,
-    downTimeDuration: Int?
+    downTimeDuration: Int
 ) {
app/src/main/java/com/cherrish/android/presentation/calendar/CalendarViewModel.kt (2)

125-132: 이벤트를 ProcedureInfoModel로 변환하는 로직이 중복됩니다.

동일한 매핑 로직이 3곳(lines 49-56, 125-132, 149-156)에서 반복되고 있습니다. 확장 함수로 추출하면 유지보수성이 향상됩니다.

♻️ 확장 함수 추출 제안
// CalendarViewModel.kt 또는 별도 매퍼 파일에 추가
private fun List<CalendarDailyEvent>.toProcedureInfoModels() = map { event ->
    ProcedureInfoModel(
        procedureId = event.userProcedureId,
        procedureName = event.name,
        procedureDay = formatProcedureDay(event.scheduledAt),
        downTimeDuration = event.downtimeDays
    )
}.toImmutableList()

사용 예시:

-procedureInfoList = dailyResponse.events.map { event ->
-    ProcedureInfoModel(
-        procedureId = event.userProcedureId,
-        procedureName = event.name,
-        procedureDay = formatProcedureDay(event.scheduledAt),
-        downTimeDuration = event.downtimeDays
-    )
-}.toImmutableList()
+procedureInfoList = dailyResponse.events.toProcedureInfoModels()

Also applies to: 149-156


59-59: 빈 에러 핸들러로 인해 사용자 피드백이 누락됩니다.

모든 .onLogFailure { } 핸들러가 비어있어 네트워크 실패 시 사용자에게 아무런 피드백이 제공되지 않습니다. 로딩 상태가 무한히 지속되거나 이전 데이터가 그대로 표시될 수 있습니다.

최소한 에러 상태를 UI에 반영하거나 토스트/스낵바로 사용자에게 알리는 것을 권장합니다:

.onLogFailure { error ->
    _uiState.update { UiState.Error(error) }
    // 또는 기존 데이터 유지하며 에러 메시지만 표시
}

Also applies to: 138-138, 159-159, 186-186

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6055ae1 and bfa7dba.

⛔ Files ignored due to path filters (1)
  • app/src/main/res/drawable/img_calendar_empty_view.png is excluded by !**/*.png, !**/*.png
📒 Files selected for processing (35)
  • .kotlin/sessions/kotlin-compiler-1697198284998868167.salive
  • app/src/main/java/com/cherrish/android/core/local/TokenManager.kt
  • app/src/main/java/com/cherrish/android/core/local/TokenManagerImpl.kt
  • app/src/main/java/com/cherrish/android/core/local/constant/DataStoreConstant.kt
  • app/src/main/java/com/cherrish/android/core/local/di/DataStoreModule.kt
  • app/src/main/java/com/cherrish/android/core/local/model/UserPreferences.kt
  • app/src/main/java/com/cherrish/android/core/network/AuthInterceptor.kt
  • app/src/main/java/com/cherrish/android/core/network/BaseResponse.kt
  • app/src/main/java/com/cherrish/android/core/network/NetworkModule.kt
  • app/src/main/java/com/cherrish/android/core/network/TokenAuthenticator.kt
  • app/src/main/java/com/cherrish/android/data/di/DataSourceModule.kt
  • app/src/main/java/com/cherrish/android/data/di/RepositoryModule.kt
  • app/src/main/java/com/cherrish/android/data/di/ServiceModule.kt
  • app/src/main/java/com/cherrish/android/data/model/CalendarDailyResponseModel.kt
  • app/src/main/java/com/cherrish/android/data/model/CalendarDownTimeResponseModel.kt
  • app/src/main/java/com/cherrish/android/data/model/CalendarMonthlyRequestModel.kt
  • app/src/main/java/com/cherrish/android/data/model/CalendarMonthlyResponseModel.kt
  • app/src/main/java/com/cherrish/android/data/remote/datasource/CalendarDataSource.kt
  • app/src/main/java/com/cherrish/android/data/remote/datasourceimpl/CalendarDataSourceImpl.kt
  • app/src/main/java/com/cherrish/android/data/remote/dto/request/.gitkeep
  • app/src/main/java/com/cherrish/android/data/remote/dto/request/CalendarDailyRequestDto.kt
  • app/src/main/java/com/cherrish/android/data/remote/dto/request/CalendarMonthlyRequestDto.kt
  • app/src/main/java/com/cherrish/android/data/remote/dto/response/CalendarDailyResponseDto.kt
  • app/src/main/java/com/cherrish/android/data/remote/dto/response/CalendarDownTimeResponseDto.kt
  • app/src/main/java/com/cherrish/android/data/remote/dto/response/CalendarMonthlyResponseDto.kt
  • app/src/main/java/com/cherrish/android/data/remote/service/CalendarService.kt
  • app/src/main/java/com/cherrish/android/data/repository/CalendarRepository.kt
  • app/src/main/java/com/cherrish/android/data/repositoryimpl/CalendarRepositoryImpl.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/CalendarUiState.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/CalendarViewModel.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/component/ProcedureInfoItem.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/component/ProcedureScheduleCard.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/model/ProcedureInfoModel.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/util/CalendarCalculator.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/util/ProcedureUtil.kt
🧰 Additional context used
📓 Path-based instructions (1)
**/*.kt

⚙️ CodeRabbit configuration file

**/*.kt: - Jetpack Compose 구조, 상태 관리, recomposition 최적화에 집중

  • ViewModel, UiState, 단방향 데이터 흐름 패턴 검토
  • 불필요한 recomposition 가능성, remember/derivedStateOf 적절한 사용 확인
  • 네이밍 컨벤션, 가독성, Google 권장 Android 아키텍처 준수 여부

Files:

  • app/src/main/java/com/cherrish/android/core/local/constant/DataStoreConstant.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/model/ProcedureInfoModel.kt
  • app/src/main/java/com/cherrish/android/core/network/BaseResponse.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/util/ProcedureUtil.kt
  • app/src/main/java/com/cherrish/android/data/di/RepositoryModule.kt
  • app/src/main/java/com/cherrish/android/data/remote/dto/response/CalendarDownTimeResponseDto.kt
  • app/src/main/java/com/cherrish/android/data/remote/datasource/CalendarDataSource.kt
  • app/src/main/java/com/cherrish/android/core/network/NetworkModule.kt
  • app/src/main/java/com/cherrish/android/data/model/CalendarMonthlyRequestModel.kt
  • app/src/main/java/com/cherrish/android/core/local/model/UserPreferences.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/util/CalendarCalculator.kt
  • app/src/main/java/com/cherrish/android/core/network/TokenAuthenticator.kt
  • app/src/main/java/com/cherrish/android/data/remote/service/CalendarService.kt
  • app/src/main/java/com/cherrish/android/data/remote/dto/request/CalendarMonthlyRequestDto.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/CalendarUiState.kt
  • app/src/main/java/com/cherrish/android/data/repository/CalendarRepository.kt
  • app/src/main/java/com/cherrish/android/data/remote/datasourceimpl/CalendarDataSourceImpl.kt
  • app/src/main/java/com/cherrish/android/data/remote/dto/response/CalendarMonthlyResponseDto.kt
  • app/src/main/java/com/cherrish/android/core/local/TokenManager.kt
  • app/src/main/java/com/cherrish/android/data/di/DataSourceModule.kt
  • app/src/main/java/com/cherrish/android/core/local/TokenManagerImpl.kt
  • app/src/main/java/com/cherrish/android/data/model/CalendarDailyResponseModel.kt
  • app/src/main/java/com/cherrish/android/data/remote/dto/response/CalendarDailyResponseDto.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/component/ProcedureScheduleCard.kt
  • app/src/main/java/com/cherrish/android/data/di/ServiceModule.kt
  • app/src/main/java/com/cherrish/android/core/network/AuthInterceptor.kt
  • app/src/main/java/com/cherrish/android/data/remote/dto/request/CalendarDailyRequestDto.kt
  • app/src/main/java/com/cherrish/android/data/model/CalendarMonthlyResponseModel.kt
  • app/src/main/java/com/cherrish/android/data/model/CalendarDownTimeResponseModel.kt
  • app/src/main/java/com/cherrish/android/core/local/di/DataStoreModule.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/component/ProcedureInfoItem.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/CalendarViewModel.kt
  • app/src/main/java/com/cherrish/android/data/repositoryimpl/CalendarRepositoryImpl.kt
🧠 Learnings (1)
📚 Learning: 2026-01-12T19:49:27.085Z
Learnt from: nhyeonii
Repo: TEAM-Cherrish/Cherrish-Android PR: 41
File: app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.kt:30-39
Timestamp: 2026-01-12T19:49:27.085Z
Learning: When a Jetpack Compose screen composable receives a Scaffold paddingValues: PaddingValues parameter (commonly from Scaffold), apply it to the root container's modifier first (e.g., .padding(paddingValues)) before applying any additional padding. This ensures content respects system bars (status/navigation) and avoids layout overlap. This pattern should be followed across presentation screens under app/src/main/java/com/cherrish/android/presentation/ to maintain consistent insets handling.

Applied to files:

  • app/src/main/java/com/cherrish/android/presentation/calendar/model/ProcedureInfoModel.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/util/ProcedureUtil.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/util/CalendarCalculator.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/CalendarUiState.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/component/ProcedureScheduleCard.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/component/ProcedureInfoItem.kt
  • app/src/main/java/com/cherrish/android/presentation/calendar/CalendarViewModel.kt
🧬 Code graph analysis (1)
app/src/main/java/com/cherrish/android/presentation/calendar/CalendarViewModel.kt (1)
app/src/main/java/com/cherrish/android/presentation/calendar/util/CalendarCalculator.kt (1)
  • formatProcedureDay (8-14)
⏰ 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). (2)
  • GitHub Check: PR Build Check
  • GitHub Check: PR Lint Check
🔇 Additional comments (35)
app/src/main/java/com/cherrish/android/data/di/RepositoryModule.kt (2)

3-4: LGTM! 패키지 구조가 명확합니다.

인터페이스(repository)와 구현체(repositoryimpl)를 분리한 구조는 Clean Architecture 원칙을 따르고 있습니다.


14-18: LGTM! Hilt DI 바인딩이 올바르게 구성되었습니다.

@Binds@Singleton 조합이 적절하며, CalendarRepository 인터페이스를 통한 의존성 주입이 정상적으로 동작할 것입니다.

app/src/main/java/com/cherrish/android/presentation/calendar/component/ProcedureScheduleCard.kt (3)

3-3: LGTM!

EmptyCardView에서 새로 추가된 Image 컴포저블에 필요한 import입니다.

Also applies to: 28-28


52-63: 스크롤 상태 감지 로직 개선 확인

canScrollBackwardcanScrollForward를 활용한 로직이 그라데이션 오버레이 표시 조건을 더 정확하게 판단합니다. derivedStateOfremember로 감싼 패턴은 recomposition 최적화에 적합합니다.


84-84: 디자인 수정 반영 확인

EmptyCardView의 상단 패딩이 64.dp에서 50.dp로 조정되었습니다.

app/src/main/java/com/cherrish/android/presentation/calendar/util/CalendarCalculator.kt (1)

16-24: LGTM!

when 표현식을 사용하여 모든 DayOfWeek 케이스를 exhaustive하게 처리하고 있으며, 한국어 요일 이름 매핑이 명확합니다.

app/src/main/java/com/cherrish/android/core/local/TokenManager.kt (1)

3-7: 인터페이스 설계가 적절합니다.

간결하고 명확한 인터페이스 설계입니다. suspend 함수 사용으로 DataStore의 비동기 특성을 잘 반영하고 있습니다.

다만, 인터페이스 이름이 TokenManager인데 메서드들은 Id를 다루고 있어 약간의 불일치가 있습니다. 향후 실제 토큰(access token, refresh token 등)도 관리할 계획이라면 현재 이름이 적절하고, 그렇지 않다면 UserIdManager 같은 이름이 더 명확할 수 있습니다.

app/src/main/java/com/cherrish/android/data/remote/dto/response/CalendarDownTimeResponseDto.kt (1)

6-20: LGTM!

DTO 구조가 깔끔하고 kotlinx.serialization 규칙을 잘 따르고 있습니다. 모든 필드에 @SerialName 어노테이션을 명시적으로 지정하여 JSON 키 매핑이 명확합니다.

app/src/main/java/com/cherrish/android/data/remote/dto/response/CalendarMonthlyResponseDto.kt (1)

6-10: LGTM!

단일 필드를 가진 간결한 DTO입니다. Map<Int, Long> 타입은 일별 시술 개수를 표현하기에 적절하며, kotlinx.serialization이 Map 직렬화를 지원합니다.

app/src/main/java/com/cherrish/android/core/network/BaseResponse.kt (1)

8-9: BaseResponse.code 필드 타입이 새로 정의되었으므로, 추가 검토가 필요합니다.

code 필드가 새로 생성된 BaseResponse 클래스에서 String 타입으로 정의되었습니다. 현재 코드베이스에서 code 필드를 직접 사용하는 부분이 없으므로, 현재로서는 호환성 문제가 없습니다. 다만 향후 이 필드를 사용할 때 String 타입에 맞게 처리되는지 확인이 필요합니다. API 응답 스펙에서 실제로 code가 문자열 형식인지 확인하시기 바랍니다.

app/src/main/java/com/cherrish/android/data/model/CalendarMonthlyResponseModel.kt (1)

5-11: LGTM!

DTO와 도메인 모델을 분리하고 mapper extension function을 사용한 구조가 깔끔합니다. 데이터 레이어와 프레젠테이션 레이어 간의 명확한 경계를 유지하는 좋은 패턴입니다.

app/src/main/java/com/cherrish/android/presentation/calendar/util/ProcedureUtil.kt (1)

47-66: LGTM!

downTimeDuration을 nullable(Int?)에서 non-null(Int)로 변경하고, null 체크 대신 == 0 체크를 사용한 것은 더 명확한 설계입니다. "다운타임 없음"을 0으로 표현하는 것이 null보다 의미가 명확하고, 관련 모델(ProcedureInfoModel)과의 일관성도 유지됩니다.

app/src/main/java/com/cherrish/android/data/di/ServiceModule.kt (1)

14-18: LGTM!

Hilt DI 모듈에서 DummyServiceCalendarService로 교체한 것이 적절합니다. @Singleton 스코프와 Retrofit 서비스 생성 패턴이 올바르게 적용되었습니다.

app/src/main/java/com/cherrish/android/data/remote/dto/request/CalendarDailyRequestDto.kt (1)

6-10: LGTM!

kotlinx.serialization을 사용한 깔끔한 DTO 정의입니다. CalendarMonthlyRequestDto와 일관된 패턴을 따르고 있습니다.

app/src/main/java/com/cherrish/android/core/network/TokenAuthenticator.kt (1)

18-26: 토큰 갱신 로직 없이 ID만 삭제하고 null 반환

현재 구현은 401 응답 시 clearId()만 호출하고 null을 반환하여 재시도하지 않습니다. 일반적인 Authenticator 패턴은 토큰을 갱신한 후 새 토큰으로 요청을 재시도합니다.

의도된 동작이라면 괜찮지만, 토큰 갱신 후 재시도가 필요하다면 추가 구현이 필요합니다.

app/src/main/java/com/cherrish/android/data/model/CalendarDownTimeResponseModel.kt (1)

5-21: LGTM!

DTO에서 Model로의 매핑 패턴이 깔끔하게 구현되었습니다. 확장 함수를 사용한 변환은 Kotlin의 관용적인 패턴입니다.

app/src/main/java/com/cherrish/android/data/remote/datasource/CalendarDataSource.kt (1)

8-12: LGTM!

인터페이스 설계가 깔끔합니다. suspend 함수를 사용한 비동기 처리와 BaseResponse 래퍼를 통한 일관된 응답 처리가 잘 구현되었습니다.

app/src/main/java/com/cherrish/android/data/remote/dto/response/CalendarDailyResponseDto.kt (1)

6-28: LGTM!

DTO 구조가 깔끔하게 정의되었습니다. @Serializable 어노테이션과 중첩 데이터 클래스 사용이 적절합니다.

참고: @SerialName이 프로퍼티명과 동일한 경우 생략 가능하지만, 명시적으로 작성하는 것도 API 계약을 명확히 하는 좋은 방법입니다.

app/src/main/java/com/cherrish/android/data/remote/datasourceimpl/CalendarDataSourceImpl.kt (1)

11-29: LGTM!

CalendarDataSource 인터페이스의 구현이 깔끔합니다. CalendarService로의 위임 패턴을 사용하여 테스트 용이성과 관심사 분리가 잘 되어 있습니다.

app/src/main/java/com/cherrish/android/data/di/DataSourceModule.kt (1)

14-18: LGTM!

Hilt의 @Binds 패턴을 올바르게 사용하여 CalendarDataSource 바인딩을 구성했습니다. DummyDataSource에서 실제 CalendarDataSource로의 전환이 깔끔합니다.

app/src/main/java/com/cherrish/android/data/model/CalendarDailyResponseModel.kt (2)

6-18: LGTM!

데이터 모델 정의가 명확하고, DTO와 Model 계층 분리가 잘 되어 있습니다.


20-23: 널 안전성 우려 해소됨

CalendarDailyResponseDtoevents 필드는 List<EventDto>로 정의되어 있어 비-널러블(non-nullable)입니다. 따라서 this.events.map() 호출은 안전하며 NPE 위험이 없습니다.

Likely an incorrect or invalid review comment.

app/src/main/java/com/cherrish/android/data/repository/CalendarRepository.kt (1)

7-20: LGTM!

Repository 인터페이스 설계가 깔끔합니다. Result<T> 반환 타입으로 일관된 에러 처리가 가능하고, suspend 함수를 통한 비동기 처리가 적절합니다.

app/src/main/java/com/cherrish/android/core/local/TokenManagerImpl.kt (1)

11-23: LGTM!

DataStore와 인메모리 캐시를 조합한 TokenManager 구현이 적절합니다. @Volatile 어노테이션으로 기본적인 가시성을 보장하고, DataStore를 통한 영속성도 잘 처리되어 있습니다.

app/src/main/java/com/cherrish/android/core/local/di/DataStoreModule.kt (1)

17-36: LGTM!

DataStoreModule DI 구성이 깔끔합니다. preferencesDataStore delegate를 사용한 DataStore 생성과 TokenManager 추상화를 통한 의존성 주입이 잘 구성되어 있습니다.

app/src/main/java/com/cherrish/android/core/local/constant/DataStoreConstant.kt (1)

1-5: LGTM!

DataStore 이름을 상수로 깔끔하게 정의했습니다. 중앙 집중식 상수 관리로 유지보수성이 좋습니다.

app/src/main/java/com/cherrish/android/core/network/NetworkModule.kt (1)

69-71: 인터셉터 순서 검토 필요

현재 loggingInterceptorauthInterceptor 전에 추가되어 있어, 인증 헤더(X-User-Id)가 로그에 기록되지 않습니다.

만약 디버깅 목적으로 인증 헤더도 로깅하려면 순서를 바꿔야 하고, 보안상 헤더를 로깅하지 않으려면 현재 순서가 맞습니다. 의도한 동작인지 확인해 주세요.

app/src/main/java/com/cherrish/android/presentation/calendar/model/ProcedureInfoModel.kt (1)

5-11: LGTM!

@Immutable 어노테이션이 적절히 적용되어 Compose의 안정성(stability)을 보장합니다. downTimeDuration을 non-nullable로 변경한 것이 관련 UI 컴포넌트들(ProcedureInfoItem, ProcedureUtil)과 일관성 있게 정렬되어 있습니다.

app/src/main/java/com/cherrish/android/data/remote/dto/request/CalendarMonthlyRequestDto.kt (1)

6-12: LGTM!

kotlinx.serialization을 사용한 깔끔한 DTO 구현입니다. @SerialName 어노테이션으로 JSON 필드명을 명시적으로 지정한 것이 유지보수성에 좋습니다.

app/src/main/java/com/cherrish/android/data/model/CalendarMonthlyRequestModel.kt (1)

5-13: LGTM!

데이터 레이어에서 모델과 DTO를 분리하고 extension function으로 매핑하는 패턴이 적절합니다. 단방향 데이터 변환이 명확하게 구현되어 있습니다.

app/src/main/java/com/cherrish/android/presentation/calendar/component/ProcedureInfoItem.kt (1)

29-75: 조건부 클릭 로직이 잘 구현되어 있습니다.

remember를 사용한 색상 메모이제이션과 Modifier.then()을 활용한 조건부 클릭 가능 modifier 적용이 적절합니다. downTimeDuration이 0일 때 클릭을 비활성화하는 로직이 명확합니다.

app/src/main/java/com/cherrish/android/data/remote/service/CalendarService.kt (1)

11-27: LGTM!

Retrofit 서비스 인터페이스가 잘 구현되어 있습니다. suspend 함수 사용으로 코루틴 지원이 적절하고, BaseResponse 래퍼를 통한 일관된 응답 처리 패턴이 좋습니다. getCalendarDailydate 파라미터는 LocalDate.toString()으로 ISO-8601 형식(yyyy-MM-dd)으로 전달되므로 표준 포맷이 이미 적용되어 있습니다.

app/src/main/java/com/cherrish/android/presentation/calendar/CalendarViewModel.kt (3)

25-34: LGTM! ViewModel 설정 및 초기화가 올바릅니다.

Hilt를 통한 의존성 주입과 UiState.Loading 초기 상태 설정이 적절합니다. init 블록에서 초기 데이터 로드를 트리거하는 패턴도 권장되는 방식입니다.


69-77: LGTM! 월 변경 로직이 명확합니다.

현재 월이면 오늘 날짜를, 아니면 해당 월의 1일을 선택하는 로직이 적절합니다.


163-188: 동일 날짜가 여러 상태 목록에 존재할 경우 덮어쓰기 동작 확인 필요

buildMap에서 sensitiveDayscautionDaysrecoveryDays 순서로 처리되므로, 동일 날짜가 여러 목록에 있으면 마지막 상태(RECOVERY)만 유지됩니다. 이것이 의도된 우선순위인지 확인이 필요합니다.

서버 응답에서 날짜 중복이 발생하지 않는다면 문제없지만, 비즈니스 로직상 우선순위가 다르다면(예: SENSITIVE가 최우선) 처리 순서를 변경하거나 중복 체크 로직을 추가해야 합니다.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread app/src/main/java/com/cherrish/android/presentation/calendar/CalendarViewModel.kt Outdated
Copy link
Copy Markdown
Contributor

@sohee6989 sohee6989 left a comment

Choose a reason for hiding this comment

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

수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!
수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!수고하셨습니다!!!!!!!!!!!!!!!!!!!

procedureDay = procedure.procedureDay,
downTimeDuration = procedure.downTimeDuration,
procedureType = getProcedureType(
displayMode,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

p3: 파라미터명 써주시면 가독성이 좀 더 좋을 것 같습니다~!!
싫으시면 어쩔수없구요ㅜ

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

image

@nhyeonii nhyeonii marked this pull request as ready for review January 17, 2026 18:09
@nhyeonii nhyeonii merged commit 9b58c70 into develop Jan 18, 2026
3 checks passed
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.

[FIX] 디자인 수정 사항 반영

2 participants