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
5 changes: 5 additions & 0 deletions src/main/java/TtattaBackend/ttatta/domain/Diaries.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ public class Diaries extends BaseEntity {
@Column(name = "enc_ver", nullable = false)
private short encVer = 1;

@Column(nullable = false)
private int memoryDiaryAlarmCoolTime;

public void setUsers(Users users) {
// 기존에 이미 등록되어 있던 관계를 제거
Expand Down Expand Up @@ -122,4 +124,7 @@ public void updateContent(String content) {
this.content = content;
}

public void updateMemoryDiaryAlarmCoolTime(int memoryDiaryAlarmCoolTime) {
this.memoryDiaryAlarmCoolTime = memoryDiaryAlarmCoolTime;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.security.core.parameters.P;
Expand Down Expand Up @@ -170,11 +171,16 @@ WHERE ST_Contains(
d.location
)
AND d.user_id = :userId
AND d.memory_diary_alarm_cool_time = 0
""", nativeQuery = true)
List<Diaries> findNearDiariesCandidates(
@Param("wkt") String wkt,
@Param("userId") Long userId
);

List<Diaries> findAllByCreatedAtBetween(LocalDateTime startDateTime, LocalDateTime endDateTime);

@Modifying
@Query("UPDATE Diaries d SET d.memoryDiaryAlarmCoolTime = d.memoryDiaryAlarmCoolTime - 1 WHERE d.memoryDiaryAlarmCoolTime > 0")
void decreaseCoolTimeOnMemoryDiaries();
}
Original file line number Diff line number Diff line change
Expand Up @@ -416,4 +416,11 @@ public AlarmResponseDTO.GetAllAlarmsResponseDTO getAllAlarms() {
getDailySummaryAlarm
);
}

// 매일 자정에 위치기반 알림 쿨타임 차감 on 알림들 예약하는 메소드 실행
@Scheduled(cron = "0 0 0 * * *", zone = "Asia/Seoul")
@Transactional
public void decreaseMemoryDiaryAlarmCoolTime() {
diaryRepository.decreaseCoolTimeOnMemoryDiaries();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import TtattaBackend.ttatta.security.EnvelopeCryptoService;
import TtattaBackend.ttatta.web.dto.DiaryRequestDTO;
import TtattaBackend.ttatta.web.dto.DiaryResponseDTO;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Coordinate;
Expand Down Expand Up @@ -52,6 +53,7 @@ public class DiaryQueryServiceImpl implements DiaryQueryService{
private static final int SEARCH_RANGE = 100; // 검색 범위 설정 (100m)
private final GeometryFactory geometryFactory;
private final EnvelopeCryptoService envelopeCryptoService;
private static final int MEMORY_DIARY_COOL_TIME_AREA_RANGE = 500; // 검색 범위 설정 (100m)

Choose a reason for hiding this comment

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

medium

상수 값이 500인데 주석에는 (100m)로 잘못 기재되어 있습니다. 코드의 의도를 명확히 하고 혼동을 피하기 위해 주석을 실제 값과 일치시켜 주세요.

Suggested change
private static final int MEMORY_DIARY_COOL_TIME_AREA_RANGE = 500; // 검색 범위 설정 (100m)
private static final int MEMORY_DIARY_COOL_TIME_AREA_RANGE = 500; // 검색 범위 설정 (500m)


@Override
public DiaryResponseDTO.FootprintDiaryListDTO getFootprintDiaryList(Long diaryCategoryId, DiaryRequestDTO.ViewOnMapDTO request){
Expand Down Expand Up @@ -269,6 +271,7 @@ public List<LocalDateTime> getDiaryDateList() {
}

@Override
@Transactional
public void findRemindDiary(DiaryRequestDTO.RemindDTO request) {
Long userId = SecurityUtil.getCurrentUserId();
Users user = userRepository.findById(userId).orElseThrow(
Expand Down Expand Up @@ -310,6 +313,8 @@ public void findRemindDiary(DiaryRequestDTO.RemindDTO request) {
));
System.out.println("nearestDiaries real Candidates: " + nearestDiary.get().getId());

// 반환한 일기(nearestDiary) 주변 500m반경 내의 일기들의 위치기반 추억 알림 쿨타임을 한달(30일)로 설정
setMemoryDiaryAlarmCoolTime(userId, nearestDiary.get(), 30);

Choose a reason for hiding this comment

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

high

nearestDiaryOptional<Diaries> 타입이며, 스트림 연산 결과 비어있을 수 있습니다. get()을 직접 호출하면 NoSuchElementException이 발생할 수 있습니다. if (nearestDiary.isPresent()) 또는 ifPresent()를 사용하여 Optional이 값을 가지고 있을 때만 후속 로직이 실행되도록 안전하게 처리해야 합니다. 이 문제는 이 메서드 호출뿐만 아니라 nearestDiary.get()을 사용하는 모든 곳에 해당됩니다(예: 314, 320, 336 라인).


// 시간 계산
long days = ChronoUnit.DAYS.between(nearestDiary.get().getDate().toLocalDate(), LocalDate.now());
Expand All @@ -331,6 +336,37 @@ public void findRemindDiary(DiaryRequestDTO.RemindDTO request) {
alarmCommandService.sendMemoryDiaryAlarm(user, timeMessage, nearestDiary.get().getId());
}

private void setMemoryDiaryAlarmCoolTime(Long userId, Diaries currentDiary, int coolTime) {
// 1. 일기 주변 500m 반경 내 일기들 조회
Decoded decoded = tryDecode(currentDiary, userId);
Double currentLatitude = decoded.lat();
Double currentLongitude = decoded.lng();
List<Pt> square = buildSquare(currentLatitude, currentLongitude, 600.0);

Choose a reason for hiding this comment

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

high

500m 반경 내의 일기를 찾기 위해 600m 변의 정사각형을 사용하는 것은 부정확합니다. 이 정사각형은 중심에서 모서리까지의 거리가 약 424m(300 * sqrt(2))이므로, 424m에서 500m 사이의 대각선 방향에 있는 일기들을 놓칠 수 있습니다.

500m 반경을 완전히 포함하려면 정사각형의 한 변의 길이는 최소 1000m(2 * 500m)가 되어야 합니다. 상수를 사용하여 2.0 * MEMORY_DIARY_COOL_TIME_AREA_RANGE로 설정하는 것이 더 명확하고 유지보수에 용이합니다.

Suggested change
List<Pt> square = buildSquare(currentLatitude, currentLongitude, 600.0);
List<Pt> square = buildSquare(currentLatitude, currentLongitude, 2.0 * MEMORY_DIARY_COOL_TIME_AREA_RANGE);

String wkt = toPolygonWKT(square);
List<Diaries> nearDiariesCandidates = diaryRepository.findNearDiariesCandidates(wkt, userId);
// 서버 로그에서 확인하기 위함
for (Diaries diary : nearDiariesCandidates) {
System.out.println("nearDiariesCandidates id: " + diary.getId());
}
Comment on lines +348 to +350

Choose a reason for hiding this comment

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

medium

디버깅 목적으로 추가된 것으로 보이는 System.out.println은 프로덕션 코드에 남겨두지 않는 것이 좋습니다. 표준 로깅 프레임워크(이 클래스에서는 SLF4J가 이미 설정되어 있음)를 사용하면 로그 레벨 제어, 형식 지정 등 다양한 이점을 얻을 수 있습니다. log.debug() 또는 log.info()로 대체해주세요.

        log.debug("Near diary candidates for cooldown: {}", nearDiariesCandidates.stream().map(Diaries::getId).toList());


if (nearDiariesCandidates.isEmpty()) { // 검색 범위 내에 일기가 없는 경우
return;
}

// 검색 범위(정사각형) 내 복호화를 진행하고, 실제로 일기 위도 경도에서 100m 원 안에 있는 일기 중 가장 최신 일기 반환
// 영 이상하면 getDate -> getCreatedAt으로 수정 (마지막줄)

Choose a reason for hiding this comment

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

medium

개발 과정에서 남겨진 것으로 보이는 주석입니다. 프로덕션 코드에는 이러한 개인적인 메모나 불확실성을 나타내는 주석을 제거하여 코드의 가독성과 전문성을 높이는 것이 좋습니다.

List<Diaries> nearestDiary = nearDiariesCandidates

Choose a reason for hiding this comment

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

medium

변수명 nearestDiary는 단일 객체를 의미하는 것처럼 보이지만 실제로는 List<Diaries> 타입을 가집니다. 이는 코드를 읽을 때 혼란을 줄 수 있습니다. diariesInRadius 또는 diariesToUpdate와 같이 복수형이면서 그 의미를 더 잘 나타내는 이름으로 변경하고, 이 변수를 사용하는 모든 곳(예: 367라인)도 함께 수정해주세요.

        List<Diaries> diariesInRadius = nearDiariesCandidates

.parallelStream()
.map(d -> tryDecode(d, userId)) // Decoded(diaries, lat, lng, ok)
.filter(Decoded::ok)
.filter(dd -> haversineMeters(currentLatitude, currentLongitude, dd.lat(), dd.lng()) <= MEMORY_DIARY_COOL_TIME_AREA_RANGE)
.map(Decoded::diary)
.toList();

// 2. 각 엔티티 값 수정 -> 트랜잭션 커밋 때 DB에 UPDATE됨(Managed라면)
nearestDiary.forEach(d -> d.updateMemoryDiaryAlarmCoolTime(coolTime));
}

@Override
public List<String> getPresignedForPost(String imageType) {
Long userId = SecurityUtil.getCurrentUserId();
Expand Down