๐Ÿ”ฅ TIL - Day 71 Kotlin & Springboot 02 null-safety (? ?. ?:)

Kim Dae Hyunยท2021๋…„ 12์›” 13์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
82/93

๐Ÿ“Œ kotlin null-safety

null์„ ์ฐธ์กฐํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” NullPointerExeption(NPE)๊ฐ€ ํ„ฐ์ง€๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•œ๋‹ค.
์—ฌ๊ธฐ์„œ ๋ฐฉ์ง€๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์— NPE๋ฅผ ์ฐพ์•„๋‚ด๋Š” ๊ฒƒ์ด๋‹ค.

[ java ]
[ ์•„๋ž˜ ์ฝ”๋“œ๋Š” ์‹คํ–‰๋˜๊ณ  ๋Ÿฐํƒ€์ž„์— NPE๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. ]

String str = "str";
str = null; 
[ Kotlin ]
[ ์–ด๋ž˜ ์ฝ”๋“œ๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์— ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. ]

str: String = "str"
str = null

Kotlin์—์„œ null์„ ํ—ˆ์šฉํ•˜๊ณ ์ž ํ•œ๋‹ค๋ฉด? (nullable)

var str: String? = "str"
str = null

null์„ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋Š”๋ฐ null์„ ์ฐธ์กฐํ•ด์„œ NPE๊ฐ€ ํ„ฐ์ง€๋Š” ์ƒํ™ฉ์„ ์›ํ•˜๋Š” ๊ฒƒ์€ ์ ˆ๋Œ€ ์•„๋‹ˆ๋‹ค. ์•ˆ์ „ํ•˜๊ฒŒ null์„ ํ—ˆ์šฉํ•˜๋Š” ํ”„๋กœํผํ‹ฐ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์ด๋ฅผ ์œ„ํ•ด ?. ๋ฌธ๋ฒ•์„ ์ง€์›ํ•œ๋‹ค.
?.๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์™ผ์ชฝ ํ”„๋กœํผํ‹ฐ๊ฐ€ null์ด๋ผ๋ฉด ์ฐธ์กฐ์—ฐ์‚ฐ์˜ ๊ฒฐ๊ณผ null์„ ๋ฆฌํ„ดํ•˜๊ณ  null์ด ์•„๋‹ˆ๋ผ๋ฉด ์ •์ƒ์ ์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

fun test() {
    var str: String? = "str"
    println(str?.length)

    str = null
    print(str?.length)
}

๋‹ค์Œ์œผ๋กœ ์—˜๋น„์Šค ์—ฐ์‚ฐ์ž์ด๋‹ค. ?:
์—˜๋น„์Šค ์—ฐ์‚ฐ์ž๋Š” null์„ ์ฐธ์กฐํ–ˆ์„ ๋•Œ null์ด ์•„๋‹Œ ํŠน์ • ๊ฐ’์„ ๋ฆฌํ„ดํ•  ์ˆ˜ ์žˆ๋‹ค.

fun test() {
    var str: String? = "str"
    println(str?.length)

    str = null
    print(str?.length ?: "์ด๊ฑด null..")
}


null safetyํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ต์ˆ™ํ•˜์ง€ ์•Š์•„์„œ ์ƒ๊ฐ๋ณด๋‹ค ๋ฒˆ๊ฑฐ๋กญ๋‹ค. ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค๋ฅผ ๊ตฌ์„ฑํ•  ๋•Œ idํ•„๋“œ๋Š” ๋ฐ˜๋“œ์‹œ ? ํƒ€์ž…์ด ๋œ๋‹ค. (save๋  ๋•Œ idํ•„๋“œ๊ฐ€ ์ฑ„์›Œ์ง€๊ธฐ ๋•Œ๋ฌธ) id๊ฐ’์€ ๊ต‰์žฅํžˆ ๋นˆ๋ฒˆํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๋Š”๋ฐ ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค ๋ณ„๊ฑฐ ์•„๋‹ˆ์ง€๋งŒ ๋ถ€๊ฐ€์ ์ธ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ๊ฒƒ์ด ๊ฝค๋‚˜ ๋ฒˆ๊ฑฐ๋กญ๋‹ค. (์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์ด ๋‚œ๋‹ค..)

ํ•˜์ง€๋งŒ ์ด ๊ฒฐ๊ณผ NPE๋ฅผ ๋งŒ๋‚˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ถฉ๋ถ„ํžˆ ๊ฐ€์น˜๊ฐ€ ์žˆ๋Š” ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ•œ๋‹ค.


๐Ÿ“Œ ์ ์šฉํ•ด๋ณด๊ธฐ

Member ์—”ํ‹ฐํ‹ฐ์˜ id๊ฐ’์œผ๋กœ Member๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์ƒ๊ฐํ•ด๋ณด์ž.
Java์˜ ๊ฒฝ์šฐ JPA ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ findById ๋ฉ”์„œ๋“œ๋Š” Optionalํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
์ด ๋ถ€๋ถ„์„ kotlin null-safety๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ˜„ํ•ด๋ณธ๋‹ค.

@Transactional(readOnly = true)
fun getMember(memberId: Long) : MemberResponseDto {
    // ์ผ๋ฐ˜์ ์ธ findById๋Š” java์˜ Optional์„ ๋ฆฌํ„ดํ•œ๋‹ค.
    // findByIdOrNull๊ณผ ์—˜๋น„์Šค ํ‘œํ˜„์‹์œผ๋กœ findById๋ฅผ ๋Œ€์‹ ํ•œ๋‹ค.
    val findMember: Member = memberRepository.findByIdOrNull(memberId) ?: throw IllegalArgumentException("์กด์žฌํ•˜์ง€ ์•Š๋Š” ID ์ž…๋‹ˆ๋‹ค.")

    return MemberResponseDto(findMember.id, findMember.username)
}

findByIdOrNull ๋ฉ”์„œ๋“œ๋Š” ์กฐํšŒ๊ฒฐ๊ณผ๊ฐ€ ์—†๋‹ค๋ฉด null์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
?: ์—˜๋น„์Šค ํ‘œํ˜„์‹์„ ์ด์šฉํ•ด์„œ null ๊ฐ’์— ๋Œ€ํ•ด ๋™์ž‘์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์œ„ ์˜ˆ์ •์˜ ๊ฒฝ์šฐ null ์ธ ๊ฒฝ์šฐ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผฐ๋‹ค.

profile
์ข€ ๋” ์ฒœ์ฒœํžˆ ๊นŒ๋จน๊ธฐ ์œ„ํ•ด ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ๐Ÿง

0๊ฐœ์˜ ๋Œ“๊ธ€