본문 바로가기
♞ | 공부일지/♝ | TIL

[Android, 내일배움캠프] 공부일지(2024-07-31)

by immgga 2024. 7. 31.
오늘 공부한 내용 정리(2024년 7월 31일)

 

출처: unsplash.com

 

코드카타 문제풀이

근무 지옥에 빠진 푸앙이(25593번, Bronze 1)

https://rkdrkd-history.tistory.com/166

 

[Kotlin, B1] 백준 25593번 근무 지옥에 빠진 푸앙이 (Small)

근무 지옥에 빠진 푸앙이 (Small)(25593번)Bronze 1#구현 #자료 구조 #문자열 #해시를 사용한 집합과 맵 문제 내용  문제 접근문제를 이해하기만 하면 된다. 입력 형식이 주의 개수인 N에서 4를 곱한

rkdrkd-history.tistory.com

 

 

베스트앨범(프로그래머스, Level 3)

https://rkdrkd-history.tistory.com/168

 

[Kotlin, Lv.3] 프로그래머스 베스트앨범

베스트앨범Level 3https://school.programmers.co.kr/learn/courses/30/lessons/42579 문제 내용  문제 접근가장 많이 재생된 노래를 장르별로 2개씩 모아서 각 노래의 고유 번호를 순서대로 출력해야 한다.문제의

rkdrkd-history.tistory.com

 

 

수준별 학습반(standard)

Retrofit

retrofit

안드로이드 및 자바 애플리케이션을 위한 인기 있는 HTTP 클라이언트 라이브러리

REST API를 쉽게 사용할 수 있도록 도와줌.

REST API의 HTTP 요청을 java interface로 변환하는 게 주목적.

 

특징

1. 간결한 코드

2. 데이터 변환: JSON, XML 등 다양한 데이터 변환을 제공.

3. 유연성: 다양한 커스터마이징 제공

 

사용법

1. gradle에 추가하기

2. API 인터페이스 정의

3. Retrofit 인스턴스 생성

4. API 호출

 

 

안드로이드 앱 개발 심화

앱 개발 프로세스

앱 개발 프로세스

앱 개발은 대략적으로 다음과 같은 프로세스로 진행된다.

아이디어 => 기획 => 디자인 => 앱 개발 => 테스트 => 출시

 

 

디버깅

디버깅

모든 소프트웨어에서 소스 코드의 오류 또는 버그를 찾아서 수정하는 과정.

프로그래머는 오류가 일어나는 원인을 알아내기 위해 코드를 분석해야 한다.

 

디버깅이 중요한 이유

컴퓨터 프로그래밍은 추상적이고 개념적인 확동인 만큼 버그와 오류가 발생하기 마련이다.

오류를 해결함으로써 소프트웨어 품질과 최종 사용자 경험이 모두 개선된다.

 

 

디버깅이 필요한 코딩 오류 종류

구문 오류: 프로그램에 잘못된 명령문이 입력된 경우.

의미론적 오류: 프로그래밍 명령문을 잘못 사용했을 때.

논리 오류: 프로그래머가 컴퓨터 프로그램의 단계적 프로세스나 알고리즘을 잘못 입력할 때.

런타임 오류: 소프트웨어 코드가 실행되는 컴퓨팅 환경에서 발생.

 

 

 

앱 개발 심화 개인 과제

compose로 bottom navigation bar 구현

심화 개인 과제는 type B를 compose로 구현해보려고 한다(compose 재활).

우선 viewPager2, tabLayout 또는 bottomNavigationBar를 쓰라고 했는데 나는 이전에 만든 기억이 어렴풋이 남아 있는 bottomNavigaionBar를 만들어서 화면 navigaion 먼저 구성을 해보려 한다.

 

BottomNavItem 정의하기

xml에서는 res -> menu 패키지에 bottom navigaion menu를 정의하듯이 compose에서는 sealed class로 정의해 주어야 한다. compose에서는 menu.xml을 쓰지 않는다.

과제에는 검색 페이지와 저장소 페이지가 필요하므로 2개의 페이지를 sealed class 내부에 data object로 생성한다.

const val searchRoute = "route_search"
const val lockerRoute = "route_locker"

sealed class BottomNavItem(
    val title: String,
    val icon: Int,
    val screenRoute: String
) {
    data object Search: BottomNavItem(title = "검색", icon = R.drawable.ic_search, screenRoute = searchRoute)
    data object Locker: BottomNavItem(title = "저장소", icon = R.drawable.ic_locker, screenRoute = lockerRoute)
}

BottomNavItem의 파라미터로 나중에 BottomNavigationItem을 구성할 때 이 값들을 사용할 생각이다.

각각의 object에서는 sealed class를 상속받아 각각의 데이터를 정의해 준다.

 

NavHost 생성

bottom navigation 연결에 필요한 NavHost를 생성한다. NavHost를 생성하면 현재 route에 따라서 내부에 정의된 NavGraph로 전환해 줄 것이다.

@Composable
fun BottomNavHost(
    modifier: Modifier = Modifier,
    navHostController: NavHostController,
    startDestination: String
) {
    NavHost(
        modifier = modifier,
        navController = navHostController,
        startDestination = startDestination
    ) {
        composable(searchRoute) { SearchScreen() }

        composable(lockerRoute) { LockerScreen() }
    }
}

내부의 composable()로 감싸져 있는 애들이 NavGraph이다. 각각의 screen(SearchScreen, LockerScreen)과 route를 연결해 주는 일을 해준다. 연결된 NavHost에서 현재 route에 맞는 NavGraph를 불러서 화면을 전환할 것이다.

 

Bottom Navigation Bar 생성

이제 우리의 앱 UI에 띄울 Bottom Navigation Bar를 생성해 줄 것이다. 우선 BottomNavItem들의 object들을 list로 정의하고, 현재 route를 불러온다.

val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
val screens = listOf(
    BottomNavItem.Search,
    BottomNavItem.Locker
)

 

그리고 본격적으로 BottomAppBar를 구현해 준다(별거 없음).

BottomAppBar(
    modifier = Modifier.shadow(elevation = 5.dp, spotColor = Color.DarkGray),
    containerColor = containerColor,
    contentColor = contentColor,
) {
    // navigationBarItem
}

containerColor로 현재 background color를 정의하고, contentColor는 콘텐츠들(icon, title)의 색을 정의한다.

 

screens의 반복문으로 NavigationBarItem을 정의해 준다.

screens.forEach { item ->
    NavigationBarItem(
        selected = currentRoute == item.screenRoute,
        label = { Text(text = item.title) },
        onClick = {
            navController.navigate(item.screenRoute) {
                navController.graph.startDestinationRoute?.let {
                    popUpTo(it) { saveState = true }
                }
                launchSingleTop = true
                restoreState = true
            }
        },
        icon = {
            Icon(painter = painterResource(id = item.icon), contentDescription = item.title)
        },
        colors = NavigationBarItemDefaults.colors(
            selectedIconColor = Color.Cyan,
            selectedTextColor = Color.Cyan,
            unselectedIconColor = Color.LightGray,
            unselectedTextColor = Color.LightGray
        )
    )
}

아이템 선택 확인을 현재 route와 item에 연결된 route가 같은지 확인한다.

label은 Text Composable을 이용해 정의하고, item을 클릭하면 화면 전환 로직을 구성한다(navController.navigate()).

navigate() 이후의 코드들은 fragment의 bottom navigation bar처럼 하나의 화면만 발생하도록 하는 역할 같다(다른 화면에서 또 다른 화면으로 이동해도 단일 화면만 보이도록 해주는 기능인 것 같다). 위 부분은 시간 나면 추가로 공부해 봐야겠다.

 

colors를 이용해 item을 클릭했을 때의 색과 클릭하지 않았을 때의 색을 따로 구분해 준다.

 

Bottom Navigation Bar 연결

MainActivity에서는 Scaffold 안에 bottomBar 파라미터를 사용해 BottomNavigationBar를 정의한다.

또한 람다 내부에는 NavHost를 정의해 주고 초기 route는 searchRoute로 정의한다.

Scaffold(
    modifier = Modifier.fillMaxSize(),
    bottomBar = {
        LockerBottomNavigation(
            navController = navController,
            containerColor = Color.White
        )
    }
) { innerPadding ->
    BottomNavHost(
        modifier = Modifier.padding(innerPadding),
        navHostController = navController,
        startDestination = searchRoute
    )
}

Scaffold의 람다에 NavHost에 padding에 innerPadding을 적용해 주어야 한다. innerPadding이 scaffold에 추가된 bottomBar의 height만큼의 값이 저장되어 있어서 화면이 침범되지 않게 해 준다.

 

이제 BottomAppBar에 화면들이 정상적으로 연결되었는지 확인해 보자.

 


 

오늘 공부 내용 정리 및 회고

앱 개발 심화 강의를 완강하고 오늘 본격적으로 심화 개인 과제를 시작했다. 나는 Type B를 선택했다.

알고 있는 기술을 마음껏 써도 된다고 했기 때문에, compose로 구현을 하려 한다.

그래서 먼저 navigation을 bottomAppBar로 구현을 해주었다.

오랜만에 쓰는 compose인데도 크게 어려운 점은 없었다. 아직까진.

728x90