Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package konkuk.thip.room.adapter.in.web.response;

import io.swagger.v3.oas.annotations.media.Schema;

import java.util.List;

@Schema(description = "내가 참여 중인 방 목록 조회 응답")
public record RoomShowMineResponse(
List<MyRoom> roomList,
String nextCursor,
Expand All @@ -12,6 +15,11 @@ public record MyRoom(
String bookImageUrl,
String roomName,
int memberCount,
String endDate // 방 진행 마감일 or 방 모집 마감일 (~ 뒤 형식)

@Schema(description = "방 진행 마감일 or 방 모집 마감일까지 남은 시간 (ex. \"3일 뒤\"), 완료된 방은 쓰레기값이 넘어갑니다. 무시해주세요.")
String endDate, // 방 진행 마감일 or 방 모집 마감일 (~ 뒤 형식)

@Schema(description = "방 상태 : [모집중(=recruiting), 진행중(=playing), 완료된(=expired)] 중 하나")
String type
Comment on lines +22 to +23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

typeString으로 노출하면 타입 안정성이 사라집니다

이미 애플리케이션 계층에 MyRoomType enum이 존재하므로 응답 DTO에도 동일한 enum을 사용해 일관성과 컴파일 타임 검증을 확보하는 편이 좋습니다. Swagger 문서에서도 자동으로 enum 값이 노출됩니다.

-@Schema(description = "방 상태 : [모집중(=recruiting), 진행중(=playing), 완료된(=expired)] 중 하나")
-String type
+@Schema(description = "방 상태")
+MyRoomType type

이렇게 변경하면 매퍼 단에서 type.name().toLowerCase()와 같은 문자열 변환 로직도 제거할 수 있어 중복이 줄어듭니다.
단, 패키지 순환 의존성 여부는 확인이 필요합니다.

🤖 Prompt for AI Agents
In
src/main/java/konkuk/thip/room/adapter/in/web/response/RoomShowMineResponse.java
around lines 22 to 23, the field 'type' is currently declared as a String, which
loses type safety. Change the type of 'type' from String to the existing enum
'MyRoomType' used in the application layer to ensure consistency and enable
compile-time validation. This also allows removal of string conversion logic
like 'type.name().toLowerCase()' in the mapper. Before applying this change,
verify that it does not introduce package cyclic dependencies.

Comment on lines +19 to +23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ private List<RoomQueryDto> fetchMyRooms(
room.title,
room.recruitCount,
room.memberCount,
room.startDate, // 방의 진행 시작일 정보 채우기
cursorExpr
))
.from(participant)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import konkuk.thip.room.adapter.in.web.response.RoomGetDeadlinePopularResponse;
import konkuk.thip.room.adapter.in.web.response.RoomShowMineResponse;
import konkuk.thip.room.application.port.out.dto.RoomQueryDto;
import konkuk.thip.room.application.port.in.dto.MyRoomType;
import org.mapstruct.Context;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.ReportingPolicy;
Expand All @@ -17,11 +19,9 @@
)
public interface RoomQueryMapper {

@Mapping(
target = "endDate",
expression = "java(DateUtil.formatAfterTime(dto.endDate()))"
)
RoomShowMineResponse.MyRoom toShowMyRoomResponse(RoomQueryDto dto);
@Mapping(target = "endDate", expression = "java(DateUtil.formatAfterTime(dto.endDate()))")
@Mapping(target = "type", expression = "java(myRoomType.getType())")
RoomShowMineResponse.MyRoom toShowMyRoomResponse(RoomQueryDto dto, @Context MyRoomType myRoomType);
Comment on lines +23 to +24
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호 MyRoomType이라는 외부 ENUM을 가져오기 위해 @Context가 사용된걸로 이해하면 되나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 response에 enum 타입이 없으므로 mapStruct가 enum은 매핑을 위해 문자열을 꺼내오는 용도로만 사용하도록 명시하기 위해 @context 어노테이션을 활용하였습니다!


@Mapping(
target = "deadlineDate",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package konkuk.thip.room.domain;
package konkuk.thip.room.application.port.in.dto;

import konkuk.thip.common.exception.InvalidStateException;
import konkuk.thip.common.exception.code.ErrorCode;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package konkuk.thip.room.application.port.out.dto;

import com.querydsl.core.annotations.QueryProjection;
import jakarta.annotation.Nullable;
import lombok.Builder;
import org.springframework.util.Assert;

Expand All @@ -13,6 +14,7 @@ public record RoomQueryDto(
String roomName,
int recruitCount, // 방 최대 인원 수
int memberCount,
@Nullable LocalDate startDate, // 방 진행 시작일
LocalDate endDate // 방 진행 마감일 or 방 모집 마감일
) {
@QueryProjection
Expand All @@ -24,4 +26,16 @@ public record RoomQueryDto(
Assert.isTrue(recruitCount > 0, "recruitCount must be greater than 0");
Assert.isTrue(memberCount >= 0, "memberCount must be greater than or equal to 0");
}

@QueryProjection
public RoomQueryDto(
Long roomId,
String bookImageUrl,
String roomName,
int recruitCount,
int memberCount,
LocalDate endDate
) {
this(roomId, bookImageUrl, roomName, recruitCount, memberCount, null, endDate);
}
Comment on lines +30 to +40
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호 오버로딩을 사용해서 코드 수정을 최소화했네요!! 역시 예리하심 👍🏻 👍🏻

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
import konkuk.thip.room.application.port.in.RoomShowMineUseCase;
import konkuk.thip.room.application.port.out.RoomQueryPort;
import konkuk.thip.room.application.port.out.dto.RoomQueryDto;
import konkuk.thip.room.domain.MyRoomType;
import konkuk.thip.room.application.port.in.dto.MyRoomType;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.time.LocalDate;

@Service
@RequiredArgsConstructor
Expand Down Expand Up @@ -43,20 +43,20 @@ public RoomShowMineResponse getMyRooms(Long userId, String type, String cursor)
};

// 3. dto -> response로 매핑 (EXPIRED 타입인 경우 endDate를 null로 처리)
boolean isExpiredType = myRoomType == MyRoomType.EXPIRED;
List<RoomShowMineResponse.MyRoom> myRooms = result.contents().stream()
var myRooms = result.contents().stream()
.map(dto -> {
var myRoomResponse = roomQueryMapper.toShowMyRoomResponse(dto);
if (isExpiredType) {
return new RoomShowMineResponse.MyRoom(
myRoomResponse.roomId(),
myRoomResponse.bookImageUrl(),
myRoomResponse.roomName(),
myRoomResponse.memberCount(),
null
);
if (myRoomType != MyRoomType.PLAYING_AND_RECRUITING) {
// PLAYING, RECRUITING, EXPIRED 경우 타입 그대로 전달
return roomQueryMapper.toShowMyRoomResponse(dto, myRoomType);
}

// PLAYING_AND_RECRUITING: startDate 기준으로 진행중/모집중 구분
LocalDate now = LocalDate.now();
if (dto.startDate() != null && dto.startDate().isBefore(now)) {
return roomQueryMapper.toShowMyRoomResponse(dto, MyRoomType.PLAYING); // 진행중인 방
} else {
return roomQueryMapper.toShowMyRoomResponse(dto, MyRoomType.RECRUITING); // 모집중인 방
Comment on lines +48 to +58
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

}
return myRoomResponse;
})
.toList();

Expand Down