Skip to Content
Backend Architecture패키지/클래스/테이블 단수·복수 네이밍

패키지/클래스/테이블 단수·복수 네이밍 규칙

개요

도메인 코드를 짤 때 event인지 events인지 헷갈리는 이유는, 계층마다 적용되는 규칙이 다르다는 걸 인지하지 못해서다. 패키지·클래스는 “개념의 이름”이라 단수, DB 테이블은 “행(레코드)의 집합”이라 복수가 관례다. 둘이 섞여 있는 것이 정상이며 불일치가 아니다.

핵심 규칙

대상규칙
패키지(package)단수event, coupon, user, order
클래스(class)단수Event, Coupon, EventRepository
DB 테이블복수events, coupons, event_participations
컬렉션 변수/엔드포인트복수List<Event> events, GET /events

왜 패키지·클래스는 단수인가

패키지는 “이 도메인 영역”이라는 개념(concept)의 이름이다. com.example.order는 “주문이라는 개념의 영역”이지 “주문들이 담긴 상자”가 아니다. 클래스도 인스턴스 하나의 타입을 정의하므로 단수다 (Event event = new Event()).

Spring/DDD 진영의 표준 패키지 구조도 모두 단수다:

com.example.order ← 단수 com.example.user com.example.payment
event/ ✅ event/domain/Event.java (자연스러움) events/ ❌ events/domain/Event.java (단/복수 불일치, 어색)

왜 DB 테이블은 복수인가

테이블은 같은 구조의 행이 여러 개 모인 집합이다. SELECT * FROM events는 “이벤트들에서 조회”로 자연스럽게 읽힌다. 그래서 ORM 매핑에서 클래스(단수)와 테이블(복수)이 어긋나는 게 정상이며, 명시적으로 매핑한다:

@Entity @Table(name = "events") // 클래스 Event(단수) → 테이블 events(복수) public class Event { ... }

패키지명과 테이블명은 독립적이다. 패키지를 단수로 둬도 @Table(name = "events")로 복수 테이블을 그대로 가리킨다.

참고: 테이블 단수 vs 복수는 팀 컨벤션 차이가 있다(일부 팀은 단수 event 선호). 핵심은 한 프로젝트 안에서 일관성이다. 다만 패키지·클래스 단수는 거의 보편적 관례다.

흔한 혼동

  • “패키지가 단수면 테이블도 단수로 맞춰야 하지 않나?” → 아니다. 서로 다른 규칙을 따르는 다른 레이어다. 일치시킬 대상이 아니다.
  • “REST 엔드포인트는?” → 컬렉션이라 복수(GET /api/v1/events). 이건 테이블과 같은 “집합” 논리다. 단일 리소스는 GET /events/{id}로 컬렉션 하위 경로를 쓴다 (REST Resource Naming 참고).

결론

  • 패키지 단수, 클래스 단수, 테이블 복수 — 이 조합이 표준이다.
  • 단·복수가 레이어마다 다른 것은 버그가 아니라 의도된 컨벤션이다.
  • event/domain/Event.java + @Table(name = "events") 형태로 가면 된다.
Last updated on