hibernate-orm/doc/reference/ko/modules/best_practices.xml
2007-06-29 19:55:14 +00:00

205 lines
15 KiB
XML

<chapter id="best-practices" revision="3">
<title>최상의 실전 경험들</title>
<variablelist spacing="compact">
<varlistentry>
<term>fine-grained 클래스들을 작성하고 <literal>&lt;component&gt;</literal>를 사용하여 그것들을 매핑하라. </term>
<listitem>
<para>
<literal>street</literal>, <literal>suburb</literal>, <literal>state</literal>, <literal>postcode</literal>
캡슐화 시키는데 <literal>Address</literal> 클래스를 사용하라. 이것은 코드 재사용성을 촉진시키고 리팩토링을 단순화 시킨다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>영속 클래스들에 대해 식별자 프로퍼티들을 선언하라.</term>
<listitem>
<para>
Hibernate는 식별자 프로퍼티들을 옵션으로 만든다. 왜 우리가 그것들을 사용해야 하는가에 대한 모든 종류의 이유들이 존재한다.
우리는 식별자들이 '합성(synthetic)'이 되는(비지니스 의미 없이 생성되는) 것을 권장한다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>고유 키들을 식별하라.</term>
<listitem>
<para>
모든 엔티티들에 대해 고유 키들을 식별하고, <literal>&lt;natural-id&gt;</literal>를 사용하여 그것들을 매핑하라.
고유 키를 구성하는 프로퍼티들을 비교하기 위해 <literal>equals()</literal><literal>hashCode()</literal>
구현하라.
</para>
</listitem>
</varlistentry>
<varlistentry><term>각각의 클래스 매핑을 그것 자신의 파일 내에 위치지워라.</term>
<listitem>
<para>
하나의 한덩어리 매핑 문서를 사용하지 말라. <literal>com/eg/Foo.hbm.xml</literal> 파일 속에
<literal>com.eg.Foo</literal>를 매핑하라. 이것은 팀 환경에서 특히 좋은 의미를 준다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>매핑들을 리소스들로서 로드시켜라.</term>
<listitem>
<para>
그것들이 매핑하는 클래스들에 따라서 매핑들을 배치하라
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>질의 문자열들을 객관화 시키는 것을 고려하라.</term>
<listitem>
<para>
당신의 질의들이 ANSI 표준이 아닌 SQL 함수들을 호출하는 경우는 좋은 실전연습이다. 질의 문자열들을 매핑 파일들에다가
외부화 시키는 것은 어플리케이션을 보다 이식성 있도록 만들어줄 것이다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>바인드 변수들을 사용하라.</term>
<listitem>
<para>
JDBC에서처럼, 상수 아닌 값들을 "?"로 대체시켜라. 질의 속에 상수 아닌 값을 바인드 시키는데 문자열 처리를 결코
사용하지 말라! 더 좋게는 질의들 속에 명명된 파라미터들을 사용하는 것을 고려하라.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>당신 자신의 JDBC 커넥션들을 관리하지 말라.</term>
<listitem>
<para>
Hibernate는 어플리케이션으로 하여금 JDBC 커넥션들을 관리하도록 한다. 이 접근법은 마지막 수단으로서 고려되어야 한다.
만일 당신이 미리 만들어진 커넥션 프로바이더들을 사용할 수 없을 경우, <literal>org.hibernate.connection.ConnectionProvider</literal>
대한 당신 자신의 구현을 제공하는 것을 고려하라.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>맞춤형 타입 사용을 고려하라.</term>
<listitem>
<para>
당신이 자바 타입을 갖고 있고, 어떤 라이브러리로부터 말하고, 그것이 영속화 될 필요가 있지만 그것을 컴포넌트로서 매핑시키는데
필요한 accessor들을 제공할 필요가 없다고 가정하자. 당신은 <literal>org.hibernate.UserType</literal>을 구현하는
것을 고려해야 할 것이다. 이 접근법은 Hibernate 타입으로/으로부터 변환들을 구현하는 것으로부터 어플리케이션 코드를 자유롭게
해준다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>병목 지점들에서 수작업으로 코딩된 JDBC를 사용하라.</term>
<listitem>
<para>
시스템의 퍼포먼스가 중대한 영역들에서, 몇몇 종류의 오퍼레이션들은 직접적인 JDBC에서 이득을 본다. 그러나 당신이 어떤 것이 병목인지를
<emphasis>알기</emphasis> 전까지 기다리길 바란다. 그리고 직접적인 JDBC가 반드시 더 빠르다고 가정하지 말라. 만일 당신이 직접적인
JDBC를 사용할 필요가 있을 경우, Hibernate <literal>Session</literal>을 열고 그 SQL 커넥션을 사용할 가치가 있다. 그 방법으로
당신은 동일한 트랜잭션 방도와 기본 커넥션 프로바이더를 여전히 사용할 수 있다
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>Session</literal> flushing을 이해하라.</term>
<listitem>
<para>
시간이 지남에 따라 Session은 그것의 영속 상태를 데이터베이스와 동기화 시킨다. 만일 이 과정이 너무 자주 발생할 경우 퍼포먼스가
영향을 받을 것이다. 당신은 때때로 자동적인 flushing을 사용 불가능하게 만들거나 특정 트랜잭션 내에서 질의들의 순서와 다른
오퍼레이션들의 순서를 변경시켜서 불필요한 flushing을 최소화 시킬 수 있다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>3-tier 아키텍처에서, <literal>saveOrUpdate()</literal> 사용을 고려하라.</term>
<listitem>
<para>
servlet / session 빈 아키텍처를 사용할 때, 당신은 sesson bean 내에 로드된 영속 객체들을 서블릿/JSP 계층으로/으로부터
전달할/받을 수 있다. 각각의 요청을 서비스하는데 새로운 세션을 사용하라. 객체들을 데이터베이스와 동기화 시키기 위해서
<literal>Session.merge()</literal> 또는 <literal>Session.saveOrUpdate()</literal>를 사용하라.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>2-tier 아키텍처에서, 수명이 긴 영속 컨텍스트들을 사용하는 것을 고려하라.</term>
<listitem>
<para>
데이터베이스 트랜잭션들은 최상의 가용성을 위해 가능한 한 짧아야 한다. 하지만 장기간 실행되는 <emphasis>어플리케이션 트랜잭션들</emphasis>,
사용자의 뷰 관점에서 한 개의 단위 작업을 구현하는 것이 가끔 필수적이다. 하나의 어플리케이션 트랜잭션은 몇 개의 클라이언트 요청들과
응답 주기들에 걸칠 수도 있다. 어플리케이션 트랜잭션들을 구현하는데 detached 객체들을 사용하는 것이 공통적이다. 2-티어 아키텍처에서
매우 적절한 대안은 어플리케이션 트랜잭션의 전체 생명주기 동안에 한 개의 열려진 영속 접속 (세션)을 유지하는 것이고 각각의 요청의 끝에서
JDBC 커넥션을 간단하게 연결해제하고 차후의 요청의 시작 시에 다시 연결하는 것이다. 한 개 이상의 어플리케이션 트랜잭션을 가로질러서
하나의 단일 세션을 결코 공유하지 말라. 공유할 경우에 당신은 실효성이 없는 데이터로 작업하게 될 것이다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>예외상황들을 복구가능한 것으로서 다루지 말라.</term>
<listitem>
<para>
이것은 "최상의" 실전이 아닌 보다 필수적인 실전이다. 예외상황이 발생할 때, <literal>Transaction</literal>을 롤백시키고
<literal>Session</literal>을 닫아라. 만일 당신이 그렇게 하지 않을 경우, Hibernate는 메모리 내 상태가 영속 상태를 정확하게
표현하는 것을 보증할 수 없다. 이 특별한 경우처럼, 만일 주어진 식별자를 가진 인스턴스가 데이터베이스 상에 존재하는지 여부를 결정하는데
<literal>Session.load()</literal>를 사용하지 말라; 대신에 <literal>Session.get()</literal> 또는 하나의 질의를
사용하라.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>연관들에 대한 lazy 페칭을 선호하라.</term>
<listitem>
<para>
eager 페칭을 관대하게 사용하라. second-level 캐시 내에 완전하게 보관되지 않을 것 같은 클래스들에 대한 대붑분의 연관들에
대해 프락시들과 lazy 콜렉션들을 사용하라. 캐시된 클래스들에 대한 연관들의 경우, 이곳은 캐시 성공의 매우 높은 확률이 존재하는
곳이며, <literal>lazy="false"</literal>를 사용하여 eager 페칭을 명시적으로 사용 불가능하게 하라. 한의 join 페칭이
특정 쓰임새에 대해 적절할 때, 하나의 <literal>left join fetch</literal>를 가진 질의를 사용하라.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
페치되지 않은 데이터 문제점들을 피하기 위해 <emphasis>뷰 내에 열려진 세션(open session in view)</emphasis> 패턴 또는
하나의 정리된 <emphasis>어셈블리 단계(assembly phase)</emphasis>를 사용하라.
</term>
<listitem>
<para>
Hibernate는 개발자들이 <emphasis>Data Transfer Objects</emphasis> (DTO)를 지루하게 작성하는 것으로부터
자유롭게 해준다. 전통적인 EJB 아키텍처에서, DTO는 이중 용도로 기능한다: 첫 번째로 그것들은 엔티티 빈즈가 직렬화 가능하지 않는
문제점에 대해 착수한다; 두 번째로 그것들은 뷰에 의해 사용되는 모든 데이터가 프리젠테이션 티어로 컨트롤을 반환하기 전에 DTO들 속으로
페치되고 마샬링되는 어셈블리 단계를 암묵적으로 정의한다. Hibernate는 첫 번째 용도를 제거시킨다. 하지만 당신이 뷰 렌더링 프로세스를
가로질러 열려져 있는 영속 컨텍스트(세션)을 보관할 준비가 되어 있지 않는 한, 당신은 여전히 어셈블리 단계를 필요로 할 것이다(detached
객체들에서 이용가능한 데이터가 무엇인지에 대해 프리젠테이션 티어와 엄격하게 계약을 갖도록 당신의 비지니스 메소드들을 고려하라)
이것은 Hibernate의 한계점이 아니다! 그것은 안전한 트랜잭션 데이터 접근의 필수 조건이다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Hibernate에서 당신의 비지니스 로직을 추상화 시키는 것을 고려하라.</term>
<listitem>
<para>
(Hibernate) 데이터 액세스 코드를 인터페이스 이면에 은폐시켜라. <emphasis>DAO</emphasis>
<emphasis>Thread Local Session</emphasis> 패턴들을 결합시켜라. 당신은 심지어 <literal>UserType</literal>
통해 Hibernate에 연관된, 수작업으로 코딩된 JDBC로서 몇몇 클래스들을 영속화 시킬 수도 있다. (이 충고는 "충분히 큰"
어플리케이션들에 대한 것이다; 그것은 5개의 테이블들을 가진 어플리케이션에 대해서는 적절하지 않다!)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>신종의 연관 매핑을 사용하지 말라.</term>
<listitem>
<para>
실제의 many-to-many 연관들에 대한 좋은 쓰임새들은 드물다. 대부분의 시간 동안 당신은 "연결 테이블" 내에 저장된 추가적인 정보를 필요로 한다.
이 경우에, 매개하는 연결 클래스에 대해 두 개의 one-to-many 연관들을 사용하는 것이 훨씬 더 좋다. 사실 우리는 대부분의 연관들이 one-to-many와
many-to-one이라고 생각하며, 당신은 다른 연관 스타일을 사용할 때 주의해야 하고 그것이 진정 필수적인지를 당신 스스로 질문하라.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>양방향 연관들을 선호하라.</term>
<listitem>
<para>
단방향 연관들은 질의하기가 더 어렵다. 많은 어플리케이션에서, 거의 모든 연관들은 질의들 내에서 양 방향으로 네비게이트 가능해야 한다.
</para>
</listitem>
</varlistentry>
</variablelist>
</chapter>