주어진 직사각형을 1 * 1 사각형으로 나눈 개수를 구할 때 두 꼭짓점을 이어서 생기는 대각선이 지나는 사각형은 제외해야 합니다.
전체 사각형 개수는 주어진 w와 h를 곱하면 해결되는데 문제는 대각선이 지나가는 사각형들의 개수를 구하는 거네요.
기울기는 높이 증가량 % 밑변 증가량 인데 이걸 사용하나?
삼각형의 기울기는 높이 / 밑변
현재 문제 상 h / w 인데...
예시에서의 기울기는 12 / 8 = 1.5 이고 차지한 칸은 16, 대각선의 길이는 \sqrt(144 + 64) = 약 14.4220510...
이라 길이와 차지한 칸은 상관이 없어보이고...
x = 0에서 y =0, x = 1에서 y = 1.5 즉 (0, 0), (0, 1) 사각형을 지난다. 차지하는 사각형은 올림으로 처리?
매 x를 증가하면서 y 변화량을 올림처리해서 개수로 처리하면 지나간 사각형의 개수가 되나?
x 최대는 8이므로 증가량(기울기)를 반올림한 2와 곱하면 16이 되기는 합니다.
대차게 실패했습니다. 정확성 38.9 %
#include <cmath>
using namespace std;
long long solution(int w,int h) {
long long answer = w * h - ceil((float)h / w)* w;
return answer;
}
어떤 식으로 생각해야 하는 지 몰라서 gemini에게 힌트를 요청했습니다.
1. 대각선이 격자를 지날 때 특정 지점에서 격자점을 정확히 통과한다.
2. GCD와 관련이 있다.
3. 직사각형을 작은 블록으로 나누어 그 블록에서 못 쓰는 사각형을 구한다. - 잘못이해한 힌트
3. 가로 , 세로 인 작은 직사각형에서 대각선이 지나가며 건드리는 정사각형의 개수는 개입니다.
그러네요.. 기울기와 두 길이의 gcd가 있다면 몇 블록 마다 정확히 꼭지점을 구하는 지 알 수 있고,
이 블록이 하나의 작은 사각형이 될 테니 전체 길이 / 블록 길이 * 블록당 사용하지 못하는 사각형 을 하면 못 쓰는 사각형의 전체 개수를 구할 수가 있네요.
대각선은 결국 격자를 하나 넘을 때마다 새로운 칸을 만납니다.
즉 x축으로 이동하며 x축 길이 만큼의 칸을, y축으로 이동하며 y축 길이 만큼의 칸을 만나게 됩니다.
x + y 에서 이중 중복되는 칸의 수를 빼주면 대각선이 지나는 칸의 개수가 됩니다. 여기서 중복되는 칸에 해당하는 것이 gcd가 됩니다.
이해했습니다. 그러면 최종적으로 사용 가능한 칸의 수는 w * h - (w + h - gcd)가 됩니다.
#include <cmath>
using namespace std;
int GetGCD(int a, int b)
{
return a % b == 0 ? b : GetGCD(b, a % b);
}
long long solution(int w,int h) {
long long answer = (long long)w * h;
int gcd = GetGCD(w, h);
answer -= (w + h - gcd);
return answer;
}
참고 문서
https://dev.epicgames.com/documentation/unreal-engine/using-animation-blueprint-linking-in-unreal-engine
https://dev.epicgames.com/documentation/unreal-engine/animation-blueprint-linking-in-unreal-engine
ALI 생성은 콘텐츠 브라우저 -> 우클!
릭 -> Animation에서 AnimLayerInterface를 설정하면 됩니다.

생성된 LayerInterface에서 MyBlueprint 창의 Add를 눌러서 레이어를 추가합니다.
레이어 선택 후 아래의 details 패널에서 Inputs를 추가 및 바인딩이 가능합니다.
사용 가능한 입력 파라메터와 다수의 입력 포즈를 노출시킬 수 있다고 합니다.
생성된 레이어는 ABP의 Class Default의 Implemented Interfaces에 Add를 해주어야 사용이 가능합니다.

레이어는 일반 노드 처럼 배치해서 사용이 가능합니다.
이 때 Instance Class를 등록하면 등록한 클래스에서 정의된 내용으로 적용이 됩니다.
정확히는 Linked Anim Layer 노드는 인스턴스 클래스(Instance Class) 프로퍼티를 가지며 이를 사용하여 디폴트 레이어 오버라이드를 지정할 수 있다고 합니다.

제대로 동작하는 지 확인하기 위해 캐릭터 BP에서 다음의 노드들을 추가합니다.

이제 H를 누르면 Lyaer에 ABP_TestUE4Mannequine이 연결되고 손을 때면 해제됩니다.
ABP_TestTemplate에서 ALI 재정의

ABP_TestUE4Mannequine에서 Sequence 값 지정

현재 ABP_TestTemplate에서 Sequence가 비어있을 때, 유효하지 않을 때는 기존 입력을 사용하도록 수정했습니다.
BlendPoses by bool을 사용하면 되는 거였네요.


문제는 지금 사용 중인 IsValid가 ThreadSafe가 아니라는 점이네요. 여기서 Property Access를 사용해야 겠습니다.

Blend Poses by bool의 Active Value에 우클릭하고 Sequence를 검색한 뒤 변수로 긍격된 Sequence를 찾아 IsValid를 클릭하면 된다고 하는데.. 검색해도 나오질 않네요.

아하!
"일반적인 애니메이션 블루프린트의 멤버 변수와 달리, 레이어 인터페이스에서 승격된 변수는 내부적으로 함수의 지역적 파라미터와 유사하게 취급되어 속성 액세스 시스템이 직접 추적하지 못할 수 있습니다." 라고 합니다.
여러 방법을 시도 중입니다.
맨처음에 변수 직접 연결했다. Thread Safe 하지 않다는 경고가 나왔습니다.
그 이후에 Bind를 시도했더니 검색이 안된 거굥,
Property Access를 사용하려 하니 Sequence는 감지가 되지만 IsValid가 드롭다운에 존재하질 않습니다.
PropertyAccess에 Sequence를 바인딩하고 그 노드에 IsValid를 연결한뒤 BlendPoses by boll에 연결하니 여전히 이런 경고가 나오고 있네요.
Result was visible but ignored
Node Blend Poses by bool uses potentially thread-unsafe call Is Valid . Disable threaded update or use a thread-safe call. Function may need BlueprintThreadSafe metadata adding.
[7439.11] Compile of ABP_TestTemplate successful, but with 1 Warning(s) [in 75 ms] (/Game/ALIStudy/Animation/ABP_TestTemplate.ABP_TestTemplate)
기본 Is Valid 노드가 멀티스레드 환경에서 안전하지 않은 로직을 포함하고 있기 때문인 것으로 보이는데..
아예 커스텀 Thread-Safe 유효성 검사 함수 생성하는 수밖에 없는 것 같았는데 이거 그냥 Valid 대신 Not Equal Null로 비교하는 게 낮나? 라는 것을 알게 되었습니다.
Thread-Safe 함수에서 어차피 IsValid 못 쓰니 내부에서 Not Equal 로 연결하는 수밖에 없는데.. 그럼 굳이 함수로 만들 필요 없이 그냥 Layer 내에서 하면 되는 게?
일단 지금 필요한 Thread-Safe 함수를 만드는 방법은 다음과 같습니다.
일반 함수 생성 처럼 My Blueprint 패널에서 Functions 옆의 [+] 버튼 클릭
Details 설정
Is Pure: 체크 (실행 핀 제거)
Thread Safe: 체크 (매우 중요), Advanced로 접혀져 있을 수 있으니 확인 필요
함수의 Inputs에 Anim Sequence (Object Reference) 타입을 추가
함수의 Outputs에 Boolean 타입을 추가하고 이름을 ReturnValue로 설정
내부로직
함수 그래프 안에서 입력받은 Sequence 핀을 끌어 Not Equal (Object) 노드(노드 모양: !=)를 검색하여 배치
Not Equal 노드의 아래쪽 핀은 Select Asset 상태(빈 값, None)로 둡니다.
이 결과값을 Return Node에 연결합니다.
참고: != None 체크는 순수 연산이므로 Thread-Safe하게 동작합니다.
만들고 테스틀 해보니 함수 만들 필요 없이 NotEqual로 바꾸기만 하면 되는 문제였습니다.

Layer를 링크하는 부분을 보니 Lyra에서는 이 링크를 태그를 보고 결정하는 식으로 되어 있겠구나 싶습니다.
위에서 ABP_TestTemplate에서 로직 구현, ABP_TestUE4Mannequine에서 Sequence 값 지정을 했는데 이중 ABP_TestTemplate은 Template로 생성된 ABP입니다.
템플릿은 특정 스켈레톤 에셋이나 애니메이션을 참조하지 않는 블루프린트입니다. 즉 애니메이션 블루프린트 로직을 모듈형 방식에 더 가깝게 재사용할 수 있다고 합니다.
생성 시에는 일반 ABP를 생성하는 과정에서 Skeleton 설정 시 옆 탭을 클릭해서 Template를 선택하면 됩니다.
애니메이션 블루프린트 템플릿은 일반 애니메이션 블루프린트와 동일한 인터페이스 및 에디터를 포함합니다. 하지만 템플릿은 스켈레톤에 대응하지 않기 때문에 특정 스켈레톤과 연관된 애니메이션이나 에셋을 직접 참조할 수 없습니다. 그 대신 템플릿 로직을 파라미터화하고 다른 블루프린트에서 설정된 변수를 노출할 수 있습니다.
제 경우에는 Sequence가 그것이었네요.
Anim Layer Interface 정의 시 Input 부분에 정의해 놓은 속성이 아니어서 핀으로 노출되지 못한 것 같습니다.
https://dev.epicgames.com/documentation/unreal-engine/animation-optimization-in-unreal-engine?application_version=5.0
공식 문서에서 다루고 있는 최적화 기법은 크게 4가지입니다.
멀티 스레드 업데이트, URO(업데이트 레이트 최적화), 패스트 패스, Thread Safe Update Animation

멀티 스레드는 애니메이션 계산을 CPU 여러 개에 분산시키는 것으로, 이미 기본값으로 켜져 있습니다. 프로젝트 세팅에서 확인 가능합니다.
URO(업데이트 레이트 최적화)는 멀리 있는 캐릭터의 애니메이션 갱신 빈도를 자동으로 줄여주는 기능입니다. 화면에 NPC가 많을수록 효과가 큽니다.
패스트 패스는 애님 그래프 노드들이 블루프린트 VM을 거치지 않고 빠르게 실행되도록 하는 것인데, 이벤트 그래프에서 미리 계산해 둔 변수를 애님 그래프에서 읽기만 하는 구조로 짜면 자연스럽게 활성화된다고 합니다.
Thread Safe Update Animation은 업데이트 로직을 워커 스레드에서 실행되도록 분리하는 중급 기법이고, FAnimInstanceProxy는 C++ 환경에서 스레드 간 데이터 충돌을 막기 위한 고급 구조라고 합니다.
처음이라면 멀티스레드와 URO가 켜져 있는지 확인하고, 패스트 패스 경고 아이콘을 줄이는 것부터 시작하는 것이 권장됩니다.
비유: 멀리 있는 NPC는 사실 자세히 볼 수 없습니다. 그래서 가까운 캐릭터는 매 프레임 애니메이션을 갱신하고, 멀리 있는 캐릭터는 2~4프레임에 한 번만 갱신합니다.
화면에 수십 명의 캐릭터가 있을 때, 모두 매 프레임 애니메이션을 갱신하면 엄청난 CPU 비용이 발생합니다. URO는 거리에 따라 업데이트 빈도를 자동으로 줄여줍니다. 멀리 있는 캐릭터는 중간 포즈를 보간(Interpolation)해서 자연스럽게 보이게 합니다.
설정 방법:
스켈레탈 메시 컴포넌트 선택 → Details 패널 → Enable Update Rate Optimizations 체크
디버그 시각화: Display Debug Update Rate Optimizations도 체크하면 화면에 현재 업데이트 빈도가 표시됩니다.
주의: 보간(Interpolation)은 게임 스레드에서 실행되므로 완전히 공짜는 아닙니다. 하지만 전체 애니메이션 평가보다 훨씬 저렴합니다.
Blueprint VM 우회 최적화
애님 그래프 안의 노드들을 계산할 때, 블루프린트 가상 머신(VM)을 거치지 않고 직접 C++ 수준으로 실행하는 최적화입니다. 단순한 변수 읽기/쓰기, 멤버 변수 직접 접근 등은 패스트 패스를 탑니다.
패스트 패스를 타지 않는 경우:
확인 방법: 애님 그래프에서 패스트 패스를 타지 않는 노드에는 경고 아이콘이 표시됩니다.
초심자 팁: 복잡한 연산은 이벤트 그래프에서 미리 계산해두고, 애님 그래프에서는 변수를 읽기만 하도록 구조를 짜면 패스트 패스 효율이 높아집니다.
스레드 안전 업데이트 함수
비유: 이벤트 그래프의 "Update Animation" 이벤트는 항상 메인 도로(게임 스레드)에서만 달립니다. "Thread Safe Update Animation" 함수는 보조 도로(워커 스레드)에서 달릴 수 있어서 메인 도로의 교통 체증을 줄여줍니다.
일반 Event Update Animation은 게임 스레드에서만 동작해서 멀티스레드 혜택을 못 받습니다. 대신 Blueprint Thread Safe Update Animation 함수를 오버라이드해서 로직을 여기에 작성하면 워커 스레드에서 실행됩니다.
사용 방법:
My Blueprint 패널 → Functions → Override 드롭다운 → Blueprint Thread Safe Update Animation 선택
주의사항: 이 함수 안에서는 게임 오브젝트의 수명에 영향을 주는 작업(예: 액터 생성/파괴)을 하면 안 됩니다. 변수 읽기/계산만 해야 합니다.
중요: Property Access 노드를 사용해서 데이터를 읽어야 합니다. 일반 변수 직접 접근은 스레드 충돌을 일으킬 수 있습니다
애님 인스턴스 프록시
비유: 원본 서류(UAnimInstance)에 직접 여러 사람이 동시에 접근하면 충돌이 생깁니다. 그래서 "복사본(Proxy)"을 만들어 워커 스레드가 복사본을 다루게 하고, 원본은 게임 스레드가 안전하게 관리합니다.
멀티스레딩 환경에서 스레드 간 데이터 충돌을 방지하기 위한 C++ 구조입니다. 애니메이션 계산에 필요한 데이터를 UAnimInstance에서 분리해서 FAnimInstanceProxy에 복사해 두고, 워커 스레드는 이 프록시 데이터만 참조합니다.
블루프린트에서 해야 할 것:
초심자라면: C++ 없이 블루프린트만 쓴다면 직접 다룰 일은 거의 없습니다. 엔진이 내부적으로 처리합니다.
C++ 개발자라면 NativeUpdateAnimation 대신 NativeThreadSafeUpdateAnimation을 오버라이드하는 것이 권장됩니다.
A: ALI 자체는 중급 기법이 맞지만, Thread Safe와의 관계는 약간 다릅니다.
애님 블루프린트의 일부 레이어를 "인터페이스"로 분리해서, 런타임에 다른 애님 블루프린트로 교체할 수 있게 해주는 기능입니다. 예를 들어 "달리기 레이어"만 캐릭터별로 다르게 교체하는 식입니다.
ALI 내부 로직이 Thread Safe여야 한다는 건, ALI 자체의 제약이 아니라 부모 애님 블루프린트가 Thread Safe 모드로 동작할 때 그 안에 연결된 ALI 레이어도 같은 스레드 환경에서 실행되기 때문입니다.
부모 AnimBP가 워커 스레드에서 실행됨
그 안에 링크된 ALI 레이어도 같은 워커 스레드에서 호출됨
따라서 ALI 레이어 안에서 게임 스레드 전용 작업(액터 참조, 컴포넌트 직접 접근 등)을 하면 크래시 또는 데이터 오염이 발생할 수 있음
Thread Safe Update Animation을 쓰지 않으면 ALI도 딱히 Thread Safe를 신경 쓸 필요가 없습니다.
음.. ABP_TestTemplate에서 Use Multi Threaded Animation Update가 켜져 있었던 것으로 추정됩니다.
ALI 레이어가 독립적으로 Thread Safe를 요구하는 게 아니라, 애님 그래프 전체가 워커 스레드에서 실행되는 환경이었기 때문에 그 안의 모든 노드에 Thread Safe가 요구된 것으로 Claude는 추측했습니다.
A: 방향은 비슷해보이지만 실제로는 역할이 꽤 다릅니다.
둘 다 "워커 스레드에서 안전하게 데이터를 읽기 위한 수단"이라는 목적을 공유합니다. 그래서 Thread Safe 맥락에서 함께 언급되는 경우가 많습니다.
Property Access는 읽기 경로(Read Path) 문제를 해결합니다. 워커 스레드에서 실행 중인 애님 그래프가 게임 스레드에 있는 데이터(캐릭터 속도, 상태 등)를 안전하게 가져오는 메커니즘입니다. 엔진이 적절한 타이밍에 값을 복사해두고, 워커 스레드는 그 복사본을 읽습니다.
FAnimInstanceProxy는 데이터 소유권(Ownership) 문제를 해결합니다. UAnimInstance 자체가 게임 스레드 오브젝트이기 때문에, 워커 스레드에서 직접 접근하면 위험합니다. 그래서 워커 스레드가 소유하고 자유롭게 읽고 쓸 수 있는 전용 데이터 공간을 따로 만드는 것입니다.
비유로 정리하면
| 비유 | 역할 | |
|---|---|---|
| Property Access | 회의 전에 미리 뽑아둔 보고서 사본 | 게임 스레드 데이터를 안전하게 읽어오는 통로 |
| FAnimInstanceProxy | 워커 전용 작업 공간 | 워커 스레드가 소유하고 자유롭게 쓸 수 있는 데이터 구역 |
Property Access는 "저쪽 데이터를 어떻게 안전하게 가져올까"의 답이고, FAnimInstanceProxy는 "워커 스레드가 자기 데이터를 어디에 보관할까"의 답입니다.
블루프린트 환경에서는 Property Access만으로 대부분 해결됩니다. FAnimInstanceProxy는 C++에서 워커 스레드가 프레임마다 계산하고 유지해야 하는 복잡한 중간 상태(예: IK 계산 결과, 누적 데이터)를 안전하게 저장할 공간이 필요할 때 사용합니다. 단순히 캐릭터의 속도나 불리언 값을 읽는 수준이라면 Property Access로 충분합니다.
URO는 제가 담당하게 될 몬스터에서도 유용하게 사용될 것 같아 추가로 알아보려 합니다.
기본 전제 — URO가 멀티플레이어에서 더 중요한 이유
싱글플레이어는 플레이어 캐릭터 1명 + 몇 명의 NPC지만, 멀티플레이어는 화면에 수십 명의 다른 플레이어 캐릭터가 동시에 있을 수 있습니다. 모두 매 프레임 풀 애니메이션 평가를 하면 CPU가 버팁니다.
실용 팁
1. 자기 자신(로컬 캐릭터)은 URO에서 제외하세요
URO를 켜면 가까운 거리에서도 업데이트가 스킵될 수 있습니다. 내 캐릭터는 항상 화면 중앙에 있고 가장 잘 보이므로, 로컬 플레이어의 캐릭터는 URO를 끄거나 업데이트 빈도를 최대로 고정하는 것이 좋습니다.
| 거리 | 권장 업데이트 빈도 |
|---|---|
| 0 ~ 10m (근거리) | 매 프레임 |
| 10 ~ 30m (중거리) | 2프레임에 1회 |
| 30m 이상 (원거리) | 4~6프레임에 1회 |
C++에서 FAnimUpdateRateParameters로 구간별로 세밀하게 제어할 수 있다고 합니다.
Interpolation(보간)은 반드시 켜두세요
URO로 업데이트를 건너뛸 때 보간 없이 쓰면 캐릭터가 뚝뚝 끊겨 보입니다. Enable Update Rate Optimizations와 함께 Enable Interpolation도 켜져 있는지 확인하세요.
보간은 게임 스레드 비용이 있지만 체감 품질 차이가 큽니다.
중요도가 높은 캐릭터는 예외 처리하세요.
같은 팀원, 파티원, 또는 전투 중인 적처럼 플레이어가 집중해서 보는 캐릭터는 URO 비율을 낮추거나 끄는 것이 좋습니다.
"지금 이 캐릭터가 얼마나 중요한가"를 게임플레이 로직으로 판단해서 동적으로 조정하는 방식입니다.
URO + LOD를 함께 쓰세요
URO는 애니메이션 업데이트 빈도를 줄이고, 스켈레탈 메시 LOD는 본(Bone) 개수를 줄입니다.
둘을 같은 거리 기준으로 맞춰두면 시너지가 납니다.
멀리 있을수록 LOD도 낮아지고 URO 빈도도 줄어드는 구조가 이상적이라 합니다.
서버에서는 URO를 더 공격적으로 적용하세요
서버는 렌더링을 하지 않으므로 애니메이션의 시각적 품질이 의미가 없습니다.
히트박스 계산 등 게임플레이에 필요한 최소한의 업데이트만 유지하고, 나머지는 과감하게 줄여도 됩니다.
URO는 거리 기반으로 애니메이션 갱신 빈도를 줄이는 기법입니다. Interpolation과 함께 켜야 끊김 없이 자연스럽게 보이고, LOD와 거리 기준을 맞춰두면 시너지가 납니다.
로컬 플레이어(본인)는 IsLocallyControlled()로 판별해서 URO에서 제외합니다. 항상 화면 중앙에 있고 가장 잘 보이기 때문입니다.
나머지 플레이어는 거리와 관계(파티원, 전투 중인 적 등)를 기준으로 빈도를 조정합니다.
0~10m: 매 프레임
10~30m: 2프레임에 1회
30m 이상: 4~6프레임에 1회
파티원이나 현재 전투 중인 적처럼 집중해서 보는 캐릭터는 URO 비율을 낮추거나 끕니다. 거리 구간은 기본값이 항상 최적이 아니므로, FAnimUpdateRateParameters로 맵 크기와 뷰 거리에 맞게 직접 튜닝하는 것이 좋습니다.
서버에서는 렌더링이 없으므로 히트박스와 이동에 필요한 최소한만 남기고 공격적으로 줄입니다. 단, 루트 모션 기반 이동을 사용하는 경우 과도하게 줄이면 위치 오차가 생길 수 있으므로 확인이 필요합니다.
로컬 제어 개념이 없으므로 전투 상태 + 몬스터 종류가 판단 기준입니다.
전투 상태에 따라 동적으로 조정합니다.
순찰/Idle: 4~6프레임에 1회 (적극 적용)
어그로/전투 중: 최소화 또는 비활성
사망/피격 등 격렬한 모션 변화: 비활성 또는 1~2프레임 (보간이 버티지 못함)
AI 상태 머신의 상태 전환 시점에 URO 설정을 함께 바꾸면 구현이 깔끔하다고 하네요.
일반 몬스터의 거리 구간은 플레이어와 유사하되, 비전투 상태에서는 더 공격적으로 줄여도 된다고 합니다.
0~10m: 비전투 2프레임 / 전투 매 프레임
10~25m: 비전투 4프레임 / 전투 2프레임
25m 이상: 비전투 6프레임 / 전투 4프레임
보스는 항상 크게 보이고 페이즈 전환, 특수 공격 등 복잡한 모션이 많으며 공격 타이밍이 게임 플레이에 직결되므로 URO를 완전히 제외합니다. 성능이 걱정딘다면 보스 전용 LOD를 충분히 세팅하는 방향으로 접근하는 것이 낫다고 합니다.
서버에서는 플레이어보다 더 공격적으로 줄일 수 있다고 합니다. 비전투 몬스터는 거의 비활성화 수준도 가능하고, 전투 중인 몬스터도 히트박스 관련 본 업데이트만 최소로 유지하면 됩니다. 루트 모션 사용 시 플레이어와 동일한 주의사항이 적용됩니다.
| 항목 | 플레이어 | 몬스터 |
|---|---|---|
| 본인 제외 로직 | IsLocallyControlled() | 해당 없음 |
| 중요도 기준 | 파티원 / 교전 중 여부 | 전투 상태 + 종류 |
| URO 강도 | 중간 | 비전투 시 더 공격적 가능 |
| 보스급 예외 | 없음 | URO 완전 제외 권장 |
| 사망/피격 모션 | 보간이 대체로 커버 | 격렬한 변화 → 보간 품질 저하 주의 |
| 서버 적용 | 공격적으로 줄임 | 더 줄일 수 있음 |
| 루트 모션 주의 | 동일 | 동일 |
Interpolation 없이 URO만 켜는 것, 보스에 URO 적용, 전투 상태 전환 시 URO 갱신 누락, 서버에서 루트 모션 캐릭터에 과도하게 적용하는 것이 자주 발생합니다. 개발 중에는 Display Debug Update Rate Optimizations를 켜서 실제 빈도를 눈으로 확인하면서 구간을 조정하는 것이 가장 빠른 튜닝 방법이라고 합니다.