포스팅에 쓸만할 썸네일을 어디서 찾나...
🔖 Samnail-maker 바로가기
벨로그 포스팅을 가끔 하려 할 때면 썸네일을 피그마에서 대충 끄적거린 후 이미지로 추출해 사용해 오다가, 매번 하는 그게 너무나도 귀찮아져 적당한 포맷을 만들어 둬야겠다 싶어 이참에 만들게 되었다. 어느 때는 블로그는 뒷전이고 피그마에서 픽셀만 한참 움직이다가 노트북을 덮은 적이 더러 있다.
핀터레스트를 둘러보다 보면 자주 보이는 태그스타일의 디자인을 레퍼런스 삼아 만들었다. 벨로그 메인에는 많은 포스트 목록이 있기에 내 포스트가 어떤 내용인지 태그 형식으로 한 눈에 들어오게 하는 것이 프로젝트 목표다. 잘 작성된 포스트는 많은 사람에게 읽히면 좋으니까.
또한 나처럼 썸네일 찾느라, 만드느라 매번 시간을 쓰지 않도록...
가벼운 어플리케이션이기에 스택을 최소하 하기로 했다.
Nuxt2 (static) | SCSS | Git | Vercel
html2Canvas
내용을 함축해 나타낼 수 있는 단어, 혹은 기술 스택 등을 입력해 추가한다. 태그 스타일에는 세 가지가 있는데, Fill | Border | Ghost 로 나뉜다. 취향에 맞게 꾸밀 수 있다.
문제는 작은 썸네일 안에서도 글자가 잘 보일 수 있도록 폰트크기, 자간, 행간을 조절하는 일이었다. 그러다보니 텍스트박스 안엔 최대 3행까지 들어갈 수 있도록 구성했는데, Flex wrap 으로 행을 구분짓기에 태그 수를 제한하는 것에 고민을 했다.
세 가지 방안이 있었다.
태그 갯수 제한
이렇게 제한을 두면 다양한 형식의 언어를 받는 상태에서 최소한의 태그 수만을 고려할 수 있었다. 예를 들어 'ive'의 length(3)와 '아이브'의 length(3)는 같지만 해당 엘리먼트의 너비가 다를 경우가 많다. 심지어 같은 'ive'라도 'IVE' 대문자로 써도 달라진다.
Byte 수 제한
그럼 byte를 제한해보는게 어떨까 하고 문득 떠올라 방법을 찾아보다가 UTF-16 코드 기준으로 charCodeAt() 을 사용하여 byte를 한 글자씩 구해보면 될 듯 하다는 생각이 들었다. 'ive'는 3byte이고 '아이브'는 6byte 이니 같은 기준에 너비 값을 비교할 수 있겠다 싶었다. 하지만 이모지 사용에서의 Emoji Modifier로 인해 byte 수를 균일하게 잡을 수 없는 점, 그래도 역시 태그 갯수 제한의 단점에서 크게 벗어나지 못한 점으로 사용하지 않았다.
.
참고
문자열 Byte 길이 구하기
이모지와 유니코드
엘리먼트 높이 제한
Flex wrap에 쌓인 한 행의 높이 * 3의 값을 구해 그 이상의 값이 감지될 때 태그추가를 막는 방법도 있었다. 3행의 공간을 제일 효율적으로 쓸 수 있는 방법이었다. 3행을 넘어 가는 태그가 추가될 때 Vue의 updated()에서 감지해 추가된 태그를 array에서 제거하는 방법이다. 프로젝트에서는 이 방법을 택했다.updated () { // DOM이 업데이트 될 때마다 실행 this.setHeight(); }, methods: { setHeight() { // 키워드를 감싸는 전체 DOM 높이 체크 const height = document.querySelector(".textBox")?.offsetHeight; this.height = height; if (this.height > 256) { this.tagList.pop(); this.$notify({title: '그러다 넘쳐요 😇', type: 'warning'}) } } }
썸네일에 본인의 아이디 태그 등 메인 태그 이외에 부수적인 정보를 입력할 수 있는 공간이다.
이 부분 역시 고민을 많이 했다. input:color를 처음에 넣고 자유도를 주었는데, 포스트 컨텐츠에 더 집중할 수 있는 시간에 색을 고르고 있는 나를 보며 테마는 프리셋으로 넣어두는게 맞다 생각하여 (내 취향으로)컬러 파레트를 구성했다. 입맛대로 고르다 없으면... 댓글에...
말 그대로 태그 리셋. 태그를 하나씩 제거할 수 있지만 편의상 넣어두었다.
프로젝트 목표인 이미지 저장 기능. 이 부분은 설정한 html 태그 내부 엘리먼트를 이미지를 캡쳐해주는 html2Canvas를 사용했다. 캡쳐할 DOM을 파라미터로 전달하여 호출하면 Promise 객체를 리턴, 생성된 canvas를 이미지로 저장한다.
downloadImage() {
html2canvas(this.$refs.canvas).then((canvas) => {
const imageUri = canvas.toDataURL();
this.downloadURI(imageUri, "thumbnail.png");
});
},
downloadURI(uri, name) {
const link = document.createElement("a");
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
}
기술블로그에 한정하지 않고 다양하게 사용해도 괜찮을 듯 하다.
태그를 Drag & Drop으로 옮길 수 있게 구현 예정이다. 이 작은 캔버스 안에 꼭 필요한 기능인가 싶어 MVP에서는 제외했다.
컬러나 레이아웃의 자유도도 혹시 누구에게는 필요할까 싶어 구상중에 있다.
이 간단한 프로젝트를 하기로 마음 먹은지가 꽤 된 것을 이제서야 마무리한다. 썸네일을 척척 뽑아 낸다고 내가 포스팅을 자주 할 지는 잘 모르겠다만, 프로젝트 하나를 끝낸 게 어딘가 싶고... 혹시나 나같은 주객전도 블로거에게 도움이 되길 바라며... 좋은 아이디어나 더 나은 코드 방식이 있다면 언제나 댓글 부탁드립니다.
Thankful for the little by little useful exercise. Has conclusively the ordinary impact from this vlog. DG Careers
헐!!! 너무 깔끔하구 이뻐요 잘 쓸게욤