<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>acapz.dev</title><description>blog</description><link>https://acapz.dev/</link><language>en</language><item><title>로아시뮬 회고 3 - 시뮬레이션 엔진 만들기</title><link>https://acapz.dev/posts/lostarksim-mid-review-3/lostarksim-mid-review-3/</link><guid isPermaLink="true">https://acapz.dev/posts/lostarksim-mid-review-3/lostarksim-mid-review-3/</guid><description>성능, 성능을 보자</description><pubDate>Thu, 07 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;본격적으로 메인 기능인 시뮬레이터를 만들자!&lt;/p&gt;
&lt;p&gt;관성적으로 원래 웹서비스를 만들던 JS로 토대를 만들다가, 이런 생각이 났다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;JS는 single thread으로 돌아갈텐데, 성능(속도)가 나올까?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;특히 node.js는 io만 multi thread고 내부 로직은 single thread로 돌아가기 때문에 blocking 문제라도 해결하기 위해서 async/await을 쓴다고 네부캠에서 학습한 기억이 나서, 단순히 single thread으로 돌아가고 + 실행속도 자체도 느린 js으로 시뮬레이터가 커버될까 의문이 들었다.&lt;/p&gt;
&lt;p&gt;이번 프로젝트는 책임에 따라 module화를 잘 해놓은 덕분에 각 모듈마다 언어를 다르게 선정할수 있어서 시뮬레이터에 적합한 언어를 선정할 수 있었다. MSA의 장점이기도 하다.&lt;/p&gt;
&lt;p&gt;보통 이런 프로젝트에서 사용되는 언어는 C++이다. 다만 전에 sdl2 + mingw 빌드환경 만들면서 쓸데없는 개고생을 한적이 있어서 뭔가 거부감이 들기도 했고, C++는 메모리 관리하기가 되게 힘들다고 생각했다. 결정적으로 C++에 그렇게 익숙하지 않아서 만들면서 배울거면 최근 유행하는 Go나 Rust와 같은 언어를 해보는것도 나쁘지 않겠다 싶어서 무턱대고 C++를 고르지 않았다.&lt;/p&gt;
&lt;h1&gt;Simulator Stack 고민&lt;/h1&gt;
</content:encoded></item><item><title>로아시뮬 회고 2 - 전투정보실 만들어보기</title><link>https://acapz.dev/posts/lostarksim-mid-review-2/lostarksim-mid-review-2/</link><guid isPermaLink="true">https://acapz.dev/posts/lostarksim-mid-review-2/lostarksim-mid-review-2/</guid><description>왜 API를 그따구로 넘겨주는거야</description><pubDate>Thu, 30 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;일단 캐릭터의 시뮬레이션을 돌리기 위해서는, 캐릭터 정보를 게임사에서 받아올 필요가 있었다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./api.png&quot; alt=&quot;api&quot; /&gt;&lt;/p&gt;
&lt;p&gt;어?&lt;/p&gt;
&lt;h1&gt;파서랑 놀기&lt;/h1&gt;
&lt;p&gt;대충 읽어보니, 프론트에서 넘겨준 코드 그-대로 띄우면 되도록 주고있었다.&lt;/p&gt;
&lt;p&gt;왜 api 서비스가 프론트가 해야할 일을 대신해서 데이터를 활용하는 개발자들이 왜 2차 파싱을 해야하는지는 모르겠다...&lt;/p&gt;
&lt;p&gt;심지어 &lt;code&gt;element-001&lt;/code&gt; 와 같은 형태라서 이름으로 구분할 수 있는 것도 아니고, 각 요소마다 파싱을 일일히 따서 했어야 했다.&lt;/p&gt;
&lt;p&gt;기술적인 뭔가가 있는건 아니고 단순 노가다라서 여기서 시간이 오래 걸렸다. 다시 한번 모듈의 책임을 명확히 해야할 필요성과 api 서버를 짠다면, 데이터를 활용하는 개발자가 어떨지 생각해봐야 하지 않을까 다시 생각해보는 계기가 되었다.&lt;/p&gt;
&lt;h1&gt;CRA -&amp;gt; Vite&lt;/h1&gt;
&lt;p&gt;나는 특히나 프론트개발을 할 일이 별로 없었기 때문에 예전에 인터넷강의에서 들었던 CRA - CreateReactApp을 사용해서 React 페이지를 짜고 있었는데, 서버에서 프론트엔드 빌드가 너무너무 오래걸려서 이상하다는 생각이 들었다. 그렇게 복잡한 사이트도 아닌데 5~10분이상 걸린다는게 말이 안된다고 생각했다.&lt;/p&gt;
&lt;p&gt;구글링과 AI와 면담을 좀 하다보니 요즘은 Vite라는 대체재를 주로 사용한다고 했다. Vite로 migration하니 build속도가 약 1/10 수준으로 줄어서 놀랐다.&lt;/p&gt;
&lt;p&gt;CRA와 Vite는 &lt;strong&gt;Build Tool&lt;/strong&gt;인데, 이름이 tool인것처럼 다양한 일을 한다. 사용자가 요청한 웹페이지를 조금이라도 빠르게 받기 위해서는, 그 웹페이지의 코드가 짧고 효율적이어야 한다. 그리고 server에 가하는 부하도 줄어든다.&lt;/p&gt;
&lt;p&gt;그래서 build tool은 다음과 같은 작업을 한다:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;import하고 안쓰는 module/export하고 안쓰는 function 정리&lt;/li&gt;
&lt;li&gt;실제 동작에 필요없는 괄호 제거 (괄호를 안써도 어짜피 우선도가 높은 경우라던가)&lt;/li&gt;
&lt;li&gt;개발자가 활용하기 용이하도록 길게 작성된 변수명/함수명을 짧게 축약&lt;/li&gt;
&lt;li&gt;typescript로 작성된 코드를 javascript으로 변환 (ts으로 작성해도 실제로 돌아가는건 js다)&lt;/li&gt;
&lt;li&gt;여러 파일로 이루어진 코드들을 하나로 만들어서 보냄 (Bundling)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;예전에 번들러에 대해서 공부했을때는 ~파일이 여러개면 각각 네트워크 비용이 들어서 비효율적이다~ 이렇게 이해했는데 생각해보니 병렬로 보내면 크게 문제되지는 않다는걸 알게 되었다.&lt;/p&gt;
&lt;p&gt;TCP 연결이 제한되어있었던 구시대의 장점이지만, 여전히 코드를 효율화할 때 번들링을 하게 되면 중복된 부분을 크게 줄일 수 있는 장점이 남아있다.&lt;/p&gt;
&lt;p&gt;빌드 자체가 빨라지는 이유는 CRA은 webpack을 쓰고, Vite는 esbuild+rollup을 사용하기 때문이다. webpack은 js기반이고, esbuild는 go기반이라 근본적인 속도차이가 크게 난다. 애초에 esbuild가 webpack의 느린 속도 문제 때문에 개발되었다.&lt;/p&gt;
&lt;p&gt;Vite는 dev 레벨에서는 esbuild만을 사용해서 빌드속도가 매우 빠르고, prod 레벨에서는 안정성을 위해서 rollup을 사용하는데, esbuild로 의존성 번들링을 전처리 하고 rollup으로 최종 번들링을 하기 때문에 stable하지만 그래도 비교적 빠르게 빌드를 할 수 있게 된다.&lt;/p&gt;
&lt;p&gt;이제 CRA는 2022년이후로 update가 없는 depreciated 상태이므로 사용되는것이 권장되지 않는데, 이를 인지하지 못했던것 같다.&lt;/p&gt;
&lt;p&gt;이런 build tool의 성능 차이에 대한 원인이 언어에 있었던 만큼, 추후 시뮬레이터 언어 선정에 대해서 무의식적으로 영향을 끼친것 아닌가 싶었다.&lt;/p&gt;
</content:encoded></item><item><title>로아시뮬 회고 1 - 기획과 초기 설계</title><link>https://acapz.dev/posts/lostarksim-mid-review-1/lostarksim-mid-review-1/</link><guid isPermaLink="true">https://acapz.dev/posts/lostarksim-mid-review-1/lostarksim-mid-review-1/</guid><description>왜 로스트아크 시뮬레이터가 필요했는데?</description><pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;로스트아크 시뮬레이터 repo에 첫 커밋을 한지 약 1년 5개월이 지났다.&lt;/p&gt;
&lt;p&gt;연습용으로 재미도 없는 CRUD 사이트를 만드는 것보다 그냥 내가 진짜 필요한 서비스를 만드는 게 도움이 된다고 생각하는 주의라서 도전적인 주제로 개발을 시작하는데, 웹 개발을 잘 모르는 상태에서 무작정 박치기했기 때문에 오래 걸린 것 같다. 예전같았으면 현실적인 기술의 벽에 막혀서 허덕이다가 결국 프로젝트를 놓아버리는 경우가 잦았는데, AI 시대에 들어서면서 모르는것은 즉각적으로 피드백 받을수 있어서 가능했던것 같다.&lt;/p&gt;
&lt;p&gt;회고를 하면서 휘발될 수도 있었던 귀중한 경험을 빠뜨리지 않도록 해보자.&lt;/p&gt;
&lt;h1&gt;기획 의도&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;./arcana-screenshot.png&quot; alt=&quot;arcana&quot; /&gt;&lt;/p&gt;
&lt;p&gt;예전에 나는 아르카나라는 클래스를 주력으로 키웠다.&lt;/p&gt;
&lt;p&gt;아르카나라는 직업에 대해서 설명해보자면,&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;아이덴디티인 &apos;카드&apos;가 랜덤으로 뽑힌다.&lt;/li&gt;
&lt;li&gt;이 &apos;카드&apos;에 따라서 딜 사이클을 유연하게 변경해야 했다.&lt;/li&gt;
&lt;li&gt;따라서 딜 편차가 꽤 심한 편이었고, 카드가 뽑힌 즉시 상황판단을 해야해서 초보와 고수의 격차가 극심했다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이런 문제 때문에 아르카나 게시판에서는, 딜 사이클을 점검할 때 단순히 한 사이클 돌려보는 다른 직업과 다르게 5분/10분, 심하게는 1시간 정도 루메루스(허수아비)를 쳐야지 내 기대 dps를 알 수 있었다.&lt;/p&gt;
&lt;p&gt;정리하자면&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;내가 딜 사이클을 잘 굴리고 있는지 알기도 힘들고,&lt;/li&gt;
&lt;li&gt;내 기대 dps가 얼마나 되는지 알기 힘들었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;그리고 한창 기획을 하게 될 때는, 단순 장비레벨과 무기 강화수치로 얼추 캐릭터의 강함을 알 수 있는 시대를 넘어 엘릭서와 초월이라는 색다른 스펙업 수단이 생겨서, 이제 레벨만 보고서는 내가, 그리고 지원자가 얼마나 셀지 알 수 없었다.&lt;/p&gt;
&lt;p&gt;더 나아가 커뮤니티에서 밸런스 토론을 할 때, &quot;무슨무슨 직업이 지금 세다더라~&quot; 하는 경험담으로만 구전되는데,이는 각 캐릭터의 스펙 상태에 따라, 그리고 경쟁 상대의 스펙 상대에 따라, 그리고 서폿 버프차이에 따라 체감하는게 너무 다를 수 밖에 없어서 명확한 지표를 삼을 수 있는 무언가가 있었으면 좋겠다고 생각했다.&lt;/p&gt;
&lt;p&gt;그래서 내 캐릭터와 샘플 캐릭터의 예상 DPS를 도출해내는 시뮬레이터가 있으면 좋겠다고 생각했다.&lt;/p&gt;
&lt;h1&gt;유사 서비스 조사&lt;/h1&gt;
&lt;p&gt;특히 AI로 서비스를 만들기 쉬워진 요즘, 경쟁 서비스나 한국 게임의 다른 서비스가 어떠한 방식을 채용했는지 생각해봤다.&lt;/p&gt;
&lt;p&gt;생각해본것은 던전앤파이터의 &apos;던X&apos;과, 메이플스토리의 &apos;환X주스탯&apos;이었는데,&lt;/p&gt;
&lt;p&gt;&apos;던X&apos;는 특정 시간 내에 해당 스킬을 몇번 사용할 수 있는지 계산해서 스킬 데미지x사용 횟수를 모두 합산해서 계산하게 된다.
던전앤파이터라는 게임 특성상, 스킬 간 연계가 적어서 스킬의 쿨타임이 돌아오는 대로 사용하기 때문에 합리적이다.&lt;/p&gt;
&lt;p&gt;하지만 로스트아크의 경우에는, 스킬간 연계가 매우 강하고, 랜덤 요소가 많아서 맞지 않는 방법이다. 아르카나라는 직업 뿐만 아니라, &apos;예리한 둔기&apos;와 같이 확률적으로 데미지가 감소하는 각인을 대중적으로 많은 캐릭터가 사용한다. 제일 중요한 부분은, 던전앤파이터는 모든 직업이 100%의 크리티컬 확률을 맞추는 것을 기본으로 한다. 로스트아크는 치명타 확률이 모두 다르기 때문에 이에 따른 편차가 분명히 존재하게 되므로 기댓값과 편차가 더욱 커진다고 생각했다.&lt;/p&gt;
&lt;p&gt;&apos;환X주스탯&apos;은 각 직업마다 딜 사이클을 잘 소화하는 사람의 딜 지분(전체 데미지에서 각 스킬의 지분이 얼마나 되는지)을 수집해서 사용자의 캐릭터가 딜을 해도 대표 딜 지분과 유사하게 나올것으로 가정하고 DPS가 얼마나 나올지 예측하는 방식을 사용한다.&lt;/p&gt;
&lt;p&gt;이 또한 로스트아크는 연계 스킬이 많은 만큼, 단순 딜지분만으로 해당 캐릭터의 DPS를 예측하기 힘들다. 또한 로스트아크는 보석 차이에 따라서 스킬의 쿨타임이 크게 변하기 때문에 치명적이다. 예를들어 특정 직업의 고점 빌드는 스킬 하나가 밀리면 모든 스킬이 사용 불가능한 경우가 발생하는 경우가 발생한다.&lt;/p&gt;
&lt;p&gt;위와 같은 방법은 결과적으로 사용자 커뮤니티에서 정형화된 데이터를 개인화 작업에 바로 적용할 수 있어서 비교적 쉽게 사용자 캐릭터의 유효한 지표를 산출할 수 있었지만, 로스트아크라는 게임에서는 불가능하다고 생각했다.&lt;/p&gt;
&lt;p&gt;따라서 월드오브워크래프트의 &apos;Simulationcraft&apos;가 사용하는 몬테카를로 통계를 내는 방식이 제일 적합한 방식이라고 생각했다. 몬테카를로 방식은 진짜 시뮬레이터로 n번 돌려서 통계를 내는 방식이다. 무식하다면 무식하지만 직관적으로 결손치없는 통계를 뽑을 수 있는 장점이 있다.&lt;/p&gt;
&lt;h1&gt;초기 기술 Stack 선정&lt;/h1&gt;
&lt;p&gt;처음에 전체적인 아키텍처와 기술스택을 선정할 때, Raidbot 서비스를 참고했다. 참고로 Simulationcraft는 포터블한 시뮬레이터 자체를 의미하고, 웹에서 서버가 이 SimC를 돌리게 해주는 서비스가 Raidbot이다.&lt;/p&gt;
&lt;p&gt;필요한 기능을 생각해보자면&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;전투정보실 처럼 내 캐릭터를 볼 수 있는 기능&lt;/li&gt;
&lt;li&gt;시뮬레이션을 하기 위해서 내 캐릭터를 커스터마이징할 수 있는 기능&lt;/li&gt;
&lt;li&gt;실제 서버에서 시뮬레이션을 돌리고 결과를 보는 기능&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;여기서 전투정보실 기능과 시뮬레이션 기능이 동일한 게임데이터를 참조하기 때문에, docker를 공부하면서 컨테이너를 설계했다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;시뮬레이션 컨테이너&lt;/li&gt;
&lt;li&gt;프론트엔드 컨테이너&lt;/li&gt;
&lt;li&gt;게임 데이터 컨테이너&lt;/li&gt;
&lt;li&gt;FE에서 DB 컨테이너랑, 시뮬레이터 컨테이너를 단일 진입점으로 관리하기 위한 api-gateway 컨테이너&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;api-gateway 컨테이너는 지금와서 생각해보면 오버엔지니어링이었다. MSA가 한창 대세일때라서 MSA와 api-gateway 개념을 잡고가고 싶은 욕심이었던것 같다. 그리고 api-gateway도 직접 만드는게 아니라, 잘 만들어진 자동화된 라이브러리를 사용하는게 맞았다. be에서 api endpoint를 하나 수정하면 api-gateway도 수정해야하니 일을 두번해야 했다. 잘 모르는 상태에서는 필요에 의해서 기술 레이어를 추가하는게 옳다는 것을 배웠다.&lt;/p&gt;
&lt;p&gt;물론 해당 프로젝트가 &apos;실제 프로젝트를 만드는것&apos;과 &apos;웹 서비스를 처음 만들어보기&apos; 그 중간에 해당해서 생긴 병목이었지만.&lt;/p&gt;
</content:encoded></item><item><title>이리 메라찍음</title><link>https://acapz.dev/posts/er-meteor/er-meteor/</link><guid isPermaLink="true">https://acapz.dev/posts/er-meteor/er-meteor/</guid><description>히히</description><pubDate>Sun, 26 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;하다보면 느는것같아서 재밌다&lt;/p&gt;
&lt;p&gt;다음엔 미스릴도 도전해봐야지&lt;/p&gt;
</content:encoded></item><item><title>First post</title><link>https://acapz.dev/posts/begin/</link><guid isPermaLink="true">https://acapz.dev/posts/begin/</guid><description>첫 블로그 실패 후 회고 및 다짐</description><pubDate>Fri, 24 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;포트폴리오용 도메인을 산 김에 블로그를 새로 팠다.&lt;/p&gt;
&lt;p&gt;원래 티스토리 블로그가 있었는데, 일주일에 글 한개씩 정해두고 쓰다보니 나중엔 마감일에 맞춰서 AI로 대충 돌린 후 블로그에 버렸다. 점점 포스트가 늘었는데도 블로그가 보기 싫어져 자연스럽게 글쓰기랑 멀어지게 된 것 같다.&lt;/p&gt;
&lt;p&gt;FE 직군을 노린다면 직접 디자인한 포트폴리오 사이트가 더 유의미했을 것 같지만, 그냥 어떤 문제가 있었고 사고과정이 어땠는지 담담하게 기록하고, 가끔은 SNS처럼 했던 경험을 올리는게 좋을 것 같아서 블로그로 전환했다.&lt;/p&gt;
&lt;p&gt;사소한 일상을 적더라도, 이제는 나중에 다시 읽어보고 싶은 내 글을 적어야지.&lt;/p&gt;
</content:encoded></item></channel></rss>