1. TRUCATE TABLE

테이블의 모든 행을 삭제한다. DELETE FROM과 동일. 삭제 후 COMMIT할 필요 없다.

2. 슈퍼타입과 서브 타입 종류

종류 설명 단점
One to One (1대1) 슈퍼타입과 서브타입을 개별 테이블로 도출 테이블 수 많고 조인 많음
Plus (슈퍼 + 서브) 슈퍼타입과 서브타입 테이블로 도출 조인이 적당히 많음
Single (올인원) 전체를 하나의 테이블로 통합 조인이 적지만 입출력 성능이 나쁨

3. Prior

  • Prior 자식 = 부모 // 순방향
  • Prior 부모 = 자식 // 역방향

4. CASCADE, CASCADE CONSTRAINT

  • CASCADE → 연관된 모든 객체 삭제
  • CASCADE CONSTRAINTS → 외래 키(FK)만 삭제, 다른 객체는 유지

5. Window 함수 표현식

  • SUM(급여): "회사 전체 급여 총액이 얼마야?" 
  • SUM(급여) OVER(): "모든 직원에게 '회사 전체 급여 총액이 이거야'라고 메모 붙여줘" 
  • 1 PRECEDING,UNBOUNDED FOLLOWING: 앞으로 1칸,  끝까지 뒤로
  • ROWS : 행을 기준으로 선택 (가로)
  • RANGE : 컬럼 값을 기준으로 선택 (세로)

6. CROSS JOIN, FULL OUTER JOIN

  • CROSS JOIN : 모든 행 조합 생성 ( 행 수 = A * B)
  • FULL OUTER JOIN : LEFT, RIGHT OUTER JOIN 교집합

7. 파티셔닝 : 데이터를 수평으로, 논리적으로 쪼갠다.

  • Range : 범위에 따라 // 월별, 년도별, 가격 범위별
  • List : 리스트에 따라 // 국가코드
  • Hash : 알아서  // 자동 균등 분할
  • Composite : 조합해서 // 예시로 Range + Hash로, 연도별로 나눈 후 Hash 균등 분배

8. ER 모델링 표기법

  • Barker : 기호로 PK 등 표기
  • IE : 동그라미 등이 표시되는 자주보는 ER 모델링

9. 기본 / 중심 / 행위 엔터티

  • 기본 : 독립적으로 존재 // 회원, 상품, 직원
  • 중심 : 기본 엔터티 기반, 행위 엔터티를 생성 // 주문, 계약, 거래
  • 행위 : 주문 이력, 체결 이력 등 

10. PL/SQL : 절차적 언어로 sql 실행하는 코드

DECLARE → FETCH → CLOSE → EXCEPTION 순서

변수정의, 가져오기, 닫기, 예외 정도만 외우면 될거같음

 

11. 계층형 질의 노드 여부

  • CONNECT_BY_ISLEAF : 단말이냐? = 1 , 자식이 있느냐? = 0
  • CONNECT_BY_ISCYCLE : 순환되냐? = 1, 순환되지 않느냐? = 0
  • SYS_CONNECT_BY_PATH : 현위치 알려줌. 마치 파일탐색기에서 C\:FOLDER1\FOLDER2 처럼

12. 식별자 여부 별 구분

  • 대표성 : 주 식별자(고객번호) / 보조 식별자(주민등록번호)
  • 스스로 생성 : 내부(스스로 생성) / 외부 (외부에서 가져옴)
  • 단일속성 : 단일(키가 하나뿐) vs 복합 (키가 둘)
  • 대체 : 본질(주민번호) vs 인조(일련번호)

13. TRUNCATE, DELETE, DROP

  • DELETE : 공간 자체는 남아있는 지우기 (커밋 전 롤백 가능)
  • TRUNCATE : 테이블 속성빼고 지우기 (롤백불가)
  • DROP : 깔끔하게 싹지우기 (롤백불가)

14. 프로시저, 트리거

구분 프로시저 트리거
실행방식 명시적으로 (execute,exec) 특정 이벤트 발생 시
목적 재사용 작업 묶어서 ⭐직접 실행 데이터 변경 시 ⭐자동 수행
사용 예 반복 작업 로그

 

15. 연산에 NULL이 있다면?

  • 가로로 null이 연산되면 null이 출력됨
    ex) a3이 null값일 때, SUM (a1+a2+a3+a4) = null
  • 세로로 null이 연산되면 null을 제외하고 출력됨
    ex) sum(a1) + sum(a2) + sum(a3) + sum(a4)

16. Window 함수 추가 노트

  • Window 함수는 자동 튜닝을 하지 않는다. 
  • Group by와 용례는 비슷하나 윈도우는 결과 건 수가 줄어들진 않는다.
  • Group by와 Window Function은 병행 사용 가능하지만 굳이 라서 필요에 따라 하나를 선택해 사용한다.

17. LAG, LEAD

  • LAG : 위에 있는걸 가져오겠다.
  • LEAD : 아래에 있는걸 가져오겠다.

18. CUBE  ROWS 계산 방법

  1. CUBE(A,B)이고, A 의 유니크한 값이 3개, B의 유니크한 값이 5개일 때
  2. 우선 1개 (전체 1건)
  3. B의 5개
  4. A의 3개
  5. A이면서 B인 경우 노가다로 세기
  6. 다 합치기

0. 개요


cmd에서는 명령을 입력하면 명령어를 한 줄씩 실행한다.
즉, 한 줄 실행이 완료될 때 까지 기다리고, 완료되면 그 다음 줄을 실행한다.
이전 회사에서, 한번에 여러개의 디바이스를 다룰 일이 많았다.

아래 예시를 보면, 두개의 디바이스가 연결된 상태에서 screencap 명령어를 통해 스크린샷을 찍어보았다.

위와 같이, more than one device/emulator 에러 메세지가 나오면서 실행이 되지 않는다!


1. -s 옵션

컴퓨터 입장에서 보면, "어떤 디바이스로 해달라는거야?" 라고 되물을 것이다.

우리는 그래서, 직접 이름을 불러주고 명령을 해야한다.

adb devices 명령어를 입력하면 연결되어있는 디바이스의 이름(시리얼넘버) 확인이 가능하다.

아래와 같이 -s 옵션을 붙이면 디바이스를 지정할 수 있다!


2. 직렬 실행

그렇다면, 한번에 두개를 실행하고 싶다면 어떻게 해야 가능할까?

이렇게 두 줄 쓰는 방법도 있을것이다.

하지만 다음과 같이 생각할 내용이 있다.

만약 스크립트가 길어진다면?

set device_1=R3CRA0JW89R
set device_2=R3CX208V22K

adb -s %device_1% shell screencap -p /sdcard/screenshot.png
adb -s %device_2% shell screencap -p /sdcard/screenshot.png

adb -s %device_1% shell screencap -p /sdcard/screenshot1.png
adb -s %device_2% shell screencap -p /sdcard/screenshot1.png

adb -s %device_1% shell screencap -p /sdcard/screenshot2.png
adb -s %device_2% shell screencap -p /sdcard/screenshot2.png

이렇게 길게 작성해야한다..

그리고 또 아래와 같은 문제점이 있다.

  1. 만약 시리얼 넘버가 계속 바뀐다면?
    이런 상황이 있을 수도 있다. 같은 디바이스에서는 같은 시리얼 넘버가 출력되지만, 만약 디바이스를 계속 바꾸면서 하는 경우도 있다.
  2. 만약 스크린샷 찍는것 뿐만 아니라 스크립트가 더 있고, 하나 완료하는데 몇분씩 걸린다면?
    처음 말했듯, cmd에서는 코드를 한줄씩 읽고 실행한다.
    만약 디바이스가 10대라고 가정하면, 1대의 디바이스가 스크립트 실행중일때 나머지 9대의 디바이스는 아무것도 안하는 상태로 있는다.

이미지로 비유하자면, 아래와 같다.

그렇다면 이게 한계일까?

 

그렇지 않다!

다소 억지스럽지만, cmd에서는 병렬 실행을 구현할 수 있다.


3. 병렬 실행

우리가 원하는건 아래 이미지와 같은 병렬 실행이다.

그러기 위해서, 디바이스 만큼 cmd 스크립트를 실행하는 방법으로 구현해냈다.

우선, 아래와 같은 폴더 구조를 만들었다.

order.bat에서는, 다음과 같은 스크립트가 들어가있다.

@echo off
setlocal enabledelayedexpansion

for /f "skip=1" %%i in ('adb devices | findstr "devices"') do (
    start /min capture.bat %%i
)

복잡한 명령어긴 하지만, 단순하게 설명하자면

  1. 'adb devices'를 실행한다.
  2. 거기서, | findstr devices (파이프)를 이용해 devices인 경우를 필터(디바이스가 오프라인, 인증되지 않은 경우 제외)
  3. skip=1 을 통해 adb devices의 List of devices attached 구문을 무시하고, 시리얼 넘버를 가져온다.
  4. start /min 옵션을 통해, 최소화된 창으로 capture.bat을 실행한다.
  5. 다만, capture.bat에 %%i 를 통해 시리얼넘버를 같이 실어서 보내준다.

capture.bat에서는, %1을 통해 해당 시리얼 넘버를 사용할 수 있다.

echo %1 시리얼 넘버를 넘겨받았습니다.
pause>nul

capture.bat을 위와같이 설정하고, 실행한다면

이렇게 시리얼넘버를 넘겨 받을 것을 확인할 수 있다.

그렇다면,

이제 이런식으로 작성하면 다소 억지스럽지만 병렬 실행을 구현할 수 있다.


4. 결론

억지스럽다 표현한 이유는, 저렇게 실행하면 실행한 수 만큼 cmd가 켜지기 때문이다..

그래도 조금은 투박하지만 분명한 성과는 있었다.

3분정도 걸리는 스크립트를 6개의 디바이스에 직렬로 실행했을 때에는 18분 가량 걸리곤 했었는데, 병렬 구현을 한 후에는 약 5분정도 걸리게 되었다. (병렬로 실행하면서 렉이 좀 걸리니까 느려지면서 추가됨)

파이썬에는 아예 병렬 실행을 하는 쓰레딩 라이브러리가 있는 것으로 알고 있다.

이후 실무에서 만약 병렬 실행 수요를 마주친다면 한번쯤 활용해보면 될 것 같다.

영상 링크 : https://www.youtube.com/watch?v=DwqwUsFmoCU

 

1. 무엇을 소개하는가?

토스 닥터라고 부르는, 스모크 테스트 자동화 툴을 소개한다.

메신저에서 /토스닥터 를 입력하고 몇가지 옵션을 선택하면 Appium을 이용해 테스트 스크립트를 실행하고, 테스트 결과를 출력하는 일종의 "딸깍" 하나에 20분치 업무를 수행해주는 툴이다.

*스모크 테스트 : 주요 기능 테스트를 빠르게 하는 것

2. 도입 배경

기존에는 수동 테스트에 너무 많은 인력 소모가 있었던 것 같다.

1회 릴리즈 할 때 평균 RC 빌드를 5회 발행하고,

1년간 Android와 iOS에서 RC 빌드를 540회 발행했으며,

기존 RC 빌드를 1회 수동 테스트하는 데에 평균 20분 걸린 것을 계산하여 총 179시간의 비용이 들었다고 한다.

**RC 빌드 : 출시 후보

하지만 토스 닥터 자동화 툴을 사용했을 때, 자동 테스트로 평균 10분 단축시키면서 두가지 확실한 이득을 볼 수 있었다.

  1. 총 RC 빌드 테스트 시간을 90 시간을 아낀다.
  2. 179시간 * 수동 테스트 참여 인원의 비용을 아낀다.

또한, RC 빌드가 발행되었을 때 기존 업무를 중단하고 다른 업무로 바꿀 때의 집중력 분산, 수동 테스트를 반복할 때에 오는 업무 피로감 등의 보이지 않는 이점 또한 얻을 수 있었다.

3. 주요한 세가지 특징

토스 닥터 컨퍼런스에서 세가지 주요한 세가지 특징을 소개했다.

  1. webdriver 세션 재사용하기
  2. 자동으로 테스트 결과 기록하기
  3. 실시간으로 테스트 진행 상황 모니터링하기

1번으로는, @pytest.fixture 이라고 부르는 데코레이터를 사용했다고 한다.

반복되는 세팅 (앱을 켜기, 로그인하기 등) 을 각 세션을 테스트 할 때 마다 실행한다면 반복되는 코드가 나올 뿐만 아니라 매번 재실행하는데에 시간 소요도 커지게 된다.

그런 낭비를 줄여주는 기능을 소개하는 것으로 보인다.

 

2번으로는, pytest의 testrail 플러그인을 사용해 테스트 결과를 testrail api로 전달하는 방식으로 구현했다고 한다.

테스트레일에 ID를 지정하고, pytest의 testrail 플러그인에 ID를 1대1 매칭해놓으면 testrail에 결과가 보고된다고 한다.

 

3번으로는, 테스트 자동화 중 테스트 시작, 성공, 실패, 경고를 통해 테스트 진행 상태를 실시간으로 볼 수 있게 구현했다.

2번에서 테스트 결과가 기록되더라도 "이걸 실시간으로 어떻게 보느냐?" 에 대한 해답을 내놓았다.

실제로 메신저에 구현한 것을 보면, 대강 이런식이다.

🎯 탭 노출 확인

✅ 로그인 (0.5s)     <- Pass

✅ 1번 탭 노출 확인 (0.3s)     <- Pass

✅ 2번 탭 노출 확인 (0.3s)     <- Pass

🔥 3번 탭 노출 확인 (0.3s)    <- Fail

⚠️ 4번 탭 노출 확인 (0.3s)    <-warn

이런식으로, 어떤 기능을 테스트하는지, 성공하였는지, Fail하였는지, 몇초 걸렸는지를 한눈에 볼 수 있게 완성도 높은 구현을 했다.

 

주요한 세가지 특징이라고 말을 했는데, 굉장히 훌륭하고 꼭 필요한 기능일 것 같다.

그리고, 굉장히 깔끔하다!

4. 느낀 점

첫 회사에서, 매 빌드마다 스모크 테스트와 같은 메뉴얼 테스트를 수동으로 한 경험이 있다.

그때 당시, 수동 테스트를 매번 반복하는 과정이 썩 즐겁지만은 않았고 기계가 된 기분이기도 했었다.

지금으로 와서, 토스 닥터와 같은 자동화에 영감을 받고 충분한 공부 시간과 역량을 갖춘다면 자동화를 구현해보고 싶을 것 같다.

하지만 과연 토스 닥터와 같이 "잘" 만들 수 있을까?

위의 주요한 세가지 특징 중 몇개나 구현이 가능할까?

한번 도전해보고싶다. 최근 시간 여유가 있는데, 한번 기획하고 만들어보는것도 좋을듯!

0. 개요

자동화의 이전 글 (https://janguri.tistory.com/4)에서, 이미지 유사도 기반 자동화 프로세스를 도입한 경험을 소개했었다.

최근 ROI라는 개념을 배우게 되어, 한번 계산해 보았다.


1. ROI?

ROI는 Return oInvestment의 약자로, 투자 대비 효과를 말한다.

쉽게 말해, "돈 얼마쓰면 얼마 벌어줄지"에 대한 경영학적인 용어이다.

공식은 아래와 같다.

ROI = (순투자수익/투자비용)*100%

 

즉, 돈 얼마 쓰면(투자비용) 얼마 벌어줄지(순투자수익)의 비율이고,

100% 미만 : 적자

100% 초과 : 흑자

라고 볼 수 있다.


2. 상황

이전 자동화 프로세스 도입 글에서, 다음과 같은 업무를 진행했다.

Before
게임을 자동 플레이를 켜 놓으면 특정 확률로 팝업이 등장하고, 해당 팝업을 수동으로 터치해서 종료한다.

 

그리고, 다음과 같이 자동화 했다.

After
특정 팝업 식별 시 팝업을 자동으로 터치해 팝업이 자동 종료된다.

 


3. 자동화 도입 전 

자동화 도입 전의 비용을 분석하기 위해, 여러가지 요인이 있어야 했다.

  1. 프로젝트 기간
    720시간으로 산정 = 43,200분
  2. 특정 확률로 팝업 등장
    10분으로 산정, 총 4,320회의 팝업 등장
  3. 터치 해서 종료
    1회당 25초, 총 108,000초 소요 = 30시간

프로젝트 기간은 6주였고, 아래와 같이 계산되었다.
근무시간 * 근무일 * 근무인원, 즉 8시간 * (6주 * 5일) * 3인 = 720 시간

특정 확률을 정확히 알 수 있다면 계산을 할 수 있겠으나, 아쉽게도 확률이 주어지지는 않았다. 하지만 체감 상 평균 10분 정도 확률로 팝업이 발생했다!

터치 해서 종료는, 다음 두가지 시간을 더했다.

업무 중 손을 뻗어 팝업 종료 버튼을 누르는데에 걸리는 시간 : 5초

업무 중단 후 재 몰입에 대한 시간 : 20초

20초를 산정하기 위해, 아래 글 (업무 중단 후 재 몰입 시간에 대한 글)을 참고했다.

https://productivityreport.org/2016/02/22/how-much-time-do-we-lose-task-switching/?utm_source=chatgpt.com

Office workers reacted to the majority of their incoming emails within 6 seconds of it arriving (Jackson 2001). Then it took them on average 64 seconds to resume work. 

위 실험에서는 이메일 확인으로 인해 집중력 분산이 64초간 이어진다고 하는데, "팝업만 누르는 단순 작업"은 그의 1/3이면 충분하지 않을까? 해서 20초로 산정했다!

즉,

43,200분의 프로젝트 기간동안 업무 중 자동 플레이에서 4,320번의 팝업이 등장하고, 이 중 30시간을 팝업 누르는데에 사용했다.

 

라고 표현할 수 있다.

 


4. 자동화 도입 후 

자동화 도입 후의 비용 계산은 매우 간단하다!

매우 간단한 툴이었고, 총 8시간의 개발, 배포, 사용법 안내 로 마무리 지었다.

정확히는, 4시간 쯤에 걸쳐 작동하는 프로토타입을 완성했고, 2시간정도에 걸쳐 사용성 개선 (자주 변경되는 값 변수화 등등의 리팩토링)을 마쳤으며, 파이썬, opencv, adb 등 사용환경에 대한 내용들을 같은 팀원에게 안내했다.

 


5. 최종 ROI

ROI = {(30-8)/8}*100% = 275%

 

ROI = 275%라는 숫자가 나온다!

즉, 투자한 시간 대비 2.75배의 효과를 봤다. 라고 말을 할 수 있는 것.

만약 내 시급이 만원이었더라면, 8만원을 투자해서 30만원의 가치를 창출한 셈이다!

 


6. 제외된 요인

24시간 활용 가능한 툴이었기에 "데이터 누적량"이 8시간에서 24시간 늘어난 효과도 있었다. 하지만 빨리 끝내는게 중요하지 않았기에 요인으로 포함되지 않았다.

만약 "데이터 누적을 마쳐야 다음 업무 진행이 가능하다." 라고 했다면 이 또한 아주 중요한 요인이 되었을 것이다.


7. 결론

팝업이 등장하는 시간, 업무 재 몰입 시간 등 일부 제멋대로 설정한 값이 있어 정확도와는 거리가 있는 내용이다.

어쩌면 정량적이지 않은 값일 수도 있다.

하지만, 이런 내용들을 잘 정리하면 성과를 어필할 상황(면접, 자기소개)에서 한 마디 붙일 수 있지 않을까 생각된다!

'자동화' 카테고리의 다른 글

[자동화] 이미지 유사도 기반 플레이 자동화 방법  (3) 2025.02.06

0. 개요

이전 포스트 (https://janguri.tistory.com/8) 에서 ffmpeg를 이용해 영상을 효율적으로 다루게 되었다.

이번 글에서는, 이전에 만든 배치파일들을 효율적으로 통합하여 사용하는 방법을 소개한다.


1. Batch Script 통합

먼저 개인적인 경험을 소개하자면, 첫 회사에서 맨땅에 배치 스크립트를 만들면서 아래 이미지처럼 배치 스크립트가 많아져 불편한 경험이 있었다.

그래서, 최종적으로 하나의 통합 툴을 만들어 사용을 조금 더 편리하게 개선하게 되었다.

위 이미지와 같이 여러 배치 스크립트를 하나에 모아두고, 숫자를 입력 해 해당하는 행동을 하는 통합 툴을 만들어냈다.


2. 통합 방식

숫자를 입력 받으면, 여러가지 방법이 있으나 경험 상 두가지 방법을 선택해 사용했다.

  1. batch 파일을 불러(call) 실행하기
  2. 한 배치 스크립트에 모든 명령어 다 집어넣고 그 명령어 찾아가(goto) 실행하기

1번 방식의 경우, 기존에 만들었던 배치파일을 한 폴더에 다 넣고 통합 배치 스크립트에서 필요할때 불러 쓰는 방식이다.

장점으로는, 수정이 필요하면 해당 배치 파일을 꺼내 수정하면 되니 편리하다는 점.

단점으로는, 폴더 하나가 더 있어서 거슬릴 수도 있다 정도?

2번 방식의 경우, 통합 배치 스크립트에 모든 스크립트를 때려박는 방식이다.

장점으로는, 배치스크립트 단 하나만 있으면 되니 매우 깔끔하다!

단점으로는, 수정이 필요할 때 하나하나 찾아가야하니 수정이 불편하다는 점.

아래 두 코드 예시를 보면 이해가 쉬울것이다.

 

REM 1번 방식 / call로 불러들이기

@echo off
:loop
cls
chcp 65001 >nul
echo [1] capture
echo [2] record
echo [3] compress
echo [4] cut
echo [5] gif
echo [6] png
set /p num="Select number : "

if %num%==1 call batch\capture.bat
if %num%==2 call batch\record.bat
if %num%==3 call batch\compress.bat
if %num%==4 call batch\cut.bat
if %num%==5 call batch\gif.bat
if %num%==6 call batch\png.bat
goto loop

1번 방식의 스크립트다.

숫자를 입력하면, call 명령어를 통해 batch 폴더 내의 배치스크립트를 실행시키고, loop를 통해 다시 처음 위치로 이동하는 형식이다.

REM 2번 방식 //goto 명령어로 찾아가기

@echo off
:loop
cls
chcp 65001 >nul
echo [1] capture
echo [2] record
echo [3] compress
echo [4] cut
echo [5] gif
echo [6] png
set /p num="Select number : "

if %num%==1 goto capture
if %num%==2 goto record
if %num%==3 goto compress
if %num%==4 goto cut
if %num%==5 goto gif
if %num%==6 goto png
goto loop

:capture
echo this is capture script
goto loop
:record
echo this is record script
goto loop
:compress
echo this is compress script
goto loop
:cut
echo this is cut script
goto loop
:gif
echo this is gif script
goto loop
:png
echo this is png script
goto loop

2번 방식의 스크립트다.

숫자를 입력하면, goto 명령어를 통해 원하는 위치로 이동해 스크립트를 실행하고, 다시 loop 위치로 이동하는 형식이다.

 

사실 첫 선택이 중요하진 않다. 규모가 커지기 전에 알맞게 리팩토링 하면 된다. ^ㅇ^

여기서는 1번 방식 (call) 을 사용하여 불러 쓰는, 파이썬으로 치면 모듈 호출과 같은 느낌으로 만들어 보겠다.


3. 호출

우선, 아래 이미지와 같은 폴더 구조를 만들었다.

Tool.bat에서 batch\실행할스크립트.bat 을 넣어주면 끝!

이전에 만들어 둔 캡쳐 스크립트를 capture.bat에 넣어준다.

set /p file_name="Input file name : "
adb shell screencap -p /sdcard/screenshot.png
adb pull /sdcard/screenshot.png %file_name%.png

그런 후, 숫자 1을 입력해 capture.bat이 작동하는지에 대해 확인을 하면

  1. [1] capture 을 입력해서
  2. batch\capture.bat 파일이 열리고
  3. capture.bat 파일이 끝날 때 goto loop을 통해 :loop으로 이동된다.

파일은 capture.bat이 위치한 폴더에 생성되지 않고 Tool.bat에서 생성된다.

 

set /p file_name="Input file name : "
echo Recording...
echo press Ctrl + C and "N" to quit recording
adb shell screenrecord /sdcard/record.mp4
adb pull /sdcard/record.mp4 %file_name%.mp4

*화면 녹화

set /p file_name="Input file name : " 
ffmpeg -i %file_name% -vcodec libx264 -crf 28 -preset slow output_%file_name%
cls
set /p answer=Delete Original? [y/n] :
if %answer%==n goto quit
if %answer%==N goto quit
del %file_name%
ren output_%file_name% %file_name%
:quit

* 영상 압축

** Deleter Original? 을 통해 변경 전의 파일을 지우고 압축된 파일을 기존 파일명으로 변경할지의 분기점을 추가했다.

 

set /p file_name="Input file name : " 
echo enter Start time and finish time...
set /p start_time="Start time : "
set /p finish_time="Finish time : "
ffmpeg -i %file_name% -ss %start_time% -to %finish_time% output_%file_name%
set /p answer=Delete Original? [y/n]
if %answer%==n goto quit
if %answer%==N goto quit
del %file_name%
ren output_%file_name% %file_name%
:quit

* 영상 자르기

 

set /p file_name="Input file name : " 
ffmpeg -i %file_name% -vf "fps=8, palettegen=max_colors=32" -y palette.png
ffmpeg -i %file_name% -i palette.png -filter_complex "fps=8,paletteuse=dither=bayer" -b:v 1000k %file_name:~0,-4%.gif
del palette.png
:quit

* gif 만들기

**배치 파일에서 문자열 추출 규칙을 활용해, %file_name:~0,-4%로 작성하였다. (0번째부터 출력하는데 뒤에 .mp4 제거)
참고 : https://sysdocu.tistory.com/1516

 

set /p file_name="Input file name : " 
if not exist frames md frames
set /p frame_per_second=" How may Frames per second? : "
ffmpeg -i %file_name% -vf "fps=%frame_per_second%" frames/%%d.png
start frames

*png 만들기

**파일명을 입력 후, 초당 프레임을 설정할 수 있는 방식으로 구현해냈다.

*** frames 폴더가 없으면 만들고, 작업 후 frames 폴더를 자동으로 실행하게 구현했다.

 


4. 오류

명령어를 통해 생성된 파일을 삭제하거나이동할때 문제가 발생할 수도 있다.

그럴때를 대비해, adb 명령어를 재시작하는 코드를 추가했다.

if %num%==7 adb kill-server

7번을 입력했을 때 , adb kill-server을 추가해줬다.

뭐.. 다른 방법이 있을 수도 있지만 그냥 단순히 이렇게 재시작해주는 방법으로 해결했다.

 


5. 결론

말고도, 배치 스크립트를 활용하는 방법이 무궁무진하다!

예로, 아래와 같이 이쁜 색상코드를 넣을 수도 있다. (ANSI ESCAPE CODE 검색)

바로 다음으로, 배치스크립트로 병렬 실행을 (다소 억지스럽게) 구현한 방법을 소개하고자 한다.

0. 개요

이전 포스트 (https://janguri.tistory.com/6) 에서, adb를 활용해 모바일의 이슈 이미지와 영상을 간편하게 확보할 수 있었다.

이번 글에서는, 확보한 영상을 효과적으로 편집하여 이슈 리포트하기 용이하게 바꾸는 방법을 소개한다.


1. FFmpeg란?

 

FFmpeg는 동영상 및 오디오를 인코딩, 디코딩, 변환, 스트리밍할 수 있는 강력한 오픈소스 멀티미디어 프레임워크.

영상 관련 작업을 할 때 자동으로 해결할 수 있고, ADB와 마찬가지로 CLI 기반이라 ADB와 통합하기 간편하다.

그리고, 오픈소스다!


2. FFmpeg 설치

ADB와 마찬가지로, FFmpeg 설치 글을 보면 쉽게 다운로드 할 수 있다.

*ffmpeg는 essentials,full 버전 두개가 있는데, 간단한 명령어만 사용하기에 essentials로도 충분한 것 같다.

혹시 심화적으로 활용할 거라면 그때가서 full 다운로드 하면 될 것 같다.

다만, 다운로드는 소스코드가 아닌 Get packages & executable files를 선택해야 한다!

좌측 하단에 있는 OS 中 선택

 

ADB와 마찬가지로 FFmpeg도

  1. FFmpeg를 OS에 맞게 설치 후 압축 해제
  2. 환경 변수 설정

을 해준 후, 명령 프롬프트(cmd) 창에서 ffmpeg를 입력해보면

이런 식으로 출력이 된다면 성공이다!


3. 압축

QA 업무를 하다보면 이슈 영상이 보통 10초에서, 길면 1분가량 확보되곤 한다.

샘플로 약 14초가량 일반적인 게임을 S24 Ultra 기종으로 녹화하자, 36 MB의 영상이 녹화되었다.

아래는 아주 간단한 ffmpeg 예시다!

ffmpeg -i Test.mp4 Output.mp4

정말 단순하게도, Test.mp4 영상을 ffmpeg에 input해서 Output.mp4로 바꿔줬다.

그런데 결과는,

위와 같이, 용량이 1/3이나 감소한 결과를 얻을 수 있었다!

그렇다면 더 압축하는 방법이 있을까?

ffmpeg에는 옵션을 넣어서 추가적인 압축 형식을 만들 수 있다.

다양한 옵션이 있지만, 아래가 가장 자주 쓰이는 예제라고 한다.

ffmpeg -i test.mp4 -vcodec libx264 -crf 28 -preset slow output2.mp4

결과를 보면,

1/6 이라는 엄청난 압축률을 구현할 수 있다!

아래는 지피티에게 물어본 압축 옵션들이다.

명령어 설명
-vf scale=1280:720 해상도를 1280x720(720p)로 축소 (화질 유지하면서 용량 절감)
-crf 28 H.264 화질 기반 압축 (값이 클수록 용량↓, 화질↓) (보통 18~28 사용)
-preset slow 압축 효율 최적화 (속도를 늦추는 대신 용량 감소) (ultrafast ~ veryslow 선택 가능)
-c:v libx264 H.264 코덱으로 압축 (높은 호환성 & 압축률)
-b:v 1000k 비디오 비트레이트를 1000kbps로 제한 (낮을수록 용량↓)
-r 24 프레임 레이트를 24fps로 변경 (프레임 수 줄여 용량↓)

체감상 -crf 옵션을 28 초과해도 약간은 뭉개지지만 내용 식별에는 무리가 없었다.

업무에 맞게 잘 테스트해보고 압축하면 용량을 효율적으로 압축시켜 공유할 수 있을 것이다.


4. 자르기

이슈 영상을 보면, 항상 시작 시간부터 끝나는 시간까지 이슈가 꽉 녹화되는 경우는 없다.

보통 시작하고 몇초 후, 그리고 끝나기 몇초 전에 이슈 상황이 녹화되곤 한다.

아래는, 아주 간단한 영상 자르기 명령어를 소개한다!

ffmpeg -i test.mp4 -ss 2 -to 10 output.mp4

-ss : 시작 초

2 : 2초부터

-to : 끝나는 초

10 : 10초까지

즉, 2초부터 10초까지의 영상을 남기고 자르겠다는 뜻.

14초의 영상이, 8초 영상으로 잘린 결과를 확인할 수 있다.

기본적으로 ffmpeg를 걸쳤기에 ffmpeg의 영상 압축 효과도 덤으로!

만약 시작 시간부터 n초동안 유지하고싶다면?

ffmpeg -i test.mp4 -ss 2 -t 8 output2.mp4

똑같은 결과가 나오는 것을 확인할 수 있다.


5. GIF로 바꾸기

또, 가끔 짧은 이슈 영상은 gif로 공유하면 편하게 이슈 리포트가 가능하다.

이슈를 받아보는 입장에서, 영상을 다운로드해서 켜는 것보다 gif파일이 이슈 리포트와 함께 나오면 보기 편하기 때문.

 

그래서 만약 gif로 그냥 변환해버리면?

ffmpeg -i output.mp4 output.gif

분명 2mb도 안되는 mp4 파일이 110mb짜리 영상이 돼버렸다......

 

이를 해결하기 위해, GPT의 도움을 받자면

ffmpeg -i output.mp4 -vf "fps=8, palettegen=max_colors=32" -y palette.png
ffmpeg -i output.mp4 -i palette.png -filter_complex "fps=8,paletteuse=dither=bayer" -b:v 1000k output.gif

위와 같은 두 줄의 코드로 실행하면 적당한 크기와 화질의 영상 파일이 palette.png와 함께 생성된다.

약 8초간의 영상을 gif파일로 변환

옵션에 대한 설명을 하자면,

옵션 설명
fps=8 프레임을 8fps로 줄여 용량 감소
palettegen=max_colors=32 GIF 색상을 32색으로 제한 (기본 256색)
paletteuse=dither=bayer 색상 품질 유지하면서 용량 압축
-b:v 1000k 비디오 비트레이트를 1000kbps로 제한하여 용량 절약

이렇다!

영상 압축처럼, 각자 테스트해보고 원하는 품질의 gif 파일을 뽑아내면 될 것 같다.


6. PNG 변환

아주 단순한 기능이다. 아래 예제를 보면

ffmpeg -i test.mp4 -vf "fps=1" %d.png

test.mp4 파일을 fps=1 단위로 쪼개서 png로 변환해준다.

이전에 -ss -to 기능을 활용해 2초부터 8초 사이의 fps=1 단위로 png로 변환해 줄수도 있다.

-vf "fps=1" 옵션은 fps=2로 변경 시 위 이미지의 2배 결과를 얻을 수 있다. 즉, 0.5초마다 사진이 찍히는 것.

조금 더 디테일하게 영상을 찍어야한다면 저 수치를 건들여 줄 수 있을것이다.

옵션을 없애도 실행은 되지만, 모든 프레임을 다 찍어버리는 탓에 꼭 fps를 명시해줘야 컴퓨터 건강에 이롭다.


7. 마침

ffmpeg 중에서도 매우 단순 기능만을 나열해봤다.

체감상 QA 업무중에는 위 4개 기능이 가장 많이 쓰였고, 그 외의 기능은 필요할때 찾아 쓰곤 했지만 딱히 저 위의 세 기능 말고는 더 쓰지는 않았었다.

이전에 사용한 adb 기능을 연계해서, 영상 녹화 이후 적절히 잘라서 이슈 리포트에 큰 도움이 되었다.

다음에는, adb와 ffmpeg 기능들을 통합하여 더욱 간편하게 사용하는 배치 스크립트 방법을 포스트하려고 한다!

* 컨퍼런스 시청 후 개인적인 느낌을 서술한 감상문이다!
 
영상 링크 : https://www.youtube.com/watch?v=OeNGEB7AAfY

1. 무엇을 소개하는가?

QAMate Autoflow라는, 넥슨의 사내 툴을 소개하는 영상이다.
뭔가 완성도가 너무 좋아서 상용화 되지 않았을까? 하는 이유로 검색을 해봤는데, 아쉽게도 사내에서만 운용되는 툴 같다..
유튜브 영상을 직접 캡쳐해서 가져오면 뭔가 안될거같아서, 어떤 툴인가를 설명하자면

https://unity.com/kr/features/unity-visual-scripting

이런 느낌으로 노드(N)와 간선(E)을 이용해 스크립트를 짜는 툴이었다.
영상에서는 메이플스토리에서 서버를 선택하고 캐릭터를 선택한 후 로그인하는 과정을 자동화 하는 시연을 보여주었다.

사전 조건 : 서버 선택 페이지

  1. 클라이언트의 특정 좌표를 클릭하는 노드 #서버 선택
  2. 몇초간 기다리는 간선 #채널 선택 페이지 나올때까지 기다림
  3. 클라이언트의 이미지 좌표를 더블 클릭하는 노드 # 채널 선택
  4. 몇초간 기다리는 간선 # 캐릭터 선택 페이지 나올때까지 기다림

이런식으로 구성되어있고, "2차 비밀번호 입력" 과 같은 좌표나 이미지를 찾아가는 것으로는 구현하기 힘든 행동에 대해서는 "커스텀 노드" 또한 만들어서 활용하는 모습을 볼 수 있었다.
 

2. 도입배경

기존 QA들이 테스트 자동화를 시도할 때, 아래와 같이 진행 중이었다고 한다.

  1. 상용 솔루션 도입 검토
  2. 내부에서 업무 중에 개발
  3. 파이썬으로 직접 스크립팅

상용 솔루션 도입 검토를 하자니 비용의 문제 + 기껏 다 구축했는데 갑자기 서비스 종료를 하면 어쩌나 라는 걱정,
내부 업무 중 개발을 하자니 QA 업무 중 자동화까지 구현하기에는 너무 리소스 낭비,
파이썬으로 직접 스크립팅 하자니 러닝커브가 있어 신입 QA에게는 벽이 있었다고 한다.
이에 따라, 툴 프로그래머 이신 발표자는 아래와 같은 목표를 했다고 한다.

  1. 상용 솔루션보다 잘 만들어야 함
  2. 파이썬 배우기보다 더 쉬워야 함
  3. 범용성 있어야 함

3. 그래서 만든것

위 목표와 요구사항을 받아들여, 아래처럼 제작을 했다고 한다.

  1. 러닝커브 낮추기
    레고로 비유해서 처음에는 난이도가 낮은 레고를 구입했다가 점점 어려운 레고를 구입하는 것 처럼, 초창기 버전에서는 간단한 기능 (ex. 어디좌표/이미지 클릭) 정도로만 구현했다가 이후 복잡한 기능을 추가했다고 한다.
  2. 귀찮음 줄이기
    보통 자동화를 구현할 때, 여러 귀찮은 과정이 있는데 이러한 문제를 최대한 단순화 했다고 한다.
    - 좌표 찾기 귀찮다: 클라이언트 스샷으로 좌표를 빠르게 얻을 수 있다고 한다.
    - 이미지 따오기 귀찮다: 위와 마찬가지로 스샷으로 이미지를 빠르게 잘라서 파라미터로 세팅할 수 있다고 한다.
    - 노드 만들기 귀찮다: 유저의 액션을 녹화하면 노드로 자동 만들어지게 했다고 한다.(Record & Replay 라고 하나?)
  3. 노드의 조합
    마우스 클릭을 10번하는 이벤트 노드를 만들기보단, 마우스 클릭 + 10번 반복노드를 만드는 방식으로 만들었다.
  4. 단축키
    가장 재미있었던 부분인데, 스타크래프트 단축키를 사용해 B + T 키를 입력하면 Text Input 노드가 생성된다!

Starcraft 단축키

분명 실무자에게는 한계가 있을 수도 있지만, 실사용을 해볼 수 없는 입장에서는 진짜 강력한 툴이라고 생각된다!
이전 회사에서 자동화 구현 중, 모바일 기기 해상도가 각기 달라 정말 단순하게도 그림판을 켜서 좌표를 손수 따오는 나의 방식을 생각하면..

4. 그리고 재미를 주기 위해

  1. 크레딧을 만들었다.
    처음 개발 당시의 기여자에 대해 명단을 작성해준다.
  2. 커스텀이 실용적이면 정식 패치에 합류한다.
    자주 사용되거나, 엄청나게 복잡한 기능을 단순하게 구현해내는 노드를 만들면 정식 패치에 합류하고, 마우스 호버 기능으로 "○ ○ ○가 만듦"  같은 내용을 써주는 것 같다.
  3. 스크립트를 만들면 서버에 올라간다.
    내가 만든거에 대해 타인에게 공유하고, 타인이 만든 효율적인 스크립트를 내가 써보면서 하나의 작은 커뮤니티 역할을 하는 것 같다.

크레딧이나 커스텀에 내 이름이 적혀있고, 신입이 사용하다가 내 이름이 적혀있는걸 본다면 어깨가 절로 솟을 것 같다!
또, 서버에서 스크립트를 공유하면서 나와 타인의 자동화 아이디어를 공유하고, 교류하지 않을까??
 

5. 추가될 기능

Git의 Pull Request 형식으로 개발자의 첨삭을 받을 수 있다고 한다. 2년 전 글이니 만약 이 툴 사용이 폐기되지 않았다면! 아마 구현되지 않았을까 한다.

6. 느낀점

역시 국내 1위 게임회사 라는 생각을 했다.
이전에 독학으로 자동화를 만들어보곤 했지만, 항상 만들다 보면 정신이 없어지는 코드가 나오고 그러는데..
정말 깔끔하게 자동화를 해석하고 구현하는게 대단했다!
이런 툴을 만드는 것 까지는 아니더라도, 이런 기능을 모듈화하는 아이디어라던가? 그렇게 만들면 범용성 높게 만들 수 있었을 것 같다.
이런걸 두고 객체 지향이라고 하는걸까? 맞는 표현인지는 모르겠지만..
아무튼 짧지만 아주 좋은 컨퍼런스를 들어서 너무 유익했다!

'노트 > 컨퍼런스' 카테고리의 다른 글

[컨퍼런스] SLASH 24 - 토스 닥터 후기  (2) 2025.02.20

0. 이슈 리포트 간소화를 하게 된 이유

모바일 기기에서 캡처 / 녹화 파일을 컴퓨터로 옮겨서 업로드하는 과정을 사수에게 묻자, 아래와 같은 방법을 소개받았다.

  1. 모바일 녹화, 캡처 기능 사용해 캡처
  2. 모바일 메신저를 이용해 업로드
  3. PC 메신저로 다운로드

업무 중 모바일 기기를 다뤄야 하는 건 굉장히 불편하고, 번거롭다.

따라서, 모바일 기기를 최대한 안 다루기 위해 툴을 만들었다.

그리고, 무엇보다 CMD 창에서 주르륵 업무가 되는 게 있어 보인다! (중요)

 

우선 직접 만들어 본 툴들을 순서대로 소개하고, 최종적으로 만든 배치 툴을 소개하려고 한다.

아래는 만들어서 쓴 기능들이다.

 

  1. 모바일 스크린샷 캡처 (ADB)
  2. 모바일 영상 녹화 (ADB)
  3. ADB Wi-Fi로 연결 (ADB) 
  4. 영상 압축 (FFMPEG)
  5. 영상 자르기 (FFMPEG)

또 유용한 기능이 있으면 얼마든지 추가할 계획이다.

우선 이번 포스트에서는 캡처, 녹화를 배치스크립트로 만들어 보려 한다.


1. ADB란?

ADB(Android Debug Bridge)는 안드로이드 디바이스와 PC를 연결하여 다양한 작업을 수행할 수 있도록 돕는 CLI 툴.

QA 엔지니어의 입장에서, 앱 설치 및 삭제, 로그 분석, 화면 캡처 등 테스트의 전반적인 도움을 얻을 수 있다!

특히, 여러가지 세팅 또는 테스트 과정에서 물리적인 조작을 명령어 입력으로 해결할 수 있고, 심지어 배치 스크립트를 활용해 행동을 자동화할 수 있다.

그리고, ADB는 오픈소스다!

ADB는 오픈소스 프로젝트

이번 글에서는 ADB와 배치 스크립트를 활용해 캡처/녹화하고, 이를 컴퓨터로 가지고 오는 과정을 자동화하는 간단한! 글이다.


 

2. ADB 설치

구글에 adb 설치를 검색하면 수 많은 글이 있으니, 보고 따라 하면 누구나 다운로드할 수 있다.

크게 해야 할 행동은 아래와 같다.

  1. ADB 설치해서 압축 해제
  2. 압축 해제 된 위치를 "시스템 환경 변수 편집"에 추가
  3. 휴대폰을 adb 사용 가능하게 설정 (USB 디버깅)

위 행동을 하고 나면, 명령 프롬프트(cmd) 창에서 adb devices를 입력해 보자.

실행 화면

위와 같이 실행되면 성공!

만약 연결된 디바이스가 있다면, 아래 이미지처럼 나온다.

R3CRA0JW89R => 내 단말기의 시리얼 넘버

device => 상태


3. 캡처

이제 다음과 같은 명령어를 입력해 볼 수 있다.

adb shell screencap -p /sdcard/screenshot.png

말 그대로, 스크린샷을 찍어보겠다는 의미.

스크린샷을 찍어서, /sdcard/screenshot.png  경로에 스크린샷이 저장된다.

adb pull /sdcard/screenshot.png

스크린샷을 찍으면, adb pull 명령어를 입력해 휴대폰에 저장된 스크린샷을 컴퓨터로 옮길 수 있다.

아래 이미지처럼, adb_cap/screenshot.png 와 같이 경로를 지정해도 된다. 대신 adb_cap 폴더가 있어야 함.

이미지 캡처

 

배치 스크립트를 만들어, 위 일련의 과정을 자동화할 수 있다.

아래 스크립트를 메모장에 적고, 확장자를 .bat로 바꿔서 저장하고 실행하면 빠르게 작동하는 캡처 스크립트가 완성된다.

@echo off

set /p file_name="Input file name : "

adb shell screencap -p /sdcard/screenshot.png

adb pull /sdcard/screenshot.png %file_name%.png

@echo off는 배치 스크립트가 깔끔하게 나오게 하는 기능이다. (실행 과정을 일일이 보여주는 "복창" 기능을 끄게 함)

file_name 변수에 파일명을 집어넣고,

스크린샷을 찍고,

추출할 때 %file_name% 을 이용해 png 이름을 파일명으로 저장한다.

 

📌 사용 방법

  1. 메모장에 위 스크립트 붙여 넣기 후 .bat 확장자로 저장 (adb_screenshot.bat)
  2. 배치 스크립트를 실행 (adb_screenshot.bat)
  3. 파일명을 작성 (영어로 작성)
  4. 자동으로 스크린샷 촬영 → "파일명.png" 파일이 PC로 이동

 

 

adb shell screencap -p /sdcard/screenshot.png 명령어를 반복하면, 기존 저장된 동일명의 이미지는 사라진다.

혹시 모바일 기기 용량 걱정에 직접 지우고 싶으면, 아래 명령어를 추가하면 된다.

adb shell rm /sdcard/screenshot.png

 

이제, 배치파일을 실행하고 파일명을 적는 것 만으로 자동으로 스크린숏이 저장되고, 컴퓨터로 옮길 수 있다!

 


4. 녹화

캡처가 있으면, 녹화 기능 또한 있다.

아래는 녹화 기능 명령어를 소개한다.

adb shell screenrecord /sdcard/record.mp4

해당 스크립트를 입력하면, 최대 3분까지 녹화가 된다.

중간에 Ctrl + C를 눌러 영상 녹화를 중단할 수 있다.

 

캡처와 마찬가지로, 일련의 과정을 배치 스크립트로 자동화할 수 있다.

 

@echo off

set /p file_name="Input file name : "

echo Recording...

echo press Ctrl + C and "N" to quit recording

adb shell screenrecord /sdcard/record.mp4

adb pull /sdcard/record.mp4 %file_name%.mp4

위와 유사하나, Ctrl + C를 누른 후 "N"을 입력하라는 안내 문구를 추가했다.

 

📌 사용 방법

  1. 메모장에 위 스크립트 붙여 넣기 후 .bat 확장자로 저장 (adb_screenrecord.bat)
  2. 배치 스크립트를 실행 (adb_screenrecord.bat)
  3. 파일명을 작성 (영어로 작성)
  4. 자동으로 스크린샷 촬영 → "파일명.mp4" 파일이  PC로 이동

 

배치 스크립트에서 Ctrl + C 는 스크립트 작업을 종료한다는 키

* Ctrl + C를 누르고, 위와같이 N 입력 후 Enter을 해야 스크립트가 진행된다.


5. 마침

adb 중 아주 기초적이고 단순한 기능이고, QA 업무를 조금이라도 해본 사람들이면 아마 쉽게 알 내용들이다..만!

분명 메신저로 파일을 옮기고 있을 사람들이 분명 있을 것 같아서.. 도움이 될 수도 있을 것 같아 길게 작성해 봤다!!

다음번에는, ffmpeg를 이용해 영상을 압축하고, 자르는 기능을 소개하려고 한다..!

1. 기초

SELECT 칼럼 FROM 테이블 : 테이블에서 칼럼을 선택하겠다는 뜻. 칼럼은 세로줄

WHERE : 어느 조건으로 할거니? 라는 뜻

DISTINCT : SELECT 앞에 쓰고, 중복없이 뽑아내겠다. 라는 뜻

AS : 별명부여, 칼럼 명칭을 별명으로 지어주면서 가독성있게 뽑아내겠다.

|| : 결합해서 뽑아내겠다. 

ex) SELECT price || '원' FROM table ; -> 테이블에서 price를 뽑아낼건데, 뒤에 '원' 텍스트를 붙이고싶다.

ORDER BY : 제일 마지막에 넣고, 마지막에 실행됨. ASC = 오름차순, DESC = 내림차순으로 정렬하겠다.

 

2. WHERE 연산자

=,<,<=,>,>= : 비교 연산자

!=,^=,<>,NOT 칼럼 명=,NOT 칼럼 명> : 부정 비교 연산자

AND,OR,NOT : 논리 연산자

LIKE '%', BETWEEN A AND B, IN (list) , IS NULL : SQL 연산자

LIKE 문에는 %, _ 와일드카드가 있음. % = 모든, _ = 한개

 

 

3. NULL에 관해

NVL(A,0) : A 칼럼이 NULL이면 0으로 바꾸겠다.

NVL2(A,1,0) : A칼럼이 NULL이면 0, NULL이 아니면 1

NULLIF(A,100) : A=100 경우 NULL, 이외에는 A 반환

 

4. GROUP BY

GROUP BY : 소규모 행을 그룹화 하겠다.

HAVING : Groupby의 조건문

ex)

SELECT NO, SUM(PRICE)
	FROM TABLE
GROUP BY NO
HAVING SUM(PRICE) >10000;

뜻 : TABLE에서 PRICE 합계가 10000 이상인 경우에만 조회가 된다.

 

ROLLUP, GROUPING SETS, CUBE 세가지 이해하기

 

ROLLUP : 계층적 합계

SELECT DEPTNO, SUM(SAL) AS TOTAL_SAL
FROM EMP
GROUP BY ROLLUP(DEPTNO, JOB);

맨 처음 명시된 칼럼 (DEPTNO)에 대한 소 그룹 합계를 구해줌

행의 수 = (DEPTNO * JOB) + JOB + 1

DEPTNO * JOB = 소그룹

+ JOB = DEPT에 해당하는 JOB 소그룹 합계

+1 = 전체 합계

 

CUBE : 모든 조합 집계

SELECT DEPTNO, JOB, SUM(SAL) AS TOTAL_SAL
FROM EMP
GROUP BY CUBE(DEPTNO, JOB);

 

저 위에값에, 두번째 칼럼(JOB)에 대한 합계도 더 있음

 

GROUPING SETS : 특정 항목 소계

SELECT DEPTNO, JOB, SUM(SAL) AS TOTAL_SAL
FROM EMP
GROUP BY GROUPING SETS((DEPTNO), (JOB));

 

DEPTNO에 대한 합계, JOB에 대한 합계만 나옴. 전체합계, 조합합계같은건 X

 

 

5. JOIN

JOIN? PK(기본키),FK(외래키) 기준으로 여러 테이블을 합치는 행위

 

EQUI JOIN, INNER JOIN : 거의 같음. 아래 차이점정도?

구분 EQUI JOIN INNER JOIN
조인 방식 =(동등 비교)만 사용 =, <, >, != 등 다양한 연산자 사용 가능
문법 스타일 WHERE 절을 사용 (구식 SQL 스타일) JOIN ON을 사용 (표준 SQL 스타일)
포함 관계 INNER JOIN의 일부 EQUI JOIN을 포함하는 더 일반적인 개념
가독성 비교적 낮음 더 읽기 쉽고 명확함
권장 여부 현대 SQL에서는 잘 안 씀 현대 SQL에서는 주로 사용

 

요약 : INNER JOIN 자주씀

 

NON EQUI JOIN : 2개의 테이블 간에 칼럼 값들이 서로 정확하게 일치하지 않는 경우에 사용 ‘=’ 연산자가 아닌 BETWEEN, >, <= 등 연산자 사용

 

NATURAL JOIN : WHERE절에서 JOIN 조건 추가 불가 / SELECT EMP.DEPT처럼 OWNER명 사용X

CROSS JOIN : WHERE절에서 JOIN 조건 추가 가능

 

 

6. SAVEPOINT, ROLLUP, COMMIT

 

SAVEPOINT : 말그대로 세이브포인트

ROLLBACK TO :어디 세이브포인트까지 롤백하겠다 

COMMIT : GIT처럼 커밋하겠다

* DDL(CREATE, ALTER, DROP, RENAME, TRUNCATE TABLE)은 자동으로 커밋됨.

** 롤백은 안적으면 가장 최근 커밋한곳까지 롤백함

7. 그 외 함수

SUBSTR : 엑셀의 =MID 함수랑 미슷한듯

TRIM : 양옆으로 특정 문자 자르기, LTRIM, RTRIM은 왼쪽오른쪽 특정

SIGN : 숫자가 양수면1, 음수면-1, 0이면 0

CEIL/CEILING : 올림 

FLOOR : 내림

ROUND : 반올림

거의 대부분 엑셀이랑 유사한 함수들

 

 

 

 

 

다음번 목표 : 기출 풀어보고, 틀려보며 유형 파악

자동 플레이가 지원되는 게임들이 많다.

하지만, 자동 플레이 중에서도 "특정 상황일 때 특정 행동을 하고싶다" 가 있을 것이다.

간단하게도, 특정 상황이 시간이라면, 타이머를 맞추고 타이머가 울리면 해당 행동을 하면 된다.

하지만, 특정 상황이 "아이템 드랍"이거나, "팝업 발생"과 같은 주로 "시각"에 의해 결정되는 경우가 많았다.

 

ex) 자동 사냥 도중, 죽었을 때 (상황) 나한테 알림이 왔으면 좋겠다 (행동).

ex) 게임 플레이 도중 게임을 멈추는 팝업이 나오면 (상황) 스킵 하고싶다 (행동).

 

아래는 실제 프로젝트에서 자동화 한 경험을 토대로, 이전에 만든 파이썬 자동화 아이디어를 소개하고자 한다.

프로젝트를 진행하면서, OPENCV 라이브러리에 대해 전혀 알지 못하고 가져다 쓴 케이스여서, 더 좋은 방법이 많겠지만 아래 방법만으로도 충분히 작동하기는 해서.. 아래 방법으로 진행했다!

(지적은 환영합니다.)

 

상황

게임을 자동 플레이 시켜 놓으면, 랜덤 확률로 특정 팝업이 등장했었다.

해당 팝업을 수동으로 터치해야 게임 자동플레이를 이어갈 수 있었다.

게임을 플레이하다보면 특정 팝업이 노출되고, 특정 영역을 터치해야 진행되는 형식

통계 목적으로 게임 자동 플레이 데이터를 누적시키기 위해 자동 플레이를 진행하며 업무를 진행 했으나, 간헐적으로 팝업이 나오면 수동으로 눌러줘야 하는 번거로움이 있었다.

또한, 업무 시간 외에는 데이터 누적이 되지 않는다는 점도 큰 단점으로 작용했다.

 

 

아이디어

팝업이 등장했는지 여부를 판단하기 위해, OPENCV의 이미지 유사도 비교 기능을 활용했다.

게임 화면에서 실시간으로 캡처한 이미지를, 저장해둔 팝업 이미지와 비교하여 일정 유사도 이상이면 "팝업 등장"으로 판단하는 방식이다.

 

# 이미지 유사도 측정

import cv2

def process_image(image_path):
    image = cv2.imread(image_path)
    image = cv2.resize(image, (300, 300))
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    hist = cv2.calcHist([gray_image], [0], None, [256], [0, 256])

    return hist


def compare(hist1, hist2):
    return print(f"Correl = {cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)})
    
image_1 = process_image("image_1.png")
image_2 = process_image("image_2.png")

compare(image_1,image_2)

 

이렇게 이미지를

  1. 읽고 (cv2.imread)
  2. 사이즈를 300x300으로 조정하고 (cv2.resize)
  3. BGR2GRAY를 통해 흑백 이미지로 변경하고 (cv2.COLOR_BGR2GRAY) // 대부분 흑백이미지로 해서 따라했다.
  4. calcHist를 통해 이미지를 히스토그램이라고 부르는 데이터로 변경했다.

위 과정을 통해 히스토그램이 도출되면, cv2.compareHist를 이용해 이미지 두개를 비교하면 유사도 값이 나왔다.

 

아래는 이미지 세개를 샘플로 사용해 보겠다!

1. 평상시 게임 화면 예시
2. 팝업이 노출된 화면 예시
3. 위 사진에서 밝기 5%를 올린 화면

 

1번 이미지와 2번 이미지 히스토그램을 compare 했을 때, 아래와 같은 값이 나왔다.

Correl = 0.5612258110033705

 

즉, HISTCMP_CORREL 방식을 이용했을 시 56%의 유사도가 있다. 라고 해석할 수 있다.

 

다음은, 2번 이미지와 3번 이미지 히스토그램을 compare 했을 때, 아래와 같은 값이 나왔다.

Correl = 0.857824606065485

즉, 이건 85.7%의 유사도가 있다. 라고 해석할 수 있다.

 

위 유사도 측정 알고리즘을, 이렇게 표현할 수 있다.

 

이러한 자동화를 안드로이드 환경에서 진행했고, 따라서 adb 기능을 활용해 이미지를 실시간으로 갱신할 수 있었다.

os.system('adb shell screencap -p /sdcard/screenshot.png')
os.system('adb pull /sdcard/screenshot.png screenshot.png >nul')

screencap으로 스크린샷을 찍고, pull 기능을 통해 스크린샷을 자동화 스크립트 폴더로 추출, While True 반복문으로 무한 반복하는 기능

 

이후, 무한 반복으로 실시간 이미지와 미리 찍어둔 팝업 이미지가 일정 유사도보다 클 경우 특정 행동을 하게끔 만들었다.

if correl > 0.85:
	print("팝업 발생")
    os.system(f'adb shell input tap {tapx} {tapy}')

 

 

결과

기존에는 업무시간에만, 데이터 누적이 가능했던 상황을 24시간 가동 가능하게끔 환경을 만들 수 있었다.

또한, 중간에 팝업이 나오면 눌러줘야하는 번거로움 + 업무가 중간에 끊겨 몰입이 깨지는 상황을 제거하여 업무에 몰입할 수 있었다.

 

 

Q&A

Q1. Appium으로 element를 찾아서 하는 방식은 왜 시도 안했을까?

A1. Unity 기반 게임이었는데, Unity 기반 게임은 uiautomator로 화면 내 element가 잡히지를 않았다.

 

Q2. 왜 팝업 화면이 100%가 아니고 85%의 유사도일까?

A2. 팝업이 나온 화면이라도, 뒷 배경에서 이펙트같은 게 나오곤 했다. 만약 이펙트 같은게 없고 뒷 배경도 동일한 게임이라면 100%의 유사도가 나올 것. 이 프로젝트를 진행할 때 실제 게임에서 팝업이 나왔을땐 Correl 값이 0.9 이상으로 나왔었다.

 

Q3. 따라해봤는데 비슷한 화면이었는데 유사도값이 잘 안나온다.. 

A3. History 비교 기능에는  'CHISQR', 'INTERSECT', 'BHATTACHARYYA', 'EMD' 와 같은 다양한 방식이 있다. 혹시 이 글을 보고 따라해봤는데 안되면 다양한 방식을 찾아보는것도 추천!

또한, 위 케이스는 전체 화면을 가리는 팝업에 대한 이미지 유사도 분석이지만, 실시간 이미지와 미리 찍어둔 이미지 특정 좌표만을 비교할 수도 있다.

 

Q4. 더 나은 방법은 없었을까?

A4. 개발중인 게임이라면 로그가 나올 수도 있다. (adb logcat과 같은) 로그에서 팝업이 나오는 시그널이 나올 수도 있다! 로그에서 팝업 시그널이 나오면 특정 좌표를 누르는 형식으로도 자동화가 가능할 것 같다.

 

 

결론

OPENCV 라이브러리를 보면서, 아래와 같은 기능을 보게 되었다.

  • 화면 내 특정 이미지의 좌표 찾기

이런 기능도 배워두면 좋지 않을까?

또, 우연찮게 OPENCV를 400페이지정도는 될 것 같은 책으로 보게 되었다.

유튜브에서는 Opencv 라이브러리를 이용해서 자동차 번호 인식하는 기능도 쓴다고 한다..!

음.. 그냥 나는 당장은 저정도 기능을 쓰는걸로 만족해야겠다고 다짐했다.. ㅎㅎ;

언젠가 필요하면 배워보는게 좋을 것 같다!

'자동화' 카테고리의 다른 글

[자동화] 테스트 자동화 ROI 계산  (1) 2025.02.19

+ Recent posts