02. SQL 중심적인 개발의 문제점

김성수·2023년 1월 23일
0
post-thumbnail

⚡ 생각대로 살지 않으면 사는대로 생각한다.
⚡ 나는 어차피 잘 될 놈이다. 이미 잘 되고 있고, 계속해서 잘 되고 있다.


서론(?)

애플리케이션을 개발할 때는 객체지향언어로 개발을 하고, 데이터베이스는 관계형 DB를 많이 사용한다.

지금 시대는 객체를 관계형 DB와 더불어서 관리하는 시대라고 한다.

그런데 객체를 관계형 DB에 저장하려면 SQL을 어엄청나게 작성해야한다.

그런데, SQL 중심적인 개발에는 문제점이 있다.

  • 무한 반복
  • 지루한 코드

하나의 클래스를 통해서 각 필드들을 정의한다.
그리고 SQL문을 작성하여 DB에 저장을 하면서 개발이 끝나갈 무렵, 기획자가 말한다.. "연락처(필드) 좀 추가해주세요~" 라고하면, 각각의 SQL문에 연락처 필드를 추가 내용해야한다. 사람이 하는 작업인지라, 수정이나 작성은 되는데 조회는 안 되는 이상한(?) 상황이 발생할 수도 있다.

하지만, 그럼에도 불구하고 결국 SQL 의존적인 개발을 피하기는 어렵다.

그리고 객체와 DB테이블은 패러다임의 불일치가 발생한다.

객체와 관계형 데이터베이스의 테이블은 비슷한 거 같으면서도 굉장히 다르다.

객체를 영구 보관하는 다양한 저장소가 있다.
RDB, NoSQL, File, OODB(옛날 꺼) 등등..

이 중에서 가장 현실적인 대안은 관계형 데이터베이스(RDB)라고 한다.

그럼, 객체를 관계형 데이터베이스에 저장하려면,
객체의 데이터를 SQL로 바꿔서, RDB에 SQL로 전달해야하는데,
이 일을 과연 누가 하는가..
바로 개발자가 한다.. 이를 통해 봤을 때 곧 개발자 ≒ SQL매퍼..?

여튼.. 이런 부분을 피하기가 어렵다.


객체와 관계형 데이터베이스의 차이

  1. 상속
  2. 연관관계
  3. 데이터 타입
  4. 데이터 식별 방법

1. 상속

객체엔 상속 관계가 있다.(extends)
그런데, DB테이블에는 상속관계란 것이 없다..ㄷㄷ;;
비슷한 게 있긴한데, 객체 상속 관계와 완전히 같지 않다.

그래서 보통 대안으로 관계형 데이터베이스의 {Table 슈퍼타입 서브타입 관계}로 해결한다.

  • 부모 같은 테이블, 자식 같은 테이블을 만들어놓고, 데이터를 분리하여, 필요하면 Join해서 가져오는 식으로 사용한다.

예를 들어 위와 같이 관계도를 설계했을 떄,

  1. Album을 저장할려고 할 때,
    왼쪽의 상속관계도에 따라, 객체를 분해해서 데이터를 테이블에 넣는 SQL을 작성해야하는데,
    데이터를 집어넣을 때, 테이블 두 군데에 데이터를 넣어야한다.
    (ITEM 테이블과, ALBUM테이블)

  2. Album을 조회하려고 할 때(저장보다 더 복잡하다..)

  3. 각각의 테이블에 따른 조인 SQL 작성한다.

  • ITEM + ALBUM 테이블을 조인해야한다.
  • 이 때, 조인 SQL을 작성해야한다.
  1. 각각의 객체를 생성한다.
  • 그 만든 객체에 또 데이터를 집어넣음.
  1. 상상만 해도 복잡쓰하다..;;
  2. 더 이상의 설명은 생략한다. ㅋㅋㅋㅋ
  3. 그래서 DB에 저장할 객체에는 상속 관계를 사용하지 않는다.

(강의 자료 그대로 나와있는 부분들이다.)
위의 1~3을 다 개발자가 한다.
?? 듣다보니 그냥 DBA 만치 하는데..??

But!!

자바 컬렉션에 저장하면?

list.add(album);

자바 컬렉션에서 조회하면?

Album album = list.get(albumId);

부모 타입으로 조회 후 다형성 활용

Item item = list.get(albumId);

이렇게 단 한 두줄로 가능.


2. 연관관계

연관관계

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

그래서 보통 객체를 테이블에 맞추어 모델링하게 되는데,
Member 클래스에 Team클래스가 아니라 Long teamId;라는 TEAM_ID라는 외래키 컬럼명을 사용한다.(아래 사진 참고)

왜냐하면... INSERT INTO MEMBER~~문에 보다 적용하기 수월하기 때문이다. (아래 사진 참고)

반대로 객체다운 모델링을 힌다고 가정했을 때,
객체는 보통 객체끼리 참조를 한다고 표현하는데, 이것 또한 문제다.
객체를 참조하다보니, Team이라는 객체를 참조하려고 했는데, INSERT문에 사용하는 건 TeamId이기 때문이다.(아래 사진 참고)

물론 member.getTeam().getId()를 함으로써 TEAM을 불러올 수 있다.

저장은 이런 방식인데,, 조회는 그냥.. 음.. 그냥..그냥 just is.. um.. 그냥 복잡해서 아래에 자료그림을 던지고, 넘어가보려고한다..

Member 찾아서 Member 데이터 조회하는 SQL을 일일이 작성하고,
Team 찾아서 Team 데이터 조회하는 SQL을 또 일일이 작성하고,
그리고 회원과 팀 관계를 설정을 또 해주며, 요리조리 볶아준다.

그러나.. 객체, 자바 컬렉션에는?

list.add(member);
// member 저장.
Member member = list.get(memberId);
// member를 꺼냄
Team team = member.getTeam();
// member와 연관된 팀을 꺼냄.

또... 단 한 두줄로 가능..

이처럼, DB에서 객체를 관리할 때 번거로운 이유는 객체와 DB간의 패러다임이 불일치하기 때문이다..
서로 연관관계를 바라보는 방법(관점?)이 다르다.

3. 데이터 타입

그리고, 객체는 자유롭게 객체 그래프를 탐색할 수 있어야 한다.
예시) 아래 사진.

그런데 DB에 객체를 저장하다보면 생기는 문제는.. 개발자가 처음에 어떤 SQL을 실행해서 객체를 만들었냐에 따라서, 객체의 탐색 범위가 결정된다.

즉, 처음 실행하는 SQL에 따라 탐색 범위가 결정된다.

예) 멤버와 팀을 조회하는 쿼리를 작성해서, 멤버와 팀을 연관관계 매핑을 한다고 가정했을 때,

member.getTemm();

를 하면 위의 코드는 실행된다.

member.getOrder(); 

이 코드를 확인하면, member안에 order가 있음에도 불구하고, null값이 나온다. 왜냐하면 DB에서 조회를 안 했기 때문이다..즉, 탐색 범위에 들어오지 않은 것...

이렇게 되면 또 문제가 되는 부분이... 엔티티에 대한 신뢰에 문제가 생긴다.
보통 계층형 아키텍쳐를 사용한다고 가정했을 때, 다음 계층을 믿고 쓸 수 있어야 하는데, 값이 들어오는지 안 들어오는지 믿을 수가 없으니...;;; 여튼.. 그렇다.

이런식으로 find로 member를 찾았다고 가정했을 때, 위의 사진과 같이,

member.getTeam();
member.getOrder().getDelivery();

이 코드로 조회를 한다고 가정하고, getter로 불러오는 객체 그래프 탐색을 할 수 있을까? 를 생각했을 때, 개발을 많이 해보신 분들은,

memberDAO.find(Long memberId);

안을 봐야할 거 같다는 생각이 들 것이라고 한다.

결국, Service 로직을 작성하는데, DAO 코드를 열어봐야 알 수 있다고 한다..

그렇다면 데이터가 다 있는 유저는 아래의 객체 그래프 참조를 다 할 수 있을까..?

만약 그렇게 하려면 어마어마한 쿼리가 작성될 것이고, 성능도 별로 나오지 않을 것이다. 왜냐하면 사용되지 않는 데이터도 무조건 다 조인해야되니까..

그렇다고 모든 객체를 미리 로딩할 수는 없다..

상황에 따라 동일한 회원 조회 메서드를 여러 번 생성해야한다..
그런데 상황도 다양하고, 고려할 부분도 상황마다 다양하다..(아래 사진 참고)

이렇게 되면,
계층형 아키텍처라고 하는 진정한 의미의 계층 분할이 어렵다.
영한님은 "물리적으로는 분할되어 있지만, 논리적으로는 엮여있다."라고 표현했다.

4. 데이터 식별 방법

그리고 객체를 조회해서 비교하려고 가정할 때,

DB에서 Id로 새로운 Member 객체를 생성해서, 데이터를 새로 넣어주다보니 다른 객체로 인식한다.(메모리 주소 달라서 당연함.)

하지만, list에서 get하게 되면 정말 똑같은 인스턴스가 나온다.
(역시 당연한 얘기)
이처럼.. 객체답게 모델링 할수록 매핑 작업만 늘어난다...

그렇다면, 객체를 자바 컬렉션에 저장 하듯이 DB에 저장할 수는 없을까?

그 해답은 바로..

JPA

이다..

그래서 다음 강의는 JPA 소개이다..


-끝-

profile
쌩수 Git >> https://github.com/SsangSoo?tab=repositories

0개의 댓글