개발자에게 '코드'는 단순한 명령어의 나열이 아닌, 동료와의 소통을 위한 가장 중요한 '언어'입니다. 특히 여러 개발자가 협업하는 풀스택 환경에서는 일관된 코드 스타일, 즉 코틀린 코딩 컨벤션을 지키는 것이 프로젝트의 성패를 좌우하기도 합니다. 이는 단순히 코드를 예쁘게 만드는 것을 넘어, 가독성을 높여 버그 발생 가능성을 줄이고, 코드 리뷰 비용을 절감하며, 새로운 팀원이 프로젝트에 빠르게 적응할 수 있도록 돕는 핵심적인 역할을 합니다. 저 또한 수많은 프로젝트를 진행하며 잘 정립된 코딩 컨벤션이 얼마나 강력한 무기가 되는지 몸소 체험했습니다. 이 글에서는 JetBrains와 Google의 공식 가이드를 바탕으로, 실무에서 마주칠 수 있는 다양한 상황에 바로 적용할 수 있는 구체적이고 깊이 있는 코틀린 스타일 가이드를 제 경험과 함께 녹여내고자 합니다.
이름에 철학을 담다: 네이밍 컨벤션
좋은 이름은 코드의 절반을 설명합니다. 어떤 역할을 하는지, 어떤 데이터를 담고 있는지 이름만으로도 명확하게 유추할 수 있어야 합니다. 코틀린은 기본적으로 자바의 네이밍 컨벤션을 따르지만, 코틀린만의 특성이 가미된 몇 가지 중요한 규칙들이 있습니다.
기본 원칙: CamelCase와 PascalCase
가장 기본적인 명명 규칙은 다음과 같습니다. 자바 개발자라면 매우 익숙할 것입니다.
- 패키지 (Packages): 모두 소문자를 사용하며, 단어 사이는 점(.)으로 구분합니다. 밑줄(`_`)은 사용하지 않습니다. 전통적으로 역순 도메인 이름을 사용합니다.
com.mycompany.projectname.feature - 클래스, 인터페이스, 객체, 어노테이션, 열거형 (Classes, Interfaces, Objects, Annotations, Enums): 파스칼 케이스(PascalCase)를 사용합니다. 이름은 명사를 사용하는 것이 일반적입니다.
class UserProfile
interface UserRepository
object StringUtils - 함수, 프로퍼티 (Functions, Properties): 카멜 케이스(camelCase)를 사용합니다. 함수 이름은 주로 동사를 사용하여 어떤 동작을 하는지 나타내고, 프로퍼티 이름은 명사를 사용합니다.
fun fetchUserData()
val userName: String
상수(Constants)와 테스트 코드 작명법
상수와 테스트 코드는 일반적인 규칙과 약간 다른 작명법을 따릅니다.
상수 작명
컴파일 타임 상수는 `const val` 키워드를 사용하며, 이름은 대문자와 스네이크 케이스(UPPER_SNAKE_CASE)를 조합하여 작성합니다. 이는 자바의 `public static final`과 유사한 역할을 합니다. `const`가 아닌 런타임 불변 값이라도 최상위 레벨이나 `object` 내에 선언된 `val` 프로퍼티는 관례적으로 대문자 스네이크 케이스를 사용하기도 합니다.
// 컴파일 타임 상수
const val MAX_RETRY_COUNT = 3
object AppConfig {
// 런타임에 결정되지만, 프로그램 전역에서 불변인 값
val BASE_URL: String = loadBaseUrlFromConfig()
}
테스트 함수 작명
일반 함수와 달리, 테스트 코드는 가독성과 명확성이 더욱 중요합니다. 코틀린에서는 백틱(`` ` ``)을 사용하여 공백과 특수문자를 포함한 자연스러운 문장 형태로 함수 이름을 지을 수 있습니다. 이는 테스트의 목적을 매우 명확하게 전달하는 데 큰 도움이 됩니다.
import org.junit.jupiter.api.Test
class UserAuthenticationTest {
@Test
fun `유효한 아이디와 비밀번호를 입력하면 로그인에 성공한다`() {
// 테스트 로직
}
@Test
fun `잘못된 비밀번호를 입력하면 AuthenticationException이 발생한다`() {
// 테스트 로직
}
}
백틱을 이용한 테스트 함수명은 BDD(Behavior-Driven Development) 스타일의 테스트 코드를 작성할 때 특히 유용하며, 테스트 실패 시 어떤 시나리오에서 문제가 발생했는지 직관적으로 파악할 수 있게 해줍니다. 풀스택 개발자의 경험
Backing Properties 작명 규칙
클래스 내부에서만 수정 가능하고 외부에서는 읽기만 가능한 프로퍼티를 구현할 때 Backing Property 패턴을 자주 사용합니다. 이때 비공개 프로퍼티(private property)의 이름은 관례적으로 밑줄(`_`)로 시작합니다.
class UserViewModel {
// 외부에서는 수정 불가 (LiveData)
val user: LiveData<User>
get() = _user
// 내부에서만 수정 가능 (MutableLiveData)
private val _user = MutableLiveData<User>()
fun loadUser(userId: String) {
// 데이터를 불러와 _user 값을 변경
_user.value = ...
}
}
이 패턴은 캡슐화를 강화하고, 외부에서 상태를 예측 불가능하게 변경하는 것을 방지하여 안정적인 코드를 작성하는 데 도움을 줍니다.
| 요소 | 규칙 | 좋은 예 ✅ | 나쁜 예 ❌ |
|---|---|---|---|
| 패키지 | 소문자, 점(.) 구분 | com.example.myapp.data |
com.example.myApp.Data_Layer |
| 클래스/인터페이스 | 파스칼 케이스 (PascalCase) | class MainActivity, interface AuthService |
class mainActivity, interface auth_service |
| 함수/프로퍼티 | 카멜 케이스 (camelCase) | fun getUserProfile(), val itemCount |
fun GetUserProfile(), val Item_Count |
| 상수 (const val) | 대문자 스네이크 케이스 (UPPER_SNAKE_CASE) | const val TIMEOUT_MS = 5000 |
const val timeoutMs = 5000 |
| 테스트 함수 | 백틱(`)을 이용한 자연어 문장 | `사용자 정보가 없으면 예외를 던진다`() |
testUserNotFoundException() |
| 비공개 Backing Property | 밑줄(_)로 시작하는 카멜 케이스 | private val _items = mutableListOf<Item>() |
private val itemsInternal = mutableListOf<Item>() |
코드의 구조를 잡는 포매팅 규칙
일관된 포매팅은 코드의 가독성을 극대화합니다. 들여쓰기, 공백, 줄 바꿈 등 사소해 보이는 규칙들이 모여 코드를 읽고 이해하는 시간을 단축시켜 줍니다.
들여쓰기와 줄 길이
코틀린의 공식 스타일 가이드는 들여쓰기로 4칸 공백(space)을 권장합니다. 탭(tab) 문자는 사용하지 않습니다. 대부분의 최신 IDE는 이를 자동으로 설정해주므로 크게 신경 쓸 필요는 없지만, 팀 전체가 동일한 설정을 공유하는 것이 중요합니다.
한 줄의 최대 길이에 대한 엄격한 규칙은 없지만, 일반적으로 100자에서 120자 사이로 유지하는 것이 좋습니다. 코드가 한 화면에 들어오지 않고 가로 스크롤이 생긴다면 가독성이 급격히 떨어지기 때문입니다. 긴 표현식, 함수 호출 체인 등은 적절한 위치에서 줄 바꿈을 해주는 것이 좋습니다.
콜론(:)의 올바른 사용법
콜론은 코틀린에서 변수 타입 선언, 상속 등 다양한 곳에 사용됩니다. 콜론 주변의 공백 규칙은 간단하지만 중요합니다.
- 타입과 상위 타입을 구분할 때: 콜론 앞에 공백을 넣습니다.
- 인스턴스와 타입을 구분할 때(객체 리터럴 등): 콜론 뒤에 공백을 넣습니다.
// 좋은 예 ✅
interface Vehicle {
fun drive()
}
// 상속: 콜론 앞에 공백
class Car(val brand: String) : Vehicle {
// 변수 타입 선언: 콜론 앞에 공백 없음, 뒤에 공백
override fun drive() {
val message: String = "Driving a $brand car"
println(message)
}
}
fun main() {
// 이름있는 인자: 콜론에 공백 없음
val myCar = Car(brand = "Hyundai")
}
클래스 헤더 포매팅
클래스 생성자의 인자 개수와 상속 구조에 따라 헤더 포매팅 방식이 달라집니다.
인자가 적은 경우
생성자 인자가 2~3개 정도로 짧고, 한 줄에 충분히 표현 가능하다면 한 줄로 작성하는 것이 간결합니다.
class Person(val id: Int, val name: String)
인자가 많은 경우
생성자 인자가 많아 한 줄에 표현하기 어렵거나, 상속을 받는 경우에는 각 인자를 별도의 줄에 작성합니다. 이때 들여쓰기 규칙이 중요합니다.
- 각 인자는 4칸 들여쓰기 합니다.
- 여는 괄호 `(`는 클래스 이름과 같은 줄에 둡니다.
- 닫는 괄호 `)`는 새로운 줄에서 시작하며, 들여쓰기 하지 않습니다.
- 상속 키워드(`:`)와 상위 클래스/인터페이스는 닫는 괄호 `)`와 같은 줄에 위치시킵니다.
// 좋은 예 ✅
class UserProfile(
val id: Long,
val username: String,
val email: String,
val profileImageUrl: String?
) : BaseEntity(), Serializable {
// 클래스 본문
}
// 나쁜 예 ❌: 가독성이 떨어짐
class UserProfile(val id: Long, val username: String, val email: String, val profileImageUrl: String?) : BaseEntity(), Serializable {
// ...
}
이렇게 포매팅하면 각 인자를 명확하게 구분할 수 있고, 버전 관리 시스템(Git 등)에서 변경 사항(diff)을 추적하기 매우 용이해집니다. 한 줄에 모든 인자를 나열하면 인자 하나만 변경되어도 전체 줄이 변경된 것으로 표시되기 때문입니다.
제어자(Modifier) 순서
클래스나 함수에 여러 제어자가 붙을 때, 일관된 순서를 유지하면 코드를 예측 가능하게 만듭니다. 공식 가이드에서 권장하는 순서는 다음과 같습니다.
- `public` / `protected` / `private` / `internal` (가시성 제어자)
- `expect` / `actual`
- `final` / `open` / `abstract` / `sealed` / `const`
- `override`
- `lateinit`
- `tailrec`
- `vararg`
- `suspend`
- `inner`
- `enum` / `annotation` / `fun` (e.g. `fun interface`)
- `companion`
- `inline` / `value`
- `infix`
- `operator`
- `data`
이 모든 순서를 외울 필요는 없습니다. IDE(IntelliJ, Android Studio)의 코드 포매터(Reformat Code) 기능을 사용하면 자동으로 순서를 맞춰주므로, 이를 적극적으로 활용하는 것이 좋습니다.
// 예시: 제어자 순서 적용
public abstract class BaseRepository {
protected open suspend fun fetchData(): String {
// ...
}
}
// override와 가시성 제어자가 함께 사용될 때
internal override suspend fun fetchData(): String {
// ...
}
함수와 프로퍼티, 현명하게 사용하기
코틀린은 자바와 달리 필드(field)를 직접 선언하지 않고 프로퍼티(property)를 사용하며, 이는 간결하고 강력한 기능을 제공합니다. 하지만 언제 함수를 쓰고 언제 프로퍼티를 써야 할지 명확한 기준이 필요합니다.
Unit 반환: 생략의 미학
함수가 아무런 값도 반환하지 않을 때, 자바에서는 `void`를 사용하지만 코틀린에서는 `Unit`을 사용합니다. `Unit`은 실제 타입이며, `object`로 구현된 싱글톤 인스턴스입니다. 하지만 함수가 `Unit`을 반환하는 경우, 반환 타입 선언을 생략하는 것이 관례입니다. 이는 코드를 더 깔끔하게 만듭니다.
// 좋은 예 ✅
fun logMessage(message: String) {
println(message)
}
// 나쁜 예 ❌: 불필요한 선언
fun logMessage(message: String): Unit {
println(message)
}
표현식 본문(Expression Body) 활용
함수가 단일 표현식(single expression)으로 구성된 경우, 중괄호 `{}`와 `return` 키워드를 생략하고 `=`를 사용하여 표현식 본문 형태로 작성할 수 있습니다. 이는 코드를 매우 간결하고 읽기 쉽게 만들어 줍니다.
// 블록 본문 (Block Body)
fun double(x: Int): Int {
return x * 2
}
// 표현식 본문 (Expression Body)
fun double(x: Int): Int = x * 2
// 반환 타입 추론이 가능하므로 타입 선언도 생략 가능
fun double(x: Int) = x * 2
표현식 본문은 특히 간단한 계산이나 값의 변환을 수행하는 함수에 적합하며, 코드의 의도를 명확하게 드러내는 장점이 있습니다.
함수(Function) vs 읽기 전용 프로퍼티(Read-only Property)
인자 없는 함수와 `val`로 선언된 읽기 전용 프로퍼티는 문법적으로 서로 대체할 수 있어 보이지만, 의미적으로는 명확한 차이가 있습니다. 어떤 것을 선택할지는 다음 기준에 따라 결정해야 합니다.
아래의 특성을 모두 만족할 때, 인자 없는 함수 대신 프로퍼티를 사용하는 것을 우선적으로 고려해야 합니다.
- 예외를 던지지 않는다 (Throws no exceptions): 프로퍼티 접근은 안전해야 합니다.
- 계산 비용이 저렴하다 (Cheap to calculate): 이상적으로는 O(1) 복잡도를 가져야 하며, 무거운 계산이나 I/O 작업을 수행해서는 안 됩니다. 최초 접근 시 계산 결과를 캐싱하는 경우는 예외적으로 허용될 수 있습니다.
- 호출할 때마다 같은 결과를 반환한다 (Deterministic): 객체의 상태가 변경되지 않는 한, 프로퍼티는 항상 동일한 값을 반환해야 합니다.
이 기준을 이해하기 위해 몇 가지 예를 살펴보겠습니다.
| 상황 | 프로퍼티 (Property) ✅ | 함수 (Function) ✅ | 설명 |
|---|---|---|---|
| 리스트의 크기 가져오기 | val size: Int |
단순한 필드 접근으로, 비용이 저렴하고(O(1)) 항상 같은 값을 반환합니다. | |
| 현재 시간 가져오기 | fun getCurrentTime(): Long |
호출할 때마다 다른 값을 반환하므로 프로퍼티에 적합하지 않습니다. | |
| 데이터베이스에서 사용자 정보 조회 | fun fetchUser(id: String): User |
네트워크나 디스크 I/O가 발생하여 비용이 비싸고, 실패 시 예외를 던질 수 있습니다. | |
| 객체를 문자열로 변환 | override val toString: String |
override fun toString(): String |
toString()은 관례적으로는 함수지만, 비용이 저렴하고 결정적이라면 프로퍼티처럼 생각할 수 있습니다. 하지만 코틀린 표준 라이브러리는 함수 형태를 유지합니다. |
| 리스트가 비어있는지 확인 | val isEmpty: Boolean |
fun isEmpty(): Boolean |
isEmpty는 `size == 0`과 동일하며, 프로퍼티의 모든 조건을 만족합니다. 코틀린 컬렉션에서는 isEmpty() 함수와 size, indices 등의 프로퍼티를 모두 제공하여 유연성을 높입니다. |
풀스택 개발자 입장에서 이 규칙은 매우 중요합니다. 예를 들어, `user.profileImage`라는 프로퍼티가 내부적으로 네트워크 요청을 통해 이미지를 다운로드한다면, 사용하는 쪽에서는 단순한 필드 접근으로 착각하여 성능 저하의 원인을 찾기 어려워집니다. 반면 `user.fetchProfileImage()`라는 함수는 이름 자체로 시간이 걸리는 작업임을 암시합니다. 이처럼 함수와 프로퍼티의 올바른 선택은 API의 의미를 명확하게 전달하고 오용을 방지하는 중요한 설계 지침입니다.
코틀린의 꽃, 람다(Lambda)와 고차 함수 스타일
람다식은 코틀린을 함수형 프로그래밍 언어답게 만들어주는 핵심 기능입니다. 람다를 올바르게 사용하면 코드가 놀랍도록 간결하고 표현력이 풍부해집니다.
람다식 포매팅
람다식의 가독성을 위한 포매팅 규칙은 간단합니다.
- 항상 중괄호 `{}` 주변에 공백을 둡니다.
- 파라미터와 본문을 구분하는 화살표 `->` 주변에도 공백을 둡니다.
// 좋은 예 ✅
list.filter { it > 10 }.map { element -> element * 2 }
// 나쁜 예 ❌: 공백이 없어 가독성이 떨어짐
list.filter{it>10}.map{element->element*2}
후행 람다 (Trailing Lambdas)
코틀린에서는 함수의 마지막 인자가 람다인 경우, 람다를 괄호 `()` 밖으로 빼내어 작성할 수 있습니다. 이를 후행 람다라고 하며, 항상 이 스타일을 사용하는 것을 강력히 권장합니다.
// 일반적인 람다 전달
users.forEach({ user -> println(user.name) })
// 후행 람다 사용 (권장)
users.forEach { user -> println(user.name) }
// 인자가 람다 하나뿐인 경우 괄호()도 생략 가능
Thread {
// 스레드에서 실행할 코드
println("Running on a new thread")
}
후행 람다는 `if`, `for`와 같은 언어의 기본 제어문처럼 보이게 만들어 코드의 가독성을 극적으로 향상시킵니다. DSL(Domain-Specific Language)을 만들 때 특히 강력한 위력을 발휘합니다.
`it` vs 명시적 파라미터
람다의 파라미터가 하나일 경우, 파라미터 선언을 생략하고 암시적 이름인 `it`을 사용할 수 있습니다. `it`은 코드를 짧게 만들어주지만, 남용하면 오히려 가독성을 해칠 수 있습니다.
- `it`을 사용하는 경우: 람다가 중첩되지 않고, `it`이 무엇을 가리키는지 문맥상 명확할 때 사용합니다.
- 명시적 파라미터를 사용하는 경우:
- 람다가 중첩되어 `it`의 스코프가 헷갈릴 때
- `it`이 가리키는 대상의 타입을 명확히 하고 싶을 때
- 파라미터에 더 의미 있는 이름을 부여하고 싶을 때
// 좋은 예 ✅: `it`이 user를 가리키는 것이 명확함
users.forEach { println(it.name) }
// 나쁜 예 ❌: 중첩된 람다에서 `it`을 사용해 혼란을 유발
// 바깥 `it`은 user, 안쪽 `it`은 permission
users.forEach {
it.permissions.forEach {
println("User ${it.name} has permission: $it") // 컴파일 오류! 안쪽 it이 바깥 it을 가림
}
}
// 좋은 예 ✅: 명시적 파라미터로 가독성 및 안정성 확보
users.forEach { user ->
user.permissions.forEach { permission ->
println("User ${user.name} has permission: $permission")
}
}
안정성을 위한 약속: 불변성과 널 안정성
코틀린의 가장 큰 장점 중 하나는 코드의 안정성을 높여주는 강력한 기능들을 언어 차원에서 제공한다는 점입니다. 불변성(immutability)과 널 안정성(null safety)은 그 핵심입니다.
`var` 대신 `val`을 우선하라
변수를 선언할 때 `val`(value, 읽기 전용)과 `var`(variable, 변경 가능) 중 선택할 수 있습니다. 항상 `val`로 먼저 선언하고, 꼭 필요한 경우에만 `var`로 변경하는 습관을 들이는 것이 좋습니다.
불변성을 지향하면 다음과 같은 이점이 있습니다.
- 예측 가능한 코드: `val`로 선언된 변수는 재할당될 수 없으므로, 코드의 특정 시점에서 그 값이 무엇인지 추론하기 쉽습니다.
- 사이드 이펙트 감소: 값이 변하지 않으므로 의도치 않은 부수 효과(side effect)로부터 자유로워집니다.
- 스레드 안전성(Thread Safety): 불변 객체는 여러 스레드에서 동시에 접근해도 안전하므로, 멀티스레딩 환경에서 복잡한 동기화 문제없이 사용할 수 있습니다.
// 좋은 예 ✅: 불변 컬렉션을 사용하여 안정성을 높임
fun processItems(items: List<Item>): List<Result> {
val processedResults = mutableListOf<Result>() // 함수 내부에서만 변경 가능
for (item in items) {
// ... item 처리 로직
processedResults.add(result)
}
return processedResults // 반환 타입은 불변 List
}
// 나쁜 예 ❌: 변경 가능한 파라미터를 받아 직접 수정 (사이드 이펙트 발생)
fun processItemsInPlace(items: MutableList<Item>) {
// items 리스트 자체를 변경하므로, 이 함수를 호출한 다른 코드에 영향을 줄 수 있음
}
특히 데이터 클래스(`data class`)의 프로퍼티는 가능하면 모두 `val`로 선언하여 불변 객체로 만드는 것이 클린 코드를 위한 첫걸음입니다.
널 포인터 예외(NPE)와 작별하기
코틀린의 타입 시스템은 널이 될 수 있는 타입(`String?`)과 널이 될 수 없는 타입(`String`)을 명확하게 구분하여 컴파일 시점에 NPE 발생 가능성을 대부분 차단합니다.
`!!` 연산자는 피하라
널이 아님을 단언하는 `!!` 연산자는 코틀린의 널 안정성 시스템을 무력화시키는 '탈출구'입니다. 이 연산자는 "나는 이 값이 절대 널이 아니라고 확신해. 만약 널이면 `NullPointerException`을 발생시켜도 좋아"라고 컴파일러에게 말하는 것과 같습니다. 이는 결국 자바와 같은 잠재적 NPE 위험을 코드에 심는 행위입니다.
`!!`는 정말 피할 수 없는 경우(예: 외부 자바 라이브러리 연동)를 제외하고는 절대 사용하지 말아야 합니다.
안전한 방법들을 사용하라
코틀린은 널을 안전하게 다룰 수 있는 다양한 방법을 제공합니다.
- 안전한 호출 (Safe Call) `?.`: 객체가 널이 아니면 메서드를 호출하고, 널이면 `null`을 반환합니다.
- 엘비스 연산자 (Elvis Operator) `?:`: 왼쪽의 표현식이 널이 아니면 그 값을 사용하고, 널이면 오른쪽의 기본값을 사용합니다.
- 안전한 캐스트 (Safe Cast) `as?`: 타입 캐스팅에 실패하면 예외를 던지는 대신 `null`을 반환합니다.
- 스코프 함수 `let`: 널이 아닌 경우에만 특정 코드 블록을 실행하고 싶을 때 `?.let` 패턴을 유용하게 사용할 수 있습니다.
// 나쁜 예 ❌: 언제 터질지 모르는 시한폭탄
val nameLength = user!!.name!!.length
// 좋은 예 ✅: 안전하고 우아한 널 처리
// 1. 안전한 호출과 엘비스 연산자
val nameLength = user?.name?.length ?: 0
// 2. 널이 아닐 때만 특정 동작 수행하기
user?.name?.let {
println("사용자 이름: $it")
// 'it'은 여기서 non-null String 타입으로 스마트 캐스팅 됨
}
이러한 도구들을 적극적으로 활용하면 NPE 걱정 없는 견고하고 안정적인 애플리케이션을 만들 수 있습니다.
마무리: 컨벤션은 도구로 강제하라
지금까지 실무에서 중요한 여러 코틀린 코딩 컨벤션을 살펴보았습니다. 하지만 아무리 좋은 규칙도 사람이 일일이 기억하고 지키기에는 한계가 있습니다. 코드 리뷰에서 스타일 문제를 지적하는 데 시간을 낭비하는 것은 비효율적입니다.
따라서 정적 분석 도구(linter)와 포매터(formatter)를 도입하여 컨벤션을 자동으로 검사하고 강제하는 것이 현대적인 개발 프로세스의 핵심입니다.
추천 도구
- ktlint: 코틀린 공식 스타일 가이드를 기반으로 하는 매우 인기 있는 린터 및 포매터입니다. 별도의 설정 없이 바로 사용할 수 있으며, Gradle 플러그인을 통해 빌드 과정에 쉽게 통합할 수 있습니다.
- IntelliJ IDEA / Android Studio 내장 포매터: IDE에서 제공하는 강력한 포매팅 기능을 활용할 수 있습니다. `Code > Reformat Code` (단축키: Ctrl+Alt+L 또는 Cmd+Option+L)를 실행하면 설정된 코드 스타일에 맞게 코드가 정리됩니다. 팀원들과 동일한 스타일 설정을 공유하기 위해 `.editorconfig` 파일을 프로젝트에 포함하는 것이 좋습니다.
# .editorconfig 파일 예시
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.{kt,kts}]
indent_size = 4
이러한 도구를 CI(Continuous Integration) 파이프라인에 통합하면, 정해진 코드 스타일을 위반하는 코드는 아예 메인 브랜치에 병합되지 않도록 막을 수도 있습니다.
코딩 컨벤션은 단순히 보기 좋은 코드를 만드는 것을 넘어, 프로젝트의 유지보수성과 팀의 협업 효율성을 결정짓는 중요한 요소입니다. 오늘 소개된 내용들을 바탕으로 자신만의, 그리고 팀만의 견고한 Kotlin 스타일 가이드를 구축하여 더 높은 품질의 소프트웨어를 만들어나가시길 바랍니다.
더 자세한 내용이 궁금하다면 아래 공식 문서를 참고하는 것도 좋은 방법입니다.
Post a Comment