JiwonDev

#2. ์ฝ”ํ‹€๋ฆฐ ๊ธฐ์ดˆ๋ฌธ๋ฒ•

by JiwonDev

๐Ÿ“Œ ๋ฉ”์ธํ•จ์ˆ˜(Main) - HelloWorld

Class์— ๊ฐ์Œ€ ํ•„์š”์—†์ด, ๋ฐ”๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

  • ๋ฐ˜ํ™˜๊ฐ’์ด๋‚˜ ํŒŒ๋ผ๋ฉ”ํƒ€๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์ด ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค.

 

  • ๋ฌผ๋ก  ์ƒ๋žต ๊ฐ€๋Šฅํ•œ๊ฑฐ์ง€, ํ•„์š”ํ•˜๋ฉด ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

 

๐Ÿค” ๋ฌธ์ž์—ด์— ์‚ฌ์šฉํ•œ ${..} ์ด๊ฒŒ ๋ญ์ฃ ?

  • ๋ฌธ์ž์—ด์„ ๋งŒ๋“ค ๋•Œ, String template๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํŽธํ•˜๊ฒŒ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

${...}๊ฐ€ ๊ธฐ๋ณธํ˜•์ด๊ณ , ๊ด„ํ˜ธ๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ดํ•ดํ•˜๋ฉด ๋œ๋‹ค.

 

  •  ์ฐธ๊ณ ๋กœ ${null}์€ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฌธ์ž์—ด์ด ์ƒ์„ฑ๋œ๋‹ค.

 

  • """ ์„ ์‚ฌ์šฉํ•˜๋ฉด, ์ค„๋ฐ”๊ฟˆ๊นŒ์ง€ ํฌํ•จํ•œ ์ŠคํŠธ๋ง์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

 

  • ๋ฌธ์ž์—ด์„ ์—ฌ๋Ÿฌ ์ค„ ์ž‘์„ฑํ•  ๋•Œ, trimMargin()๊ณผ trimIndent()์„ ์ด์šฉํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ์กฐ๊ธˆ ๋” ๊น”๋”ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
// ๋ฌธ์ž์—ด ์•ž๋ผ์ธ์— | ๋“ฑ์„ ์‚ฌ์šฉํ•ด์„œ, ๊ฐ€๋…์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค.
fun foo() {
    val heroes = """
        |D.Va
        |Lucio
        |Mercy
        |Soldier: 76
        """.trimMargin() // .trimMargin(marginPrefix = "|") ์™€ ๊ฐ™์€ ๋™์ž‘
}
// ๋˜๋Š” ๊ทธ๋ƒฅ ๋“ค์—ฌ์“ฐ๊ธฐ๋กœ ๊น”๋”ํ•˜๊ฒŒ ์“ฐ๊ณ , trimIndent()๋กœ ๋ชจ๋“  ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ์ œ๊ฑฐํ•ด๋„ ๋œ๋‹ค.
val str1 = """
        Hello World
        var a = 10
        println(a)
    """.trimIndent()

 


๐Ÿ“Œ ๋ณ€์ˆ˜(Variables) - var, val

์ฝ”ํ‹€๋ฆฐ์—์„œ๋Š” ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•  ๋•Œ var, val์„ ์‚ฌ์šฉํ•œ๋‹ค.

  • val (Value): ์ฝ๊ธฐ์ „์šฉ immutable ๋ณ€์ˆ˜. ์ž๋ฐ”์˜ final๊ณผ ๋™์ผํ•˜๋‹ค.
  • var (Variables): ์ผ๋ฐ˜์ ์ธ mutable ๋ณ€์ˆ˜.

์ฐธ๊ณ ๋กœ val๋กœ ๋งŒ๋“  ๋ณ€์ˆ˜๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด, ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

 

๐Ÿค” ํƒ€์ž…์€ ์–ด๋”จ์ฃ ? JS, Python์ฒ˜๋Ÿผ ๋™์ ์œผ๋กœ ๊ฒฐ์ •๋˜๋‚˜์š”?

์•„๋‹ˆ๋‹ค. ์ฝ”ํ‹€๋ฆฐ์€ ์ž๋ฐ”์™€ ๋™์ผํ•˜๊ฒŒ ์ •์ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ์–ธ์–ด์ด๋‹ค. ์ปดํŒŒ์ผ ์‹œ์ ์— ํƒ€์ž…์ด ์ถ”๋ก ๋œ๋‹ค.

์ปดํŒŒ์ผ ์‹œ์ ์— ์œ„์™€ ๊ฐ™์ด ํƒ€์ž…์ด ๊ฒฐ์ •๋œ๋‹ค.

 

์‹ค์ œ๋กœ ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋ฉด ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. Int ๋กœ ๊ฒฐ์ •๋œ ๋ณ€์ˆ˜์— String ์„ ๋Œ€์ž…ํ•˜๊ณ  ์žˆ์–ด์„œ ๊ทธ๋ ‡๋‹ค.

var string = 1 // Int๋กœ ํƒ€์ž…์ด ๊ฒฐ์ •๋จ
string = "abc" // Compiler error: Typemismatch inferred type is String but Int was expected

 

๐Ÿค” ํƒ€์ž…์€ ๋‹ค ์ƒ๋žตํ•˜๊ณ  ์จ๋„ ๋˜๊ฒ ๋„ค์š”?

์•„๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•˜๋ฉด ํƒ€์ž…์„ ๋ช…์‹œํ•ด์ฃผ๋Š”๊ฒŒ ์ข‹๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์€ ์‹ค์ˆ˜๋ฅผ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

  • val ๋Š” ์ž๋ฐ”์˜ final๊ณผ ๊ฐ™๋‹ค๊ณ  ํ–ˆ๋‹ค. ๋ ˆํผ๋Ÿฐ์Šค ํƒ€์ž…, ์ฆ‰ ๊ฐ์ฒด ๋‚ด๋ถ€์˜ ๊ฐ’๊นŒ์ง€ ์ƒ์ˆ˜๋กœ ๋งŒ๋“ค์–ด์ฃผ์ง€๋Š” ์•Š๋Š”๋‹ค.

val๋กœ ์„ ์–ธํ–ˆ๋”๋ผ๋„, ๊ฐ์ฒด ๋‚ด๋ถ€์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ํ•˜์ง€๋งŒ ํƒ€์ž…์ถ”๋ก ์„ ์‚ฌ์šฉํ•˜๊ฒŒ๋˜๋ฉด, val๋กœ ์„ ์–ธํ•œ ๊ฐ’์€ [๋ถˆ๋ณ€ ํƒ€์ž…]์ด ์บ์ŠคํŒ…๋œ๋‹ค. ์ฆ‰ ๊ฐ’์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๋‹ค.
    ์ด๋Š” ๋ถˆ๋ณ€ ํƒ€์ž…์„ ์‚ฌ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด์ง€, val๋กœ ์„ ์–ธํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด ์•„๋‹ˆ๋‹ค. final My myClass = new (..๋‚ด๋ถ€๋Š” ๋ณ€์ˆ˜..)  

์•„๋ž˜์˜ readOnlyList.add(...)๋Š” ์ปดํŒŒ์ผ ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

 


๐Ÿ“Œ ํ•จ์ˆ˜, ๋ฉ”์„œ๋“œ (Functions)

์ฝ”ํ‹€๋ฆฐ์˜ ํ•จ์ˆ˜๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์„ธ๋ฏธ์ฝœ๋ก (;)์€ ์ƒ๋žต๊ฐ€๋Šฅํ•˜๋‹ค.

 

  • ๋ฐ˜ํ™˜๊ฐ’์ด ์—†๋‹ค๋ฉด ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๊ณ , ์•„๋ž˜์™€ ๊ฐ™์ด ๋žŒ๋‹ค์‹์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
    ์ฐธ๊ณ ๋กœ ๋ฐ˜ํ™˜๊ฐ’์„ ์ƒ๋žตํ•˜๋ฉด ์ฝ”ํ‹€๋ฆฐ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” fun method(): Unit๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. Unit์€ ์ž๋ฐ”์˜ void ์™€ ๊ฐ™์€ ์˜๋ฏธ. 

IntelliJ ์˜ Convert to expression ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด ์‰ฝ๊ฒŒ ์ „ํ™˜์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

 

  • Python์„ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด ์ต์ˆ™ํ•˜๊ฒ ์ง€๋งŒ, ๊ธฐ๋ณธ ํŒŒ๋ผ๋ฉ”ํƒ€ ๊ฐ’๊ณผ Named argument๋ฅผ ์ง€์›ํ•œ๋‹ค.
    ๋‚ด๋ถ€์ ์œผ๋กœ Java์˜ ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋กœ๋”ฉ๊ณผ ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•œ๋‹ค. ๊ทธ๋ƒฅ ์‚ฌ์šฉํ•˜๊ธฐ ํŽธํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ค€๊ฑฐ.

์‚ฌ์šฉ๋ฐฉ๋ฒ•์€ python๊ณผ ๋™์ผํ•˜๋‹ค. method( a, b, age=10, isHuman=true)
ํŒŒ๋ผ๋ฉ”ํƒ€ ๊ธฐ๋ณธ๊ฐ’๋„ ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฒƒ๋„ python๊ณผ ๋™์ผ. ํŒŒ๋ผ๋ฉ”ํƒ€ ์ˆœ์„œ ์ง€์ผœ์ค˜์•ผํ•จ

 

  • ์ž๋ฐ”์—์„œ ์ƒ์„ฑ์ž๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์ด ๋งŒ๋“ค์–ด์ง€๋Š”๊ฒŒ ๊ฑฐ์Šฌ๋ฆฐ๋‹ค๋ฉด, @JvmOverloads๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ•์ œ๋กœ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.
    ๋‹ค๋งŒ ๊ตณ์ด ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”๊ฑธ ๊ถŒ์žฅํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค. ์ฝ”ํ‹€๋ฆฐ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ๋ถˆํŽธํ•˜๊ธฐ๋„ ํ•˜๊ณ 

๋ชจ๋“  ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ๋”ฐ์ง„๋‹ค๋ฉด, ์ด 8๊ฐœ์˜ ์ƒ์„ฑ์ž๊ฐ€ ๋งŒ๋“ค์–ด์ง€์ง€๋งŒ ์ด๋ ‡๊ฒŒ 4๊ฐœ๋กœ ์ œํ•œํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

  • ์ฝ”ํ‹€๋ฆฐ์€ ํ•จ์ˆ˜๋ฅผ ์–ด๋””์—์„œ๋“  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ผญ ํด๋ž˜์Šค ์•ˆ์— ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

 

๐Ÿค” ์ฝ”ํ‹€๋ฆฐ๋„ ๊ฒฐ๊ตญ JVM์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์–ด๋–ป๊ฒŒ ํด๋ž˜์Šค ์—†์ด ๋ฉ”์„œ๋“œ๋ฅผ ์“ธ ์ˆ˜๊ฐ€ ์žˆ์ฃ ?

  • ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ํด๋ž˜์Šค๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค. ์ด๋Š” static final ํ•จ์ˆ˜๋กœ ์„ ์–ธ๋˜๋ฉฐ, ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‚ด ์ฝ”ํ‹€๋ฆฐ ํŒŒ์ผ๋ช…์„ (๊ธฐ๋ณธ ํด๋ž˜์Šค๋ช…)์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. ๊ทธ ์•ˆ์— static ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•จ.

 

  • ๋งŒ์•ฝ ์ปดํŒŒ์ผ๋˜๋Š” ๋ฉ”์„œ๋“œ๋ช…์„ ๋ฐ”๊พธ๊ณ  ์‹ถ๋‹ค๋ฉด, @JvmName("~")์„ ์ด์šฉํ•ด์„œ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.
    ์ž๋ฐ”์—์„œ ์ฝ”ํ‹€๋ฆฐ์œผ๋กœ ๋งŒ๋“  ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ์œ ์šฉํ•˜๊ฒŒ ์“ธ ์ˆ˜ ์žˆ๋‹ค.
@JvmName("fooListString")
fun foo(a : List<String>) {
    println("foo(a : List<String>)")
}

@JvmName("fooListInt")
fun foo(a : List<Int>) {
    println("foo(a : List<Int>)")
}

์ด ์ฝ”ํ‹€๋ฆฐ ์ฝ”๋“œ๋Š” ์•„๋ž˜์˜ ์ž๋ฐ” ์ฝ”๋“œ์™€ ๊ฐ™์€ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์–ด๋‚ธ๋‹ค.

public final class MyKotlin{ // MyKotlin.kt

    public static final void fooListString(@NotNull List a) {
       String var1 = "foo(a : List<String>)";
       System.out.println(var1);
    }

    public static final void fooListInt(@NotNull List a) {
       String var1 = "foo(a : List<Int>)";
       System.out.println(var1);
    }
}

 

  • ๋ฌผ๋ก  ๋ฉ”์„œ๋“œ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ์•„์˜ˆ ํด๋ž˜์Šค๋ช…(ํŒŒ์ผ๋ช…)์„ ๋‹ค๋ฅด๊ฒŒ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. @file:JvmName("~")์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

๊ทธ ์™ธ @get:JvmName(), @set:JvmName() ๋“ฑ๋„ ์žˆ๋‹ค.

 


๐Ÿ“Œ ์กฐ๊ฑด๋ฌธ(Conditionals) - if & when

  • ์ฝ”ํ‹€๋ฆฐ์—์„œ๋Š” ์‚ผํ•ญ์—ฐ์‚ฐ์ž(? :)๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค. ์™œ๋ƒํ•˜๋ฉด if-else ๋ฌธ๋ฒ•๊ณผ ๊ธฐ๋Šฅ์ด ๋˜‘๊ฐ™์•„์„œ ํ•„์š”์—†๊ธฐ ๋•Œ๋ฌธ.

if ๋Š” ์ด๊ฒŒ ์ „๋ถ€๋‹ค. ์—ฌ๋Ÿฌ ์ค„์€ if(condition){...} ์“ฐ๋ฉด ๋จ.

 

  • ์ฝ”ํ‹€๋ฆฐ์—์„œ๋Š” ์ž๋ฐ”์˜ switch ๋Œ€์‹ , when์ด๋ผ๋Š” ๋ฌธ๋ฒ•์„ ์ œ๊ณตํ•ด์ค€๋‹ค.
    ๊ธฐ๋ณธ์ ์ธ ์‚ฌ์šฉ๋ฒ•์€ JDK17์˜ ์ƒˆ๋กœ์šด switch๋ฌธ๊ณผ ๊ฑฐ์˜ ๋น„์Šทํ•˜๋‹ค.

return ๋ฐ˜ํ™˜๊ฐ’์— when์„ ๋ฐ•์„ ์ˆ˜ ์žˆ๋‹ค. (JDK17 switch์™€ ๋™์ผ)

 

  • Break๋ฌธ์€ ํ•„์š”์—†๊ณ , ๊ธฐ๋ณธ๊ฐ’์€ else๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

 

  • ์—ฌ๋Ÿฌ ์กฐ๊ฑด์„ ํ•œ ์ผ€์ด์Šค์— ๋„ฃ์„ ์ˆ˜ ์žˆ๊ณ , ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ณต์žกํ•œ ์กฐ๊ฑด๋„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

 

  • is (Type)์„ ์‚ฌ์šฉํ•˜๋ฉด, ๊ฐ์ฒด์˜ ํƒ€์ž…์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ์บ์ŠคํŒ…ํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

Pet์ด ์ƒ์œ„ํƒ€์ž…์ด๊ณ , Cat๊ณผ Dog๊ฐ€ ํ•˜์œ„ํƒ€์ž…
์ด๋ ‡๊ฒŒ ๋™์ž‘ํ•œ๋‹ค. ํ•˜์œ„ํƒ€์ž…์œผ๋กœ ์บ์ŠคํŒ…ํ•ด์ค€๋‹ค.

 

  • when(~) ์•ˆ์—๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ”๋กœ ๋„ฃ์–ด๋„ ๋œ๋‹ค. ๋ฐ˜ํ™˜๊ฐ’์ด ์‚ฌ์šฉ๋œ๋‹ค.

์ฐธ๊ณ ๋กœ ์ด๋Š” Kotlin1.3 (2020๋…„)์— ์ถ”๊ฐ€๋œ ๊ธฐ๋Šฅ์ด๋‹ค.
ํ•จ์ˆ˜์˜ return ๊ณผ ์กฐํ•ฉํ•˜๋ฉด ๋Œ€์ถฉ ์ด๋Ÿฐ ๋ชจ์Šต.

 

  • when์€ ๊ผญ switch์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด ๊ทธ๋ƒฅ case์— ์กฐ๊ฑด์„ ๋ฐ”๋กœ ๋„ฃ์–ด๋„ ๋œ๋‹ค.
    ์ด ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด์„œ ๋ชจ๋“  if๋ฌธ์„ when์œผ๋กœ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ตณ์ด ๊ทธ๋ ‡๊ฒŒ ๋ณ€ํƒœ ๊ฐ™์ด ์‚ฌ์šฉํ•˜์ง€๋Š” ๋ง์ž.

์ž๋ฐ” ์ฝ”๋“œ๋กœ ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜๋ฉด ๊ฐ™์€ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

 

๐Ÿค” "cold" to BLUE..? ์ด๊ฒŒ ๋ฌด์Šจ ๋ฌธ๋ฒ•์ด์ฃ ?

์ฐธ๊ณ ๋กœ ์ฝ”ํ‹€๋ฆฐ์—๋Š” ๊ฐ’์„ ๋ฌถ์„ ์ˆ˜ ์žˆ๋Š” ํŠœํ”Œ์ธ Pair()์™€ Triple()์ด ์ œ๊ณต๋œ๋‹ค.

val (hello, number) = Pair("Hello", 1234)
val (hello, world, number) = Triple("Hello", "World", 1234)

var p: Pair<Int, String> = Pair(5, "Test")
p.first // 5
p.second // "Test"
// to ์ค‘์œ„ํ•จ์ˆ˜๋Š” Pair<String, Int>๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
val pair : Pair<String, Int> = "Hello" to 1234
val (hello, world) = "Hello" to "World"

 

์•„๋งˆ ์˜ˆ์ƒํ–ˆ๊ฒ ์ง€๋งŒ, ์ด๋Š” Immutableํ•œ ํŠœํ”Œ๋กœ, ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณต์‚ฌํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

new = p.copy(first = 3)
val list = pair.toList() // list๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

๋‚˜์ค‘์— ๋‚˜์˜ค๊ฒ ์ง€๋งŒ to ๊ฐ™์€ ์ค‘์œ„ํ•จ์ˆ˜(Infix)๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ๋‹ค.

infix fun Int.multiply(x: Int): Int {
    // infix๋Š” ํ™•์žฅํ•จ์ˆ˜๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.
    return this * x
}


fun main(){
    val ํ™•์žฅํ•จ์ˆ˜ = 3.multiply(10)
    val ์ค‘์œ„ํ•จ์ˆ˜ = 3 multiply 10
	
    println("๊ฒฐ๊ณผ: $ํ™•์žฅํ•จ์ˆ˜, $์ค‘์œ„ํ•จ์ˆ˜")
}

 


๐Ÿ“Œ ๋ฐ˜๋ณต๋ฌธ(Loop) - for in

์ฐธ๊ณ ๋กœ while, do-while๋„ ์กด์žฌํ•˜๋Š”๋ฐ ์ด๋Š” ์ž๋ฐ” ๋ฌธ๋ฒ•๊ณผ ๋™์ผํ•˜๋‹ค. ๊ทธ๋ƒฅ ์“ฐ๋ฉด ๋œ๋‹ค.

 

  • for๋ฌธ์€ python๊ณผ ๋˜‘๊ฐ™๋‹ค. ์•„๋ž˜ ์˜ˆ์ œ๋ฅผ ๋ณด์ž

 

  • ๋‚ด์žฅ ๋ฉ”์„œ๋“œ๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ํ™œ์šฉํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฒƒ๋„ python๊ณผ ๋น„์Šทํ•˜๋‹ค.

list.withIndex๋ฅผ ์ด์šฉํ•ด์„œ ์ธ๋ฑ์Šค์™€ ํ•จ๊ป˜ ๋ฐ›์•„์˜ค๊ธฐ

 

  • range()๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

until์„ ์‚ฌ์šฉํ•˜๋ฉด ์ต์ˆ™ํ•œ ๋ฐ˜๋ณต๋ฌธ์ด ๋‚˜์˜จ๋‹ค.

 

  • infix ํ•จ์ˆ˜๋“ค์„ ์ ์ ˆํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณต์žกํ•œ ์ธ๋ฑ์Šค๋„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

์ฝ”ํ‹€๋ฆฐ์—๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๊ธฐ๋Šฅ์ด ์žˆ์ง€๋งŒ, ์ž๋ฐ”์˜ ๋ฐ˜๋ณต๋ฌธ๊ณผ ๊ธฐ๋Šฅ์€ ๊ฐ™๋‹ค๋Š”๊ฑธ ์ธ์ง€ํ•˜๋ฉด ๋ญ๋“ ์ง€ ์‰ฝ๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

for (c in '0' until '9'){
    print(c)
}
for (char c ='0'; c <'9'; c++){
    System.out.print(c);
}

 


๐Ÿ“Œ ์กฐ๊ฑด ๊ฒ€์‚ฌ - in

  • ์ด๊ฒƒ๋„ python๊ณผ ๋น„์Šทํ•˜๋‹ค. ๋ฐ˜๋ณต๋ฌธ์ด ์•„๋‹ˆ๋”๋ผ๋„ in์œผ๋กœ ์กฐ๊ฑด์„ ๊ฒ€์‚ฌํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

  • in์„ ํ™œ์šฉํ•˜์—ฌ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๊ฑฐ๋‚˜, When ์กฐ๊ฑด์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

  • ์ฐธ๊ณ ๋กœ "String".."String"์€ ๋‹จ์–ด์˜ ์‚ฌ์ „ ์ˆœ์„œ๋ฅผ ๋น„๊ตํ•œ๋‹ค.
    ๋งŒ์•ฝ ์ผ์น˜ํ•˜๋Š”์ง€ ๊ฒ€์‚ฌํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, in setOf(...)๋ฅผ ์‚ฌ์šฉํ•˜์ž
println("Kotlin" in "Java".."Scala")// ์‚ฌ์ „ ์ˆœ์„œ๊ฐ€ ๋‘ ๋‹จ์–ด์˜ ์ค‘๊ฐ„์ธ๊ฐ€? true
println("Kotlin" in setOf("Kotlin","Java")) // ํฌํ•จ์—ฌ๋ถ€ true
println("Kotlin" in setOf("Scala","Java")) // ํฌํ•จ์—ฌ๋ถ€ false

๊ฐ์ฒด(String)๋ฅผ ๋น„๊ต์—ฐ์‚ฐ์œผ๋กœ ๋น„๊ตํ•˜๋ฉด compareTo๋กœ ์บ์ŠคํŒ…๋œ๋‹ค.

 

  • ์ฐธ๊ณ ๋กœ ์ด๋ ‡๊ฒŒ ์ •์˜ํ•œ in ์กฐ๊ฑด์€, ์•„๋ž˜์™€ ๊ฐ™์€ ํƒ€์ž…์œผ๋กœ ์ƒ์„ฑ๋œ๋‹ค.

๋‹น์—ฐํžˆ ๊ธฐ๋ณธ ํƒ€์ž…์ธ IntRange๊ฐ€ ๊ฐ€์žฅ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ๊ฒŒ ๋จน๋Š”๋‹ค. ์„ฑ๋Šฅ๋„ ์ข‹๊ณ &nbsp;

 

  • ์ฆ‰, ์•„๋ž˜์˜ 3๊ฐœ์˜ if๋ฌธ์€ ๊ฐ™์€ ๋™์ž‘์„ ํ•œ๋‹ค๊ณ  ์ดํ•ดํ•˜๋ฉด ๋œ๋‹ค.

๊ฐ์ฒด๋ฅผ ๋น„๊ต์—ฐ์‚ฐํ•˜๋ฉด compareTo๋กœ ๋ณ€ํ™˜๋œ๋‹ค. ์ฆ‰ 3๊ฐœ์˜ if๋ฌธ์€ ๋™์ž‘์ด ๊ฐ™๋‹ค.

 


๐Ÿ“Œ ์˜ˆ์™ธ์ฒ˜๋ฆฌ (Exception)

  • Exception, try-catch-finally, throw๋Š” ์ž๋ฐ”์™€ ๋™์ผํ•˜๋‹ค. ์ฝ”ํ‹€๋ฆฐ ๋ฌธ๋ฒ•์— ๋งž์ถฐ์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

 

  • try-catch๋ฅผ ์—ฐ์‚ฐ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ’์„ ๋ฐ”๋กœ ๋Œ€์ž…ํ•  ์ˆ˜ ์žˆ๋‹ค.
fun readNumber(reader: BufferedReader) {
    val number = try {
        reader.readLine().toInt() // ๊ฐ’ ๋Œ€์ž…
    } catch (e: NumberFormatException) {
        null // null ๋Œ€์ž…
    }
}

 

  • ์ž๋ฐ”์˜ method() throws Exception์€ ์ฝ”ํ‹€๋ฆฐ์—์„œ @Throws(Execption:class)๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

void foo() throws IOException

์ž๋ฐ”์—์„œ๋Š” ์ฒดํฌ์˜ˆ์™ธ(RuntimeException์ด ์•„๋‹Œ ์˜ˆ์™ธ)๋ฅผ ๋ฐ˜๋“œ์‹œ ์ฒ˜๋ฆฌํ•ด์ค˜์•ผํ–ˆ์ง€๋งŒ, ์ฝ”ํ‹€๋ฆฐ์€ ์ด๋ฅผ ๊ฐ•์ œํ•˜์ง€ ์•Š๋Š”๋‹ค.
๋งŒ์•ฝ @Throws๋ฅผ ์ ์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์•„๋ฌด๋Ÿฐ ์˜ˆ์™ธ๋„ ๋ฐ–์œผ๋กœ ๋˜์ง€์ง€ ์•Š๊ณ  ๋ฉ”์„œ๋“œ ๋‚ด์—์„œ ์‚ผ์ผœ๋ฒ„๋ฆฐ๋‹ค.

 


๐Ÿ“Œ ํ™•์žฅ ํ•จ์ˆ˜(Extension Functions)์™€ this

์ฝ”ํ‹€๋ฆฐ์—์„œ๋Š” ํ™•์žฅ ํ•จ์ˆ˜๋ผ๋Š” ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค.

๊ธฐ์กด์— ์ •์˜๋œ ํด๋ž˜์Šค์— ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.

fun ๊ธฐ์กดํด๋ž˜์Šค.myMethod() = ...

ํ™•์žฅํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•  ๋•Œ์—๋Š” this๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. this๋Š” ๊ธฐ์กด ํด๋ž˜์Šค๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
๐Ÿงจ ๋‹น์—ฐํ•œ๊ฑฐ์ง€๋งŒ ๊ธฐ์กดํด๋ž˜์Šค์˜ private ๋ฉ”์„œ๋“œ๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค. ํ•„๋“œ๊ฐ’์ด private๋ผ๋ฉด this.get()์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

์ฐธ๊ณ ๋กœ this๋Š” ์ƒ๋žต์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

 

์ด๋ ‡๊ฒŒ ๋งŒ๋“  ํ™•์žฅํ•จ์ˆ˜๋Š” importํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
์ฐธ๊ณ ๋กœ ์ฝ”ํ‹€๋ฆฐ์˜ ํ™•์žฅํ•จ์ˆ˜๋Š” ์ž๋ฐ”์—์„œ๋Š” ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ static ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋™์ž‘ํ•œ๋‹ค.

๋ฌผ๋ก  import com.example.util.* ์œผ๋กœ ์ „์ฒด๋ฅผ ๊ฐ€์ ธ์™€์„œ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด ๊ธฐ๋ณธํด๋ž˜์Šค String์— ์•„๋ž˜์™€ ๊ฐ™์€ ํ™•์žฅํ•จ์ˆ˜(repeat)๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ์ž๋ฐ” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

fun String.repeat(n: Int): String {...}

 

๋ฌผ๋ก  StringUtilKt ํด๋ž˜์Šค ์ด๋ฆ„์€ ๋ฐ”๋€” ์ˆ˜ ์žˆ๋‹ค.

 

 

  • ํ™•์žฅํ•จ์ˆ˜์˜ ๊ฐ•๋ ฅํ•จ์€, ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ๊ฑด๋“œ๋ฆฌ์ง€์•Š๊ณ  ๋ฉ”์„œ๋“œ ์ฒด์ด๋‹(Curring)์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ์•„๋ž˜์™€ ๊ฐ™์€ ๊ณ ์ „์ ์ธ sum()ํ•จ์ˆ˜๊ฐ€ ์žˆ์„ ๋•Œ

fun sum(list: List<Int>): Int {
    var result = 0
    for (i in list) {
        result += i
    }
    return result
}

fun main(args: Array<String>) {
    val sum = sum(listOf(1, 2, 3))
}

ํ™•์žฅํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค. (์ฐธ๊ณ ๋กœ IntelliJ Convert parameter to receiver๋กœ ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค)

// ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋งŒ ํ™•์žฅํ•จ์ˆ˜๋กœ ๋ณ€๊ฒฝํ•จ.
fun List<Int>.sum(): Int {
    var result = 0
    for (i in list) {
        result += i
    }
    return result
}

fun main(args: Array<String>) {
    val sum = listOf(1, 2, 3).sum()
}

 

  • ๐Ÿงจ ํ™•์žฅํ•จ์ˆ˜๋Š” ๊ฐ์ฒด์˜ ํƒ€์ž…์œผ๋กœ ๋งค์นญ๋œ๋‹ค.
    ๋งŒ์•ฝ ๋‹คํ˜•์„ฑ์„ ํ™œ์šฉํ•ด์„œ val parent = Child() ์œผ๋กœ ์„ ์–ธํ•˜๋”๋ผ๋„. ํ™•์žฅํ•จ์ˆ˜๋Š” ํƒ€์ž…์„ ๊ธฐ์ค€์œผ๋กœ ๋งค์นญ๋œ๋‹ค.

์œ„ ์ฝ”๋“œ๋Š” "parent"๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. ์‚ฌ์‹ค ์ž๋ฐ” ์ฝ”๋“œ๋ฅผ ์ƒ๊ฐํ•ด๋ณด๋ฉด ๋‹น์—ฐํ•œ ์‚ฌ์‹ค.

 

  • ๊ฐ์ฒด ์•ˆ์— ๊ฐ™์€ ํ•จ์ˆ˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ๊ฐ€์ง„ ๋ฉค๋ฒ„ ํ•จ์ˆ˜๊ฐ€ ์กด์žฌํ•œ๋‹ค๋ฉด, ํ™•์žฅํ•จ์ˆ˜๋ณด๋‹ค ๋จผ์ € ์‹คํ–‰๋œ๋‹ค.
    ์–ด์ฐŒ๋ณด๋ฉด ๋‹น์—ฐํ•œ ์‚ฌ์‹ค. ๋ฌผ๋ก  ์ด๋ ‡๊ฒŒ ํ™•์žฅํ•จ์ˆ˜๊ฐ€ ๊ฐ€๋ ค์ง€๋ฉด ์ปดํŒŒ์ผ warning์„ ๋„์›Œ์ค€๋‹ค.
    ๋ฌผ๋ก  ์ด๋ฆ„๋งŒ ๊ฐ™๊ณ , ํŒŒ๋ผ๋ฉ”ํƒ€๋‚˜ ๋ฐ˜ํ™˜๊ฐ’์ด ๋‹ค๋ฅด๋‹ค๋ฉด ๊ฐ€๋ ค์ง€์ง€ ์•Š๋Š”๋‹ค.

๊ฐ์ฒด ์•ˆ์— ์„ ์–ธ๋œ ๋ฉค๋ฒ„ํ•จ์ˆ˜๊ฐ€ ์šฐ์„ ๊ถŒ์„ ๊ฐ€์ง„๋‹ค.


๐Ÿ“Œ ์ฝ”ํ‹€๋ฆฐ์˜ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • ์ฝ”ํ‹€๋ฆฐ์€ ์ž๋ฐ” ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(ex ์ปฌ๋ ‰์…˜ ํ”„๋ ˆ์ž„์›Œํฌ)๋ฅผ ์ „๋ถ€ ์ œ๊ณตํ•œ๋‹ค.

๋ฌธ๋ฒ•์ด ๋‹ค๋ฅผ ๋ฟ, ์ฐ์–ด๋ณด๋ฉด JDK ์ž๋ฐ” ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.

 

  • ๊ฑฐ๊ธฐ์— ์ถ”๊ฐ€์ ์œผ๋กœ ์ฝ”ํ‹€๋ฆฐ๋งŒ์˜ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ์ œ๊ณตํ•œ๋‹ค. ์ด๋Š” JDK๋งŒ ์žˆ์œผ๋ฉด ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
    ์ฐธ๊ณ ๋กœ ์ฝ”ํ‹€๋ฆฐ ์ „์šฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ์ปดํŒŒ์ผ์‹œ ์ž‘์€ JAR๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„๋˜์–ด์žˆ๋‹ค.

์ž๋ฐ”์—๋Š” ์—†๋Š” ์ฝ”ํ‹€๋ฆฐ ์ปฌ๋ ‰์…˜์˜ ์ถ”๊ฐ€๋ฉ”์„œ๋“œ(ํ™•์žฅํ•จ์ˆ˜)
์ฐธ๊ณ ๋กœ ํ™•์žฅํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜๋ฉด ์‰ฝ๊ฒŒ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ) getOrNull(index)

 


๐Ÿ“Œ infix, ์ค‘์œ„ ํ•จ์ˆ˜ ( 1 until 10 , a to b)

์ฝ”ํ‹€๋ฆฐ์—์„œ๋Š” infix ํ‚ค์›Œ๋“œ๋ฅผ ํ†ตํ•ด ํ™•์žฅ ํ•จ์ˆ˜๋ฅผ ์ค‘์œ„ ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ญ”๊ฐ€ ํŠน๋ณ„ํ•ด์ง€๋Š”๊ฑด ์•„๋‹ˆ๊ณ , ์œ„ ์˜ˆ์ œ์—์„œ ๋ณธ๊ฒƒ์ฒ˜๋Ÿผ ํ•จ์ˆ˜๋ฅผ ํž™-ํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

infix fun Int.multiply(x: Int): Int {
    return this * x
}

fun main() {
    // ์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜ ์‚ฌ์šฉ๋ฒ•
    val value = 3.multiply(10)
    
    // ์ค‘์œ„(infix) ํ•จ์ˆ˜ ์‚ฌ์šฉ๋ฒ•
    val value = 3 multiply 10
}

 

์•ž์—์„œ ๋ดค๋˜ Pair๋„ ์ฝ”ํ‹€๋ฆฐ์˜ ํŠน๋ณ„ํ•œ ๊ธฐ๋Šฅ์ด ์•„๋‹ˆ๋ผ, ์ค‘์œ„ ํ™•์žฅํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ํ•œ ๊ฒƒ์ด๋‹ค.

a to b

 


๐Ÿ“Œ toInt(), toIntOrNull(), toRegex()

์ฝ”ํ‹€๋ฆฐ์˜ ํ™•์žฅํ•จ์ˆ˜ ๋•๋ถ„์—, ์žฌ๋ฐŒ๋Š” ํ‘œ์ค€๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ๋งŽ์ด ์กด์žฌํ•œ๋‹ค.

๋Œ€ํ‘œ์ ์œผ๋กœ """~""".toRegex()๋กœ ์ •๊ทœํ‘œํ˜„์‹ Regex ๊ฐ์ฒด๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

 

Integer.toInt() ์ด๋Ÿฐ ๊ฒƒ๋“ค๋„, ํ™•์žฅํ•จ์ˆ˜๋กœ ์‰ฝ๊ฒŒ ์“ธ ์ˆ˜ ์žˆ๊ฒŒ ๊ตฌํ˜„ํ•ด๋†“์•˜๋‹ค.

์ฐธ๊ณ ๋กœ toXxxOrNull ์„ ์‚ฌ์šฉํ•˜๋ฉด ์˜ˆ์™ธ ๋Œ€์‹  null์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

 

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

JiwonDev

JiwonDev

ํ™œ๋™ํ•˜๊ธฐ