Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

왜 Grunt에서 Gulp로 갈아탔는가?

Gruntgulp는 JavaScript 빌드 도구이다. Make나 Java의 Ant, Maven, Gradle이나 Ruby의 Rake처럼 프로젝트에서 반복해서 수행하는 빌드과정, 테스트, 배포 등을 자동화해서 하나의 명령어로 간단하게 실행할 수 있게 하는 도구이다.

웹 브라우저에서 실행되는 JavaScript에는 딱히 빌드도구가 존재하지 않고 서버사이드 언어의 빌드도구에 포함되어서 사용되다가 Node.js가 등장한 이후 몇 가지 시도가 이뤄지다가 Grunt가 등장했다. 2013년 초에 처음 Grunt를 보고 맘에 들어서 공부한 이후에 계속해서 JavaScript 빌드에는 Grunt를 사용하고 있었다. 어쨌든 몇 달 전부터 Gulp로 갈아타기로 완전히 맘을 먹고 현재까지 관리하는 프로젝트나 새로운 프로젝트는 모두 Gulp를 적용하고 있다.

Grunt와 Gulp

여기서 두 도구의 특징을 다 얘기하긴 어렵지만 Grunt는 2011년 후반기부터 개발이 시작됐는데 릴리스한 이후 큰 인기를 끌었고 현재 5,000여개의 플러그인이 존재할 정도로 JavaScript 관련 테스크는 대부분 Grunt 플러그인으로 이미 만들어졌다. JSON을 통해서 선언적인 설정을 통해서 테스크를 정의하고 이를 간단한 명령어(혹은 alias)로 테스트로 연결해서 실행한다. 본격적으로 인기를 얻기 시작한 것은 API가 꽤 정리된 0.4 버전이 릴리즈된 2013년 2월 이후이다.

gulp는 Grunt가 이미 인기를 얻은 이후 2013년 여름부터 개발이 시작되었고 등장한 이후 빠르게 Grunt를 대체해갔다. 하는 일은 거의 같지만 선언적인 설정 대신에 Node.js의 스트림 기능을 이용해서 Grunt 같은 설정 대신 코드로 테스크를 선언한다.(Code over Configuration) 이미 Grunt가 인기를 얻고 있는 상황에서 새로운 도구인 gulp도 빠르게 인기를 얻기 시작했고 많은 프로젝트가 gulp로 갈아타기 시작했다. 현재 2,000여개의 플러그인이 존재한다.

Grunt와 Gulp 로고

내가 Gulp로 갈아탈까를 고민하기 시작한 것은 작년(2014년) 여름 정도였던 것 같다. 이미 Grunt를 쓴 지가 1년이 넘었기 때문에 상당히 익숙해져 있었고 웬만한 경우에 대해서는 경험도 쌓인 상태였다. 대세가 이미 Gulp로 바뀐 것 같아서 작년 내에 Gulp로 갈아타야겠다고 결심했지만, 시간이 없어서 갈아타지 못했다.

새로운 도구를 학습할 시간이 없었던 것이 가장 큰 이유이기도 하지만 열심히 갈아타지 않은 이유가 몇 가지 있다.

  • Grunt와 Gulp는 하는 일이 거의 같다. 사용방법이 약간 다를 뿐 만들어 놓으면 두 도구가 하는 일이 거의 같다. 새로운 도구를 쓰려면 학습비용이 필요한데 그렇다고 얻는 부분이 크지는 않기 때문에 갈아타는 동기부여가 크지 않았다. Gulp 말고도 새로 공부하고 익혀야 할 것이 산더미였다.(물론 지금도...)
  • 플러그인이 많지 않다. 지금은 또 1년이 지난 상황이지만 작년만 해도 핵심 플러그인은 양쪽에 모두 존재하지만 약간 엣지케이스에 있거나 많이 사용하지 않는 기능은 Gulp에는 아직 없는 상태였다. Grunt는 없는 것이 없다고 할 수 있을 정도였으므로 갈아탔을 때 이런 부분은 직접 해결해야 했으므로 약간 망설여졌다.
  • Grunt의 설정방식이 나쁘지 않아 보였다. Gulp가 좋다고 더 주장하던 이유 중 하나는 JSON으로 선언하는 Grunt의 설정이 장황하고 읽기 어려우므로 코드로 작성하는 게 훨씬 직관적이다는 점이었는데 완전히 동의하지는 않았다. 익숙해 져서인지 JSON 설정이 딱히 보기 어렵다는 느낌도 별로 없었고 Gulp의 코드가 훨씬 깔끔하다는 느낌도 받지 못했다.

Grunt 프로젝트의 상황

이번에 Gulp로 갈아타기로 결정한 가장 큰 이유는 현재 Grunt 프로젝트의 상황이 좋지 않기 때문이다.

Grunt와 Gulp의 커밋 그래프 비교

위는 Grunt(위)와 Gulp(아래)의 커밋그래프인데 Grunt는 올해 커밋이 거의 없다. 현재 최신 버전인 0.4.5가 2014년 5월에 릴리즈되었지만 1년 반동안 새로운 릴리즈가 전혀 안 되고 있다. 현재 Grunt를 사용하면서 큰 버그나 문제가 있어서 사용에 문제를 느끼고 있는 것은 아니지만 아무런 문제가 없어서 새버전이 안 나오는 건 당연히 아닐 것이다.

올해 이러한 상황을 깨닫기 시작하면서 Grunt에 대해서 불안감을 가지기 시작했다. 현재 사용에 아무런 문제가 없더라도 유지보수가 제대로 되지 않는 도구를 사용하는 것은 불안한 일이고 대체재가 없다면 모르겠지만, Gulp라는 대체재가 있었으므로 앞에서 갈아타지 않은 이유로 적었던 동기부여 문제가 크게 해결되면서 갈아타야 할 이유가 생겼다. 그래서 Grunt에서 문제를 겪기 전에 Gulp로 갈아타기로 했고 프로젝트에 적용하기 시작했다.

Grunt의 개발이 왜 멈추었는지는 아는 바가 전혀 없다. 사람들이 이슈에 0.4.6을 릴리즈해달라는 요청을 올렸지만, 오랫동안 대답이 없다가 Grunt를 만든 Ben AlmanGrunt needs your help!라는 이슈를 올리고 새로 Grunt의 개발을 도와줄 사람을 공식적으로 찾기 시작했다. 이는 공식적으로 현재 Grunt 개발팀이 깨졌거나 유지 보수할 여력이 없다는 것을 발표한 것이나 다름없다. 그리고 Grunt는 jQuery 재단밑으로 옮겨가기로 결정이 되었고 아직 새로운 개발팀을 찾는 중이다.

아직 큰 변화의 결과는 없지만, jQuery 재단 밑으로 이동을 했고 새로운 개발팀을 꾸리기 시작했다는 것은 Grunt 프로젝트를 포기하지 않고 계속 개발해 나가겠다는 의지로 보인다. Grunt가 주춤거린 상황에서(이것 자체가 Gulp 때문일 수도 있다.) 이미 대세는 Gulp로 넘어갔지만 새롭게 개편된 팀이 더 잘할지도 모를 일이고 이미 Gulp로 갈아타고 있지만, Grunt를 상당히 좋아했기 때문에 잘되기를 상당히 기대하고 있다.

Gulp에 대한 인상

이미 국내에도 Gulp에 대한 글이 많이 있고 쓰는 사람도 꽤 많이 보이므로 Gulp에 대한 사용방법을 적기보다는 Gulp를 몇 달 사용해 본 느낌을 적어보려고 한다.

  • 플러그인을 연결해서 사용할 수 있다. 설정보다는 코드가 직관적이라는 부분에는 동의하지 못했지만, 코드로 테스크를 작성할 수 있고 기본적으로 스트림을 이용해서 플러그인을 만들도록 하므로 플러그인을 연결할 수 있다. Grunt였다면 concat 플러그인, uglify 플러그인을 설치해서 각각 설치한 뒤에 alias로 연결해야 했다면 gulp에서는 src().pipe(conat()).pipe(uglify()).dest()같은 식으로 이어붙일 수 있다. 테스크 정의가 훨씬 간단해지고 각 플러그인은 재사용성이 증가한다.
  • Node스럽다. Node.js에서 항상 얘기하는 것이 "Write programs that do one thing and do it well."이라는 Unix 철학이다. 그래서 npm 모듈들은 대게 하나의 일만 하는 작은 모듈을 많이 만들게 되는데 Grunt의 플러그인이 all-in-one 느낌이라면 Gulp는 Node.js의 느낌을 더 많이 닮아서 작은 모듈이 많이 있고 이를 조합해서 테스크를 만든다. 나한테는 이 특징이 주는 느낌이 꽤 좋았다.
  • 복잡해지면 더 읽기 어려워지는 느낌이 있다. 간단한 코드는 어느 쪽이든 상관없지만 복잡해 지면 설정을 읽기가 상당히 어려워지는 느낌이 있다.(아직 익숙지 않아서 그럴 수도 있다.) Grunt가 JSON 설정을 기반으로 하고 있기 때문에 모듈화나 구조화를 하더라도 그 형태 자체를 바꿀 수는 없으므로 프로젝트마다 크게 다르지 않다면 Gulp는 결국은 코드이기 때문에 추상화하는 방식이나 모듈화하는 방식이 다양해서 사용하는 사람마다 아주 다르다. 간단한 설정은 쉽지만, 설정파일 따로 분리하고 소스파일이나 배포파일 선언을 나누어서 서로 간에 불러와서 선언하게 파일을 많이 나누다 보면 테스크의 동작을 파악하기가 꽤 어려운 느낌이다. 이는 아직 Gulp를 써진 지 오래 안돼서 그럴 수도 있다.
2015/12/19 23:10 2015/12/19 23:10