본문 바로가기
BackEnd/배포

[배포] Azure 발음 평가 사용시 SpeechConfig 초기화 오류

by 경험의 가치 2024. 5. 1.

 

외국 유학생들이 우리 대학 적응을 돕도록 만드는 앱 개발을 진행하고 있다.

해당 앱에 대해 궁금하면 외국민 Github를 참조 바란다.

 

우리 앱 기능 중에서, 외국인들이 한국에서 자주 쓰이는 표현, 발표 스크립트 발음을 평가해주는 기능이 존재한다. 그래서 이걸 어떻게 구현할까 찾던중, Microsoft에서 발음평가 API를 발견하였다. 그래서 Spring 서버에서 이 기능을 사용하여 구현하였다.

 

https://learn.microsoft.com/ko-kr/azure/ai-services/speech-service/

 

음성 서비스 설명서 - 자습서, API 참조 - Azure AI 서비스 - Azure AI services

음성을 인식하거나, 음성을 합성하거나, 실시간 번역을 받거나, 대화를 받아쓰거나, 음성을 봇 경험에 통합합니다.

learn.microsoft.com

 

하지만, local에서 분명히 잘됐음에도 불구하고, Docker로 띄워서 클라우드 서버에 올리니깐 아래와 같은 오류가 계속 발생했다.

 

Could not initialize class com.microsoft.cognitiveservices.speech.SpeechConfig

 

이유를 전혀 모르겠어서 한참 해맸다. 결론은 SDK 설치 설명서 안에 있었다.

 

 

위와 같이 Alpine Linux는 Debian 환경으로 만들어주는 작업이 필요했다. 우리 Spring의 Base Image가 eclipse-temurin:17-jdk:alpine이었다. 그래서 작동이 안됐던 것이다. 기존 DockerFile은 이랬다.

 

FROM eclipse-temurin:17-jdk-alpine AS build
WORKDIR /workspace/app

COPY . /workspace/app

RUN chmod +x ./gradlew
RUN --mount=type=cache,target=/root/.gradle ./gradlew clean bootJar
RUN mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*-SNAPSHOT.jar)

FROM eclipse-temurin:17-jdk-alpine
VOLUME /tmp
ARG DEPENDENCY=/workspace/app/build/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
RUN apk add tzdata

ENTRYPOINT ["java","-cp","app:app/lib/*","com.example.capstone.CapstoneApplication"]

 

그래서 base image를 alpine이 아닌걸로 바꿨다. 그런데 또 다른 문제가 발생했다. 참고로 Spring을 왜 이렇게 Build했는지에 대해서 궁금하면 Spring Multistaging Build   이 글에 내가 작성해놨으니 이거 봐주면 좋겠다.

 

 

설명서를 잘 보면, Ubuntu 22.04는 기본값이 OpenSSL 3.0인데, 이는 지원하지 않는다고 한다. 불행이도, eclipse-temurin:17-jdk는 Ubuntu 22.04이다. (제일 안정된 버전으로 가져오기 때문임) 따라서, Open SSL 1.1 버전을 까는 과정이 필요했다. 그래서 기존 DockerFile을 수정했다.

 

FROM eclipse-temurin:17-jdk AS download

WORKDIR /workspace/app

RUN wget http://www.openssl.org/source/openssl-1.1.1.tar.gz

FROM eclipse-temurin:17-jdk AS build
WORKDIR /workspace/app

COPY --from=download /workspace/app/openssl-1.1.1.tar.gz .

RUN apt-get update
RUN apt-get install -y tzdata build-essential ca-certificates libasound2 wget

RUN tar -xzvf openssl-1.1.1.tar.gz \
    && cd openssl-1.1.1 \
    && ./config \
    && make \
    && make install \
    && ldconfig

COPY . /workspace/app

RUN chmod +x ./gradlew
RUN --mount=type=cache,target=/root/.gradle ./gradlew clean bootJar
RUN mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*-SNAPSHOT.jar)

FROM eclipse-temurin:17-jdk
VOLUME /tmp
ARG DEPENDENCY=/workspace/app/build/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app

ENTRYPOINT ["java","-cp","app:app/lib/*","com.example.capstone.CapstoneApplication"]

 

SDK에서 기본으로 요구하는 패캐지들은 아래와 같다.

sudo apt-get update
sudo apt-get install build-essential libssl-dev ca-certificates libasound2 wget

 

여기서, libssl-dev만 wget을 통해서 따로 받아왔다. 그랬더니, SpeechConfig 오류 현상은 해결됐다.

 

 

하지만, 이제 다른 오류가 발생했다. 전부다 0점이 나왔다. 이유를 찾아야한다.

 

https://learn.microsoft.com/ko-kr/azure/ai-services/speech-service/how-to-use-logging 

 

Speech SDK 로깅 - Speech Service - Azure AI services

Speech SDK(C++, C#, Python, Objective-C, Java)에서 로깅을 사용하도록 설정하는 방법에 대해 알아봅니다.

learn.microsoft.com

 

위에 글을 보면, Speech SDK를 로깅하는 방법이 나와있다. 그래서, 로그를 한번 출력해보니...

 

[856528]: 212ms SPX_TRACE_ERROR: AZ_LOG_ERROR:  tlsio_openssl.c:691 error:1416F086:SSL 
routines:tls_process_server_certificate:certificate verify failed
[856528]: 212ms SPX_TRACE_ERROR: AZ_LOG_ERROR:  tlsio_openssl.c:2464 FORCE-Closing 
tlsio instance.
[856528]: 212ms SPX_TRACE_SCOPE_ENTER:  uws_web_socket.cpp:247 OnWebSocketOpened
[856528]: 212ms SPX_TRACE_ERROR:  web_socket.cpp:907 WS open operation failed with 
result=1(WS_OPEN_ERROR_UNDERLYING_IO_OPEN_FAILED), code=2573[0x00000a0d], 
time=2024-05-01T10:38:42.8680426Z
[856528]: 212ms SPX_TRACE_INFO:  usp_connection.cpp:933 TS:151, TransportError: 
connection:0x34021870, code=5, string=Connection failed (no connection to the remote host). 
Internal error: 1. Error details: Failed with error: WS_OPEN_ERROR_UNDERLYING_IO_OPEN_FAILED
wss://koreacentral.stt.speech.microsoft.com/speech/universal/v2
X-ConnectionId: 51c962ed10cc4e2bb07a9591eb582f6e
[856528]: 212ms SPX_TRACE_ERROR:  usp_reco_engine_adapter.cpp:2009 Response: On Error: 
Code:5, Message: Connection failed (no connection to the remote host). Internal error: 1. 
Error details: Failed with error: WS_OPEN_ERROR_UNDERLYING_IO_OPEN_FAILED

 

ssl 인증서 오류가 나서 Socket 통신이 진행되고 있지 않았다... 처음에는 통신이 안되니깐 방화벽 인바운드/아웃바운드 규칙 때문인줄 알았다. (AWS EC2에 올려서 사용중이기 때문에...) 그런데 확인을 해보니깐 이 부분은 전혀 문제가 없었다. 그래서 혹시 openssl이 제대로 설치가 안됐나..? 확인해보았다.

 

docker exec {container_name} openssl version

 

위 명령어를 통해 컨테이너 내부의 openssl version을 체크해보니, 3.0이 나오는 것이었다. 즉, open ssl 1.1.1이 제대로 설치되지 않았다는 것이다. 그래서, Docker File을 제정비 했다.

 

FROM eclipse-temurin:17-jdk AS download
WORKDIR /workspace/app
RUN wget https://www.openssl.org/source/openssl-1.1.1o.tar.gz

FROM eclipse-temurin:17-jdk AS build
WORKDIR /workspace/app

RUN apt-get update && apt-get remove -y openssl && apt-get install -y perl libfindbin-libs-perl build-essential zlib1g-dev

COPY --from=download /workspace/app/openssl-1.1.1o.tar.gz .
RUN tar -zxvf openssl-1.1.1o.tar.gz

WORKDIR /workspace/app/openssl-1.1.1o
RUN ./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl shared zlib
RUN make && make install

RUN apt-get update && apt-get install -y tzdata ca-certificates

COPY . /workspace/app
WORKDIR /workspace/app
RUN chmod +x ./gradlew
RUN --mount=type=cache,target=/root/.gradle ./gradlew clean bootJar
RUN mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*-SNAPSHOT.jar)

FROM eclipse-temurin:17-jdk
VOLUME /tmp

COPY --from=build /usr/local/ssl /usr/local/ssl

ARG DEPENDENCY=/workspace/app/build/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app

ENV PATH="/usr/local/ssl/bin:$PATH"
ENV LD_LIBRARY_PATH="/usr/local/ssl/lib:$LD_LIBRARY_PATH"
ENV SSL_CERT_DIR "/etc/ssl/certs"

ENTRYPOINT ["java", "-cp", "app:app/lib/*", "com.example.capstone.CapstoneApplication"]

 

Stackoveflow를 뒤지면서 oepn ssl을 다운그레이드 하는 법을 엄청 찾았다.

또한, Azure Speech Git Repo Issue를 하나하나 뒤져보았다.

 

https://github.com/Azure-Samples/cognitive-services-speech-sdk/issues/2276

 

OpenSSL Issue When Running Azure Speech (TTS) in GKE Container · Issue #2276 · Azure-Samples/cognitive-services-speech-sdk

(X posted from https://learn.microsoft.com/en-us/answers/questions/1599303/openssl-issue-when-running-azure-speech-(tts)-in-g?comment=question#newest-question-comment) Hey folks, I'm attempting to ...

github.com

 

이 글에서 참고하여 위에 같이 DockerFile을 재구성했고

 

 

정상적으로 결과가 나왔다!!! 몇일 밤새면서 겨우 고쳤다...

추후, 해당 API를 이용하여 개발하시는 분들을 위하여... 나처럼 고생하지 말라고 글을 써봤다.