Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
abb0031
[feat] User의 WaybleZone 상세 조회 기록을 Log로 저장하는 기능 구현
KiSeungMin Jul 14, 2025
e8b6b54
[feat] User가 WaybleZone 상세 조회 시 기록을 남길 수 있도록 임시 코드 구현
KiSeungMin Jul 14, 2025
d4371a8
[feat] WaybleZone 추천 기능 초안 구현
KiSeungMin Jul 14, 2025
2f5c861
[feat] WaybleZone 추천 기능 controller, service 로직 구현
KiSeungMin Jul 14, 2025
d63d0fd
[chore] User 관련 Merge Conflict 해결
KiSeungMin Jul 17, 2025
b60ec90
[chore] User 관련 Merge Conflict 해결
KiSeungMin Jul 17, 2025
d62c354
[feat] VisitLog의 id를 무작위 문자열로 설정
KiSeungMin Jul 14, 2025
5154e55
[feat] 추천 시스템 테스트 데이터 삽입 코드 완성
KiSeungMin Jul 14, 2025
d525040
[feat] 추천 시스템 초안 구현 완료(에러 없이 조회 성공)
KiSeungMin Jul 14, 2025
5502ac1
[feat] 추천 시스템에서 상위 N개의 웨이블존을 구하는 기능 구현
KiSeungMin Jul 14, 2025
9426867
[feat] 상위 N개의 웨이블존을 구하는 기능 테스트 코드 작성 완료
KiSeungMin Jul 14, 2025
b020978
[feat] 유사 사용자 기반 추천 가중치 계산 기능 구현 완료
KiSeungMin Jul 17, 2025
86db2bd
[feat] 추천 시스템이 여러 개의 가게를 반환할 수 있도록 개선
KiSeungMin Jul 17, 2025
10171cb
[feat] 추천 시스템 http 요청 body를 dto로 받도록 개선
KiSeungMin Jul 17, 2025
56f97db
[feat] 추천 기록 저장 엔티티 구현
KiSeungMin Jul 17, 2025
43c3c05
[feat] 추천 기록 로그 엔티티 저장, 수정 로직 구현 완료
KiSeungMin Jul 17, 2025
b12229b
[fix] 추천 날짜가 Long 타입으로 저장되던 문제 해결
KiSeungMin Jul 17, 2025
ecd2ae8
[feat] 웨이블존 추천 결과 캐싱 기능 구현
KiSeungMin Jul 17, 2025
3befa38
[feat] 웨이블존 추천 기록 저장 테스트 완료
KiSeungMin Jul 17, 2025
d7efd3f
[feat] 추천 테스트 코드 출력 양식 개선
KiSeungMin Jul 17, 2025
cea00c9
[fix] 일부 document의 repository id 타입 매핑 오류 해결
KiSeungMin Jul 17, 2025
c6730cf
[chore] 웨이블존 조회 개수 필드명 count -> size로 변경
KiSeungMin Jul 17, 2025
26b0fb4
[feat] 추천 시스템 구현 완료
KiSeungMin Jul 17, 2025
3c336b9
[feat] 추천 시스템 테스트 완료
KiSeungMin Jul 17, 2025
8b8f5b7
[chore] 불필요한 import 제거
KiSeungMin Jul 17, 2025
e27cfa8
[chore] Elastic Search Query 연산 코드에 주석 추가
KiSeungMin Jul 17, 2025
c8327dc
[refactor] test용 임시 UserRegisterDto 삭제 -> createUser()로 대체
KiSeungMin Jul 17, 2025
b23d589
[feat] CodeRabbit이 알려준 교정사항 반영
KiSeungMin Jul 17, 2025
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
Expand Up @@ -4,7 +4,6 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;

@Configuration
public class ElasticsearchConfig extends ElasticsearchConfiguration {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.wayble.server.explore.controller;

import com.wayble.server.common.response.CommonResponse;
import com.wayble.server.explore.dto.recommend.WaybleZoneRecommendConditionDto;
import com.wayble.server.explore.dto.recommend.WaybleZoneRecommendResponseDto;
import com.wayble.server.explore.service.WaybleZoneRecommendService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequiredArgsConstructor
Expand All @@ -18,10 +19,17 @@ public class WaybleZoneRecommendController {

private final WaybleZoneRecommendService waybleZoneRecommendService;

@GetMapping("/{userId}")
public CommonResponse<WaybleZoneRecommendResponseDto> getWaybleZonePersonalRecommend(
@PathVariable("userId") Long userId) {
WaybleZoneRecommendResponseDto dto = waybleZoneRecommendService.getWaybleZonePersonalRecommend(userId);
return CommonResponse.success(dto);
@GetMapping()
public CommonResponse<List<WaybleZoneRecommendResponseDto>> getWaybleZonePersonalRecommend(
@Valid @ModelAttribute WaybleZoneRecommendConditionDto conditionDto,
@RequestParam(name = "size", defaultValue = "1") int size) {

List<WaybleZoneRecommendResponseDto> result = waybleZoneRecommendService.getWaybleZonePersonalRecommend(
conditionDto.userId(),
conditionDto.latitude(),
conditionDto.longitude(),
size
);
return CommonResponse.success(result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.wayble.server.explore.dto.recommend;

import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;

@Builder
public record WaybleZoneRecommendConditionDto(
@DecimalMin(value = "-90.0", message = "위도는 -90.0 이상이어야 합니다.")
@DecimalMax(value = "90.0", message = "위도는 90.0 이하여야 합니다.")
@NotNull(message = "위도 입력은 필수입니다.")
Double latitude,

@DecimalMin(value = "-180.0", message = "경도는 -180.0 이상이어야 합니다.")
@DecimalMax(value = "180.0", message = "경도는 180.0 이하여야 합니다.")
@NotNull(message = "경도 입력은 필수입니다.")
Double longitude,

@NotNull(message = "유저 ID는 필수입니다.")
Long userId
) {
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,51 @@
package com.wayble.server.explore.dto.recommend;

import com.wayble.server.explore.entity.WaybleZoneDocument;
import com.wayble.server.wayblezone.entity.WaybleZoneType;
import lombok.Builder;

@Builder
public record WaybleZoneRecommendResponseDto(

String username
Long zoneId,

String zoneName,

WaybleZoneType zoneType,

String thumbnailImageUrl,

Double latitude,

Double longitude,

Double averageRating,

Long reviewCount,

Double distanceScore,

Double similarityScore,

Double recencyScore,

Double totalScore

) {
public static WaybleZoneRecommendResponseDto from(WaybleZoneDocument waybleZoneDocument) {
return WaybleZoneRecommendResponseDto.builder()
.zoneId(waybleZoneDocument.getZoneId())
.zoneName(waybleZoneDocument.getZoneName())
.zoneType(waybleZoneDocument.getZoneType())
.thumbnailImageUrl(waybleZoneDocument.getThumbnailImageUrl())
.averageRating(waybleZoneDocument.getAverageRating())
.reviewCount(waybleZoneDocument.getReviewCount())
.latitude(waybleZoneDocument.getAddress().getLocation().getLat())
.longitude(waybleZoneDocument.getAddress().getLocation().getLon())
.distanceScore(0.0)
.similarityScore(0.0)
.recencyScore(0.0)
.totalScore(0.0)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.wayble.server.explore.entity;
import org.springframework.data.annotation.Id;
import lombok.*;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.time.LocalDate;

@ToString
@Builder
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "recommend_log")
public class RecommendLogDocument {

@Id
@Field(name = "id")
private String id;

private Long userId;

private Long zoneId;

@Field(type = FieldType.Date, format = DateFormat.date)
private LocalDate recommendationDate;

private Long recommendCount;

public void updateRecommendLog(LocalDate recommendationDate, Long recommendCount) {
if(recommendationDate != null) {
this.recommendationDate = recommendationDate;
}
if(recommendCount != null) {
this.recommendCount = recommendCount;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class WaybleZoneVisitLogDocument {

@Id
@Field(name = "id")
private Long logId;
private String logId;

private Long userId;

Expand All @@ -31,7 +31,7 @@ public class WaybleZoneVisitLogDocument {

public static WaybleZoneVisitLogDocument fromEntity(User user, Long zoneId) {
return WaybleZoneVisitLogDocument.builder()
.logId(UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE)
.logId(UUID.randomUUID().toString())
.userId(user.getId())
.zoneId(zoneId)
.gender(user.getGender())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
@RequiredArgsConstructor
public enum RecommendErrorCase implements ErrorCase {

INVALID_USER(400, 6001, "잘못된 유저 정보입니다.");
INVALID_USER(400, 6001, "잘못된 유저 정보입니다."),

RECOMMEND_LOG_NOT_EXIST(400, 6002, "해당하는 추천 기록이 존재하지 않습니다."),

WAYBLE_ZONE_NOT_EXIST(400, 6003, "추천 기록에 해당하는 웨이블존이 존재하지 않습니다.");

private final Integer httpStatusCode;
private final Integer errorCode;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.wayble.server.explore.exception;

import com.wayble.server.common.exception.ErrorCase;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum VisitLogErrorCase implements ErrorCase {

USER_NOT_EXIST(400, 7001, "해당하는 유저가 존재하지 않습니다."),
ZONE_NOT_EXIST(400, 7002, "해당하는 웨이블존이 존재하지 않습니다.");

private final Integer httpStatusCode;
private final Integer errorCode;
private final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.wayble.server.explore.repository;

import com.wayble.server.explore.entity.RecommendLogDocument;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.time.LocalDate;
import java.util.Optional;

public interface RecommendLogDocumentRepository extends ElasticsearchRepository<RecommendLogDocument, String> {
Optional<RecommendLogDocument> findByUserIdAndZoneId(Long userId, Long zoneId);

boolean existsByUserIdAndZoneId(Long userId, Long zoneId);

Optional<RecommendLogDocument> findByUserIdAndRecommendationDate(Long userId, LocalDate recommendationDate);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import com.wayble.server.explore.entity.WaybleZoneVisitLogDocument;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.List;

public interface WaybleZoneVisitLogDocumentRepository extends ElasticsearchRepository<WaybleZoneVisitLogDocument, Long>{

public interface WaybleZoneVisitLogDocumentRepository extends ElasticsearchRepository<WaybleZoneVisitLogDocument, String>{
List<WaybleZoneVisitLogDocument> findAll();
}

Loading
Loading