본문 바로가기

IT/프로젝트 및 실습

python을 이용한 다중 채팅 구현하기




다음 프로젝트는 서적 '초보자를 위한 파이썬 200제'를 기반으로 한 포스팅입니다.




파이썬을 이용하여 TCP 소켓을 이용한 다중채팅을 구현하여 보겠다.


구현에 앞서 몇가지 고려해야할 사항이 있는 데, 이를 언급하고 직접 코드로 보이겠다.


다중채팅은 기본적으로 에코서버를 기반으로 한다.


대화에 참여한 모든 클라이언트에게 받은 메세지를 전송하여 주면된다.


[사용자ID : ] + ["사용자가 보낸 문자열"]



두번 째로 고려해야 할 사항은,


다중 클라이언트 채팅과 같은 경우는 비동기(asynchronous handling)로 처리해야한다.


이 말인 즉슨, 만약 소스코드에서 반복문을 이용하여 순차적으로 사용자에게 메세지를 처리하는 코드를 작성한다면, (동기식으로)


하나의 클라이언트에 대한 요청을 모두처리하고 두 번째 클라이언트 요청을 처리하는 방식이기에 채팅 서버와 같이 다수의 클라이언트가 동시 다발적으로 메세지를 서버로 전송하고


수신하는 경우에,  특정한 한명의 클라이언트에 대한


요청을 처리하기 전까지는 다른 클라이언트는 모두 기다려야 하는 난감한 상황이 발생한다.


사람 수가 적을 때나 처리하는 데이터가 적을 때는 문제가 없겠지만 


데이터가 방대하거나, 게임과 같은 대규모 채팅서버에서는 문제가 생길 수 밖에 없다.



마지막으로 스레드 동기화를 해줘야 하는데


위의 이유로 구현할 채팅 서버는 클라이언트의 요청을 독립된 스레드로 실행하여 처리하게 되면


동시의 여러개의 스레드가 실행되, 이들 스레드가 공용으로 사용하는 데이터


즉, 스레드가 공유하는 데이터의 두개 이상의 스레드가 동시 접근하여 값을 변경하려고 하여 문제가 발생할 수 있다.



일상적인 상황에서 예를들어


은행의 계좌에 저장된 잔금데이터에서


ATM현금 인출기에서 통장과 카드를 이용하여 동시에 인출한다고 생각해 보자



만약 잔고에 300,000이 있다고 가정해서


카드로 10,000을 인출하고 통장으로 20,000을 인출한다고 하였을 때


카드에서 10,000을 인출하는 동시에


300,000 - 10,000이라는 연산이 데이터에 취해지기도 전에


통장에서 20,000이 인출 된다면


290,000 - 20,000으로 정상적으로 시행되는 것이 아닌


300,000 - 10,000이란 연산이 진행된 후


다시 


300,000 - 20,000이라는 연산이 진행되여


잔금이 270,000이 아닌 280,000인 상황이 되버릴 수 있다.



돈을 인출하는 사람 입장에서는 개이득인 경우가 있을 수 있겠지만,


민약 무수하게 많은 사람들이 이와 같은 에러를 이용하여,


부당한 이득을 취한다면 국가적으로 돈의 가치가 낮아지는 인플레이션이 진행되어 사회 혼란을 빚을 수 있을정도로 중요한 것이다.



이러한 크리티컬(critical)한 버그를 막기위해서는


여러 개의 프로세스나 스레드가 구동하고 있는 환경에서 공용으로 사용하는 데이터에 값을 변경하려고 접근할 때 


단 하나의 프로세스나 스레드만을 접근하도록 하면 된다.


파이썬에서는 threading.Lock( ) 객체를 활용하여 막고있다.




시연영상





서버 소스코드



클라이언트 소스코드