일급 컬렉션은 하나의 컬렉션을 객체로 감싸고, 해당 컬렉션과 관련된 로직을 한 곳에서 관리하도록 설계한 객체를 의미합니다.
즉, 단일 컬렉션(List, Set, Map 등)만을 인스턴스 변수로 가지며, 이를 통해 컬렉션과 관련된 비즈니스 로직과 제약 조건을 한 곳에서 캡슐화합니다.
컬렉션만 포함
불변성을 보장
비즈니스 로직 캡슐화
자체적인 유효성 검사
데이터에 이름 부여
List
나 Map
과 같은 컬렉션 객체를 사용하는 대신 의미 있는 클래스 이름으로 표현하여 코드 가독성과 의도를 명확히 합니다.다음은 일반적으로 List
를 사용하는 코드입니다:
class Order {
private List<Item> items;
public Order(List<Item> items) {
this.items = items;
}
public List<Item> getItems() {
return items;
}
}
items
에 대한 검증이나 추가 로직이 필요한 경우, 해당 로직이 분산될 가능성이 있습니다.Items
라는 일급 컬렉션을 만들어 관리합니다:
class Items {
private final List<Item> items;
public Items(List<Item> items) {
validate(items);
this.items = new ArrayList<>(items); // 불변성 보장
}
private void validate(List<Item> items) {
if (items == null || items.isEmpty()) {
throw new IllegalArgumentException("아이템 리스트는 비어 있을 수 없습니다.");
}
}
public int size() {
return items.size();
}
public boolean contains(Item item) {
return items.contains(item);
}
public List<Item> getItems() {
return Collections.unmodifiableList(items); // 불변 리스트 반환
}
}
Order
는 Items
를 필드로 가지도록 변경됩니다:
class Order {
private final Items items;
public Order(Items items) {
this.items = items;
}
public Items getItems() {
return items;
}
}
Items
에서 관리됩니다.items
컬렉션을 직접 수정할 수 없습니다.Order
객체가 다수의 Item
객체를 포함하는 경우, Items
라는 일급 컬렉션으로 관리.Tags
라는 일급 컬렉션을 만들어 유효성 검사와 추가 로직을 캡슐화.Scores
라는 일급 컬렉션을 사용하여 평균 계산, 최대/최소 점수 구하기 등의 로직을 처리.불변성을 유지해야 함
컬렉션 외의 상태를 추가하지 않음
지나친 사용 지양
일급 컬렉션 클래스에 로직을 포함하거나 비즈니스에 특화된 명확한 이름을 부여할 수 있습니다. 또한, 불필요한 컬렉션 API를 외부로 노출하지 않도록 할 수 있으며, 컬렉션을 변경할 수 없도록 만든다면 예기치 않은 변경으로부터 데이터를 보호할 수 있습니다.
일급 컬렉션은 컬렉션과 관련된 모든 로직을 하나의 객체로 캡슐화하여 응집성, 가독성, 재사용성을 높이고, 데이터 무결성을 보장합니다. 적절히 사용하면 유지보수가 쉬운 구조를 만들 수 있지만, 과도한 설계는 피해야 합니다.
추가 학습 자료