Skip to content

[소켓통신] Any Type과의 싸움

김성훈 edited this page Dec 13, 2023 · 1 revision

소켓 통신 Any Type 파싱

오리 서비스에서 체크리스트 동시편집 을 위해 iOS는 웹 소켓으로 서버와 통신을 진행 했습니다.

서버와 본격적인 구현에 앞서서 iOS 측은 다음과 같은 요구를 했습니다

  • iOS - "JSON 데이터 타입을 지정해주세요!!"
  • BE - "저희는 데이터 타입 그냥 Any 로 해서 보내는데요?"

iOS의 요청은 JSON 패킷 데이터 타입을 바이너리 데이터 로 지정해 달라는 요청이었습니다. 반면 서버가 이해한 것은 조금 달랐습니다

2023-12-14_01-18-45

소통의 오류로 인해 iOS의 고통은 이때부터 시작이었습니다.

서버 측에서 보내주는 JSON 내부의 Any 타입은 파싱하는데에 굉장히 까다로웠습니다.

struct CRDTResponseDTO: Decodable {
    let event: Event
    let data: [Any]
}

기존에는 이런식으로 [Any] 타입으로 선언해두고 다음과 같은 코드로 경우에 따라 파싱을 했어야 했습니다.

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    self.event = try container.decode(Event.self, forKey: .event)

    if let message = try? container.decode(CRDTMessageResponseDTO.self, forKey: .data) {
        self.data = [message]
    } else if let messages = try? container.decode([CRDTMessageResponseDTO].self, forKey: .data) {
        self.data = messages
    } else {
        self.data = []
    }
}

여기에 Socket에 대한 다양한 이벤트 처리를 해야했습니다

  • 양방향 소켓통신 중 로컬 사용자의 CRDT 문서작성(event: Send)
  • 양방향 소켓통신 중 다른 사용자의 CRDT 문서작성(event: Listen)
  • 사용자가 중간에 소켓통신에 참가할 때 CRDT 전체 전송(event: History)

이렇게 이벤트에 따라 생기는 다양한 데이터 타입들이 발생했습니다

struct CRDTRequestDTO: Encodable {}                // 글자 하나에 대한 요청
struct CRDTDocumentRequestDTO: Encodable {}        // TextField 하나에 대한 요청
struct CRDTMessageRequestDTO: Encodable {}         // 전체 History를 보내는 요청
struct CRDTCheckListToggleRequestDTO:Encodable {}  // 체크리스트 체크 이벤트 요청

struct CRDTResponseDTO: Encodable {}                // 글자 하나에 대한 응답
struct CRDTDocumentResponseDTO: Encodable {}        // TextField 하나에 대한 응답
struct CRDTMessageResponseDTO: Encodable {}         // 전체 History를 보내는 응답
struct CRDTCheckListToggleResponseDTO:Encodable {}  // 체크리스트 체크 이벤트 응답

CRDT 관련 이벤트가 늘어 남에 따라 데이터를 처리하는 것이 어려웠고 다음과 같이 추상화를 진행했습니다

protocol CRDTData {
    var id: UUID { get }
    var number: Int { get }
}

그리고 기존에 CRDTRequestDTO, CRDTResponseDTO가 가지고 있던 data 타입을 CRDTData 타입으로 추상화 했습니다.

let data: [Any]        // 기존

let data: [CRDTData]   // 추상화 이후

이렇게 추상화를 진행한뒤 다른 CRDT 관련 Response 데이터 타입들이 CRDTData 프로토콜을 채택하게 함으로써 CRDTResponseDTO 한곳에서 파싱을 진행할 수 있었습니다.

물론 해당 코드 부분이 어지럽기는 합니다. Any Type으로 오다 보니 어쩔 수 없더군요

작성자는 소켓 프로그래밍도 처음이고 이렇게 복잡한 타입의 데이터 파싱도 처음인데 팀원들과 함께 추상화를 고민하며 해결할 수 있었던 좋은 경험이었습니다. 또한 BE 캠퍼들과 조금 더 소통이 원활했다라고 한다면 수월하지 않았을까 생각이 들며 소통의 중요성을 깨달았습니다!

오리들의 애자일한 개발 여정

📜 기획

💢 규칙

🐥 1주차 회의록, 회고

데일리 스크럼

회의록

회고

🐥 2주차 회의록, 회고

데일리 스크럼

회의록

회고

🐥 3주차 회의록, 회고

데일리 스크럼

회고

🐥 4주차 회의록, 회고

데일리 스크럼

회고

🐥 5주차 회의록, 회고

데일리 스크럼

회고

🐥 6주차 회의록, 회고

데일리 스크럼

회고

🍎 iOS

아키텍처 의사 결정 기록

Clone this wiki locally