diff --git a/SodaLive/Sources/Live/LiveApi.swift b/SodaLive/Sources/Live/LiveApi.swift
index a933c3f..b973fe0 100644
--- a/SodaLive/Sources/Live/LiveApi.swift
+++ b/SodaLive/Sources/Live/LiveApi.swift
@@ -37,6 +37,8 @@ enum LiveApi {
     case deleteDonationMessage(roomId: Int, messageUUID: String)
     case getUserProfile(roomId: Int, userId: Int)
     case getAllMenuPreset(creatorId: Int)
+    case likeHeart(request: LiveRoomLikeHeartRequest)
+    case getTotalHeartCount(roomId: Int)
 }
 
 extension LiveApi: TargetType {
@@ -129,15 +131,21 @@ extension LiveApi: TargetType {
             
         case .getAllMenuPreset:
             return "/live/room/menu/all"
+            
+        case .likeHeart:
+            return "/live/room/like-heart"
+            
+        case .getTotalHeartCount(let roomId):
+            return "/live/room/\(roomId)/heart-total"
         }
     }
     
     var method: Moya.Method {
         switch self {
-        case .roomList, .recentVisitRoomUsers, .getReservations, .getReservation, .getRoomDetail, .getTags, .getRecentRoomInfo, .getRoomInfo, .donationStatus, .donationTotal, .getDonationMessageList, .getUserProfile, .getAllMenuPreset:
+        case .roomList, .recentVisitRoomUsers, .getReservations, .getReservation, .getRoomDetail, .getTags, .getRecentRoomInfo, .getRoomInfo, .donationStatus, .donationTotal, .getDonationMessageList, .getUserProfile, .getAllMenuPreset, .getTotalHeartCount:
             return .get
             
-        case .makeReservation, .enterRoom, .createRoom, .quitRoom, .donation, .refundDonation, .kickOut:
+        case .makeReservation, .enterRoom, .createRoom, .quitRoom, .donation, .refundDonation, .kickOut, .likeHeart:
             return .post
             
         case .setListener, .setSpeaker, .setManager, .cancelReservation, .startLive, .cancelRoom, .editLiveRoomInfo:
@@ -166,7 +174,7 @@ extension LiveApi: TargetType {
                 parameters: parameters,
                 encoding: URLEncoding.queryString)
             
-        case .recentVisitRoomUsers, .getTags, .getRecentRoomInfo, .getRoomInfo, .refundDonation, .donationStatus, .donationTotal, .getUserProfile:
+        case .recentVisitRoomUsers, .getTags, .getRecentRoomInfo, .getRoomInfo, .refundDonation, .donationStatus, .donationTotal, .getUserProfile, .getTotalHeartCount:
             return .requestPlain
             
         case .getReservations(let isActive):
@@ -233,6 +241,9 @@ extension LiveApi: TargetType {
             
         case .getAllMenuPreset(let creatorId):
             return .requestParameters(parameters: ["creatorId" : creatorId], encoding: URLEncoding.queryString)
+            
+        case .likeHeart(let request):
+            return .requestJSONEncodable(request)
         }
     }
     
diff --git a/SodaLive/Sources/Live/LiveRepository.swift b/SodaLive/Sources/Live/LiveRepository.swift
index 42f8fc2..9ed713e 100644
--- a/SodaLive/Sources/Live/LiveRepository.swift
+++ b/SodaLive/Sources/Live/LiveRepository.swift
@@ -120,4 +120,12 @@ final class LiveRepository {
     func getAllMenuPreset(creatorId: Int) -> AnyPublisher<Response, MoyaError> {
         return api.requestPublisher(.getAllMenuPreset(creatorId: creatorId))
     }
+    
+    func likeHeart(roomId: Int) -> AnyPublisher<Response, MoyaError> {
+        return api.requestPublisher(.likeHeart(request: LiveRoomLikeHeartRequest(roomId: roomId)))
+    }
+    
+    func getTotalHeartCount(roomId: Int) -> AnyPublisher<Response, MoyaError> {
+        return api.requestPublisher(.getTotalHeartCount(roomId: roomId))
+    }
 }
diff --git a/SodaLive/Sources/Live/Room/Chat/LiveRoomChat.swift b/SodaLive/Sources/Live/Room/Chat/LiveRoomChat.swift
index 8af0bcc..f775496 100644
--- a/SodaLive/Sources/Live/Room/Chat/LiveRoomChat.swift
+++ b/SodaLive/Sources/Live/Room/Chat/LiveRoomChat.swift
@@ -8,7 +8,7 @@
 import Foundation
 
 enum LiveRoomChatType: String {
-    case CHAT, DONATION, JOIN, ROULETTE_DONATION
+    case CHAT, DONATION, JOIN, ROULETTE_DONATION, HEART
 }
 
 protocol LiveRoomChat {
@@ -48,3 +48,9 @@ struct LiveRoomJoinChat: LiveRoomChat {
     
     var type: LiveRoomChatType = .JOIN
 }
+
+struct LiveRoomHeartDonationChat: LiveRoomChat {
+    let nickname: String
+    
+    var type: LiveRoomChatType = .HEART
+}
diff --git a/SodaLive/Sources/Live/Room/Chat/LiveRoomChatRawMessage.swift b/SodaLive/Sources/Live/Room/Chat/LiveRoomChatRawMessage.swift
index cb6679a..d7f2e1f 100644
--- a/SodaLive/Sources/Live/Room/Chat/LiveRoomChatRawMessage.swift
+++ b/SodaLive/Sources/Live/Room/Chat/LiveRoomChatRawMessage.swift
@@ -9,7 +9,7 @@ import Foundation
 
 struct LiveRoomChatRawMessage: Codable {
     enum LiveRoomChatRawMessageType: String, Codable {
-        case DONATION, SECRET_DONATION, EDIT_ROOM_INFO, SET_MANAGER, TOGGLE_ROULETTE, ROULETTE_DONATION
+        case DONATION, SECRET_DONATION, EDIT_ROOM_INFO, SET_MANAGER, TOGGLE_ROULETTE, ROULETTE_DONATION, HEART_DONATION
     }
     
     let type: LiveRoomChatRawMessageType
diff --git a/SodaLive/Sources/Live/Room/Chat/LiveRoomHeartDonationChatItemView.swift b/SodaLive/Sources/Live/Room/Chat/LiveRoomHeartDonationChatItemView.swift
new file mode 100644
index 0000000..0bb3936
--- /dev/null
+++ b/SodaLive/Sources/Live/Room/Chat/LiveRoomHeartDonationChatItemView.swift
@@ -0,0 +1,38 @@
+//
+//  LiveRoomHeartDonationChatItemView.swift
+//  SodaLive
+//
+//  Created by klaus on 10/24/24.
+//
+
+import SwiftUI
+
+struct LiveRoomHeartDonationChatItemView: View {
+    
+    let chatMessage: LiveRoomHeartDonationChat
+    
+    var body: some View {
+        HStack(spacing: 0) {
+            Text("'")
+                .font(.system(size: 12))
+                .foregroundColor(Color.gray11)
+            
+            Text(chatMessage.nickname)
+                .font(.system(size: 12, weight: .bold))
+                .foregroundColor(Color(hex: "ec3aa6"))
+            
+            Text("'님이 마음을 전했습니다 : 💕")
+                .font(.system(size: 12))
+                .foregroundColor(Color.gray11)
+        }
+        .padding(.vertical, 6.7)
+        .frame(width: screenSize().width - 86)
+        .background(Color.white.opacity(0.7))
+        .cornerRadius(4.7)
+        .padding(.leading, 20)
+    }
+}
+
+#Preview {
+    LiveRoomHeartDonationChatItemView(chatMessage: LiveRoomHeartDonationChat(nickname: "닉네임"))
+}
diff --git a/SodaLive/Sources/Live/Room/LiveRoomViewModel.swift b/SodaLive/Sources/Live/Room/LiveRoomViewModel.swift
index 1536de5..a2d88d2 100644
--- a/SodaLive/Sources/Live/Room/LiveRoomViewModel.swift
+++ b/SodaLive/Sources/Live/Room/LiveRoomViewModel.swift
@@ -118,6 +118,7 @@ final class LiveRoomViewModel: NSObject, ObservableObject {
     }
     
     @Published var totalDonationCan = 0
+    @Published var totalHeartCount = 0
     @Published var donationMessageList = [LiveRoomDonationMessage]()
     @Published var donationMessageCount = 0
     
@@ -361,6 +362,7 @@ final class LiveRoomViewModel: NSObject, ObservableObject {
                         )
                         
                         getTotalDonationCan()
+                        getTotalHeartCount()
                         
                         if data.isAdult && !UserDefaults.bool(forKey: .auth) {
                             changeIsAdult = true
@@ -1133,6 +1135,32 @@ final class LiveRoomViewModel: NSObject, ObservableObject {
         }
     }
     
+    private func getTotalHeartCount() {
+        repository.getTotalHeartCount(roomId: AppState.shared.roomId)
+            .sink { result in
+                switch result {
+                case .finished:
+                    DEBUG_LOG("finish")
+                case .failure(let error):
+                    ERROR_LOG(error.localizedDescription)
+                }
+            } receiveValue: { [unowned self] response in
+                self.isLoading = false
+                let responseData = response.data
+                
+                do {
+                    let jsonDecoder = JSONDecoder()
+                    let decoded = try jsonDecoder.decode(ApiResponse<GetLiveRoomHeartTotalResponse>.self, from: responseData)
+                    
+                    if let data = decoded.data, decoded.success {
+                        self.totalHeartCount = data.totalHeartCount
+                    }
+                } catch {
+                }
+            }
+            .store(in: &subscription)
+    }
+    
     func getTotalDonationCan() {
         repository.getTotalDoantionCan(roomId: AppState.shared.roomId)
             .sink { result in
@@ -1821,11 +1849,61 @@ final class LiveRoomViewModel: NSObject, ObservableObject {
         if isAvailableLikeHeart {
             if !isLoadingLikeHeart {
                 isLoadingLikeHeart = true
-                addHeart()
                 
-                DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { [unowned self] in
-                    self.isLoadingLikeHeart = false
-                }
+                repository.likeHeart(roomId: AppState.shared.roomId)
+                    .sink { result in
+                        switch result {
+                        case .finished:
+                            DEBUG_LOG("finish")
+                        case .failure(let error):
+                            ERROR_LOG(error.localizedDescription)
+                        }
+                    } receiveValue: { [unowned self] response in
+                        self.isLoadingLikeHeart = false
+                        let responseData = response.data
+                        
+                        do {
+                            let jsonDecoder = JSONDecoder()
+                            let decoded = try jsonDecoder.decode(ApiResponseWithoutData.self, from: responseData)
+                            
+                            if decoded.success {
+                                UserDefaults.set(UserDefaults.int(forKey: .can) - 1, forKey: .can)
+                                
+                                let donationRawMessage = LiveRoomChatRawMessage(
+                                    type: .HEART_DONATION,
+                                    message: "",
+                                    can: 1,
+                                    donationMessage: nil
+                                )
+                                
+                                agora.sendRawMessageToGroup(
+                                    rawMessage: donationRawMessage,
+                                    completion: { [unowned self] errorCode in
+                                        if errorCode == .errorOk {
+                                            let (nickname, _) = self.getUserNicknameAndProfileUrl(accountId: UserDefaults.int(forKey: .userId))
+                                            self.messages.append(LiveRoomHeartDonationChat(nickname: nickname))
+                                            
+                                            totalHeartCount += 1
+                                            addHeart()
+                                            
+                                            self.messageChangeFlag.toggle()
+                                            if self.messages.count > 100 {
+                                                self.messages.remove(at: 0)
+                                            }
+                                        } else {
+                                            refundDonation()
+                                        }
+                                    },
+                                    fail: { [unowned self] in
+                                        refundDonation()
+                                    }
+                                )
+                            }
+                        } catch {
+                            refundDonation()
+                        }
+                    }
+                    .store(in: &subscription)
             }
         } else {
             isShowNoticeLikeHeart = true
@@ -2114,6 +2192,10 @@ extension LiveRoomViewModel: AgoraRtmChannelDelegate {
                     self.isActiveRoulette = decoded.isActiveRoulette!
                 } else if decoded.type == .EDIT_ROOM_INFO || decoded.type == .SET_MANAGER {
                     self.getRoomInfo()
+                } else if decoded.type == .HEART_DONATION {
+                    self.messages.append(LiveRoomHeartDonationChat(nickname: nickname))
+                    self.totalHeartCount += decoded.can
+                    self.addHeart()
                 }
             } catch {
             }
diff --git a/SodaLive/Sources/Live/Room/V2/Component/View/LiveRoomChatView.swift b/SodaLive/Sources/Live/Room/V2/Component/View/LiveRoomChatView.swift
index 9b614b6..f70936f 100644
--- a/SodaLive/Sources/Live/Room/V2/Component/View/LiveRoomChatView.swift
+++ b/SodaLive/Sources/Live/Room/V2/Component/View/LiveRoomChatView.swift
@@ -28,6 +28,10 @@ struct LiveRoomChatView: View {
                     let chatMessage = messages[index] as! LiveRoomJoinChat
                     LiveRoomJoinChatItemView(chatMessage: chatMessage)
                     
+                case LiveRoomChatType.HEART:
+                    let chatMessage = messages[index] as! LiveRoomHeartDonationChat
+                    LiveRoomHeartDonationChatItemView(chatMessage: chatMessage)
+                    
                 default:
                     let chatMessage = messages[index] as! LiveRoomNormalChat
                     LiveRoomChatItemView(
diff --git a/SodaLive/Sources/Live/Room/V2/Component/View/LiveRoomInfoGuestView.swift b/SodaLive/Sources/Live/Room/V2/Component/View/LiveRoomInfoGuestView.swift
index 3bd6158..af0cbf7 100644
--- a/SodaLive/Sources/Live/Room/V2/Component/View/LiveRoomInfoGuestView.swift
+++ b/SodaLive/Sources/Live/Room/V2/Component/View/LiveRoomInfoGuestView.swift
@@ -10,6 +10,7 @@ import SwiftUI
 struct LiveRoomInfoGuestView: View {
     
     let title: String
+    let totalHeart: Int
     let totalDonationCan: Int
     
     let isOnBg: Bool
@@ -163,7 +164,23 @@ struct LiveRoomInfoGuestView: View {
                     
                     Spacer()
                     
-                    HStack(spacing: 2.7) {
+                    HStack(spacing: 6.7) {
+                        Image("ic_heart_pink")
+                            .resizable()
+                            .frame(width: 12, height: 12)
+                        
+                        Text("\(totalHeart)")
+                            .font(.custom(Font.medium.rawValue, size: 12))
+                            .foregroundColor(.graybb)
+                    }
+                    .padding(.horizontal, 11)
+                    .padding(.vertical, 5.3)
+                    .overlay(
+                        RoundedRectangle(cornerRadius: 5.3)
+                            .stroke(Color.graybb, lineWidth: 1)
+                    )
+                    
+                    HStack(spacing: 6.7) {
                         Image("ic_can")
                             .resizable()
                             .frame(width: 12, height: 12)
@@ -202,6 +219,7 @@ struct LiveRoomInfoGuestView_Previews: PreviewProvider {
     static var previews: some View {
         LiveRoomInfoGuestView(
             title: "qwer",
+            totalHeart: 1234,
             totalDonationCan: 123456,
             isOnBg: true,
             isOnNotice: false,
diff --git a/SodaLive/Sources/Live/Room/V2/Component/View/LiveRoomInfoHostView.swift b/SodaLive/Sources/Live/Room/V2/Component/View/LiveRoomInfoHostView.swift
index ac8846e..55c2cfb 100644
--- a/SodaLive/Sources/Live/Room/V2/Component/View/LiveRoomInfoHostView.swift
+++ b/SodaLive/Sources/Live/Room/V2/Component/View/LiveRoomInfoHostView.swift
@@ -11,6 +11,7 @@ import Kingfisher
 struct LiveRoomInfoHostView: View {
     
     let title: String
+    let totalHeart: Int
     let totalDonationCan: Int
     let participantsCount: Int
     
@@ -161,7 +162,23 @@ struct LiveRoomInfoHostView: View {
                     
                     Spacer()
                     
-                    HStack(spacing: 2.7) {
+                    HStack(spacing: 6.7) {
+                        Image("ic_heart_pink")
+                            .resizable()
+                            .frame(width: 12, height: 12)
+                        
+                        Text("\(totalHeart)")
+                            .font(.custom(Font.medium.rawValue, size: 12))
+                            .foregroundColor(.graybb)
+                    }
+                    .padding(.horizontal, 11)
+                    .padding(.vertical, 5.3)
+                    .overlay(
+                        RoundedRectangle(cornerRadius: 5.3)
+                            .stroke(Color.graybb, lineWidth: 1)
+                    )
+                    
+                    HStack(spacing: 6.7) {
                         Image("ic_can")
                             .resizable()
                             .frame(width: 12, height: 12)
@@ -217,6 +234,7 @@ struct LiveRoomInfoHostView_Previews: PreviewProvider {
     static var previews: some View {
         LiveRoomInfoHostView(
             title: "오늘의 라이브방송은 OOO입니다.",
+            totalHeart: 1234,
             totalDonationCan: 123456,
             participantsCount: 18,
             isOnBg: true,
diff --git a/SodaLive/Sources/Live/Room/V2/GetLiveRoomHeartTotalResponse.swift b/SodaLive/Sources/Live/Room/V2/GetLiveRoomHeartTotalResponse.swift
new file mode 100644
index 0000000..02202f1
--- /dev/null
+++ b/SodaLive/Sources/Live/Room/V2/GetLiveRoomHeartTotalResponse.swift
@@ -0,0 +1,12 @@
+//
+//  GetLiveRoomHeartTotalResponse.swift
+//  SodaLive
+//
+//  Created by klaus on 10/24/24.
+//
+
+import Foundation
+
+struct GetLiveRoomHeartTotalResponse: Decodable {
+    let totalHeartCount: Int
+}
diff --git a/SodaLive/Sources/Live/Room/V2/LiveRoomLikeHeartRequest.swift b/SodaLive/Sources/Live/Room/V2/LiveRoomLikeHeartRequest.swift
new file mode 100644
index 0000000..df51545
--- /dev/null
+++ b/SodaLive/Sources/Live/Room/V2/LiveRoomLikeHeartRequest.swift
@@ -0,0 +1,11 @@
+//
+//  LiveRoomLikeHeartRequest.swift
+//  SodaLive
+//
+//  Created by klaus on 10/24/24.
+//
+
+struct LiveRoomLikeHeartRequest: Encodable {
+    let roomId: Int
+    let container: String = "ios"
+}
diff --git a/SodaLive/Sources/Live/Room/V2/LiveRoomViewV2.swift b/SodaLive/Sources/Live/Room/V2/LiveRoomViewV2.swift
index d4d49ee..2245a56 100644
--- a/SodaLive/Sources/Live/Room/V2/LiveRoomViewV2.swift
+++ b/SodaLive/Sources/Live/Room/V2/LiveRoomViewV2.swift
@@ -25,6 +25,7 @@ struct LiveRoomViewV2: View {
                     if liveRoomInfo.creatorId == UserDefaults.int(forKey: .userId) {
                         LiveRoomInfoHostView(
                             title: liveRoomInfo.title,
+                            totalHeart: viewModel.totalHeartCount,
                             totalDonationCan: viewModel.totalDonationCan,
                             participantsCount: liveRoomInfo.participantsCount,
                             isOnBg: viewModel.isBgOn,
@@ -75,6 +76,7 @@ struct LiveRoomViewV2: View {
                     } else {
                         LiveRoomInfoGuestView(
                             title: liveRoomInfo.title,
+                            totalHeart: viewModel.totalHeartCount,
                             totalDonationCan: viewModel.totalDonationCan,
                             isOnBg: viewModel.isBgOn,
                             isOnNotice: viewModel.isShowNotice,