2016.02.17 13:15

소프트웨어 역사의 주요 인물


소프트웨어 발전에 기여하신 분들을 출생 연도 순으로 정리했습니다. 기술 혁신, 알고리즘 개발 등 학문 및 공학 발전에 이바지 한 분들로 한정한 것입니다.

 

한글 이름 영문 이름 출생 연도
찰스 베비지 Charles Babbage 1791

에이다 러브레이스

Augusta Ada King 1815
조지 George Boole 1815
폰 노이만 John von Neumann 1903
알론조 처치 Alonzo Church 1903

그레이스 호퍼

Grace Murray Hopper 1906
모클리 John William Mauchly 1907
엘런 튜링 Alan Mathison Turing 1912
J 에커트 J Presper Echert 1919
에드가 코드 Edgar Frank "Ted" Codd 1923
더글러스 엥겔바트 Douglas C. Engelbart 1925
메카시 John McCarthy 1927
마빈 민스키 Marvin Minsky 1927
에츠허르 데이크스트라 Edsger Wybe Dijkstra 1930
찰스 앤터니 리처드 호어 Sir Charles Antony Richard Hoare 1934
니클라우스 비르트 Niklaus Wirth 1934
도널드 커누스 Donald Ervin Knuth 1938
엘런 케이 Alan Curtis Kay 1940
데니스 리치 Dennis MacAlistair Ritchie 1941
브라이언 커니핸 Brian Wilson Kernighan 1942
게리 킬달 Gary Arlen Kildall 1942
톰프슨 Kenneth Lane Thompson 1943
찰스 시모니 Charles Simonyi 1948
비야네_스트롭스트룹 Bjarne Stroustrup 1950
리처드 스톨먼 Richard Matthew Stallman 1953
조이 William Nelson Joy 1954
팀 버너스 리 Sir Timothy John "Tim" Berners-Lee 1955
제임스 고슬링 James Arthur Gosling 1955
조슈아 블로흐 Joshua Bloch 1961
마틴 파울러 Martin Fowler 1963
리누스 토르발스 Linus Benedict Torvalds 1969
로버트 마틴 Robert Cecil Martin



[인물 소개 및 업적]


찰스 베비지


영국의 수학자이자 철학자, 발명가, 기계공학자로서 "프로그램이 가능한 컴퓨터" 개념을 창안했다. 배비지는 기계식 컴퓨터를 최초로 개발한 인물로 평가 받고 있으며, 그의 연구 이후 더욱 복잡한 형태의 컴퓨터들이 등장하게 된다. 배비지는 인간의 수작업에 이한 계산으로 인해 자주 오차가 발생하는 것을 확인하고, 이를 개선하기 위해 기계를 이용한 계산 방법을 고안하려 애썼다. 그의 기계적 컴퓨터는 데이터와 메모리를 분리하고, 명령을 입력할 수 있으며, 입/출력 장치를 분리하는 등 현대적 컴퓨터에 사용되는 기법을 포함하고 있었다.


이다 러브레이스


영국 시인 조지 고든 바이런의 유일한 법적 친자이며, 세계 최초의 프로그래머로 알려져 있다. 에이다는 찰스 배비지의 연구에 대한 좋은 이해자이자 협력자였고, 배비지가 고안한 해석기관을 위한 공동작업을 수행한 것으로 널리 알려져 있다. 배비지의 해석기관에서 처리될 목적으로 작성된 알고리즘이 최초의 컴퓨터 프로그램으로 인정되고 있으며, 해석기관을 단순한 계산기 정도로 생각했던 당대의 과학자들과 달리 훨씬 다양한 목적으로 활용될 가능성에 주목해 현대 컴퓨터의 출현을 예측했다. 프로그래밍 언어에 사용되는 중요한 개념인 루프, GOTO 문, IF 문과 같은 제어문의 개념을 소개했다. 또한 서브루린(subroutine)에 대한 개념을 고안하였다.


조지 불


영국의 수학자, 논리학자이다. 논리 대수인 불 대수(Boolean Algebra)를 창안해, 기호논리학 분야에 큰 업적을 남겼다. 부울 대수는 현대 컴퓨터의 논리 연산 기능의 기본 원리이다.


폰 노이만


현대적 컴퓨터의 구조를 설계한 사람이다. 지금까지 거의 모든 컴퓨터는 폰 노이만이 정립한 아키텍쳐를 따르고 있기 때문에 "폰 노이만 머신"이라고도 부른다. 프로그램 내장 방식, 이진법을 컴퓨터에 도입했으며, 순서도와 서브루티, 몬테카를로법을 최초로 사용했다. 1945년 병합 정렬(merge sort)를 만들었고, 간단한 원칙만으로 스스로 진화하는 복잡한 프로그램을 구상했고 이를 오토마톤이라고 명명했다. 유명한 일화는 제자들이 어셈블리어를 만들 당시에 노발대발 했다는데, 그 이유가 '완벽한 신의 언어가 있는데, 그걸 놔두고 저런 조잡한걸 만들려고 하느냐?'였다.


알론조 처치


알론조 처치는 미국의 수학자이자, 논리학자이다. 전산학의 이론적인 기초를 세운 사람 중의 한 명이다. 1936년 람다 대수에 대한 논문을 썼고, 람다 셈법에 대한 처치의 연구는 리스프(LISP) 계열의 프로그래밍 언어 뿐만 아니라, 일반적인 함수형 언어 전반에 큰 영향을 끼쳤다.


그레이스 호퍼


미국의 프로그래머, 수학 교수이자 해군 제독으로 제대한 여성 군인.1906년 뉴욕에서 태어나 후일 바서대학에서 부교수로 수학을 강의했다. 2차대전 발발 직후, 1943년 미 해군에 입대했고 수학적 재능을 이용해 탄도를 계산하는 일과 최초의 컴퓨터 중 하나인 마크Ⅰ의 프로그램을 개발하는 일을 수행하며, 전쟁 이후에는 최초의 상업용 컴퓨터인 유니박(UNIVAC) 개발팀과 함께 프로그램을 개발하고 최초의 컴파일러를 개발하는데 참여했다. 그 후 해군에 복귀해 코볼(COBOL) 언어와 컴파일러 개발에 참여했고 후일 해군 제독으로 전역했다. 또한, 그는 컴퓨터에서 버그라는 단어를 최초로 사용한 것으로 유명하다. 1946년 하버드대학의 컴퓨터 마크Ⅱ를 사용하던 중 컴퓨터에 고장이 발생했는데 컴퓨터에 나방이 붙어 장애를 일으킨 것을 확인하고, 일지에 고장을 일으킨 벌레를 테이프로 붙인 후, 컴퓨터 버그란 이름을 붙였다


존 모클리


J 프레스퍼 에커트와 함께 최초의 전자 컴퓨터인 애니악을 만든 미국의 물리학자이다. 1943년 미국 전쟁성(지금의 국방부)은 펜실베니아 대학교의 공학 교수였던 모클리를 ENIAC 개발을 위한 프로젝트 총괄 책임자로 임명했다. J. 프레스퍼 에커트와 함께 ENIAC을 제작하였으며 이후 EDVAC, UNIAC 등의 컴퓨터를 설계했다.


엘런 튜링


영국의 수학자, 암호학자, 논리학자이자 컴퓨터 과학의 선구적 인물이다. 이론 컴퓨터 과학과 인공지능 분야에 지대한 공헌을 했기 때문에 "컴퓨터 과학의 아버지"라고 불린다. 튜링 기계는 튜링이 알고리즘을 설명하기 위해 도입한 가상의 기계이다. 이 기계는 한정된 종류의 기호 중 하나를 기록할 수 있는 칸들이 무한히 이어진 띠와 각 칸의 정보를 읽고 수정하는 기계로 이루어져 있다. 그리고 튜링 머신의 상태와 칸에 기록된 기호에 따라 지정된 절차를 수행한다. 튜링 머신이 수행하는 절차는 1. 현재 기계가 위치하는 칸의 기호를 수정 2. 띠의 위치 이동 3. 튜링 머신의 상태 변경 이 있다. 현대적 소프트웨어는 그 기본 원리가 튜링 머신에 기초한다.


J 에커트


존 모클리의 제자로서 ENIAC을 설계 및 개발하는 프로젝트에서 수석 엔지니어로 참여했다.


에드가 코드


관계형 데이터 베이스 이론의 창안자. 미국 미시간대학교에서 컴퓨터과학 박사 학위를 받은 후, IBM 에서 근무하다 "A Relational Model of Data for Large Shared Data Banks"라는 논문을 썼다. 코드의 관계형 모멜에 대한 논문에 크게 감명 받은 래리 앨리슨(Larry Ellison)은 지금의 오라클(ORACLE)로 이름을 바꾼 회사를 설립했다.


더글러스 엥겔바트


더글러스 엥겔바트(Douglas C. Engelbart, 1925년 1월 30일 ~ 2013년 7월 2일, 오리건 주 출생)는 노르웨이/스웨덴계 미국인 발명가이다. 그는 특히 컴퓨터 마우스의 발명자로 유명하다. 또한 그래픽 사용자 인터페이스, 하이퍼텍스트, 네트워크 컴퓨터 등 인간과 컴퓨터 상호 작용 분야의 선구자이다.


존 메카시


존 매카시(John McCarthy, 1927년 9월 4일 - 2011년 10월 24일)는 미국의 전산학자이자 인지과학자이다. 인공지능에 대한 연구 업적을 인정받아 1971년 튜링상을 수상했다. 리스프 프로그래밍 언어를 발명했으며, 1956년에 다트머스 학회에서 처음으로 '인공지능'(Artificial Intelligence)이라는 용어를 창안했다.


마빈 민스키


마빈 리 민스키(Marvin Lee Minsky, 1927년 8월 9일 ~ 2016년 1월 24일)은 인공지능(AI) 분야를 개척한 미국인 과학자이다. MIT의 인공지능 연구소의 공동 설립자이며, AI와 관련된 몇 개의 책의 저자이기도 하다.


에츠허르 데이크스트라


데이크스트라는 전산학이 아직 학문으로 완전하게 정립되지 않았던 시절에 전산학의 여러 분야에 걸쳐 많은 공헌을 했다. 그의 다방면에 걸친 업적은 다음과 같다. 데이크스트라 알고리즘을 개발하여 최단경로 알고리즘에 대한 학문적 연구를 시작했다. GOTO문을 사용하지 말 것을 주장했으며, 그의 주장은 1968년에 그의 논문 "GOTO문의 해로움"(Go To Statement Considered Harmful)에 정리되었다. 세마포어에 대한 연구를 처음으로 시작하였다.


찰스 앤터니 리처드 호어


찰스 앤터니 리처드 호어 경, Kt (Sir Charles Antony Richard Hoare, 1934년 1월 11일 ~ )은 영국의 컴퓨터 과학자이다. 애칭 토니 호어(Tony Hoare)로도 불린다. 가장 널리 쓰이는 정렬 알고리즘의 하나인 퀵 정렬을 고안해낸 것으로 유명하다. 그는 호어 이론, 형식 언어의 한 종류로 병행 프로세스간 통신을 기술하는데 이용되는 커뮤니케이팅 시퀀셜 프로세스(CSP)의 개발, 프로그래밍 언어인 Occam에도 영향을 끼친 것으로 알려져 있다.


니클라우스 비르트


스위스의 컴퓨터 과학자이며, 파스칼을 포함한 다양한 프로그래밍 언어를 설계한 것으로 가장 유명하다. 


도널드 커누스


커누스는 컴퓨터 과학 분야에서 가장 권위있는 책인 《The Art of Computer Programming》의 저자로 가장 널리 알려져 있다. 알고리즘 분석 분야를 실질적으로 창조했으며, 이론 컴퓨터 과학의 여러 분야에서 기초적인 중요한 공헌을 했다. TEX 조판 시스템과 메타폰트 폰트 디자인 시스템을 만들었으며 문학적 프로그래밍 (literate programming)의 개념을 처음으로 주장했다.


엘런 케이


앨런 커티스 케이는 미국의 전산학자이다. 객체 지향 프로그래밍과 사용자 인터페이스 디자인 분야의 선구자로 잘 알려져 있다. 


데니스 리치


켄 톰슨(Ken Thompson) 등과 함께 최초의 유닉스(Unix) 시스템을 개발했고, 1971년 최초의 〈Unix Programmer's Manual〉을 썼다. 또한 C 언어를 개발한 후 브라이언 커니핸과 함께 〈C 프로그래밍 언어〉(The C Programming Language)를 기술했다. 커니핸과 〈C 프로그래밍 언어〉책을 썼기에 커니핸이 C 언어 개발에 참여한 것으로 종종 오해받으나 커니핸의 말에 따르면 자신은 C언어 개발에 참여하지 않았다고 한다. 그는 ALTRAN, B언어, BCPL, Multics 등의 개발에도 영향을 끼친 것으로도 알려져 있다.


브라이언 커니핸


C를 만든 데니스 리치와 함께 최초의 C언어 해설서인 〈C 언어 프로그래밍〉를 써서 널리 알려져 있다. 커니핸은 자신은 C 언어의 탄생에 전혀 기여하지 않았다고 밝혔다. 그는 dirtroff를 비롯한 수많은 유닉스 프로그램을 작성했다. 선 린과 함께 그래프 분할과 외판원 문제를 푸는 유명한 휴리스틱을 개발하였다. 전자는 커니핸-린 알고리즘 (줄여서 KL), 후자는 린-커니핸 알고리즘 (줄여서 LK)이라고 부른다.


게리 킬달


게리 알렌 킬달은 운영 체제 CP/M과 GEM의 개발자이며, 디지털 리서치(Digital Research)의 설립자이다. 윈도와 메뉴로 동작하는 사용자 인터페이스를 갖춘 선점형 멀티태스킹 운영 체제를 도입했다. 최초의 디스크 트랙 버퍼링 체계, 미리 읽기 알고리즘, 파일 디렉터리 캐시와 램 디스크 에뮬레이터의 창조, 1980년대에 바이너리 재컴파일러의 도입, 최초로 마이크로프로세서에 특화된 프로그래밍 언어와 컴파일러 제작 등의 업적을 이루었다.


켄 톰프슨


케니스 레인 톰프슨은 미국의 컴퓨터 프로그래머로, AT&T 벨 연구소에서 유닉스와 플랜 9 운영 체제의 개발을 주도했다. C언어의 모체가 된 B언어를 개발하기도 했다. 2006년부터 구글에서 근무하면서 고 언어의 개발에 참여했다. 그밖에 정규표현식, QED 편집기, UTF-8 인코딩 등의 개발에도 기여했고, 체스 기계 벨의 개발에도 동참했다. 1983년에 유닉스 개발과 관련된 공로로 데니스 리치와 함께 튜링상을 수상했다.


찰스 시모니


헝가리 태생의 미국 소프트웨어 개발자, MS에서 근무하면서 MS Word 와 Excel을 개발했다. "헝가리안 명명법"이라 불리는 코딩 스타일을 창안했다.


비야네_스트롭스트룹


리처드 스톨먼


빌 조이


팀 버너스 리


제임스 고슬링


조슈아 블로흐


마틴 파울러


리누스 토르발스


로버트 마틴



켄트 벡,  조엘 스폴스키, 제프 맷우드, 앤디 루빈, 롭 파이크, 마츠모토 유키히로, 귀도 반 로섬, Robert Donner, Curt Johnson (mine sweeper), Robert sedgewick, GoF, three amigos, 허먼 훌러리스, 레이 오지, 와츠 험프리, 마크 안드레센, 마가렛 해밀턴, 앤더스 해즐스버그, John Vincent Atanasoff, 제프리 리처

Posted by 善 곽중선
2014.11.25 14:16

NoORM의 디자인과 컨셉은 오라클의 의존하지 않지만, 스토어드 프로시져(stored procedue)  사용하는데 있어서는 데이터베이스 세계의 공통 표준이 부족하기 때문에 오라클에 종속될 수 밖에 없습니다. NoORM 은 오라클 데이터베이스 10gR2 혹은 상위 비전을 지원하며, 오라클 익스프레스 에디션을 포함한 모든 에디션을 지원합니다.


Though design and concept of NoORM do not depend on Oracle, the usage of stored procedures, which still lack a common standard in the database world, currently requires the usage of Oracle. NoORM supports Oracle database 10gR2 or higher. All editions are supported, including Oracle Express Edition.


NoORM은 Java 6 혹은 상위 버전을 필요로 합니다.


NoORM requires Java 6 or higher.


NoORM은 두개의 파트로 구성되어 있습니다. 코드 생성기(code generator)와 런타임 라이브러리(runtime library)입니다.  코드 생성기는 어플리케이션 개발 단계에서 필요하며, 런타임 라이브러리는 개발 및 어플리케이션 실행 과정에서 모두 필요합니다. NoORM 코드 생성기 없이 어플리케이션을 개발할 수 있지만 권장하지는 않습니다. 개발 생산성 향상은 코드 생성기 활용으로 인해 야기됩니다.


NoORM comes with two parts: the code generators and the runtime library. The code generators are required for application development, the runtime library is required for both, development and your applications runtime. Though you can develop applications without the NoORM code generators, this approach is not recommended. The improvement of development productivity is primarily caused by the usage of the code generators.


코드 생성기는 아파치 벨로시티(Apache Velocity)를 사용합니다. 코드 생성기는 다양한 옵션을 제공합니다. 고유한 환경 설정 메커니즘으로 인해 코드 생성기의 강점을 가려지지 않게끔, 코드 생성기는 환경설정을 위한 커스텀 XML 스키마를 포함한 메이븐(Maven) 플러그인 형태로 만들어져 있습니다. Maven 3 사용을 권장하지만, Maven 2 역시 지원합니다.


The code generators use Apache Velocity. Various configuration options are available for the code generators. To exploit the power of the code generators without the need for a new proprietary configuration mechanism, the code generators are wrapped into a Maven plugin using a custom XML schema for the configuration. We recommend the usage of Maven 3, though Maven 2 is also supported.


NoORM을 사용하기 위해서는 이어지는 자바 라이브러리들이 필요합니다. (코드 생성기 포함) Oracle JDBC 는 법적인 이유로 공개 메이븐 저장소에서 제공하지 않기 때문에 제공되지 않지만 나머지 의존성은 메이븐에 의해 자동으로 검색(resolve)됩니다.


The following Java libraries are required to use NoORM (including the code generators). Except for the Oracle JDBC driver, which is not provided by a public Maven repository for legal reasons, all other dependencies can be resolved automatically using Maven:


Oracle JDBC Driver (NoORM has been tested with all available Versions of the Oracle 10.2g, 11g and 12c series, note that for Oracle 12c you may have to add Oracle XML libraries to your classpath)

Velocity 1.7

SLF4J API 1.7.5

Logback Classic 1.0.13 (or any other logging library with support for SLF4J like log4j)


NoORM은 두개의 내장 PL/SQL 패키지를 포함합니다. NOORM_METADATA 패키지는 자바 코드 생성기를 위해 필요하며, 자동 클래스 검증(Automatic Class Validation) 기능을 런타임 시에 사용하고자 한다면 런타임 환경에서도 필요합니다. DYNAMIC_SQL 패키지는 런타임 시에 동적인 SQL 생성을 지원하기 위해 제공됩니다. 패키지들과 패키지에 필요한 부가적인 데이터베이스 요소들이 운영 중인 오라클 데이터베이스 스키마에 설치되어야 합니다. Maven SQL 플러그인을 사용하면 NoORM 데이터베이스 요소들과 어플리케이션 고유의 데이터베이스 객체에 대한 생성과 운영을 메이븐 빌드에 통합할 수 있기에 추천합니다. SQL 빌드 통합 섹션을 참조하면 좀 더 자세한 정보를 얻을 수 있습니다.


NoORM comes with two internal PL/SQL packages: package NOORM_METADATA is required by the Java code generator and, if you make use of the Automatic Class Validation feature, it is required at runtime, too. Package DYNAMIC_SQL provides support for Dynamic SQL generation at runtime. The packages and additional database objects required by these packages must be installed into your working Oracle database schema. It is recommended to use the Maven SQL Plugin to integrate the creation and maintenance of NoORM database objects and your own database objects with your Maven build. Refer to section SQL Build Integration for more information.

 

NoORM PL/SQL 패키지와 관련된 데이터베이스 요소들을 생성하는 필요한 SQL 스크립트들은 NoORM 런타임 라이브러리에 포함되어 있습니다. (JAR 파일 내의 /plsql 폴더)

 

The SQL scripts required to install the NoORM PL/SQL packages and associated database objects are bundled with the NoORM runtime library (under /plsql in the JAR-file)


샘플 스키마 

Sample Schema


이어지는 퀵스타트(quick start) 튜터리얼은 잘 알려진 오라클 샘플 스키마인 HR (인사 정보 : Human Resources)에 기초한 것입니다. 일부 오라클 에디션들은 사전 설치된 데이터베이스에 이 스키마를 포함하고 있습니다. (예를 들면, 오라클 익스프레스 에디션)  만일, 데이터베이스 설치에 HR 스키마가 포함되어 있지 않다면, 오라클 샘플 스키마 온라인 문서를 참조하기 바랍니다. 해당 도큐먼트에는 스키마 다이어그램과 샘플 스키마들에 대한 설명이 포함되어 있습니다.


The following quick-start tutorial is based on the well-known Oracle sample schema HR ("human resources"). Some Oracle editions contain this schema in the pre-installed database (e.g. Oracle Express Edition). If schema HR is not available with your database installation, refer to the Oracle Sample Schemas Online Documentation for more information about the sample schemas. The referred document also contains schema diagrams and explanations about the meaning of the sample schemas (Note that you may have to unlock the account prior to accessing it).


설정되어 있는 코드 생성기


Configuring the Code Generator


제대로 설정된 코드 생성기가 준비되어 있다면, 작업할 준비가 거의 된 것입니다. 그러나, 코드 생성기 설정을 시작하기에 앞서, 데이터베이스 객체들과 그에 상응하는 코드 생성에 관련된 자바 클래스들에 대해 빠르게 살펴 볼 필요가 있습니다.


With properly configured code generators, you are already close to code ready for operation. But before we start with the configuration of the code generators, we should have a quick look at the database objects and their corresponding Java class types, which are subject to code generation:


자바 빈(java bean)은 데이터베이스 테이블 혹은 뷰(view)를 표현합니다 : 데이터베이스 데이터를 자바 어플리케이션에서 사용하기 위해서는 데이터베이스 테이블 및 뷰에 포함된 데이터를 표현하는 클래스 명세가 필요합니다. NoORM은 테이블이나 뷰를 표현하는 자바 빈들을 생성합니다.


Java Beans representing database tables or views: To utilize database data in your Java application, we need a class specification to represent the data contained in database tables or views. NoORM generates Java Beans for tables or views of your choice for this purpose.


자바 열거형(Enums) 은 컨텐츠를 포함하는 데이터베이스 테이블들을 표현합니다 : 일부 테이블들은 어플리케이션 라이플 사이클의 단일 사이클에서 변하지 않는 데이터를 가지고 있습니다. 예를 들자면, 사전 부류의 컨텐츠(성별, 주문 유형, 상품 유형 등)를 포함한 테이블을 가지고 제3의 양식을 채우는 업무를 구현하는 것일 수도 있습니다.  이런 데이터 유형은 일반적으로 어플리케이션의 기능에 가깝고, 어플리케이션 기능이 수정될 때 값이 변경됩니다. 따라서, 테이블 컨텐츠를 자바 Enum 타입을 이용해 자바 어플리케이션 코드에 고정(hard-wiring)하는 것이 가능합니다. 보다 자세한 정보는 자바 Enums 생성 섹션을 참고하기 바랍니다.


Java Enums representing database tables including content: Some tables may contain data which does not change within one cycle of your application life-cycle (e.g. release). For instance, you may have a table with some dictionary-like content to fulfil requirements to the third normal form in your database model like gender, order types, product types, etc. Data of this kind is typically closely tied to the functionality of your application and does only change when your application is modified. Thus it is possible to hard-wire the tables content into your application using a Java Enum. Refer to section Generating Java Enums for more information.


PL/SQL 코드를 감싼 자바 서비스 혹은 DAO(Data Access Object) : NoORM는 PL/SQL 프로시져에 내장된 SQL 쿼리들을 지원합니다. 오라클 REF CURSOR 타입을 이용해 저장 프로시져에서 JDBC ResultSet을 반환하는 것도 가능합니다. 자바 코드 생성기는 PL/SQL 패키지들을 분석하고 상응하는 API 자바 클래스를 생성합니다. 또한 SQL 쿼리에서 참조하는 테이블들에 상응하는 자바 빈들도 생성합니다.


Java Services or Data Access Objects wrapping PL/SQL code: NoORM supports SQL queries embedded into a PL/SQL procedure, resp. PL/SQL package. By utilizing the Oracle type REF CURSOR it is possible to return a JDBC ResultSet from a stored procedure. The Java code generator analyzes your PL/SQL packages and creates a corresponding Java class providing the API of the package under consideration of the Java Beans generated for the entities addressed in the SQL queries. Whether you denote the generated Java classes as service or as DAO (Data Access Object) depends on the semantically richness of the PL/SQL and is up to your development team. Refer to section PL/SQL is easy for more information.


단순하고 전형적인 쿼리 : 대다수의 SQL 문들은 단순한 형태를 띄게 마련입니다. FROM 절에 하나의 테이블을 사용하고, WHERE 조건에 AND로 연결된 조건들을 선언하는 것입니다. 이러한 SQL 문을 위해 PL/SQL 패키지를 선언하는 것은 부담이 될 수 있습니다. NoORM 은 단순한 쿼리를 설정할 수 있는 옵션을 제공함으로써 간편한 개발 절차를 제공합니다.


Declared Queries for canonical trivial SQL statements: Most SQL statements are rather trivial, using a single entity in the FROM-clause and using WHERE-conditions combined by an AND. For these statements even the implementation of PL/SQL packages can be a burden. NoORM provides configuration options to declare simple queries, which simplifies the development process significantly.



The very first step for the Maven configuration is the plugin configuration. The NoORM generator plugin requires the database connection parameters as mandatory parameters. All application specific parameters are specified in a separate XML file (One can specify a location for the NoORM configuration file, the default location is src/noorm/configuration.xml).

 

We start with a code generator configuration for Java Beans only in the first step. Only a few configuration parameters are mandatory, so the NoORM Maven plugin configuration is pretty straight-forward:

 

Minimal but complete Maven pom.xml with a NoORM code generator configuration:

<?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>noorm-tutorial</groupId>

    <artifactId>noorm-tutorial</artifactId>

    <version>1.0</version>


    <properties>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    </properties>


    <build>

        <plugins>

            <plugin>

                <groupId>org.noorm</groupId>

                <artifactId>noorm-generator</artifactId>

                <version>1.0.0</version>

                <dependencies>

                    <dependency>

                        <groupId>com.oracle</groupId>

                        <artifactId>ojdbc6</artifactId>

                        <version>11.2.0.4.0</version>

                    </dependency>

                    <dependency>

                        <groupId>ch.qos.logback</groupId>

                        <artifactId>logback-classic</artifactId>

                        <version>1.0.13</version>

                    </dependency>

                </dependencies>

                <executions>

                    <execution>

                        <goals>

                            <goal>generate-noorm</goal>

                        </goals>

                    </execution>

                </executions>

                <configuration>

                    <url>jdbc:oracle:thin:@localhost:1521:XE</url>

                    <username>hr</username>

                    <password>hr</password>

                </configuration>

            </plugin>

        </plugins>

    </build>


    <dependencies>

        <dependency>

            <groupId>ch.qos.logback</groupId>

            <artifactId>logback-classic</artifactId>

            <version>1.0.13</version>

        </dependency>

        <dependency>

            <groupId>org.noorm</groupId>

            <artifactId>noorm-runtime</artifactId>

            <version>1.0.0</version>

        </dependency>

    </dependencies>


</project>


Let's go step by step through this configuration.


The first part of a Maven plugin configuration is always about the plugin itself. The groupId and the artifactId specify the NoORM Java code generator. The dependency for the Oracle JDBC driver requires that the drivers library is available for your local Maven installation (for more information see section Local Maven Repository).

 

The NoORM Java code generator has only the execution goal generate-noorm, so this part will stay the same for any configuration.

 

The values for url, username and password in the configuration section are self-explanatory and already provide a working setting, when you have installed Oracle Express Edition.

We will start with a minimal generator configuration containing not more than the package names for the generated beans and services:

 

Minimal NoORM code generator configuration file (configuration.xml)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<generatorConfiguration xmlns="http://www.noorm.org/generator-configuration/1.0.0"

                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                        xsi:schemaLocation="http://www.noorm.org/generator-configuration/1.0.0

                                            http://www.noorm.org/xsd/generator-configuration-1.0.0.xsd">


    <beanJavaPackage name="org.noorm.tutorial.hr.beans"/>

    <serviceJavaPackage name="org.noorm.tutorial.hr.services"/>


</generatorConfiguration>


 

For a first minimal project this is indeed enough! You may use your favourite IDE or you may setup a Maven project manually to build this project. The NoORM code generator creates a Java Bean for each table or view in the addressed database schema. For the Oracle sample schema HR, this results in the following classes (assuming you have used the package names as described in the listed configuration.xml):

 

Java Bean Class generated by the NoORM Java code generator

org.noorm.tutorial.hr.beans.Countries

org.noorm.tutorial.hr.beans.Departments

org.noorm.tutorial.hr.beans.EmpDetailsView

org.noorm.tutorial.hr.beans.Employees

org.noorm.tutorial.hr.beans.GenericBeanValidator

org.noorm.tutorial.hr.beans.JobHistory

org.noorm.tutorial.hr.beans.Jobs

org.noorm.tutorial.hr.beans.Locations

org.noorm.tutorial.hr.beans.Regions

 

You will find the generated classes in your Maven project in target/classes/org/noorm/tutorial/hr/beans.

The directory for the generated services in target/classes/org/noorm/tutorial/hr/services contains a single class file called BeanDML. This class contains a complete API for all DML operations applicable for the generated beans (insert, update and delete for single objects and lists of objects).

 

Naming Conventions and Custom Name Mappings


Java developers and database engineers typically use different naming conventions. For the generated Java code, NoORM follows best practices used by the Majority of Java developers (Code Conventions for the Java Programming Language).

Usually, this results in class, method and attribute names, which slightly differ from database object names. Database names are typically in upper-case with underscores to separate different parts of a single name. NoORM removes underscores and changes names according to the Camel-Case mechanism, i.e., a Java Bean generated for table JOB_HISTORY gets the name JobHistory.

 

However, you may have special requirements concerning the names of you Java classes, methods and attributes. In this case, the generator configuration parameters tableNameMappings and columnNameMappings provide the required functionality to adjust the generated names (see Code Generator Reference).

Posted by 善 곽중선
2014.11.21 18:11

http://www.noorm.org/


Efficient persistence for Java applications

자바 어플리케이션을 위한 효율적인 퍼시스턴스(persistence)


NoORM 은 코드 생성기(code generator) 및 자바 오픈소스 프로젝트 (아파치 라이센스)

NoORM는 코드 생성기를 제공하며 손쉽게 오라클 데이터베이스의 관계형 데이터에 대한 액세스를 자동화하는 런타임 라이브러리를 제공하는 자바 오픈 소스 프로젝트 (아파치 라이센스, 소스 코드와 이슈는 Java.Net 에서 확인) 입니다. NoORM은 현재까지는 오라클에 제한되어 있지만, 버전 2.0에서는 MySQL에 대해서도 지원을 제공할 것입니다. 많은 다른 툴과 라이브러리가 유사한 기능을 제공하고 있지만, NoORM는 데이터베이스 중심의 접근 방식을 따른다. 적절한 관계형 데이터 모델을 기반으로 NoORM는 자바 애플리케이션을 위해 오라클의 강점을 이끌어내는 자바 빈즈, 자바 열거형 및 Java 서비스에 필요한 자바 코드를 생성 할 수 있습니다. 특히, NoORM를 사용하여 당신에게 다음과 같은 혜택을 가져올 수 있습니다 :


NoORM is a Java open source project (Apache Licensing, source code and issue tracking at Java.Net) providing code generators and a runtime library to simplify and automate access to relational data residing in an Oracle database. Even though NoORM is still presently limited to Oracle, version 2.0 will offer support also for MySQL. In distinction to many other tools and libraries providing functionality in this area, NoORM follows a consequent database-centric approach. Having a proper relational data model, NoORM can generate the required Java code for Java Beans, Java Enums and Java Services to exploit the power of Oracle for Java applications. In particular, using NoORM can bring you the following benefits:

 

가파른 학습 곡선 : 런타임 환경설정 없음, 복잡한 API 없음. (실질적으로 의존적인 API가 거의 없음!)

놀라운 성능 : 성능 벤치 마크 자체에 복잡한 문제이지만, 우리는 자신있게 NoORM이 경쟁자들 보다 거의 항상 빠를 것이라도  주장할 수 있습니다.

관심사의 완전히 분리 : SQL은 클라이언트의 문제가 아니다! 데이터베이스 개체는 클라이언트 응용 프로그램에서 직접 해결해야 할 문제가 아닙니다! NoORM 응용 프로그램을 개발하는 것은 개발자도 데이터베이스 개체를 직접 조작하거나 데이터베이스 외부에서 SQL을 사용하지 않는다는 의미입니다!

향상된 코드 품질 : 코드 생성은 두 가지 장점이 있습니다 : 이기종 시스템을 위한 소프트웨어를 개발한다는 것은 항상 플랫폼 간의 중복이 어느 정도 발생하게 되어 있습니다. NoORM 데이터베이스 오브젝트에 액세스하기 위해 자바 코드를 생성하는  코드 생성기를 활용하면, 시스템 접속에 대한 코드를 생성하는 단 하나의 시스템만을 분석 할 수 있게 됩다. 코드 생성기의 두 번째 장점은 빌드 프로세스에서 런타임 시스템의 복잡한 작업을 '미리보기(preview)' 할 수 있다는 점 입니다. NoORM의 가장 복잡한 중요한 파트는 코드 생성기에 의해 구현되며, 이를 활용해 런타임 시점에 발생할 수 있는 잠재적인 문제점들을 빌드 시점에 점검할 수 있게 됩니다.


Steep learning curve: No runtime configuration, no complex API (actually almost no proprietary API at all!)

Extraordinary performance: Though performance benchmarking is a complex issue on its own, we can confidently assert that NoORM is almost always significantly faster than its competitors.

Clean Separation of Concerns: SQL is not a matter of the client! Database objects are not to be addressed directly from a client application! Developing applications with NoORM means that the developer neither addresses database objects directly nor uses SQL outside of the database!

Improved Code Quality: Code generation has two benefits: developing software for heterogeneous systems always includes some degree of redundancy across the different systems and platforms in use. Code generators can analyze one system to generate code for a connecting system, like NoORM generates Java code to access database objects.

A second benefit of code generators evolves from the pre-drawing of complex operations from the runtime system already in the build process. A significant part of the complexity of NoORM is implemented with the code generators, which will cause potential problems to occur at build time rather than at runtime!


왜 새로운 ORM 도구 또는 프레임워크가 필요합니까?


이 글을 쓰는 시점에서 이미 다양한객체 관계형 매핑 (ORM) 라이브러리와 프레임워가 나와 있습니다. 그럼, 왜 우리에게 새로운 툴이 더 필요할까요?

오라클 데이터베이스의 기능 활용 범위(혹은 수준)는 오라클을 사용하는 다수의 기업 자바 프로젝트 사이에 크게 다릅니다. 대부분의 엔터프라이즈 자바 프로젝트는 주로 자바 세계의 근원적인 설계 사상에 의해 구축됩니다. 많은 (기업) 자바 아키텍트들은 자바로 생각(Thinking in Java) 합니다.


Do we need another ORM Tool or Framework for Java?


There are plenty of ORM-tools (ORM : Object-Relational-Mapping) , libraries and frameworks available for Java at the time of this writing. So, why do we need one more?

The utilization of the features of an Oracle database varies significantly between numerous enterprise Java projects using Oracle. Many enterprise Java projects are mainly driven by architectural guidelines having their origin in the Java world. Many (enterprise) Java architects perceive themselves as "thinking in Java" (this is not to be understood as a hidden cross reference to the great Java book "Thinking in Java" from Bruce Eckel).


그 자체가 나쁜 것은 아닙니다. 그러나, 복잡한 엔터프라이즈 자바 프로젝트를 고려하면, 거의 항상 관계형 데이터베이스 관리 시스템을 사용하여 데이터를 유지하게 마련인데, 앞서의 접근방안은 관계형 데이터베이스 시스템의 역할 및 성능을 제대로 이끌어내지 못할 수 있다.

데이터베이스의 성능을 제대로 활용하면 응용 프로그램의 아키텍처와 디자인을 주목할만큼 개선할 수 있습니다.


This is not a bad thing per se. However, considering complex enterprise Java projects, which almost always use a relational database management system to persist data, this approach could easily result in an underestimation of the role and power of the relational database system. 

Leveraging the power of the database could significantly improve architecture and design of an application.


NoORM 은 오라클 데이터베이스 엑세스를 구성하는데 도움이 되는 또 다른 도구이지만, 소프트웨어 기능 요구사항을 기술하기 위한 새로운 스펙을 제시하지는 않습니다. NoORM 을 사용하기 위해 새로운 고유 API를 배울 필요가 없습니다. SQL 코드의 관리 및 유지는 생성기 설정의 간단한 쿼리 선언으로 이루어지며, 기존의 지식과 코드를 활용해 SQL을 구성할 수 있습니다.


Though NoORM is yet another tool to help you organize Oracle database access from a Java application, it does not introduce new specifications to specify your requirements. You do not even have to learn a new proprietary API to use NoORM. Managing and maintaining your SQL code is done through simple query declarations in the generator configuration or by using PL/SQL, so even for SQL you can build upon existing knowledge and/or code.


"NoORM"이름은 무엇을 의미 하는가?


NoORM이 실질적인 의미는 "no ORM"이나, 실제로 그런 것은 아닙니다. 자바와 같은 객체지향 프로그래밍 환경에서 관계형 데이터베이스를 사용하기 위해서는 언제나 "ORM(Object Relational Mapping)"이 필요합니다. 즉, 데이터베이스 데이터와 어플리케이션 데이터 간의 매핑(mapping) - 데이터베이스의 데이터가 어플리케이션에서 이용되는 방법 - 을 정의해야 하는 것입니다. NoORM 은 종종 '황금률'이라고 불리는 단순히 자바 클래스에 대에티베이스 테이블 또는 뷰를 매핑하는 아주 기본적인 ORM 패러다음을 사용합니다.


What does the name "NoORM" mean?


NoORM actually means "no ORM", which, of course, is not really true, since using a relational database system with an object-oriented programming environment like Java always requires some "ORM", i.e., you are required to define some mapping between database data and your application data, resp. the way the database data is utilized in your application. NoORM uses the very basic ORM paradigm often referred to as "golden rule", which simply maps a database table or view to a Java class (i.e., rows of a table or view are represented as object instances of the Java class representing the table or view).


사실상, 데이터를 매핑하는 것에 대해 더 할 말은 없습니다. NoORM은 최소한 매핑을 통해 중복을 최소화하는 기술을 제공하는 ORM 도구로 고려할 만 합니다.  좀 더 깊이 얘기하자면, NoORM 은 관계형 데이터 모델 (혹은 ER-모델)의 상세한 특성들을 다루지 않는데, 관계 조언, 제약 조건 등은 데이터베이스에 실행 책임을 맡기는 것이 최선입니다.


Effectively, there is not much more to say about mapping data, i.e., NoORM can be considered as an ORM-tool reducing the required redundancy implied by the mapping to the bare minimum. In particular, this means that NoORM does not care about the detailed characteristics of your relational data model or ER - model, but leaves this part to the database, which is effectively the best place to deal with relationships, joins, constraints, etc.


대상 그룹


NoORM 은 분명히 오라클을 사용하는 모든 엔터프라이즈 자바 프로젝트에 대해 관심을 두고 있습니다.  특히 PL / SQL을 사용할 수 있게 하는 것입니다. (그것뿐 아니라!).


Target Group


NoORM is obviously of interest for all enterprise Java projects using Oracle, in particular those which make use of PL/SQL (but not only!).


엔터프라이즈 자바 개발자들에게 있어 다른 ORM 도구들이 익숙하지만, PL/SQL 사용에 있어서는 의문이 있습니다. PL/SQL을 사용하지 않는 프로젝트 또한 그렇습니다. 하지만, NoORM 은 비즈니스 로직을 stored procedure에 저장된 PL/SQL로 이전할 것을 요구하지는 않습니다. PL/SQL 적용 범위는 매우 가변적이며 프로젝트의 요구사항에 따라 달랍니다. 기본적으로 PL / SQL의 사용에 관한 두 가지 시나리오를 고려할 수 있습니다. (물론, 상상할 수 있는 모든 시나리오 또한 가능합니다.)


It is quite natural that enterprise Java developers familiar with other ORM - tools question the usage of PL/SQL, in particular for projects which are not using PL/SQL yet. However, NoORM does not require moving your business logic into PL/SQL stored procedures. The degree of PL/SQL usage is quite variable and depends on your projects needs. Basically two scenarios concerning the usage of PL/SQL are possible (though any thinkable scenario in the range in between is possible, too):


PL/SQL 패키지로서의 SQL 컨테이너 : 어떤 ORM 도구를 사용하던 SQL을 사용할 수 밖에 없고, SQL을 어디에 저장할 지 고민해야 합니다. 엔터프라이즈 자바 어플리케이션 내부는 SQL을 관리하기 위한 적절한 저장소가 아닙니다. SQL을 XML 파일 같은 리소스 파일들에 저장하거나, 정적 클래스 변수 혹은 어노테이션에 저장하던 간에 둘 다 자바 어플리케이션 환경에서는 아무런 의미 없는 형식으로 저장됩니다. 데이터베이스로 SQL 명령이 전송될 때까지 SQL은 아무런 가치(의미)가 없습니다.그러므로, 궁극적으로 SQL 명령의 존재 의의가 있는 데이터베이스에 저장하는 것이 너무나 자연스러운 것입니다.


PL/SQL packages as SQL - container: Whatever ORM - tool you use, in any case you have to deal with SQL, in particular deciding where to store your SQL. We think that an enterprise Java application does not seem to be the appropriate place for maintaining SQL. Whether SQL is stored in (proprietary) resource files like XML - files, in static class variables or in (proprietary) annotations, in either case SQL is kept in a format which is actually meaningless to its environment (here: the Java application). The SQL does not become meaningful until it is submitted to the database. So it sounds quite natural to store SQL in a place which ultimately gives the SQL statements their meaning - in the database.


SQL 컨테이너로서의 PL / SQL 패키지는 SQL 코드의 검증 기능을 포함하는 선택 가능한 옵션입니다. 결국, PL/SQL을 sql 컨테이너로 사용하기 위한 방법을 학습하는 것은 엔터프라이즈 자바 어플리케이션에서 SQL을 관리하는 방법을 익히는 것보다 많은 것을 노력을 요구하지 않습니다.


SQL로 PL / SQL을 사용하는 방법을 학습 - (절대 PL / SQL 초보자 용) 용기 당신의 엔터프라이즈 자바 응용 프로그램과 함께 저장 SQL에 사용할 수있는 독점적 인 방법 중 하나를 배우는 것보다 더 요구하지 않습니다.

비즈니스 로직을 포함하는 PL / SQL : PL / SQL이 이미 프로젝트에 대한 비즈니스 로직의 중요한 부분을 포함하는 경우, 어쨌든 NoORM 을위해 잘 준비가 되어 있는 것입니다.


Using PL/SQL packages as SQL - container is a viable option here, including the validation of the SQL code. In the end, learning how to use PL/SQL as a SQL - container (for an absolute PL/SQL beginner) is not more demanding than learning one of the proprietary methods available to store SQL with your enterprise Java application.

PL/SQL to contain business logic: When PL/SQL is already used in your projects for significant parts of your business logic, you are well prepared for NoORM anyway.

 

그러나, SQL 문 대다수를 사용하는데 있어서 PL/SQL을 사용할 필요는 없다. SQL 문장의 대부분은 SELECT * <하나의 엔티티> WHERE A = X와 B = Y FROM ...' 와 같은 사소한 형식을 따른다.  이러한 단순한 형식의 쿼리들은 쿼리 생성을 위한 각종 설정과 쿼리(코드) 생성기에 손쉽게 통합될 수 있다. 데이터베이스 뷰를 이용해 복잡한 쿼리 조차 쿼리를 선언하는 출발점으로 활용할 수 있고, 거의 모든 쿼리 또한 간결한 형식으로 제공할 수 있다.


However, for the majority of SQL statements it is not even necessary to use PL/SQL. The vast majority of SQL statements follow a rather trivial format: SELECT * FROM <one single entity> WHERE A = x AND B = y ...

Queries with this trivial format can easily be integrated (and generated) using the code generator for an appropriate query declaration as part of the generator configuration. By using database views it is even possible to provide even complex SQL as starting point for the declared query, turning almost all queries into this trivial format.

 

"데이터베이스 중심"코드 생성의 기본 원리는 직접 데이터베이스 객체에 접근하지 않는다는 것이다. 테이블, 뷰 등의 데이터베이스 객체의 이름은 생성기 설정에서만 사용되면, 손으로 만든(hand-made) 자바 코드에서 사용되지 않는다.

 

The basic principle of "database-centric" code-generation is that the developer using NoORM will never address a database object directly (the names of database objects, i.e., tables, views, etc. are used in the generator configuration only, but never in the ("hand-made") Java code.


왕복 엔지니어링


엔터프라이즈 소프트웨어 환경의 시스템이나 구성 요소 간의 매핑 데이터는 항상 코드 및 사양에 약간의 고유 중복을 포함한다. NoORM로 구현된 최소한의 객체 관계형 매핑 접근 방식은 완전 자동화 된 왕복 엔지니어링 솔루션을 실현한다. 이것은 데이터베이스 데이터에 대한 표현과, 필요한 기능이 완전히 NoORM 코드 생성기에 의해 생성된다는 것을 의미한다.


Roundtrip Engineering


Mapping data between systems or components of enterprise software environments always includes some intrinsic redundancy in code and specifications. The minimal object-relational-mapping approach implemented with NoORM is realized as fully automated roundtrip engineering solution. This means that the code required to represent database data and functionality is completely generated by the NoORM code generator.

Posted by 善 곽중선
2014.04.27 16:08

여우는 입을 다물고 어린 왕자를 오랫동안 쳐다보더니

"부탁이야...... 나를 길들여 줘!" 하고 말했다.


어느새 나이를 많이 먹어 나도 보아뱀을 삼킨 코끼리를 모자라 착각하는 아저씨가 되어 간다.

어릴 적에는 생 떽쥐베리의 어린 왕자가 아름답게만 여겨지더니, 나이를 먹고 보니 이런 처참한 절규로 가득한 이야기 달리 없다.


세상에나.. 생 떽쥐베리... 그는 얼마나 외로운 사람이었을까?

어찌하여 생의 마지막 순간조차 차가운 밤 바다에서 사라져야만 했을까?

아.... 이제 그를 이해하는 나이가 되어간다.


부탁이야... 부탁이야.. 

그래 나도 부탁하고 싶다.

목구멍에서 터져나오는 듯 그러나, 아무 소리조차 나지 않는다.


아무에게도 들리지 않는다. 다들 무심히 내 곁을 지나칠 뿐이다.


’부탁이야...... 나를 길들여줘!’

Posted by 善 곽중선
2012.02.07 17:35
본 포스트는 이터너티님의 DDD(Domain-Driven Design) 해설을 학습한 과정을 정리한 것입니다.

PART 1. VALUE OBJECT와 REFERENCE OBJECT

어플리케이션을 구성하는 객체는 Value Object와 Reference Object로 나뉜다. VO와 RO를 구분하는 기준에 대해서 이터니티 님은 아래와 같은 가이드를 제시한다.

시스템 내에서 해당 객체를 계속 추적해야 하는가객체가 표현하는 개념이 유일하게 하나만 존재해야 하는가? 그렇다면 REFERENCE OBJECT로 만든다단지 객체가 추적할 필요가 없는 단순한 값인가속성값이 동일하면 동일한 객체로 간주해도 무방한가고민할 필요 없다그냥 VALUE OBJECT로 만든다.

Reference Object는 유일하게 존재해야 하는 것이라고 말한다. 어떤 것들이 해당할까?

- 유일하게 존재한다는 것은 객체들이 같거다 혹은 다르다는 점을 명확히 구분할 수 있어야 한다. 달리 말해, ID를 가지는 객체들을 말한다.
- 물리적인 장치(DB, file system)에 저장되거나, 네트워크를 통해 전송되는 객체들이다. 잠시 만들었다가 사라지는 데이터에 추적할 필요가 없기 때문이다.

이러한 두가지 특징을 가지는 객체들은 무엇이 있을까? 가장 좋은 사례는 DB에 저장되며, 기본 키(primary key)를 가지는데이터(혹은 엔티티)일 것이다. Reference Object로 정의해야 것들은 최종적으로 DB에 저장되는 객체들이라고 간주하는 것이 무방하다.
 
동일함의 의미 

앞서, Reference Object들은 유일하게 존재해야 한다고 정의했다. 그렇다면, Reference Object를 만들어 쓴다는 것은  유일한 객체임을 보장할 수 있는 수단이 제공되어야 한다는 말이다. 이너니티님의 글을 다시 인용한다.

모든 객체 지향 시스템은 생성된 객체에게 고유한 식별자(identity)를 부여한다. 대부분의 객체 지향 언어는 객체가 위치하고 있는 메모리 상의 주소를 객체의 식별자로 할당하고 이 주소 값을 사용하여 객체를 구별한다.
 
그렇다면 자바에서 객체의 고유 식별자를 알아내는 방법이 있을까? 그리고, 고유 식별자를 이용해 유일성(uniqueness)을 보장받을 수 있을까?

In java there is no any specific method that provides us the object's ID. But each object has its own unique hash value which can be treated as unique Id for that object.
- Rose India 인용

자바에서는 해시 코드(hash code)를 객체의 고유 식별자로 사용할 수 있다고 한다. 그런데, 유일성을 확실히 보장해주지 않는다고 말한다.이게 대체 무슨 말인가? 아래와 같이 설명할 수 있다.

- 동일한 객체는 항상 동일한 해시 코드를 반환한다.
- 하지만, 서로 다른 객체가 동일한 해시 코드를 반환 할 수도 있다.

달리 말해서, 동명이인(同名異人)이 존재할 수도 있다는 말이다. 즉, 해시 코드는 우리가 특정 사람을 지칭할 때 쓰는 이름과 같은 것이다. 그래서, 이너니티님은 아래와 같이 가이드하고 있다.

각 언어는 객체의 식별자를 비교할 수 있는 연산자를 제공하는데 Java의 경우 “==”와 “!=” 연산자를 사용한다. 두 참조가 가리키는 객체가 동일한 식별자를 가지는 경우, 즉 동일한 주소에 위치하는 경우 “==” 연산자는 true를 반환한다.

“==” 연산자를 사용하여 동일성을 판단하기 보다는 equals() 메소드를 오버라이딩하여 금액의 동등성을 테스트해야 한다.

한 발 더 나아가, 동일성(identity)와 동등성(equality)의 차이에 대해서 얘기해 보자.

- 동일성(identity)은 비교하려는 두 개의 객체가 동일한 식별자를 반환할 경우 같다고 판단하는 것이다.
- 동등성(equality)는 두 객체의 내용 (혹은 데이터)이 일치할 경우, 같다고 판단하는 것이다.

대부분의 상황에서는 '동일성 비교'를 기본으로 적용한다. 그러나, DDD(Domain Driven Design)에서는 동등 비교를 원칙으로 한다. (DDD에서는 데이터를 안전하고, 정확하게 사용하는 것이 주된 관심사이다.) 그러니 개발자들은 Reference Object 및 Value Object를 정의함에 있어서 어떻게 동등 비교를 실현할 수 있는지 그 방법론을 정확히 이해해야 한다.

동일 비교 시에 발생하는 문제

일반적인 동일 비교 방식을 적용했을 때, 발생하는 문제에 대해서 간단한 코드를 작성해서 테스트해 보도록 하자. 먼저, 금액을 나타내는 클래스를 작성해 보았다.

 
package org.eternity.customer;

public class Money {
	private long amount;
	
	public Money(long amount) {
		this.amount = amount;
	}
	
	public Money(int amount) {
		this.amount = amount;
	}

	public String toString() {
		return String.valueOf(amount);
	}
}
같은 데이터를 가지고 있지만, 다른 객체로 인식되는 경우를 확인해 보자. 단위 테스트 코드를 아래와 같이 작성했다. 서로 다른 객체이지만, 분명 동일한 금액을 가지고 있다.

package test.eternity.customer;

import static org.junit.Assert.*;

import org.eternity.customer.Money;
import org.junit.Test;

public class MoneyTest {

	@Test
	public void testAmount() {
		Money money1 = new Money(1000);
		Money money2 = new Money(1000);
	
		System.out.println( "money1's hash code = " + money1.hashCode() );
		System.out.println( "money2's hash code = " + money2.hashCode() );

		// money1 == money2 (?)
		assertEquals(money1, money2);
	}

}
테스트는 실패하고 만다. 서로 다른 객체로 판정하는 것이다. 왜 이런 결과가 나오는지 확인하기 위해, 해시 코드의 출력 값을 확인해 보면 아래와 같다. (해시 코드 값은 실행할 때마다 달라질 수 있다.)

money1's hash code = 4565111
money2's hash code = 20392474
이제 동등 비교를 하기 위해 Money 클래스를 아래와 같이 수정했다.

package org.eternity.customer;

public class Money {
	private long amount;
	
	public Money(long amount) {
		this.amount = amount;
	}
	
	public Money(int amount) {
		this.amount = amount;
	}

	public String toString() {
		return String.valueOf(amount);
	}
	
	public boolean equals(Object other) {
		if(this == other) 
			return true;
		
		if(!(other instanceof Money))
			return false;
		
		if( this.amount == ((Money)other).amount )
			return true;
		
		return false;
		
	}
}
이제 단위 테스트를 통과했다. 그런데, 뭔가 문제가 남아 있다. 테스트를 통과했는데 뭐가 문제냐고? 두 개의 객체가 동일하다는 결과가 나오는데 해시 코드는 서로 다르게 출력되는 것이다. 자바의 기본 원칙을 위배한 것이다.

Equal objects must produce the same hash code as long as they are equal, however unequal objects need not produce distinct hash codes. - Equals and Hash Code 참조 

자바의 원칙을 준수하면서, 동등 비교를 구현하기 위해서는 equals() 메소드와 hashCode() 메소드를 함께 오버라이드(override) 해야만 한다.


package org.eternity.customer;

public class Money {
	private long amount;
	
	public Money(long amount) {
		this.amount = amount;
	}
	
	public Money(int amount) {
		this.amount = amount;
	}

	public String toString() {
		return String.valueOf(amount);
	}
	
	public boolean equals(Object other) {
		if(this == other) 
			return true;
		
		if(!(other instanceof Money))
			return false;
		
		if( this.amount == ((Money)other).amount )
			return true;
		
		return false;
		
	}
	
	public int hashCode()
	{
		return (int)(amount ^ (amount >>> 32));
	}
}
이제 테스트를 수행하면 두 객체가 동일하다고 판정되고, 해시 코드 역시 동일한 값을 출력한다.
money1's hash code = 1000
money2's hash code = 1000
hashCode() 메소드는 자바의 컬렉션 클래스들(List, Map 등) 에서 보이지 않게(?) 호출되며, 다양한 API, 라이브러리에서 객체를 관리하기 위한 목적으로 해시 코드 반환 값을 사용하기 때문에 equals() 함수를 오버라이드(override)할 경우에는 잊지 말고, 함께 구현해야 한다. 혹여 잊어 버린다고 해서 컴파일 오류는 나지 않는다. 하지만, 예기치 않은 문제가 발생할 경우에는 원인을 추적하기 매우 어렵게 된다. 어떤 문제가 발생할 수 있는지, hashCode() 함수를 오버라이드 하지 않고 아래와 같은 테스트 코드를 작성했더니, 역시나 문제가 발생했다. 길지 않은 코드이니 직접 컴파일 한 후 확인해 보시는 것을 권장한다.
package test.eternity.customer;

import static org.junit.Assert.*;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.eternity.customer.Money;
import org.junit.Test;

public class MoneyTest {

	@Test
	public void testAmount() {
		Money money1 = new Money(1000);
		Money money2 = new Money(1000);
		
		System.out.println( "money1's hash code = " + money1.hashCode() );
		System.out.println( "money2's hash code = " + money2.hashCode() );
	
		// money1 == money2
		assertEquals(money1, money2);
	}
	
	@Test
	public void setSet() {
		Money money1 = new Money(1000);
		Money money2 = new Money(1000);
		
		Set moneyPocket = new HashSet();
		moneyPocket.add(money1);
		assertEquals(1, moneyPocket.size());
		moneyPocket.add(money2);
		assertEquals(2, moneyPocket.size());
		
		Map moneyMap = new HashMap();
		moneyMap.put(money1, 1);
		moneyMap.put(money2, 2);
		
		assertEquals(1, moneyMap.size());
	}
}
Posted by 善 곽중선