우선 타이포 그래피란 위키백과에서도 볼 수 있듯 정해진 글꼴과 서체를 정하는 것이다.
타이포 그래피 관련해서 적용하며 실패한 케이스 공유와 최종 적용한 케이스에 대한 설명을 하겠습니다.
먼저 실패했던 케이스를 공유하겠다.
import styled from 'styled-components';
const weight = {
Bold: 700,
Medium: 500,
Regular: 400,
Default: 400
};
const size = {
XL: '1.5rem',
L: '1.125rem',
M: '1rem',
S: '0.938rem',
XS: '0.875rem',
XXS: '0.75rem'
};
const font = {
pretendard: 'Pretendard Variable'
};
const Body = styled.div`
font-family: ${font.pretendard};
font-size: ${(props) => {
switch (props.size) {
case 'XL':
return size.XL;
case 'L':
return size.L;
}
}};
font-weight: ${(props) => {
switch (props.size) {
case 'XL':
return weight.XL;
case 'L':
return weight.L;
}
}}; `;
export default Body;
// components
<HDS.Body size="XL" weight="XL" />
첫번째 생각으로 만든 케이스이다.
스위치 케이스문으로 styled-components내 사용하여 사용할 때 HDS.Body컴퍼넌트에 props를 넘겨 타이포를 적용했다.
위의 타이포그래피의 문제는 스위치 케이스 문이다 보니 조합이 가능하다는 점이다. 타이포 그래피는 단순한 앞으로 반복적으로 사용되는 "정해진"글꼴과 서체를 정의하는 취지와는 맞지 않다고 생각했다. 결론으로 의도한 타이포그래픽 규칙보다 더 많은 타이포그래피 케이스가 생성가능하다는 점이다.
import styled from 'styled-components';
const weight = {
Bold: 700,
Medium: 500,
Regular: 400,
Default: 400
};
const size = {
XL: '1.5rem',
L: '1.125rem',
M: '1rem',
S: '0.938rem',
XS: '0.875rem',
XXS: '0.75rem'
};
const font = {
pretendard: 'Pretendard Variable'
};
const Body = {
XlBold = styled.div`
font-family: ${font.pretendard};
font-weight: ${weight.Bold};
font-size: ${size.XL};
`,
LRegular = styled.div`
font-family: ${font.pretendard};
font-weight: ${weight.Regular};
font-size: ${size.L};
`,
XXSRegular = styled.div`
font-family: ${font.pretendard};
font-weight: ${weight.Regular};
font-size: ${size.XXS};
`,
}
export default Body;
// components
<HDS.Body.XLBold />
실제 여러 레퍼런스를 보면서 타이포그래피 적용사례를 볼 때 가장 많이 보았던 구조이다.
하나하나의 타이포그래피를 일일히 선언하여 사용하며 적용할 때 props를 받는 형태가 아닌 단순 서체를 지정하는 식이다. <HDS.Body.XLBold>와 같이
여기서 문제는 2가지이다.
const Body = {
XlBold = styled.div`
font-family: ${font.pretendard};
font-weight: ${weight.Bold};
font-size: ${size.XL};
@media all and (max-width: 800px) {
font-family: ${font.pretendard};
font-weight: ${weight.Medium};
font-size: ${size.L};
} `,
}
만약 타이포그래피에서 위와같이 Body.XLBold를 사용하면 무조건 모바일 웹 경우는 Body.LMedium이 된다고 정해져도 문제는 있다. 역시 가독성이다.
컴퍼넌트명은 <Body.XLBold>를 사용하는데 모바일웹의 경우 Body.LMedium이 되는 것이다. 가독성이 이미 좋지 않은데 더 안좋아진다. 그렇다고 아래와 같이 코드 구조로 작성을 해야하나?
const Body = {
XlBold = styled.div`
${(props) => props.XLBold}
@media all and (max-width: 800px) {
${(props) => props.LMedium}
}
`, }
이러면 컴퍼넌트에서는 아래와 같이 호출하게 될 것이다.
<HDS.BodyXLBold props={HDS.BodyLMedium} />
실제 사용해본 결과 진짜 불편하다. 그리고 만약 HDS.BodyXLBold가 모웹인 경우 HDS.HeadingXXSMedium으로 변해야한다면...?
그러면 다른 스타일 객체의 size와 weight가 필요하게되니 전역에 모든 객체별 size, weight를 선언해서 사용해야한다. 타이포를 한번 쓰는데 3~4개의 컴퍼넌트가 동작해야 한다는 것이다. 개인적인데 위의 방식으로 타이포그래피를 사용해야한다면 안쓰고싶었다. 너무 불편하다 생각했고 이로인해 개발 생산성역시 떨어진다 판단했다.
사실 결론적으로 적용한 타이포그래피를 보면 너무 단순해서 힘이 빠진다. 위에서 처음 말했듯 타이포그래피의 정의는 정해진 글꼴과 서체를 그냥 적용하면 그만이다.
즉, 그냥 리터럴 객체를 선언해서 필요시 해당 객체를 불러와 사용하면 그만이였다.
const weight = {
Bold: 700,
Medium: 500,
Regular: 400,
Default: 400
};
const size = {
XL: '1.5rem',
L: '1.125rem',
M: '1rem',
S: '0.938rem',
XS: '0.875rem',
XXS: '0.75rem'
};
const font = {
'font-family': Pretendard Variable
};
const Body = {
XlBold: {
'letter-spacing': '-0.4px',
'font-weight': `${weight.Bold}`,
'font-size': `${size.XL}`,
'font-family': `${font['font-family']}`
},
XlMedium: {
'letter-spacing': '-0.4px',
'font-weight': `${weight.Medium}`,
'font-size': `${size.XL}`,
'font-family': `${font['font-family']}`
},
LMedium: {
'letter-spacing': '-0.4px',
'font-weight': `${weight.Medium}`,
'font-size': `${size.L}`,
'font-family': `${font['font-family']}`
} };
export default Body;
보시다시피 단순 리터럴 객체들이다. 이렇게 적용 결과 실제 어떻게 사용되는지 확인해보자
import * as HDS from '/HDS/typoGraphy/index';
import styled form "styled-components"
<S.PriceText price="5000" {...props} />
const S = {
PriceText: styled.div`
${HDS.Body.MBold}
@media all and (max-width: 800px) {
${HDS.Heading.XXSRegular}
}
`
}
위에서 계속 언급했던 가독성, 규칙 범위를 넘어감, 모바일 웹인 경우를 포함해 유지보수와 같은 문제점들까지 해결되었다.