EUC-KR 인코딩 하기

설명

iOS에서 EUC-KR로 인코딩 하는 문제가 프로젝트를 진행하면서 오랜 시간동안 Warning을 발생시켜서 눈에 가시처럼 보였는데 해결방안을 찾아서 포스팅 하게 되었습니다. 일단 먼저 EUC-KR(EUC-KR은 KS X 1001와 KS X 1003을 사용하는 8비트 문자 인코딩, EUC의 일종이며 대표적인 한글 완성형 인코딩이기 때문에 보통 완성형이라고 불린다. - 위키백과사전) 말그대로 한글 완성형 인코딩이기 때문에 오랜 시간 사용해왔습니다. 네이버,네이트,우체국등 오래된 한국기업 웹페이지는 EUC-KR로 되어있습니다. UTF-8을 사용하면 좋겠지만 용량문제, 전환비용등 때문인지 아직도 사용되고 있습니다. 특히 우체국 API를 통해 주소 검색을 구현할때는 쿼리를 EUC-KR로 인코딩 해서 보내야 올바른 값을 받을 수 있습니다.
기존에 사용 하고 있던 이 방식은 안타깝게도 iOS9버전 부터는 Warning을 발생시킵니다. iOS9에서는 더 이상 사용되지 않기 때문에 권장 UTF-8인코딩을 사용하라는 것입니다.

 NSString *queryString = [str stringByAddingPercentEscapesUsingEncoding:-2147481280];

    //first deprecated in iOS 9.0 - Use -stringByAddingPercentEncodingWithAllowedCharacters: instead, which always uses the recommended UTF-8 encoding, and which encodes for a specific URL component or subcomponent since each URL component or subcomponent has different rules for what characters are valid.

포기하고 있다가 다른분을 도와주다가 우연찮게 찾아서 이렇게 포스팅을 하게되었습니다.


사용환경

* Swift3.x
* Xcode 8.3.3

소스 코드

  • Objective-C
- (NSString *)euckrEncodingObjectiveC:(NSString *)str {

    NSMutableString *outputQuery = [NSMutableString string];

    NSUInteger encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingEUC_KR);
    const char * source = [str cStringUsingEncoding:encoding];
    NSInteger sourceLen = strlen((const char *)source);

    for (int i = 0; i < sourceLen; ++i)
    {
        const unsigned char thisChar = source[i];
        if (thisChar == ' ') {
            [outputQuery appendString:@"+"];
        } else if (thisChar == '.' || thisChar == '-' || thisChar == '_' ||
                 (thisChar >= 'a' && thisChar <= 'z') ||
                 (thisChar >= 'A' && thisChar <= 'Z') ||
                 (thisChar >= '0' && thisChar <= '9'))
        {
            [outputQuery appendFormat:@"%c", thisChar];
        } else {
            [outputQuery appendFormat:@"%%%02X", thisChar];
        }
    }
    return outputQuery;
}
  • Swift
func euckrEncoding(_ query: String) -> String { //EUC-KR 인코딩

    let rawEncoding = CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(CFStringEncodings.EUC_KR.rawValue))
    let encoding = String.Encoding(rawValue: rawEncoding)

    let eucKRStringData = query.data(using: encoding) ?? Data()
    let outputQuery = eucKRStringData.map {byte->String in
        if byte >= UInt8(ascii: "A") && byte <= UInt8(ascii: "Z")
            || byte >= UInt8(ascii: "a") && byte <= UInt8(ascii: "z")
            || byte >= UInt8(ascii: "0") && byte <= UInt8(ascii: "9")
            || byte == UInt8(ascii: "_") || byte == UInt8(ascii: ".") || byte == UInt8(ascii: "-")
        {
            return String(Character(UnicodeScalar(UInt32(byte))!))
        } else if byte == UInt8(ascii: " ") {
            return "+"
        } else {
            return String(format: "%%%02X", byte)
        }
        }.joined()

    return outputQuery
}

마치며

EUC-KR보다 UTF-8을 권장하지만 아직 한국내에서는 불가능한거 같습니다. 위에도 언급해듯이 전환비용, 용량문제등 아직 해결할 문제들이 많은거 같습니다. 오랫동안 눈에 밟히던 Warning을 없앤것만으로도 기분 좋은 일인거 같습니다. 틀린점이나 궁금한점이 있다면 댓글 남겨주시면 감사합니다 :)


참고 사이트

https://stackoverflow.com/questions/41270687/swift-euc-kr-korean-encoding-not-working-but-works-in-python



+ Recent posts