Roblox Studio를 배우다 보면 어느 순간 Script, LocalScript, RemoteEvent가 한꺼번에 등장하면서 어려워집니다. 초보자가 가장 많이 헷갈리는 부분은 “이 코드는 누구 컴퓨터에서 실행되는가?”입니다. 서버와 클라이언트 차이를 이해하면 데미지가 두 번 들어가거나, 내 화면에서만 문이 열리거나, UI 버튼을 눌러도 서버 데이터가 바뀌지 않는 문제를 훨씬 쉽게 찾을 수 있습니다.
1. 서버는 모든 플레이어가 공유하는 게임 상태를 관리합니다
서버는 한 게임 서버에 들어와 있는 플레이어들이 공통으로 봐야 하는 중요한 상태를 관리한다고 생각하면 쉽습니다. 적 체력, 웨이브 진행, 실제 아이템 지급, 점수 저장처럼 조작되면 안 되는 값은 보통 서버에서 최종 판단하는 구조가 안전합니다. 한 플레이어의 화면에서 임의로 값을 바꾼 것이 곧바로 전체 게임의 진짜 상태가 되어서는 안 됩니다.
2. 클라이언트는 각 플레이어의 화면과 입력에 가깝습니다
클라이언트는 각 플레이어의 기기에서 실행되는 부분입니다. 버튼 클릭, 카메라, 일부 화면 효과, 개인 UI처럼 플레이어마다 다르게 보여야 하는 요소를 처리하기 좋습니다. 같은 서버에 네 명이 있어도 각자 카메라 위치와 UI 상태는 다르므로 이런 부분을 서버가 전부 직접 관리할 필요는 없습니다.
3. Script와 LocalScript를 위치만 보고 섞지 않기
Script는 일반적으로 서버에서 실행되는 코드를 작성할 때 사용하고, LocalScript는 플레이어 클라이언트에서 실행되는 작업에 사용합니다. 하지만 단순히 종류만 맞춘다고 끝나는 것이 아니라 어디에 배치했는지에 따라 실행 여부가 달라질 수 있습니다. 코드가 전혀 시작되지 않는다면 문법보다 먼저 스크립트 종류와 위치를 확인해보세요.
4. RemoteEvent는 서버와 클라이언트가 대화하는 통로입니다
예를 들어 플레이어가 UI에서 “유닛 소환” 버튼을 눌렀다고 합시다. 버튼 클릭 자체는 클라이언트가 감지하기 편하지만 실제 재화 차감과 유닛 생성은 서버가 확인하는 편이 좋습니다. 클라이언트가 RemoteEvent로 “이 유닛을 소환하고 싶다”고 요청하고, 서버가 돈과 조건을 확인한 뒤 실제로 생성하는 식입니다.
5. 클라이언트가 보낸 값을 그대로 믿으면 안 됩니다
클라이언트가 “나는 돈이 999999 있으니 최고 유닛을 지급해줘”라는 값을 보낼 수 있다고 가정해보면 이유가 명확합니다. 서버는 클라이언트가 보낸 요청을 그대로 실행하지 말고 서버가 가진 실제 데이터로 조건을 다시 검증해야 합니다. 데미지, 가격, 보상, 쿨타임 같은 중요한 값도 서버에서 확인하는 구조가 좋습니다.
6. 내 화면에서만 바뀌는 문제는 클라이언트 변경을 의심하기
문 색을 바꿨는데 나에게만 보이고 다른 플레이어에게는 그대로라면 LocalScript에서만 변경했는지 확인해볼 수 있습니다. 반대로 모든 플레이어에게 공유돼야 하는 변화라면 서버가 상태를 바꾸는 방식이 더 자연스럽습니다. 물론 연출처럼 굳이 공유할 필요가 없는 효과는 각 클라이언트에서 따로 실행해도 됩니다.
7. 데미지가 두 번 들어가면 중복 실행부터 확인하기
공격 시스템에서 서버 Script와 LocalScript가 둘 다 데미지를 적용하거나, 같은 RemoteEvent 연결이 여러 번 만들어지면 한 번 공격했는데 두세 번 처리될 수 있습니다. 이런 문제는 데미지 공식을 의심하기 전에 “실제로 몇 번 이벤트가 호출됐는가”를 print로 확인하는 것이 좋습니다. 기존 공격 서버나 Remote가 남아 있는지도 같이 살펴보세요.
8. 간단한 기준으로 나누기
- 개인 입력·UI·카메라: 클라이언트 중심
- 재화·보상·체력·저장: 서버가 최종 검증
- 서로 전달해야 하는 요청: RemoteEvent 또는 RemoteFunction
- 모든 플레이어가 공유해야 하는 결과: 서버에서 처리 후 필요한 정보를 전달
처음에는 완벽하게 외울 필요가 없습니다. 기능 하나를 만들 때 “이 값은 한 명만 알아도 되는가, 아니면 모두가 믿어야 하는 진짜 게임 상태인가?”를 먼저 질문해보세요. 그 기준이 서버와 클라이언트를 나누는 가장 쉬운 출발점입니다.
