[iOS/SwiftUI] SwiftUI 에서 SocketiO 사용하기 (1)
SwiftUI와 Socket.io를 활용한 실시간 채팅 앱 구현하기
빅데이터, 웹, 모바일에서 실시간 통신의 중요성이 높아지면서 Socket 통신을 활용한 채팅 기능이 각광받고 있습니다. 이번 포스팅에서는 SwiftUI와 Socket.io를 활용하여 실시간 채팅 앱의 ChatViewModel
을 어떻게 구성하고 사용하는지 알아보겠습니다.
1. 준비물
- Swift 프로젝트
- SocketIO 및 Alamofire 라이브러리 설치
alamofire와 Socket.io Swift Package Manager로 설치하기
1. 의존성 추가
- 상단 메뉴에서 File > Swift Packages > Add Package Dependency를 선택합니다.
- 패키지 저장소 URL을 입력하는 창이 표시됩니다. Alamofire의 경우:
https://github.com/Alamofire/Alamofire.git
를 입력하고 Next 버튼을 클릭합니다.
- 원하는 버전을 선택하고 Next를 클릭하여 설치를 진행합니다.
- Alamofire 설치가 완료되면 같은 방법으로 Socket.io를 추가합니다. Socket.io의 경우 저장소 URL은:
https://github.com/socketio/socket.io-client-swift.git
를 입력합니다.
- 원하는 버전을 선택하고 Next를 클릭하여 설치를 진행합니다.
2. 프로젝트에 의존성 적용
설치가 완료되면, 소스 코드 파일 내에서 아래와 같이 import 구문을 사용하여 라이브러리를 프로젝트에 추가합니다.
import Alamofire import SocketIO
2. 변수 설명
- messages
@Published var messages = [ChatMessage]()
설명: 사용자와 상대방의 채팅 메시지 목록을 저장하는 배열입니다.
타입: ChatMessage 타입의 배열.
@Published 속성은 ObservableObject 프로토콜의 일부로, 해당 변수가 변경될 때마다 SwiftUI 뷰에게 알려주어 뷰를 다시 그리게 합니다.
- error
@Published var error: Error? = nil
설명: Socket 통신이나 다른 작업 중 발생하는 에러를 저장하는 변수입니다.
타입: Error 타입 (옵셔널). 초기 값으로 nil이 설정되어 있습니다.
이 역시 @Published 속성을 사용하여 에러가 발생하면 해당 정보를 SwiftUI 뷰에게 알릴 수 있습니다.
- receivedAlert
@Published var receivedAlert: Bool = false
설명: 새로운 알림이 도착했는지 여부를 나타내는 불린 변수입니다.
타입: Bool
@Published 속성을 통해 알림의 유무에 따라 SwiftUI 뷰의 상태를 업데이트 할 수 있습니다.
- receivedNoti
@Published var receivedNoti: Bool = false
설명: 새로운 푸시 알림이나 기타 알림이 도착했는지 여부를 나타내는 불린 변수입니다.
타입: Bool
마찬가지로 @Published 속성을 사용해 알림 상태에 따른 뷰 업데이트가 가능합니다.
기타 변수
private let refreshTokenManager = RefreshTokenManager.shared
private let baseUrl = SHAREVAR.BASEURL
private var cancellables = Set<AnyCancellable>()
private var manager: SocketManager?
var socket: SocketIOClient?
refreshTokenManager: 토큰 갱신을 관리하는 객체.
baseUrl: 기본 URL 주소. 서버와의 통신에 사용됩니다.
cancellables: Combine 프레임워크와 관련된 리소스 해제를 관리하는 변수.
manager: Socket.io 연결을 관리하는 객체.
socket: Socket.io 클라이언트 객체로, 실제 소켓 통신 작업을 수행합니다.
각 변수는 뷰모델 내에서 소켓 통신과 채팅 기능을 구현하는데 필요한 핵심 요소들입니다. 이를 바탕으로 사용자 인터페이스와 통합하여 실시간 채팅 앱을 완성할 수 있습니다.
3. Socket.io 이벤트 핸들러 소개
Socket.io를 사용하여 실시간 통신을 구현할 때, 서버와 클라이언트 간에 발생하는 여러 이벤트들을 핸들링할 필요가 있습니다. ChatViewModel
에서는 다음과 같은 이벤트 핸들러들을 정의하고 있습니다.
Socket.io에서 on
이벤트의 중요성
Socket.io
의 on
메소드를 사용하여 이벤트 핸들러를 설정할 때, 해당 이벤트 이름 (예: "join", "leave" 등)은 서버와 클라이언트 모두에서 동일하게 정의되어야 합니다.
예를 들어, 클라이언트에서 socket.on("messageReceived")
라는 이벤트 핸들러를 설정했다면, 서버에서도 "messageReceived"라는 이름의 이벤트를 발송해야 합니다. 그렇지 않으면 클라이언트에서는 해당 이벤트를 감지할 수 없습니다.
중요 포인트:
- 동일한 이벤트 이름: 서버와 클라이언트 사이에서 사용되는 이벤트 이름은 항상 동일해야 합니다.
- 이벤트 정의의 중요성: 클라이언트에서 임의로
on
이벤트를 설정하더라도, 해당 이벤트는 서버에서 명시적으로 발송되지 않는 한 실제로 발생하지 않습니다. - 백엔드 개발자와의 협업: 이벤트의 정의와 사용은 클라이언트와 서버 개발자 간의 철저한 협업이 필요합니다. 이벤트 이름, 데이터 형식, 발생 시점 등의 세부 사항에 대해 논의하고 합의해야 합니다.
따라서, Socket.io
를 사용할 때는 백엔드 개발자와 긴밀하게 소통하며 이벤트의 이름, 데이터 구조, 발생 시점 등을 명확히 정의하고 동기화하는 것이 중요합니다.
1. join
self.socket?.on("join") { data, ack in
// ...
}
- 설명: 사용자가 채팅방에 참여할 때 발생하는 이벤트입니다.
- 작업: 사용자의 참여를 인지하고, 필요한 UI 업데이트나 알림 처리 등의 작업을 수행합니다.
2. redDot
self.socket?.on("redDot") { data, ack in
// ...
}
- 설명: 새로운 알림이 도착했을 때 발생하는 이벤트입니다.
- 작업: 알림의 도착을 사용자에게 알려주거나, 알림과 관련된 UI 업데이트를 수행합니다.
3. receive
self.socket?.on("receive") { data, ack in
// ...
}
- 설명: 채팅 메시지가 도착했을 때 발생하는 이벤트입니다.
- 작업: 도착한 메시지를 채팅 UI에 표시하고, 필요한 알림이나 푸시를 사용자에게 전달합니다.
4. exit
self.socket?.on("exit") { data, ack in
// ...
}
- 설명: 사용자가 채팅방에서 나갈 때 발생하는 이벤트입니다.
- 작업: 사용자의 퇴장을 처리하고, 관련 UI 업데이트나 알림을 수행합니다.
5. noti
self.socket?.on("noti") { data, ack in
// ...
}
- 설명: 특별한 알림이나 푸시가 도착했을 때 발생하는 이벤트입니다.
- 작업: 해당 알림을 처리하고, 필요한 UI 업데이트나 푸시를 사용자에게 전달합니다.
6. error
self.socket?.on("error") { data, ack in
// ...
}
- 설명: 소켓 통신 중 에러가 발생했을 때의 이벤트입니다.
- 작업: 에러를 처리하고, 사용자에게 적절한 메시지나 알림을 전달합니다.
7. leave
self.socket?.on("leave") { data, ack in
// ...
}
- 설명: 다른 사용자가 채팅방에서 나갔을 때 발생하는 이벤트입니다.
- 작업: 해당 사용자의 퇴장을 인지하고, 필요한 UI 업데이트나 알림을 수행합니다.