Firebase RealtimeDatabase 내 데이터 저장하기

오늘은 앱 내 다양한 라이브러리를 바탕으로 생체데이터, 생활 데이터 등 이용자의 데이터를 수집하고 해당 데이터를 저장하기 위해 firebase에 데이터를 저장하는 방식에 대해서 알아보려고 한다.

 

이전에 다룬적이 있으니 SPM을 통해 firebase 를 추가하고 firebase에서 콘솔에 프로젝트를 추가해 GoogleService-Info.plist를 추가하는 과정은 생략하고 진행해보자 ㅎㅎ 이미 많이 해봤으니까!

 

firebase 중 realtimeDatabase에 데이터를 저장하는 과정을 기록해보려고 한다.

 

먼저 Firebase 데이터 베이스에 접근하기 위해 Database 참조를 생성해 담아주어야 한다.

private let realtimeDatabase = Database.database().reference()

이런 방식을 통해 루트 참조를 생성하고 클래스의 초기화 과정에서 이를 생성해 어디서든 사용할 수 있도록 구현할 수도 있다.

 

그런 다음 저장할 데이터의 구조를 먼저 정의해야 데이터를 넣을 수 있기 때문에 데이터 모델을 먼저 생성한다. 해당 예시는 이용자의 음성을 기록할 수 있는 로직을 기준으로 작성했다.

struct TelephonySpeechMetricsDataPoint: Identifiable, Encodable {
    var id = UUID()
    let timestamp: Int64
    let confidence: Double
    let mood: Double
    let valence: Double
    let activation: Double
    let dominance: Double
    let audioLevel: Double?
    let speechRecognitionResult: String?
}

그 다음 데이터를 Firebase Realtime Database에 저장할 때 특정 경로로 저장할 수 있게 참조를 만들고 데이터를 설정해줄 수 있다.

 

경로를 한번 지정해보자 특정 경로로 데이터를 저장하기 위해서 realtimeDatabase.child() 메서드를 활용해 경로를 원하는 곳에 설정해 저장할 수 있다. pinNumber와 deviceModel을 구분을 해줘야 하는 상황이기 때문에 트리 구조로 iOS → pinNumber → deviceModel → SpeechMetricsData 이런 방식으로 데이터를 구분해 넣어줄 예정이다.

 

이 과정을 코드로 작성하면

let speechDataRef = realtimeDatabase.child("iOS").child(pinNumber).child(deviceModel).child("TelephonySpeechMetricsData")

이렇게 child를 넣어 간단하게 설정할 수 있다. firebase가 많이 쓰이는 이유를 좀 알겠다.. 뭔가 처음 사용을해도 굉장히 쉽고 간편하게 사용할 수 있다는 점이 아주 장점인 것 같다.

 

그리고 데이터를 저장할 때 아무래도 중복된 데이터는 저장되지 않는게 좋기 때문에 firebase 내 저장된 데이터와 이제 저장할 데이터가 중복인지 여부를 판단해 새로운 데이터만 들어갈 수 있도록 구현할 예정이다.

 

이렇게 구현하기 위해서 사용한 방식은 queryOrdered(byChild:)이다 이 메서드를 활용하면 지정한 childKey의 값을 기준으로 해당 데이터의 자식 노드들을 정렬해 검색할 수 있도록 한다.

 

즉, 특정 키를 기준으로 데이터 검색 후 데이터 중복 확인해 필터링 된 결과에서 최소값 또는 최대값을 기준으로 데이터를 제한한다.

speechDataRef.queryOrdered(byChild: "timestamp").queryEqual(toValue: speechData.timestamp).observeSingleEvent(of: .value) { snapshot in
    if snapshot.exists() {
        print("중복된 데이터가 이미 저장되어 있습니다.")
    } else {
        // 고유 ID 생성 후 데이터 삽입
        let newSpeechDataRef = speechDataRef.childByAutoId()
        
        // 저장할 데이터를 딕셔너리 형태로 준비
        let dataToUpload: [String: Any] = [
            "timestamp": speechData.timestamp,
            "confidence": speechData.confidence,
            "mood": speechData.mood,
            "valence": speechData.valence,
            "activation": speechData.activation,
            "dominance": speechData.dominance,
            "audioLevel": speechData.audioLevel ?? "
        ]
        
        // 데이터베이스에 데이터 삽입
        newSpeechDataRef.setValue(dataToUpload) { error, _ in
            if let error = error {
                print("데이터 업로드 실패: \\(error.localizedDescription)")
            } else {
                print("데이터 업로드 성공")
            }
        }
    }
}

상기 내용을 바탕으로 데이터를 저장할때 queryOrdered(byChild:) 를 활용해 timestamp 값을 정렬해 동일한 timestamp의 값은 데이터 저장을 하지 않고 새로운 값만 들어오도록 구현하였다.

 

데이터를 저장할 때 Key:Value 타입으로 지정한 뒤 저장하고 싶은 명칭과 저장할 데이터를 지정해주면 아주 쉽게 firebase 저장 구현이 완료된다.

 

dataToUpload 배열에 데이터가 들어가고 해당 데이터는 setValue를 통해 데이터가 저장되게 된다.

그럼 firebase realtimeDatabase에 데이터가 이렇게 잘 저장되게 된다!!

 

오늘은 여기까지!!!!