지인이 우아콘 2023에 당첨되어 운좋게 양도 받아 우아콘에 다녀왔다!
강의 내용을 중간 중간 메모하려 했는데 너무 집중해서 보느라 필기를 잘 못했고 발표 내용에서 흐름과 해결과정을 집중해서 기억했다.
우아콘 트랙A 첫 이야기 요약
2.
이벤트 유실
•
무분별한 이벤트 발행으로 인해 복잡도가 증가하고 이벤트 유실이 많아졌다.
•
이벤트 로직 처리 지점을 단일화하여 복잡도를 낮추었다.
•
이벤트를 발행하기 전에 미리 Payload를 저장해서 이벤트가 유실되더라도 재요청을 할 수 있도록 했다.
3.
무자비한 Read 요청으로 조회성능 하락
•
RDBMS의 Join 대신 NoSQL로 관리
2번의 경우 특정 로직을 실행하기 전 유실을 막기 위해 저장했다는 점에서 이전에 내가 생각했던 방식이랑 비슷해서 신기했다.
이번 프로젝트에 적용해볼 주제는 3번 내용이다.
데이터베이스 예시
id | name | age | school |
1 | 김하나 | 20 | 고려대학교 |
2 | 김두리 | 23 | 고려대학교 |
만약 이런 테이블이 있다면 필요성에 따라 중복데이터를 기준으로 정규화를 진행할 수 있다.
id | name | age | univ_id |
1 | 김하나 | 20 | 1 |
2 | 김두리 | 23 | 1 |
id | name | city |
1 | 고려대학교 | 서울특별시 |
2 | 연세대학교 | 서울특별시 |
이 경우엔 하지만 데이터가 많아질 경우 조회 성능이 점점 안나오고 쿼리가 복잡해진다는 단점이 있다.
SELECT *
FROM users AS u
INNER JOIN univ AS un
ON un.id = u.univ_id
WHERE un.id = 1;
SQL
복사
이 쿼리들을 요청하는 빈도가 높을수록 데이터베이스의 부하는 심해진다.
•
물론 READ의 경우 Scale Out 으로 풀어갈 수 있으나 1차적으로 최적화를 고려해야한다.
MongoDB
MongoDB는 NoSQL중 DocumentDB로 RDB보다 자유도가 높다.
위 상황으로 예시를 든다면 NoSQL을 사용해 아래와 같이 데이터들을 영속할 수 있다.
id | uname | univ_id | name | city | other_info |
xxx1 | 김하나 | 1 | 고려대학교 | 서울특별시 | xxx |
xxx2 | 김두리 | 1 | 고려대학교 | 서울특별시 | yyy |
xxx3 | 김세모 | 2 | 연세대학교 | 서울특별시 | zzz |
SQL만 사용한다면 Join을 통해 가져올 데이터를 ID를 가지고 단 번에 조회할 수 있다.
•
배민의 경우 주문이 발생한 경우 주문서 정보들을 NoSQL로 영속하여 Join을 없앤다고 한다.
스프링부트에서 MongoDB를 적용하는 방법은 아래 페이지에서 볼 수 있다.
•
해당 내용을 사용한 깃 레포지토리 주소
적용 후
기존의 경우 스토어 테이블과 상품 테이블을 조인했지만 이미 조인된 결과가 NoSQL에 영속되어 있기 때문에
historyId 필드 하나만으로 검색할 수 있어 데이터베이스 부하를 줄일 수 있다.
{
"status": "OK",
"data": {
"histories": [
{
"historyId" : "xxxxxxyyyy1"
"storeName": "메가커피",
"locationName": "홍대입구역점",
"productName": "xx커피",
"productPrice": 2500,
"createdAt": "2023-12-01T15:41:04.535",
"updatedAt": "2023-12-01T15:41:04.535"
}, ...
]
}
}
Java
복사