자라선

[자바 ORM 표쥰 JPA 프로그래밍] 2일차 - 패러다임의 불일치 본문

Develop/JPA

[자바 ORM 표쥰 JPA 프로그래밍] 2일차 - 패러다임의 불일치

자라선 2021. 3. 10. 01:21

패러다임(paradigm) - 한 시대의 사람들의 견해나 사고를 근본적으로 규정하고 있는 인식의 체계. 또는, 사물에 대한 이론적인 틀이나 체계. 순화어는 `틀'.

 

IT 업계에서 말하는 패러다임은 어플리케이션과 인프라가 나날히 발전하면서 변화하는 것들을 포괄적으로 지징하는데 사용한다.

 

관계형 데이터베이스와 객체지향 프로그래밍은 이 점에서 서로 일치하지 않는 문제점이 발생한다.

일반적으로 객체지향 프로그래밍에서는 은닉성, 상속, 추상화, 다형성 등을 고려하여 개발을 진행하게 된다.

하지만 관계형 데이터베이스는 ACID 라는 특성을 고려하여 설계하여 구성한다.

 

이렇게 서로 다른 방향을 가지고 있기 때문에 패러다임의 불일치라 부르게 된다.

이러한 패러다임 불일치의 예시는 다음과 같다.


1. 객체들의 상속에 따른 INSERT, SELECT 문제

abstract class Weapon {
	long id;
	String Name;
}

class Sword extends Weapon {
	String Type;	
}

class Gun extends Weapon {
	String magazine;
}

데이터베이스 상에서는 Weapon 이라는 슈퍼타입 테이블과 Sword, Gun 이라는 서브타입 테이블이 있고

Weapon 이라는 추상 클래스를 상속받은 Sword와 Gun를 데이터베이스에 INSERT를 하고자할 때 어떻게 할 것인가?

JDBC API를 사용한 일반적인 방법이라면 각각 Weapon INSERT 다음 Sword를 INSERT 하면서 순차적으로 데이터베이스에 올려보낼것 이다.

INSERT INTO WEAPON ...
INSERT INTO SWORD ...

 

하지만 지금은 비록 2~3개 밖에 안되는 테이블과 클래스를 사용하고 있지만 규모가 커질수록 상속받는 클래스와 테이블들이 많아질것 이고 개발자는 서로 매핑시켜주기 위해 일일히 INSERT 쿼리를 짜고 있어야할 것이다.

 

또한 이렇게 INSERT를 하게된 데이터를 어플리케이션에서 조회하고자 할떄 SQL로는 JOIN를 사용하여 불러올 것이다.

SELECT	T1.ID, T1.NAME, T2.TYPE
FROM	WEAPON T1
	JOIN SWORD T2
    	ON T1.ID = T2.ID

JOIN을 하여 데이터를 읽지만 이것을 객체로 담아두기 위해서는 또 Weapon 객체 따로 Sword 객체 따로 구분해서 담아주어야한다.

 

이러한 번거로운 절차가 많아질 수록 비용이 증가하며 개발과 유지보수가 어려워지게 된다.

 

하지만 이것을 JPA로 바꾸게 된다면 아래와 같이 간단하게 바꿀 수 있다.

// weapon를 상속한 sword 인스턴스를 DB에 저장
jpa.persist(sword);

// 100001 의 Weapon id의 값을 DB에서 SELECT 한다.
String id = "100001";
Sword sword = jpa.find(Sword.class, id);

 

2. 객체의 연관관계 문제

관계형 데이터베이스는 서로 테이블의 연관관계를 정의하기 위해 FK 를 사용하여 매핑하게 되는데

이것을 객체에서 진행하고자한다면 필드에 다른 객체의 id 필드를 넣게 되면 얼추 비슷하게 맞춰지게 된다.

class Student {
	long id;
	String name;
	long schoolId;
}

class School {
	long schoolId;
	String name;
}

Student 테이블과 School의 테이블이 서로 FK로 이어져있는것을 객체로 표현했을때 Student에 School의 PK용 필드를 생성하였다.

하지만 이것은 데이터 중심형이라 실제 객체지향 개발에서는 사용될 수가 없다.

 

실제 객체지향 모델링을 하게 된다면 Student의 schoolId를 가지고 또 DB에서 가져와야만한다. 

실질적으로 사용하기 위해서는 Student 객체의 schoolId 라는 FK 전용 필드가 아닌 School의 객체 타입의 필드가 필요하여 처음 SELECT 시 해당 필드에 객체를 넣어주어야한다.

 

class Student {
	long id;
	String name;
	School school;	// School 객체로 변경
}

class School {
	long schoolId;
	String name;
}

 

하지만 결국 이렇게 된다면 SELECT 로 JOIN해서 가져온다 하더라도 내부적으로 Student와 School를 따로따로 구분하여 Student 안에 School를 setter를 통해 넣어주어야한다. 

번거로운 작업이 된다는 것이 보이게된다.

 

이것을 JPA로 변경한다면 다음과 같이 쉽게 바꿀 수 있다.

// 객체를 저장시
student.setSchool(school);	// Student와 School의 연관관계를 설정
jpa.persist(student);		// 두 객체를 저장

// 객체를 조회시
Student student = jpa.find(Student.class, id);
School school = student.getSchool();

 

Comments