react로 만들어본 퇴근시간 계산기

기능

메인 페이지

  • 목표 시각까지 남은 시간 계산
  • url param을 통해 목표 시각 세팅
  • 목표 시각이 지나면 퇴근하라는 메시지를 뛰움

about 페이지

  • 링크 공유 기능
  • 퇴근 시간 설정 기능
  • 자동 클립보드 복사

깃허브 페이지 spa 세팅

배경이미지 출처

해결한 문제들

gsap 적용안됨

Share.tsx
1
2
3
4
5
import { Power3, TimelineLite } from 'gsap';
import CSSPlugin from 'gsap/CSSPlugin'; // 추가

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const C = CSSPlugin; // 추가
  • 로컬에서는 애니메이션이 잘 실행되었는데, 빌드 후 애니메이션이 안 나오는 문제 해결

후기

  • 어느 정도 리액트에 익숙해진 것 같다
  • 주로 사용하는 패턴이 생긴 것 같다
  • 엄청 간단해 보이지만 이것저것 신경 쓴 것 같은데, 기록을 안 해놨다 ㅠㅠ
  • 나는 코드에 조금의 변화가 생겨도 커밋을 했었는데,,
  • 이번에는 커밋을 안 하고 한 번에 몰아서 마지막에 파일별로 커밋을 했다
  • 그래서 해결한 문제들이 기억이 잘 안 난다.. ㅠㅠ

신경 썼던 것들

input element

  • about 페이지에서는 링크를 생성하는 부분이 있다
  • 처음에는 input width가 좁았었다. 그래서 고민했던 것이…
  • input 넓이보다 안의 내용이 더 길면은 끝부분이 감춰진다

  • input에서 포커스를 해제하면 위 그림처럼,
  • 계속 앞쪽으로 포커스가 자동으로 이동했다

  • 나는 input 내용의 가장 뒤쪽,
  • url param이 변하는 것에 포커스가 가도록 만들려고 이것저것 해봤는데…
  • 결국엔 그냥 input width를 늘려버리고 끝을 냈다…

github pages SPA

  • 깃허브 페이지는 기본적으로 SPA를 지원하지 않는다
  • react-router-dom 으로 여러 경로들을 만들어 두면 index 말고는 404 페이지로 리디렉트 된다
  • 그래서 찾아보니까,,.!
404.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var segmentCount = 1;

var l = window.location;
l.replace(
l.protocol +
'//' +
l.hostname +
(l.port ? ':' + l.port : '') +
l.pathname
.split('/')
.slice(0, 1 + segmentCount)
.join('/') +
'/?p=/' +
l.pathname
.slice(1)
.split('/')
.slice(segmentCount)
.join('/')
.replace(/&/g, '~and~') +
(l.search ? '&q=' + l.search.slice(1).replace(/&/g, '~and~') : '') +
l.hash
);
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(function (l) {
if (l.search) {
var q = {};
l.search
.slice(1)
.split('&')
.forEach(function (v) {
var a = v.split('=');
q[a[0]] = a.slice(1).join('=').replace(/~and~/g, '&');
});
if (q.p !== undefined) {
window.history.replaceState(
null,
null,
l.pathname.slice(0, -1) + (q.p || '') + (q.q ? '?' + q.q : '') + l.hash
);
}
}
})(window.location);
  • 원리는 index 경로 외에 나머지 경로로 들어오면 404페이지를 반환하는데,
  • 커스텀 404페이지에서 스크립트를 통해서 index페이지로 리디렉트 하게 한다
  • 이때, url params 및 query string을 가공한다
  • index.html에서는 404.html로부터 넘겨받은 값으로 라우팅이 적용된 화면을 보여준다
  • 이걸 만든 사람은 정말 대단한 것 같다. ㄷㄷ;

소스코드

참고

github pages spa

Banner Maker 클론코딩

데모

기능

  • 캔버스 크기 조절
  • 실시간 캔버스 업데이트
  • 폰트 사이즈 조절
  • 폰트색 조절
  • 캔버스색에 따른 폰트색 자동조절
  • 캔버스색 조절
  • 랜덤 캠버스색
  • 이미지로 다운로드
  • 클립보드로 카피
  • 컬러 히스토리 기능
  • 컬러 히스토리 임포트, 익스포트 기능

후기

  • 타입스크립트 공부 겸 리액트도 같이 하자는 생각으로 리액트 타입스크립트를 시작했다
  • velopert님의 리액트 프로젝트에서 타입스크립트 사용하기 글을 보고 따라하다가
  • 튜토리얼을 통해 잘 만들어진 프로젝트 구조를 기반으로 만들었다
  • 리액트가 아직 익숙하지 않은데 리액트의 훅이라던지 처음부터 고급??개념들을 사용하니까
  • 사실 뭐가 좋은지, 이렇게 써서 좋은점이 무엇인지..
  • 이 개념을 도입하기전의 것들을 시도해보지 않았기 때문에 막연한 감이 있었다
  • 나는 공부할때 이론보단 무조건 실기이고, 일단 만들어보면서 익히고 이해하자라는 주의이다
  • 그래서 이것저것 쉽게만들 수 있다고 생각한다. (나중에 보면 코드가 엄청 구릴지라도..)
  • 이번에 만들면서 신경썼던 것은
  • 사용성..?? 인 것같다

  • 나는 보통 이미지를 ctrl c 카톡에다가 ctrl v 하여 톡방에 올리는데
  • 그걸위한 copy clipboard 버튼을 만들었다. 저장후 이미지 올리기는 귀찮기 때문에..

  • 또 랜덤 칼러 버튼을 만들어서 색을 쇼핑했다
js/index.jshtml-banner-maker/commit/5cccc1594309f732ea8edd8ca08c91800d97d317
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// https://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color
/**
* Get color (black/white) depending on bgColor so it would be clearly seen.
* @param bgColor
* @returns {string}
*/
function getColorByBgColor(bgColor) {
if (!bgColor) {
return '';
}
return parseInt(bgColor.replace('#', ''), 16) > 0xffffff / 2
? '#000'
: '#fff';
}
  • 사용해보면 알겠지만 랜덤으로 생성된 배경색에 따라 폰트색도 검정색/흰색 적절한게 선택된다

  • 컬러 히스토리 기능이다
  • copy 버튼이나 download 버튼을 누르면 해당 배경색과, 폰트색이 히스토리에 저장된다
  • 만약에 같은 최근 히스토리에 저장된 색과 같은 색이면 저장하지 않도록 하였다. 버튼을 누를때마다 증식되지 않도록..
  • export 버튼을 눌러 현재 저장된 컬러 히스토리를 json 파일로 내보내는 기능도있다
  • 깃허브 페이지를 이용해 호스팅하기때문에, 내 앱은 정적이다
  • 어떻게 히스토리를 저장하고 불러올까 생각하다가 json 파일로 내보내고 다시 불러오도록 만들게 되었다

개선방향

  • 칼러픽커에서 알파값을 바꿀 수 있도록 하기
  • 폰트 변경 기능
  • textarea를 div안에 넣어버리기..? (html2canvas 사용해보기)
  • json파일로부터 컬러히스토리 임포트할때 덮어쓰기가 아니라 병합으로 불러오기
src/modules/common/copyToClipboard.js
1
2
3
4
5
6
7
8
9
10
11
export function copyToClipboard() {
const canvas = document.querySelector(`#myCanvas`);
if (!canvas) {
return;
}
canvas.toBlob(function (blob) {
// eslint-disable-next-line no-undef
const item = new ClipboardItem({ 'image/png': blob });
navigator.clipboard.write([item]);
});
}
  • 클립보드 복사 js 코드를 ts로 변환하지 못한 코드..

소스코드

참고

리액트로 네이버 퍼센트 계산기 클론코딩

  • 막 배운 리액트로 처음 만들어본 프로젝트이다
  • 계산하기 귀찮아하는 나는 평소 네이버 퍼센트 계산기를 이용했었는데
  • 이 계산기를 리액트를 사용해 클론코딩해보자..

데모

후기

  • 내가 너무 간단한 것을 만들어서 그런지 모르겠지만
  • 리액트를 처음 써본 내 기준으로 너무 복잡하다고 느껴졌다
  • 기존에 html, css, js로 만들때 보다 시간이 배로 걸렸다
  • 나중에 훨씬 복잡한 것을 만들게 되었을 때 리액트가 좋다고한다
  • 이미 잘 만들어진 리액트 튜토리얼을 따라만들고, 수정하는 방식으로 만들었다
  • 사용한 개념에 대해 완전히 이해하고 익숙해지는데 시간이 필요할 것 같다

소스코드

  • react-percentage-calculator
  • README.md에 리액트로 만든 화면을 깃허브 페이지로 보여주는 방법 등 메모해놨다