전체 글 25

멀티플레이 슈팅게임 만들기 (6)

슈팅게임 서버, C++로 처음부터 만들어보기 — 상태를 어디에 둘 것인가지금까지 모든 상태는 Session 안에 있었다. 소켓, 유저네임, 로그인 여부. 전부 "그 연결만의 것"이라 문제가 없었다.방은 다르다. 방 목록은 모두가 공유하는 상태다. alice가 만든 방을 bob이 볼 수 있어야 한다. alice의 Session에 방 목록을 넣으면 bob은 그걸 볼 방법이 없다.드디어 중앙 관리자그래서 모든 Session 바깥에서 공유 상태를 들고 있을 Server 클래스를 만들었다.여태 안 만들었던 이유는 필요가 없었기 때문이다. 필요해지기 전에 구조부터 잡지 않는다는 원칙을 지키다 보니 딱 지금이 그 시점이 됐다.기능보다 리팩터링 먼저방 기능을 바로 붙이지 않고, 먼저 main()에 있던 accept 루..

멀티플레이 슈팅게임 만들기 (5)

슈팅게임 서버, C++로 처음부터 만들어보기 — 서버는 아직 "누구"인지 모른다지난 편에서 메시지를 구조화해서 주고받을 수 있게 됐다. 그런데 서버는 여전히 중요한 걸 모르고 있었다 — 누가 보낸 메시지인지.채팅이든 방 생성이든 경매든, 전부 "누가"가 전제되는 기능이다. 그래서 이번엔 로그인을 붙였다.Session에 상태가 생겼다지금까지 Session은 순수하게 네트워크만 다뤘다. 소켓, 버퍼, 송신 큐. 여기에 게임 상태가 들어간다.uint64_t player_id_;std::string username_;bool logged_in_ = false;왜 하필 Session인가Session은 연결마다 하나씩 만들어지는 객체다. A가 접속하면 A의 Session, B가 접속하면 B의 Session이 따로 ..

멀티플레이 슈팅게임 만들기 (4)

슈팅게임 서버, C++로 처음부터 만들어보기 — TCP는 메시지 단위로 오지 않는다지금까지 만든 echo 서버엔 사실 치명적인 함정이 숨어있었다. TCP는 "바이트 스트림"이지 "메시지 스트림"이 아니다.직접 확인해봤다클라이언트에서 3000자짜리 문자열을 WriteLine 한 번으로 보냈는데, 서버 로그는 이랬다:Received 1024 bytesReceived 1024 bytesReceived 954 bytes한 번에 보낸 게 세 조각으로 쪼개져서 도착했다. 1024씩 잘린 건 내 수신 버퍼가 char buffer_[1024]였기 때문이다.반대로 여러 번 보낸 게 한 덩어리로 합쳐져 오기도 한다. 보낸 쪽이 "한 번에 썼다"는 사실은 받는 쪽에 전혀 전달되지 않는다.지금은 echo라 상관없지만, {"t..

멀티플레이 슈팅게임 만들기 (3)

슈팅게임 서버, C++로 처음부터 만들어보기 — 한 명 처리하다 막혀있던 문제지난 편까지는 한 명씩 순서대로 접속 받고 echo 해주는 서버였다. 근데 이거, 사실 치명적인 문제가 있다 — 한 명이 접속해서 아무것도 안 보내고 가만히 있으면, 다른 사람은 접속 자체가 안 되는 것처럼 멈춰버린다.직접 재현해봤다PowerShell 창 두 개 열어서:창 1: 접속만 하고 아무것도 안 보냄창 2: 접속하고 메시지 보냄 → 응답 대기결과: 창 2가 응답을 영원히 못 받고 멈춰있었다. 서버가 창 1을 처리하는 루프에 갇혀서, 창 2를 위해 다시 "새 접속 받아라"를 호출할 기회 자체가 없었던 거다.비동기로 전환accept(), read_some()처럼 "끝날 때까지 기다리는" 함수들을, async_accept, a..

멀티플레이 슈팅게임 만들기 (2)

슈팅게임 서버, C++로 처음부터 만들어보기 — 보낸 거 그대로 돌아오게 하기지난 편에서 접속만 받아서 로그 찍는 서버를 만들었다. 이번엔 한 단계 더 — 클라이언트가 보낸 텍스트를 그대로 돌려주는 echo 서버를 만들어봤다.뭘 바꿨나접속을 받고 바로 끊던 걸, read_some()으로 데이터를 읽고 write()로 그대로 돌려주는 루프로 바꿨다. 클라이언트가 연결을 끊으면(EOF) 루프를 빠져나와서 다시 다음 접속을 기다린다.char buffer[1024];while (true) { boost::system::error_code error; size_t length = socket.read_some(boost::asio::buffer(buffer), error); if (error ==..

멀티플레이 슈팅게임 만들기 (1)

슈팅게임 서버, C++로 처음부터 만들어보기 - 서버 올리기뭘 만들고 있나2D 멀티플레이 슈팅게임을 만들어보고 있다. 채팅, 경매, 방 생성, 보스 클리어 리워드, 매칭, 친구추가까지가 목표다.왜 클라이언트/서버를 나눴나멀티플레이 게임에서 제일 먼저 정해야 하는 건 "누가 진실을 결정하는가"다.보스 체력이 얼마 남았는지, 경매에서 누가 이겼는지 같은 걸 플레이어 각자의 게임 화면이 판단하게 두면, 클라이언트 값을 조작해서 우기는 걸 막을 수가 없다.그래서 서버 권위형(server-authoritative) 구조로 가기로 했다. 클라이언트는 요청만 보내고, 판정은 항상 서버가 한다.기술 스택클라이언트: Unity + C# — Unity는 스크립트가 C#만 지원해서 자연스럽게 결정됐다서버: C++ + Boo..

[Git] Git 커밋 덮어쓰기

저번엔 작업한 내용을 완전히 삭제하는 방법에 대해 글을 썼지만, 이번엔 오타나 사소한 수정같은 경우 history를 남기면서 작업하는건 상당히 깔끔해보이지 않기 때문에, 이번엔 커밋 덮어 쓰는 방법에 대해 글을 적습니다.1. 가장 최근 커밋 덮어쓰기: git commit --amend가장 흔하게 쓰이는 방법으로, 방금 만든 직전 커밋을 통째로 갈아 끼우거나 수정할 때 사용합니다.상황 A: 깜빡하고 빼먹은 파일이 있을 때Bash git add 빼먹은파일.javagit commit --amend --no-edit # 메시지는 그대로 두고, 방금 커밋에 파일만 쏙 집어넣어 덮어씀상황 B: 커밋 메시지를 오타 없이 고치고 싶을 때Bash git commit --amend -m "수정된 올바른 커밋 메시지"2...

Git 2026.09.08

[Git] Git 커밋 내역 및 작업 내용 삭제/초기화 명령어 총정리

Git으로 작업하다 보면, History가 더럽혀지는 꼴을 보지 못하는 사람들에게 유용한 Git Bash 명령어들을 정리해 드립니다.1. 최근 커밋 삭제하기 (git reset)git reset 명령어 뒤에 붙는 옵션(--soft, --mixed, --hard)에 따라 작업 중인 파일의 보존 여부가 달라집니다.① 커밋만 취소하고 작업 내역은 그대로 유지하기 (--soft / 기본값)코드 수정 내역은 남겨둔 채 커밋 상태만 취소하고 싶을 때 사용합니다.# 가장 최근 커밋 1개 취소 (수정 파일은 Staging 상태 유지)git reset --soft HEAD~1# 가장 최근 커밋 1개 취소 (수정 파일은 Unstaged 상태로 변경)git reset HEAD~1② 커밋 내역과 작업 파일 모두 완전히 삭제하..

Git 2026.08.31

맨해튼 거리(Manhattan Distance)

맨해튼 거리란?맨해튼 거리는 두 점 사이의 가로와 세로 이동 거리만을 고려해 계산하는 방식이다.도시 블록처럼 격자 구조에서 직선이 아닌, “블록 따라 이동하는 거리”를 수학적으로 표현한 개념이다. 공식 표현두 점 A(x₁, y₁), B(x₂, y₂)가 있을 때: 맨해튼 거리 = |x₁ − x₂| + |y₁ − y₂| 즉, x 좌표 차이의 절대값과 y 좌표 차이의 절대값을 더해 거리를 구한다. 예를 들어, A(2, 3) → B(5, 1)인 경우,|2 − 5| = 3 (가로 이동)|3 − 1| = 2 (세로 이동)총 거리 = 3 + 2 = 5맨허튼 거리는 게임 (타일 기반 거리)와 알고리즘 (휴리스틱, 탐색)에 주로 사용된다.#include #include using namespace std;int main..

C++/알고리즘 2025.08.22

소수 구하기

소수란?소수는 1과 자기 자신만을 약수로 가지는 수를 의미한다.예를 들어 7의 약수는 1과 7뿐이므로 7은 소수이다.반면 8은 1, 2, 4, 8을 약수로 가지므로 소수가 아니다.소수를 구하는 방법1. 직접 나눗셈 (시간 복잡도: O(N))2부터 N-1까지 모든 수로 나누어보아어떤 수로도 나누어떨어지지 않으면 소수라고 판단할 수 있다.하지만 수가 커질수록 연산량이 많아지는 비효율적인 방법이다.#include using namespace std;int main(){ int n; cin >>n; if (n 2. 제곱근까지만 나눗셈 (시간 복잡도: O(√N))소수가 아닌 수는 두 수의 곱으로 표현되는 합성수다.즉, N = a × b라고 하면, a와 b는 모두 1과 N 사이의 자연수이고a와 b가 모두 √N보다 ..

C++/알고리즘 2025.07.16