🎞 부록
지난 시간에는 엔티티 프레임워크 코어의 데이터 모델링에 대해서 학습하였다. 데이터 모델링은 크게 관례형, 데이터 주석형, 플루언트 API 형이 있다. 어떤 걸 사용해야 하는지는 필요로 하는 기능에 따라 각각의 종류를 알맞게 사용하면 되는 것 까지 알아보았다. 이번 시간에는 일전에 학습하였던 엔티티 프레임 코어의 데이터 관계 모델링에 대해서 알아보는 시간을 가져보도록 한다.
💥 EF Core 데이터 관계 모델링
일전에 배운 것은 '엔티티 프레임워크 데이터 모델링'이였다면, 오늘 배울 것은 엔티티 프레임워크 데이터 관계 모델링'이다. 용어가 비슷하니 헷갈리지 말자. 이번 주제는 데이터 관계를 어떤식으로 모델링을 해서 엔티티 프레임워크에게 넘겨줄까? 이다.
먼저 관계라는 것이 무엇인지 알아보자. 우리가 일전에 웹 서버에서 간단한 테스트를 진행할 때에는 테이블당 하나의 데이터를 물고있었다. 그러나 조금 복잡한 MMO 게임을 만들 경우, 이런저런 데이터가 서로 물려있는 경우가 많아질 것이다. 아래 Book 클래스와, Review 클래스를 보더라도 웹 사이트에서 책 구매시 참조할 수 있는 책과 리뷰의 형태가 서로 얽힌 것을 알 수 있다. 더 나아가 Book 클래스가 Review를 들고 있을 순 있겠지만, Review가 Book 클래스를 들고 있을 순 없다. 따라서 이와 같이 여러 데이터가 서로 연동되어 있는 관계가 종종 생긴다. 이런 것읅 관계의 개념이라고 이해하면 된다.
EF Core의 문서를 살펴보면 여러 단어들이 등장하는데 주로 등장하는 단어들은 위와 같다. 먼저 Primary Key는 DB에서 사용하는 주 키의 개념이 된다. 물론 경우에 따라 고유식별자로도 사용할 수 있다. 예를 들어 ISBN 이라는 함수는 Primary Key는 아니지만 책의 고유 식별번호이기 때문에 대체 키로 사용할 수 있다. 이와 같이 Primary Key (주키)와 Alternate Key (대체 키)를 섞은 것을 Principal Key라고 한다. Principal Key는 외래키가 참조하는 주체가 되는 키이다. Reviews는 ICollection을 사용하기 때문에 Navigation Property가 되며, Review의 BookId는 외래 키가 되어 사용된다.
데이터 관계를 표현하는 방법도 일전에 학습했던 것과 같이 3가지 방법이 있다. 관계를 통해 표현하는 방법에 먼저 알아보도록 하자. 엔티티 클래스는 DbSet으로 연결해 줄 시 실제로 엔티티 프레임워크에 이어 데이터베이스에도 연동이 된다. 관계에서 외래 키를 찾는 방법은 크게 3가지가 있는데 PrincipalKeyName을 이용하는 방법, Class/PrincipalKeyName을 이용하는 방법, 마지막으로 네비게이션 프로퍼티 네임과 PrincipalKeyName을 이용하는 방법이 있다. 각각의 방법은 일전에 학습했던 데이터 모델링과 같은 방법이므로 추가적인 설명은 하지 않는다.
이 후 외래 키를 찾은 다음에는 nullable 여부에 따라 required와 optional의 여부가 갈리게 되는데 이는 nullable에 따라 필요시 삭제 정책에 따라 유용하게 작동한다. 또한 외래 키를 명시적으로 알려주지 않을 경우 Shadow Key 라는 개념으로 EF Core에 이를 넣어준다. Shadow Key는 보통 사용되진 않지만, 일부 함수를 통해 Read/Write를 할 수 있다. 무엇보다 가장 중요한 것은 관계 방식에서는 서로 참조하는 1:1 관계를 나타내지 못하는 것이 가장 중요하다. 이에 따라 주석 방법을 통해 이를 표현해야 한다.
데이터 주석 형을 이용할 때에는 Attribue를 추가해서 해당 키가 외래 키 임을 명시해주는 방법을 사용하면 된다.
플루언트 API를 활용하여서 1:1 대응 관계를 표현하는 방법은 닭이 먼저냐, 알이 먼저냐?가 될 수 있다. 티켓과 Attendee를 살펴보면 티켓을 발급하고 티켓을 구매해 참석하는 형태이므로 Ticket이 Main이고, Attendee가 Sub가 되는 관계가 된다. 이는 1:1 대응이라고는 하지만 외래 키를 양쪽 방향으로 연결할 수 없고 한쪽 방향으로만 연결을 해줄 수 있기 때문이다.
사용자의 성향에 따라 플루언트 API의 외래 키 방향을 달리 설정할 수 있다. Sub로 생각하던 attend를 Ticket에다가 넣어줄 수도 있고, 경우에 따라 Attendee에도 넣을 수 있다. 이 경우 외래 키를 넣는 방향에 따라 HasForeginKey의 함수를 달리 설정하면 된다. 물론 플루언트 API를 통해 1대 多의 관계도 설정할 수 있다. 이 경우 HasOne이 아닌 HasMany, WithOne, HasForeginKey와 같이 복수형(?) 형태의 함수를 사용하면 된다.
예시에서는 ICollection을 사용했지만, 이 말고도 다른 옵션으로도 구현할 수 있다. 다만 가장 간단한 ICollection이 성능이 좋기 때문에 예제에서는 이를 채용해서 사용한 것 뿐이다. 그 외에도 플루언트 Api에서는 delete, required, ContraintName등 다양한 함수가 존재한다. 해당 함수를 모두 외울필요는 없고 필요 할 때 마다 찾아서 사용하면 된다.
다음은 포함 관계이다. 포함 관계는 OrderInfo 클래스와 Address 클래스를 예로 들 수 있는데 딱 보았을 때 비슷한 유형의 데이터 테이블이지만, 서로 하고자 하는 기능이 달라서 네비게이션 프로퍼티가 다른 애를 참조하고 있음을 알 수 있다. 하지만 그럼에도 불구하고 마이그레이션을 진행 할 때 OwnOne 함수를 통해 이를 하나의 테이블에 모든 데이터를 넣어서 처리할 수 있다.
TPH는 결제 기능을 구현했을 때 payment cash와 payment card가 있는 대 이 경우 똑같은 정보를 여러 번 넣을 필요가 없으므로 상속 관계를 통해 하나의 테이블로 넣어 처리하는 개념이다. 그렇다면 왜 두 개로 분리하지 않을까? 테이블이 분리되었을 경우 사용자가 어떤 타입으로 결제했는지 찾아보기 위해서는 카드와 현금 모두 찾아봐야하는 문제가 생긴다. 하지만 테이블이 합쳐져있는 경우에는 이런 번거로움이 줄어들기 때문에 하나로 합쳐서 관리하면 이점이 생긴다.
'공부 > 인프런 - Rookiss' 카테고리의 다른 글
Part 7-1-1. 개론 : OT & 환경설정 (4) | 2024.10.25 |
---|---|
Part 7. MMO 컨텐츠 구현 (Unity + C# 서버 연동 기초) (1) | 2024.10.25 |
Part 6-8-1. 부록 : EF Core 데이터 모델링 (1) | 2024.10.20 |
Part 6-7-5. WebAPI와 REST 서비스 : Unity와 WebApi 연동 (6) | 2024.10.17 |
Part 6-7-4. WebAPI와 REST 서비스 : Blazor와 WebApi 연동 (2) | 2024.10.16 |