writersclub.io 개발기록

8월 초, 새로 출근하려던 회사가 출근일을 몇 주 앞두고 난데없이 경영진들끼리 다투더니 모든 합류 일정이 취소되었습니다. 새로운 도전에 두근거리던 마음은 갈 곳을 잃었지요. 하지만 흔치 않게 자유로운 시간이 주어진 것이기도 합니다. 마음을 가다듬기 위해 방망이를 깎는다는 마음으로 몇년 전 도메인을 사두고서 수년 전부터 퇴근 이후 조금씩 채워가던 코드를 다시 꺼내보았습니다.

그렇게, 9월 24일, writersclub을 공개하게 되었습니다.

writersclub

글에 집중하는 서비스 writersclub

writersclub은 글쓰기에 집중하고 글에 집중하는 서비스입니다. 대화는 관계의 시작이고, 글은 말과 함께 마음을 표현할 수 있는 가장 쉬운 수단입니다. 누구나 글을 쓸 수 있고 누구나 온라인에서 타인을 만날 수 있지만, 우리는 온라인에서 늘 일정한 규칙을 지닌 플랫폼에서만 규칙에 맞게 글을 쓰고 사람을 만납니다. 가끔은 글 이외의 이모티콘을 잘 섞어 쓰는 것이 권장되기도 하고, 예쁜 이미지를 섞을 것이 권장되기도 합니다. 때로는 어떤 리그에 진입하거나 노출 기회를 얻기 위해 유명세나 경력에 대한 평가를 받기도 하고, 때로는 미션에 동참해야하기도 합니다. 늘 모든 글에 댓글이 달리고, 타인의 평가가 달리며, 글을 쓰는 이들도 댓글과 조회수, 인기도를 신경쓰곤 합니다. 그래서 실은, 플랫폼이 글을 결정하고 글쓰는 이의 마음을 휘젓는 것이 디지털 시대의 글쓰기 환경이 되었습니다.

writersclub은 그런 소음들을 거두어 내고, 그저 마음을 담은 글을 쓰고 싶을 때, 쓰는 것 이외에는 아무런 고민도 안해도 되는, 지치지 않고 글을 쓸 수 있는 플랫폼을 목표로 만들었습니다. 그래서 Plain Text, 글을 구조적으로 쓰는 것 이외에는 아무런 추가 기능도 담지 않았습니다. 그림, 사진, 비디오, 링크, 코드, 파일은 올릴 수 없고, 색깔을 지정하거나 페이지 스킨을 꾸미는 기능도 없습니다. 댓글도, 조회수 확인 기능도 없습니다. 흑백의 디자인만 존재합니다. 대신, 중제목, 소제목, 인용구, 구분선, 목록, 굵은 글씨 등 글의 맥락을 강조하는 기능은 지원합니다. 비공개 글을 친구에게만 공유하는 기능도 제공합니다. 긴 글을 쓰는 일은 보통 키보드가 잘 펼쳐질 수 있는 맥북/랩탑/태블릿에서 하는 일이라고 가정했기 때문에, 글쓰기 에디터 역시 모바일 지원을 하지 않습니다. 스펙아웃은 개발자에겐 늘 좋은 일이지만, 실은 모두 이유가 있어 스펙아웃을 한 것이기도 합니다.

CSS only, Text only 디자인

글을 쓰는 화면은 글쓰기에 집중할 수 있어야 하고, 글쓰기 서비스의 콘텐츠는 글에 집중해서 공유되어야 한다고 생각했습니다. 그래서, 디자인 역시 최대한 글에 집중할 수 있는 디자인을 구성해보려 했습니다. 저는 디자이너가 아니어서 제가 할 수 있는 것만 도전해보려 했습니다. 타이포 위주의 디자인을 구성하고, 이미지는 최소화해야겠다고 생각하다가, 더 나아가 이미지를 하나도 안쓰는 디자인에 도전해보기로 했습니다. 사실 스토리지와 트래픽 비용을 줄여 지속 가능한 서비스를 만드는데에도 부합되는 목표였습니다. 그래서 writersclub.은 CSS에 넣은 버튼 SVG와 파비콘, og:image 외에는 실제로도 이미지 리소스가 거의 없는 서비스입니다.

이미지가 없다고 해서 디자인이 없는 것은 아닙니다. 타이포 위주의 디자인만 존재하는 웹서비스는 흔치 않기 때문에 잡지 등 인쇄물 레퍼런스를 주로 참조했습니다. 브랜드 로고에는 일부러 Serif 폰트를 채택했습니다. Sans-serif 로 브랜드를 바꾸는 것이 요즘의 트랜드라지만, 타자기 시절의 느낌을 살려내고 좀 더 인간적인 가치를 드러내는데에는 Serif 폰트가 제격이라고 보았습니다. 이미 한글에 웹폰트를 쓰고 있었기때문에, 로고에도 웹폰트를 쓰지는 않고 싶어서 Georgia 폰트를 활용하기로 했습니다. Georgia 폰트는 MacOS과 Windows 두 OS에서 모두 기본으로 제공하는 Serif 폰트라 별도의 로딩이나 설치가 필요하지 않았습니다.

개별 콘텐츠를 읽을 때 글에 집중할 수 있도록 writersclub. 이라는 로고 대신 쓸 수 있는 축약형 브랜드를 w. 형태로 구성했습니다. 한국어와 영어 글에는 늘 마침표가 붙기 때문에 마침표(.)를 중요한 메타포로 사용하였고, 마우스 hover에서는 이를 살짝 움직여 writersclub. 정식 로고와 크게 이질적이지 않도록 했습니다.

편안한 글쓰기, 그리고 글 읽기 경험을 위해 다크모드와 세피아모드를 추가하였습니다. 미디어 콘텐츠 서비스를 만들어보았던 경험에 비추어볼 때, 잠들기 직전의 콘텐츠 소비량은 업무시간을 훨씬 능가하기 때문에 눈을 편안하게 하는 색상이 중요하다고 보았습니다. 읽는 사람 뿐만 아니라 글을 쓰는 사람에게도 눈은 늘 중요합니다. 그래서 눈에 편안한 화면은 꼭 챙기고 싶었습니다. 물론 CSS 일이 세배가 되기 때문에, 다른 색상구성은 블랙/그레이로만 최소화했습니다.

칼라칩을 고르는 것 역시 저의 역량 밖의 일이었지만, 다크모드와 세피아톤 읽기 모드는 다양한 브라우저에서 기본적으로 제공하기 때문에 이들 환경을 참고하여 맞추었습니다. 어느정도 흉내를 내긴 했지만 여전히 칙칙해보인다는 의견도 있었습니다. 주변 디자이너의 도움을 구해볼까 하는데, 언젠가는 기회가 있지 않을까 합니다.

언어와 프레임워크 고르기

수년 전 여러 웹/앱 서비스를 한꺼번에 운영한 적이 있었습니다. 뉴스 모니터링 사이트부터 공연정보 사이트에 이어 커뮤니티 사이트까지, 다양한 서비스를 만들고 운영했습니다. 처음 서비스를 만들 때는 즐거웠지만, 시간이 지날수록 관리도 버겨워지고, 운영 이슈도 많아지고, 기술 스택도 금방 낡아지고, 일상의 짐만 늘어난다는 느낌이 들곤 했습니다. 회사 업무로 만드는 서비스에서 기술부채를 신경쓰듯, 취미로 만드는 서비스도 일상의 부채가 생길 수 밖에 없었습니다.

그래서 다시 취미로 웹서비스를 만든다면 생업이나 일상에 영향이 없을 수준으로만, 가벼운, 기술적인 도전은 가끔 생겨나는 서비스를 만들고 싶었습니다. 글쓰기 서비스는 그에 적당한 수준이라 생각했고, 기술 스택 역시 같은 기준으로 골랐습니다.

  • 웹프레임워크는 TypeScript/SvelteKit 으로 만들었습니다. 전 직장에서 잠시 써보면서 Svelte의 설계 철학이 마음에 들었습니다. 한 코드에서 스타일과 로직 코드를 한꺼번에 다룰 수 있다는 점도 좋았고, SvelteKit은 SSR에 Static Page 굽기에 Prerendering까지 알아서 해준다는 점도 끌렸습니다.
  • 서버 프레임워크는 Python/Django 로 만들었습니다. Strapi 같은 CMS/DB SaaS도 이제 많아졌고 Amazon Cognito 가 알아서 로그인을 구현해주는 시대이지만, 그래도 개발 수고가 크지 않을거라 직접 만들어보고 싶었습니다. 프론트엔드는 TypeScript를 쓸테니 서버는 다른 언어를 써보고 싶었습니다. API와 인증처리만 구성하면 되기 때문에 생산성 높은 웹서버 프레임워크로 간단히 만들어보기로 했습니다.
  • API는 GraphQL로 짰습니다. 직전 회사에서 전면 도입을 해보고 싶었지만 이래 저래 미루다 기회를 놓쳤던 것이 아쉬워 개밥먹기 차원에서 다시 도전해보고 싶어 골랐습니다. 서버는 Graphene을 썼고, 클라이언트는 Apollo 를 쓰다 urql로 바꾸었습니다.
  • 위지윅에디터만큼은 VanillaJS로 만들었습니다. 다양한 오픈소스 에디터가 있긴 하지만, 가볍게 만들기 위해, CJK 언어 문제(중국어-일본어-한국어 문제)를 직접 다루기 위해, 그리고 앞으로 마주하게 될 다양한 문제들을 직접 해결하기 위해 처음부터 직접 설계했습니다. 첫 직장에서도 위지윅에디터로 고생하는 서비스를 만드는 팀에서 일하더니, 요즘에도 똑같은 에디터를 만들게 될 줄은 몰랐습니다. 앞으로도 취미로 퇴근 후 코드를 짜는데에는 에디터쪽 일이 많을거라 생각합니다.
  • UI프레임워크는 TailwindCSS 로 얼개를 잡다가, 타이포 위주의 디자인을 직접 짜고자 모두 다 거두어내고 그냥 CSS로 직접 짰습니다.
  • 소셜 로그인은 Twitter와 Google만 붙였습니다. 아이디/비밀번호 기반의 자체 로그인을 구현하지 않기 위해서였고, 특정 국가에 의존하지 않기 위해 두 플랫폼을 골랐습니다.
  • DB는 오래전부터 EC2에 자체적으로 구성한 MariaDB에 그냥 넣었습니다. RDS나 서버리스 데이터베이스는 관리하기에 편하기는 하지만, 수익이 나지 않는 개인프로젝트에서 쓰기엔 비용이 살짝 아까웠고, MySQL/MariaDB 정도는 docker 한줄로도 구축이 가능한 점을 고려했습니다.
  • 배포도 옛날식입니다. GitHub Action에서 ECS를 거쳐 Fargate로 올리거나 Vercel 등을 쓸 수도 있겠지만 그냥 AWS EC2 인스턴스에 올렸습니다. 제일 저렴하기 때문입니다. nginx를 씌우고 upstream을 교체하는 식으로 무중단 배포를 구성하고, rsync로 코드를 보내고, docker container를 재가동하기만 하면 됩니다. 서버 배포는 10초, 웹 배포는 30초 걸립니다. 평소에 돌리고 있던 인스턴스가 있는데 그냥 같이 쓰면 되지..라고 생각했습니다.

향후 계획

수년 전, 제가 만들어왔던 모든 서비스를 종료시킨 일이 있었습니다. 코파운더였던 회사의 서비스를 만드는 데에 저의 에너지를 모두 집중해야한다는 요구도 고려했지만, 각 서비스의 존재 이유도 조금씩 사라질 즈음이기도 했습니다. 그래서 새로운 서비스를 취미로 다시 만드는데에는 많은 망설임이 있었습니다. 회사 업무 외 다른 서비스를 만들거나 외부 스터디/커뮤니티 활동을 하는 것을 꺼려하는 회사들이 요즘 훨씬 많아졌다는 점도 신경쓰지 않을 수 없었습니다. 그래서, 다시 새로운 서비스를 취미로 만들때는 그 서비스의 끝을 먼저 상상하곤 했습니다. 존재의 이유가 스스로를 납득시킬 수 없다면 시작부터 하지 않으려 했습니다. 가벼운 글쓰기 서비스가 필요하다는데에는 특별히 다른 반론이 떠오르지 않았습니다. 저 역시도 글을 쓰고 읽는 것을 좋아하니까요.

writersclub은 본질적으로 글에 집중하는 서비스이고, 이미 다양한 도구를 가진 이들이 아닌, 그동안 도구를 갖지 못했거나 그동안의 도구를 꺼려했던 이들이 가벼운 마음으로 접근할 수 있는 도구이기를 바랬습니다. 기업이 만드는 플랫폼은 늘 존재의 이유를 증명해내야하고, 지표상의 J커브 성장을 위해 게이미피케이션을 도입해 경쟁을 유도하거나, 상호 피드백으로 자극을 주는 환경을 만드는 쪽으로 흘러가기 마련이었습니다. 이 서비스는 저와, 글쓰기를 좋아하는 제 주변 동료들이 함께 취미로 만들 서비스이기 때문에 성장을 쫓지는 않아도 될 것입니다. 그리고, 그런 글쓰기 플랫폼도 하나쯤 있었으면 했습니다.

저의 일상 속에서 가끔 시간을 내어 가꿀 수준의 서비스를 하나쯤 가꾸고 싶다는 마음으로 시작했으니, 앞으로도 그 정도 수준에서만 돌볼 생각입니다. 그래서 기능 개선은 매우 더딜 것입니다. 반영이 조금 느려도 그 역시 그러려니 해주시면 더욱 감사하겠습니다. 그래도 다양한 관심과 제안은 언제나 감사하게 귀기울이겠습니다.