2017년 12월 18일 월요일

나눔스퀘어 글꼴에서는 안보이는 글자들

요즘 만들고 있는 웹어플리케이션에서 나눔스퀘어를 한글의 기본 글꼴로 사용하고 있다. 그런데 최종테스트 중에 특정 글자가 보이지 않는다는 결함이 발생해서 그 원인과 해결책을 블로그로 남긴다.

1.
결함의 내용은 이러했다.
한자 입력하면 글자색이 흰색이라 보이지 않음
"넫넫"  등 잘못된 한글 입력해도 글자색이 흰색으로 보임
한자를 입력하거나 넫넫을 입력해봤더니 정말 보이지 않는 것이었다. 이게 뭔가라는 생각에 나눔스퀘어 사이트에서 입력을 해보았더니 여기서도 보이지 않게 된다!



이번에는 "덜거덕"을 입력해보았다. "덜거덕"을 입력하려다 보면, "덝"까지만 입력한 상태가 만들어지는데, 이때 "덝"글자가 보이지 않게된다.



이럴수가! 나눔스퀘어 글꼴에 뭔가 문제가 있을 거라고 생각하고 글꼴 파일을 파헤쳐보기 시작했다.


2.
나눔스퀘어 글꼴은 "꼭 필요한 2,350자만을 추렸기" 때문에 한자나 "넫"같은 글자가 제외되어 만들어진 것이다. 그런데 제외된 글자들이 글꼴 파일에서도 제외되어야 브라우저가 다른 글꼴로 표시할 텐데, 실제로 제외하지 않고 투명한 글자로 포함시켜서 만들어진 것이 문제였다.

글꼴의 상세한 내용을 볼 수 있는 FontForge로 나눔스퀘어 글꼴 파일의 내용을 열어보면 이렇다. 가운데에 파란색으로 선택된 부분이 "덝"글자가 표시되는 자리이다. 그런데 다른 여러 빈 공간처럼 "덝"부분도 비어있다. 즉, 나눔스퀘어 글꼴이 "덝"글자를 빈 공간으로 표시하는 것이다.


다른 글꼴 중에도 2350자만 추려서 "경량화"된 글꼴이 존재한다. 최근에 글꼴과 관련되어 좋은 글이 여러번 올라와 알게된 스포카한산스도 그 중 하나이다.  아래 캡쳐를 자세히 보면 "덝"에 해당하는 부분이 붉은색 X 표시되어 있어서, 글꼴 파일에 포함되지 않은 것을 알 수 있다.










참고로 경량화 되지 않은 글꼴은 아래와 같이 모든 문자가 포함되어 있다.










3.
결국 나눔스퀘어가 실제로는 포함하지 않는 2350자 이외의 문자에 대해서 실제 파일에서도 포함하지 않도록 하는 것이 해결책이라고 할 수 있겠다.

우선 나눔스퀘어에 포함된 2350자가 명확하게 어떤 글자들인지 그 목록이 명시되어 있지 않지만, 일반적으로 완성형 한글의 2350자일 것이라 추측했다. 그리고 실제 완성형 한글의 2350자의 목록은 나무위키에서 얻을 수 있었다.

2350자만 추출하여 새로운 글꼴 파일을 만들어내는 방법을 통해서 투명한 글자가 생기지 않도록 새로운 나눔스퀘어 글꼴 파일을 만들 수 있었다. 그리고 2350자가 올바르게 추출되었는지를 확인하기 위해 SIL ViewGlyph를 이용해서 글꼴에 포함된 글자의 수를 확인했다.


4.
이 문제를 나눔스퀘어 글꼴이 가지고 있다는 것을 어딘가에 알려주고 싶은데, 알려줄 방법이 없다.


2017년 12월 3일 일요일

spring boot + gradle + proguard + 실행가능한 jar

spring boot + gradle + proguard를 사용하여 웹어플리케이션의 실행가능한 jar를 만드는 방법을 소개한다.


1.
spring boot를 사용하면 보통 gradle을 빌드도구로 사용하게 되고, 웹어플리케이션을 만들 때 보통 실행가능한 jar를 만들어서 쓰곤 한다. 아래와 같이 build.gradle을 구성하고 gradle assemble 명령어로 실행가능한 jar를 만든다.

buildscript {
    repositories {
     mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.8.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'

springBoot {
    executable = true
} 

2.
만들어진 jar를 보면 BOOT-INF/clesses에 내가 만든 클래스들이, BOOT-INF/lib에 내가 사용하는 라이브러리들이 포함된다.

여기서 내가 만든 클래스들을 proguard로 난독화를 적용하고 싶으면 proguard가 제공하는 gradle 플러그인을 이용하면 손쉽게 만들수 있다.

buildscript {
    repositories {
     mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.8.RELEASE")
        classpath("net.sf.proguard:proguard-gradle:5.3.3")
    }
}

def proguardJarPath = jar.archivePath.absolutePath.replace(".jar", "-proguard.jar")

task proguard(type: proguard.gradle.ProGuardTask, dependsOn: jar) {
    configuration "proguard.conf"

    injars jar.archivePath.absolutePath
    outjars proguardJarPath

    libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
    libraryjars project.configurations.compile
}


3.
그런데 난독화된 jar를 실행가능한 jar에 포함시키려면 gradle 설정이 조금 더 필요하다. 실행가능한 jar를 만드는 gradle의 spring boot 플러그인의 bootRepackage 태스크가 사용하게 되는 jar를 난독화된 jar로 바꿔줘야 한다.

bootRepackage {
 withJarTask = proguardJar
}

이때 withJarTask에 대입이 가능한 값은 Jar 타입의 gradle 태스크여야 한다. ProGuardTask는 Jar 타입이 아니다. 그래서 proguardJar라고 내가 만든 Jar 타입의 태스크가 필요하다. 이미 난독화된 jar 파일이 있으므로 zipTree로 파일 구조를 유지하면서 새로운 jar 파일을 만들어야 한다.

task proguardJar(type: Jar, overwrite: true, dependsOn: proguard) {
 from zipTree(proguardJarPath)
}

4.
다 합치면 아래와 같은 gradle 설정이 된다.