데이터 베이스와 웹소켓을 활용하여 기본적인 채팅이 가능한 웹서버가 되었다. 이번에는 디자인을 개선하여 본격적으로 카카오톡과 비슷하게 구성하도록 할 것이다. 다만 이 글은 오로지 채팅창의 디자인만 구현한다.


결과물

먼저 결과물을 살펴보도록 하자.

대체 이미지


구현

먼저 채팅이 전달되면 p 태그를 생성하여 #chatLog라는 div에 삽입하도록 하였다. 다만 카카오톡의 경우 상대의 메시지와 내 메시지를 다른 색상으로 다른 위치에 출력하므로 그 부분까지 신경을 써줘야 했다.

1
io.emit('receive message', name, text);

서버에서 메세지를 합치는 것에서 나눠서 보내는 것으로 변경하여 클라이언트가 자신의 이름을 구분하여 위치를 조정한다.

1
2
3
4
5
6
7
8
9
10
11
socket.on('receive message', function(n, m) {
    var tagP = document.createElement('p');
    var msg = n + ' : ' + m;
	if(n == $('#name').val()) {
        tagP.className = 'myMessage';
        msg = m;
	}
	tagP.appendChild(document.createTextNode(msg))
	document.getElementById('chatLog').appendChild(tagP);
	document.getElementById('chatLog').scrollTop = document.getElementById('chatLog').scrollHeight;
});

p태그를 추가할 때 자신과 같은 닉네임의 글이면 myMessage라는 클래스를 추가한다. 또한 자신의 닉네임은 출력할 필요가 없으므로 메세지를 약간 변경시키도록 하였다.

p태그는 기본이 부모를 채우도록 되있는데 컨텐츠 크기에는 맞으면서 위 처럼 하나씩 나열되도록 구현하고자 하였다. 정말 갖가지 방법을 동원했지만 필자의 능력으로는 해결이 불가능해 보였다. 찾아보니 그 동안 단 한번도 써본적도 본적도 없었던 clear라는 속성을 통해서 해결할 수 있었다.

1
2
3
4
5
6
7
8
9
.chatLog > p {
	display: inline-block;
	padding: 15px;
	margin: 10px;
	background-color: rgba(255,255,255,1);
	border-radius: 10px;
	float: left;
	clear: both;
}

먼저 부모의 크기를 따라가지 않도록 inline-block으로 변경한다. 그럼 애들이 순차적으로 본문의 내용에 맞는 크기로 나열되는데 float: left 속성으로 왼쪽으로 붙이고 이때 중요한 점이 clear: both를 사용하여 중복 배치는 안되게 하도록 한다.

1
2
3
4
5
.chatLog > p.myMessage {
	background-color: rgba(255,235,51,1);
	float: right;
	clear: both;
}

이후 myMessage라는 클래스가 적용된 p태그는 오른쪽으로 붙이고 노랑색으로 표시한다. 색상은 카카오톡에서 추출한 것이다. 아래는 CSS와 HTML의 전체코드다.

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
::-webkit-scrollbar {
	display: none;
}

* {
	margin: 0;
	padding: 0;
}

body {
	background-color: rgba(178, 199, 217, 1);
	margin: 0;
	padding: 0;
}

.chatLog {
	max-width: 850px;
	width: 100%;
	margin-right: auto;
	margin-left: auto;
	height: 95vh;
	padding-bottom: 30px;
	overflow: scroll;
}

.chatLog > p {
	display: inline-block;
	padding: 15px;
	margin: 10px;
	background-color: rgba(255,255,255,1);
	border-radius: 10px;
	float: left;
	clear: both;
}

.chatLog > p.myMessage {
	background-color: rgba(255,235,51,1);
	float: right;
	clear: both;
}

.chatBox {
	position: fixed;
	bottom: 0;
	left: 0;
	width: 100%;
	background-color: rgba(255,255,255,0.8);
	text-align: center;
}

.name {
	border: none;
	height: 30px;
	width: 10%;
	background: #ddd;
}

.message {
	border: none;
	height: 30px;
	width: 50%;
}

.chatBox button {
	width: 15%;
	border: none;
	padding: 5px;
	background: rgba(255,255,255,1);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html>
	<head lang="ko">
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1, sharink-to-fit=no">
		<title>REAL CHAT</title>
		<meta name="theme-color" content="#000">
		<link rel="stylesheet" href="/main.css">
	</head>
	<body>
		<div id="chatLog" class="chatLog">
		    <p>배진오 : 매너 있는 채팅 부탁드립니다 :)</p>
			<p class="myMessage">나 : 싫어</p>
		</div>
		<div class="chatBox">
			<input id="name" class="name" type="text" readonly>
			<button class="name" onclick="rename()">변경</button>
			<input id="message" class="message" onkeydown="javascript:checkEnter();" type="text" autocomplete="off">
			<button class="chat" onclick="chat()">전송</button>
		</div>
	</body>
</html>
WRITTEN BY

배진오

소비적인 일보단 생산적인 일을 추구하며, 좋아하는 일을 잘하고 싶어합니다 :D
im@baejino.com

comments powered by Disqus