구리

[Github Actions] 빌드 환경을 바꿨더니 장애가 발생한 이유 본문

오류해결

[Github Actions] 빌드 환경을 바꿨더니 장애가 발생한 이유

guriguriguri 2025. 9. 5. 13:56

이슈

로컬 빌드 방식에서 GitHub Actions 기반의 빌드 자동화 방식으로 전환한 뒤, 특정 기능이 정상적으로 동작하지 않는 문제가 발생했다.

에러 메시지는 다음과 같다.

TypeError: Invalid attempt to spread non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.

원인

해당 기능은 코드 변경이 없었기 때문에, 원인은 코드 자체가 아니라 빌드 환경 차이에 있다고 생각했다.

  • 로컬 빌드 시에는 문제 없음
  • GitHub Actions 빌드 시 생성된 이미지의 결과물이 달랐음

같은 코드가 빌드 결과에서 다음과 같이 달라졌다.

<Input @add="addInput('allow', ...$event)" />

# 정상 이미지 js 코드
on: {
  add: function(t) {
    return e.addInput.apply(void 0, ["allow"].concat(t))
  }
}
# 에러 이미지 js 코드
on: {
  add: function(t) {
    return e.addInput.apply(e, ["allow"].concat(Object(a["a"])(t)))
  }
}

json-diffpackage-lock.json을 비교한 결과, Vue 버전이 달랐다.

  • 정상 이미지: Vue 2.6.14
  • 에러 이미지: Vue 2.7.16
에러 이미지 (1.0.19-build-1)
vue : 2.7.16 (22년도)
webpack 4.47.0
webpack cli 4.10.0
@babel/core 7.26.7 (최신)
babel-loader 8.4.1 (5개월전)

정상 이미지 (1.0.19-build-6)
vue : 2.6.14 (21년도)
webpack : 4.46.0
webpack cli : 4.9.3
@babel/core : 7.26.0 (3개월전)
babel-loader : 8.2.5 (3년전)

package.json의 버전 범위 지정자(^, ~) 때문에 정확한 버전이 고정되지 않았고, 빌드 시점마다 다른 버전이 설치된 것이다. 추가로, Vue 2.6과 2.7에서 이벤트 바인딩 처리 방식이 다르다는 점도 확인했다.

  • Vue 2.6: 기본적인 이벤트 핸들러 처리 (vue-template-compiler)
  • Vue 2.7: 템플릿 컴파일러가 개선되어 이벤트 핸들러의 arguments 처리가 더 엄격해짐 (@vue/compiler-sfc)

해당 코드에서는 문자열만 전달하고 있지만, Vue 2.7과 최신 Babel 조합에서 스프레드 연산자 처리 로직이 변경되어 런타임에서 예상과 다른 값으로 변환되었다. Dockerfile에서 package.json만 사용해 빌드하면서 버전 차이가 발생했고, 그 결과 이벤트 바인딩 로직이 달라졌다.

해결

기존에 yarn.lock 파일이 있었기에 변경했고 테스트시 이상 없어서 dockerfile에서 빌드할때 yarn.lock도 복사해서  사용했다. 또한 빌드시 패키지 매니저를 npm에서 yarn으로 변경했다. 참고로 npm, yarn의 주요 차이는 다음과 같다.

  • npm: package-lock.json 사용, 순차적 패키지 설치
  • yarn: yarn.lock 사용, 병렬 패키지 설치로 더 빠름, 더 엄격한 버전 잠금