codestates / codestates/withpuppy

[✍️ Dev Log] 최우철 / 2021-12-18

Open
#171 0 comments 0 reactions 1 assignee Claimed by @chltjdrhd777 View on GitHub
Dev-Log
Dominant language
JavaScript
Stars
0
Forks
3
PR merge metrics
No merged PRs in 30d

Description

### 오늘은 어떻게 프로젝트에 기여했나요?

- 오늘은 다른 유저가 채팅을 업데이트 하는 경우, 그 당사자에게 곧바로 응답이 갈 수 있도록 로직을 구현하는데 주력하였다
- 해당 논리가 되기 위해서는 서버에 연결되는 직후, 서버와 계속해서 소통을 해야하는 것을 구현해야했다
- 단순무식하게 구현하려고 한다면, 일정 주기마다 서버에 요청을 날려서 변경사항이 있으면 업데이트를 가져오는 방식을 사용했을 것이다
( 실제로, 과거에는 이런식으로 실시간 업데이트를 개발했다고 한다. 그것을 polling이라고 칭한다)
- 하지만 HTML5의 웹소캣이라는 개념이 표준화된 뒤로, 서버와 연결을 유지하는 객체인 "socket" 을 사용하면 지속적인 연결과 더불어 서버에서 유저의 요청이 없더라도 클라이언트단에 데이터와 함께 응답을 날릴 수 있는 장점이 있다

> 와이파이와 같은 개념, 혹은 http2에서 응답이 다 끝나기 전까지는 서로의 핸드쉐이크 연결이 유지되는 것을 생각해보자. 마찬가지로 websocket 역시 연결이 끊기기 전까지는 계속해서 지속적으로 그 연결이 유지된다. 어떻게? socket이라는 객체를 통해서 말이다.
1

- 근데, 보통은 양방향 통신을 위해서 pure websoket을 사용하기보단 socketIo를 사용한다.
- socketIo는 websocket보다 더 무거움(1mb)에도 불구하고 사용되는 이유는 상당히 다양하고, 편리한 기능들을 많이 제공해주기 때문이다.

> 정확하게 말하면, socketIo는 양방향 실시간 통신을 위한 방법 중 하나로 Websocket을 쓰는 것이고, 그 외에도 만약 소켓연결이 끊기거나 예상치 못한 상황을 마주하게 될 경우에도 연결을 유지시키기 위한 방법들을 계속해서 찾는 로직을 가지고 있다.
> 더불어, websocket에 비해서 훨씬 더 직관적이고, 간편하게 연결을 만들 수 있게 만들어져 있으므로 사용하는 것이 좋다

- 사용법은 생각보다 간단하다
- 서버쪽은 이미 listening이 돌고있는 app 객체에다가 socket을 감싸주기만 하면 된다
server1
스크린샷 2021-12-18 오후 8 01 46

- 위에 보이는 코드 중 app.set() 을 통해서 app 객체의 req에 io 프로퍼티를 만들고, 웹소켓으로 감싸진 앱객체를 담는다.
- 그렇게 하면 어느 라우트에서 req.get을 통해 접근해도 미리 설정해뒀던 io 객체에 접근이 가능해진다
server3

- 그 후 클라이언트 측에도 역시 마찬가지로 연결을 위해 클라이언트용 소켓을 설정하고 서버와 연결을 하게되면, 양방향 통신을 위한 다리가 놓여지게 된다
client1

- 이후 양쪽이 통신하는 논리의 근간은 event에 대한 listner인 **on** 과 **emit**을 통해 이루어진다.
- 서버의 요청에 따라 필요에 의하면 on과 emit을 적절이 활용하여 지속적인 실시간 통신을 만들어줄 수 있다

> 예를들어, 현재 로그인 상태에 따라 클라이언트측에서 "emit"을 이용하여 요청을 날리고
client2

> 해당 요청을 on을 통해 받을 수 있다. 이것은 반대의 경우도 가능하다(서버 => 클라이언트)
server4

- 얼핏 보면 그냥 일반 서버의 요청과 응답이랑 무슨 차이인가 할 수 있겠는데, 이 on 메소드는 말 그대로 "실시간" 리스너라는 사실이 중요하다. 즉, 서버가 켜져있고 클라이언트와 서버가 연결되어 있는 한 요청과 응답이 따로 없더라도 언제든지 둘은 리스너를 통해 필요한 내용을 주고받고 할 수 있다는 점이 중요하다.

---

## Apply

- 이 실시간 응답기능은 현재 구현하길 원하는 기능 즉, 타인이 나의 핀포인터에 있는 채팅에 글을 남겼을 때 이것을 실시간으로 전달받는 구현에서 특히나 큰 의미를 가진다
- 만약 유저가 접속을 한 상태일 때 핀포인터 메세지에 대한 업데이트의 내용을 소켓을 통해 받게된다면 실시간으로 이것을 UI로 표현하면 되는 것이다.
>채팅이 업데이트되기 전에는 이런 상황이다가
스크린샷 2021-12-18 오후 5 59 36

>채팅이 업데이트된다면
스크린샷 2021-12-18 오후 6 01 48

> 실시간으로 알람문구가 변하고
스크린샷 2021-12-18 오후 6 02 04

> 눌러서 확인해보면 업데이트된 핀이 강조되어 있는 형태로 구현을 하였다.
스크린샷 2021-12-18 오후 6 57 00

---

## Complement

- 현재 확인은 하지 않았지만, 이런 구현 방식이면 유저가 "로그인이 된 상태" 에만 실시간 응답을 받고, 그 외에는 업데이트에 대한 요청을 받지 못하는 상태일것이다
- 따라서, join을 통해 join된 대상에게만 업데이트를 진행하는 것이 아니라 만약 join 상태가 아니라면 소켓의 영역에 마치 세션처럼 저장하고 있다가 유저가 로그인을 하는 순간 해당 내용을 전달해주는 방식으로 조금 더 보안을 해야 할 것이라고 생각했다

- 근데, 그렇게 되면 서버가 계속 켜져있어야 하고(in-memory), 다시금 서버가 모든 데이터를 저장하고 있어야 하므로 서버의 부담도 커진다

- 따라서, 유저가 일단 로그인을 하면 자신이 쓴 핀포인터와그 핀포인터에 들어있는 메세지의 길이를 받는다,
- 그리고 그것을 클라이언트의 리덕스에 저장되어 있는 핀포인터와, 그 메세지의 길이랑 대조한다
- 만약 길이가 달라진게 있다 => 그게 만약 이미 updatedmessages 리덕스 상태 안에 들어가 있는 핀이면 무시하고, 아니라면 그 안에 넣는다
- 그리고 나서 서버로부터 응답받았던 그 핀포인터와, 메세지의 길이를 저장한다.
- 다음에 유저가 로그인을 하지 않은 상태였다가 다시 들어왔을 때에는 첫번째 과정이 반복될 것이고, 접속한 상태면 socketIO를 통해 실시간으로 업데이트가 될 것이다

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.