본문 바로가기
TellingUs: TellingMe(텔링미)

[TellingMe/Android] 텔링미 안드로이드 개발 🔥1차 스프린트🔥

by JongSeok 2024. 1. 8.

TellingUs팀의 TellingMe

최근 TellingMe(텔링미) 서비스를 개발하고 운영하고 있는 TellingUs(텔링어스)팀에 안드로이드 개발자로 합류하게 되었다.

TellingUs에서는 텔링미 iOS를 주력으로 개발하며 운영 중에 있고, 약 1,000명 정도의 사용자들을 대상으로 서비스하고 있다.

iOS 앱을 주력으로 먼저 서비스하며 안드로이드 앱에 대한 수요도 확인했고 당시 팀에는 안드로이드 개발자가 없어 간단하게 웹뷰로 만들어 안드로이드 앱은 비교적 가볍게 서비스되고 있었다.

그리고 이번에 기존 앱을 전체적으로 고도화&리팩토링하는 과정을 거치기로 했고, 다른 안드로이드 개발자 한 분과 같이 텔링미 안드로이드 개발을 함께 하기로 했다.

 

내가 TellingUs팀에 합류하기로 결정했던 이유로는 크게 두 가지가 있다.

1. 실제 사용자들을 대상으로 하는 서비스를 경험할 수 있다.
2. 텔링미 안드로이드 버전은 사실상 신규 개발이기 때문에 내가 사용해보고 싶은 기술들을 모두 적용해 볼 수 있다.

 

프로젝트 설계부터 개발, 운영까지 직접적으로 관여하면서 내가 팀에 꽤 많은 기여를 할 수 있겠다는 생각이 들었다. 

내가 원하는대로 개발하면서 유저들에게 서비스까지 할 수 있다니? 안 할 이유가 없다. 게다가 함께 안드로이드 개발을 진행할 동료분은 현직에서 근무하고 계서 앞으로 배울 점이 많을 것 같다.


매 스프린트는 약 2주 정도의 기간 동안 진행되고, 이번 스프린트에서는 간단한 인수인계와 컨벤션 논의, 디자인시스템 일부를 구축하는 작업을 했다.

 

🔥 1차 스프린트에서 결정된 내용

- MVVM + Clean Architecture 구조를 따른다.
- 단일모듈로 개발하되 추후 멀티모듈로 리팩토링한다.
- 코드 형상관리는 Rebase And Merge 전략을 사용한다.
- UI 개발은 Jetpack Compose로 진행한다. (100% Compose 사용을 지향하자.)

- 아직 Compose에 낯설기 때문에 Compose로 개발하면서 겪는 어려움, 고민을 Slack, Notion, Git을 통해 적극적으로 공유하고 리뷰한다.

 

디자인시스템은 크게 컬러, 폰트, 컴포넌트를 정의하는 것으로 구분하고 있고, 지난 포스팅에서 폰트시스템을 정의한 내용을 볼 수 있고 이번 포스팅에서는 컴포넌트를 어떻게 정의하고 있는지 일부를 살펴보자.

 

[Jetpack Compose] Compose에서 폰트시스템(Typography) 구축하기

최근 Compose로 신규 안드로이드 앱을 개발하는 프로젝트에 참여하게 되었습니다. 본격적인 개발을 시작하기 전 앱 전체에서 사용하게 될 Text의 Style을 지정하기 위해 어떤 방법들이 있나 찾아보

develop-oj.tistory.com

PrimaryButton.kt

@Composable
fun PrimaryButton(
    modifier: Modifier = Modifier,
    size: BUTTON_SIZE,
    text: String,
    onClick: () -> Unit,
    enable: Boolean = true
) {
    CompositionLocalProvider(LocalRippleTheme provides PrimaryButtonRippleTheme) {
        Button(
            modifier = modifier,
            shape = RoundedCornerShape(dimensionResource(R.dimen.button_radius)),
            onClick = onClick,
            colors = ButtonDefaults.buttonColors(
                containerColor = Primary400,
                contentColor = Base0,
                disabledContainerColor = Primary100,
                disabledContentColor = Base0
            ),
            contentPadding = when(size) {
                BUTTON_SIZE.LARGE -> PaddingValues(
                    vertical = dimensionResource(R.dimen.button_padding_vertical_large),
                    horizontal = dimensionResource(R.dimen.button_padding_horizontal_large)
                )
                BUTTON_SIZE.MEDIUM -> PaddingValues(
                    vertical = dimensionResource(R.dimen.button_padding_vertical_medium),
                    horizontal = dimensionResource(R.dimen.button_padding_horizontal_medium)
                )
                BUTTON_SIZE.SMALL -> PaddingValues(
                    vertical = dimensionResource(R.dimen.button_padding_vertical_small),
                    horizontal = dimensionResource(R.dimen.button_padding_horizontal_small)
                )
            },
            enabled = enable
        ) {
            Text(
                text = text,
                style = when(size) {
                    BUTTON_SIZE.LARGE -> TellingmeTheme.typography.body1Bold
                    BUTTON_SIZE.MEDIUM -> TellingmeTheme.typography.body2Bold
                    BUTTON_SIZE.SMALL -> TellingmeTheme.typography.caption1Bold
                }
            )
        }
    }
}

 

PrimaryButton은 앱의 여러 화면에서 사용될 메인 버튼이다.

 

PrimaryButton을 사용하는 모든 스크린에서 PrimaryButton에 매개변수를 전달하는 것만으로 Button의 UI가 결정되고 그려질 수 있도록 하기 위해 size, text, onClick 매개변수를 필수로 전달받을 수 있도록 정의했다.

PrimaryButton은 사이즈(Large, Medium, Small)와 enable/disenbale 여부에 따라 색상, 폰트, 패딩이 달라져 BUTTON_SIZE라는 enum class를 매개변수로 받으면서 buttonColors, padding, Text의 style를 지정하고 있다.

 

dimen.xml

또한, Button의 padding 또한 dp를 직접 지정하지 않고, dimen.xml에서 공통으로 관리될 수 있도록 정의했다.

그렇지 않다면 만약 LARGE 크기 버튼의 수평방향 padding이 변경된다면 모든 Button 컴포넌트의 horizontal의 padding 수치를 변경해야 하지만 dimen.xml을 통해 padding을 지정하고 있기 때문에 Button 컴포넌트의 수치를 변경할 필요 없이 dimen.xml에서 수치를 변경하면 모든 Button 컴포넌트에 적용된다.

 

위와 같이 앱에서 자주 사용되는 UI(Button, Text, TopBar...)를 컴포넌트화 할 수 있다면 매번 번거롭게 여러 속성들을 정의할 필요 없이 필요한 속성만을 전달해 스크린의 UI를 조립(?)하는 방식으로 개발할 수 있다.

PrimaryButton 컴포넌트의 Preview


📝 1차 스프린트 리뷰

고민 1. 익숙한 XML vs 낯선 Jetpack Compose

- 이번 스프린트에서 가장 잘했다고 생각하는 부분은 Jetpack Compose 개발 방식을 도입한 것이다.

Compose를 조금씩 공부하고는 있지만 프로젝트에 도입하기에는 다소 무리가 있을 것 같아 망설이던 와중에 동료 안드로이드 개발자분과 고민한 결과 Compose를 기반으로 개발하기로 결정했고, 사용해 본 결과 아주아주 만족하고 있다. (왜 다들 컴포즈가 좋다고 노래를 부르는지 알 것 같다..)

물론 xml(명령형 UI) 개발 방식과는 다소 차이가 있어 프로젝트를 진행하면서 정말 많은 공부가 필요하다. 프로젝트와는 별개로 컴포즈 공부도 병행하고 있다.

 

 

고민 2.  디자인 시스템 설계에 대한 고민

- 현재는 Button의 구성을 SIZE(Large, Medium, Small)와 STATE((Default, Hover, Diabled, Enabled, Selected)의 상태를 정의하는 enum class로 구분해 구성하고 있는데 Button의 State가 컴포넌트마다 일관되게 정의하고 있지 않다.

그래서인지 준비된 디자인 시스템을 프로젝트에서 구축하면서 디자인 시스템의 컴포넌트 State가 일관되게 관리되지 않고, 과도하게 분리되어 있지 않나?라는 의문이 자주 들었다. 추후 디자이너와 협의를 통해 일관되게 유지할 필요가 있을 것 같다.

 

그리고 이번 프로젝트는 디자인이 완료된 시점에 개발을 시작하게 되어 컴포넌트들을 예쁘게 만들어두고 본격적인 개발을 시작하려고 디자인시스템 설계와 구축에 정말 많은 고민과 노력을 하고 있다.

일반적으로 권장되는 방법에는 어떤 것들이 있는지, 다른 Compose 개발팀에서는 어떻게 하는지 참고하기 위해 타팀의 github 레포지토리도 많이 참고하고 있고, Compose에서 국룰(?)을 지향하면서 공부하고 있다.

Button, Chip, Widget 등 컴포넌트 중 일부

 

728x90
반응형