이 블로그는 구글 애드 센스 설치를 계획하고 만들어졌다. 그러나 연이은 신청 거절에 블로그 컨텐츠를 손봐야 겠다는 생각을 했고 겸사겸사 디자인까지 새롭게 개편했다. 이 글은 디자인 개편 과정에서 배운점과 느낀점들을 기록하기 위해 써본다.
벨벳카푸치노의 이름을 걸고 만든 앱들이 몇 가지 있다. 플래너, 방문 장소 기록 앱, 품앗이 플랫폼. 앞으로도 계속 생겨날텐데, 플래너와 방문 장소 기록 앱을 만들 때 까지만 해도 정해진 디자인 컨셉이 딱히 없었다.
파워 P 답게 그때그때 앱 느낌에 따라 새롭게 디자인을 해왔었는데, 그러다보니 매번 개발을 진행할 때마다 많은 시간을 쓰게 되었다.
그러나 품앗이 플랫폼 부터는 플래너 앱의 디자인 컨셉을 따라 만들었고, 그에 따라 현재 블로그의 디자인도 변경하게 되었다. 아직 디자인 시스템 수준의 단계는 아니지만 그래도 통일된 하나의 컨셉을 사용하니 요소의 배치 정도만 고민하면 돼서 작업 속도가 한결 빨라졌다.
나중에는 완전히 규격화 해서 글을 써볼까 한다.
나만의 위지윅 에디터를 만들고 싶다는 생각은 오래 전부터 해왔다. 하지만 위지윅 에디터의 복잡함과 난해함 때문에 번번히 실패하고 결국 Markdown-It 데모 페이지처럼 마크다운을 작성하는 부분과, 미리보기를 보여주는 부분으로 나눠진 에디터를 만들어서 쓰고 있었다.
그러나 리디자인을 진행하며 다시 또 위지윅 에디터를 만들어야겠다는 생각이 들었고, 어떻게 만들까 알아보다보니 ProseMirror라는 패키지를 알게 되었다.
기존에 에디터를 만들 땐 Quill이나 EditorJS를 사용했다. 두 패키지의 단점은 완성된 형태의 에디터를 제공한다는 것이다. 나는 Angular SSR 기반의 웹 앱을 주로 제작하는데, 이런 경우 서버 사이드에서 항상 예상치 못한 문제가 발생했다. 대부분의 문제는 패키지가 서버 사이드에는 존재하지 않는 window나 document 객체에 접근하는 것이었다.
그리고 완성된 형태의 에디터를 제공하다보니 내가 원하는대로 수정하는 것도 정해진 틀 내에서만 이뤄져야 한다는 답답함이 있었다.
반면 ProseMirror는 앞선 두 패키지보다 더 로우레벨의 라이브러리였다. 완성된 에디터를 만들 수 있는 예제 코드가 있지만 기본적으로 스스로 대부분의 에디터 기능을 구현해야 했다. 핵심 기능은 플러그인을 제공하기 때문에 자유도와 편의성 두 마리 토끼를 모두 잡아주었다.
ProseMirror는 프레임워크에 독립적이고 플랫폼에 독립적이다. Angular, React, Vanilla 어디서든 사용할 수 있고, 타입스크립트 자바스크립트를 가리지 않는다. 심지어 서버 사이드에서도 사용할 수 있다.
독립적인 라이브러리가 주는 유용함은 어떤 깨달음을 얻게 해주었다.
나는 여러 프로젝트를 진행하며 다양한 형태의 드래그 앤 드랍 기능을 구현했었다. 당시 만들었던 기능은 Angular 프레임워크와 밀접하게 결합되어 Component와 Directive, Service들로 구성되어 있었고, 프로젝트에 특화된 상황을 가정하고 만들었다보니 다른 프로젝트에서 재사용 할 때마다 상당한 수정이 필요했다. 어떤 때는 아예 처음부터 다시 만들어야 할 때도 있었다.
하지만 ProseMirror로 영감을 얻은 지금은 어떻게 독립적인 형태의 드래그 앤 드랍 기능을 구현할 지에 대한 아이디어가 떠올랐고, 이를 적용해 나중에 플래너 앱도 개편을 진행할 예정이다. 지금 플래너 앱에 있는 드래그 앤 드랍 코드는 내가 봐도 엉망진창이다.
나는 JSONWebToken으로 생성된 액세스 토큰을 로컬 스토리지에 저장하고 불러오는 방식으로 자동 로그인을 구현했다. 이 방법은 세 가지 단점이 있다.
첫 번째는 CSR, Client-Side Rendering에서만 사용할 수 있다는 것이다. 로컬 스토리지는 서버 사이드에서 접근할 수 없기 때문이다.
두 번째는 UX에 좋지 않다는 것이다. 사용자는 자동 로그인이 활성화 되어있는 경우 페이지 로딩 후 로그인이 완료될 때까지 대기해야 한다.
마지막 세 번째는 SSR을 사용하는 장점을 누릴 수 없다는 것이다.
이 블로그는 아직 아무도 쓰지 않지만 계정을 생성하면 좋아요를 누를 수 있다. 그리고 게시글 로딩 시 좋아요 여부를 포함해서 리턴하는데, 로컬 스토리지에 액세스 토큰을 저장하고 있으면 서버 사이드에서는 좋아요 여부를 확인할 수가 없다.
그러면 결국 게시글은 클라이언트 사이드에서 조회해야하고, SSR의 큰 장점 중 하나가 검색 엔진 최적화가 불가능한 것이다.
물론 편법은 있다. 게시글을 서버 사이드에서 로딩한 다음에 클라이언트 사이드에서 액세스 토큰이 있을 경우 좋아요 여부만 조회하는 별도의 API를 호출하는 것이다.
이렇게 하면 검색 엔진 최적화가 가능하지만, 게시글 목록을 조회할 때는 이 방법을 사용할 수 없다. 로드된 게시글 수만큼의 API가 클라이언트에서 호출되니까.
처음에는 이 문제를 해결하기 위해 백엔드 서버 쿠키에 액세스 토큰을 저장했다. 이 방법은 SSR을 사용하지 않을 때는 상당히 유용했지만, SSR 사용 시에는 의미가 없었다. 서버와 서버 간에는 쿠키가 유지되지 않기 때문에 서버 사이드에서 API는 액세스 토큰 없이 호출되었다.
그래서 이번엔 방법을 바꿨다. 클라이언트 사이드에서 로그인이 진행되고 나면 프론트엔드 서버 쿠키에 액세스 토큰을 저장했다가 서버 사이드 API 호출 시 사용하게 한 것이다.
결과는 성공적이었고, 너무 간단해서 그 동안 왜 못했었는지 의문이 들 정도였다. 실제로 예전에 이와 유사한 방법을 시도했던 적이 있는데 그 때는 뭐가 문제였는지 잘 되지 않았다. 어쨌든 지금 잘 되니 참 다행이다.
블로그 리디자인을 진행하며 여러 우여곡절이 있었지만 성공적으로 반영이 가능했다. 리팩토링에 대한 귀찮음이 있어서 예전 같았으면 처음부터 다시 만들었을텐데, 회사 일을 하며 리팩토링을 해야만 하는 상황을 겪다보니 경험이 쌓여 성공적으로 단 시간 내에 완성할 수 있었다.
이제 새로운 블로그로 새로운 컨텐츠들을 쌓아나가야겠다.