자동 환경 설정과 Spring Environment 및 다른 Spring 프로그래밍 모델 관념의 바인딩을 바탕으로 Spring Boot 어플리케이션을 위한 Netflix OSS(Open Source Software) 통합을 제공합니다. 몇 가지 간단한 어노테이션을 사용하여 어플리케이션 내부의 공통 패턴을 신속하게 사용하고 설정할 수 있습니다. 그리고 battle-tested를 거친 Netflix component를 통해 대규모 분산 시스템을 구축할 수 있습니다.
API를 통해 특정 시스템의 보호된 자원에 접근하기 위해서는 해당 시스템의 사용자 인증 정보(아이디, 패스워드)를 알고 있어야 합니다. 시스템 차원에서 다른 시스템의 보호된 자원에 접근하기 위해 그 시스템의 사용자 인증 정보를 관리하고 이 정보를 사용하는 것은 보안상 많은 문제들을 유발할 수 있습니다. 이런 문제들이 발생하지 않도록 API 접근을 위임하여 인증을 처리하는 방법을 사용할 수 있습니다.
많은 서비스 제공자(Google, Yahoo, AOL 등)들이 이런 인증 방식을 별도로 구현하여 사용하였습니다. 이렇게 구현된 결과들은 서로 조금씩 다르고 서로 호환되지 않았는데 이를 통일하기 위해 OAuth 1.0 표준안을 만들었습니다.
OAuth 1.0 발표 이후 몇 년 동안 사용하면서 커뮤니티는 아래와 같은 단점들에 대해 고민하였고 그 결과 OAuth 2(이후 ‘OAuth’로 명명)를 표준으로 정리하였습니다.
암호화 요구사항의 복잡성
웹 기반 애플리케이션만 지원
성능 확장에 어려움
1. OAuth 역할들(Roles)
OAuth에서 위임 방식의 인가를 처리하기 위해 4 개의 역할들을 정의하고 있으며 이들은 아래 표와 같습니다.
역할설명
자원 서버 (Resource Server)
자원 서버는 보호된 정보를 제공하는 서버로 일반적으로 웹 애플리케이션입니다.
자원 소유자 (Resource Owner)
자원 소유자는 자원 서버에 계정을 가지고 있는 사용자로 클라이언트가 그들의 계정을 통해 자원 서버에 접근하는 것을 인가(authorize)합니다.
클라이언트 (Client)
클라이언트는 자원 소유자를 대신하여 자원 서버의 서비스를 사용하고자 하는 애플리케이션입니다.
인가 서버 (Authorization Server)
인가 서버는 클라이언트가 자원 서버의 서비스를 사용할 때 사용하는 접근 토큰(Access Token)을 발행합니다.
2. 인가 승인 유형(Authorization Grant Types)
클라이언트가 접근 토큰을 요청하기 위해서는 자원 소유자의 인가를 받아야 하는데 OAuth는 서로 다른 용도를 위해 다양한 인가 승인 유형을 제공합니다. OAuth에서 정의한 4가지 인가 승인 유형은 아래와 같습니다.
인가 승인 유형용도비고
인가 코드 승인 (Authorization Code)
웹 서버 상에서 동작하는 애플리케이션
가장 많이 사용되는 유형
암시적 승인 (Implicit)
모바일 앱 또는 단말기에서 동작하는 웹 애플리케이션
자원 소유자 패스워드 승인 (Resource Owner Password)
단말기 OS 또는 높은 신뢰 관계의 애플리케이션
다른 유형들을 사용할 수 없는 경우에만 사용
클라이언트 인증 정보 승인 (Client Credentials)
애플리케이션 API 접근
신뢰하는 클라이언트만 사용
2.1. 인가 코드 승인(Authorization Code Grant)
인가 코드 승인 방식은 HTTP 리다이렉션 기반 흐름이어서 클라이언트는 자원 소유자의 웹 브라우저와 상호작용할 수 있어야 하며 인가 서버로부터의 요청을 처리할 수 있어야 합니다. 승인 흐름은 아래 그림과 같습니다.
클라이언트가 사용자 에이전트를 인가 서버로 리다이렉트 함으로써 흐름을 시작합니다. (상태(State) 값과 인가 서버로부터 응답을 수신할 Redirect URI 포함)
유효한 인증 이력이 없는 인증 요청에 대해 인가 서버는 로그인 페이지로 응답합니다.
자원 소유자는 인가 서버의 인증을 통해 클라이언트를 인가합니다.
인가 서버는 정상적인 자원 소유자의 인증/인가 요청을 클라이언트로 리다이렉트 합니다. (인가 코드, 상태 값 포함)
인가 코드를 포함한 요청을 받은 클라이언트는 인가 서버로 접근 토큰 요청을 전송하여 그 결과로 접근 토큰을 획득합니다. (인가 코드, 클라이언트 인증 정보 포함)
이 방식은 위 그림에서 볼 수 있듯이 클라이언트의 인증 과정을 거치고 인가 서버와 클라이언트 간에만 접근 토큰이 포함된 통신을 수행하는 등 보안 상 많은 이점을 포함하고 있습니다.
3. 로그인 시나리오
SSO 구성 환경에서 SSO 처리 시나리오는 아래 그림과 같습니다.
한 시스템을 통해 로그인한 사용자가 다른 시스템의 인증이 요구되는 페이지를 요청하면 해당 시스템은 이 요청을 SSO 서버로 리다이렉트 합니다.
유효한 인증 이력이 있는 요청에 대해 SSO 서버는 이 요청을 시스템으로 리다이렉트 (인가 코드 포함)합니다.
인가 코드를 포함한 요청을 받은 시스템은 SSO 서버로부터 접근 토큰과 사용자 정보를 획득하여 해당 사용자의 로그인 처리를 한 후 원래 요청의 결과로 응답합니다.
4. 로그아웃 시나리오
로그인한 사용자가 SSO 환경에서 로그아웃 시 처리 과정은 아래 그림과 같습니다.
로그인한 사용자가 한 시스템에게 로그아웃을 요청하면 시스템은 이 요청을 SSO 서버의 로그아웃 페이지로 리다이렉트 합니다.
로그아웃 요청을 받은 SSO 서버는 해당 사용자로 로그인된 모든 시스템에게 로그아웃을 요청합니다.
[스프링부트] jar, war 내에서 ResourceUtil.getFile() 사용시 FileNotFoundException 발생
//XML 파일의 내용을 가져온다.
XmlMapper xmlMapper = new XmlMapper();
File file = ResourceUtils.getFile(replicationXmlFilePath);
if (!file.exists()) {
throw new Exception("replication.xml is Not File..");
}
List<DBInfo> dbInfoList = xmlMapper.readValue(file, xmlMapper.getTypeFactory().constructCollectionType(List.class, DBInfo.class));
[ERROR](org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler:95) Unexpected error occurred in scheduled task.
java.io.FileNotFoundException: class path resource [replication.xml] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/home/service/App.war!/WEB-INF/classes!/replication.xml
at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:215)
at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:53)
at com.MonitoringJob.execute(MonitoringJob.java:69)
at com.JobConfiguration.monitoringJob(JobConfiguration.java:210)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Intellij 에서는 Path의 문제가 없었지만 war 내에서는 문제가 생긴다.
//XML 파일의 내용을 가져온다.
XmlMapper xmlMapper = new XmlMapper();
ClassPathResource classPathResource = new ClassPathResource(replicationXmlFilePath);
List<DBInfo> dbInfoList = xmlMapper.readValue(classPathResource.getInputStream(), xmlMapper.getTypeFactory().constructCollectionType(List.class, DBInfo.class));
Maven Scope 정리 pom.xml에서 상용되는 scope에 대한 정리 ※compile - 아무런 scope를 명시하지 않았을때 사용되는 기본값. - 테스트 및 런타임에도 classpath에포함된다. ※provied - JDK 또는 컨테이너에 의해서 runtime에 제공되는 모듈 - 이 scope는 이미 컨테이너가 해당 라이브러리를 제공하고 있을때 유용 그러므로 실제로 배포시에 제외대상 - 예를 들면 아래 servlet api의 경우 이미 웹서버에서 제공하고 있는 경우에 maven scope를 provied로 기재
※runtime - 런타임시 필요하지만 컴파일시에 필요하지 않는 경우에 사용 - 테스트와 런타임에는 사용 되지만 컴파일시에 사용 되지 않음 - 대표적 예로 JDBC Driver
TheJava Platform Module Systemintroduces a new kind of Java programing component, the module, which is a named, self-describing collection of code and data. The JDK itself has been divided into a set of modules
Thejlinktool is used to assemble modules and their dependencies into a reduced runtime package, and perform optimizations during the newlink timephase after thecompile timephase
jshellis a Read-Eval-Print Loop (REPL) tool for the Java platform. Can be used to interactively evaluate input code and print the results
Multi-Release JAR Files: Enables multiple, Java release-specific versions of class files to coexist in a single archive
Private methods can be defined in interfaces. They can be used for example by the default methods of an interface to refactor code
Factory methods for collections, such asSet.ofandList.of
Local-Variable Type Inferenceusing the keywordvar, a way to automatically deduce the type of a local variable without declaring it.var set = new HashSet<String>();is now a valid expression.
A new methodorElseThrowhas been added to theOptionalclass
New APIs for creating unmodifiable collections such asList.copyOf,Set.copyOf, andMap.copyOf
Performance optimization for theG1garbage collector by using aParallel Full GC
Removed modules that contain CORBA and Java EE technologies such as JAX-WS and JAXB
Flight Recorder: A profiling and monitoring tool with a very low-overhead used to record events originating from Java applications and the OS
Nest 기반 접근 제어
Nest-based access controls. Nest 는 접근 제어 컨텍스트로 논리적으로는 같은 클래스를 분리된 클래스로 컴파일할 수 있게 해줍니다. 그러면 다른 클래스의 private 멤버에 getter/setter 없이 바로 접근 가능합니다. 여러 클래스를 하나의 클래스처럼 묶어줄 수 있는 기술로 보입니다.
새로운 가비지 컬렉터
ZGC: A Scalable Low-Latency Garbage Collector (Experimental). 성능을 향상시킨 새로운 가비지 컬렉터(Carbage Collector)입니다. 메모리를 자동으로 정리해주는 가비지 컬렉터는 자바의 장점 중 하나이지만, 가비지 컬렉터가 동작할 때 JVM이 애플리케이션을 멈추기 때문에 자바의 단점이기도 합니다. ZGC는 이 시간을 10ms 미만으로 줄이고 15% 이하의 성능 페널티를 목표로 합니다.
GC 일시 중지 시간은 10ms를 초과하지 않는다.
작은 크기(수백 메가) ~ 매우 큰 크기(수 테라) 범위의 힙을 처리한다.
G1에 비해 애플리케이션 처리량이 15%이상 감소하지 않는다.
향후 GC 최적화를 위한 기반 마련.
처음에는 Linux / x64을 지원 (향후 추가 플랫폼 지원 가능).
Flight Recorder
Flight Recorder. 자바 애플리케이션과 HotSpot JVM의 문제 해결을 위한 오버헤드가 낮은 데이터 수집 프레임워크입니다. 이전에는 유료 기능이었지만 오픈소스로 공개되었습니다.
새로운 표준 HTTP 라이브러리
HTTP Clinet(Standard).java.net.http패키지의 새로운 모듈로 flow 기반의 HTTP/1.1과 HTTP/2를 지원합니다. 자바 9과 자바 10에서 사용되었던jdk.incubator.http패키지가 표준화되어java.net.http패키지로 추가되었습니다.
Non-Blocking request and response 지원 (with CompletableFuture)
Backpressure 지원(java.util.concurrent.Flow패키지를 통해 RX Flow를 구현체에 적용)
단일 실행 파일로 제공되는 프로그램을 실행할 수 있도록, Java Launcher를 개선하는 feature입니다.shebang파일(유닉스 계열 OS에서, 프로그램으로 실행되는 스크립트 파일임을 나타내는 구문)을 인식할 수 있도록 하는 것인데요, 이 파일을 인식하기 위해서JLS(Java Launguage Specification) 또는,javac를 변경하거나 Java를 범용 스크립팅 언어로 개발하는 것이 목표는 아닙니다.
단일 파일 프로그램은 일반적으로, 처음 Java를 학습하는 과정이나 소규모 유틸리티가 필요한 경우에 사용될 수 있지만, 단일 소스파일이 여러 클래스 파일로 컴파일될 수 있으므로, "run this program." 이라는 단순한 목표에 패키징이라는 오버헤드가 추가될 수 있습니다.
"Shebang" files
#!/path/to/java --source 11 public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World"); } }
- 지금까지BCL(Binary Code License)이라는 라이선스 체계를 따랐다. (~2018년 6월)
- BCL은 유료와 무료가 섞인 라이선스 체계다. (프로그램을 작동(running)하기 위한 목적으로 사용되는 것만을 허용한다.)
- 서버 컴퓨터나 PC, 태블릿, 스마트폰 등의 '일반 목적 컴퓨팅' 용도로는 무료로 사용할 수 있고, 키오스크 등 특수한 목적의 컴퓨팅 장비에 사용할 때는 유료인 요금제다.
- 프로그램을 내부적인 비즈니스 운영 또는 상업용 목적, 제품화 목적으로 사용하고자 할 때에는 수정하지 않은 상태로 프로그램의 번들 된 부분으로서(bundled as part of) 소유권에 대한 고지문 등을 삭제하거나 대체하지 않은 상태로 사용해야 한다.
▶ 현재 변경된 라이센스 정책
- BCL 라이센스가 2018년 7월 부로Java SE Subscription라는 이름의 년 단위 유료 구독형 라이센스로 새롭게 개편되었다. (영구 라이선스에서 구독 모델(서브스크립션)으로 변경, 서브스크립션을 도입하면서 오라클 자바 SE의BCL 정책을 폐지)
- 지속적인 업데이트 & 보안 패치를 받고자 하는 고객에 대해서 서브스크립션 라이선스(Subscription License)를 구해야 한다.
- 오라클의 이번 정책변경은 무료에서 유료로 바뀌는 것이 아니라, 라이선스 과금 모델에서 서브스크립션 과금 모델로 바뀌는 것이다.
- 이는 소프트웨어 업계의 전반적인 트렌드다. 어도비시스템즈, 마이크로소프트 등 대표적인 소프트웨어 회사들이 이같은 흐름을 이끌고 있다. (요즘 포토샵, 오피스도 월정액 요금을 내고 사용하는 것이 일반적, 불법 소프트웨어 차단하고, 고객들이 최신 버전을 사용하도록 유도한다는 점에서 소프트웨어 업체에는 큰 이득)
2. Oracle Java Subscription
▶ 서브스크립션
-서브스크립션을 구매하지 않은 기업은 오라클 JDK 자바 SE를 업무용, 상업용, 운영용으로 사용할 수 없다. (비상업적인 용도에 한해서는 이전과 같은 무료 사용이 가능)
- 업데이트 및 버그 패치도 제공되지 않는다.
- 서브스크립션 구매 후 기간이 종료되면 모든 접속이 금지된다.
- 새로운 라이센스는 서버 및 클라우드 인스턴스의 경우 프로세서 당 월 25달러를, 데스크탑의 경우 사용자 당 월 2.5달러를 요구한다. 대량구매 및 2년, 3년 장기 구독에 따른 할인이 제공된다. (개발용으로 프로젝트에서 사용시 '개발자 수' 이고 운영시에는 운영서버의 'core' 수 이다.)
- Subscription 계약은 월단위 과금이지만, 계약은 1년 단위로 이루어진다.
▶ Java SE Desktop Subscription (데스크톱 가격) - 사용자당 $2.5 / 월 | Monthly Subscription Price | Subscription Metric |Volume| 2.5Named User Plus1-999 2.0Named User Plus1,000-2,999 1.75Named User Plus3,000-9,999 1.5Named User Plus10,000-19,999 1.25Named User Plus20,000-49,999 Contact for Details50,000+
▶ Java SE Subscription (서버 및 클라우드 배포 환경) - 프로세서당 $25 / 월 | Monthly Subscription Price | Subscription Metric |Volume| 25Processor1-99 23.75Processor100-249 22.5Processor250-499 20Processor500-999 17.5Processor1,000-2,999 15Processor3,000-9,999 12.5Processor10,000-19,999 Processor20,000+
ex1) Java 운용 Application 서버 10 core / Desktop 사용자 100명 (28,031 * 10) + (2,803 * 100) = 560,610원 / 1개월 6,727,320원 / 1년
ex2) Java 운용 Application 서버 10 core / Desktop 사용자 100명 ※ 총 JAVA 이용비 = 서버 비용비 + 데스크톱 이용비 ※ 서버 이용비 = 25$ * 코어수 * 코어팩터(프로세서 성능지수) ※ 데스크톱 이용비 = 10(직원수)*2.50$=25$
▶ 기존 Oracle JDK 8 바이너리의 경우 2019년 1월 이후 업데이트부터 라이센스 구독을 요구한다. - 새로운 라이센스는 Oracle JDK 11 바이너리부터 적용된다. 또한, 오직 라이센스 구독자 만이 LTS 업데이트 지원을 받을 수 있다.
※ LTS : 장기지원서비스, JDK 11 : 2018.9월 출시된 자바SE 버전, 다음 LTS 지원 버전(Oracle JDK 17)의 출시는 2021년 가을(약 3년 뒤))
(오라클은 앞으로 6개월마다 새버전을 내놓고, 특정버전만 LTS(장기지원서비스)를 하겠다고 밝혔다. 오라클은 자바SE9 버전부터 6개월마다 자바를 업데이트한다. 버그패치와 같은 지원 서비스도 6개월까지만 진행한다. 원칙적으로 기업들은 6개월마다 자바SE 를 업그레이드 해야 한다. 하지만 기업에서 운영되는 플랫폼을 6개월마다 업그레이드 하는 것은 사실상 불가능하다. 이를 위해 LTS가 있다고 봐도 될 것 이다.)
※ 도입 검토 실제 사례 - 삼성 SDS에서도 이와 관련하여 개발자용 Subscription 구독을 검토하였으나 약 100몇억이나 비용이 발생한다고 추정 되어 구매를 포기하였다고 한다.
3. Oracle Jdk vs Open JDK
※ Open JDK와 Oracle 유료 JDK간 차이점
(1) Oracle 유료 JDK에는 개발, 버전관리 편의성을 증진시켜주는 관리 Tool 제공 - Java Web Start - Java SE 엔터프라이즈 관리 기능 · Java SE 8 AMC(Advanced Management Console) : 기업 전반에 배포된 Java 버전의 대시보드 뷰 제공 · Java SE 8 MSI Enterprise JRE Installer · Java SE 8 Java Flight Recorder & Mission control · Java SE 8 Java Usage Logger
(2) Oracle 유료 JDK는 최대 8년까지 패치/업데이트 제공, Open JDK는 6개월 간격으로 Minor 버전을 제공
- Open JDK6에서 파일 처리와 같은 기본적인 OS-Integration 관련 기능과 네트워크 처리 및 Swing에서 몇몇 문제점이 보고 되었으므로, Open JDK 사용 시에는 Open JDK 7 이상 사용을 권고한다고 한다.
(4) JDK8, JDK11, JDK 17이 앞으로 LTS로 지원됨을 알 수 있다. 이도 JDK 선택시 고려
4. OpenJDK는 운영 환경에 적합할까?
- TCK 인증을 받은 OpenJDK 기반의 빌드 버전을 사용하면 운영 환경에 아무런 문제가 없다.
- Java SE 7부터 모든 JDK는 OpenJDK 레퍼런스 소스 코드를 기반으로 제작된다. (Jave SE 6 버전의 OpenJDK는 백포트 방식으로 구현되어 성능 저하 이슈가 존재한다.) (OpenJDK는 자바 스펙을 명시한 JSR 336, JSR 337를 빠짐없이 완전히 구현한 구현체이다.)