티스토리 뷰

728x90

두 번째 주제

매주 진행하는 백엔드 스터디 시간이 돌아왔다. 이번 주제는 DataBase 모델링에 대해 알아보는 시간이다!

이번 주 질문은 2가지로 지난 주에 비하면 절반이다. 이번 주는 특별히 지난번 무쓸모톤에서 만들었던 장고 모델을 직접 mySQL을 통해 제작해보는 실습이 있다.

 

공부에 앞서 일단 생각을 해보자, 모델링이란 무엇일까?

Django에서 우리가 썼던 데이터베이스 이름이 모델이라고 불렸는데 아마 데이터베이스를 구축하는 과정을 모델링이라고 부르는 것일까? 그래서 지난주에 배웠던 관계 데이터베이스 방식이나 NoSQL 방식 중 선택해서 하는 방식인가?

혼자 골똘히 생각해보았으니 그럼 이제 데이터베이스 모델링에 대해 알아보자.

728x90

질문1 : Data Modeling이란 무엇일까요?

우선 모델링이란 무엇일까?

주변에 있는 사물이나 사람, 개념 등 다양한 현상을 일정한 표기법에 따라 표현하는 것을 의미한다. 그래서 누구나 그 표기법만 이해할 수 있으면 단순하고 명확하게 표현된 것을 통해서 쉽게 이해할 수 있다.

그럼 데이터 모델링은 무엇일까?

 

데이터 모델링은 우리가 쓰고 있는 현실 세계의 데이터들을 데이터베이스로 표현하기 위해서 추상화를 하는 과정이다. 이 과정은 크게 3가지의 특징을 가지고 있는데 바로 추상화, 단순화, 명확성이다.

 

이 과정을 거치게 되면 현실 세계의 데이터들을 데이터 베이스에 넣어서 손 쉽게 열람하고 생성하고 삭제, 편집 할 수 있다. 

 

데이터 모델링은 막무가내로 현실 세계의 데이터를 조작해서 데이터베이스를 구축하는 것이 아니다. 다음에서 보여주는 단계별로 모델링을 진행해야 고객의 업무를 손 쉽게 해줄 수 있는 데이터베이스를 만들 수 있다.

 

이렇게 3가지로 나눠있는데 예시를 통해서 이해해보자.

 

나는 이제 갓 개원한 병원의 주문을 받아 데이터베이스를 만들어야한다. 그럼 가장 먼저 생각해야할 것이 무엇일까? 바로 병원에서 쓰이는 데이터의 중요도 분류, 데이터의 지속성 그리고 병원 측에서는 이러한 데이터를 어떻게 사용하려는지를 파악해야한다. 가장 추상적으로 생각할 부분이며 쉽게 말해 큰 틀을 잡는다고 생각하면 편하다.

이렇게 개념적 모델링을 마치고 논리적 모델링으로 들어가야한다. 우리가 파악한 데이터들과 병원 측에서 데이터를 어떻게 사용하는지를 파악한 후 데이터들을 서로 연관지어서 관계를 통해 분류한다. 만약 환자 데이테를 구체적인 예시로 보면 환자 데이터에는 어떠한 내용이 있으며 환자 데이터는 서로 어떻게 분류하는지, 어떤 데이터로 이루어져있는지를 작성한다.

마지막으로 물리적 모델링을 해야한다. 물리적 모델링은 실제로 내가 만든 서버(예를 들면 A동 301호 서버 관리실)에 데이터를 저장하는 과정이다. 앞서 두 가지 과정을 거친 데이터들을 실제로 보관하고 만약 데이터들끼리 오류가 나면 어떻게 해결하는지, 이런 데이터는 어떻게 접근해야하는지 규칙을 정해야한다.

 

실제 데이터베이스를 만드는 과정은 다르겠지만 학교에서 공부를 했을 때 이렇게 이해했을 때 훨씬 받아들이기 쉬웠다.

 

그럼 이제 모델링에 대해 다 알아봤으니 질문에 답을 하자면!

 

데이터 모델링은 주변에서 사용하는 데이터들을 누구나 쉽게 알아볼 수 있도록 일정한 규칙에 맞게 재구성하는 과정이라고 생각한다.

 

질문2 : RDB와 NoSQL의 모델링 방법 차이를 설명해주세요.

우리가 앞서 알아본 모델링은 데이터를 이용해서 일정한 규칙에 맞게 재구성하는 과정이었는데 이전 포스팅에 보면 RDB와 NoSQL에 대한 차이점을 보여준 적이 있다. 모델링은 기존에 있던 데이터를 이용하는 방식으로 RDB와 NoSQL이 같은 방식의 모델링으로 표현될 수 없다는 것을 이제 슬슬 눈치챌 것이다. 과연 모델링의 방법에서는 어떤 차이가 있을까?

 

RDB의 모델링

RDB를 모델링은 위와 같은 방법으로 진행된다.

 

1. 업무 파악

- : 이 데이터들이 어디에 쓰이는가 / 사용자는 어떠한 요구사항이 있는가

2. 개념적 데이터 모델링

 : 만들고자 하는 데이터들은 어떤 개념들이 있고 이러한 개념들은 서로 어떠한 관계를 가지고 있는가 / 그리고 어떠한 상호작용을 하는가 

 - 이 때 ERD 다이어그램을 통해 식별자로 전체적인 데이터들의 관계와 개념을 짚고 넘어간다.

3. 논리적 데이터 모델링

 : 이전에 만들어둔 ERD 다이어그램을 구체화하면서 관계형 데이터베이스에 맞게 구체화 및 정규화 진행

4. 물리적 데이터 모델링

 : 데이터가 저장될 공간을 효율적으로 배치 / 응답시간을 최소화

 

 

NoSQL의 모델링

NoSQL의 모델링은 RDB와 다르게 관계로 이뤄진 데이터들이 아니고 매우 단순한 쿼리만을 지원하기 때문에 데이터를 조작하기 위해선 어떠한 쿼리문이 필요한지 파악한 다음, 그러한 쿼리문을 통해 결과를 얻을 수 있도록 테이블을 만들어야한다.

 

말로만은 어려우니 그림을 통해 살펴보자!

 

 

다음 그림은 모델링을 마친 RDB이다.

한 테이블 안에 거의 모든 데이터가 들어가있는 상태이다. 게다가 적혀있진 않지만 아마 기본키나 외래키 등 식별자를 통해서 다른 테이블과의 관계를 표현하고 있을 것이다.

 

다음 그림은 모델링을 마친 NoSQL이다.

 

RDB와 다르게 Key 가 2개인 것도 있고 Key에 따라 나오는 데이터들도 다르다. 마치 우리가 RDB에서 쿼리문을 실행시켰을 때 나오는 결과물이 나온 것 같다. 바로 이 점이 RDB와 NoSQL의 차이점이다.

 

RDB는 데이터간의 관계를 정의하고 정규화를 통해 중복되는 데이터를 제거하는 모델링을 하지만

NoSQL은 데이터간의 관계가 없어 쿼리문을 실행시켰을 때 원하는 데이터가 나오게끔 비정규화를 통해 모델링을 한다.

 

 

[추가 실습] 무쓸모톤에서 설계한 Database 스키마를 만들고 CRUD를 해보세요!

우선 무쓸모톤에서 만든 Database를 보자.

class Item(models.Model):
    title = models.CharField(max_length=50, default='')
    author = models.ForeignKey('account.User', on_delete=models.CASCADE)
    pub_date = models.DateTimeField()
    body = models.TextField(default='')
    image = models.ImageField( blank=True, null=True)
    value = models.IntegerField(default=0)
    clickCount = models.IntegerField(default=0)

class Comment(models.Model):
    content = models.TextField(default='')
    writer = models.CharField(max_length=50, default='')
    itemForeign = models.ForeignKey(Item, on_delete=models.CASCADE, null=True)
    
class User(AbstractUser):
    nickname = models.CharField(max_length=30, default='')
    profileImg = models.ImageField(upload_to="account/", blank=True, null=True)

우리는 이렇게 크게 3가지 클래스를 만들었는데 맨 아래는 따로 account라는 앱 속에 만든 모델이다.

그럼 CRUD를 하기 위해선 먼저 이 3가지 클래스를 통해 3개의 테이블을 만들어야한다. 여기서 테이블을 만들 때 주의할 점은 상속받는 테이블을 먼저 생성해야한다는 뜻이다. 매우매우 당연한 개념이지만 옛날에 헤메이던 기억이 났다.

여기 보면 Item 클래스에서 author 항목은 User에서 외래키를 통해 참조하고 있는데 User를 먼저 생성하지 않으면 Item의 author를 생성할 수 없다.

 

user 테이블을 만들었다. 물론 원래 user 모델에는 이름, 나이 등등 여러가지가 있었지만 코드에 보이는 내용만 우선적으로 넣었다.

다른 테이블에 참조하기 위해서 lion이라는 nickname을 가진 사람의 프로필을 넣어보았다.

실수로 2개가 들어갔다 ㅎㅎ...

이미지를 넣어줘야했기 때문에 구글링으로 데이터베이스에 대한 이미지를 아무거나 넣어줬다.

이제 Item 테이블을 만들기 위해 외래키로 참조를 하려고 했는데 오류가 떴다.

 

외래키로 참조하려는 것(nickname)이 유일하지 않다는 얘기라고 한다.

그래서 참조하는 nickname를 기본키로 지정하기 위해 alter문을 사용하게되었다. alter문은 update문과는 다르게 속성에 대한 제약을 변경하는 기능을 가졌다. 나는 속성에 대한 제약을 변경해야하기 때문에 alter문을 사용했다.

이렇게 기본키 지정을 하고 다시 Item 테이블을 만들었다.

 

마지막으로 Comment 테이블까지 완료했다.

 

이제 User 모델에 lion이라는 사람이 있으니 lion이 올린 아이템을 DB에 올려보겠다. 지난 포스팅을 보면 데이터를 삽입할 때는 INSERT를 쓴다고 설명했다.

주의할 점은 insert문을 작성할 때 내가 외래키로 지정한 속성의 값이 삽입하는 속성의 값과 같아야한다. 내가 삽입하는 속성의 값이 테이블의 값 중에서 없다면 참조 무결성에 어긋나기 때문에 실행이 되지 않는다.

 

마지막으로 comment에도 똑같이 삽입해줬다.

 

이제 update문을 실행해보자.

comment에서 '제발 가져가주세요 ㅎㅎ' 보다는 '애착이 많이가서 가치가 궁금합니다' 가 더욱 감정에 호소하는 느낌이나서 가치를 좋게 평가해줄 것 같다. 얼른 고쳐보자.

이렇게 update문을 살펴보았다. 남은건 삭제인데 데이터베이스에서는 삭제가 두 종류이다. 데이터만 삭제하거나 테이블을 삭제하거나. 우리는 두 가지 모두 해볼 것이다.

 

지난 포스팅에 나왔던 delete문은 데이터만 삭제하는 쿼리문이다. comment에 내용을 더 추가하고 하나만 삭제해보겠다.

 

이렇게 2개 중 lion의 댓글만 삭제해보겠다.
야무지게 삭제되었다.

그러면 테이블을 삭제하기 위해서는 어떻게 할까?

DROP이라는 쿼리문을 사용한다. 주의할 점은 다른 친절한 시스템처럼 '삭제하시겠습니까?' 라던가 '휴지통에 보관되었습니다' 라는 문구가 뜨지 않고 바로 삭제되니 정말정말 조심히 해야한다... 어떻게 알았는지는 상상에 맡긴다..

이렇게 drop 문을 사용하게 되면 select 문으로 조회할 수 없다는 오류를 받게 된다. 이렇게 되면 정상적으로 삭제된 것이다!

 

삭제할 때 주의할 점이 있는데 이렇게 관계를 맺은 테이블 간에서 참조하는 테이블을 삭제하면 문제가 생긴다.

예로 들면, 현재 comment 테이블은 Item 테이블의 item_id를 참조하고 있는데  comment가 달린 item_id를 삭제하거나 아니면 테이블 자체를 삭제하면 어떻게 될까?

 

아까 우리가 create문을 쓸 때 마지막에 써준 문장이 혹시 기억나는가?

바로 마지막 줄 문장!!

on delete cascade라는 문장이 있는데 이는 만약 item_id가 삭제되거나 테이블이 삭제될 시 그 item_id를 가지고 있는 튜플은 연쇄 삭제된다는 뜻이다. 연쇄 삭제(CASCADE) 뿐만아니라 SET NULL(삭제 시 null로 바꿈), NO ACTION(기본값으로, 어떠한 동작도 취하지 않는다) 등이 있다. 

이렇게 외래키를 지정할 때 옵션에 따라 우리가 원하는 삭제 방법을 선택할 수 있다.

 

실습 끝!!!

 

 

2주차를 마치며..

이렇게 2주차를 마쳤다. 다시 책을 펴서 공부하기도 하고 그때는 아예 몰랐었던 자바에서 mySQL 응용하기 등 여러 챕터를 다시 보게 되니 얼핏 알 것 같기도 하다. 하지만 개념 부분을 공부하면서 아직까지 아리까리 한 부분들이 많아서 열심히 해야겠다라는 생각이 들었다.

728x90
300x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크