with ChatGPT/코틀린 with ChatGPT

[코틀린 with ChatGPT #10] 코틀린의 클래스(Class)와 객체(Object)를 어떻게 정의하고 사용하는가?

dev_writer 2025. 3. 24. 09:00
with ChatGPT 시리즈는 ChatGPT의 내용과 개인의 생각을 토대로 학습해 보는 컨텐츠입니다.

 

Kotlin은 객체지향의 기본 개념을 간결하게 표현할 수 있도록 설계된 언어입니다.

Java보다 코드량이 훨씬 적고, 클래스의 구조를 명확하게 표현할 수 있다는 장점이 있습니다.

 

이번 글에서는 Kotlin에서 클래스와 객체를 어떻게 정의하고 사용하는지, 그리고 자바와의 차이점은 무엇인지 살펴보겠습니다.

🔹 1. 클래스 정의와 생성자

Kotlin에서는 클래스 선언과 생성자를 한 줄로 표현할 수 있습니다.

class User(val name: String, val age: Int)
  • val: 읽기 전용 (immutable) 프로퍼티
  • var: 읽고 쓰기 가능한 (mutable) 프로퍼티
  • 생성자 파라미터는 자동으로 클래스 프로퍼티로 선언

자바 코드로 따지면 다음과 같습니다:

public class User {
    private final String name;
    private int age;
    
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() { return name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
}

✅ 클래스 본문과 init 블록

class User(val name: String) {
    init {
        println("사용자가 생성됨: $name")
    }
    
    fun greet() {
        println("안녕하세요, $name입니다.")
    }
}
  • init 블록은 주 생성자 호출 직후 실행되는 초기화 코드

🔹 2. 객체 생성 및 기본값

✅ 객체 생성은 new 없이

val user = User("Alice", 30)
  • Kotlin에서는 new 키워드 없이 바로 인스턴스 생성 가능

✅ 기본값이 있는 생성자

class ApiResponse(val status: String = "OK", val code: Int = 200)

val response = ApiResponse(code = 404)
  • 불필요한 생성자 오버로딩 없이 다양한 초기화 가능
  • Named Argument와 함께 사용하면 실무에서 매우 유용

🔹 3. 접근 제어자와 프로퍼티 캡슐화

✅ Kotlin의 기본 접근자는 public이지만, 실무에서는 캡슐화가 중요합니다.

class Account(private val id: String, var balance: Int) {
    fun deposit(amount: Int) {
        balance += amount
    }
}
  • id는 외부에서 접근 불가능
  • balance는 외부에서 읽고 쓸 수 있음 → 필요에 따라 private set으로 보호 가능
class SafeAccount(val id: String, balance: Int) {
    var balance: Int = balance
        private set
}
  • 위와 같이 하면 읽기는 가능하지만, 클래스 외부에서 balance 변경 불가

🔹 4. companion object: Java의 static을 대체하는 Kotlin 방식

Kotlin에서는 static 키워드가 없고, 대신 정적 멤버는 companion object를 사용합니다.

class Logger {
    companion object {
        fun log(message: String) {
            println("LOG: $message")
        }
    }
}

Logger.log("Hello") // static처럼 호출 가능
  • companion object는 해당 클래스에 소속된 싱글턴 객체
  • 내부적으로는 Logger.Companion.log(...) 형태지만, 직접 Logger.log()처럼 호출 가능

✅ Java의 static과 Kotlin companion object 비교

항목 Java (static) Kotlin (companion object)
선언 방식 static 키워드 companion object 블록
접근 방식 ClassName.method() 동일 (ClassName.method())
객체인가? ❌ 아님 ✅ 객체로 존재함
인터페이스 구현 불가 가능

✅ 인터페이스 구현 예시

interface Factory<T> {
    fun create(): T
}

class User(val name: String) {
    companion object : Factory<User> {
        override fun create(): User = User("default")
    }
}
  • companion object는 객체이기 때문에 인터페이스를 구현할 수 있음
  • 이 패턴은 Spring에서 @Converter, @Deserializer 같은 구조 구현 시 유용

 

🚀 결론

기능 Kotlin 방식 특징
클래스 정의 class User(val name: String) 생성자와 프로퍼티를 간결하게 표현
객체 생성 User("Alice") new 키워드 없음
초기화 블록 init { ... } 생성자 직후 실행
프로퍼티 접근 제어 private, private set 등 읽기/쓰기 범위를 명확히 제어
정적 멤버 companion object Java의 static을 대체, 객체 기반

 

🤔 추가로 생각해 볼 질문들

  1. Kotlin에서 private set을 활용하면 어떤 상황에서 유용할까?
  2. companion object와 object 키워드는 어떤 차이를 가질까?
  3. Kotlin에서는 정적 유틸리티 함수는 어떻게 관리하는 것이 좋을까? (top-level function vs companion object)
  4. 여러 개의 companion object를 허용하지 않는 이유는 무엇일까?
  5. companion object와 Java static 유틸리티 클래스의 실제 메모리 차이는?