개발자

클라이언트, 서버 두 DB의 데이터를 동시에 수정할 때 무결성 보장

2024년 02월 14일조회 140

안녕하세요 어플리케이션을 만드는 도중 문제가 생겼습니다. indexedDB( 클라이언트 ), postgreSql( 서버 ) 2곳의 데이터를 동일하게 수정해야할 때 ( 추가, 삭제, 수정 등 ) 한 곳의 api 가 실패하는 순간 이미 수정이 된 곳의 트랜잭션을 롤백 ( abort ) 하여 연동된 두 곳의 데이터가 동일 하도록 무결성을 보장하고자 합니다. 그런데 2가지 문제를 발견하였습니다. 1. indexedDB 의 트랜잭션 도중 다른 api 의 await를 쓰는 순간 indexedDB 는 트랜잭션을 즉시 종료시켜 서버 데이터 수정이 실패해도 abort() 가 불가능하다. 2. postgreSql 의 트랜잭션은 next.js 의 서버사이드 api에서 쿼리를 날리기에 중간에 클라이언트 사이드의 indexedDB 수정 api 사용이 불가능하다. indexedDB는 idb, postgreSql 은 pg 라이브러리를 사용중입니다. 수정 되기 전 상태를 임의로 기록 > 2번째 api 실패? > 기록된 상태로 수정하는 api 요청 이라는 단순한 방법도 생각해봤지만 결국 마지막 상태로 수정하는 것도 별도의 api 요청이기에 이 것또한 실패할 시 무결성 보장이 되지않기에 포기하였습니다... 선배님들은 서버와 클라이언트 데이터를 연동할때 무결성 보장을 어떻게 하시나요? next.js 14 환경입니다.

이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.

답변 1

인기 답변

박범수님의 프로필 사진

기종이 다른 두 가지 데이터베이스를 동기화 시키는 작업은 아주 어려운 과제입니다. 만들고 계신 어플리케이션이 어떤 일을 하는지 모르겠지만, 어플리케이션 전체를 개발하는 것 보다 이 작업이 더 어려울수도 있습니다. 우선 데이터베이스 두 개를 싱크하는 작업이 꼭 필요한지를 먼저 생각하셔야 합니다. 서버가 MSA 구조여서 서로 데이터를 싱크하는 경우는 많이 봤지만, 클라이언트도 각자의 DB를 가지고 있어 중앙 서버와 싱크해야 하는 경우는 드뭅니다. 보통 클라이언트단의 데이터베이스는 서버의 데이터베이스와 지위가 다릅니다. 데이터가 통째로 삭제되더라도 큰 지장이 없는 데이터만 저장해야 합니다. 중요한 데이터를 클라이언트에도 저장해두는 것은 보안 문제를 야기시킬 수 있습니다. 프론트엔드의 코드는 사용자에게도 공개된다는 점을 기억하셔야 합니다. 여기에 postgres 주소라도 적어놓으면 해커들의 엄청난 공격에 시달릴 것입니다. 클라이언트마다 각자 DB를 가지고 있기 때문에 사용자가 늘어날수록 부하도 심해질 겁니다. 데이터를 postgres에만 저장하는 방안을 생각해봅시다. 혹시 성능 때문에 indexedDB를 캐싱 용으로 사용하시는 건가요? 동기화 작업을 수행하는 순간 성능은 희생될 수 밖에 없습니다. 성능과 동기화를 동시에 챙기는 것은 어려운 것이 아니라 불가능한 과제입니다. 분산 데이터 저장의 트레이드오프에 대해서는 다음 글을 참조 부탁드립니다. https://velog.io/@skynet/%EC%84%B8%EC%83%81%EC%97%90-%EC%99%84%EB%B2%BD%ED%95%9C-%EB%B6%84%EC%82%B0-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%80-%EC%97%86%EB%8B%A4-%EB%B6%84%EC%82%B0-%EC%8B%9C%EC%8A%A4%ED%85%9C%EA%B3%BC-CAP-%EC%A0%95%EB%A6%AC 아무리 생각해봐도 싱크가 꼭 필요하다면 2-phase commit 이나 saga 패턴 같은 기법을 적용하시면 됩니다. 참고로 현재 구상중인 구조, 즉 한 DB의 트랜잭션 안에 다른 DB의 트랜잭션을 포함시키는 것은 유효한 대안이 아닙니다. indexedDB가 postgres를 호출하는 것을 허용한다고 가정해봅시다. indexedDB가 마지막 커밋에 실패하면 어떻게 해야 할까요? postgres에 이미 저장된 데이터를 삭제/수정해서 되돌려야 할 겁니다. 그런데 이 수정, 삭제 작업마저 실패하면 데이터의 싱크를 맞추는 것이 거의 불가능해집니다.

세혁님의 프로필 사진

세혁

작성자

삼성 청년 SW 아카데미 웹 개발2024년 02월 26일

얕은 질문에 깊게 답변해주셔서 감사합니다. 단순히 오프라인에서도 사용 가능한 PWA 어플리케이션을 만들고자 클라이언트 DB 와 서버 DB 를 동기화 하고자 한 것인데 그동안 서치해본 결과로는 선생님께서 말씀해주신대로 배보다 배꼽이 더 커지는 작업인 것 같습니다. 다시 한번 답변해주셔서 감사드립니다!

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

AI 답변
커리어리 AI 봇 프로필 이미지

커리어리 AI 봇

GPT가 달아주는 답변입니다.

2024년 02월 14일

DB 무결성 문제는 일반적으로 트랜잭션을 이용하여 관리합니다. 그러나 클라이언트와 서버 모두에서 동시에 업데이트를 처리해야 하는 경우에는 이어지는 추가적인 복잡성을 다루어야 합니다. 하나의 방법은 Two-Phase Commit(2PC) 프로토콜을 사용하는 것입니다. 이 방식은 분산된 DB 시스템에서 일반적으로 사용됩니다. 과정은 크게 두 단계로 나뉘어져 있습니다: 준비(phase 1)와 커밋(phase 2). 각 참가자(DB)에 대해 쿼리가 성공적으로 실행할 수 있는지 묻는 준비 단계, 그리고 성공/실패를 알려주는 커밋 단계가 있습니다. `indexedDB`에서 긴 트랜잭션 동안 `await`를 수행할 경우, 트랜잭션이 종료되는 문제가 발생하므로 비동기 로직을 `indexedDB` 트랜잭션 외부에서 처리하고, 결과만 확정된 후 `commit`/`abort`하는 방식을 고려해 볼 수 있습니다. PostgreSql의 경우 서버 사이드 API 내부에서 트랜잭션을 시작하고, 클라이언트 사이드에서 `indexedDB`의 상태를 확인한 후 결과에 따라 PostgreSql 트랜잭션을 `commit`/`rollback`하는 방안도 고려해 볼 수 있습니다. 다만 이러한 아키텍처는 복잡성이 많이 증가하므로, 간단하게 해결할 수 있는 다른 접근법을 찾아보는 것도 좋습니다. 예를 들어, 변경사항을 일시적으로 저장하여 나중에 동기화하는 등의 방법을 고려해볼 수 있습니다. 하지만 이러한 해결책들은 어플리케이션의 요구 사항에 따라 달라질 수 있으므로 주의 깊게 분석하고 선택해야 합니다.

목록으로

지금 가입하면 모든 질문의 답변을 볼 수 있어요!