본 가이드는 Kotlin 공식 코딩 컨벤션을 바탕으로 하여, 코틀린 프로그래밍 시 일관된 코딩 스타일을 유지하기 위한 권장 사항을 제공합니다.
Helper❌, Wrapper❌) ArrayList⭕️, FileReader⭕️, RunCommand❌ → CommandRunner⭕️)isDirty, sorted, hasDigit)close, readFile, appendNode)FileStream.readStream()❌ → FileStream.read()⭕️)IOStream, myPKFieldfun addXmlDeclaration() { ... }.(점)만을 사용합니다. 단 숫자는 단어 가장 앞에 사용하지 않습니다. (com.company.departure⭕️, com.company.departure.v1.0❌)com.mycompany.myproject❌)com.myCompany.myProject)class MyClass {}
data class SomeDataClass {}
object DerivedObject : BaseObject() {}
interface MyTableRepository : JpaRepository<MyEntity, IdClass>
_, underscore)은 사용하지 않습니다.class MyClass {
private var myPrivateProperty: Int = 0
...
fun getPrivatePropertyPlusOne() = myPrivateProperty + 1
}
object NullResponse {
const val STRING = "null"
const val INT = -1
const val LONG = -1L
const val DOUBLE = 0.0
val DATE = LocalDate.MIN
const val YEAR = 1970
}
enum class PeriodType(val value: String, val comment: String) {
UNKNOWN("", ""),
STUDY_PERIOD("P", "학습 기간"),
STUDY_START("S", "학습 시작일"),
STUDY_END("E", "학습 종료일");
}
class SomeClass {
private val _propertyList = mutableListOf<Property>()
val propertyList: List<Property>
get() = _propertyList
}
`)을 이용하여 자유 문장형 네이밍이 가능합니다./, \, ., <, >, [, ] 문자는 사용할 수 없습니다.class MyTestCase {
@Test
fun `과정 별 수료 현황 API를 테스트하고 Rest-Doc으로 OAS 문서를 생성한다`() { ... }
}
들여 쓰기는 공백(스페이스) 문자 4개를 사용합니다. 탭 문자(\t)는 사용하지 않습니다.
중괄호 ({ })
{)는 중괄호가 필요한 구문 줄 끝에 한 칸 공백을 넣어서 배치하고, 닫는 중괄호(})는 별도 줄의 여는 중괄호가 있는 구문과 수직 줄맞춤된 위치에 배치합니다.if (elements != null) {
for (element in elements) {
// ...
}
}
fun from(v: String) = values().find { v.equals(it.value, true) }
괄호 (( ))
if, when, for, while) 뒤의 여는 괄호 앞에 공백을 한 칸 넣습니다.class A(val x: Int)
fun foo(x: Int) {
if (x > 100) ...
}
fun bar() {
foo(1)
}
콜론 (:)
object 키워드 뒤에 사용될 때abstract class Foo<out T : Any> : IFoo {
abstract fun foo(a: Int): T
}
class FooImpl : Foo() {
constructor(x: String) : this(x) { ... }
val x = object : IFoo { ... }
}이항 연산자 앞 뒤에 공백을 넣습니다. ( a + b * c ) 단, 범위 연산자(..) 앞 뒤에는 공백을 넣지 않습니다. (0..i)
(), [], <> 사이에 공백을 넣지 않습니다.
fun <T : Annotation> collectConstantsAsClass(clazz: Class<T>): List<Class<*>> { ... }
., ?., :: 앞뒤에 공백을 넣지 않습니다. ?: 앞 뒤에는 공백을 넣어 줍니다.
list?.filter { it != "" }?.joinToString(", ") { it.toString() } ?: ""
// 또는 , 뒤에 공백을 넣어 줍니다. // 주석입니다. (1, 2, 3)
Nullable 지정자 (?) 앞에 공백을 넣지 않습니다.
class StringToCourseTypeConverter : Converter<String, CourseType> {
override fun convert(source: String): CourseType? {
return CourseType.values().firstOrNull {
it.value.equals(source, true)
} ?: findEnumInsensitiveCase(CourseType::class.java, source)
}
}
class CompletionRequest(
val page: Int = 1, // 페이지 번호
val perPage: Int = DEFAULT_PER_PAGE, // 페이지당 건수
val trainingCenterSeq: Int = 0, // 연수원 코드
var fromDate: LocalDate, // 기간 검색 시작일
var toDate: LocalDate // 기간 검색 종료일
) {
fun setRequest(
page: Int = 1, perPage: Int = DEFAULT_PER_PAGE,
trainingCenterSeq: Int = 0,
fromDate: LocalDate, toDate: LocalDate
) { ... }
}:)을 줄 마지막에 붙이고 상속 받을 유형들을 다음 줄로 줄바꿈하여 하나씩 나열합니다.class MyFavouriteVeryLongClassHolder :
MyLongHolder<MyFavouriteVeryLongClass>(),
SomeOtherInterface,
AndAnotherOne {
fun foo() { /*...*/ }
}또는 class MyFavouriteVeryLongClassHolder :
MyLongHolder<MyFavouriteVeryLongClass>(),
SomeOtherInterface,
AndAnotherOne
{
fun foo() { /*...*/ }
}. 또는 ?. 연산자로 시작하는 한칸 들여쓰기로 줄바꿈을 합니다.RestDocumentationRequestBuilders
.get("$API_BASE_PATH/completion/course")
.characterEncoding("UTF-8")
.queryParam("page", "1")
.queryParam("perPage", "5")
.queryParam("trainingCenterSeq", "111")
.queryParam("periodSearchType", PeriodSearchType.BY_PERIOD.value)
.queryParam("periodSearchYear", "2023")
.queryParam("periodSearchMonth", "12")
.queryParam("periodType", PeriodType.STUDY_START.value)
.queryParam("companySeq", "208")
.queryParam("companySeq", "224")
.queryParam("courseType", CourseType.ONLINE.value)
.queryParam("exceptCourse", ExceptCourseType.SAFETY.value, ExceptCourseType.FREE.value)
.queryParam("fromDate", "2023-01-01")
.queryParam("toDate", "2023-12-31")또는RestDocumentationRequestBuilders.get("$API_BASE_PATH/completion/course")
.characterEncoding("UTF-8")
.queryParam("page", "1")
.queryParam("perPage", "5")
.queryParam("trainingCenterSeq", "111")
.queryParam("periodSearchType", PeriodSearchType.BY_PERIOD.value)
.queryParam("periodSearchYear", "2023")
.queryParam("periodSearchMonth", "12")
.queryParam("periodType", PeriodType.STUDY_START.value)
.queryParam("companySeq", "208")
.queryParam("companySeq", "224")
.queryParam("courseType", CourseType.ONLINE.value)
.queryParam("exceptCourse", ExceptCourseType.SAFETY.value, ExceptCourseType.FREE.value)
.queryParam("fromDate", "2023-01-01")
.queryParam("toDate", "2023-12-31")/** 로 열어서 */ 로 끝나는 주석 형식을 사용해 주세요. 주석 중간의 라인은 * 로 시작하게 합니다.@param 이나 @return 태그는 사용하지 않는 것이 좋습니다. TODO: FIXME: 같은 태그는 적극 활용하는 것이 좋습니다. /**
* status = 1이고 learningTime = 0이면
* 전체 교육 시간을 리턴한다.
* TODO: 전체 교육 시간 계산 산식이 변경될 경우 이 함수를 수정해 주자.
* by hyh 2024/01/10
*/val name = "Kotlin"object YnFlag {
const val Y = "Y"
const val N = "N"
const val y = "y"
const val n = "n"
const val UNKNOWN = ""
fun isY(target: String, ignoreCase: Boolean = true) = target.equals(Y, ignoreCase)
fun isN(target: String, ignoreCase: Boolean = true) = target.equals(N, ignoreCase)
fun getYn(condition: Boolean) = if (condition) Y else N
}
fun String.isY(ignoreCase: Boolean = true) = equals(YnFlag.Y, ignoreCase)
fun String.isN(ignoreCase: Boolean = true) = equals(YnFlag.N, ignoreCase)
fun Boolean.getYn() = YnFlag.getYn(this)
...
var checked = YnFlag.Y
if (checked.isY()) { ... }fun checkCondition(someCondition: Boolean): String {
var conditionState: Int
if (someCondition)
conditionState = 1
else
conditionState = 0
...
when(conditionState) {
0 -> return "False"
else -> return "True"
}
}이 코드는 다음과 같이 작성하는 것이 훨씬 간결합니다.fun checkCondition(someCondition: Boolean): String {
var conditionState = if (someCondition) 1 else 0
...
return when(conditionState) {
0 -> "False"
else -> "True"
}
};)은 코틀린에서는 생략이 가능하므로 가능한한 생략합니다.apply, with, run, also, let)를 사용해 주세요.