본문 바로가기

프로젝트

java script - 프로젝트 1 - 1. 영어 한글 변환기

아는 것과 할 줄 아는 것은 다르다고 합니다. 그리고 할 줄 아는지 체크하기 가장 좋은 방법은 직접 무언가를 만들어 보는 것이라 생각합니다. 여기서 ":무엇을 만들 것인가"가 정말 힘든데 저는 3가지 기준에 따라서 정합니다.

  1. 나에게 지금 당장 필요한 것이 무엇인가
  2. 취미와 관련된 무언가를 만들 수 있는가
  3. 지금 눈 앞에 있는 것을 클론코딩 할 수 있는가

wjsms vudthdp ejffjdrjflsms ausdl

저는 평소에 덜렁거리는 면이 있어서 가끔 한글로 써야 하는데 영어로 쓰거나 영어로 써야 하는데 한글로 쓰는 경우가 있습니다. 이런 경우 자동으로 한글과 영어를 바꿔주는 프로그램이 있으면 많이 편할 것 같네요. 한번 만들어 보겠습니다.

한글 -> 영어

한글을 영어로 바꾸는 것이 더 쉬워 보여서 이것부터 시작하겠습니다.

  1. 한글을 입력받는다
  2. 유니코드로 변환한다.
  3. 유니코드에 따라 영어로 출력한다.

간단히 생각하면 이런 구조가 될 것입니다.

1. 입력

입력은 자바스크립트 내장 라이브러리인 readline을 이용할 것입니다.

// 1. 라이브러리 가져오기
const readline = require('readline');

// 2. readline 객체 만들기. 터미널로 입출력을 할 수 있도록 세팅
const rl = readline.createInterface({
    input: process.stdin, // 터미널에서 입력
    output: process.stdout, // 터미널에 출력
});

// 3. 줄을 읽을 때 마다 실행되는 함수 만들기. answer에는 입력한 줄이 들어감
rl.on('line', (answer) => {
    console.log(answer);
  
    //한 줄 읽으면 바로 종료
    rl.close();
});

 

실행하면 다음과 같이 입출력을 할 수 있습니다.

 

2. 유니코드로 변환

"문자".charCodeAt(인덱스)

를 이용해 해당 인덱스의 문자를 유니코드로 변환해 줄 수 있습니다. 문자열을 쭉 보면서 유니 코드를 출력해 주면 됩니다. 

rl.on('line', (answer) => {

    for(char of answer){
        console.log(char.charCodeAt(0))
    }
    
    rl.close();
});

 

그럼 다음과 같은 결과가 나옵니다.

3. 영어 출력

여기가 제일 어려운 부분입니다. 유니코드는 12593(ㄱ)부터 12643(ㅣ)까지, 44032(가)부터 55203(힣)까지 있습니다.

(ㄱ)부터 (ㅣ)까지는 전부 손으로 처리해 줘야 합니다. (가)부터 (힣)까지는 글자를 자음, 모음으로 나누어 (ㄱ)부터 (ㅣ)까지 처리한 방법을 그대로 적용해 줍니다.

우선 (ㄱ)부터 (ㅣ)까지를 처리하겠습니다. 한글을 영어로 바꾸는 함수를 먼저 만듭니다.

let ko = ["ㄱ","ㄲ","ㄳ","ㄴ","ㄵ","ㄶ","ㄷ","ㄸ","ㄹ","ㄺ","ㄻ","ㄼ","ㄽ","ㄾ","ㄿ","ㅀ","ㅁ","ㅂ","ㅃ","ㅄ","ㅅ","ㅆ","ㅇ","ㅈ","ㅉ","ㅊ","ㅋ","ㅌ","ㅍ","ㅎ","ㅏ","ㅐ","ㅑ","ㅒ","ㅓ","ㅔ","ㅕ","ㅖ","ㅗ","ㅘ","ㅙ","ㅚ","ㅛ","ㅜ","ㅝ","ㅞ","ㅟ","ㅠ","ㅡ","ㅢ","ㅣ"]
let en = ["r","R","rt","s","sw","sg","e","E","f","fr","fa","fq","ft","fx","fv","fg","a","q","Q","qt","t","T","d","w","W","c","z","x","v","g","k","o","i","O","j","p","u","P","h","hk","ho","hl","y","n","nj","np","nl","b","m","ml","l"]
function koToEn(uni){
    uni = uni - 'ㄱ'.charCodeAt(0); // 해당 글자의 인덱스를 찾습니다.
    process.stdout.write(en[uni]); // 출력 마지막에 줄바꿈이 들어가지 않습니다.
}

 

그리고 (ㄱ)부터 (ㅣ)까지면 함수를 실행해 줍니다.

rl.on('line', (answer) => {

    for(char of answer){
        if(ko.includes(char)){
            koToEn(char.charCodeAt(0))
        }
    }

    rl.close();
});

 

이제 (가)부터 (힣)까지를 처리하겠습니다. (가)부터 (마)까지 출력해 보았습니다.

차이가 1176, 588, 1176, 588이 나고 있습니다. 아마 (가)와 (나), (다)와 (라) 사이에 뭔가 있는 것 같습니다. 44032부터588 간격으로 쭉 출력해 보겠습니다. String.fromCharCode()로 유니코드를 문자로 바꿀 수 있습니다.

전부 (ㅏ)로 끝이 나는 것을 보니 초성은 588 간격으로 바뀌는 것을 알 수 있습니다.

 

초성이 (ㄱ)인 글자들 중 200개를 출력해 봤습니다.

44060에서 중성이 처음 바뀝니다. 그럼 중성은 28 간격으로 바뀌는 것을 알 수 있습니다.

종성은 계속 바뀌고 있으니 1 간격으로 바뀝니다.

그럼 이제 나머지 연산을 이용해서 쉽게 계산해 줄 수 있습니다.

우선 koToEn의 함수명을 바꾸고 입력으로 한글을 받도록 수정합니다.

function singleKoToEn(ko){
    let uni = ko.charCodeAt(0) - 'ㄱ'.charCodeAt(0);
    process.stdout.write(en[uni]);
}

 

자음과 모음이 같이 오는 경우를 처리하는 함수를 만듭니다.

function multiKoToEn(ko){
    let first=["ㄱ","ㄲ","ㄴ","ㄷ","ㄸ","ㄹ","ㅁ","ㅂ","ㅃ","ㅅ","ㅆ","ㅇ","ㅈ","ㅉ","ㅊ","ㅋ","ㅌ","ㅍ","ㅎ"]
    let second=["ㅏ","ㅐ","ㅑ","ㅒ","ㅓ","ㅔ","ㅕ","ㅖ","ㅗ","ㅘ","ㅙ","ㅚ","ㅛ","ㅜ","ㅝ","ㅞ","ㅟ","ㅠ","ㅡ","ㅢ","ㅣ"]
    let third=["","ㄱ","ㄲ","ㄳ","ㄴ","ㄵ","ㄶ","ㄷ","ㄹ","ㄺ","ㄻ","ㄼ","ㄽ","ㄾ","ㄿ","ㅀ","ㅁ","ㅂ","ㅄ","ㅅ","ㅆ","ㅇ","ㅈ","ㅊ","ㅋ","ㅌ","ㅍ","ㅎ"]
    let uni = ko.charCodeAt(0) - '가'.charCodeAt(0);
    singleKoToEn(first[Math.floor(uni/588)]);
    singleKoToEn(second[Math.floor(uni%588/28)]);
    if(uni%28==0) return;
    singleKoToEn(third[Math.floor(uni%28)]);
}

 

이제 각 케이스마다 적절한 함수를 호출해 주면 됩니다.

rl.on('line', (answer) => {

    for(char of answer){
        if(char >= 'ㄱ' && char <= 'ㅣ'){
            singleKoToEn(char)
        }
        else if(char >= '가' && char <= '힣'){
            multiKoToEn(char)
        } else {
            process.stdout.write(char);
        }
    }

    rl.close();
});

 

결과

const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin, // 터미널에서 입력
    output: process.stdout, // 터미널에 출력
});

let ko = ["ㄱ","ㄲ","ㄳ","ㄴ","ㄵ","ㄶ","ㄷ","ㄸ","ㄹ","ㄺ","ㄻ","ㄼ","ㄽ","ㄾ","ㄿ","ㅀ","ㅁ","ㅂ","ㅃ","ㅄ","ㅅ","ㅆ","ㅇ","ㅈ","ㅉ","ㅊ","ㅋ","ㅌ","ㅍ","ㅎ","ㅏ","ㅐ","ㅑ","ㅒ","ㅓ","ㅔ","ㅕ","ㅖ","ㅗ","ㅘ","ㅙ","ㅚ","ㅛ","ㅜ","ㅝ","ㅞ","ㅟ","ㅠ","ㅡ","ㅢ","ㅣ"]
let en = ["r","R","rt","s","sw","sg","e","E","f","fr","fa","fq","ft","fx","fv","fg","a","q","Q","qt","t","T","d","w","W","c","z","x","v","g","k","o","i","O","j","p","u","P","h","hk","ho","hl","y","n","nj","np","nl","b","m","ml","l"]
function singleKoToEn(ko){
    let uni = ko.charCodeAt(0) - 'ㄱ'.charCodeAt(0);
    process.stdout.write(en[uni]);
}
function multiKoToEn(ko){
    let first=["ㄱ","ㄲ","ㄴ","ㄷ","ㄸ","ㄹ","ㅁ","ㅂ","ㅃ","ㅅ","ㅆ","ㅇ","ㅈ","ㅉ","ㅊ","ㅋ","ㅌ","ㅍ","ㅎ"]
    let second=["ㅏ","ㅐ","ㅑ","ㅒ","ㅓ","ㅔ","ㅕ","ㅖ","ㅗ","ㅘ","ㅙ","ㅚ","ㅛ","ㅜ","ㅝ","ㅞ","ㅟ","ㅠ","ㅡ","ㅢ","ㅣ"]
    let third=["","ㄱ","ㄲ","ㄳ","ㄴ","ㄵ","ㄶ","ㄷ","ㄹ","ㄺ","ㄻ","ㄼ","ㄽ","ㄾ","ㄿ","ㅀ","ㅁ","ㅂ","ㅄ","ㅅ","ㅆ","ㅇ","ㅈ","ㅊ","ㅋ","ㅌ","ㅍ","ㅎ"]
    let uni = ko.charCodeAt(0) - '가'.charCodeAt(0);
    singleKoToEn(first[Math.floor(uni/588)]);
    singleKoToEn(second[Math.floor(uni%588/28)]);
    if(uni%28==0) return;
    singleKoToEn(third[Math.floor(uni%28)]);
}


rl.on('line', (answer) => {

    for(char of answer){
        if(char >= 'ㄱ' && char <= 'ㅣ'){
            singleKoToEn(char)
        }
        else if(char >= '가' && char <= '힣'){
            multiKoToEn(char)
        } else {
            process.stdout.write(char);
        }
    }

    rl.close();
});

 

다음에 영어를 한글로 바꾸는 작업을 해 보겠습니다.