알파피플 앱

홈 커버 Scheme

Assigned to
이재철, Backend at Alphapeople 이재철
Notes


홈 커버의 Scheme 및 Query가 별도로 정의가 필요할 것 같습니다.
현재 앱에서는 listLcInterviews를 기반으로 홈 커버 리스트를 보여주고 있는데, 
백엔드에서 별도로 큐레이션 하는 것이 필요해보여서 검토 부탁드립니다.

Comments & Events

이재철, Backend at Alphapeople
조재현, CEO at Alphapeople 조재현  

셀럽과 관련된 컨텐츠는 현재
  1. 매거진
  2. 인터뷰

이렇게 2개가 있는데, 

  1. 홈 커버에 쓰이는 것은 인터뷰가 맞긴 한가요?
  2. 맞다면 인기 인터뷰를 모두 보여주는건가요? 아니면 인터뷰 중에 홈 커버용 인터뷰 리스트를 따로 큐레이션 하는건가요?
조재현, CEO at Alphapeople
총 커버 사진 4장 중 3번째에는 인터뷰 제목이 노출 되는 겁니다~
이재철 moved this card to In progress.
이재철, Backend at Alphapeople
셀럽마다 4장씩 사진이 다 있는건가요?
조재현, CEO at Alphapeople
네 커버에는 반드시 해당 알파피플 마다 총  4장의 사진이 있습니다. 
이재철, Backend at Alphapeople
조재현, CEO at Alphapeople 조재현  

해당 커버사진 4장은 커버에서만 쓰이는거죠?
매거진과는 무관한거죠? (물론 같은 사진이 중복될순 있겠지만)
조재현, CEO at Alphapeople 네 맞아요~
이재철, Backend at Alphapeople
조재현, CEO at Alphapeople 조재현  

매거진을 재활용해서 하는것도 가능할것 같은데요,

1. 매거진이 있는 셀럽 중에서 홈에 내보낼 셀럽을 정한다.
2. 해당 매거진 중 보여줄 사진 4장을 정한다.
3. 해당 셀럽이 인터뷰를 가지고 있다면 인터뷰 링크도 1장 넣는다.

어떤가요?
조재현, CEO at Alphapeople
현재 매거진의 커버 및 매거진 내용 모두 별로로 이미지 제작하여 노출됩니다. 
이재철, Backend at Alphapeople
그럼 커버와 매거진, 인터뷰는 사진이 서로 재활용되기 어렵다는걸로 이해하면 될까요?
이재철, Backend at Alphapeople
일단 서로 독립적이라고 생각하고 진행할께요
조재현, CEO at Alphapeople
네~ 그리고 이 글만으로 이해 안되는 부분들도 있을수 있으니 있다 회의때 다시 체크하여 이야기하도록 해요
이재철, Backend at Alphapeople
김기범, Flutter at Alphapeople 김기범  

지금 Image 묶음이 Magazine, LcInterview 이렇게 2개 있었는데, 홈 커버까지 만들려니 중복이 너무 심해서, Album이라는걸로 합칠께요.
이재철, Backend at Alphapeople

김기범, Flutter at Alphapeople 김기범  

listAlbums 단일 graphql 로 통합했고, purpose 를 추가했습니다.

  • 매거진 (MAGAZINE)
  • 인터뷰 (LC_INTERVIEW)
  • 홈커버 (FEATURED_ALBUM)

홈커버 이미지를 다 표시한 후, 인터뷰가 있는 경우에 한해 마지막 페이지에 인터뷰 링크를 추가하면 될것 같습니다. (피그마에 있는대로 3페이지에 굳이 할 필요가 있나 싶네요)
김기범, Flutter at Alphapeople
이재철, Backend at Alphapeople 이재철

Album에 Interview 필드가 있고, Interview 안에 Album 필드가 있는, 순환 참조 형태로 표현되어 있는데요, Dart로 표현하게 되면 stack overflow 이슈가 발생합니다.

가능한 type간에 순환 참조는 지양되었으면 하는데, 혹시 Album에서 Interview 필드가 꼭 필요할지 검토 부탁드리겠습니다.
이재철, Backend at Alphapeople
스택오버플로우가 컴파일 단계에서 발생하나요?
실행 단계에서 발생하나요?
김기범, Flutter at Alphapeople
런타임 단계에서 발생합니다. 
이재철, Backend at Alphapeople
데이터 구조상 
A has B 면
B belongs to A 여서
순환 참조는 피할수가 없습니다. 
(binary tree node 등 대부분의 데이터 구조에서 순환참조가 쓰이는데, 아무문제가 없듯이)

그리고 지금까지 순환참조가 많았었는데, 지금 처음 발견됐다니 다른 이유가 있지 않을까 싶습니다.

혹시 에러 메시지를 복붙해주실수 있나요? 
김기범, Flutter at Alphapeople
Dart 쪽 에러 메시지 말씀이실까요?
참고로 Stack Overflow는 GraphQL이 아닌, Dart 클래스 내에서 발생하는 이슈입니다.
이재철, Backend at Alphapeople
순환참조에서 전체가 required reference면 컴파일이 안되어야 할것 같고(컴파일러 stack overflow가 생기거나 에러메시지..),
optional reference 면 그 자체로는 문제가 있다고 생각되지 않아서요. 
binary tree node처럼..
이재철, Backend at Alphapeople
혹시 lcInterviews 가 아니라, curLcInterview에서 발생한건가요?
이재철, Backend at Alphapeople
lcInterviews 만 보고 있었는데... curLcInterview 가 required 로 되어 있어서 문제를 일으킨거 같네요.

순환참조에서 전체가 required reference 인 경우네요... 고쳐서 배포할께요.
이재철, Backend at Alphapeople
같은 문제가 curLcProfile에도 있어서 

curLcInterview, curLcProfile 둘다 optional 로 변경해서 배포 중입니다.
김기범, Flutter at Alphapeople
필드를 optional로 만들더라도 실제로 해당 필드에 값이 들어있으면,  
재귀적인 참조를 끊기는 어려울 것 같습니다.

Interview.curLcInterview도 현재 optional로 되어 있으나, 값이 들어가게 되는 순간 순환참조가 발생합니다.

재귀참조 중에 어느 한 군데에서는 확실하게 null로 끊어주던가, 아예 필드를 없애는 것이 안전할 것 같네요.
이재철, Backend at Alphapeople
아, lcInterviews 는 graphql 에 노출하지 않은 필드라 curLcInterview 였겠군요.
김기범, Flutter at Alphapeople
참고로 비슷한 이슈가 Image에서도 존재합니다.

Image > Album > ImageConnection > Image > Album > ImageConnection...

Image > Message > Image > Message ...
이재철, Backend at Alphapeople
graphql 에서 graph 는 DAG 가 아니라서 순환은 허용되고, 그 자체는 문제가 아닐텐데요. 실제로 필요한 경우도 많구요.

Image 예시도, 쿼리할때 필요한 graph 만큼만 쿼리하면 될것 같습니다.
이재철, Backend at Alphapeople
배포 완료 됐습니다~
김기범, Flutter at Alphapeople
넵 감사합니다!
클라이언트에서 쿼리할 때 순환참조를 끊어주는 부분이 필요할 것 같습니다.

쿼리할 때 필드들이 반복사용 되다보니 모듈화를 했는데, 해당 모듈끼리도 순환참조가 발생하는 것 같네요.
이재철, Backend at Alphapeople
네, 왠지 그 이유일것 같았습니다.

그리고 GraphQL 자체는 닭과 달걀 문제가 발생하는 required reference들로 구성된 순환참조도 만들어지는군요. 주의할께요~
김기범, Flutter at Alphapeople
네 도움 주셔서 감사합니다! 👍
김기범, Flutter at Alphapeople
이재철, Backend at Alphapeople 이재철

Album > Interview는 홈커버에서 인터뷰를 보여줄 떄 사용되는 값일까요?

홈 커버에서 각 앨범마다 4개의 콘텐츠(interview 포함)를 보여줘야 하는데,
각 앨범의 contents 값이 2개로만 내려오고 있어서요.

의도하신 활용법이 아래와 같은지 문의드립니다:
- 1페이지: Album.cover
- 2페이지: Album.contents[0]
- 3페이지: Album.interview
- 4페이지: Album.contents[1]
이재철, Backend at Alphapeople
cover 가 첫장
contents 가 나머지 장.

일부로 4장을 맞춰 넣진 않았어요. api 에서 내려주는만큼 다 보여지게 해달라고.

interview 는 album.user.interviews[0].curLcInterview 가 존재할때만 해당 cover 를 사용해서 보여주면 될듯 해요. (존재하지 않으면 인터뷰는 제외)

피그마에서는 3번째 장이 인터뷰던데, 마지막 장에 넣는게 심플할것 같긴 한데, 3번째장이 필수 조건이면 클라에서 조합해야 할듯요 
김기범, Flutter at Alphapeople
이재철, Backend at Alphapeople 이재철  

네 우선 홈커버 페이지들은 클라이언트에서 조합하도록 하겠습니다.

추가로, 현재 listNewCelebs, listHotCelebs, listRecentActiveCelebs 쿼리에서 User 노드에 magazines 필드를 추가할 경우 502 에러가 발생하는데요, 혹시 홈커버 업데이트 건과 연관 있을까요?
김기범, Flutter at Alphapeople
정확히는 아래 링크처럼 User 노드에 모든 필드를 추가한 경우, magazines 필드 유무에 따라 502 에러가 발생합니다.

listNewCelebs
이재철, Backend at Alphapeople
제가 해보니, magazines 를 빼도 502 에러가 발생하더라구요.
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 는 필요할때만 쿼리하세요.
이재철, Backend at Alphapeople
우선 개발 진행이 가능하도록 여유 메모리를 2GB 로 4배 높여둘께요. 나중에 쿼리 정리 꼭 해주셔야 합니다. 서버 비용과 직결됩니다.

(기존에는 1.5GB 에서 free mem: 500MB, 현재는 3GB에서 free mem: 2GB)
이재철, Backend at Alphapeople
3GB 에서도 OOM 나서 8GB 로 올리는 중입니다.
이재철, Backend at Alphapeople
8GB 로 올려서 OOM 은 고쳤으나, 쿼리가 4초가 걸리네요.

Ash framework 가 합칠수 있는 DB 쿼리는 합치는데, (부모와 자식. user 와 langs)
서로 합칠수 없는 쿼리가 너무 많습니다. (부모의 자식들끼리는 쿼리 합치기가 불가.. langs 와 interviews) 

정석대로 필요한 필드만 쿼리해주세요.
김기범, Flutter at Alphapeople
이재철, Backend at Alphapeople 이재철

사실 이 부분이 염려가 되어서 이전 미팅 때 모든 필드를 쿼리해도 되는지 문의했었던 건데요, 역시나 성능 이슈가 발생하네요.

참고로 현재 클라이언트에서는 유지보수성을 위해 필드를 템플릿화 해서 사용하고 있고, 각 Schema 마다 required 필드군optional 필드군을 구분해서 템플릿화 해놓았습니다.

이렇게 구분한 이유는 이전에 문의드린 '순환 참조' 문제 때문인데요,
말씀 주신 aggregatesrelationships 필드들은 optional 필드로 표현된다고 봐도 될까요?

만약 그렇지 않을 경우 필드 템플릿이 너무 파편화 될 것 같아서 고민 되네요.
이재철, Backend at Alphapeople
required field 여도 query 하지 않으면 계산하지 않습니다.

예를 들어, chat.msgCount 는 채팅방의 메시지 갯수이기 때문에 0 이상의 정수이지, null 을 가질순 없기 때문에 required 입니다.. 하지만 query 하지 않으면 계산하지도 않고 결과 json 에 포함하지도 않습니다.
이재철, Backend at Alphapeople
모든 필드를 쿼리해도 되는지 --> 기능적으로 가능한가를 물어보신줄 ㅎㅎ.. 화면에 안 보여줄 필드까지 쿼리해도 성능상 괜찮냐로 생각했다면 답이 달랐을것 같네요. "역시나 성능 이슈가 발생하네요" 라고 생각하실만큼, 필드가 늘어나면 느려지는건 사실 당연한거라...
김기범, Flutter at Alphapeople
결국 필드들을 통일성 있게 쿼리할 수 있는 것이 아니라, 각 API 하나하나 마다 쿼리할 필드군들을 커스텀하게 설계해야 할 것 같은데, 이 경우 유지보수성이 많이 떨어질 것 같네요.

우선 aggregatesrelationships 필드들은 별도로 템플릿화해서 필요한 경우에만 넣도록 수정하겠습니다.
이재철, Backend at Alphapeople 👍
이재철 moved this card to Done.
이재철, Backend at Alphapeople
이재철 completed this card.