1. 시작하기 전에
SociaLite는 다양한 Android 플랫폼 API를 사용하여 소셜 네트워크 앱에서 흔히 보는 기능을 구현하는 방법을 보여주므로 다양한 Jetpack API를 활용하여 더 많은 기기에서 안정적으로 작동하면서도 코드는 더 적게 필요한 복잡한 기능을 달성할 수 있습니다.
이 Codelab에서는 SociaLite 앱을 Android 15 더 넓은 화면 시행과 호환되도록 하고 앱을 하위 호환 방식으로 더 넓은 화면으로 설정하는 방법을 설명합니다. 더 넓은 화면으로 설정한 후 SociaLite는 기기와 탐색 모드에 따라 다음과 같이 표시됩니다.
3버튼 탐색이 포함된 SociaLite | 동작 탐색이 포함된 SociaLite |
대형 화면 기기에서 SociaLite |
기본 요건
- 기본적인 Kotlin 지식
- Android 스튜디오 설정 Codelab 완료 또는 Android 스튜디오 사용 방법과 에뮬레이터나 Android 15를 실행하는 실제 기기에서 앱을 테스트하는 방법에 관한 지식
학습할 내용
- Android 15 더 넓은 화면 변경사항 처리 방법
- 앱을 하위 호환 방식으로 더 넓은 화면으로 설정하는 방법
필요한 항목
- Android 스튜디오 최신 버전
- Android 15 베타 1 이상을 실행하는 테스트 기기나 에뮬레이터
- Android 15 베타 1 SDK 이상
2. 시작 코드 가져오기
- GitHub에서 시작 코드를 다운로드합니다.
또는 저장소를 클론하고 codelab_improve_android_experience_2024
브랜치를 확인합니다.
$ git clone git@github.com:android/socialite.git
$ cd socialite
$ git checkout codelab_improve_android_experience_2024
- Android 스튜디오에서 SociaLite를 열고 Android 15 기기나 에뮬레이터에서 앱을 실행합니다. 화면이 다음 중 하나와 같이 표시됩니다.
3버튼 탐색 | 동작 탐색 |
대형 화면 |
- 채팅 페이지에서 대화의 하나를 선택합니다(예: 반려견이 포함된 대화).
3버튼 탐색이 포함된 반려견 채팅 메시지 | 동작 탐색이 포함된 반려견 채팅 메시지 |
3. Android 15에서 앱을 더 넓은 화면으로 설정
더 넓은 화면이란 무엇인가요?
앱이 시스템 표시줄 뒤에 그려질 수 있으므로 사용자 환경이 깔끔해지고 디스플레이 공간을 최대한 사용할 수 있습니다. 이를 더 넓은 화면을 활용한다고 합니다.
Android 15 더 넓은 화면 변경사항 처리 방법
Android 15 전에는 기본적으로 앱의 UI가 상태 표시줄과 탐색 메뉴 등 시스템 표시줄 영역을 피하도록 배치되어야 했습니다. 앱에서 더 넓은 화면을 활용하기로 선택했습니다. 앱에 따라 이러한 선택은 사소한 것부터 번거로운 것까지 다양할 수 있습니다.
Android 15부터는 앱이 기본적으로 더 넓은 화면을 활용하게 됩니다. 기본적으로 다음과 같이 표시됩니다.
- 3버튼 탐색 메뉴가 반투명입니다.
- 동작 탐색 메뉴가 투명합니다.
- 상태 표시줄이 투명합니다.
- 콘텐츠에 인셋이나 패딩을 적용하지 않는 한 콘텐츠는 탐색 메뉴와 상태 표시줄, 자막 표시줄 등 시스템 표시줄 뒤에 그려집니다.
이렇게 하면 앱 품질 향상의 수단으로 더 넓은 화면을 간과하지 않고 앱이 더 넓은 화면을 활용하는 데 필요한 작업을 줄일 수 있습니다. 하지만 이 변경으로 앱에 부정적인 영향을 미칠 수 있습니다. 타겟 SDK를 Android 15로 업그레이드한 후 SociaLite 내에서 발생하는 두 가지 부정적인 영향을 예로 들어 보겠습니다.
타겟 SDK 값을 Android 15로 변경
- SociaLite 앱의 build.gradle 파일 내에서 타겟 SDK 버전과 컴파일 SDK 버전을 Android 15나
VanillaIceCream
으로 변경합니다.
Android 15 안정화 버전 출시 전에 이 Codelab을 진행하는 경우 코드는 다음과 같이 표시됩니다.
android {
namespace = "com.google.android.samples.socialite"
compileSdkPreview = "VanillaIceCream"
defaultConfig {
applicationId = "com.google.android.samples.socialite"
minSdk = 21
targetSdkPreview = "VanillaIceCream"
...
}
...
}
Android 15 안정화 버전 출시 후 이 Codelab을 진행하는 경우에는 코드가 다음과 같이 표시됩니다.
android {
namespace = "com.google.android.samples.socialite"
compileSdk = 35
defaultConfig {
applicationId = "com.google.android.samples.socialite"
minSdk = 21
targetSdk = 35
...
}
...
}
- SociaLite를 다시 빌드하고 다음 문제를 확인합니다.
- 3버튼 탐색 배경 보호가 탐색 메뉴와 일치하지 않습니다. 동작 탐색을 위해 개발자의 개입 없이 채팅 화면이 더 넓은 화면으로 보입니다. 하지만 3버튼 탐색 배경 보호가 있으며 이는 삭제해야 합니다.
3버튼 탐색이 포함된 채팅 화면 | 동작 탐색이 포함된 채팅 화면 |
- 가려진 UI. 대화의 하단 UI 요소가 탐색 메뉴에 가려져 있습니다. 이 부분이 3버튼 탐색에서 가장 분명하게 나타납니다.
3버튼 탐색이 포함된 반려견 채팅 메시지 | 동작 탐색이 포함된 반려견 채팅 메시지 |
SociaLite 문제 해결
기본 3버튼 탐색 배경 보호를 삭제하려면 다음 단계를 따르세요.
MainActivity.kt
파일에서 window.isNavigationBarContrastEnforced 속성을 false로 설정하여 기본 배경 보호를 삭제합니다.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
super.onCreate(savedInstanceState)
setContent {
// Add this block:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
window.isNavigationBarContrastEnforced = false
}
}
}
...
}
window.isNavigationBarContrastEnforced
는 완전히 투명한 배경이 요청될 때 탐색 메뉴의 대비가 충분한지 확인합니다. 이 속성을 false로 설정하면 사실상 3버튼 탐색 배경을 투명으로 설정하는 것입니다. window.isNavigationBarContrastEnforced
는 3버튼 탐색에만 영향을 미치며 동작 탐색에는 영향을 미치지 않습니다.
- Android 15 기기에서 앱을 다시 실행하고 대화의 하나를 확인합니다. 이제 타임라인, 채팅, 설정 화면이 모두 더 넓은 화면으로 표시됩니다. 앱의
NavigationBar
(타임라인, 채팅, 설정 버튼 포함)가 시스템의 투명한 3버튼 탐색 메뉴 뒤에 그려집니다.
밴딩이 삭제된 채팅 화면. | 동작 탐색 변경사항 없음 |
하지만 대화의 InputBar
는 여전히 시스템 표시줄에 가려집니다. 이 문제를 해결하려면 인셋을 적절히 처리해야 합니다.
3버튼 탐색의 반려견 대화 하단의 입력란이 시스템의 탐색 메뉴에 가려져 있습니다. | 동작 탐색의 반려견 대화. 하단의 입력란이 시스템의 탐색 메뉴에 가려져 있습니다. |
SociaLite에서는 InputBar
가 가려져 있습니다. 실제로 가로 모드로 회전하거나 대형 화면 기기를 사용할 때는 상단과 하단, 오른쪽과 왼쪽의 요소가 가려져 있을 수 있습니다. 이러한 모든 사용 사례에서 인셋 처리 방법을 고려해야 합니다. SociaLite의 경우 패딩을 적용하여 탭 가능한 InputBar
콘텐츠를 위로 올립니다.
인셋을 적용하여 가려진 UI를 수정하려면 다음 단계를 따르세요.
ui/chat/ChatScreen.kt
파일로 이동하여 178번 줄 부근에서ChatContent
컴포저블을 찾습니다. 여기에는 대화 화면의 UI가 포함되어 있습니다.ChatContent
는Scaffold
를 활용하여 UI를 쉽게 구성합니다. 기본적으로Scaffold
는 시스템 표시줄의 깊이와 같은 시스템 UI에 관한 정보를Scaffold
의 패딩 값(innerPadding
매개변수)과 함께 사용할 수 있는 인셋으로 제공합니다.Scaffold
의innerPadding
을 사용하여 패딩을InputBar
에 추가합니다.- 214번 줄 부근에서
ChatContent
내의InputBar
를 찾습니다. 이는 사용자가 메시지를 작성하는 UI를 만드는 맞춤 컴포저블입니다. 미리보기는 다음과 같습니다.
InputBar
는 contentPadding
을 가져와서 나머지 UI가 포함된 Row 컴포저블에 패딩으로 적용합니다. 패딩은 Row 컴포저블의 모든 측면에 적용됩니다. 432번 줄 부근에서 이를 확인할 수 있습니다. 다음은 참조용 InputBar
컴포저블입니다(이 코드를 추가하면 안 됨).
// Don't add this code because it's only for reference.
@Composable
private fun InputBar(
contentPadding: PaddingValues,
...,
) {
Surface(...) {
Row(
modifier = Modifier
.padding(contentPadding)
...
) {
IconButton(...) { ... } // take picture
IconButton(...) { ... } // attach picture
TextField(...) // write message
FilledIconButton(...){ ... } // send message
}
}
}
}
ChatContent
내InputBar
로 다시 이동하고 시스템 표시줄 인셋을 사용하도록contentPadding
을 변경합니다. 220번 줄 부근에 있습니다.
InputBar(
...
contentPadding = innerPadding, //Add this line.
// contentPadding = PaddingValues(0.dp), // Remove this line.
...
)
- Android 15 기기에서 앱을 다시 실행합니다.
인셋이 잘못 적용된 3버튼 탐색의 반려견 대화 | 인셋이 잘못 적용된 동작 탐색의 반려견 대화 |
시스템 표시줄에 버튼이 더 이상 가려지지 않도록 하단 패딩이 적용되었지만 상단 패딩도 적용되었습니다. 상단 패딩은 TopAppBar
및 시스템 표시줄의 깊이를 포함합니다. Scaffold는 패딩 값을 콘텐츠에 전달하여 상단 앱 바는 물론 시스템 표시줄을 피할 수 있도록 합니다.
- 상단 패딩 문제를 해결하려면
innerPadding
PaddingValues
의 사본을 만들고 상단 패딩을0.dp
로 설정한 후 수정된 사본을contentPadding
에 전달합니다.
InputBar(
...
contentPadding = innerPadding.copy(layoutDirection, top = 0.dp), //Add this line.
// contentPadding = innerPadding, // Remove this line.
...
)
- Android 15 기기에서 앱을 다시 실행합니다.
인셋이 올바르게 적용된 3버튼 탐색의 반려견 대화 | 인셋이 올바르게 적용된 동작 탐색의 반려견 대화 |
축하합니다. SociaLite를 Android 15 더 넓은 화면 플랫폼 변경사항과 호환되도록 했습니다. 이제 SociaLite를 하위 호환 방식으로 더 넓은 화면으로 설정하는 방법을 알아봅니다.
4. SociaLite를 하위 호환 방식으로 더 넓은 화면으로 설정
SociaLite는 이제 Android 15에서 더 넓은 화면으로 설정되지만 여전히 이전 Android 기기에서는 더 넓은 화면으로 설정되지 않습니다. 이전 Android 기기에서 SociaLite를 더 넓은 화면으로 설정하려면 MainActivity.kt
파일에서 콘텐츠를 설정하기 전에 enableEdgeToEdge
를 호출하세요.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
enableEdgeToEdge() // Add this line.
window.isNavigationBarContrastEnforced = false
super.onCreate(savedInstanceState)
setContent {... }
}
}
enableEdgeToEdge
가져오기는 import androidx.activity.enableEdgeToEdge
입니다. 종속 항목은 AndroidX Activity 1.8.0 이상입니다.
하위 호환 방식으로 앱을 더 넓은 화면으로 설정하는 방법과 인셋을 처리하는 방법에 관한 자세한 내용은 다음 가이드를 참고하세요.
이로써 개발자 과정의 더 넓은 화면 부분이 마무리되었습니다. 다음 섹션은 선택사항이며 앱에 적용할 수 있는 더 넓은 화면 관련 기타 고려사항을 설명합니다.
5. 선택사항: 더 넓은 화면 추가 고려사항
아키텍처 전반에 걸친 인셋 처리
구성요소
SociaLite의 여러 구성요소가 타겟 SDK 값 변경 후에도 변경되지 않았습니다. SociaLite는 권장사항에 따라 설계되었으므로 이 플랫폼 변경을 쉽게 처리할 수 있습니다. 권장사항은 다음과 같습니다.
- 인셋을 자동으로 적용하므로
TopAppBar
,BottomAppBar
,NavigationBar
와 같은 Material Design 3 구성요소를 사용합니다(androidx.compose.material3
). - 앱이 대신 Compose에서 Material 2 구성요소(
androidx.compose.material
)를 사용한다면 이러한 구성요소는 인셋 자체를 자동으로 처리하지 않습니다. 하지만 인셋에 액세스하여 수동으로 적용할 수 있습니다.androidx.compose.material 1.6.0
이상에서windowInsets
매개변수를 사용하여BottomAppBar
,TopAppBar
,BottomNavigation
,NavigationRail
에 인셋을 수동으로 적용합니다. 마찬가지로Scaffold
에는contentWindowInsets
매개변수를 사용합니다. 그 외에는 수동으로 인셋을 패딩으로 적용합니다. - 앱에서 뷰 및 Material 구성요소(
com.google.android.material
)를 사용한다면 뷰 기반 Material 구성요소(예:BottomNavigationView
,BottomAppBar
,NavigationRailView
,NavigationView
)는 대부분 인셋을 처리하므로 추가 작업이 필요하지 않을 수 있습니다. 하지만AppBarLayout
을 사용하는 경우에는android:fitsSystemWindows="true"
를 추가해야 합니다. - 앱에서 뷰와
BottomSheet
,SideSheet
또는 맞춤 컨테이너를 사용하는 경우ViewCompat.setOnApplyWindowInsetsListener
를 사용하여 패딩을 적용합니다.RecyclerView
의 경우에는 이 리스너를 사용하여 패딩을 적용하고clipToPadding="false"
도 추가합니다. - 복잡한 UI에는
Surface
가 아닌Scaffold
(또는NavigationSuiteScaffold
나ListDetailPaneScaffold
)를 사용합니다.Scaffold
를 사용하면TopAppBar
,BottomAppBar
,NavigationBar
,NavigationRail
을 쉽게 배치할 수 있습니다.
콘텐츠 스크롤
앱에는 목록이 포함될 수 있으며 Android 15 변경사항으로 목록의 마지막 항목이 시스템의 탐색 메뉴에 가려질 수 있습니다.
목록의 마지막 항목이 3버튼 탐색으로 가려진 것을 보여줍니다.
Compose로 콘텐츠 스크롤
TextField
를 사용하지 않는 한 Compose에서 LazyColumn
의 contentPadding을 사용하여 마지막 항목에 공간을 추가합니다.
Scaffold { innerPadding ->
LazyColumn(
contentPadding = innerPadding
) {
// Content that does not contain TextField
}
}
목록의 마지막 항목이 3버튼 탐색으로 가려지지 않은 것을 보여줍니다.
TextField
의 경우 Spacer
를 사용하여 LazyColumn
의 마지막 TextField
를 그립니다. 자세한 내용은 인셋 사용을 참고하세요.
LazyColumn(
Modifier.imePadding()
) {
// Content with TextField
item {
Spacer(
Modifier.windowInsetsBottomHeight(
WindowInsets.systemBars
)
)
}
}
뷰를 사용하여 콘텐츠 스크롤
RecyclerView
나 NestedScrollView
의 경우 android:clipToPadding="false"
를 추가합니다.
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layoutManager="LinearLayoutManager" />
setOnApplyWindowInsetsListener
를 사용하여 창 인셋에서 왼쪽, 오른쪽, 하단 패딩을 제공합니다.
ViewCompat.setOnApplyWindowInsetsListener(binding.recycler) { v, insets ->
val i = insets.getInsets(
WindowInsetsCompat.Type.systemBars() + WindowInsetsCompat.Type.displayCutout()
)
v.updatePadding(
left = i.left,
right = i.right,
bottom = i.bottom + bottomPadding,
)
WindowInsetsCompat.CONSUMED
}
LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS 사용
SDK 35를 타겟팅하기 전에 SociaLite는 가로 모드에서 다음과 같이 표시되었습니다. 왼쪽 가장자리에 카메라 컷아웃을 처리하는 큰 흰색 상자가 있습니다. 3버튼 탐색에서 버튼은 오른쪽에 있습니다.
SDK 35를 타겟팅한 후 SociaLite는 다음과 같이 표시됩니다. 더 이상 왼쪽 가장자리에 카메라 컷아웃을 고려하는 큰 흰색 상자가 없습니다. 이 효과를 달성하기 위해 Android에서는 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS를 자동으로 설정합니다.
앱에 따라 여기서 인셋을 처리할 수도 있습니다.
SociaLite에서 이렇게 하려면 다음 단계를 따르세요.
ui/ContactRow.kt
파일에서 Row 컴포저블을 찾습니다.- 디스플레이 컷아웃을 처리하도록 패딩을 수정합니다.
@Composable
fun ChatRow(
chat: ChatDetail,
onClick: (() -> Unit)?,
modifier: Modifier = Modifier,
) {
// Add layoutDirection, displayCutout, startPadding, and endPadding.
val layoutDirection = LocalLayoutDirection.current
val displayCutout = WindowInsets.displayCutout.asPaddingValues()
val startPadding = displayCutout.calculateStartPadding(layoutDirection)
val endPadding = displayCutout.calculateEndPadding(layoutDirection)
Row(
modifier = modifier
...
// .padding(16.dp) // Remove this line.
// Add this block:
.padding(
PaddingValues(
top = 16.dp,
bottom = 16.dp,
// Ensure content is not occluded by display cutouts
// when rotating the device.
start = startPadding.coerceAtLeast(16.dp),
end = endPadding.coerceAtLeast(16.dp)
)
),
...
) { ... }
디스플레이 컷아웃 처리 후 SociaLite는 다음과 같습니다.
개발자 옵션 화면의 디스플레이 컷아웃 아래에서 다양한 디스플레이 컷아웃 구성을 테스트할 수 있습니다.
앱에 LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
나 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
, LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
를 사용하는 비 플로팅 창(예: 활동)이 있으면 Android에서는 Android 15 베타 2부터 이러한 컷아웃 모드를 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
로 해석합니다. 이전 Android 15 베타 1에서는 앱이 다운되었습니다.
자막 표시줄도 시스템 표시줄입니다
자막 표시줄도 시스템 표시줄입니다. 상단 제목 표시줄 등 자유 형식 창의 시스템 UI 창 장식을 설명하기 때문입니다. Android 스튜디오의 데스크톱 에뮬레이터 내에서 자막 표시줄을 확인할 수 있습니다. 다음 스크린샷에서 자막 표시줄은 앱 상단에 있습니다.
Compose에서 Scaffold의 PaddingValues
, safeContent
, safeDrawing
또는 내장 WindowInsets.systemBars
를 사용하는 경우 앱이 예상대로 표시됩니다. 하지만 statusBar
를 사용하여 인셋을 처리하는 경우 앱 콘텐츠가 예상대로 표시되지 않을 수 있습니다. 상태 표시줄이 자막 표시줄을 고려하지 않기 때문입니다.
뷰에서 WindowInsetsCompat.systemBars
를 사용하여 수동으로 인셋을 처리하는 경우 앱이 예상대로 표시됩니다. WindowInsetsCompat.statusBars
를 사용하여 인셋을 수동으로 처리한다면 앱이 예상대로 표시되지 않을 수 있습니다. 상태 표시줄이 자막 표시줄이 아니기 때문입니다.
몰입형 모드의 앱
몰입형 모드의 화면은 Android 15의 더 넓은 화면 시행에 대부분 영향을 받지 않습니다. 몰입형 앱은 이미 더 넓은 화면을 활용하기 때문입니다.
시스템 표시줄 보호
동작 탐색에는 투명한 표시줄, 3버튼 탐색에는 반투명 또는 불투명 표시줄을 사용하고 싶을 수 있습니다.
Android 15에서는 반투명 3버튼 탐색이 기본값입니다. 플랫폼에서 window.isNavigationBarContrastEnforced
속성으로 true
로 설정하기 때문입니다. 동작 탐색은 투명하게 유지됩니다.
기본적으로 반투명인 3버튼 탐색 |
일반적으로 3버튼 탐색은 반투명이면 됩니다. 하지만 때에 따라 앱에 불투명 3버튼 탐색이 필요할 수 있습니다. 먼저 window.isNavigationBarContrastEnforced
속성을 false
로 설정합니다. 그런 다음 뷰의 경우 WindowInsetsCompat.tappableElement
를 사용하고 Compose의 경우 WindowInsets.tappableElement
를 사용합니다. 값이 0이면 사용자가 동작 탐색을 사용하는 것입니다. 0이 아니면 사용자가 3버튼 탐색을 사용하는 것입니다. 사용자가 3버튼 탐색을 사용한다면 탐색 메뉴 뒤에 뷰나 상자를 그립니다. Compose 예는 다음과 같습니다.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
window.isNavigationBarContrastEnforced = false
MyTheme {
Surface(...) {
MyContent(...)
ProtectNavigationBar()
}
}
}
}
}
// Use only if required.
@Composable
fun ProtectNavigationBar(modifier: Modifier = Modifier) {
val density = LocalDensity.current
val tappableElement = WindowInsets.tappableElement
val bottomPixels = tappableElement.getBottom(density)
val usingTappableBars = remember(bottomPixels) {
bottomPixels != 0
}
val barHeight = remember(bottomPixels) {
tappableElement.asPaddingValues(density).calculateBottomPadding()
}
Column(
modifier = modifier.fillMaxSize(),
verticalArrangement = Arrangement.Bottom
) {
if (usingTappableBars) {
Box(
modifier = Modifier
.background(MaterialTheme.colorScheme.background)
.fillMaxWidth()
.height(barHeight)
)
}
}
}
불투명 3버튼 탐색 |
6. 솔루션 코드 검토
MainActivity.kt
파일의 onCreate
메서드는 다음과 같습니다.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
enableEdgeToEdge()
window.isNavigationBarContrastEnforced = false
super.onCreate(savedInstanceState)
setContent {
Main(
shortcutParams = extractShortcutParams(intent),
)
}
}
}
ChatScreen.kt
파일 내 ChatContent
컴포저블은 다음과 같이 인셋을 처리해야 합니다.
private fun ChatContent(...) {
...
Scaffold(...) { innerPadding ->
Column {
...
InputBar(
input = input,
onInputChanged = onInputChanged,
onSendClick = onSendClick,
onCameraClick = onCameraClick,
onPhotoPickerClick = onPhotoPickerClick,
contentPadding = innerPadding.copy(
layoutDirection, top = 0.dp
),
sendEnabled = sendEnabled,
modifier = Modifier
.fillMaxWidth()
.windowInsetsPadding(
WindowInsets.ime.exclude(WindowInsets.navigationBars)
),
)
}
}
}
솔루션 코드는 main 브랜치에서 확인할 수 있습니다. 이미 SociaLite를 다운로드 했다면 다음을 실행하세요.
git checkout main
다운로드하지 않은 경우 코드를 다시 다운로드하여 직접 또는 git을 통해 main 브랜치를 확인할 수 있습니다.
git clone git@github.com:android/socialite.git