-
Notifications
You must be signed in to change notification settings - Fork 1
feat: 컬렉션 모듈 및 마이페이지 진입 구조 구현 #941
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
ed79214
8ef6498
1d920b3
d5613f6
f86631e
23a17d9
e1777ed
89bbc45
5027cb0
63b0259
233767c
fbb35f2
08066a8
6d5c227
db82975
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package com.into.websoso.ui.collection | ||
|
|
||
| import android.content.Context | ||
| import android.content.Intent | ||
| import android.os.Bundle | ||
| import androidx.activity.ComponentActivity | ||
| import androidx.activity.compose.setContent | ||
| import com.into.websoso.core.designsystem.theme.WebsosoTheme | ||
| import com.into.websoso.feature.collection.CollectionNavHost | ||
| import dagger.hilt.android.AndroidEntryPoint | ||
|
|
||
| @AndroidEntryPoint | ||
| class CollectionActivity : ComponentActivity() { | ||
| override fun onCreate(savedInstanceState: Bundle?) { | ||
| super.onCreate(savedInstanceState) | ||
|
|
||
| setContent { | ||
| WebsosoTheme { | ||
| CollectionNavHost() | ||
| } | ||
| } | ||
| } | ||
|
|
||
| companion object { | ||
| fun getIntent(context: Context): Intent = Intent(context, CollectionActivity::class.java) | ||
| } | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fragment도 현재 compose 환경에서는 잘 사용되지 않아 레거시인것 같습니다.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Compose-first 구조의 최종 방향에서 Fragment를 제거하는 것이 좋다는 점에는 공감합니다! MyPageFragment를 제거하려면 기존 마이페이지 XML과 ViewModel 연결, 스크롤 및 툴바 동작 등 컬렉션과 관계없는 영역까지 함께 마이그레이션해야 합니다. 해당 작업은 이번 컬렉션 PR의 범위를 크게 벗어나기 때문에, 따라서 이번에는 기존 Fragment를 유지하고 ComposeView로 점진적 적용하게끔 선택했습니다. 마이페이지 전체의 Compose 전환은 별도 작업으로 분리하는 것이 안전하다고 판단했습니다.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 마이페이지 전체를 compose로 분리하는 것이 아닌 MyPageFragment, HomeFragment, FeedFragment는 지금 그대로 MainActivity의 탭으로 두고, 컬렉션만 앱 레벨 Compose NavHost의 destination으로 붙이면 마이페이지에 대한 이전은 나중에 하고 collection만 간단하게 변경할 수 있을거라 생각됩니다! 여기 ai가 알려준 상세 코드 첨부합니다. activity_main.xml에 fcv_main 위를 덮는 ComposeView 하나만 추가합니다. <androidx.compose.ui.platform.ComposeView MainActivity에 앱 레벨 NavHost를 두되, startDestination은 아무것도 그리지 않는 main 으로 둡니다. 즉 기본 상태에서는 기존 Fragment 화면이 그대로 보이고, Compose destination으로 // app/src/main/java/com/into/websoso/ui/main/AppNavHost.kt private lateinit var navController: NavHostController private fun setupComposeNavHost() { } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import com.into.websoso.setNamespace | ||
|
|
||
| plugins { | ||
| id("websoso.android.feature") | ||
| } | ||
|
|
||
| android { | ||
| setNamespace("feature.collection") | ||
| } | ||
|
|
||
| dependencies { | ||
| implementation(libs.navigation.compose) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <manifest> | ||
|
|
||
| </manifest> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| package com.into.websoso.feature.collection | ||
|
|
||
| import androidx.compose.foundation.Image | ||
| import androidx.compose.foundation.background | ||
| import androidx.compose.foundation.clickable | ||
| import androidx.compose.foundation.layout.Row | ||
| import androidx.compose.foundation.layout.Spacer | ||
| import androidx.compose.foundation.layout.fillMaxWidth | ||
| import androidx.compose.foundation.layout.padding | ||
| import androidx.compose.foundation.layout.size | ||
| import androidx.compose.material3.Text | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.ui.Alignment | ||
| import androidx.compose.ui.Modifier | ||
| import androidx.compose.ui.graphics.vector.ImageVector | ||
| import androidx.compose.ui.res.vectorResource | ||
| import androidx.compose.ui.tooling.preview.Preview | ||
| import androidx.compose.ui.unit.dp | ||
| import com.into.websoso.core.designsystem.theme.Gray300 | ||
| import com.into.websoso.core.designsystem.theme.Primary100 | ||
| import com.into.websoso.core.designsystem.theme.WebsosoTheme | ||
| import com.into.websoso.core.designsystem.theme.White | ||
| import com.into.websoso.core.resource.R | ||
|
|
||
| @Composable | ||
| fun CollectionEntry( | ||
| onClick: () -> Unit, | ||
| modifier: Modifier = Modifier, | ||
| collectionCount: Int = 0, | ||
| ) { | ||
| Row( | ||
| modifier = modifier | ||
| .fillMaxWidth() | ||
| .background(White) | ||
| .clickable(onClick = onClick) | ||
|
Sadturtleman marked this conversation as resolved.
Outdated
|
||
| .padding( | ||
| horizontal = 20.dp, | ||
| vertical = 20.dp, | ||
| ), | ||
| verticalAlignment = Alignment.CenterVertically, | ||
| ) { | ||
| Text( | ||
|
Sadturtleman marked this conversation as resolved.
|
||
| text = "컬렉션 ", | ||
| color = Gray300, | ||
| style = WebsosoTheme.typography.title2, | ||
| ) | ||
| Text( | ||
| text = collectionCount.toString(), | ||
| color = Primary100, | ||
| style = WebsosoTheme.typography.title2, | ||
| ) | ||
| Text( | ||
| text = "개", | ||
| color = Gray300, | ||
| style = WebsosoTheme.typography.title2, | ||
| ) | ||
| Spacer(modifier = Modifier.weight(1f)) | ||
| Image( | ||
| imageVector = ImageVector.vectorResource(R.drawable.btn_setting_right), | ||
| contentDescription = null, | ||
| modifier = Modifier.size(24.dp), | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| @Preview(showBackground = true) | ||
| @Composable | ||
| private fun CollectionEntryPreview() { | ||
| WebsosoTheme { | ||
| CollectionEntry(onClick = {}) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package com.into.websoso.feature.collection | ||
|
|
||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.ui.Modifier | ||
| import androidx.navigation.compose.NavHost | ||
| import androidx.navigation.compose.composable | ||
| import androidx.navigation.compose.rememberNavController | ||
|
|
||
| private const val COLLECTION_ROUTE = "collection" | ||
|
|
||
| @Composable | ||
| fun CollectionNavHost(modifier: Modifier = Modifier) { | ||
| val navController = rememberNavController() | ||
|
|
||
| NavHost( | ||
| navController = navController, | ||
| startDestination = COLLECTION_ROUTE, | ||
| modifier = modifier, | ||
| ) { | ||
| composable(route = COLLECTION_ROUTE) { | ||
| CollectionScreen() | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| package com.into.websoso.feature.collection | ||
|
|
||
| import androidx.compose.foundation.background | ||
| import androidx.compose.foundation.layout.Arrangement | ||
| import androidx.compose.foundation.layout.Column | ||
| import androidx.compose.foundation.layout.fillMaxSize | ||
| import androidx.compose.foundation.layout.padding | ||
| import androidx.compose.material3.Text | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.ui.Alignment | ||
| import androidx.compose.ui.Modifier | ||
| import androidx.compose.ui.tooling.preview.Preview | ||
| import androidx.compose.ui.unit.dp | ||
| import com.into.websoso.core.designsystem.theme.Black | ||
| import com.into.websoso.core.designsystem.theme.Gray200 | ||
| import com.into.websoso.core.designsystem.theme.WebsosoTheme | ||
| import com.into.websoso.core.designsystem.theme.White | ||
|
|
||
| @Composable | ||
| fun CollectionScreen(modifier: Modifier = Modifier) { | ||
| Column( | ||
| modifier = modifier | ||
| .fillMaxSize() | ||
| .background(White) | ||
| .padding(horizontal = 20.dp), | ||
| horizontalAlignment = Alignment.CenterHorizontally, | ||
| verticalArrangement = Arrangement.Center, | ||
| ) { | ||
| Text( | ||
| text = "컬렉션", | ||
| color = Black, | ||
| style = WebsosoTheme.typography.headline1, | ||
| ) | ||
| Text( | ||
| text = "임시화면", | ||
| color = Gray200, | ||
| style = WebsosoTheme.typography.body2, | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| @Preview(showBackground = true) | ||
| @Composable | ||
| private fun CollectionScreenPreview() { | ||
| WebsosoTheme { | ||
| CollectionScreen() | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
activity로 두는게 아닌 SAA 형태로 조금씩 바꾸는게 좋을 것 같습니다. 굳이 레거시 구조를 유지할 이유가 없는 것 같아요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SAA를 지향하는 방향에는 공감합니다!
다만 현재 앱에는 앱 레벨의
Compose NavHost가 없고,MainActivity가FragmentContainerView와FragmentManager를 통해 홈/피드/서재/마이페이지 Fragment를 직접 전환하고 있습니다.MyPageFragment역시 이번 작업에서 추가한 것이 아니라 기존 화면입니다.컬렉션 진입 구조를 설계하면서 아래와 같은 방법들을 고려해보았습니다.
CollectionFragment를 추가하면 기존 Fragment 구조를 다시 확장하게 됩니다.MainActivity의 Compose destination으로 연결하려면 하단 탭, 기존 Fragment 호스팅, 뒤로 가기 처리를 포함한 앱 단위 내비게이션 변경이 필요합니다.CollectionActivity를 사용하면 기존 마이페이지와 메인 내비게이션에는 영향을 주지 않으면서, 새로 개발하는 컬렉션 내부 흐름은 Compose Navigation으로 구성할 수 있습니다.이번 PR은 컬렉션 기능을 단계적으로 추가하는 첫 PR이기 때문에 기존 화면의 마이그레이션까지 범위를 넓히기보다, 수정 범위를 컬렉션에 집중하는 편이 안전하다고 판단해
CollectionActivity를 진입 경계로 선택했습니다. Activity가 추가되어 향후 SAA 전환 시 마이그레이션 대상이 늘어난다는 단점은 있지만, 현재 구조와 PR 범위에서는 가장 적절한 선택이라고 보았습니다.SAA 로의 전환은
MainActivity내비게이션 마이그레이션 작업으로 별도 분리하는 것이 적절하다고 생각합니다.혹시 기존 메인 구조를 크게 변경하지 않으면서 이번 PR에서 점진적으로 적용할 수 있다고 생각하신 구체적인 구조가 있다면 의견 부탁드립니다!
+공식 Android 문서에서도 기존 View/Fragment 앱은 Compose와 공존시키며 화면 단위로 점진적으로 이전하도록 권장하고 있습니다. Fragment가 남아 있는 동안 ComposeView를 사용하는 것도 전환 방식으로 안내하고 있으며, 모든 navigation destination을 Composable로 전환할 수 있을 때 Navigation Compose로 마이그레이션하도록 설명하고 있습니다.
Compose 마이그레이션 전략, ComposeView와 Fragment 연동