BE/Kotlin

[Kotlin] 코틀린 문법 4 (apply, let, also, run, with)

baek-dev 2025. 2. 18. 22:15

Kotlin에서는 apply, let, also, run, with 같은 스코프 함수(Scope Functions) 를 제공하여 객체를 더 간결하고 읽기 쉽게 다룰 수 있도록 함.

이 함수들은 객체의 상태를 변경하거나 임시적인 컨텍스트에서 특정 작업을 수행할 때 유용함.

 

Java에서는 이러한 기능을 Optional, Stream API, 람다 표현식 등을 활용하여 비슷하게 구현할 수 있음.

Kotlin과 Java의 차이를 비교하면서 각 함수의 역할을 정리해 보겠음.

 

🛠️ 1. apply

객체의 설정(초기화)을 수행한 후, 객체 자신을 반환함.

this를 사용하여 객체 내부의 속성 변경 가능함.

Java에서는 보통 생성자 내부에서 직접 설정하거나 빌더 패턴을 사용함.

 

✅ Java 코드 (빌더 패턴 활용)

class User {
    String name;
    int age;
    
    public User setName(String name) {
        this.name = name;
        return this;
    }
    
    public User setAge(int age) {
        this.age = age;
        return this;
    }
    
    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + "}";
    }
}

User user = new User()
    .setName("김철수")
    .setAge(30);

System.out.println(user); // User{name='김철수', age=30}

→ Java에서는 apply와 유사한 기능을 setter 메서드 체이닝을 통해 구현함.

하지만 Kotlin에서는 apply를 사용하면 더 간결하고 직관적으로 표현할 수 있음.

 

✅ Kotlin 코드 (apply)

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

val user = User("홍길동", 25).apply {
    name = "김철수"
    age = 30
}
println(user) // User(name=김철수, age=30)

→ apply를 사용하여 객체를 초기화하고, 최종적으로 변경된 객체를 반환함.

 

🛠️ 2. let

객체를 인자로 받아서 특정 작업을 수행한 후, 새로운 값을 반환함.

it을 사용하여 객체를 참조함.

Java에서는 Optional.map() 을 활용하여 비슷한 효과를 낼 수 있음.

 

✅ Java 코드 (Optional.map())

import java.util.Optional;

class User {
    String name;
    int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }
}

User user = new User("김철수", 40);

int nameLength = Optional.ofNullable(user)
    .map(User::getName)
    .map(String::length)
    .orElse(0);

System.out.println(nameLength); // 3

→ Java에서는 Optional.map()을 사용하여 null 체크 후 특정 연산을 수행할 수 있음.

하지만 Kotlin에서는 ?.let을 활용하면 더 간단하게 표현할 수 있음.

 

✅ Kotlin 코드 (let)

val user: User? = User("김철수", 40)

val userNameLength = user?.let {
    println("User name is: ${it.name}")
    it.name.length
}

println(userNameLength) // 3 (김철수 → 3글자)

→ let을 사용하면 객체가 null이 아닐 때 특정 작업을 수행한 후 새로운 값을 반환할 수 있음.

 

🛠️ 3. also

객체를 인자로 받아서 특정 로직을 수행한 후, 원본 객체를 반환함.

디버깅 및 로깅(logging) 할 때 유용함.

Java에서는 일반적으로 System.out.println()을 활용하여 디버깅을 수행함.

 

✅ Java 코드 (일반적인 로그 출력)

User user = new User("김철수", 45);
System.out.println("Creating user: " + user);

→ Java에서는 System.out.println()을 직접 사용하여 로그를 출력해야 함.

Kotlin에서는 also를 사용하여 객체를 유지하면서 추가 작업을 수행할 수 있음.

 

✅ Kotlin 코드 (also)

val user = User("김철수", 45).also {
    println("Creating user: $it")
}

→ also는 객체를 변경하지 않고 로깅 같은 부가적인 작업을 수행하는 데 사용함.

 

🛠️ 4. run

객체의 설정과 함께 특정 로직을 수행하고, 마지막 결과 값을 반환함.

apply와 다르게 블록의 마지막 결과를 반환함.

Java에서는 일반적으로 객체를 생성한 후 메서드를 호출하여 원하는 결과를 얻음.

 

✅ Java 코드 (일반적인 메서드 호출)

User user = new User("이영희", 18);
user.setName("김철수").setAge(25);
String result = "이름 변경 완료: " + user.name;

System.out.println(result); // "이름 변경 완료: 김철수"

→ Java에서는 run과 같은 기능을 메서드 체이닝과 별도의 변수 할당으로 구현해야 함.

 

✅ Kotlin 코드 (run)

val user = User("이영희", 18).run {
    name = "김철수"
    age = 25
    "이름 변경 완료: $name"
}
println(user) // "이름 변경 완료: 김철수"

→ run을 사용하면 특정 연산을 수행한 후, 마지막 표현식의 결과를 반환할 수 있음.

 

🛠️ 5. with

객체 내부에서 여러 작업을 수행할 때 사용하며, this를 기본 컨텍스트로 사용함.

객체를 전달받지만, 결과 값은 블록의 마지막 값을 반환함.

Java에서는 일반적으로 객체의 메서드를 연속 호출하는 방식으로 처리함.

 

✅ Java 코드 (일반적인 메서드 호출)

User user = new User("김철수", 50);

String result = "이름: " + user.name + ", 나이: " + user.age;
System.out.println(result);

→ Java에서는 with 없이 직접 객체의 프로퍼티를 접근하여 문자열을 생성해야 함.

Kotlin에서는 with를 활용하면 더 깔끔하게 처리할 수 있음.

 

✅ Kotlin 코드 (with)

val user = User("김철수", 50)

val result = with(user) {
    println("User name: $name")
    println("User age: $age")
    "이름: $name, 나이: $age"
}
println(result) // "이름: 김철수, 나이: 50"

→ with는 여러 프로퍼티를 다룰 때 this를 활용하여 코드의 가독성을 높여줌.

 

🔥 정리: apply, let, also, run, with 비교표

함수 객체 반환 결과 반환 this or it 사용용도
apply O X this 객체 설정
(초기화, 프로퍼티 변경)
let X O it 연산 수행 후 값 반환
안전 호출과 변환
(Nullable처리, 새로운 값 반환)
also O X it 로깅 및 부가 작업
객체 유지 + 추가 로직 수행
(디버깅, 로깅)
run X O this 객체 설정 후 결과 반환
(객체 없이 블록 실행도 가능)
with X O this 여러 작업 수행
객체를 컨텍스트로 작업 수행 후 결과 반환

 

 

 

 

출처 : ChatGPT