인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

hxcva1님의 프로필 이미지

작성한 질문수

웹소켓/STOMP 채팅서비스(spring, vue, redis)

이전메시지조회

쿼리, jpa 질문 있습니다.

해결된 질문

작성

·

97

0

16:00 초에 보면 채팅 메세지를 가져오는데 이때 멤버 정보도 같이 가져오는 것 같다고 보여지는데 findByRoomOrderByCreatedTimeAsc를 호출할때 쿼리가 어떻게 날아가는지 이해가 잘 안되서 질문드립니다. 메세지의 개수마다 멤버 테이블에 join해서 가져오는게 맞는걸까요?

답변 2

0

bradkim님의 프로필 이미지
bradkim
지식공유자

findByRoomOrderByCreatedTimeAsc 쿼리는 select * from chat_message where room_id=? order by created_time asc; 이러한 raw쿼리와 같습니다.

이러한 쿼리를 통해 ChatMessage객체를 List형태로 조회하게 되는데, ChatMessage객체 안에는 Member객체를 가지고 있어서, 메시지마다 member정보를 꺼낼수 있게 되는 거라고 보시면되겠습니다.

hxcva1님의 프로필 이미지
hxcva1
질문자

멤버테이블과 조인되지 않는데 member 정보를 가져올 수 있는걸까요?

bradkim님의 프로필 이미지
bradkim
지식공유자

Message객체에 ManyToOne으로 Member가 잡혀있어서 Member정보를 가져 올수 있습니다! join걸린것과 같다고 보시면되겠습니다.

hxcva1님의 프로필 이미지
hxcva1
질문자

그럼 메세지 리스트를 가져올 때 멤버당 1번만 정보를 가져오는 건지 아니면 메세지마다 멤버의 정보를 가져오는건지 궁금합니다

bradkim님의 프로필 이미지
bradkim
지식공유자

지금 현재 코드로서는 메시지마다 member를 가지고 오고 있습니다. 성능최적화를 위해서는 fetch join을 통해서 한꺼번에 member객체를 가져오는 것이 좋을것 같습니다. 우리 수업에서는 채팅아키텍처에 집중하기 위해서 성능부분들은 많이 배제하고 넘어갔습니다.

hxcva1님의 프로필 이미지
hxcva1
질문자

db설계를 변경해서 풀어낼 수 있는 방법이 있을까요?

bradkim님의 프로필 이미지
bradkim
지식공유자

DB설계변경으로 풀어낼방법은 message테이블이 작성자 정보를 넣어놔야 하는데, 그건 추천드리지 않습니다. 정규화가 되지 않아, 추후 member정보가 변경됐을때 message테이블에 데이터가 갱신되지 않는 문제등 여러 문제가 발생할 가능성이 있어보입니다.

hxcva1님의 프로필 이미지
hxcva1
질문자

결론적으로 모든 메세지에 대해서 작정자 정보를 가져와야하는데 이것을 fetch join으로 한번에 가져올지 아니면 메세지마다 하나씩 가져오는지의 차이라고 이해하면 될까요?

bradkim님의 프로필 이미지
bradkim
지식공유자

넵 맞습니다. 효율성을 위해서는추후 프로젝트에서는 fetch join을 사용하심이 좋아보입니다.

0

인프런 AI 인턴님의 프로필 이미지

안녕하세요, 인프런 AI 인턴입니다. hxcva1님.

채팅 메세지와 멤버 정보를 함께 가져오는 경우, findByRoomOrderByCreatedTimeAsc 메서드는 JPA를 통해 데이터베이스에서 데이터를 조회할 때 주로 사용됩니다. 이러한 메서드는 내부적으로 JPQL(Querydsl과 비슷한 동작 방식) 또는 네이티브 SQL 쿼리를 사용하여 필요한 데이터를 가져옵니다.

여기서 findByRoomOrderByCreatedTimeAsc는 특정 채팅 방(room)에 있는 메세지를 시간 순으로 정렬하여 가져오는 용도로 보입니다. 이 쿼리를 통해 반환되는 메세지 리스트는 각 메세지에 연결된 멤버 정보도 함께 가져오기 위해 @ManyToOne 또는 @Join 자연적인 관계 설정을 포함하고 있을 수 있습니다.

쿼리 작동 방식:
- JPA는 해당 메서드를 실행하면서 메세지 엔티티와 멤버 엔티티 간의 관계가 설정되어 있다면, JPQL 쿼리로 자동으로 조인(Join)하여 관련 데이터를 가져옵니다.
- 예를 들어, 메세지 엔티티에서 @ManyToOne 어노테이션으로 멤버 엔티티를 참조하고 있다면, JPA는 관련 멤버 데이터를 자동으로 가져와서 객체에 주입합니다.
- 따라서 결과적으로는 각 메세지마다 연결된 멤버 데이터를 조인하여 한 번의 쿼리로 모두 가져오는 방식이 됩니다.

성능 측면에서 이러한 JOIN 쿼리는 데이터가 많을 경우 속도가 느려질 수 있으므로, 필요에 따라 페치 조인 또는 배치(fetch size) 옵션을 사용하여 최적화할 수 있습니다. 이는 데이터베이스와 네트워크 부하를 줄이는 데 도움을 줄 수 있습니다.

아래의 유사한 질문과 답변을 통해 추가적인 정보를 얻으실 수 있습니다:
- Spring Data JPA 상에서의 JOIN 사용법에 대한 논의 - JPA 조인 및 페치 전략 설명 포함

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

hxcva1님의 프로필 이미지

작성한 질문수

질문하기