나는 흥미롭다고 생각하는 기술적인 콘텐츠를 트윗하지만, 재미있는 트윗이 가장 많은 참여를 이끌어냅니다. 저는 3월에 JavaLand 컨퍼런스에 참석하여 우연히 Gradle 부스를 발견하고 다음과 같은 보석을 발견했습니다.
물론 어느 순간 팬보이가 스레드를 가로채서 소위 Gradle의 우월성을 주장하기도 했습니다. 이 게시물에서 나는 동일한 "논리"를 반복적으로 폭로하는 대신 사람들에게 이에 대한 지침을 제공할 수 있도록 내 입장에 대해 약간의 조명을 제공하고 싶습니다.
이것을 관리하려면 제 시간에 돌아가야 합니다. 소프트웨어 개발은 빠르게 변화하는 분야이며 우리가 이해하는 대부분은 개인적인 경험을 바탕으로 이루어졌습니다. 여기 내 것이 있습니다.
저는 2002년부터 Java로 개발을 시작했습니다. 당시에는 빌드 도구가 없었습니다. IDE를 통해 컴파일하고 빌드했습니다. 참고로 저는 Visual Age for Java를 처음 사용했습니다. 그런 다음 Borland JBuilder로 옮겼습니다.
IDE를 사용하여 빌드하는 것은 큰 문제가 있습니다. 각 개발자는 전용 설정을 갖고 있으므로 아티팩트 생성은 개발자-머신 조합에 따라 달라집니다.
반복 불가능한 빌드는 오래된 문제입니다. 반복 가능한 빌드에 대한 나의 첫 경험은 Apache Ant입니다.
Apache Ant는 빌드 파일에 설명된 프로세스를 서로 종속된 대상 및 확장 지점으로 구동하는 것을 임무로 하는 Java 라이브러리 및 명령줄 도구입니다. Ant의 알려진 주요 용도는 Java 애플리케이션 빌드입니다. Ant는 Java 애플리케이션을 컴파일, 어셈블, 테스트 및 실행할 수 있는 다양한 내장 작업을 제공합니다. Ant는 C 또는 C++ 애플리케이션과 같은 비 Java 애플리케이션을 구축하는 데에도 효과적으로 사용될 수 있습니다. 보다 일반적으로 Ant는 대상과 작업 측면에서 설명할 수 있는 모든 유형의 프로세스를 시험하는 데 사용할 수 있습니다.
Ant는 세 가지 주요 추상화를 기반으로 합니다.
javac
, 웹 아카이브를 조합하는 war
등). Ant는 기본적으로 많은 작업을 제공하지만 사용자 정의 작업을 추가할 수 있습니다.
나는 곧 Ant에 "유창"해졌습니다. 컨설턴트로서 저는 회사에서 회사로, 프로젝트에서 프로젝트로 이동했습니다. 처음에는 Ant를 주로 설치했는데, 시간이 지날수록 Ant가 널리 보급되면서 기존 Ant 설정도 접하게 되었습니다. 나는 내 프로젝트에서 일관성을 유지했지만 다른 프로젝트는 서로 매우 달랐습니다.
매번 새 프로젝트에 도착할 때 사용자 정의 빌드를 이해하기 위해 Ant 설정을 주의 깊게 읽어야 했습니다. 게다가 각 프로젝트의 구조도 달랐습니다. 일부는 소스를 src
에, 일부는 sources
, 일부는 중첩 구조 등에 넣습니다.
조직의 전체 프로젝트 요구 사항을 수용하려고 시도한 일반 빌드 파일이 기억납니다. 2,000줄이 넘는 XML에 80개 이상의 대상을 정의했습니다. 도움을 받아 이를 사용하는 방법을 이해하는 데 적지 않은 시간이 걸렸고, 프로젝트를 중단하지 않고 이를 조정할 수 있으려면 훨씬 더 많은 시간이 걸렸습니다.
위의 프로젝트는 나에게 많은 생각을 하게 했다. 관리자가 이미 Ant의 한계를 뛰어넘었기 때문에 나는 상황을 개선하고 싶었습니다. 당시 저는 소나(Sonar)로 유명한 친구 프레디 말렛( Freddy Mallet )과 함께 일하고 있었습니다. 우리는 이야기를 나눴고 그는 나에게 Maven을 가리켰습니다. 나는 한때 Maven으로 프로젝트를 구축했지만 다른 사전 경험은 없었습니다. 저는 몇 시간 동안 문서를 연구했으며 시행착오를 거쳐 Freddy의 지도 하에 전체 Ant 빌드 파일을 간단한 상위 POM으로 마이그레이션했습니다.
Ant에서는 각 프로젝트의 모든 것을 정의해야 합니다. 예를 들어 Ant에서는 컴파일을 위해 Java 파일 위치를 구성해야 합니다. Maven은 src/main/java
아래에 있다고 가정하지만 이를 재정의하는 것이 가능합니다. Maven은 구성에 대한 컨벤션 접근 방식을 통해 Java 빌드 분야에 혁명을 일으켰습니다. 요즘에는 많은 소프트웨어가 기본적으로 합리적인 구성을 제공합니다.
나처럼 프로젝트에서 프로젝트로 이동하는 개발자의 경우 이는 새 프로젝트에 참여할 때 인지 부하가 훨씬 적다는 것을 의미합니다. Java 소스는 src/main/java
아래에 있을 것으로 예상합니다. Maven 규칙은 프로젝트 구조를 넘어 계속됩니다. 또한 단위 및 통합 테스트를 통해 컴파일부터 원격 레지스트리에 아티팩트 업로드까지 프로젝트의 수명 주기를 정의합니다.
마지막으로 주니어 개발자들은 이를 인식하지 못하는 경향이 있지만 Maven은 종속성 관리라는 용어를 정의했습니다. 이는 변경 불가능한 종속성을 다운로드하고 아티팩트를 푸시할 수 있는 아티팩트 레지스트리의 아이디어를 도입했습니다. 그 전에는 각 프로젝트가 전용 저장소에 종속성을 저장해야 했습니다.
참고로 위에서 언급한 프로젝트에는 몇 가지 저장된 종속성이 있었습니다. Ant에서 Maven으로 마이그레이션할 때 정확한 종속성 버전을 찾아야 했습니다. 대부분의 경우 파일 이름이나 JAR 매니페스트에 있으므로 간단했습니다. 그러나 하나는 추가 클래스로 업데이트되었습니다.
불변성에 대해서는 이만큼입니다.
Maven은 이후의 모든 빌드 도구에 지대한 영향을 미쳤습니다. Maven을 참조하여 스스로를 정의했습니다.
Gradle의 주요 주장은 Maven의 단점, 또는 적어도 그렇게 인식된 부분을 수정하는 것이었습니다. Maven이 비난에서 면제되는 것은 아니지만 Gradle은 가장 중요한 문제가 유연성 부족이라고 생각했습니다. 이는 Maven이 Ant에 비해 정확히 개선된 것이기 때문에 놀라운 가정입니다. Maven 프로젝트는 유사한 구조를 가지며 동일한 라이프사이클을 사용합니다. 즉 , 최소 놀라움의 원칙이 적용됩니다. 반대로 Gradle을 사용하면 수명주기를 포함하여 거의 모든 빌드 측면을 맞춤설정할 수 있습니다.
유연성 논쟁에 직면하기 전에 Maven이 나중에 구현한 두 가지 훌륭한 원래 Gradle 기능인 Gradle 데몬과 Gradle 래퍼에 대해 알아보겠습니다.
Maven과 Gradle은 모두 JVM에서 실행되는 Java 애플리케이션입니다. JVM을 시작하는 것은 시간과 자원 측면에서 비용이 많이 듭니다. 장점은 장기 실행 JVM이 시간이 지남에 따라 JIT 코드를 최적화한다는 것입니다. 단기 작업의 경우 JVM 시작 시간을 고려하면 이점이 전혀 없으며 해로울 수도 있습니다. Gradle은 Gradle 데몬을 생각해 냈습니다. Gradle을 실행하면 실행 중인 데몬을 찾습니다. 그렇지 않으면 새로운 것이 시작됩니다. 명령줄 앱은 모든 것을 데몬에 위임합니다. 이름에서 알 수 있듯이 명령줄이 완료되어도 데몬은 중지되지 않습니다. 데몬은 JVM의 이점을 활용합니다.
귀하의 애플리케이션이 현재 빌드 도구보다 오래 지속될 가능성이 있습니다. 지금부터 5년 후에 버그를 수정해야 하는데 프로젝트의 빌드 도구를 온라인에서 사용할 수 없다는 사실을 알게 되면 어떻게 될까요? Gradle 래퍼의 기본 아이디어는 프로젝트와 함께 정확한 Gradle 버전을 유지하고 인터넷을 통해 정식 버전을 다운로드할 수 있는 충분한 코드만 유지하는 것입니다. 부작용으로 개발자는 Gradle을 로컬에 설치할 필요가 없습니다. 모두 동일한 버전을 사용하여 불일치를 방지합니다.
Gradle은 Maven이 통합한 위의 두 가지 훌륭한 기능을 가져와 경쟁이 좋다는 것을 증명했습니다. 그럼에도 불구하고 나는 여전히 Gradle의 이점을 찾지 못했습니다.
감정적인 부분을 밀어내려고 노력하겠습니다. 처음에 Gradle 마케팅은 가능한 모든 경우에 Maven을 무시하려고 노력했고 미친 비교 차트를 게시했으며 일반적으로 커뮤니케이션에 매우 공격적이었습니다. 이 단계가 시장에서 자리를 찾으려는 젊은 회사가 허용할 수 있는 것보다 훨씬 더 오래 지속되었다고 가정해 보겠습니다. Gradle은 Maven "아버지"를 죽이려는 접근 방식에서 매우 오이디푸스적이라고 말할 수 있습니다. 마침내, 오랜 세월이 흐른 후, 그것은 현명해졌고 이제는 "Maven을 사랑"하는 것 같습니다.
Maven이 인수되기 전에는 모든 Ant 프로젝트가 임시적이었다는 점을 기억하십시오. Maven은 그것을 끝냈습니다. 그것은 맞춤형 프로젝트의 World Wild West에 법을 가져 왔습니다. 법에 동의하지 않을 수도 있지만 어쨌든 그것은 법이고 모두가 이를 지켜야 합니다. Maven 표준은 너무 확고해서 일부 매개변수( 예 : 소스 위치)를 재정의하는 것이 가능하더라도 누구도 이를 수행하지 않습니다.
나는 Gradle의 유연성에 대해 두 가지 증상을 경험했습니다. 나는 훨씬 더 많은 것이 존재한다고 생각합니다.
Maven은 4단계로 통합 테스트를 관리하며 순서대로 실행됩니다.
pre-integration-test
: 테스트에 필요한 모든 것을 설정합니다.integration-test
: 테스트를 실행합니다.post-integration-test
: 리소스가 있는 경우 정리합니다.verify
: 테스트 결과에 따라 행동
각 테스트에는 전용 설정 및 분해 로직이 있었기 때문에 저는 사전 및 사후 단계를 사용하지 않았습니다.
반면에 Gradle에는 통합 테스트에 대한 개념이 전혀 없습니다 . 하지만 Gradle 팬보이들은 원하는 단계를 추가할 수 있다고 기꺼이 설명할 것입니다. 실제로 Gradle은 수명 주기 "맞춤화"를 허용합니다. 일반 수명 주기에 원하는 만큼 추가 단계를 추가할 수 있습니다.
각 프로젝트마다 필요한 단계 수와 이름( integration-test
, integration-tests
, integration-testing
, it
(게으른 사용자용) 등)을 모두 제시해야 하기 때문에 혼란스럽습니다. 옵션은 끝이 없습니다.
Maven은 모든 프로젝트를 일반 표준 프로젝트로 취급합니다. 그리고 특정한 요구사항이 있는 경우 이를 위한 플러그인을 작성하는 것도 가능합니다. Maven 플러그인을 작성하는 것은 확실히 재미가 없습니다. 따라서 법이 귀하에게 적용되지 않는다고 결정했기 때문에가 아니라 필요할 때만 작성하면 됩니다.
Gradle은 유연성 부족이 문제라고 주장합니다. 따라서 문제를 해결하려고 합니다. 나는 그 반대 입장입니다. 빌드 도구의 유연성 부족은 버그가 아니라 기능입니다. Gradle을 사용하면 빌드를 쉽게 해킹할 수 있습니다. 따라서 자신의 프로젝트가 특별한 눈송이이고 맞춤화할 가치가 있다고 생각하는 사람은 누구나 기꺼이 그렇게 할 것입니다. 현실 확인: 그런 경우는 거의 없습니다. 그렇다면 일반 프로젝트가 아닌 프레임워크용입니다. Gradle 지지자들은 쉬운 구성을 허용하면서도 여전히 표준을 제공한다고 말합니다. 문제의 핵심은 누군가의 변덕에 따라 변경될 수 있다면 표준이 아니라는 것입니다.
Gradle은 사실상 Android 프로젝트를 위한 빌드 도구입니다. 제가 근무했던 회사 중 한 곳에서는 누군가 Gradle 빌드에 사용자 정의 Groovy 코드를 작성하여 Sonar를 실행하고 측정항목을 내부 Sonar 인스턴스로 보냈습니다. 당시에는 즉시 사용 가능한 Sonar 플러그인이 없었거나 제대로 작동하지 않았다고 가정합니다. 여태까지는 그런대로 잘됐다.
다른 팀이 회사의 두 번째 Android 프로젝트를 만들 때 첫 번째 프로젝트의 구조와 빌드 파일을 복사하여 붙여넣었습니다. 이때 해야 할 현명한 일은 Sonar 전용 코드로 내부 Gradle 플러그인을 만드는 것이었습니다. 하지만 Gradle을 사용하면 빌드를 해킹하는 것이 너무 쉽기 때문에 그들은 그렇게 하지 않았습니다. 그리고 Gradle을 싫어하는 저는 스스로 플러그인을 만들었습니다. 최소한으로 말하면 더 나은 개발자 경험이었을 수도 있습니다. 품질 문서가 부족하고 유형이 지정되지 않은 언어(Groovy)를 사용하여 콘솔을 사용하여 객체의 구조를 인쇄하여 진행했습니다.
경쟁은 좋으며 Gradle은 Maven, 래퍼 및 데몬을 통합한 새로운 아이디어를 가져왔습니다. 그러나 Gradle은 유연성이 좋다는 전제를 바탕으로 구축되었지만 내 경험에 따르면 그 반대였습니다. Ant는 매우 유연했고, 한 프로젝트에서 다음 프로젝트로 이동하는 인지 부하도 높았습니다.
우리 개발자는 인간입니다. 우리는 우리 프로젝트가 다른 프로젝트와 다르다고 생각하고 싶어합니다. 대부분의 경우 그렇지 않습니다. 커스터마이징은 우리의 자아를 만족시키는 방법일 뿐입니다. 유연한 빌드 도구를 사용하면 보증 여부에 관계없이 이러한 사용자 정의를 구현할 수 있습니다.
관련 없는 사용자 정의는 이점이 없으며 개발하기 쉽지만 유지 관리 비용이 많이 듭니다. 소프트웨어 자산 관리가 내 책임의 일부라면 나는 항상 내 빌드 도구에 대해 유연성보다 안정성을 선택합니다.
원래 2023년 8월 6일 A Java Geek 에 게시되었습니다.