Skip to content

Conversation

@eemdeeks
Copy link
Member

@eemdeeks eemdeeks commented Jan 8, 2025

🌁 Background

화이트보드 오브젝트의 실시간 데이터 일관성을 보장하기 위해 레지스터를 구현 했습니다.

👩‍💻 Contents

화이트보드 오브젝트의 실시간 데이터 일관성을 보장하기 위해서 CRDT의 LWW 알고리즘을 사용했습니다.
해당 알고리즘을 적용한 Register를 구현하여 화이트보드 오브젝트의 데이터가 시간상 이후에 들어온 데이터로 일관성을 갖게 했습니다.

노션페이지: 실시간 데이터 일관성 보장하기

✅ Testing

LWWRegister

  • merge()
    • timestamp가 같을 때

    • 새로 들어온 timestamp가 작을때

      • 새로 들어온 updatedAt이 더 빠를 때

      • updatedAt은 같지만 UUID가 작을때

    • 새로 들어온 timestamp가 클 때

      • 새로 들어온 updatedAt이 더 느릴 때

      • updatedAt은 같지만 UUID가 클 때

📝 Review Note

📣 Related Issue

@eemdeeks
Copy link
Member Author

eemdeeks commented Jan 8, 2025

구현하면서 고민한 부분들

커밋 내용과 함께 그 외에 여러번 지운 커밋들이 갖고 있는 고민과 플로우에 대해서 적어보았습니다.
실시간 데이터 일관성 보장에 대한 내용보다도 그와 함께 해결할 문제인 동시성문제에 대한 여러 고민과 해결들을 담아 보았습니다.

  1. actor를 통한 WhiteboardObject에 대한 동시성 문제 해결
  2. SerialQueue를 통한 동시성 문제 해결
  3. 테스트 코드를 작성하며..
  4. struct와 Register를 통한 WhiteboardObject에 대한 동시성 문제 해결

자세한 내용은 딴의 일일 개발회고에 있으니 궁금하면 간단하게 읽어보시길!

Copy link
Collaborator

@taipaise taipaise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

정말 고생하셨습니다!!!!
몇 가지 궁금한 점이 있는데요, WhiteboardObjectRegisters의 동작 방식이 기존의 WhiteboardObjectSet과 유사하다고 느꼈습니다. 이제 저희 Airplain이 겪고 있던 동시성 문제를 해결할 수 있었다고 하셨는데, WhiteboardObjectSetWhiteboardObjectRegisters로 대체되는 것일까요? (물론 이 부분은 아직 WhiteboardObjectRegisters를 실제 코드에서 사용하는 부분이 없어 헷갈리는 것 같긴 합니다)
LWWRegister 자체를 struct로 설계한 부분은 정말 좋다고 생각합니다. 혹시 이 부분은 데이터의 불변성을 고려하신 것인지 궁금합니다. (동시성 문제를 줄이고 안정성을 높이기 위한!!) 만약 불변성을 염두에 두셨다면, struct 내부에 있는 레퍼런스 타입(whiteboardObject)의 내부 상태 변화에 대해서도 고려하신건지 궁급합니다!

}

public static func < (lhs: Timestamp, rhs: Timestamp) -> Bool {
if lhs.updatedAt == rhs.updatedAt { return lhs.updatedBy < rhs.updatedBy }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 요 부분 덕분에 updatedAt이 같더라도, 우선 순위가 생기겠군요 죠습니다 🦈

@eemdeeks
Copy link
Member Author

eemdeeks commented Jan 9, 2025

정말 고생하셨습니다!!!! 몇 가지 궁금한 점이 있는데요, WhiteboardObjectRegisters의 동작 방식이 기존의 WhiteboardObjectSet과 유사하다고 느꼈습니다. 이제 저희 Airplain이 겪고 있던 동시성 문제를 해결할 수 있었다고 하셨는데, WhiteboardObjectSetWhiteboardObjectRegisters로 대체되는 것일까요? (물론 이 부분은 아직 WhiteboardObjectRegisters를 실제 코드에서 사용하는 부분이 없어 헷갈리는 것 같긴 합니다) LWWRegister 자체를 struct로 설계한 부분은 정말 좋다고 생각합니다. 혹시 이 부분은 데이터의 불변성을 고려하신 것인지 궁금합니다. (동시성 문제를 줄이고 안정성을 높이기 위한!!) 만약 불변성을 염두에 두셨다면, struct 내부에 있는 레퍼런스 타입(whiteboardObject)의 내부 상태 변화에 대해서도 고려하신건지 궁급합니다!

WhiteboardObjectRegisters가 기존의 WhiteboardObjectSet을 대체하는 것인지?

맞습니다. 크게 변한 부분은 없이 LWWRegisterSet을 갖고 수정하도록 했습니다.
실제로 바로 사용할 수 있도록 하기 위해 프로토콜(인터페이스)을 비슷한 형태로 설계하느라 거의 변화가 없어 보이는데요, 이후에 리팩토링 과정과 함께 네트워크에 연결하면서 수정될 부분들이 꽤 있을 것으로 판단합니다.

struct로 구현 했지만 내부 프로퍼티인 WhiteboardObject에 대한 상태 변화

제 일일 개발회고 가장 아래쪽 제목을 보면 어떻게 데이터 불변성과 함께 동시성 문제를 고려했는지 확인하실 수 있습니다.
간단히 적어보자면 데이터 불변성을 어디까지로 볼 것인가에 대해서 생각해 볼 필요가 있을 것 같습니다.
걱정하시는 바와 같이 WhiteboardObject 내부를 변경한다면 WhiteboardObject에 대한 데이터 불변성이 깨질 수 있습니다.
다만 그 점을 고려해 기각각의 WhiteboardObject를 관리하는 LWWRegister를 값으로 사용하고, Registers를 통해서 변경에 대한 적용과 반응을 하게 하여, LWWRegister의 프로퍼티 값 자체의 데이터 불변성을 지키고 있다고 판단하였습니다.

+
이들을 고민하면서 whiteboardObject를 actor 또는 struct로 변경해 보는 것에 대한 고민도 많이 해보게 되었습니다.

  • 현재 whiteboardObject의 프로퍼티들을 접근제어자(private)으로 감춰주고 있지만, 내부 프로퍼티를 변경할 수 있는 메소드들을 둠으로써 어느정도 변경이 가능합니다.
  • whiteboardObject에 대한 접근에 대해 계속해서 이야기가 나오고 있습니다.
    • 동시성문제
    • 불변성등

@taipaise
Copy link
Collaborator

걱정하시는 바와 같이 WhiteboardObject 내부를 변경한다면 WhiteboardObject에 대한 데이터 불변성이 깨질 수 있습니다.
다만 그 점을 고려해 기각각의 WhiteboardObject를 관리하는 LWWRegister를 값으로 사용하고, Registers를 통해서 변경에 대한 적용과 반응을 하게 하여, LWWRegister의 프로퍼티 값 자체의 데이터 불변성을 지키고 있다고 판단하였습니다.

답변 감사합니다! 다만 LWWRegister 자체가 값 타입이더라도, 내부 프로퍼티가 class로 존재하는 것이 조금 우려됩니다.
도메인 모듈 안이라면 WhiteboardObjectRegisters 외부에서 여전히 whiteboardObject의 setter 메서드를 통해 whiteboardObject를 동시 접근하여 수정할 수 있기 때문입니다. 이를 해결하기 위해, whiteboardObject에 대한 수정은 whiteboardObjectSet안에서만 진행하고, whiteboardObject를 set외부로 꺼낼 때는 복사본을 전달하는 방식으로 동시성을 해결하고자 했던 것으로 기억합니다. 하지만 현재 WhiteboardObjectRegisters 로직에서는 그런 부분이 보이지 않는데, 이 부분은 어떻게 구현이 되는 것일까요?

조금 더 자세히 예를 들면 아래와 같은 상황이 있을 것 같습니다.
'WH'라는 화이트 오브젝트를 가지고 있는 레지스터 A, B가 있다 가정하겠습니다. 두 레지스터 모두 값 타입이지만, 내부 프로퍼티로 가지고 있는 화이트보드는 레퍼런스 타입입니다. 따라서 A, B 레지스터 모두 같은 화이트보드 레퍼런스를 가지고 있습니다. 만약 두 개의 스레드에서 각각 A, B 레지스터 내부의 'WH' 오브젝트를 수정하고자 하면, 데이터 레이스 현상이 있을 수 있지 않을까?? 합니다

@eemdeeks
Copy link
Member Author

eemdeeks commented Jan 10, 2025

조금 더 자세히 예를 들면 아래와 같은 상황이 있을 것 같습니다. 'WH'라는 화이트 오브젝트를 가지고 있는 레지스터 A, B가 있다 가정하겠습니다. 두 레지스터 모두 값 타입이지만, 내부 프로퍼티로 가지고 있는 화이트보드는 레퍼런스 타입입니다. 따라서 A, B 레지스터 모두 같은 화이트보드 레퍼런스를 가지고 있습니다. 만약 두 개의 스레드에서 각각 A, B 레지스터 내부의 'WH' 오브젝트를 수정하고자 하면, 데이터 레이스 현상이 있을 수 있지 않을까?? 합니다

  • 같은 오브젝트를 다른 레지스터가 갖고있는 상태에서 다른 쓰레드에서 동시 접근하는 경우에 대해서 생각해보면 좋을 것 같습니다.
    다른 레지스터가 같은 화이트보드오브젝트를 갖고있는 상태는 찾지 못해서 경우를 알려주시면 감사하겠습니다!

이에 더해서 고려하고 계신 부분인 화이트보드오브젝트가 레퍼런스 타입이라 동시 접근이 가능할 수도 있다 라는 경우를 생각해 봤을 때는,
말씀하신 대로 여러 쓰레드에서 접근시(ex. 화이트보드 오브젝트 수정을 다른 태스크에서 동시에 할 경우)에 대해서는 화이트보드오브젝트가 class인 이상, 그리고 지금 상황에서는 deepCopy형태를 가져가야 할 것 같습니다!

이부분에 대해서 이 후 리팩토링과 LWW 적용 단계에서 더 수정할 계획이긴합니다!

@eemdeeks
Copy link
Member Author

@taipaise
whiteboardObject에 대한 deepcopy 추가하여 수정 했습니다!!

Copy link
Collaborator

@choijungp choijungp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아직 .... 액터에 대한 공부가 많이 필요하지만 ....
덕분에 LWW 알고리즘에 대해서 알 수 있었슴니다 !!! !!

굿쟙 C팀 !!!!!!!! 어푸 어푸 고생하셨습니다 !! 👍🏻

Copy link
Collaborator

@taipaise taipaise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다!!!!! 피드백 감사합니다 :) 리팩까지 파이팅!!

@eemdeeks eemdeeks merged commit 0b7ad66 into develop Jan 13, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 화이트보드 오브젝트의 실시간 데이터 일관성 보장

5 participants