QR 코드
QR 코드 (QRCode)
텍스트를 QR 코드로 변환해 보여 주는 컴포넌트예요. URL이나 데이터를 스캔 가능한 QR 코드 이미지로 렌더링해요.
출처: 문서
본문
언제 사용하나요 (When To Use)
- 텍스트를 QR 코드로 변환해야 할 때 사용해요.
예시 (Examples)
기본 (base)
기본 사용법이에요.
import React from 'react';
import { Input, QRCode, Space } from 'antd';
const App: React.FC = () => {
const [text, setText] = React.useState('https://ant.design/');
return (
<Space vertical align="center">
<QRCode value={text || '-'} />
<Input
placeholder="-"
maxLength={60}
value={text}
onChange={(e) => setText(e.target.value)}
/>
</Space>
);
};
export default App;
아이콘과 함께 (With Icon)
아이콘이 있는 QRCode예요.
import React from 'react';
import { QRCode } from 'antd';
const App: React.FC = () => (
<QRCode
errorLevel="H"
value="https://ant.design/"
icon="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
/>
);
export default App;
다른 상태 (other status)
status 값으로 상태를 제어할 수 있어요. active, expired, loading, scanned 네 가지 값이 제공돼요.
import React from 'react';
import { Flex, QRCode } from 'antd';
const value = 'https://ant.design';
const App: React.FC = () => (
<Flex gap="medium" wrap>
<QRCode value={value} status="loading" />
<QRCode value={value} status="expired" onRefresh={() => console.log('refresh')} />
<QRCode value={value} status="scanned" />
</Flex>
);
export default App;
커스텀 상태 렌더 (custom status render)
statusRender 값으로 상태별 QR 코드 렌더링 로직을 제어할 수 있어요.
import React from 'react';
import { CheckCircleFilled, CloseCircleFilled, ReloadOutlined } from '@ant-design/icons';
import type { QRCodeProps } from 'antd';
import { Button, Flex, QRCode, Space, Spin } from 'antd';
const value = 'https://ant.design';
const customStatusRender: QRCodeProps['statusRender'] = (info) => {
switch (info.status) {
case 'expired':
return (
<div>
<CloseCircleFilled style={{ color: 'red' }} /> {info.locale?.expired}
<p>
<Button type="link" onClick={info.onRefresh}>
<ReloadOutlined /> {info.locale?.refresh}
</Button>
</p>
</div>
);
case 'loading':
return (
<Space vertical>
<Spin />
<p>Loading...</p>
</Space>
);
case 'scanned':
return (
<div>
<CheckCircleFilled style={{ color: 'green' }} /> {info.locale?.scanned}
</div>
);
default:
return null;
}
};
const App: React.FC = () => (
<Flex gap="medium" wrap>
<QRCode value={value} status="loading" statusRender={customStatusRender} />
<QRCode
value={value}
status="expired"
onRefresh={() => console.log('refresh')}
statusRender={customStatusRender}
/>
<QRCode value={value} status="scanned" statusRender={customStatusRender} />
</Flex>
);
export default App;
커스텀 렌더 타입 (Custom Render Type)
type으로 렌더링 결과를 커스터마이즈해요. canvas와 svg 옵션을 제공해요.
import React from 'react';
import { QRCode, Space } from 'antd';
const App: React.FC = () => (
<Space>
<QRCode type="canvas" value="https://ant.design/" />
<QRCode type="svg" value="https://ant.design/" />
</Space>
);
export default App;
커스텀 크기 (Custom Size)
크기를 직접 지정해요.
import React, { useState } from 'react';
import { MinusOutlined, PlusOutlined } from '@ant-design/icons';
import { Button, QRCode, Space } from 'antd';
const MIN_SIZE = 48;
const MAX_SIZE = 300;
const App: React.FC = () => {
const [size, setSize] = useState<number>(160);
const increase = () => {
setSize((prevSize) => {
const newSize = prevSize + 10;
if (newSize >= MAX_SIZE) {
return MAX_SIZE;
}
return newSize;
});
};
const decline = () => {
setSize((prevSize) => {
const newSize = prevSize - 10;
if (newSize <= MIN_SIZE) {
return MIN_SIZE;
}
return newSize;
});
};
return (
<>
<Space.Compact style={{ marginBottom: 16 }}>
<Button onClick={decline} disabled={size <= MIN_SIZE} icon={<MinusOutlined />}>
Smaller
</Button>
<Button onClick={increase} disabled={size >= MAX_SIZE} icon={<PlusOutlined />}>
Larger
</Button>
</Space.Compact>
<QRCode
errorLevel="H"
size={size}
iconSize={size / 4}
value="https://ant.design/"
icon="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
/>
</>
);
};
export default App;
커스텀 색상 (Custom Color)
색을 직접 지정해요.
import React from 'react';
import { QRCode, Space, theme } from 'antd';
const { useToken } = theme;
const App: React.FC = () => {
const { token } = useToken();
return (
<Space>
<QRCode value="https://ant.design/" color={token.colorSuccessText} />
<QRCode
value="https://ant.design/"
color={token.colorInfoText}
bgColor={token.colorBgLayout}
/>
</Space>
);
};
export default App;
QR 코드 다운로드 (Download QRCode)
QRCode를 다운로드하는 방법이에요.
import React from 'react';
import { Button, QRCode, Segmented, Space } from 'antd';
import type { QRCodeProps } from 'antd';
function doDownload(url: string, fileName: string) {
const a = document.createElement('a');
a.download = fileName;
a.href = url;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
const downloadCanvasQRCode = () => {
const canvas = document.getElementById('myqrcode')?.querySelector<HTMLCanvasElement>('canvas');
if (canvas) {
const url = canvas.toDataURL();
doDownload(url, 'QRCode.png');
}
};
const downloadSvgQRCode = () => {
const svg = document.getElementById('myqrcode')?.querySelector<SVGElement>('svg');
const svgData = new XMLSerializer().serializeToString(svg!);
const blob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });
const url = URL.createObjectURL(blob);
doDownload(url, 'QRCode.svg');
};
const App: React.FC = () => {
const [renderType, setRenderType] = React.useState<QRCodeProps['type']>('canvas');
return (
<Space id="myqrcode" vertical>
<Segmented options={['canvas', 'svg']} value={renderType} onChange={setRenderType} />
<div>
<QRCode
type={renderType}
value="https://ant.design/"
bgColor="rgba(255,255,255,0.5)"
style={{ marginBottom: 16 }}
icon="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
/>
<Button
type="primary"
onClick={renderType === 'canvas' ? downloadCanvasQRCode : downloadSvgQRCode}
>
Download
</Button>
</div>
</Space>
);
};
export default App;
오류 수준 (Error Level)
오류 수준을 설정해요.
import React, { useState } from 'react';
import type { QRCodeProps } from 'antd';
import { QRCode, Segmented } from 'antd';
const App: React.FC = () => {
const [level, setLevel] = useState<QRCodeProps['errorLevel']>('L');
return (
<>
<QRCode
style={{ marginBottom: 16 }}
errorLevel={level}
value="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
/>
<Segmented options={['L', 'M', 'Q', 'H']} value={level} onChange={setLevel} />
</>
);
};
export default App;
고급 사용법 (Advanced Usage)
Popover와 함께 사용해요.
import React from 'react';
import { Button, Popover, QRCode } from 'antd';
const App: React.FC = () => (
<Popover content={<QRCode value="https://ant.design" bordered={false} />}>
<Button type="primary">Hover me</Button>
</Popover>
);
export default App;
시맨틱 DOM 스타일링 (Custom semantic dom styling)
classNames와 styles로 객체나 함수를 전달해 QRCode의 시맨틱 DOM 스타일을 커스터마이즈할 수 있어요.
import React from 'react';
import { Flex, QRCode } from 'antd';
import type { GetProp, QRCodeProps } from 'antd';
import { createStaticStyles } from 'antd-style';
const classNames = createStaticStyles(({ css }) => ({
root: css`
border: 1px solid #ccc;
border-radius: 8px;
padding: 16px;
`,
}));
const stylesObject: QRCodeProps['styles'] = {
root: {
border: '2px solid #1890ff',
borderRadius: 8,
padding: 16,
backgroundColor: 'rgb(24, 144, 255, 0.1)',
},
};
const stylesFunction: QRCodeProps['styles'] = (info): GetProp<QRCodeProps, 'styles', 'Return'> => {
if (info.props.type === 'canvas') {
return {
root: {
border: '2px solid #ff4d4f',
borderRadius: 8,
padding: 16,
backgroundColor: 'rgba(255, 77, 79, 0.1)',
},
};
}
};
const App: React.FC = () => {
const sharedProps: QRCodeProps = {
value: 'https://ant.design/',
size: 160,
classNames,
};
return (
<Flex gap="medium">
<QRCode {...sharedProps} styles={stylesObject} />
<QRCode
{...sharedProps}
type="canvas"
icon="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
styles={stylesFunction}
/>
</Flex>
);
};
export default App;
API
공통 props는 Common props를 참고해요.
이 컴포넌트는
[email protected]부터 사용할 수 있어요.
| 속성 (Property) | 설명 (Description) | 타입 (Type) | 기본값 (Default) | 버전 (Version) | 글로벌 설정 |
|---|---|---|---|---|---|
| value | 스캔될 텍스트 | string | string[] |
- | string[]: 5.28.0 |
× |
| type | 렌더 타입 | canvas | svg |
canvas |
5.6.0 | × |
| icon | 포함할 이미지 URL (이미지 링크만 지원돼요.) | string | - | - | × |
| size | QRCode 크기 | number | 160 | - | × |
| iconSize | 포함할 이미지 크기 | number | { width: number; height: number } | 40 | 5.19.0 | × |
| color | QRCode 색 | string | #000 |
- | × |
| classNames | 컴포넌트 내부의 각 시맨틱 구조에 대한 class를 지정해요. 객체 또는 함수를 지원해요. | Record<SemanticDOM, string> | (info: { props })=> Record<SemanticDOM, string> | - | 6.0.0 | 6.0.0 |
| bgColor | QRCode 배경색 | string | transparent |
5.5.0 | × |
| marginSize | 조용한 영역(Quiet zone) 크기(모듈 단위). 0은 여백 없음을 의미해요. |
number | 0 |
6.2.0 | × |
| bordered | 테두리 스타일 여부 | boolean | true | - | × |
| errorLevel | 오류 수준 | 'L' | 'M' | 'Q' | 'H' |
M |
- | × |
| boostLevel | 활성화하면 결과의 오류 수정 수준이 지정한 값보다 높아질 수 있어요. | boolean |
true | 5.28.0 | × |
| status | QRCode 상태 | active | expired | loading | scanned |
active |
scanned: 5.13.0 | × |
| statusRender | 커스텀 상태 렌더 | (info: StatusRenderInfo) => React.ReactNode | - | 5.20.0 | × |
| styles | 컴포넌트 내부의 각 시맨틱 구조에 대한 인라인 스타일을 지정해요. 객체 또는 함수를 지원해요. | Record<SemanticDOM, CSSProperties> | (info: { props })=> Record<SemanticDOM, CSSProperties> | - | 6.0.0 | 6.0.0 |
StatusRenderInfo
type StatusRenderInfo = {
status: QRStatus;
locale: Locale['QRCode'];
onRefresh?: () => void;
};
시맨틱 DOM (Semantic DOM)
시맨틱 DOM 구조는 https://ant.design/components/qr-code/semantic.md 에서 확인할 수 있어요.
디자인 토큰 (Design Token)
글로벌 토큰 (Global Token)
| 토큰 이름 (Token Name) | 설명 (Description) | 타입 (Type) | 기본값 (Default Value) |
|---|---|---|---|
| borderRadiusLG | LG 크기 테두리 반경이에요. Card, Modal 등 큰 테두리 반경을 가진 컴포넌트에 사용돼요. | number | |
| colorSplit | 구분자 색으로 사용돼요. colorBorderSecondary와 같은 색이지만 투명도를 가져요. | string | |
| colorText | W3C 표준을 따르는 기본 텍스트 색이에요. 가장 어두운 중성색이기도 해요. | string | |
| colorWhite | 테마에 의해 변경되지 않는 순수한 흰색 | string | |
| controlHeight | Ant Design에서 버튼, 입력 상자 같은 기본 컨트롤의 높이 | number | |
| fontFamily | Ant Design의 글꼴은 시스템의 기본 인터페이스 글꼴을 우선시하고, 화면 표시에 적합한 대체 글꼴 라이브러리를 제공해 플랫폼과 브라우저에 따라 가독성을 유지하며 친근하고 안정적이며 전문적인 특성을 반영해요. | string | |
| fontSize | 디자인 시스템에서 가장 널리 쓰이는 글자 크기로, 여기서 텍스트 그라데이션이 파생돼요. | number | |
| lineHeight | 텍스트의 줄 높이예요. | number | |
| lineType | 기본 컴포넌트의 테두리 스타일 | string | |
| lineWidth | 기본 컴포넌트의 테두리 두께 | number | |
| marginXS | 작은 크기의 요소 여백을 제어해요. | number | |
| paddingSM | 요소의 작은 패딩을 제어해요. | number |
FAQ
QRCode 오류 수준에 대해 (About QRCode ErrorLevel)
오류 수준(ErrorLevel)은 QR 코드가 일부 가려져도 정상적으로 스캔될 수 있는 최대 가려진 면적, 즉 오류 수정률을 의미해요.
일반적으로 QR 코드는 4가지 오류 수정 수준으로 나뉘어요. 수준 L은 약 7%, 수준 M은 약 15%, 수준 Q는 약 25%, 수준 H는 약 30%의 오류를 수정할 수 있어요. QR 코드 콘텐츠에 담긴 정보가 적을 때, 즉 value 링크가 짧을 때는 오류 수정 수준을 다르게 설정해도 생성된 이미지가 달라지지 않아요.
더 자세한 내용은 다음을 참고해요: https://www.qrcode.com/en/about/error_correction
⚠️⚠️⚠️ QR 코드를 스캔할 수 없나요?
QR 코드를 인식할 수 없다면 링크 주소가 너무 길어 픽셀이 너무 촘촘해졌기 때문일 수 있어요.
size로 QR 코드를 더 크게 설정하거나, 단축 링크 서비스로 링크를 줄여 보세요.