Slide for talk "Effective Scala" at SpringCamp 2013 explaining how to use Scala in Scala (or more broadly functional language) style. This talk is for Scala novices who are usually ignorant of functional language paradigm but familiar with OOP.
SLiPP(https://slipp.net) 서비스를 Java에서 Scala로 전환하는 과정에 대해 살펴본다. Scala를 선택한 이유, Java와 Scala를 동시에 서비스하면서 점진적으로 리팩토링하는 과정, Scala + Spring 기반으로 개발할 때 고려사항, Java에서 Scala로 전환하는 과정에 대한 경험담을 공유한다.
Slide for talk "Effective Scala" at SpringCamp 2013 explaining how to use Scala in Scala (or more broadly functional language) style. This talk is for Scala novices who are usually ignorant of functional language paradigm but familiar with OOP.
SLiPP(https://slipp.net) 서비스를 Java에서 Scala로 전환하는 과정에 대해 살펴본다. Scala를 선택한 이유, Java와 Scala를 동시에 서비스하면서 점진적으로 리팩토링하는 과정, Scala + Spring 기반으로 개발할 때 고려사항, Java에서 Scala로 전환하는 과정에 대한 경험담을 공유한다.
스프링 컨테이너는 base-package의 클래스를 검색해서 자동으로 자바빈으로 등록하는데 이에 해당하는것이 @Component, @Repository, @Service, @Contoroller, @RestController 어노테이션이다.
자동스캔을 위해서는 <context:component-scan /> 과 같이 base-package를 기술하며, 패키지가 여럿인 경우, 콤마로 구분하여
기술한다.
박교수의 Swift강좌10-열거형과 구조체, 클래스에 대하여 이론적인 설명과 예제 프로그램을 통해 살펴보도록 하겠습니다. Swift의 열거형은 튜플값을 멤버로 가질 수 있으므로 C/C++보다 풍부하고 강력한 기능이 가능합니다. 또한 클래스와 구조체 모두 메소드를 가질 수 있다는 점이 C++와는 다른 점입니다.
Youtube
- https://www.youtube.com/watch?v=TykLyvMsGho
Scala, Spring-Boot, JPA를 활용한 웹 애플리케이션 개발 과정에 대해 다룬다. Spring-Boot와 JPA 조합만으로도 생산성 있는 웹 애플리케이션 개발이 가능하다. 이 조합만으로도 충분히 의미가 있지만 여기에 Scala라는 약간은 불편한 듯 보이는 언어를 도입함으로써 얻을 수 있는 즐거움을 공유한다. Spring-Boot + JPA 조합에 Scala를 적용하면서의 좌충우돌 경험담을 전한다.
8. 추상 클래스 Abstract Class
• 인스턴스화 될 수 없다.
• 클래스를 통해 상속할 수 있다.
• 추상 메소드는 구현부 없이 정의된 메소드이다
• abstract method를 포함한 클래스는 abstract로 정의되어야 한
다.
• Abstract class를 상속한 클래스는 abstract method의 구현부를
제공해야 한다. 그렇지 않으면, 자식 클래스도 abstract로 정의
되어야 한다.
9. Abstract Class vs Interface
• 공통점
• 인스턴스화 할 수 없다.
• 구현부 없는 메소드들을 정의할 수 있다.
• 차이점
• Abstract class
• Non-static, final 필드 정의 가능
• Public, protected, private concrete method 작성 가능
• 한 클래스만 상속 가능하다.
• Interface
• 모든 요소들의 접근 제어자가 public이다.
• 여러 인터페이스를 한번에 구현할 수 있다.
10. 언제 어떤것을 써야 하나요?
• 추상 클래스를 고려해야 하는 상황
• 긴밀하게 연결된 클래스들 간 코드를 공유하고 싶다.
• Abstract class를 상속받는 클래스들이 공통적인 메소드, 필드, public외의 다른 접근자가 필요하다고
예측할 경우
• non-static 이나 non-final 필드를 정의하고 싶을 경우.
• 인터페이스 사용을 고려해야 하는 상황
• 관계없는 클래스들도 당신의 인터페이스를 구현할 수 있다. 예를 들어, Comparable 과 Clonable
interface는 많은 관계없는 클래스들이 구현하고 있다.
• 특정 데이터 타입의 행동을 특정하고 싶을 때. 하지만 누가 행동을 구현하는지는 중요하게 생각하지
않을 때.
• 여러 개의 상속을 통한 이득을 얻고 싶을 때.
11. Generics
• 클래스, 인터페이스, 메소드를 정의 할 때 타입을 파라미터화 할
수 있게 만든다.
• 일반적인 paramter처럼, 다양한 입력들에 대해 같은 코드를 사
용할 수 있게 만들어준다.
• 일반적인 parameter에서는 입력이 값이고, Generics에서는 입
력이 type이다.
13. Generics 장점
• 컴파일 단계에서 타입 체크를 강하게 한다.
자바 컴파일러는 제네릭 코드에 대해 강하게 타입 체크를 하고 type safet를 충족하지 못하면 에러를 냅니다. 런타임 에
러는 찾기 어려울 수 있기 때문에 컴파일중 에러를 고치는 것이 더 수월합니다.
• 캐스팅을 없앨 수 있습니다.
• Generics를 쓰지 않는 코드:
• List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0);
• Generics를 쓴 코드:
• List<String> list = new ArrayList<String>();
• List.add("hello");
• String s = list.get(0); // no cast
• 프로그래머가 일반적인 알고리즘을 구현할 수 있게 합니다.
타입별로 다른 알고리즘을 구현하지 않아도 되고, type safe하고 읽기 쉽습니다.
15. Diamond operator
• 컴파일러가 Type를 결정할 수 있을 때 <>만 써줘도 된다.
• JDK 7 이후부터 지원
• List<String> list = new ArrayList<String>(c);
List<String> list = new ArrayList<>(c);
16. Java Collections Framework란?
• 자바 플랫폼에 포함된 프레임워크
• Collection?
• 여러 요소를 한 단위로 묶은 것
• 객체들의 그룹을 표현한 객체
• JCF는 collection을 표현하고 조작하는 것들을 통합한 아키텍처
17. 구성 요소들
• Collection 인터페이스. Collection들의 형태를 표현한다. 프레임워크의 기반을 형성하고 있다. Ex) sets, lists, maps.
• 일반적인 목적의 구현. 인터페이스들의 주요한 구현
• 알고리즘. Sorting같은 유용한 static 함수들
• 특별한 목적을 위한 구현
• 비동기 처리를 위한 구현
• Wrapper 구현. Synchronization 등의 구현을 더하는 기능
• 편리함을 위한 구현
• Abstract 구현. Cutsom Collection을 지원하기 위한 목적
• Infrastructure. Collection 인터페이스를 지원하는 필수적인 인터페이스들. Ex) Iterator, Comparable, …
• Array 유틸리티.
18. Advantages
• 프로그래밍 수고를 덜어줍니다.
자료구조나 알고리즘을 직접 작성하지 않아도 됩니다.
• 퍼포먼스를 향상시킵니다.
인터페이스간 다양한 구현들을 교체할 수 있기 때문에 구현을 프로그램을 튜닝하기 용이합니다.
• 관계없는 API간 상호 정보교환이 가능하도록 만듭니다.
• API를 배우는 수고를 덜어줍니다.
이전에는 API마다 각자 본인들의 collection을 사용해 익히기 어려웠습니다.
• 위와 같은 이유로, API를 디자인하는 수고를 들여줍니다.
Collection을 만들도 되지 않기 때문입니다.
• 소프트웨어 재사용성을 높입니다.
25. Vector & Stack – 권장하지 않는 이유
• 자바 1.0부터 이어져 왔지만 1.2버전부터 사용하지 않게 됨
• Vector
• 각 연산에 대해서 동기화 처리를 한다. -> 단일 스레드에서도 동기화 처리를 계속 한다.
• 퍼포먼스가 매우 안좋음
• 동기화 처리를 원한다면 SynchronizedList로 대체
• 동기화 처리를 원하지 않는다면 ArrayList로 대체
• Stack
• 위와 같은 이유로 퍼포먼스가 매우 안좋음
• 동기화 처리를 원한다면 SynchronizedStack으로 대체
• 동기화 처리를 원하지 않는다면 ArrayDeque으로 대체
27. List
• 순서가 있는 Collection
• 중복 요소를 가질 수 있음
• Collection에 더해 인터페이스에 포함된 기능들
• 위치로 접근 가능 – 숫자 위치에 기반하여 요소를 조작할 수 있음. Get, set,
add, addAll, remove.
• 검색 — 특정 객체를 검색하여 위치를 반환. indexOf, lastIndexOf.
• listIterator – 순서가 있다는 성질을 이용해 기존 iterator보다 많은 기능을 사
용 할 수 있습니다. 거꾸로 iterate, 특정 위치의 iterator 획득 등등.
• 범위 — sublist 관련한 method
31. ArrayList
• Array를 기반으로 List interface 구현.
• List의 모든 Optional 기능들을 구현. null을 포함해 모든 요소들을 허용한다.
• 연산들의 속도가 LinkedList보다 대부분 빠릅니다.
• Capacity : ArrayList 내부 배열의 크기
Size : ArrayList가 가지고 있는 요소들의 개수
Capacity는 최소 size만큼의 크기를 가지고 있습니다.
• ArrayList에 Capacity를 넘는 양의 데이터가 들어오면, 2배 크기의 배열을 만들고
값을 복사해 Capacity를 2배로 늘립니다.
36. PriorityQueue
• 힙 기반으로 구현된 우선순위 큐
• *natural ordering을 사용하기 때문에 non-comparable한 객체들은 삽입할 수 없다.
• Natrual ordering – Comparable 인터페이스 구현을 통해 순서를 정하는 방식
• 또는 PriorityQueue가 생성될 때 Comparator를 통해 순서 방식을 정해줄 수 있습니다.
• Queue의 헤드는 특정 순서법에 따른 최소값입니다. 최소값을 가진 요소가 여러가지라면, 그 중에 하나가 헤드가 됩니
다.
• 우선순위 큐는 크기 제한이 없습니다. ArrayList와 같이 Capacity는 내부적으로 저장하고 있는 배열의 크기이고, size는
담고 있는 요소들의 개수입니다. Element가 더해지면 capacity는 자동으로 커집니다. 크기가 커지는 정책은 정해져있지
않습니다.
• Collection과 Iterator 인터페이스의 메소드(optional 포함)들을 전부 구현하고 있습니다.
• 이 클래스에서 제공되는 iterator는 순서를 보장하지 않습니다. 만약 정렬된 상태를 원한다면 Arrays.sort(pq.toArray())
를 고려해야 합니다.
39. Deque
• Double ended queue
• 크기를 제한할 수 있다.
• 양 끝에서 요소에 접근할 수 있는 메소드들이 정의되어 있다.
• 용량이 제한된 덱을 위해 operation이 실패하면 special value를
리턴하는 형태의 메소드가 구현되어 있다.
40. The twelve methods described above are summarized in
the following table:
45. LinkedList
• 이중 연결 리스트 기반으로 List와 Deque을 구현
• 모든 optional 메소드들을 구현했다.
• Null을 포함해 모든 요소들을 허용한다.
• 이중 연결 리스트의 알고리즘을 사용한다. Index를 통해 접근하
려면 앞이나 뒤에서 차례차례 접근해 나가야 한다.
• 대부분 경우 효율이 좋지 않다. 정말 특정한 상황에서만 사용하
는 것을 권장
48. Map
• 키와 값를 매핑해주는 것
• 중복 키를 가질 수 없음.
• 각 키는 하나의 값만 가질 수 있음
• 기본적인 연산들 – put, get, remove, containsKey,
containsValue, size, empty
• 묶음(bulk) 연산들 – putAll, clear
• Collection Views – keySet, entrySet, values
49. Collection View
• View 는 Java Collections Framework에서 Collection 이나 Map
인터페이스를 구현한 가벼운 객체입니다. 하지만 실제로는
collection은 아닙니다. 사실은, 뷰는 다른 collection, 배열이나
단일 객체를 참조하고 이를 이용해 사용자에게 데이터를 제공
합니다.
52. HashTable – 사용하지 않는 이유
• 자바 1.0부터 이어져 왔지만 1.2버전부터 사용하지 않게 됨
• 각 연산에 대해서 동기화를 한다. -> 단일 스레드에서도 동기화
처리를 계속 한다.
• 퍼포먼스가 매우 안좋음
• 동기화를 원한다면 ConcurrentHashMap로 대체
• 동기화를 원하지 않는다면 HashMap로 대체
55. HashMap
• 해시 테이블 기반으로 맵을 구현
• Optional map 메소드들도 구현
• Null 키와 null 값 허용함.
• 시간이 지남에 따라 순서가 일정하게 유지된다는 것을 보장하
지 않음.
56. HashMap
• Hash function이 적절하게 구현되어 있다는 전제에 한해 Get,
put은 O(1)의 효율을 냅니다.
• Collection View를 Iterate 하는 것은 HashMap의 Capacity와
Key-value 쌍의 개수를 더한 것에 비례합니다.
• Iteration 효율이 중요하다면 초기 용량을 너무 크게 잡지 않아
야 합니다.
58. LinkedHashMap
• HashMap에 더해서 순서를 저장하는 doubly-linked list를 유지
합니다.
• 이 링크드 리스트는 iteration order를 정의하고, 보통은
insertion-order이다.
• HashMap과 같이 iterator를 사용하더라도 LinkedHashMap은
순서를 맞춰 iterator를 반환
60. SortedMap
• 키를 바탕으로 순서를 만드는 맵
• *natural ordering을 사용하기 때문에 non-comparable한 객체들은 삽입할 수 없습니다.
키들은 상호간에 비교가 가능해야 합니다.
• 또는 SortedMap이 생성될 때 Comparator를 통해 순서 방식을 정해줄 수 있습니다.
• 순서는 entrySet, keyset, values 메소드를 통해 반환되는 Collection view들에도 적용됩니
다.
• Key를 이용해 값을 꺼낼 때는 isEqual을 사용하고, 순서를 정할 때는 compareTo를 사용합
니다. 같은 객체에 대헤 isEqual과 comapreTo가 동일하게 계산되도록 주의해야 합니다.
63. NavigableMap
• 검색할 수 있는 Map
• 정확히 같은 객체 뿐 아니라 lower, floor, ceiling, higher로 검색
할 수 있습니다.
• lowerEntry : 제공된 Key보다 작은 최대의 Entry를 반환합니다. 없을 경
우에 null를 반환합니다.
• floorEntry : 제공된 Key와 같거나 작은 Key 중 최대의 Entry를 반환합
니다. 없을 경우에 null를 반환합니다.
• higherEntry, ceilingEntry 는 반대의 동작
66. Red-Black Tree
• 노드는 레드 혹은 블랙 중의 하나이다.
• 루트 노드는 블랙이다.
• 모든 리프 노드는 블랙이다.
• 레드 노드의 자식노드 양쪽은 언제나 모두 블랙이다. (즉, 레드 노드는 연달아 나타날 수 없으며, 블랙 노드만이 레드 노
드의 부모 노드가 될 수 있다)
• 어떤 노드로부터 시작되어 리프 노드에 도달하는 모든 경로에는 리프 노드를 제외하면 모두 같은 개수의 블랙 노드가
있다.
• 위 조건들을 만족하게 되면, 레드-블랙 트리는 가장 중요한 특성을 나타내게 된다: 루트 노드부터 가장 먼 경로까지의
거리가, 가장 가까운 경로까지의 거리의 두 배 보다 항상 작다. 다시 말해서 레드-블랙 트리는 개략적(roughly)으로 균
형이 잡혀 있다(balanced). 따라서, 삽입, 삭제, 검색시 최악의 경우(worst-case)에서의 시간복잡도가 트리의 높이(또는
깊이)에 따라 결정되기 때문에 보통의 이진 탐색 트리에 비해 효율적이라고 할 수 있다.
67. TreeMap
• Red-Black Tree를 기반으로 구현된 NavigableMap.
• Key를 통해 Natural ordering을 하거나, 맵을 생성할때 제공된
Comparator를 이용하여 순서를 정합니다.
69. java.util.Set
• 수학에서의 집합을 모델링
• 중복된 요소를 포함하지 않는 collection
• 정확히는 e1.equals(e2) 를 충족하는 어떤 요소도 포함하지 않는
다.
• Mutable 객체가 Set의 요소로 사용된다면 굉장한 주의를 기울
여야 합니다. Set은 요소의 값이 바뀌어 equals 연산에 영향을
주는 것에 대해 어떤 동작도 하지 않습니다.
72. HashSet
• HashMap 기반으로 구현된 Set
• 시간이 지남에 따라 순서가 일정하게 유지된다는 것을 보장하
지 않음.
• Null 요소 허용
• HashMap 기반이기 때문에 HashMap의 특성을 가집니다. 예를
들어, iteration을 효율적으로 하기 위해서는 capacity 조절해야
합니다.
76. LinkedHashSet
• HashMap에 더해서 순서를 저장하는 이중 연결 리스트를 유지
합니다.
• 이 연결 리스트를 통해 입력된 순서로 iteration order를 정의합
니다.
• 순서에 맞춰 iterator를 반환합니다.
• 추가적으로 구현된 메소드는 없습니다.
78. SortedSet
• 순서가 있는 집합
• *natural ordering을 사용하기 때문에 non-comparable한 객체들은 삽입할 수 없습니다.
키들은 상호간에 비교가 가능해야 합니다.
• 또는 SortedSet가 생성될 때 Comparator를 통해 순서 방식을 정해줄 수 있습니다.
• 순서는 entrySet, keySet and values 메소드를 통해 반환되는 Collection view들에도 적용
됩니다.
• Key를 이용해 값을 꺼낼 때는 isEqual을 사용하고, 순서를 정할 때는 compareTo를 사용합
니다. 같은 객체에 대헤 isEqual과 comapreTo가 동일하게 계산되도록 주의해야 합니다.
81. NavigableSet
• 검색할 수 있는 Set
• 정확히 같은 객체 뿐 아니라 lower, floor, ceiling, higher로 검색
할 수 있습니다.
• lower : 제공된 요소보다 작은 것 중 최대의 요소를 반환합니다. 없을
경우에 null를 반환합니다.
• Floor : 제공된 요소와 같거나 작은 것 중 최대의 요소를 반환합니다. 없
을 경우에 null를 반환합니다.
• higher, ceiling 는 반대의 동작
84. TreeSet
• TreeMap을 기반으로 구현된 Set
• 요소를 통해 Natural ordering을 하거나, Set을 생성할때 제공된
Comparator를 이용하여 순서를 정합니다.
85. Custom Collection 구현
• Custom 구현을 해야할 이유들
• Persistent: ex) 외부 데이터베이스와 직접 연결되는 Collection 등.
• 앱에 특화된 Collection: ex) 전파와 관련된 데이터를 가지는 Map. Key가 위치일때, value는 위치를 이용해 센서에서 읽
어온 전파 값.
• 고효율, 특별한 목적
• 고효율, 일반적인 목적
• 기능 강화: ex) MultiSet – 중복 요소를 허용하는 Set. Suppose you need an efficient bag implementation (also known
as a multiset): a Collection that offers constant-time containment checks while allowing duplicate elements. It's
reasonably straightforward to implement such a collection atop a HashMap.
• 편리성: ex) 특정 범위의 연속되는 자연수를 가진 리스트가 자주 필요할 경우
• Adapter : legacy API를 사용해 Java Collections Framework와 연결해주는 Adapter가 필요할 경우
87. AbstractList
• 수정할 수 없는 리스트를 구현하기 위해서는 이 클래스를 상속
해서 get(int)와 size() 메소드만 구현하면 된다.
• 수정 가능한 리스트를 구현하기 위해선 추가적으로 set(int, E)
메소드를 override 해야 한다.
• 가변적인 크기를 가진 리스트를 구현하기 위해선 add(int, E),
remove(int) 를 추가적으로 구현해야 한다.
• Argument가 없는 생성자를 제공해야 하고, Collection 인터페이
스 명세에 따르는 것을 권장한다.
91. Arrays.asList
• asList는 java.util.ArrayList가 아니라
java.util.Arrays$ArrayList를 반환합니
다.
• Immutable list이고, view의 역할을
합니다 – 값을 복사하지 않습니다.
• 따라서 값을 바꿀일이 없을 때,
asList를 활용하면 더 빠른 효과를
낼 수 있습니다.
92. Google Guava
• Google에서 제공하는 Java library
• 그 중 Collection과 관련된 항목들
• Immutable collection
• New collection types
• Powerful collection utilities
• Extension utilities
93. Immutable collections
• 신뢰할 수 없는 라이브러리로부터 안전하다.
• 쓰레드와 함께 사용하기 안전하다.
• 수정을 제공할 필요가 없어서, 시간과 공간을 절약할 수 있다.
• 상수로 사용할 수 있다.
94.
95. 결론
• 항상 생각없이 ArrayList만 사용했었는데, 좀 더 고민을 하고 자
료구조를 결정하는 것이 좋겠습니다.
• 기회가 되면 Google Guava를 공부해 적용하는 것도 좋을 것 같
습니다.
• immutable 여부를 생각해보기
• Reference Type을 List로 쓰는 등 다형성을 통해 내부 구현을 쉽
게 바꿀수 있도록 코딩 습관을 고쳐야 겠습니다.