← 글 목록

notes

Andriod - kotlin

Android Kotlin 문법·구조와 앱 개발에서 사용하는 기본 개념 메모.


Kotlin 공식/안드로이드 코드랩 북마크를 여기 붙여 두었었다. 지금 본문에 .kt 확장자·null 안전·디렉토리(data/domain/presentation)·MVVM 뼈대가 그 내용이다.

1.확장자명은 .kt

2.
현재 Android 공식 개발 언어가 Kotlin이며, Java보다 권장
Java(.java)로도 개발 가능하지만, 구글이 Kotlin을 선호


Kotlin의 장점:
Null 안정성
간결한 문법
Java와 100% 호환
함수형 프로그래밍 지원


디렉토리

app/
├── manifests/
│   └── AndroidManifest.xml
├── java/
│   └── com.example.app/
│       ├── data/                  # 데이터 계층
│       │   ├── api/              # 네트워크 통신
│       │   ├── repository/       # 저장소
│       │   └── model/            # 데이터 모델
│       ├── di/                   # 의존성 주입
│       ├── domain/               # 비즈니스 로직
│       │   └── usecase/          # 유스케이스
│       ├── presentation/         # UI 계층
│       │   ├── main/            # 화면별 패키지
│       │   ├── detail/
│       │   └── common/          # 공통 컴포넌트
│       └── util/                 # 유틸리티
└── res/      

  • 주요 아키텍처 패턴
  • 주요 아키텍처 패턴

a) Clean Architecture (가장 많이 사용)

참고:

Clean Architecture 다이어그램 북마크 자리. 한 줄로: UI(presentation) → domain usecase → data(repository/api/db). 의존성은 안쪽(domain)을 바라보게.

MVVM

(권장되는 UI 패턴)

  • ViewModel: UI 로직 처리
  • View: UI 표시
  • Model: 데이터 처리


주요 구성요소

// UI 컴포넌트
class MainActivity : AppCompatActivity()
class MainFragment : Fragment()

// ViewModel
class MainViewModel : ViewModel()

// Repository
class UserRepository @Inject constructor(
    private val api: ApiService,
    private val db: AppDatabase
)

// UseCase
class GetUserUseCase @Inject constructor(
    private val repository: UserRepository
)

  • 자주 사용되는 라이브러리
  • Dagger Hilt: 의존성 주입
  • Retrofit: 네트워크 통신
  • Room: 로컬 데이터베이스
  • Coroutines: 비동기 처리
  • Jetpack Compose: 현대적 UI 개발

변수 선언

// 변수 (가변)
var name: String = "Kim"
var age = 25  // 타입 추론

// 상수 (불변)
val PI = 3.14

데이터 타입


함수선언

// 기본 함수
fun sum(a: Int, b: Int): Int {
    return a + b
}

// 한 줄 함수
fun sum(a: Int, b: Int) = a + b

// 기본값 있는 함수
fun greet(name: String = "Guest") = "Hello $name"

nullable 처리

// Nullable 타입
var name: String? = null

// Null 안전 호출
val length = name?.length  // name이 null이면 length도 null

// Elvis 연산자
val length = name?.length ?: 0  // null이면 0 반환

// Not-null 단언
val length = name!!.length  // null이면 예외 발생

조건문

// if-else (식으로 사용 가능)
val max = if (a > b) a else b

// when (switch 대체)
when (x) {
    1 -> print("One")
    2, 3 -> print("Two or Three")
    in 4..10 -> print("Between 4 and 10")
    else -> print("Other")
}

반복문

// for
for (i in 1..10) { }  // 1부터 10까지
for (i in 1 until 10) { }  // 1부터 9까지
for (i in 10 downTo 1) { }  // 10부터 1까지
for (i in 1..10 step 2) { }  // 2씩 증가

// while
while (condition) { }

컬렉션 (arrary ,tuple 과 같은 개념 )

// List
val list = listOf(1, 2, 3)  // 불변
val mutableList = mutableListOf(1, 2, 3)  // 가변

// Map
val map = mapOf("a" to 1, "b" to 2)
val mutableMap = mutableMapOf<String, Int>()

// Set
val set = setOf(1, 2, 3)

클래스

// 기본 클래스
class Person(val name: String, var age: Int)

// 데이터 클래스
data class User(val name: String, val age: Int)

// 상속
open class Animal(val name: String)
class Dog(name: String): Animal(name)

// object (싱글톤)
object DatabaseConfig {
    val url = "jdbc:mysql://localhost"
}

람다

// 람다 기본
val sum = { x: Int, y: Int -> x + y }

// 고차 함수
fun operation(x: Int, y: Int, op: (Int, Int) -> Int): Int {
    return op(x, y)
}

확장 함수

fun String.addHello(): String {
    return "Hello $this"
}
// 사용: "World".addHello()  // "Hello World"

스코프 함수

// let
user?.let { it.name = "New Name" }

// with
with(user) {
    name = "New Name"
    age = 25
}

// apply
user.apply {
    name = "New Name"
    age = 25
}

// also
user.also {
    println(it.name)
}

// run
user.run {
    name = "New Name"
    age = 25
}

코루틴 (Coroutines , thread)

  • 비동기 프로그래밍kotlin

// 코루틴 스코프
launch {
    delay(1000L)
    println("World!")
}

// 비동기 함수
suspend fun fetchUser(): User
suspend fun fetchData() = coroutineScope {
    val user = async { fetchUser() }
    val data = async { fetchData() }
    user.await() + data.await()
}

제네릭 (Generics)

// 제네릭 클래스
class Box<T>(var value: T)

// 제네릭 제약
class Box<T : Number>(var value: T)

// 변성
class Producer<out T>  // 공변성
class Consumer<in T>   // 반공변성

Sealed 클래스/인터페이스

sealed class Result {
    data class Success(val data: String): Result()
    data class Error(val message: String): Result()
    object Loading: Result()
}

위임

// 프로퍼티 위임
class Example {
    var name: String by Delegates.observable("") { 
        prop, old, new -> println("$old -> $new") 
    }
}

// 인터페이스 위임
class DelegatingCollection<T>(
    private val collection: Collection<T>
) : Collection<T> by collection

타입 알리아스

typealias NetworkHandler = (Result<String>) -> Unit
typealias StringMap = Map<String, String>

중위 함수 (Infix functions)

infix fun Int.plus(x: Int) = this + x
// 사용: 1 plus 2

연산자 오버로딩

operator fun Point.plus(other: Point): Point {
    return Point(x + other.x, y + other.y)
}

DSL 빌더

fun buildHTML() = html {
    head {
        title { +"Title" }
    }
    body {
        div {
            +"Content"
        }
    }
}

리플렉션

val kClass = String::class
val properties = kClass.memberProperties

어노테이션

@Target(AnnotationTarget.CLASS)
annotation class MyAnnotation

@MyAnnotation
class Example

인라인 함수

inline fun <T> lock(lock: Lock, body: () -> T): T {
    lock.lock()
    try {
        return body()
    } finally {
        lock.unlock()
    }
}

컨텍스트 리시버

fun List<Int>.sum() with Calculator {
    var sum = 0
    for (item in this) {
        sum = add(sum, item)
    }
    return sum
}