2024. 7. 27. 21:14ㆍ카테고리 없음
최근에 면접 대비 사이트를 만들면서 TTS 기능이 필요해졌습니다. 그래서 TTS 기능을 제공하는 자바스크립트 내장 객체인 SpeechSynthesisVoice를 이용하여 구현을 했습니다. 이후에 동료 개발자 분과 얘기를 나누면서 해당 함수를 npm 라이브러리로 배포해보면 좋을 것 같다 라는 말을 듣고 해당 함수를 npm에 라이브러리로 배포하였습니다. 이 포스트에서는 라이브러리의 코드 설명부터 npm에 배포하는 전체 과정을 단계별로 안내해드리겠습니다.
*면접 대비 사이트 주소: https://dmmhn-next-js.vercel.app/
1. getSpeech 함수 설명
getSpeech 함수는 주어진 텍스트를 한국어로 음성 출력하는 기능을 제공합니다. 주요 기능은 다음과 같습니다:
- 사용 가능한 음성 목록을 가져와서 한국어 음성을 찾습니다.
- 음성 합성 중에 기존 음성을 중지하고 새로운 음성을 시작합니다.
- 음성 시작 및 종료 시 상태를 업데이트합니다.
// getSpeech 함수는 주어진 텍스트를 음성으로 변환하여 재생하는 기능을 제공한다.
export const getSpeech = (text: string) => {
// 음성 합성에 사용할 음성 목록을 저장할 배열과 현재 음성 재생 상태를 나타내는 변수를 선언한다.
let voices: SpeechSynthesisVoice[] = [];
let isSpeaking = false;
// setVoiceList 함수는 사용 가능한 음성 목록을 가져와 voices 배열에 저장한다.
const setVoiceList = () => {
voices = speechSynthesis.getVoices();
};
// 음성 목록이 변경될 때 setVoiceList 함수를 호출하도록 이벤트 핸들러를 설정한다.
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = setVoiceList;
}
// 초기화 시도: 음성 목록을 동기적으로 가져와 voices 배열에 저장한다.
setVoiceList();
// speech 함수는 주어진 텍스트를 음성으로 변환하여 재생한다.
const speech = (text: string) => {
// 기존에 재생 중인 음성을 중지하고 isSpeaking 상태를 false로 설정한다.
speechSynthesis.cancel();
isSpeaking = false;
// 사용할 언어를 한국어로 설정한다.
const lang = "ko-KR";
// 주어진 텍스트를 음성으로 변환하기 위한 SpeechSynthesisUtterance 객체를 생성한다.
const utterThis = new SpeechSynthesisUtterance(text);
// 언어 설정
utterThis.lang = lang;
// 한국어 음성을 찾는다. (언어 코드가 "ko-KR" 또는 "ko_KR"인 음성을 찾는다)
const kor_voice = voices.find((elem) => elem.lang === lang || elem.lang === lang.replace("-", "_"));
// 한국어 음성이 존재하면 해당 음성을 설정하고, 그렇지 않으면 함수 종료
if (kor_voice) {
utterThis.voice = kor_voice;
} else {
return;
}
// 음성 재생이 시작될 때 isSpeaking 상태를 true로 설정한다.
utterThis.onstart = () => {
isSpeaking = true;
};
// 음성 재생이 끝날 때 isSpeaking 상태를 false로 설정한다.
utterThis.onend = () => {
isSpeaking = false;
};
// 음성 재생을 시작한다.
speechSynthesis.speak(utterThis);
};
// 음성 목록이 이미 로드되었으면 바로 텍스트를 말하도록 호출한다.
if (voices.length > 0) {
speech(text);
} else {
// 음성 목록이 아직 로드되지 않았으면, 음성 목록이 변경될 때 텍스트를 말하도록 설정한다.
speechSynthesis.onvoiceschanged = () => {
setVoiceList();
speech(text);
};
}
};
2. 해당 라이브러리 사용 방법
npm에서 해당 라이브러리를 install 합니다.
npm install @striker1826/use-tts
사용할 파일에서 import를 해준 뒤 getSpeech 함수에 음성으로 변환할 문자열을 parameter로 넘겨주면 끝입니다.
import { getSpeech } from '@striker1826/use-tts';
getSpeech('Hello!');
3. 브라우저 호환성
이 함수는 브라우저 환경에서만 작동합니다. Node.js 환경에서는 window 객체와 speechSynthesis API가 없기 때문에 작동하지 않습니다.
4. npm 배포방법
4-1. 패키지 이름 중복 체크
배포를 위한 초기 설정 전에 내가 배포하려는 패키지의 이름과 동일한 패키지가 없는 지 확인해야 한다.
npm info 패키지명
배포된 패키지가 없을 경우에는 아래와 같이 뜬다.
npm ERR! code E404
npm ERR! 404 Not Found - GET https://registry.npmjs.org/패키지명 - Not found
npm ERR! 404
npm ERR! 404 '패키지명' is not in this registry.
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.
4-2. npm 정보 입력
npm init
위 코드를 터미널에 입력하면 package.json을 생성할 수 있다.
이때, 절차대로 정보를 작성하고 싶지 않다면 -y나 --yes 플래그를 사용하여 기본 템플릿이 작성된 package.json을 생성할 수 있다.
나는 npm init으로 아래의 절차대로 정보를 작성했다.
- package name: 배포할 패키지명
package name: @striker1826/use-tts
- description: 패키지에 대한 간략한 설명
description: An npm library that reads text aloud as it is typed.
- entry point: 패키지의 시작점. 다른 프로젝트에서 import할 수 있는 파일 경로. useCalendar는 빌드된 폴더인 dist의 index.js를 접근 포인트로 둔다.
entry point: dist/use-tts.js
- test command: 패키지의 테스트를 실행하는 명령 (나는 테스트 코드가 없어 비워두었다.)
- git repository: 소스코드가 있는 git 저장소. 필수 항목은 아니나, 패키지 사용자들이 소스코드를 쉽게 찾아볼 수 있도록 도움을 줄 수 있다.
git repository: https://github.com/striker1826/use-tts.git
- keywords: 패키지와 관련된 키워드author: 패키지를 만든 사람의 정보. 이름과 이메일 주소를 작성할 수 있다.
author: minseobKim <alstjq123579@daum.net>
- license: 라이센스. 패키지 소스의 활용 범위에 대한 제약을 둘 수 있다.
license: MIT
위 절차대로 작성했을 때, 아래의 package.json 파일이 생성된다. 위에서 언급했듯 절차대로 작성하는 것이 불편하다면 기본 package.json 생성한 뒤 원하는 포맷을 작성하면 된다. package.json의 필드에 대한 설명이 필요하다면 package.json - npmjs을 읽어보자.
{
"name": "@striker1826/use-tts",
"version": "1.0.7",
"description": "An npm library that reads text aloud as it is typed.",
"main": "dist/use-tts.js",
"scripts": {
"build": "rm -rf ./dist && tsc",
"prepare": "npm run build"
},
"repository": {
"type": "git",
"url": "git+https://github.com/striker1826/use-tts.git"
},
"keywords": [
"react",
"hooks",
"tts",
"typescript",
"react-hook"
],
"author": "minseobKim <alstjq123579@daum.net>",
"license": "MIT",
"bugs": {
"url": "https://github.com/striker1826/use-tts/issues"
},
"homepage": "https://github.com/striker1826/use-tts#readme",
}
4-3. npmignore 작성
git에 업데이트할 파일을 제외하는 .gitignore처럼 npm 배포시 제외할 .npmignore 파일이 있다. .npmignore 파일을 작성하자.
# npm
node_modules/
# dev
src
.gitignore
tsconfig.json
# GIT
.git
- package.json에 의존성을 추가해두었으니 node_modules를 제외하고,
- build된 dist 폴더를 배포하는 것이기 때문에 개발에 필요했던 src 폴더를 제외한다.
- .gitignore와 tsconfig.json 또한 개발과정에 필요한 폴더이므로 제거하고,
- git으로 버전 관리를 하고 있기 때문에 생성된 .git 또한 제거한다.
4-4. 배포시 build 관련 설정 추가
npm 배포 명령어를 입력하면 프로젝트가 새롭게 build 되도록 package.json의 scripts를 수정한다.
{
"scripts": {
"build": "rm -rf ./dist && tsc",
"prepare": "npm run build"
}
}
prepare 명령을 사용하여 패키지를 패키징하기 전에 필요한 작업을 수행하는 것으로, 배포 명령어인 npm publish 명령을 실행하면 prepare가 실행된다.
따라서,
- 배포 명령어를 실행하면, prepare가 실행되고 npm run build를 호출한다.
- build가 실행되면 기존 dist 폴더를 삭제하고 tsc 명령어로 타입스크립트 컴파일을 수행한다.
- tsconfig.json의 outDir 옵션으로 ./dist를 지정했기 때문에, 컴파일이 완료되면 새로운 dist 폴더를 생성한다.
4-5. npm 계정 생성 및 로그인
npm 배포를 위해서는 npm 로그인이 필요하다.
- npm 회원가입 페이지에서 회원가입을 하고,
- 로컬의 터미널에서 npm login을 입력한다.
- 터미널에 Press ENTER to open in the browser... 라는 메세지가 표시되면 Enter 키를 누른다.
- npm 회원가입 시 입력한 이메일 주소로 일회성 비밀번호가 발송된다. 이를 브라우저에 뜨는 로그인 창에 입력한다.
- 브라우저에서 로그인이 완료되면 로컬 터미널에 Logged in on https://registry.npmjs.org/. 메시지가 출력된다.
- 로컬 터미널에서 npm whoami 명령을 입력하여 본인의 아이디를 확인한다.
드디어, 배포
패키지를 public으로 배포할 건지, private으로 배포할 건지에 따라 배포 명령어가 다르다.
npm publish
위 명령어는 private으로 배포할 때 사용된다.
나는 public으로 배포할 것이기 때문에 아래 명령어를 입력했다.
npm publish --access public
npm info 명령어나 npm 사이트로 배포가 완료되었는지 확인해보자.
마치며
이번 작업을 통해 TypeScript 환경에서의 React 커스텀 훅을 npm으로 배포하는 방법을 배웠다. 특히 타입스크립트 설정은 처음이라 어려움이 있었지만, .d.ts 파일과 타입스크립트 구성 옵션들에 대한 이해도를 높일 수 있었던 좋은 기회였다. 배포에 대한 두려움도 있었지만, 다른 배포도 빨리 해보고 싶다는 기대감이 생겼다. 프로젝트 배포나 컴포넌트 단위의 npm 배포도 해보고 싶다.