개발완료된 병원 관련 웹 소프트웨어에서 기능 추가해달라는 요청사항이 들어왔다. 요청 사항은 크게 7가지였다.
https://warpgate3.tistory.com/entry/java-jar-윈도우-서비스-등록하기
기존의 프로젝트는 springboot + jsp 형식으로 만들어졌다. 분석요청은 rest를 통해서 flask 서버와 통신해 그 결과를 불러와서 프로그레스바 진행상황을 업데이트하면 되었다. 간단한 기능추가 요구사항이었지만 개발환경이 갖추어지지 않아서 무척 고생을 했다. 환자 리스트를 불러와서, 분석요청을 해야되는데, 기존 연결된 병원 oracle DB는 현재상황에서 원격으로 접속할 수 없는 상황이었다.
가짜 테스트 DB를 만들어내서 병원 스키마 구조와 비슷하게 덤프를 떠서 작업 중, 계속 난항을 겪다가 결국에 운영계 DB와 직접 연결할 수 있는 환경의 서버에 원격접속하여 작업하는 것으로 변경됐다. (Chrome 원격데스트탑,mstsc ) 운영계 DB를 직접 건드린다는 게 부담스러웠고, 실제로 실수로 select를 제외한 쿼리문을 날려서 그쪽에 롤백을 문의하기도 했지만, 커다란 문제점이 없다고 답변하여 다행이었다.
분석요청을 날리던 service layer의 method를 비동기 처리하였다.
프로그레스바 진행 상황을 표시하기 위해 전역변수로 Arraylist와 Interger를 만들었다. 비동기로 처리되기 때문에 threadSafe한 자료구조로 선언하였다. 원래는 진행상황을 표시할 DB Table을 하나 더 만들려고 했는데 그건 오바같아서 그냥 전역변수로 선언하였다.
뷰단에서 분석요청 버튼을 클릭하면 ajax로 컨트롤러를 때리고, 컨트롤러는 비동기 서비스 메서드를 호출하는 식인데, 컨트롤러를 때리면 바로 그 인자를 전역리스트에 넣고, 호출된 개수를 total로 숫자에 저장하였다. 그리고 바로 리턴
비동기 메서드 안에서는 rest 호출하고 그 결과값이 정상이면 추가된 전역리스트 값을 삭제, 아니라면 예외를 던짐
이렇게 변경되는 값들을 sse 프로토콜을 활용해 뷰단에 전달. 뷰단은 이벤트소스를 리스닝해 받은 값들을 가공해 UI 프로그레스바로 표시
SseEmitter를 활용하여
서버에서 뷰로 단방향 통신을 하였는데, 전역 변수만 thread safe한 구조로 생각 중이다가 sseemitter 자체는 그런 구조로 설계를 못 하였다. 브라우저가 새로고침되거나, 새로 들어갈때마다 새로운 객체가 생성되는데 만료가 된 sseemitter 객체를 삭제할떄 exception이 터졌음. synchronized
메서드를 사용해 해결비동기 스레드로 분석요청을 하는 중 결과값으로 에러코드를 리턴받으면 예외상황이 터지도록 설계를 하였는데, @RestControllerAdvice
에서 예외를 낚아채지 못하는 상황. 조사해보니 비동기 예외처리는 AsyncUncaughtExceptionHandler
라는 인터페이스를 상속받은 객체를 등록해줘야지 낚아챌 수 있었다.
예외처리를 낚아채는 데는 성공했지만 이걸 다시 ServerSentEvent를 활용해서, 뷰단에 전달하는데는 실패. 시간을 꽤 많이 소모한 결과 AsyncUncaughtExceptionHandler
라는 인터페이스를 상속받은 객체를 @ApplicationScope
으로 등록해주어 해결하였다. bean의 scope과 관련된 문제로 보이는데 뭔가 감은 잡히는데 정확하게 이유는 파악하지 못했다.
기존 코드는 이미지를 생성할때, JPEGImageEncoder 를 사용하였는데, maven install 하여 war 파일로 압축하는 과정에서 문제가 생김. 표준 API가 아니라서 인식을 못하는 문제가 발생했다. ImageIo로 대체
jai_imageio-1_0_01-lib-windows-i586-jdk 를 사용하여 자바8 32 bit 에 등록하고 dicom 파일을 변환하는데, 이것도 buildpath에 등록하지 못해서 com.sun.image.codec.jpeg.JPEGImageEncoder를 찾지 못하였다. 배포시에 꼭 자바 풀경로 적어주고, buildpath도 명확하게 설정함으로써 해결하였다.