← All articles

엔지니어링 노트

Image to Prompt에서 스타일 보존하기: 무엇을 바꿨고 왜 바꿨는가

저희의 Image to Prompt 도구는 피사체는 정확히 맞혔지만 스타일은 틀리게 만들고 있었습니다. 90년대의 거친 스냅사진이 세련된 영화 포스터로 되돌아오는 식이었습니다. 이 글은 왜 그런 일이 일어나는지, 저희가 무엇을 바꿨는지, 그리고 어떤 부분을 어떤 도구에서든 직접 손으로 적용할 수 있는지에 대한 기록입니다.

Cover image for Image to Prompt에서 스타일 보존하기: 무엇을 바꿨고 왜 바꿨는가

피사체는 충실하지만 스타일은 잘못된 경우

신고 내용은 일관되었습니다. 누군가 레퍼런스를 업로드하고, 프롬프트를 받고, 그것을 실행하면 결과물은 알아볼 수 있을 만큼 같은 장면입니다. 같은 피사체, 같은 프레이밍, 대략 같은 빛인데도 자신의 이미지처럼 보이지 않습니다. 질감은 더 깨끗해지고, 색은 더 풍부해졌으며, 무언가가 매끈하게 다듬어져 있습니다.

이 패턴은 하나의 단서입니다. 피사체와 구도는 살아남지만 표면과 마감은 살아남지 못한다면, 프롬프트가 프레임이 어떻게 만들어졌는지가 아니라 프레임 안에 무엇이 있는지만 묘사하고 있다는 뜻입니다. 이 둘은 서로 다른 작업이며, 두 번째 작업이 훨씬 틀리기 쉽습니다.

스타일은 아홉 개 항목 중 하나에 불과했다

저희가 비전 모델에게 내린 지시는 원래 '피사체, 배경, 구도, 렌즈 혹은 시점, 조명, 팔레트, 재질, 분위기, 스타일'을 담아내라는 것이었습니다. 언뜻 철저한 체크리스트처럼 보이지만, 실제로는 스타일이 전체 주의력의 9분의 1만 받도록 보장하는 방식이었습니다.

단순 나열형 목록은 균등한 배분을 유도합니다. 하지만 스타일은 아홉 개 속성 중 하나가 아니라, 나머지 여덟 개가 어떻게 렌더링될지를 결정하는 요소입니다. 게다가 말로 표현하기 가장 어려운 요소이기도 해서, 추가적인 안내가 가장 필요하면서도 이런 목록에서는 가장 안내를 받지 못하는 항목이 됩니다.

스타일에 형용사가 아니라 어휘를 부여하라

언어 모델에게 스타일이 무엇으로 이루어져 있는지 알려주지 않은 채 스타일을 묘사하라고 하면, 그 개념에 가장 가까운 단어들, 즉 '디지털 아트', '매우 정교한', '시네마틱한' 같은 단어를 집어 듭니다. 이런 것들은 묘사가 아닙니다. 눈앞에 있는 특정 이미지에 대한 정보를 거의 담고 있지 않습니다.

더 나쁜 것은, 이런 표현들이 빈틈을 남긴다는 점입니다. 그러면 다운스트림의 이미지 모델이 그 빈틈을 자신의 기본 미학으로 채워버리는데, 이는 정확히 여러분이 덮어쓰려던 바로 그것입니다. 해결책은 스타일이 실제로 분해되는 축을 명확히 짚어주어, 모델이 구체적으로 참고할 곳을 갖게 하는 것입니다.

  • 매체와 기법: 35mm 필름 사진, 구아슈, 3D 렌더, 플랫 벡터, 잉크 라인 아트.
  • 시대나 사조. 이는 종종 어떤 단일 형용사보다 더 많은 정보를 담고 있습니다.
  • 카메라의 특성: 초점 거리의 느낌, 피사계 심도, 필름 종류, 혹은 모방하고 있는 렌더 엔진.
  • 마크 메이킹(mark-making): 선의 굵기, 붓의 움직임, 엣지의 질, 표면이 맞닿는 방식.
  • 색 보정과 색온도. 어떤 색이 등장하는지와는 별개로 고려합니다.
  • 그레인, 질감, 표면 마감.
  • 후처리: 헐레이션(halation), 색수차, 하프톤 도트, 셀 셰이딩, 강한 압축.

레퍼런스를 절대 업그레이드하지 말 것

이 부분은 저희조차 놀랄 만큼 중요했습니다. 파이프라인 안의 모든 모델, 즉 이미지를 읽는 모델과 프롬프트로부터 생성하는 모델 모두 개선 편향(improvement bias)을 갖고 있습니다. 평면적이거나, 노출이 부족하거나, 조명이 값싸거나, 압축된 이미지를 주면 조용히 더 나은 버전을 돌려줍니다.

하지만 불완전함도 하나의 스타일입니다. 직접 플래시를 사용한 파티 사진, 하이라이트가 날아간 휴대폰 스냅샷, 밴딩이 보이는 저해상도 스캔 같은 특성들은 대개 누군가가 그 이미지를 저장한 바로 그 이유입니다. 그래서 이제 지시문은 명확히 말합니다. 이미지가 아마추어스럽거나, 평면적이거나, 화질이 낮거나, 불완전하다면 그것을 있는 그대로 말하고 유지하라고요.

직접 프롬프트를 작성한다면, 이것이 가장 손쉽게 적용할 수 있는 개선점입니다. 결함을 의도적으로 묘사하세요.

속이 빈 품질 단어는 공짜가 아니다

'아름다운', '멋진', '걸작', '매우 정교한', '8k', '수상작'. 이런 표현들은 마치 볼륨 손잡이를 돌리는 것처럼 무해해 보입니다. 하지만 그렇지 않습니다. 프롬프트에는 한정된 주의력 예산이 있고, 채움말 하나하나가 실제로 이미지를 묘사하는 단어들의 몫을 가져갑니다.

게다가 이런 표현들은 결과를 평균 쪽으로 끌어당깁니다. '수상작'이라는 말은 시각적으로 아무런 의미가 없으므로, 모델은 그것을 자신이 학습한 '수상작처럼 보이는 것'으로 해석합니다. 이는 여러분의 레퍼런스와는 동떨어진, 강력하지만 흔한 미학입니다. 이제 저희 지시문은 이런 단어 목록을 명시적으로 금지합니다.

프롬프트를 쓰기 전에 스타일부터 파악하라

분석과 출력을 한 단계에서 요청하면 모델은 스타일을 그저 근처에 있는 아무 형용사로 채우는 빈칸처럼 취급하게 됩니다. 이제 지시문은 두 단계로 실행됩니다. 아무것도 쓰기 전에 모델은 먼저 매체와 제작 기법을 파악한 다음, 하나의 구체적인 질문에 답합니다.

그 차이를 명확히 짚어내는 것이 이 작업의 전부입니다. 일단 그것이 명명되면, 프롬프트는 매체와 스타일을 피사체보다 앞세워 작성됩니다. 모든 타깃 모델이 이 부분에 가장 큰 가중치를 두기 때문입니다.

모든 모델은 프롬프트를 다르게 읽는다

저희가 이전에 모델별로 두었던 지시문은 어조를 조정하는 데 그쳤습니다. Midjourney 프롬프트는 '함축적으로', GPT Image 프롬프트는 '직접적이고 문자 그대로' 쓰라는 식이었습니다. 이는 문체상의 톤일 뿐, 스타일이 살아남는지를 결정하는 요인이 아닙니다.

이를 결정하는 것은 모델이 사용하는 텍스트 인코더, 프롬프트 안에서 스타일 관련 단어가 위치하는 곳, 그리고 모델이 제공하는 고유한 제어 기능입니다. 이런 것들은 구체적이며, 대부분의 프롬프트 가이드가 인정하는 것보다 훨씬 더 큰 차이를 만듭니다.

  • Nano Banana와 GPT Image는 자연어 산문을 읽습니다. 피사체보다 먼저, 첫 문장에서 매체를 선언하세요.
  • Flux는 T5 인코더를 사용하며 긴 문장을 잘 처리하지만, (term:1.2)와 같은 가중치 문법은 완전히 무시합니다. 강조는 단어 선택과 어순에서 나와야 합니다.
  • Midjourney는 프롬프트 앞부분에 무거운 가중치를 두고, 쉼표로 구분된 밀도 높은 구문을 선호하며, 문장 형태로 쓰인 부정 표현을 이해하지 못합니다.
  • Stable Diffusion은 CLIP 토큰을 77토큰 단위로 읽고 각 청크의 앞부분에 가중치를 두므로, 매체와 스타일 태그는 맨 뒤가 아니라 맨 앞에 와야 합니다.

Midjourney에는 여러분의 묘사와 싸우는 파라미터가 있다

이 글에서 가장 유용한 내용이지만, 사실 프롬프트 작성 기법은 전혀 아닙니다. Midjourney는 --stylize에 의해 통제되는 자체 미학을 여러분의 프롬프트 위에 덧씌우며, 기본값은 100입니다. 이 설정에서는 모델이 여러분이 요청한 것보다 'Midjourney답게' 이미지를 만들도록 적극적으로 유도됩니다.

그래서 레퍼런스를 변환하는데 결과물이 계속 원본보다 더 세련되고, 더 시네마틱하고, 더 아트 디렉팅된 느낌으로 돌아온다면, 아무리 묘사를 더해도 고칠 수 없습니다. 바로 이 파라미터가 여러분의 의도를 덮어쓰고 있는 것입니다.

이제 저희가 생성하는 모든 Midjourney 프롬프트는 그 고유 미학을 비활성화하는 --style raw로 끝나며, --stylize도 50 정도로 낮게 설정합니다. 제외할 항목은 문장이 아니라 --no로 표현하는데, 여기서는 문장 형태의 부정이 통하지 않기 때문입니다.

Stable Diffusion에서는 프롬프트의 절반이 네거티브 프롬프트다

Stable Diffusion 사용자는 프롬프트와 네거티브 프롬프트, 두 개의 블록을 기대합니다. 스타일 충실도는 후자에 크게 의존하는데, 그렇지 않으면 모델이 적용했을 기본 미학으로의 쏠림을 억제하는 곳이 바로 여기이기 때문입니다.

저희는 첫 번째 블록만 생성하고 있었는데, 이는 결과물의 절반에 불과했습니다. 이제 생성되는 Stable Diffusion 프롬프트는 매체와 스타일 태그를 앞세우고, 룩(look)을 정의하는 한두 개의 태그에만 (term:1.2) 가중치를 아껴서 적용하며, 복사-붙여넣기한 상투적인 목록 대신 해당 이미지에 맞춰 작성된 네거티브 프롬프트를 포함합니다.

출력 형식과 타깃 모델이 서로 어긋날 때

이 도구에서는 출력 형식(일반 프롬프트, 구조화된 블루프린트, JSON)과 타깃 모델을 각각 선택할 수 있습니다. 이 두 선택은 서로 모순될 수 있습니다. '유효한 JSON만 반환하라'와 '파라미터로 끝나는 쉼표 구분 태그를 작성하라'는 동시에 충족될 수 없습니다.

저희는 예전에 두 지시를 모두 전달하고 모델이 알아서 정리하도록 두었습니다. 모델은 실제로 정리해냈지만, 실행할 때마다 다른 방식으로 처리했습니다. 이런 불일치는 버그로서는 드러나지 않지만 사용자 경험으로서는 매우 두드러집니다. 같은 이미지, 같은 설정인데도 눈에 띄게 성격이 다른 프롬프트가 만들어지고, 이는 스타일이 무작위로 사라지는 것처럼 느껴집니다.

이제 우선순위는 명시적입니다. 자유 형식(freeform)은 전체 출력을 타깃 모델에 맡기고 그 문법과 파라미터를 온전히 적용합니다. 구조화된 형식은 자체적인 형태를 유지하므로, 타깃 모델은 어휘만 기여할 뿐 파라미터는 생성하지 않습니다.

이미지를 읽는 것은 창작이 아니라 전사(transcription)다

작지만 효과가 큰 변화 하나: 저희는 이미지를 읽는 도구들의 샘플링 온도(sampling temperature)를 낮췄습니다. 막연한 아이디어로부터 프롬프트를 쓰는 것은 창작 행위이며 어느 정도의 자유로움이 도움이 됩니다. 반면 레퍼런스를 읽는 것은 전사에 더 가까우며, 그 과정에서의 자유도 하나하나가 실제 프레임 안에 있는 것으로부터 멀어지는 정도를 뜻합니다.

Text to Prompt는 기존의 여유를 그대로 유지했습니다. Image to Prompt와 describer는 눈에 띄게 더 문자 그대로에 가깝게 바뀌었습니다.

여기서 얻어갈 것

이런 변화들 대부분은 어떤 도구를 사용하든 여러분이 직접 손으로 적용할 수 있는 것들입니다.

  • 모든 프롬프트에서 피사체보다 먼저 매체를 명시하라.
  • 불완전함을 의도적으로 묘사하라. 그렇게 하지 말라고 하지 않으면 모델은 그것을 없애버린다.
  • 품질을 나타내는 채움말은 삭제하라. 주의력을 낭비하고 결과를 평균 쪽으로 끌어당긴다.
  • Midjourney에서는 프롬프트를 또다시 고쳐 쓰기 전에 --style raw와 낮은 --stylize부터 시도하라.
  • Stable Diffusion에서는 네거티브 프롬프트를 작업의 절반으로 취급하라.
  • 먼저 식별하는 질문을 던져라. 무엇이 이 이미지를 다른 무엇도 아닌 바로 이 이미지처럼 보이게 만드는가?