์ˆํผํ”Œ๋ ˆ์ด(์œ ํŠœ๋ธŒ์‡ผ์ธ , ๋ฌด๋ฃŒ ๋™์˜์ƒ)
Hello! I am a mobile app developer and leader with more than 10 years of experience. In particular, I havedeveloped video streaming Android apps and live related services, and I am working to grow video OTT service apps and player SDKs with development team members, value user feedback, value data, and promote organizational and corporate profits based on technology.

3ํ™”.๊ฐœ๋ฐœ์—…๋ฌด์™€ ๊ด€๋ จ๋œ ๋ฌธํ™” ์ฝ”๋”ฉ ๊ทœ์น™ ์ •ํ•˜๊ธฐ

๋”ฉ ๊ทœ์น™์ด ์™œ ํ•„์š”ํ•œ์ง€, ๊ทธ๋ฆฌ๊ณ  Kotlin ๊ธฐ๋ฐ˜์˜ ์‹ค์ „ ์ฝ”๋”ฉ ๊ทœ์น™๊ณผ ์ ์šฉ ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋”ฉ ์Šคํƒ€์ผ ํ†ต์ผ, ์ฝ”๋“œ ๋ฆฌ๋ทฐ ํšจ์œจํ™”, Klint ๊ฐ™์€ ์ž๋™ํ™” ๋„๊ตฌ ํ™œ์šฉ๊นŒ์ง€ ๊ฐœ๋ฐœ ๋ฌธํ™” ์ •๋ฆฝ์„ ์œ„ํ•œ ๊ตฌ์ฒด์ ์ด๊ณ  ์‹ค์งˆ์ ์ธ ๊ฐ€์ด๋“œ๋ฅผ ํ™•์ธํ•ด๋ณด์„ธ์š”.

์ฝ”๋”ฉ ๊ทœ์น™ ์ •ํ•˜๊ธฐ


๊ฐœ๋ฐœ ์—…๋ฌด์—์„œ ๊ทœ์น™์„ ์ •ํ•˜๋Š” ๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ์ค‘์š”ํ•œ์ง€๋Š” ๋ชจ๋‘๊ฐ€ ์•Œ๊ณ  ์žˆ์„ ๊ฒƒ์ด๋‹ค.

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

์ฝ”๋”ฉ๊ทœ์น™


์ฝ”๋”ฉ ๊ทœ์น™์„ ์ •ํ•˜๋ฉด ์ข‹์€ ์ด์œ 

  • ์ฝ”๋“œ์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์ด ์‰ฌ์›Œ์ง„๋‹ค.

  • ์‹ ๊ทœ ์ž…์‚ฌ์ž๋‚˜ ์™ธ๋ถ€ ํ˜‘์—…์ž๊ฐ€ ๋“ค์–ด์™€๋„ ๋น ๋ฅด๊ฒŒ ์ ์‘ ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ์ฝ”๋“œ ๋ฆฌ๋ทฐ ์‹œ ๊ทœ์น™ ๊ธฐ๋ฐ˜์œผ๋กœ ๋…ผ์˜๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ์ฝ”๋“œ ํ’ˆ์งˆ์ด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋†’์•„์ง€๊ณ , ๊ฐ€๋…์„ฑ์ด ๊ฐœ์„ ๋œ๋‹ค.

  • ์ •์  ๋ถ„์„ ๋„๊ตฌ(์˜ˆ: Ktlint)์™€ ์—ฐ๊ณ„ํ•˜์—ฌ ์ฝ”๋“œ ํ’ˆ์งˆ์„ ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ๋‹ค.


๋‚˜์˜ ๊ฒฝ์šฐ Kotlin, Java ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐœ๋ฐœ์„ ์ฃผ๋กœ ํ•ด์™”์œผ๋ฉฐ, ์ตœ๊ทผ์—๋Š” AI ๊ด€๋ จ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•˜๊ณ  ์žˆ๋‹ค.

ํŠนํžˆ Kotlin์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ๊ธฐ๋ณธ์ ์ธ ์ฝ”๋”ฉ ๊ทœ์น™์„ ์ •๋ฆฌํ•˜๊ณ  ์ƒํ™ฉ์— ๋งž๊ฒŒ ์ถ”๊ฐ€ ๊ทœ์น™์„ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ํšจ๊ณผ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค.


์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.


isEmpty:Boolean = false
//์•„๋ž˜ 2๊ฐ€์ง€๋Š” ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•˜๋Š”๋ฐ sonarqube ์—์„œ๋Š” ์ฒซ๋ฒˆ์งธ๋Š” ํ†ต๊ณผ ์•„๋ž˜๋Š” ์‹คํŒจ๋กœ ๋‚˜์˜จ๋‹ค. 
//๊ฐœ์ธ์ ์œผ๋กœ๋Š” ๋‘๋ฒˆ์งธ๊ฐ€ ๊ฐ€๋…์„ฑ ์ธก๋ฉด์—์„œ๋Š” ์ข‹๋‹ค๊ณ  ๋ณด์ง€๋งŒ ์ƒํ™ฉ์— ๋”ฐ๋ผ์„œ ๊ทœ์น™์„ ์ •ํ•˜๋ฉด ๋œ๋‹ค.
if(!isEmpty) 
if(isEmpty == false)


์œ„ ๋‘ ์ฝ”๋“œ๋Š” ๊ฐ™์€ ๋™์ž‘์„ ํ•˜์ง€๋งŒ SonarQube ๊ธฐ์ค€์—์„œ๋Š” ์ฒซ ๋ฒˆ์งธ๊ฐ€ ํ†ต๊ณผ๋˜๊ณ  ๋‘ ๋ฒˆ์งธ๋Š” ์‹คํŒจํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค. ๊ฐ€๋…์„ฑ ๊ด€์ ์—์„œ๋Š” ๋‘ ๋ฒˆ์งธ๊ฐ€ ๋ช…ํ™•ํ•˜๋‹ค๊ณ  ๋ณด์ง€๋งŒ, ํŒ€์˜ ์ƒํ™ฉ๊ณผ ๋„๊ตฌ ๊ธฐ์ค€์— ๋”ฐ๋ผ ๊ทœ์น™์„ ํ†ต์ผํ•ด์•ผ ํ•œ๋‹ค


Kotlin ์ฝ”๋”ฉ ๊ทœ์น™ ์ฃผ์š” ํฌ์ธํŠธ

  • Kotlin ๊ธฐ๋ณธ ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ๋ฅผ ๋”ฐ๋ฅธ๋‹ค.

  • ๋ณ€์ˆ˜๋ช…, ํด๋ž˜์Šค๋ช…์—๋Š” ์–ธ๋”์Šค์ฝ”์–ด(_) ์‚ฌ์šฉ์„ ์ง€์–‘ํ•œ๋‹ค.

  • ์ฃผ์„์€ KDoc์„ ํ™œ์šฉํ•˜์—ฌ ์ฝ๊ธฐ ์‰ฌ์šด ๋ฌธ์„œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

  • Klint, GitHub Action ๊ฐ™์€ ์ž๋™ํ™” ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์†Œ์Šค Push ์‹œ์ ์—์„œ Fail ์ฒดํฌ๋ฅผ ํ•˜๋„๋ก ํ•œ๋‹ค.

  • ํด๋ž˜์Šค๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค๋Š” Companion Object๋ฅผ ์ œ์™ธํ•˜๊ณ  ๋ฌธ์„œ ์„ค๋ช…์„ ๋ฐ˜๋“œ์‹œ ํฌํ•จํ•œ๋‹ค.

  • if/when ๋ฌธ, while/for ๋ฃจํ”„๋Š” ์ผ๊ด€์„ฑ ์žˆ๋Š” ํฌ๋งท์„ ์œ ์ง€ํ•œ๋‹ค.

  • ํด๋ž˜์Šค ๋‚ด ๋ฉค๋ฒ„์˜ ์ˆœ์„œ๋Š” ์ฝ๊ธฐ ์ „์šฉ → ์ฝ๊ธฐ/์“ฐ๊ธฐ → ์ดˆ๊ธฐํ™” → ์ƒ์„ฑ์ž → ํ•จ์ˆ˜ ์ˆœ์œผ๋กœ ์ •๋ฆฌํ•œ๋‹ค.

  • ์ƒ์ˆ˜ ๊ฐ’์€ SNAKE_CASE๋กœ ์„ ์–ธํ•˜๊ณ , const ์ˆ˜์‹์ž๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.



// GOOD
private val modifiableElementList: MutableList = mutableListOf()
val elementList: List = modifiableElementList
// BAD
private val _elementList: MutableList = mutableListOf()
val elementList: List = _elementList

์ฝ”๋ฉ˜ํŠธ

KDOC์ด๋‚˜ Dokka ๊ทœ์น™์„ ๋”ฐ๋ฅธ๋‹ค.

๋˜ํ•œ Klint์™€ github Action ๊ฐ™์€ ์ž๋™ํ™”๋ฅผ ํ•œ๋‹ค๋ฉด  ์†Œ์Šค push ์‹œ์ ์—์„œ Fail ์ฒดํฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์—  ์šฉ์ดํ•˜๋‹ค.

๋‚˜ ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” klint๋ฅผ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ๋ฃฐ์„ ์ •์˜ํ•˜๊ณ  push ์ „์ฒด ํ•œ๋ฒˆ ์ฒดํฌ ํ›„ Push๋ฅผ ์ง„ํ–‰ํ–ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค.


ํด๋ž˜์Šค

๊ฐ ํด๋ž˜์Šค, ์ธํ„ฐํŽ˜์ด์Šค ๋˜๋Š” ์˜ค๋ธŒ์ ํŠธ๋Š” companion object ๋ฐ ์ต๋ช… ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ œ์™ธํ•˜๊ณ  ๋ฌธ์„œ ์„ค๋ช…์„ ํฌํ•จํ•ด์•ผ ํ•œ๋‹ค.

๋ฌธ์„œ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‘ ๊ฐ€์ง€ ์š”๊ตฌ์‚ฌํ•ญ์ด ์žˆ๋‹ค.

  • Javadoc/Kdoc ๊ทœ์น™์„ ๋”ฐ๋ฅด์ž. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ฝ”๋ฉ˜ํŠธ ์Šคํƒ€์ผ์€ "์ด์–ด์•ผ ํ•œ๋‹ค./**... */
  • ๋จผ์ € "์œ ํ˜•์ด ๋ฌด์—‡์ธ์ง€ , ์œ ํ˜•์ด ๋ฌด์—‡์ธ์ง€"๋ฅผ ์„ค๋ช…ํ•˜๋Š” ์งง์€ ์š”์•ฝ์œผ๋กœ ๋ช…์‚ฌ ๊ตฌ์ ˆ์„ ์‹œ์ž‘ํ•˜์ž.
  • ๊ทธ๋‹ค์Œ, ์„ ํƒ์  ๋ฌธ์žฅ์€ ์‚ฌ์šฉ๋ฒ•, ์ œํ•œ์‚ฌํ•ญ ๋“ฑ์„ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ์งง์€ ์š”์•ฝ์— ๋”ฐ๋ฅผ ์ˆ˜ ์žˆ๋‹ค.
์ฐธ๊ณ : ์„ค๋ช…์„œ๊ฐ€ ์—†๋Š” ๊ธฐ์กด ํด๋ž˜์Šค๋ฅผ ์ฐพ์œผ๋ฉด ์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ž‘์„ฑํ•˜์ž.


์ œ์–ด ํ๋ฆ„

"if"/"when" ํ‘œํ˜„/ํ‘œํ˜„

  • if-message:ํ˜ธ์ถœ์ž๊ฐ€ ๊ฒฐ๊ณผ๋ฅผ ์†Œ๋น„ํ•œ๋‹ค(์˜ˆ: ํ• ๋‹น, ๋ฐ˜ํ™˜ ๊ฐ’ ๋˜๋Š” ํ•จ์ˆ˜ ๋งค๊ฐœ ๋ณ€์ˆ˜).
    •  if-expression์˜ ๋ณธ๋ฌธ์€ ๋™์ผํ•œ ์ฝ”๋“œ ๋ผ์ธ์— ๋ชจ๋‘ ์ ํ•ฉํ•œ ๊ฒฝ์šฐ ๋‹จ์ผ ๋ผ์ธ ํ˜•์‹(*)์œผ๋กœ ๊ฐˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋‘ ๊ฐ€์ง€ ์ค„์˜ ๋ณธ์ฒด์— ๋Œ€ํ•ด ๋‹ค์ค‘ ๋ผ์ธ ํ˜•์‹(**)์„ ์ ์šฉํ•ด์•ผ ํ•œ๋‹ค.
  • if-datement:if-statement ๋ณธ๋ฌธ์€ ๋‹ค์ค‘ ํ–‰ ํ˜•์‹๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•œ๋‹ค.
  • (*) ๋‹จ์ผ ์ค„ ํ˜•์‹:์ปฌ๋ธŒ ๋ธŒ๋ ˆ์ด์Šค({})๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ ๋œ๋‹ค.
  • (**) ๋‹ค์ค‘ ํ–‰ ํ˜•์‹:({})๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

๋‹ค์Œ ์˜ˆ์ œ๋ฅผ ์ฐธ์กฐํ•ด ๋ณด์ž.


// Standard style
if (condition) {
    statement()
}
// with else
if (condition) {
    statement()
} else {
    anotherStatement()
}
// Assignment on a line
val value = if (condition) valueA else valueB
 
val longLongLongLongLongNameValue = if (condition) valueA else valueB
  
// Assignment with block
val anotherValue = if (condition) {
    longLongLongLongLongLongNameValueA
} else {
    longLongLongLongLongLongNameValueB
}
  
val oneMoreValue =
    if (longLongLongCondition) {
        longLongLongLongLongLongNameValueA
    } else {
        longLongLongLongLongLongNameValueB
    }


ํ• ๋‹น ๋˜๋Š” ๋ฐ˜ํ™˜ ๊ฐ’์— ์‹์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๊ฐ ๋ณธ๋ฌธ ๋ธ”๋ก์—๋Š” ์‹์ด ํ•˜๋‚˜๋งŒ ์žˆ์–ด์•ผ ํ•œ๋‹ค

์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ ์ฝ”๋“œ๋Š” ์ง€์–‘ํ•œ๋‹ค.


// BAD: ๊ฐ ๋ณธ๋ฌธ ๋ธ”๋ก์—๋Š” ์ถ”๊ฐ€ ๋ช…๋ น๋ฌธ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณธ๋ฌธ์„ ํ•จ์ˆ˜๋กœ ์ถ”์ถœํ•˜์—ฌ "if" ํ‘œํ˜„์‹ ๊ฐ’์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
val string = if (i % 2 == 0) {
    methodCall()
    anotherMethodCall()
    "even"
} else {
    furtherMoreMethodCall()
    "odd"
}


  • ์‹์ด ํ• ๋‹น ๋˜๋Š” ๋ฐ˜ํ™˜ ๊ฐ’์˜ ๋‹ค๋ฅธ ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜์–ด์„œ๋Š” ์•ˆ ๋  ๊ฒฝ์šฐ ๊ฐ’์ด๋‹ค.


์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ ์ฝ”๋“œ๋Š” ์ง€์–‘ํ•œ๋‹ค.


// BAD: "if" ํ‘œํ˜„์‹์˜ ์–ด๋–ค ๊ฐ’๋„ ๋ฉ”์„œ๋“œ ์ธ์ˆ˜๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋จผ์ € ๋กœ์ปฌ ๊ฐ’์œผ๋กœ ์ •์˜ํ•˜์„ธ์š”.
function(if (i % 2 == 0) "even" else "odd")
 
// BAD: 
"if" ํ‘œํ˜„์‹์˜ ์–ด๋–ค ๊ฐ’๋„ ํ•จ์ˆ˜ ์ˆ˜์‹ ์ž๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋จผ์ € ๋กœ์ปฌ ๊ฐ’์œผ๋กœ ์ •์˜ํ•˜์„ธ์š”.
if (i % 2 == 0) {
    "even"
} else {
    "odd"
}.capitalize()



  • ๋‹ค์ค‘ ์กฐ๊ฑด ๋ธ”๋ก์˜ ๊ฒฝ์šฐ ์ธ์ˆ˜๊ฐ€ ์—†๋Š” ์‹์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๊ฐ€๋…์„ฑ์ด ๊ฐœ์„ ๋œ ํŠน์ˆ˜ํ•œ ์ƒํ™ฉ์—์„œ๋งŒ ๋ฌธ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

์˜ˆ์ œ

// BAD
if (expression1) {
    doStuff()
} else if (expression2) {
    doOtherStuff()
} else {
    doOtherOtherStuff()
}
  
// GOOD
when {
    expression1 -> doStuff()
    expression2 -> doOtherStuff()
    else -> doOtherOtherStuff()
}

"while"/"for" ๋ฃจํ”„

๋งˆ์น˜ ํ‘œํ˜„๊ณผ ๊ฐ™์ด, ๋ฐ˜๋ฉด/๋Œ€์šฉ ๋ฃจํ”„๋Š” ๊ฐ body ๋ธ”๋ก์— ๋Œ€ํ•ด ๋ธŒ๋ ˆ์ด์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•˜๋ฉฐ ๋ธ”๋ก์€ ์ƒˆ๋กœ์šด ์„ ์œผ๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•œ๋‹ค.

(์กฐ๊ฑด) ๋ฃจํ”„๊ฐ€ ์žˆ๋Š” ๋™์•ˆ {}์— do์„(๋ฅผ) ์‚ฌ์šฉํ•˜์ง€ ๋ง์ž.

๋นˆ ๋ธ”๋ก

๋นˆ ๋ธ”๋ก์„ ์ •์˜ํ•˜๋ ค๋ฉด ์ฒซ ๋ฒˆ์งธ ์ค„์— ์—ด๋ฆฐ  ๋ธŒ๋ ˆ์ด์Šค๋ฅผ, ๋‘ ๋ฒˆ์งธ ์ค„์— ๋‹ซํžŒ ๋ธŒ๋ ˆ์ด์Šค๋ฅผ ๋†“์ž.

https://android.github.io/kotlin-guides/style.html#empty-blocks).



try {
      doSomething()
  } catch (e: Exception) { // break the line for an empty block
  }
:

๋ฉค๋ฒ„ ๋ณ€์ˆ˜ ์ˆœ์„œ

ํด๋ž˜์Šค, enum, interface, object ๋“ฑ์˜ ๋ฉค๋ฒ„ ์˜ค๋”๋Š” ์•ˆ๋“œ๋กœ์ด๋“œ ์ŠคํŠœ๋””์˜ค์—์„œ ์ œ๊ณตํ•˜๋Š” ์ž๋ฐ”์˜ ์˜ค๋” ํฌ๋งทํ„ฐ๋ฅผ ๋”ฐ๋ฅธ๋‹ค.

์ฝ”ํ‹€๋ฆฐ ์ฃผ๋ฌธ ํฌ๋งทํ„ฐ๋‚˜ ๊ณต์‹ ์ปจ๋ฒค์…˜ ๋“ฑ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ž๋ฐ”์ฝ”๋“œ๊ฐ€ ์ฝ”ํ‹€๋ฆฐ์œผ๋กœ ์ „ํ™˜๋˜๋ฉด์„œ ์ผ๊ด€์„ฑ์„ ์ œ๊ณตํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ "์ •์  ํ•„๋“œ"๋Š” ๋™๋ฐ˜ ๋Œ€์ƒ์˜ ํ•„๋“œ์— ์˜ํ•ด ์‹คํ˜„๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ตœ์ข…์ ์œผ๋กœ ๋ฐฐ์น˜๋˜์–ด์•ผ ํ•œ๋‹ค.

์ˆœ์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ์ฝ๊ธฐ ์ „์šฉ ์†์„ฑ(val)์œผ๋กœ ์ •์˜
  • ์ฝ๊ธฐ-์“ฐ๊ธฐ ์†์„ฑ(var)์œผ๋กœ ์ •์˜
  • ์ดˆ๊ธฐํ™” ๋ธ”๋ก(์ดˆ๊ธฐ)
  • ๋ณด์กฐ ์ƒ์„ฑ์ž(๊ตฌ์„ฑ์ž)
  • ํ•จ์ˆ˜()
  • ์ฝ๊ธฐ ์ „์šฉ ์†์„ฑ ํ™•์žฅ(val T.x)
  • ์ฝ๊ธฐ-์“ฐ๊ธฐ ์†์„ฑ ํ™•์žฅ(var T.x)
  • ํ•จ์ˆ˜  extention(T.foo())
  • ์ค‘์ฒฉ ๋˜๋Š” ๋‚ด๋ถ€ ํด๋ž˜์Šค, ์—ด๊ฑฐํ˜•, ์ธํ„ฐํŽ˜์ด์Šค ๋ฐ ๊ฐœ์ฒด
  • companion object 

๋‹ค์Œ ์˜ˆ์ œ๋ฅผ ์ฐธ์กฐํ•˜์ž.


class Klass(val parameter: Value) {
 
    // Read-only properties
    val publicValue: Value = Value()
    private val value: Value = Value()
 
    // Read-write properties
    var publicVariable: Value = Value()
    private var variable: Value = Value()
 
    // Initialization block
    init {
        // ...
    }
 
    // Other constructors
    constructor(firstValue: Int, secondValue: Int) : this(Value())
 
    // Functions
    fun publicFunction() { ... }
 
    private fun privateFunction() { ... }
 
    // Extensions of read-only properties
    val  T.publicReadonly: Value get() = Value()
    private val  T.readonly: Value get() = Value()
  
    // Extensions of read-write properties
    var  T.publicReadWrite: Value
        get()
        set()
    private var  T.readWrite: Value
        get()
        set()
  
    // Extensions of functions
    fun  T.publicFunction() { ... }
  
    private fun .privateFunction() { ... }
    // Nested or inner classes, enums, interfaces, and objects
    enum class EnumType private constructor(val enumField: Int) {
        DEFAULT(1),
        A_ENUM_TYPE(2),
    }
 
    private data class NestedDataClass(val int: Int)
 
    // Constants
    companion object {
        const val PRIMITIVE_CONSTANT = 0
 
        @JvmField
        val NON_PRIMITIVE_CONSTANT: OtherClass = OtherClass()
    }
}



๊ฐ ๋ฒ”์ฃผ์— ๋Œ€ํ•ด ๊ฐ€๋Šฅํ•œ ํ•œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ทœ์น™์„ ์ง€ํ‚ค๋„๋ก ๊ถŒ์žฅํ•œ๋‹ค.

  • public ์ด  private ๋ณด๋‹ค  member ordering ์ด ๋†’๋‹ค.
  • ์ •์  ํ•ญ๋ชฉ์ด ๋™์ ์œผ๋กœ ๊ฒฐ์ •๋œ ํ•ญ๋ชฉ ์ด์ƒ์ž„
  • ์ถ”์ƒํ™” ์ˆ˜์ค€์ด ๋†’์€ ํ•ญ๋ชฉ์€ ๋‚ฎ์€ ์ถ”์ƒํ™” ์ˆ˜์ค€ ํ•ญ๋ชฉ๋ณด๋‹ค ๋†’๋‹ค.

์œ ํ˜• ์„ ์–ธ

  • ํ˜•์‹ ์„ ์–ธ์€ ๋ฐ˜๋“œ์‹œ ์ง€์ผœ์•ผ ํ•œ๋‹ค.
    • ์ƒ์„ฑ์ž ๋˜๋Š” ๋ฉ”์„œ๋“œ์˜ ๋งค๊ฐœ ๋ณ€์ˆ˜
    • ๋น„์œ ๋‹› ๋ฆฌํ„ดํ˜• ํ•จ์ˆ˜
    • ์ „๋ถ€ **var** properties
  • ๋‹ค์Œ ํ˜•์‹ ์„ ์–ธ์„ ์‚ญ์ œํ•˜์‹ญ์‹œ์˜ค.
    • ๋‹จ์œ„๋ฐ˜ํ™˜ํ˜•๋ฒ•
    • "const" ํ•œ์ •์ž๊ฐ€ ์žˆ๋Š” ๋ชจ๋“  ํ•„๋“œ
  • ... ์— ๋Œ€ํ•œ ํ˜•์‹ ์„ ์–ธ์„ ์œ ์ง€ํ•˜๊ฑฐ๋‚˜ ์ทจ์†Œํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ๋กœ์ปฌ ๊ฐ’ ๋ฐ ๋ณ€์ˆ˜
    • ๋žŒ๋‹ค์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ์œ ํ˜•
    • val
    • ๊ฐ€์‹œ์„ฑ๊ณผ ๊ด€๊ณ„์—†์ด ์ƒ์„ฑ์ž์— ๋Œ€ํ•œ ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฆ‰์‹œ ํ• ๋‹น๋˜๋Š” ์†์„ฑ

๋‹ค์Œ ์˜ˆ์ œ๋ฅผ ์ฐธ์กฐํ•˜์ž.


// You must keep type for public values and any variables
private var variable: Type = Type() // Type required because `var`
 
// You must keep type if the right value is not direct constructor call or primitive value
private val array: Array = arrayOf(1, 2, 3) // `arrayOf` is not a constructor.
private val sum: Int = 1 + 2 // The right value is the result of `plus` function.
private val valueWithApply: Type = Type().apply { ... } // `.apply` is appended.
 
// You may keep or drop the type for values instantiated with constructor calls
// With constructor call
val value: Type = Type() // Kept (somewhat repetitive)
val value = Type() // Dropped
private val value1: Type = Type() // Kept (somewhat repetitive)
private val value2 = Type( // Dropped
    parameter,
    parameter2
)
// With primitive value assignment
private val value3: Int = 1 // Kept
private val value4 = 1 // Dropped
 
// Anti-pattern: dropping type declarations in situations other than explicit constructor calls
private val value = Type.generateInstance() // Not an actual constructor call
private val value2 = Type( // Starts with a constructor call...
    parameter,
    parameter2
).toOtherType() // But may be deceptive
 
// You must keep the type for private variables
private var variable: Superclass = Subclass() // The type may be different than the initial value, because it can be reassigned
/* ... */
        variable = OtherSubclass() // The variable might take on another type
    } else {
        variable = Superclass() // ...or it might be assigned with the super-type
// Even if the type was dropped, this code would be compiled successfully due to Kotlin's inferred typing system, but this isn't immediately obvious to readers
 
// You must keep return type with non-Unit methods
fun nonUnitFunction(): Int = 1
 
// You must skip return type if it is Unit
fun unitFunction() = Unit
 
// You must keep parameter type
fun unitFunction(i: Int) {
    // You may skip local value/variable type...
    val j = 0
    // or you may also keep the type.
    val k: Int = i + j
 
    // For lambdas, you can choose from any valid format.
    val firstLambda: (Int) -> Int = { it + 1 }
    val secondLambda = { i: Int -> i + 1 }
    val thirdLambda: (someMeaningfulName: Int) -> Int = { anotherName -> anotherName + 1 }
}

ํ•จ์ˆ˜ ์ •์˜

ํ—ค๋” ํฌ๋งท

ํ—ค๋” ํ˜•์‹์€ Kotlin ์ฝ”๋”ฉ ๊ทœ์น™์˜ ํด๋ž˜์Šค ํ—ค๋” ํ˜•์‹์— ๋”ฐ๋ฅธ๋‹ค. ํ—ค๋”๊ฐ€ ์ถฉ๋ถ„ํžˆ ์งง์œผ๋ฉด ๋ฐ˜๋“œ์‹œ ํ•œ ์ค„์— ์จ์•ผ ํ•œ๋‹ค. ํ—ค๋”๊ฐ€ ๊ธด ๊ฒฝ์šฐ ๊ฐ ๋งค๊ฐœ๋ณ€์ˆ˜ ์„ ์–ธ์€ ๋ณ„๋„์˜ ์ค„์— ์žˆ์–ด์•ผ ํ•œ๋‹ค. ๋‹ค์Œ ์˜ˆ์ œ๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.


fun shortHeader(): Int {
    // ...
    // ...
}
  
fun shortHeader(parameter: Int): Int {
    // ...
    // ...
}
  
fun longHeader(
        parameter: Parameter,
        anotherParameter: Parameter,
        oneMoreParameter: Parameter
): Type {
    // ...
    // ...
}
 
fun longHeaderWithUnitReturnType(
        parameter: Parameter
) {
    // ...
    // ...
}

Brace ๋ฐ = ์ •์˜ ๊ธฐํ˜ธ

  • ํ•˜๋‚˜์˜ ํ‘œํ˜„์‹์œผ๋กœ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋ ค๋ฉด ๋ฐ˜ํ™˜ ์œ ํ˜•์ด ๋‹จ์œ„์ธ ๊ฒฝ์šฐ์—๋„ ****= ๊ธฐํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜์ž.
  • ์—ฌ๊ธฐ์—๋Š” if, when, function calls with lambda์™€ ๊ฐ™์€ ํ‘œํ˜„์ด ํฌํ•จ๋œ๋‹ค.
  • ์‚ฌ์šฉํ•˜๋‹ค= Unit์ด ๊ทœ์น™์˜ ์˜ˆ์™ธ๋Š” ๋ณด์กฐ ์ƒ์„ฑ์ž๊ฐ€ ๋‹ค๋ฅธ ์ƒ์„ฑ์ž์—๊ฒŒ ์œ„์ž„ํ•˜๋Š” ๊ฒฝ์šฐ๋‹ค.
  • ๋นˆ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜์‹ญ์‹œ์˜ค.

๋‹ค์Œ ์˜ˆ์ œ๋ฅผ ์ฐธ์กฐํ•˜์ž.


fun function(): Int = 1 + 2
  
fun function(parameter: Int): Int =
    1 + parameter
 
fun anotherFunction(): Type = Type().also {
    it.variable = "variable"
    it.anotherVariable = "variable"
}
  
fun whenFunction(type: Type): String = when(type) {
    Type1 -> "Type1"
    Type2 -> "Type2"
}
 
fun unitFunction() = anotherUnitFunction()
  
fun emptyFunction() = Unit
  
// Exception for secondary constructors
constructor(type: Type) : super(type)
constructor(type: Type, anotherType: Type) : this(type)

์ƒ์ˆ˜ ๊ฐ’

์ƒ์ˆ˜ ๊ฐ’์€ ์ž๋ณธํ™”๋จ_์œผ๋กœ ์„ ์–ธํ•ด์•ผ ํ•จ์Šค๋„ค์ดํฌ_์ผ€์ด์Šค_๋ผ์ดํฌ_์ด๊ฒƒ. ๋˜ํ•œ ๋™๋ฐ˜ ๊ฐ์ฒด์˜ ํ•„๋“œ ๋˜๋Š” ๊ธ€๋กœ๋ฒŒ ๊ฐ’์œผ๋กœ ์ •์˜ํ•ด์•ผ ํ•œ๋‹ค(๋‹ค์Œ ์„น์…˜ ์ฐธ์กฐ). ์ƒ์ˆ˜ ๊ฐ’์ด ์›์‹œ ๊ฐ’์ด๋‚˜ ๋ฌธ์ž์—ด์ธ ๊ฒฝ์šฐ const ์ˆ˜์‹์–ด๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค. ๊ธฐ๋ณธ ์ƒ์ˆ˜๊ฐ€ ์•„๋‹Œ ์ƒ์ˆ˜์˜ ๊ฒฝ์šฐ, Java์—์„œ ํ‘œ์‹œ๋˜๋„๋ก ํ•˜๋ ค๋ฉด @JvmField ์ฃผ์„์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.


const val PRIMITIVE_CONSTANT = 0
 
@JvmField
val NON_PRIMITIVE_CONSTANT: NonPrimitive = NonPrimitive()


global value  ๋ฐ global function

๊ธ€๋กœ๋ฒŒ ๊ฐ’, ๊ฐ์ฒด(์ˆœ์ˆ˜ํ•จ์ˆ˜๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ๋„ ์žˆ์Œ) ๋˜๋Š” ํ™•์žฅ์ž๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ๊ธฐ๋Šฅ ๋˜๋Š” ์ „์—ญ ๊ฐ’์„ ์ •์˜ํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ ์ ˆํ•œ ํŒจํ‚ค์ง€์— ์ƒˆ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์‹ญ์‹œ์˜ค.

YourConstants.kt


**`package`** `com.linecorp.yourpackage`

`const **val**` `YOUR**_**CONSTANT**:**` `Int **=**` `0;`

**`@**JvmField`

**`val`** `YOUR**_**ANOTHER**_**CONSTANT**:**` `Value **=**` `Value();`


YourUtils.kt



**`package`** `com.linecorp.yourpackage`

`fun yourUtilityFunction()**:**` `ReturnValue {`

`// ...`

`**return**` `ReturnValue()`

`}`


Java์—์„œ ์ ‘์†ํ•  ๋•Œ ํŒŒ์ผ ์ด๋ฆ„ ๋˜ํ•œ ํด๋ž˜์Šค ์ด๋ฆ„์œผ๋กœ ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํŒŒ์ผ ์ด๋ฆ„์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ œํ•œ๋œ๋‹ค.

  • ํŒŒ์ผ ์ด๋ฆ„ ์ ‘๋ฏธ์‚ฌ๋Š” ์ƒ์ˆ˜์˜ "Constants"์—ฌ์•ผ ํ•œ๋‹ค.
  • ํšจ์šฉ ํ•จ์ˆ˜์˜ ํŒŒ์ผ ์ด๋ฆ„ ์ ‘๋ฏธ์‚ฌ๋Š” "Utils"์—ฌ์•ผ ํ•œ๋‹ค.
  • ํ™•์žฅ ๊ธฐ๋Šฅ ๋ชจ์Œ์— ๋Œ€ํ•œ ํŒŒ์ผ ์ด๋ฆ„ ์ ‘๋ฏธ์‚ฌ๋Š” "ํ™•์žฅ"์ด์–ด์•ผ ํ•œ๋‹ค.

๊ธ€๋กœ๋ฒŒ ํ™•์žฅ์„ ๋งŒ๋“ค๋ ค๋ฉด, ๋‹ค์Œ ์†Œ์œ ์ž์—๊ฒŒ ์š”์ฒญํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

Lamda

์ค‘์ฒฉ๋œ ๋žŒ๋‹ค(๋žŒ๋‹ค(๋žŒ๋‹ค))๋ฅผ ํ”ผํ•˜์‹ญ์‹œ์˜ค.

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




//BAD
list.map { innerList ->
    innerList.map {
        // DON'T DO THIS !!!
    }
}


์˜ˆ์™ธ:

์˜ˆ์™ธ์ ์œผ๋กœ ์™ธ๋ถ€ ๋žŒ๋‹ค๊ฐ€ ๊ธ€๋กœ๋ฒŒ ๋ฒ”์œ„ ๋˜๋Š” ํด๋ž˜์Šค์˜ ์ตœ์ƒ์œ„ ์ˆ˜์ค€(=์—ฐ์‚ฐ์ž ํฌํ•จ ํ•จ์ˆ˜/๊ฐ’ ํ• ๋‹น ๋ฒ”์œ„ ํฌํ•จ) ๋ฐ”๋กœ ์•„๋ž˜์— ์žˆ์œผ๋ฉด ์ค‘์ฒฉ๋œ ๋žŒ๋‹ค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ํ—ˆ์šฉ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.


class Klass {
 
    val intValue: Int by lazy {
        intList.sumBy { it + it * it }
    }
 
    fun function(mutableObject: MutableClass?, list: List) = mutableObject?.apply {
        firstEven = list.first { it % 2 == 0 }
        firstOdd = list.first { it % 2 != 0 }
        // And more
    }
}

๋‹ค์Œ ์ฝ”๋“œ๋Š” ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค.

//BAD
class Klass {
 
    fun function(mutableObject: MutableClass?, list: List) {
        mutableObject?.apply {
            firstEven = list.first { it % 2 == 0 }
            firstOdd = list.first { it % 2 != 0 }
        }
        // And more
}

๊ธด ๋žŒ๋‹ค ํ”ผํ•œ๋‹ค.

์ฝ๊ธฐ ์‰ฝ๋„๋ก "๊ธด" ๋žŒ๋‹ค๋Š” ํ”ผํ•ด์•ผ ํ•œ๋‹ค. ๋‹ค์Œ ์กฐ๊ฑด ์ค‘ ํ•˜๋‚˜๋ฅผ ๋งŒ์กฑํ•˜๋Š” ๋žŒ๋‹ค๋Š” "๊ธด" ๋žŒ๋‹ค.

  • ๋ฐ˜ํ™˜ ์‹์„ ์ œ์™ธํ•œ 2๊ฐœ ์ด์ƒ์˜ ๋ฌธ์žฅ์ด ์žˆ๋Š” ๋žŒ๋‹ค.
  • if ์‹, a when ์‹ ๋˜๋Š” for/while ๋ฃจํ”„๊ฐ€ ์žˆ๋Š” ๋žŒ๋‹ค.

๋‹ค์Œ ์˜ˆ๋ฅผ ์ฐธ์กฐํ•˜์ž.


// Short lambda expression: 1 statement and 1 return expression
list.map {
    methodCall(it)
    returnValue(it)
}
 
// Long lambda: with for when
dialogBuilder.setPositiveButton("OK") { dialog: DialogInterface, which: Int ->
    when (which) {
        0 -> // ...
        else -> // ...
    }
}
  
// Long lambda: 2 statements (the second line is not return expression)
obj.apply {
    methodCall()
    anotherMethodCall()
}


"๊ธด" ๋žŒ๋‹ค๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ ค๋ฉด ํ‘œํ˜„์‹์„ ๋ฐฉ๋ฒ•์œผ๋กœ ์ถ”์ถœํ•˜๊ณ  ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ€๋Šฅํ•˜๋ฉด ๋ช…๋ช…๋œ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“œ์‹ญ์‹œ์˜ค.


์˜ˆ์™ธ:

ํŽธ์˜์ƒ "๊ธด" ๋žŒ๋‹ค(long)๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์— ํ—ˆ์šฉ๋œ๋‹ค.

  • ๋ฐ˜ํ™˜ ๊ฐ’์œผ๋กœ ์ง์ ‘ ์‚ฌ์šฉ๋˜๋Š” ๋žŒ๋‹ค
  • ํ•จ์ˆ˜์˜ ๋งˆ์ง€๋ง‰ ์ธ์ˆ˜๋กœ ์ง์ ‘ ์‚ฌ์šฉ๋˜๋Š” ๋žŒ๋‹ค. ์—ฌ๊ธฐ์„œ...
    • ๋‹ค๋ฅธ ์ฃผ์žฅ์€ ๋žŒ๋‹ค๊ฐ€ ์•„๋‹ˆ๋‹ค.
    • ๋žŒ๋‹ค๋Š” ์œ„์ž„ ๋˜๋Š” ์ˆ˜์ • ์ˆ˜์‹ ๊ธฐ๋ฅผ ํฌํ•จํ•œ ๊ธฐ๋Šฅ์˜ ๋ฐ˜ํ™˜ ๊ฐ’์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐ๋งŒ ์‚ฌ์šฉ๋œ๋‹ค.
    • ํ•จ์ˆ˜ ๋ฐ˜ํ™˜ ๊ฐ’์€ ํ˜ธ์ถœ์ž์˜ ํ• ๋‹น ๋˜๋Š” ๋ฐ˜ํ™˜ ๊ฐ’์— ์‚ฌ์šฉ๋˜์ง€ ์•Š๊ฑฐ๋‚˜ ์ง์ ‘ ์‚ฌ์šฉ๋œ๋‹ค.
// OK: Long lambda directly used for return value
fun createComparator(): (Int, Int) -> Int = { x: Int, y: Int ->
    // Code...
    // Code...
    result
}
 
// OK: Long lambda used for assignment directly.
val mappedList = list.map {
    when (it) {
        0 -> it
        else -> it + 1
    }
}
  
// OK: Long lambda used for delegation directly.
val view by lazy {
    // initialization
    // another initialization
    inflatedView
}

๋‹ค์Œ ์ฝ”๋“œ๋Š” ํ—ˆ์šฉ๋˜์ง€ ์•Š์Œ:

// BAD: the result of function taking lambda is not directly used for assignment
val mappedList = list.map {
    when (it) {
        0 -> it
        else -> it + 1
    }
}
.map { /* another map */ }
  
// BAD: the result of function taking lambda is not directly used for assignment
val value: View = parent?.let {
    // initialization
    // another initialization
    foundView
} ?: defaultView


๋กœ์ปฌ ๊ฐ’/๋ณ€์ˆ˜์™€ ๊ด€๋ จํ•˜์—ฌ ๋‹ซ๊ธฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Œ

๋Œ€์‹  concrete ํด๋ž˜์Šค ๋˜๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ์‹ญ์‹œ์˜ค.

try-catch ๋ธ”๋ก๋ณ„๋กœ ์˜ˆ์ƒ๋œ ์˜ˆ์™ธ ์œ ํ˜•์„ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•˜์‹ญ์‹œ์˜ค.




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


์‹ค์ „์—์„œ ๋А๋‚€ ์ 


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


๋‚ด๊ฐ€ ์—ฌ๋Ÿฌ ๊ตญ๊ฐ€ ๊ฐœ๋ฐœ์ž๋“ค๊ณผ ํ˜‘์—…ํ•˜๋ฉด์„œ ๊ฐ€์žฅ ํฌ๊ฒŒ ๋А๋‚€ ์ ์€, ์‚ฌ๋žŒ๋งˆ๋‹ค, ์ธ์ข…๋งˆ๋‹ค ์ฝ”๋”ฉ ์Šคํƒ€์ผ์ด ์ฒœ์ฐจ๋งŒ๋ณ„์ด๋ผ๋Š” ๊ฒƒ์ด๋‹ค. ํŠนํžˆ ํ•œ๊ตญ, ์ธ๋„, ๊ธฐํƒ€ ๊ตญ๊ฐ€๋“ค์˜ ๊ฐœ๋ฐœ์ž๋“ค์ด ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋Š” ๊ฐ๊ฐ ๋˜ ๋‹ค๋ฅธ ๋งค๋ ฅ์ด ์žˆ๋‹ค. ๋‹ค์–‘ํ•œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด์„œ ๋‚˜๋งŒ์˜ ์Šคํƒ€์ผ์„ ์ฐพ์•„๊ฐ€๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋ผ ์ƒ๊ฐํ•œ๋‹ค.


AI ์‹œ๋Œ€์— ์ ‘์–ด๋“  ์ง€๊ธˆ, ์ž์‹ ์ด ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ฅผ ChatGPT ๊ฐ™์€ AI์˜ ๋„์›€์œผ๋กœ ๊ฐœ์„ ํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์€ ์Šต๊ด€์ด๋‹ค. ๋ฌผ๋ก  ๋ชจ๋“  ๊ฒƒ์„ AI์— ์˜์กดํ•˜๋Š” ๊ฒƒ์€ ์ข‹์€ ํƒœ๋„๊ฐ€ ์•„๋‹ˆ์ง€๋งŒ, AI๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋Œ€์•ˆ์„ ์ฐธ๊ณ ํ•˜๋ฉด์„œ ๋” ๋‚˜์€ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค.


๋งˆ์น˜๋ฉฐ


์ด๋ฒˆ ํŽธ์—์„œ๋Š” ์ฝ”๋”ฉ ๊ทœ์น™์„ ์ •ํ•˜๋Š” ์ด์œ ์™€ ์‹ค์ „ ์ ์šฉ ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ–ˆ๋‹ค.

์ž‘์ง€๋งŒ ๋ช…ํ™•ํ•œ ๊ทœ์น™ ํ•˜๋‚˜๊ฐ€ ํŒ€์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜๊ณผ ์ƒ์‚ฐ์„ฑ์— ํฐ ์ฐจ์ด๋ฅผ ๋งŒ๋“ค์–ด๋‚ธ๋‹ค.

๋‹ค์Œ ํŽธ์—์„œ๋Š” ์ฝ”๋“œ ๋ฆฌ๋ทฐ ๋ฌธํ™”์™€ ๊ทธ ์›์น™์„ ์ •๋ฆฌํ•˜์—ฌ, ์ฝ”๋“œ ํ’ˆ์งˆ๊ณผ ํŒ€ ํ˜‘์—…์„ ํ•œ์ธต ๋” ๊ฐ•ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•˜๊ณ ์ž ํ•œ๋‹ค.


๋‹ค์Œ ํŽธ ์˜ˆ๊ณ 


๊ฐœ๋ฐœ ๋ฌธํ™” ์ •๋ฆฝ ์‹œ๋ฆฌ์ฆˆ - 4ํ™” : ์ฝ”๋“œ ๋ฆฌ๋ทฐ ์›์น™๊ณผ ๋ฌธํ™” ์ •๋ฆฝํ•˜๊ธฐ

์ข‹์€ ์ฝ”๋“œ ๋ฆฌ๋ทฐ๋Š” ํŒ€์˜ ์„ฑ์žฅ ์—”์ง„์ด๋‹ค.

๋‹ค์Œ ํŽธ์—์„œ๋Š” ์ฝ”๋“œ ๋ฆฌ๋ทฐ ์‹œ ์ง€์ผœ์•ผ ํ•  ์›์น™๊ณผ, ๋ฆฌ๋ทฐ ๋ฌธํ™”๋ฅผ ๊ฑด๊ฐ•ํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ํŒ์„ ๊ณต์œ ํ•  ์˜ˆ์ •์ด๋‹ค.


๋Œ“๊ธ€ ์“ฐ๊ธฐ