Skip to content
This repository was archived by the owner on Jan 11, 2026. It is now read-only.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.spot.repository.querydsl.impl;

import com.example.spot.domain.Region;
import com.example.spot.domain.enums.Gender;
import com.example.spot.domain.enums.Status;
import com.example.spot.domain.enums.StudySortBy;
Expand Down Expand Up @@ -433,6 +434,10 @@ private static void getConditions(Map<String, Object> search, QStudy study,
List<ThemeType> themeTypes = (List<ThemeType>) search.get("themeTypes");
builder.and(study.studyThemes.any().theme.studyTheme.in(themeTypes));
}
if (search.get("regions") != null) {
List<Region> regionList = (List<Region>) search.get("regions");
builder.and(study.regionStudies.any().region.in(regionList));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.example.spot.domain.Region;
import com.example.spot.domain.Theme;
import com.example.spot.domain.enums.ApplicationStatus;
import com.example.spot.domain.enums.Gender;
import com.example.spot.domain.enums.Status;
import com.example.spot.domain.enums.StudyLikeStatus;
import com.example.spot.domain.enums.StudySortBy;
Expand All @@ -24,6 +25,7 @@
import com.example.spot.repository.MemberThemeRepository;
import com.example.spot.repository.PreferredRegionRepository;
import com.example.spot.repository.PreferredStudyRepository;
import com.example.spot.repository.RegionRepository;
import com.example.spot.repository.RegionStudyRepository;
import com.example.spot.repository.StudyRepository;
import com.example.spot.repository.StudyThemeRepository;
Expand Down Expand Up @@ -86,6 +88,7 @@ public class StudyQueryServiceImpl implements StudyQueryService {
// 지역 관련 조회
private final PreferredRegionRepository preferredRegionRepository;
private final RegionStudyRepository regionStudyRepository;
private final RegionRepository regionRepository;

private final RedisTemplate<String, String> redisTemplate;

Expand Down Expand Up @@ -866,25 +869,10 @@ private List<Long> getOngoingStudyIds(Long memberId) {
* @return 검색 조건 맵을 반환합니다.
*
*/
private static Map<String, Object> getSearchConditions(SearchRequestStudyDTO request) {
log.info("request: {}", request.getIsOnline());
private Map<String, Object> getSearchConditions(SearchRequestStudyDTO request) {
// 검색 조건 맵 생성
Map<String, Object> search = new HashMap<>();
if (request.getGender() != null)
search.put("gender", request.getGender());
if (request.getMinAge() != null)
search.put("minAge", request.getMinAge());
if (request.getMaxAge() != null)
search.put("maxAge", request.getMaxAge());
if (request.getIsOnline() != null)
search.put("isOnline", request.getIsOnline());
if (request.getHasFee() != null)
search.put("hasFee", request.getHasFee());
if (request.getMaxFee() != null)
search.put("maxFee", request.getMaxFee());
if (request.getMinFee() != null)
search.put("minFee", request.getMinFee());
return search;
return getBasicStudyFilteringConditions(request.getGender(), request.getMinAge(), request.getMaxAge(),
request.getIsOnline(), request.getHasFee(), request.getMaxFee(), request.getMinFee(), request.getRegionCodes());
}

/**
Expand All @@ -895,23 +883,10 @@ private static Map<String, Object> getSearchConditions(SearchRequestStudyDTO req
* @return 검색 조건 맵을 반환합니다.
*
*/
private static Map<String, Object> getSearchConditionsWithTheme(SearchRequestStudyWithThemeDTO request) {
Map<String, Object> search = new HashMap<>();

if (request.getGender() != null)
search.put("gender", request.getGender());
if (request.getMinAge() != null)
search.put("minAge", request.getMinAge());
if (request.getMaxAge() != null)
search.put("maxAge", request.getMaxAge());
if (request.getIsOnline() != null)
search.put("isOnline", request.getIsOnline());
if (request.getHasFee() != null)
search.put("hasFee", request.getHasFee());
if (request.getMaxFee() != null)
search.put("maxFee", request.getMaxFee());
if (request.getMinFee() != null)
search.put("minFee", request.getMinFee());
private Map<String, Object> getSearchConditionsWithTheme(SearchRequestStudyWithThemeDTO request) {
Map<String, Object> search = getBasicStudyFilteringConditions(request.getGender(), request.getMinAge(),
request.getMaxAge(), request.getIsOnline(),
request.getHasFee(), request.getMaxFee(), request.getMinFee(), request.getRegionCodes());

if (request.getThemeTypes() != null && !request.getThemeTypes().isEmpty()) {
search.put("themeTypes", request.getThemeTypes());
Expand All @@ -920,6 +895,45 @@ private static Map<String, Object> getSearchConditionsWithTheme(SearchRequestStu
return search;
}

private Map<String, Object> getBasicStudyFilteringConditions(Gender gender, Integer minAge, Integer maxAge,
Boolean isOnline, Boolean hasFee,
Integer maxFee, Integer minFee, List<String> regions) {
Map<String, Object> search = new HashMap<>();

if (gender != null)
search.put("gender", gender);
if (minAge != null)
search.put("minAge", minAge);
if (maxAge != null)
search.put("maxAge", maxAge);
if (isOnline != null)
search.put("isOnline", isOnline);
if (hasFee != null)
search.put("hasFee", hasFee);
if (maxFee != null)
search.put("maxFee", maxFee);
if (minFee != null)
search.put("minFee", minFee);

// 지역 코드가 null 이거나 비어있으면 검색 조건에 추가하지 않음
if (regions == null || regions.isEmpty())
return search;

List<Region> regionList = convertCodeToRegion(regions);

if (regionList != null && !regionList.isEmpty())
search.put("regions", regionList);
return search;
}

private List<Region> convertCodeToRegion(List<String> regions) {
List<Region> regionList = regions.stream()
.map(regionCode -> regionRepository.findByCode(regionCode)
.orElseThrow(() -> new StudyHandler(ErrorStatus._STUDY_REGION_NOT_EXIST)))
.toList();
return regionList;
}


/**
* 스터디 목록을 DTO로 변환하는 메서드입니다.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -25,12 +26,10 @@ public class BaseSearchRequestStudyDTO {

@Schema(description = "최소 나이 (18 이상).", example = "18")
@Min(value = 18, message = "최소 나이는 18세 입니다.")
@NotNull(message = "최소 나이는 필수 입력 값입니다.")
private Integer minAge;

@Schema(description = "최대 나이 (60 이하).", example = "60")
@Max(value = 60, message = "최대 나이는 60세 입니다.")
@NotNull(message = "최대 나이는 필수 입력 값입니다.")
private Integer maxAge;

@Schema(description = "스터디 온라인 진행 여부 (true, false).", example = "true")
Expand All @@ -47,6 +46,9 @@ public class BaseSearchRequestStudyDTO {
@Min(value = 0, message = "최소 활동비는 0원 입니다.")
private Integer minFee;

@Schema(description = "스터디 활동 지역")
private List<String> regionCodes;

// 공통 검증 로직
@AssertTrue(message = "최소 나이는 최대 나이보다 작아야 합니다.")
private boolean isValidAgeRange() {
Expand All @@ -72,4 +74,12 @@ private boolean isValidFeeRange() {
return minFee <= maxFee;
}

@AssertTrue(message = "온라인 스터디 조회 시, 스터디 지역을 입력받지 않습니다.")
private boolean isValidRegion() {
if (isOnline == null || !isOnline) {
return true;
}
return regionCodes == null || regionCodes.isEmpty();
}

}