저번시간에 Photo까지만 만들고 끝이 났는데 이번에는 User를 만들어서 User가 다수의 Photo를 가질 수 있도록 1대다 관계를 만들어보도록 하겠습니다.
type User {
githubLogin: ID!
name: String
avatar: String
postedPhotos: [Photo!]!
}
하는 방법은 간단합니다. User 타입을 만들고 potedPhotos 필드로 Photo목록에 접근하도록 설정만 하면 됩니다.
Photo또한 User와 1대1 관계를 만들어줘서 무방향 그래프 형식이 되도록 해주겠습니다.
type Photo {
id: ID!
url: String!
name: String!
description: String
category: PhotoCategory!
postedBy: User!
}
테스트를 위해 샘플 데이터도 만들어줬습니다.
const users = [
{
githubLogin: 'ckstn0777',
name: 'ckstn'
},
{
githubLogin: 'gildong0878',
name: 'gildong hong'
},
{
githubLogin: 'incheon0897',
name: 'incheon univ'
}
];
const photos = [
{
id: "1",
name: "Test 1",
description: "Test Photo 1",
category: "GRAPHIC",
githubLogin: "ckstn0777",
},
{
id: "2",
name: "Test 2",
description: "Test Photo 2",
category: "SELFIE",
githubLogin: "gildong0878",
},
{
id: "3",
name: "Test 3",
description: "Test Photo 3",
category: "PORTRAIT",
githubLogin: "gildong0878",
},
];
User: {
postedPhotos: (parent) => {
// filter : 조건에 만족하는 모든 요소를 모아 새로운 배열로 반환
return photos.fillter((p) => p.githubLogin === parent.githubLogin);
},
},
Photo: {
url: (parent) => `http://yoursite.com/img/${parent.id}.jpg`,
postedBy: (parent) => {
// find : 조건에 만족하는 첫번째 요소의 값을 반환
return users.find((u) => u.githubLogin === parent.githubLogin);
},
},
parent가 뭔지 아직도 헷갈린다면 저번시간글을 읽어보는 것을 추천합니다. filter와 find는 자바스크립트 배열 내장함수 중에서 기초에 해당하기 때문에 알거라고 생각합니다. (이것도 나중에 정리해야지)
query photos {
allPhotos {
name
url
postedBy {
name
}
}
}
성공적으로 postedBy에서 name이 반환된 것을 볼 수 있습니다.
이번에는 타입연결이 다대다인경우를 해보도록 하겠습니다. 예를 들어, 사진에 사용자를 태그하는 기능을 넣어보려고 합니다. User 한명이 여러 장의 사진에 태그될 수도 있고, Photo 한장에는 여러명의 사용자가 태그될 수도 있습니다.
type Photo {
(생략)
taggedUsers: [User!]!
}
type User {
(생략)
inPhotos: [Photo!]!
}
만드는 방법은 간단하죠?
const tags = [
{ photoID: '1', userID: 'ckstn0777'},
{ photoID: '2', userID: 'gildong0878'},
{ photoID: '2', userID: 'incheon0897'},
{ photoID: '2', userID: 'ckstn0777'},
]
테스트를 위해 샘플 데이터도 생성해줍니다.
User: {
(...생략...)
inPhotos: (parent) => {
return tags
.filter(tag.userID === parent.id)
.map((tag) => tag.photoID)
.map((photoID) => photos.find((p) => p.id === photoID));
},
},
Photo: {
(...생략...)
taggedUsers: (parent) => {
return tags
.filter((tag) => tag.photoID === parent.id)
.map((tag) => tag.userID)
.map((userID) => users.find((u) => u.githubLogin === userID));
},
},
query listPhotos {
allPhotos {
url
taggedUsers {
name
}
}
}
각 사진마다 url과 태그되어있는 사용자 목록이 taggedUsers에 나오는 것을 볼 수 있습니다. 근데 마지막 taggedUsers는 빈배열입니다. [User!]! 를 썼기 때문에 안되는거 아닌가 의아했지만 알고보니 빈배열은 GraphQL에서는 null로 취급하지 않습니다. (저번시간 참고)
여기서 알 수 있는 점은 Tag라는 타입은 만들지 않았다는 것입니다. 다시말해 DB의 데이터 모델과 스키마 타입이 반드시 매칭할 필요는 없다는 소리가 됩니다. User과 Photo타입만을 이용해 충분히 찾을 수 있다면 그렇게 하는게 더 좋은 방법입니다.
참고자료 및 사이트