Socket.io 설정하기
대부분의 웹 앱은 HTTP를 사용합니다. 흐름은 다음과 같은 간단한 패턴을 따릅니다:
클라이언트가 요청을 보냅니다. 서버가 응답을 보냅니다. 연결이 종료됩니다.
이는 인증이나 데이터 페칭(fetching)에는 적합합니다. 하지만 서버가 요청 없이 데이터를 보내야 하는 경우에는 작동하지 않습니다.
팀원이 작업을 업데이트하거나 상태가 변경될 때, HTTP 방식은 브라우저가 "새로운 데이터가 있나요?"라고 반복해서 묻게 만듭니다. 이를 폴링(polling)이라고 하며, 이는 리소스를 낭비합니다.
Socket.io는 이 문제를 해결합니다. 지속적인 연결을 생성하여 연결 상태를 유지합니다.
통신이 양방향으로 이루어집니다: 클라이언트 ↔ 서버
클라이언트가 데이터를 보내고, 서버도 데이터를 보냅니다. 이를 통해 실시간 앱 구현이 가능해집니다.
흔히 하는 실수는 Socket.io를 Express에 직접 연결하려고 하는 것입니다. Express는 내부의 HTTP 서버를 숨깁니다. Socket.io는 해당 서버에 직접 접근해야 합니다.
대신 다음과 같이 하세요:
- Express 앱을 사용하여 서버를 생성합니다.
- 해당 서버에 Socket.io를 연결합니다.
- 포트에서 리스닝(listening)을 시작합니다.
Socket.io는 두 가지 메서드에 의존합니다:
• socket.emit(): 이벤트를 보냅니다.
• socket.on(): 이벤트를 수신합니다.
Room(룸) 기능을 사용하면 Socket.io를 효율적으로 사용할 수 있습니다. 무전기 채널과 같다고 생각하면 됩니다. 사용자를 특정 프로젝트 룸으로 그룹화할 수 있습니다.
사용자가 프로젝트를 열면 특정 룸에 참여하게 됩니다. 업데이트가 발생하면 해당 룸에만 이벤트를 보냅니다(emit). 이를 통해 데이터가 필요 없는 사용자에게까지 데이터를 보내는 것을 방지할 수 있습니다.
올바른 구현이 중요합니다. Socket.io 핸들러 내부에 비즈니스 로직을 넣지 마세요. 비즈니스 로직은 라우트 핸들러(route handlers)에 작성해야 합니다.
올바른 흐름은 다음과 같습니다:
- 사용자가 라우트로 요청을 보냅니다.
- 서버가 데이터베이스를 업데이트합니다.
- 데이터베이스 작업이 성공합니다.
- 서버가 Socket.io 이벤트를 보냅니다(emit).
- 클라이언트가 UI를 업데이트합니다.
데이터베이스에서 변경 사항이 확인되기 전에 이벤트를 절대 보내지 마세요.
코드를 깔끔하게 유지하려면 Socket.io 인스턴스를 Express 앱에 저장하세요. app.set("io", io)를 사용하면 복잡한 import 과정 없이 어떤 라우트에서도 인스턴스에 접근할 수 있습니다.
실시간 통신이란 사용자가 페이지를 새로고침하지 않고도 업데이트를 즉시 확인할 수 있음을 의미합니다.