AI와 노래 한 곡 만들기 — 스무 번의 단계와 세 번의 사고
노래 한 곡이 나오기까지
요즘 SVIL 스튜디오에는 오리지널 곡이 한 곡씩 쌓이고 있습니다. 가사도 멜로디도 목소리도 전부 로컬 워크스테이션 한 대에서 나옵니다. 그런데 버튼 하나 누르면 곡이 나오는 건 아니에요. 이 글은 곡 하나가 통과하는 스무 개 남짓한 단계를, 실제로 겪은 사고와 함께 적은 기록입니다.
시작은 질문 다섯 개
곡 작업의 첫 단계는 프롬프트가 아니라 질문입니다. 어떤 이야기인지, 누가 누구에게 하는 말인지, 감정이 어디서 시작해 어디로 가는지, 꼭 담고 싶은 문장이 있는지, 피하고 싶은 표현이 있는지. 이 다섯 개가 가사의 재료가 됩니다. 재료가 얇으면 어김없이 상투적인 가사가 나옵니다.

설명하지 말고 장면으로
가사를 쓸 때 규칙이 하나 있습니다. '외로웠다'라고 쓰지 않고 '편의점 불빛 아래 서 있던 너를'이라고 씁니다. 감정을 설명하는 순간 노래는 일기가 되고, 장면을 보여주면 듣는 사람이 자기 기억을 얹습니다.
민감한 이야기일수록 더 그렇습니다
실화를 바탕으로 한 곡일수록 직접 쓰지 않습니다. 몸이 불편했던 시간을 담은 곡에서는 그 단어 대신 '창밖은 늘 저만치 있었고'라는 문장을 썼습니다. 사연은 지키면서 노래로 만드는 방법입니다.

구조 태그 — 모델과의 약속
가사는 [verse] [pre-chorus] [chorus] [bridge] [outro] 태그로 구조를 표시해서 넘깁니다. 생성 모델이 이 태그를 읽고 절과 후렴의 에너지를 다르게 가져갑니다. 4분 곡 기준으로 본문 37줄 안팎이 적당했습니다.
엔진은 ACE-Step 1.5, 전부 로컬
작곡 엔진은 ACE-Step 1.5입니다. 한국어 가사를 받아 보컬까지 함께 생성합니다. 클라우드 API가 아니라 RTX 5060 Ti 한 장이 있는 로컬 워크스테이션에서 돌아갑니다. 4분짜리 곡 하나에 2분 안팎이 걸립니다.

GPU 한 장의 규율
이미지, 영상, 음성, 작곡이 같은 GPU 한 장을 나눠 씁니다. 그래서 규칙이 있습니다. VRAM에는 한 번에 엔진 하나만. 겹쳐 올리면 에러가 아니라 품질 저하로 나타나서, 로그는 멀쩡한데 결과물이 망가집니다. 조용한 실패가 제일 비쌉니다.
시드 — 같은 가사, 다른 곡
같은 가사와 같은 조건에서도 시드가 다르면 전혀 다른 멜로디가 나옵니다. 그래서 한 곡을 세 번 뽑아 고릅니다. 뽑아 놓고 고르는 것이 다시 만드는 것보다 쌉니다. 시드는 반드시 기록해 둡니다 — 나중에 같은 곡을 다시 만들 수 있는 유일한 열쇠입니다.

첫 번째 사고 — 음이탈
어느 날 세 곡 중 두 곡에서 음이탈과 불협화음이 났습니다. 듣는 순간 알 수 있는 종류였죠. 문제는 로그에 아무 이상이 없었다는 겁니다. 생성은 성공했고, 파일도 멀쩡했고, 길이도 정확했습니다.
원인은 프롬프트 한 줄
측정해 보니 원인이 나왔습니다. 프롬프트에 '힘차게 뻗는 후렴'을 주문하면서 음역 상한을 빼먹었던 겁니다. 모델은 '힘차게'를 음높이로 해석했고, 시드에 따라 마지막 후렴이 한 옥타브 위로 올라갔습니다. 사람이 낼 수 없는 대역에서 배음이 무너진 것이 불협화음의 정체였습니다.

귀를 수치로 바꾸다
그날 이후 곡이 나오면 자동으로 후반 구간의 음높이를 측정합니다. 최고음 한 점이 아니라 상위 5% 음높이를 봅니다. 순간적인 이탈은 최고음을 튀게 하지만, 상위 5%는 그 대역에 얼마나 머물렀는지를 보여줘서 실제 체감과 맞습니다.
규칙은 한 곳에만 둔다
음역 상한 규칙을 어디에 둘지가 문제였습니다. 작업 지침에 적으면 웹 화면이 낡고, 웹에 넣으면 자동화 경로가 빠집니다. 결론은 게이트웨이 서버 한 곳. 어느 경로로 곡을 만들든 같은 서버를 거치니, 규칙을 한 번만 고치면 전부 따라옵니다.

코드가 있다고 동작하는 건 아니다
관문을 만들고 커밋까지 했는데, 웹 화면 경로에서는 한 번도 걸리지 않고 있었습니다. 웹은 보컬 정보를 별도 필드가 아니라 프롬프트 문장에 녹여 보내고 있었거든요. 필드만 보던 관문이 통째로 비껴간 겁니다. 실제로 돌려보기 전까지는 아무도 몰랐습니다.
보컬 다음은 반주였다
보컬이 잡히니 반주가 보였습니다. 클래식 기타 반주에서 음정이 흔들리는 문제였는데, 생성 스텝을 올려도 잡히지 않았습니다. 접근을 바꿔야 했습니다.

코드 진행 3원칙
해법은 코드 진행을 프롬프트 맨 앞에 박는 것이었습니다. 첫째, 코드 진행을 무조건 고정한다. 둘째, 코드 밖 음을 금지한다. 셋째, 진행이 자연스러운지 먼저 검증한다. 검증된 정석 진행 다섯 가지를 서버에 목록으로 두고, 별칭 하나로 불러 쓰게 했습니다.
맨 앞이어야 하는 이유
왜 맨 앞이냐면, 생성 모델의 주의가 프롬프트 앞쪽 토큰에 쏠리기 때문입니다. 같은 문구도 꼬리에 붙이면 약하게 듣고 머리에 두면 강하게 듣습니다. 순서가 곧 우선순위입니다.

스텝 실험 — 8, 16, 20
생성 품질을 좌우하는 추론 스텝을 같은 시드로 8, 16, 20 세 번 뽑아 비교했습니다. 보컬의 감정 표현이 스텝과 함께 눈에 띄게 좋아졌습니다. 놀라운 건 시간이었는데, 150초, 120초, 100초로 오히려 줄었습니다.
공짜 품질은 받아야 한다
시간을 지배하는 건 스텝이 아니라 언어모델 플래너였던 겁니다. 스텝을 상한까지 올려도 비용이 없다면 안 올릴 이유가 없죠. 기본값을 상한인 20으로 고정했습니다. 커뮤니티 통념 중 '베이스 모델이 품질 상한'이라는 이야기도 확인해 봤는데, 공식 문서 기준으로는 터보가 최상이라 그대로 두었습니다.

프리셋 — 좋은 조합은 이름을 붙여둔다
'여자보컬 한국발라드 80BPM 기타솔로' 같은 조합이 마음에 들면 이름 붙여 저장합니다. 프리셋도 게이트웨이가 보관해서 웹 화면과 자동화 경로가 같은 목록을 봅니다. 다음 곡은 프리셋 하나 골라 가사만 넣으면 됩니다.
제목은 가사에서 꺼낸다
제목은 새로 짓지 않고 가사에서 꺼냅니다. 마지막 후렴의 끝 줄, 곡 전체의 깨달음이 모이는 한 마디가 대개 제목이 됩니다. 말하듯 얹는 한국 발라드 제목의 문법입니다.

새벽 4시의 청소부와 아카이브
이 워크스테이션에는 새벽 4시에 다운로드 폴더를 비우는 정리 작업이 돕니다. 곡 파일이 사라진 줄 알고 복구 소동을 벌인 적도 있죠. 지금은 곡이 나오는 즉시 전용 아카이브에 시드·발행 주소와 함께 보관됩니다. 기록 없는 작업은 완료가 아니라는 원칙이 여기서도 적용됩니다.
뮤직비디오 — 가사 한 줄이 한 장면
곡이 확정되면 뮤직비디오를 만듭니다. 가사 서른일곱 줄이면 장면도 서른일곱 개. 각 줄의 정서를 장면 묘사로 옮겨 이미지를 만들고, 켄번즈 효과와 인물 클립을 얹어 조립합니다. 자막은 균등 분할이 아니라 후렴과 아웃트로에 가중치를 둡니다.

발행 — 유튜브와 블로그
완성된 곡은 유튜브 SVIL 스튜디오 재생목록과 이 블로그에 함께 올라갑니다. 블로그에는 음원 플레이어와 가사 전문, 제작 노트가 실립니다. 심야에는 발행하지 않고 아침 8시로 예약합니다.
결국 사람이 하는 일
자동화가 늘어도 남는 일이 있습니다. 어떤 이야기를 노래로 만들지 정하는 일, 세 곡 중 하나를 고르는 일, 이 감정 표현이 맞는지 판단하는 일. 기계는 음높이를 재지만 좋은 노래인지는 귀가 정합니다. 그 역할 분담이 이 파이프라인의 뼈대입니다.

SVIL (Singularity Visual Intelligence Lab) — 전 과정 로컬 워크스테이션 제작
유튜브 인블루의 작업실 · 블로그 blog.svil.dev