Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat] 커피챗 수신 API 문자 발송 기능 추가 #487

Merged
merged 21 commits into from
Oct 15, 2024

Conversation

jun02160
Copy link
Member

@jun02160 jun02160 commented Oct 12, 2024

🐬 요약

기존 커피챗 수신 API를 리팩토링 하고, 문자 발송 기능을 추가하여 쪽지 보내기와 커피챗 신청하기를 분리하여 처리합니다.

👻 유형

PR의 유형에 맞게 체크해주세요!

  • 버그 수정
  • 기능 개발
  • 코드 스타일 수정 (formatting, local variables)
  • 리팩토링 (no functional changes, no api changes)
  • 빌드 관련 변경사항
  • CI 관련 변경사항
  • CD 관련 변경사항
  • 문서 내용 변경
  • Release
  • 기타... (다음 줄에 사유를 입력해주세요)

🍀 작업 내용

AS-IS

  • 커피챗 수신 API에서 쪽지 보내기와 커피챗 신청하기를 한번에 처리합니다.
  • 해당 API 호출 시, 이메일을 통해 receiverId의 유저에 커피챗이 온 사실을 알립니다.
  • senderEmail (회신 받을 이메일)의 요청을 강제합니다.
  • email_history에서 쪽지 보내기 시 요청한 데이터를 저장합니다.

TO-BE

  • 커피챗 수신 API에서 쪽지 보내기와 커피챗 신청하기를 한번에 처리합니다.
  • 해당 API 호출 시, category 값에 따라 문자(gabia) 또는 이메일을 통해 receiverId의 유저에 커피챗이 온 사실을 알립니다.
  • senderPhone, senderEmail이 요청 바디에 없더라도 default 값으로(멤버 프로필 기준) 지정되어 정상적으로 동작합니다.
  • 커피챗 신청 시 email_history 테이블이 아닌, coffee_chat_history 테이블에 적재하도록 신규 테이블을 추가합니다. (추후 별점 기능 등 커피챗 기능 고도화에 대한 확장성 고려)

Test

쪽지 보내기

senderEmail 필드 없이 request 를 보내도 default email로 정상 처리 (email_history 테이블에 row 추가)
image

커피챗 신청하기

senderPhone 필드 없이 request 를 보내도 default phone으로 정상 처리 (coffee_chat_history 테이블에 row 추가)
image

Action Item

  • prod ddl 반영
create table internal_prod.coffee_chat_history
(
    id              bigserial primary key,
    created_at      timestamp default now() not null,
    updated_at      timestamp default now() not null,
    request_content text,
    receiver_id     bigint    not null
        constraint fk_receiver_id
            references internal_prod.users,
    sender_id       bigint    not null
        constraint fk_sender_id
            references internal_prod.users
);

alter table internal_prod.coffee_chat_history
owner to sopt_makers;

dev에서 coffee_chat_history2 테이블 생성하도록 ddl 실행 테스트 완료했습니다.
image

Agenda

  1. coffee_chat_history 테이블에 senderPhone 정보도 저장해야 할까요?
  2. val 과 타입 명시 중 하나로 통일했으면 하는데.. 승헌님은 어떤 게 더 좋다고 보시나요?? 변수 재활용 해야 할 때는 무조건 타입 명시가 좋은 것 같아서 일단 혼용해둔 상태입니다..! (val은 데이터 변경이 불가하므로)

🌟 관련 이슈

PR과 관련된 이슈 번호를 작성해주세요!

close: #483

- EmailHistory와 비슷한 역할을 수행하나, 추후 별점 등 커피챗 별도의 기능을 추가할 수 있는 확장성을 고려해 신규 테이블 생성

related issue #483
- ChatCategory enum 추가하여 COFFEE_CHAT / 그 외 카테고리에 따른 분기처리

related issue #483
@jun02160 jun02160 added ✨Feature 새로운 기능 개발시 사용합니다 ♻️ Refactor 코드 리펙토링 시 사용합니다. 예준🐈 예준이 연 PR, Issue에 사용 labels Oct 12, 2024
@jun02160 jun02160 requested a review from dev-Crayon October 12, 2024 11:32
@jun02160 jun02160 self-assigned this Oct 12, 2024
Copy link

height bot commented Oct 12, 2024

Link Height tasks by mentioning a task ID in the pull request title or commit messages, or description and comments with the keyword link (e.g. "Link T-123").

💡Tip: You can also use "Close T-X" to automatically close a task when the pull request is merged.

Copy link

Hi there 👋

Using this App for a private organization repository requires a paid subscription.

You can click Edit your plan on the Pull Request Size GitHub Marketplace listing to upgrade.

If you are a non-profit organization or otherwise can not pay for such a plan, contact me by creating an issue

- requestBody에서 senderEmail이 누락되더라도 이메일 발송이 정상 동작하도록 수정
- 각 분기에서 호출하는 함수 변경 (fix)

related issue #483
- private 생성자 선언과 중복

related issue #483
- 커피챗 수신 API -> 커피챗/쪽지 수신 API

related issue #483
Comment on lines 6 to 10
Long receiverId,
String senderEmail,
@JsonProperty(required = false) String senderEmail,
@JsonProperty(required = false) String senderPhone,
String category,
String content
Copy link
Contributor

Choose a reason for hiding this comment

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

각 데이터들에 대한 Validation도 추가되면 좋을 것 같습니다!

Copy link
Member Author

Choose a reason for hiding this comment

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

1956902에서 반영했습니다

@Parameter(hidden = true) @AuthenticationPrincipal InternalMemberDetails memberDetails
) {
coffeeChatService.sendCoffeeChatRequest(request, memberDetails.getId());
val response = new CommonResponse(true, "커피챗/쪽지 수신 요청에 성공했습니다.");
Copy link
Contributor

Choose a reason for hiding this comment

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

val 사용에 대해서 한 번 정하고 가는 게 좋을 것 같습니다! 제 기억으로는 리팩토링 하면서 val 사용을 지양하기로 했던 것 같은데 혹시 제가 잘못기억하고 있거나, 예준님 의견이 있다면 편하게 말씀해주시면 좋을 것 같습니다!

Copy link
Member Author

Choose a reason for hiding this comment

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

아하 이거 PR 본문의 agenda로 적어두었는데 이전에 이미 논의된 내용이었군요!!
저도 동의합니다. 앞으로 val 사용 지양하는 걸로 통일하겠습니다 👍

Copy link
Member Author

Choose a reason for hiding this comment

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

1561ce1에서 수정했습니다!

Comment on lines +24 to +28
public List<String> concatPartAndGeneration(Long memberId) {
return memberSoptActivityRepository.findAllByMemberId(memberId).stream()
.map(activity -> String.format("%d기 %s", activity.getGeneration(), activity.getPart()))
.toList();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

그럴 일은 없겠지만 findAllByMemberId로 조회를 했을 때 YB인데 length가 1보다 크거나 OB인데 기수의 길이가 2보다 작은 경우를 에러로 던지는 로직이 있으면 좋다고 생각합니다. 저희가 아직은 수동으로 기수정보를 처리하다보니 혹시나 생길 수 있는 휴먼에러에 대응하기 위한 것 인데요 혹시 공수가 조금 크다면 //TODO 주석을 남겨놓는 것도 방법인 것 같습니다.

Copy link
Member Author

Choose a reason for hiding this comment

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

넵! 이건 TODO로 남겨두고 이슈 생성해두겠습니다 ~~ 좋은 의견 감사합니당

Comment on lines 51 to 52
val receiver = memberRetriever.findMemberById(request.receiverId());
val sender = memberRetriever.findMemberById(senderId);
Copy link
Contributor

Choose a reason for hiding this comment

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

val 관련 부분은 위의 코멘트와 동일합니다.

Copy link
Member Author

Choose a reason for hiding this comment

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

1561ce1에서 수정했습니다!

Comment on lines 53 to 58
if (request.category().equals(ChatCategory.COFFEE_CHAT.getValue())) {
sendCoffeeChatMessage(request, sender, receiver);
} else {
sendChatEmail(request, sender, receiver);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

ChatCategory에 따라서 문자를 발송할지 이메일을 발송할지 구분하는 부분은 커피챗 신청에 따른 분기처리라고 생각됩니다.
따라서 서비스 계층에 직접적으로 드러나있기보다는 "커피챗 request가 들어오면 receiver에게 무언가(이메일, 문자)를 보낸다!" 라는 것만 서비스계층을 알고 있으면 된다고 생각합니다. 실제로 어떻게 보내는지는 서비스 계층이 궁금한 부분은 아니라고 생각해요
만약 나중에 email이나 문자가 아닌 다른 방식으로 메세지를 전달해야한다면 코드 변경 및 전송로직을 변경을 해야할 것 같아요

따라서 ChatCategory에 따라 사용자에게 정보를 전달해주는 객체가 따로 있으면 좋다고 생각합니다.

추가적으로 현재는 request에서 category를 문자열로 받아서 처리하고 있는데 ENUM을 사용하는 만큼 enum으로 받아서 확인하는 로직을 조금 더 간단하게 할 수 있을 것 같습니다!

Copy link
Member Author

Choose a reason for hiding this comment

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

따라서 ChatCategory에 따라 사용자에게 정보를 전달해주는 객체가 따로 있으면 좋다고 생각합니다.

너무 좋은 피드백인 것 같습니다 👍 ServiceFactory에서 추상화하도록 리팩토링하였고, strategy 패턴을 이용해 말씀 주신 방향대로 변경에도 용이한 구조로 개선했습니다!

추가적으로 현재는 request에서 category를 문자열로 받아서 처리하고 있는데 ENUM을 사용하는 만큼 enum으로 받아서 확인하는 로직을 조금 더 간단하게 할 수 있을 것 같습니다!

좋은 의견 감사합니다!! 38820f1에서 반영 후 enum validation 적용했습니다

image image

Comment on lines 83 to 89
emailHistoryRepository.save(EmailHistory.builder()
.senderId(senderId)
.receiverId(request.receiverId())
.senderEmail(request.senderEmail())
.category(request.category())
.content(request.content())
.createdAt(LocalDateTime.now(KST)).build());
.senderId(sender.getId())
.receiverId(request.receiverId())
.senderEmail(email)
.category(request.category())
.content(request.content())
.createdAt(LocalDateTime.now(KST)).build());
Copy link
Contributor

Choose a reason for hiding this comment

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

커피챗 관련 메일을 보내는 함수에서 테이블에 데이터를 저장하는 로직이 담겨있는 부분은 조금 어색할 수도 있는 것 같아요
메일 발송에 에러가 발생하지 않았다면, 그 후 테이블에 저장하는 방식으로도 크게 문제가 없다고 생각합니다!

Copy link
Member Author

Choose a reason for hiding this comment

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

넵! 4b96180 에서 반영 및 리팩토링 진행했습니다

- Request Validation 추가

related issue #483
- val -> type 명시

related issue #483
@dev-Crayon
Copy link
Contributor

Agenda 1.
현재는 굳이 필요 없다고 생각이 되긴하는데요, 이미 멤버테이블에 있는 데이터기도하고 커피챗 신청은 여러 번 가능한데 이때마다 중복으로 번호가 저장될 것 같아서 그렇습니다!

- sendChatEmail, sendCoffeeChatSMS 와 history 테이블에 insert 하는 메서드 분리
- 메시지 발송 시, receiver의 phone으로 넘기도록 수정 (fix)
- phone, email requestBody에 없는 경우 default 값 지정하는 로직 별도 메서드로 분리

related issue #483
- RequestBody에서 ChatCategory 타입을 사용하도록 변경
- ChatCategory에 정의된 값들 중에 존재하는지 검사하는 validation 추가

related issue #483
- EmailSender package 변경 : domain/ -> external/email/
- EmailHistoryService 분리
- MessageSenderFactory를 통해 Email / SMS send 로직 추상화

related issue #483
- self-qa 중 발견된 버그 수정

related issue #483
- 동일한 if-else 구문 제거

related issue #483
- TODO comment 추가

related issue #483
@jun02160 jun02160 requested a review from dev-Crayon October 12, 2024 15:08
@jun02160
Copy link
Member Author

@dev-Crayon 의견 주셔서 감사합니다!! 코드리뷰 반영 완료해서 피드백 마구마구 주시면 감사하겠습니다아 ㅎㅎ

- swagger required 여부 반영

related issue #483
@Pattern(regexp = PHONE_NUMBER_REGEX, message = "잘못된 전화번호 형식입니다. '-'을 제외한 11자의 번호를 입력해주세요.")
String senderPhone,

ChatCategory category,
Copy link
Contributor

Choose a reason for hiding this comment

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

ChatCategory 필드는 required = false 인가요? 그렇지 않다면 @NotNull을 사용해도 좋을 것 같습니다.

Copy link
Member Author

Choose a reason for hiding this comment

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

enum validation이 이미 적용된 상태에서 Spring Validator의 @NotNull을 중복 적용할 수 없어서 제외해두었습니다!
swagger는 required=true로 반영해두겠습니다! 1efd25c

@dev-Crayon
Copy link
Contributor

마지막 코멘트만 확인해주시고 merge해도 될 것 같습니다! 고생하셨습니다

- swagger required 여부 반영

related issue #483
@jun02160
Copy link
Member Author

아직 문자 메시지 본문 픽스가 안 나서 고거까지 반영 후에 머지하겠습니다 ㅎㅎ

@jun02160 jun02160 merged commit 3ef7127 into develop Oct 15, 2024
1 check passed
@jun02160 jun02160 deleted the feat/send_coffee_chat_message branch October 15, 2024 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨Feature 새로운 기능 개발시 사용합니다 ♻️ Refactor 코드 리펙토링 시 사용합니다. size/L 예준🐈 예준이 연 PR, Issue에 사용
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feat] 커피챗 제안 신청(문자 발송) 기능 추가
2 participants