Skip to content

ConversationViewModel 메시지 목록을 swift-collections의 OrderedSet<E>로 이행하기 #9

Description

@unstabler

현재 상황

ConversationScreen.swiftConversationViewModel에서 메시지 목록을 [DirectMessage] 배열로 관리하고 있으며, 여러 곳에서 수동으로 중복 체크를 수행하고 있습니다.

문제점

  • 중복 체크가 O(n) 성능 (contains(where:) 사용)
  • 여러 위치에서 중복 체크 로직이 반복됨 (143-147줄, 186-189줄 등)
  • WebSocket 재연결 시 놓친 메시지 처리가 복잡함

제안 사항

swift-collectionsOrderedSet<DirectMessage>를 사용하여 메시지 목록을 관리

장점

  1. 자동 중복 제거: OrderedSet이 중복을 자동으로 처리
  2. 성능 개선: O(1) contains 체크
  3. 코드 단순화: 중복 체크 로직 제거 가능

구현 방향

@Published private var messages = OrderedSet<DirectMessage>()

중요 고려사항

  1. UUIDv7 활용: 현재 메시지 ID가 UUIDv7이므로 ID 기반 정렬이 곧 시간순 정렬
  2. Hashable 구현: DirectMessageHashable로 만들어야 함 (ID 기반)
  3. 정렬 전략:
    • 옵션 1: 삽입 후 전체 정렬 (간단하지만 O(n log n))
    • 옵션 2: 이진 탐색으로 적절한 위치에 삽입 (O(log n))

이진 탐색 삽입 예제 코드

extension OrderedSet where Element == DirectMessage {
    mutating func insertSorted(_ message: DirectMessage) {
        // 이미 있으면 무시 (중복 제거)
        guard \!contains(message) else { return }
        
        // 이진 탐색으로 적절한 위치 찾기
        let index = firstIndex { $0.id.uuidString > message.id.uuidString } ?? endIndex
        insert(message, at: index)
    }
    
    mutating func insertSortedBatch(_ messages: [DirectMessage]) {
        for message in messages {
            insertSorted(message)
        }
    }
}

// 사용 예시
class ConversationViewModel: ObservableObject {
    @Published private var messageSet = OrderedSet<DirectMessage>()
    
    var messages: [DirectMessage] {
        Array(messageSet)
    }
    
    // WebSocket으로 새 메시지 받을 때
    private func handleNewMessage(_ message: DirectMessage) {
        messageSet.insertSorted(message)
    }
    
    // 놓친 메시지들 가져올 때
    private func fetchMissedMessages(since date: Date) async {
        // ... API 호출 ...
        let newMessages = // ... 
        messageSet.insertSortedBatch(newMessages)
    }
}

영향받는 코드

  • 메시지 추가 로직 (WebSocket, API 응답)
  • 중복 체크 로직 제거
  • loadMessages(), loadPreviousMessages(), fetchMissedMessages() 메서드

참고

데이팅 앱 특성상 대화당 메시지 수가 많지 않을 것으로 예상되므로, 성능 최적화보다는 코드 간결성에 중점을 둬도 무방할 것으로 판단됩니다.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions