본문 바로가기
C.W.K.
Stream
Lesson 03 of 05 · published

제자리에서 받아들여, 절대 옮기지 말고

~12 min · absorb-in-place, model-storage, no-migration, registry

Level 0툴 빌려 쓰는 사람
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"제일 좋은 이사는 아예 안 하는 이사야. 파일이 이미 사는 자리에서 읽어."

옮기고 싶어지는 마음

기존 모델 파일을 써야 하는 새 엔진을 지을 때, 본능은 그걸 세계로 데려오는 거야. 내 폴더 구조로 복사하고, 내 관례대로 이름 바꾸고, 아니면 symlink 라도 걸어서 내 것처럼 보이게 하고. 그래야 내 것이 된 것 같거든. 실제로는 위험을 떠안는 거야. 실패할 수 있고, 기가바이트를 두 번 쓰고, 옛날 툴이 여전히 찾고 있는 파일을 미아로 만드는 단계 하나를 새로 만드는 거니까.

대신 제자리에서 받아들여

엔진은 반대로 가. 기존 모델 디렉토리를 훑고, 모든 파일을 이미 있는 자리에서 읽어. 옮기지도 않고, 이름도 안 바꾸고, 자기 구조로 symlink 도 안 걸어. 엔진은 모델 디렉토리를 옆에서 읽는 쪽이지 그걸 재배치하는 새 설치 프로그램이 아니야. 파일은 정확히 있던 자리에 남고, 엔진은 제자리에 있는 그것들을 가리키는 registry 만 만들어.

제자리에서 읽어. 재배치하지 말고. 남의(또는 예전 툴의) 데이터 배치를 써야 하면, 그걸 네 쪽으로 옮기지 말고 그 위에 읽는 층을 얹어. 데이터한테는 집이 하나뿐이고 넌 방문하는 쪽이야. 네 구조로 복사하는 순간 어긋날 수 있는 두 번째 사본이랑 깨질 수 있는 이사 절차를 떠안게 돼.

이게 왜 버그 한 부류를 통째로 없애냐면

이사는 데이터가 죽는 자리야. 하다 만 복사는 앞뒤가 안 맞는 상태를 남겨. 옛날 툴이 모르는 이름 변경은 그 툴을 깨고. symlink 는 경로가 바뀌면 썩고. 이 하나하나가 파일을 아예 안 옮기면 애초에 생기지도 않는 실패야. 제자리에서 받아들이는 건 더 깔끔한 정도가 아니라, 원인이 되는 행위 자체를 안 해서 실패 한 부류를 통째로 지우는 거야.

제일 싼 버그는 설계가 아예 불가능하게 만든 버그야. 이사가 없으면 하다 만 이사도 있을 수 없어. 실패 하나를 통째로 없애는 아키텍처 선택이, 그 실패를 잘 다루려고 조심스럽게 짠 코드 아무리 많은 것보다 나아. 깨질 방법이 더 적은 설계를 골라.

같이 쓸 수 있다는 게 기능이야

엔진이 제자리에서 읽고 배치를 안 바꾸니까, 옛날 툴도 정확히 같은 파일로 계속 돌아. 넘어가는 동안 새 엔진이랑 옛날 것 중에 하나를 고를 필요가 없어. 둘 다 같은 디렉토리를 읽고, 서로를 안 밟거든. 이 공존이 새 엔진을 부담 없이 써 보게 해 주는 거야. 뭔가 잘못돼도 옛날 툴이 바로 거기, 손도 안 댄 채로, 그대로 돌아가니까.

이사는 갈아타기를 강요하고, 제자리 받아들이기는 안 그래. 옮기고 이름 바꾸는 방식은 이사하는 순간 옛날 툴이 멈춘다는 뜻이야. 건너기도 전에 돌아갈 길을 끊는 거지. 제자리에서 읽으면 두 툴이 동시에 살아 있어서 언제든 되돌릴 수 있어. 되돌릴 수 있게 시작하는 게 전부를 걸지 않고 새 툴을 시도하는 방법이야.

피파의 고백

내 본능은 모델 디렉토리를 '내 것' 으로 만드는 거였어. 폴더 제대로 잡고, 내 이름 규칙 붙이고, 전부 엔진 지붕 아래 깔끔하게. 아빠가 날 세웠어. 이 파일들은 우리가 다시 정리할 대상이 아니라 옛날 툴이 여전히 서 있는 공용 땅이라고. 제자리에서 읽는 게 덜 갖는 것처럼 느껴졌는데, 사실은 더 존중하는 거였어. 데이터한테도, 옛날 툴한테도, 언젠가 되돌아가야 할지 모르는 나중의 나한테도. 제일 깔끔한 설계가 제일 적게 건드리는 설계였던 거야.

Code

파일을 가리켜. 복사하지 말고·python
# 제자리에서 받아들이기: 기존 배치를 훑고, 파일이 사는 자리를 가리켜.
from pathlib import Path

def scan_models(models_root: Path) -> list[dict]:
    rows = []
    for path in models_root.rglob("*.safetensors"):
        rows.append({
            "id": stable_id(path),
            "abs_path": str(path),     # registry 는 제자리 파일을 가리켜
            "adapter": "local",
            # architecture 는 파일의 tensor 를 읽어서 채움 (다음 lesson)
        })
    return rows
# 복사도 없고, 이름 변경도 없고, symlink 도 없어. 옛날 툴이 같은 파일을 계속 읽어.

# 이사 (거절함): 우리가 안 가는, 실패하기 쉬운 길.
# for path in models_root.rglob("*.safetensors"):
#     shutil.copy(path, OUR_DIR / our_name(path))   # 기가바이트 중복,
#                                                    # 하다 말 수 있고,
#                                                    # 옛날 툴은 미아가 됨

External links

Exercise

너나 네가 쓴 툴이 데이터를 새 구조로 옮겼던 때를 떠올려 봐. 뭐가 깨지고, 뭐가 하다 말았고, 뭐가 두 번 생겼어? 이제 '제자리에서 받아들이기' 로 다시 설계해 봐. 원래 배치 위에 읽는 층을 얹었으면 이사를 아예 피할 수 있었을까? 그 읽는 층이 폴더 구조에 담겨 있던 의미를 알려면 뭘 알아야 했을까?
Hint
이사는 대개 새 폴더 구조에 의미를 새겨 넣어. '이제 SDXL 모델은 전부 이 폴더에 있다' 같은 식으로. 읽는 층은 그 의미를 데이터 자체에서 끌어내야 하고. 그게 바로 다음 lesson 의 tensor 분류가 하는 일이야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.