47
Object Relational Mapping( 이이 ORM) 이이 이이 이 이이 이이 이이이 www.slipp.n et

ORM을 활용할 경우의 설계, 개발 과정

Embed Size (px)

DESCRIPTION

SpringCamp에서 발표한 ORM 프레임워크를 활용했을 때의 설계 및 개발 과정을 담고 있다.

Citation preview

Page 1: ORM을 활용할 경우의 설계, 개발 과정

Object Relational Mapping( 이하 ORM) 기반 설계 및 개발 과정

박재성www.slip-p.net

Page 2: ORM을 활용할 경우의 설계, 개발 과정

오늘 할 이야기

Page 3: ORM을 활용할 경우의 설계, 개발 과정
Page 4: ORM을 활용할 경우의 설계, 개발 과정

요구사항

사용자는 질문을 할 수 있어야 한다 .

질문에 대한 답변을 할 수 있어야 한다 .

질문을 할 때 태그를 추가할 수 있어야 한다 .

태그는 태그 풀에 존재하는 태그만 추가할 수 있다 .

태그가 추가될 경우 해당 태그 수는 +1 증가 , 삭제될 경우 해당 태그 수는 -1 증가해야 한다 .

Page 5: ORM을 활용할 경우의 설계, 개발 과정

Question

Answer

Tag

1

0..n 0..n

0..n

User1 0..n

1

0..n

Page 6: ORM을 활용할 경우의 설계, 개발 과정

어디서부터 시작할 것인가 ?

객체 or 테이블

Page 7: ORM을 활용할 경우의 설계, 개발 과정

테이블 주도 개발

Page 8: ORM을 활용할 경우의 설계, 개발 과정

테이블 설계로부터 시작 한다면…

요구사항질문 할 때 태그를 추가할 수 있다 . ( 예 java eclipse)

질문을 수정할 때 태그를 수정할 수 있다 . ( 예 . eclipse ant)

Page 9: ORM을 활용할 경우의 설계, 개발 과정
Page 10: ORM을 활용할 경우의 설계, 개발 과정

질문 추가시 java eclipse 태그 추가할 경우

insert into question values( ?, ?, ?, ?, ?); => question_id = 1

select id, name from tag where name=’java’; => tag_id = 11select id, name from tag where name=’eclipse’; => tag_id = 12

insert into question_tag values( 1, 11 );insert into question_tag values( 1, 12 );

update tag set tagged_count = tagged_count + 1 where name=’java’;update tag set tagged_count = tagged_count + 1 where name=’eclipse’;

Page 11: ORM을 활용할 경우의 설계, 개발 과정

질문 수정시 eclipse ant 태그 추가할 경우

update question set title=?, contents=? where question_id = 1;

delete from question where question_id = 1;

select id, name from tag where name=’eclipse’; => tag_id = 12select id, name from tag where name=’ant’; => tag_id = 13

insert into question_tag values(1, 13);delete from question_tag where question_id=1 and tag_id=11;

update tag set tagged_count = tagged_count + 1 where name=’ant’;update tag set tagged_count = tagged_count - 1 where name=’java’;

Page 12: ORM을 활용할 경우의 설계, 개발 과정

객체 간의 관계는 사라지고 데이터베이스에 대한 처리에 집중하게 된다 .

즉 , 비즈니스 로직 구현 보다 데이터베이스 접근 로직 구현에 집중한다 .

Page 13: ORM을 활용할 경우의 설계, 개발 과정

도메인 ( 객체 ) 주도 개발

Page 14: ORM을 활용할 경우의 설계, 개발 과정

객체 설계로부터 시작 한다면…

요구사항질문 할 때 태그를 추가할 수 있다 . ( 예 java eclipse)

질문을 수정할 때 태그를 수정할 수 있다 . ( 예 . eclipse ant)

Page 15: ORM을 활용할 경우의 설계, 개발 과정

일단 테이블 구조는 의식하지 않고 비즈니스 로직 구현한다 .

Page 16: ORM을 활용할 경우의 설계, 개발 과정

• 쉼표 (,) 로 구분되어 있는 태그를 파싱한다 .( 예 . java eclipse)

• 태그가 태그 풀에 존재하는지 확인한다 .

• 태그 풀에 존재하지 않으면 태그를 신규 태그로 등록한다 .

질문 추가 1 단계 – 태그 목록을 추출한다 .

데모

Page 17: ORM을 활용할 경우의 설계, 개발 과정

• 태그 목록을 Question 에 전달한다 .

• Question 에 추가한 모든 Tag 의 taggedCount 를 +1

증가시킨다 .

질문 추가 2 단계 – Question 에 태그 추가

데모

Page 18: ORM을 활용할 경우의 설계, 개발 과정

• 질문 추가할 때와 같이 태그 목록을 구한다 .( 예 . eclipse ant)

• 추가된 태그는 Tag 의 taggedCount 를 +1 증가한다 .

• 삭제된 태그는 Tag 의 taggedCount 를 -1 감소한다 .

질문을 수정

데모

Page 19: ORM을 활용할 경우의 설계, 개발 과정

객체와 테이블 매핑

Page 20: ORM을 활용할 경우의 설계, 개발 과정

@Entitypublic class Question { @ManyToOne @org.hibernate.annotations.ForeignKey(name = "fk_question_writer")

private User writer;

@Column(name = "title", length = 100, nullable = false)private String title;

@Temporal(TemporalType.TIMESTAMP) @Column(name = "created_date", nullable = false, updatable = false)

private Date createdDate;

[...]}

데모

Page 21: ORM을 활용할 경우의 설계, 개발 과정

테이블의 primary key 와 이와 매핑되는 객체의 필드를 설계한다 .

@Entitypublic class Question { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long questionId;

[...]}

Page 22: ORM을 활용할 경우의 설계, 개발 과정

데이터베이스 성능에 대한 고려해 설계한다 .

@Entitypublic class Question { @ElementCollection(fetch = FetchType.LAZY) @CollectionTable(name = "question_content_holder", joinColumns = @JoinColumn(name

= "question_id", unique = true)) @org.hibernate.annotations.ForeignKey(name =

"fk_question_content_holder_question_id") @Lob @Column(name = "contents", nullable = false) private Collection<String> contentsHolder;

public Question(User writer, String title, String contents, Set<Tag> tags) { this.writer = writer; this.title = title; this.contentsHolder = Lists.newArrayList(contents); processTags(tags); this.tags = tags; this.createdDate = new Date(); }

[...] public String getContents() { if (isEmptyContentsHolder()) { return ""; }

return Iterables.getFirst(contentsHolder, ""); }}

Page 23: ORM을 활용할 경우의 설계, 개발 과정

객체의 구조 ( 특히 상속 ) 와 테이블의 구조가 일치하지 않는 부분을 고려해 설계한다 .

Page 24: ORM을 활용할 경우의 설계, 개발 과정

안정화 단계까지 ORM 의 스키마 자동 생성 기반으로 개발

<?xml version="1.0" encoding="UTF-8" standalone="no"?><persistence xmlns="http://java.sun.com/xml/ns/persistence" [...]> <persistence-unit name="slipp.qna" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.dialect"

value="org.hibernate.dialect.MySQLDialect" /> <property name="hibernate.hbm2ddl.auto" value="create" /> <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" /> <property name="hibernate.format_sql" value="true" /> <property name="hibernate.show_sql" value="false"/> </properties> </persistence-unit></persistence>

Page 25: ORM을 활용할 경우의 설계, 개발 과정

ORM 사용시 테이블 스키마 관리

Page 26: ORM을 활용할 경우의 설계, 개발 과정

public class JPASchemaExport { public static void main(String[] args) { Ejb3Configuration cfg = new Ejb3Configuration(); HashMap<String, String> props = new HashMap<String, String>(); props.put("hibernate.format_sql", "true"); Ejb3Configuration configured = cfg.configure("slipp.qna", props); SchemaExport se = new SchemaExport(configured.getHibernateConfiguration()); se.setDelimiter(";"); se.create(true, false); }}

객체와 테이블을 매핑하면 테이블 스키마를 자동으로 Export 할 수 있다 .

데모

Page 27: ORM을 활용할 경우의 설계, 개발 과정

DB Migration 도구를 활용해 스키마 관리Maven Carbon Five 플러그인 활용 (https://code.google.com/p/c5-db-migration/)

데모

Page 28: ORM을 활용할 경우의 설계, 개발 과정

기능 추가 및 변경시 스키마 관리

Page 29: ORM을 활용할 경우의 설계, 개발 과정

<?xml version="1.0" encoding="UTF-8" standalone="no"?><persistence [...]> <persistence-unit name="slipp.qna" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.dialect"

value="org.hibernate.dialect.H2Dialect" /> <property name="hibernate.hbm2ddl.auto" value="update" /> <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" /> <property name="hibernate.format_sql" value="true" /> <property name="hibernate.show_sql" value="false"/> </properties> </persistence-unit></persistence>

기능 안정화 단계DB Migration 도구를 활용해 테이블 스키마 변경 관리한다 .

Page 30: ORM을 활용할 경우의 설계, 개발 과정

요구사항

질문을 상세보기 할 때마다 조회수를 1 증가시킨다 .

데모

Page 31: ORM을 활용할 경우의 설계, 개발 과정

schema_version 테이블

Page 32: ORM을 활용할 경우의 설계, 개발 과정
Page 33: ORM을 활용할 경우의 설계, 개발 과정

자바 진영에서 사용할 수 있는 DB Migration Tools• Flyway

• Liquibase

• c5-db-migration

• dbdeploy

• mybatis

• MIGRATEdb

• migrate4j

• dbmaintain

• AutoPatch

Page 34: ORM을 활용할 경우의 설계, 개발 과정

DB Migration Tools 시작• http://flywaydb.org/에 각 도구별 비교 자료 확인

• 자신의 프로젝트에 적합한 도구 선정

• 개발 단계부터 DB Migration Tool 기반으로 개발해야 성공 가능성이 높다 .

Page 35: ORM을 활용할 경우의 설계, 개발 과정

QnA 게시판 완료 - SLiPP

데모

Page 36: ORM을 활용할 경우의 설계, 개발 과정

마치며…

Page 37: ORM을 활용할 경우의 설계, 개발 과정

객체와 테이블 매핑

객체 속성 추가 및 테이블 칼럼 추가 객체 ( 도메인 ) 설계

매핑 정보를 활용해 테이블 스키마 생성

비즈니스 로직 구현

도메인 주도 개발

데이터베이스 접근 로직 구현

Page 38: ORM을 활용할 경우의 설계, 개발 과정

객체와 테이블 매핑

객체 속성 추가 및 테이블 칼럼 추가 테이블 설계

테이블로부터 객체 생성비즈니스 로직 구현

테이블 주도 개발

데이터베이스 접근 로직 구현

Page 39: ORM을 활용할 경우의 설계, 개발 과정

객체와 테이블 매핑

객체 속성 추가 및 테이블 칼럼 추가 객체 ( 도메인 ) 설계

매핑 정보를 활용해 테이블 스키마 생성

비즈니스 로직 구현

도메인 주도 개발

데이터베이스 접근 로직 구현

데이터베이스 서버가 없는 상태에서 개발 가능데이터베이스 서버 필요함

Page 40: ORM을 활용할 경우의 설계, 개발 과정

객체와 테이블 매핑

객체 속성 추가 및 테이블 칼럼 추가 테이블 설계

테이블로부터 객체 생성비즈니스 로직 구현

테이블 주도 개발

데이터베이스 접근 로직 구현

데이터베이스 서버에 항상 의존관계를 가진다 .

Page 41: ORM을 활용할 경우의 설계, 개발 과정

도메인 주도 개발

데이터베이스에 의존하지 않은 상태에서 개발 가능한 시간이 있기 때문에 구현 – 피드백 사이클이

빠르다 .

빠른 피드백 사이클은 삽질할 수 있는 시간을 확보함으로써 빠른 지식 축적이 가능하다 .

지식 축적은 도메인에 최적화된 설계를 할 수 있도록 한다 .

좋은 설계는 사용자의 요구사항 변화에 빠르게 대응할 수 있다 .

개발자는 소스 코드에 대한 자부심과 여유 시간을 확보할 수 있다 .

Page 42: ORM을 활용할 경우의 설계, 개발 과정

질문 : 지금 내가 일하는 곳은 DBA 의 영향력이 너무 커서 변화를 만들 수 없다 .

어떻게 ??

틈틈이 객체 설계 , ORM 에 대한 공부한다 . 장난감 프로젝트를 하면 더 좋다 .

몇 년이 지나 본인이 프로젝트를 주도할 때 도메인 주도 개발로 진행한다 .

Page 43: ORM을 활용할 경우의 설계, 개발 과정

질문 : ORM 적용하고 싶은데 팀장님이나 선배 개발자가 못하게 해요 .

어떻게 ??

틈틈이 객체 설계 , ORM 에 대한 공부한다 . 장난감 프로젝트를 하면 더 좋다 .

몇 년이 지나 본인이 프로젝트를 주도할 때 도메인 주도 개발로 진행한다 .

Page 44: ORM을 활용할 경우의 설계, 개발 과정

현재 내 영향력 하에서 변화를 만들 수 있는 부분에 집중하자 .

점차 영향력을 확대해 나간다 .

Page 45: ORM을 활용할 경우의 설계, 개발 과정

질문 및 후기

Page 46: ORM을 활용할 경우의 설계, 개발 과정

www.slipp.net

Page 47: ORM을 활용할 경우의 설계, 개발 과정

데모 소스 코드• https://github.com/javajigi/slipping• 이 프로젝트의 slipp-qna 프로젝트• orm_start 부터 orm_step5 브랜치