
Dae Young, Lee
199X.11.24
010-4343-1354
plum_flower@naver.com
isLoad.
Frontend Developer's portfolio

199X.11.24
010-4343-1354
plum_flower@naver.com
UI디자이너&퍼블리셔
(2020.04~2021.04)
프리랜서 웹퍼플리셔
(2021.05~2022.10)
프로덕트개발팀 프론트엔드
(2022.10~2023.07)
클라우드서비스팀 프론트엔드
(2023.08~현재)
총 경력 5년 7개월
웹사이트 구축 및 운영
완벽한 반응형 웹개발
프론트개발 디자인 시스템 구축
일본어 비즈니스 대화
영어 메일 의사소통
국민대학교 임산생명공학과 졸업 2018.08
이젠컴퓨터아카데미 UI/UX 과정 2020.02
더조은컴퓨터아카데미 PHP/MySQL 프로그래밍 2021.07
이젠컴퓨터아카데미 React.js 자바스크립트 2021.11
이젠컴퓨터아카데미 React Native 앱개발 2022.04
인프런 프론트엔드 개발환경(webpack, babel...) 2023.05
패스트캠퍼스 Java&Spring 웹 개발 종합반 2023.08
패스트캠퍼스 3D 인터랙티브 (R3F & Three.js) 2024.03
패스트캠퍼스 블렌더로 완성하는 3D 캐릭터 2024.06
JLPT N1 - 2022
TOEIC 825 - 2021
웹디자인 기능사 - 2020
TOEIC Speaking 140 - 2019
ITQ Internet A급 - 2018
GTQ Photoshop 1급 - 2017
HTML5 / CSS3 / JS(ES6) / React / Vue / Nextjs
Nodejs(express) / PHP
MySQL / MongoDB
Photoshop / Illustrator / Xd
Premiere Pro
다정다감하고 누구와도 잘 어울립니다.
내가 맡은 임무는 극한의 책임감을 가지고
끝까지 완수하여 팀원으로서 모범이 됩니다.
HTML5 | 웹표준 및 웹접근성을 준수하며, 최상의 SEO를 위한 태그를 작성합니다. 검색노출을 위한 적절한 타이틀 사용과 최적의 HTML구조, 스크린리더를 위한 정확한 태그사용 등 모든 면에 대응합니다. | CSS3 | 거의 모든 스타일을 자유자재로 다룰 수 있습니다. 주로 BEM 방법으로 클래스명을 작성합니다. |
|---|---|---|---|
SASS | 반복문과 변수사용 및 코드 중복 방지를 위한 모듈입니다. 체계적으로 SASS를 작성할 경우 다크모드나 기타 상황에서 쉽게 color를 변경 가능합니다. SCSS 문법을 사용합니다. | Bootstrap | 스타일시트를 처음부터 제작하기 부담스러운 토이 프로젝트에 가끔 사용합니다. |
ES6+ | 화살표함수, 스프레드연산자, const, let 등을 사용하며, this의 바인딩과 TDZ에 유의하며 스크립트를 작성합니다. ES5 및 ES6 이상의 스펙의 스크립트에 대응합니다. 바벨을 사용하지 않는 환경의 경우, 또한 ie까지 대응하는 경우 ES5 스펙으로 작성합니다. 이벤트 루프를 이해하며, 순서에 맞는 스크립트 작성에 유의합니다. | React.js | 함수형 컴포넌트를 사용합니다. 주로 관심사별로 묶는 스크립트를 작성하며, 개발팀의 코딩 컨벤션에 맞춰서 코드를 만듭니다. 생명주기를 이해하며, 기능이 정확하게, 또 알맞는 타이밍에 작동하도록 스크립트를 작성합니다. 모든 동작은 state로 제어합니다. |
Next.js | SSG, SSR의 장점을 살려, 최대한 Server side에서 많은 정보를 제공하도록 스크립트를 작성합니다. 경우에 따라 SSG나 ISR 활용이 가능합니다. | Vue.js | 주로 options api를 사용합니다. composition api는 실무에서 사용하는 곳을 아직 경험해보지 못했으나, toy project로 간단하게 다뤄봤습니다. react와 마찬가지로, state로 모든 동작을 제어합니다. vue2 및 vue3 모두 대응합니다. |
Typescript | 엄격한 타입 적용을 위해, 컴파일 단계에서 에러를 잡기 위해 사용합니다. 되도록 any를 사용하지 않도록 노력하고 있습니다. | React-query | 이제는 tanstack으로 알려진 React query를 서버상태 관리 및 관찰용으로 넣었습니다. fetch의 성공/실패/로딩중 등 관측이 가능하고, 언제 시도했는지, 몇 번째 시도인지 등 서버와의 통신상태를 점검할 수 있습니다. |
Redux | 전역 상태 관리를 위해 사용하고 있습니다. props가 전달되는 범위가 넓어질 때, redux로 상태관리를 진행합니다. | Recoil | Redux보다 가독성이 훨씬 좋아서 자주 사용합니다. 거의 useState와 비슷하죠. App이 켜질 때 browser storage를 읽어서 상태 초기값을 설정할 수 있다는 점도 매력적입니다. |
JQuery | legacy 프로젝트 외에는 크게 사용할 일이 없으나, 종종 jsp로 제작된 프로젝트에 jquery가 사용되고 있어 이 때 사용합니다. 기본적인 ui메소드와 ajax를 사용합니다. |
PHP | 기본적인 CRUD를 알고있습니다. 게시판 제작 경험이 있으며, 실제 자체 제작 블로그에 PHP가 사용됐던 적이 있습니다. SSR의 개념을 알게해준 고마운 언어입니다. | Node.js | express를 사용하여, 클라이언트에서 오는 각종 요청에 대해 처리합니다. 기본적으로는 PHP와 같이 간단한 CRUD를 처리하며, 클라이언트사이드 언어인 자바스크립트로 서버사이드까지 다룰 수 있는 점에 주목하고 있습니다. |
|---|---|---|---|
MySQL | 간단한 쿼리문 작성은 스스로 가능합니다. | mongoDB | 데이터가 json 그 자체이며, nodejs서버 상에서 객체를 자유롭게 다룰 수 있기 때문에 SQL과 마찬가지로 간단한 CRUD가 가능합니다. SQL과는 달리 별도로 쿼리문을 만들어도 되지 않아서 편리합니다. |
Spring | Java 및 Spring 기초교육을 수강한 적이 있어 간단한 Spring 코드는 직접 수정이 가능합니다. | ||
React Native | React Native 컴포넌트를 사용하여 간단한 UI제작이 가능합니다. | ||
|---|---|---|---|
Git | github앱이나 git bash, 혹은 fork로 작업물을 관리합니다. 되도록 conflict가 일어나지 않도록 최신 소스를 주기적으로 pull 합니다. | Confluence | 프론트 소스의 관리를 위해, 중요 내용은 Confluence에 작성해둡니다. 혹은, 문서를 업로드 해놓습니다. |
|---|---|---|---|
Github | Jira | 모든 작업에 대해 Jira에 내용을 작성 후 진행합니다. 전사적으로 HR이 어떻게 관리되는지 알기 쉽게 하기 위해 되도록 자세한 내용을 작성해 넣어둡니다. | |
Gitlab |
Photoshop | 사진사, 디자이너 업무 등으로 포토샵은 10년 이상 다루어 전문가 수준입니다. | Illustrator | 벡터그래픽 제작 시 사용합니다. |
|---|---|---|---|
XD | 주로 웹사이트/앱 UI제작 시 사용합니다. 금융권 프로젝트에서 UI제작 시 사용했습니다. | Zeplin | 디자이너들이 작업해놓은 UI를 보고 개발에 옮깁니다. |
Figma | 기능과 UI가 XD와 흡사하여, 어렵지 않게 기능을 다룰 수 있습니다. | ||
개인서버 | 본 포트폴리오 및 모든 작업물은 자택 개인서버에 띄워져 있습니다. nginx로 리버스 프록시를 적용하여, domain.com/ 은 프론트 서버에, domain.com/api/는 api 서버에 연결되도록 포트번호를 지정합니다. | Jenkins | 배포 자동화 구축 경험이 있습니다. 예를 들면, SVN 커밋을 감지하고 변동내역이 있으면 5분에 한 번씩 배포한다던지, 특정 Git Branch를 매개변수로 배포하면 mv로 작업물을 덮어씌운 뒤 pm2 reload로 프로세스를 다시 띄우거나 하는 것 말이죠. |
|---|

이제는 볼 수 없는, 그리운 싸이월드를 되살린 컨셉의 개발 블로그 입니다.
명색이 개발자인데, 네이버나 티스토리같은 기성품보다는 블로그 시스템 자체를 제가 만들어보고 싶었어요.
글쓰기 기능이 생각보다 어려웠던 기억이 납니다. 코드에디터와 코드 하이라이팅 기능이 들어가야하는데, 에디터 자체를 만드는 것은 상당히 시간을 많이 잡아먹는 일이었기에 summernote라는 WISYWIG editor로 구현을 했습니다.
다만 커스텀해야할 기능이 많이 있었기에 (code highlighter 포함) 글 작성 기능에 상당한 시간이 걸렸습니다.
이미지는 첨부하자마자 바로 webp로 변환하여 서버에 저장합니다.
블로그에 존재하는 모든 내용은 ServerSide Rendering으로 구현됩니다.
이미 클라이언트에 도착한 시점에 모든 HTML이 완성되어 있으니,
검색엔진 최적화에 큰 도움이 될거라 생각하고 있습니다.
PC버전 기준으로, lighthouse로 채점해본 web vital은 거의 만점에 가깝습니다.
다들 성능최적화 한다고 쉽게 말은 해도,
어떤걸 최적화하는지, 구체적으로 뭘 해야 하는지 모르는 경우가 많으니깐요.
제가 아는 FE최적화 지식은 다 욱여넣은 것 같아요.
거의 모든 코드에 Memoization을 적용시켜서 웬만하면 재렌더는 일어나지 않습니다.
폭풍같은 작업량이었지만, 즐거웠습니다.
자택 서버가 좀 더 성능이 우수한 고가 제품이었다면, 점수가 더 잘나왔을지도 모르겠습니다.
CRUD: 글 작성, 댓글 작성으로 INSERT INTO를, 글 수정, 댓글 수정으로 UPDATE SET을, 임시글이 정식 포스트가 될 때 임시글 DELETE를, 거의 모든 데이터 조회에 SELECT를, 쿼리문은 원없이 사용해본 것 같습니다.
이외에 이미지 첨부시 바로 webp로 전환해서 temp 이미지 폴더에 넣는기능, 임시 저장글이 정작글로 포스팅 될 때 temp image dir에서 정식 이미지 dir 옮기는 기능, 정규식으로 포스팅 내용의 <img> 태그를 읽어서 정식 이미지 dir로 src 내용을 바꾸는 기능이 들어가 있습니다.
JWT: 로그인 기능 개발을 위해 도입했습니다. 토큰이 이상하면 400을 보내고, 토큰이 파기날짜가 되었으면 403을 보냅니다.
어느 쪽이든, 프론트에서는 자동 로그아웃 기능을 적용시킵니다.
게시판이라는 것이 생각보다 복잡하고
경우의 수가 너무나도 많다는 것에 놀랐습니다.
조금 아쉬웠던 점은, 블로그라는 것은 실시간 데이터를 보여주는 시스템이다보니
SSG, ISR 같은 캐싱 전략을 활용할 기회가 적었습니다.

기본적으로 다크모드로 생활을 하는 사람들이 있습니다.
바로 제가 그러한 경우이죠.
핵심은 lightness를 계산하는 기능입니다.
#000 => rgb(0, 0, 0) => hsl(0, 0, 0)로 변경해서, 배경이 어두우면 그대로 두고, 밝으면 어둡게 바꿉니다.
// 16진수 색상을 RGB로 변환하는 함수
function hexToRgb(hex) {
hex = hex.replace('#', '');
if (hex.length === 3) {
hex = hex.split('').map(x => x + x).join('');
}
const bigint = parseInt(hex, 16);
return [(bigint >> 16) & 255, (bigint >> 8) & 255, bigint & 255];
}
// RGB를 HSL로 변환하는 함수
function rgbToHsl(r, g, b) {
r /= 255;
g /= 255;
b /= 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const l = (max + min) / 2;
let h, s;
if (max === min) {
h = s = 0; // 무채색
} else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return [h, s, l];
}
return 값을 [h, s, l]로 빼낼 필요는 없지만(l만 이용하기 때문),
추후 색상은 살리고 밝기만 어둡게 하는 기능을 추가할 예정이기 때문에 hue와 saturation도 return하게 제작했습니다.
위와 같이 동작합니다.
한 번 동작을 일으키면, localStorage에 다크모드 적용 여부를 저장해둡니다.
manifest.json은 PWA에도 사용되지만,
이렇게 크롬 웹스토어에서 이 APP이 어떤 APP인지 정보를 담는 역할도 합니다.
브라우저 엔진으로 chromium을 사용하는 모든 브라우저에 대응합니다.
(chrome 객체 사용 가능한 브라우저 - chrome.runtime, chrome.tabs 등)
단, DOM 요소 중 iframe이나 shadowDom이 다른 도메인을 가지고 있다면,
Cross Origin 보안 작동으로 인해 적용이 안됩니다.

| Concept | 태그 만들기 |
|---|---|
| Frontend | ESModule, typescript, react |
| Deployment | NPM Library |
| 제작참여도 | 100% |
| 다운로드 수 | 1235 명 |
| 사용하는 법 | 로 설치합니다.react에서는 해당 예시와 같이 사용할 수 있습니다. |
요즘 게시판이나 커뮤니티 등에는 전부 태그가 들어가죠?
useState를 선언하는 것만으로 쉽게 태그를 배열로 받을 수 있습니다.
import GloomyTags from 'react-tag-maker';
function App() {
const [state, setState] = useState([]);
return (
<GloomyTags
state={state}
setState={setState}
/>
);
}
export default App;
props는 매우 간단합니다.
그냥 state와 setState 두 개만 넣으세요.

결과물은 ['show', 'me', 'the', 'money'] 와 같은 배열로 만들어집니다.
npm publish로 배포합니다.
npm i react-tag-maker
Reactjs는 물론, Nextjs client component도 대응합니다.
typescript, 일반 js 둘 다 대응합니다.
자매품으로 vue-tag-maker(다운로드 수: 1765)도 만들었어요.

| Concept | webRTC 영상통화 + websocket채팅 + OAuth 로그인 |
|---|---|
| Frontend | Next.js 13 |
| Backend | Node.js(express, socket.io) |
| Database | mongoDB |
| Deployment | 자택 개인서버(NAS) |
| 제작참여도 | 기획(100%), 디자인(100%), FE개발(100%), BE개발(10%) |
| 사용방법 | 한 명은 id: admin, pw: admin으로 로그인, 한 명은 id: admin2, pw: admin2으로 로그인, 서로 영상통화와 채팅을 즐겨봅시다. 원한다면 google이나 github 소셜 로그인도 가능합니다. |
채팅: 채팅 기능의 핵심은 웹소켓입니다. 소켓에 메세지를 emit하면, 웹소켓 서버에서 해당 방에 참여한 모든 이들에게 broadcast해주고, broadcast 받은 클라이언트들은 모두 새로운 메세지를 받게되는 형태입니다.
화상통화: 2개의 PEER, 시그널 서버, TURN서버가 주 핵심요소입니다. 최초 동작시, 웹소켓으로 만들어진 시그널 서버에 sdp정보를 보내어 PEER끼리 서로 정보를 주고받습니다. 이후 서로 주고받은 sdp를 토대로 STUN서버 (stun:stun.google.com:19302)에 중계요청을 보내며, 중계기로부터 받은 영상데이터 혹은 PEER에게 직접 받은 영상데이터를 video태그에 재생시킵니다.
채팅: 서버에서는 웹소켓 connection이 일어나면 클라이언트에서 받은 uuid를 토대로 방을 생성합니다. 이제 그 uuid로 전달된 메세지를 해당 방에 참가한 사람들에게 broadcast해줍니다.
화상통화: 시그널 서버는 클라이언트로부터 받은 sdp 정보를 상대방 peer에게 전송하여, 서로 연결을 잘 수립할 수 있도록 합니다. 이후 STUN서버나 TURN서버를 통해 Interaction Connection Establishment 후보를 찾고, 서로의 PEER간 연결이 수립되면, 그 이후부터는 서버의 역할이 매우 작아집니다.
단, TURN서버의 경우 직접 구축하는 것이 어려웠기 때문에 google 공개도메인을 사용했습니다.
OAuth: NextAuth 라이브러리를 통해 구현합니다. 사용자(Resource Owner)는 현 프로젝트의 인증서버에 인증 요청을 보냅니다. 그후 인증서버는 구글의 Resource 서버에 요청을 보내게 되고, Resource Owner의 인증을 위임받은 구글서버에 의해 인증서버에는 사용자의 정보(이름, 메일)이 도착하여 토큰화되어 사용할 수 있게 됩니다.

| Concept | PWA(Progressive Web App), react query, mysql, nextjs13, 쿠키, 카카오 공유 |
|---|---|
| Frontend | Next.js 13, React-query(서버상태관리) |
| Backend | Next.js 13 |
| Database | MariaDB (MySQL) |
| Deployment | 자택 개인서버(NAS) |
| 제작참여도 | 기획(100%), 디자인(100%), FE개발(100%), BE개발(100%) |
| 사용방법 | 사용자의 정보는 접속해서 쿠키를 허용하는 순간부터 고유한 아이디로 저장됩니다. 이제 투표를 만들고, 카카오톡으로 공유해보세요! 정말 쉽습니다. 그냥 투표를 제작하고, 링크를 뿌려보세요. 자유로운 익명투표의 시작입니다. |
우선 getServerSideProps로 해당 투표의 uuid를 토대로, 투표 데이터가 있는지 확인 후 없으면 custom 404페이지로 안내합니다.
존재한다면 실제 투표페이지로 안내합니다.
투표 데이터는 React Query를 통해서 fetch 하며, 데이터가 정상적으로 송/수신 되고 있는지 React-query devtool을 통해 관찰할 수 있습니다.
이 프로젝트는 Build하지 않고, React Query devtool을 보여주기 위해 pm2 - npm run dev로 .env.development 환경으로 돌리고 있는 상태입니다. (꽃 이미지)
투표를 간편하게 생성 가능하며, 언제든지, 자유롭게 생성 가능합니다.
투표를 하면, 바로 DB에 내용이 업데이트 되고, react query에 설정된 의존성 배열에 의해 한 번 더 fetch를 거치게 됩니다. 이후 투표 결과 화면이 송출됩니다.
나의 데이터는 쿠키에 저장되어있으며, (랜덤으로 배정된 고유한 uuid를 마치 id처럼 사용) 내가 이미 투표를 했으면 투표 결과를 보여줍니다.
복사하기 및 카카오 공유가 가능합니다.
모바일, PC 어느쪽이든 쉽게 투표 URL을 공유할 수 있습니다.

DB: 비록 백엔드 전문가는 아니나, 나름대로 DB를 설계도 해보고 효율적인 환경을 구축하기 위해 연구했습니다.
vote table: 투표의 개요를 저장합니다.
votemenu table: 해당 투표의 보기를 저장합니다. parentid로 vote table의 uuid를 추적합니다.
voter table: 투표자들이 어떤 보기에 투표했는지 저장합니다. 몇 번 보기의 index를 선택했는지만 저장하면 됩니다.
백엔드에서는 이를 정제하지 않고 전부 클라이언트로 보내서, 클라이언트에서 알아서 데이터를 정제해서 map으로 뿌려줍니다.
Nextjs API: 크게 네 가지 기능으로 나뉩니다.
1. 단순히 투표 DB내용을 클라이언트로 쏴주는 기능
2. 쿠키 데이터가 있는 사용자에 한해서, 내가 만든 투표방을 보여주고, 내가 선택한 투표 보기에 [선택함]을 노출시켜 줍니다.
다만 쿠키가 제거되면 이는 모두 사용할 수 없게 됩니다.
3. 투표 삭제하기 기능: bcrypt를 사용해서 암호화 및 verify를 실행합니다. 올바른 비밀번호를 입력하면, 투표가 실제로 삭제됩니다.
특정 Flag를 만들어서 투표를 비노출 시키는 방법도 있으나, 투표 row가 무한이 늘어나는 것을 방지하기 위해 실제 row를 삭제하는 방법을 채택했습니다. 집에 비싼 서버가 있고 전기세 감당이 된다면 전자의 방법을 택할 수도 있습니다.
4. 투표 관측기간이 지나면, scheduler가 24시간에 한 번씩 실제 row를 삭제하여 더이상 투표를 볼 수 없게 합니다.
node-cron vs node-schedule 둘 중에 고민을 많이 했으나, 사용자가 많은 후자를 택했습니다.

| Concept | 손쉬운 날짜계산 |
|---|---|
| Frontend | ES Module |
| Deployment | NPM, 자택 개인서버(NAS) |
| 제작참여도 | 100% |
| 다운로드 수 | 1453 명 |
| 사용하는 법 | 로 설치합니다.react에서는 해당 예시와 같이 사용할 수 있습니다. |
게시판, 댓글 등에서 일일이 날짜를 계산하기 어려웠을 경우, string을 gloomyDate.date(str)에 담는 것만으로 이 게시글이 며칠전에 작성됐는지 return합니다.
개발자는 간편하게 날짜를 bind할 수 있습니다!
function App() {
const [data,setData] = useState([
{ title: 'title1', date: gloomyDate.date('2022-05-10 10:55:40')},
{ title: 'title2', date: gloomyDate.date('2023-02-11 15:50:30')},
{ title: 'title3', date: gloomyDate.date(new Date())},
{ title: 'title4', date: gloomyDate.date(Number(new Date()) + 1000)},
])
return (
<div className='list'>
{
data.map((elm,idx)=>
<div key={idx}>
<p className='title'>{elm.title}</p>
<p className='date'>{elm.date}</p> {/* expected: XX 전 */}
</div>
)
}
</div>
);
}
예상 출력결과
title1
1년 전
title2
2달 전
title3
방금 전
title4
잠시 후
npm publish로 배포합니다.
npm i gloomydate로 설치할 수 있습니다.
모듈 번들러(웹팩 등)에 대응하기 위해 es module형태로 제작했으며, tree shaking에 대응하기위해 추후 모듈의 기능이 늘어날 경우 named export로 제작할 예정입니다.
(현재는 모듈 기능이 하나뿐이라 tree shaking이 크게 의미를 가지지 않음)
일반 HTML 프로젝트의 경우
<script src='https://cdn.gloomystore.com/gloomyDate/gloomyDate.js'></script>
로 commonJS에 대응합니다.
react의 예시와 동일하게 사용가능합니다.
3개 국어에 대응하며, 3가지 타입의 데이터 input을 지원합니다.
gloomyDate.date('2023-04-26 08:10:22','en') // formatted string
gloomyDate.date('20230426081022','jp') // string
gloomyDate.date(1723722833597,'ko') // number
gloomyDate.date((new Date()),'ko') // Date
'ko', 'jp', 'en'
3개 국어에 대응합니다.
예상되는 결과:
2days ago
2日前
2일 전
방금 전
아무 인자도 넣지 않을 경우 'ko'가 default로 작동합니다.
14 length의 string, number에 대응하며,
'YY-mm-dd H:i:s' 형태의 string에도 대응합니다.

| Concept | Next.js Hydrating |
|---|---|
| Frontend | Next.js 15, Typescript, App Router |
| Backend | Next.js 15, Typescript, MySQL |
| Deployment | 자택 개인서버(NAS) |
| 제작참여도 | 기획(100%), 디자인(100%), FE개발(100%) |
기존의 CSR형식의 SPA는 검색노출이 어렵고, 설령 구글 검색로봇이라 하더라도 웹서버상에서 index.html을 받았을 때 빈문서 이외에는 내용이 나오지 않습니다.
이러한 점을 해결하기 위해 Next.js의 SSG에 주목했으며, JSX가 서버사이드상에서 이미 html태그로 렌더된 상태로 전송이 되기 때문에 현 포트폴리오의 검색 노출이 더 잘될 것으로 기대하고 있습니다.
최하단 Today, Total은 pages/api 폴더 내에 제작해둔 api를 page에서 GetServerSideProps로 받아오며, DB에 오늘날짜의 테이블이 없다면 오늘 방문자 0명으로 INSERT합니다.
아! app router에서는 fetch action을 GetServerSideProps로 하지는 않겠군요.
cache 설정을 하지 않았으니 pages router의 GetServerSideProps와 유사하게 동작합니다.
이미지, 폰트 등 모든 컨텐츠가 로딩되고, ajax에서 return을 받아오면 비로소 로딩화면이 사라집니다.
(개발자 도구에서 네트워크를 3G로 하고 강력 새로고침을 하면 로딩화면을 볼 수 있습니다.)
서버에서 사용하는 것은 오늘 날짜의 today hit, total hit을 구하는 것입니다.
시간 기준은 클라이언트 기준이 되어야하기 때문에, 클라이언트에서 한국시간을 구해줍니다.
(new Date()에서 9 * 60 * 60 * 1000를 더함)
시간은 보안정보가 아니기 때문에 get요청으로 parameter에 붙여서 보내줍니다.
const [rows] = await pool.query<RowDataPacket[]>('SELECT * FROM visitor_today WHERE REGDATE='${'todayDate'}'');
const [rows2] = await pool.query<RowDataPacket[]>('SELECT * FROM visitor_total WHERE REGDATE='${'todayDate'}'');
// const count = rows;
res.status(200).json([...rows,...rows2]);
api에서는 DB에 오늘날짜의 테이블이 없다면 오늘 방문자 0명으로 INSERT합니다. 만약 존재한다면 오늘 방문자의 배열을 가져와서 클라이언트로 return합니다.
가볍게 만들어보고 있는 토이프로젝트입니다.



| Concept | CSS 3D Effect, Mouse Pointer Offset |
|---|---|
| Frontend | Next.js 13 |
| 제작참여도 | 100% |

| Concept | 실시간 온라인 게임 |
|---|---|
| Frontend | React, vite, R3f |
| Backend | Express, socket.io |
| Deployment | 자택 개인서버(NAS) |
| 제작참여도 | 100% |
Fix incorrect Korean translation for MULTIPLE_ERRORS string
| 설명 | Adobe Brackets(전신) 였던 피닉스 에디터입니다. 국제화 관련 코드를 수정하여 PR을 올렸고, 승인 되었습니다. |
|---|---|
| 상태 | MERGED |
| 날짜 | 2025-03-26 20:18:06.000Z |
| github | https://github.com/phcode-dev/phoenix/pull/2189 |