이번 스프린트는, 채팅을 할 수 있는 chat application의 클라이언트 부분을 만들어 보는 것이었다. 서버는 AWS에 배포되어 있는 코드스테이츠 서버를 활용하고 fetch library 를 활용하여, GET과 POST method를 사용해 서버에 메시지를 요청해 받고, 또 메세지를 보낼 것이다.
fetch를 잘 활용해, GET method 일때는 지금까지 서버에 있는 메시지를 불러와 함수를 통해 페이지에 트위틀러에서 했던 것 처럼 usernamer과 메시지가 나오게 해주면 된다.
POST method 일때는,
var message = {
"username": "JoshuaSong",
"text": "hello",
"roomname": "weWork"
}
이런 식의 메세지 오브젝트의 형식으로 서버에 보내서 response로는 {id: number}형태의 객체를 받는다. 친절하게도, 아니면 당연하게도, API docs를 통해 코드스테이츠는 서버가 무엇을 받고 무엇을 돌려주는지 명시한다.
Base URL
baseURL = "http://52.78.206.149:3000"
Retrieve Messages
HTTP Method: GET
URL: {baseURL}/messages
Response: JSON, Array of Messages.
Retrieved Messages have...
id: number - unique message id
username: string
text: string
roomname: string
date: string - Example) 2017-07-28T03:54:21.134
also possible to use query parameters
e.g. URL: {baseURL}/messages?roomname=1 will provide messages with roomname is 1
Send Message
HTTP Method: POST
URL: {baseURL}/messages
Body: application/json
{ "username": string, "text": string, "roomname": string, }
Response: application/json
{ id: number }
id: unique id of your message
페어와 함께 시작하기 전 수도코드? 어떤식으로 문제를 접근할지 계획을 짜는게 먼저일 것 같아서 간단하게 정리해본다.
// eslint-disable-next-line
var message = {
username: "크러쉬",
text: "",
roomname: "아메바컬쳐"
};
var idNumber = -1;
var chatArea = document.querySelector("#chats");
var submitButton = document.querySelector("#submit");
var newMessage = document.querySelector("#message");
var makeRoom = document.querySelector("#room");
const app = {
server: "http://52.78.206.149:3000/messages",
init: function() {
app.print();
app.makeRoom();
setInterval(function() {
app.print();
}, 1000);
},
fetch: function() {
return fetch(app.server).then(response => response.json());
},
print: function() {
app.fetch().then(json => {
if (idNumber < json[json.length - 1].id) {
for (let i = idNumber + 1; i < json.length; i++) {
app.renderMessage(json[i]);
}
idNumber = json[json.length - 1].id;
}
});
},
send: function(text) {
fetch("http://52.78.206.149:3000/messages", {
method: "POST",
body: JSON.stringify(text),
headers: {
"Content-Type": "application/json"
}
})
.then(response => response.json())
.then(() => {
app.print();
app.makeRoom();
});
},
clearMessages: function() {
document.querySelector("#chats").innerHTML = "";
},
renderMessage: function(json) {
if (chatArea === null) {
chatArea = document.querySelector("#chats");
}
let messageBlock = document.createElement("div");
messageBlock.setAttribute("class", "messageBlock");
messageBlock.innerHTML = `<div class="username">${json.username}</div>
<div class="message">${json.text}</div>`;
chatArea.prepend(messageBlock);
},
makeRoom: function() {
app.fetch().then(json => {
for (let element of json) {
if (!makeRoom.innerHTML.includes(element.roomname)) {
var roomName = document.createElement("option");
roomName.innerHTML = element.roomname;
makeRoom.appendChild(roomName);
}
}
});
},
filterByRoomname: function(roomname) {
app.fetch().then(json => {
app.clearMessages();
for (let element of json) {
if (element.roomname === roomname) {
app.renderMessage(element);
}
}
});
},
resetFilter: function() {
idNumber = -1;
app.clearMessages();
app.print();
}
};
app.init();
submitButton.addEventListener("click", function() {
if (newMessage.value.trim().length === 0) {
window.alert("내용을 입력해");
} else {
message.text = newMessage.value;
app.send(message);
newMessage.value = "";
}
});
makeRoom.addEventListener("click", function(x) {
let roomname = x.target.value;
if (roomname === "Room") {
// window.location.reload();
app.resetFilter();
} else {
app.filterByRoomname(roomname);
}
});
//**옵션이 클릭되면 이벤트를 걸고, 클릭이 된 이름으로 클리어 메시지를 다 날려버리고, fetch 를 한 후 fetch 한거 중에서 filter를 해서
//**roomname이 선택한 것과 동일한 것과 렌더.
각 함수를 보면, 각 기능에 맞춰서 실행되는 함수가 다르다. 처음에 app.init을 실행시켜 주는 이유는 페이지가 로딩될 때, 지금까지 작성되어 있는 챗들을 프린트 해주기 위해서이다. 함수이름은 보시다시피 이름에 나와있는 기능을 구현한다. 함수를 실행시킬때 그 안에 실행되는 다른 함수는 흐름을 생각하고 따라가면 말이 된다.
챗들을 보여줄 구역을 index.html에 만들어 주었고 새로운 챗들을 받아와 prepend로 추가해 준다.
기본 메시지 틀을 만들어서 그 안의 내용만 계속 바꾸어주면 좀 더 편리하다. 하지만 원하면 유저네임과 방 이름을 위한 칸도 만들어서 내용을 수정해 줄수 있다. 그건 간단하다.
시간이 그래도 조금 있어 Advanced 기능도 만들어 주었다. setInterval을 통해 auto fetching을 해 다른 유저가 채팅을 추가해도 렌더를 해주게 만들었고 또 room에 따라 챗들을 필터 할 수 있게 만들었다.