'maven'에 해당하는 글 6건

AWS CDK

Server/AWS 2022. 2. 13. 23:54

AWS CDK(Cloud Development Kit) 를 이용하면 Java, Python, Script 등을 통해 AWS CloudFormation 을 만들어 AWS 클라우드 리소스를 프로비저닝 할 수 있다. AWS 콘솔 창에서 클릭과 타이핑으로 생성하던 리소스들을 code 화 하여, 반복적인 리소스 생성이 필요할 때 유용하다.

 

쉽게 말해 CDK 에서 지원하는 언어(Java, Python, TypeScript, ...) 로 프로그래밍하고, 커맨드 라인 도구인 CDK 툴킷을 통해 AWS CloudFormation 템플릿을 생성하고, stack 을 배포하여 AWS 의 모든 리소스들을 생성/설정할 수 있다.

 

준비해야 할 것은..

  • AWS cli 설치
  • 자격증명(credentials)
  • cdk 설치...
    > npm install -g aws-cdk@1.140.0

 

현재 CDK 는 v2 버전대가 있지만, 이런저런 이유으로 인하여 v1 을 사용하였다. 차이라면 v2 는 새로나온 리소스등을 계속해서 추가해 줄 것이고, v1 은 점점 deprecated 되는 메소드들이 많아질 것이다. 또 bootstrap 도 v2 에서는 필수로 설치하는 거 같고... 참고로 AWS 는 2023년 6월 1일에 CDK v1 에 대한 지원을 종료한다.

 

준비를 마쳤다면  Java(JDK 8+) 로 S3 버킷을 하나 생성하는 간단한 단계는 다음과 같다.

 

 

1. cdk 프로젝트 자동 생성

 

> cdk init app --language java

 

위 명령은 현재 디렉토리에서 cdk 를 쉽게 개발할 수 있도록 관련 library 들의 설정이 포함된 maven 기반의 빈 프로젝트를 생성해 준다. IDE 로 열어보면 Java 기본 구조로 된 maven 프로젝트를 볼 수 있다.

 

 

2. dependency 추가

 

<dependency>
    <groupId>software.amazon.awscdk</groupId>
    <artifactId>s3</artifactId>
    <version>${cdk.version}</version>
</dependency>

 

v2 는 대부분의 리소스를 기본적으로 지원하는 거 같긴한데... 필요하다면 추가할 artifactId 는 대부분의 AWS 서비스 이름으로 검색하고 dependency 에 추가해야 한다.

 

 

3. java 파일 확인/수정/빌드

 

main 메소드가 들어있는 App.java 파일과, 기본적인 Stack.java 파일이 생성되어 있다. App 에는 하나 이상의 Stack(구체적인 AWS 리소스) 을 정의할 수 있다. Stack 파일을 바탕으로 리소스를 추가하면 되고, main 메소드에는 계정 정보와 함께 새로 생성한 Stack 파일을 로드하면 된다.

 

// App.java
public class App {
    public static void main(final String[] args) {
        App app = new App();

        new MyS3Stack(app, "MyCdkS3Stack", StackProps.builder()
                .env(Environment.builder()
                        .account("111122223333")
                        .region("ap-northeast-2")
                        .build())
                build());

        app.synth();
    }
}

 

// MyS3Stack
public class MyS3Stack extends Stack {
    public MyS3Stack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public MyS3Stack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        Bucket.Builder.create(this, "MyFirstBucket")
                .bucketName("cdk-test1")
                .build();
    }
}

 

Stack 의 모든 리소스는 scope, id, props 등으로 구성되는데, scope 는 부모 stack 을 명시한다. id 는 App 내부에서 사용될 id(hash 문자열이 붙음). props 는 해당 리소스의 속성이다.(null 가능) 위 예제에서는 각각 this, MyfirstBucket, bucketName 등이 되겠다. Java에서는 props를 전달하기 위해 Builder가 제공된다. 위 예에서는 BucketProps 나 Bucket 을 사용할 수 있다.

 

// Bucket
Bucket.Builder.create(this, "MyFirstBucket")
    .bucketName("cdk-test1")
    .build();

// BucketProps
new Bucket(this, "MyFirstBucket", new BucketProps.Builder()
    .bucketName("cdk-test1")
    .build());

 

 

4. CDK 병합(synth)

 

코드를 모두 작성했다면 App 의 루트 디렉토리에서 synth / deploy 명령으로 병합/배포해야 한다. cdk synth 를 실행하면 자동으로 빌드(mvn package) 도 되지만, 수동으로 빌드하여 미리 에러 등을 체크할 수 있다. 마찬가지로 deploy 역시 synth 를 자동으로 실행 해주기 때문에 사실상 빌드없이 deploy 만 해도 무방하긴 하다.

 

> cdk synth --profile my
Resources:
  MyFirstBucketB8881111:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: cdk-test1
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
    Metadata:
      aws:cdk:path: MyS3Stack/MyFirstBucket/Resource
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Analytics: v2:deflate64:H5sIAAAAAAAA/yWKQQ5EIAwA3+Idq1UfYNbbHvUFpNYEiZBQ0APh70Y8zSQzCNgN0FajvqSm1TaZfGDIS9Rk1eSdxJAoqmlzM4tPgbio55Ue8i+R4bd9Vor651M3iNAC9tUuxtQhuWgOhvnjDSNKfjhxAAAA
    Metadata:
      aws:cdk:path: MyS3Stack/CDKMetadata/Default

 

위와 비슷한 yaml 형식으로 출력되며 cdk.out/MyS3Stack.template.json 파일에 저장되고, 배포시 cdk.out 디렉토리를 기반으로 배포된다.

aws-cli 에 profile 이 여러개일 경우 원하는 profile 로 지정해야 한다. 소스와 aws-cli 의 계정이 일치하지 않는 경우 아래와 같은 에러가 발생한다.

 

Need to perform AWS calls for account 111122223333, but the current credentials are for 444455556666

 

위 오류가 발생해서 profile 을 정상적으로 설정했는데 아래 오류가 또 발생했다.

 

MyCdkS3Stack (MyFirstBucketB8881111) cdk-test1 already exists
The stack named KpsCdkS3Stack failed creation, it may need to be manually deleted from the AWS console: ROLLBACK_COMPLETE

 

S3 를 확인해보니 비어 있는데 웬 cdk-test1 already exists... 처음 profile 오류나면서 잘못된 계정으로 cdk-test1 을 생성하려는 시도가 있었을 것이고, 그 정보가 어딘가에 남아 있는듯...; (이해할 수 없음)

 

 

5. CDK 배포(destroy)

 

deploy 로 배포하고 나면, CloudFormation 과 S3 에서 리소스들을 확인할 수 있다.

 

> cdk deploy --profile my
MyS3Stack: deploying...
MyS3Stack: creating CloudFormation changeset...
  0/3 |오후 12:12:13 | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | MyS3Stack User Initiated
  0/3 |오후 12:12:18 | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | MyS3Stack User Initiated
  0/3 |오후 12:12:22 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata)
  0/3 |오후 12:12:22 | CREATE_IN_PROGRESS   | AWS::S3::Bucket    | MyFirstBucket (MyFirstBucketB8881111)
  0/3 |오후 12:12:24 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
  0/3 |오후 12:12:24 | CREATE_IN_PROGRESS   | AWS::S3::Bucket    | MyFirstBucket (MyFirstBucketB8881111) Resource creation Initiated
  1/3 |오후 12:12:24 | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata)
  2/3 |오후 12:12:45 | CREATE_COMPLETE      | AWS::S3::Bucket    | MyFirstBucket (MyFirstBucketB8881111)
  3/3 |오후 12:12:46 | CREATE_COMPLETE      | AWS::CloudFormation::Stack | MyS3Stack

 ✅  KpsCdkS3Stack

Stack ARN:
arn:aws:cloudformation:ap-northeast-2:111122223333:stack/MyS3Stack/1231dca0-8a2f-12ec-8c62-0618df8ff132

 

cloudformation-cdk

 

s3-cdk

 

여러 스택을 동시 실행하는 것도 가능하다.

 

> cdk deploy Happy Grumpy   # app defines two or more stacks; two are deployed
> cdk synth "Stack?"    # Stack1, StackA, etc.
> cdk deploy "*Stack"   # PipeStack, LambdaStack, etc.

 

 

6. CDK 재배포

 

> cdk diff --profile my

 

위 명령으로 기존 소스와 수정된 소스간의 변경점을 출력해 볼 수 있으며, cdk deploy 로 계속해서 코드의 변경사항을 리소스에 적용할 수 있다. (버전 관리가 유용할 수 있다.)

 

 

7. stack 삭제

 

생성한 stack 을 삭제한다.

 

> cdk ls
MyS3Stack

> cdk destroy MyS3Stack --profile my
Are you sure you want to delete: MyS3Stack (y/n)? y
MyS3Stack: destroying...

 ✅  MyS3Stack: destroyed

 

CloudFormation 의 Stack 은 정상적으로 삭제되었지만, S3 버킷은 삭제되지 않았다. 기본적으로 사용자 데이터가 포함될 수 있는 리소스에는 RETAIN 의 removePolicy 속성이 있으며, 해당 리소스는 생성될 때 스택과 분리되므로 수동으로 삭제해야 한다. Stack 삭제시 비어있는 버킷을 삭제하고자 한다면 removePolicy 설정을 Destroy 변경하면 된다. 또한 버킷이 비어있지 않다면 이 또한 실패하는데, 버킷의 autoDeleteObjects 속성을 true로 설정할 수 있다.

 

.removalPolicy(RemovalPolicy.DESTROY)
.autoDeleteObjects(true)

 

코드 변경하며 여러 버킷을 만들었었는데 마지막 소스에만 국한하지 않고, 모든 버킷을 삭제한 건 조금 굿잡...

 

 

Java 의 더 많은 예제는 요기...
https://github.com/aws-samples/aws-cdk-examples/tree/master/java

 

GitHub - aws-samples/aws-cdk-examples: Example projects using the AWS CDK

Example projects using the AWS CDK. Contribute to aws-samples/aws-cdk-examples development by creating an account on GitHub.

github.com

 

 

약 3일 정도 CDK 를 사용해 봤다. 위에 s3 의 예는 약 100개 이상의 리소스 중에 하나일 뿐이다. API 꾸역꾸역 찾아가며 각종 리소스를 생성해 봤다. Terraform 이든 CDK 든 당연히 누군가에게는 좋은 IaC 도구이다. 본인이 얼마나 많은 리소스를 관리해야 할지에 따라 필요할 수도, 그렇지 않을 수도 있다. 디테일한 설정을 위해서 리소스마다 많은 옵션들을 찾아봐야 하며 정상적으로 세팅이 되는지 테스트해야 하고... 이런 시간들이 만만치 않다. 여러 설정들을 생성하고 수정하고를 테스트해 보았는데 실제 운영중인 리소스들을 과연 CDK 를 이용하여 한번에 컨트롤할 수 있을지는 확신하지 못했다. 그리고 반복적인 작업도 마찬가지로 코드레벨에서 naming 과 ip 대역 등의 무수한 수정들이 동반된다고 할 때 CDK 가 과연 나에게 필요한 것인지에 대해서는 확신할 수 없었다. 반복적인 작업에 대해 시간을 단축하려고 맛을 보긴 했지만, 내가 앞으로 지금까지의 시스템을 복제하는데 3일은 안걸릴 것이라는 확신과 함께 빨리 손을 떼었다. 언젠가 시간이 좀 날때 다시 봐야할 듯...


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret

Maven vs Gradle

Tool/Gradle 2018. 3. 20. 23:55



빌드 관리 툴로써 이 둘 중 하나를 고민한다면 어느 것이 나을까.

정답이 있는 건 아니지만, 처음 빌드 관리 툴을 사용하는 입장이라면 gradle 을 추천하고 싶다.

일단 maven 보다 나은 점을 꼽아보자면, 빠른 성능과 간결한 설정을 들 수 있다. https://gradle.org/maven-vs-gradle/ 참고.

아무래도 maven 의 단점을 보완한 최신 툴이고, 계속해서 많은 버전 업그레이드를 진행하고 있어 그 격차가 계속 벌어지고 있는 듯 하다.

동일한 역할을 하는 툴이므로 maven 에 익숙한 분들은 굳이 약간의 성능을 느끼기 위해 gradle 로 갈아타려 하지 않을 수도 있다.

빌드만 잘되면 그 뿐이지만... gradle 의 엄청난 기능들과 확장성을 공부한다면 마음이 바뀔 수도 있을지 모른다.


아래는 Maven 과 Gradle 의 간단한 비교이다.


gradle 의 빌드 스크립트는 groovy 라는 언어로 작성해야 하므로 maven 의 xml 에 비하면 친숙하진 않지만 확장성이 뛰어나다.

maven 은 프로젝트가 커질수록 빌드 스크립트의 내용이 길어지고 가독성이 떨어지는 반면, gradle 은 훨씬 적은 양의 스크립트로 짧고 간결하게 작성할 수 있다.

maven 의 경우 멀티 프로젝트에서 특정 설정을 다른 모듈에서 사용하려면 상속을 받아야 하지만 gradle 은 설정 주입 방식으로 이를 해결한다.

그래서 gradle 은 멀티 프로젝트에 매우 적합하며, 빌드 속도는 다양한 시나리오 상에서 10~100배 가량이 빠르다.


선택은 자유.


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret

Spring 의 어플리케이션에서 외부 라이브러리를 사용하려면 필요한 라이브러리(jar 파일) 를 다운받아 런타임시 그것들을 클래스 패스로 가져와야 한다.

Dependency 란 말이 어렵다면 필요한 외부 라이브러리라고 봐도 무방할 듯하다.

Dependency 관리는 외부 라이브러리가 있는 해당 리소스 위치에서 로컬에 라이브러리를 저장하고 클래스 패스에 추가하는 것이다.


Spring 을 사용하려면 필요한 Spring 모듈의 jar 라이브러리 사본을 얻어야 한다.

예를 들어, 웹 어플리케이션을 작성하지 않는다면, spring-web 모듈이 필요하지 않다.

Spring 라이브러리 모듈은 spring-core, spring-webmvc, spring-jms 처럼 spring-* 형식의 이름으로 각각 저장소에 게시된다.



Spring Framework 배포판(RELEASE) 다운로드


  • Maven Central
    Maven 에서 쿼리하는 기본 저장소이며 Spring 이 의존하고있는 많은 공통 라이브러리들도 Maven Central 에서 구할 수 있다. 이 곳에서 Spring 모듈인 jar 의 이름은 spring-*-<version>.jar 형식이며 Maven groupId 는 org.springframework 가 된다.

  • Spring Repogitory (https://repo.spring.io)
    이 저장소는 Spring 을 위해 특별히 호스팅 되는 공개 Maven 저장소이며, 최종 GA(General Available) 릴리즈 외에도 개발 snapshot 및 milestone 을 호스팅한다. jar 파일 이름이 Maven Central 과 같은 형식이기 때문에, Spring 의 개발 버전을 Maven Central 에서 배포된 다른 라이브러리와 함께 얻을 수 있는 유용한 장소이다. 이 저장소는 또한 번들로 묶인 모든 Spring jar 파일들을 포함하는 번들 zip 파일도 제공한다.


다운받는 실제 jar 파일 이름은 spring-core-4.3.6.RELEASE.jar 처럼 일반적으로 버전 번호와 연결된 모듈 이름이다.


가장 먼저 결정해야 할 것은 의존성을 관리하는 방법이다.

모든 Jar를 직접 다운로드하여 수동으로 작업할 수도 있지만, 일반적으로 Maven, Gradle 등의 빌드 자동화 툴을 사용하는 것이 좋다.



Maven 의존성 관리


Maven Central 저장소로부터 Spring 어플리케이션 컨텍스트를 만들기 위해 Maven dependencies 를 다음과 같이 구성할 수 있다.

Spring API에 대해 컴파일 할 필요가 없다면 적용범위(scope) 를 runtime 으로 선언한다.


<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.6.RELEASE</version>
        <scope>runtime</scope>
    </dependency>
</dependencies>
cs


Spring Maven 저장소(예: milestones, 개발자 snapshots) 를 사용하려면 Maven 구성에서 저장소 위치를 지정해야 한다.


For releases:


<repositories>
    <repository>
        <id>io.spring.repo.maven.release</id>
        <url>http://repo.spring.io/release/</url>
        <snapshots><enabled>false</enabled></snapshots>
    </repository>
</repositories>
cs


For milestones:


<repositories>
    <repository>
        <id>io.spring.repo.maven.milestone</id>
        <url>http://repo.spring.io/milestone/</url>
        <snapshots><enabled>false</enabled></snapshots>
    </repository>
</repositories>
cs


For snapshots:


<repositories>
    <repository>
        <id>io.spring.repo.maven.snapshot</id>
        <url>http://repo.spring.io/snapshot/</url>
        <snapshots><enabled>true</enabled></snapshots>
    </repository>
</repositories>
cs



Maven BOM (Bill Of Materials) Dependency


Maven 을 사용하다 보면 다른 버전의 Spring JAR 파일들이 혼합될 수 있지만, BOM dependency 를 사용하면 이를 막을 수 있다.

모든 Spring 의존성을 동일한 버전으로 가져오도록 dependencyManagement 섹션에서 spring-framework-bom 을 import 하면 Spring Framework artifact 작성할 때 더 이상 <version> 속성을 지정할 필요가 없다.


<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-framework-bom</artifactId>
            <version>4.3.6.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
cs



Gradle 의존성 관리


Gradle 로 Spring 저장소를 사용하려면, repositories 섹션에 Maven Central 이나 특정 URL 을 포함시킨다.


repositories {
    mavenCentral()
    // and optionally...
    maven { url "http://repo.spring.io/release" }
}
cs


repositories URL 을 /release 에서 /mileestone 나 /snapshot 으로 변경하거나 더 추가할 수 있다. 

저장소가 설정되었으면, 일반적인 Gradle 방식으로 dependencies 를 선언할 수 있다.


dependencies {
    compile("org.springframework:spring-context:4.3.6.RELEASE")
    testCompile("org.springframework:spring-test:4.3.6.RELEASE")
}
cs




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret

Unindexed remote maven repositories found. Disable...


The following repositories used in your gradle projects were not indexed yet: http://repo1.maven.org/maven2


If you want to use dependency completion for these repositories artifacts, Open Repositories List, select required repositories and press "Update" button (show balloon)


Gradle 프로젝트를 만들자마자 만난 첫번째 경고.

원격 maven 저장소가 아직 인덱싱 되지 않았다...


[File] - [Settings] - [Build, Execution, Deployment] - [Build Tools] - [Maven] - [Repositories] 

해당 저장소에 [Update] 버튼을 눌러 동기화 시켜주면 해결.



WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret

servlet-api with Maven

Daily/Prog 2013. 5. 22. 22:45

Goals - tomcat:run
이클립스 내부 톰캣을 이용해 실행을 시킬 때 다음과 같은 내부 오류(HTTP Status 500)가 나타났습니다.

 

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/jasper/servlet/JasperLoader) previously initiated loading for a different type with name "javax/servlet/http/HttpServletRequest"
 org.apache.jasper.servlet.JspServlet.service(JspServlet.java:268)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

root cause

java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/jasper/servlet/JasperLoader) previously initiated loading for a different type with name "javax/servlet/http/HttpServletRequest"

 

servlet-api 가 이미 로딩이 되었다. 근데 또 로딩을 하는건 반칙이다. 이런건가...
<tomcat_home>/lib 에 하나, WEB-INF/lib 에 하나.
pom.xml 파일에서 scope의 기본값인 compile 을 런타임시에는 사용하지 않도록 provided 로 변경합니다.

 

<dependency>
     <groupId>servletapi</groupId>
     <artifactId>servlet-api</artifactId>
     <version>2.4</version>
     <scope>provided</scope>
</dependency>


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret