Skip to content

🛠 AN 컨벤션

Dongjoo Seo edited this page Jul 10, 2025 · 3 revisions

📝 안드로이드 개발 컨벤션

본 컨벤션 문서는 PRNDcompany/android-style-guideKotlin.mdResource.md를 기반으로 작성되었습니다.

1. 일반 원칙

  • 기존 컨벤션 유지: 현재 문서에 명시된 모든 기존 컨벤션은 어떠한 경우에도 변경할 수 없습니다.
  • 신규 컨벤션 추가: 프로젝트 진행 중 필요한 경우 새로운 컨벤션을 논의하고 본 문서에 추가할 수 있습니다.

2. Kotlin 코드 컨벤션

2.1. Boolean 비교

  • if (a?.b?.isTraded ?: false) 방식보다는 if (a?.b?.isTraded == true) 와 같은 방식으로 명시적인 비교를 선호합니다.

2.2. Custom Accessor vs Function

2.4. Naming Rules

2.4.1. Package 이름

  • package 이름은 소문자로 작성합니다.
    • 예시: package kr.co.prnd.domain
  • underscore(_)는 사용하지 않습니다.
    • //warning package kr.co.prnd.domain_module
  • 예외적으로 불가피하게 연결된 단어를 붙여서 사용해야 하는 경우에는 camelCase로 처리합니다.
    • 예시: package com.example.myProject

2.4.2. LiveData 변수명

2.4.3. 함수 이름

  • ViewModel을 observe()할 때 모아 놓는 함수 이름:

    • setupXXX()
  • 서버에서 데이터를 불러올 때 함수 이름:

    • fetchXXX()
  • 서버에 데이터를 저장할 때 함수 이름:

    • saveXXX()
  • Return 값이 있는 데이터를 불러올 때 함수 이름:

    • getXXX()
  • 특정 객체를 찾는 함수 이름:

    • findXXX()
  • 복수형 데이터를 가져올 때는 뒤에 s를 붙입니다.

    • getBrands() // O
    • getBrandList() // X
  • Raw 값으로부터 enum을 찾을 때 함수 이름은 find()로 합니다.

    enum class Color {
        RED, BLUE, GREEN;
    
        fun find(rawColor: String): Color = when (rawColor) {
            "red" -> RED
            "blue" -> BLUE
            "green" -> GREEN
            else -> throw IllegalArgumentException("invalid color: $rawColor")
        }
    }

2.5. Listener Naming

2.5.1. Listener 인터페이스 이름

  • function을 1개만 가진 경우: fun interface OnXXXXListener
  • function을 2개 이상 가진 경우: interface XXXListener

2.5.2. on[명사][동사]() (현재형)

  • Publisher(이벤트 발생 주체)가 이벤트만 전달하고 Listener가 전적인 책임을 처리할 때 사용합니다.
  • 이벤트를 handle하는 주체가 listen하고 있는 곳일 때 사용합니다.
    • 예시: fun onClick(), fun onFocusChange(), fun onScrollChange(), fun onAnimationStart(), fun onTextChange()

2.5.3. on[명사][동사 과거형]()

  • Publisher가 무언가를 처리하고 Listener에게 해당 동작이 완료되었음을 알릴 때 사용합니다.
  • 어떤 동작을 하고 나서 이 동작이 일어났음을 Listener에게 알려줄 때 사용합니다.
  • onEach(), doOnXXX() 개념처럼 특정 이벤트를 intercept해서 쓸 때 사용합니다.
  • 동작을 한 뒤에 Listener를 호출해야 과거형의 이름과 일치합니다.
    • 예시: fun onScrollStateChanged(), fun onTextChanged()

2.5.4. 기타 Listener 규칙

  • Listener를 구현하는 곳에서 과거형 여부에 따라, 해당 이벤트에 대한 처리를 해야 하는지 말아야 하는지를 판단할 수 있습니다.

2.6. Formatting

2.6.1. 개행

  • 생성자, 함수에서 Parameter를 정의할 때 한 줄로 정의 가능하면 한 줄로 작성합니다.
  • 한 줄로 정의하기 어렵다면 각 parameter별로 개행합니다.

2.6.2. When Statement

  • 한 줄에 들어가는 when 분기는 중괄호({})를 사용하지 않습니다.

    when (value) {
        0 -> return
        // ...
    }
  • 여러 개의 조건을 동시에 사용하는 경우 >를 포함한 블록은 다음 줄로 내려서 작성합니다.

    when (value) {
        foo -> // ...
        bar,
        baz     -> return
    }

3. Android Resource 컨벤션

3.1. Layout

3.1.1. Layout 파일 이름 (<WHAT>_<WHERE>)

WHAT Prefix 설명
activity_ Activity에서 쓰이는 layout
fragment_ Fragment에서 쓰이는 layout
dialog_ Dialog에서 쓰이는 layout
view_ CustomView에서 쓰이는 layout
item_ RecyclerView, GridView, ListView 등 ViewHolder에 쓰이는 layout
layout_ 로 재사용되는 공통의 layout

3.2.3. Background Drawable 이름

  • 배경색이 pressed 상태에 따라 white -> sky_blue로 변하는 경우: bg_white_to_sky_blue.xml
  • 배경이 white 색의 24dp로 테두리를 그리는 경우: bg_white_radius_24dp.xml
  • 배경이 투명하며 배경의 선만을 sky_blue 색의 8dp로 테두리를 그리는 경우: bg_stroke_sky_blue_radius_8dp.xml

3.2.4. 기타 Drawable 규칙

  • img_xxx의 경우 파일의 크기가 큰 경우가 많으므로 tinypng에서 파일 크기를 줄인 뒤에 추가해야 합니다. (GitHub imgbot을 사용한다면 생략 가능)
  • 대부분 용량이 큰 파일이어서 xxxhdpi에만 넣습니다.
  • 예시:
    • btn_call_normal.png: 전화 걸기 버튼 이미지
    • btn_call_pressed.png: 전화 걸기 버튼 눌렸을 때의 이미지
    • btn_call.xml: 전화 걸기 버튼 이미지의 selector xml
    • ic_dealer_gift.png: 딜러가 보내준 기프티콘을 보여줄 때 표시되는 이미지
    • img_splash_chart.png: 스플래시 화면에서 보여지는 차트 이미지

3.3. Dimension

3.3.1. Dimension 이름

  • 여러 군데에서 재사용되는 개념이라면 변수로 정의하여 @dimen/xxx와 같이 사용합니다.
  • 그렇지 않다면 명시적으로 16dp와 같이 XML 코드에 직접 작성합니다.

3.3.2. Margin/Padding4

  • 대부분의 margin/padding은 아래 정의된 space_xxx로만 사용되도록 합니다.
    • <dimen name="space_small">12dp</dimen>
    • <dimen name="space_median">16dp</dimen>
    • <dimen name="space_s_large">18dp</dimen>
    • <dimen name="space_large">20dp</dimen>
    • <dimen name="space_x_large">24dp</dimen>
  • 그 외에 특정 화면에서 위의 값을 따르지 않는 경우, <WHERE>_<DESCRIPTION>_<WHAT>의 규칙으로 만듭니다.
    • 예시:
      • <dimen name="register_car_item_car_model_start_padding">40dp</dimen>
      • <dimen name="register_car_item_grade_start_padding">56dp</dimen>
      • <dimen name="register_car_item_car_detail_start_padding">72dp</dimen>
  • 2번 이상 쓰이는 경우는 dimen에 정의하는 것을 강제하고, 1번만 쓰이는 경우에는 XML 코드에 직접 넣어도 괜찮습니다.

3.3.3. Height/Size

  • 높이만 지정할 때는 height, 1:1 비율로 같은 값이 들어갈 때는 size로 합니다.
    • 예시:
      • <dimen name="toolbar_height">56dp</dimen>
      • <dimen name="register_input_view_default_height">280dp</dimen>
      • <dimen name="register_input_view_collapse_height">200dp</dimen>
      • <dimen name="dealer_profile_image_size">48dp</dimen>

3.4. String

3.4.1. String 이름 (<WHERE>_<DESCRIPTION>)

  • 특정 화면에서 쓰이는 텍스트가 아니라 여러 군데에서 공통으로 재사용될 텍스트라면 all_<DESCRIPTION>으로 이름을 짓습니다.
  • 예시:
    • permission_dialog_camera_title: 카메라 권한을 요구하는 Dialog의 제목
    • permission_dialog_camera_description: 카메라 권한을 요구하는 Dialog의 설명 내용
    • all_yes: 네
    • all_ok_understand: 여러 Dialog에서 네, 알겠습니다로 쓰이는 공통의 텍스트

3.4.2. 문단

  • 문단 형태의 긴 문자열로 개행(\\n)이 필요한 경우, \\n을 다음 줄의 앞에 씁니다.

    <string name="sample">문단 첫번째줄
        \\\\n문단 두번째줄
        \\\\n문단 세번째줄</string>
    

3.5. Theme/Style

3.5.1. 파일 위치 및 사용 규칙

  • Themethemes.xml, Stylestyles.xml에 추가합니다.
  • 1번만 쓰이는 경우에는 style을 만들지 않습니다. (단, 앞으로 재사용될 가능성이 높은 경우에는 가능)
  • 모든 styleparent를 갖습니다.

3.5.2. Naming

  • style의 이름은 parent의 이름 패턴과 맞춥니다.

    <style name="Widget.HeyDealer.Button" parent="@style/Widget.AppCompat.Button">
    </style>
    
  • parent에서 일부 내용만 수정하고자 하는 경우, parent 이름 뒤에 달라진 내용의 내용을 추가해줍니다.

    <style name="Theme.HeyDealer.Transparent" parent="Theme.HeyDealer">
    </style>
    
  • Base StyleTheme의 경우는 앞에 Base를 붙입니다.XML

    <style name="Base.Theme" parent="..." />
    <style name="Base.Theme.Transparent">...</style>
    

    <style name="HeyDealerTheme" parent="Base.Theme">...</style> <style name="HeyDealerTheme.Transparent" parent="Base.Theme.Transparent" />

    <style name="Base.TextAppearance.HeyDealer" parent="...">...</style> <style name="Base.TextAppearance.HeyDealer.Headline">...</style> <style name="TextAppearance.HeyDealer.Headline1" parent="Base.TextAppearance.HeyDealer.Headline">...</style> <style name="TextAppearance.HeyDealer.Headline2" parent="Base.TextAppearance.HeyDealer.Headline">...</style>

3.5.3. Attribute

  • Attribute 이름은 camelCase로 합니다.XML

    <attr name="numStars" format="integer" />
    
  • 기존에 정의되어 있는 android:xxx와 같은 동작을 유도하는 경우, 이 태그를 재사용합니다.XML

    <declare-styleable name="SpannedGridLayoutManager">
        <attr name="android:orientation" />
        </declare-styleable>
    

3.6. 기타 Resource 규칙

  • android:xxxLeft/android:xxxRight 대신 **android:xxxStart/android:xxxEnd*를 사용합니다. (모든 Left/Right 사용 부분에 적용)

Clone this wiki locally