클래스 경로 속성 과정: 구축
Gradle 프로젝트의 클래스 경로와 클래스가 불러오는 시리즈의 두 번째 부분에 오신 것을 환영합니다.만약 네가 아직 읽지 않았다면, 나는 네가 먼저 보아야 한다고 건의한다. 왜냐하면 그것은 다음 내용에 기초를 다졌기 때문이다.이 부분에서 우리는 구축 과정 자체가 사용할 수 있는 클래스 경로를 중점적으로 주목할 것이다.
'건설'은 무슨 뜻입니까?
내가 첫 번째 글에서 언급한 바와 같이 현대 JVM 개발(적어도 안드로이드 개발도 포함)은 SDK 도구(예를 들어 javac
또는 kotlinc
)와의 직접적인 상호작용과 관련된 것이 매우 드물다.반대로 우리는 '구축 도구' 를 사용하여 '구축 실행' 을 한다막후에서 이러한 구축 도구(예를 들어Gradle)는 더욱 기본적인 SDK 도구를 호출했다.예를 들어Gradle의 java
플러그인은 compileJava
유형의 퀘스트 JavaCompile
을 등록했다.이 작업을 수행하는 동안 Java 컴파일러 javac
이 호출됩니다.
이제 구축에 대한 간단한 정의를 내릴 수 있습니다.
The build is a high-level abstraction over the more fundamental SDK tool operations that compile and run your software applications.
이것은 클래스 경로와 클래스 불러오는 것과 어떤 관계가 있습니까?다음은 그렇습니다.
클래스 경로 만들기
Gradle 구축 중의 구축 스크립트는 구축을 실행하기 위해 컴파일을 거쳐야 합니다.스크립트가 Groovy(.gradle
)든 Kotlin(.gradle.kts
)이든 이 과정은Gradle에서 자동으로 완성됩니다.구축을 실행할 때 (안드로이드 스튜디오에서 녹색 화살표를 누르든지 명령줄에서 ./gradlew app:assembleDebug
을 실행하든지) Gradle은 두 가지 단계로 나뉘어 이 명령을 실행합니다. 먼저 구축 스크립트를 컴파일하고 구축을 실행합니다.Gradle build lifecycle에 익숙하다면 첫 번째 단계는 구성 단계로 간주하고 두 번째 단계는 실행 단계로 간주하는 것이 도움이 될 수 있습니다.
JVM의 다른 컴파일링과 마찬가지로 컴파일 스크립트는 컴파일 클래스 경로를 필요로 합니다. 이를 구축 컴파일 클래스 경로라고 합니다.간단한 예를 통해 그것이 어떤 모양인지 봅시다.이를 위해 Gradle build scans을 편리한 시각화 도구로 사용할 것입니다.
이것은 간단한 예이다
우선 아주 간단한 구축 스크립트를 고려하고 구축 클래스 경로를 검사합니다. 이것은 구축 스캔의 구축 의존 부분에 있습니다.
In the examples below, I am deliberately using gradle
and not ./gradlew
. I'm doing this to demonstrate that you can use the global installation of Gradle on your system to build projects, and to simplify the example setup. Just create a build.gradle
and run it!
// root build.gradle
println "project name = $name"
그런 다음 gradle help --scan
을 실행하면 나머지 출력에서 다음과 같은 내용을 볼 수 있습니다.
> Configure project :
project name = classpaths-example
이 간단한 구축에 대해 우리는 build scan을 볼 수 있다.다음은 빌드 종속성입니다.
보시다시피 없습니다.스크립트의 단순성을 감안하면 이상하지 않은 것 같지만 엄밀히 말하면 정확하지 않다.우선, 우리는 println
문장의 효과적인 사실로Groovy 개발 도구 패키지(GDK)가 클래스 경로에 있고 JDK도 클래스 경로에 있다고 추정할 수 있다.(println
은 System.out.println()
의 일반 속기다.)마지막으로 name
변수는Gradle 스크립트를 지원하는 Project
인스턴스의 속성으로, 기본적으로Gradle API도 사용할 수 있음을 의미합니다.따라서 구축 스캔을 했지만 기본적으로Gradle은 구축 클래스 경로에 많은 것을 제공합니다.
마지막으로 숨겨진 의존항이 하나 더 있다.--scan
옵션을 사용하여 Gradle Enterprise (GE) 플러그인을 구축에 은밀하게 추가했습니다.스캔에서 왜 이 점을 볼 수 없는지는 아직 분명하지 않다.빈 settings.gradle
을 추가하고 빌드를 다시 실행하면 다음과 같은 new scan이 제공됩니다.
GE 플러그인은 구축 의존항임을 알 수 있습니다.
프로젝트에 플러그인 추가
그런데 플러그인이 없는Gradle 항목은 뭘까요?플러그인을 추가해서 구축 클래스의 경로를 어떻게 바꾸는지 봅시다.
// root build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.21'
}
}
(Yes, mavenCentral) 1
만약에 우리가 gradle help --scan
으로 이 프로젝트를 설정하면(우리가 좋아하는 것처럼) 우리는 see이 우리의 구축 클래스 경로에 대해 무엇을 했는지 볼 수 있다.
루트 구축 스크립트의 구축 클래스 경로에는 Google Kotlin Gradle 플러그인이 있습니다.우리는 심지어 이 플러그인을 아직 사용하지 않았고, 어떤 방식으로든 설정하는 것은 말할 것도 없다는 것을 알게 될 것이다.반대로 우리는 오래된 buildscript
블록을 사용하여 이를 구축 클래스 경로에 명확하게 추가했다.
비록 우리들 대다수의 사람들이 (모두가 아니었다면) 이런 코드를 본 적이 있다고 나는 확신하지만, 우리는 그것이 좀 지루하다는 것을 인정하지 않을 수 없다.왜 우리는 우리의 플러그인 의존항을 명확하게 지정해야 합니까? 특히 의존항 좌표와 플러그인 ID 사이에 일반적으로 뚜렷한 매핑이 없을 때?(간단히 말하면 kotlin
, 본례의 apply plugin: 'kotlin'
과 같다.)이 일은 좀 의심스럽다.
상품숭배
플러그인 차단
구축 클래스 경로에 현식으로 추가하는 대체 방법은 plugins
블록을 사용하는 것입니다.위의 예를 바꾸어 어떤 변화가 있는지 봅시다.
// root build.gradle
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.4.21'
}
이 블록은 Kotlin Gradle 플러그인 (KGP) 을 추가하고 적용하기 때문에 위의 동작과 약간 다르다.
Sometimes it can be useful to split these operations and maintain an explicit buildscript
block, but the scenarios in which that makes sense are rapidly disappearing. They're also outside of the scope of this post!
gradle help --scan
을 다시 실행하면
을 사용하여 클래스 경로를 구축할 수 있습니다.
inspect
우리가 본 바와 같이 그것은 다른 예와 매우 비슷하다.세 가지 중요한 차이점은 다음과 같습니다.
The build is a high-level abstraction over the more fundamental SDK tool operations that compile and run your software applications.
Gradle 구축 중의 구축 스크립트는 구축을 실행하기 위해 컴파일을 거쳐야 합니다.스크립트가 Groovy(
.gradle
)든 Kotlin(.gradle.kts
)이든 이 과정은Gradle에서 자동으로 완성됩니다.구축을 실행할 때 (안드로이드 스튜디오에서 녹색 화살표를 누르든지 명령줄에서 ./gradlew app:assembleDebug
을 실행하든지) Gradle은 두 가지 단계로 나뉘어 이 명령을 실행합니다. 먼저 구축 스크립트를 컴파일하고 구축을 실행합니다.Gradle build lifecycle에 익숙하다면 첫 번째 단계는 구성 단계로 간주하고 두 번째 단계는 실행 단계로 간주하는 것이 도움이 될 수 있습니다.JVM의 다른 컴파일링과 마찬가지로 컴파일 스크립트는 컴파일 클래스 경로를 필요로 합니다. 이를 구축 컴파일 클래스 경로라고 합니다.간단한 예를 통해 그것이 어떤 모양인지 봅시다.이를 위해 Gradle build scans을 편리한 시각화 도구로 사용할 것입니다.
이것은 간단한 예이다
우선 아주 간단한 구축 스크립트를 고려하고 구축 클래스 경로를 검사합니다. 이것은 구축 스캔의 구축 의존 부분에 있습니다.
In the examples below, I am deliberately using gradle
and not ./gradlew
. I'm doing this to demonstrate that you can use the global installation of Gradle on your system to build projects, and to simplify the example setup. Just create a build.gradle
and run it!
// root build.gradle
println "project name = $name"
그런 다음 gradle help --scan
을 실행하면 나머지 출력에서 다음과 같은 내용을 볼 수 있습니다.
> Configure project :
project name = classpaths-example
이 간단한 구축에 대해 우리는 build scan을 볼 수 있다.다음은 빌드 종속성입니다.
보시다시피 없습니다.스크립트의 단순성을 감안하면 이상하지 않은 것 같지만 엄밀히 말하면 정확하지 않다.우선, 우리는 println
문장의 효과적인 사실로Groovy 개발 도구 패키지(GDK)가 클래스 경로에 있고 JDK도 클래스 경로에 있다고 추정할 수 있다.(println
은 System.out.println()
의 일반 속기다.)마지막으로 name
변수는Gradle 스크립트를 지원하는 Project
인스턴스의 속성으로, 기본적으로Gradle API도 사용할 수 있음을 의미합니다.따라서 구축 스캔을 했지만 기본적으로Gradle은 구축 클래스 경로에 많은 것을 제공합니다.
마지막으로 숨겨진 의존항이 하나 더 있다.--scan
옵션을 사용하여 Gradle Enterprise (GE) 플러그인을 구축에 은밀하게 추가했습니다.스캔에서 왜 이 점을 볼 수 없는지는 아직 분명하지 않다.빈 settings.gradle
을 추가하고 빌드를 다시 실행하면 다음과 같은 new scan이 제공됩니다.
GE 플러그인은 구축 의존항임을 알 수 있습니다.
프로젝트에 플러그인 추가
그런데 플러그인이 없는Gradle 항목은 뭘까요?플러그인을 추가해서 구축 클래스의 경로를 어떻게 바꾸는지 봅시다.
// root build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.21'
}
}
(Yes, mavenCentral) 1
만약에 우리가 gradle help --scan
으로 이 프로젝트를 설정하면(우리가 좋아하는 것처럼) 우리는 see이 우리의 구축 클래스 경로에 대해 무엇을 했는지 볼 수 있다.
루트 구축 스크립트의 구축 클래스 경로에는 Google Kotlin Gradle 플러그인이 있습니다.우리는 심지어 이 플러그인을 아직 사용하지 않았고, 어떤 방식으로든 설정하는 것은 말할 것도 없다는 것을 알게 될 것이다.반대로 우리는 오래된 buildscript
블록을 사용하여 이를 구축 클래스 경로에 명확하게 추가했다.
비록 우리들 대다수의 사람들이 (모두가 아니었다면) 이런 코드를 본 적이 있다고 나는 확신하지만, 우리는 그것이 좀 지루하다는 것을 인정하지 않을 수 없다.왜 우리는 우리의 플러그인 의존항을 명확하게 지정해야 합니까? 특히 의존항 좌표와 플러그인 ID 사이에 일반적으로 뚜렷한 매핑이 없을 때?(간단히 말하면 kotlin
, 본례의 apply plugin: 'kotlin'
과 같다.)이 일은 좀 의심스럽다.
상품숭배
플러그인 차단
구축 클래스 경로에 현식으로 추가하는 대체 방법은 plugins
블록을 사용하는 것입니다.위의 예를 바꾸어 어떤 변화가 있는지 봅시다.
// root build.gradle
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.4.21'
}
이 블록은 Kotlin Gradle 플러그인 (KGP) 을 추가하고 적용하기 때문에 위의 동작과 약간 다르다.
Sometimes it can be useful to split these operations and maintain an explicit buildscript
block, but the scenarios in which that makes sense are rapidly disappearing. They're also outside of the scope of this post!
gradle help --scan
을 다시 실행하면
을 사용하여 클래스 경로를 구축할 수 있습니다.
inspect
우리가 본 바와 같이 그것은 다른 예와 매우 비슷하다.세 가지 중요한 차이점은 다음과 같습니다.
In the examples below, I am deliberately using gradle
and not ./gradlew
. I'm doing this to demonstrate that you can use the global installation of Gradle on your system to build projects, and to simplify the example setup. Just create a build.gradle
and run it!
// root build.gradle
println "project name = $name"
> Configure project :
project name = classpaths-example
그런데 플러그인이 없는Gradle 항목은 뭘까요?플러그인을 추가해서 구축 클래스의 경로를 어떻게 바꾸는지 봅시다.
// root build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.21'
}
}
만약에 우리가
gradle help --scan
으로 이 프로젝트를 설정하면(우리가 좋아하는 것처럼) 우리는 see이 우리의 구축 클래스 경로에 대해 무엇을 했는지 볼 수 있다.루트 구축 스크립트의 구축 클래스 경로에는 Google Kotlin Gradle 플러그인이 있습니다.우리는 심지어 이 플러그인을 아직 사용하지 않았고, 어떤 방식으로든 설정하는 것은 말할 것도 없다는 것을 알게 될 것이다.반대로 우리는 오래된
buildscript
블록을 사용하여 이를 구축 클래스 경로에 명확하게 추가했다.비록 우리들 대다수의 사람들이 (모두가 아니었다면) 이런 코드를 본 적이 있다고 나는 확신하지만, 우리는 그것이 좀 지루하다는 것을 인정하지 않을 수 없다.왜 우리는 우리의 플러그인 의존항을 명확하게 지정해야 합니까? 특히 의존항 좌표와 플러그인 ID 사이에 일반적으로 뚜렷한 매핑이 없을 때?(간단히 말하면
kotlin
, 본례의 apply plugin: 'kotlin'
과 같다.)이 일은 좀 의심스럽다.상품숭배
플러그인 차단
구축 클래스 경로에 현식으로 추가하는 대체 방법은 plugins
블록을 사용하는 것입니다.위의 예를 바꾸어 어떤 변화가 있는지 봅시다.
// root build.gradle
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.4.21'
}
이 블록은 Kotlin Gradle 플러그인 (KGP) 을 추가하고 적용하기 때문에 위의 동작과 약간 다르다.
Sometimes it can be useful to split these operations and maintain an explicit buildscript
block, but the scenarios in which that makes sense are rapidly disappearing. They're also outside of the scope of this post!
gradle help --scan
을 다시 실행하면
을 사용하여 클래스 경로를 구축할 수 있습니다.
inspect
우리가 본 바와 같이 그것은 다른 예와 매우 비슷하다.세 가지 중요한 차이점은 다음과 같습니다.
// root build.gradle
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.4.21'
}
Sometimes it can be useful to split these operations and maintain an explicit buildscript
block, but the scenarios in which that makes sense are rapidly disappearing. They're also outside of the scope of this post!
org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.4.21
의 최상위 의존도를 보여 줍니다.이것은 이라고 불리는데, 이것은Gradle이 플러그인 ID를 '물리적' 공작물 (jar 및 전달 가능한 의존항) 에 비추는 문제를 어떻게 처리하는가이다.mavenCentral()
)에서 해석된 것이고 두 번째 스캔에서 모두 https://repo.maven.apache.org/maven2/(또는 gradlePluginPortal()
)에서 해석된 것을 볼 수 있습니다.플러그인 해석을 바꿀 수 있는 저장소가 있습니다. 잠시 후에 그것들을 토론하겠습니다.plugins
도 이 플러그인을 응용했다.모든 구축 검색에 있는 플러그인 링크를 보면서 이 점을 검증할 수 있습니다.https://plugins.gradle.org/m2 실제로 너는 플러그인을 사용하지 않아도 플러그인을 사용할 수 있다
나는
plugins
을 사용하여 플러그인을 구축에 자동으로 응용하는 방법에 대해 알고 있다. 나는 큰일을 했다.이 동작은 기본 동작이지만 Gradle에게 하지 말라고 말할 수 있습니다.// root build.gradle
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.4.21' apply false
}
내가 아는 바에 의하면, 두 가지 상황이 이것을 유용한 모델로 만들었다.우선, 클래스 경로를 구축하는 데 Kotlin 플러그인만 사용하면 됩니다. 다른 플러그인이 필요하기 때문일 수도 있습니다. (다음 글에서 설명하고자 하는 이유 때문일 수도 있습니다.)두 번째 경우, 이것은 구축 중인 모든 하위 항목이 주어진 플러그인의 같은 버전을 사용하도록 강제하는 방법이다.고려 사항:// settings.gradle
include ':app'
// root build.gradle
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.4.21' apply false
}
// app/build.gradle
plugins {
id 'org.jetbrains.kotlin.jvm'
}
너는 다음에 무슨 일이 일어날지 알고 있다. gradle help --scan
(
).link
우리는 구축 클래스의 경로가 기본적으로 바뀌지 않았음을 볼 수 있다. (비록 지금은 Gradle Enterprise 플러그인을 볼 수 있지만, 우리는
settings.gradle
을 추가했기 때문이다.)이것은 KGP가 app
하위 프로젝트의 구축 클래스 경로에 추가되지 않았음을 확인합니다. 이것은 루트 구축 스크립트의 클래스 경로에만 있습니다.그럼에도 불구하고Gradle의 정의가 양호하고 (문서 기록이 부족하지만) 클래스 인코더 차원 구조로 인해 하위 항목은 접근할 수 있으며, 루트 인코더는 모든 하위 항목 클래스 인코더의 부모 클래스가 됩니다.이 하위 항목 클래스 마운트는 본 시리즈의 첫 번째 글에서 논의한 바와 같이 정상적인 방식으로 부모 클래스에 의뢰한다.Android Gradle 플러그인
KGP와 달리 AGP의 대다수 버전은 plugins
에 간단하게 적용될 수 없다. 왜냐하면
시리즈의 플러그인 표기 부품만 발표하기 시작했기 때문이다.그러나 AGP 4.2.0-beta04에서 현대의 plugins
방법을 사용하여Gradle의 중요한 특성을 보여줄 수 있는 좋은 기회를 제공했고 많은 사람들이 이 점을 모른다고 생각합니다.
// settings.gradle
pluginManagement {
repositories {
google() // AGP
gradlePluginPortal() // KGP
}
}
include ':app'
// app/build.gradle
plugins {
id 'com.android.application' version '4.2.0-beta04'
id 'org.jetbrains.kotlin.android' version '1.4.21'
}
이 예는 두 가지 흥미로운 특성이 있다. 우리는 더 이상 뿌리 build.gradle
을 필요로 하지 않는다. 우리는 설정 스크립트에 이 새로운 pluginManagement
블록이 있다.첫 번째는 우리가 지금까지 배운 내용에 근거하고 두 번째는 범위를 조금 벗어났기 때문에 저는 여러분들이 4.2.0을 읽도록 격려합니다.저장소뿐만 아니라 매우 강력합니다.스크립트 설정 - 더 이상 include
문구만 겨냥한 것이 아닙니다!
docs
Gradle 구축 스크립트 컴파일
이 기초가 있으면 우리는 다시 시작할 수 있다.건물이 뭐예요?그것은 클래스 경로와 어떤 관계가 있습니까?본문에서 우리는 기본적으로 편역을 구축할 때 토론했다.우리의 목표는 프로젝트를 컴파일하는 것일 수도 있지만, 그 전에 구축 스크립트를 컴파일해야 합니다.우리가 이 글에서 배운 모든 것은 구축 유형의 경로에 영향을 주는 다른 방식으로 귀결된다. 그러면 우리는 우리의 구축 스크립트를 컴파일하고 최종적으로 우리의 프로젝트를 컴파일할 수 있다.이것은 정말 걸어오는 종류의 경로다.
마틴 보닝
2021년 1월 8일 오후 23:18
다음은요?
현재 우리는'구축 컴파일링 시'에 대해 좋은 처리를 했고, 다음에 우리는...그러면 컴파일링에 영향을 주는 기교를 하나 더 배우고'구축 운행시'에 주목한다.전자에 대해서는 유용하고 솔직하게 멋있는 원숭이 패치 기술을 배울 것이고, 후자에 대해서는 플러그인 작성자의 주의사항을 중점적으로 주목할 것이다.
그때 봐요!
대단히 감사합니다
다시 한 번 이 글을 자세히 읽고 몇 가지 관건적인 부분에서 내가 침묵을 유지하도록 도와준 것에 감사 드립니다.
미주
1 하나를
에 붓는다.jcenter
Reference
이 문제에 관하여(클래스 경로 속성 과정: 구축), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/autonomousapps/a-crash-course-in-classpaths-build-l08
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
// settings.gradle
pluginManagement {
repositories {
google() // AGP
gradlePluginPortal() // KGP
}
}
include ':app'
// app/build.gradle
plugins {
id 'com.android.application' version '4.2.0-beta04'
id 'org.jetbrains.kotlin.android' version '1.4.21'
}
이 기초가 있으면 우리는 다시 시작할 수 있다.건물이 뭐예요?그것은 클래스 경로와 어떤 관계가 있습니까?본문에서 우리는 기본적으로 편역을 구축할 때 토론했다.우리의 목표는 프로젝트를 컴파일하는 것일 수도 있지만, 그 전에 구축 스크립트를 컴파일해야 합니다.우리가 이 글에서 배운 모든 것은 구축 유형의 경로에 영향을 주는 다른 방식으로 귀결된다. 그러면 우리는 우리의 구축 스크립트를 컴파일하고 최종적으로 우리의 프로젝트를 컴파일할 수 있다.이것은 정말 걸어오는 종류의 경로다.
마틴 보닝
2021년 1월 8일 오후 23:18
다음은요?
현재 우리는'구축 컴파일링 시'에 대해 좋은 처리를 했고, 다음에 우리는...그러면 컴파일링에 영향을 주는 기교를 하나 더 배우고'구축 운행시'에 주목한다.전자에 대해서는 유용하고 솔직하게 멋있는 원숭이 패치 기술을 배울 것이고, 후자에 대해서는 플러그인 작성자의 주의사항을 중점적으로 주목할 것이다.
그때 봐요!
대단히 감사합니다
다시 한 번 이 글을 자세히 읽고 몇 가지 관건적인 부분에서 내가 침묵을 유지하도록 도와준 것에 감사 드립니다.
미주
1 하나를
에 붓는다.jcenter
Reference
이 문제에 관하여(클래스 경로 속성 과정: 구축), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/autonomousapps/a-crash-course-in-classpaths-build-l08
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
다시 한 번 이 글을 자세히 읽고 몇 가지 관건적인 부분에서 내가 침묵을 유지하도록 도와준 것에 감사 드립니다.
미주
1 하나를
에 붓는다.jcenter
Reference
이 문제에 관하여(클래스 경로 속성 과정: 구축), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/autonomousapps/a-crash-course-in-classpaths-build-l08
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(클래스 경로 속성 과정: 구축), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/autonomousapps/a-crash-course-in-classpaths-build-l08텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)