블루밍 작업 중 골에 참여하는 참여자 리스트 관련 로직이 많아져 이를 Teams
로 따로 뺐다. (이전 글 참고) 그런데 이 Teams
의 경우 독립된 하나의 역할을 맡는 엔티티 클래스라고 보긴 어려웠다. 그래서 Teams
의 생성자를 그대로 사용하기보다 생성 역할을 하는 팩토리 메서드를 사용하는 것이 어떻냐는 의견에 팩토리 메서드로 분리 작업을 수행했다.
리팩토링 도중 아래와 같은 에러를 마주하게 되었는데…
위의 에러를 좀 더 자세히 알아보자면
UnsupportedOperationException
불변 리스트의 변이: 만약goalTeams
가 불변 리스트로 처리된다면(예: 직렬화/역직렬화 또는 외부 요인으로 인해), 해당 리스트를 수정하려고 할 때UnsupportedOperationException
이 발생합니다. 리스트가 실제로 가변인지 확인하십시오.
출처: chatGPT
처음보는 에러라 매우 당황했다.
goalTeams
를 받을 Teams
의 goalTeams
는 필드 선언부에서 new ArrayList<>()
로 초기화 해줬기 때문에 가변상태였고, 그 이후로는 이 ArrayList
에 추가할 뿐이라 에러가 날 곳이 없다고 생각했다. 문제는…. 생성자에 있었다.
Teams 생성 로직
private Teams(final List<GoalTeam> goalTeams) {
this.goalTeams = goalTeams;
}
public static Teams create(final List<User> users, final Goal goal) {
validateUsersSize(users);
final List<GoalTeam> goalTeams = users.stream()
.map(user -> new GoalTeam(user, goal))
.toList();
return new Teams(goalTeams);
}
이렇게 생성자에서 생성을 해준 이후에는 수정이 불가한 상태가 되어버린 것이다.
Teams
를 생성할 때는 문제없이 잘 돌아가던 로직이었는데, 수정에서 문제가 발생했다.
기존 Teams
의 goalTeams
에 없는 사용자로 새로운 GoalTeam
객체들을 만들고, 이들을 stream().map().toList()
로 받아 기존 Teams
의 goalTeam
에 추가해주려고 했는데 추가에서 문제가 생겼다.
이유인 즉슨, this.goalTeams
를 new ArrayList<>()로
초기화 했으나 생성자에서 파라미터로 받은 goalTeam
을 그대로 할당해 기존 초기화가 의미가 없어졌으며, 파라미터로 받은 goalTeam
은 stream
을 toList
형태로 바꿔준 것이라 원소가 추가되거나 제거될 수 없다고 한다. 그러니까 stream().map().toList()
자체가 불변상태였던 것이다..
그래서 위의 생성자 로직을 다음과 같이 기존 리스트에 추가하는 식으로 바꿔주니 에러가 발생하지 않고 잘 돌아갔다.
private Teams(final List<GoalTeam> goalTeams) {
this.goalTeams.addAll(goalTeams);
}
이렇게 또 하나 배워간다.. 자바 공부 좀 해야할 것 같다ㅎ