Flutter 개발
Flutter 메신저 업그레이드: 메시지 버블, 시간, 닉네임 추가 방법 (코드 변경점 자세히 설명)
withmilk
2025. 4. 27. 17:19
Flutter와 Firebase로 간단한 메신저 앱을 만들었다면, 이제 진짜 메신저처럼 멋지게 업그레이드해볼 차례입니다!
이번 글에서는 메시지 버블, 닉네임 표시, 보낸 시간 표시, 내 메시지와 다른 사람 메시지 구분까지,
코드를 어떻게 변경했는지 하나하나 자세히 알려드릴게요.
🧩 Flutter 메신저 업그레이드에서 변경된 부분
- 메시지를 보낼 때 닉네임과 시간도 함께 저장
- 메시지를 시간순으로 정렬해서 보여주기
- 내 메시지는 오른쪽, 다른 사람 메시지는 왼쪽 정렬
- 메시지를 버블 디자인으로 예쁘게 꾸미기
- 닉네임과 보낸 시간도 화면에 표시하기
업그레이드된 메신저 예제 코드
//chat_screen.dart
import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:intl/intl.dart'; // 시간 포맷을 위해 필요해요.
class ChatScreen extends StatefulWidget {
@override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final TextEditingController _controller = TextEditingController();
final DatabaseReference _messagesRef = FirebaseDatabase.instance.ref(
'messages',
);
final String myNickname = '나'; // 내 닉네임 (테스트용)
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Flutter 메신저')),
body: Column(
children: [
Expanded(
child: StreamBuilder(
stream: _messagesRef.orderByChild('timestamp').onValue,
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data!.snapshot.value != null) {
Map data = snapshot.data!.snapshot.value as Map;
List items = data.entries.map((e) => e.value).toList();
items.sort(
(a, b) => a['timestamp'].compareTo(b['timestamp']),
); // 시간순 정렬
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
bool isMe = items[index]['sender'] == myNickname;
return _buildMessageBubble(
text: items[index]['text'],
sender: items[index]['sender'],
timestamp: items[index]['timestamp'],
isMe: isMe,
);
},
);
} else {
return Center(child: Text('아직 메시지가 없어요.'));
}
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: InputDecoration(labelText: '메시지 입력'),
),
),
IconButton(icon: Icon(Icons.send), onPressed: _sendMessage),
],
),
),
],
),
);
}
void _sendMessage() {
if (_controller.text.isNotEmpty) {
_messagesRef.push().set({
'text': _controller.text,
'sender': myNickname,
'timestamp': DateTime.now().millisecondsSinceEpoch,
});
_controller.clear();
}
}
Widget _buildMessageBubble({
required String text,
required String sender,
required int timestamp,
required bool isMe,
}) {
String time = DateFormat(
'HH:mm',
).format(DateTime.fromMillisecondsSinceEpoch(timestamp));
return Align(
alignment: isMe ? Alignment.centerRight : Alignment.centerLeft,
child: Container(
width: MediaQuery.of(context).size.width * 0.7,
margin: EdgeInsets.symmetric(vertical: 4, horizontal: 8),
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: isMe ? Colors.blueAccent : Colors.grey[300],
borderRadius: BorderRadius.circular(16),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(sender, style: TextStyle(fontSize: 12, color: Colors.black54)),
SizedBox(height: 4),
Text(
text,
style: TextStyle(
fontSize: 16,
color: isMe ? Colors.white : Colors.black,
),
),
SizedBox(height: 4),
Align(
alignment: Alignment.bottomRight,
child: Text(
time,
style: TextStyle(fontSize: 10, color: Colors.black45),
),
),
],
),
),
);
}
}
0. 의존성 추가
pubspec.yaml에 데이터 포맷팅을 위한 intl 패키지를 추가해주세요.
dependencies:
flutter:
sdk: flutter
firebase_core: ^3.13.0
firebase_database: ^11.3.5
intl: ^0.20.2 # 의존성 추가
1. 메시지 저장할 때 데이터 구조 변경
🔥 변경 전
_messagesRef.push().set({'text': _controller.text});
메시지 텍스트만 저장했어요.
✨ 변경 후
_messagesRef.push().set({
'text': _controller.text,
'sender': myNickname,
'timestamp': DateTime.now().millisecondsSinceEpoch,
});
텍스트, 닉네임(sender), 보낸 시간(timestamp)까지 함께 저장합니다.
✅ 왜 바꿨을까요?
- 닉네임과 시간을 표시하려면 저장할 때부터 함께 기록해야 해요.
- 나중에 누가 보냈고, 언제 보냈는지 쉽게 알 수 있어요.
2. 메시지 불러올 때 시간순 정렬 추가
🔥 변경 전
stream: _messagesRef.onValue,
👉 그냥 가져와서 순서가 랜덤일 수 있었어요.
✨ 변경 후
stream: _messagesRef.orderByChild('timestamp').onValue,
👉 시간순(timestamp)으로 정렬해서 가져와요.
✅ 왜 바꿨을까요?
- 대화 흐름이 자연스럽게 이어지게 만들려고요.
- 최근 메시지가 맨 밑에 나오도록 정렬하기 위해서예요.
3. 내 메시지와 다른 사람 메시지 정렬 다르게 만들기
🔥 변경 전
- 모든 메시지가 왼쪽에 똑같이 정렬.
✨ 변경 후
bool isMe = items[index]['sender'] == myNickname; ... alignment: isMe ? Alignment.centerRight : Alignment.centerLeft,
- 내 메시지는 오른쪽, 다른 사람 메시지는 왼쪽 정렬!
✅ 왜 바꿨을까요?
- 누구의 메시지인지 한눈에 알아보기 쉽게 하기 위해서예요.
- 카카오톡처럼 자연스럽게 구분되게 만들었어요.
4. 메시지를 버블 형태로 디자인 변경
🔥 변경 전
ListTile(
title: Text(message),
);
👉 그냥 텍스트만 덜렁 나왔어요.
✨ 변경 후
Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: isMe ? Colors.blueAccent : Colors.grey[300],
borderRadius: BorderRadius.circular(16),
),
child: ...
)
👉 말풍선(버블) 모양으로 예쁘게 만들었어요!
✅ 왜 바꿨을까요?
- 채팅이 훨씬 보기 좋아지고, 프로 느낌이 납니다.
- 사용자가 대화를 읽을 때 더 편하게 볼 수 있어요.
5. 닉네임과 보낸 시간 표시
🔥 변경 전
- 메시지 내용만 보여줬어요.
✨ 변경 후
Text(sender),
...
Text(time),
- 위에는 닉네임, 아래에는 시간을 작게 표시했어요.
✅ 왜 바꿨을까요?
- 대화 상대가 누구인지, 언제 보냈는지 쉽게 알 수 있어야 해요.
- 친구랑 채팅할 때 누가 썼는지 몰라서 헷갈리면 안 되겠죠?
🧠 Flutter 메신저 업그레이드 요약 표
변경 내용 | 이유 |
닉네임과 시간 저장 | 보낸 사람과 시간을 표시하려고 |
시간순 정렬 | 대화 흐름을 자연스럽게 하려고 |
내 메시지/남 메시지 정렬 구분 | 누가 보냈는지 쉽게 구분하려고 |
메시지 버블 디자인 | 보기 좋고 읽기 쉽게 하려고 |
닉네임과 시간 화면 표시 | 혼동 없이 대화하려고 |
마무리하며
이번 업그레이드를 통해
우리 Flutter 메신저는 훨씬 진짜 메신저앱처럼 변했어요!
앞으로는 이 위에
- 프로필 사진 붙이기
- 닉네임 설정 기능 추가하기
- 메시지 읽음 표시 넣기
같은 것도 해볼 거예요!
조금씩 추가하면서, 진짜 카카오톡 같은 멋진 앱을 같이 만들어 봐요! 🚀