[Spring] 구인구직 서비스 5-1 쪽지 조회 수정

춤인형의 개발일지·2025년 1월 31일

Spring실습

목록 보기
26/40

쪽지 조회 수정

쪽지 조회의 문제점은 아래와 같았다.

  • 내가 보낸 쪽지 조회와 받은 쪽지 조회의 코드가 너무나도 유사하다. 개발자or기업의 이름때문에 저렇게 중복되는 코드를 작성해야하는걸까?
  1. 일단 쪽지를 보낸 쪽지, 받은 쪽지를 나누었던 이유는 기능이 다르기 때문!
  2. 그리고 if문으로 나눴던 이유는 개발자, 기업의 이름을 가져와야하기 때문!
    쪽지를 조회할 때 보낸 사람의 이름을 조회해야하기 때문에, 이렇게 코드를 작성했다.
List<Message> messageList = messageRepository.findAllByReceiverId(receiveId);
        List<MessageSendResponse> messageSendResponses = new ArrayList<>();

        for (Message message : messageList) {
            if(receiveId.startsWith("C")){
                Programmer programmer = programmerRepository.findById(message.getSenderId())
                        .orElseThrow(() -> new NoSuchElementException(message.getSenderId() + "님이 보낸 쪽지가 없습니다."));
                messageSendResponses.add(new MessageSendResponse(message.getId(), programmer.getName()));
            }
            if(receiveId.startsWith("P")){
                Company company = companyRepository.findById(message.getSenderId())
                        .orElseThrow(() -> new NoSuchElementException(message.getSenderId() + "님이 보낸 쪽지가 없습니다."));
                messageSendResponses.add(new MessageSendResponse(message.getId(), company.getCompanyname()));
            }
        }
        return messageSendResponses;
    }

근데 약간 굳이인 것 같다는 생각이 들었다.

첫번째 해결 방법 - Entity 칼럼 추가

첫번째로 생각한건

message 엔티티에 senderName을 추가해서 쪽지를 생성할 때 senderName을 같이 줘서 조회할 때 가져오는 방식을 사용했다.

  1. 쪽지 생성(쪽지 보내기)
  • 기업/개발자의 receiverName을 저장한다.
public MessageResponse create(String senderId, MessageRequest request) {
        String receiverName = "";
        if(request.receiverId().startsWith("C")){
            Company company = companyRepository.findById(request.receiverId())
                    .orElseThrow(() -> new NoSuchElementException("해당 기업이 존재하지 않습니다!"));
            receiverName = company.getCompanyname();
        }
        if (request.receiverId().startsWith("P")) {
            Programmer programmer = programmerRepository.findById(request.receiverId())
                    .orElseThrow(() -> new NoSuchElementException("해당 개발자가 존재하지 않습니다!"));
            receiverName = programmer.getName();
        }


        Message message = messageRepository.save(
                new Message(
                        senderId,
                        request.receiverId(),
                        receiverName
                        ));

        return new MessageResponse(
                message.getId(),
                message.getReceiverId(),
                receiverName;
    }
  1. 내가 보낸 쪽지 조회
 public List<MessageSendResponse> findAllSendMessages(String senderId) {
        List<Message> messageList = messageRepository.findAllBySenderId(senderId);
        List<MessageSendResponse> messageSendResponses = new ArrayList<>();
        for (Message message : messageList) {
            messageSendResponses.add(new MessageSendResponse(message.getId(), message.getSenderName()));
        }
        return messageSendResponses;
    }

이렇게 메세지의 id와 보낸 사람의 이름만 저장을 해 조회할 때도 이름만 보이게 된다.

  1. 내가 받은 쪽지 조회
  • 보낸 쪽지 조회랑 똑같다.
public List<MessageSendResponse> findAllSendMessages(String receiverId) {
        List<Message> messageList = messageRepository.findAllBySenderId(senderId);
        List<MessageSendResponse> messageSendResponses = new ArrayList<>();
        for (Message message : messageList) {
            messageSendResponses.add(new MessageSendResponse(message.getId(), message.getSenderName()));
        }
        return messageSendResponses;
    }

받은 쪽지도 보낸 사람의 이름이 포함되어야하는 거니까 senderName이 있는건 똑같은 것이다.

근데 문제점이 있다.

❗️따지고 보면 receiverName이 있어야 하고, senderName도 있어야한다.
❓근데 둘 다 칼럼에 저장하는 것이 맞는가?
이미 sender or receiver id가 있는데 굳이인 거 아닐까? id를 통해서 알 수 있지 않을까?


두번째 방법

그럼 id를 통해서 그 이름을 알아보자
쿼리메서드로 할 수 있지 않을까?

String findReceiverNameByReceiverId(String receiverId);
String findSenderNameBySenderId( String senderId);

이런 코드를 작성해봤다. senderId를 통한 senderName을 찾는 쿼리 메서드이다.
근데 애초에 String 값으로 return타입을 적는 것도 안된다 했기 때문에 이거 실행하면 에러난다. 그리고 이게 성립될 수 없는 이유는
senderId와 실제 sender는 join(ManyToOne)이 되어 있지 않기 때문에 join을 할 수가 없다!!!!!!!

따라서 다른 코드를 작성해야한다.


세번째 방법

그럼 Id를 찾아서 그 Id에 대한 아이를 먼저 찾은 다음에 그 속에 name을 적으면 되지 않을까?

나는 그래서 getSenderName / getReceiverName 함수를 따로 만들었다. 그래서 만약에 보낸사람 혹은 받은 사람이 C/P인지 구별하고, 그 이후 해당 Name을 가져오는 방법으로 하면 구현했다.

// 보낸 사람의 이름 가져오기 (받은 쪽지함에서 사용)
    private String getSenderName(String senderId) {
        if(senderId.startsWith("C")){
            Company company = companyRepository.findById(senderId).orElseThrow();
            return company.getCompanyname();
        } else if (senderId.startsWith("P")) {
            Programmer programmer = programmerRepository.findById(senderId).orElseThrow();
            return programmer.getName();
        }
        throw new IllegalArgumentException("에러");
    }

전체 코드는 그래서 전체 조회할 때 get~Name을 가지고 구현하게 되었다.

//보낸 쪽지함(내가 보낸 메세지)
    public List<MessageResponse> findAllSendMessages(String senderId) {
        List<Message> messageList = messageRepository.findAllBySenderId(senderId)
                .stream()
                .filter(message -> !message.isDeletedBySender()) // 내가 삭제한 메세지 빼고
                .toList();

        return messageList.stream()
                .map(message -> new MessageResponse(
                        message.getId(),
                        message.getReceiverId(),
                        message.getSenderId(),
                        getReceiverName(message.getReceiverId()) // 받는 사람 이름 조회
                ))
                .toList();
    }
    
    // 받는 사람의 이름 가져오기 (보낸 쪽지함에서 사용)
    private String getReceiverName(String receiverId) {
        if(receiverId.startsWith("C")){
            Company company = companyRepository.findById(receiverId).orElseThrow();
            return company.getCompanyname();
        } else if (receiverId.startsWith("P")) {
            Programmer programmer = programmerRepository.findById(receiverId).orElseThrow();
            return programmer.getName();
        }
        throw new IllegalArgumentException("에러 ");
    }

0개의 댓글