Java 패키지명 소문자로 붙여 쓰는 이유가 뭘까?
Java로 처음 프로젝트를 시작할 때 많은 개발자들이 의아해하는 규칙이 있습니다. 바로 Java 패키지명 소문자 작성 규칙입니다. com.mycompany.projectname처럼 여러 단어를 모두 붙이고, 대문자 없이 소문자만 사용하는 방식이죠.
클래스명은 MyClassName처럼 카멜케이스를 쓰는데, 왜 패키지만 다를까요? 단순한 코딩 컨벤션이 아니라, 실제 개발 환경에서 발생할 수 있는 문제를 예방하기 위한 설계입니다.

운영체제 파일시스템의 제약
Java 패키지 명명 규칙의 핵심은 크로스 플랫폼 호환성입니다.
Windows는 파일명 대소문자를 구분하지 않습니다. MyPackage와 mypackage를 같은 디렉토리로 인식하죠. 반면 Linux와 macOS는 이 둘을 완전히 다른 디렉토리로 취급합니다.
Windows: mypackage/ = MyPackage/ = MYPACKAGE/
Linux: mypackage/ ≠ MyPackage/ ≠ MYPACKAGE/
실제로 팀에서 개발할 때 이런 상황이 발생합니다:
- 개발자 A가 Mac에서
com.company.UserService패키지 생성 - 개발자 B가 Windows에서
com.company.userservice패키지 생성 - Git 저장소에서 충돌 발생 또는 한쪽 코드 손실
- 배포 서버(주로 Linux)에서 예기치 않은 ClassNotFoundException 발생
패키지명 붙여쓰기 이유도 여기서 출발합니다. 소문자로 통일하면 이런 문제가 원천 차단됩니다.
도메인 이름 규칙과의 일관성
Java 패키지명은 역순 도메인 네임(reverse domain name) 방식을 사용합니다. Oracle의 공식 문서(Naming a Package)에서도 이를 권장하고 있습니다.
도메인: example.com
패키지: com.example.projectname
인터넷 도메인은 대소문자를 구분하지 않습니다. Example.com과 example.com은 같은 주소죠. 패키지명도 이 규칙을 따라 소문자로 작성하면 도메인과 패키지 간 일관성이 유지됩니다.
특히 회사 도메인을 패키지명으로 사용할 때 혼란이 줄어듭니다:
// 일관성 있음
mycompany.com → com.mycompany.app
// 혼란스러움
MyCompany.com → com.MyCompany.app (X)
클래스명과의 명확한 구분
패키지명을 소문자로 작성하는 또 다른 이유는 클래스명과의 충돌을 방지하기 위해서입니다. Java에서 클래스명은 대문자로 시작합니다. 만약 패키지명도 대문자를 섞어 쓴다면 어떻게 될까요?
// 혼란스러운 상황
import com.company.UserService.UserService;
// 무엇이 패키지고, 무엇이 클래스인가?
com.company.UserService.UserServiceImpl
위 코드에서 UserService가 패키지인지 클래스인지 한눈에 구분하기 어렵습니다. 반면 소문자로 작성하면
// 명확한 구분
import com.company.userservice.UserService;
// 패키지: userservice (소문자)
// 클래스: UserService (대문자 시작)
com.company.userservice.UserServiceImpl
코드를 읽는 사람이 즉시 네임스페이스 구조를 파악할 수 있습니다. 특히 긴 import 문이나 약어가 아닌 전체 단어를 사용할 때 이런 구분이 중요합니다. 실제로 리팩토링 도구나 IDE도 이 규칙을 전제로 동작합니다. 패키지와 클래스를 자동으로 구분하여 import 최적화, 네임스페이스 충돌 감지 등의 기능을 제공하죠.
언더스코어를 피하는 이유
user_service처럼 언더스코어로 단어를 구분하면 가독성이 좋아 보입니다. 하지만 Java는 이를 권장하지 않습니다.
첫째, 패키지명이 URL이나 파일 경로로 변환될 때 특수문자가 문제를 일으킬 수 있습니다. 일부 빌드 도구나 웹 서버에서 언더스코어를 제대로 처리하지 못하는 경우가 있죠.
둘째, Java 언어 자체에서 언더스코어를 식별자로 사용할 때 제약이 있습니다. Java 9부터 단독 언더스코어(_)는 키워드로 예약되었고, 향후 버전에서 더 많은 제약이 생길 가능성이 있습니다.
// 비권장
com.my_company.user_service
// 권장
com.mycompany.userservice
가독성 vs 명확성
여러 단어를 붙여 쓰면 가독성이 떨어진다는 비판이 있습니다. useraccountmanagement보다 user-account-management가 읽기 쉽다는 것이죠.
하지만 실무에서는 다르게 접근합니다.
짧은 단어 조합 선호
// 나쁨
com.company.userauthenticationandauthorizationservice
// 좋음
com.company.auth
com.company.usermgmt
의미 단위로 패키지 분리
com.company.user // 사용자 관련
com.company.user.auth // 인증 하위 패키지
com.company.user.profile
패키지는 네임스페이스의 역할을 하므로, 한 단계당 단어를 짧게 유지하면 가독성 문제가 크게 줄어듭니다.
실제 프로젝트 적용 사례
대규모 오픈소스 프로젝트를 보면 이 규칙이 얼마나 일관되게 적용되는지 알 수 있습니다.
// Spring Framework
org.springframework.boot.autoconfigure
org.springframework.web.servlet
// Apache Commons
org.apache.commons.lang3.builder
org.apache.commons.io.filefilter
// Google Guava
com.google.common.collect
com.google.common.base
모두 소문자로 붙여 쓰고, 계층 구조로 명확하게 분리되어 있습니다. 10년 이상 유지되는 여러 프로젝트에서 이 규칙이 바뀌지 않는 이유는 실용성이 증명되었고, 큰 문제도 없었기 때문이 아닐까 합니다.
마무리: Java 패키지명 소문자 붙여쓰기 권장사항이지만 안 할 이유도 없다.
여러 단어를 소문자로 붙여 쓰는 게 마음에 안 들 때가 많았었는데 역시 다 이유가 있었습니다. 따로 알아보지 않았다면 패키지명에 대문자나 언더스코어를 왠지 저는 넣었을 것 같습니다.
Java 패키지명 소문자 붙여쓰기는 단순한 코딩 스타일이 아닌 예상치 못한 문제를 예방하기 좋은 의미 있는 권장사항이니 특별한 이유가 있다면 따르는 것이 좋을 것 같습니다. 딱히 논쟁의 여지도 없어 보입니다.
자주 묻는 질문(FAQ)
모든 Java 프로젝트가 이 규칙을 따라야 하나요?
공식 Java 코딩 컨벤션은 권장사항이지 강제는 아닙니다. 하지만 업계 표준으로 자리 잡았기 때문에, 특별한 이유가 없다면 따르는 것이 협업에 유리합니다.
카멜케이스(camelCase)를 패키지명에 쓰면 안 되나요?
기술적으로는 가능하지만, 파일시스템 충돌 위험과 가독성 저하 때문에 권장하지 않습니다. userService보다 user.service로 패키지를 분리하는 것이 더 나은 구조입니다.
숫자는 패키지명에 사용할 수 있나요?
사용 가능하지만 첫 글자로는 올 수 없습니다. com.company.api2 (O), com.company.2api (X). 버전 표시가 필요하다면 v2처럼 접두사를 붙이는 것이 일반적입니다.
패키지명 길이에 제한이 있나요?
Java 언어 스펙상 제한은 없지만, 일부 파일시스템은 전체 경로 길이(255자 또는 4096자)에 제약이 있습니다.