01signal.com

FPGA 설계자를 위한 이론적 역량

이 페이지는 전문 FPGA 설계자가 되는 방법을 다루는 다섯 편짜리 연재의 두 번째 글입니다. 이번 글에서는 모든 FPGA 설계자가 익혀야 한다고 생각하는 여러 이론 주제를 짚어 보고, 각 주제가 왜 중요한지도 설명해 보겠습니다.

로직 이론

이론을 아는 것은 사치가 아닙니다. 협조를 거부하는 개발 도구와 씨름할 때나, 전자 부품들이 제멋대로 굴 것처럼 보일 때는 그렇게 느껴지지 않겠지만, 이론은 다른 모든 것이 세워지는 토대입니다.

FPGA 엔지니어는 자신이 작성한 Verilog가 어떻게 로직 소자로 구현되는지 머릿속에 그릴 수 있어야 합니다. 모든 세부 사항까지는 아니더라도, 어느 부분이 설계 속도를 늦추고 클록 주파수를 제한할지, 어느 부분이 로직 자원을 많이 잡아먹을지를 판단할 수 있을 정도는 되어야 합니다. 예를 들어 어떤 작업에 레지스터를 추가해 파이프라인 (pipeline)을 적용해야 하는지 판단하는 데 이것이 결정적입니다. 파이프라이닝은 보통 설계를 복잡하게 만들지만, 요구되는 속도에 도달하는 유일한 방법인 경우가 많습니다. 다른 중요한 설계 결정들도 이 능력에 기대고 있습니다.

또한 합성기 (synthesizer)가 무엇을 했고 왜 그렇게 했는지 따라가는 데에도 결정적입니다. 예를 들어 합성기가 무엇을 최적화로 걷어내는 경향이 있는지 알면, 읽기 쉽고 효율적인 Verilog 코드를 작성할 수 있습니다. 합성기가 여러분의 코드를 어떻게 처리할지 모른다면, 눈 감고 코드를 쓰는 셈입니다.

그러면 어떤 주제들이 관련이 있을까요? 다음 체크리스트로 시작해 보시길 권합니다. 이것이 전부라고 말하려는 것은 아닙니다.

로직 패러다임과 기법

순수한 로직 이론을 아는 것 외에도, 안정적이고 효율적으로 동작하며 시뮬레이션에서와 하드웨어에서 똑같이 동작하는 코드를 작성하기 위해 필요한 몇 가지 주제가 있습니다. 소프트웨어 세계에서는 거의 당연한 일이지만, FPGA 설계자는 다른 영역에 살고 있습니다. 모든 FPGA 설계자는 이런 주제들을 항상 염두에 두어야 합니다.

핵심 아이디어는 RTL 패러다임, 즉 Register Transfer Level입니다. 간단히 말해, 값을 저장하는 모든 것은 클록 에지에 반응해서만 그 값을 바꾼다는 뜻입니다. 비동기 리셋 (asynchronous reset)이 유일하게 신중히 통제된 예외가 될 수 있습니다. 이 사고방식이 몸에 익으면, 제대로 해 낼 가능성이 큽니다.

리셋은 그 자체로 하나의 주제입니다. 동기 리셋 (synchronous reset)과 비동기 리셋 (asynchronous reset), 그리고 리셋 동기화는 어떤 설계를 하든 정리해 두어야 하는 문제입니다. 그렇게 하지 않으면 설계는 대부분 잘 동작하다가, 이따금 산발적으로 말썽을 부립니다. 납품할 만한 동작하는 시스템은 갖게 되겠지만, 이런 산발적 실패 때문에 출시를 못 하게 됩니다. 프로젝트는 점점 늦어지는데, 무엇이 잘못됐는지 전혀 알 수 없습니다. 이런 상황에서 리셋 처리가 문제라고 떠올리는 사람은 없습니다. 이 주제는 정말 깊이 이해해 두어야 합니다. 이 사이트에 이 주제를 다룬 짧은 연재가 있습니다.

이와 밀접하게 관련된 것이 클록 인에이블 (clock enable)과 게이티드 클록 (gated clock) 중 무엇을 쓸지의 문제입니다. 본질적으로 이 둘은 로직 설계가 매 클록 사이클마다 돌지 않게 만드는 두 가지 기법입니다. FPGA에는 클록 게이팅을 위한 전용 자원이 있지만, 잘못 쓰면 신비로운 문제를 만들어 내는 좋은 방법이 됩니다. 안전한 습관은 로직에 클록 인에이블을 쓰는 것이지만, 낮아진 실효 클록 레이트를 활용해 타이밍 제약 조건 (timing constraints)을 완화하고 싶다면 곤란을 겪을 수도 있습니다.

상태 머신 인코딩도 언급할 가치가 있습니다. 바이너리, 원핫 (one-hot), 그레이 (Gray) 인코딩은 각자 쓰임새가 있고, 선택에 따라 속도와 자원 사용량이 모두 영향을 받습니다. 도구가 알아서 골라 주는 경우가 많지만, 각 선택지가 무엇을 뜻하는지는 알아야 합니다. 특히 원핫 코딩은 큰 상태 머신에 아주 좋습니다. 하지만 상태 머신이 제대로 리셋되지 않으면, 이 코딩 방식 때문에 Verilog 코드상으로는 불가능한 동작을 하게 만들 수 있습니다. FPGA 내부에서 마법이 일어나는 것처럼, 혹은 합성기의 버그처럼 보이지만, 아닙니다. 원핫 코딩과 어설프게 적용된 리셋 때문입니다.

그리고 마지막으로 파이프라이닝입니다. 이것은 단순한 기법이 아니라 사고방식입니다. 레지스터를 추가하는 것은 사소하지만, 데이터 처리가 여러 클록 사이클에 걸친다는 사실은 셀 수 없이 많은 문제를 만들어 냅니다. 예를 들어, 유효한 데이터의 첫 조각이 도착하기 전에 이 데이터를 받는 쪽은 무엇을 해야 할까요? 입력 데이터가 연속해서 들어오지 않아 파이프라인을 잠시 멈춰야 한다면 어떻게 할까요? 처리 체인의 모든 로직 소자에 걸쳐 있는, 팬아웃 (fan-out)이 큰 클록 인에이블 (clock enable) 하나 없이 어떻게 그걸 할까요?

모든 시나리오마다 다른 종류의 파이프라인 설계가 필요하고, 각각 나름의 어려움과 특성이 있습니다.

디지털 설계

위에서 언급했듯이, FPGA 설계자는 Verilog가 어떻게 FPGA 안의 로직 소자가 되는지 그려 볼 수 있어야 합니다. 구체적인 예를 들어 보겠습니다.

Verilog에서 평범하게 "assign x = a + b;"라고 썼다고 합시다. 이 덧셈기는 어떻게 구현될까요? 이 FPGA는 덧셈기를 구현하는 특별한 요령을 쓸까요? 예를 들어 전용 하드 블록인 DSP 블록을 쓸까요? 만약 그렇다면, 덧셈기의 결과가 와이어가 아니라 레지스터일 때는 도움이 얼마나 될까요? "assign x = a + b + c;"처럼 세 수를 더하면 어떻게 될까요? FPGA에 세 수를 더하는 지름길이 있을까요? 답은 대개 없음입니다. 그러면 이것은 대략 (a + b) + c처럼 구현됩니다. 두 개의 로직 연산이 직렬로 이어지면 설계가 상당히 느려질 수 있습니다. 그런데 여러분이 쓰는 특정 FPGA에서는 어떻게 동작할까요?

타깃으로 삼는 특정 FPGA에 어떤 자원이 있는지 아는 것은 중요합니다. 그것이 Verilog를 쓰는 방식을 결정하며, 그래야 합성기가 빠르고 효율적인 로직을 만들 수 있습니다. 합성기는 던져 주는 어떤 문제든 풀어 주는 마법사가 아닙니다. Verilog를 현명하게 쓰고 그 한계를 안다면, 자원을 적게 쓰고 전력도 비교적 적게 먹으며 높은 클록 주파수에서 동작하는 설계를 얻게 됩니다. 이것은 경험에서 나오는 것이고, 디지털 설계 지식이 이런 지혜를 얻는 과정을 앞당겨 줍니다.

실제로는 보통 타이밍 클로저 (timing closure) 문제를 풀 때만 FPGA 내부의 로직 구현을 들여다보게 됩니다. 결과가 왜 느렸는지, 혹은 자원을 왜 그렇게 많이 썼는지 이해할 필요가 생기기 때문입니다. 그래서 시간이나 자원의 낭비를 찾아 로직 구현의 자잘한 세부 사항을 하나하나 훑게 됩니다. 하지만 그냥 지식을 더 쌓기 위해, 혹은 엉뚱한 일이 벌어지지 않았는지 확인하기 위해, 때때로 자발적으로 결과를 분석해 보는 것도 좋은 생각입니다. 장기적으로 이득이 됩니다.

자신의 FPGA를 알기

Verilog가 어떻게 로직 소자가 되는지 그려 보는 것의 또 다른 측면은 기본 로직 자원과 관련이 있습니다. 즉, FPGA의 구성 요소를 알고, 그것들이 무엇에 좋은지 아는 것입니다.

먼저 FPGA 자체의 구조입니다. 기본 소자, CLB, 그리고 여러분의 FPGA의 슬라이스 (slice) 말이죠. Verilog 코드를 작성할 때, 이 소자들이 필요한 로직을 구현하는 데 어떻게 쓰일지 그려 볼 수 있다면 큰 장점입니다. 이렇게 하면 지금 쓰는 코드가 설계의 타이밍 클로저 (timing closure)에서 병목이 될지, 아니면 이 코드 조각이 다시는 신경 쓰이지 않을지를 판단할 수 있습니다.

대부분의 FPGA는 구조가 대동소이합니다. 모든 FPGA에는 산술 덧셈기, 멀티플렉서, 디멀티플렉서 등을 효율적으로 구현하는 방법이 있습니다. 이런 기능이 많이 쓰이기 때문입니다. 예를 들어 많은 FPGA에는 곱셈기가 하드 블록으로 있어서, "assign x = a * b;" 같은 연산이 빠른 클록 주파수에서 돌아갑니다.

하지만 이 곱셈기의 정확한 특성은 다를 수 있습니다. 어떤 FPGA에서는 이 곱셈기 블록의 피연산자가 18 비트 부호 있는 정수입니다. 그러면 이 폭 이하의 피연산자로 하는 곱셈은, 피연산자 하나가 19 비트 폭이 될 때보다 훨씬 높은 클록 주파수에서 동작합니다. 이것도 FPGA의 로직 블록을 알아야 하는 또 하나의 예입니다. 1 비트가 더 늘어나는 것만으로 클록 주파수가 상당히 떨어질 수 있습니다. 다른 FPGA 패밀리라면 피연산자 폭도 완전히 다른 게임이 될 수 있다는 점에 유의하세요.

라우팅 자원도 중요합니다. 로직 소자는 절반의 이야기일 뿐이고, 그것들을 잇는 배선이 나머지 절반입니다. 꽤 자주, 배선이 혼잡해져서 느려지기 때문에 설계가 원하는 클록 주파수에 도달하지 못합니다. FPGA를 로직 용량의 거의 100%까지 쓰면서 설계에 폭이 넓은 데이터 버스가 많다면 이 점을 생각해 봐야 합니다. FPGA 안의 어떤 라우팅 자원('와이어')은 빠르고, 어떤 것은 더 느립니다. 빠른 것이 다 소진되면 전체 설계가 느려집니다.

FIFO와 BRAM도 이해해야 합니다. 이것들은 FPGA 내부의 메모리 자원이고, 데이터를 저장하고 버퍼링하는 데도, 클록 도메인 (clock domain) 사이를 넘는 데도 끊임없이 쓰게 됩니다. FIFO를 다루는 방법을 아는 것은 기본 중의 기본입니다. 이 사이트에 이 주제를 다룬 연재가 있습니다.

클로킹 자원은 그들만의 작은 세계입니다. PLL, 클록 버퍼, 그리고 글로벌 및 리저널 클록 네트워크 말이죠. PLL은 들어오는 클록을 여러분의 로직이 실제로 필요로 하는 클록으로 바꿔 주는 소자입니다. 주파수를 체배하고 분주하며, 위상 이동도 가능하게 합니다. 어떤 클록이 위상 정렬되어 있고 어떤 것은 아닌지 아는 것도 중요합니다. 예를 들어 PLL이 두 개의 클록을 내보내는데 하나가 다른 하나의 두 배 주파수라고 합시다. 첫 번째 클록으로 동작하는 레지스터가 두 번째 클록으로 동작하는 레지스터의 출력을 샘플링하는 것이 안전할까요? 대개는 안전하지만, 이 두 클록이 위상 정렬되어 있는지에 달려 있습니다. 그런데 정말 그런지 확인하는 방법을 알아야 합니다. 이 사이트에 이 주제를 다룬 페이지가 있습니다.

다음은 I/O 블록 자원입니다. DDR이나 SERDES처럼 고속 I/O 신호를 다루는 설계에서는, I/O 블록이 여러분에게 무엇을 해 줄 수 있는지, 그리고 어떻게 설계의 클록 주파수보다 훨씬 높은 데이터 레이트로 I/O를 가능하게 하는지 이해해야 합니다. 또한 종단 저항을 추가하는 방식으로 임피던스 정합을 돕도록 구성할 수도 있고, 다른 저수준 전자 기능도 수행합니다.

그리고 초당 1 기가비트를 넘는 데이터 레이트가 필요하다면, MGT(Multi-Gigabit Transceiver)가 답입니다. 비교적 고급이고 복잡한 주제라서, 특정 프로젝트에 필요하지 않다면 초보자용은 아닙니다. 이 사이트에도 그 주제를 다룬 연재가 있습니다.

그리고 마지막으로 다소 지루한 주제 하나. 구성 메모리와 비트스트림 (bitstream) 로딩입니다. 설계를 다 하고 나면, 매번 컴퓨터에서 FPGA로 비트스트림을 넣고 싶지는 않을 것입니다. 그래서 FPGA가 플래시 메모리에서 스스로 읽어 들일 수 있습니다. 아니면 SD 카드에서 읽어 들이거나요. 혹은 보드 위의 별도 부품이 비트스트림을 FPGA로 밀어 넣을 수도 있는데, 보드에 별도 프로세서가 있을 때 자주 선택하는 방식입니다.

FPGA를 로딩하는 기법 자체에는 재미있는 게 없습니다. 하지만 작은 팀에서 일한다면 이것도 여러분 몫입니다. 그리고 보드에 전원이 들어온 뒤 FPGA가 얼마나 빨리 동작을 시작해야 하는지에 대한 요구 사항이 있는 경우도 많습니다. 그것도 여러분이 알아내야 합니다.

이 주제를 알아 두어야 하는 또 다른 이유는, 특히 평가 보드에서 FPGA가 전원이 들어오면 플래시 메모리에서 자동으로 로딩되는 경우가 많기 때문입니다. 더 까다롭게도, FPGA 보드에는 비트스트림을 읽어 올 수 있는 메모리 소스가 여러 개 있는 경우가 많습니다. 예전 버전의 프로젝트가 FPGA에 로딩된 걸 모르고 디버깅을 아주 길게 하는 일이 벌어집니다. 설계에서 무엇을 바꾸든 FPGA가 똑같이 동작하는데, 매번 엉뚱한 플래시 메모리를 갱신하고 있기 때문입니다.

타이밍

먼저 타이밍이 무엇인지(로직 설계 맥락에서) 짧게 설명하겠습니다. 길게 말할 것 없이, FPGA 안팎의 모든 디지털 신호는 특정 시간 구간 동안 전기적으로 안정되어 있어야 합니다. 보통 클록 에지와의 관계에서 말이죠. 그렇지 않으면 로직의 동작이 예측 불가능해집니다. 개발 도구는 필요한 곳마다 이런 타이밍 요구 사항이 충족되도록 보장합니다. 하지만 그러려면 우리가 이 도구들에 특정 정보를 아주 정확하게 제공해야 합니다. 게다가 로직 설계 자체도 도구가 타이밍 요구 사항을 충족할 수 있는 방식으로 만들어야 합니다. 이것이 타이밍에 관한 이야기의 핵심입니다.

타이밍은 아마 FPGA 설계자로서 가장 어려운 부분일 것입니다. 또한 정말로 익혀서 제대로 구현해야 하는 가장 중요한 영역이기도 합니다. 불행히도 이 주제를 등한시해도 설계가 꽤 잘 동작하거나, 적어도 거의 다 끝난 것처럼 보일 정도로만 동작하게 만들기는 꽤 쉽습니다. 모든 것이 잘 동작하는데도, 보름달이 뜨면 갑자기 실패를 일으키는 초자연적인 힘이 FPGA 안에 있는 것처럼 보입니다. 저는 이런 사고방식을 '흑마법 모드'라고 부르는데, 이에 관한 별도 페이지가 있습니다.

운이 좋으면, 타이밍을 염두에 두지 않고 작성한 FPGA 설계도 타이밍 제약 조건 (timing constraints) 몇 개를 추가하는 것만으로 쉽게 고칠 수 있습니다. 때로는 거의 모든 것을 처음부터 다시 해야 하는 경우도 있습니다. 올바른 타이밍 요구 사항이 강제되면, 개발 도구가 요구되는 클록 주파수에서 동작하게 만들지 못하기 때문입니다. 그렇다면 Verilog 코드 자체를 다시 손봐야 합니다.

정말 운이 나쁜 날에는 PCB를 부분적으로 다시 설계해야 합니다. 보드의 모든 물리적 신호가 안정되어 있어야 하는 시간 구간 안에서 안정된 전압을 유지하도록 보장하는 것이 불가능하기 때문입니다. PCB가 양산 승인되기 전에 제대로 된 타이밍 분석을 했다면 그 사실이 드러났겠지만, 그것을 등한시했다면 하드웨어가 그 일을 감당하지 못할 수도 있습니다.

반대로 타이밍을 신중하고 올바르게 처리하면, FPGA는 세상에서 가장 신뢰할 수 있는 부품이 됩니다. 많은 FPGA 설계자가 설계에 사소한 변경 하나 가하는 것도 두려워하고, 새 배치의 FPGA 칩이 양산에 투입될 때마다 걱정합니다. FPGA가 조금이라도 따뜻해지면 큰일 나는 것처럼 엄청난 냉각을 적용하기도 하죠. 저는 이렇게 말합니다. 타이밍을 제대로 처리하세요. 그러면 모든 걱정은 잊어도 됩니다.

첫날부터 이것을 완벽하게 익혀야 할까요? 저는 사실 그렇다고 말하고 싶습니다. 원칙적으로는, FPGA 설계자 팀에서 한 사람만 타이밍을 정말 잘해도 충분하다는 데 동의합니다. 그 한 사람이 되세요. 이유는 간단합니다. 다른 누구도 그렇게 하지 않을 가능성이 크기 때문입니다.

이 웹사이트에는 타이밍에 관한 꽤 긴 연재가 있으므로, 여기서 주제를 자세히 풀어내는 것은 별 의미가 없습니다. 그래서 모든 FPGA 설계자가 익숙해져야 한다고 생각하는 주제를 간단히 나열해 보겠습니다.

전자공학

FPGA는 전자 소자이고, FPGA 설계는 전기공학 안의 한 전문 분야입니다. 회로도와 데이터시트, 전압과 전류, 신호 무결성과 임피던스 정합을 다루는 종류의 전기공학이죠. 모든 PCB 설계자가 갖춰야 하는 지식이고, FPGA 설계자도 이런 지식이 있으면 삶이 훨씬 편해집니다.

FPGA 설계자가 FPGA가 보드의 다른 부품들과 올바르게 인터페이스하도록 보장하는 일을 맡는 경우가 흔합니다. 사실 PCB 설계자가 이런 부품들이 동작하게 만드는 책임에서 벗어나려고, 연결할 수 있는 모든 것을 FPGA에 몰아넣는 일도 드물지 않습니다. 그래서 FPGA 설계자는 PCB 위에서 부품들이 서로 어떻게 인터페이스하는지 깊이 이해해야 하는 경우가 많습니다. 고주파로 스위칭하는 배선에서 다뤄야 할 신호 무결성 문제를 지적해야 하는 사람도 흔히 FPGA 엔지니어입니다.

새 PCB를 설계할 때는 보통 팀의 FPGA 설계자가 그 설계를 승인해야 합니다. 즉, FPGA로의 연결이 올바른지 확인하는 것이죠. FPGA의 모든 핀이 모든 용도에 적합한 것은 아니고, 특정 연결이 FPGA 핀의 특정 그룹('뱅크')에 속해야 하는 경우도 있으며, 그럴 때가 때로는 훨씬 좋기도 합니다. 이런 것들은 FPGA 설계자가 익혀야 하거나, 적어도 확고한 의견을 가지고 있어야 하는 사항입니다.

FPGA 설계자가 이전에 PCB 설계자였던 경우도 드물지 않습니다. 보드 설계에서 FPGA 설계로 가는 길은 자연스러운 것이고, 그 길을 걸어 본 사람은 뚜렷한 이점을 가집니다. PCB 설계자가 책임지고 완벽하게 좋은 보드를 설계하더라도, FPGA 설계자는 FPGA의 I/O 블록을 제대로 구성하기 위해 PCB 위 고속 신호의 어려움을 이해해야 합니다.

앞서 언급했듯이, 모든 FPGA 엔지니어가 전자 부품을 직접 다루는 것은 아닙니다. 어떤 사람들은 제가 '처리 로직'이라고 부른 내부 로직 개발에만 국한되고, 시뮬레이션과 검증만 하도록 엔지니어를 채용하는 회사도 있습니다. 하지만 우리 대부분은 전자 부품을 직접 다루며 일하고, 그러려면 관련 지식이 좀 필요합니다.

절대적인 기초부터 시작합니다. 전압, 전류, 저항, 그리고 옴의 법칙입니다. 디지털 신호가 한 부품에서 다른 부품으로 이렇게 이동합니다. 커패시턴스와 커패시터가 어떻게 충전되고 방전되는지 이해하는 것도 좋은 생각입니다. 그래야 전류와 커패시턴스가 스위칭 속도와 전력 소모에 어떻게 영향을 미치는지 이해할 수 있습니다.

회로도를 읽을 수 있어야 합니다. IC, 모듈, 인덕터, 전원 공급 장치, 디지털 및 아날로그 그라운드 말이죠. MOSFET과 바이폴라 트랜지스터도 가끔 나오는데, 적어도 알아볼 수는 있어야 합니다. MOSFET 트랜지스터가 어떻게 동작하는지 감을 잡아 두면 손해 볼 일은 없습니다.

데이터시트를 읽는 데에도 많은 시간을 쓰게 됩니다. 가장 어려우면서 중요한 부분은 데이터시트의 타이밍 명세를 타이밍 제약 조건 (timing constraints)과 FPGA의 적절한 I/O 설계로 옮기는 일입니다. 보드 스큐 (skew)는 I/O 타이밍에 고려해야 할 수도 있는 요소입니다.

그뿐만 아니라 데이터시트의 전압 및 전류 명세를 이해하고, FPGA의 해당 I/O 블록을 올바른 전압 표준으로 구성하는 일도 여러분 몫입니다. 싱글 엔디드 및 차동 인터페이스, LVCMOS, SSTL, LVDS 등등이 있죠.

모든 FPGA 설계자가 정말 이걸 제대로 할까요? 답은 아니오입니다. 전자적인 실수 때문에 아예 동작하지 말아야 할 설계가 완벽하게 동작하는 것처럼 보이는 경우가 꽤 흔합니다. 한 부품의 출력 핀이 다른 부품의 입력 핀에 절대 최대 정격을 넘는 전압을 공급하는 경우도 드물지 않습니다. 물론 엄청난 실수이고, 데이터시트에 따르면 과전압을 받는 부품은 언제든 타 버릴 수 있습니다. 그런데도 모든 것이 영원히 잘 동작합니다. 그러다 갑자기 고장이 나고, 똑똑한 사람들이 왜 그런 일이 일어났는지 어처구니없는 변명을 늘어놓습니다.

분명히 PCB 설계자의 책임인 주제들도 짧게 나열해 보겠습니다. 하지만 그 사람이 그리 뛰어나지 않을 때는 FPGA 엔지니어가 이것들에 대해서도 좀 아는 것이 도움이 됩니다.

그러면 FPGA 설계자가 이 모든 것 중에서 정말로 알아야 하는 것은 무엇일까요? 처음부터 결정적으로 중요한 것은 무엇일까요? 사실 저도 딱 잘라 말하기 어렵습니다. 주위에 더 좋은 팀이 있을수록 알아야 할 전자공학 지식은 줄어듭니다. 그래도 어떤 FPGA 설계자든 회로도를 읽을 수 있어야 하고, FPGA에 무엇이 연결되어 있는지 이해할 수 있어야 하며, 그것이 왜 그 특정한 방식으로 연결되었는지 어느 정도는 이해해야 한다고 말하고 싶습니다.

이것으로 이 연재의 두 번째 페이지를 마칩니다. 다음 페이지에서는 위와 같은 취지로 실전 역량을 다룹니다.1

이 페이지는 영어 원문을 기계 번역한 것입니다. 의문이 드는 부분이 있으면 원문을 참조하시기 바랍니다.
Copyright © 2021-2026. All rights reserved. (852e87d4)