-
Notifications
You must be signed in to change notification settings - Fork 6
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
[Chat] 채팅방에 초대할 때 사용할 코드 생성 API 구현 #149
[Chat] 채팅방에 초대할 때 사용할 코드 생성 API 구현 #149
Conversation
UserChatRoomInvitationRepository, InvitationChatRoomRepository 하나만 있어도 기능 구현이 가능하지 않을까요? |
그렇긴 한데 채팅방에 링크로 참여하는 경우에는 참여코드 -> 채팅방 id 이렇게 읽어야 하잖아요 찾아보니까 Redis는 Value로 검색하는 경우에 시간복잡도가 굉장히 증가한다고 하더라고요 인덱스 설정을 잘 하면 된다고 하긴 하던데 인덱스 설정하는것보다 그냥 key랑 value를 반대로 해서 저장하면 성능이 좋다고 생각했어요 어차피 key랑 value를 반대로 해서 두번 저장할거면 다른 레파지토리에 저장하는게 나아보여서 분리했어요 (같은 레파지토리에다 저장하면 채팅방id:유저id로 참여코드 찾을때는 참여코드->채팅방id는 볼 필요도 없는데 같이 보여서 성능이 안 좋아질 거 같아서요) |
chat/compose.yml
Outdated
- "27018:27017" | ||
environment: | ||
MONGO_INITDB_ROOT_USERNAME: root | ||
MONGO_INITDB_ROOT_PASSWORD: 58155815 | ||
MONGO_INITDB_DATABASE: mongodb No newline at end of file | ||
MONGO_INITDB_ROOT_USERNAME: root | ||
MONGO_INITDB_ROOT_PASSWORD: testpassword1234 | ||
MONGO_INITDB_DATABASE: mongodb | ||
|
||
redis: | ||
image: redis:alpine | ||
container_name: redis_link | ||
ports: | ||
- "6379:6379" | ||
environment: | ||
- REDIS_PASSWORD = "testpassword1234" | ||
command: [ "redis-server","--requirepass","${REDIS_PASSWORD}" ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저번에 한번 본 코드처럼 보이는데요? 중복된 코드가 많으면 코드 리뷰가 힘들어요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저번 pr에 올렸는데 closed되어서 다시 올렸어요
fun getInvitation( | ||
userId: String, | ||
chatRoomId: String, | ||
): InvitationResponse { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
repository에서 InvitationResponse를 반환하는 로직은 어울리지 않은 것 같아요. response는 http 와 관련된 용어라서 오해의 소지가 있어보이는데요? InvitationResponse의 다른 이름은 없을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좋은 지적이네요 더 고민해볼게요ㅕ!
page: | ||
size: 100 | ||
chatroom: | ||
expiration: 1d | ||
baseurl: "http://localhost:8081/" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
baseurl을 사용한 곳이 있나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
지금은 사용하지 않고 있어요 빼겠습니다!
|
||
@Configuration | ||
@ConfigurationProperties(prefix = "chatroom") | ||
class PropertyConfig { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Config 보다는 Property가 더 어울리는 이름인 것 같아요. ChatroomProperty
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
일단 설정파일이라 그렇게 했는데 의미를 생각하면 그게 나아보이네요~!
@Component | ||
class InvitationChatRoomRepository( | ||
private val redisTemplate: RedisTemplate<String, String>, | ||
private val propertyConfig: PropertyConfig, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
init을 통해서 property의 값으로 미리 초기화 하도록 구성하면 더 좋을 것 같아요.
class InvitationChatRoomRepository(
..
){
val ttl = propertyConfig.getExpiration()
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static이 아니라서 주입받아야 할 것 같고 뭔가 변수가 추가되었을때도 한번만 주입받기 위해서 저렇게 사용했습니다!
@@ -12,4 +12,7 @@ enum class ErrorCode(val httpStatus: Int, val message: String) { | |||
|
|||
// 404 | |||
CHATROOM_NOT_FOUND(HttpStatus.NOT_FOUND.value(), "해당 id로 chatroom을 찾을 수 없습니다"), | |||
|
|||
// 500 | |||
INVITATION_LINK_SAVE_FAILURE(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Invitation Code가 저장되지 않았습니다"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
client로 노출할 메시지라서 에러 메시지가 너무 상세하지 않은가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좋은 지적이네요 다시 생각해볼게요ㅕ
조회할 때, 초대받은 유저가 코드로 검색하지않으면 되지 않을까요? |
이 방향으로 처음에 개발을 시작했었는데 만약 채팅방id:유저id의 정보로만 참여하게 되면 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
초대 코드를 생성하고 조회에 문제가 없는지 단위 테스트를 작성하면 더 좋을 것 같아요! 다음에는 테스트를 통해서 어플리케이션을 신뢰적으로 만들어보죠
fun getInvitationCode( | ||
userId: String, | ||
chatRoomId: String, | ||
): InvitationResponse { | ||
): String { | ||
val key = generateKey(userId, chatRoomId) | ||
var value = redisTemplate.opsForValue().get(key) | ||
if (value == null) { | ||
value = setInvitation(key, chatRoomId) | ||
} | ||
|
||
val expiration = redisTemplate.getExpire(key) | ||
|
||
return InvitationResponse(value, LocalDateTime.now().plusSeconds(expiration).toString()) | ||
return generateCode(key, value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getInviationCode이지만 코드를 생성하고 저장하는 역할을 같이 구현되어있는 것 같아요. 겳합도를 낮추는 방향으로 개선하면 좋을 것 같아요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네 좋습니다
key: String, | ||
value: String, | ||
): String { | ||
val combine = "$key,$value" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
combine 동사이기도 하고 무슨 의미인지 직관적으로 파악이 힘든 것 같아요!, key, value의 의미가 무엇인지 파악이 힘들어서 주석으로 무슨 의미인지를 좀 더 설명을 해주면 좋을 것 같아요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네~! 변수명이 가독성이 떨어지는거 같긴 하네요
import java.util.* | ||
|
||
@Component | ||
class UserChatRoomInvitationRepository( | ||
class InvitationRepository( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
초대 저장소가 하는 역할이 무엇인가요? 서비스 layer에 더 어울리는 역할을 수행하는 것 같은 느낌?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
재사용할 수 있는 컴포넌트인가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
findbyId 나 save등만 있는게 아니라서 재사용이 불가능할 것 같아요
chatService랑은 좀 동떨어진 일을 하는 것 같아서 저 repository로 초대/참여 관련 로직을 분리했었는데 생각해보면 다른 Service로 분리하는게 더 나아보이네요
private val invitationRepository: InvitationRepository, | ||
private val chatRoomProperty: ChatRoomProperty, | ||
) { | ||
fun getOrCreateInvitation( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get과 create 두가지 책임을 담당하는 메서드라서 분리하는 것이 좋다고 생각합니다.
#️⃣연관된 이슈
#87
📝작업 내용
채팅방에 초대할 때 사용할 코드 생성
💬리뷰 요구사항
채팅방 참가자가 채팅방에 초대하기 위해서 참여코드를 발급받을때에 쓰는
key: 채팅방id,유저id
value: 참여 코드
인 UserChatRoomInvitationRepository를 하나 만들고
채팅방 비참여자가 채팅방에 참여할때 쓸 (아직 api 구현이 안 되어서 사용하지는 않고 있습니다)
key: 참여 코드
value: 채팅방id 인 InvitationChatRoomRepository를 하나 만들었습니다
그런데 UserChatRoomInvitationRepository에서 참여 코드를 새로 생성할때
참여코드 -> 채팅방 id도 InvitationChatRoomRepository에 저장해야해서
UserChatRoomInvitationRepository에서 InvitationChatRoomRepository를 주입받아
이런식으로 사용하게 했는데 Repository끼리 저런식으로 결합되는게 좋은지 의문입니다
Service단에서 처리하려면 Return되는 DTO에 필드 하나를 추가해야할 것 같아서 저렇게 했는데
필드를 하나 추가하고 결합도를 낮추는게 더 나을까요?