코틀린의 자료형, 변수형과 같은 기본적인 나무들을 공부하기 전에, 숲을 한 번 보자. 코틀린은 프로젝트, 모듈, 패키지, 파일로 구성되어 있다. 그럼 하나 하나 살펴보자.
코틀린 프로젝트는 모듈을 포함하고, 모듈은 다시 패키지를 포함한다. 다시 패키지는 파일로 구성되어 있다. (프로젝트 > 모듈 > 패키지 > 파일 순)
아래 그림을 보면 더 이해하기 쉬운데, HelloKotlin이라는 프로젝트 안에 HelloKotlin 모듈과 OtherModule이 포함되어 있다. HelloKotlin 모듈안에는 default와 com.example.edu 패키지 2개가 포함되어 있으며, 각 패키지에는 HelloKotlin.kt과 같은 파일들이 들어 있다. 보통 대규모 프로젝트에서는 기능을 모듈로 분리하여 관리하기에, HelloKotlin 프로젝트는 크게 2개의 기능을 가진 것이라 볼 수 있다.
[출처: https://acaroom.net/ko/blog/youngdeok/%EC%97%B0%EC%9E%AC-%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%8C%A8%ED%82%A4%EC%A7%80]
코틀린 파일은 .kt 확장자를 가지며 파일의 맨 위에는 이 파일이 어떤 패키지에 포함된 것인지 컴파일러가 알 수 있도록 패키지 이름을 선언해주어야 한다. (이름을 선언하지 않으면 해당 파일은 default 패키지에 포함된 것으로 간주한다.)
꿀팁!!!
파일 하나에 클래스가 1개면 해당 파일은 곧 클래스를 나타내고, 파일 하나에 클래스가 여러 개 정의되어 있다면 해당 파일은 단순 묶음으로 보인다. 안드로이드 스튜디오에서 파일별로 아이콘이 달라 이 둘을 구분할 수 있다.
파일이 곧 클래스면 안드로이드 스튜디오의 project 창에서 .kt을 생략하고, 파일 안에 클래스가 여러 개가 있다면 .kt을 생략하지 않는다.
두 명의 개발자가 프로젝트를 진행하다가 우연히 같은 이름의 파일을 만든다 가정해보자. 이 경우 파일이 중복되어 당연히 오류가 발생한다. 단, 패키지가 다르면 오류가 발생하지 않아서 프로그램이 정상적으로 실행된다. (위의 예시 중 default 패키지에도 Person 파일이 있고 com.example.edu 패키지에도 Person 파일이 있는데도 문제가 안 생기는 것처럼) 이처럼 클래스간의 이름 충돌을 막으면서 파일을 쉽게 관리하기 위해 패키지가 필요하다.
패키지명을 선정할 때는 조심해야할 부분이 몇 가지 있다. 패키지 이름은 특수문자, 숫자로 시작하면 안되고 이름에 분류가 필요하면 .을 붙여서 구분한다.
주의!!!!!
패키지명에 example이 포함되어 있을 경우, 플레이 스토어에 업로드 할 수 없다. 반드시 com.회사명 혹은 com.본인이름.앱이름 (예: com.soeun.habitpallete) 형태로 작성해야 한다. 패키지명은 나중에도 바꿀 수 있다.
기본 패키지명이 com.soeun.habitpallete 이었고, 이 패키지에 네트워크 기능을 추가한다면 com.soeun.habitpallete.net으로 명명하고, 해당 패키지 안에 네트워크 업로드 기능도 구현한다면 com.soeun.habitpallete.net.upload로 명명하면 소스를 보다 쉽게 관리할 수 있다.
코딩을 하다보면 패키지를 import해야 하는 경우가 많이 생긴다. 이 경우, 안드로이드 스튜디오에서 ALT+Enter를 누르면 자동으로 패키지가 import 된다.
주의!!!
import 할 때 *을 사용해서 패키지의 하위 요소를 모두 불러올 수 있다. 하지만, 이 경우 프로젝트 용량이 늘어나 코드 최적화에 문제가 될 수 있으므로 필요한 패키지 1개만 불러오는 것을 권장한다.
안드로이드 스튜디오에서 기본적으로 제공하는 패키지가 아닌, 사용자가 정의한 클래스도 다른 패키지에서 가져올 수 있다. 이 경우에도 패키지 이름과 요소를 import하면 된다.
package.cahp02.section1 //현재 package
import com.example.edu.Person //가져온 사용자 정의 클래스
fun main(){
val user1 = Person("Soeun", 25)
}
만약 import로 가져올 클래스 외에, 현재 패키지에도 동명의 클래스가 존재한다면 as 키워드를 사용해 클래스 이름에 별명을 붙이면 된다.
package.cahp02.section1 //현재 package
import com.example.edu.Person as User//가져온 사용자 정의 클래스
fun main(){
val user1 = User("Soeun", 25) // com.example.edu 패키지의 Person이 User로 재명명
val user2 = Person("Soeun", "Lee") //현재 패키지의 파일 안에 있는 Person 클래스
}
class Person(val firstName: String, vak lastName: String)