๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

ํ›„๊ธฐ, ํšŒ๊ณ 

๐Ÿ—ƒ๏ธ ์ด๊ด€ ์—…๋ฌด ์ค‘ ์ƒ๊ฐํ•ด ๋ณธ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ๊ฐ€์น˜ (Java to Kotlin)

์™œ ์ด ๊ธ€์„ ์“ฐ๊ฒŒ ๋˜์—ˆ์„๊นŒ?

๋ถ€์„œ์—์„œ ์‚ฌ์šฉํ•˜๋Š” Java ํ”„๋กœ์ ํŠธ๋ฅผ Kotlin์œผ๋กœ ์ „ํ™˜ํ•˜๋Š” ์ž‘์—…์„ ๋งก๊ฒŒ ๋˜์—ˆ๋‹ค.
๋ฌธ์ œ๋Š”, ์ด ํ”„๋กœ์ ํŠธ์˜ ๋„๋ฉ”์ธ๋„ ์ œ๋Œ€๋กœ ์•Œ์ง€ ๋ชปํ–ˆ๊ณ , ๊ธฐ์กด ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ถ€์„œ์— ๋‚จ์•„ ์žˆ์ง€๋„ ์•Š์•˜๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ ์ „ํ™˜ ์ž‘์—…๋งŒ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋„ ์•„๋‹ˆ๊ณ , ๊ธฐ์กด์˜ ๋‹ค๋ฅธ ์—…๋ฌด๋“ค๋„ ๋ณ‘ํ–‰ํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด์—ˆ๋‹ค.

์ด๋Ÿฐ ์กฐ๊ฑด์ด๋ผ๋ฉด ๋‹น์—ฐํžˆ ์‹ค์ˆ˜๊ฐ€ ๋‚˜์˜ฌ ์ˆ˜๋ฐ–์— ์—†๋‹ค. ์ฝ”๋“œ ํ•œ ์ค„ ์ˆ˜์ •ํ•  ๋•Œ๋งˆ๋‹ค ‘์ด๊ฒŒ ์ •๋ง ์›๋ž˜ ๊ธฐ๋Šฅ๋Œ€๋กœ ๋™์ž‘ํ• ๊นŒ?’๋ผ๋Š” ์˜๋ฌธ์ด ๋“ค์—ˆ๋‹ค. ๋‹คํ–‰ํžˆ๋„, ์ด ํ”„๋กœ์ ํŠธ์—๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์ž˜ ์ž‘์„ฑ๋˜์–ด ์žˆ์—ˆ๋‹ค. ๋•๋ถ„์— ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์—†์—ˆ๋‹ค๋ฉด ํ›จ์”ฌ ๋” ๋งŽ์€ ์‹œํ–‰์ฐฉ์˜ค๋ฅผ ๊ฒช์—ˆ์„ ๊ฒƒ์ด๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค.

์ด ๊ฒฝํ—˜์„ ๋ฐ”ํƒ•์œผ๋กœ, ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” Java์—์„œ Kotlin์œผ๋กœ ์ „ํ™˜ํ•˜๋Š” ๊ณผ์ •์—์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์–ด๋–ค ๋„์›€์ด ๋˜์—ˆ๋Š”์ง€๋ฅผ ์ •๋ฆฌํ•˜๋ ค ํ•œ๋‹ค. ํŠนํžˆ, ๋‘ ๊ฐ€์ง€ ์ธก๋ฉด์—์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์œ ์šฉํ–ˆ๋‹ค.

  1. ๋ณ€๊ฒฝ ํ›„์—๋„ ๊ธฐ๋Šฅ์ด ์ •์ƒ ๋™์ž‘ํ•˜๋Š”์ง€ ์ฆ‰์‹œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.
  2. ์ด์ „ ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ณ ๋ คํ–ˆ๋˜ ํ•ต์‹ฌ ๋กœ์ง๊ณผ ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™์„ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. (๊ฐœ์ธ์ ์œผ๋กœ ๊ฐœ๋ฐœ ๊ณผ์ •์—์„œ ์Œ“์ธ ์ผ์ข…์˜ ํžˆ์Šคํ† ๋ฆฌ ์—ญํ• ์„ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค.)

๋ถ€์„œ ์ฝ”๋“œ ์ž์ฒด๋ฅผ ๊ฐ€์ ธ์™€์„œ ์„ค๋ช…ํ•  ์ˆ˜๋Š” ์—†๊ธฐ ๋•Œ๋ฌธ์—, ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ๊ฐ€์ƒ์˜ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค์–ด Java์—์„œ Kotlin์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •๊ณผ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ์—ญํ• ์„ ์ •๋ฆฌํ•ด ๋ณด๊ฒ ๋‹ค. ์ด ์˜ˆ์ œ๋Š” ์‹ค์ œ ํ”„๋กœ์ ํŠธ์˜ ์ฝ”๋“œ๊ฐ€ ์•„๋‹Œ, ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“  ๊ฐ€์ƒ์˜ ์ฃผ๋ฌธ(Order) ์‹œ์Šคํ…œ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ๋‹ค.


๊ฐ€์ƒ์˜ ๋„๋ฉ”์ธ: ์ฃผ๋ฌธ ์‹œ์Šคํ…œ(Order System)

์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ๋„๋ฉ”์ธ์œผ๋กœ ์ฃผ๋ฌธ(Order)๊ณผ ๊ด€๋ จ๋œ ๊ฐ„๋‹จํ•œ ์‹œ์Šคํ…œ์„ ์„ค์ •ํ•ด๋ณด์ž. ์ฃผ๋ฌธ์„ ์ƒ์„ฑํ•˜๊ณ , ์ด ๊ธˆ์•ก์„ ๊ณ„์‚ฐํ•˜๋ฉฐ, ํ• ์ธ ์ •์ฑ… ๋ฐ ์ถ”๊ฐ€ ๋น„์šฉ(์˜ˆ: ๋ฐฐ์†ก๋น„, ์ฟ ํฐ ์ ์šฉ ๋“ฑ)์ด ํฌํ•จ๋œ ๋กœ์ง์„ ๊ตฌํ˜„ํ•œ๋‹ค.

ํ•˜์ง€๋งŒ, ๋„๋ฉ”์ธ๊ณผ ๊ธฐํš ์š”๊ตฌ์‚ฌํ•ญ์„ ์ •ํ™•ํžˆ ์ดํ•ดํ•˜์ง€ ๋ชปํ•œ ์ƒํƒœ์—์„œ Kotlin์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์—์„œ ์–ด๋–ค ์‹ค์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š”์ง€๋„ ํ•จ๊ป˜ ์‚ดํŽด๋ณด๊ฒ ๋‹ค.

๊ธฐ์กด Java ์ฝ”๋“œ

import java.util.List;

public class OrderService {
    public int calculateTotalPrice(List<OrderItem> items, DiscountPolicy discountPolicy, ShippingFeeCalculator shippingFeeCalculator) {
        int total = items.stream()
                         .mapToInt(item -> item.getPrice() * item.getQuantity())
                         .sum();
        total = discountPolicy.applyDiscount(total);
        return total + shippingFeeCalculator.calculateShippingFee(total);
    }
}

public class DiscountPolicy {
    public int applyDiscount(int totalPrice) {
        if (totalPrice >= 500) return totalPrice - 50;
        if (totalPrice >= 300) return totalPrice - 20;
        return totalPrice;
    }
}

public class ShippingFeeCalculator {
    public int calculateShippingFee(int totalPrice) {
        return totalPrice >= 400 ? 0 : 30;
    }
}

Java ํ…Œ์ŠคํŠธ ์ฝ”๋“œ

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import java.util.Arrays;

class OrderServiceTest {
    @Test
    void testCalculateTotalPrice() {
        OrderService orderService = new OrderService();
        DiscountPolicy discountPolicy = new DiscountPolicy();
        ShippingFeeCalculator shippingFeeCalculator = new ShippingFeeCalculator();
        List<OrderItem> items = Arrays.asList(
            new OrderItem(200, 2),
            new OrderItem(100, 1)
        );
        assertEquals(430, orderService.calculateTotalPrice(items, discountPolicy, shippingFeeCalculator));
    }
}

Java → Kotlin ์ „ํ™˜ ํ›„ ์ฝ”๋“œ (์ž˜๋ชป๋œ ๋ณ€ํ™˜)

๋‹จ์ˆœํžˆ Java ์ฝ”๋“œ๋ฅผ Kotlin ๋ฌธ๋ฒ•์œผ๋กœ ์˜ฎ๊ธฐ๋Š” ๊ฒƒ๋งŒ ์ƒ๊ฐํ•˜๋‹ค๊ฐ€ ์ฝ”๋“œ ๋กœ์ง์„ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜์ง€ ์•Š๊ณ  ๋ณ€ํ™˜ํ•˜๋ฉด ํ• ์ธ ์ •์ฑ…๊ณผ ๋ฐฐ์†ก๋น„ ๊ณ„์‚ฐ์ด ๋น ์ง€๋Š” ์‹ค์ˆ˜๋ฅผ ์ €์ง€๋ฅผ ์ˆ˜ ์žˆ๋‹ค.

๋ณ€ํ™˜๋œ (์ž˜๋ชป๋œ) Kotlin ์ฝ”๋“œ

class OrderService {
    fun calculateTotalPrice(items: List<OrderItem>): Int {
        return items.sumOf { it.price * it.quantity }
    }
}

Kotlin ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์‹คํ–‰ ๊ฒฐ๊ณผ (์‹คํŒจ)

class OrderServiceTest {
    @Test
    fun `์ด ์ฃผ๋ฌธ ๊ธˆ์•ก ๊ณ„์‚ฐ`() {
        val orderService = OrderService()
        val items = listOf(
            OrderItem(200, 2),
            OrderItem(100, 1)
        )
        assertEquals(430, orderService.calculateTotalPrice(items)) // ์‹คํŒจ: ํ• ์ธ ์ •์ฑ…, ๋ฐฐ์†ก๋น„ ๊ณ„์‚ฐ ๋ˆ„๋ฝ๋จ
    }
}


๊ฒฐ๊ณผ์ ์œผ๋กœ
ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•œ๋‹ค. ์›๋ž˜๋Š” 430์ด ๋‚˜์™€์•ผ ํ•˜๋Š”๋ฐ, ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋Š” 500์ด ๋‚˜์˜จ๋‹ค. ์ด์ „ ์ฝ”๋“œ์—์„œ ์กด์žฌํ–ˆ๋˜ ํ• ์ธ ์ •์ฑ…๊ณผ ๋ฐฐ์†ก๋น„ ๊ณ„์‚ฐ์ด ์ ์šฉ๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.


Kotlin์œผ๋กœ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ˆ˜์ •ํ•œ ์ฝ”๋“œ

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๋•๋ถ„์— ๋ฌธ์ œ๋ฅผ ๋น ๋ฅด๊ฒŒ ๋ฐœ๊ฒฌํ•˜๊ณ  ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

์ˆ˜์ •๋œ Kotlin ์ฝ”๋“œ

class OrderService {
    fun calculateTotalPrice(items: List<OrderItem>, discountPolicy: DiscountPolicy, shippingFeeCalculator: ShippingFeeCalculator): Int {
        val total = items.sumOf { it.price * it.quantity }
        val discountedTotal = discountPolicy.applyDiscount(total)
        return discountedTotal + shippingFeeCalculator.calculateShippingFee(discountedTotal)
    }
}

๋‹ค์‹œ ์‹คํ–‰ํ•œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ (์„ฑ๊ณต)

class OrderServiceTest {
    @Test
    fun `์ด ์ฃผ๋ฌธ ๊ธˆ์•ก ๊ณ„์‚ฐ`() {
        val orderService = OrderService()
        val discountPolicy = DiscountPolicy()
        val shippingFeeCalculator = ShippingFeeCalculator()
        val items = listOf(
            OrderItem(200, 2),
            OrderItem(100, 1)
        )
        assertEquals(430, orderService.calculateTotalPrice(items, discountPolicy, shippingFeeCalculator)) // ์„ฑ๊ณต
    }
}

๊ทธ๋ž˜์„œ ๊ฒฐ๋ก ์€?

์ฒ˜์Œ์—๋Š” ๋‹จ์ˆœํžˆ ์ฝ”๋“œ๋ฅผ Kotlin์œผ๋กœ ์˜ฎ๊ธฐ๋Š” ์ž‘์—…๋งŒ ํ–ˆ์ง€๋งŒ, ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•˜๋ฉด์„œ ๋†“์นœ ์š”๊ตฌ์‚ฌํ•ญ์„ ๊นจ๋‹ฌ์„ ์ˆ˜ ์žˆ๋‹ค. ๋งŒ์•ฝ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์—†์—ˆ๋‹ค๋ฉด, ์‹ค์ˆ˜ํ•œ ์ฑ„๋กœ ๋ฐฐํฌ๋  ๊ฐ€๋Šฅ์„ฑ์ด ์ปธ์„ ๊ฒƒ์ด๋‹ค.

์ด์ฒ˜๋Ÿผ, ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋Š” ๋‹จ์ˆœํžˆ ๋ฒ„๊ทธ๋ฅผ ์žก๋Š” ๊ฒƒ ์ด์ƒ์˜ ์—ญํ• ์„ ํ•œ๋‹ค.

  • ์ฝ”๋“œ ๋ณ€๊ฒฝ ํ›„ ์ •์ƒ ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ์•ˆ์ „๋ง ์—ญํ• ์„ ํ•˜๊ณ ,
  • ์ด์ „ ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ณ ๋ คํ–ˆ๋˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ๊ทœ์น™์„ ๋ณด์กดํ•˜๋Š” ์—ญํ• ๋„ ํ•œ๋‹ค.
  • ๋ฌธ์„œ๋ฅผ ๋‚จ๊ธฐ์ง€ ์•Š๋”๋ผ๋„, ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋งŒ ๋ณด๋ฉด ์–ด๋–ค ์š”๊ตฌ์‚ฌํ•ญ์ด ์žˆ์—ˆ๋Š”์ง€ ์ถ”๋ก ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐœ๋ฐœ ํžˆ์Šคํ† ๋ฆฌ ์—ญํ• ์„ ํ•œ๋‹ค.

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ๊ท€์ฐฎ์„ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ๊ฒฐ๊ตญ ๋ฏธ๋ž˜๋ฅผ ์œ„ํ•œ ๋ณดํ—˜๊ณผ๋„ ๊ฐ™๋‹ค. Kotlin ์ „ํ™˜์„ ํ•˜๋ฉด์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๋•๋ถ„์— ์ˆ˜๋งŽ์€ ์‹œํ–‰์ฐฉ์˜ค๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์—ˆ๊ณ , ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ฐ”๋€Œ๋”๋ผ๋„ ์ฝ”๋“œ์˜ ์‹ ๋ขฐ์„ฑ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

๊ทธ๋ž˜์„œ, ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ๋‹จ์ˆœํ•œ '์„ ํƒ'์ด ์•„๋‹ˆ๋ผ, ๋” ์ข‹์€ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ํ•„์ˆ˜ ๊ณผ์ •์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค. (๋‹ค๋งŒ, ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ์ค‘์š”์„ฑ์„ ๊นจ๋‹ฌ์•˜๋‹ค๊ณ  ํ•ด์„œ ๋ฐ˜๋“œ์‹œ TDD๊ฐ€ ํ•„์ˆ˜๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ์ด๋Š” ๋˜ ๋‹ค๋ฅธ ๋…ผ์˜์˜ ์˜์—ญ์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค...)