Spring SQL 중심적인 개발의 문제점

강정우·2024년 1월 25일
0

JPA

목록 보기
1/12
post-thumbnail

SQL 중심적인 개발의 문제점

우선 우리는 어플리케이션을 개발할 때 보통은 객체지향 언어를 사용한다. 예를들어 JAVA, Scala, Kotlin 등등...
그리고 DB는 보통 관계형 DB를 사용한다. 예를들어 Oracle, MySQL 등등...

그럼 이를 합치면 객체를 관계형 DB에 관리한다는 뜻인데
문제는 관계형 DB는 SQL만 알아들을 수 있다.

이는 개발을 할 때 개발자로 하여금 "sql문 작성 -> sql을 JAVA 객체" 로 혹은 "JAVA 객체를 다시 sql문" 으로 이러한 반복적이고 방대한 양의 코드를 노가다 해야한다.

물론 이때 MyBatis, JDBC template을 사용하면 되지만 결국 sql문은 개발자가 직접 작성해야한다.

사진으로 보면 더 명확한데 만약 JAVA 객체에서 필드값이 추가된다면 각각의 sql문을 다 고치고 있어야한다.
이게 바로 SQL에 의존적인 개발인 것이다.

1. 패러다임의 차이

객체지향 프로그래밍은 추상화, 캡슐화, 정보은닉, 상속, 다형성 등이 이런 시스템의 복잡성을 제어할 수 있는 다양한 장치들을 제공한다.

그럼 어쨌든 JAVA 객체가 관계형 DB를 사용하기 위한 sql문으로 바뀌어서 들어가야한다.
그러기 위해서는 결국 개발자기 이 코드(위 사진에서 "SQL 변환")를 작성해야하는데
여기서 첫번째 문제가 들어난다. 개발자가 SQL Mapper 역할을 하고있는것이다.

2. 객체와 관계형 DB의 차이

1. 상속


RDB에는 상속의 개념이 없다. 그나마 비슷한 슈퍼타입, 서브타입이 존재하지만 부모를 고대로 따오는 상속은 아니다.

그래서 백엔드 어플리케이션에서 "Item을 상속받은 Album 객체"를 DB에 데이터를 입력할 때 Item, Album 테이블에 각각 insert 문을 작성해야한다.

그리고 select문으로 DB에서 백엔드 어플리케이션을 값을 가져올 땐 더 일이다. Item, Album 테이블을 join하여 객체를 생성하고.. 개귀찮다.
그래서 DB에 저장할 객체에는 상속 관계를 안 쓴다.

2. 연관관계

객체는 참조를 사용: member.getTeam()
테이블은 외래 키를 사용: JOIN ON M.TEAM_ID=T.TEAM_ID

그래서 객체를 테이블에 맞춰서 모델링을 많이 한다.

class Member {
	String id;
    Long teamId;
    String username;
}

class Team {
	Long id;
    String name;
}

즉, 백엔드 어플리케이션에서는 사용하지도 않는 필드값을 추가하는 것이다.

하지만 사실 정말 객체지향 다운 코드는 아래와 같다.
또 하지만 이를 구현하려면 중간에 일일이 Team을 idSeq로 변환하는 과정을 거쳐줘야한다. 대충 아래 코드 처럼

SELECT M.*, T.*
FROM MEMBER M
JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
public Member find(String memberId){
	// sql 실행하고
    // DB에서 조회한 회원 관련 정보를 모두 입력
	Member member = new Member();
    // DB에서 조회한 팀 관련 정보를 모두 입력
    Team team = new Team();
    // 회원과 팀 관계 설정
    member.setTeam(team);
    return member;
}

또한 객체는 자유롭게 객체 그래프를 탐색할 수 있어야 한다.
하지만 RDB는 sql에 의해 탐색 범위가 결정되어버린다.

SELECT M.*, T.*
FROM MEMBER M
JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
member.getTeam(); // => OK!
member.getOrder(); // => null

그럼 이게 뭐가 문제냐면 바로 entity 신뢰의 문제가 되어버린다. 코드를 돌려보기 전까지 아니면 해당 find()메서드에 들어가 sql과 DB를 뒤져보기 전까지 해당 값이 null인지 아닌지 알 수 없다는 것이다.

class MemberService {
	...
    public void process(){
    	Member member = memberRepository.find(memberId);
        member.getTeam();
        member.getOrder().getDelivery(); 
    }
}

그렇다고 상황에 따라 동일한 회원 조회 메서드들을 여러개를 생성할 수 없다.

// 멤버 테이블
memberRepository.getMember();
// 멤버 + 팀 테이블
memberRepository.getMemberWithTeam();
// 멤버 + 주문 + 배달 테이블
memberRepository.getMemberWithOrderWithDelivery();
...

미친거지
그래서 이게 무슨말이냐면 계층형 아키텍처는 진정한 의미의 계층 분할이 어렵다는 것이다.

3. 데이터 타입

4. 데이터 식별 방법

profile
智(지)! 德(덕)! 體(체)!

0개의 댓글