Android

Kotlin의 Data Class(feat. iOS의 struct)

TDCIAN 2026. 1. 27. 19:27

 

1. Kotlin Data Class 탄생 배경: POJO(Plain Old Java Object) 지옥에서 벗어나기

Java POJO

// Java: 20줄 코드로 User 하나 만들기
public class User {
    private String name;
    private int age;
    
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // getter/setter 8줄
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    
    @Override public boolean equals(Object o) { /* 30줄 */ }
    @Override public int hashCode() { /* 15줄 */ }
    @Override public String toString() { /* 10줄 */ }
}

실제 사용되는 것은 name, age

 

Kotlin Data Class

data class User(val name: String, val age: Int)

한 줄로 끝낼 수 있으며, equals, hashCode, toString, copy까지 지원

 

 

2. Data Class 실전 용도

2.1 API Response Model (Retrofit)

data class UserResponse(
    val id: Long,
    val name: String,
    val email: String,
    val profileImage: String?
)

data class PostResponse(
    val id: Long,
    val title: String,
    val content: String,
    val user: UserResponse,
    val createdAt: String
)

// Retrofit에서 바로 사용!
@GET("posts")
suspend fun getPosts(): List<PostResponse>

 

2.2 RecyclerView Adapter 데이터

sealed class TodoItem {
    data class Task(val id: Long, val title: String, var isDone: Boolean) : TodoItem()
    data class SectionHeader(val title: String) : TodoItem()
}

// DiffUtil에서 자동 equals 작동!
override fun areContentsTheSame(old: TodoItem, new: TodoItem): Boolean {
    return old == new  // data class가 알아서 비교!
}

 

2.3 Room Entity + Repository

@Entity(tableName = "todos")
data class TodoEntity(
    @PrimaryKey val id: Long,
    val title: String,
    val priority: Int,
    val createdAt: Long
)

@Dao
interface TodoDao {
    @Query("SELECT * FROM todos ORDER BY priority DESC")
    fun getAllTodos(): Flow<List<TodoEntity>>  // Flow도 data class와 완벽 호환!
}

 

2.4 Room Entity + Repository

data class UiState(
    val isLoading: Boolean = false,
    val data: List<User>? = null,
    val error: String? = null
) {
    val isSuccess get() = data != null && !isLoading && error == null
}

// ViewModel에서 사용
private val _uiState = MutableStateFlow(UiState())
val uiState: StateFlow<UiState> = _uiState.asStateFlow()

fun updateData(users: List<User>) {
    _uiState.value = _uiState.value.copy(data = users)  // copy() 마법!
}

 

핵심: Data class는 불변성(immutability) + 편의 메서드

 

 

3. Swift의 Struct와 Kotlin의 Data Class

3.1 비교 표

특징 Swift Struct Kotiln Data Class
타입 Value Type Reference Type
복사 자동 값 복사 명시적 copy()
메모리 Stack/Heap 혼합 항상 Heap
equals 자동(내용) 자동(내용)
toString 자동 description 자동 toString
Thread Safety 완전 안전 val 사용 권장

 

3.2 복사 동작 비교(가장 중요한 차이)

 

Kotlin

// Kotlin: 참조 타입 → copy() 명시 필요
data class User(val name: String, var age: Int)

val user1 = User("철수", 20)
val user2 = user1  // 같은 객체!
user2.age = 25
println(user1.age)  // 25 (같이 바뀜!)

val user3 = user1.copy(age = 30)  // 새 객체!

 

Swift

// Swift: 값 타입 → 자동 복사
struct User {
    let name: String
    var age: Int
}

var user1 = User(name: "철수", age: 20)
var user2 = user1  // 완전 복사!
user2.age = 25
print(user1.age)  // 20 (안 바뀜!)

// 새 객체는 이렇게
var user3 = User(name: user1.name, age: 30)

 

3.3 상태 업데이트 활용 사례

 

Kotlin

// Kotlin - copy()로 불변 업데이트
data class Todo(val id: Long, val title: String, val isDone: Boolean)

val todo = Todo(1, "공부", false)
val updatedTodo = todo.copy(isDone = true)  // 한 줄!
todos = todos.map { if (it.id == todo.id) updatedTodo else it }

 

Swift

// Swift - 직접 새로 생성
struct Todo: Identifiable {
    let id: UUID
    var title: String
    var isDone: Bool
}

let todo = Todo(id: UUID(), title: "공부", isDone: false)
let updatedTodo = Todo(id: todo.id, title: todo.title, isDone: true)
todos = todos.map { $0.id == todo.id ? updatedTodo : $0 }

 

 

참고: Android Studio, Perflexity

'Android' 카테고리의 다른 글

Android Activity Life Cycle(feat. iOS App Life Cycle)  (0) 2026.01.22