-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDB Info.txt
322 lines (263 loc) · 9.45 KB
/
DB Info.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# 테스트 데이터를 위한 Postgre DB 초기화 데이터
-- MongoDB
Port: 27017
User: tongstar, PW: @***********
DB Name: Minigram
mongodb://localhost:27017/?minPoolSize=3&maxPoolSize=3와 같이 스레드 풀 개수도 정해줄 수 있음
--- 주의점
계정이 생성되는 DB 개인별로 존재할 수 있기에 특정 DB에서 계정 인증을 받고 특정 DB로 이동해야 됨.
즉 계정 이름과 비번이 모두 같은 계정이 존재할 수 있음.
계정을 인증 받는 DB가 중요.
-- Postgre
Port: 5432
User: tongstar, PW: @***********
DB Name: Minigram
tongstar 유저에게 웬만하면 superuser 권한을 주자.
안그러면 따로 Role을 생성하여 관리하거나 각 테이블마다 `GRANT SELECT ON user_tb TO PUBLIC` 이런 명령어로 수정 권한을 줘야 soci 라이브러리가 작동한다.
## Postgre 테이블 생성
### user_tb
설명: 유저 정보가 담기는 table
CREATE TABLE user_tb
(
user_id VARCHAR(32) NOT NULL,
user_nm VARCHAR(64) NOT NULL,
user_info TEXT,
password VARCHAR(32) NOT NULL,
img_path VARCHAR(255),
login_ip VARCHAR(40),
login_port INTEGER,
CONSTRAINT chk_user_id CHECK (user_id ~* '/^\w{6,31}$/'),
CONSTRAINT chk_password CHECK (password ~* '/^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,31}$/'),
PRIMARY KEY (user_id)
)
### contact_tb
설명: 연락처 정보가 담기는 table
CREATE TABLE contact_tb
(
user_id VARCHAR(32) NOT NULL,
acquaintance_id VARCHAR(32) NOT NULL,
status INTEGER NOT NULL,
CONSTRAINT fk_user_id FOREIGN KEY(user_id) REFERENCES user_tb(user_id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT fk_acquaintance_id FOREIGN KEY(acquaintance_id) REFERENCES user_tb(user_id) ON DELETE CASCADE ON UPDATE CASCADE,
PRIMARY KEY (user_id, acquaintance_id)
)
status: 친구 요청 상태, 친구 연결 상태 등을 다룸 / 0: 요청 보냄, 1: 친구, 2: 숨김, 3: 차단
### session_tb
설명: 채팅방 관련 테이블
CREATE TABLE session_tb
(
session_id VARCHAR(65) NOT NULL,
session_nm VARCHAR(255) NOT NULL,
session_info TEXT,
img_path VARCHAR(255),
CONSTRAINT chk_session_id CHECK (session_id ~* '/^\w{6,31}-\d{4}(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])-\d{6}$/'),
PRIMARY KEY (session_id)
)
session_id 제약: 생성자 ID + '_' + 세션 생성일
ex) tongstar_1706838249711 / tongstar 사용자가 1706838249711 since_epoch_time_milli에 첫번째로 만든 채팅방이라는 정보가 담김
### participant_tb
설명: 유저와 채팅방 사이 관계 정의 테이블
CREATE TABLE participant_tb
(
session_id VARCHAR(65) NOT NULL,
participant_id VARCHAR(32) NOT NULL,
message_id BIGINT,
CONSTRAINT fk_session_id FOREIGN KEY(session_id) REFERENCES session_tb(session_id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT fk_participant_id FOREIGN KEY(participant_id) REFERENCES user_tb(user_id) ON DELETE CASCADE ON UPDATE CASCADE,
PRIMARY KEY (session_id, participant_id)
)
message_id: participant가 가장 최근 읽은 메시지의 id, 채팅방 처음 들어오면 가장 최신 message_id로 설정
## MongoDB 컬렉션 생성
### [SESSION_ID]_log 구조 / SESSION_ID에 따라 동적으로 생성됨
설명: 채팅방 하나당 `[SESSION_ID]_log`라는 컬렉션이 하나씩 생김, 해당 컬렉션에 sort 속도 개선을 위한 ensureIndex 필요할 수도...
밑은 말풍선 하나당 컬렉션에 저장되는 정보
sender_id와 send_date를 조합하면 고유하기에 key로 작동할 수 있음
{
"message_id" : (메시지 id, 보낸 순서 big int)
"sender_id": "보낸 사람 USER_ID",
"send_date": ISODate("2023-10-19T13:21:40.125"),
"content_type": 컨텐츠 타입 (size_t),
"content": "7LGE7YyF7J2EIOyzkOuztOyekH4",
"reader_id" : [ "tongstar", "yellowjam" ... ]
}
### [SESSION_ID]_cnt
[SESSION_ID]_log가 생성될 때 같이 생성되는 컬렉션
sender_id와 send_date를 조합하면 고유하기에 key로 작동할 수 있음
{
"message_cnt" : 여태껏 메시지 개수
}
원자적으로 관리되는 변수로 해당 컬렉션에는 단 하나의 document만 존재함
find_one_and_update()를 이용하여 원자적 연산을 해야됨
### user_login_info
설명: 로그인된 사용자들의 ip를 저장해두고 있는 collection
{
"login_id": "사용자 id",
"login_info": [ { "ip": ip_01, "port": port_01 }, { "ip": ip_02, "port": port_02 } ]
}
## Client - Server 통신 규격
### Server -> Client
####
#### Get Session List
채팅방 초기화시 밑과 같은 형식을 서버와 클라이언트가 주고 받음
실제 채팅방의 컨텐츠를 모두 가져오진 않고 마지막 채팅 내용과 사용자가 읽지 않은 메시지 개수 정도를 가져옴
{
"session_init_data": [
{
"session_id": "세션 id",
"session_name": "세션 이름",
"session_img_name": "이미지 이름",
"session_info": "",
// 클라이언트 사용자가 채팅방 채팅을 읽지 않은 개수, 음수면 채팅방을 상대방이 지우거나 추방된거임
"unread_count": 10
// 마지막으로 생성된 채팅 정보
"chat_info": {
"sender_id": "보낸 사람 USER_ID",
"send_date": since_epoch_time,
"message_id": 462,
"content_type": int형,
// content_type이 text가 아니라면 content 내용은 간략화됨
"content": "7LGE7YyF7J2EIOyzkOuztOyekH4"
}
},
...
]
}
해당 json과 함께 raw img 파일 배열 보내야 함
#### Session Recieve Chat
클라이언트에서 채팅 받는 경우
{
"message_id" : (메시지 id, 보낸 순서 big int)
"sender_id": "보낸 사람 USER_ID",
"send_date": ISODate("2023-10-19T13:21:40.125"),
"content_type": 컨텐츠 타입 (size_t),
"content": "7LGE7YyF7J2EIOyzkOuztOyekH4",
"reader_id" : [ "tongstar", "yellowjam" ... ]
}
#### Session Refresh
채팅방을 눌렀을 때 서버가 보내주는 정보
클라이언트 채팅방 리스트뷰에 메시지가 하나라도 이미 차 있다면 다 가져와서 리스트뷰에 넣는다.
클라이언트 메신저를 열고 나서 처음 채팅방에 입장하는 것이라면 가장 최신 메시지 100개만 가져와서 넣는다.
{
"fetched_chat_list" [
{
"sender_id": "보낸 사람 USER_ID",
"send_date": time since epoch,
"message_id": 462,
"content_type": 숫자,
"content": "7LGE7YyF7J2EIOyzkOuztOyekH4",
"reader_id": [ "tongstar", "yellowjam" ... ]
},
...
],
"participant_infos": [
{
"user_id": "참가자 id",
"user_name": "참가자 이름",
"user_info": "참가자 정보",
"user_img_name": "참가자 이미지 이름",
},
...
]
}
raw data: participant_img 01 | participant_img 02 ...
#### Fetch More Message
클라이언트 채팅방에서 스크롤을 계속 위로 올리면 발생하게 되는 과거 채팅 이력 서버에서 가져오는 경우
{
"fetched_chat_list": [
{
"sender_id": "보낸 사람 USER_ID",
"send_date": time since epoch,
"message_id": 462,
"content_type": 숫자,
"content": "7LGE7YyF7J2EIOyzkOuztOyekH4",
"reader_id": [ "tongstar", "yellowjam" ... ]
},
...
],
}
#### Contact Init
연락처 목록 초기화시 서버에서 클라로 던져주는 json 데이터
{
"contact_init_data": [
{
"user_id": "tongstar",
"user_name": "KyungJoonLee"
"user_img": 이미지 이름(확장자 포함),
"user_info": "어쩌구 저쩌구 블라블라"
},
...
]
}
#### Contact Request Init
친구 추가 정보 가져올 때 서버가 클라로 던져주는 json 데이터
{
"contact_request_init_data": [
{
"user_id": "tongstar",
"user_name": "KyungJoonLee",
"user_img": 이미지 이름(확장자 포함),
"user_info": "어쩌구 저쩌구 블라블라"
},
...
]
}
raw img file이 담긴 배열을 함께 전송함
#### Add Session
세션 추가할 때 접속중인 메신저한테 보내는 json 파일
{
"session_id": "세션 ID",
"session_name": "세션 이름",
"session_info": "세션 각종 정보",
"session_img_name": "세션 이미지 이름",
"participant_infos": [
{
"user_id": "참가자 ID",
"user_name": "참가자 이름",
"user_info": "참가자 정보",
"user_img_name": "참가자 이미지 이름",
},
...
]
}
raw data: session_img | participant_img 01 | participant_img 02 | participant_img 03
raw img file이 담긴 배열을 함께 전송함, 처음에 세션 이미지, 그 담부터 참가자 이미지
## Client Cache 구성
클라이언트에 남는 캐시 파일은 대화에서 생성되는 미디어 정보로 구성된다.
일반적인 텍스트 형식은 서버에서 가져온다.
캐시 파일 구성은 밑과 같다.
Minigram.exe
minigram_cache
L user_id
L profile_img
L 날짜.이미지_확장자
L sessions
L session_id
L 날짜.이미지_확장자
L participant_data
L participant_id
L profile_img
L 날짜.이미지_확장자
L profile_info.txt -> 사용자 이름, 상태 메시지 등...
L contact
L acquaintance_id
L profile_img
L 날짜.이미지_확장자
L contact_request
L requester_id
L 날짜.이미지_확장자
L setting_info
날짜는 이미지 갱신 날짜(time since epoch)
## Server Cache 구성
MinigramServer.exe
server_data
L user_id
L profile_img
L 날짜.이미지_확장자
L sessions
L session_id
L session_img
L 날짜.이미지_확장자
## 참고할 만한 글
https://marketsplash.com/tutorials/cpp/how-to-create-a-messenger-application-cplusplus/
http://tsfkb.wikidot.com/tips:android:cache
https://insidetelegram.eu/en/2022/01/20/telegram-what-is-cache-how-to-cancel-it/