Windows 작업 관리자에서 CPU와 GPU 부분이 나뉘어져 있는 이유는 이 두 장치가 서로 다른 역할을 수행하기 때문입니다. CPU와 GPU는 각각 컴퓨터의 계산 작업을 처리하지만, 구조와 용도가 다르기 때문에 별도로 관리하고 모니터링할 필요가 있습니다.

1. CPU와 GPU의 역할 차이

  • CPU (Central Processing Unit): 컴퓨터의 중앙 처리 장치로, 일반적으로 직렬 처리에 적합합니다. 운영 체제, 애플리케이션 실행, 논리적 연산, 입출력(I/O) 처리 등 다양한 작업을 수행합니다. 보통 4~16개의 코어를 가지고 있으며, 다양한 작업을 수행하도록 최적화되어 있습니다.
  • GPU (Graphics Processing Unit): 그래픽 카드의 주요 부품으로, 다수의 코어를 가지고 병렬 작업에 최적화되어 있습니다. 이미지 렌더링, 영상 처리, 게임 그래픽 등과 같은 대규모 데이터를 동시에 처리하는 데 유리하며, 최근에는 인공지능(AI) 및 머신러닝 작업에도 많이 활용됩니다.

2. 자원 사용 모니터링의 필요성

  • CPU와 GPU는 각기 다른 작업을 수행하면서 시스템 자원을 소비하므로, 사용자가 두 장치의 상태를 개별적으로 모니터링할 수 있도록 작업 관리자가 나누어 보여줍니다.
  • CPU 부분에서는 시스템 전반에서 발생하는 프로세스, 스레드, 메모리 사용량을 주로 확인할 수 있고, GPU 부분에서는 그래픽 렌더링이나 GPU 가속이 필요한 작업에 사용된 자원을 모니터링할 수 있습니다.

3. 성능 최적화와 문제 해결에 도움

  • CPU와 GPU 자원을 분리하여 표시하면 사용자가 각 장치의 자원 사용량을 독립적으로 모니터링할 수 있어, 어떤 장치가 과부하 상태인지, 특정 프로그램이 CPU나 GPU 자원을 과도하게 사용하고 있는지 쉽게 확인할 수 있습니다.
  • 예를 들어, 게임을 실행할 때 GPU 사용량이 높아지고 CPU 사용량은 상대적으로 낮다면, 게임의 그래픽 처리에 GPU가 적절히 활용되고 있음을 알 수 있습니다. 반대로 CPU 사용량이 과도하게 높다면, 프로그램 최적화 문제를 의심할 수 있습니다.

이처럼, CPU와 GPU 부분을 분리해 보여주는 작업 관리자는 시스템 성능 모니터링과 문제 해결에 있어 사용자에게 중요한 정보를 제공합니다.

1. GPU 드라이버가 설치되지 않음 또는 오래된 경우
  • 문제: GPU가 제대로 인식되지 않으면 작업 관리자가 해당 정보를 표시할 수 없습니다.
  • 해결 방법: GPU 제조사(NVIDIA, AMD, Intel 등)의 최신 드라이버를 설치하거나 업데이트합니다. Windows 업데이트에서도 기본적인 GPU 드라이버가 제공될 수 있으므로 확인해 보세요.

2. 작업 관리자 업데이트 미지원 (Windows 버전 문제)

  • 문제: Windows 10 버전 1709(2017년 출시) 이전 버전에서는 GPU 사용량을 작업 관리자에서 표시하지 않습니다.
  • 해결 방법: Windows 버전을 최신 상태로 업데이트하세요. 현재 지원되는 Windows 10 또는 Windows 11을 사용 중인지 확인해 보세요.

3. 내장 그래픽만 활성화된 경우 (외장 GPU 비활성화)

  • 문제: 데스크탑이나 랩톱에서 외장 GPU가 비활성화되면 GPU 정보가 작업 관리자에 나타나지 않을 수 있습니다.
  • 해결 방법: BIOS 설정에서 외장 GPU가 활성화되어 있는지 확인하거나, 장치 관리자를 열어 GPU가 비활성화되었는지 확인한 후, 필요한 경우 활성화합니다.

4. 장치 관리자에서 GPU 인식 문제

  • 문제: 장치 관리자에 GPU가 나타나지 않으면, 작업 관리자에서도 GPU 정보가 표시되지 않습니다.
  • 해결 방법: Windows 장치 관리자(Device Manager)를 열고 "디스플레이 어댑터" 항목에서 GPU가 제대로 인식되고 있는지 확인합니다. 표시되지 않거나 오류가 있는 경우, 드라이버 재설치 또는 하드웨어 점검이 필요할 수 있습니다.

5. 원격 데스크톱 사용 시 제한

  • 문제: 원격 데스크톱 연결을 통해 컴퓨터에 접속할 경우, GPU 정보가 작업 관리자에 표시되지 않을 수 있습니다. 이는 원격 세션에서 GPU 사용량을 표시하는 것이 제한되기 때문입니다.
  • 해결 방법: GPU 사용량을 확인하려면 물리적으로 컴퓨터에 직접 접속하거나, GPU 모니터링 프로그램(예: GPU-Z)을 사용해 보세요.

6. Windows 작업 관리자 문제

  • 문제: Windows의 작업 관리자에 일시적인 버그가 발생했을 수 있습니다.
  • 해결 방법: 작업 관리자를 재시작하거나, 컴퓨터를 재부팅하여 문제를 해결할 수 있는지 확인해보세요.

이 외에도 GPU 사용량을 확인할 수 있는 프로그램(예: GPU-Z, MSI Afterburner, HWMonitor)을 활용하면 GPU가 제대로 작동하는지 확인할 수 있습니다.

Windows에서 리눅스의 Shared Memory와 유사한 구조는 메모리 맵 파일 (Memory-Mapped File) 입니다.

메모리 맵 파일은 두 프로세스 간의 데이터 공유를 위해 사용할 수 있으며, 파일의 내용을 메모리에 매핑하여 프로세스가 이를 공유하게끔 합니다. 이는 리눅스의 shm_open()와 mmap() 함수로 메모리를 공유하는 방식과 유사합니다. Windows에서는 CreateFileMapping()과 MapViewOfFile() 함수를 사용하여 메모리 맵 파일을 생성하고, 이를 통해 메모리에 데이터를 매핑하여 여러 프로세스 간에 공유할 수 있습니다.

이 방식을 사용하면 각 프로세스가 같은 메모리 영역을 볼 수 있어 효율적으로 데이터를 교환할 수 있으며, 주로 큰 데이터 집합을 공유하거나 IPC(Inter-Process Communication)를 구현할 때 사용됩니다.

struct  KSEJONG_MEMREC     {
Ubyte lock_flag; /* 메모리사용상태 */
Ubyte seq[4];
Ubyte seq_no[4];
Ubyte   full_code[12];
Ubyte   code[7];
Ubyte jmast[SZ_JMAST +1];
Ubyte jsise[SZ_JSISE +1];
Ubyte info[SZ_INFO  +1];
Ubyte hando[SZ_HANDO +1];
Ubyte chegyul_cnt[2];
Ubyte danilsise[SZ_DANILSISE+1];
Ubyte   danilchegyul[CNT_DANILCHEGYUL][SZ_TIMECHEGYUL + 1];
};
#define SZ_KSEJONG_MEMREC  sizeof(struct   KSEJONG_MEMREC)
#define OFF_KSESHM (SZ_KSEJONG_MEMREC * CNT_KSEJONG)

Windows에서 C 언어로 KSEJONG_MEMREC 구조체를 메모리 맵 파일을 통해 공유하는 예제를 구성해보겠습니다. 아래 코드는 KSEJONG_MEMREC 구조체를 정의하고, 메모리 맵 파일을 통해 데이터를 공유하는 예제입니다. 한 프로그램에서 데이터를 쓰고, 다른 프로그램에서 이를 읽을 수 있도록 작성하였습니다.

1. 구조체 정의 및 메모리 맵 파일에 쓰기

먼저, 메모리 맵 파일에 데이터를 쓰는 코드를 작성하겠습니다.

#include <windows.h>
#include <stdio.h>
#include <string.h>

#define SZ_JMAST 20
#define SZ_JSISE 20
#define SZ_INFO 20
#define SZ_HANDO 20
#define SZ_DANILSISE 20
#define CNT_DANILCHEGYUL 5
#define SZ_TIMECHEGYUL 20
#define CNT_KSEJONG 10

// KSEJONG_MEMREC 구조체 정의
#pragma pack(push, 1)
typedef struct {
    BYTE lock_flag;                 // 메모리 사용 상태
    BYTE seq[4];                    // 주소
    BYTE seq_no[4];                 // 신코드Seq
    BYTE full_code[12];             // 풀코드
    BYTE code[7];                   // 단축코드
    BYTE jmast[SZ_JMAST + 1];       // 거래소 종목마스터
    BYTE jsise[SZ_JSISE + 1];       // 거래소 종목시세
    BYTE info[SZ_INFO + 1];         // 거래소 거래원정보
    BYTE hando[SZ_HANDO + 1];       // 거래소 외국인한도
    BYTE chegyul_cnt[2];            // 체결 갯수
    BYTE danilsise[SZ_DANILSISE + 1]; // 시세
    BYTE danilchegyul[CNT_DANILCHEGYUL][SZ_TIMECHEGYUL + 1]; // 체결
} KSEJONG_MEMREC;
#pragma pack(pop)

#define MEM_SIZE (sizeof(KSEJONG_MEMREC) * CNT_KSEJONG)

int main()
{
    // 메모리 맵 파일 생성
    HANDLE hMapFile = CreateFileMapping(
        INVALID_HANDLE_VALUE,
        NULL,
        PAGE_READWRITE,
        0,
        MEM_SIZE,
        TEXT("KSEJONG_SharedMemory"));

    if (hMapFile == NULL) {
        printf("Could not create file mapping object (%d).\n", GetLastError());
        return 1;
    }

    // 메모리 맵 파일에 대한 뷰 생성
    KSEJONG_MEMREC* pBuf = (KSEJONG_MEMREC*) MapViewOfFile(
        hMapFile,
        FILE_MAP_ALL_ACCESS,
        0,
        0,
        MEM_SIZE);

    if (pBuf == NULL) {
        printf("Could not map view of file (%d).\n", GetLastError());
        CloseHandle(hMapFile);
        return 1;
    }

    // 데이터 초기화 및 쓰기
    memset(pBuf, 0, sizeof(KSEJONG_MEMREC));
    pBuf->lock_flag = 1;
    memcpy(pBuf->seq, "1234", 4);
    memcpy(pBuf->seq_no, "5678", 4);
    memcpy(pBuf->full_code, "FULLCODE1234", 12);
    memcpy(pBuf->code, "CODE123", 7);
    memcpy(pBuf->jmast, "MasterInfo", 10);
    memcpy(pBuf->jsise, "PriceInfo", 9);
    memcpy(pBuf->info, "TradeInfo", 9);
    memcpy(pBuf->hando, "HandoInfo", 9);
    pBuf->chegyul_cnt[0] = 1;
    pBuf->chegyul_cnt[1] = 2;
    memcpy(pBuf->danilsise, "PriceData", 9);
    memcpy(pBuf->danilchegyul[0], "TradeData1", 10);

    printf("Data written to shared memory.\n");

    // 메모리 뷰 및 핸들 닫기
    UnmapViewOfFile(pBuf);
    CloseHandle(hMapFile);

    return 0;
}

2. 메모리 맵 파일에서 데이터 읽기

다음은 메모리 맵 파일에 저장된 데이터를 읽는 코드입니다.

#include <windows.h>
#include <stdio.h>

#define SZ_JMAST 20
#define SZ_JSISE 20
#define SZ_INFO 20
#define SZ_HANDO 20
#define SZ_DANILSISE 20
#define CNT_DANILCHEGYUL 5
#define SZ_TIMECHEGYUL 20
#define CNT_KSEJONG 10

#pragma pack(push, 1)
typedef struct {
    BYTE lock_flag;
    BYTE seq[4];
    BYTE seq_no[4];
    BYTE full_code[12];
    BYTE code[7];
    BYTE jmast[SZ_JMAST + 1];
    BYTE jsise[SZ_JSISE + 1];
    BYTE info[SZ_INFO + 1];
    BYTE hando[SZ_HANDO + 1];
    BYTE chegyul_cnt[2];
    BYTE danilsise[SZ_DANILSISE + 1];
    BYTE danilchegyul[CNT_DANILCHEGYUL][SZ_TIMECHEGYUL + 1];
} KSEJONG_MEMREC;
#pragma pack(pop)

#define MEM_SIZE (sizeof(KSEJONG_MEMREC) * CNT_KSEJONG)

int main()
{
    // 기존 메모리 맵 파일 열기
    HANDLE hMapFile = OpenFileMapping(
        FILE_MAP_ALL_ACCESS,
        FALSE,
        TEXT("KSEJONG_SharedMemory"));

    if (hMapFile == NULL) {
        printf("Could not open file mapping object (%d).\n", GetLastError());
        return 1;
    }

    // 메모리 맵 파일에 대한 뷰 생성
    KSEJONG_MEMREC* pBuf = (KSEJONG_MEMREC*) MapViewOfFile(
        hMapFile,
        FILE_MAP_ALL_ACCESS,
        0,
        0,
        MEM_SIZE);

    if (pBuf == NULL) {
        printf("Could not map view of file (%d).\n", GetLastError());
        CloseHandle(hMapFile);
        return 1;
    }

    // 데이터 읽기
    printf("Read from shared memory:\n");
    printf("Lock Flag: %d\n", pBuf->lock_flag);
    printf("Seq: %.4s\n", pBuf->seq);
    printf("Seq No: %.4s\n", pBuf->seq_no);
    printf("Full Code: %.12s\n", pBuf->full_code);
    printf("Code: %.7s\n", pBuf->code);
    printf("Jmast: %.10s\n", pBuf->jmast);
    printf("Jsise: %.9s\n", pBuf->jsise);
    printf("Info: %.9s\n", pBuf->info);
    printf("Hando: %.9s\n", pBuf->hando);
    printf("Chegyul Cnt: %d %d\n", pBuf->chegyul_cnt[0], pBuf->chegyul_cnt[1]);
    printf("Danilsise: %.9s\n", pBuf->danilsise);
    printf("Danilchegyul[0]: %.10s\n", pBuf->danilchegyul[0]);

    // 메모리 뷰 및 핸들 닫기
    UnmapViewOfFile(pBuf);
    CloseHandle(hMapFile);

    return 0;
}

설명

  1. 쓰기 코드는 CreateFileMapping으로 메모리 맵 파일을 생성하고 MapViewOfFile로 메모리 뷰를 얻습니다. 이후 구조체 데이터를 메모리에 씁니다.
  2. 읽기 코드는 OpenFileMapping을 통해 기존 메모리 맵 파일에 접근하고, MapViewOfFile로 메모리 뷰를 얻어 데이터를 읽어옵니다.

이 코드를 통해 Windows 환경에서 C 언어로 Shared Memory를 사용할 수 있습니다.

이 코드는 Windows API 함수(CreateFileMapping, MapViewOfFile, UnmapViewOfFile, CloseHandle 등)를 사용하기 때문에 추가적인 라이브러리 링크는 필요하지 않습니다. Windows API는 기본적으로 Windows 운영 체제에 포함되어 있으므로 별도의 라이브러리를 링크하지 않아도 됩니다.

Visual Studio와 GCC(MinGW) 모두 Windows API 함수가 기본적으로 포함되어 있어서, 별도의 라이브러리 옵션을 명시하지 않고도 컴파일할 수 있습니다.

gcc write_memory.c -o write_memory.exe
gcc read_memory.c -o read_memory.exe

아래 명령을 사용하여 모든 .cs 파일에서 아스키 코드 123 ({)을 제거할 수 있습니다.

find 명령으로 찾은 .cs 파일들에서 아스키 코드 123 ({, 즉 16진수로는 7B)를 제거하려면, 다음과 같은 방법을 사용할 수 있습니다.

sed 사용)

아래 명령을 사용하여 모든 .cs 파일에서 아스키 코드 123 ({)을 제거할 수 있습니다.

find ./ -name "*.cs" -exec sed -i 's/\%x7B//g' {} +

비고) 문장전체를 바꿀때에
1)AddItemToList("QCS:" + queueName, jsonText);
2)AddItemToList("QCS:" + APMMemory.GetInstance.redisSenderQueueNM, jsonString);

find ./ -name "*.cs" -exec sed -i 's/AddItemToList("QCS:" + queueName, jsonText)/AddItemToList("QCS:" + APMMemory.GetInstance.redisSenderQueueNM, jsonString)/g' {} \;

현재 Text파일의 인코딩형식을 알려면)
B210145_BK@DESKTOP-QNNUCER MINGW64 ~/Downloads/NodeServer/redis_web_5_5_ticker/multiloginredistickserver
$ find ./ -name "*.cs" -exec file -i {} \;
./APMMemory.cs: text/x-c++; charset=utf-8
./APMSQLite.cs: text/x-c++; charset=us-ascii
./DataEncoding.cs: text/x-c++; charset=utf-8
./ExturePlusElw.cs: text/x-c++; charset=utf-8
./ExturePlusElwText.cs: text/x-c++; charset=utf-8
./ExturePlusFuture.cs: text/x-c++; charset=utf-8
./ExturePlusFutureText.cs: text/x-c++; charset=utf-8
./ExturePlusKosdaq.cs: text/x-c++; charset=utf-8
./ExturePlusKosdaqQuote10.cs: text/x-c++; charset=utf-8

인코딩변경)
./ExturePlusElwText.cs: text/x-c++; charset=utf-8
./ExturePlusFuture.cs: text/x-c++; charset=utf-8
./ExturePlusFutureText.cs: text/x-c++; charset=iso-8859-1
./ExturePlusFutureTextText.cs: text/x-c++; charset=iso-8859-1
./ExturePlusKosdaq.cs: text/x-c++; charset=utf-8
./ExturePlusKosdaqQuote10.cs: text/x-c++; charset=utf-8


find ./ -name "*.cs" -exec iconv -f utf-8 -t iso-8859-1 {} -o {}.tmp \; -exec mv {}.tmp {} \;

Redis는 클라이언트의 연결 수를 제한하는 기능을 제공합니다. 이를 통해 Redis 서버가 과도한 연결로 인해 리소스가 소모되는 것을 방지할 수 있습니다. 기본적으로 Redis는 클라이언트 연결 수에 대한 제한을 설정하지 않지만, 몇 가지 방법으로 이를 조정할 수 있습니다:

  1. maxclients 설정: Redis의 설정 파일(redis.conf)에서 maxclients 옵션을 사용하여 허용할 최대 클라이언트 연결 수를 설정할 수 있습니다. 예를 들어, maxclients 10000이라고 설정하면 최대 10,000개의 클라이언트가 동시에 연결될 수 있습니다. 이 값은 Redis 서버의 메모리와 시스템의 자원에 따라 조정해야 합니다.
  2.  
    maxclients 10000
  3. 운영 체제의 파일 핸들 제한: Redis는 운영 체제의 파일 핸들 수에 따라 제한을 받을 수 있습니다. Redis는 각 클라이언트 연결을 파일 핸들로 처리하므로, 운영 체제에서 허용하는 파일 핸들의 수에 따라 Redis의 최대 연결 수가 제한될 수 있습니다. 이를 조정하려면 운영 체제의 설정을 변경해야 합니다. 예를 들어, Linux에서는 ulimit 명령어를 사용하여 파일 핸들 수를 조정할 수 있습니다.
  4.  
    ulimit -n 10000
  5. 클라이언트 연결 수의 모니터링: Redis 서버의 연결 상태를 모니터링하는 것도 중요합니다. INFO clients 명령어를 사용하여 현재 연결된 클라이언트의 수를 확인할 수 있습니다.
  6.  
    INFO clients
  7. client-output-buffer-limit 설정: Redis는 클라이언트의 출력 버퍼가 너무 커지는 것을 방지하기 위해 client-output-buffer-limit 설정을 제공합니다. 이 설정은 클라이언트가 보내는 데이터의 크기를 제한하여 서버가 과도한 메모리를 소비하지 않도록 합니다.
  8.  
    client-output-buffer-limit pubsub 33554432 8388608 60

Redis 서버의 연결 제한을 적절히 설정하면 성능을 안정적으로 유지할 수 있으며, 시스템 자원을 효율적으로 관리할 수 있습니다.

Linux에서 C# 프로젝트를 설정하고 빌드하는 과정은 다음과 같습니다. 이 과정에서는 .NET Core 또는 .NET 5/6/7 SDK를 사용하여 C# 프로젝트를 설정하고 빌드합니다. 이 가이드는 Ubuntu 시스템을 기준으로 작성되었습니다.

1. .NET SDK 설치

패키지 목록 업데이트 및 필수 패키지 설치
sudo apt update
sudo apt install -y wget apt-transport-https software-properties-common
wget https://packages.microsoft.com/keys/microsoft.asc
sudo apt-key add microsoft.asc
sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/ubuntu/20.04/prod focal main" > /etc/apt/sources.list.d/dotnetdev.list'

.NET SDK 설치
sudo apt update
sudo apt install -y dotnet-sdk-7.0

설치 확인
dotnet --version

2. C# 프로젝트 생성
> dotnet new console -o mdiwebrowser

비고)
WPF 프로젝트 생성(다음 명령어로 WPF 프로젝트를 생성합니다.)
> dotnet new wpf -o <프로젝트이름>


프로젝트 디렉토리로 이동

프로젝트 빌드 및 실행

프로젝트 빌드
dotnet build


dotnet add package Newtonsoft.Json
dotnet add package ServiceStack.Redis
dotnet add package System.Data.SQLite


프로젝트 실행
dotnet run

$ find ./ -name "*.cs" | xargs grep "Data Source"

grep 명령어 실행 시 "No such file or directory" 메시지를 피하려면, 다음과 같은 방법을 사용할 수 있습니다.
grep 명령어 실행 시 "No such file or directory" 메시지를 피하려면, 다음과 같은 방법을 사용할 수 있습니다.

B210145_BK@DESKTOP-QNNUCER MINGW64 ~/Downloads/EXTURE_3_0_APM_BASIC
$ find ./ -name "*.cs" | xargs grep "Data Source"
./APM/APM/APMMain.cs:            APMSQLite.GetInstance.Conn = new SQLiteConnection("Data Source=:memory:;Version=3;");
./APM/APM/APMMainForm.cs:            APMSQLite.GetInstance.Conn = new SQLiteConnection("Data Source=:memory:;Version=3;");
grep: ./APM/Screen/Live-Charts-master/Examples/UWP/CartesianChart/Basic: No such file or directory
grep: Bars/BasicColumn.xaml.cs: No such file or directory
grep: ./APM/Screen/Live-Charts-master/Examples/UWP/CartesianChart/Basic: No such file or directory
grep: Bars/BasicRowExample.xaml.cs: No such file or directory
grep: ./APM/Screen/Live-Charts-master/Examples/UWP/CartesianChart/Basic: No such file or directory
grep: Stacked: No such file or directory
grep: Bar/BasicStackedColumnExample.xaml.cs: No such file or directory
grep: ./APM/Screen/Live-Charts-master/Examples/UWP/CartesianChart/Basic: No such file or directory
grep: Stacked: No such file or directory
grep: Bar/BasicStackedRowPercentageExample.xaml.cs: No such file or directory
grep: ./APM/Screen/Live-Charts-master/Examples/UWP/CartesianChart/Chart: No such file or directory
grep: to: No such file or directory
grep: Image/ChartToImageSample.xaml.cs: No such file or directory
grep: ./APM/Screen/Live-Charts-master/Examples/UWP/CartesianChart/Customized: No such file or directory
grep: Series/CustomizedLineSeries.xaml.cs: No such file or directory

1. 오류 메시지 무시하기: grep 명령어의 표준 오류를 /dev/null로 리디렉션하여 오류 메시지를 무시할 수 있습니다.

find ./ -name "*.cs" | xargs grep "Data Source" 2>/dev/null

2. 존재하는 파일만 찾기: find 명령어로 실제 존재하는 파일만 대상으로 하여 grep을 실행하도록 합니다. -exec 옵션을 사용하면 find 명령어가 각각의 파일에 대해 grep을 실행하게 할 수 있습니다.

find ./ -name "*.cs" -exec grep "Data Source" {} +

 

아래검색파일에서 Value="14"를 Value="10"으로 변경하고자, 구글링하려고 했으나, (CHAT.GPT)를 이용하니, 바로 리눅스명령어 알려줌
아래검색파일에서 Value="14"를 Value="10"으로 변경하고자, 구글링하려고 했으나, (CHAT.GPT)를 이용하니, 바로 리눅스명령어 알려줌


xterm@DESKTOP-VVAIF4D MINGW64 ~/Downloads/tmp/WindowsPresenFoundation/WINPAYCalcM
$ find ./ -name "*.xaml" | xargs grep FontSize | grep Value=
./BasicInfoDialog.xaml:            <Setter Property="FontSize" Value="14"/>
./BasicInfoDialog.xaml:            <Setter Property="FontSize" Value="14"/>
./BasicInfoDialog.xaml:            <Setter Property="FontSize" Value="14"/>
./FileListNM.xaml:        <Setter Property="FontSize" Value="14"/>
./FileListNM.xaml:        <Setter Property="FontSize" Value="14"/>
./FileListNM.xaml:        <Setter Property="FontSize" Value="14"/>
./MainWindow.xaml:            <Setter Property="FontSize" Value="10"/>
./SpecificDialog.xaml:        <Setter Property="FontSize" Value="14"/>
./SpecificDialog.xaml:        <Setter Property="FontSize" Value="14"/>
./SpecificDialog.xaml:        <Setter Property="FontSize" Value="14"/>

xterm@DESKTOP-VVAIF4D MINGW64 ~/Downloads/tmp/WindowsPresenFoundation/WINPAYCalcM
$ sed -i 's/Value="10"/Value="11"/g' ./BasicInfoDialog.xaml ./FileListNM.xaml ./SpecificDialog.xaml

xterm@DESKTOP-VVAIF4D MINGW64 ~/Downloads/tmp/WindowsPresenFoundation/WINPAYCalcM
$ find ./ -name "*.xaml" | xargs grep FontSize | grep Value=
./BasicInfoDialog.xaml:            <Setter Property="FontSize" Value="10"/>
./BasicInfoDialog.xaml:            <Setter Property="FontSize" Value="10"/>
./BasicInfoDialog.xaml:            <Setter Property="FontSize" Value="10"/>
./FileListNM.xaml:        <Setter Property="FontSize" Value="10"/>
./FileListNM.xaml:        <Setter Property="FontSize" Value="10"/>
./FileListNM.xaml:        <Setter Property="FontSize" Value="10"/>
./MainWindow.xaml:            <Setter Property="FontSize" Value="10"/>
./SpecificDialog.xaml:        <Setter Property="FontSize" Value="10"/>
./SpecificDialog.xaml:        <Setter Property="FontSize" Value="10"/>
./SpecificDialog.xaml:        <Setter Property="FontSize" Value="10"/>

xterm@DESKTOP-VVAIF4D MINGW64 ~/Downloads/tmp/WindowsPresenFoundation/WINPAYCalcM
$

FTP로 파일을 전송 시 아스키(ASCII) 모드와 바이너리(Binary) 모드 두 가지가 있습니다. 
아스키 모드로 전송하는 경우 수신 컴퓨터에서 파일을 읽지 못하는 문제가 발생할 수 있습니다. 
ftp로 전송했는데 파일에 문제가 있다면 혹시 아스키 모드로 보냈는지 확인해보세요.

FTP 전송 모드
바이너리 모드로 보내야 하는 경우
바이너리 모드는 파일을 0과 1로 구성된 원시 데이터로 전송하는 모드입니다. 
가공되지 않은 원본 데이터이기 때문에 발송자가 보내는 파일과 수신자가 받는 파일이 정확히 같습니다.

반드시 바이너리 모드로 전송해야만 하는 파일들이 존재합니다. 
이미지 파일(.jpg, bmp, png), 사운드 파일(.mp3, .avi, .wma), 비디오 파일(.flv, .mkv, .mov, .mp4), 아카이브 파일(.zip, .rar, .tar), 그 외 실행 및 문서 파일(.exe, .doc, .xls, .pdf) 등이 그렇습니다. 사실 이렇게 나열할 필요도 없고 텍스트 형식이 아니면 그냥 바이너리로 보내야 한다고 보시면 됩니다.

아스키 모드 사용 이유
아스키 모드는 파일을 텍스트로 전송할 때 사용되는 모드입니다. 
ASCII는 American Standard Code for Information Interchange의 약자입니다. 정보 교환을 위해 만든 미국의 표준 코드입니다. .txt, html, .php, .cgi, .js, .txt, .css 등 확장자를 보낼 때 아스키 모드가 권고되기도 합니다.
당연하게도 텍스트 파일 역시 바이너리로 전송해도 됩니다. 
다만 아스키 모드로 전송 시 CR(Carriage Return)이 제거된다는 장점(?)이 있습니다. 
이게 무슨 말이냐 하면, 운영체제 간 행바꿈을 표현하는 기호의 차이를 보정해준다는 것입니다.

굳이 아스키 모드 안 써도 되는 이유
그럼에도 아스키 모드는 현재로서 영향력을 잃어가는 추세입니다. 
왜냐하면 바이너리 모드로도 별 문제가 없기 때문입니다. 
위에서 언급한 형식의 문제는 이미 상용 프로그램들이 스스로 보정을 해주기 때문입니다.
게다가 아스키 모드는 한국어, 일본어, 중국어 등의 문자를 처리하지 못합니다. 
텍스트 파일이라 할지라도 한글로 쓴 문서는 어차피 바이너리로 보내야 합니다.
이런 흐름을 반영하듯 sftp에선 모든 데이터는 바이너리 모드로 전송됩니다. 아스키 모드는 없습니다. 

비고)
윈도우는 띄어쓰기를 하면 캐리지 리턴(CR)과 라인피드(LF)가 모두 표기됩니다. 
두 용어는 과거 타자기에서 유래된 용어인데, 그게 중요한 건 아니고 결과적으로 아래의 예시 같은 차이가 발생한다는 것만 이해하시면 됩니다.
윈도우의 경우 줄을 바꾸면 \r\n
이렇게 \r\n 둘이 표시됩니다.
리눅스, 맥, FreeBSD, AIX 등 유닉스 시스템의 경우 줄을 바꾸면 \n
이렇게 \n만 표시됩니다.
그러니 윈도우에서 작성한 텍스트 파일을 리눅스에 보낼 때 아스키 모드는 CR(\n)을 제거해 차이를 보정해주기 때문에 이점이 있습니다.

클로바 AI에게 물어본결과)
FTP(File Transfer Protocol)는 파일 전송을 위한 프로토콜로, ASCII와 Binary 모드를 구분하여 사용합니다.
ASCII 모드: 텍스트 파일 전송에 사용되며, 각 문자를 7비트의 ASCII 코드로 변환하여 전송합니다. 전송 과정에서 데이터의 손실이나 변형이 일어날 가능성이 적습니다.
Binary 모드: 이미지, 동영상, 압축 파일 등의 바이너리 파일 전송에 사용되며, 파일의 원래 형태를 그대로 유지하여 전송합니다.
모드의 선택은 전송할 파일의 종류와 특성에 따라 달라집니다. 이를 고려하여 적절한 모드를 선택해야 합니다.

+ Recent posts