✔ 홈 커버 Scheme
Completed by 이재철
- Assigned to
-
이재철
- Notes
-
홈 커버의 Scheme 및 Query가 별도로 정의가 필요할 것 같습니다.
현재 앱에서는 listLcInterviews를 기반으로 홈 커버 리스트를 보여주고 있는데,
백엔드에서 별도로 큐레이션 하는 것이 필요해보여서 검토 부탁드립니다.
셀럽과 관련된 컨텐츠는 현재
이렇게 2개가 있는데,
해당 커버사진 4장은 커버에서만 쓰이는거죠?
매거진과는 무관한거죠? (물론 같은 사진이 중복될순 있겠지만)
매거진을 재활용해서 하는것도 가능할것 같은데요,
1. 매거진이 있는 셀럽 중에서 홈에 내보낼 셀럽을 정한다.
2. 해당 매거진 중 보여줄 사진 4장을 정한다.
3. 해당 셀럽이 인터뷰를 가지고 있다면 인터뷰 링크도 1장 넣는다.
어떤가요?
지금 Image 묶음이 Magazine, LcInterview 이렇게 2개 있었는데, 홈 커버까지 만들려니 중복이 너무 심해서, Album이라는걸로 합칠께요.
listAlbums 단일 graphql 로 통합했고, purpose 를 추가했습니다.
홈커버 이미지를 다 표시한 후, 인터뷰가 있는 경우에 한해 마지막 페이지에 인터뷰 링크를 추가하면 될것 같습니다. (피그마에 있는대로 3페이지에 굳이 할 필요가 있나 싶네요)
Album에 Interview 필드가 있고, Interview 안에 Album 필드가 있는, 순환 참조 형태로 표현되어 있는데요, Dart로 표현하게 되면 stack overflow 이슈가 발생합니다.
가능한 type간에 순환 참조는 지양되었으면 하는데, 혹시 Album에서 Interview 필드가 꼭 필요할지 검토 부탁드리겠습니다.
실행 단계에서 발생하나요?
A has B 면
B belongs to A 여서
순환 참조는 피할수가 없습니다.
(binary tree node 등 대부분의 데이터 구조에서 순환참조가 쓰이는데, 아무문제가 없듯이)
혹시 에러 메시지를 복붙해주실수 있나요?
참고로 Stack Overflow는 GraphQL이 아닌, Dart 클래스 내에서 발생하는 이슈입니다.
optional reference 면 그 자체로는 문제가 있다고 생각되지 않아서요.
binary tree node처럼..
순환참조에서 전체가 required reference 인 경우네요... 고쳐서 배포할께요.
User > InterviewConnection > Interview > Album > Interview > Album > Interview ...
curLcInterview, curLcProfile 둘다 optional 로 변경해서 배포 중입니다.
재귀적인 참조를 끊기는 어려울 것 같습니다.
Interview.curLcInterview도 현재 optional로 되어 있으나, 값이 들어가게 되는 순간 순환참조가 발생합니다.
재귀참조 중에 어느 한 군데에서는 확실하게 null로 끊어주던가, 아예 필드를 없애는 것이 안전할 것 같네요.
Image > Album > ImageConnection > Image > Album > ImageConnection...
Image > Message > Image > Message ...
Image 예시도, 쿼리할때 필요한 graph 만큼만 쿼리하면 될것 같습니다.
클라이언트에서 쿼리할 때 순환참조를 끊어주는 부분이 필요할 것 같습니다.
쿼리할 때 필드들이 반복사용 되다보니 모듈화를 했는데, 해당 모듈끼리도 순환참조가 발생하는 것 같네요.
그리고 GraphQL 자체는 닭과 달걀 문제가 발생하는 required reference들로 구성된 순환참조도 만들어지는군요. 주의할께요~
Album > Interview는 홈커버에서 인터뷰를 보여줄 떄 사용되는 값일까요?
홈 커버에서 각 앨범마다 4개의 콘텐츠(interview 포함)를 보여줘야 하는데,
각 앨범의 contents 값이 2개로만 내려오고 있어서요.
의도하신 활용법이 아래와 같은지 문의드립니다:
- 1페이지: Album.cover
- 2페이지: Album.contents[0]
- 3페이지: Album.interview
- 4페이지: Album.contents[1]
contents 가 나머지 장.
일부로 4장을 맞춰 넣진 않았어요. api 에서 내려주는만큼 다 보여지게 해달라고.
interview 는 album.user.interviews[0].curLcInterview 가 존재할때만 해당 cover 를 사용해서 보여주면 될듯 해요. (존재하지 않으면 인터뷰는 제외)
네 우선 홈커버 페이지들은 클라이언트에서 조합하도록 하겠습니다.
추가로, 현재 listNewCelebs, listHotCelebs, listRecentActiveCelebs 쿼리에서 User 노드에 magazines 필드를 추가할 경우 502 에러가 발생하는데요, 혹시 홈커버 업데이트 건과 연관 있을까요?
listNewCelebs
local 에서 하면 성공해서 로그 찾아보니 OOM 이 발생하고 있습니다.
여유 메모리가 500MB 정도 있는데, 쿼리 하나 하다가 500MB 를 다 쓰는 상황입니다.
(ci에서는 1명만 접속하지만, 프로덕션에서는 동시 접속이 일어날것이기 때문에 ci 에서부터 쿼리 최적화를 해둬야 하기 때문에 일부러 작게 잡고, OOM을 일으키는 쿼리를 찾아내는 것입니다.)
---------------------------------------------------------------
<문제>
사용하신 쿼리가 모든 attributes, relationship을 다 로드하고 있는 994줄에 달하는 쿼리던데, 메모리를 늘려서 OOM 해결하더라도 느려서 못 씁니다. 제 mac에서 1.1초가 걸리네요. 서버는 사양이 떨어져서 2~3초 걸릴껍니다.
<문제 원인>
grpahql 로는 다 field 이지만, 3가지로 나뉩니다.
1. attributes : 아시다시피 테이블의 컬럼 (ex. user.chatName)
2. aggregates : 하위 테이블에 대한 통계 (ex. chat.msgCount)
3. relationships : parent 또는 children 관계 (ex. image.user, user.images, user.curLcProfile)
(1,2 는 graphql schema에서 둘다 scala field 여서 구분이 가지 않지만, msgCount 처럼 이름에서 아실수 있으실껍니다)
여기서 1은 템플릿화 하셔서 늘 전체 attributes 를 query해도 성능 영향이 거의 없습니다. 하지만, 2, 3 은 필요없는 경우에는 query하면 안됩니다. 읽어야 하는 테이블 갯수가 계속 늘어나서 메모리와 응답 시간이 늘어나기 때문입니다.
-----------------------------------------------------------------
<제안>
개발 편의성과 성능을 모두 고려했을 때,
1. attributes 는 템플릿화 해서 모든 필드를 쿼리하세요.
2. aggregates 와 relationhips 는 필요할때만 쿼리하세요.
(기존에는 1.5GB 에서 free mem: 500MB, 현재는 3GB에서 free mem: 2GB)
Ash framework 가 합칠수 있는 DB 쿼리는 합치는데, (부모와 자식. user 와 langs)
서로 합칠수 없는 쿼리가 너무 많습니다. (부모의 자식들끼리는 쿼리 합치기가 불가.. langs 와 interviews)
정석대로 필요한 필드만 쿼리해주세요.
첨부하신 쿼리 실행시 메모리가 2GB 정도 사용되네요.
사실 이 부분이 염려가 되어서 이전 미팅 때 모든 필드를 쿼리해도 되는지 문의했었던 건데요, 역시나 성능 이슈가 발생하네요.
참고로 현재 클라이언트에서는 유지보수성을 위해 필드를 템플릿화 해서 사용하고 있고, 각 Schema 마다 required 필드군과 optional 필드군을 구분해서 템플릿화 해놓았습니다.
이렇게 구분한 이유는 이전에 문의드린 '순환 참조' 문제 때문인데요,
말씀 주신 aggregates나 relationships 필드들은 optional 필드로 표현된다고 봐도 될까요?
만약 그렇지 않을 경우 필드 템플릿이 너무 파편화 될 것 같아서 고민 되네요.
예를 들어, chat.msgCount 는 채팅방의 메시지 갯수이기 때문에 0 이상의 정수이지, null 을 가질순 없기 때문에 required 입니다.. 하지만 query 하지 않으면 계산하지도 않고 결과 json 에 포함하지도 않습니다.
우선 aggregates와 relationships 필드들은 별도로 템플릿화해서 필요한 경우에만 넣도록 수정하겠습니다.