일급 컬렉션은 하나의 컬렉션을 객체로 감싸고, 해당 컬렉션과 관련된 로직을 한 곳에서 관리하도록 설계한 객체를 의미합니다.
즉, 단일 컬렉션(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를 외부로 노출하지 않도록 할 수 있으며, 컬렉션을 변경할 수 없도록 만든다면 예기치 않은 변경으로부터 데이터를 보호할 수 있습니다.
일급 컬렉션은 컬렉션과 관련된 모든 로직을 하나의 객체로 캡슐화하여 응집성, 가독성, 재사용성을 높이고, 데이터 무결성을 보장합니다. 적절히 사용하면 유지보수가 쉬운 구조를 만들 수 있지만, 과도한 설계는 피해야 합니다.
추가 학습 자료