병원관련 웹 기능 추가 및 수정

공부는 혼자하는 거·2021년 11월 20일
0

업무

목록 보기
4/15

요구사항

개발완료된 병원 관련 웹 소프트웨어에서 기능 추가해달라는 요청사항이 들어왔다. 요청 사항은 크게 7가지였다.

  1. 기존의 블락킹이 걸리던 AI 분석요청을 비동기로 처리요구
  2. 비동기로 처리된 진행상황은 UI로 프로그레스바 표시
  3. 진행 상황은 클라이언트의 입장이 아니라 서버의 입장. 각각의 클라이언트가 브라우저로 5개의 요청을 보내면 서버 입장에서 표시되기 때문에 화면단에서 total 개수 10으로 표시
  4. 기존의 분석요청시 이미지 파일을 Base64 인코딩해서 쿼리스트링으로 보냈던 것을 multipart-Form 형식으로 바이너리 파일로 전송
  5. Dicom에서 이미지 추출포맷을 jpg로 변경
  6. selectBox 전체선택 기능 추가
  7. 서버 재부팅 시 NSSM 을 사용해 배치파일을 만들어 서비스 자동재시작

https://warpgate3.tistory.com/entry/java-jar-윈도우-서비스-등록하기

기존의 프로젝트는 springboot + jsp 형식으로 만들어졌다. 분석요청은 rest를 통해서 flask 서버와 통신해 그 결과를 불러와서 프로그레스바 진행상황을 업데이트하면 되었다. 간단한 기능추가 요구사항이었지만 개발환경이 갖추어지지 않아서 무척 고생을 했다. 환자 리스트를 불러와서, 분석요청을 해야되는데, 기존 연결된 병원 oracle DB는 현재상황에서 원격으로 접속할 수 없는 상황이었다.

가짜 테스트 DB를 만들어내서 병원 스키마 구조와 비슷하게 덤프를 떠서 작업 중, 계속 난항을 겪다가 결국에 운영계 DB와 직접 연결할 수 있는 환경의 서버에 원격접속하여 작업하는 것으로 변경됐다. (Chrome 원격데스트탑,mstsc ) 운영계 DB를 직접 건드린다는 게 부담스러웠고, 실제로 실수로 select를 제외한 쿼리문을 날려서 그쪽에 롤백을 문의하기도 했지만, 커다란 문제점이 없다고 답변하여 다행이었다.

개발과정

  1. 분석요청을 날리던 service layer의 method를 비동기 처리하였다.

  2. 프로그레스바 진행 상황을 표시하기 위해 전역변수로 Arraylist와 Interger를 만들었다. 비동기로 처리되기 때문에 threadSafe한 자료구조로 선언하였다. 원래는 진행상황을 표시할 DB Table을 하나 더 만들려고 했는데 그건 오바같아서 그냥 전역변수로 선언하였다.

  3. 뷰단에서 분석요청 버튼을 클릭하면 ajax로 컨트롤러를 때리고, 컨트롤러는 비동기 서비스 메서드를 호출하는 식인데, 컨트롤러를 때리면 바로 그 인자를 전역리스트에 넣고, 호출된 개수를 total로 숫자에 저장하였다. 그리고 바로 리턴

  4. 비동기 메서드 안에서는 rest 호출하고 그 결과값이 정상이면 추가된 전역리스트 값을 삭제, 아니라면 예외를 던짐

  5. 이렇게 변경되는 값들을 sse 프로토콜을 활용해 뷰단에 전달. 뷰단은 이벤트소스를 리스닝해 받은 값들을 가공해 UI 프로그레스바로 표시

헤맸던 사안

  1. SseEmitter를 활용하여 서버에서 뷰로 단방향 통신을 하였는데, 전역 변수만 thread safe한 구조로 생각 중이다가 sseemitter 자체는 그런 구조로 설계를 못 하였다. 브라우저가 새로고침되거나, 새로 들어갈때마다 새로운 객체가 생성되는데 만료가 된 sseemitter 객체를 삭제할떄 exception이 터졌음. synchronized 메서드를 사용해 해결
  2. 파일을 multipart-from 형식으로 보낼때, postman으로 테스트하는 방법을 몰라서 고민, 진짜 별거 아니지만 생각보다 시간이 걸렸다..

  1. 비동기 스레드로 분석요청을 하는 중 결과값으로 에러코드를 리턴받으면 예외상황이 터지도록 설계를 하였는데, @RestControllerAdvice 에서 예외를 낚아채지 못하는 상황. 조사해보니 비동기 예외처리는 AsyncUncaughtExceptionHandler 라는 인터페이스를 상속받은 객체를 등록해줘야지 낚아챌 수 있었다.

  2. 예외처리를 낚아채는 데는 성공했지만 이걸 다시 ServerSentEvent를 활용해서, 뷰단에 전달하는데는 실패. 시간을 꽤 많이 소모한 결과 AsyncUncaughtExceptionHandler 라는 인터페이스를 상속받은 객체를 @ApplicationScope 으로 등록해주어 해결하였다. bean의 scope과 관련된 문제로 보이는데 뭔가 감은 잡히는데 정확하게 이유는 파악하지 못했다.

  3. 기존 코드는 이미지를 생성할때, JPEGImageEncoder 를 사용하였는데, maven install 하여 war 파일로 압축하는 과정에서 문제가 생김. 표준 API가 아니라서 인식을 못하는 문제가 발생했다. ImageIo로 대체

  4. jai_imageio-1_0_01-lib-windows-i586-jdk 를 사용하여 자바8 32 bit 에 등록하고 dicom 파일을 변환하는데, 이것도 buildpath에 등록하지 못해서 com.sun.image.codec.jpeg.JPEGImageEncoder를 찾지 못하였다. 배포시에 꼭 자바 풀경로 적어주고, buildpath도 명확하게 설정함으로써 해결하였다.

profile
시간대비효율

0개의 댓글