불변객체라고 부른다. Java에만 있는 개념은 아니고, 일반적으로 왠만한 언어에는 다 있는 개념이다.

간단히 설명하면 immutable object는 최초에 생성된 뒤 변화할 수 없는 객체이다.

대조적으로 mutable object는 수정이 가능하다.


String s = "ABCDEC";

s.toLowerCase();

toLowerCase는 "ABCDE"를 바꾸는 것이 아니라 "abcde"라는 새로운 String 객체를 생성한다.

(jdk소스를 보면  return new String(result, 0, len + resultOffset); 와 같이 되어있다.)


유사한 immutable로는 Integer, Long, Short, Double, Float, Character, Byte, Boolean등의 Primitive wrapper가 있다. 이러한 immutable object들은 thread-safe와 보안의 목적으로 자주 사용된다.


인위적으로 불변객체를 만들어서 값의 변경이 불가능하도록 하는 것도 가능하지만 생각보다 귀찮은 방법이다. 

(방어복사 : defensive copying)

간략하게 설명하면 class와 멤버변수를 final로 정의하고, setter메소드를 없앤다.

또한 getter메소드에서 값을 반환할 때 clone을 생성하여 반환하도록 한다.

(만약에 멤버변수가 객체라면 해당객체를 deep copy해야 보다 완벽할 듯)


immutable object에는 많은 장점이 있다.

- 기본적으로 thread safe하고

- 동기화작업에서 이점이 있다. (lock을 걸 필요가 없다.)

- 또한 안정한 공유,재사용이 되기 때문에 cache를 사용하여 성능향상 및 메모리 효율을 도모한다.

- 이러한 공유는 복잡도를 감소시킨다. O(n) => O(1)


다만 대량 작업을 수행할때 몇가지 속도에 단점이 있어서 튜닝이 필요한 부분들이 있었다.

- concatenation연산이 새로운 객체생성으로 인한 비용이 비싼편이다. 물론 1.6이후였나? StringBuilder를 사용하기 떄문에 대부분 해소가 된다.

- 반복적인 new copy의 경우 메모리 소모가 매우 증가한다. 100만번 loop문을 수행하면 @.@


내가 수행하고자 하는 업무의 특성에 따라 맞게 사용하면 될 듯한데, WAS상의 온라인업무에서는 적극 활용되는 모습니다.


참고(http://stackoverflow.com/questions/9544182/why-are-strings-immutable-in-many-programming-languages)


1. 공통점과 차이점 비교

공통점

- 인스턴스화 할 수 없다.

- 상세구현없이 메소드를 정의한다.


차이점

- Interface의 경우 public만 가능하다.

- Interface의 경우 동시에 여러개 사용이 가능하지만, Abstract Class의 경우 하나만 사용가능하다.


2. 적용되는 유형

Abstract Class

- 연관되는 클래스들이 공통되는 코드를 포함하고 있을 때

- public외의 접근자 사용이 필요할 때

Interfaces

- 연관성없는 클래스들이 각기 구현이 필요할 경우

- 상세구현내용에 대해서는 몰라도 될때


3. 정리

- Interface의 경우 제공되는 기능을 중심으로 정리되는 듯 하다. 

  ex) JDBCOperation, ItemOperation

- Abstract의 경우 추상화를 통한 공통변수, 메소드 정리에 사용된다. 

  ex) Graphic Object (Line, Circle, Rectangle)

- Interface와 Abstract 동시사용이 가능하다. 일반적으로 팩토리 패턴에서 많이 사용된다.


인터페이스의 경우 원격호출을 통해서 사용할 때 상대에게 방식을 알려주는 용도로 많이 사용된다.

따라서 한번 정의되면 변경이 쉽지 않기 때문에 처음 정의시 고민이 필요하다.

Abstract의 경우 기본구현을 통해서 뼈대를 만들고 각 상세메소드는 상속클래스에서 정의하는 방식을 많이 사용한다.

이 때 상위클래스의 빈 메소드는 Abstract Method로 정의해주는 것이 혼란을 피할 수 있다.


짧지 않은 IT생활을 하면서 얻었던 소중한 경험중에 하나는 Rebecca Wirfs-Brock에게 6개월간 강의를 들었던 것이다. 온/오프라인에 걸쳐서 업무와 병행하여 수강하는 것이(그것도 영어로 ㅜㅜ) 쉽지는 않았지만... 그 뒤로 Application Design을 보는 눈이 달라졌다고 생각한다.

하나를 만들더라도 재사용이 가능하게, 쉽게 확장이 가능하게

이를 위해서 배웠던, 어쩌면 이미 모두가 알고 있는 Designing Object-Oriented Software 에 대해서 차근차근 정리해보려고 한다.  (벌써 2년이나 지나서 가물가물 @.@)

빅데이터 분석에서 배치활용

최근 다양한 분야에서 빅데이터 분석이 활용되고 있다. 일반적으로 빅데이터 플랫폼을 구현하기 위해서는 수집->정제->분석->결과전이->Visualization등의 단계가 필요하다고 볼 수 있다.

이 중 수집단계에서는 수집주기에 따라서 RealTime/배치성/NearRealTime으로 나누며, 유형에 따라서는 정형/비정형으로 나눌 수 있다. 

기존 배치작업의 경우 정기적 정형데이터 (ex, RDBMS or File등)의 수집에서 활용될 수 있다.

다만 몇가지 차이점을 고려해야 한다.


배치작업으로 빅데이터 수집 시 고려해야 할 점

범용성

여러 노드에 위치한 다양한 Legacy DB로부터 데이터를 수집해야 하기 때문에 범용성이 있어야 한다. SQL은 되도록 ANSI SQL을 준수하고 DBMS자체의 함수사용을 자제한다. 처리속도의 향상을 위해서 프로시저는 제한적으로 사용이 가능하지만 추후 유지보수나 비지니스 변경을 적시에 반영하기 위해서는 신중한 검토가 필요하다.

원격서버에 대한 실행제어

데이터 수집의 속도향상을 위해서는 분산환경을 이용해야 하며, 데이터 유형에 따라서 이미지수집,로그수집 등 다양한 프로세스가 존재할 수 있다. 이를 한곳에서 모니터링하고 제어할 수 있는 환경이 필요하다.

사용성

분석자는 개발을 모른다는 전제하에 수집기능이 제공되어야 한다. 분석작업을 위해서 데이터를 수집할 때 단순한 쿼리수행과 옵션만으로 기능을 사용할 수 있어야 한다. UI기반으로 수집모델을 만들어 낼 수 있다면 더욱 좋다.

경량성

일반적으로 빅데이터 분석시 사용하는 Hadoop은 여러노드에서 분산처리된다. 수집작업을 같은 노드에서 수행할 경우 서버자원에 경합이 발생하여 성능저하를 야기할 수 있다. HDFS적재의 편리성 때문에 Hadoop 노드에서도 수집작업이 이루어짐을 감안한다면 최소한의 패키징과 라이브러리로 자원소모량을 줄일 필요가 있다.

데이터 매핑

빅데이터 분석을 위해서 수집되는 데이터는 과거 업무프로세스에 의해서 정의된 배치작업과는 다르게 수시로 Input/Output Layout이나 쿼리문이 변경되어야 한다. 이를 위해서 쉽게 데이터 매핑을 지원해야 한다.


ps)파일을 읽어야 하는 수집작업이지만 배치성이 아니라 Near-Real Time의 수집처리가 있을 수 있다. (ex, System Log, Daemon Process)

'Software Architecture' 카테고리의 다른 글

Go Reactive Systems  (0) 2015.03.25
scale out 이 가능한 architecture? micro service?  (0) 2015.03.25
배치 어플리케이션 개발시 고려사항  (0) 2014.04.20
Batch Architecture 고려사항  (0) 2014.03.31
Enterprise Batch  (0) 2014.03.31

배치 어플리케이션 개발시 고려사항

배치 아키텍처가 준비되었다면 실제 배치 어플리케이션을 설계/개발해야 한다. 이를 위해서 고려해야될 사항을 살펴본다.

데이터 설계

배치에서는 대용량의 데이터를 다루기 때문에 이부분에 대한 고민이 많이 필요하다.

Resource유형

File

기본적으로 배치는 데이터를 순차적으로 처리하기 때문에 File처리가 DB처리보다 속도에 장점이 있다. 또한 다른 시스템으로 처리결과를 전달하기 위해서는 일반적으로 파일전송을 많이 사용한다. File을 생성하거나 참조할때에는 Charset에 주의해야 한다. 또한 File Input/Output 레이아웃 정의시 한글이 포함된 컬럼의 경우 byte length가 달라지는 것을 감안해야 하며 숫자컬럼을 표현할 때에는 부호,소수점에 따라서 교정이 필요할 수 있다.

  • Fixed Length : 레코드의 각 컬럼이 고정길이로 구성되어 있다. length로 각 컬럼을 구분한다. (ex, SAM파일)
  • Variable Length : 레코드의 각 컬럼이 가변길이로 구성되어 있다. Column Separator로 각 컬럼을 구분한다. (ex, CSV파일)

DB

DB의 경우 Connection을 얻고 PreparedStatement를 생성하여 쿼리를 날리는 작업이 필요하기 때문에 상대적으로 느릴 수 있으나 배치작업을 통해서 생성된 데이터가 다른 곳에서 많이 참조가 될 경우에는 데이터 Access에 이점이 있다. 또한 File 처리에 비해서 개발방법이 쉽고, 변경이 발생해도 빠르게 반영할 수 있다.

CHAR vs VARCHAR

과거 COBOL을 사용했던 시스템에서는 가변형이라는 데이터 타입이 존재하지 않았기 때문에 CHAR타입이 아직도 많이 남아있다. 고정길이 데이터에는 CHAR타입을 사용하는 것이 원칙이지만 데이터 타입은 언제 어떻게 변경될지 모르기 때문에 차세대 이후부터는 CHAR타입보다는 VARCHAR타입을 사용하는 것을 권장한다. 예로 CHAR형으로 데이터가 선언되어 있을 경우 남는 공간에 공백문자가 들어가게 되는데 이는 저장공간에 낭비가 발생할 뿐만 아니라 값비교를 위해서 trim등의 스트링 연산이 추가되어야 한다. 대용량 데이터를 처리해야하는 경우 이에 대한 비용도 무시할 수 없다. 운영시 용이성과 개발시 용이성을 볼 때 VARCHAR로 통일하는 것을 추천한다.

INDEX 재설계

INDEX는 데이터 Access를 빠르게 할 수 있으나, 데이터 추가/삭제/수정이 빈번하게 발생할 경우 속도저하를 발생시킨다. 온라인에서 사용하는 테이블과 최대한 겹치지 않도록 배치 테이블을 설계하는 것이 바람직하며 부득이하게 같은 테이블을 사용할 경우 적절하게 INDEX를 제어하도록 한다. (테이블당 3~4개 권고) 또한 SELECT를 사용할때 테이블 대부분의 자료를 읽어야 하는 경우에는 Full Scan하는 것이 더 빠를 수 있다. 그리고 배치작업에서 대용량 데이터를 적재할 경우에는 DROP INDEX를 하고 데이터 적재를 마친 뒤 INDEX재생성을 하는 것이 일반적으로 속도에 이점이 있다.

파티션 테이블 활용

데이터 저장공간에 파티션 개념을 도입하여, 테이블의 특정컬럼을 기준으로 하여 분리된 파티션에 데이터를 저장할 수 있도록 하는것이다. 데이터 로드, INDEX생성, 백업 및 복구등을 파티션 레벨에서 수행할 수 있으며 수행시간을 단축시킬 수 있다.특히 주기단위로 대용량 데이터를 관리하는데 매우 유용하며 쿼리를 파티션 테이블에서 수행할 경우 분할된 파티션들 중 일부에만 접근하기 때문에 성능이 향상된다. 병렬 프로그래밍과 같이 사용할 경우 효과를 극대화할 수 있다.

비지니스 로직 구성

비지니스 로직구성이 배치 어플리케이션의 핵심이다. 전체적으로 업무 프로세스를 재설계하는지가 관건이다.

업무 프로세스 재설계

기존 업무의 분석과 재설계를 통해 비지니스 로직자체를 단순화 한다. 유사한 업무를 통합하고, 불필요한 반복작업을 제거해야 한다. DBMS의 신규기능(ex, sum, over)을 활용할 수 있으며, 어플리케이션을 효율적으로 작성해야 한다. 반복문내의 불필요한 연산을 제거하고 I/O를 최소화해야 한다.

Application 효율화

loop 문내 불필요 로직 최소화

  • Loop내에서 DB건당 Read는 최소화 하는 것이 좋다. JOIN쿼리를 활용하여 처음에 다수의 필요한 테이블 자료를 조회하면 DB Read횟수를 줄일 수 있다. 
  • 변경 전
    • while(DB.ReadA()){ 비지니스로직처리 DB.ReadB(); } 
    • DB.READ.A=> SELECT * FROM A
    • DB.READ.B=> SELECT * FROM B WHERE NAME=?
  • 변경 후
    • while(DB.ReadC()){ 비지니스로직처리 } 
    • DB.READ.C=> SELECT * FROM A,B WHERE A.NAME=B.NAME
  • Loop내에서 DB건당 Write는 최소화 하는 것이 좋다. 로직처리 후 데이터를 모아서 처리하는 것을 권장한다. 또한 Java의 경우 JDBC addBatch기능을 활용하면 2~10배정도 속도향상이 있다. 
  • 변경 전
    • void a(){ 비지니스 로직 } void b(){ DBWrite();} 
    • while(DBRead()){ a(); b(); } 
  • 변경 후
    • while(DBRead()){ a(); }
    • while(DBRead(a의결과){ b(); }
  • 불필요한 객체생성이나 연산을 제거한다. 대표적으로 String연산을 loop내에서 반복할 경우 메모리 사용량 및 처리속도에 악영향을 줄 수 있다. MultiThread일 경우 StringBuffer를, SingleThread일 경우 StringBuilder를 사용하는 것이 일반적이다. 그 외에도 loop내에서 객체하나로 값만 바꿔서 사용할 수 있는 경우는 new를 loop문 밖으로 빼는 것이 필수이다.

단순 코드성 정보 Memory 활용

자주 참조되는 데이터(ex, 코드성 데이터, 영업일등)는 Memory이 Loading후 로직에서 활용하면 매번 DB Read를 하는 것보다 속도향상의 효과가 있다. 단, Loading되는 데이터의 사이즈를 감안해야 한다.

병렬처리를 감안한 파라미터 설계

  • Multi Process
  • Multi Thread

 

'Software Architecture' 카테고리의 다른 글

Go Reactive Systems  (0) 2015.03.25
scale out 이 가능한 architecture? micro service?  (0) 2015.03.25
빅데이터 분석에서 배치활용  (0) 2014.10.21
Batch Architecture 고려사항  (0) 2014.03.31
Enterprise Batch  (0) 2014.03.31

Batch Architecture 고려사항

아래 언급되는 내용들은 배치뿐 아니라 일반적인 Enterprise Application Architecture에서 공통적으로 해당되는 내용이다.

Language

 최근 금융권 시스템에도 Java가 많이 도입되면서 배치에서도 Java를 사용하는 경우가 늘어나고 있다. 하지만 Java의 경우 가상머신(VM)을 통해서 수행되기 때문에 C나 COBOL에 비해서 속도에 약점을 보일 수 있어서 배치에는 적합하지 않다는 인식도 많이 있다.

 실제로 프로젝트에서 가장 많이 나오는 불만이 "로직 변경없이 똑같이 작성하면 기존보다 느리다"는 것이다. 하지만 장점도 있다. 일반적으로 온라인과 동일한 Language를 사용하기 때문에 아키텍처 통일성이 확보되고 프로그램 재사용이 가능하다. 또한 다양한 Opensource의 활용이 용이하고 멀티쓰레드 처리에 쉽게 접근할 수 있다.

따라서 다양한 관점의 분석과 이해당사자들의 협의를 통하여 Language선택이 이루어져야 한다. 실제로 프로젝트를 수행할 때 성능 최적화에 가장 큰 요소는 Language가 아니라 업무에 관련된 부분이다.

불필요한 작업단계를 제거하거나 통합하고, CriticalPath작업의 위치를 조정하고 작업간 선/후행관계를 재조정하는 등 업무의 최적화에서 더 큰 효과를 볼 수 있다.

Resource Management

현재 시스템에서 수행되어야 할 작업의 상세한 내용을 5w1h원칙으로 정확하게 파악해야 한다.

  • who : 작업명은 무엇인가? 작업의 주체는 누구인가?
  • when : 언제 수행되는가? 일단위인가? 월단위인가?
  • what : 무엇을 수행하는 작업인가? File처리인가? 그렇다면 어느파일에 접근하는가? DB처리인가? 그렇다면 어느 테이블에 접근하는가?
  • why : 작업의 목적은 무엇인가? 어떤한 작업의 선행인가? 후행인가?
  • where : 어느서버에서 수행되는가? 어느계정으로 수행되는가?
  • how : 스케쥴링에 의해서 수행되는가? 원격호출로 수행되는가?

    또한 배치 시스템의 특성상 많은 데이터가 생성되고 참조되는데 이에 대한 관리도 필요하다. 예를 들면 다음과 같다.

  • 파일명명규칙 : 생성되는 파일에 대해서 명명규칙이 필요하다. 업무구분/보관주기/생성모듈등 정보관리가 필요하다. 특히 장기간 불필요파일들이 남아있을 경우 저장공간 부족을 야기시킬수 있기때문에 보관주기에 따라 주기적으로 정리하는 것이 좋다.
  • 테이블레이아웃 : 배치에서 LOAD/UNLOAD작업을 하기 위한 테이블 정보도 관리 되어야 한다.
  • FTP목록 : 작업결과를 FTP로 전송할 경우가 있다. 이 때 사용되는 서버/계정정보/권한 등도 관리 되어야 한다.

    이외에도 실제로 현장에서는 정보 관리주체가 각각 다르다 보니 한눈에 영향도를 파악하기 어려운 경우가 많이 있다.

Capacity

 총 작업의 개수, 각 작업이 소모하는 자원, 작업의 처리대상/주기, Peak Time등을 알고 있어야 한다. 예를 들어서 평상시에는 정상적으로 동작하던 작업이 특정요일만 되면 지연현상이 발생하는 경우가 있다. 상황을 분석해보니 특정요일 같은시간대에 수행되는 다른작업이 같은 처리대상에 접근하고 있어서 Table Lock발생하는 경우였다. 또 월초/월말에 처리해야하는 데이터의 양이 큰 폭으로 증가하여 작업시간이 지연되거나 시스템에 부하를 발생하는 경우도 있을 수 있다. RuleEngine을 사용하는 배치작업의 경우 메모리를 많이 소모하여 동시에 다수의 작업이 수행될 경우 자원부족현상이 발생할 수도 있다.

 이러한 상황을 예방하기 위해서 작업Dependency Diagram작성, 배치작업관리 메타시스템 구축등을 통해서 작업 패턴을 사전에 분석하는 등의 노력이 필요하다.

Deployment & FailOver

 시스템 장애가 발생하여 부득이하게 다른 서버를 사용할 경우를 대비하여 사전에 준비가 되어 있어야 한다. 예를 들어서 배치프로그램은 물론이고 배치프로그램들이 생성하는 File들도 동일한 버전으로 배포가 되어 있어야 하며 스케쥴러와 같은 기타 솔루션들도 유지가 되어야 한다. 또한 설정정보들 역시 신속하게 변경/적용할 수 있어야 한다. 최근에는 파일공유 솔루션이나 NAS를 통해서 어플리케이션 및 파일을 공유하여 사용하고 있다.

개발표준

 전체 개발표준 뿐만 아니라 대표적인 케이스를 선정하여 유형별 Sample코드를 제공하는 것도 하나의 방법이 될 수 있다. 배치의 경우 예를 들면 입력되는 데이터에 따라서 후행배치를 분기시키는 데몬배치도 있고 Resource를 읽어서 처리하는 비지니스 배치도 있다. 비지니스 배치도 처리하는 Resource유형에 따라서 File to File, DB to File등이 존재할텐데 이에 따른 처리패턴을 확보하여 Sample코드로 제공하면 개발뿐 아니라 성능테스트에도 많은 도움이 된다.

 

+ Recent posts