무심코 쓴 솔루션에 메인테이너가 이모지 눌러주고간 썰
작년에 회사에서 프로젝트를 새로 배정 받으면서 Prisma라는 orm을 새로 쓰게 되었어요.
보시다시피, 차세대 typescript-Nodejs ORM이라는 정체성을 가진 아이입니다. 쿼리 빌더의 형태로 꽤나 직관적으로 DB 데이터를 가져올 수 있는 인터페이스를 제공하더군요.
또한 이미 만들어진 DB를 보고 자동으로 prisma에서 사용할 수 있도록 스키마를 만들어주는 추출해주는 기능도 꽤 쏠쏠했습니다. 그리고 이 기능이 구 서버를 새로 마이그레이션해야했던 저희의 서비스에게는 꽤 매력적이었(다고 추측하고 있🙄)어요.
개인적으로 원하는 기능을 지원하지 않는 경우가 종종 있었습니다.
예를들어 count 쿼리를 날릴 때 distinct로 중복을 없애고 싶었는데... 안되더라구요...?(그리고 다른 사람들도 답답했는지 이슈 제기함ㅎhttps://github.com/prisma/prisma/issues/4228)
이러한 점들 때문에 공식문서에 명시되어있는 것 이외의 것을 해보려고 하면 "과연 이걸 지원할까...?"라는 스트레스가 있었습니다.
ps. 그래서 그런지 prisma가 raw 쿼리를 잘 지원하긴 해요(아마 본인들이 제공하지 않는 부분들은 직접 쿼리를 날리라는 뜻이겠죠?),
근데 raw 쿼리를 적극 사용할거면 ORM을 쓰는 이유가 퇴색되지 않을까?라는 개인적인 의견이에요.
가장 치명적인 이슈였던 것은 prisma가 "0000-00-00 00:00:00" 형식의 DateTime을 지원하지 않는다는 것이었어요. 해당 값이 쿼리 결과에 포함이 되면 그 행 조회가 되지 않는것이 아니라 예외가 터지면서 쿼리 결과를 모두 확인할 수 없었습니다.
저는 2017년에 출시된 Mysql5.7 버전의 DB를 쓰고 있었어요. 그때에는 "0000-00-00 00:00:00"과 같은 형식의 DateTime도 퍽 잘 사용했었나봐요. 그래서 저 문제가 아주 자주 터졌답니다.
이에대한 해결책으로 NO_ZERO_DATE이라는 옵션을 DB에 global로도 설정해보고 url파라미터도로 전달해보았는데, DB에 연결할때 prisma에서 내부적인 커넥션을 새로 생성하는지 잘 동작이 되지 않았습니다.
사용하는 Mysql 버전을 호환시키기 위한 옵션 마저 prisma에서는 제공하지 않아서...
다른 대책이 필요했습니다...!
근본적으로 문제를 접근해 보았습니다. 불러오는 데이터가 문제라면은 그 데이터를 안가져오면 되는게 아닌가 싶었습니다.
"0000-00-00 00:00:00"이라는 형식이 문제면 해당 값을 null로 바꿔서 가져오면 어떨까라는 접근을 해보았습니다. 팀장님과의 논의 끝에 generated column을 도입하는 방안을 고안했어요.
사실 읽어오지 못하는 값을 null로 UPDATE 한다면 문제가 해결되긴해요. 하지만 Production DB에 대규모로 업데이트를 하는 행위는 굉장히 리스크가 있다고 판단했습니다. 그래서 최대한 기존 칼럼을 안건드리는 방향으로 가닥을 정했어요.
generated column이란 말 그대로 임의로 생성된 컬럼을 말합니다. 존재하는 값으로부터 새로운 칼럼을 만들 수 있습니다. 엑셀에서 함수가 적용된 열이라고 생각하면 편할것 같아요.
generated colum에는 VIRTUAL 타입과 STORED 타입이 있습니다. VIRTUAL 타입을 사용할 경우, 기존 칼럼에 영향도 주지 않고 원하는 데이터를 읽어올 수 있을 뿐만 아니라, 가상으로 존재하는 칼럼이라 실제 DB에는 별다른 영향을 줄 수 있어요.
저는 이 기능을 사용해서 데이터를 똑같이 갖되, 문제가 되는 데이터("0000-00-00 00:00:00" 형식의 날짜 데이터) 인 경우 null을 갖도록 하는 가상 칼럼을 만들었어요.
그리고 문제가 되는 칼럼 대신에 새로 만든 가상 칼럼을 읽어 오는 방식으로 문제를 해결했습니다👏
사실 이 문제는 prisma에서 꽤나 유서 깊은 이슈였어요. 2019년에 처음 이슈가 등록된 이후로 여태까지 많은 사람들이 고통 받고 있었습니다.
사람들이 내놓은 해결책은 대부분 "0000-00-00 00:00:00인 데이터를 null로 업데이트 해라.", "raw query를 사용해라" 였어요. 근데 이러한 방법들은 전부 리스크가 있고, orm을 사용하는 의미가 퇴색되는 해결방법이라 좋아 보이지 않았어요.
이러한 방법들보다 제가 사용한 방법이 DB 데이터를 건드리지 않아 안전하고, orm도 온전히 쓸 수 있는 최선의 방법이라고 생각했어요.
그래서 처음으로 한번 github 커뮤니티에 공유해보기로 했습니다...!
아래는 제가 실제로 prisma github에 올린 코맨트입니다.
없는 영어 실력 긁어와서 솔루션을 작성해올려보았답니다 헤헤
https://github.com/prisma/prisma/issues/5006#issuecomment-1224036491
이모지도 남았어요.
적어도 5명의 사람에겐 도움이 되었다는거겠지...?ㅎ
사실 글을 올린지는 꽤 됐어요. (작년 8월쯤 올렸었나?🤔)
올려놨던 글의 근황이 궁금하여 최근에 다시 들어가봤는데 뭔가 기시감을 느꼈습니다.
이 분 이름을 어디서 봤는데 어디서 봤냐면은
prisma 메인테이너신데요...?
그래도 꽤 투자 많이 받고 유명한 오픈소스인데... 그런곳의 메인테이너가 내 댓글 보고 이모지 달아줬다고 생각하니까... 뭔가 신기하고... 얼떨떨하고... 막그럼...😵💫 💫
첫 github 커뮤니티 활동이었는데, 그냥 지나가는 댓글 하나 달았다고 생각했는데, 첫 시도에 메인테이너가 반응해준거면 꽤나 좋은 스타트가 아닐까??
맘만 먹으면 github 같은 개발자 커뮤니티에서 활동하는것도 생각보다 할만 할것 같다는 자신감을 얻은 경험이었습니다.
오픈소스에 컨트리뷰션을 해보는 것이 제 목표 중 하나에요. 목표긴한데 여태 엄두도 못 낸채 막연한 꿈으로 방치두었어요. 오픈소스는 감히 넘볼 수 없다는 위압감이 있었는데, 이번 경험을 통해 그런게 많이 사라진 것 같습니다.
그래요 뭐 오픈 소스도 사람이 만든건데 뭐 다 완벽하겠슴까 그 사람들도 사람이겠지요 뭐
다음에 한놈 잘 못 걸리면 바로 PR날린다 는 마인드로 살아보려구요. 헿
다른 이슈 중에 generated column을 지원해달라는 이슈가 있었나봄. 그래서 "다른 사람들은 이케 쓰드라~@" 라는 식으로 내 글도 다른 이슈에서 인용해줌ㄷㄷ 😳
나... 뭐...돼..?
https://github.com/prisma/prisma/issues/6336#issuecomment-1492429927