알아보자 · · 읽는 시간 14분

Kortress Beach 제작기: 같이 앉아 노래를 듣는 밤바다를 만들기까지

이 글의 차례
  1. 바다에서 무엇을 할 수 있을까
  2. 함께 앉고 걷는 장면에 예전 기억을 담았다
  3. 손을 맞잡으면 손목의 어긋남이 먼저 보인다
  4. 바닥은 파도가 닿은 다음에 젖어야 했다
  5. 도화선에 불이 붙는 순간도 장면의 일부다
  6. 스파클러로 그린 선을 캐릭터의 손까지 이어 붙였다
  7. 같은 음악은 앉아 있는 시간을 이어 준다
  8. 다른 사람에게도 지금의 해변이 보여야 한다
  9. 예쁜 장면에 도착하기 전의 조작도 다듬고 있다
  10. 직접 둘러보고 이어서 읽기
  11. 구현과 촬영 기준

한국어 · English · 日本語 · 简体中文

밤바다를 함께 바라보고, 손에 든 불꽃을 켜고, 같은 노래를 듣는 공간을 만들고 싶었다. Kortress Beach의 출발점은 산사였다. 말을 많이 하지 않아도 다른 사람과 한 공간에 머무를 수 있다는 점에서 영감을 받았다. 그 생각을 내 사이트의 캐릭터와 내가 기억하는 장면으로 옮긴 것이 Beach다.

처음에는 산사처럼 투박하지만 귀여운 캐릭터를 따로 만들어 넣을까 생각했다. 결국 Kortress의 마스코트인 코시(Korsh)를 사용하기로 했다. Kortress에서 쓰던 코시를 Beach에도 등장시켰다. 오붓한 분위기를 만들고 캐릭터의 모습을 다양하게 하고 싶어 여자 코시도 추가했다. 여자 코시의 이름은 아직 정하지 않았다.

현재 버전에서 나란히 앉은 코시들. 2026년 11월 4일 로컬 시뮬레이션 모드에서 촬영했다. 함께 보이는 캐릭터는 컴퓨터 캐릭터다.

현재 버전에서 나란히 앉은 코시들. 2026년 11월 4일 로컬 시뮬레이션 모드에서 촬영했다. 함께 보이는 캐릭터는 컴퓨터 캐릭터다.

이 글은 기능을 소개하면서 그 장면 뒤에서 무엇을 고쳤는지도 함께 기록한 제작기다. 코드는 2026년 11월 4일의 0280637 커밋을 기준으로 살폈다. 새로 촬영한 현재 화면과 보관해 둔 개발 중 영상을 구분해 실었다. 영상 속 Mina는 테스트 상대의 닉네임이며 여자 코시의 이름이 아니다.

영감을 준 공간이 궁금하다면 산사에서 살펴본 말없는 상호작용을 먼저 읽어도 좋다.

바다에서 무엇을 할 수 있을까

Kortress Beach에 들어가면 닉네임과 캐릭터를 선택한다. 이후 해변을 돌아다니거나 도구를 골라 불꽃을 켤 수 있다. 혼자 주변을 구경해도 되고, 다른 사람에게 함께할 행동을 제안해도 된다.

현재 도구 메뉴에는 빈손 외에 다섯 종류가 있다. 손에 드는 스파클러와 손 연발, 땅에 놓는 분수와 터지는 연발, 큰 꽃 연발이다. 손 가까이에서 빛나는 불꽃과 먼 하늘로 올라가는 불꽃은 바라보는 거리부터 다르다. 도구의 종류에 따라 손에 들거나 바닥에 놓는 과정도 달라진다.

하고 싶은 일화면에서의 행동함께 보면 좋은 부분
해변 돌아보기이동하고 화면을 돌리거나 확대·축소하기캐릭터와 수평선의 거리
작은 불꽃 켜기스파클러나 손 연발 선택 후 점화하기손과 도구 끝의 움직임
바닥에 불꽃 놓기분수·연발을 배치하고 점화하기도구 간격, 점화 자세, 발사 방향
빛으로 쓰기스파클러 글쓰기 화면에서 직접 선 그리기입력한 선과 캐릭터 팔의 연결
함께 머무르기상대에게 나란히 앉기·손잡고 걷기 제안하기수락 후의 거리와 시선
같은 노래 듣기음악 같이 듣기로 YouTube 음악 공유하기앉기·걷기와 음악을 함께 유지하기

데스크톱에서는 WASD나 방향키로 움직이고, 드래그로 시점을 돌린다. 휠은 거리 조절, Shift는 달리기, Space는 점프에 쓴다. F는 상황에 따라 놓기나 점화에 쓰인다. 처음에는 단축키를 외우기보다 화면에 나타나는 도구 이름과 행동 버튼을 따라가는 편이 쉽다. 모바일에는 별도의 이동 패드와 점프 버튼을 두었다.

함께 앉고 걷는 장면에 예전 기억을 담았다

나란히 앉기, 같이 걷기, 노래를 함께 듣는 기능에는 예전 기억이 들어 있다. 불꽃이 쉬는 순간에도 함께 앉아 있을 수 있고, 앉아 있는 동안 같은 음악을 들을 수 있게 했다. Beach에서 오붓한 분위기를 만들고 싶었다는 생각은 캐릭터의 모습뿐 아니라 이런 행동에도 이어졌다.

영상으로 보기: 서로 바라보기 — 개발 중 프로토타입

함께하는 행동은 상대를 선택하고 제안한 뒤 수락을 기다리는 방식이다. 캐릭터 둘을 장면에 놓고 정해진 애니메이션 하나를 재생하면 끝날 것 같지만, 실제로는 준비해야 할 것이 많았다. 서로 떨어져 있다면 가까워져야 하고, 각자의 모델 준비가 끝나는 시점도 다르다. 기다리던 중 취소하거나 연결이 끊길 수도 있다. 이미 취소한 준비 작업이 늦게 끝나 새 상태를 덮어쓰지 않도록 막아야 했다.

이 때문에 코드에는 요청, 접근, 준비, 활성 상태와 취소 처리가 함께 들어 있다. 접근과 준비에 제한 시간을 두고, 준비됐다는 신호를 다시 보내며, 오래된 비동기 작업을 걸러낸다. 둘이 함께 있는 짧은 장면도 서로 다른 두 화면에서 같은 순서로 성립해야 했다. 버튼을 누른 뒤 아무 일도 없는 것처럼 보이는 시간이 길어지면 그 장면까지 가기 전에 관심이 끊긴다.

특히 수락 순간에 실제 캐릭터 리그를 복제하고 손바닥 표면과 보행 데이터를 측정하던 작업은 부담이 됐다. 매번 할 필요가 없는 측정을 준비 데이터로 옮기고 기존 머티리얼과 보행 표를 재사용했다. 모델이나 계산 방식이 바뀌면 이전 데이터가 그대로 쓰이지 않도록 지문도 확인한다. 여기서 줄이고 싶었던 것은 화면 속 행동의 길이가 아니라, 행동을 시작하기 위해 반복하던 준비 작업이었다.

이 내용은 저장소의 deploy/couple-stability-2026-11-03.md에 수정과 검증 범위가 남아 있다.

손을 맞잡으면 손목의 어긋남이 먼저 보인다

영상으로 보기: 손잡고 걷기 — 개발 중 프로토타입

손잡고 걷기는 두 캐릭터를 같은 속도로 움직이는 일보다 손이 만나는 모양이 더 까다로웠다. 손의 위치만 가까이 두면 손바닥 방향이 틀어지거나 팔이 당겨질 수 있다. 이를 손목 하나의 회전으로 해결하려 하면 피부가 사탕 포장지처럼 꼬이는 문제가 생긴다.

현재 구현은 손바닥의 중심과 방향을 기준으로 접촉 관계를 잡고 양쪽 팔을 반복해서 보정한다. 팔 길이가 모자라는 자세에서는 접촉점도 조정한다. 손목에 회전이 몰리지 않도록 어깨와 아래팔 쪽으로 비틀림을 나누는 처리도 있다. 손가락을 쥐는 모양과 맞잡는 모양 역시 자세의 일부로 다룬다.

여기에 쓰인 IK는 손이 있어야 할 위치를 정한 뒤 팔 관절을 맞추는 방법이다. 이름보다 중요한 것은 결과다. 몸이 움직이고 고개가 돌아가더라도 손은 상대와의 관계를 유지해야 한다. 정지 화면에서는 괜찮던 손이 걷기 시작하면 어색해지는지 함께 봐야 했다.

서로 바라보는 고개 회전, 걷다가 멈추는 가중치와 속도도 서서히 바꾸도록 했다. 다만 모든 앉기·일어서기 전환이 하나의 완성된 전신 애니메이션으로 이어지는 단계는 아니다. 지금 다듬은 부분과 앞으로 더 자연스럽게 만들 부분을 구분해 두고 싶다.

현재 버전의 서로 보기 기능. 로컬 시뮬레이션의 컴퓨터 캐릭터와 촬영했다.

현재 버전의 서로 보기 기능. 로컬 시뮬레이션의 컴퓨터 캐릭터와 촬영했다.

바닥은 파도가 닿은 다음에 젖어야 했다

바다와 젖는 바닥은 특히 신경 쓴 부분이다. 물에 반짝임을 더하고 모래를 어둡게 만드는 것만으로는 물가처럼 보이지 않았다. 작은 순서가 어긋나도 파도가 배경 효과처럼 느껴졌다.

실제로 코드에 남아 있는 피드백 중에는 젖은 바닥이 먼저 생긴 뒤 파도가 들어와 순서가 반대로 보인다는 지적이 있다. 이전 방식은 새 파도가 시작될 때 그 파도가 나중에 도달할 끝 지점까지 미리 젖은 것으로 처리했다. 다음 파도로 넘어갈 때 이전 자국의 모양도 갑자기 바뀌었다. 물보다 젖은 흔적이 앞서고, 흔적이 끊기는 두 문제가 겹친 것이다.

개선 전: 물가의 파도 표현 — 개발 중 프로토타입

개선 후: 물가의 파도 표현 — 개발 중 프로토타입

두 영상은 개발 당시 파도 표현 비교 자료이며, 아래의 현재 젖음 처리만을 따로 검증한 대조 실험은 아니다.

현재는 이번 파도가 실제로 도달한 최대 지점만 기록한다. 동시에 직전 파도가 남긴 끝 지점과 무늬, 물이 물러난 시간도 따로 기억한다. 새 파도가 시작됐다고 이전 흔적까지 새 무늬로 바꾸지 않는다. 앞선 파도의 자국은 자기 시간에 따라 마르고, 다음 파도는 실제로 들어온 만큼만 새 자국을 만든다.

그 흐름을 순서로 쓰면 이렇다.

  1. 흰 물결이 물가 쪽으로 다가온다.
  2. 물이 닿은 범위까지 젖은 영역을 넓힌다.
  3. 물은 물러나지만 젖은 자국은 남긴다.
  4. 남은 자국의 어두움과 광택을 시간이 흐르며 줄인다.
  5. 다음 파도가 들어와도 아직 남아 있는 앞선 자국을 함께 계산한다.

젖은 정도는 exp(-age/9) 형태로 줄인다. 9초 뒤 갑자기 완전히 마르는 타이머가 아니라 시간이 지날수록 서서히 약해지는 감쇠다. 이 값은 모래 색, 광택, 하늘 반사와 불꽃 빛의 반응에 이어진다. 무엇이 얼마나 반짝이는지에 앞서 왜 그 자리가 아직 젖어 있는지 설명할 수 있게 만든 셈이다.

파도가 들어오고 빠지는 시점은 철썩이는 소리와도 맞춘다. 앞바다의 흰 선, 물가로 들어오는 선, 뒤에 남는 거품은 서로 다른 역할을 한다. 완전한 유체 시뮬레이션을 만든 것은 아니다. 눈에 보이는 흔적과 귀에 들리는 소리가 같은 파도를 가리키도록 절차적으로 연출한 바다다.

이 수정은 풍경의 설득력이 한 프레임뿐 아니라 장면의 연결에서도 나온다는 사례다. 앞 장면의 결과가 다음 장면에 남아 있어야 한다. 젖은 모래에서는 그 기억이 짧게 남는 파도 자국이었다.

도화선에 불이 붙는 순간도 장면의 일부다

불꽃 도구의 리얼함에도 공을 들였다. 버튼을 누르면 캐릭터가 도구를 다루고 불을 붙이는 과정을 보여준다. 손에 든 도구와 땅에 놓은 도구는 불을 붙이는 자세부터 달라야 한다.

점화 동작 보기 — 손을 뻗고 도구를 켜는 개발 중 프로토타입

현재 코드는 손 도구와 지면 도구의 점화 도달 시간과 전체 동작 시간을 따로 둔다. 바닥의 도구에 불을 붙일 때는 캐릭터가 몸을 돌리고 낮춘다. 이때 몸통만 숙이면 발도 함께 밀리는 것처럼 보일 수 있다. 그래서 발 위치와 방향을 저장하고, 다리 관절을 보정해 발을 원래 자리에 두도록 했다.

오른손이 쥔 점화봉은 끝이 도화선에 닿도록 팔을 다시 맞춘다. 점화가 끝나면 들고 있던 자세로 돌아오는 시간도 둔다. 중요한 것은 불꽃의 밝기뿐 아니라 손, 봉 끝, 도화선이 같은 사건을 보여주는 것이다. 불이 켜졌는데 손이 다른 곳을 가리키면 도구를 사용했다는 느낌이 약해진다.

현재 버전 해변의 도구 배치와 점화 주변 장면. 로컬 시뮬레이션에서 촬영했다.

현재 버전 해변의 도구 배치와 점화 주변 장면. 로컬 시뮬레이션에서 촬영했다.

도구마다 효과의 성격도 나눴다. 스파클러는 손 근처에서 이어지는 빛을, 분수는 바닥에서 솟는 분사를 보여준다. 연발과 큰 꽃은 발사와 터지는 순서를 가진다. 이 구분은 모든 화약의 물리를 정확하게 재현했다는 뜻은 아니다. 어디에 놓고 어떻게 불을 붙여 어떤 빛이 나오는지, 화면 안에서 납득할 수 있게 만드는 작업이다.

현재 버전에서 손에 든 스파클러가 얼굴과 주변을 비춘다. 로컬 시뮬레이션에서 가까운 각도로 촬영했다.

현재 버전에서 손에 든 스파클러가 얼굴과 주변을 비춘다. 로컬 시뮬레이션에서 가까운 각도로 촬영했다.

스파클러로 그린 선을 캐릭터의 손까지 이어 붙였다

빛으로 글씨 쓰기 — 개발 중 좌표 매핑 비교 영상

스파클러 글쓰기는 화면에 텍스트를 입력해 띄우는 기능과 다르다. 사용자가 직접 그린 선을 캐릭터가 든 도구의 궤적으로 연결한다. 위 영상은 개발 중 입력과 팔의 움직임을 맞추던 비교 화면이며, 현재 UI는 전체 화면 캔버스를 사용한다.

마우스나 손가락이 움직이는 곳은 평면 화면이고, 캐릭터의 손은 입체 공간에 있다. 화면 좌표를 그대로 넓은 공간으로 바꾸면 손이 닿을 수 없는 점이 생긴다. 캐릭터의 팔 길이와 도구 방향, 글을 쓸 평면의 크기를 함께 정해야 했다.

현재는 입력 좌표를 캔버스 기준으로 정규화한 뒤 팔이 닿는 쓰기 공간으로 옮긴다. 입력 면적을 키우는 것과 캐릭터의 움직임을 키우는 것은 같은 일이 아니다. 작은 화면에서도 그리기 편하게 하되, 장면에서는 손이 무리하게 뻗지 않아야 한다. 전체 화면 쓰기 UI로 바꾼 것도 이 입력 경험을 정리하는 과정이었다.

독자 입장에서는 선을 그리는 짧은 동작이지만, 제작할 때는 화면 입력과 캐릭터의 몸을 함께 다뤄야 하는 기능이었다. 불꽃의 궤적은 손에 든 도구의 움직임과 연결된다.

같은 음악은 앉아 있는 시간을 이어 준다

음악 같이 듣기 UI — 개발 중 프로토타입·무음 녹화

같은 노래를 함께 듣는 기능에도 예전 기억을 담았다. 그래서 음악을 시작한다고 앉기나 걷기를 먼저 끝내지 않도록 했다. 이미 함께 앉거나 걷는 상대에게 음악을 덧붙일 수 있다. 코드에서도 기존 동행 행동을 유지하고 그 안에 음악 상태를 연결한다.

음악은 YouTube 재생을 이용한다. 요청한 쪽이 기준 재생 시각을 주기적으로 보내고, 받은 쪽은 전달 이후 흐른 시간을 고려한다. 재생 위치가 2초보다 많이 어긋나면 해당 위치로 이동시킨다. 두 화면이 완전히 같은 오디오 시계로 움직이는 것은 아니며, 서로의 버퍼링 상태까지 공유하지는 않는다.

외부 영상의 임베드 제한이나 브라우저 자동 재생 정책도 영향을 준다. 차단됐을 때 오류를 안내하고 자동으로 재생되지 않으면 직접 재생하도록 안내하는 경로가 있다.

위 영상은 테스트 상대를 이용한 공유 UI 시연이다. 실제 두 사람의 네트워크 재생 검증 영상과는 구분한다.

다른 사람에게도 지금의 해변이 보여야 한다

혼자 보는 불꽃과 다른 사람과 함께 보는 불꽃은 구현할 문제가 다르다. 나중에 들어온 사람에게도 이미 바닥에 놓인 도구가 보여야 한다. 누군가 불을 켰다면 다른 화면에서도 그 도구가 켜진 상태여야 한다. 앉은 사람의 손 모양이 관찰자에게는 엉뚱한 자세로 보이는 문제도 다뤄야 한다.

Beach는 모든 불꽃 입자의 좌표를 계속 보내는 방식으로 만들지는 않았다. 도구의 종류, 위치, 진행 상태와 시간 같은 정보를 나눠 보내고 각 화면에서 효과를 구성한다. 빠르게 바뀌는 손 도구, 캐릭터 이동, 비교적 오래 남는 바닥 도구의 전송 주기도 구분한다. 바닥 도구는 전체 목록을 다시 보내 누락된 상태를 맞추고, 비어 있는 목록 역시 보내 오래된 도구를 지운다.

함께하는 캐릭터의 자세는 행동 이름만 공유하는 것으로 끝내지 않았다. 애니메이션과 관절 보정 후의 실제 자세, 손가락을 쥐는 모양까지 전송·복원하는 처리가 있다. 누군가가 “앉기 중”이라는 사실과 지금 어떤 자세로 앉아 있는지는 서로 다른 정보였기 때문이다.

연결과 후입장 복구를 위한 장치를 넣었지만 이것이 모든 끊김을 없앴다는 뜻은 아니다. 현재 방 정원 같은 설정값도 실제 여러 기기에서 쾌적하게 움직인다는 성능 측정과는 다르다.

예쁜 장면에 도착하기 전의 조작도 다듬고 있다

최근 변경에는 달리기, 점프, 입장 안내, 모바일 조작 개선이 포함돼 있다. 달리기는 걷기 재생 속도만 높이는 방식에서 별도의 Run 애니메이션으로 바꿨다. 기존 리그와 애니메이션을 유지하면서 달리기 데이터를 추가하고, 실제 신발과 손의 형상을 측정해 움직임을 확인했다. 그 뒤에도 팔과 손목, 보폭 타이밍을 다시 조정한 기록이 이어진다.

두 코시의 달리기 동작을 확인한 개발 프리뷰

해변 플레이 화면이 아닌, 두 코시의 달리기 애니메이션을 확인하던 개발 프리뷰다.

모바일에서는 보이지 않는 이동 판정 영역이 보이는 패드보다 넓어, 시점을 돌리려다 캐릭터가 움직일 수 있었다. 이동 영역과 엄지가 닿는 위치를 정리하고 화면 가장자리와 도구 바를 함께 고려했다. 작은 화면에서 버튼이 겹치지 않는 확인과 실제 휴대폰의 발열·프레임 확인은 별도로 봐야 한다.

입장 과정에서도 캐릭터 준비가 끝나기 전에 조작이 시작되지 않도록 했다. 오래 기다리거나 오류가 생기면 상태를 알리고 재시도할 수 있게 했다. 입장 뒤에는 이동 방법을 알려준다. 바닷가에서 무엇을 할지 모르는 상태나 화면이 멈춘 듯한 대기 역시 제작에서 해결해야 할 부분이었다.

다음에 점검할 항목도 이런 작은 끊김이다. 처음 온 사람이 움직임을 이해하는지, 제안 후 기다리는 이유를 아는지, 두 사람이 행동을 끝낼 때 어색하지 않은지가 기준이 된다. 손을 잡고 음악을 듣는 기능이 있어도 그 장면까지 가는 과정이 어렵다면 의도가 충분히 전달되지 않는다.

산사에서 받은 영감은 Beach에서 코시, 바다, 불꽃과 음악으로 이어졌다. 내가 공들인 것은 함께 있는 시간이 어색해지지 않도록 작은 동작과 흔적을 이어두는 일이었다.

직접 둘러보고 이어서 읽기

구현과 촬영 기준

구현 설명은 Beach 저장소 web/index.html, 네트워크 코드, 2026년 11월 3~4일 변경 기록 및 동행 안정화 보고서를 대조했다. 현재 화면은 2026년 11월 4일 공개 배포본의 로컬 시뮬레이션에서 촬영했다. 개발 영상은 별도 보관된 프로토타입 자료이며 실제 방문자나 운영 성능의 증거로 사용하지 않았다. 세부 근거와 미디어 원본 목록은 집필용 조사 보고서에 별도로 보관했다.

1 / 1