밥먹고 자는 시간 외에는 항상 컴퓨터 앞에 앉아 있었던 일주일이었다.
항상 부족함을 느끼기에 자는 시간조차 아까울 따름이다. 약 3주 전에 안구건조증으로 심하게 고생해서 치료받았고 지금도 주기적으로 안구건조증 치료용 점안액과 인공눈물을 넣고 있다. 지금은 많이 완화되었지만 다시 또 병이 도질 수 있기 때문에 건강관리에 힘을 써야겠다. 헬스도 계속 다니려고 생각하고 있지만 프로젝트 기간 때 도저히 짬이 나지 않을 거 같아 프로젝트가 끝나고 등록해야겠다.
1년간 불어난 살을 더 이상 마스크가 가려주지 않기에..
지난주 회고록에 언급했듯, 실전 프로젝트 front 구성을 javascript에서 typescript로 바꾸기로 결정하였고, 5월 9일 월요일에 migration을 완료했다.
그 후 typescript를 좀 더 편하고 원활하게 사용하기 위하여, 하루 정도 시간을 소비하여 깊게 공부하는 시간을 가졌다.
전체적으로 한 번 훑긴 했으나, 하루만에 너무 많은 양의 정보가 들어와서 그런지 모든 지식을 온전히 내 것으로 만들지는 못했다.
프로젝트를 진행하면서 부딪히는 문제들을 해결하며 알고 있다고 착각하고 있는 부분들을 내 지식으로 채워야겠다.
디자이너분들의 요청이었다.
styled-componets의 도움을 받지 않고 tailwindcss 하나만 가지고 세부적인 설정은 물론 전역적인 설정까지 완료하는 게 이번 프로젝트의 1차 목표이다.
/* index.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
@font-face {
font-family: 'NotoSansKR';
src: url('./assets/fonts/NotoSans-Bold.woff') format('woff');
font-weight: 700;
font-display: swap;
}
@font-face {
font-family: 'NotoSansKR';
src: url('./assets/fonts/NotoSans-Medium.woff') format('woff');
font-weight: 500;
font-display: swap;
}
@font-face {
font-family: 'NotoSansKR';
src: url('./assets/fonts/NotoSans-Regular.woff') format('woff');
font-weight: 400;
font-display: swap;
}
@font-face {
font-family: 'Roboto';
src: url('./assets/fonts/Roboto-Bold.woff') format('woff');
font-weight: 700;
font-display: swap;
unicode-range: U+0041-005A, U+0061-007A, U+0030-0039;
}
@font-face {
font-family: 'Roboto';
src: url('./assets/fonts/Roboto-Medium.woff') format('woff');
font-weight: 500;
font-display: swap;
unicode-range: U+0041-005A, U+0061-007A, U+0030-0039;
}
@font-face {
font-family: 'Roboto';
src: url('./assets/fonts/Roboto-Regular.woff') format('woff');
font-weight: 400;
font-display: swap;
unicode-range: U+0041-005A, U+0061-007A, U+0030-0039;
}
./assets/fonts/
폴더에 사용할 폰트를 넣고, index.css
파일에 font-face 정의를 하였다. 요구사항이 한글은 Notosans 영문,숫자는 Roboto 였기 때문에
unicode-range를 사용하여 적용범위를 따로 지정해주었다.
전체 : U+0020-007E
특수문자 : U+0020-002F, U+003A-0040, U+005B-0060, U+007B-007E
영문 : U+0041-005A(대문자), U+0061-007A(소문자)
숫자 : U+0030-0039
이후 tailwind.connfig.js
파일에 default font를 적용해 주었다.
// tailwind.config.js
// eslint-disable-next-line
const defaultTheme = require('tailwindcss/defaultTheme');
module.exports = {
content: ['./src/**/*.{js,jsx,ts,tsx,html}'],
theme: {
...
extend: {
fontFamily: {
sans: ['Roboto', 'NotoSansKR', ...defaultTheme.fontFamily.sans],
},
...
},
plugins: [require('@tailwindcss/line-clamp')],
};
eslint에서 defaultTheme을 require로 불러오는 것을 오류로 처리하기 때문에 // eslint-disable-next-line
부분을 적용해주었고, tailwind default font인 sans에 'Roboto'(영문, 숫자), 'NotoSansKR'(영문, 숫자 외)을 추가 하여 매번 다른 설정이 없어도 기본 font가 적용되게 구성을 해놓았다.
이외에 tailwind.config.js
설정을 작업하기 손쉽게 하기위해 여러가지 설정을 해놓았다.
내가 시각디자인을 전공을 해서 그런지는 몰라도 1px의 오차도 보기 싫어서 굉장히 공을 들여 작업을 했고, 앞으로 추가 보완할 예정이다.
팀원 분과 합의 끝에 폴더 구조를 다시 잡았다.
/src
└──/apis - api를 묶어서 관리
└──/assets - 프로젝트에서 사용할 이미지, 아이콘, 폰트 등을 저장
└──/components - atomic desing pattern 적용
├── /atoms
├── /molecules
├── /organisms
└── /templates
└──/lib
└──/pages - 페이지 단위의 컴포넌트 폴더로 구성
└──/redux - redux toolkit을 활용한 상태 관리
├── /modules
└── /configureStore.ts
└──/utils - 유틸 함수 폴더
├── /app.tsx
├── /index.tsx
├── /index.css
├── /custom.d.ts
현재 axios instance 설정 및 device-detect 기능은 lib 폴더에 넣었고 cookie 관련 함수는 utils 폴더에 정리해 놓았는데, 이 부분에 대한 정확한 정리가 필요해 보인다.
폴더구조는 정말 정답이 없다. 많이 고민해보아야할 부분이고, 추후 리팩토링 과정에서 수정이 될지도 모르겠다.
Typescript에서 svg 사용하기(모듈화 포함) #12
typescript에서는 svg를 import 시키는 방법이 달랐고, 이를 해결하여 같은 팀원 분에게 공유를 해드렸다.
링크를 눌러도 같은 내용이 나오게된다.
React+Typescript에서는 React+Javascript와는 다른 방식으로 svg를 import 시켜주어야합니다.
해결하여 적용까지 해보아서 방법을 공유해드립니다.
custom.d.ts
파일을 생성해 줍니다.declare module '*.svg' {
const content: any;
export default content;
}
tsconfig.json
에서 include에 포함시켜 줍니다."include": [ "src", "src/custom.d.ts" ]
2번까지는 진행을 해놓았고, 새로운 svg 파일을 추가하실 때 3번부터 참고하시면 되겠습니다.
/src/assets/icons
폴더에 svg 파일을 추가해줍니다./src/assets/icons/index.ts
파일을 수정해줍니다.import Bookmark from './Bookmark.svg';
import 추가파일 from './추가파일.svg
export { Bookmark, 추가파일 };
import {추가파일} from '../assets/icons/index';
...
<img src={추가파일}/>
프로젝트의 최종 목표는 웹으로 구현하지만 추후 PWA를 적용하여 웹앱의 기능을 수행하도록 할 예정이다.
프로젝트 도메인에 연결이 될 때, 모바일인지 웹인지 감지하고 그에 따라 다른 레이아웃을 보여줘야하므로 react-device-detect
패키지를 사용하여 DeviceDetect.tsx
파일을 구성하였다.
import { isMobile } from 'react-device-detect';
import BottomNav from '../components/BottomNav';
interface Children {
children: React.ReactNode;
}
function DeviceDetect({ children }: Children) {
return isMobile ? (
<div className='relative w-full h-full'>
{children}
<BottomNav />
</div>
) : (
<div className='w-screen h-screen bg-gradient-to-r from-cyan-500 to-blue-500 bg-cover bg-no-repeat bg-fixed'>
<div className='fixed w-[391px] h-[836px] right-1/2 top-1/2 translate-x-1/2 -translate-y-1/2 bg-slate-600 rounded-2xl overflow-hidden'>
<div className='absoulte w-full h-full max-w-[375px] max-h-[812px] translate-x-2 rounded-3xl overflow-hidden translate-y-3 bg-white'>
<div className='absoulte w-full h-full rounded-3xl overflow-scroll no-scrollbar'>
{children}
</div>
<BottomNav />
</div>
</div>
</div>
);
}
export default DeviceDetect;
가비아에서 프로젝트에 사용할 도메인을 구입하였다.
새로 S3 버킷을 생성하고 Cloudfornt, Route 53을 통한 웹 호스팅을 하였고,
CI/CD 부분도 yml 파일을 수정하여 자동 배포까지 확인을 마쳤다.
추후에 어떤 식으로 구성했는지 정리를 하여 포스팅을 할 에정이다.
리팩토링에 너무 힘쓰지 말라는 멘토님의 말씀도 있었지만, 약간 병적으로 clean code를 쓰기 위해 노력한다.
무지성으로 기능을 뽑아낼 수 있지만, 나중에 후회하게 될 게 분명해 보였고 이러한 습관을 들이는 게 나쁘지 않다고 생각한다.
axios instance 생성부분, api부분을 나누고 redux module에는 apis 폴더에서 해당 api만 가져오면 동작하게 구성했다.
분명 지금의 내 코드가 완벽하다고는 할 수 없다. 하지만 이게 어제, 오늘의 나에겐 최선이었고 실력이 쌓이면서 더 나은 코드 한 줄을 쓰기 위해 노력하는 사람이 되겠다.
이번 주(5/9-5/15)는 프로젝트 구성을 위한 기본적인 것들을 많이 진행했고, axios 통신을 이용한 서버 통신, 소셜로그인 인증을 구현하였다. 같은 팀원분은 커뮤니티 부분을 맡아주시고 현재 카카오 Maps API를 공부 중이시다.
약간 느린 감이 없지 않아 있다. 수요일에 기획 멘토링 시간에 구현된 것을 보여드리고, 토요일에 중간 발표가 있는데, MVP(Minimum Viable Product, 최소 기능 제품) 구성에 힘을 쏟아야겠다.
너무 조급해하지 말자 생각하고 있다. 매일 최선을 다하며,
그 하루 하루가 쌓여 더 나은 내일의 내가 되길 바란다.