GitHub - lsh2613/spring-rabbitmq: Spring + RabbitMQ를 활용한 1:1 채팅방 구현
Spring + RabbitMQ를 활용한 1:1 채팅방 구현. Contribute to lsh2613/spring-rabbitmq development by creating an account on GitHub.
github.com
1. 채팅 내역을 MongoDB에 저장하는 이유
1. MongoDB는 NoSQL의 한 종류로 RDB보다 더 빠른 읽기/쓰기 성능을 가진다.
2. 사용자가 많아질수록 채팅 데이터는 훨씬 많아지기 때문에 scale-out을 고려해야 하는데, 대부분의 NoSQL을 클러스터링을 지원하여 보다 쉬운 scale-out을 적용할 수 있다.
3. 채팅은 정형화되어 있기 보다는 언제든지 바뀔 수 있으며 채팅 특성 상 많은 읽기, 쓰기가 일어날 것이다
위와 같은 이유로 NoSQL을 선택했다. 그럼 NoSQL 중에서도 왜 MongoDB를 선택했을까?
우선 처음 다뤄보는 NoSQL에 대해 자료가 많은 걸 찾았고 크게 MongoDB, AWS DynamoDB를 후보지로 생각했다.
MongoDB vs DynamoDB
조사해본 결과 두 DB의 공통점으로 Spring 호환, 클러스터링 지원, JSON 지원이 가능하다는 점이다.
사실 위 조건만 봐도 아무거나 사용해도 괜찮았지만 MongDB는 SpringBoot ORM을 지원해줘서 기존에 사용하던 JPA 기능들을 비슷하게 사용할 수 있다는 점때문에 MongoDB를 선택했다
ChatGPT에 물어본 두 DB의 차이점이다
2. 구현
메인 DB는 MySQL, 채팅내역은 MongoDB를 사용하기 위해 추가된 코드들을 살펴보자
docker-compose.yml
version: '3.8'
services:
mongodb:
image: mongo:latest
container_name: mongodb
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: 1234
MONGO_INITDB_DATABASE: message_history
ports:
- "27017:27017"
application.yml
spring:
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:testdb # h2 url ex_): jdbc:h2:tcp://localhost/~/test
username: sa # h2 id
password: # h2 password
h2:
console:
enabled: true
data:
mongodb:
uri: mongodb://root:1234@localhost:27017/message_history?authSource=admin&authMechanism=SCRAM-SHA-1
username: root
password: 1234
MongoDB는 JDBC를 통해 연결하지 않고, MongoDB 드라이버와 스프링의 MongoDB 관련 라이브러리를 사용하여 직접 연결합니다. 따라서 일반적인 datasource 설정이 아닌, spring.data.mongodb 섹션에서 설정을 지정하게 됩니다
MongoDBConfig
@Configuration
@RequiredArgsConstructor
@EnableMongoRepositories("com.rabbitmqprac.chatmessage")
@EnableMongoAuditing
public class MongoDBConfig {
@Bean
public MappingMongoConverter mappingMongoConverter(MongoDatabaseFactory mongoDatabaseFactory, MongoMappingContext mongoMappingContext) {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDatabaseFactory);
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext);
converter.setTypeMapper(new DefaultMongoTypeMapper(null)); // '_class' 필드를 제거
return converter;
}
}
@EnableMongoRepositories(...) -> MongoDB를 사용할 범위를 지정
@EnableMongoAuditing -> @CreatedAt을 사용하기 위한 auditing
기존 MySQL-JPA를 사용하기 위해 작성했던 코드들을 수정하자
ChatMessage
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "chat_message")
@ToString
public class ChatMessage {
@Id
private String id;
private Long chatRoomId;
private Long memberId;
private String message;
@CreatedDate
@Column(name = "createdAt", updatable = false)
private LocalDateTime createdAt;
}
MongoDB로 바뀌며 Entity -> Document로 변경
JPA 연관관계 제거
여기까지 MySQL -> MongoDB로 변환은 끝이다. 이전 코드가 정상적으로 작동하겠지만 테스트를 위해 ChatMessage 조회 기능도 추가해보았다
// ChatMessageController
@GetMapping("/chat-messages/chat-room/{chatRoomId}")
public ResponseEntity getChatMessages(@PathVariable Long chatRoomId) {
List<ChatMessageRes> chatMessageResList = chatMessageService.getChatMessagesByChatRoomId(chatRoomId);
return ResponseEntity.ok(chatMessageResList);
}
// ChatMessageService
public List<ChatMessageRes> getChatMessagesByChatRoomId(Long chatRoomId) {
List<ChatMessage> chatMessages = chatMessageRepository.findByChatRoomIdOrderByCreatedAtAsc(chatRoomId);
return chatMessages.stream()
.map(ChatMessageRes::createRes)
.toList();
}
3. 테스트
STOMP를 통해 메시지를 보내고 MongDB를 확인해보자
'Project > RabbitMQ(STOMP)를 적용한 1:1 채팅' 카테고리의 다른 글
Spring + RabbitMQ를 통한 1:1 채팅방 구현 - 인증 적용 (4) (0) | 2024.11.16 |
---|---|
Spring + RabbitMQ를 통한 1:1 채팅방 구현 - 읽음/안읽음 적용 (3) (2) | 2024.11.16 |
Spring + RabbitMQ를 통한 1:1 채팅방 구현 (1) (0) | 2024.10.31 |