Skip to content

Commit ab45240

Browse files
committed
fix : n+1 문제 해결 (#18)
1 parent cddfb81 commit ab45240

File tree

6 files changed

+25
-34
lines changed

6 files changed

+25
-34
lines changed

src/main/java/cmf/commitField/domain/noti/noti/controller/ApiV1NotiController.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package cmf.commitField.domain.noti.noti.controller;
22

33
import cmf.commitField.domain.noti.noti.dto.NotiDto;
4-
import cmf.commitField.domain.noti.noti.entity.Noti;
54
import cmf.commitField.domain.noti.noti.service.NotiService;
65
import cmf.commitField.domain.user.entity.User;
76
import cmf.commitField.domain.user.repository.UserRepository;
@@ -21,7 +20,6 @@
2120

2221
import java.util.List;
2322
import java.util.Map;
24-
import java.util.stream.Collectors;
2523

2624
@RestController
2725
@RequestMapping("/api/notifications")
@@ -35,19 +33,14 @@ public class ApiV1NotiController {
3533
@GetMapping("")
3634
public GlobalResponse<List<NotiDto>> getNoti() {
3735
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
38-
log.info("getNoti - userRequest: {}", authentication);
3936

4037
if (authentication instanceof OAuth2AuthenticationToken) {
4138
OAuth2User principal = (OAuth2User) authentication.getPrincipal();
4239
Map<String, Object> attributes = principal.getAttributes();
4340
String username = (String) attributes.get("login"); // GitHub ID
4441
User user = userRepository.findByUsername(username).orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_USER));
45-
List<Noti> notis = notiService.getNotReadNoti(user);
46-
47-
List<NotiDto> notiDtos = notis.stream()
48-
.map(NotiDto::new)
49-
.collect(Collectors.toList());
50-
return GlobalResponse.success(notiDtos);
42+
List<NotiDto> notis = notiService.getNotReadNoti(user);
43+
return GlobalResponse.success(notis);
5144
}
5245

5346
return GlobalResponse.error(ErrorCode.LOGIN_REQUIRED);

src/main/java/cmf/commitField/domain/noti/noti/dto/NotiDto.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package cmf.commitField.domain.noti.noti.dto;
22

3-
import cmf.commitField.domain.noti.noti.entity.Noti;
43
import lombok.Getter;
54

65
import java.time.LocalDateTime;
@@ -12,9 +11,10 @@ public class NotiDto {
1211
private String message;
1312
private String formattedCreatedAt; // 변환된 날짜를 저장할 필드
1413

15-
public NotiDto(Noti noti) {
16-
this.message = noti.getMessage();
17-
this.formattedCreatedAt = formatCreatedAt(noti.getCreatedAt()); // 변환된 날짜 저장
14+
// JPQL에서 사용할 수 있도록 필드 값 직접 받는 생성자 추가
15+
public NotiDto(String message, LocalDateTime createdAt) {
16+
this.message = message;
17+
this.formattedCreatedAt = formatCreatedAt(createdAt); // 변환된 날짜 저장
1818
}
1919

2020
private String formatCreatedAt(LocalDateTime createdAt) {
@@ -25,12 +25,8 @@ private String formatCreatedAt(LocalDateTime createdAt) {
2525
return "오늘";
2626
} else if (daysBetween == 1) {
2727
return "어제";
28-
} else if (daysBetween == 2) {
29-
return "1일 전";
30-
} else if (daysBetween == 3) {
31-
return "2일 전";
32-
} else if (daysBetween == 4) {
33-
return "3일 전";
28+
} else if (daysBetween <= 3) {
29+
return (daysBetween - 1) + "일 전";
3430
} else {
3531
return createdAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
3632
}
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package cmf.commitField.domain.noti.noti.repository;
22

3+
import cmf.commitField.domain.noti.noti.dto.NotiDto;
34
import cmf.commitField.domain.noti.noti.entity.Noti;
45
import cmf.commitField.domain.user.entity.User;
6+
import io.lettuce.core.dynamic.annotation.Param;
57
import org.springframework.data.jpa.repository.JpaRepository;
8+
import org.springframework.data.jpa.repository.Query;
69
import org.springframework.stereotype.Repository;
710

811
import java.util.List;
@@ -11,5 +14,8 @@
1114
@Repository
1215
public interface NotiRepository extends JpaRepository<Noti, Long> {
1316
Optional<List<Noti>> findNotiByReceiverAndRelId(User receiver, long season);
14-
Optional<List<Noti>> findNotiByReceiverAndIsRead(User receiver, boolean read);
17+
@Query("SELECT new cmf.commitField.domain.noti.noti.dto.NotiDto(n.message, n.createdAt) " +
18+
"FROM Noti n JOIN n.receiver u WHERE u.id = :receiverId AND n.isRead = :isRead")
19+
Optional<List<NotiDto>> findNotiDtoByReceiverId(@Param("receiverId") Long receiverId, @Param("isRead") boolean isRead);
20+
1521
}

src/main/java/cmf/commitField/domain/noti/noti/service/NotiService.java

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
package cmf.commitField.domain.noti.noti.service;
22

3+
import cmf.commitField.domain.noti.noti.dto.NotiDto;
34
import cmf.commitField.domain.noti.noti.entity.Noti;
45
import cmf.commitField.domain.noti.noti.entity.NotiDetailType;
56
import cmf.commitField.domain.noti.noti.entity.NotiMessageTemplates;
67
import cmf.commitField.domain.noti.noti.entity.NotiType;
78
import cmf.commitField.domain.noti.noti.repository.NotiRepository;
89
import cmf.commitField.domain.season.entity.Season;
9-
import cmf.commitField.domain.season.repository.SeasonRepository;
10-
import cmf.commitField.domain.season.service.SeasonService;
1110
import cmf.commitField.domain.user.entity.User;
1211
import cmf.commitField.domain.user.repository.UserRepository;
1312
import cmf.commitField.global.error.ErrorCode;
@@ -27,40 +26,33 @@
2726
public class NotiService {
2827
private final NotiRepository notiRepository;
2928
private final UserRepository userRepository;
30-
private final SeasonRepository seasonRepository;
31-
private final SeasonService seasonService;
3229

3330
// 알림 메시지 생성
3431
public static String generateMessage(NotiDetailType type, Object... params) {
3532
String template = NotiMessageTemplates.getTemplate(type);
36-
log.info("generateMessage - params: {}", params);
37-
log.info("generateMessage - template: {}", template); // template 자체를 출력
3833
String message = MessageFormat.format(template, params); // params 배열을 그대로 전달
39-
log.info("generateMessage - message: {}", message);
4034
return message;
4135
}
4236

4337

44-
public List<Noti> getNotReadNoti(User receiver) {
45-
log.info("getNotReadNoti - receiver: {}", receiver);
46-
List<Noti> notis = notiRepository.findNotiByReceiverAndIsRead(receiver, false).orElse(null);
47-
log.info("getNotReadNoti - notis: {}", notis);
38+
public List<NotiDto> getNotReadNoti(User receiver) {
39+
System.out.println("알림 조회");
40+
List<NotiDto> notis = notiRepository.findNotiDtoByReceiverId(receiver.getId(), false).orElse(null);
41+
System.out.println("알림 조회 끝");
4842
return notis;
4943
}
5044

5145
public List<Noti> getSeasonNotiCheck(User receiver, long seasonId) {
52-
log.info("getSeasonNotiCheck - receiver: {}, seasonId: {}", receiver, seasonId);
5346
return notiRepository.findNotiByReceiverAndRelId(receiver, seasonId)
5447
.orElseThrow(() -> new CustomException(ErrorCode.ERROR_CHECK)); // 알림이 없을 경우 예외 발생
5548
}
5649

5750
// 새 시즌 알림 생성
5851
@Transactional
5952
public void createNewSeason(Season season) {
60-
log.info("createNewSeason - season: {}", season.getName());
53+
System.out.println("새 시즌 알림 생성");
6154
// 메시지 생성
6255
String message = NotiService.generateMessage(NotiDetailType.SEASON_START, season.getName());
63-
log.info("createNewSeason - message: {}", message);
6456

6557
// 모든 사용자 조회
6658
Iterable<User> users = userRepository.findAll();
@@ -79,5 +71,6 @@ public void createNewSeason(Season season) {
7971

8072
notiRepository.save(noti);
8173
});
74+
System.out.println("새 시즌 알림 생성 끝");
8275
}
8376
}

src/main/java/cmf/commitField/domain/user/service/CustomOAuth2UserService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public OAuth2User loadUser(OAuth2UserRequest userRequest) {
9292
// 알림 테이블에서 Active인 시즌의 알림을 해당 유저가 가지고 있는지 체크
9393
String season_key = "season_active:" + user.getUsername();
9494
Season season = seasonService.getActiveSeason();
95+
log.info("Active season: {}", season);
9596
if(notiService.getSeasonNotiCheck(user, season.getId()).isEmpty()){
9697
log.info("User {} does not have season noti", user.getUsername());
9798
// 가지고 있지 않다면 알림을 추가

src/main/java/cmf/commitField/global/websocket/WebSocketConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
public class WebSocketConfig implements WebSocketConfigurer {
1313

1414
private final ChatWebSocketHandler chatWebSocketHandler;
15+
private final NotiWebSocketHandler notiWebSocketHandler;
1516

1617
@Override
1718
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
1819
registry.addHandler(chatWebSocketHandler, "/chat").setAllowedOrigins("*");
20+
registry.addHandler(notiWebSocketHandler, "/notifications").setAllowedOrigins("*"); // 알림 엔드포인트 추가
1921
}
2022
}

0 commit comments

Comments
 (0)