React용 천지인 + 영문 + 숫자 + 기호 커스텀 키보드 컴포넌트
스마트폰 천지인 키보드를 웹앱, PWA 같은 환경에서도 쓸 수 있도록 만든 가상 키보드입니다.
(공모전 파트너 단체에서 “수중에서 모바일 키보드가 너무 작아 기록이 힘들다”는 피드백을 받고 시작한 프로젝트입니다.)
- 장갑을 끼거나, 물속/현장 환경처럼 작은 쿼티 키보드를 누르기 어려운 상황,
- 모바일 브라우저에서 기본 키보드를 숨기고 화면 안에 큰 키보드를 띄우고 싶은 경우,
- 특정 입력 칸에서만 천지인 전용 입력 UX를 제공하고 싶은 경우
에 기본 키패드 대신 사용할 수 있도록 설계되었습니다.
|
|
|
|
npm install react-cji-keyboard
# 또는
yarn add react-cji-keyboard이 라이브러리는 입력 상태를 내부에서 관리하면서 onChange(text: string) 콜백으로 완성된 문자열을 돌려줍니다.
TypeScript 프로젝트에서는 index.d.ts를 통해 자동으로 타입이 인식되고, JS/JSX 환경에서도 동일한 코드로 사용할 수 있습니다.
import { useState } from "react";
import CheonjiinKeyboard from "react-cji-keyboard";
import "react-cji-keyboard/style.css"; // ★ 기본 CSS
function App() {
const [value, setValue] = useState("");
return (
<div style={{ maxWidth: 420, margin: "0 auto", padding: 16 }}>
<h1>천지인 키보드 데모</h1>
{/* 실제 입력을 보여줄 필드 (readOnly로 두고 onChange로만 갱신) */}
<textarea
value={value}
readOnly
rows={3}
style={{
width: "100%",
borderRadius: 8,
border: "1px solid #ddd",
padding: "8px 10px",
marginBottom: 12,
whiteSpace: "pre-wrap",
}}
placeholder="천지인 키보드로 입력해보세요"
/>
{/* 가상 키보드 */}
<CheonjiinKeyboard onChange={setValue} />
</div>
);
}
export default App;JS/JSX 프로젝트에서도 동일한 코드를 사용할 수 있고,
TypeScript에서는onChange인자와value가 자동으로string타입으로 추론됩니다.
export interface CheonjiinKeyboardProps {
value?: string;
onChange?: (text: string) => void;
className?: string;
}
declare const CheonjiinKeyboard: React.FC<CheonjiinKeyboardProps>;
export default CheonjiinKeyboard;- 키보드에서 글자가 바뀔 때마다 호출됩니다.
- 한글/영문/숫자/기호를 모두 포함한 현재 전체 문자열이 인자로 넘어옵니다.
보통 이렇게 사용합니다:
const [text, setText] = useState("");
return (
<>
<textarea value={text} readOnly />
<CheonjiinKeyboard onChange={setText} />
</>
);- 키보드의 값을 바깥에서 직접 관리하고 싶을 때 사용합니다.
- 예를 들어, 상위 컴포넌트에서 상태를 들고 있다가
onChange로 받은 값을 다시 넣어주는 식으로 씁니다:
const [text, setText] = useState("");
return (
<CheonjiinKeyboard
value={text}
onChange={setText}
/>
);value를 지정하지 않으면, 키보드가 자기 내부에서 값 상태를 관리하면서onChange로 결과만 알려줍니다.- 리셋 버튼으로 값 지우기, 다른 입력 컴포넌트와 값 공유하기 등
외부에서 값에 간섭해야 할 때
value를 함께 사용하는 패턴이 편합니다.
- 키보드 최상위 래퍼에 추가로 클래스명을 붙이고 싶을 때 사용합니다.
- 예를 들어, 화면 하단에 붙는 바텀시트 스타일로 쓰고 싶다면:
<CheonjiinKeyboard
onChange={setText}
className="fixed inset-x-0 bottom-0 border-t bg-white"
/>처럼 프로젝트에서 사용하는 CSS / Tailwind 클래스와 함께 조합해서 쓸 수 있습니다.
기본 스타일은 style.css 에 정의된 CSS 클래스 기반입니다.
프로젝트에서 같은 클래스 이름을 다시 정의하면 손쉽게 테마를 변경할 수 있습니다.
.cheon-keyboard– 키보드 전체 래퍼.cheon-grid– 5열(또는 4열) 그리드 레이아웃.cheon-grid--english– 영문 모드에서 4열 그리드.cheon-key– 기본 키 스타일.cheon-key--func– 기능 키 (한/영, 123, 기호, 백스페이스 등).cheon-key--space– 스페이스 키.cheon-key--enter– 엔터 키.cheon-key--empty– 비워두는 자리용 키
/* global.css 또는 App 전체에 적용되는 CSS에서 */
.cheon-keyboard {
background: #020617;
padding: 12px;
border-radius: 16px 16px 0 0;
}
/* 모든 키 공통 스타일 */
.cheon-key {
background: #111827;
color: #e5e7eb;
border-radius: 10px;
border: 1px solid #1f2937;
font-size: 16px;
}
/* 기능 키(한/영, 123, 기호, 백스페이스 등) 강조 */
.cheon-key--func {
background: #1f2937;
color: #f9fafb;
}
/* 스페이스바 크게/연하게 */
.cheon-key--space {
background: #0f172a;
color: #e5e7eb;
font-size: 14px;
}이렇게 하면 라이브러리 기본 스타일 위에 덮어씌워져,
레이아웃 구조는 그대로 유지하면서 색감/테마만 바꿀 수 있습니다.
import CheonjiinKeyboard from "react-cji-keyboard";
import "react-cji-keyboard/style.css";
function BottomSheetKeyboard({ open, value, onChange }) {
return (
<div
className={`fixed inset-x-0 bottom-0 transition-transform duration-200
${open ? "translate-y-0" : "translate-y-full"}`}
>
<div className="mx-auto max-w-sm bg-white rounded-t-2xl shadow-xl p-3">
<textarea
value={value}
readOnly
className="w-full mb-2 p-2 rounded-md border text-sm"
/>
<CheonjiinKeyboard onChange={onChange} />
</div>
</div>
);
}


