diff --git a/README.md b/README.md index 0134068bb..a1ad43095 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,72 @@ -# second-hand-max -2023 마스터즈 맥스 중고거래 프로젝트 +# second-hand +> 2023 마스터즈 맥스 네번째 팀 프로젝트 +- 미션 기간: `2023-09-21 ~ 2023-10-6` [6 Week] +중고 거래 서비스 +## 구성원 + + + + + + + + + + + + + + + + + +
#BE#FE
+ + + + + + + +
+ light + + charlie + + 아티 + + litae +
+ +## 사용하는 기술 +### 프로젝트 관리 +[![Notion](https://img.shields.io/badge/Notion-000000.svg?style=for-the-badge&logo=Notion&logoColor=white)](https://placid-fork-b42.notion.site/SecondHand-BE-A-a00c7636a4db4c1f982b4bbe81694b9b?pvs=4) + +### BE +![](https://img.shields.io/badge/Java-007396?style=flat&logo=OpenJDK&logoColor=white) +![](https://img.shields.io/badge/SpringBoot-6DB33F?style=flat&logo=SpringBoot&logoColor=white) +![](https://img.shields.io/badge/MySQL-4479A1?style=flat&logo=MySQL&logoColor=white) +![](https://img.shields.io/badge/GitHub_Actions-2088FF?style=flat&logo=githubactions&logoColor=white) +![](https://img.shields.io/badge/-NginX-269539?style=flat&logo=Nginx&logoColor=white) +![](https://img.shields.io/badge/-Docker-2496ED?style=flat&logo=Docker&logoColor=white) +![](https://img.shields.io/badge/AWS%20EC2-FA7343?style=flat&logo=amazonec2&logoColor=white) +![](https://img.shields.io/badge/-AWS_S3-569A31?style=flat&logo=Amazon-S3&logoColor=white) +![](https://img.shields.io/badge/AWS_RDS-527FFF?style=flat&logo=amazonrds&logoColor=white) +![](https://img.shields.io/badge/Redis-FF4D4D?style=flat&logo=redis&logoColor=white) + +- Java: `JDK 11` +- SpringBoot: `ver. 2.7.14` +- MySQL: `ver. 8.0.33` +- Redis: `7.2.0` +- Amazon AWS: `EC2`, `S3`, `RDS` + +## ERD +![image](https://github.com/masters2023-project-06-second-hand/be-a/assets/100547825/675dcfcf-5809-445a-98c2-d4cbea8c346a) + + +## Infra +image + + + + diff --git a/secondhand/src/main/java/com/codesquad/secondhand/common/interceptor/StompInterceptor.java b/secondhand/src/main/java/com/codesquad/secondhand/common/interceptor/StompInterceptor.java index d491f1010..183c2681b 100644 --- a/secondhand/src/main/java/com/codesquad/secondhand/common/interceptor/StompInterceptor.java +++ b/secondhand/src/main/java/com/codesquad/secondhand/common/interceptor/StompInterceptor.java @@ -74,6 +74,7 @@ private Long getChatRoomId(StompHeaderAccessor accessor) { private Long validateAccessToken(StompHeaderAccessor accessor) { try { String token = extractAccessTokenFromAccessor(accessor); + log.info("token : {}", token); return jwtProvider.getClaims(token).get("memberId", Long.class); } catch (RuntimeException e) { throw new CustomRuntimeException(JwtException.from(e)); diff --git a/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/controller/ChatController.java b/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/controller/ChatController.java index 862f5cd7a..f6483dd8c 100644 --- a/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/controller/ChatController.java +++ b/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/controller/ChatController.java @@ -21,6 +21,7 @@ import com.codesquad.secondhand.domain.chat.dto.request.MessageRequest; import com.codesquad.secondhand.domain.chat.dto.response.ChatRoomDetailsResponse; import com.codesquad.secondhand.domain.chat.dto.response.ChatRoomListResponse; +import com.codesquad.secondhand.domain.chat.dto.response.ChatSendMessageResponse; import com.codesquad.secondhand.domain.chat.service.ChatService; import lombok.RequiredArgsConstructor; @@ -36,10 +37,10 @@ public class ChatController { @MessageMapping("/message") public void sendMessage(MessageRequest messageRequest) { - chatService.sendMessage(messageRequest); + ChatSendMessageResponse chatSendMessageResponse = chatService.sendMessage(messageRequest); // 채널아이디 만들기 simpMessageSendingOperations.convertAndSend("/sub/room/" + messageRequest.getChatRoomId(), - messageRequest.getMessage()); + chatSendMessageResponse); } @PostMapping("/api/chats/room-id") diff --git a/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/dto/response/ChatRoomMessageResponse.java b/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/dto/response/ChatRoomMessageResponse.java index a5cbe032a..d5e497631 100644 --- a/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/dto/response/ChatRoomMessageResponse.java +++ b/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/dto/response/ChatRoomMessageResponse.java @@ -6,14 +6,22 @@ import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; @Getter @Builder +@NoArgsConstructor public class ChatRoomMessageResponse { private LocalDateTime sendAt; private String message; private Long unreadMessageCount; + public ChatRoomMessageResponse(LocalDateTime sendAt, String message, Long unreadMessageCount) { + this.sendAt = sendAt; + this.message = message; + this.unreadMessageCount = unreadMessageCount; + } + public static ChatRoomMessageResponse of(ChatMessage chatMessage, Long count) { return ChatRoomMessageResponse.builder() .sendAt(chatMessage.getSendAt()) diff --git a/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/dto/response/ChatSendMessageResponse.java b/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/dto/response/ChatSendMessageResponse.java new file mode 100644 index 000000000..0911d1bc7 --- /dev/null +++ b/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/dto/response/ChatSendMessageResponse.java @@ -0,0 +1,24 @@ +package com.codesquad.secondhand.domain.chat.dto.response; + +import com.codesquad.secondhand.domain.chat.entity.ChatMessage; +import com.codesquad.secondhand.domain.chat.entity.ChatRoom; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +@AllArgsConstructor +public class ChatSendMessageResponse { + + private Long chatRoomId; + private ChatMessageResponse messages; + + public static ChatSendMessageResponse of(ChatMessage chatMessage, ChatRoom chatRoom) { + return ChatSendMessageResponse.builder() + .messages(ChatMessageResponse.of(chatMessage)) + .chatRoomId(chatRoom.getId()) + .build(); + } +} diff --git a/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/repository/ChatMessageQueryRepository.java b/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/repository/ChatMessageQueryRepository.java index 36cb33e1d..df0e89354 100644 --- a/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/repository/ChatMessageQueryRepository.java +++ b/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/repository/ChatMessageQueryRepository.java @@ -2,6 +2,8 @@ import static com.codesquad.secondhand.domain.chat.entity.QChatMessage.*; +import java.util.Optional; + import org.springframework.stereotype.Repository; import com.codesquad.secondhand.domain.chat.entity.ChatMessage; @@ -15,12 +17,12 @@ public class ChatMessageQueryRepository { private final JPAQueryFactory query; - public ChatMessage findLatestMessage(ChatRoom chatRoom) { + public Optional findLatestMessage(ChatRoom chatRoom) { ChatMessage latestMessage = query .selectFrom(chatMessage) .where(chatMessage.chatRoom.eq(chatRoom)) .orderBy(chatMessage.sendAt.desc()) .fetchFirst(); - return latestMessage; + return Optional.ofNullable(latestMessage); } } diff --git a/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/service/ChatQueryService.java b/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/service/ChatQueryService.java index 11446f879..991965e47 100644 --- a/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/service/ChatQueryService.java +++ b/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/service/ChatQueryService.java @@ -1,6 +1,7 @@ package com.codesquad.secondhand.domain.chat.service; import java.util.List; +import java.util.Optional; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,7 +61,7 @@ public Long getUnReadCount(Member opponent, ChatRoom chatRoom) { return chatMessageJpaRepository.countUnreadMessages(opponent, chatRoom); } - public ChatMessage findLastMessage(ChatRoom chatRoom) { + public Optional findLastMessage(ChatRoom chatRoom) { return chatMessageQueryRepository.findLatestMessage(chatRoom); } diff --git a/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/service/ChatService.java b/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/service/ChatService.java index 0fd19706a..f4fac62c7 100644 --- a/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/service/ChatService.java +++ b/secondhand/src/main/java/com/codesquad/secondhand/domain/chat/service/ChatService.java @@ -1,6 +1,7 @@ package com.codesquad.secondhand.domain.chat.service; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import org.springframework.stereotype.Service; @@ -15,6 +16,7 @@ import com.codesquad.secondhand.domain.chat.dto.response.ChatRoomMessageResponse; import com.codesquad.secondhand.domain.chat.dto.response.ChatRoomOpponentResponse; import com.codesquad.secondhand.domain.chat.dto.response.ChatRoomProductResponse; +import com.codesquad.secondhand.domain.chat.dto.response.ChatSendMessageResponse; import com.codesquad.secondhand.domain.chat.entity.ChatMessage; import com.codesquad.secondhand.domain.chat.entity.ChatRoom; import com.codesquad.secondhand.domain.chat.redis.RedisChatMember; @@ -39,7 +41,7 @@ public class ChatService { private final NotificationService notificationService; @Transactional - public void sendMessage(MessageRequest messageRequest) { + public ChatSendMessageResponse sendMessage(MessageRequest messageRequest) { //1. chatRoomId 가 존재하는지 검증 ChatRoom chatRoom = chatQueryService.findChatRoomByChatRoomId(messageRequest.getChatRoomId()); @@ -55,11 +57,12 @@ public void sendMessage(MessageRequest messageRequest) { if (redisChatMembers.size() == MAX_CHAT_MEMBERS) { // 메세지의 읽음 상태를 true 로 변경 (채팅방에 user 가 2명이기 때문에) chatMessage.updateReadStatusToTrue(); - return; + return ChatSendMessageResponse.of(chatMessage, chatRoom); } //SSE 재요청 알림 보내기 Long receiverId = chatRoom.findOpponentId(sender); notificationService.refreshChatRoomList(receiverId); + return ChatSendMessageResponse.of(chatMessage, chatRoom); } @Transactional @@ -104,7 +107,8 @@ public List getChatRoomList(Long memberId) { .map(chatRoom -> { ChatRoomProductResponse productResponse = mapToChatRoomProduct(chatRoom); ChatRoomOpponentResponse opponentResponse = mapToChatRoomOpponent(chatRoom, memberId); - ChatRoomMessageResponse chatRoomMessageResponse = mapToChatRoomMessage(chatRoom, memberId); + ChatRoomMessageResponse chatRoomMessageResponse = mapToChatRoomMessage(chatRoom, memberId) + .orElseGet(() -> new ChatRoomMessageResponse()); return ChatRoomListResponse.of(chatRoom.getId(), productResponse, opponentResponse, chatRoomMessageResponse); }).collect(Collectors.toList()); @@ -120,11 +124,15 @@ private ChatRoomOpponentResponse mapToChatRoomOpponent(ChatRoom chatRoom, Long m return ChatRoomOpponentResponse.of(member.getNickname(), member.getProfileImg()); } - private ChatRoomMessageResponse mapToChatRoomMessage(ChatRoom chatRoom, Long memberId) { - ChatMessage message = chatQueryService.findLastMessage(chatRoom); + private Optional mapToChatRoomMessage(ChatRoom chatRoom, Long memberId) { + Optional optionalMessage = chatQueryService.findLastMessage(chatRoom); + if (!optionalMessage.isPresent()) { + return Optional.empty(); + } + ChatMessage message = optionalMessage.get(); Member member = findOpponentMember(chatRoom, memberId); Long count = chatQueryService.getUnReadCount(member, chatRoom); - return ChatRoomMessageResponse.of(message, count); + return Optional.of(ChatRoomMessageResponse.of(message, count)); } private Member findOpponentMember(ChatRoom chatRoom, Long memberId) {