Skip to content

[Feat] Profile 프로필 관련 API 연동#145

Merged
nahy-512 merged 18 commits into
developfrom
feat/#134-profilescreen-logic-and-api
Jan 20, 2026
Merged

[Feat] Profile 프로필 관련 API 연동#145
nahy-512 merged 18 commits into
developfrom
feat/#134-profilescreen-logic-and-api

Conversation

@nahy-512

@nahy-512 nahy-512 commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

📮 관련 이슈

📌 작업 내용

  • 프로필 취향 키워드 UI 이슈 고쳤어요.
  • 프로필 정보, 취향 키워드 API 연동했어요.

📸 스크린샷

프로필 API 연동

[취향 키워드]
image

😅 미구현

  • userId 하드코딩 제거
  • 내 프로필/타인 프로필 구분
  • 로딩 상태 관리

🫛 To. 리뷰어

Summary by CodeRabbit

  • 새로운 기능

    • 사용자 프로필 조회 기능 추가 — 프로필 이미지/닉네임/Fliner 상태 표시 가능
    • 프로필 키워드 새 그리드 레이아웃과 별도 새로고침 버튼 UI 추가
  • 개선사항

    • 프로필 화면 진입 시 자동 데이터 로드 및 동시 조회로 응답성 개선
    • 키워드 배열 로직 개선으로 표시 안정성 향상
    • 디자인 시스템에 그라디언트 색상 추가 및 프로필 헤더에 적용

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

nahy-512 and others added 16 commits January 20, 2026 03:14
- `Brush.linearGradient` 대신 `ShaderBrush`와 `LinearGradientShader`를 사용하여 정교한 그라데이션 좌표(Offset) 적용
- gradient900, gradient700, gradient400 색상에 대한 그라데이션 시작/끝 지점 커스텀 구현
… feat/#134-profilescreen-logic-and-api

# Conflicts:
#	app/src/main/java/com/flint/core/designsystem/component/listItem/CollectionItem.kt
#	app/src/main/java/com/flint/core/designsystem/component/listItem/SavedContentItem.kt
#	app/src/main/java/com/flint/core/designsystem/component/listView/SavedContentsSection.kt
#	app/src/main/java/com/flint/data/dto/content/response/BookmarkedContentListResponseDto.kt
#	app/src/main/java/com/flint/domain/mapper/collection/CollectionMapper.kt
#	app/src/main/java/com/flint/domain/mapper/content/ContentMapper.kt
#	app/src/main/java/com/flint/domain/repository/CollectionRepository.kt
#	app/src/main/java/com/flint/domain/repository/ContentRepository.kt
#	app/src/main/java/com/flint/domain/repository/HomeRepository.kt
#	app/src/main/java/com/flint/presentation/home/HomeScreen.kt
#	app/src/main/java/com/flint/presentation/home/HomeViewModel.kt
#	app/src/main/java/com/flint/presentation/profile/ProfileUiState.kt
@nahy-512 nahy-512 self-assigned this Jan 20, 2026
@nahy-512 nahy-512 requested a review from a team as a code owner January 20, 2026 18:48
@nahy-512 nahy-512 added 🔖 API feat - API 연동 Feat ✨ 신규 기능을 추가하거나 기존 기능의 동작, 정책을 변경 labels Jan 20, 2026
@nahy-512 nahy-512 linked an issue Jan 20, 2026 that may be closed by this pull request
4 tasks
@coderabbitai

coderabbitai Bot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

프로필 조회 API(getUserProfile)와 DTO/모델/매퍼 추가, UserRepository와 ProfileViewModel에 프로필 로드 로직 추가, ProfileScreen·ProfileKeywordSection·ProfileUiState·디자인 시스템 색상(gradient) 및 일부 UI 수식 변경을 포함한 리팩토링입니다.

Changes

Cohort / File(s) 변경 요약
API
app/src/main/java/com/flint/data/api/UserApi.kt
@GET("/api/v1/users/{userId}") suspend fun getUserProfile(userId: String): BaseResponse<UserProfileResponseDto> 추가
DTO
app/src/main/java/com/flint/data/dto/user/response/UserProfileResponseDto.kt
@Serializable 데이터 클래스 UserProfileResponseDto(id, profileImageUrl, isFliner, nickname) 추가
도메인 모델 & 매퍼
app/src/main/java/com/flint/domain/model/user/UserProfileResponseModel.kt
app/src/main/java/com/flint/domain/mapper/user/ProfileMapper.kt
UserProfileResponseModel 추가(Empty, Fake 포함) 및 UserProfileResponseDto.toModel() 매퍼 추가
리포지토리
app/src/main/java/com/flint/domain/repository/UserRepository.kt
@Inject 생성자 도입, myTempUserId 폴백 추가, suspend fun getUserProfile(userId: String?)getUserKeywords(userId: String?) 추가(에러 처리: suspendRunCatching)
뷰모델
app/src/main/java/com/flint/presentation/profile/ProfileViewModel.kt
getProfile() 공개 함수 추가; profile/keywords 동시 fetch 및 ProfileUiState 생성·발행 로직 추가
UI 상태
app/src/main/java/com/flint/presentation/profile/uistate/ProfileUiState.kt
패키지 변경(profile → profile.uistate), profile 타입을 AuthorModel에서 UserProfileResponseModel로 변경 및 Empty/Fake 초기값 갱신
프로필 화면
app/src/main/java/com/flint/presentation/profile/ProfileScreen.kt
컴포지션 시 viewModel.getProfile() 호출 추가(LaunchedEffect), onRefreshClick: () -> Unit = {} 파라미터 도입, profileUrlprofileImageUrl로 바인딩 변경, UserRoleType 제거
키워드 섹션
app/src/main/java/com/flint/presentation/profile/component/ProfileKeywordSection.kt
KeywordChipsLayout/rotateKeywordByRank 제거, KeywordChipsGridLayout, arrangeKeywordsByRank, ProfileRefreshButton 등 그리드 기반 배치로 재구성; 프리뷰 데이터 변경(FakeList3 포함)
샘플 키워드 데이터
app/src/main/java/com/flint/domain/model/user/UserKeywordResponseModel.kt
FakeList1 내용 변경 및 FakeList2, FakeList3 신규 추가
컬렉션 아이템 UI
app/src/main/java/com/flint/presentation/collectionlist/component/CollectionFileItem.kt
이미지 modifier 체인에서 rotate/offset을 dropShadow 이전으로 이동하고 중복 변환 제거
디자인 시스템
app/src/main/java/com/flint/core/designsystem/theme/Color.kt
Colors에 myGradient: Brush 추가 및 FlintColors에 수직 그라디언트 초기화
프로필 상단 섹션
app/src/main/java/com/flint/presentation/profile/component/ProfileTopSection.kt
로컬 gradient 제거 후 FlintTheme.colors.myGradient 사용으로 스타일링 변경

Sequence Diagram(s)

sequenceDiagram
    participant UI as ProfileScreen (UI)
    participant VM as ProfileViewModel (ViewModel)
    participant Repo as UserRepository (Repository)
    participant API as UserApi (API)
    participant Server as Backend

    UI->>VM: getProfile()
    activate VM
    VM->>Repo: getUserProfile(userId)
    VM->>Repo: getUserKeywords(userId)
    activate Repo

    par Parallel Fetch
        Repo->>API: getUserProfile()
        activate API
        API->>Server: GET /api/v1/users/{userId}
        Server-->>API: UserProfileResponseDto
        API-->>Repo: BaseResponse<UserProfileResponseDto>
        deactivate API
    and
        Repo->>API: getUserKeywords()
        activate API
        API->>Server: GET /api/v1/users/{userId}/keywords
        Server-->>API: UserKeywordResponseDto[]
        API-->>Repo: BaseResponse<List<...>>
        deactivate API
    end

    Repo-->>VM: Result<UserProfileResponseModel>, Result<List<UserKeywordResponseModel>>
    deactivate Repo

    VM->>UI: emit UiState.Success(ProfileUiState)
    deactivate VM
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • #134: 프로필 조회 API 연동 및 키워드 UI 변경 요구사항과 직접적으로 일치 — getUserProfile/리포지토리/뷰모델/프로필 UI 변경을 포함함.

Possibly related PRs

  • #114: Profile UI(화면·뷰모델·모델) 변경과 중첩되는 수정 지점 존재.
  • #104: Colors 데이터 구조에 Brush 속성 추가 관련 변경이 중복됨.
  • #135: UserApi/DTO/매퍼/리포지토리 영역의 유사 변경사항 존재.

Suggested reviewers

  • giovannijunseokim
  • kimjw2003

시 🐰

새 프로필 불러왔네, 당근 대신 API로 🥕
칩들이 그리드에서 리듬을 타네 🎶
DTO가 모델로 발돋움해 춤추고 🐇
리포지토리와 뷰모델이 손잡네 🤝
코드 밭에 봄이 왔구나, 껑충!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 PR의 주요 변경사항을 명확하게 요약하고 있습니다. 프로필 관련 API 연동이라는 핵심 기능을 정확하게 나타냅니다.
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.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@app/src/main/java/com/flint/presentation/profile/ProfileViewModel.kt`:
- Line 39: Remove the stray unused construction Pair(profileResult.getOrThrow(),
keywordsResult.getOrThrow()) and instead use the already-evaluated results when
building/returning the combined value in ProfileViewModel (e.g., reuse the local
variables or assign profileResult.getOrThrow() and keywordsResult.getOrThrow()
to locals once and create the Pair from those locals); update the code paths
that currently call getOrThrow() again (lines using profileResult and
keywordsResult) to reference the stored values so getOrThrow() is invoked only
where the result is actually used.
- Around line 49-52: 현재 ProfileViewModel의 흐름에서 }.onSuccess { combinedState ->
_uiState.update { UiState.Success(combinedState) } } 부분에 onFailure 처리가 빠져 있어 API
오류 시 상태가 업데이트되지 않습니다; 해당 체인(ProfileViewModel 내의 해당 flow 콜) 바로 뒤에 onFailure {
throwable -> _uiState.update { UiState.Error(/* 적절한 오류 메시지 또는 throwable */) } }
를 추가해 실패 케이스를 UiState의 에러 상태로 전파하고, 필요하면 throwable을 사용자용 문자열로 변환하거나 로그에 남기도록
처리하세요.
🧹 Nitpick comments (3)
app/src/main/java/com/flint/domain/model/user/UserKeywordResponseModel.kt (1)

66-84: FakeList2/3의 인덱스 의존을 방어적으로 처리하는 편이 안전합니다.

FakeList1의 항목 수나 순서가 바뀌면 초기화 시 IndexOutOfBounds가 날 수 있어요. 최소한 getOrNull 기반으로 구성하거나 take(6)로 전제 조건을 명시해 주세요.

🔧 예시 변경안
-        val FakeList2: ImmutableList<UserKeywordResponseModel> =
-            persistentListOf(
-                FakeList1[0],
-                FakeList1[1],
-                FakeList1[2],
-                FakeList1[3].copy(name = "키워드"),
-                FakeList1[4].copy(name = "설레는"),
-                FakeList1[5].copy(name = "키워드"),
-            )
+        val FakeList2: ImmutableList<UserKeywordResponseModel> =
+            listOfNotNull(
+                FakeList1.getOrNull(0),
+                FakeList1.getOrNull(1),
+                FakeList1.getOrNull(2),
+                FakeList1.getOrNull(3)?.copy(name = "키워드"),
+                FakeList1.getOrNull(4)?.copy(name = "설레는"),
+                FakeList1.getOrNull(5)?.copy(name = "키워드"),
+            ).toPersistentList()
app/src/main/java/com/flint/presentation/profile/component/ProfileKeywordSection.kt (2)

71-95: ProfileRefreshButton이 현재 미사용입니다.

리프레시 UI가 의도된 기능이면 헤더에 배치하고, 아니라면 버튼과 onRefreshClick 파라미터를 정리해 주세요.


158-181: 키워드 6개 초과 입력 시 처리 의도를 명시하는 게 좋습니다.

현재 로직은 6개 초과 시 상위 6개만 사실상 사용됩니다. 의도가 맞다면 take(6)로 가정을 명시해 주세요.

🔧 예시 변경안
-    val sortedByRank = keywordList.sortedBy { it.rank }
+    val sortedByRank = keywordList.sortedBy { it.rank }.take(6)

// 프로필/컬렉션/작품 목록 등 설정 필요한 초기 데이터 로드 필요
}
}
Pair(profileResult.getOrThrow(), keywordsResult.getOrThrow())

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.

⚠️ Potential issue | 🟡 Minor

사용되지 않는 코드 제거 필요

Pair(profileResult.getOrThrow(), keywordsResult.getOrThrow()) 결과가 변수에 할당되지 않고 버려지고 있습니다. 이 줄은 불필요하며, 라인 42-43에서 동일한 getOrThrow() 호출이 다시 수행됩니다.

🐛 수정 제안
                 val profileResult = profileDeferred.await()
                 val keywordsResult = keywordsDeferred.await()

-                Pair(profileResult.getOrThrow(), keywordsResult.getOrThrow())
-
                 ProfileUiState(
                     profile = profileResult.getOrThrow(),
📝 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.

Suggested change
Pair(profileResult.getOrThrow(), keywordsResult.getOrThrow())
val profileResult = profileDeferred.await()
val keywordsResult = keywordsDeferred.await()
ProfileUiState(
profile = profileResult.getOrThrow(),
🤖 Prompt for AI Agents
In `@app/src/main/java/com/flint/presentation/profile/ProfileViewModel.kt` at line
39, Remove the stray unused construction Pair(profileResult.getOrThrow(),
keywordsResult.getOrThrow()) and instead use the already-evaluated results when
building/returning the combined value in ProfileViewModel (e.g., reuse the local
variables or assign profileResult.getOrThrow() and keywordsResult.getOrThrow()
to locals once and create the Pair from those locals); update the code paths
that currently call getOrThrow() again (lines using profileResult and
keywordsResult) to reference the stored values so getOrThrow() is invoked only
where the result is actually used.

Comment on lines +49 to 52
}.onSuccess { combinedState ->
_uiState.update { UiState.Success(combinedState) }
}
}

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.

⚠️ Potential issue | 🟠 Major

에러 처리 누락

onFailure 처리가 없어서 API 호출 실패 시 사용자에게 에러 피드백이 전달되지 않고 UiState.Empty 상태로 유지됩니다. PR 목표에 로딩 상태 관리가 남은 작업으로 명시되어 있지만, 에러 상태 처리도 함께 추가하는 것이 좋습니다.

🐛 에러 처리 추가 제안
             }.onSuccess { combinedState ->
                 _uiState.update { UiState.Success(combinedState) }
+            }.onFailure { exception ->
+                _uiState.update { UiState.Error(exception) }
             }
🤖 Prompt for AI Agents
In `@app/src/main/java/com/flint/presentation/profile/ProfileViewModel.kt` around
lines 49 - 52, 현재 ProfileViewModel의 흐름에서 }.onSuccess { combinedState ->
_uiState.update { UiState.Success(combinedState) } } 부분에 onFailure 처리가 빠져 있어 API
오류 시 상태가 업데이트되지 않습니다; 해당 체인(ProfileViewModel 내의 해당 flow 콜) 바로 뒤에 onFailure {
throwable -> _uiState.update { UiState.Error(/* 적절한 오류 메시지 또는 throwable */) } }
를 추가해 실패 케이스를 UiState의 에러 상태로 전파하고, 필요하면 throwable을 사용자용 문자열로 변환하거나 로그에 남기도록
처리하세요.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In
`@app/src/main/java/com/flint/presentation/profile/component/ProfileKeywordSection.kt`:
- Around line 73-97: ProfileRefreshButton is implemented but never used in
ProfileKeywordSection, so the onRefreshClick handler is never invoked; open the
ProfileKeywordSection composable and add a call to ProfileRefreshButton (passing
the existing onRefreshClick lambda) into the top Row (the section header Row
that contains the title/actions) so the refresh control is visible and
interactive; ensure you import/use the same modifier and alignment conventions
as the Row and remove any conflicting click handlers so ProfileRefreshButton
receives clicks.
- Around line 160-183: arrangeKeywordsByRank currently discards keywords beyond
the first 6; preserve extras by applying the special 6-item reordering only to
the top-six and appending any remaining items after that. Concretely, inside
arrangeKeywordsByRank use sortedByRank.take(6) (or similar) to build the
reordered block using threeRowOrder/twoRowOrder, then append
sortedByRank.drop(6) to the resulting list before converting toPersistentList
and returning; ensure shouldUseThreeRows is still computed from the top-six
(e.g., checkTargets from the taken list) and keep the existing row-count return
value logic or make it dynamic as needed.

Comment on lines +73 to +97
private fun ProfileRefreshButton(
onRefreshClick: () -> Unit,
modifier: Modifier = Modifier,
) {
Box(
contentAlignment = Alignment.Center,
Column(
verticalArrangement = Arrangement.spacedBy(4.dp),
horizontalAlignment = Alignment.CenterHorizontally,
modifier =
modifier
.fillMaxWidth(),
.noRippleClickable(
onClick = onRefreshClick,
),
) {
FlowRow(
horizontalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterHorizontally),
verticalArrangement = Arrangement.spacedBy(12.dp),
itemVerticalAlignment = Alignment.CenterVertically,
maxItemsInEachRow = 3,
modifier =
Modifier
.align(Alignment.Center),
) {
keywordList.forEach {
with(it) {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_refresh),
contentDescription = null,
tint = FlintTheme.colors.secondary400,
)
Text(
text = "업데이트",
style = FlintTheme.typography.micro1M10,
color = FlintTheme.colors.gray100,
)
}
}

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.

⚠️ Potential issue | 🟠 Major

리프레시 버튼이 실제 UI에 연결되지 않아 동작이 막힙니다.
ProfileRefreshButton가 정의됐지만 ProfileKeywordSection에서 호출되지 않아 onRefreshClick이 죽어 있습니다. 의도된 기능이면 상단 Row에 배치해 동작을 복원하세요.

🛠️ 연결 예시
         Row(
             verticalAlignment = Alignment.CenterVertically,
             horizontalArrangement = Arrangement.SpaceBetween,
             modifier = Modifier.fillMaxWidth(),
         ) {
             Column {
                 Text(
                     text = "${nickname}님의 취향키워드",
                     style = FlintTheme.typography.head3Sb18,
                     color = FlintTheme.colors.white,
                 )
                 Spacer(Modifier.height(4.dp))
                 Text(
                     text = "${nickname}님이 관심있어하는 키워드에요",
                     style = FlintTheme.typography.body2R14,
                     color = FlintTheme.colors.gray100,
                 )
             }
+            ProfileRefreshButton(
+                onRefreshClick = onRefreshClick,
+            )
         }
🤖 Prompt for AI Agents
In
`@app/src/main/java/com/flint/presentation/profile/component/ProfileKeywordSection.kt`
around lines 73 - 97, ProfileRefreshButton is implemented but never used in
ProfileKeywordSection, so the onRefreshClick handler is never invoked; open the
ProfileKeywordSection composable and add a call to ProfileRefreshButton (passing
the existing onRefreshClick lambda) into the top Row (the section header Row
that contains the title/actions) so the refresh control is visible and
interactive; ensure you import/use the same modifier and alignment conventions
as the Row and remove any conflicting click handlers so ProfileRefreshButton
receives clicks.

Comment on lines +160 to +183
private fun arrangeKeywordsByRank(
keywordList: ImmutableList<UserKeywordResponseModel>
): Pair<ImmutableList<UserKeywordResponseModel>, Int> {
if (keywordList.size < 6) return keywordList to 3

val sortedByRank = keywordList.sortedBy { it.rank }

// rank 1, 2, 3 (상위 3개) → Large
val topRanks = sortedByRank.take(3)
// rank 4, 5, 6 (하위 3개) → Small
val bottomRanks = sortedByRank.drop(3)
val checkTargets = listOf(
sortedByRank[0], // rank 1
sortedByRank[1], // rank 2
sortedByRank[3], // rank 4
)

// 번갈아 배치: 1, 4, 2, 5, 3, 6
return topRanks
.zip(bottomRanks)
.flatMap { (top, bottom) -> listOf(top, bottom) }
.toPersistentList()
val shouldUseThreeRows = checkTargets.any { it.name.length >= 3 }

return if (shouldUseThreeRows) {
// 3줄 배치: [1, 4], [5, 2], [3, 6]
val threeRowOrder = listOf(0, 3, 4, 1, 2, 5)
threeRowOrder.map { sortedByRank[it] }.toPersistentList() to 2
} else {
// 2줄 배치: [1, 4, 2], [5, 3, 6]
val twoRowOrder = listOf(0, 3, 1, 4, 2, 5)
twoRowOrder.map { sortedByRank[it] }.toPersistentList() to 3
}

@coderabbitai coderabbitai Bot Jan 20, 2026

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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the file structure and find related code
cd app/src/main/java/com/flint/presentation/profile/component && pwd

Repository: imflint/Flint-Android

Length of output: 142


🏁 Script executed:

# Search for arrangeKeywordsByRank function and its usages
rg "arrangeKeywordsByRank" --type kt -B 2 -A 10

Repository: imflint/Flint-Android

Length of output: 91


🏁 Script executed:

# Check the UserKeywordResponseModel to understand the data structure
fd "UserKeywordResponseModel" --type kt --exec cat {} \;

Repository: imflint/Flint-Android

Length of output: 234


🏁 Script executed:

# Look for API response models and constraints
rg "UserKeyword" --type kt -l | head -20

Repository: imflint/Flint-Android

Length of output: 91


🏁 Script executed:

# Search for arrangeKeywordsByRank function and its usages
rg "arrangeKeywordsByRank" -B 2 -A 10

Repository: imflint/Flint-Android

Length of output: 3031


🏁 Script executed:

# Look for UserKeywordResponseModel definition
rg "UserKeywordResponseModel" -B 2 -A 10

Repository: imflint/Flint-Android

Length of output: 26127


🏁 Script executed:

# Find the ProfileKeywordSection file and check the full context
cat -n app/src/main/java/com/flint/presentation/profile/component/ProfileKeywordSection.kt

Repository: imflint/Flint-Android

Length of output: 8766


🏁 Script executed:

# Search for API calls or data sources that provide keyword data
rg "keywordList" app/src/main/java/com/flint/presentation/profile/component/ProfileKeywordSection.kt -B 5 -A 5

Repository: imflint/Flint-Android

Length of output: 2502


🏁 Script executed:

# Check API response DTO to see if there's a 6-keyword limit
find . -name "*UserKeywords*Dto*" -o -name "*KeywordDto*" | head -20

Repository: imflint/Flint-Android

Length of output: 144


🏁 Script executed:

# Look for API interface to understand the contract
rg "UserApi" -A 10 --type-list | head -50

Repository: imflint/Flint-Android

Length of output: 454


🏁 Script executed:

# Search for any configuration or limits related to keywords
rg "limit|MAX.*KEYWORD|KEYWORD.*MAX|6" app/src/main/java/com/flint/data -i | grep -i keyword | head -20

Repository: imflint/Flint-Android

Length of output: 47


🏁 Script executed:

# Check the API interface definition
fd "UserApi" -type f --exec cat {} \;

Repository: imflint/Flint-Android

Length of output: 235


🏁 Script executed:

# Read the UserKeywordsResponseDto to understand the API structure
cat -n app/src/main/java/com/flint/data/dto/user/response/UserKeywordsResponseDto.kt

Repository: imflint/Flint-Android

Length of output: 783


🏁 Script executed:

# Find and read the UserApi interface
find . -name "UserApi.kt" -exec cat -n {} \;

Repository: imflint/Flint-Android

Length of output: 977


🏁 Script executed:

# Search for any configuration constants or limits
rg "keyword" app/src/main/java/com/flint --ignore-case -B 2 -A 2 | grep -i "limit\|max\|count\|size" | head -30

Repository: imflint/Flint-Android

Length of output: 1015


🏁 Script executed:

# Check if there's any documentation or comments about 6 keywords
rg "6|keyword" app/src/main/java/com/flint/presentation/profile/component/ProfileKeywordSection.kt -B 1 -A 1 | head -50

Repository: imflint/Flint-Android

Length of output: 1754


🏁 Script executed:

# Search for any comments or documentation about 6 keywords
rg "3줄|2줄|배치|줄|row|grid" app/src/main/java/com/flint/presentation/profile -B 5 -A 5 | head -60

Repository: imflint/Flint-Android

Length of output: 5696


🏁 Script executed:

# Check if there are other uses of this function or similar logic elsewhere
rg "arrangeKeyword|chunked|itemsPerRow" app/src/main/java/com/flint --type-list

Repository: imflint/Flint-Android

Length of output: 454


🏁 Script executed:

# More precise search
find . -name "*.kt" -path "*/profile/*" -exec grep -l "keyword" {} \;

Repository: imflint/Flint-Android

Length of output: 537


6개 초과의 키워드가 자동으로 버려집니다.

현재 arrangeKeywordsByRank 함수는 6개 이상의 키워드가 입력되면 상위 6개만 재배치하고 나머지를 버립니다. API 응답(UserKeywordsResponseDto)에는 키워드 개수 제한이 없으며, 실제로 6개를 초과할 수 있습니다. 데이터 손실이 명시적으로 문서화되지 않았으며, 사용자는 일부 키워드가 무시되는 이유를 알 수 없습니다.

개선 방법:

  • 6개 제한이 API 계약이라면 명시적으로 문서화하기
  • 또는 초과분을 그리드 아래에 추가로 표시하기
  • 또는 명시적으로 제한하되 take(6) 전에 사용자에게 알리기
🤖 Prompt for AI Agents
In
`@app/src/main/java/com/flint/presentation/profile/component/ProfileKeywordSection.kt`
around lines 160 - 183, arrangeKeywordsByRank currently discards keywords beyond
the first 6; preserve extras by applying the special 6-item reordering only to
the top-six and appending any remaining items after that. Concretely, inside
arrangeKeywordsByRank use sortedByRank.take(6) (or similar) to build the
reordered block using threeRowOrder/twoRowOrder, then append
sortedByRank.drop(6) to the resulting list before converting toPersistentList
and returning; ensure shouldUseThreeRows is still computed from the top-six
(e.g., checkTargets from the taken list) and keep the existing row-count return
value logic or make it dynamic as needed.

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.

6개 초과면 그냥 버리라고 해

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.

@nahy-512, 알겠습니다! 6개 초과 시 버리는 것이 의도된 동작이라는 점 확인했습니다. 👍


✏️ Learnings added
Learnt from: nahy-512
Repo: imflint/Flint-Android PR: 145
File: app/src/main/java/com/flint/presentation/profile/component/ProfileKeywordSection.kt:160-183
Timestamp: 2026-01-20T19:26:26.529Z
Learning: In ProfileKeywordSection.kt's arrangeKeywordsByRank function, discarding keywords beyond 6 items is the intended behavior per design requirements. The function should only process and display the top 6 keywords.

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.

@giovannijunseokim giovannijunseokim left a comment

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.

LGTM 👍

Comment on lines +33 to +37
val profileDeferred = async { userRepository.getUserProfile(userId = null) }
val keywordsDeferred = async { userRepository.getUserKeywords(userId = null) }

private fun loadInitialData() {
viewModelScope.launch {
_uiState.emit(UiState.Success(ProfileUiState.Fake)) // TODO: 임시 로직
val profileResult = profileDeferred.await()
val keywordsResult = keywordsDeferred.await()

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: userRepository.getUserProfile, userRepository.getUserKeywords가 이미 suspend 함수이므로, async와 await()을 굳이 사용할 필요가 없어 보입니다.

그냥 val profile = userRepository.getUserProfile(userId = null).getOrThrow로 사용하면 되지 않을까요?

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.

다음 작업에서 확인해보겠습니다! 감사합니다

@nahy-512 nahy-512 merged commit 6311653 into develop Jan 20, 2026
2 checks passed
@nahy-512 nahy-512 deleted the feat/#134-profilescreen-logic-and-api branch January 20, 2026 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔖 API feat - API 연동 Feat ✨ 신규 기능을 추가하거나 기존 기능의 동작, 정책을 변경

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat] ProfileScreen 취향 키워드 UI 수정 및 프로필 관련 API 연동

3 participants