728x90

학습목표

  1. VMware에 Rocky Linux 8.10 설치
  2. Oracle 19c 설치
  3. 데이터베이스 실행 및 사용자, 테이블 생성, 데이터 생성
  4. 테이블 생성, 데이터 생성(PL/SQL) SQL Script

 

1. VMware에 Rocky Linux 8.10 설치 Rocky Linux 설치

  • Rocky Linux : Rocky Linux는 RHEL(Red Hat Enterprise Linux)과 100% 호환되는 무료 오픈소스 리눅스 배포판, CentOS의 대체재로 탄생
  • https://dl.rockylinux.org/pub/rocky/8/isos/x86_64/ 들어가서 iso 다운로드
    • ISO 파일은 CD나 DVD의 이미지 파일로, 국제 표준화 기구(ISO)가 제정한 광학 디스크의 압축 파일. "이미지 파일”이라고도 불림. 마치 디스크를 사진처럼 찍어서 파일로 만든 느낌

  • VMware 세팅

 

네트워크 유형 설명 외부 네트워크 연결 가능 여부
Bridged (VMnet0) 게스트 OS가 실제 물리 네트워크와 직접 연결됨 (공유기에서 IP 할당) ✅ 가능
NAT (VMnet8) VMware가 가상 게이트웨이 역할을 하며, 게스트 OS가 NAT을 통해 인터넷 연결 가능 ✅ 가능
Host-Only (VMnet1) 게스트 OS와 호스트 OS 간에만 통신 가능, 외부 네트워크 연결 불가 ❌ 불가능
Custom 사용자가 직접 네트워크 환경을 설정 가능 설정에 따라 다름

 

 

 

2. Oracle 19c 설치

  • oracle 19c rpm 다운로드(yum 안돼서 직접 ISO 파일 다운 or SSH로 로컬 PC에서 VMware로 파일전송)

 

  • oracle-database-preinstall-19c 설치
sudo dnf install -y oracle-database-preinstall-19c
# sudo : superuser do (관리자 권한으로 실행)
# dnf : Dandified YUM, RPM 기반 리눅스 배포판을 위한 패키지 관리도구
# install -y dnf가 설치를 시작하기 전에 물어보면 -y를 넣으면 자동으로 yes
  • Oracle 19c가 동작하는 데 필요한 라이브러리 및 유틸리티 패키지들을 자동으로 설치(glibc, binutils, gcc, libaio, make 등)
  • Oracle이 원활하게 실행되도록 공유 메모리, 파일 핸들 수, 네트워크 설정 등을 자동으로 변경(설정 파일: /etc/sysctl.conf)
    • kernel.shmmax = 4398046511104 # 공유 메모리 최대 크기
    • kernel.shmall = 1073741824 # 공유 메모리 페이지 수
    • fs.file-max = 6815744 # 최대 파일 핸들 개수

 

  • 오라클 설치 전
mkdir -p /u01/app/oracle # 오라클 데이터베이스가 설치될 기본 디렉토리
chown -R oracle:oinstall /u01/app/oracle # 소유자를 oracle로 변경
chmod -R 775 /u01/app/oracle # 적절한 권한을 부여

 

  • 오라클 사용자로 전환 후 설치 작업 ( su - oracle )
  • 사용자 프로파일 수정 vi /home/oracle/.bash_profile

  • ORACLE_BASE : 오라클 기본 디렉토리
  • ORACLE_HOME : 오라클 프로그램이 설치된 디렉토리
  • ORACLE_SID : 데이터베이스 인스턴스 이름
  • PATH : 오라클 실행 파일을 PATH에 추가
  • NLS_LANG : 오라클 메시지 시스템 설정이 한국어라 깨짐 방지로 설정 필요

 

  • 이후 바뀐 설정 적용 명령어 : source /home/oracle/.bash_profile

 

  • which dbca 명령어로 dbca 확인 후 실행
    • dbca (Database Configuration Assistant) : 데이터베이스를 자동으로 생성하는 유틸리티
dbca -silent -createDatabase \
    -gdbName orcl \
    -sid orcl \
    -templateName "General_Purpose.dbc" \
    -characterSet AL32UTF8 \
    -memoryPercentage 40 \
    -emConfiguration NONE \
    -sysPassword ora951753 \
    -systemPassword ora951753 \
    -createAsContainerDatabase true

 

옵션 설명
-silent 무인 설치 (GUI 없이 자동 실행)
-createDatabase 새 데이터베이스 생성
-gdbName orcl 전역 데이터베이스 이름 설정
-sid orcl 인스턴스 이름 (SID) 설정
-templateName "General_Purpose.dbc" 템플릿 지정 (OLTP용)
-characterSet AL32UTF8 문자셋 UTF-8 설정 (다국어 지원)
-memoryPercentage 40 서버 메모리의 40%를 Oracle에 할당
-emConfiguration NONE Enterprise Manager 설정 안 함
-sysPassword ora951753 SYS 관리자 비밀번호 설정
-systemPassword ora951753 SYSTEM 관리자 비밀번호 설정
-createAsContainerDatabase true CDB(컨테이너 DB) 활성화

 

  • General_Purpose.dbc : database options, storage attributes, init.ora 설정값이나 파라미터를 참고할 수 있는 기본 템플릿 파일
728x90

3. 데이터베이스 실행 및 사용자, 테이블 생성, 데이터 생성

  • 리스너 실행
netca # (Network Configuration Assistant)는 Oracle Listener를 설정하는 유틸리티
lsnrctl start # 리스너 start
lsnrctl status # 리스너 상태 확인

 

-- sqlplus / as sysdba 로 sqlplus 접속 후
SELECT NAME, OPEN_MODE FROM V$DATABASE; -- 로 실행중인 DATABASE 확인

CREATE USER C##ERP IDENTIFIED BY 1234 DEFAULT TABLESPACE USERS;
GRANT CONNECT, RESOURCE TO C##ERP;
ALTER USER C##ERP QUOTA UNLIMITED ON USERS;
  • 오라클 12c부터는 공통계정앞에 c##을 붙이도록 네이밍 규칙이 바뀜. C## 가 붙는 이유는 12c 버전부터 등장하는 CDB, PDB 개념 때문
  • nano 로 테이블, 데이터생성을 위한 SQL 스크립트 파일 생성 (글 맨 아래 해당 스크립트 파일별로 적어놓음)
  • sqlplus를 해당 폴더에서 실행 후 @파일명 으로 스크립트 실행

EXEC DBMS_STATS.GATHER_SCHEMA_STATS('C##ERP'); -- 해당 유저의 테이블 통계 업데이트

-- 생성된 테이블 row 수 확인
SELECT table_name, num_rows FROM user_tables WHERE num_rows IS NOT NULL;

 

 

4. 테이블 생성, 데이터 생성(PL/SQL) SQL Script

  • 테이블 생성 스크립트
/***************************************
****************CUST_COM****************
****************************************/

 DROP TABLE "CUST_COM";

CREATE TABLE "CUST_COM" (
	"CUST_ID"	VARCHAR2(10)		NOT NULL,
	"CUST_GRP"	CHAR(4)		NOT NULL,
	"NAME"	VARCHAR2(30)		NOT NULL,
	"CNTR_CODE"	CHAR(4)		NULL,
	"CITY_CODE"	CHAR(4)		NULL,
	"POST_CODE"	CHAR(5)		NULL,
	"ADDR1"	VARCHAR2(100)		NULL,
	"ADDR2"	VARCHAR2(100)		NULL,
	"REPR_NAME"	VARCHAR(30)		NULL,
	"BIZ_TYPE"	VARCHAR(30)		NULL,
	"IDST_TYPE"	VARCHAR(20)		NULL,
	"REMK"	VARCHAR2(200)		NULL,
	"STAT"	CHAR(1)		NULL,
	"DEL_FLAG"	CHAR(1)		NULL,
	"CREA_BY"	VARCHAR(20)		NULL,
	"CREA_DATE"	DATE		NULL,
	"UPDT_BY"	VARCHAR(20)		NULL,
	"UPDT_DATE"	DATE		NULL
);

COMMENT ON COLUMN "CUST_COM"."CUST_ID" IS '고객아이디';

COMMENT ON COLUMN "CUST_COM"."CUST_GRP" IS '고객그룹';

COMMENT ON COLUMN "CUST_COM"."NAME" IS '이름';

COMMENT ON COLUMN "CUST_COM"."CNTR_CODE" IS '국가코드';

COMMENT ON COLUMN "CUST_COM"."CITY_CODE" IS '도시코드';

COMMENT ON COLUMN "CUST_COM"."POST_CODE" IS '우편번호';

COMMENT ON COLUMN "CUST_COM"."ADDR1" IS '주소1';

COMMENT ON COLUMN "CUST_COM"."ADDR2" IS '주소2';

COMMENT ON COLUMN "CUST_COM"."REPR_NAME" IS '대표자이름';

COMMENT ON COLUMN "CUST_COM"."BIZ_TYPE" IS '사업유형';

COMMENT ON COLUMN "CUST_COM"."IDST_TYPE" IS '산업유형';

COMMENT ON COLUMN "CUST_COM"."REMK" IS '비고';

COMMENT ON COLUMN "CUST_COM"."STAT" IS '상태';

COMMENT ON COLUMN "CUST_COM"."DEL_FLAG" IS '삭제플래그';

COMMENT ON COLUMN "CUST_COM"."CREA_BY" IS '생성자';

COMMENT ON COLUMN "CUST_COM"."CREA_DATE" IS '생성일자';

COMMENT ON COLUMN "CUST_COM"."UPDT_BY" IS '수정자';

COMMENT ON COLUMN "CUST_COM"."UPDT_DATE" IS '수정일자';

ALTER TABLE "CUST_COM" ADD CONSTRAINT "PK_CUST_COM" PRIMARY KEY (
	"CUST_ID"
);

/***************************************
****************MATR_COM****************
****************************************/

 DROP TABLE "MATR_COM";

CREATE TABLE "MATR_COM" (
	"MATR_CODE"	VARCHAR2(10)		NOT NULL,
	"MATR_TYPE"	CHAR(4)		NOT NULL,
	"NAME"	VARCHAR2(30)		NOT NULL,
	"DESC"	VARCHAR2(100)		NULL,
	"PRDT_LINE"	CHAR(3)		NULL,
	"BASE_UOM"	VARCHAR(5)		NULL,
	"MATR_HIER"	VARCHAR2(30)		NULL,
	"MATR_HIER_LV1"	CHAR(3)		NULL,
	"MATR_HIER_LV2"	CHAR(3)		NULL,
	"MATR_HIER_LV3"	CHAR(3)		NULL,
	"MATR_HIER_LV4"	CHAR(3)		NULL,
	"MATR_HIER_LV5"	CHAR(3)		NULL,
	"STAT"	CHAR(1)		NULL,
	"DEL_FLAG"	CHAR(1)		NULL,
	"CREA_BY"	VARCHAR(20)		NULL,
	"CREA_DATE"	DATE		NULL,
	"UPDT_BY"	VARCHAR(20)		NULL,
	"UPDT_DATE"	DATE		NULL
);

COMMENT ON COLUMN "MATR_COM"."MATR_CODE" IS '자재코드';

COMMENT ON COLUMN "MATR_COM"."MATR_TYPE" IS '자재유형';

COMMENT ON COLUMN "MATR_COM"."NAME" IS '이름';

COMMENT ON COLUMN "MATR_COM"."DESC" IS '설명';

COMMENT ON COLUMN "MATR_COM"."PRDT_LINE" IS '제품라인';

COMMENT ON COLUMN "MATR_COM"."BASE_UOM" IS '기본측정단위';

COMMENT ON COLUMN "MATR_COM"."MATR_HIER" IS '자재계층구조';

COMMENT ON COLUMN "MATR_COM"."MATR_HIER_LV1" IS '자재계층구조레벨1';

COMMENT ON COLUMN "MATR_COM"."MATR_HIER_LV2" IS '자재계층구조레벨2';

COMMENT ON COLUMN "MATR_COM"."MATR_HIER_LV3" IS '자재계층구조레벨3';

COMMENT ON COLUMN "MATR_COM"."MATR_HIER_LV4" IS '자재계층구조레벨4';

COMMENT ON COLUMN "MATR_COM"."MATR_HIER_LV5" IS '자재계층구조레벨5';

COMMENT ON COLUMN "MATR_COM"."STAT" IS '상태';

COMMENT ON COLUMN "MATR_COM"."DEL_FLAG" IS '삭제플래그';

COMMENT ON COLUMN "MATR_COM"."CREA_BY" IS '생성자';

COMMENT ON COLUMN "MATR_COM"."CREA_DATE" IS '생성일자';

COMMENT ON COLUMN "MATR_COM"."UPDT_BY" IS '수정자';

COMMENT ON COLUMN "MATR_COM"."UPDT_DATE" IS '수정일자';

ALTER TABLE "MATR_COM" ADD CONSTRAINT "PK_MATR_COM" PRIMARY KEY (
	"MATR_CODE"
);

/***************************************
**************SALE_ORD_HEAD*************
****************************************/

 DROP TABLE "SALE_ORD_HEAD";

CREATE TABLE "SALE_ORD_HEAD" (
	"SALE_ORD_NO"	NUMBER(10)		NOT NULL,
	"SOLD_TO_PTY"	VARCHAR2(10)		NOT NULL,
	"ORD_DATE"	DATE		NOT NULL,
	"ORD_TYPE"	CHAR(4)		NOT NULL,
	"SALE_DEPT"	CHAR(3)		NULL,
	"SALE_OFIS"	CHAR(3)		NULL,
	"SALE_GRP"	CHAR(3)		NULL,
	"DIST_CHAN"	CHAR(2)		NOT NULL,
	"ORD_RESN"	CHAR(3)		NULL,
	"PRIC_DATE"	DATE		NULL,
	"CURR"	CHAR(3)		NOT NULL,
	"PRC_STAT"	CHAR(1)		NULL,
	"RJEC_RESN"	CHAR(2)		NULL,
	"DEL_FLAG"	CHAR(1)		NULL,
	"CREA_BY"	VARCHAR(20)		NULL,
	"CREA_DATE"	DATE		NULL,
	"UPDT_BY"	VARCHAR(20)		NULL,
	"UPDT_DATE"	DATE		NULL
);

COMMENT ON COLUMN "SALE_ORD_HEAD"."SALE_ORD_NO" IS '영업문서번호';

COMMENT ON COLUMN "SALE_ORD_HEAD"."SOLD_TO_PTY" IS '판매처(고객아이디)';

COMMENT ON COLUMN "SALE_ORD_HEAD"."ORD_DATE" IS '주문일자';

COMMENT ON COLUMN "SALE_ORD_HEAD"."ORD_TYPE" IS '주문유형';

COMMENT ON COLUMN "SALE_ORD_HEAD"."SALE_DEPT" IS '영업부서';

COMMENT ON COLUMN "SALE_ORD_HEAD"."SALE_OFIS" IS '영업오피스';

COMMENT ON COLUMN "SALE_ORD_HEAD"."SALE_GRP" IS '영업그룹';

COMMENT ON COLUMN "SALE_ORD_HEAD"."DIST_CHAN" IS '유통채널';

COMMENT ON COLUMN "SALE_ORD_HEAD"."ORD_RESN" IS '주문사유';

COMMENT ON COLUMN "SALE_ORD_HEAD"."PRIC_DATE" IS '가결결정일';

COMMENT ON COLUMN "SALE_ORD_HEAD"."CURR" IS '통화';

COMMENT ON COLUMN "SALE_ORD_HEAD"."PRC_STAT" IS '처리상태';

COMMENT ON COLUMN "SALE_ORD_HEAD"."RJEC_RESN" IS '거부사유';

COMMENT ON COLUMN "SALE_ORD_HEAD"."DEL_FLAG" IS '삭제플래그';

COMMENT ON COLUMN "SALE_ORD_HEAD"."CREA_BY" IS '생성자';

COMMENT ON COLUMN "SALE_ORD_HEAD"."CREA_DATE" IS '생성일자';

COMMENT ON COLUMN "SALE_ORD_HEAD"."UPDT_BY" IS '수정자';

COMMENT ON COLUMN "SALE_ORD_HEAD"."UPDT_DATE" IS '수정일자';

ALTER TABLE "SALE_ORD_HEAD" ADD CONSTRAINT "PK_SALE_ORD_HEAD" PRIMARY KEY (
	"SALE_ORD_NO"
);

ALTER TABLE "SALE_ORD_HEAD" ADD CONSTRAINT "FK_CUST_COM_TO_SALE_ORD_HEAD_1" FOREIGN KEY (
	"SOLD_TO_PTY"
)
REFERENCES "CUST_COM" (
	"CUST_ID"
);


/***************************************
**************SALE_ORD_ITEM*************
****************************************/

DROP TABLE "SALE_ORD_ITEM";

CREATE TABLE "SALE_ORD_ITEM" (
	"ITEM_SEQ"	NUMBER(5)		NOT NULL,
	"SALE_ORD_NO"	NUMBER(10)		NOT NULL,
	"SHIP_TO_PTY"	VARCHAR2(10)		NOT NULL,
	"MATR_CODE"	VARCHAR2(10)		NOT NULL,
	"ITEM_NAME"	VARCHAR2(30)		NULL,
	"PRDT_LINE"	CHAR(3)		NULL,
	"ORD_QTY"	NUMBER(18,6)		NULL,
	"SALE_UOM"	VARCHAR(5)		NULL,
	"NET_VAL"	NUMBER(18,6)		NULL,
	"CURR"	CHAR(3)		NULL,
	"GROS_VAL"	NUMBER(18,6)		NULL,
	"TAX_VAL"	NUMBER(18,6)		NULL,
	"DELV_REQ_DATE"	DATE		NULL,
	"RJEC_RESN"	CHAR(2)		NULL,
	"PRC_STAT"	CHAR(1)		NULL,
	"CREA_BY"	VARCHAR(20)		NULL,
	"CREA_DATE"	DATE		NULL,
	"UPDT_BY"	VARCHAR(20)		NULL,
	"UPDT_DATE"	DATE		NULL
);

COMMENT ON COLUMN "SALE_ORD_ITEM"."ITEM_SEQ" IS '아이템순번';

COMMENT ON COLUMN "SALE_ORD_ITEM"."SALE_ORD_NO" IS '영업문서번호';

COMMENT ON COLUMN "SALE_ORD_ITEM"."SHIP_TO_PTY" IS '납품처(고객아이디)';

COMMENT ON COLUMN "SALE_ORD_ITEM"."MATR_CODE" IS '자재코드';

COMMENT ON COLUMN "SALE_ORD_ITEM"."ITEM_NAME" IS '아이템이름';

COMMENT ON COLUMN "SALE_ORD_ITEM"."PRDT_LINE" IS '제품라인';

COMMENT ON COLUMN "SALE_ORD_ITEM"."ORD_QTY" IS '주문수량';

COMMENT ON COLUMN "SALE_ORD_ITEM"."SALE_UOM" IS '영업측정단위';

COMMENT ON COLUMN "SALE_ORD_ITEM"."NET_VAL" IS '순가치';

COMMENT ON COLUMN "SALE_ORD_ITEM"."CURR" IS '통화';

COMMENT ON COLUMN "SALE_ORD_ITEM"."GROS_VAL" IS '총가치';

COMMENT ON COLUMN "SALE_ORD_ITEM"."TAX_VAL" IS '세금가치';

COMMENT ON COLUMN "SALE_ORD_ITEM"."DELV_REQ_DATE" IS '납품요청일';

COMMENT ON COLUMN "SALE_ORD_ITEM"."RJEC_RESN" IS '거부사유';

COMMENT ON COLUMN "SALE_ORD_ITEM"."PRC_STAT" IS '처리상태';

COMMENT ON COLUMN "SALE_ORD_ITEM"."CREA_BY" IS '생성자';

COMMENT ON COLUMN "SALE_ORD_ITEM"."CREA_DATE" IS '생성일자';

COMMENT ON COLUMN "SALE_ORD_ITEM"."UPDT_BY" IS '수정자';

COMMENT ON COLUMN "SALE_ORD_ITEM"."UPDT_DATE" IS '수정일자';

ALTER TABLE "SALE_ORD_ITEM" ADD CONSTRAINT "PK_SALE_ORD_ITEM" PRIMARY KEY (
	"ITEM_SEQ",
	"SALE_ORD_NO"
);

ALTER TABLE "SALE_ORD_ITEM" ADD CONSTRAINT "FK_SALE_ORD_HEAD_TO_SALE_ORD_ITEM_1" FOREIGN KEY (
	"SALE_ORD_NO"
)
REFERENCES "SALE_ORD_HEAD" (
	"SALE_ORD_NO"
);

ALTER TABLE "SALE_ORD_ITEM" ADD CONSTRAINT "FK_CUST_COM_TO_SALE_ORD_ITEM_1" FOREIGN KEY (
	"SHIP_TO_PTY"
)
REFERENCES "CUST_COM" (
	"CUST_ID"
);

ALTER TABLE "SALE_ORD_ITEM" ADD CONSTRAINT "FK_MATR_COM_TO_SALE_ORD_ITEM_1" FOREIGN KEY (
	"MATR_CODE"
)
REFERENCES "MATR_COM" (
	"MATR_CODE"
);

 

  • 고객 공통 정보 테이블(CUST_COM) 데이터 생성
DECLARE
    TYPE CompanyArray IS TABLE OF VARCHAR2(100);
    company_names CompanyArray := CompanyArray(
        'Alpha Corporation', 'Beta Tech', 'Gamma Solutions', 'Delta Enterprises', 'Epsilon Holdings',
        'Zeta Innovations', 'Theta Solutions', 'Iota Technologies', 'Kappa Enterprises', 'Lambda Group',
        'Mu Systems', 'Nu Consulting', 'Xi Manufacturing', 'Omicron Inc.', 'Pi Enterprises',
        'Rho Financials', 'Sigma Tech', 'Tau Solutions', 'Upsilon Logistics', 'Phi Innovations',
        'Chi Holdings', 'Psi Retail', 'Omega Consulting', 'AlphaPlus Tech', 'BetaMax Solutions',
        'GammaPrime Inc.', 'DeltaX Enterprises', 'EpsilonSoft', 'ZetaPro Consulting', 'ThetaAI',
        'Omega Retail', 'Lambda Innovations', 'Kappa Systems', 'Mu Technologies', 'Nu Financials',
        'Xi Logistics', 'Omicron Consulting', 'Pi Tech', 'Rho Manufacturing', 'Sigma Retail',
        'Tau AI', 'Upsilon Innovations', 'Phi Systems', 'Chi Enterprises', 'Psi Holdings',
        'Omega AI', 'AlphaEdge Solutions', 'BetaCore Tech', 'GammaFusion', 'DeltaCloud'
    );
    v_cust_id    VARCHAR2(10);
    v_cust_grp   CHAR(4);
    v_cntr_code  CHAR(4);
    v_city_code  CHAR(4);
    v_post_code  CHAR(5);
    v_addr1      VARCHAR2(100);
    v_addr2      VARCHAR2(100);
    v_repr_name  VARCHAR2(30);
    v_biz_type   VARCHAR2(30);
    v_idst_type  VARCHAR2(20);
    v_remk       VARCHAR2(200);
    v_stat       CHAR(1);
    v_del_flag   CHAR(1);
    v_crea_by    VARCHAR2(20);
    v_crea_date  DATE;
    v_updt_by    VARCHAR2(20);
    v_updt_date  DATE;
BEGIN
    FOR i IN 1..company_names.COUNT LOOP
        -- 랜덤한 CUST_ID 생성 (CUST_00001 ~ CUST_99999)
        v_cust_id := LPAD(TRUNC(DBMS_RANDOM.VALUE(1, 9999999999)), 10, '0');
        
        -- 랜덤한 그룹 코드 (A001 ~ A005)
        v_cust_grp := 'A00' || TRUNC(DBMS_RANDOM.VALUE(1, 4));

        -- CNTR_CODE (랜덤 국가코드)
        v_cntr_code := CASE TRUNC(DBMS_RANDOM.VALUE(1, 6))
            WHEN 1 THEN 'KR' WHEN 2 THEN 'US' WHEN 3 THEN 'JP'
            WHEN 4 THEN 'CN' WHEN 5 THEN 'SG' ELSE 'DE' END;
        
        -- CITY_CODE (랜덤 도시코드)
        v_city_code := CASE v_cntr_code
            WHEN 'KR' THEN 'SEO' WHEN 'US' THEN 'NY' WHEN 'JP' THEN 'TKY'
            WHEN 'CN' THEN 'SH' WHEN 'SG' THEN 'SIN' ELSE 'BER' END;

        -- 랜덤한 우편번호 (10000 ~ 99999)
        v_post_code := LPAD(TRUNC(DBMS_RANDOM.VALUE(10000, 99999)), 5, '0');

        -- 주소 랜덤 생성
        v_addr1 := 'Street ' || TRUNC(DBMS_RANDOM.VALUE(1, 500));
        v_addr2 := 'Building ' || TRUNC(DBMS_RANDOM.VALUE(1, 100));

        -- 대표자명 및 업종 정보 랜덤
        v_repr_name := 'CEO_' || DBMS_RANDOM.STRING('U', 3);
        v_biz_type := 'Biz_' || DBMS_RANDOM.STRING('U', 4);
        v_idst_type := 'Industry_' || TRUNC(DBMS_RANDOM.VALUE(1, 10));

        -- 비고 (REMK) 및 상태 (STAT), 삭제 플래그 (DEL_FLAG)
        v_remk := 'Generated by PL/SQL';

        -- STAT (A: Active, I: Inactive, D: Deleted 랜덤)
        v_stat := CASE TRUNC(DBMS_RANDOM.VALUE(1, 4))
            WHEN 1 THEN 'A' ELSE 'I' END;

        v_del_flag := '';

        -- 생성자, 생성 날짜, 업데이트 정보
        v_crea_by := 'System';
        v_crea_date := SYSDATE - TRUNC(DBMS_RANDOM.VALUE(1, 365)); -- 최근 1년 내 생성
        v_updt_by := 'System';
        v_updt_date := v_crea_date + TRUNC(DBMS_RANDOM.VALUE(0, 30)); -- 생성일 이후 랜덤 업데이트

        -- 데이터 삽입
        INSERT INTO CUST_COM (
            CUST_ID, CUST_GRP, NAME, CNTR_CODE, CITY_CODE, POST_CODE,
            ADDR1, ADDR2, REPR_NAME, BIZ_TYPE, IDST_TYPE, REMK, STAT,
            DEL_FLAG, CREA_BY, CREA_DATE, UPDT_BY, UPDT_DATE
        ) VALUES (
            v_cust_id, v_cust_grp, company_names(i), v_cntr_code, v_city_code, v_post_code,
            v_addr1, v_addr2, v_repr_name, v_biz_type, v_idst_type, v_remk, v_stat,
            v_del_flag, v_crea_by, v_crea_date, v_updt_by, v_updt_date
        );

    END LOOP;

    -- 커밋
    COMMIT;

    DBMS_OUTPUT.PUT_LINE('✅ 50개 데이터가 CUST_COM 테이블에 삽입되었습니다.');
END;
/

  • 자재 공통 정보 테이블(MATR_COM) 데이터 생성
DELETE MATR_COM;
INSERT INTO MATR_COM (MATR_CODE, MATR_TYPE, NAME, "DESC", PRDT_LINE, BASE_UOM, MATR_HIER, MATR_HIER_LV1, MATR_HIER_LV2, MATR_HIER_LV3, STAT, DEL_FLAG, CREA_BY, CREA_DATE)
VALUES ('1001', 'FNGD', 'Steel Plate', 'Heavy-duty steel plate', 'PLT', 'KG', 'STL', '001', '001', '001', 'A', 'N', 'admin', SYSDATE);

INSERT INTO MATR_COM (MATR_CODE, MATR_TYPE, NAME, "DESC", PRDT_LINE, BASE_UOM, MATR_HIER, MATR_HIER_LV1, MATR_HIER_LV2, MATR_HIER_LV3, STAT, DEL_FLAG, CREA_BY, CREA_DATE)
VALUES ('1002', 'WINP', 'Copper Wire', 'High conductivity copper wire', 'WR', 'M', 'COP', '001', '001', '002', 'A', 'N', 'admin', SYSDATE);

INSERT INTO MATR_COM (MATR_CODE, MATR_TYPE, NAME, "DESC", PRDT_LINE, BASE_UOM, MATR_HIER, MATR_HIER_LV1, MATR_HIER_LV2, MATR_HIER_LV3, STAT, DEL_FLAG, CREA_BY, CREA_DATE)
VALUES ('1003', 'WINP', 'Aluminum Sheet', 'Aluminum alloy sheet', 'ALM', 'M2', 'ALM', '001', '002', '001', 'A', 'N', 'admin', SYSDATE);

INSERT INTO MATR_COM (MATR_CODE, MATR_TYPE, NAME, "DESC", PRDT_LINE, BASE_UOM, MATR_HIER, MATR_HIER_LV1, MATR_HIER_LV2, MATR_HIER_LV3, STAT, DEL_FLAG, CREA_BY, CREA_DATE)
VALUES ('1004', 'FNGD', 'Plastic Pellet', 'Polyethylene pellets for molding', 'PLT', 'KG', 'PLA', '002', '001', '001', 'A', 'N', 'admin', SYSDATE);

INSERT INTO MATR_COM (MATR_CODE, MATR_TYPE, NAME, "DESC", PRDT_LINE, BASE_UOM, MATR_HIER, MATR_HIER_LV1, MATR_HIER_LV2, MATR_HIER_LV3, STAT, DEL_FLAG, CREA_BY, CREA_DATE)
VALUES ('1005', 'FNGD', 'Rubber Mold', 'High-density rubber mold', 'RUB', 'KG', 'RUB', '002', '002', '001', 'A', 'N', 'admin', SYSDATE);

INSERT INTO MATR_COM (MATR_CODE, MATR_TYPE, NAME, "DESC", PRDT_LINE, BASE_UOM, MATR_HIER, MATR_HIER_LV1, MATR_HIER_LV2, MATR_HIER_LV3, STAT, DEL_FLAG, CREA_BY, CREA_DATE)
VALUES ('1006', 'FNGD', 'Iron Rod', 'Solid iron rod for construction', 'CON', 'M', 'IRN', '003', '001', '001', 'A', 'N', 'admin', SYSDATE);

INSERT INTO MATR_COM (MATR_CODE, MATR_TYPE, NAME, "DESC", PRDT_LINE, BASE_UOM, MATR_HIER, MATR_HIER_LV1, MATR_HIER_LV2, MATR_HIER_LV3, STAT, DEL_FLAG, CREA_BY, CREA_DATE)
VALUES ('1007', 'FNGD', 'Cement Bag', 'Portland cement for construction', 'CON', 'KG', 'CEM', '003', '001', '002', 'A', 'N', 'admin', SYSDATE);

INSERT INTO MATR_COM (MATR_CODE, MATR_TYPE, NAME, "DESC", PRDT_LINE, BASE_UOM, MATR_HIER, MATR_HIER_LV1, MATR_HIER_LV2, MATR_HIER_LV3, STAT, DEL_FLAG, CREA_BY, CREA_DATE)
VALUES ('1008', 'WINP', 'Brick', 'Red clay brick for wall construction', 'CON', 'PC', 'BRK', '003', '002', '001', 'A', 'N', 'admin', SYSDATE);

INSERT INTO MATR_COM (MATR_CODE, MATR_TYPE, NAME, "DESC", PRDT_LINE, BASE_UOM, MATR_HIER, MATR_HIER_LV1, MATR_HIER_LV2, MATR_HIER_LV3, STAT, DEL_FLAG, CREA_BY, CREA_DATE)
VALUES ('1009', 'FNGD', 'LED Panel', 'Energy-efficient LED panel', 'ELE', 'EA', 'LED', '004', '001', '001', 'A', 'N', 'admin', SYSDATE);

INSERT INTO MATR_COM (MATR_CODE, MATR_TYPE, NAME, "DESC", PRDT_LINE, BASE_UOM, MATR_HIER, MATR_HIER_LV1, MATR_HIER_LV2, MATR_HIER_LV3, STAT, DEL_FLAG, CREA_BY, CREA_DATE)
VALUES ('1010', 'FNGD', 'Power Supply', '12V power supply for LED lights', 'ELE', 'EA', 'PSU', '004', '002', '001', 'A', 'N', 'admin', SYSDATE);

INSERT INTO MATR_COM (MATR_CODE, MATR_TYPE, NAME, "DESC", PRDT_LINE, BASE_UOM, MATR_HIER, MATR_HIER_LV1, MATR_HIER_LV2, MATR_HIER_LV3, STAT, DEL_FLAG, CREA_BY, CREA_DATE)
VALUES ('1011', 'FNGD', 'Fiber Optic Cable', 'High-speed fiber optic cable', 'TEL', 'M', 'FOC', '005', '001', '001', 'A', 'N', 'admin', SYSDATE);

INSERT INTO MATR_COM (MATR_CODE, MATR_TYPE, NAME, "DESC", PRDT_LINE, BASE_UOM, MATR_HIER, MATR_HIER_LV1, MATR_HIER_LV2, MATR_HIER_LV3, STAT, DEL_FLAG, CREA_BY, CREA_DATE)
VALUES ('1012', 'FNGD', 'Wireless Router', 'High-speed wireless router', 'TEL', 'EA', 'WLR', '005', '001', '002', 'A', 'N', 'admin', SYSDATE);

INSERT INTO MATR_COM (MATR_CODE, MATR_TYPE, NAME, "DESC", PRDT_LINE, BASE_UOM, MATR_HIER, MATR_HIER_LV1, MATR_HIER_LV2, MATR_HIER_LV3, STAT, DEL_FLAG, CREA_BY, CREA_DATE)
VALUES ('1013', 'FNGD', 'Bicycle Frame', 'Aluminum bicycle frame', 'BIK', 'EA', 'BIC', '006', '001', '001', 'A', 'N', 'admin', SYSDATE);

INSERT INTO MATR_COM (MATR_CODE, MATR_TYPE, NAME, "DESC", PRDT_LINE, BASE_UOM, MATR_HIER, MATR_HIER_LV1, MATR_HIER_LV2, MATR_HIER_LV3, STAT, DEL_FLAG, CREA_BY, CREA_DATE)
VALUES ('1014', 'FNGD', 'Bike Tire', 'Durable rubber tire for bicycles', 'BIK', 'EA', 'TIR', '006', '002', '001', 'A', 'N', 'admin', SYSDATE);

-- 서비스 자재 2: 소프트웨어 라이선스
INSERT INTO MATR_COM (MATR_CODE, MATR_TYPE, NAME, "DESC", PRDT_LINE, BASE_UOM, MATR_HIER, MATR_HIER_LV1, MATR_HIER_LV2, MATR_HIER_LV3, STAT, DEL_FLAG, CREA_BY, CREA_DATE)
VALUES ('1015', 'SRVC', 'Software License', 'Annual software license for office suite', 'SVC', 'EA', 'SWL', '008', '002', '001', 'A', 'N', 'admin', SYSDATE);

COMMIT;

UPDATE MATR_COM SET MATR_HIER = MATR_HIER_LV1 || MATR_HIER_LV2 || MATR_HIER_LV1;

COMMIT;
  • 주문 헤더 테이블(SALE_ORD_HEAD) 데이터 생성
DECLARE
    v_sale_ord_no NUMBER := 1;
    v_sold_to_pty VARCHAR2(10);
    v_ord_date DATE := TO_DATE('2025-01-01', 'YYYY-MM-DD');
    v_ord_type CHAR(4);
    v_sale_dept CHAR(3);
    v_sale_ofis CHAR(3);
    v_dist_chan CHAR(2);
    v_ord_resn CHAR(3);
    v_curr CHAR(3);
    v_prc_stat CHAR(1);
    v_del_flag CHAR(1);
    
    TYPE cust_id_table IS TABLE OF VARCHAR2(10);
    v_cust_ids cust_id_table;
    
    v_daily_count NUMBER;
    v_total_count NUMBER := 0;
    
    CURSOR c_cust IS SELECT CUST_ID FROM CUST_COM;
    
BEGIN
    -- CUST_COM 테이블에서 모든 CUST_ID를 가져와서 배열에 저장
    OPEN c_cust;
    FETCH c_cust BULK COLLECT INTO v_cust_ids;
    CLOSE c_cust;

    -- 2025년 1월 1일부터 12월 31일까지 반복
    WHILE v_ord_date <= TO_DATE('2025-12-31', 'YYYY-MM-DD') LOOP
        -- 하루에 100~200건 생성 (랜덤)
        v_daily_count := TRUNC(DBMS_RANDOM.VALUE(150, 300));

        FOR i IN 1..v_daily_count LOOP
            EXIT WHEN v_total_count >= 100000; -- 10만 건에 근접하면 종료

            -- SOLD_TO_PTY 랜덤 선택
            v_sold_to_pty := v_cust_ids(TRUNC(DBMS_RANDOM.VALUE(1, v_cust_ids.COUNT + 1)));

            -- ORD_TYPE 설정 (비율 9:0.2:0.2:0.2:0.2:0.2)
            v_ord_type := CASE 
                WHEN DBMS_RANDOM.VALUE < 0.9 THEN 'NORM'
                WHEN DBMS_RANDOM.VALUE < 0.92 THEN 'FREE'
                WHEN DBMS_RANDOM.VALUE < 0.94 THEN 'SRVC'
                WHEN DBMS_RANDOM.VALUE < 0.96 THEN 'RETN'
                WHEN DBMS_RANDOM.VALUE < 0.98 THEN 'AJCR'
                ELSE 'AJDR'
            END;

            -- SALE_DEPT 설정
            v_sale_dept := CASE TRUNC(DBMS_RANDOM.VALUE(1, 5))
                WHEN 1 THEN 'A01'
                WHEN 2 THEN 'A02'
                WHEN 3 THEN 'B01'
                ELSE 'B02'
            END;

            -- SALE_OFIS 설정
            v_sale_ofis := CASE v_sale_dept
                WHEN 'A01' THEN CASE WHEN DBMS_RANDOM.VALUE < 0.5 THEN '10A' ELSE '11A' END
                WHEN 'A02' THEN CASE WHEN DBMS_RANDOM.VALUE < 0.5 THEN '20A' ELSE '21A' END
                WHEN 'B01' THEN CASE WHEN DBMS_RANDOM.VALUE < 0.5 THEN '10B' ELSE '11B' END
                ELSE CASE WHEN DBMS_RANDOM.VALUE < 0.5 THEN '20B' ELSE '21B' END
            END;

            -- DIST_CHAN 설정
            v_dist_chan := CASE WHEN DBMS_RANDOM.VALUE < 0.5 THEN 'LO' ELSE 'EX' END;

            -- ORD_RESN 설정
            v_ord_resn := NULL;
            IF v_ord_type = 'AJCR' THEN
                v_ord_resn := CASE WHEN DBMS_RANDOM.VALUE < 0.5 THEN 'SAL' ELSE 'SDC' END;
            ELSIF v_ord_type = 'FREE' THEN
                v_ord_resn := CASE WHEN DBMS_RANDOM.VALUE < 0.5 THEN 'SMP' ELSE 'QAN' END;
            ELSIF v_ord_type = 'RETN' THEN
                IF DBMS_RANDOM.VALUE < 0.5 THEN
                    v_ord_resn := 'DAM';
                END IF;
            END IF;

            -- CURR 설정
            v_curr := CASE WHEN v_dist_chan = 'LO' THEN 'KRW' ELSE 'USD' END;

            IF v_ord_date < TO_DATE('2025-12-01', 'YYYY-MM-DD') THEN
                v_prc_stat := CASE 
                    WHEN DBMS_RANDOM.VALUE < 0.98 THEN 'D'
                    ELSE 'E'
                END;
            ELSE 
                v_prc_stat := CASE 
                    WHEN DBMS_RANDOM.VALUE < 0.2 THEN 'A'
                    WHEN DBMS_RANDOM.VALUE < 0.2 THEN 'B'
                    WHEN DBMS_RANDOM.VALUE < 0.2 THEN 'C'
                    WHEN DBMS_RANDOM.VALUE < 0.3 THEN 'D'
                    WHEN DBMS_RANDOM.VALUE < 0.1 THEN 'E'
                    ELSE 'E'
                END;
            END IF;

            v_del_flag := NULL;
            IF v_prc_stat = 'E' AND DBMS_RANDOM.VALUE < 0.5 THEN
                v_del_flag := 'Y';
            END IF;

            -- 데이터 삽입
            INSERT INTO SALE_ORD_HEAD (
                SALE_ORD_NO, SOLD_TO_PTY, ORD_DATE, ORD_TYPE, SALE_DEPT, SALE_OFIS, 
                DIST_CHAN, ORD_RESN, CURR, PRIC_DATE, CREA_DATE, PRC_STAT, DEL_FLAG
            ) VALUES (
                v_sale_ord_no, v_sold_to_pty, v_ord_date, v_ord_type, v_sale_dept, v_sale_ofis, 
                v_dist_chan, v_ord_resn, v_curr, v_ord_date, v_ord_date, v_prc_stat, v_del_flag
            );

            -- SALE_ORD_NO 증가
            v_sale_ord_no := v_sale_ord_no + 1;
            v_total_count := v_total_count + 1;
            

            -- 1,000건마다 커밋
            IF MOD(v_total_count, 1000) = 0 THEN
                COMMIT;
            END IF;
        END LOOP;

        -- ORD_DATE 하루 증가
        v_ord_date := v_ord_date + 1;
    END LOOP;

    -- 마지막 커밋
    COMMIT;
    
END;
/

  • 주문 아이템 정보 테이블(SALE_ORD_ITEM) 데이터 생성
DECLARE
    TYPE matr_table IS TABLE OF MATR_COM%ROWTYPE;
    v_matr_list matr_table;
    
    TYPE sale_ord_table IS TABLE OF SALE_ORD_HEAD%ROWTYPE;
    v_sale_orders sale_ord_table;

    v_item_seq NUMBER;
    v_ship_to_pty VARCHAR2(10);
    v_matr_code VARCHAR2(10);
    v_item_name VARCHAR2(30);
    v_prdt_line CHAR(3);
    v_ord_qty NUMBER(18,6);
    v_sale_uom VARCHAR2(5);
    v_net_val NUMBER(18,6);
    v_gros_val NUMBER(18,6);
    v_tax_val NUMBER(18,6);
    v_delv_req_date DATE;
    
    v_total_count NUMBER := 0;
    
    CURSOR c_sale IS SELECT * FROM SALE_ORD_HEAD;
    CURSOR c_matr IS SELECT * FROM MATR_COM;
    
BEGIN
    -- MATR_COM 데이터를 가져와서 메모리에 저장
    OPEN c_matr;
    FETCH c_matr BULK COLLECT INTO v_matr_list;
    CLOSE c_matr;
    
    -- SALE_ORD_HEAD 데이터를 가져와서 메모리에 저장
    OPEN c_sale;
    FETCH c_sale BULK COLLECT INTO v_sale_orders;
    CLOSE c_sale;

    -- SALE_ORD_HEAD를 순회하면서 SALE_ORD_ITEM 데이터 삽입
    FOR i IN 1..v_sale_orders.COUNT LOOP
        -- SALE_ORD_HEAD 정보 가져오기
        v_ship_to_pty := v_sale_orders(i).SOLD_TO_PTY;

        -- 랜덤한 아이템 개수 (1~5개)
        FOR j IN 1..TRUNC(DBMS_RANDOM.VALUE(1,6)) LOOP
            v_item_seq := j;

            -- MATR_COM에서 랜덤한 데이터 선택
            IF v_sale_orders(i).ORD_TYPE = 'SRVC' THEN
                -- SRVC일 경우 PRDT_LINE이 'SVC'인 데이터 하나 포함
                SELECT MATR_CODE, NAME, PRDT_LINE, BASE_UOM
                INTO v_matr_code, v_item_name, v_prdt_line, v_sale_uom
                FROM MATR_COM
                WHERE PRDT_LINE = 'SVC'
                AND ROWNUM = 1;
            ELSE
                -- 일반적인 경우 랜덤한 제품 선택
                v_matr_code := v_matr_list(TRUNC(DBMS_RANDOM.VALUE(1, v_matr_list.COUNT + 1))).MATR_CODE;
                v_item_name := v_matr_list(TRUNC(DBMS_RANDOM.VALUE(1, v_matr_list.COUNT + 1))).NAME;
                v_prdt_line := v_matr_list(TRUNC(DBMS_RANDOM.VALUE(1, v_matr_list.COUNT + 1))).PRDT_LINE;
                v_sale_uom := v_matr_list(TRUNC(DBMS_RANDOM.VALUE(1, v_matr_list.COUNT + 1))).BASE_UOM;
            END IF;

            -- ORD_QTY 설정
            IF v_prdt_line = 'SVC' THEN
                v_ord_qty := 1;
            ELSE
                v_ord_qty := TRUNC(DBMS_RANDOM.VALUE(100, 1001));
            END IF;

            -- NET_VAL 설정
            IF v_sale_orders(i).ORD_TYPE = 'FREE' THEN
                v_net_val := 0;
            ELSIF v_sale_orders(i).ORD_TYPE = 'RETN' THEN
                v_net_val := -1 * v_ord_qty * TRUNC(DBMS_RANDOM.VALUE(10, 100));
            ELSE
                v_net_val := v_ord_qty * TRUNC(DBMS_RANDOM.VALUE(10, 100));
            END IF;

            -- GROS_VAL & TAX_VAL 설정
            v_gros_val := TRUNC(v_net_val * 1.1);
            v_tax_val := v_gros_val - v_net_val;

            -- DELV_REQ_DATE 설정 (8:1:1 비율)
            v_delv_req_date := v_sale_orders(i).ORD_DATE + CASE 
                WHEN DBMS_RANDOM.VALUE < 0.8 THEN 0 
                WHEN DBMS_RANDOM.VALUE < 0.9 THEN 1 
                ELSE 2 
            END;

            -- 데이터 삽입
            INSERT INTO SALE_ORD_ITEM (
                ITEM_SEQ, SALE_ORD_NO, SHIP_TO_PTY, MATR_CODE, ITEM_NAME, PRDT_LINE, ORD_QTY, 
                SALE_UOM, NET_VAL, CURR, GROS_VAL, TAX_VAL, DELV_REQ_DATE, 
                RJEC_RESN, PRC_STAT, CREA_DATE
            ) VALUES (
                v_item_seq, v_sale_orders(i).SALE_ORD_NO, v_ship_to_pty, v_matr_code, v_item_name, v_prdt_line, v_ord_qty,
                v_sale_uom, v_net_val, 
                CASE WHEN v_sale_orders(i).DIST_CHAN = 'LO' THEN 'KRW' ELSE 'USD' END,
                v_gros_val, v_tax_val, v_delv_req_date, 
                v_sale_orders(i).RJEC_RESN, v_sale_orders(i).PRC_STAT, v_sale_orders(i).CREA_DATE
            );

            -- 1,000건마다 COMMIT
            v_total_count := v_total_count + 1;
            IF MOD(v_total_count, 1000) = 0 THEN
                COMMIT;
            END IF;
        END LOOP;
    END LOOP;

    -- 마지막 COMMIT
    COMMIT;
    
END;
/

 

728x90
728x90

 

 

  • Demultiplexing : Internet Layer로부터 받은 segment나 datagram에 있는 payload를 적절한 socket으로 전달하는 것
  • Multiplexing : Internet Layer로 socket들로부터 데이터를 수집해서 각각 segment나 datagram으로 만든 후 보내는 것
  • Internet Layer의 TCP/UDP 정보가 있어 해당 정보를 확인하여 각 Transport Layer 양식에 맞춰 Transport Layer에 보내줌
  • Transport가 어떤 프로세스(Socket)으로 데이터를 보내야 하는지 어떻게 판단할까?
    • port로 구분
      • UDP : Destination Port로 보내면 끝
      • TCP
        • syn flag가 1이면 listening socket으로 보내고
        • 이미 연결된 Connection이면 TCP, IP Address, Port 다 같은 곳으로 보냄

 

 

*Layer는 

728x90
728x90

Socket

  • Application(process)이 시스템의 기능을 마음대로 사용하는 것은 불가능
  • 대신 System은 네트워크 통신을 위한 Interface를 제공
  • Application(process)이 Socket을 통해 데이터를 주고 받음(=통신)
  • 개발자는 Socket Programming을 통해 네트워크 상의 다른 Process와 데이터를 주고 받을 수 있도록 구현한다.
  • 대부분의 System(OS)은 Socket 형태로 네트워크 기능을 제공(Linux, Window 등)

 

  • 개발자로서 일하면서 Socket Programming을 한 적이 없는 이유
    • 대체로 Application Layer의 프로토콜을 라이브러리로 가져와 사용하게 된다. 이 라이브러리가 보통 Socket을 사용한 네트워크 통신을 구현하고 있음. 즉, 실제로는 사용하고 있지만 잘 모르고 있는 것임.
    • 따라서 일반 Application 개발자는 Socket Programming을 직접할 일이 적다.

 

  • Socket = < Protocol , IP address, Port number >
    • Port number는 Socket을 구분하기 위한 숫자
    • UDP는 3개(protocol, ip, port)로 식별할 수 있지만 TCP는 불가능
  • TCP에서의 동작

- Connection A와 Connection B는 source의 IP, Port와 target의 IP, Port의 조합으로 연결을 식별한다.

- 그래서 서로 다른 프로세스(socket C1, socket C2)가 같은 정보의 소켓을 가지고 동일한 서버 프로세스와 연결을 생성하려고 하면 에러가 발생할 것이다. 

- 표준 문서에서는 TCP Socket이 IP address와 Port만으로 식별할 수 있다고 써있지만 실제 구현에서는 위와 같이 Connection을 구별하기 위해 양 프로세스의 Socket 정보를 모두 활용한다.

 

*UDP는 Connection 개념이 없이 그냥 데이터 주고 받는다.

 

TCP, UDP 각각의 사용처

  • TCP : Connection(연결) 기반, 신뢰성 보장, 데이터 순서 보장 => 느림
    • 웹 - HTTP, HTTPS 통신
    • 파일전송 - FTP, SFTP
    • 이메일 - SMTP, IMAP, POP3
    • 원격접속 - SSH, Telnet
    • 데이터베이스와 클라이언트간 통신
  • UDP : 신뢰성보다 속도효율성 중시, 비연결 지향 => 빠름
    • Streaming 서비스 - Youtube, Netflix
    • 온라인 게임
    • VoIP(Voice over Internet Protocol) - Skype, Zoom 
    • DNS(Domain Name Service) <= 도메인 이름을 IP주소로 바꿔주는 건 가볍고 빠르게 처리해야 함.
    • IoT 통신 - MQTT-SN, CoAP <= IoT 장치들은 제한된 리소스를 가지고 있어 빠른 UDP를 주로 사용

 

 

728x90
728x90

- 소켓과 포트가 속하는 위치는?

 

- process와 port가 1대1 반드시 구조여야 하는 것은 아니다.

- Port name으로 식별한다.(OS마다 다른 방식으로 port에 name을 부여한다)

 

- TCP/IP의 Internet 계층의 Internet Protocol(IP)를 이용하여 데이터를 전달하게 되는 데 프로세스간 이 때, IP는 unreliable(신뢰할 수 없는)하다는 특성을 지니고 있다. 

- Data loss와 out-of-order 위험이 있으므로 그 위에서 동작하는 Application(Process)간, 즉 transport 계층의 통신에 신뢰성을 부여해야 한다. => TCP 개념 등장

 

  • TCP; Transmission Control Protocol 
    • 프로세스 사이에서 데이터를 안정적으로 주고받도록 함.
    • TCP 에서의 Connection이란 프로세스 간 안정적이고 논리적인 통신 통로를 의미한다.
      • 3-way handshake로 초기화(initialization)을 통해 데이터를 주고 받을 수 있는 환경인 Connection을 연다.
      • 4-way handshake로 Connection을 닫는다.
      • 이런 방식을 Connection-oriented 라고 부른다.

 

  • 그렇다면 Connection을 구축하기 위해 인터넷 상에서 어떻게 port를 식별하는가?
    • port number(port라고도 부름)를 정의 : 16bit(0~65535)
    • port number만으로는 부족 => Internet Address(IP)와 port number로 인터넷 상에서 각 포트를 식별할 수 있음 => 이를 Socket이라고 부름
    • 즉, Socket은 각 포트를 유일하게 식별하기 위해 나온 개념이므로 Socket은 인터넷 상에서 unique해야 함.
    • TCP 표준에서는 한 쌍의 Socket으로 Connection을 유일하게 식별할 수 있다.
      • source의 IP address, port number
      • destination의 IP address, port number
      • 이렇게 4가지로 Connection을 유일하게 식별 가능.
    • 하나의 소켓은 여러 개의 연결에 사용될 수 있다. (서버의 경우 소수의 socket으로 여러 클라이언트의 connection을 상대해야 할 것이다.

 

  • UDP : User Datagram Protocol 
    • Connection 없이 데이터를 주고 받음. 즉, Connectionless
    • Internet Protocol을 거의 그대로 사용하여 unreliable함. 그래서 UDP 공식문서에는 Socket이란 단어는 나오지 않지만 UDP에서도 Socket의 개념을 사용함(목적지 소켓이 있어야 하므로)

 

  • TCP, UDP 통틀어서 Socket을 구별하기 위해서는 Protocol, IP address, Port number 3가지로 구성된다.
  • 위 TCP 설명에선 Socket을 IP와 Port number의 조합이라고 했지만 UDP를 포함한 개념에서는 Socket을 3가지 조건으로 식별해야 한다.

- process A, B는 프로토콜이 다르므로 서로 다른 socket에 연결되어 있는 것이다. 

 

- 각각의 Connection은 서로 다른 조합의 Socket 한 쌍을 가지므로 유일하게 식별 가능하다.

 

 

- 위 내용들은 모두 표준에 관한 내용이기 때문에 실제 구현의 세계에서는 소켓의 개념이 좀 다르게 쓰인다고 함.

728x90
728x90

World Wide Web : 여러 정보들을 링크를 통해 효율적으로 접근할 수 있는 인터넷 상에서 동작하는 전 지구적인 정보시스템

 

  • Hypertext 기반 링크 방식 시스템 개발
  • Link는 어떤 서버로 가야 데이터를 요청할 수 있는지를 담고 있음 => URL 개념

Web Browser 발명

  • CERN Httpd 서버 발명(최초의 Web Server)
  • 최초의 Website 발명
  • hypertext의 마크업 언어 HTML 개발
  • HTML 통신 프로토콜 HTTP 개발 - web의 토대가 되는 프로토콜
  • UDI(오늘날의 URL) : 데이터를 요청할 서버의 위치를 특정할 대상
  • 1993년 4월 30일 www 관련 software, source code 무료 공개 후 급성장

- 최초의 웹서버, This machine is a server. DO NOT POWER IT DOWN!! 라고 쓰여 있다.

728x90
728x90
  • Network 의 역할
    • 어플리케이션의 목적에 맞는 통신 방법 제공
    • 신뢰할 수 있는 데이터 전송 방법 제공
    • 네트워크 간 최적의 통신경로 결정
    • 목적지로 데이터 전송
    • 각 노드 사이의 데이터 전송
  • 통신 기능이 제대로 이루어지기 위해선 참여자들 사이에 약속된 통신 방법이 있어야 한다. => 형식, 절차, 규약이 있어야 한다. 이러한 통신 규약을 네트워크 Protocol 이라고 한다.
  • 네트워크의 역할이 여러 개이므로 Protocol 또한 여러 종류가 있어야 한다. 즉 각 역할별로 Protocl이 모듈화 되어 있다.

 

  • 각 기능별로 나눈 계층 구조(Layered Architecture)가 필요하다. 각 레이어 별로 역할에 따라 모듈화되어 있는 것이다. 
    • OSI model (7 layer) : 범용적인 네트워크 계층 구조 
    • TCP/IP model (4 layer) : 인터넷에 특화된 네트워크 계층 구분법
  • 각 Layer의 Protocol은 하위 Layer의 Protocol이 제공하는 기능을 사용하여 동작한다.

 

  • L7 - Application Layer : HTTP, DNS, SMTP, FTP 등 application 목적에 맞는 통신방법제공
    • 실제로 데이터가 어떻게 전송될지는 관심없음
  • L6 - Presentation Layer : APP간 통신에서 메시지 format 관리
    • 인코딩 <=> 디코딩
    • 암호화 <=> 복호화
    • 압축 <=> 압축풀기
  • L5 - Session Layer : App 간 통신에서 session 관리, RPC(Remote Procedure Call) 동작이 이 위에서 이루어짐.
  • *L5 ~ L7 : Application과 관련된 기능 담당
  • L4 - Transport Layer : App간 통신담당 => 목적지 App으로 데이터 전송, 어떤 방법 (TCP,UDP)으로 보낼지 결정
    • TCP : 안정적, 신뢰성있는 데이터 전송 보장
    • UDP : 필수 기능만 제공
  • L3 - Network Layer
    • Host간 통신담당(IP)
    • 목적지 호스트로 데이터 전송
    • 네트워크간 최적 경로 결정
  • L2 - Data Link Layer 
    • 직접 연결된 노드 간 통신담당
    • MAC 주소 기반 통신(ARP)
  • L1 - Physical Layer : 물리적인 매개체(케이블, 무선 등)를 통해 bit 단위로 데이터 전송(전기신호)

  • 각 계층을 거치면서 데이터에 각각의 계층에 해당하는 Header 정보를 담는다.(L2 데이터 링크 계층에서는 Header뿐만 아니라 꼬리 부분에 Trailer 정보를 붙인다, 또한 L1의 헤더는 없다, 그냥 보내는 역할을 칭하는 것)

 

 

  • 라우터를 거치면서 Encapulation과 Decapsulation을 거치면서 목적지에 도달하게 된다.
  • TCP/IP 모델과는 아래와 같이 대응된다.

728x90
728x90

네트워크 기초 시리즈는 유튜버 '쉬운코드'의 네트워크 강의를 정리함

https://youtu.be/oFKYzp6gGfc?si=pMc1aOUFQ_Y2y4qo

 

  • IP address : 인터넷에 연결되기 위한 필요한 인터넷상의 주소
  • 모뎀(modem)
    • 네트워크 통신에 필요한 신호변환장치
    • 디지털 정보를 아날로그 신호로 변조(modulation)하여 송신하고, 수신된 아날로그 신호를 디지털 신호로 복조(demodulation)
  • 공유기(Home Router)
    • 여러 기기들이 인터넷에 연결될 수 있도록 하는 장치(LAN, wifi를 통해 기기들을 공유기에 연결)
    • 하나의 IP 주소로 동시에 여러기기들이 인터넷을 사용하게 하는 것이 가능.
    • 공유기에 연결된 기기들은 같은 네트워크 소속

  • 스위치(switch)
    • 같은 네트워크에 있는 기기들이 서로 통신할 수 있도록 하는 장치
    • 보통 공유기의 LAN 포트가 부족할 때 사용
    • '스위칭 허브' 혹은 '허브'라고 불림

 

  • Network : 컴퓨터나 기기들이 리소스를 공유하거나 데이터를 주고 받기 위해 유무선으로 연결된 통신 체계
  • LAN(Local Area Network) : 집, 회사, 건물 등 제한된 범위의 네트워크
    • LAN 구성 기술
      • Ethernet : 유선 통신
      • wireless LAN : 무선 통신(=wifi)
  • WAN(Wide Area Network) : 여러 LAN이나 다른 종류의 네트워크를 하나로 묶어서 통신이 되도록 만든 네트워크
    • Ex) 은행 ATM, wireless WAN, Internet(=> 4G, 5G)
  • Internet : 네트워크들의 네트워크, the World's Largest WAN, Global network
  • ISP(Internet Service Provider) : 일반 사용자, 회사 등이 인터넷을 사용하도록 인터넷 연결 서비스를 제공하는 업체
    • ex) AT&T , NTT, SKT, KT, LG 등
  • 서로 다른 ISP의 네트워크들이 서로 연결되어 있기 때문에 서로 다른 ISP의 사용자들이 통신할 수 있다.

 

  • ISP는 역할과 규모에 따라 tier가 나뉜다.
    • Tier 1 
      • 국제 범위의 네트워크 보유
      • 인터넷의 모든 네트워크 접근 가능
      • 인터넷의 중축, Backbone
      • Tier 1 간 트래픽 전송 비용 없음 - 청구해봤자 서로 상계되기 때문에
      • 그래서 인프라 자체로 수익을 얻음
    • Tier 2
      • 국가/지방 범위 네트워크 보유
      • Ex) SKT, KT, LG 등
      • 일반 사용자나 기업대상 서비스 제공
      • Tier 2간의 트래픽은 비용 없음
    • Tier 3
      • 작은 지역 범위 제공
      • 상위 ISP에게 비용을 내고 인터넷 트래픽 구매하여 서비스
      • Tier 2가 모든 지역을 커버하지 못하는 미국같은 넓은 지역에서 존재하는 서비스

  • ISP 네트워크 간에는 Router를 이용하여 연결한다.
    • Router : 목적하는 네트워크에 데이터를 보내는 장치
  • 네트워크를 이루는 각각의 장치들을 Node라고 부른다. PC, 공유기, 모뎀, 라우터 등이 모두 Node이다.
  • 네트워크의 끝에 있는 노드(핸드폰, PC 등) : End system, Host
    • 네트워크를 사용하기 위한 목적
    • Client(요청하는 host)와 Server(제공하는 host)로 역할이 나뉨

 

728x90
728x90

백업과 복구

  •  백업
    • 온라인 백업 : 데이터베이스 운영 상황에서 백업 => BEGIN BACKUP과 END BACKUP 사이에 변경이 일어난 블록을 Redo 로그에 기록하여 불완전 복구 방지
    • 콜드 백업 : 인스턴스 정지 후 백업
  • 복구
    • 장애(인스턴스) 복구 : 장애 발생 시 자동으로 실행되는 복구
    • 미디어 복구 : 사용자가 명시적으로 실행
    • 완전복구 : 최신 데이터까지 복구
    • 불완전 복구 : 특정 시점까지 복구
    • 데이터베이스/테이블스페이스/데이터파일/블록의 복구
  • 기본적인 복구 흐름
    1. 데이터베이스 손상 확인
    2. 재작업할 수 있도록 현재 상태 백업
    3. 필요한 데이터 파일과 아카이브 리두 로그 파일 restore
    4. 복구 실행

 

백그라운드 프로세스의 동작과 역할

  • DBWR(DBW) : 이미 변경된 데이터를 캐시에서 디스크로 기록
  • LGWR : commit 시 redo 로그를 기록
  • PMON : 서버 프로세스가 비정상 종료 시 메모리나 프로세스 정리 => 세션 및 프로세스 정리, 내부 락 해제 등
    • PMON이 인스턴스의 정보를 정기적으로 리스너에게 전달
  • SMON : 공간 청소 - 테이블 스페이스 빈 공간 합치기, 필요 이상의 undo 세그먼트 정리, 임시 세그먼트 정리 등
  • ARCH : redo 로그 파일을 아카이브하여 아카이브 로그 파일로 보관
  • RECO : 분산 트랜잭션 해결
  • CKPT : 체크포인트 작업 시 DBWR에게 작업 신호를 보내고, 가장 최신의 컨트롤 파일과 데이터 파일의 헤더에 체크포인트 기록

 

 

728x90

+ Recent posts