검색

레이블이 Open Source인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Open Source인 게시물을 표시합니다. 모든 게시물 표시

2023년 8월 10일

코딩 - M1 환경에서 OpenCV 설치하기

◼︎ 환경
  • Model : MacBook Pro (14-inch, 2021)
  • CPU : Apple M1 Pro
  • MENORY : 16GB
  • DISK : 512 GB SSD
  • OS : macOS 13.2.4 (22F66)
  • TOOLS : Visual Studio Code, Java 11, Gradle, Docker
  • Version Control : GitHub
  • Programming Language : Java
  • Framework : Spring Boot 2.7.12
  • DBMS : MySql 8.0.33

M1 환경에서 OpenCV 을 컴파일하고 설치하는 것은 아래와 같은 순서로 진행한다.
  • Step 1: Homebrew and Xcode Command Line Tools Installation
  • Step 2: Install Miniforge
  • Step 3: Create a virtual environment with python3.8
  • Step 4: Install necessary dependencies
  • Step 5: Compile and Build OpenCV
 

Step 1: Homebrew and Xcode Command Line Tools Installation

❶ 다음 명령을 터미널에서 입력하여 brew 설치 여부를 확인한다.

brew --version

설치되어 있지 않는 경우 다음 명령을 터미널에 붙여넣기하여 설치를 진행한다.

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"


❷ brew 가 준비되면 wget (다운로드 유틸리티) , cmake (크로스 플랫폼 빌드 도구) 를 설치한다.

brew install wget cmake 


❸ 맥에서 지원하는 XCode Command Line 도구를 설치한다.

xcode-select --install


Step2: Install Miniforge

Miniforge는 가상 환경에서 Python 패키지 관리를 지원하는 Conda 설치을 위한 프로그램을 제공하고 있다. miniforge GitHub 에서 arm64(Apple Silicon) 용 버전을 설치한다. 




❶ 스크립트를 다운로드 하고 아래와 같이 bash 명령을 사용하여 터미널에서 설치를 진행한다.

bash Miniforge3-MacOSX-arm64.sh




❷ 설치가 완료되면 가이드에 따라 Conda 에서 제공하는 디폴트 환경을 비활성화 한다. 

conda config --set auto_activate_base false


Step3: Create a virtual environment with python3.8

❶ testcv 이름으로 python 3.8 버전의 가상 환경을 생성한다.

conda create --name testcv python=3.8

% conda create --name testcv python=3.8

Collecting package metadata (current_repodata.json): done

Solving environment: done



==> WARNING: A newer version of conda exists. <==

  current version: 23.1.0

  latest version: 23.7.2


Please update conda by running


    $ conda update -n base -c conda-forge conda


Or to minimize the number of packages updated during conda update use


     conda install conda=23.7.2




## Package Plan ##


  environment location: /miniforge3/envs/testcv


  added / updated specs:

    - python=3.8



The following packages will be downloaded:


    package                    |            build

    ---------------------------|-----------------

    ca-certificates-2023.7.22  |       hf0a4a13_0         146 KB  conda-forge

    openssl-3.1.2              |       h53f4e23_0         2.1 MB  conda-forge

    pip-23.2.1                 |     pyhd8ed1ab_0         1.3 MB  conda-forge

    python-3.8.17              |h3ba56d0_0_cpython        13.1 MB  conda-forge

    wheel-0.41.1               |     pyhd8ed1ab_0          56 KB  conda-forge

    ------------------------------------------------------------

                                           Total:        16.8 MB


The following NEW packages will be INSTALLED:


  bzip2              conda-forge/osx-arm64::bzip2-1.0.8-h3422bc3_4 

  ca-certificates    conda-forge/osx-arm64::ca-certificates-2023.7.22-hf0a4a13_0 

  libffi             conda-forge/osx-arm64::libffi-3.4.2-h3422bc3_5 

  libsqlite          conda-forge/osx-arm64::libsqlite-3.42.0-hb31c410_0 

  libzlib            conda-forge/osx-arm64::libzlib-1.2.13-h53f4e23_5 

  ncurses            conda-forge/osx-arm64::ncurses-6.4-h7ea286d_0 

  openssl            conda-forge/osx-arm64::openssl-3.1.2-h53f4e23_0 

  pip                conda-forge/noarch::pip-23.2.1-pyhd8ed1ab_0 

  python             conda-forge/osx-arm64::python-3.8.17-h3ba56d0_0_cpython 

  readline           conda-forge/osx-arm64::readline-8.2-h92ec313_1 

  setuptools         conda-forge/noarch::setuptools-68.0.0-pyhd8ed1ab_0 

  tk                 conda-forge/osx-arm64::tk-8.6.12-he1e0b03_0 

  wheel              conda-forge/noarch::wheel-0.41.1-pyhd8ed1ab_0 

  xz                 conda-forge/osx-arm64::xz-5.2.6-h57fd34a_0 



Proceed ([y]/n)? 



❷ 가상환경 생성이 완료되면 생성시 사용한 이름을 사용하여 가상환경을 활성화 한다.

conda activate testcv


info 옵션을 사용하여 활성화된 가상환경을 확인할 수 있다.

conda info 


Step4: Install necessary dependencies

OpenCV를 설치하려면 Apple에서 M1용으로 제공하는 호환 가능한 버전의 Numpy를 설치해야 한다. 
터미널에서 다음 명령을 실행하여 Numpy 및 기타 종속 요소를 설치한다.

conda install -c apple tensorflow-deps

Step5: Compile and Build OpenCV

❶ OpenCV 와 OpenCV Contrib 소스를 먼저 다운로드 한다. (여기에서는 opencv 폴더를 생성하고 다우로드 및 빌드 작업을 진행했다.)

wget -O opencv.zip https://github.com/opencv/opencv/archive/4.8.0.zip
wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.8.0.zip

❷ 다운로드한 소스 압축을 푼다.

unzip opencv.zip && unzip opencv_contrib.zip

❸ opencv 소스 폴더에 build 폴더를 생성하고 이동한다.

cd opencv-4.8.0/
mkdir build && cd build


❹ cmake 을 실행하여 소스를 빌드한다.  실행 옵션은 아래와 같다.




Cmake 를 실행하면 아래와 같은 화면이 보여진다. 컴파일에는 그리 많은 시간이 소요되지 않는다.



❺ make 명령 사용 CMake가 생성한 Makefile을 기반으로 빌드 실행한다. 여기서 M1 맥의 경우 8코어 CPU 이기 때문에 j8은 옵션을 사용하여 make를 실행했다. 

make -j8


make 과정에서  다양한 어려움이 발생되었다. 

⑴ No rule to make target 'zlib'. 

make[2]: *** No rule to make target `zlib', needed by `lib/libopencv_imgcodecs.4.8.0.dylib'.  Stop


zlib 을 설치하였지만 문제가 해결되지 않았다

brew install zlib

brew 때문에 발생하는 것이라는 글이 있어 삭제 후 다시 설치 해보았으나 문제가 해결되지 않았다.

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)"
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install wget cmake 


⑵ fatal error: 'ft2build.h' file not found


텍스트 렌터링 오픈 소스 halfbuzz 를 설치.

brew install halfbuzz 

설치 결과물을 보면 java 부분이 누락되었는데 확인을 위하여 cmake 결과를 확인해보니 java 부분 설정이 일반적이지 않는 것을 확인했다.



아래 명령을 입력하여 설치된 자바 경로를 확인하였다.

/usr/libexec/java_home --verbose

확인 된 자바 위치 정보를 사용하여 JAVA_HOME, JRE_HOME 경로를 설정해준다.

export JAVA_HOME=/Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home
export JRE_HOME=/Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home


누락된 ant 빌드 도구를 설치하였다.

brew install ant 

여기에서는  M1 을 지원하는 자바 버전 설치를 위하여 https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/downloads-list.html  방문하여 맥용 (macOS aarch64) 설치파일을 다운로드 하여 설치하였다. 

% /usr/libexec/java_home --verbose

Matching Java Virtual Machines (2):

    17.0.8 (x86_64) "Amazon.com Inc." - "Amazon Corretto 17" /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home

    11.0.11 (x86_64) "AdoptOpenJDK" - "AdoptOpenJDK 11" /Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home


export JAVA_HOME=/Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home
export JRE_HOME=/Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home

다시 cmake 를 실행하면 JAVA 항목은 NO 로 표기되고 있지만 정상적으로 빌드가 된다. 


make -j8
sudo make install

/usr/loca/share/java/opencv 경로에 자바 라이브러리가 생성됨을 확인

2022년 11월 9일

코딩 - Job Scheduling in Spring with Quartz - Database Clustering

 Spring 프레임워크 기반의 웹 프로그램에서 시간 주기에 따라 작업을 수행하는 것은 유명 오픈소스  Quartz 을 사용하여 손쉽게 구현할 수 있다. Spring 프레임워크 역시 추상화를 통하여 Quartz 스케줄러를 위한 인스턴스 생성을 위한 FactoryBean 및 (MethodInvokingFactoryBean을 사용하여) 컨텍스트에 존재하는 Bean 함수 호출을 할 수 있게 지원하고 있다.

안정성을 중요시하는 요즘에 서버 이중화는 그리 특별한 것이 아니며 하나 이상의 프로그램 서버에 스케줄러 기반의 배치 작업을 포함하는 웹 프로그램의 경우 해결해야 하는 몇가지 이슈가 있다.

  1. 서버 인스턴스 A, B 가 있는 경우 오직 인스턴스 A 에 스케줄러 설정 포함하여 운영하는 방식을 많이 사용한다. 이경우 인스턴스 A 가 다운된 상태의 경우 스케줄러 작업이 진행되지 않는 이슈가 있음. 
  2. Quartz Jdbc Clustering 의 경우 스케줄러 작업에서 스프링에 등록된 서비스를 호출하여 작업을 하는 경우 이부분에 대한 처리가 잘 되지 않음. (구현 방법이 명확하게 기술된 자료를 확인하지 못함)

이러한 어려움들은 몇가지 문서들을 기초로하여 해결 할 수 있었다. 참고로 이글에서는 어노테이션이 아닌 XML 을 이용한 설정으로 구현하였다. Spring 프레임워크 기반에서 Quartz 스케줄러를 이용한 작업은 아래 3가지를 정의하여 구현할 수 있다.


Quartz Scheduler 

❶ 특정 Job 을 정의하는 JobDetail 정의

Quartz 스케줄러에서 실행될 작업을 담는 Job 정의하는 JobDetail 인스턴스는 JobBuilder API를 사용하면 쉽게 생성할 수 있다. Spring 에서는 ⑴ 등록된 다른 Bean 의 함수를 호출하는 작업을 위한 MethodInvokingJobDetailFactoryBean  클래스와 ⑵  실행되는 작업은 반듯이 구현해야하는 인터페이스   org.quartz.Job  을 구현하는 JobDetail 인스턴스 생성을 돕는 JobDetailFactoryBean 클래스가 있다. 

❷ Trigger 정의

스케줄러를 어떤 방식, 어떤 주기로 작동할 지를 정의한다. Trigger 은 ⑴ start time, end time, interval time, repeat times 주기를 설정하는  SimpleTrigger  과 ⑵ Cron 형식으로 일정 주기를 지정하는  CronTrigger  가  있다.

❸ Quartz Scheduler 정의 

❶ 과 ❷ 입력하여 작업을 실행한다.

그림1. Quartz Scheduler 구성요소

그림2. Quartz Scheduler 내부 구조 

Quartz 스케줄러 스레드 실행 방법을 결정하는 스레드 실행기 같이 작업 실행을 구성하고 용이하게 하는 데 도움이 되는 더  많은 구성요소들이 있다. 작업이 실행을 위해 위임된 스레드 풀을 관리하는 스레드 풀, 작업 저장소(하나는 메모리 기반이고 다른 하나는 데이터베이스 기반). 참고로 동일한 작업을 가르키는 여러 트리거가 존재할 수 있지만 하나의 트리거는 하나의 작업만 가리킬 수 있다.

테스트는 다음 환경에서 진행되었다.

테스트 환경

  • Springframework 5.3.6
  • Quartz 2.3.2 
  • Apache Tomcat 8.5.57
  • JAVA 1.8 (인프라 호환성 유지를 위하여 낮은 버전을 사용)
  •  HW : Macbook Pro 2020 ( 2.3GHz 8Core Intel Core i9  16GB Memory) 


JDBC 을 이용한 Clustering 과정에서 경험한 것들

1. Schema 생성하기

데이터베이스 스키마는 직접 생성해야 하는 데 버전에 맞는 스키마를 사용해야 한다. 다른 버전의 스키마를 이용하여 테이블을 생성하는 경우 역직렬화 오류가 발생한다.

2. Job Detail 설정

Quartz 2.1.7 버전의 경우 JobDetail 의 JobDataMap 값이 Job 구현 클래스에 자동으로 바인딩되지 않아 Job 구현 클래스에서 executeInternal() 구현시 인자로 전달되는 JobExecutionContext 에서 JobDataMap 데이터를 꺼내어 설정하는 작업이 필요했다. Quartz 2.3.2 버전에서는 자동으로 바인인되었다. 주의할 것은 JobDetail 객체를 JobDetailFactoryBean 사용하여 정의할 때 applicationContextJobDataKey 값을 설정하게 되면 Spring Context 객체가 해당 이름으로 JobDataMap 에 추가되고 결과적으로 데이터베이스  Job Store 에 저장을 시도하면서 오류를 발생시키게 된다. 


3. Quartz 설정

applicationContextSchedulerContextKey 값을 applicationContext로 지정하고 Job 구현 클래스에서 같은 이름으로 setApplicationContext 함수를 정의하면 자동으로 바인딩된다. 이를 통하여 Job 구현 클래스에서 Spring Context 에 접근이 가능하게 할 수 있다.

 

org.quartz.jobStore.useProperties 속성을 true 로 설정하면 JobDataMaps 데이터는 객체가 아닌 String 형태로 저장된다. 이경우는 JobDataMap 에 객체 값을 추가하는 것이 불가능하게 된다.


org.quartz.JobPersistenceException: Couldn't store job: JobDataMap values must be Strings when the 'useProperties' property is set.  Key of offending value: applicationContext



다음은 위의 과정들을 통하여 적용된 내용이다.


동일 이름의 Quartz 스케줄러 인스턴스가 하나 이상인 경우에 최초 활성화된 인스턴스가 동작하게 되고 다른 인스턴스들은 대기하게 된다. (로그를 보면 추정하건데 데이터베이스 컬럼 Lock 에 의존하여 클러스터링을 구현하는 것으로 보여진다.)
그림3. 대기하는 Quartz Scheduler 인스턴스 로그

참고자료

  1. Quartz Scheduler Model
  2. Scheduling in Spring with Quartz
  3. Quartz Configuration Reference - Configure Clustering with JDBC-JobStore
  4. pass JobDataMap in the JobDetailFactoryBean not working
  5. Issue with Quartz persistent jobs while using with Spring
  6. One thought on “Configuring Quartz 2 with Spring in clustered mode”