FE 개발자의 기본적인 역량이라고 함은, 당연히 디자이너가 준 화면 설계를 그대로 구현해내는 Publishing 능력이 기본이라고 할 수 있다. 하지만 내가 의외로 남이 만든 디자인으로 퍼블리싱을 해본 적이 없다는 걸 깨닫고 해보는 퍼블리싱 프로젝트.
디자인은 피그마에서 Dmutro Tomashuk님이 만들어놓은 Flower Delivery Website를 가져와서 퍼블을 해보려고 한다. 이 콘텐츠가 내가 찾아봤을 때 제일 정리가 잘 되어있었고, 컴포넌트화가 분명하게 되어있어 개발자 입장에서 접근하기 편해보였다. 일단 내가 직접 디자인을 하지 않는다는 것부터 넘편안
먼저 이번 프로젝트를 하면서 목표를 설정한 것들이 있다.
1번은 한 번 잡아놓은 디자인에서 사소하게 바뀌는 디자인에 대응하기 위해서 필요하다. 예를 들어 같은 버튼인데 왼쪽에 아이콘이 들어가냐, 오른쪽에 아이콘이 들어가냐 같은, 아이콘 위치가 달라진다고 새로 코딩을 해야하는 불상사를 없애기 위함!
2번은 언젠가 한번 잡아야겠다 생각했던 건데, 이제서야 해본다. 웹에서 일관성을 나타내기 위해 가장 기본적인 것이 폰트인데, 이 폰트에 대해서 얼레벌레 넘어간 것들이 많아 이번에 확 잡으려고 한다.
3번은 반응형으로 만든 것은 많은데, 이에 대해서 그때그때 마다 느낌적인 느낌으로 갔기 때문에 정해진 구조가 없었다. 이번에 확실하게 잡고 싶은 마음이 크다.
가보자고!
나는 화면 디자인을 그래도 직접 짜본 적이 많아서 디자인에 들어가기 전에 어떤 걸 잡고 들어가야 하는지 대강 느끼고 있었기에, 먼저 그것부터 파악해보려고 한다. 그게 머냐면 ..
어디까지나 내 주관적인 기준이지만~ 이정도만 파악해놔도 통일감을 주는 요소들에 대해 파악할 수 있다. 그리구 이렇게 해놓으면 대충 디자인이 어떻게 생겨먹었는지 그려지니까, 나중에 디자이너가 아니라 내가 직접 화면 그려야 할 때가 오면(그런 경우가 안 오는 게 최고지만) 참고해서 쓱쓱 디자인도 가능하다.
아주 친절하게도(그리고 당연한) 폰트에 대한 스타일을 지정해주셨다.
크게 데탑+모바일로 나눠두셨고, 폰트는 Gilroy를 쓰셨다. Weight는 다 쓰지 않았고 Semibold, Medium, Regular만 썼다.
디자인에 쓰인 명암에 대해서도 명시해주셨다.
그레이스케일은 6개로 나누셨고, 상태는 성공/실패로만 나눠셨다. 흑백 사이트라 포인트 컬러가 없이 작업하셨나보다.
min-width 기준 데스크탑은 1440px, 타블렛은 768px, 모바일은 320px로 잡으셨다.
그리드 시스템을 쓰신 것 같긴 한데~ 박스에 대한 크기가 다 명시가 되어있어서 마진(Spacing)만 가져오면 될 것 같다. 보니까 컨테이너를 뷰포트 100%를 다 쓰더라고요.
아이콘은 Google Material UI에서 가져오신 것 같았다. 왼쪽은 W300, 오른쪽은 W400이다.
이제 디자인 분석을 끝냈으니 기본적인 프로젝트 설정을 해보자. 개발 환경은 언제나 그랬듯 React + Typescript + Vite + Tailwind~
yarn create vite
# 프로젝트 명: flower-delivery
# 언어: React
# Typescript + SWC
# package 설치
yarn
yarn add tailwindcss postcss autoprefixer -D
npx tailwindcss init -p
# prettier 설정
yarn add prettier prettier-plugin-tailwindcss -D
#.prettierrc
{ "plugins": ["prettier-plugin-tailwindcss"] }
먼저 폰트는 Gilroy를 기본으로 쓰고 있으므로, static 파일로 가져오도록 한다. 이때, 용량의 최적화를 위해서 ttf뿐만 아니라 woff2, woff로도 변환해서 로드하기로 한다.
이 링크에서 Gilroy 폰트를 다운로드 할 수 있다.
주의: Gilroy 폰트는 Light, ExtraLight에 대해서만 완전 Free이며, 개인적인 용도에 한해서 나머지도 무료이다. 이 폰트로 배포하고 싶으면 폰트 라이센스를 구입 후 사용해야 한다.
원래라면 TTF 파일을 WOFF, WOFF2로 각각 변환 후 한 폴더에 몰아 넣은 뒤 각각 Font-face를 만들어주는 작업을 해야겠지만,, 생각만으로도 귀찮은 작업이니까 Font-face Generator를 이용해보자.
이 링크에서 TTF 파일을 업로드하면 자동으로 변환 후 Font-Face CSS 파일까지 만들어준다! 개편해
우리는 Regular, Medium, Semibold만 필요하니까 이 폰트들만 골라주고, 밑 설정에서 TTF, WOFF, WOFF2를 체크, 폰트 폴더 경로까지 설정해 준 다음 Convert 버튼을 눌러주면 다음과 같이 변환된다.
@font-face {
font-family: "Gilroy";
src:
url("Gilroy-Regular.woff2") format("woff2"),
url("Gilroy-Regular.woff") format("woff"),
url("Gilroy-Regular.ttf") format("truetype");
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Gilroy";
src:
url("Gilroy-Medium.woff2") format("woff2"),
url("Gilroy-Medium.woff") format("woff"),
url("Gilroy-Medium.ttf") format("truetype");
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Gilroy";
src:
url("Gilroy-SemiBold.woff2") format("woff2"),
url("Gilroy-SemiBold.woff") format("woff"),
url("Gilroy-SemiBold.ttf") format("truetype");
font-weight: 600;
font-style: normal;
font-display: swap;
}
캬~
그렇지만 이대로 쓰기보다 local()을 추가해주는 것이 좋다. local()을 쓰면, 사용자가 이미 설치된 폰트라면 다운로드를 요청하지 않기 때문이다.
@font-face {
font-family: "Gilroy";
src:
local("Gilroy"),
url("Gilroy-Regular.woff2") format("woff2"),
url("Gilroy-Regular.woff") format("woff"),
url("Gilroy-Regular.ttf") format("truetype");
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Gilroy";
src:
local("Gilroy"),
url("Gilroy-Medium.woff2") format("woff2"),
url("Gilroy-Medium.woff") format("woff"),
url("Gilroy-Medium.ttf") format("truetype");
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Gilroy";
src:
local("Gilroy"),
url("Gilroy-SemiBold.woff2") format("woff2"),
url("Gilroy-SemiBold.woff") format("woff"),
url("Gilroy-SemiBold.ttf") format("truetype");
font-weight: 600;
font-style: normal;
font-display: swap;
}
좋다~
아참, 나는 font-display를 fallback이 아닌 swap으로 설정했다. 폰트가 제대로 안 나타나더라도 일단 내용을 표기하는 게 사용자에게 좋은 경험을 줄 수 있다고 생각하기 때문.
Font-face를 설정했으면 이제 tailwind에 요 font-family를 알려주자.
// tailwind.config.js
export default {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {
fontFamily: {
gilroy: "Gilroy",
},
},
},
plugins: [""],
};
그러면 이제 font-gilroy라는 클래스로 작성하면 해당 Element는 gilroy를 font-family로 가지게 된다 ^___^
기본적으로 사용할 컬러들을 따로 지정해주자. tailwind.config.js에 다음과 같이 추가하자.
// tailwind.config.js
export default {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {
colors: {
white: "#FFF",
extraLight: "#F5F5F7",
lightGray: "#D2D2D7",
gray: "#808080",
darkGray: "#424245",
black: "#121212",
succeess: "#32936F",
error: "#F55F56",
},
},
},
plugins: [""],
};
브랜드 컬러와 상태 컬러를 다 넣어주었다. extend가 아닌 theme 아래 바로 넣어줘도 상관 없겠지만(어차피 저 색상만 쓸거니) 혹시 몰라서 extend에 추가해주었다.
tailwind에서는 기본적으로 반응형에 대한 유틸리티 클래스를 제공하지만, 여기에서는 따로 추가해주기로 하자.
// tailwind.config.js
screens: {
mobile: "320px",
tablet: "768px",
desktop: "1440px",
},
마진 역시 정해진 것만 쓸 예정이니 따로 설정해주자. 이때, 모바일 기준과 타블렛 기준과 데스크톱에서의 vw 값이 다르니 요것만 신경써주자.
모바일은 320px기준, 타블렛은 768px, 데스크탑은 1440px 기준이다.
// tailwind.config.js
spacing: {
// Mobile
m8: "2.50vw",
m12: "3.75vw",
m16: "5.00vw",
m24: "7.50vw",
m32: "10.00vw",
m40: "12.50vw",
m48: "15.00vw",
m64: "20.00vw",
m80: "25.00vw",
// Tablet
t8: "1.04vw",
t12: "1.56vw",
t16: "2.08vw",
t24: "3.13vw",
t32: "4.17vw",
t40: "5.21vw",
t48: "6.25vw",
t64: "8.33vw",
t80: "10.42vw",
// Desktop
d8: "0.56vw",
d12: "0.83vw",
d16: "1.11vw",
d24: "1.67vw",
d32: "2.22vw",
d40: "2.78vw",
d48: "3.33vw",
d64: "4.44vw",
d80: "5.56vw",
}
여기는 으으음 안 해줘도 될 것 같긴 한데(컴포넌트 클래스를 만들 때 지정해주면 될 것 같아서) 그래도 만들어 놓으면 좋을 것 같다!
피그마에서 쓰이는 폰트 사이즈들을 미디어별로 설정해주자.
// tailwind.config.js
fontSize: {
// Mobile
m40: "12.50vw",
m34: "10.63vw",
m26: "8.13vw",
m22: "6.88vw",
m18: "5.63vw",
m16: "5.00vw",
m14: "4.38vw",
m12: "3.75vw",
// Tablet
t67: "8.72vw",
t50: "6.51vw",
t38: "4.95vw",
t28: "3.65vw",
t21: "2.73vw",
t18: "2.34vw",
t16: "2.08vw",
t14: "1.82vw",
t12: "1.56vw",
// Desktop
d67: "4.65vw",
d50: "3.47vw",
d38: "2.64vw",
d28: "1.94vw",
d21: "1.46vw",
d18: "1.25vw",
d16: "1.11vw",
d14: "0.97vw",
d12: "0.83vw",
}
그래. 하는 김에 leading(line-height)도 해주겠다 ...
// tailwind.config.js
lineHeight: {
140: "140%",
120: "120%",
100: "100%",
},
컴포넌트 클래스는 일종의 클래스의 조합이라고 보면 된다. 예를 들어, 피그마에서 Heading1 스타일은 다음과 같다.
타블렛과 데스크탑
모바일
타블렛과 데스크탑에서는 Size는 67px, Line Height는 120%, Weight는 Semibold인 것을 Heading1로 지정하고 있다. 모바일에서는 40px, 120%, Medium으로 지정하고 있다.
이걸 tailwind에서 컴포넌트 클래스로 만들면 다음과 같다.
@layer components {
.heading1 {
@apply text-m40 font-medium leading-120 tablet:text-t67 tablet:font-semibold desktop:text-d67;
}
}
tailwind는 mobile-first 디자인이라 모바일 스타일을 먹이고 미디어 대응을 해준다
... 이제 이걸 다 하면 된다.
@layer components {
.heading1 {
@apply text-m40 font-medium leading-120 tablet:text-t67 tablet:font-semibold desktop:text-d67;
}
.heading2 {
@apply text-m34 font-medium leading-120 tablet:text-t50 tablet:font-semibold desktop:text-d50;
}
.heading3 {
@apply text-m26 font-normal leading-120 tablet:text-t38 tablet:font-medium desktop:text-d38;
}
.heading4 {
@apply text-m22 font-normal leading-120 tablet:text-t28 tablet:font-medium desktop:text-d28;
}
.heading5 {
@apply text-m18 font-medium leading-120 tablet:text-t21 tablet:font-medium desktop:text-d21;
}
.heading6 {
@apply text-m16 font-medium leading-100 tablet:text-t16 tablet:font-medium tablet:leading-120 desktop:text-d16;
}
.subtitle {
@apply text-m18 font-medium leading-140 tablet:text-t18 tablet:font-medium tablet:leading-120 desktop:text-d18;
}
.body {
@apply text-m16 font-normal leading-140 tablet:text-t16 tablet:font-normal desktop:text-d16;
}
.button {
@apply text-m14 font-medium uppercase leading-100 tablet:text-t16 tablet:font-medium tablet:leading-120 desktop:text-d16;
}
.links {
@apply text-m14 font-medium leading-120 tablet:text-t16 tablet:font-medium desktop:text-d16;
}
.overline {
@apply text-m12 font-medium uppercase leading-120 tablet:text-t14 tablet:font-medium desktop:text-d14;
}
.caption {
@apply text-m14 font-normal leading-120 tablet:text-t14 tablet:font-normal desktop:text-d14;
}
.caption-small {
@apply text-m12 font-medium leading-120 tablet:text-t12 tablet:font-medium desktop:text-d12;
}
}
우우...
이번 포스팅은 디자인의 기초가 되는 스타일들을 정의하는 것으로 마무리! 다음 포스팅엔 UI 컴포넌트를 구현해보자.