2018년 3월 4일 일요일

RESTful - Stateless

Stateless.. 서버가 클라이언트의 상태를 저장하지 않는 것.

클라이언트는 매 요청마다 자신을 인증할 수 있는 Token이나 Key 등을 Request에 포함시켜 전송해야 한다. 또는 연속된 작업에서의 상태 정보를 포함시켜야 할 수도 있다.

이렇게 했을 때 가져갈 수 있는 장점은?
Caching, Load balancing, Scale-out.

단점은? 매 요청시마다 상태 정보를 전달해야 하기 때문에 그 만큼의 네트워크 리소스가 소모될 수 있다. (또는 상태 정보 처리에 따른 서버의 부하..)

/

REST architecture(참고 : https://ko.wikipedia.org/wiki/REST)는 stateless 하면서 동시에 어떤 클라이언트 관련정보도 서버에 저장하지 않는 방식을 사용한다. 즉, 상태 정보는 클라이언트가 관리하고 서버는 scale-out 할 수 있게 된다. (클라이언트의 요청을 어느 서버가 처리하던 동일한 결과를 보장할 수 있다.)

만약에, 대규모 환경에서 동일한 웹서버를 다수 배치해 로드밸런싱 하는 경우에 stateful 하다면 각 서버는 클라이언트의 상태(세션)을 공유할 수 있는 Redis와 같은 별도 시스템이 필요하게 된다.

인증을 거치는 서비스가 Stateless 하다면 매번 인증을 위해 ID / Password를 보내야 하나? 그렇게 해도 되지만 대신할 수 있는 몇 가지 기술이 있다.

- HTTP Basic Auth
- HTTP Digest Authentication
- API Key or Access Token
- OAuth

Lombok

Lombok은 getter, setter, toString, equals, hashCode 메서드 등을 자동으로 추가해주는 Annotation 기반 라이브러리이다.

아래 링크에서 다운받을 수 있다.
https://projectlombok.org/download

다운로드 받은 Jar를 실행해서 설치하면 되는데, 설치 IDE를 인스톨러가 찾아준다. 기다리기 귀찮으면 직접 지정해주어도 됨.

설치가 끝났으면.
lombok.jar를 프로젝트에 추가 > IDE를 재시작 해주면 적용된다.

gradle엔 dependencies에 compileOnly('org.projectlombok:lombok:1.16.20')과 같이 지정해주고,

쓰면 된다.

/

주로 쓰게되는 Annotation은 '@Data' 이다.
모든 필드에 getter, setter를 만들어 주고 toString, equals, hashCode 메서드를 만들어 준다.

그 밖에 toString 출력 형식을 조정하거나, 특정 프로퍼티의 getter 또는 setter의 접근 레벨을 제한하거나, 등등의 디테일한 조정을 할 수 있다.

세부적인 기능은 https://projectlombok.org/features/all를 참고할 것.

2018년 1월 10일 수요일

Spring @Bean vs @Component

@Bean의 경우 개발자가 컨트롤할 수 없는 외부 라이브러리를 Bean으로 등록하고 싶은 경우에 쓰인다. (외부 라이브러리 인스턴스를 생성하는 메서드를 만들고 해당 메서드에 @Bean을 선언하여 Bean으로 등록한다.)
개발자가 직접 컨트롤할 수 있는 클래스엔 @Component를 사용한다.

@Bean
@Scope("prototype")
public SomeService someService() {
    switch (state) {
    case 1:
        return new Impl1();
    case 2:
        return new Impl2();
    case 3:
        return new Impl3();
    default:
        return new Impl();
    }
}
위는 @Bean의 전형적인 사용 패턴이다. @Component로 대체할 수 없다. 좀 더 단순화 하면 @Bean은 반환되는 객체를 Bean으로 등록하기 위함이다. @Component는 사용자가 작성한, Component Scanning 되는 대상이다.

그리고 스프링이 제공하는 컨테이너를 통해서 관리되는 인스턴스를 모두 Bean이라 부를 수 있다. Bean은 기본적으로 싱글톤 scope를 가진다. 따라서 일반적으로 Bean으로 지정된 클래스는 컨테이너에서 1개의 인스턴스로만 존재할 수 있다.

Bean

이름을 왜 'Bean'으로 지었는지는 알 수 없지만 Java Bean은 아래의 특성을 가지고 있다.

1. 직렬화 가능해야 한다. (Serializable)
2. 인자가 없는 기본 생성자를 갖고 있어야 한다.
3. 속성에 대해 'public' setter / getter를 가지고 있어야 한다.
4. 인스턴스의 속성은 'private'로 지정되어 있어야 한다.

A JavaBean is a Java object that satisfies certain programming conventions:  
1.The JavaBean class must implement either Serializable or Externalizable
2.The JavaBean class must have a no-arg constructor
3.All JavaBean properties must have public setter and getter methods
4.All JavaBean instance variables should be private

스프링 프레임워크에는 이 외에도 다양한 Annotation이 존재한다.
@Controller: 스프링 MVC의 컨트롤러를 나타낸다. Spring 4+에선 REST 웹 서비스 용으로 @RestController가 추가로 제공된다. 차이점은 다음과 같다. @Controller의 주-동작은 View를 반환하는 것이고 @RestController의 주-동작은 데이터를 반환하는 것이다. 물론 @Controller에서 View가 아니라 데이터 반환 목적으로 @ResponseBody를 선언해 사용할 수도 있다. @RestController에선 @ResponseBody를 붙이지 않아도 되고, 상태 코드를 위한 ResponseEntity 장치가 준비되어 있다. (http://doublesprogramming.tistory.com/105)
@Service: 서비스 클래스를 나타내나 기능면에선 @Component와 동일하다.
@Repository: 리포지터리 클래스를 나타낸다. 이 Annotation이 붙은 클래스 내에서 발생한 예외는 DataAccessException으로 교체된다.

Java Servlet이란?


A servlet is a java programming language class that is used to extend the capabilities of servers that host applications accessed by means of request-response programming model.

Java Servlet(이하 서블릿)은 자바 프로그래밍 언어를 사용하여 웹페이지를 동적으로 생성하는 서버측 프로그램 사양을 의미한다. 즉 스펙이다.
비슷한 기술로는 CGI가 있는데 CGI는 요청마다 새로운 프로세스를 생성하여 응답하는 데 비해, 서블릿은 요청마다 프로세스보다 가벼운 스레드로 응답하므로 보다 가볍다.

서블릿엔 'main'과 같은 진입점이 없다. (~let으로 끝나는 형태의 프로그램은 자체적인 실행파일구조를 가진게 아니라 다른 환경에 의해 실행되어지는 단위로 유추 가능하다.) 이러한 서블릿을 구동하기 위해서는 Tomcat이나 Jetty와 같은 서블릿 컨테이너가 필요하다. 따라서 서블릿이 올바르게 동작하려면 서블릿 컨테이너에게 구체적인 동작 정보를 알려주어야 하고 이러한 정보는 web.xml 파일에 기술된다.

web.xml에 기술되어야 하는 내용은 대략 다음과 같다. (서블릿 3.0 부터는 WebApplicationInitializer을 통해 설정을 자바 코드에서 할 수도 있고, 아예 없앨 수도 있다.)
- 특정 외부 요청에 대해 어떤 서블릿이 응답할 것인지. (servlet mapping)
- 특정 외부 요청에 대해 어떤 필터가 반응할 것인지. (filters)
- 웹 애플리케이션 내 특정 이벤트가 발생했을 때 어떤 클래스에게 통지해야 하는지. (listeners)
- 웹 애플리케이션의 설정 파라미터 (context-params), 보안 관련 설정 등..

서블릿 컨테이너는 초기 구동시에 사용자가 작성한 web.xml을 읽어 서블릿을 생성해주고 클라이언트의 Request를 받고, Response를 보낼 수 있게 통신을 해준다. (소켓을 만들고, Request / Response에 대한 스트림 처리등의 수고를 서블릿 컨테이너가 대신 수행해주는 것이다.) 서블릿의 생명주기 또한 서블릿 컨테이너가 관리해준다.

+ JSP vs Servlet
JSP가 HTML 문서 안에 Java 코드를 포함하고 있는 반면, 서블릿은 자바 코드 안에 HTML을 포함하고 있다. 그렇지만 결과적으로론 JSP를 컴파일 하면 서블릿으로 변환된다.

+ Spring과 Servlet
스프링과 서블릿 간에 직접적인 관계는 없다. 스프링은 '의존성 주입'이라는 디자인 패턴을 구현해놓은 자바 프레임워크이다. 단지 스프링 프레임워크가 서블릿 기반 MVC 웹 애플리케이션을 쉽게 구축할 수 있는 기능을 제공하고 있을 뿐이다.

2018년 1월 4일 목요일

Jetty 사용하기.

자바 기반의 웹 서비스를 구동하기 위해선 Tomcat이나 Jetty 같은 WAS(서블릿 컨테이너)를 선정해야 한다. Tomcat을 가장 많이 쓰는 것으로 알고 있지만 Jetty도 나름의 장점이 있다.
Jetty는 다른 WAS에 비해 가볍고 설정이 쉬우며, 사용자가 원하면 Jetty의 HTTP 모듈을 애플리케이션에 직접 넣어 구동시킬 수도 있다.
(Jetty엔 'Don't deploy your application in Jetty, deploy Jetty in your application! 이라는 슬로건이 있다.)

Jetty를 설치하는 방법부터 사용 방법까지 간단히 알아보기로 하자.

Jetty는 아래 url에서 다운로드할 수 있다.
http://www.eclipse.org/jetty/download.html

Jetty의 설정과 관련된 내용이 궁금하면 아래 링크를 참조하면 되는데, 굳이 설정을 변경할 일은 크게 없어 보인다.
http://www.eclipse.org/jetty/documentation/current/

Jetty를 설치하면,
Jetty XML 설정 파일이 위치하는 etc/ 폴더가 있고,
start.ini
start.jar
webapps/ 폴더가 생성된다.

start.jar를 실행시키면 Jetty가 실행되는 구조인데, 배포하려는 war 파일을 webapps 폴더에 넣어주면 된다. 만약 파일명이 abc.war이면 이 servlet의 url은 /abc/...로 매핑된다는 점을 기억하자.

Jetty 실행 방법은 좀 전에 적혀있듯이 그냥 start.jar를 실행시켜주면 된다.
java -jar start.jar 명령어와 함께 실행 옵션을 같이 부여할 수 있다.

Jetty를 종료할 땐 Jetty를 구동한 콘솔에서 Ctrl + C를 누르면 되고,
실행 콘솔과 종료 콘솔이 다른 경우엔 STOP.PORT, STOP.KEY 시스템 프로퍼티를 이용해서 Jetty를 켜고 끄면 된다.

+ Spring boot에선 기본 WAS가 Tomcat으로 지정되어 있는데, Jetty로 변경하고 싶은 경우 다음과 같이 설정을 변경해주면 된다. 
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot/groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

Gradle 설정은 아래 링크의 73.11 Use Jetty instead of Tomcat을 참고하면 된다.

2017년 12월 27일 수요일

Guava와 Java 8

# 과제도 끝났고, 모르던거 살펴보는 중인데.. 아. 부끄러움은 나의 몫이다. Java 8 버전을 쓰고 있지만 정작 편의상 버전만 올렸을 뿐이지 뭐가 어떻게 바뀌었는지 전혀 따라가지 못했다.

# Guava는 JDK에서 제공되지 않는 자주 쓸법한 기능들을 대신 지원해주는 라이브러리이다. 그런데 Java가 8로 업데이트 되면서 Guava에서 제공하던 기능을 유사하게 제공하게 됨에따라 역할이 다소 모호해졌다. (그렇지만 라이브러리 대신 JDK를 써야할 의무는 없고, 모두가 Java 8을 쓰는 것도 아니다.)


Java 8 LocalDate
: 낮은 버전의 Java를 사용해보면 날짜 관련 기능이 굉장히 불편하다 느낄 수 밖에 없는데 Java 8에서 비약적으로 개선되었다. LocalDate, LocalDateTime, LocalTime이 그것이다.
Date, DateTime, Time 버전이 각각 있고, 메서드는 거의 동일하다.

LocalDate day = LocalDate.of(2017, 12, 28);
LocalDate.now(); // ,... LocalDateTime, LocalTime
LocalDate.of(2017, 12, 28).format(DateTimeFormatter.BASIC_ISO_DATE); // 20171228
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));


Guava Strings
: C#에서 자주쓰는 isNullOrEmpty가 참 반갑다.

Strings.isNullOrEmpty(s);
Strings.nullToEmpty(s);
Strings.repeat("-", 70);


Guava Joiner
List<String> parts = ,...
Joiner.on(", ").skipNulls().join(parts);


Guava MapSplitter
MapSplitter splitter = Splitter.on(" ").withKeyValueSeparator(":");
splitter.split("a:1 b:2"); // => Map {a=1, b=2}


Guava Iterable
Iterable<Person> adults = Iterables.filter(persions,
new Predicate<Person>() {
@Override
public boolean apply(Person p) {
return p.getAge() >= 18;
}
});
List<String> names = Lists.newArrayList(Iterables.transform(adults,
new Function<Person, String>() {
@Override
public String apply(Person p) {
return p.getName();
}
}));


Guava FluentIterable
FluentIterable.from(persons)
.filter(new Predicate<Person>() {
@Override
public boolean apply(Person p) {
return p.getAge() >= 18;
}
})
.transform(new Function<Person, String>() {
@Override
public String apply(Person p) {
return p.getName();
}
})
.toList();


Java 8 Lambdas
: 반갑다 람다 :D

Predicate<Person> predicate = p -> p.getAge() >= 18;
Comparator<Person> comparator = (a, b) -> a.getName().compareTo(b.getName());
Runnable runnable = () -> ...;


Guava & Java 8
FluentIterable.from(persons)
.filter((Person p) -> p.getAge() >= 18)
.transform((Person p) -> p.getName())
.toList();
#Eclipse: Quick Fix (Ctrl + 1) -> Convert to lambda expression


Java 8 Streams
: 일반적인 loop 구문과 비교했을 때, 빠르게 동작하진 않는 것 같다. 병렬 버전의 parallelstream도 있다.

persons.stream()
.filter(p -> p.getAge() >= 18)
.map(p -> p.getName())
.collect(Collectors.toList());

List<String> parts = ...;
parts.stream().collect(Collectors.joining(", "));

Map<Integer, List<Person>> personByAge = persons.stream()
.collect(Collectors.groupingBy(p -> p.getAge()));

Double averageAge = persons.stream()
.collect(Collectors.averagingInt(p -> p.getAge()));


Guava Comparing
Ordering.natural()
.onResultOf(new Function<Person, String>() {
public String apply(Person input) {
return input.getName();
}
})
.compound(Ordering.natural()
.onResultOf(new Function<Person, Integer>() {
public Integer apply(Person input) {
return input.getAge();
}
}));


Java8 Comparing
Comparator.comparing(Person::getName)
.thenComparing(Person::getAge);


Guava I/O
List<String> line = Files.readLines(new File(...), Charsets.UTF_8);
Files.copy(new File(...), new File(...));
FluentIterable<File> traversal = Files.fileTreeTraverser().postOrderTraversal(new File("dir"));


Guava Stopwatch
Stopwatch stopwatch = Stopwatch.createStarted();
...
logger.info("Elapsed: " + stopwatch);


Guava Math
IntMath.checkedPow(2, 10); // => 1024
IntMath.divide(7, 2, RoundingMode.HALF_UP); // => 4

출처: https://github.com/robinst/guava-java8-presentation

2017년 12월 17일 일요일

제10회 코리아 DATA 테크 세미나

4차산업혁명시대 산업별 데이터 활용 전략 및 성공사례

일시: 2017년 12월 14일(목) 14:00 - 17:00
장소: 과학기술회관 대회의실

01 데이터로 달리는 자동차
- 자동차의 진화
- 자동차 내부 데이터 활용
- 자동차 주변 환경 데이터 활용
- 운전자와 이용자 데이터 활용
# 순수 기계 > 전기의 이용 > 전자 부품 도입 > 제어 컴퓨터의 사용 > 소프트웨어 발전 > 인지 센서의 발전 > 인공지능.
# 인간 편의를 극대화 하는 방향으로 발전 중.
# Tesla Autopilot > Strike Out System > Nvidia Drive PX2

02 데이터 기반의 스마트 팩토리
- Industry 4.0과 Data 분석
- 선진사 Case Study
- 두산 중공업 Data 분석 추진 방향
- 중공업 Data 분석 사례
- Wrap up
# 기계 > 에너지 > 컴퓨터 > 데이터 + 분석.
# 3 Keywords. > Hyper-Connected; 정보를 제공 및 생산, Hyper-Intelligent; 정보를 분석해 일정한 패턴을 파악, Predictivility; 분석 결과를 통해 인간과 기계의 행동을 예측.
# 두산중공업에선 데이터 분석에 대한 조직의 변화 관리 / 교육을 수행하고 있음. > 자체 공장을 보유하고 있고, 작은 개선이더라도 효과가 큰 업종이라 가능한 것으로 보임.
# 사례에서 특이점은 없음. 여러 참여자의 협업이 중요. 경험상 3Cycle 정도의 순환이 일어난 다음에 성공을 거두는 사례가 많았다고 함. 

03 빅데이터 분석 기반의 소비자 행동 예측
- 예측의 개념과 범위
- 금융 산업의 주요 이슈
- 예측 관련 이론과 시사점
- 금융산업의 예측과 적용 사례
# 금융회사 경쟁력 4대 요소. 인재, 기술, 프로세스, 데이터. 그 중 '데이터'는 그동안 가장 활용되지 못햇던 부분.
# 데이터는 변하지 않는 요소. 지속 가능한 가치.
# 요건 정의가 중요하다고 판단됨. 예를 들어 '이탈 고객'의 수를 예측 해야 한다고 할 때. '이탈'에 대한 정의는 하기 나름이므로.
# What > How > Why 순으로 업무를 진행할 것이 아니라
Why > How > What으로 진행하는 것이 옳다고 생각함.
# 저이용&고충성 > 고객 관리, 고이용&고충성 > 이탈 방지, 저이용&저충성 > Up Selling, 고이용&저충성 > 핵심 Target

04 데이터 공유에서 증거공유로 : 글로벌 10억명 임상의료데이터 공급망
- 데이터 공유 vs 증거공유
- 분산연구망
- 공통데이터모델(CDM)과 오픈이노베이션
- 오딧세이 컨소시엄 국내외 현황
# 의료 데이터 연구 쪽에서 굉장히 유명하신 분이신듯. (박래웅 교수님)
# 다기관 데이터 결합에서 기술적, 법적 문제보다 데이터 공유에 대한 두려움, 데이터를 공유하고 싶지 않아 하는 '인간본성 문제'의 걸림돌이 컸음.
# 다기관 임상자료 수집/통합의 어려움. > 데이터를 공유하지 않고 증거를 공유함으로써 문제를 해결.
# ami.ajou.ac.kr:8080