2020년 11월 24일 화요일

spring-boot + kotlin 기반 API 애플리케이션 구현 Recklessly Handson


spring-boot Initializr를 통한 One-step 프로젝트 구성

브라우저에서 "https://start.spring.io/" 사이트를 열로 SAMPLES 의 Initializr 를 클릭 한다.

화면에서 아래와 같이 주요 항목을 선택 및 기재 한다.


Project 기본 정보 기입

Project: Maven Project

Language: Kotlin

Spring Boot Version: 2.4.0


POM 정보 기입

  • Group: demo.opsflex.example
  • Artifact: user-service
  • Name: user-service
  • Package name: demo.opsflex.example.user
  • Packaging: Jar
  • Java: 11

Dependencies 라이브러리 추가

화면 에서 "ADD DEPENDENCIES..." 버튼을 클릭 하고 Dependency 라이브러리를 다음과 같이 추가 하자.

  • Spring Web

  • Spring Security

  • Spring Boot Actuator

  • Spring Configuration Processor

    하단의 GENERAGE 버튼을 통해 프로젝트 템플릿 파일 "user-service.zip"을 다운로드 하고 로컬 PC(macOS)의 프로젝트 폴더에 압축 해제 한다.


IntelliJ와 같은 IDE 툴로 프로젝트를 열면(Open or Import) 아래와 같은 초기 구성된 프로젝트를 확인 할 수 있다.


왼쪽 메뉴에 프로젝트 구조가 나오며 중앙에 UserServiceApplication.kt 메인 애플리케이션 클래스를 열어서 배치 하였다. 오른쪽 패널엔 Maven 툴을 통해 프로젝트에서 필요로 하는 dependencies 관리와 프로젝트 소스 코드에 대한 compile / package / clean / spring-boot 와 같은 작업을 할 수 있다.


참고로, Spring Initializr를 통한 Maven 구성 정보와 IntelliJ 프로젝트가 참조 하는 Java 버전이 일치 하는지 확인 하자.


애플리케이션 빌드

우측 Maven 툴의 패털에서 "build" 을 더블 클릭 하면 프로젝트 소스 코드가 빌드 되고, BUILD SUCCESS 메시지와 함께 그 결과물로 target/user-service-0.0.1-SNAPSHOT.jar 파일이 생성 된다.





애플리케이션 구동

빌드 된 jar 파일은 "java -jar user-service-0.0.1-SNAPSHOT.jar" 명령으로 간단하게 실행이 가능 한다.

~/user-service/target $ java -jar user-service-0.0.1-SNAPSHOT.jar


몇 가지 단계 만으로 프로젝트 구성이 simple 하게 완료 되었다.


.


2020년 11월 18일 수요일

Java 개발 환경 구성 Recklessly Handson


라떼(Latte)의 선배님은 훌륭한 목수는 연장탓을 하지 않는다며 emacs 또는 vim 편집기만 쥐어 주면 뭐든지 가능 하다고 했었다. 

IDE 가 등장한 뒤부터 이 소리는 개 풀 뜯어먹는 소리 이다. (bullshit) 

SW 를 빠르게 구현 / 테스트 / 빌드 / 구동 할 수 있는 애자일한 개발자로 거듭나기 위해 쾌적한 개발 환경을 구성 해 보자.

  

개발 환경 구성

개발 환경을 구성 하는 몇가지 편리한 툴 들을 아래와 같이 소개 한다.

이름 기능 사용 가능한 OS
YUM / APT 범용 패키지 관리 도구 Linux
alternatives 범용 패키지 버전 선택 도구 Linux
Homebrew 범용 패키지 관리 도구 macOS
Chocolatey 범용 패키지 관리 도구 Windows
SDKMAN 범용 패키지 관리 도구 Linux

macOS

Windows
jabba JDK 설치 특화 도구 Linux

macOS

Windows
jEnv JDK 버전 선택 특화 도구 Linux

macOS
direnv 범용 디렉토리별 환경 변수 관리 도구 Linux

macOS

Windows


이들 중 macOS에 "sdkman" 을 통해 JAVA 개발 환경에 필요한 도구(jdk, graalvm, maven, gradle, scala)을 설치 하자.


sdkman 설치

zsh 사용자는 $HOME/.zshrc 파일에 추가

curl -s "https://get.sdkman.io" | bash

https://sdkman.io/sdks 에 관리 가능한 패키지 목록을 확인 가능 하다.


sdkman 실행 환경 구성

zsh 사용자는 $HOME/.zshrc 파일에 추가

source "$HOME/.sdkman/bin/sdkman-init.sh"
(새로운 터미널을 열고 버전을 확인 하자)sdk version


JDK 설치 

sdk list java 명령을 통해 사용 가능한 패키지 및 현재 설치된 패키지 정보를 확인 할 수 있고, 필요한 모듈을 설치 하려면 install 명령을 사용 한다.


sdk list java
sdk install java 11.0.9-zulu (OpenJDK Zulu-11 버전 설치 예시)


GraalVM 설치

Graalvm 은 고성능 자바, Polyglot을 기반으로 다양한 언어의 통합 기능, Native 자바의 특성을 통해서 빠른 startup time을 제공 하며 Cloud-Native-Application 을 위한 런타임 환경으론 최적이라고 생각 된다.

sdk install java 20.2.0.r11-grl
java -version (설치된 garrlvm 버전을 확인)
openjdk version "11.0.8" 2020-07-14OpenJDK Runtime Environment GraalVM CE 20.2.0 (build 11.0.8+10-jvmci-20.2-b03) OpenJDK 64-Bit Server VM GraalVM CE 20.2.0 (build 11.0.8+10-jvmci-20.2-b03, mixed mode, sharing)


Maven 설치

sdk list maven 을 통해 패키지를 확인하고 원하는 버전을 설치 하자.

sdk list maven
sdk install maven 3.6.3 (3.6.3 버전 설치)


Gradle 설치

sdk list gradle
sdk install gradle 6.5.1 (6.5.1 버전 설치)


Scala 설치

sdk list scala
sdk install scala 2.13.4

sdkman과 같은 패키지 관리 툴을 이용 하면 패키지(오픈소스) 들에 대해 쉽고 간편하게 설치 및 특정 환경을 선택 할 수 있다.


sdkman 을 통한 패키지 관리

동일한 패키지로 여러 버전을 설치 할 수 있고 사용 중인 환경(터미털 세션)에서 원하는 버전을 언제든 switching 할 수 있다.

특정 version 으로 switching 하는 명령 
  • 현재 세션(터미널) 에서만 특정 버전으로 사용: sdk use java {version}
  • 영구적으로 특정 버전을 사용: sdk default java {version) 
sdk use java 11.0.9-zulu (현재 세션(터미널)만 Zulu11.43+21-CA 으로)sdk default java 20.2.0.r11-grl (GraalVM CE 20.2.0 으로)

통합 개발 툴(IDE: eclipse, intellij, v-code, ...)

통합 개발 환경(IDE)을 제공 하는 대표적인 애플리케이션으로 IntelliJ 와 eclipse가 있다. 이 중 IntelliJ 의 Java 개발 환경을 위한 기본 환경을 설정 한다.


IntelliJ 신규 프로젝트 구성







"New Project" 를 클릭 하여 신규 프로젝트를 생성 한다.



프로젝트 유형을 Maven 으로 선택하고 Project SDK 는 원하는 JDK 버전을 선택 하면 된다.


Maven 프로젝트 속성을 기입하고 Finish 를 눌러 완료 한다.


Maven 프로젝트가 아래와 같이 구성 된다.




Java와 같은 컴파일러를 언어를 IntelliJ와 같은 IDE 환경에서 개발을 하려면 JDK 버전을 3가지 환경에 맞추어야 한다.

  • Project SDK: Java 편집기에서 참조 하는 JDK 설정으로 프로젝트 생성시에 이미 정의 하였다.
    (File > Project Structure > Project Settings > Project SDK 에서 설정 한다.)
  • Java Compile: 컴파일에 사용되는 JDK 설정 이다.
    (Preferences > Build, Execution, Deployment > Compiler > Java Compiler 에서 설정 한다. )
  • 외부 플러그인 모듈: Maven과 같은 외부의 툴을 사용 하는 경우 별도의 설정 파일을 통해 JDK 버전을 맞추어야 한다. (예: pom.xml)  


pom.xml 파일 설정 예시 

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>first-example</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

</project>


프로젝트 구성을 마쳤다면 아주 간단한 클래스를 구현 하고 IDE 에서 컴파일과 Runtime 실행이 정상적으로 동작 하는지 확인 하자.


package org.example;

public class FirstApp {

public static void main(String[] args) {
System.out.printf("Hello %s", "World!");
}

}


그리고 Maven 의 package, clean 과 같은 기본적인 명령이 정상 동작 하는지 확인 하자.





2020년 11월 12일 목요일

AWS 2 Tier Arthitecture 설계 (Recklessly HandsOn)

Recklessly Handson for design 2 Tier infra architecture on AWS Cloud.

AWS 클라우드 경험을 남기기 위해 무작정 핸즈온(Recklessly Handson)을 해보려 한다.

먼저 진행할 아이템을 생각나는대로 기술 하고, 스케치 하고 IaC 코드를 짜고 빌드를 해볼 예정 이다.

1. 구성도 스케치
2. 태깅 전략
3. 네트워크 및 보완


1. 구성도 스케치 작업

구성도 스케치를 위해 PPT로 간략하게 스케치 한다. (aws symbol icon 으로 검색하면 템플릿이 나올듯)
 
Convention 규칙
AWS 에서 제공하는 Symbol Icon 은 리소스의 타입과 Guideline 역시 존재 한다. 
표기법이 어렵지 않고 Guideline 을 준수하는 것 만으로 여러 사람들이 쉽게 이해 할 수 있으니 규칙을 따르도록 하자.

"AWS 아키텍처 아이콘" 사이트를 보니 "visual-paradigm" 을 통해 더욱 간단하게 아키텍처를 그릴수 있는 것 아닌가? AWS 최신 아이콘도 이미 적용 되어 있으니 이것으로 시도하는것도 나쁘진 않다.

visual-paradigm



그리고자 하는 2 Tier 아키텍처 backend API 와 DB(postgresql) 을 배치하는 단순한 시나리오이다.




주요 특징으로
  1. api 인스턴스는 2개가 서로다른 AZ 존에 배치되어 하나가 죽더라도 정상 서비스 되도록 구성 한다.
  2. 외부 접근을 막기위해 private subnet 에 API와 DB 서버를 배치 하였다.
  3. 보안 그룹을 통해 API와 DB 서버에 대해 필요한 서비스 포트만 열어 두어서 보안을 강화 하였다.
  4. API 인스턴스의 탄력적인 확장이 가능 하도록 타겟 그룹을 설정 하였다. 
  5. 애플리케이션 로드 밸런서를 두어 외부의 트래픽 유입량에 탄력적으로 대응 하도록 하였고, Gateway API 와 같이 URI 패턴에 대응하는 서비스 라우이팅이 가능 하다.  
  6. public subnet 은 인터넷 게이트웨이를 통한 인터넷 액세스를 지원 한다.
  7. private subnet의 인스턴스는 NAT 게이트웨이를 통해 인터넷을 액세스 할 수 있도록 지원 한다.

 
2. 태깅 전략
AWS와 같은 클라우드 벤더가 제공하는 서비스와 구성 할 수 있는 리소스는 너무나 많아서 효율적인 관리 전략이 필요 하다.

가만히 생각하면 아래와 같은 중요한 컨디션이 있다. 
  1. 제공 하는 서비스가 무엇인지 식별 할 수 있어야 한다.
  2. 서비스에 관련된 리소스를 식별 할 수 있어야 한다.
  3. 리소스의 관리 주체가 누구인지 식별 할 수 있어야 한다.
  4. 서비스 이용 요금을 식별 할 수 있어야 한다.
  5. 리소스의 큰 범위부터 가장 작은 서비스 단위까지 체계적인 네이밍 규칙이면 좋다.

리소스마다 Key, Value 형태의 태그 정보를 입력함으로써 위의 주요 고려 사항을 해결 가능 하다. 

아래 링크를 참고 하자.

그리고 아래는 리소스 태깅 샘플 이다.

Key Value
Name devapp-an2-p-sonarqube-ec2
Project devapp
Owner symplesims@ggmail.com
Team devops-1
Env poc
Compliance HIPAA
Application sonarqube
Version 2.1
AutoStop false


3. 네트워크 및 보완

네트워크를 구성 할 때 애플리케이션 인스턴스는 private subnet 에 배치 하도록 한다. 
각각의 애플리케이션을 위한 보안 그룹을 설정 하자. (보안 그룹은 기본이 50개 한정 이다).
외부 사용자로부터 인터넷 접근을 처리하는 ELB는 인증서(TLS)를 발급 및 적용 한다.
jumphost 와 같은 터널링을 통한 외부 접속을 위한 베스천을 두지 않는다.
Access Key 와 같은 Credentials 정보는 외부 유출이 안되도록 각별히 조심 한다.
IAM 정책을 위해 사용자 및 역할을 구분 하고 제한된 policy 를 구성 한다.


의도적으로 무작정 핸즈온을 시도 했는데 시간이 상당히 많이 걸렸다.

simple 하고 싶은데 심플 하지 않게 되었다.


2020년 11월 10일 화요일

Simple 에 대한 생각

Simple is Best.


누구나 다 한번쯤은 들어보았을 말이다.


Simple은 복잡한것을 싫어하는 사람들에게 마법과도 같아서


지금과 같이 복잡한 시대에 성공하는 서비스를 만들고 많은 사람들이 경험하길 원한다면 Simple을 보여 주면 된다.


IT 세상에서 Simple 을 구현 해야 할 프로그래머는


"복잡한 세상을 단순화 하는 것은 너무나 복잡한 문제를 쉽게 해결하는 것과 같다."는 고찰이 필요 하다.


여러 실들이 서로 얽혀서 동그랗게 말려진 실타래를 풀어야 한다고 가정해 보자.


힐끔 보면 너무 복잡해 보여서 어디서부터 시작해야 할지 엄두가 나지 않을 것이다.


해경 방법 중 하나로 실 한가닥을 양 손가락 중심에 두고 놓치지 않게 집중하여 천천히 풀어 헤치면서 영역을 넓히다 보면 언젠가는 풀려질 것이다.


말하고자 하는점은 문제의 원천을 식별하고 포기하지 않고 꾸준히 진행 하다 보면 문제가 해결될 것이다. 

물론, 그 과정에서 무수한 실패와 좌절감을 경험함은 너무나 당연 하다.


여기에서 Simple 을 추구하는것은 결국 "프로세스 자동화" 이다.


원천적인 문제를 빠르게 식별하는 방법과 실수없이 수없이 반복해야하는 일들에대해 자동화를 추구 하는 것이다.

Cloud Native Applicatoin 생각

Cloud Native Application(CNA) 에 대한 생각


클라우드의 등장과 그 의미

클라우드 세상에선, 데이터센터와 같은 물리적인 인프라스트럭처와 그 기반 위해 구성되는 플랫폼 서비스, OS, 미들웨어, 기타 애플리케이션 서비스를 소프트웨어(코드)를 통해 정의하고 프로비저닝 하여 실체화 할 수 있게 되었다.


클라우드 환경에서 서비스

과거 컴퓨터 박스의 눈에 보이던 한정된 컴퓨팅 자원이 이제는 설정 가능한 만큼 한계선이 높아지고, 글로벌 서비스를 위한 물리적인 제약 또한 사라졌다.

예를 들자면, IDC에서 1 시간에 한국에서만 서비스 가능 했던 제한된 데이터양이 클라우드에선 1 시간에 글로벌을 대상으로 과거 기준 상상하는 만큼의 데이터양으로 성장했다는 것이다.

현실로 예를 들자면, IDC 에서 1시간에 BTS 음악을 국내에서만 음원 스트리밍 서비스만 가능 하던 것이 동일한 1시간 기준으로 8K 영상으로 글로벌 서비스가 가능해 진다라는 의미 이다.

이런 서비스를 가능하게 하는것은 결국 클라우드를 잘 이해 하고 클라우드 환경에 맞게(Cloud Native) 애플리케이션을 구현 / 배치 / 구성 하여야 하는 것이다.


클라우드 네이티브 애플리케이션

결론은 분산 컴퓨팅 기술이 핵심이다.

쉽게 말하자면 동일 시간대비 안정적으로 더 많은 일을 하도록 하기 위해 일꾼들을 늘리는 것이다.


Cloud Native Application(CNA) 의 조건을 생각해 보자.

- Business 로직이 단순할수록 탄력적인 확장이 쉽다.

- Business 로직이 작을 수록 Runtime(구동) 시간이 단축되고 구성 정보도 단순해 진다.

   => Docker 이미지와 같이 Immutable된 서비스 이미지는 Runtime을 전원의 on/off 처럼 단순화 한다.

- 영속적인 저장소(Volume)를 사용하지 않아야 데이터 충돌을 회피하고, 탄력적인 복원을 할 수 있다.

- 애플리케이션 확장, 네트워크 라우팅, 트래픽제어, 모니터링과 같은 애플리케이션 지원은 클라우드의 자원을 활용 하자. (애플리케이션에는 순수한 비즈니스 로직만 포함 하자)

- 컴퓨팅 스펙(예: CPU의 등급)을 올리는 것 보단 확장을 통해 데이터 처리량을 늘리는 것이 좋다.

  => Scale-up 보다 Scale-out 을 염두해 두고 설계 하자. (일꾼의 몸집을 키우기보단 일꾼을 늘리자.)

- 셀 수 없이 확장되는 자원을 셀 수 있도록 특정 하고 식별 할 수 있도록 카테고리(레이블 정책) 정책 구조를 정의 하고 정책 규칙을 따르자.

- 클라우드가 제공하는 안전한 보안 환경을 구성 하자.


정리하고 보니 뻔하고 뻔한 이야기지만 하나 하나는 심플하지 아니한가?

Build AWS Golden Image using Packer + Ansible

AWS Golden Image 이미지는 Immutable 특성으로 런-타임 환경 적용에서 환경 변수나 설정 파일 조정 등의 개입이 없습니다. 이는 서비스 환경의 애플리케이션 런-타임 환경의 일관성을 보장 합니다. 또한, 빠른 start-up 구성 하므...