woowa Kotlin
μ½νλ§ λ§€μ° μμ 체νκΈ°
μλ ν ν¬ μΈλ―Έλ λ΄μ©μ μμ½ν λ΄μ©μ λλ€.
Kopring Sample Repository
Kotlin?
μ½νλ¦°μ λ©ν° νλ«νΌ μΈμ΄


μ½λ© 컨벀μ
μ»€λ° λ©μΈμ§
ktlint
μ½λμ 컨벀μ κ·μ½
ktlintλ
Kotlin Coding Conventionκ³ΌAndroid Kotlin Style Guideλ₯Ό κΈ°λ³ΈμΌλ‘ λ°λ₯΄κ³ μλ€.
ktlint: μ½νλ¦° style, convention κ°μ΄λ μ μ©
βοΈ IntelliJ IDEA formatterλ₯Ό ktlintμ λ§κ² μ€μ (ν΄λΉ νλ‘μ νΈλ§):
$ ./gradlew ktlintApplyToIdea
IntelliJ μ¬μ© λͺ¨λ νλ‘μ νΈμ formatter μ μ©(λͺ¨λ IDEA νλ‘μ νΈμ):
$ ./gradlew ktlintApplyToIdeaGlobally
μλμΌλ‘ ktlintλ₯Ό μ΄μ©νμ¬ μ€νμΌ μ²΄ν¬:
$ ./gradlew clean ktlintCheckktlInt Check:
Tasks β verification β ktlintCheck
βοΈ Git hookμ ν΅ν΄ ktlint μ€μ : μ»€λ° μ μ ktlintCheck ν μ€νΈ μ€ν
Kotlin/JVM
Basic

μ½νλ¦°μ μμ νκ² μ½λ©νλλ‘ μμνμ§ μμλ μμ νκ² μ½λ©λλλ‘ μ§μ
@NotNull, @Nullable, final μλ μ μ©
μμ νκ² μ½λ©νκ³ μΆμ§ μμ κ²½μ° μμμ μΌλ‘ μ½λ©
μ½νλ¦° μ»΄νμΌ
μ½νλ¦° μ½λλ§ μ¬μ©ν κ²½μ°

μ½νλ¦°, μλ° μ½λλ₯Ό ν¨κ» μ¬μ©ν κ²½μ°
둬볡μμ μμ±λ μλ° μ½λλ μ½νλ¦° μ½λμμ μ κ·Ό λΆκ°

Item 1. μ½νλ¦° νμ€ λΌμ΄λΈλ¬λ¦¬
μ½νλ¦° νμ€ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ΅νκ³ μ¬μ©νκΈ°
μ½νλ¦°μμ μλ°μ κ΄λ ¨λ importλ₯Ό μ΅λν μ κ±°νλ €κ³ λ Έλ ₯νμ
νμ€ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νλ©΄ κ·Έ μ½λλ₯Ό μμ±ν μ λ¬Έκ°μ μ§μκ³Ό μ¬λ¬λΆλ³΄λ€ μμ μ¬μ©ν λ€λ₯Έ νλ‘κ·Έλλ¨Έλ€μ κ²½νμ νμ©ν μ μλ€.
AS-IS
TO-BE
μ½νλ¦°μ μ½κΈ° μ μ© μ»¬λ μ κ³Ό λ³κ²½ κ°λ₯ν 컬λ μ μ ꡬλ³ν΄ μ 곡
μΈν°νμ΄μ€λ₯Ό λ§μ‘±νλ μ€μ 컬λ μ μ΄ λ°ν
λ°λΌμ νλ«νΌλ³ 컬λ μ μ μ¬μ© κ°λ₯
Item 2. μλ°λ‘ μμ»΄νμΌ
μλ°λ‘ μμ»΄νμΌνλ μ΅κ΄ λ€μ΄κΈ°
μ½νλ¦° μλ ¨λλ₯Ό λμ΄λ κ°μ₯ μ’μ λ°©λ²μ μ½νλ¦°μΌλ‘ μμ±ν μ½λκ° μλ°λ‘ μ΄λ»κ² ννλλμ§ νμΈνκΈ°
μμ»΄νμΌλ‘ μκΈ°μΉ μμ μ½λ μμ±μ λ°©μ§
κΈ°μ‘΄ μλ° λΌμ΄λΈλ¬λ¦¬μ νλ μμν¬λ₯Ό μ¬μ©νλ©° λ¬Έμ κ° λ°μν λ λΉ λ₯΄κ² νμΈ κ°λ₯
Kotlin to Java
Tool > Kotlin > Show Kotlin Bytecode > Decompile
Java to Kotlin
Convert Java File to Kotlin File
Item 3. 둬볡λμ λ°μ΄ν° ν΄λμ€
둬볡 λμ λ°μ΄ν° ν΄λμ€ μ¬μ©νκΈ°
λ°μ΄ν° ν΄λμ€λ₯Ό μ¬μ©νλ©΄ μ»΄νμΌλ¬κ°
equals(),hashCode(),toString(),copy()λ±μ μλ μμ±μ£Ό μμ±μμ λ§€κ°λ³μλ₯Ό κΈ°μ€μΌλ‘ μμ±νκ³ , μ£Ό μμ±μμλ νλ μ΄μμ λ§€κ°λ³μκ° μμ΄μΌ ν¨
λ§€κ°λ³μλ val λλ varλ‘ νμ
λ°μ΄ν° ν΄λμ€μ property λ₯Ό μ μΈνλ μκ° ν΄λΉ property λ field, Getter, Setter, μμ±μ νλΌλ―Έν° μν


plugins
Spring Boot
final ν΄λμ€
@SpringBootApplicationμ@Configurationμ ν¬ν¨νκ³ , μ€νλ§μ κΈ°λ³Έμ μΌλ‘ CGLIBμ μ¬μ©ν΄μ@Configurationν΄λμ€μ λν νλ‘μλ₯Ό μμ±νμ§λ§, final ν΄λμ€λ μμμ΄λ μ€λ²λΌμ΄λκ° λΆκ°νλ―λ‘ νλ‘μ μμ±μ΄ λΆκ°
μμμ νμ©νκ³ μ€λ²λΌμ΄λλ₯Ό νμ©νλ €λ©΄
openλ³κ²½μ μΆκ° νμSpring Framework 5.2 λΆν°λ
@Configurationμ proxyBeanMethod μ΅μ μ ν΅ν΄ νλ‘μ μμ± λΉνμ±ν κ°λ₯
All-open μ»΄νμΌλ¬ νλ¬κ·ΈμΈ
μ½νλ¦°μ λ€μν μ»΄νμΌλ¬ νλ¬κ·ΈμΈμ μ 곡
all-openμ»΄νμΌλ¬ νλ¬κ·ΈμΈμ μ§μ ν μ λν μ΄μ μ΄ μλ ν΄λμ€μ λͺ¨λ λ©€λ²μ open λ³κ²½μλ₯Ό μΆκ°μ€νλ§μ μ¬μ©ν κ²½μ°
all-openμ»΄νμΌλ¬ νλ¬κ·ΈμΈμ λννkotlin-springμ»΄νμΌλ¬ νλ¬κ·ΈμΈμ μ¬μ© κ°λ₯@Component,@Transactional,@Asyncλ±μ΄ κΈ°λ³Έμ μΌλ‘ μ§μ
File > Project Structure > Project Settings > Modules > Kotlin > Compiler Plugins μμ μ§μ λ μ λν μ΄μ νμΈ κ°λ₯
Item 4. μ§μ° μ΄κΈ°ν
νλ μ£Όμ μ΄ νμνλ©΄ μ§μ° μ΄κΈ°νλ₯Ό μ¬μ©νμ
μ½νλ¦°μμ
lateinitλ³κ²½μλ₯Ό λΆμ΄λ©΄ νλ‘νΌν°λ₯Ό λμ€μ μ΄κΈ°νν μ μλ€. λμ€μ μ΄κΈ°ννλ νλ‘νΌν°λ νμ var
jackson-module-kotlin
jacksonμ κΈ°λ³Έμ μΌλ‘ μμ§λ ¬ν κ³Όμ μ μν΄ λ§€κ°λ³μκ° μλ μμ±μκ° νμνμ§λ§
μ½νλ¦°μμ λ§€κ°λ³μκ° μλ μμ±μλ₯Ό λ§λ€κΈ° μν΄ λͺ¨λ λ§€κ°λ³μμ κΈ°λ³Έ μΈμκ° νμ
jackson-module-kotlinμ λ§€κ°λ³μκ° μλ μμ±μκ° μλλΌλ μ§λ ¬νμ μμ§λ ¬νλ₯Ό μ§μμ½νλ¦°μ λ§€κ°λ³μκ° μλ μμ±μλ₯Ό λ§λ€κΈ° μν΄ μμ±μμ λͺ¨λ λ§€κ°λ³μμ κΈ°λ³Έ μΈμκ° νμ
Kotlin Annotation

λ°μ΄ν° ν΄λμ€μ propertyλ₯Ό μ μΈνλ μκ° field, Getter, Setter, μμ±μ νλΌλ―Έν° μν μν
@param.JsonProperty: parameterμ μ¬μ©λ μ΄λ¦@get.JsonProperty: getterμ μ¬μ©λ μ΄λ¦
Item 5. λ³κ²½ κ°λ₯μ± μ ν
λ³κ²½ κ°λ₯μ±μ μ ννμ
μ½νλ¦° ν΄λμ€μ λ©€λ²κ° finalμΈ κ²μ²λΌ μΌλ¨ valλ‘ μ μΈνκ³ νμ μ varλ‘ λ³κ²½νμ.
μμ±μ λ°μΈλ©μ μ¬μ©νλ €λ©΄
@EnableConfigurationPropertiesλλ
@ConfigurationPropertiesScanμ¬μ©
private property and backing property
κ³΅κ° API μ ꡬν μΈλΆ μ¬ν νλ‘νΌν°λ‘ λλ κ²½μ°
private νλ‘νΌν° μ΄λ¦μ μ λμ¬λ‘ λ°μ€μ μ¬μ©(backing property)
JVMμμλ κΈ°λ³Έ getter, setterκ° μλ private νλ‘νΌν°μ λν΄ ν¨μ νΈμΆ μ€λ²ν€λλ₯Ό λ°©μ§νλλ‘ μ΅μ ν
Persistence
No-arg μ»΄νμΌλ¬ νλ¬κ·ΈμΈ
JPAμμ μν°ν° ν΄λμ€λ₯Ό μμ±νλ €λ©΄ λ§€κ°λ³μκ° μλ μμ±μκ° νμ
no-argμ»΄νμΌλ¬ νλ¬κ·ΈμΈμ μ§μ ν μ λν μ΄μ μ΄ μλ ν΄λμ€μ λ§€κ°λ³μκ° μλ μμ±μλ₯Ό μΆκ°JPA, Kotlinμμ μ§μ νΈμΆν μ μμ§λ§ 리νλμ μ μ¬μ©νμ¬ νΈμΆ κ°λ₯
kotlin-spring Compiler Pluginκ³Ό λ§μ°¬κ°μ§λ‘ JPAλ₯Ό μ¬μ©νλ κ²½μ° no-arg μ»΄νμΌλ¬ νλ¬κ·ΈμΈμ λννkotlin-jpa Compiler Pluginμ¬μ© κ°λ₯JPA, Kotlin μ¬μ© μ μλμΌλ‘
kotlin-jpa Compiler PluginμΆκ°@Entity,@Embeddable,@MappedSuperclassκ° κΈ°λ³Έμ μΌλ‘ μ§μ
Item 6. μν°ν°
μν°ν°μ λ°μ΄ν° ν΄λμ€ μ¬μ©μ νΌνμ.
μλ°©ν₯ μ°κ΄ κ΄κ³μ κ²½μ°
toString(),hashcode()λ‘ λ¬΄ν μν μ°Έμ‘°κ° λ°μ
Item 7. μ¬μ©μ μ§μ getter
μ¬μ©μ μ§μ getterλ₯Ό μ¬μ©νμ.
JPA μ μν΄ μΈμ€ν΄μ€ν λ λ, μ΄κΈ°ν λΈλ‘μ΄ νΈμΆλμ§ μμΌλ―λ‘, μμννμ§ μλ νλλ μ¬μ©μ μ§μ getterλ₯Ό μ¬μ©νμ.
Item 8. Null νμ
μ κ±°
Nullμ΄ λ μ μλ νμ μ λΉ λ₯΄κ² μ κ±°νμ.
Nullμ΄ λ μ μλ νμ μ μ¬μ©νλ©΄ Null κ²μ¬λ !! μ°μ°μκ° νμνλ€.
μν°ν° ν΄λμ€μ idλ₯Ό 0 λλ λΉ λ¬Έμμ΄λ‘ μ΄κΈ°νν΄μ Nullμ΄ λ μ μλ νμ μ μ κ±°νμ.
Optional λ³΄λ€ Nullable ν νμ μ μ¬μ©ν΄μ λΆνμν java import λ₯Ό μ€μ΄μ.
νμ₯ ν¨μλ₯Ό μ¬μ©ν΄ λ°λ³΅λλ Null κ²μ¬λ₯Ό μ κ±°ν μ μλ€.
Test
λ¨μ ν
μ€νΈ
Junit, Mockito κ°μ Java λΌμ΄λΈλ¬λ¦¬λ‘ ν μ€νΈνλ―λ‘ Kotlin λ€μ΄ μ½λ μμ±μ΄ μ΄λ €μ
μμΈ ν μ€νΈλ JUnit5μ
assertThrowsλ°assertDoesNotThrowκ°μ Kotlin ν¨μλ₯Ό μ¬μ©νλ©΄ κ°κ²°
ν
μ€νΈ ν©ν 리
ν μ€νΈ ν½μ€μ²λ₯Ό λ°ννλ
ν©ν 리 ν¨μλ₯Ό λ§λ€ μ μλ€.ν μ€νΈ ν½μ€μ²: ν μ€νΈλ₯Ό μν μ μ 쑰건
Kotlin κΈ°λ³Έ μΈμλ₯Ό μ¬μ©νλ©΄
λΉλ ν¨ν΄μ²λΌ λ€μν κ²½μ°λ₯Ό μ²λ¦¬ κ°λ₯κΈ°λ³Έ μΈμμμ΄λ¦ λΆμΈ μΈμλ₯Ό μ μ ν μ¬μ©νλ©΄ ν μ€νΈνλ €λ κ΄μ¬μ¬λ₯Ό λλ¬λ΄λ λ° μ¬μ© κ°λ₯
ν
μ€νΈ νμ₯ ν¨μ
νμ₯ν¨μλ₯Ό μ¬μ©νμ¬ κ°μ λ μ½κ² νν
νμ₯ν¨μλ‘ κ²μ¦νκ³ μ νλ λΆλΆμ κ°λ μ± ν₯μ
Kotest μ΄μ€μ
ππ» ν μ€νΈ μ΄μ€μ
μΌλΆ μ΄μ€μ μ΄ μ€ν¨νλλΌλ ν μ€νΈκ° μ¦μ μ€μ§λμ§ μκ³ , λκΉμ§ κ²μ¦
μ΄λ€ νλ‘νΌν° λλ¬Έμ μ€ν¨νλμ§ λ°λ‘ μμμ±κΈ° μ΄λ €μ
μΈμ€ν΄μ€λ₯Ό λ°μ΄ν° ν΄λμ€λ‘ λ§λ€κ³ λΉκ΅νλ κ²μ κΆμ₯
μ£Όλ‘ JUnitμ Assertions λμ μ½κΈ° μ¬μ΄ AssertJμ Assertionsλ₯Ό μ¬μ©
ππΌ Kotest μ΄μ€μ
Kotest μ΄μ€μ μ κ°κ²°νκ³ κΈ°μ‘΄ JUnit5μ νΌμ© κ°λ₯
μ€λ§νΈ μΊμ€νΈ κ°μ Kotlin κΈ°λ₯μ μ§μ
ν λ² μ€λ§νΈ μΊμ€ν λμλ€λ©΄ nullμ λ€λ£¨μ§ μμλ λλ€.
Kotlinμμ Kotestκ° κ°μ₯ λ§μ΄ μ¬μ©
λ€μν μ€νμΌμ ν μ€νΈ λ μ΄μμμ μ 곡
κ·Έ μ€μμλ StringSpecμ μ¬μ©νλ©΄ μ λν μ΄μ μ μ¬μ©νμ§ μμλ λλ€.
λͺ¨μ ν
μ€νΈ
MockK
ππ» Mockito
Mockito final ν΄λμ€μ final λ©μλλ λͺ¨μ λΆκ°
Kotlin νμ₯ ν¨μλ Javaμ μ μ λ©μλμ΄λ©° Mockitoλ μ΄λ₯Ό μ€ν λΆκ°
μ΅μμ ν¨μλ νΉμ ν΄λμ€μ μνμ§ μκΈ° λλ¬Έμ μ€ν λΆκ°
ππΌ MockK
DSL κΈ°λ° Kotlin λͺ¨μ λΌμ΄λΈλ¬λ¦¬
μ½λ κΈ°λ°, μ λν μ΄μ κΈ°λ° λ± λλΆλΆ Mockitoμ λμΌ
β MockKλ₯Ό μ΄μ©ν μ°μ μ€ν°λΉ
MockKλ‘ μ μ ν¨μλ₯Ό λͺ¨μνμ§ μκ³ νμ₯ ν¨μλ₯Ό μ€ν νμ¬ λ΄λΆμ λ©€λ² ν¨μλ₯Ό μ€ν νλ λ°©λ²
λκ΅¬κ° κΈ°λ₯μ μ 곡νλ€κ³ ν΄μ νμ μ¬μ©ν΄μΌ νλ κ²μ μλλ€
κ°μ§ κ°μ²΄λ₯Ό μ¬μ©νλ κ²λ μ’μ λ°©λ²
ππ» Junit 5 + Mockito

ππΌ Kotest + MockK

Kotestλ₯Ό μ΄μ©ν λͺ¨μ ν
μ€νΈ
BDDλ₯Ό μ§μνλ BehaviorSpec, DescribeSpecμ΄ μ‘΄μ¬
ν μ€νΈκ° νλμ λ¬Έμλ‘μ λμ± νλΆ
μ€μ²© ν μ€νΈλ ν μ€νΈ μλͺ μ£ΌκΈ°λ₯Ό μ΄ν΄νλ κ²μ΄ μ€μ
Kotest μλͺ μ£ΌκΈ°
Given, When, Then μ μ΄λ£¨λ λͺ¨λ κ²μ beforeSpec, afterSpecμΌλ‘ listen
Given, When, Then λ§μ λ³Έλ€λ©΄ Container λΌκ³ λΆλ₯΄κ³
beforeContainer, afterContainer λ©μλλ‘ μλͺ μ£ΌκΈ° κ΄λ¦¬ κ°λ₯
Then μ beforeEach, afterEach λ©μλλ‘ μλͺ μ£ΌκΈ° κ΄λ¦¬ κ°λ₯
Kotestμ 격리 λͺ¨λ
Kotestλ SingleInstance, InstancePerLeaf, InstancePerTest μΈ κ°μ§ κ°μ΄ μ‘΄μ¬
κΈ°λ³Έμ
SingleInstanceμ΄λ©° ν μ€νΈ μν©μ λ§κ² 격리 λͺ¨λλ₯Ό μ νex. ν μ€νΈ ν΄λμ€ μ 체μ λͺ¨μ κ°μ²΄λ₯Ό λ§λλ λ° λΉμ©μ΄ λ§μ΄ λ λ€λ©΄
SingleInstanceλ₯Ό μ ννκ³ , clearMocks()μ νΈμΆνλ κ²μ΄ λ λμ μ μλ€.
ν΅ν© ν
μ€νΈ
Spring 5.2λΆν° @TestConstructor μ¬μ© μ μμ±μλ₯Ό ν΅ν μ£Όμ
μ΄ κ°λ₯
Kotestλ Spring ν΅ν© ν μ€νΈλ₯Ό μ§μνκΈ° μν΄
SpringExtenstionμ μ 곡λ³λμ μ λν μ΄μ μμ΄ μμ±μ μ£Όμ μ΄ κ°λ₯νλ©°,
SpringExtenstionμ ν΅ν΄μ νΈλμμ λ‘€λ°±λ κ°λ₯
μΈμ ν
μ€νΈ
μ¬μ©μ κ΄μ μμ κΈ°λ₯μ΄ μ¬λ°λ₯΄κ² μλνλμ§ νμΈνκΈ° μν ν μ€νΈ
μΌλ°μ μΌλ‘ μ¬μ©μ μ€ν 리μ λ°λΌ Given-When-Then μ€νμΌλ‘ μμ±
μ°κ΄ κ΄κ³κ° 볡μ‘ν μλ‘ ν μ€νΈ ν½μ€μ² μμ±μ΄ μ΄λ €μμ§
μΈμ ν μ€νΈλ₯Ό μν DSL
μ°κ΄ κ΄κ³λ₯Ό λλ©μΈμ νΉνλ μΈμ΄λ‘ νννκ³ , νμν λ°μ΄ν°κ° μμ±λλλ‘ ν μ μλ€.
μ½λλ₯Ό μ²μ μ νλ μ¬λλ€μ λλ©μΈ νμ΅μ λ§μ λμμ΄ λλ€.

λΆλ‘
Kover
IntelliJ, JaCoCo μμ΄μ νΈλ₯Ό μ¬μ©νλ Kotlin μ½λ 컀λ²λ¦¬μ§ λꡬ
Kotlinμ΄ μμ±ν λ°μ΄νΈμ½λλ‘ μΈ‘μ νλ©° μΈλΌμΈ ν¨μμ κ°μ΄ JaCoCoλ‘ μΈ‘μ ν μ μλ μμλ μΈ‘μ
Last updated