iframe으로 특정서버의 화면을 띄워야하는 일이 생겼다.

현재 운영되고 있는 서버에 추가적으로 batch Application을 올리고 iframe으로 호출하는 방식을 사용하기로 했다.

 


 

서버구성

 

 


문제1. batch 내부의 cookie 사용이 안되어 url에 jsessionId가 붙어감

예시로 /batch;jsessionid=~~~~~~~  형태로 잘못된 url이 생성되었다. 그로인데 Controller를 잘못찾아가는 문제가 발생

 

원인을 찾아보니 로컬에서 테스트 할 때 브라우저의 url을 localhost:8080~~~ 를 사용하였고 iframe의 주소는 
<iframe src="127.0.0.1:8099"..... 형식으로 사용하였기 때문에 발생

 

둘 다 같은 localhost로 변경하여 사용 하니 문제를 해결하였다.
다만 이로인해 운영에서 iframe으로 <iframe src="IP:PORT" ..... 구조를 사용 할수 없을 듯하였다.

 

운영에서는 <iframe src="도메인/batch" 형태로 사용하기로 한다.

 

 


문제2. nginx에 도메인/batch로 들어오면 2번 서버의 8099포트로 보내야한다.

 

배치서버는 1대지만 iframe 껍데기를 호출하는 서버는 2대 이다. 그렇다면 도메인/batch를 접속하게 된다면 LB를 통해
1번 서버 2번 서버 어느곳으로 갈지 알 수 없다.

 

그렇기 때문에 nginx에서 2번서버의 8099 포트로 이동 할수 있도록 proxy를 구성해야한다.

 

이를 위해 nginx의 default.conf를 수정

 

1번 서버, 2번서버 모두  location /batch/를 추가하여 어떤 서버로 요청이 오더라도 2번서버의 8099를 바라볼 수 있도록 구성

......

upstream backend{
	hash #remote_addr;
    server 1번서버아이피:8080;
    server 2번서버아이피:8080;
    
    keepalive 1024;
}

server {
	listen 443 lls;
    .... 
    기타 nginx 설정들, ssl 포함 
    
    ....
    
    location /batch/ {
    	proxy_pass http://2번서버 IP:8099;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    
    location / {
    	proxy_pass http://backend;
    }

 

 


문제3. https에서 http의 iframe을 사용 할 수 없음

브라우저에서 iframe으로 데이터를 불러올 때 데이터가 보이지 않아 console 을 확인해보니

 

에러로그가 발생

was loaded over an insecure connection. this file should be served over https

 

찾아보니 https 도메인을 사용하며 http를 iframe으로 사용할 수 없어서 발생하는 에러로그 

 

아마 배치 application에 

return "redirect:/" 와 같이 302 redirect를 발생시키며 생기는 문제로 보임.

 

nginx의 batch location에 강제로 http를 https로 변환해주도록 설정 추가

location /batch/ {
...
  proxy_redirect http:// https://
...
}

서버에 ssh로 접속 후 프로그램을 실행 후 ssh를 끊게 되면 해당 프로세스는 종료된다.

 

이때 사용 할 수 있는 명령어가 nohup이다

nohup java -jar -Dspring.profiles.active=dev test.jar 1> /dev/null 2>& &

 

nohup을 사용하면 nohup.out이라는 로그 파일이 생성되는데 이를 생성하지 않고자 한다면 

1> /dev/null 2>& 를 사용하도록 하자

let data = [
  {"id": "ROOT", "name" : "ROOT", "upperId": '', "level" : 0, "order": 0},

  {"id": "HOME",   "name" : "HOME",   "upperId": 'ROOT', "level" : 1, "order": 1},
  {"id": "MOBILE", "name" : "MOBILE", "upperId": 'ROOT', "level" : 1, "order": 2},
  {"id": "COMMON", "name" : "COMMON", "upperId": 'ROOT', "level" : 1, "order": 3},

  {"id": "cH1", "name" : "카테고리1", "upperId": 'HOME', "level" : 2, "order": 1},
  {"id": "cH2", "name" : "카테고리2", "upperId": 'HOME', "level" : 2, "order": 2},
  {"id": "cM3", "name" : "카테고리3", "upperId": 'MOBILE', "level" : 2, "order": 3},
  {"id": "cM4", "name" : "카테고리3", "upperId": 'MOBILE', "level" : 2, "order": 4},
  {"id": "cM5", "name" : "카테고리3", "upperId": 'MOBILE', "level" : 2, "order": 5},

  {"id": "c1s1", "name" : "시나리오1", "upperId": 'cH1', "level" : 3, "order": 2},
  {"id": "c1s2", "name" : "시나리오2", "upperId": 'cH1', "level" : 3, "order": 1},
  {"id": "c1s3", "name" : "시나리오3", "upperId": 'cH1', "level" : 3, "order": 3},
  {"id": "c2s4", "name" : "시나리오4", "upperId": 'cH2', "level" : 3, "order": 4},
  {"id": "c2s5", "name" : "시나리오5", "upperId": 'cH2', "level" : 3, "order": 6},
  {"id": "c2s6", "name" : "시나리오6", "upperId": 'cH2', "level" : 3, "order": 5},
  {"id": "c2s7", "name" : "시나리오7", "upperId": 'cH2', "level" : 3, "order": 7},
  {"id": "c3s8", "name" : "시나리오8", "upperId": 'cM3', "level" : 3, "order": 8},
]

function dataSort(data){
  return data.sort((a, b) => a.level - b.level || a.order - b.order )
}

function makeHierachy(data) {
  // root를 제외한 모든 id 별 포함되는데이터 추출(upperId를 사용)
  const dataMap = data.filter(x => x.level !== 0).reduce((acc, x) => {
    if (!acc[x.upperId]) {
      acc[x.upperId] = []
    }
    // order를 재정의
    x.order = acc[x.upperId].length + 1
    acc[x.upperId].push(x)

    return acc
  }, {})

  // 각 데이터들에 children에 데이터 할당
  for(const d of data) {
    if (dataMap[d.id]) {
      d.children = dataMap[d.id]
    } else {
      delete d.children
    }

  }

}

// 데이터 조회
function look(data) {
  console.log(String(data.name).padStart(data.level * 5)  )
  if(!data.children){
    return
  }
  for(const d of data.children){
    look(d)
  }
}

dataSort(data)
makeHierachy(data)
console.log(data)
// 루트부터 깊이 우선 탐색으로 조회
look(data[0])

 

 

문제

연계기관에서 API를 통해 데이터를 가져가는 케이스가 있다. 

데이터를 가져가게 되면 TRAN_YN을 'Y'로 update 하는데 테스트 요청 시 마다 'N'으로 업데이트를 해주어야한다...

... 나는 언제 퇴근 하라고...

 

해결

MYSQL에 Event기능이 있다고 하여 추가 하였다.

 

이벤트 생성

CREATE EVENT IF NOT EXISTS FRANS_SET
 ON SCHEDULE
   EVERY 1 MINUTE
   STARTS '2024-06-20 15:30:00'
  DO UPDATE TBL_XXXX SET TRANS_YN ='N'

 

이벤트 조회

SHOW EVENTS;

 

이벤트 삭제

DROP EVENT TRAN_SET

 

 

얏호 퇴근하자.

+ Recent posts