[java] Ant와 Maven의 차이점 [닫기]

누군가 Ant와 Maven의 차이점을 말해 줄 수 있습니까? 나는 한 번도 사용하지 않았습니다. Java 프로젝트 빌드를 자동화하는 데 사용된다는 것을 알고 있지만 어디서부터 시작해야할지 모르겠습니다.



답변

에서 메이븐 : 확실한 가이드 , 나는 섹션 제목은 도입에서 메이븐과 개미의 차이점에 대해 쓴 “개미와 메이븐의 차이” . 여기 소개에있는 정보와 몇 가지 추가 메모가 결합 된 답변이 있습니다.

간단한 비교

가장 기본적인 수준에서 Maven에는 기본 제공 규칙이 있다는 아이디어를 설명하기 위해이 내용 만 표시합니다. 간단한 Ant 빌드 파일은 다음과 같습니다.

<project name="my-project" default="dist" basedir=".">
    <description>
        simple example build file
    </description>
    <!-- set global properties for this build -->
    <property name="src" location="src/main/java"/>
    <property name="build" location="target/classes"/>
    <property name="dist"  location="target"/>

    <target name="init">
      <!-- Create the time stamp -->
      <tstamp/>
      <!-- Create the build directory structure used by compile -->
      <mkdir dir="${build}"/>
    </target>

    <target name="compile" depends="init"
        description="compile the source " >
      <!-- Compile the java code from ${src} into ${build} -->
      <javac srcdir="${src}" destdir="${build}"/>
    </target>

    <target name="dist" depends="compile"
        description="generate the distribution" >
      <!-- Create the distribution directory -->
      <mkdir dir="${dist}/lib"/>

      <!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file
-->
      <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>
   </target>

   <target name="clean"
        description="clean up" >
     <!-- Delete the ${build} and ${dist} directory trees -->
     <delete dir="${build}"/>
     <delete dir="${dist}"/>
   </target>
 </project>

이 간단한 Ant 예제에서는 Ant에게 정확히 무엇을해야하는지 알려야합니다. src / main / java 디렉토리의 소스를 target / classes 디렉토리로 컴파일하는 javac 태스크를 포함하는 컴파일 목표가 있습니다. 소스가 어디에 있는지, 결과 바이트 코드를 어디에 저장하고 싶은지,이 모든 것을 JAR 파일로 패키징하는 방법을 Ant에게 정확히 알려야한다. Ant의 절차를 덜 만드는 데 도움이되는 몇 가지 최근 개발이 있지만 Ant에 대한 개발자의 경험은 XML로 작성된 절차 언어를 코딩하는 것입니다.

이전 Ant 예제와 Maven 예제를 대조하십시오. Maven에서 일부 Java 소스에서 JAR 파일을 작성하려면 간단한 pom.xml을 작성하고 소스 코드를 $ {basedir} / src / main / java에 배치 한 후 명령 행에서 mvn install을 실행하기 만하면됩니다. . 동일한 결과를 얻는 Maven pom.xml 예제

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.sonatype.mavenbook</groupId>
  <artifactId>my-project</artifactId>
  <version>1.0</version>
</project>

이것이 pom.xml에 필요한 전부입니다. 명령 행에서 mvn install을 실행하면 자원을 처리하고, 소스를 컴파일하고, 유닛 테스트를 실행하고, JAR을 작성하고, JAR을 로컬 프로젝트에 설치하여 다른 프로젝트에서 재사용 할 수 있습니다. 수정하지 않고 mvn site를 실행 한 다음 target / site에서 JavaDoc에 대한 링크와 소스 코드에 대한 몇 가지 보고서가 포함 된 index.html 파일을 찾을 수 있습니다.

물론 이것은 가장 간단한 예제 프로젝트입니다. 소스 코드 만 포함하고 JAR을 생성하는 프로젝트. Maven 규칙을 따르고 종속성이나 사용자 정의가 필요하지 않은 프로젝트. 동작 커스터마이징을 시작하고자한다면, pom.xml의 크기가 커질 것이며, 대부분의 프로젝트에서 많은 플러그인 커스터마이제이션 및 의존성 선언이 포함 된 매우 복잡한 Maven POM 모음을 볼 수 있습니다. 그러나 프로젝트의 POM 파일이 더 커져도 Ant를 사용하여 비슷한 크기의 프로젝트 빌드 파일과는 완전히 다른 종류의 정보를 보유합니다. Maven POM에는 “This is a JAR project”및 “source code is src / main / java”선언이 포함되어 있습니다. Ant 빌드 파일에는 “이것은 프로젝트입니다”, “src/main/java“,” javac이 디렉토리에 대해 실행 “,” target/classses“,”…에서 JAR 생성 “등 의 결과 를 입력하십시오. Ant가 프로세스에 대해 명시해야하는 경우 Maven에”내장 “무언가가있었습니다. 소스 코드의 위치와 처리 방법을 알았습니다.

높은 수준의 비교

이 예제에서 Ant와 Maven의 차이점은 무엇입니까? 개미…

  • 일반적인 프로젝트 디렉토리 구조와 같은 공식적인 규칙이 없으므로 Ant에게 소스를 찾을 위치와 출력 위치를 정확하게 알려 주어야합니다. 비공식적 인 협약은 시간이 지남에 따라 등장했지만 제품에 체계화되지 않았습니다.
  • 절차 적이므로 Ant에게 정확히 무엇을해야하고 언제해야하는지 알려야합니다. 컴파일하고 복사 한 다음 압축하도록 지시해야했습니다.
  • 수명주기가없는 경우 목표 및 목표 종속성을 정의해야합니다. 각 목표에 일련의 작업을 수동으로 첨부해야했습니다.

메이븐이있는 곳 …

  • 컨벤션을 가지고 있는데, 컨벤션을 따랐기 때문에 소스 코드의 위치를 ​​이미 알고있었습니다. 바이트 코드를 대상 / 클래스에 넣고 대상에 JAR 파일을 생성했습니다.
  • 선언적입니다. pom.xml 파일을 만들고 소스를 기본 디렉토리에두기 만하면됩니다. 메이븐은 나머지를 보살 took습니다.
  • 를 실행할 때 호출 한 수명주기가 있습니다 mvn install. 이 명령은 Maven에게 수명주기에 도달 할 때까지 일련의 시퀀스 단계를 실행하도록 지시했습니다. 라이프 사이클을 통한 이러한 여정의 부작용으로 Maven은 JAR 컴파일 및 작성과 같은 여러 기본 플러그인 목표를 실행했습니다.

아이비는 어떻습니까?

Steve Loughran과 같은 누군가가 그 비교를 읽고 파울을 부를 것입니다. 그는 대답이 아이비 (Ivy)라는 것을 완전히 무시하는 방법과 Ant가 최신 버전의 Ant에서 빌드 로직을 재사용 할 수 있다는 사실에 대해 이야기 할 것입니다. 사실입니다. Ant + antlibs + Ivy를 사용하는 많은 똑똑한 사람들이 있다면 잘 설계된 빌드로 끝납니다. 비록 Maven이 의미가 있다고 확신하지만, 매우 날카로운 빌드 엔지니어를 가진 프로젝트 팀과 함께 Ant + Ivy를 행복하게 사용할 것입니다. 즉, Jetty 플러그인과 같은 많은 가치있는 플러그인을 놓칠 수 있으며 시간이 지남에 따라 수행 할 필요가없는 많은 작업을 끝내게 될 것이라고 생각합니다.

Maven vs. Ant보다 더 중요

  1. 리포지토리 관리자를 사용하여 소프트웨어 아티팩트를 추적한다는 것입니다. Nexus를 다운로드 하는 것이 좋습니다 . Nexus를 사용하여 원격 저장소를 프록시하고 팀이 내부 아티팩트를 배치 할 수있는 장소를 제공 할 수 있습니다.
  2. 소프트웨어 구성 요소의 적절한 모듈화가 있습니다. 하나의 큰 모 놀리 식 구성 요소는 시간이 지남에 따라 거의 확장되지 않습니다. 프로젝트가 개발됨에 따라 모듈과 하위 모듈의 개념을 원할 것입니다. Maven은이 접근 방식에 아주 적합합니다.
  3. 빌드에 대한 몇 가지 규칙을 채택합니다. Ant를 사용하더라도 다른 프로젝트와 일치하는 일부 규칙을 채택하도록 노력해야합니다. 프로젝트가 Maven을 사용한다는 것은 Maven에 익숙한 사람이라면 누구나 컴파일하는 방법을 알아 내기 위해 구성을 고민하지 않고도 빌드를 선택하고 실행할 수 있다는 의미입니다.

답변

Maven은 프레임 워크이고 Ant는 Toolbox입니다.

Maven은 사전 제작 된로드 카인 반면 Ant는 자동차 부품 세트입니다. Ant를 사용하면 자신의 자동차를 만들어야하지만 적어도 오프로드 주행을해야하는 경우 올바른 유형의 자동차를 만들 수 있습니다.

달리 말하면 Maven은 프레임 워크 인 반면 Ant는 도구 상자입니다. 프레임 워크의 범위 내에서 작업하는 것에 만족한다면 Maven은 잘 작동합니다. 나를위한 문제는 내가 프레임 워크의 경계에 부딪 혔고 나를 풀어 줄 수 없다는 것입니다.

XML 상세

tobrien은 Maven에 대해 많은 것을 알고있는 사람이며 두 제품에 대해 매우 훌륭하고 정직한 비교를 제공했다고 생각합니다. 그는 간단한 Maven pom.xml을 간단한 Ant 빌드 파일과 비교하여 Maven 프로젝트가 어떻게 복잡해질 수 있는지 언급했습니다. 간단한 실제 프로젝트에서 볼 수있는 몇 가지 파일을 비교해 볼 가치가 있다고 생각합니다. 아래 파일은 다중 모듈 빌드에서 단일 모듈을 나타냅니다.

먼저 Maven 파일 :

<project
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-4_0_0.xsd">

    <parent>
        <groupId>com.mycompany</groupId>
        <artifactId>app-parent</artifactId>
        <version>1.0</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>persist</artifactId>
    <name>Persistence Layer</name>

    <dependencies>

        <dependency>
            <groupId>com.mycompany</groupId>
            <artifactId>common</artifactId>
            <scope>compile</scope>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>com.mycompany</groupId>
            <artifactId>domain</artifactId>
            <scope>provided</scope>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate</artifactId>
            <version>${hibernate.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>${commons-lang.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring</artifactId>
            <version>${spring.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.dbunit</groupId>
            <artifactId>dbunit</artifactId>
            <version>2.2.3</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>${testng.version}</version>
            <scope>test</scope>
            <classifier>jdk15</classifier>
        </dependency>

        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>${commons-dbcp.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc</artifactId>
            <version>${oracle-jdbc.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.easymock</groupId>
            <artifactId>easymock</artifactId>
            <version>${easymock.version}</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>

그리고 동등한 Ant 파일 :

<project name="persist" >

    <import file="../build/common-build.xml" />


    <path id="compile.classpath.main">
        <pathelement location="${common.jar}" />
        <pathelement location="${domain.jar}" />
        <pathelement location="${hibernate.jar}" />
        <pathelement location="${commons-lang.jar}" />
        <pathelement location="${spring.jar}" />
    </path>


    <path id="compile.classpath.test">
        <pathelement location="${classes.dir.main}" />
        <pathelement location="${testng.jar}" />
        <pathelement location="${dbunit.jar}" />
        <pathelement location="${easymock.jar}" />
        <pathelement location="${commons-dbcp.jar}" />
        <pathelement location="${oracle-jdbc.jar}" />
        <path refid="compile.classpath.main" />
    </path>


    <path id="runtime.classpath.test">
        <pathelement location="${classes.dir.test}" />
        <path refid="compile.classpath.test" />
    </path>


</project>

tobrien은 Maven에 내장 규칙이 있음을 보여주기 위해 그의 예제를 사용했지만 반드시 XML을 적게 쓰는 것은 아닙니다. 나는 그 반대가 사실이라는 것을 알았습니다. pom.xml은 build.xml보다 3 배 더 길며 관례에서 벗어나지 않습니다. 사실, Maven 예제는 플러그인을 구성하는 데 필요한 추가 54 줄없이 표시됩니다. 그 pom.xml은 간단한 프로젝트를위한 것입니다. 추가 요구 사항을 추가하기 시작하면 많은 프로젝트에서 일반적이지 않은 XML이 실제로 크게 커지기 시작합니다.

하지만 Ant에게해야 할 일을 알려줘야합니다

위의 Ant 예제는 아직 완료되지 않았습니다. 우리는 여전히 청소, 컴파일, 테스트 등에 사용되는 대상을 정의해야합니다. 이들은 다중 모듈 프로젝트의 모든 모듈이 가져 오는 공통 빌드 파일에 정의되어 있습니다. 이 모든 것들이 Ant로 명시 적으로 작성되어야하는 반면 Maven에서는 선언적이라는 점을 알려줍니다.

사실, 이러한 Ant 대상을 명시 적으로 작성할 필요가 없으면 시간을 절약 할 수 있습니다. 그러나 얼마나 많은 시간? 내가 지금 사용하는 일반적인 빌드 파일은 5 년 전에 그 이후로 약간만 수정하여 작성한 파일입니다. Maven으로 2 년 동안 실험 한 후, 오래된 Ant 빌드 파일을 옷장에서 꺼내어 먼지를 털어 다시 작동시켰다. 저에게, Ant에게해야 할 일을 명시 적으로 알려주는 데 드는 비용은 5 년 동안 일주일 이내에 추가되었습니다.

복잡성

다음으로 언급하고자하는 주요 차이점은 복잡성과 실제 효과의 차이점입니다. Maven은 빌드 프로세스 작성 및 관리 작업을 수행하는 개발자의 워크로드를 줄이기 위해 작성되었습니다. 이렇게하려면 복잡해야합니다. 불행히도 그 복잡성은 의도 된 목표를 부정하는 경향이 있습니다.

Ant와 비교할 때 Maven 프로젝트의 빌드 담당자는 더 많은 시간을 소비합니다.

  • 문서 읽기 : Maven에 대해 더 많은 문서가 있습니다. 배울 것이 훨씬 더 많기 때문입니다.
  • 팀원 교육 : 그들은 스스로 답을 찾으려고하지 않고 아는 사람에게 물어 보는 것이 더 쉽다는 것을 알게됩니다.
  • 빌드 문제 해결 : Maven은 Ant, 특히 비 핵심 플러그인보다 안정성이 떨어집니다. 또한 Maven 빌드는 반복 할 수 없습니다. SNAPSHOT 버전의 플러그인에 의존하는 경우, 변경하지 않으면 빌드가 중단 될 수 있습니다.
  • Maven 플러그인 작성 : 플러그인은 일반적으로 특정 작업을 염두에두고 작성합니다 (예 : 웹 스타트 번들 작성). 다른 작업에 재사용하거나 조합하여 목표를 달성하기가 더 어렵습니다. 따라서 기존 플러그인 세트의 임시 해결책으로 공백을 작성해야 할 수도 있습니다.

대조적으로 :

  • Ant 문서는 간결하고 포괄적이며 모두 한 곳에 있습니다.
  • 개미는 간단하다. Ant를 배우려는 새로운 개발자는 알아야 할 나머지 부분을 파악할 수 있도록 몇 가지 간단한 개념 (대상, 작업, 종속성, 속성) 만 이해하면됩니다.
  • 개미는 믿을만하다. 지난 몇 년 동안 Ant가 이미 출시 되었기 때문에 많은 릴리스가 없었습니다.
  • Ant 빌드는 일반적으로 온라인 저장소, 실험용 타사 플러그인 등과 같은 외부 종속성없이 작성되므로 반복 가능합니다.
  • 개미는 포괄적입니다. 도구 상자이므로 도구를 결합하여 원하는 거의 모든 작업을 수행 할 수 있습니다. 사용자 정의 작업을 작성해야하는 경우 매우 간단합니다.

정통

또 다른 차이점은 친숙 함입니다. 새로운 개발자는 항상 속도를 내기 위해 시간이 필요합니다. 기존 제품에 익숙하면 이러한 점에서 도움이되며 Maven 지지자는 이것이 Maven의 이점이라고 올바르게 주장합니다. 물론 Ant의 유연성으로 원하는 규칙을 만들 수 있습니다. 그래서 내가 사용하는 규칙은 소스 파일을 src / main / java 디렉토리 이름에 넣는 것입니다. 컴파일 된 클래스는 target / classes라는 디렉토리로 이동합니다. 익숙하지 않은 것 같습니다.

Maven에서 사용하는 디렉토리 구조가 마음에 듭니다. 나는 그것이 의미가 있다고 생각합니다. 또한 빌드 수명주기. 따라서 Ant 빌드에서 동일한 규칙을 사용합니다. 의미가있을뿐 아니라 이전에 Maven을 사용해 본 사람에게도 친숙 할 것입니다.


답변

Ant는 주로 빌드 도구입니다.

Maven은 프로젝트 및 종속성 관리 도구입니다 (물론 프로젝트도 빌드 함).

Maven을 피하고 싶다면 Ant + Ivy 는 꽤 좋은 조합입니다.


답변

더 많은 차이점을 나열하면됩니다.

  • 개미는 공식적인 협약이 없습니다. 소스를 찾을 위치, 출력 위치 등을 정확하게 Ant에게 알려야합니다.
  • 개미는 절차 적입니다. Ant에게 정확히 무엇을해야하는지 알려줘야합니다. 컴파일, 복사 및 압축 등을 지시하십시오.
  • Ant에는 수명주기가 없습니다.
  • Maven은 규칙을 사용합니다. 이 규칙을 따르는 한 소스 코드가 자동으로 어디에 있는지 알고 있습니다. Maven에게 어디에 있는지 말하지 않아도됩니다.
  • Maven은 선언적입니다. pom.xml 파일을 만들고 소스를 기본 디렉토리에두기 만하면됩니다. 메이븐은 나머지를 돌볼 것입니다.
  • 메이븐은 라이프 사이클을 가지고 있습니다. mvn install을 호출 하면 일련의 시퀀스 단계가 실행됩니다.
  • Maven에는 일반적인 프로젝트 작업에 대한 정보가 있습니다. 테스트를 실행하려면 파일이 기본 위치에있는 한 mvn test를 실행 하십시오. Ant에서 먼저 JUnit JAR 파일이 있어야합니다 .JUnit JAR을 포함하는 클래스 경로를 작성한 다음 Ant에게 테스트 소스 코드를 찾아야하는 위치를 알려주고 테스트 소스를 컴파일하는 목표를 작성한 다음 최종적으로 단위 테스트를 실행하십시오. JUnit과 함께.

최신 정보:

이것은 Maven : The Definitive Guide 에서 나왔습니다 . 미안, 나는 그것을 인용하는 것을 완전히 잊었다.


답변

메이븐 또는 개미? 이 질문과 매우 유사한 질문으로, 질문에 답변하는 데 도움이됩니다.

메이븐이란? 공식 사이트에서.

편집 : 새로운 / 그린 필드 프로젝트의 경우 Maven을 사용하는 것이 좋습니다. “컨벤션 오버 컨벤션”을 사용하면 빌드 및 배포 스크립트를 작성하고 설정하는 데 상당한 시간을 절약 할 수 있습니다. ant를 사용할 때 빌드 스크립트는 시간이 지남에 따라 복잡하고 길어집니다. 기존 프로젝트의 경우 구성 / 레이아웃을 Maven 시스템에 적용하기가 어려울 수 있습니다.


답변

Maven은 종속성 관리 도구 역할을합니다. 중앙 저장소 또는 설정 한 저장소에서 jar를 검색하는 데 사용할 수 있으며 선언적 빌드 도구로 사용할 수 있습니다. “선언적”빌드 도구와 ant 또는 make와 같은 더 전통적인 도구의 차이점은 수행 방식이 아니라 수행해야 할 사항을 구성한다는 것입니다. 예를 들어, maven 스크립트에서 프로젝트를 WAR 파일로 패키지해야한다고 maven은이를 처리하는 방법을 알고 있습니다.

Maven은 “선언”을 달성하기 위해 프로젝트 디렉토리를 배치하는 방법에 대한 규칙에 의존합니다. 예를 들어, 기본 코드를 어디에 두어야하는지, web.xml을 넣을 위치, 단위 테스트 등을위한 규칙이 있지만 필요한 경우이를 변경할 수 있습니다.

또한 maven 내에서 ant 명령을 실행하기위한 플러그인이 있음을 명심해야합니다.

http://maven.apache.org/plugins/maven-ant-plugin/

또한 maven의 원형은 프로젝트를 매우 빠르게 시작합니다. 예를 들어 Wicket 아키타 입은 실행 가능한 헬로 월드 타입 프로젝트 전체를 얻기 위해 실행하는 maven 명령을 제공합니다.

https://wicket.apache.org/start/quickstart.html


답변

개미를 본 적이없는 사람을 데려 갈 수 있습니다. 개미 build.xml는 합리적으로 잘 쓰여져 있으며 무슨 일이 일어나고 있는지 이해할 수 있습니다. 나는 같은 사람을 데리고 그들에게 Maven POM을 보여줄 수 있으며 그들은 무슨 일이 일어나고 있는지 전혀 모른다.

거대한 엔지니어링 조직에서 사람들은 Ant 파일이 커지고 관리 할 수 ​​없게되는 것에 대해 씁니다. 나는 그 종류 작성한 깨끗한 개미 스크립트를. 앞으로해야 할 일을 미리 이해하고 3 년 이상 변화와 확장에 대응할 수있는 템플릿 세트를 설계합니다.

간단한 프로젝트가 없다면, Maven 컨벤션과 Maven 방식을 배우는 것은 꽤 많은 일입니다.

하루가 끝나면 Ant 또는 Maven을 사용한 프로젝트 시작을 고려할 수 없습니다. 실제로 총 소유 비용입니다. 조직이 몇 년 동안 빌드 시스템을 유지 관리하고 확장하는 데 고려해야 할 주요 요소 중 하나입니다.

빌드 시스템의 가장 중요한 측면은 빌드 레시피를 표현할 때 종속성 관리 및 유연성입니다. 잘하면 다소 직관적이어야합니다.