Dynamic HTML

1. 종목코드를 입력하면
2. 데이타를 출력할때에 동적으로 HTML을 생성한다.

app.js
0.01MB
index.html
0.05MB

 

SQLite는 독립적인 파일 기반 데이터베이스로, SQLite 명령줄 도구 sqlite3.exe를 통해 데이터베이스 파일(exture3_0_group_a_file.db)을 쉽게 핸들링할 수 있습니다.
다음은 sqlite3.exe를 사용하여 exture3_0_group_a_file.db 파일을 관리하는 방법에 대한 단계별 가이드입니다:


1. sqlite3.exe 실행

  • SQLite 명령줄 도구를 실행합니다.

또는 특정 데이터베이스 파일과 함께 실행합니다:

 

결과: SQLite 명령 프롬프트가 표시됩니다.


2. 데이터베이스 연결

SQLite가 실행된 상태에서 데이터베이스 파일을 연결하려면 다음 명령을 사용합니다:

.open exture3_0_group_a_file.db

성공적으로 연결되면 데이터베이스 파일이 열립니다.


3. 테이블 확인

데이터베이스의 테이블 목록을 확인하려면:

.tables

결과: 데이터베이스에 존재하는 모든 테이블 목록이 출력됩니다.


4. 테이블 구조 확인

특정 테이블의 구조를 확인하려면:

.schema 테이블명

5. 데이터 조회

테이블에서 데이터를 조회하려면 SQL 쿼리를 사용합니다:

SELECT * FROM 테이블명;

6. 데이터 삽입

데이터 삽입도 SQL 명령을 통해 가능합니다:

INSERT INTO 테이블명 (컬럼1, 컬럼2) VALUES ('값1', '값2');

7. 데이터 수정

데이터를 수정하려면:

UPDATE 테이블명 SET 컬럼명 = '새로운값' WHERE 조건;

8. 데이터 삭제

데이터를 삭제하려면:

DELETE FROM 테이블명 WHERE 조건;

9. SQLite 명령 사용

SQLite 도구 자체 명령은 .로 시작합니다:

  • 도움말 확인:
     
    .help
  • 데이터 저장 및 닫기:
     
    .exit

10. 스크립트 실행

SQL 파일을 실행하여 작업하려면:

.read script.sql

예: script.sql 파일에 SQL 명령이 포함되어 있으면 해당 명령이 실행됩니다.


예제

샘플 테이블 생성 및 데이터 관리

  1. 테이블 생성:
  2. sql
    CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER);
  3. 데이터 삽입:
  4. sql
    INSERT INTO users (name, age) VALUES ('Alice', 30);
  5. 데이터 조회:
  6. sql
    SELECT * FROM users;
  7. 데이터베이스 닫기:
  8. sql
    .exit

추가 참고

  • SQLite는 SQL 표준에 가까운 쿼리를 사용하므로, SQL 문법에 익숙하다면 쉽게 다룰 수 있습니다.
  • 데이터베이스 파일(aa.db)은 복사만으로 다른 환경에서도 사용할 수 있습니다.


실제활용예)
C:\Users\B210145_BK\Downloads\StockDesignNodeServer\redis_web_5_6_ticker\multiloginredistickserver>sqlite3
SQLite version 3.47.1 2024-11-25 12:07:48
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> .open exture3_0_group_a_file.db
sqlite> .tables
EXTUREPLUSFUTUREINVESTORINDEX
EXTUREPLUSFUTUREMASTER
EXTUREPLUSFUTURETRADE
EXTUREPLUSFUTURPRIORITYQUOTE
EXTUREPLUSKOSPIVOLATILITYINTERRUPTIONPERINSTRUMENT
EXTUREPLUSSTOCKFOREIGNERMASTER
EXTUREPLUSSTOCKJISUMASTER
EXTUREPLUSSTOCKMARKETOPERATIONSCHEDULEDISCLOSURE
EXTUREPLUSSTOCKMARKETOPERATIONTS
EXTUREPLUSSTOCKMASTER
EXTUREPLUSSTOCKPROGRAMTRADE
EXTUREPLUSSTOCKQUOTE10
EXTUREPLUSSTOCKSECURITIESTRADE
EXTUREPLUSSTOCKTOTALINVESTORINDEX
EXTUREPLUSSTOCKTRADE
EXTUREPLUSSTOCKUPDOWN
EXTUREPLUSTOTALSTOCKINDEX
EXTURESTOCKTOTALBULKTRADE
SECURITIESTRADE
sqlite> .schema SECURITIESTRADE
CREATE TABLE [SECURITIESTRADE] (
        [DATA_CATEGORY] VARCHAR2(2),
        [INFOMARKETCLASS] VARCHAR2(3),
        [STOCKCODE] VARCHAR2(12),
        [A_DESIGNATED_NUMBER_FOR_AN_ISSUE] VARCHAR2(6),
        [MEMBER_NUMBER_1_FOR_ASK] VARCHAR2(5),
        [ASK_TRADING_VOLUME_1] VARCHAR2(12),
        [ASK_TRADING_VALUE_1] VARCHAR2(22),
        [MEMBER_NUMBER_1_FOR_BID] VARCHAR2(5),
        [BID_TRADING_VOLUME_1] VARCHAR2(12),
        [BID_TRADING_VALUE_1] VARCHAR2(22),
        [MEMBER_NUMBER_2_FOR_ASK] VARCHAR2(5),
        [ASK_TRADING_VOLUME_2] VARCHAR2(12),
        [ASK_TRADING_VALUE_2] VARCHAR2(22),
        [MEMBER_NUMBER_2_FOR_BID] VARCHAR2(5),
        [BID_TRADING_VOLUME_2] VARCHAR2(12),
        [BID_TRADING_VALUE_2] VARCHAR2(22),
        [MEMBER_NUMBER_3_FOR_ASK] VARCHAR2(5),
        [ASK_TRADING_VOLUME_3] VARCHAR2(12),
        [ASK_TRADING_VALUE_3] VARCHAR2(22),
        [MEMBER_NUMBER_3_FOR_BID] VARCHAR2(5),
        [BID_TRADING_VOLUME_3] VARCHAR2(12),
        [BID_TRADING_VALUE_3] VARCHAR2(22),
        [MEMBER_NUMBER_4_FOR_ASK] VARCHAR2(5),
        [ASK_TRADING_VOLUME_4] VARCHAR2(12),
        [ASK_TRADING_VALUE_4] VARCHAR2(22),
        [MEMBER_NUMBER_4_FOR_BID] VARCHAR2(5),
        [BID_TRADING_VOLUME_4] VARCHAR2(12),
        [BID_TRADING_VALUE_4] VARCHAR2(22),
        [MEMBER_NUMBER_5_FOR_ASK] VARCHAR2(5),
        [ASK_TRADING_VOLUME_5] VARCHAR2(12),
        [ASK_TRADING_VALUE_5] VARCHAR2(22),
        [MEMBER_NUMBER_5_FOR_BID] VARCHAR2(5),
        [BID_TRADING_VOLUME_5] VARCHAR2(12),
        [BID_TRADING_VALUE_5] VARCHAR2(22),
        [END_KEYWORD] VARCHAR2(1)
);
sqlite> SELECT * FROM EXTUREPLUSSTOCKTRADE WHERE STOCKCODE LIKE '%005930%';
A3|01S|        |G1|40|KR7005930003|000379|090016340616|2|00000000600|00000065900|0000000014|00000065900|00000066000|00000065800|000000740706|000000048808907100.000|1|000000000000000|00000066000|00000065900|NULL
A3|01S|        |G1|40|KR7005930003|000379|090025123774|2|00000000600|00000065900|0000000002|00000065900|00000066000|00000065800|000000760056|000000050084680100.000|1|000000000000000|00000066000|00000065900|NULL
A3|01S|        |G1|40|KR7005930003|000379|090032461321|2|00000000600|00000065900|0000000300|00000065900|00000066000|00000065800|000000776391|000000051161505100.000|1|000000000000000|00000066000|00000065900|NULL
A3|01S|        |G1|40|KR7005930003|000379|090042478696|2|00000000600|00000065900|0000000500|00000065900|00000066000|00000065800|000000848910|000000055939747800.000|2|000000000000000|00000065900|00000065800|NULL
A3|01S|        |G1|40|KR7005930003|000379|090051008868|2|00000000400|00000065700|0000000010|00000065900|00000066000|00000065700|000000906933|000000059757225500.000|1|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090106260640|2|00000000500|00000065800|0000000840|00000065900|00000066000|00000065700|000000917944|000000060480855400.000|2|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090116920780|2|00000000400|00000065700|0000000001|00000065900|00000066000|00000065700|000001023081|000000067388878900.000|1|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090128579478|2|00000000500|00000065800|0000000070|00000065900|00000066000|00000065700|000001092332|000000071941374800.000|1|000000000000000|00000065900|00000065800|NULL
A3|01S|        |G1|40|KR7005930003|000379|090141812818|2|00000000500|00000065800|0000000005|00000065900|00000066000|00000065700|000001104001|000000072709240100.000|1|000000000000000|00000065900|00000065800|NULL
A3|01S|        |G1|40|KR7005930003|000379|090159102608|2|00000000400|00000065700|0000000001|00000065900|00000066000|00000065700|000001215512|000000080046464600.000|1|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090203148634|2|00000000300|00000065600|0000000001|00000065900|00000066000|00000065600|000001311321|000000086341981200.000|1|000000000000000|00000065700|00000065600|NULL
A3|01S|        |G1|40|KR7005930003|000379|090220102040|2|00000000500|00000065800|0000000030|00000065900|00000066000|00000065600|000001355636|000000089254054400.000|2|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090234155211|2|00000000500|00000065800|0000000303|00000065900|00000066000|00000065600|000001378418|000000090751086200.000|2|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090249967609|2|00000000400|00000065700|0000000002|00000065900|00000066000|00000065600|000001460248|000000096127749300.000|1|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090308108824|2|00000000400|00000065700|0000000002|00000065900|00000066000|00000065600|000001467995|000000096636862100.000|1|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090326000851|2|00000000500|00000065800|0000000001|00000065900|00000066000|00000065600|000001473722|000000097013567900.000|2|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090343621379|2|00000000400|00000065700|0000000029|00000065900|00000066000|00000065600|000001480597|000000097465600800.000|1|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090400381512|2|00000000500|00000065800|0000000391|00000065900|00000066000|00000065600|000001487021|000000097888010900.000|2|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090415057289|2|00000000400|00000065700|0000000101|00000065900|00000066000|00000065600|000001494009|000000098347463700.000|1|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090423000680|2|00000000400|00000065700|0000000005|00000065900|00000066000|00000065600|000001576270|000000103752684500.000|1|000000000000000|00000000000|00000000000|NULL
A3|01S|        |G1|40|KR7005930003|000379|090423001705|2|00000000400|00000065700|0000000001|00000065900|00000066000|00000065600|000001580913|000000104057729600.000|1|000000000000000|00000000000|00000000000|NULL
A3|01S|        |G1|40|KR7005930003|000379|090427244354|2|00000000400|00000065700|0000000500|00000065900|00000066000|00000065600|000001647503|000000108432821900.000|1|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090441886146|2|00000000500|00000065800|0000000001|00000065900|00000066000|00000065600|000001764679|000000116143106600.000|1|000000000000000|00000065900|00000065800|NULL
A3|01S|        |G1|40|KR7005930003|000379|090502252835|2|00000000600|00000065900|0000000001|00000065900|00000066000|00000065600|000001811710|000000119237947600.000|2|000000000000000|00000065900|00000065800|NULL
A3|01S|        |G1|40|KR7005930003|000379|090512180351|2|00000000500|00000065800|0000000034|00000065900|00000066000|00000065600|000001899118|000000124989388400.000|1|000000000000000|00000065900|00000065800|NULL
A3|01S|        |G1|40|KR7005930003|000379|090528606862|2|00000000500|00000065800|0000000080|00000065900|00000066000|00000065600|000001997391|000000131455846300.000|1|000000000000000|00000065900|00000065800|NULL
A3|01S|        |G1|40|KR7005930003|000379|090539160461|2|00000000500|00000065800|0000000003|00000065900|00000066000|00000065600|000002082407|000000137049917400.000|1|000000000000000|00000065900|00000065800|NULL
A3|01S|        |G1|40|KR7005930003|000379|090556611200|2|00000000500|00000065800|0000000005|00000065900|00000066000|00000065600|000002085664|000000137264298800.000|1|000000000000000|00000065900|00000065800|NULL
A3|01S|        |G1|40|KR7005930003|000379|090602188802|2|00000000500|00000065800|0000010414|00000065900|00000066000|00000065600|000002205154|000000145126765700.000|2|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090625239029|2|00000000500|00000065800|0000000140|00000065900|00000066000|00000065600|000002211624|000000145552251700.000|2|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090645718364|2|00000000500|00000065800|0000000014|00000065900|00000066000|00000065600|000002214961|000000145771622700.000|2|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090703209584|2|00000000400|00000065700|0000000027|00000065900|00000066000|00000065600|000002221642|000000146210758000.000|1|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090722715549|2|00000000400|00000065700|0000000010|00000065900|00000066000|00000065600|000002227671|000000146607253900.000|1|000000000000000|00000065800|00000065700|NULL
A3|01S|        |G1|40|KR7005930003|000379|090732035363|2|00000000400|00000065700|0000006159|00000065900|00000066000|00000065600|000002295791|000000151083337900.000|1|000000000000000|00000000000|00000000000|NULL
A3|01S|        |G1|40|KR7005930003|000379|090745655162|2|00000000300|00000065600|0000000011|00000065900|00000066000|00000065600|000002343441|000000154213744500.000|1|000000000000000|00000065700|00000065600|NULL
A3|01S|        |G1|40|KR7005930003|000379|090812088869|2|00000000300|00000065600|0000000005|00000065900|00000066000|00000065600|000002352796|000000154827633700.000|1|000000000000000|00000065700|00000065600|NULL
A3|01S|        |G1|40|KR7005930003|000379|090835813027|2|00000000200|00000065500|0000000038|00000065900|00000066000|00000065500|000002484408|000000163461117500.000|1|000000000000000|00000065600|00000065500|NULL
A3|01S|        |G1|40|KR7005930003|000379|090858671239|2|00000000200|00000065500|0000000010|00000065900|00000066000|00000065400|000002637593|000000173494693400.000|1|000000000000000|00000065600|00000065500|NULL
A3|01S|        |G1|40|KR7005930003|000379|090927535167|2|00000000300|00000065600|0000000006|00000065900|00000066000|00000065400|000002666334|000000175377323300.000|2|000000000000000|00000065600|00000065500|NULL
A3|01S|        |G1|40|KR7005930003|000379|091001251410|2|00000000300|00000065600|0000000100|00000065900|00000066000|00000065400|000002671009|000000175683819400.000|2|000000000000000|00000065600|00000065500|NULL
A3|01S|        |G1|40|KR7005930003|000379|091029485349|2|00000000200|00000065500|0000000005|00000065900|00000066000|00000065400|000002682855|000000176459947500.000|1|000000000000000|00000065600|00000065500|NULL
A3|01S|        |G1|40|KR7005930003|000379|091054365941|2|00000000200|00000065500|0000000005|00000065900|00000066000|00000065400|000002694349|000000177212927500.000|1|000000000000000|00000065600|00000065500|NULL
A3|01S|        |G1|40|KR7005930003|000379|091056697133|2|00000000200|00000065500|0000000002|00000065900|00000066000|00000065400|000002766420|000000181933578000.000|1|000000000000000|00000065600|00000065500|NULL
A3|01S|        |G1|40|KR7005930003|000379|091126171772|2|00000000200|00000065500|0000000002|00000065900|00000066000|00000065400|000002820049|000000185446154600.000|2|000000000000000|00000065500|00000065400|NULL
A3|01S|        |G1|40|KR7005930003|000379|091156752631|2|00000000200|00000065500|0000000030|00000065900|00000066000|00000065400|000002850973|000000187471537300.000|1|000000000000000|00000065600|00000065500|NULL
A3|01S|        |G1|40|KR7005930003|000379|091223205147|2|00000000300|00000065600|0000000049|00000065900|00000066000|00000065400|000002933690|000000192897266600.000|1|000000000000000|00000065700|00000065600|NULL
A3|01S|        |G1|40|KR7005930003|000379|091253459756|2|00000000300|00000065600|0000000003|00000065900|00000066000|00000065400|000002993560|000000196824606100.000|2|000000000000000|00000065600|00000065500|NULL
A3|01S|        |G1|40|KR7005930003|000379|091327722198|2|00000000300|00000065600|0000000015|00000065900|00000066000|00000065400|000003000500|000000197279783800.000|2|000000000000000|00000065600|00000065500|NULL
A3|01S|        |G1|40|KR7005930003|000379|091358826380|2|00000000200|00000065500|0000000001|00000065900|00000066000|00000065400|000003086095|000000202886442000.000|1|000000000000000|00000000000|00000000000|NULL
A3|01S|        |G1|40|KR7005930003|000379|091358827630|2|00000000200|00000065500|0000000005|00000065900|00000066000|00000065400|000003106065|000000204194477000.000|1|000000000000000|00000000000|00000000000|NULL
sqlite>


Redis.Tick.Server 1개 + Node 조회 Server(포트별로 다르게)
Redis.Tick.Server 1개 + Node 조회 Server(포트별로 다르게)

1. SQLite.SISE.Tick.Server
2. Node 조회 Server : 포트(3000번) - 웹소켓(8080번)
3. Node 조회 Server : 포트(4000번) - 웹소켓(8090번)


Architecture)

스타일변경)

index_3000.html
0.01MB
index_4000.html
0.04MB
app_4000.js
0.01MB
app_3000.js
0.01MB

 

 

- Select Option에서 선택시에
1. SQLite에 저장되어진, 10단계 호가정보(B601S)의 Top 10을 가져와서 출력한다.
- 해당종목코드를 클릭시에 마스터,호가,체결정보를 보여준다.

- Select Option에서 선택시에
2. SQLite에 저장되어진, 체결정보(A301S)의 Top 10을 가져와서 출력한다.
- 해당종목코드를 클릭시에 마스터,호가,체결정보를 보여준다.

 

app.js
0.01MB
index.html
0.01MB

웹페이지에서 종목코드 호출시에 HTML전체를 서버에서 완성해서 Response 하는 형태

HTML전체
- 마스터
- 10단계 호가
- 시간별 체결

 

app.js
0.01MB
index.html
0.01MB

 

언어마다 스택(Stack)과 힙(Heap) 영역을 다루는 기준은 메모리 관리 방식과 언어 설계 철학에 따라 다릅니다.


1. 스택(Stack) 영역

스택은 함수 호출지역 변수를 위한 메모리를 관리하는 영역입니다.

특징

  • 자동 메모리 관리: 함수가 호출될 때 스택에 메모리가 할당되고, 함수가 종료되면 자동으로 해제됩니다.
  • 고정된 크기: 스택의 크기는 프로그램이 시작될 때 미리 정해지며, 크기를 초과하면 **스택 오버플로우(Stack Overflow)**가 발생합니다.
  • 빠른 접근: 스택은 LIFO(Last In, First Out) 방식으로 작동하며, 메모리 할당과 해제가 매우 빠릅니다.
  • 주요 용도:
    • 함수 호출 시 매개변수와 반환 주소 저장.
    • 함수 내부의 지역 변수 저장.

예시

 
void func() { int a = 10; // 지역 변수 (스택에 저장) int b = 20; // 지역 변수 (스택에 저장) } // 함수 종료 시 a와 b가 자동으로 해제됨

2. 힙(Heap) 영역

힙은 동적 메모리 할당을 위해 사용되는 메모리 영역입니다.

특징

  • 수동 메모리 관리: 개발자가 직접 메모리를 할당하고(malloc, calloc, realloc), 필요 없을 때 해제(free)해야 합니다.
  • 크기와 수명: 힙의 크기는 운영 체제에 의해 제한되며, 동적으로 필요한 만큼 할당할 수 있습니다. 메모리 해제를 명시적으로 하지 않으면 메모리 누수(Memory Leak)가 발생할 수 있습니다.
  • 느린 접근 속도: 스택보다 메모리 접근 속도가 느립니다.
  • 주요 용도: 프로그램 실행 중 메모리 크기를 동적으로 조절해야 하는 경우.

예시

 
#include <stdlib.h> // malloc, free 사용을 위한 헤더 void func() { int* ptr = (int*)malloc(sizeof(int)); // 힙에 메모리 할당 *ptr = 100; // 할당된 메모리에 값 저장 free(ptr); // 메모리 해제 }

스택과 힙의 비교

특성스택(Stack)힙(Heap)
메모리 관리 자동 관리 수동 관리 (malloc/free)
속도 빠름 느림
메모리 크기 고정 크기 가변 크기
사용 용도 지역 변수, 함수 호출 스택 등 동적 메모리 할당
수명 함수 실행 중 명시적으로 해제될 때까지

요약:
스택은 짧고 빠른 메모리 할당에 유리하며 지역 변수 및 함수 호출에 사용됩니다. 힙은 동적 메모리 할당을 위해 사용되며, 관리가 어렵지만 유연성이 높습니다. 프로그램의 목적과 요구사항에 따라 적절히 활용해야 합니다.

C 언어에서 **배열(array)**은 선언 방식과 사용 방법에 따라 스택(Stack) 또는 힙(Heap) 영역 중 하나에 저장될 수 있습니다.


1. 스택 영역에 할당되는 배열

  • 정적 배열 또는 지역 배열로 선언된 경우, 배열은 스택 영역에 저장됩니다.
  • 배열의 크기가 컴파일 시점에 고정되어야 하며, 함수가 종료되면 배열도 자동으로 해제됩니다.

예시

void func() { int arr[10]; // 크기가 고정된 정적 배열 (스택에 할당) arr[0] = 1; // 스택에 있는 배열에 접근 }
  • 배열 arr는 함수 func이 실행되는 동안만 유효합니다. 함수가 종료되면 arr는 사라집니다.

2. 힙 영역에 할당되는 배열

  • 배열의 크기를 동적으로 할당하는 경우, 배열은 힙 영역에 저장됩니다.
  • 동적 메모리 할당 함수(malloc, calloc, realloc)를 사용하며, 사용 후 free를 통해 명시적으로 해제해야 합니다.

예시

 
#include <stdlib.h> void func() { int* arr = (int*)malloc(10 * sizeof(int)); // 힙에 배열 동적 할당 arr[0] = 1; // 힙에 있는 배열에 접근 free(arr); // 메모리 해제 }
  • 배열 arr는 명시적으로 free를 호출하기 전까지 힙에 남아있습니다.

3. 전역 또는 정적 배열

  • 전역 배열이나 static 키워드로 선언된 배열은 **데이터 영역(Data Segment)**에 저장됩니다.
  • 프로그램 시작부터 종료 시까지 메모리에 유지됩니다.

예시

 
int arr[10]; // 전역 배열 (데이터 영역에 저장) void func() { static int arr2[10]; // 정적 배열 (데이터 영역에 저장) }

요약

배열 선언 방식메모리 영역특징
지역 배열 스택 함수 실행 중에만 유효, 자동 해제
동적 배열 동적 크기, 명시적 해제 필요 (free)
전역/정적 배열 데이터 영역 프로그램 종료 시까지 유지

배열이 스택 또는 에 할당되는지는 선언 방식에 따라 다릅니다. 크기가 고정된 지역 배열은 스택에, 동적으로 할당된 배열은 힙에 저장된다고 기억하면 됩니다.

 

C# 언어는 동적 할당이 없는 것이 아니며, **스택(Stack)**과 힙(Heap) 영역을 모두 사용합니다. 하지만 C#은 **가비지 컬렉션(Garbage Collection)**을 통해 메모리를 자동으로 관리하므로, 개발자가 명시적으로 메모리를 할당하거나 해제할 필요가 없습니다.


1. C#에서 스택과 힙의 역할

스택(Stack)

  • 값 타입(Value Type) 데이터가 저장되는 영역입니다.
    • 예: int, float, double, bool, struct 등.
  • 함수 호출 시 지역 변수와 매개변수도 스택에 저장됩니다.
  • 스택에 저장된 데이터는 함수가 종료되면 자동으로 해제됩니다.
  • 고정 크기 데이터를 저장하며, 할당 및 해제가 매우 빠릅니다.

힙(Heap)

  • 참조 타입(Reference Type) 데이터가 저장되는 영역입니다.
    • 예: class, string, array, object 등.
  • 힙에 저장된 객체는 프로그램이 실행되는 동안 가비지 컬렉터가 메모리를 관리합니다.
  • 힙은 가변 크기 데이터를 저장할 수 있으며, 스택보다 접근 속도가 느립니다.

2. C#에서 동적 할당

C#에서도 힙 메모리에서 동적 할당이 가능합니다. 다만, 동적 메모리 관리는 가비지 컬렉션을 통해 이루어지며, 개발자가 직접 해제하지 않아도 됩니다.

예시: 동적 할당

 
class Program { static void Main() { int[] arr = new int[10]; // 힙에 동적 할당된 배열 arr[0] = 1; string str = "Hello, World!"; // 힙에 동적 할당된 문자열 } // 가비지 컬렉터가 필요하지 않은 메모리를 자동 해제 }
  • 배열 arr와 문자열 str은 힙에 저장되며, 가비지 컬렉터가 필요 없어진 시점에 메모리를 자동 해제합니다.

3. 값 타입과 참조 타입의 차이

값 타입 (Value Type)

  • 값 자체가 스택에 저장됩니다.
  • 크기가 작고 고정된 데이터에 적합합니다.

참조 타입 (Reference Type)

  • 힙에 저장된 객체를 참조합니다.
  • 객체가 복잡하거나 크기가 가변적인 경우 적합합니다.
 
class Program { struct MyStruct { public int x; } class MyClass { public int x; } static void Main() { MyStruct structObj = new MyStruct { x = 10 }; // 스택에 저장 MyClass classObj = new MyClass { x = 10 }; // 힙에 저장 } }
  • structObj는 값 타입이므로 스택에 저장됩니다.
  • classObj는 참조 타입이므로 힙에 저장되고, 스택에는 힙 객체의 참조만 저장됩니다.

4. 가비지 컬렉션의 역할

C#에서는 동적 할당된 메모리(힙 메모리)는 **가비지 컬렉션(Garbage Collection)**이 자동으로 관리합니다.

  • 메모리를 명시적으로 해제(free)할 필요가 없습니다.
  • 객체가 더 이상 사용되지 않으면 가비지 컬렉터가 힙에서 메모리를 해제합니다.

결론

C#은 스택만 사용하는 것이 아닙니다.

  • 값 타입은 주로 스택에 저장되고, 참조 타입은 힙에 저장됩니다.
  • 동적 메모리 할당은 힙에서 이루어지며, 가비지 컬렉션이 자동으로 관리합니다.
    따라서 개발자는 스택과 힙을 직접 관리할 필요 없이, 언어의 메모리 관리 기능을 믿고 사용할 수 있습니다.

 

언어마다 **스택(Stack)**과 힙(Heap) 영역을 다루는 기준은 메모리 관리 방식언어 설계 철학에 따라 다릅니다. 핵심적인 차이점은 **값의 종류(값 타입 vs 참조 타입)**와 **메모리 관리 방식(자동 관리 vs 수동 관리)**입니다. 아래는 이를 기준으로 한 설명입니다.


1. 스택과 힙을 다루는 기준

(1) 데이터의 성격

  • 값 타입 (Value Type):
    • 크기가 고정되고 비교적 작은 데이터를 저장합니다.
    • 주로 스택에 저장됩니다.
    • 예: 기본 데이터 타입(정수, 실수, Boolean 등), 구조체 등.
    • 언어 예시: C, C++, C#, Java (기본 타입).
  • 참조 타입 (Reference Type):
    • 크기가 가변적이거나 복잡한 데이터를 저장합니다.
    • 데이터는 에 저장되고, 스택에는 해당 데이터를 가리키는 참조만 저장됩니다.
    • 예: 객체, 배열, 문자열 등.
    • 언어 예시: C#, Java, Python.

(2) 메모리 관리 방식

  • 자동 메모리 관리 (가비지 컬렉션):
    • 메모리 할당과 해제를 런타임에 자동으로 처리합니다.
    • 주로 을 적극적으로 활용하며, 필요 없어진 메모리는 가비지 컬렉터가 해제합니다.
    • 언어 예시: C#, Java, Python, JavaScript.
  • 수동 메모리 관리:
    • 개발자가 직접 메모리를 할당(malloc)하고 해제(free)합니다.
    • 스택은 자동으로 관리되지만, 은 명시적으로 관리해야 합니다.
    • 언어 예시: C, C++.

(3) 성능과 용도

  • 스택:
    • 빠른 속도, 고정된 크기의 데이터에 적합.
    • 지역 변수, 함수 호출 스택, 값 타입 데이터 등에 사용.
  • 힙:
    • 느리지만 유연한 크기의 데이터에 적합.
    • 동적 메모리 할당, 참조 타입 데이터 등에 사용.

2. 언어별 스택과 힙 사용 기준

C 언어

  • 스택: 지역 변수, 함수 매개변수 등 고정 크기 데이터.
  • 힙: 동적 할당(malloc, calloc, realloc)된 데이터.
  • 메모리 관리: 스택은 자동, 힙은 수동(free 필요).

C++

  • 스택: 지역 변수, 기본 타입 데이터.
  • 힙: 동적 할당 (new, delete).
  • 메모리 관리: 스택은 자동, 힙은 수동 또는 스마트 포인터로 자동 관리 가능.

Java

  • 스택: 기본 데이터 타입(int, float 등), 참조 변수의 주소.
  • 힙: 객체(new로 생성), 배열, 문자열.
  • 메모리 관리: 가비지 컬렉터가 힙 메모리를 자동 관리.

C#

  • 스택: 값 타입 데이터(int, struct 등), 참조 변수의 주소.
  • 힙: 참조 타입 데이터(클래스, 배열, 문자열).
  • 메모리 관리: 가비지 컬렉터로 힙 메모리를 자동 관리.

Python

  • 스택: 함수 호출 스택.
  • 힙: 모든 객체(정수, 문자열, 리스트 등).
  • 메모리 관리: 가비지 컬렉터로 힙 메모리를 자동 관리.

JavaScript

  • 스택: 원시 타입 데이터(Number, String, Boolean 등).
  • 힙: 객체(Object, Array, Function 등).
  • 메모리 관리: 가비지 컬렉터로 힙 메모리를 자동 관리.

3. 스택과 힙 사용에 영향을 주는 요소

  1. 언어의 메모리 관리 철학:
    • C, C++: 개발자가 세밀하게 관리.
    • Java, C#, Python: 자동 메모리 관리(가비지 컬렉터).
  2. 값의 생명 주기:
    • 짧은 생명 주기의 데이터 → 스택.
    • 긴 생명 주기 또는 크기가 가변적인 데이터 → 힙.
  3. 데이터 크기와 유연성:
    • 고정 크기 → 스택.
    • 가변 크기 또는 동적 크기 → 힙.

결론

언어마다 스택의 사용 기준은 데이터의 성격(값 타입 vs 참조 타입)과 메모리 관리 방식(수동 vs 자동)에 따라 결정됩니다. **저수준 언어(C, C++)**에서는 개발자가 직접 메모리를 관리해야 하지만, **고수준 언어(Java, Python)**에서는 자동 관리 기능이 강화되어 사용자가 스택과 힙의 구분을 신경 쓰지 않아도 되는 구조로 설계됩니다.

증권웹(조회 & 실시간) 서버 + 클라이언트
- 마스터
- 호가
- 체결등


>Simple Architecture

>삼성전자/KR7005930003/005930/ 모두 검색키로 사용가능

app.js
0.01MB
index.html
0.04MB

컴퓨터 그래픽스에서 4x4 행렬은 3D 변환(translation, rotation, scaling 등)을 표현하기 위한 중요한 수학적 도구입니다. 이 행렬의 구조는 일반적으로 **동차 좌표(homogeneous coordinates)**를 사용하는 3D 그래픽스에서 사용됩니다. 다음은 4x4 행렬의 구조와 각 요소의 역할에 대한 설명입니다:


4x4 행렬의 기본 구조

M=[m11m12m13m14m21m22m23m24m31m32m33m34m41m42m43m44]\mathbf{M} = \begin{bmatrix} m_{11} & m_{12} & m_{13} & m_{14} \\ m_{21} & m_{22} & m_{23} & m_{24} \\ m_{31} & m_{32} & m_{33} & m_{34} \\ m_{41} & m_{42} & m_{43} & m_{44} \end{bmatrix}

  • 각 요소는 3D 공간의 변환을 정의하는 역할을 합니다.
  • 일반적으로 좌측 상단 3x3 부분은 **회전(rotation)**과 **스케일링(scaling)**을 담당하고, 마지막 열(translation vector)은 **이동(translation)**을 담당합니다.



각 부분의 역할

  1. 회전 및 스케일링 (3x3 부분)
    좌측 상단의 3×33 \times 3 부분 행렬은 객체의 회전 및 크기 조정을 담당합니다:[m11m12m13m21m22m23m31m32m33]\begin{bmatrix} m_{11} & m_{12} & m_{13} \\ m_{21} & m_{22} & m_{23} \\ m_{31} & m_{32} & m_{33} \end{bmatrix}
    • 이 부분은 단위 행렬(identity matrix)이면 변환 없이 유지됩니다.
    • 각 요소는 회전 축과 스케일링 계수를 정의합니다.


  2. 이동 (Translation vector)
    네 번째 열(m14,m24,m34m_{14}, m_{24}, m_{34})은 위치 이동(translation)을 정의합니다:[m14m24m34]\begin{bmatrix} m_{14} \\ m_{24} \\ m_{34} \end{bmatrix}
    • 예를 들어, xx, yy, zz 방향으로 이동하려면 이 값들을 해당 값으로 설정합니다.
  3. 투영 (Projection)
    마지막 행 (m41,m42,m43,m44m_{41}, m_{42}, m_{43}, m_{44})은 일반적으로 투영 변환에 사용됩니다.
    • 3D 공간을 2D 화면에 투영할 때 원근감을 표현하는 역할을 합니다.
    • 일반적인 경우, m41=m42=m43=0m_{41} = m_{42} = m_{43} = 0, m44=1m_{44} = 1로 설정됩니다(비투영 변환 시).




주요 변환 예시

  1. 이동 (Translation):T=[100tx010ty001tz0001]\mathbf{T} = \begin{bmatrix} 1 & 0 & 0 & t_x \\ 0 & 1 & 0 & t_y \\ 0 & 0 & 1 & t_z \\ 0 & 0 & 0 & 1 \end{bmatrix}
    • tx,ty,tzt_x, t_y, t_z는 각각 xx, yy, zz 방향으로의 이동 거리.
  2. 회전 (Rotation):
    • zz-축 회전: Rz=[cos⁡θ−sin⁡θ00sin⁡θcos⁡θ0000100001]\mathbf{R_z} = \begin{bmatrix} \cos\theta & -\sin\theta & 0 & 0 \\ \sin\theta & \cos\theta & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
  3. 스케일링 (Scaling):S=[sx0000sy0000sz00001]\mathbf{S} = \begin{bmatrix} s_x & 0 & 0 & 0 \\ 0 & s_y & 0 & 0 \\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
    • sx,sy,szs_x, s_y, s_z는 각각 xx, yy, zz 방향의 스케일 팩터.
  4. 투영 (Projection):
    • 원근 투영 행렬은 m41,m42,m43m_{41}, m_{42}, m_{43} 값을 설정하여 원근 효과를 적용합니다.



동차 좌표(homogeneous coordinates)의 역할

3D 점 (x,y,z)(x, y, z)를 동차 좌표계에서는 (x,y,z,1)(x, y, z, 1)로 확장합니다.
이렇게 하면 행렬 계산으로 이동, 회전, 스케일링을 하나의 연산으로 통합할 수 있습니다.

활용

  • 3D 그래픽스 엔진(OpenGL, DirectX 등)은 4x4 행렬을 사용해 변환을 수행합니다.
  • 여러 변환을 하나의 행렬로 병합하여 효율적으로 계산할 수 있습니다.

Windows에서 Redis 서버를 여러 개 설치하여 각기 다른 포트를 사용하는 방법은 다음과 같습니다.

  1. Redis 설치 파일 복사:
    • Redis 설치 디렉토리(예: C:\Redis)를 여러 개 복사합니다.
    • 각 복사본은 다른 인스턴스를 위해 사용됩니다. 예를 들어 C:\Redis\Redis1, C:\Redis\Redis2와 같은 식으로 만듭니다.
  2. Redis 설정 파일 수정:
    • 각 디렉토리에 있는 redis.windows.conf 파일을 엽니다.
    • port 설정을 변경하여 각 인스턴스가 다른 포트를 사용하도록 설정합니다. 예를 들어, Redis1 인스턴스의 redis.windows.conf 파일에서 port 6379를 port 6380으로 변경합니다.
  3. 서버 실행:
    • 각 디렉토리에서 Redis 서버를 실행합니다. 예를 들어, 명령 프롬프트를 열고 다음 명령을 실행합니다. 
    • bash
      코드 복사
      cd C:\Redis\Redis1 redis-server.exe redis.windows.conf
    • 각 인스턴스에서 다른 포트 번호로 실행이 되며, 다른 인스턴스(Redis2 등)도 동일한 방법으로 다른 포트에서 실행하면 됩니다.
  4. 서비스로 등록(선택 사항):
    • 각 Redis 인스턴스를 Windows 서비스로 등록하고 싶다면 redis-server.exe에 --service-install 옵션을 사용해 서비스로 등록할 수 있습니다.
    • 각 서비스에는 고유한 이름을 지정하고 각 설정 파일을 참조하도록 설정해야 합니다.
      bash
      코드 복사
      redis-server --service-install redis.windows.conf --service-name Redis6380
  5. 클라이언트 연결:
    • 이제 Redis 클라이언트를 통해 각기 다른 포트(예: 6379, 6380, 6381 등)로 접속하여 원하는 인스턴스를 사용할 수 있습니다.

이 과정을 통해 Redis 서버를 Windows 환경에서 여러 개의 포트로 실행할 수 있습니다.

 

Node.Server Port 변경 Redis Connect

// 포트와 호스트를 지정하여 Redis 클라이언트 생성
        redisClient = createClient({
            url: 'redis://127.0.0.1:6380' // 새로운 포트 6380으로 연결
        });

besideredisClient = createClient({
            socket: {
                host: '127.0.0.1', // Redis 서버 호스트
                port: 6380 // 변경된 포트 번호
            }
        });

Agent 데이타 수집을 통한
Application Monitoring Service 개요)

1. Agent 데이타 수집

1.1.CPU(Central Processing Unit)
    % Processor Time: CPU 사용률의 총합을 나타내며, 특정 프로세서의 사용률을 모니터링하는 데 유용합니다.
    Processor Queue Length: 실행 대기 중인 프로세스 또는 스레드 수를 나타냅니다. 이 값이 지속적으로 높으면 CPU 병목 가능성이 있습니다.
1.2. 메모리 (Memory)
    Available MBytes: 사용 가능한 메모리 용량으로, 메모리 부족 상태를 파악하는 데 중요합니다.
    Pages/sec: 메모리 페이지가 디스크에 읽기/쓰기된 횟수입니다. 이 값이 높다면 메모리 부족을 나타낼 수 있습니다.
    Cache Bytes: 시스템의 캐시 메모리 크기를 나타냅니다. 일반적으로 캐시 메모리가 많을수록 시스템 성능이 향상됩니다.
1.3. 디스크 (Disk)
    % Disk Time: 디스크가 사용 중인 비율을 보여줍니다. 디스크가 과도하게 사용 중일 경우 I/O 병목 현상이 발생할 수 있습니다.
    Disk Bytes/sec: 초당 디스크에서 읽기 및 쓰기된 바이트 수를 측정합니다. 디스크 성능과 처리량을 파악하는 데 유용합니다.
    Avg. Disk Queue Length: 디스크 요청 큐의 평균 길이입니다. 이 값이 높으면 디스크가 과도하게 사용 중일 가능성이 있습니다.
1.4. 네트워크 (Network)
    Bytes Total/sec: 네트워크 인터페이스를 통해 초당 전송된 총 바이트 수입니다. 네트워크 사용률을 파악하는 데 유용합니다.
    Packets/sec: 초당 전송된 패킷 수로, 네트워크 연결 상태를 확인하는 데 유용합니다.
    Output Queue Length: 네트워크 인터페이스 대기열의 길이로, 이 값이 높으면 네트워크 병목이 발생할 가능성이 있습니다.
1.5. 시스템 (System)
    System Up Time: 시스템이 부팅된 후 경과한 시간입니다.
    Context Switches/sec: 초당 발생하는 문맥 교환 수로, 많은 문맥 교환은 시스템 부하가 크다는 신호일 수 있습니다.
    Processes: 현재 실행 중인 프로세스 수로, 과도한 프로세스 실행이 성능 저하를 유발할 수 있습니다.
1.6. 특정 프로세스 (Process-Specific)
    특정 애플리케이션의 성능을 모니터링할 때 유용합니다.
    % Processor Time (for a specific process): 특정 프로세스의 CPU 사용률을 나타냅니다.
    Private Bytes: 특정 프로세스가 사용하는 비공유 메모리 크기입니다.
    Handle Count: 특정 프로세스가 사용하는 핸들 수를 나타내며, 핸들 누수 여부를 확인할 수 있습니다.
1.7. GPU (Graphics Processing Unit) -(Windows 10 이상)
    GPU 사용량은 그래픽이 많이 사용되는 애플리케이션이나 게임의 성능을 모니터링할 때 유용합니다.
    GPU Engine Usage: 각 GPU 엔진의 사용량을 보여줍니다.
    Dedicated/Shared GPU Memory Usage: GPU에서 사용하는 전용 및 공유 메모리 양입니다.

2. Redis를 통한 Application.Monitoring.Service.DB에 저장

3. Node.js를 통한 WebBrowser와 데이타 송수신을 통한 표시

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가 제대로 작동하는지 확인할 수 있습니다.

- c#을 이용한 OpenGL 큐빅 control(by.Mouse)

dotnet new console -o openNM

cd openNM

\openNM>dotnet add package OpenTK --version 3.3.3
\openNM>dotnet add package Microsoft.Win32.SystemEvents
\openNM>dotnet add package System.Drawing.Common

.NET Core 또는 .NET 5 이상의 버전에서는 패키지 파일이 프로젝트 폴더 내에 다운로드되지 않고, 일반적으로 글로벌 NuGet 패키지 캐시(기본적으로 %USERPROFILE%\.nuget\packages 경로)에 저장됩니다.

C:\Program Files (x86)>cd %USERPROFILE%

C:\Users\B210145_BK>wsl
root@DESKTOP-QNNUCER:/mnt/c/Users/B210145_BK# find ./ -name "Open*.dll"
./.nuget/packages/opentk/3.3.3/lib/net20/OpenTK.dll
./.nuget/packages/opentk.audio.openal/4.8.2/lib/netcoreapp3.1/OpenTK.Audio.OpenAL.dll
./.nuget/packages/opentk.compute/4.8.2/lib/netcoreapp3.1/OpenTK.Compute.dll
./.nuget/packages/opentk.core/4.8.2/lib/netstandard2.1/OpenTK.Core.dll
./.nuget/packages/opentk.glcontrol/4.0.1/lib/netcoreapp3.1/OpenTK.GLControl.dll
./.nuget/packages/opentk.graphics/4.8.2/lib/netcoreapp3.1/OpenTK.Graphics.dll
./.nuget/packages/opentk.graphics/4.8.2/lib/netstandard2.1/OpenTK.Graphics.dll
./.nuget/packages/opentk.input/4.8.2/lib/netstandard2.0/OpenTK.Input.dll
./.nuget/packages/opentk.mathematics/4.8.2/lib/netcoreapp3.1/OpenTK.Mathematics.dll
./.nuget/packages/opentk.mathematics/4.8.2/lib/netstandard2.1/OpenTK.Mathematics.dll
./.nuget/packages/opentk.windowing.common/4.8.2/lib/netcoreapp3.1/OpenTK.Windowing.Common.dll
./.nuget/packages/opentk.windowing.common/4.8.2/lib/netstandard2.1/OpenTK.Windowing.Common.dll
./.nuget/packages/opentk.windowing.desktop/4.8.2/lib/netcoreapp3.1/OpenTK.Windowing.Desktop.dll
./.nuget/packages/opentk.windowing.graphicslibraryframework/4.8.2/lib/netcoreapp3.1/OpenTK.Windowing.GraphicsLibraryFramework.dll
root@DESKTOP-QNNUCER:/mnt/c/Users/B210145_BK#

dotnet build
dotnet run


Program.cs
0.00MB
Program.cs
0.00MB

 

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

 

1) 기초자산 Kospi200기준 선물,옵션추가

app.js
0.01MB
index.html
0.12MB

Node.js를 통한 Redis 실시간 데이타+조회(+로그인)
- Redis Search & RealTime Push(Exture3.0 Stock)
- Kse 추가
- Kosdaq 추가
- Elw,Etn,Etf 추가

1. 첫화면에서 로그인한다.
2. 로그인정보는 현재 클라이언트의 정보를 서버에 보낸다.
3. 서버에 정보를 보내면서, 동시에 Redis에 접속해서, 실시간데이타를 받아로도록 한다.
// Function to fetch data from Redis list using BLPOP (blocking pop)
async function fetchDataFromRedis() {
console.error('fetchDataFromRedis entered:[' + redisPublicKey + ']');

    try {
        const result = await redisClient.blPop(`QCS:${redisPublicKey}`, 0); // redisPublicKey 사용
        if (result) {
            const data = JSON.parse(result.element);
            return Array.isArray(data) ? data : [data]; // Ensure data is an array
        }
    } catch (err) {
        console.error('Error fetching data from Redis:', err);
    }
    return [];
}

// Polling Redis every second and sending data to WebSocket clients
setInterval(async () => {
    if (redisClient && redisPublicKey && redisPublicKey.length >= 4) { // Redis 클라이언트 연결 여부 체크
        const processedData = await fetchDataFromRedis();
        console.log('Sending data:', processedData); // Log the data being sent
        connectedClients.forEach((client) => {
            if (client.readyState === client.OPEN) {
                client.send(JSON.stringify(processedData));
            }
        });
    }
}, 1000); // 1 second interval
// Redis Public Key 설정 엔드포인트
app.post('/set-public-key', async (req, res) => {
    const { publicKey } = req.body;

    if (publicKey) {
        redisPublicKey = publicKey; // publicKey 업데이트
        console.log('Redis Public Key updated to:', redisPublicKey);
        await connectToRedis(); // Redis에 연결 시도(로그인시에)
        res.json({ message: 'Public Key updated successfully.' });
    } else {
        res.status(400).json({ error: 'Public Key is required.' });
    }
});


로그인후에 Node.js에서 Redis에 접속을 시도한다.)

- NODE.SERVER
- REDIS.TICKER.SERVER
- 실시간 PUSH & 조회

app.js
0.01MB
index.html
0.10MB

외부VPN을 통한 NODE.SERVER 조회

1) HOME.VPN.라우팅.설정(SK BROADBAND)

2) HOME.UBUNTU(LINUX) DESKTOP.CONTROL
2.1) REDIS.TICK.SERVER - SQLite조회해서, REDIS에 전송
2.2) REDIS에서 데이타 POP후에, WEB.BROWSER에 WEB.SOCKET으로 전송(REAL.TIME 데이타등)


3) 외부에서.VPN접속.설정후에.브라우져를 통한.조회

비고) WiseGuard VPN에 대해서


WireGuard VPN에서 PrivateKey와 PublicKey는 VPN 연결을 보안하고 암호화하는 데 중요한 역할을 합니다. 
이 두 키는 비대칭 암호화 방식을 따르며, 각 역할은 다음과 같습니다.

1. PrivateKey (개인 키)
PrivateKey는 각 클라이언트 또는 서버가 비밀로 유지해야 하는 개인 키입니다. 
이 키는 외부에 노출되지 않아야 하며, 오직 해당 장치에서만 사용됩니다.
암호화와 서명: 이 키를 사용하여 데이터를 암호화하거나 서명할 수 있습니다. 
PrivateKey로 암호화된 데이터는 해당 PrivateKey와 짝을 이루는 **PublicKey(공개 키)**로만 복호화할 수 있습니다.
WireGuard 설정: WireGuard 설정 파일에서 PrivateKey 항목에 개인 키가 포함됩니다. 이 키는 VPN 터널을 설정하는 데 사용됩니다.

2. PublicKey (공개 키)
PublicKey는 각 장치의 공개된 키로, 다른 장치들이 이 키를 사용해 해당 장치로 안전하게 통신할 수 있도록 합니다.
공유: PublicKey는 클라이언트와 서버 간에 공유됩니다. 
즉, 연결하려는 다른 장치에 이 공개 키를 제공하여 암호화된 데이터를 주고받을 수 있습니다.

WireGuard 설정: WireGuard 설정 파일에서 PublicKey는 각 피어(peer, 즉 통신 상대)의 공개 키를 나타냅니다. 이는 해당 피어와의 통신을 암호화하고 보장하는 역할을 합니다.

동작 방식

키 생성: 각 장치는 고유한 PrivateKey와 PublicKey 쌍을 생성합니다.

PublicKey 교환: 클라이언트와 서버는 서로의 PublicKey를 공유하여 암호화된 통신을 설정합니다.

데이터 암호화: 클라이언트는 서버의 PublicKey를 사용해 데이터를 암호화하고, 서버는 자신의 PrivateKey를 사용해 이 데이터를 복호화합니다. 
반대로 서버도 클라이언트의 PublicKey로 데이터를 암호화하고 클라이언트는 자신의 PrivateKey로 복호화합니다.
이렇게 PublicKey와 PrivateKey는 WireGuard VPN에서 데이터의 기밀성, 무결성 및 인증을 보장하는 핵심 요소로 작동합니다.


아래 명령을 사용하여 모든 .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 {} \;

 

증권정보.홈페이지(Infra.Introduction)
1) 조회
2) 실시간

Ubuntu에서 Node.js를 설치하려면 다음 단계를 따르세요:

패키지 목록 업데이트:

sudo apt update
Node.js 설치: Node.js는 여러 방법으로 설치할 수 있지만, 가장 간편한 방법은 NodeSource PPA를 사용하는 것입니다. 다음 명령어를 실행하여 Node.js를 설치합니다.

curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
위 명령어에서 setup_18.x는 Node.js의 최신 LTS 버전을 설치합니다. 다른 버전이 필요하다면, 해당 버전의 번호로 변경하세요.

설치 확인: 설치가 완료되면 Node.js와 npm(노드 패키지 관리자)이 제대로 설치되었는지 확인합니다.

node -v
npm -v
이제 Node.js와 npm이 정상적으로 설치되었습니다. 필요한 패키지를 설치하거나 프로젝트를 시작할 수 있습니다!

npm install express
npm install @redis/client
npm install ws

sinfo@sinfo:~$ netstat -an | grep 3000
tcp6       0      0 :::3000                 :::*                    LISTEN
sinfo@sinfo:~$

sudo ufw status
sudo ufw allow 3000
sudo ufw status
sudo ufw enable

sudo ufw allow 8080
sudo ufw status
sudo ufw enable


app.js 수정부분)

app.listen(port, '0.0.0.0', () => {
    console.log(`HTTP Server is running at http://0.0.0.0:${port}`);
});
const wss = new WebSocketServer({ port: 8080, host: '0.0.0.0' });
위의 수정으로 WebSocketServer도 모든 인터페이스에서 접속을 허용하게 됩니다.


index.html 수정부분)

<script>
    // ... (이전 코드)

    const ws = new WebSocket('ws://192.168.45.54:8080'); // 수정된 부분

    // ... (이후 코드)
</script>
이제 수정한 코드를 사용하여 index.html을 테스트해 보세요. 추가적인 질문이 있으면 언제든지 말씀해 주세요!


 

app.js
0.00MB
index.html
0.05MB

NODE.JS.SERVER를 이용한 조회/실시간 통합(4)

1. NODE.JS.SERVER를 이용한 SQLite조회 (3)버젼
2. NODE.JS.SERVER를 이용한 실시간데이타 반영 (2)버젼
3. NODE.JS.SERVER를 이용한 조회/실시간 통합(4)

1과 2를 3으로 통합할수 있는 핵심은, 1번의 주고받는 REDIS.QUEUE.NAME과
2번의 주고받는 REDIS.QUEUE.NAME의 PREFIX를 틀리게 운용하면 된다.

조회시에는
SEQRCHSEND:클라이언트고유키, SEQRCHRECV:클라이언트고유키
실시간에는
SEND:클라이언트고유키, RECV:클라이언트고유키

물론 REDIS에 데이타를 제공하는 REDIS.TICKER.SERVER또한 한쌍의 주고받는 부분의 로직이 추가되어야 한다.

개략적인구조)


여러개의.브라우져에서.각각.조회가.가능하며, 실시간 PUSH는 모든 브라우져에 적용된다.)


PUSH데이타.실시간.데이타화면)

버튼을 통해서 SQLite의 데이타를 가져오는 화면)

app.js
0.00MB
index.html
0.05MB

+ Recent posts