YANSEN 2TB 2.5" SATA SSD Benchmark

YANSEN 2TB 2.5” SATA SSD (YSS25P2YT02TCNNNN) Benchmark on Arch Linux

I recently got my hands on the YANSEN 2TB 2.5” SATA SSD (model YSS25P2YT02TCNNNN). This drive is based on their YSISXXX-P330 series, and I decided to put it through its paces on my Arch Linux setup to see how it performs against its official specs.

Here’s a detailed breakdown of my findings.

1. Manufacturer Specifications

First, let’s look at the specs provided on the official datasheet.

Specification Details
Model YANSEN YSISXXX-P330 (2TB)
Interface SATA III (6Gb/s), backward compatible with SATA II
Form Factor 2.5-inch
NAND Flash 3D TLC
Sequential Read 510 - 560 MB/s
Sequential Write 500 - 550 MB/s
4K Random Read 47K IOPS
4K Random Write 90K IOPS
TBW 2000 TB
Features TRIM, S.M.A.R.T., NCQ, Wear-Leveling
Warranty 5 years

The specs look solid on paper, especially the high endurance rating (TBW) and top-tier sequential speeds for a SATA drive.

2. Testbed Configuration

All benchmarks were run on the following system to ensure transparency.

  • OS: Arch Linux
  • Kernel: 6.17.5-arch1-1
  • CPU: Intel(R) N150 (Low-power processor)
  • RAM: 32GB DDR4 (Single Channel)
  • Tools: hdparm, fio
  • Filesystem: EXT4

3. Benchmark Results & Analysis

Here’s a summary of the advertised specs versus my measured results.

Metric Advertised Spec Measured Result Comment
Sequential Read 510 - 560 MB/s 563 MB/s Exceeds Spec
Sequential Write 500 - 550 MB/s 530 MB/s Meets Spec
4K Random Read 47,000 IOPS 40,300 IOPS Below Spec (Likely testbed bottleneck)
4K Random Write 90,000 IOPS 79,600 IOPS Below Spec (Likely testbed bottleneck)

Sequential Performance

Sequential speeds are crucial for handling large files, like video editing, game installations, or transferring disk images.

  • Sequential Read: The drive achieved an impressive 563 MB/s, exceeding the manufacturer’s maximum advertised speed.
  • Sequential Write: It delivered a solid 530 MB/s, sitting comfortably within the official spec range of 500-550 MB/s.

These results are excellent. For large file operations, this drive pushes the SATA III interface to its absolute limit.

Random 4K Performance (IOPS)

Random 4K performance is a key indicator of real-world responsiveness, affecting OS boot times, application loading, and web browsing.

  • 4K Random Read: I measured 40.3k IOPS.
  • 4K Random Write: The result was 79.6k IOPS.

These figures, while decent, are noticeably lower than the advertised specs. I strongly suspect this performance gap is due to my testbed’s configuration. The Intel N150 is a low-power processor, and the system is running single-channel DDR4 memory. High-intensity benchmarks like 4K random I/O are sensitive not just to the drive itself, but also to the CPU’s ability to handle the high interrupt load and the available memory bandwidth.

It’s highly probable that on a more powerful desktop system (e.g., a Core i5 or higher with dual-channel memory), these IOPS figures would be much closer to the official specifications.

4. Final Verdict

The YANSEN 2TB 2.5” SSD (YSS25P2YT02TCNNNN) proved to be a very capable drive.

The Good:

  • Excellent sequential read and write performance that meets and even exceeds official claims.
  • A high endurance rating of 2000 TBW and a 5-year warranty inspire confidence in its longevity.

The Caveat:

  • Random 4K performance was likely bottlenecked by our low-power test system. Its full potential was not realized in this specific setup.

Overall, this SSD is a solid choice for anyone needing a high-capacity SATA drive for mass storage, a game library, or even as a primary OS drive. While its full random I/O potential was held back by my hardware, its sequential performance is top-tier for the interface. On a more powerful rig, it should perform even better.


Appendix: Full Benchmark Logs

For full transparency, here are the raw commands and outputs from my tests.

hdparm

$ sudo hdparm -T /dev/sda

/dev/sda:
 Timing cached reads:   18786 MB in  2.00 seconds = 9412.80 MB/sec

$ sudo hdparm -t /dev/sda

/dev/sda:
 Timing buffered disk reads: 1440 MB in  3.00 seconds = 479.93 MB/sec

fio - Sequential Read

$ sudo fio --name=seq-read --ioengine=libaio --rw=read --bs=1M --size=2G --direct=1 --iodepth=32 --numjobs=1 --directory=/mnt/test_ssd --group_reporting --runtime=60
...
  read: IOPS=536, BW=537MiB/s (563MB/s)(2048MiB/3815msec)
...
Run status group 0 (all jobs):
   READ: bw=537MiB/s (563MB/s), 537MiB/s-537MiB/s (563MB/s-563MB/s), io=2048MiB (2147MB), run=3815-3815msec

fio - Sequential Write

$ sudo fio --name=seq-write --ioengine=libaio --rw=write --bs=1M --size=2G --direct=1 --iodepth=32 --numjobs=1 --directory=/mnt/test_ssd --group_reporting --runtime=60
...
  write: IOPS=505, BW=505MiB/s (530MB/s)(2048MiB/4054msec); 0 zone resets
...
Run status group 0 (all jobs):
  WRITE: bw=505MiB/s (530MB/s), 505MiB/s-505MiB/s (530MB/s-530MB/s), io=2048MiB (2147MB), run=4054-4054msec

fio - 4K Random Read

$ sudo fio --name=rand-read --ioengine=libaio --rw=randread --bs=4k --size=2G --direct=1 --iodepth=64 --numjobs=4 --directory=/mnt/test_ssd --group_reporting --runtime=60
...
  read: IOPS=40.3k, BW=157MiB/s (165MB/s)(8192MiB/52030msec)
...
Run status group 0 (all jobs):
   READ: bw=157MiB/s (165MB/s), 157MiB/s-157MiB/s (165MB/s-165MB/s), io=8192MiB (8590MB), run=52030-52030msec

fio - 4K Random Write

$ sudo fio --name=rand-write --ioengine=libaio --rw=randwrite --bs=4k --size=2G --direct=1 --iodepth=64 --numjobs=4 --directory=/mnt/test_ssd --group_reporting --runtime=60
...
  write: IOPS=79.6k, BW=311MiB/s (326MB/s)(8192MiB/26338msec); 0 zone resets
...
Run status group 0 (all jobs):
  WRITE: bw=311MiB/s (326MB/s), 311MiB/s-311MiB/s (326MB/s-326MB/s), io=8192MiB (8590MB), run=26338-26338msec

Memory-safe in C

근래 갑작스럽게, 백악관, ‘C’와 ‘C++’ 사용 중단 촉구라는 글이 노출이 되어, 기술에 대해 이렇게 직관적이고 공격적인 단어를 사용해서 방향을 제시했을까라는 의문이 들어 원문을 찾아보았습니다. 역시나 원문은 NSA의 권고가 있다는 내용이고, 취지는 메모리 관리에 유리한 프로그래밍 언어들의 리스트를 취합하는 과정에서 “White House urges developers to avoid C and C++, use ‘memory-safe’ programming languages” 라고 정중하게 말한 것 뿐이었습니다. 프로그램을 작성할 때 메모리 관리에 대해 강조하고자 했다는 의도에는 동감하나, 굳이 이렇게 노골적인 단어로 번역했어야 하나하는 의문은 남습니다.

메모리 관리

어떠한 프로그램을 작성하든 결국 프로그래머가하는 일은 가용한 자원을 가져오고, 사용하고, 반납하는 작업을 반복해서 하는 것입니다. 언젠가부터 최근까지 {Front, Backend} 개발자라는 용어가 통용되고 있는 듯하고, 각 역할에 따라 각기 다른 철학을 가진 프로그래밍 언어를 사용하는 것으로 세분화 되어 있는 듯하여, 여기서 언급하는 “자원”에 대해서 쉽게 동의하지 않을 수도 있습니다. 하지만, 간단한 문자열 하나만 변수에 할당하더라도 우리는 “메모리”라는 자원을 할당하고 사용하는 것입니다. 프로그래밍 언어에 따라서는 반납에 대해 가비지 컬렉터(Garbage Collector)에 그 수행을 위임하여 편리함을 제공하고 있기는 하나, 모든 절차는 이 흐름에서 벗어나지 않게 됩니다.

여러가지 자원 중에서 메모리는 프로그램의 성능과 안전에 관련된 가장 중요한 자원이기 때문에, 별도로 메모리 관리라는 주제로 각 프로그래밍 언어별 많은 서적을 찾아 볼 수 있습니다. 당연한 말이지만, 굳이 구분하자면 메모리를 가져오고(할당), 반납하는 과정은 안정성과 관련이 있으며 성능은 메모리의 사용과 관련이 있다고 할 수 있습니다.

이를 설명하기 위해 임의의 문자열을 생성하는 generate_random_string() 함수와 주어진 문자열에서 숫자와 알파벳이 몇개씩 있는지 찾아보는 count_alnum() 함수를 만들어 보았습니다.

Function generate_random_string(length):
    Define characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
    Define random_string = ''

    For i from 1 to length:
        Generate a random index from 0 to the length of characters - 1
        Append the character at the random index in characters to random_string

    Return random_string

Function count_alnum(input_string):
    Define count_digits = 0
    Define count_letters = 0

    For each character in input_string:
        If character is a digit:
            Increment count_digits by 1
        Else if character is an alphabet letter:
            Increment count_letters by 1

    Return count_digits, count_letters

이 두 함수를 사용하는 방법은 아마도 다음과 같이 진행 될 것입니다.

# Step 1: Generate a random string
length_of_random_string = 10  # Arbitrary length
random_string = generate_random_string(length_of_random_string)
print("Generated random string:", random_string)

# Step 2: Count numbers and alphabets in the generated string
digits_count, alphabets_count = count_alnum(random_string)
print("Digits count:", digits_count)
print("Alphabets count:", alphabets_count)

문자열은 generate_random_string() 함수내에서 생성되고, random_string으로 전달 됩니다. 이 random_string은 다시 count_alnum() 함수에 전달되어 {digits,alphabets}_count로 결과값을 반환 하도록 되어있습니다. 명시적으로 나타나지는 않았지만, random_string의 역할은 count_alnum()이 연산한 뒤에는 더이상 필요가 없기에 반환되어야하는 것이 마땅하나, 이 pseudo code가 가비지 컬렉터를 가지고 있어서 반환되었을 것이라고 생각하는 것이 편리할 듯합니다.

다만 여기서 말하고 싶은 것은, 위 문장에서 전달이라고 표현한 부분입니다. 생성한 random_string을 전달할 때, 새로운 메모리 영역으로 복사를 할 것인지, 아니면 random_string이 저장된 장소(포인터)를 알려줄지에 따라 사용하는 메모리의 양뿐만 아니라, 메모리 관리 (할당, 반환) 절차의 필요 여부가 결정되기 때문에 이는 성능과 연결이 될 수 밖에 없습니다.

문제는 C/C++로 작성하는 코드들은 대게 성능을 중요시하다보니, 메모리를 복사하기 보다는, 포인터를 전달하는 구조로 작성하게 됩니다. 전달 횟수가 거듭될수록, 그리고 한번에 처리해아는 할당된 메모리의 수가 많을수록, 관리하기는 어려워지며 이로 인하여 할당과 반환이 적절하기 이루어지지 않아 결국 Memory-Safe 문제를 불러오게 된다고 볼 수 있습니다.

이제 우리가 집중해야할 문제는 무엇인지 간단해졌습니다. 할당된 메모리의 사용 방법은 프로그램마다, 알고리즘마다, 심지어 프로그래머의 개인 선호도에 따라 달라질 수 있습니다. 하지만 명확한 것은 할당한 것은 반드시 반환해야한다는 것이고, 다행이도 이를 위한 해결책은 GLib의 Automatic Cleanup 매크로가 제시를 하고 있습니다. C에서는 말이죠.

예외 처리를 포함한 메모리 할당 및 반환

C에서는 기본적으로 malloc()free()를 통해 메모리를 관리합니다. 그러나 이러한 primitive function은 내부적으로는 유저 영역에서 커널 영역으로 호출을 하는 것이고, 커널이 직접 응답하는 구조로 커널의 사정에 따라 반드시 성공한다는 보장이 없습니다. 실패한 경우에는 커널에서 알려준 에러코드를 확인해야하는 절차가 필요하며, 예외 상황에 대해 적절하게 대응하는 코드는 다음과 같습니다.

#include <stdio.h>
#include <stdlib.h>

void* safe_malloc(size_t size) {
    void *ptr = malloc(size);
    if (ptr == NULL) {
        // Handle the memory allocation failure
        fprintf(stderr, "Error: Memory allocation failed for %zu bytes.\n", size);
        exit(EXIT_FAILURE); // Exit the program or handle the error as per your requirement
    }
    return ptr;
}

void safe_free(void **ptr) {
    if (ptr != NULL && *ptr != NULL) {
        free(*ptr);
        *ptr = NULL; // Prevents double-free errors
    }
}

int main() {
    int *numbers = safe_malloc(10 * sizeof(*numbers)); // Allocate memory for 10 integers
    
    // Use the memory...
    for(int i = 0; i < 10; i++) {
        numbers[i] = i;
    }
    
    // When done, free the memory safely
    safe_free((void**)&numbers);
    
    // After safe_free, numbers is NULL and cannot be accidentally freed again
    if(numbers == NULL) {
        printf("Memory successfully freed and pointer is NULL.\n");
    }

    return 0;
}

기본적으로 메모리 할당에 실패한 것과 NULL에 대해 접근하는 경우를 방지한 것이기 때문에 위의 코드는 malloc()free()를 직접사용하는 것보다는 안전하다고 할수는 있습니다. 하지만 한가지 메모리 사용에 대해서는 그 효율을 장담할 수 없습니다. 반복적인 메모리 할당과 반환은 메모리를 조각으로 만들게 되고(fragmentation), 이는 결국 충분히 사용가능한 메모리가 있음에도 요청한 크기만큼의 연속된 공간이 존재하지 않아, 실제 할당에는 실패하는 상황이 발생하게 됩니다. 메모리 할당이 실패한 경우에는 위 코드에 기술한 내용에 따르면 프로그램을 바로 종료하게 되어있고 이는 메모리 관리에 실패한 것이나 다름없는 결과가 나오게 됩니다.

메모리 할당 및 반환 with GLIB

GNOME 프로젝트에서는 여러가지 경우를 상정하여 고안한 GLib를 제공하고 있습니다. 이는 기존 C에서 제공하는 시스템 호출에 대한 안성성과 효율성을 확보하기 위한 기능과 여러 유용한 자료구조를 제공하고 있으며, 거의 모든 운영체제에 호환이 되도록 작성되어있습니다. 메모리 할당과 반환의 관점에서만 본다면, 다음과 같은 예제로부터 시작할 수 있습니다.

#include <glib.h>
#include <stdio.h>

int main() {
    // Allocate memory for 10 integers using GLib's g_new
    // Syntax: g_new(Type, Number_of_Elements)
    gint *numbers = g_new(gint, 10);

    // Use the allocated memory
    for (int i = 0; i < 10; i++) {
        numbers[i] = i * 10; // Example operation
        printf("numbers[%d] = %d\n", i, numbers[i]);
    }

    // Free the allocated memory using GLib's g_free
    g_free(numbers);

    // After g_free, it's a good practice to set the pointer to NULL to avoid accidental use
    numbers = NULL;

    return 0;
}

여전히 메모리의 할당과 반환은 프로그래머의 몫입니다만, 다음 예제는 좀더 진보된 형태의 자료구조와 매크로를 통해 마치 가비지 콜렉터가 있는 듯한 형태로 사용하는 것을 볼 수 있습니다.

#include <glib.h>
#include <stdio.h>

// Automatic cleanup for GArray
G_DEFINE_AUTO_CLEANUP_FREE_FUNC(GArray, g_array_unref, NULL)

int main() {
    // Allocate a GArray with automatic cleanup
    g_autoptr(GArray) numbers = g_array_new(FALSE, FALSE, sizeof(gint));
    
    // Use the allocated array
    for (int i = 0; i < 10; i++) {
        gint num = i * 10; // Example operation
        g_array_append_val(numbers, num);
        printf("numbers[%d] = %d\n", i, g_array_index(numbers, gint, i));
    }

    // No need to manually free the array; it will be automatically freed
    // when it goes out of scope (i.e., at the end of the main function)
    
    return 0;
}

G_DEFINE_AUTO_CLEANUP_FREE_FUNC 매크로는 메모리 할당에 사용할 자료구조에 대해 반환할 때 사용하는 함수를 정의합니다. 그러면 해당 자원에 대해 참조점이 없을때 자동으로 여기서 선언한 반환용 함수가 호출 되게 됩니다. 메모리 할당시에 C에서는 포인터를 사용하나, 포인터에 대한 참조점 추적을 위해 g_autoptr 매크로를 통해서 포인터를 선언합니다. 그러면 이제 더이상 할당된 메모리에 대한 반환 시점을 고민하지 않아도 됩니다.

실제 프로젝트에서 사용 예

GLib의 자동화된 메모리 관리 매크로들은 가비지 컬렉터가 있는 언어인 양 어느정도 메모리 할당과 반환의 고민에서 해방되게끔 도와줍니다. 다만 이렇게 할당 메모리를 전달할때에 주의해야하는데, g_autoptr을 선언한 포인터는 블럭을 벗어나는 시점에서 반환 함수가 호출되기 때문에 블럭이 종료되는 시점에서 해당 포인터의 소유권을 g_steal_pointer를 통해 넘겨주는(말그대로 훔치는) 작업이 필요합니다.

다음은 이러한 매크로들을 공격적으로 사용했던 황새울 프로젝트의 코드의 일부 입니다.

///
/// https://github.com/hwangsaeul/gaeguli/blob/110822e039888b2fcc8a400e6fd20a88dd956fa2/gaeguli/pipeline.c#L498
///
GaeguliPipeline *
gaeguli_pipeline_new (GVariant * attributes)
{
  g_autoptr (GaeguliPipeline) pipeline = NULL;
  GaeguliVideoSource source;
  const gchar *device = NULL;
  GaeguliVideoResolution resolution;
  guint framerate = 0;
  GVariantDict attr;

  g_return_val_if_fail (g_variant_is_of_type (attributes,
          G_VARIANT_TYPE_VARDICT), NULL);

  g_variant_dict_init (&attr, attributes);
  g_variant_dict_lookup (&attr, "source", "i", &source);
  g_variant_dict_lookup (&attr, "device", "s", &device);
  g_variant_dict_lookup (&attr, "resolution", "i", &resolution);
  g_variant_dict_lookup (&attr, "framerate", "u", &framerate);

  g_debug ("source: [%d / %s]", source, device);
  pipeline = g_object_new (GAEGULI_TYPE_PIPELINE, "source", source, "device",
      device, "resolution", resolution, "framerate", framerate, "attributes",
      g_variant_dict_end (&attr), NULL);

  return g_steal_pointer (&pipeline);
}

...

///
/// https://github.com/hwangsaeul/gaeguli/blob/110822e039888b2fcc8a400e6fd20a88dd956fa2/tests/test-pipeline.c#L74C1-L103C2
/// 
static void
test_gaeguli_pipeline_instance (TestFixture * fixture, gconstpointer unused)
{
  GaeguliTarget *target;
  g_autoptr (GaeguliPipeline) pipeline =
      gaeguli_pipeline_new_full (GAEGULI_VIDEO_SOURCE_VIDEOTESTSRC, NULL,
      GAEGULI_VIDEO_RESOLUTION_640X480, 30);
  g_autoptr (GError) error = NULL;

  g_signal_connect (pipeline, "stream-started", G_CALLBACK (_stream_started_cb),
      fixture);
  g_signal_connect (pipeline, "stream-stopped", G_CALLBACK (_stream_stopped_cb),
      fixture);

  target = gaeguli_pipeline_add_srt_target_full (pipeline,
      GAEGULI_VIDEO_CODEC_H264_X264, GAEGULI_VIDEO_STREAM_TYPE_MPEG_TS, 2048000,
      "srt://127.0.0.1:1111", NULL, &error);

  g_assert_no_error (error);
  g_assert_nonnull (target);
  g_assert_cmpuint (target->id, !=, 0);
  fixture->target = target;

  gaeguli_target_start (target, &error);
  g_assert_no_error (error);

  g_main_loop_run (fixture->loop);

  gaeguli_pipeline_stop (pipeline);
}

위 코드에서 주의깊게 보실 부분은 GaeguliPipeline 포인터입니다. gaeguli_pipeline_new()의 내부에서 할당한 메모리를 외부 함수에서 불러와서 사용할때 포인터의 소유권을 넘긴 부분과 할당한 메모리의 반환을 위해 별다른 노력을 기울이지 않은 것을 볼 수 있습니다.

맺음말

우리는 답을 찾을 것이다. 늘 그랬듯이.


K-UAM, 도심항공모빌리티 #1 (Intro)

이전글: 도심항공모빌리티(UAM)와 오픈소스

UAM, K-UAM

도심항공모빌리티(UAM, Urban Air Mobility)는 출발지와 목적지를 정해두고 계획한 일정에 따라 주기적으로 정해진 항로를 날아다니는 형태의 교통 수단이라고 할 수 있습니다. 5인승 정도 되는 저소음 수직 이착륙 비행체가 고도 300M에서 600M 사이에서 이동하는 모습을 2025년 즈음에는 서울에서 볼 수 있을 것이라는 것이 K-UAM의 목표이기도 합니다.

ConVairCar Model 118 이미지 출처:The Fascinating History of the Flying Car

K-UAM에 설계자로 참여하게 된 2022년 1월만하더라도 2025년이라고 시점을 언급한 것이 너무 섣부른 판단이 아닐까 하는 걱정이 더 많았습니다. 하지만 이 글을 쓰고 있는 8월 시점으로 본다면 2025년 상용화 목표 달성 가능성이 더 크다는 생각들고 있습니다. 비단 이것은 자만심이라기 보다는 많은 부분에서 불확실성이 해소되고 있기 때문일 것입니다.

K-UAM 정립의 기준

UAM은 많은 부분에 있어서 항공 산업에서 사용하고 있는 시스템들을 기준으로 다른 점들을 분석하고 수정할 부분과 새롭게 정의할 부분을 정의하고 있습니다. 기존 시스템을 기준으로 UAM이 나아갈 방향을 정립하는 단계라고 말할 수 있고, 이 기준의 축은 항공 산업, 교통 체계, 정책이라고 보고 있습니다. 이 중 가장 빠른 속도로 진행되는 축은 아무래도 보여줄 수 있는 실체를 만들 수 있는 항공 산업 기반의 축이라고 생각됩니다. 교통 체계로서는 기존에 운용되고 있는 택시, 버스, 철도, 그리고 역시 항공 서비스와 연계에 대해서 고민하다보니 이용자의 입장에서 사용할 수 있는 서비스 모델에 대한 정립이 필요하지만, 새롭게 등장한 교통 수단이기 때문에 획기적인 서비스 모델을 만든다하더라도 검증할 방법이 마땅치 않아 많은 고민을 할 수 밖에 없는 분야라고 할 수 있습니다. 또한 교통 체계의 완성과 성공 여부는 결국 이용자의 호응도에 따르는데 신기술로 무장한 UAM을 거부감 없이 이용할 사용자들이 얼마나 될지 예측하는 것도 사실 어려움이 있습니다. 마지막으로 정책에 대해서는 국가 단위의 의사 결정이 필요한 부분이므로 가장 속도가 느린 축이라고 말할 수 있습니다.

혼잡한 도심 내에서 이동 효율을 획기적으로 높일 수 있다는 기대감에 출발한 UAM은 이러한 세 기준을 어떻게 해석하느냐에 따라 각자의 특성을 가지고 발전을 하게 될 것입니다.

K-UAM

UAM은 체계의정립은, 미국은 FAA(Federal Aviation Administration)를 중심으로 유럽은 EASA(European Union Aviation Safety Agency)를, 그리고 우리나라는 국토교통부와 한국 항공 우주 연구원의 주도로 진행되고 있습니다.

미국의 경우, 넓은 지역과 다양한 민간 사업자를 고려하여 분산 운용 관제를 추구하고 있는 반면, 유럽의 경우는 기존 항공과 유사함을 근거로 중앙 집중식 관제 방식을 정립하고 있다는 것이 큰 차이점이라고 할 수 있습니다. 우리나라의 경우 미국의 선례를 따라서 분산 운용을 우선적으로 검토하고 있으나, 아직까지는 결론이 나지 않아 많은 연구와 실험을 통하여 최종 방안에 대한 권고안을 작성할 예정입니다.

UAM의 운용 방식은, 국가별로 가용한 혹은 계획한 인프라의 상태와 신기술 도입에 대한 적극성, 기술 수준에 따라 다를 수 밖에 없으며, 우리나라의 UAM 체계는 K-UAM이라는 틀안에서 적합한 운용 방법을 찾아 나가고 있는 상황입니다.

K-UAM 인프라

우리나라와 미국, 유럽과 또 다른 상황은 UAM에 적용할 건설, 교통 및 통신 인프라의 차이 입니다. UAM을 운용하기 위해서는 UAM 기체가 있어야함은 물론이지만, 뜨고 내릴 수 있는 공항인 버티포트(Vertiport)가 있어야 합니다. 버티포트는 이착륙장뿐만 아니라 UAM 기체의 배터리 충전 및 정비가 가능해야하며, 승객과 UAM을 연결하는 창구가 됩니다. 즉 도심의 혼잡한 교통 상황을 해결하기 위해서 버티포트는 혼잡한 도심에 위치하는 것이 가장 이용률을 높일 수 있는 방안이라는 아이러니한 결론을 얻게되지만, 충전 및 정비 설비가 동작할 수 있도록 막대한 전력 공급이 가능하고 안전한 이착륙을 보장하기 위해 상공의 공간이 열려 있는 곳이어야 하기 때문에 그 위치 선정이 쉽지 않습니다. 그렇기 때문에 기존의 건설과 교통 인프라를 활용하는 방안이 검토되고 있습니다.

또 다른 큰 차이점을 만드는 부분은 UAM이 데이터 통신을 기반으로 시작하는 최초의 교통 수단이기 때문이라고 할 수 있습니다. 기존의 항공은 VHF 대역의 음성 통신 기반으로 운용이 되고 있고, 초기에는 많은 부분을 기존 항공 산업에서 사용하던 장비들을 활용할수 밖에 없겠지만, UAM 교통 관제, UAM 기체 조종사, 버티포트 등은 상용화 이후, 이전의 방식보다는 유무선 데이터 통신을 통해 주요한 의사 결정을 하는 체계를 완성하는 것을 목표로 하고 있습니다. 특히 UAM이 이용하는 하늘길에서 4G/5G 혹은 앞으로 출현할 6G 통신망의 사용은, UAM에 대한 명령과 제어를 하는 데이터와 일반 승객들이 이용하는 데이터를 같은 통신 인프라를 통해서 사용하게 될 것이라는 점에서 통신 인프라 설계자들의 고민을 깊게 만들고 있습니다. 불행 중 다행인 것은 우리나라의 지상 무선 통신망 인프라는 매우 품질이 좋은 편이며, 지상 인프라를 활용하여 상공망을 구축하는 것을 시작할 수 있어 다른 국가들에 비해 우위에 있다고 볼수 있다는 점입니다.

K-UAM 운용 시나리오

우리나라는 대부분의 공역이 비행허가구역으로 지정되어있기 때문에 UAM이 사용할 수 있는 구간은 정책에 의해서 결정될 수 있습니다. UAM이 비행할 수 있는 구간이 정해졌다고 해서 UAM 사업자가 원하는 시점에 해당 구간을 사용할 수 있는 것은 아니며, 원칙적으로는 하늘길을 합법적으로 사용하기 위해서 ATM(Air Traffic Management)의 관제를 받아야합니다. 하지만 UAM은 기존 항공기에 비해 짧고 빈번하게 운행되는 특성을 갖기 때문에, ATM의 통제하에 있기 보다는 UAM 항로에 대해서는 UAM 교통 관제 시스템이 담당을 하고, ATM와 연계하는 방식으로 진행되고 있습니다.

UAM 기체가 비행할 계획을 사전에 수립하고, 이/착륙 및 비행시에 정해진 프로토콜에 따라 운행하되, 계획에서 벗어난 상황에서 UAM 시스템들이 어떻게 동작해야하는지는 결국 운영 시나리오를 통해서 확립할 수 밖에 없습니다. 또한 이 운용 시나리오가 정교해질 수록 UAM을 구성하는 시스템의 역할과 운영 주체도 판별할 수 있게 됩니다.

즉 하늘길을 안전하게 사용할 수 있는 기반은 K-UAM 인프라가 제공을 하는 것이며, 우리 나라의 하늘길을 사용하기 위한 시스템은 K-UAM 운용 시나리오를 바탕으로 연구하고 있다고 말할 수 있습니다.

현재까지 구성한 K-UAM 시나리오에서는, UAM이 이동하는 경로는 UAM 교통 관제 시스템이 관제를 하는 것이 원칙이지만, 버티포트는 UAM 기체와 승객의 접점이 되는 공간으로 특별히 주의 깊게 관리해야하는 지역으로 버티포트 주변 영역의 관제와 UAM 운항 경로에 대한 관제를 구분하여 설정하고 있습니다.

도심항공교통 가상 통합 운용 및 검증 기술

운용 시나리오를 검증하는 가장 좋은 방법은 시나리오를 실제로 수행해보는 것입니다. 도심항공교통 가상 통합 운용 및 검증 기술 과제는 270억 규모로 약 40여개의 민간 기관이 2022년부터 2025년까지 K-UAM을 운용할 가상의 환경을 구축하는 사업으로, 상황별 시나리오를 모의 시스템 내에서 수행하여 해당 시나리오의 유효성을 검증하는 것 뿐 아니라, K-UAM을 효율적으로 운용하기 위한 최소 요구 조건을 수립하는 것을 목표로 진행하고 있습니다.

K-UAM의 체계를 정립하고 검증하기 위해 수행하고 있는 이 과제는 5개의 세부 분야로 나뉘어져있습니다. 가상의 버티포트를 구성하고, 모의 조종석을 통해 기체를 제어할 수 있는 시스템과, 버티포트와 기체 그리고 전체적인 상황을 통제하는 교통 관제 시스템, 교통 관제의 의사 결정을 위한 정보를 제공하는 운항 정보 제공 시스템을 구성중에 있고, 최종 시스템은 가상 통합 운용 센터로 통합하여 과제를 진행하면서, 그리고 종료 후에도 5년간 운용하면서 K-UAM운용 시나리오를 점검하고 검증하는데 사용될 예정입니다.

과제 구성도

다음글: K-UAM 교통 관제 시스템 (예정)

관련 세미나 정보

UAM의 미래상과 기술 개발 전략

  • 일시 2022년 08월 16일 (화)
  • 시간 16:00 ~ 18:00
  • 장소 SKT타워 4층 SUPEX홀

Memory-safe in C

근래 갑작스럽게, 백악관, ‘C’와 ‘C++’ 사용 중단 촉구라는 글이 노출이 되어, 기술에 대해 이렇게 직관적이고 공격적인 단어를 사용해서 방향을 제시했을까라는 의문이 들어 원문을 찾아보았습니다. 역시나 원문은 NSA의 권고가 있다는 내용이고, 취지는 메모리 관리에 유리한 프로그래밍 언어들의 리스트를 취합하는 과정에서 “White House urges developers to avoid C and C++, use ‘memory-safe’ programming languages” 라고 정중하게 말한 것 뿐이었습니다. 프로그램을 작성할 때 메모리 관리에 대해 강조하고자 했다는 의도에는 동감하나, 굳이 이렇게 노골적인 단어로 번역했어야 하나하는 의문은 남습니다.

More …