ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 빠르겠다고 동시에 던졌더니, 에이전트들이 서로를 밟고 있었어요
    AI Agent 2026. 6. 23. 09:00
    728x90
    반응형

    한 화면을 통째로 갈아엎고 싶었어요.
    그래서 할 일을 잘게 쪼갰어요.
    이건 이 모듈, 저건 저 함수, 요건 호출부 정리.
    잘게 쪼개니까 신이 나서, 그 조각들을 에이전트들한테 한 메시지로 한꺼번에 던졌어요.
    자동 여덟에 합성 하나, 한 아홉 개쯤 됐어요.
    던지는 순간 손맛이 좋았어요.
    "이거 한 번에 다 돌아가면 30분 걸릴 게 5분이겠는데" 싶었거든요.

    그게 30초였어요.
    좋았던 게.

    첫 발사부터 셋이 같은 데서 죽었어요

    처음 발사 때부터 좀 이상하긴 했어요.
    여섯 개 중 셋이 동시에 같은 데를 잡으려다 타임아웃으로 죽었거든요.
    근데 그때도 별생각 없었어요.
    "아 동시성 좀 빡세네" 하고 그냥 재발사했어요.
    죽은 애들만 다시 던지면 되는 거 아니냐고.
    그때 한 번 멈췄어야 했는데.

    근데 겹치는 건 누가 막나요?

    문제는 던지면서 제가 아무것도 안 막아놨다는 거였어요.
    아홉 개가 전부 같은 작업 트리 하나, 같은 인덱스 하나를 공유하고 있었어요.
    격리가 0이었어요.
    각자 다른 방에서 일하는 게 아니라, 한 책상 위에서 아홉 명이 동시에 같은 종이를 고치고 있던 거예요.
    근데 저는 그걸 "잘게 쪼갰으니까 안 겹치겠지"라고 멋대로 믿고 있었어요.

    안 겹칠 리가 없죠.
    인접한 모듈은 결국 붙어 있으니까.

    두 에이전트가 같은 모듈을 거의 동시에 잡았어요.
    한쪽은 호출부를 새 형태로 바꾸고 있었고, 다른 쪽은 그 함수의 정의랑 메서드를 옛날 그대로 둔 채로 자기 변경만 저장했어요.
    같은 파일을 둘이 동시에 쓰면, 결국 마지막에 저장 누른 쪽이 이겨요.
    앞 사람 작업을 그냥 덮어쓰는 거예요.
    둘 다 자기 할 일은 했는데, 합쳐놓으면 둘 중 하나는 통째로 증발해 있는.

    더 어이없는 건 따로 있었어요.
    한 에이전트가 공유 인덱스에서 통째로 커밋을 돌리고 체크아웃을 했는데, 그게 옆 레인에서 아직 커밋도 안 한 파일들을 같이 쓸어가 버린 거예요.
    내가 분명히 고친 파일이, 다시 옛날 상태로 돌아가 있었어요.
    누가 망친 게 아니라, 공유 상태를 만질 권한을 아무한테도 안 정해놔서, 먼저 통째로 커밋한 쪽이 남의 미커밋을 그냥 되돌려버린 거죠.

    합성 단계에서, 에러 열 줄이 한꺼번에 떴어요

    이걸 합성 단계에서 알았어요.

    각 에이전트 결과를 한 곳에 모아서 검증을 돌렸거든요.
    그 순간 컴파일 에러가 한 줄씩 주르륵 떴어요.
    열 개.
    맨 위 줄이 "인자가 3개여야 하는데 2개가 왔다"였어요.
    한쪽 에이전트가 호출부를 인자 하나 더 넘기는 새 형태로 바꿔놨는데, 정의는 옆 에이전트가 옛날 그대로 두 개만 받게 둔 거죠.
    안 맞는 만큼 한꺼번에 터진 거예요.
    그 열 줄이 화면에 차오를 때 명치가 턱 막히면서, "아 이거 내가 만든 거다" 싶었어요.
    빠르겠다고 좋아하던 30초 전이 갑자기 부끄러워졌어요.
    마우스 쥔 손에 괜히 힘이 들어가고.

    같은 화면을 건드리는 다른 작업은 한 에이전트한테 그냥 통으로 던져놨었어요.
    그쪽도 멀쩡할 리가 없었어요.
    "또 깨졌어요" 보고가 오고, 고치면 다른 데가 깨지고, 또 고치면 또 깨지고.
    그 되돌림이랑 재작업 루프가 네 바퀴를 돌았어요.
    같은 화면에서 네 번.
    같은 패턴으로 네 번 깨지는 걸 보고 나서야, 작업이 어려운 게 아니라는 걸 알았어요.
    일은 안 어려웠어요.
    동시성이 서로를 밟고 있던 거예요.

    빌드를 다시 돌려도 못 믿겠더라고요.
    공유 트리를 빌드하니까, 옆 레인이 반쯤 쓰다 만 편집까지 같이 읽어버려서 결과가 진짜인지 아닌지 알 수가 없었어요.
    정적분석도 마찬가지였고요.
    "검증 통과했으니까 됐겠지"가 안 통했어요.
    한 레인의 단위 검증은 통과했는데, 그게 다른 레인을 깬 채로 합쳐졌으니까.
    통과가 일이 됐다는 뜻이 아니었던 거예요.

    빠진 건 경계, 그중에서도 소유권이었어요

    그제야 뭐가 빠졌는지 보였어요.
    일을 잘게 쪼갠 건 잘한 건데, 던지기 전에 경계를 안 박은 거였어요.
    제일 큰 빵꾸는 소유권이었어요.
    같은 트리랑 인덱스를 아홉이 같이 쓰는데, 누가 그걸 통째로 커밋하고 체크아웃할 권한이 있는지를 아무도 안 정해놨거든요.
    각자 "나는 여기만 건드린다"를 말 안 해서 작업영역이 겹친 것도, 같이 기대는 선행 항목을 먼저 안 박고 의존 작업을 동시에 풀어버린 것도, 따져보면 다 거기서 새어나온 거였고요.
    무서운 건, 이게 작업이 만든 문제가 아니라 동시성이 만든 문제라서, 일을 더 잘게 쪼갤수록 충돌하는 면이 오히려 넓어졌다는 거였어요.

    그래서 다음 회차엔 던지기 전에 한 줄씩 물었어요.
    "너 어디 건드려?" 겹친다고 하면 아예 안 던지고, 겹치는 애들은 각자 다른 방으로 떼어놨어요.
    독립 worktree로, 트리도 브랜치도 따로.
    그리고 공유 트리에 통째로 커밋하고 체크아웃하는 건 그냥 막아버렸어요.
    남의 미커밋을 쓸어가던 게 딱 그거였으니까.
    나머지 잔손질은 그날 하나씩 메웠고요.
    그렇게 경계부터 박고 돌린 다음 회차는, 충돌 0건으로 끝났어요.

    근데 아직 못 믿는 게 하나 있어요

    근데 솔직히 다 풀린 건 아니에요.
    한 가지가 계속 걸려요.
    자동이랑 확인 분리를 다 챙겨서 던지면 메인 컨텍스트 비용이 확 커지거든요.
    그래서 한 번에 몇 개를 던질지는 여전히 제 손으로 조절해야 해요.
    경계는 박았는데, "그래서 몇 개까지 동시에 던져도 되냐"는 아직 감으로 하고 있어요.
    어제 아홉을 던졌던 그 감을, 아직 못 믿겠어요.

    728x90
    반응형
Designed by Tistory.