개발을 하던 중, Room 엔티티를 아래와 같이 redis hash로 생성하고 빌더 사용 시 playerContents 필드를 HashMap으로 초기화 해주었다.
@Getter
@Setter
@RedisHash(value = "room", timeToLive = 3600)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Room {
@Id
private String roomId;
private Status status;
private int maxPlayers;
private int totalRounds;
private int timer;
private List<String> currentPlayers;
private Map<String, List<String>> playerContents;
// private String gameType;
@Builder
public Room(String roomId, Status status, int maxPlayers, int totalRounds, int timer, List<String> currentPlayers, Map<String, List<String>> playerContents) {
this.roomId = roomId;
this.status = status;
this.maxPlayers = maxPlayers;
this.totalRounds = totalRounds;
this.timer = timer;
this.currentPlayers = currentPlayers;
this.playerContents = playerContents;
}
}
Java
복사
Room room = Room.builder()
.roomId(UUID.randomUUID().toString())
.status(Status.WAITING)
.maxPlayers(request.maxPlayers())
.totalRounds(request.totalRounds())
.timer(request.timer())
.currentPlayers(currentPlayers)
.playerContents(new HashMap<>())
.build();
Java
복사
그런데 엥… 바로 NullPointerException..
데이터를 확인해보니 다음과 같았다.
아예 키값 자체가 생성되고 있지 않기에 찾아보니, Redis는 기본적으로 null 또는 비어 있는 데이터는 저장하지 않는 동작을 가진다. 라고 한다.
엔티티 부분에서 기본값을 지정할 수도 있고, RedisRepository가 아닌 RedisTemplate를 사용한다면 직렬화 방식을 수정하여 null값 저장을 허용할수 있다고도 한다.
나는 조회 시 기본값을 보장해주는 방식으로 해결했다.
@Override
@Transactional(readOnly = true)
public Room findRoomById(String roomId) {
Room room = roomRepository.findById(roomId)
.orElseThrow(() -> new RoomException(ExceptionMessage.ROOM_NOT_FOUND));
if (room.getPlayerContents() == null) {
room.setPlayerContents(new HashMap<>()); // 기본값 설정
}
return room;
}
Java
복사