일반적인 숫자 단위 컴퓨터 숫자 단위
영문(한글) 기호
bit () 1 b 1
1 1
Byte (바이트) 10 B 2^3
10 8
Kilobyte (킬로 바이트) 1,000^1 = 10^3 KB 1,024 = 2^10
1,000 1,024
Megabyte (메가 바이트) 1,000^2 = 10^6 MB 1,024^2 = 2^20
1,000,000 1,048,576
Gigabyte (기가 바이트) 1,000^3 = 10^9 GB 1,024^3 = 2^30
1,000,000,000 1,073,741,824
Terabyte (테라 바이트) 1,000^4 = 10^12 TB 1,024^4 = 2^40
1,000,000,000,000 1,099,511,627,776
Petabyte (페타 바이트) 1,000^5 = 10^15 PB 1,024^5 = 2^50
1,000,000,000,000,000 1,125,899,906,842,624
Exabyte (엑사 바이트) 1,000^6 = 10^18 EB 1,024^6 = 2^60
1,000,000,000,000,000,000 1,152,921,504,606,846,976
Zettabyte (제타 바이트) 1,000^7 = 10^21 ZB 1,024^7 = 2^70
1,000,000,000,000,000,000,000 1,180,591,620,717,411,303,424
Yottabyte (요타 바이트) 1,000^8 = 10^24 YB 1,024^8 = 2^80
1,000,000,000,000,000,000,000,000 1,208,925,819,614,629,174,706,176
Vrontobyte (브론토 바이트) 1,000^9 = 10^27 VB 1,024^9 = 2^90
1,000,000,000,000,000,000,000,000,000 1,237,940,039,285,380,274,899,124,224
Geobyte (지오 바이트) 1,000^10 = 10^30 GB 1,024^10 = 2^100
1,000,000,000,000,000,000,000,000,000,000 1,267,650,600,228,229,401,496,703,205,376

 

모달창에서 동적으로 생성되는 inputbox에 ajax로 db의 상품을 like 로 긁어와서 autocomplete 뿌려주려고 함.

모달창의 내역부분에 autocomplete를 붙여 놨더니, 보이지도 않는 dim 처리 되어있는 좌상단에 선택콤포넌트가 숨어있음

TASK

1) 숨어있는 autocomplete 의 머리 끄덩이를 잡고 팝업창 위로 끌어내자!

2) input box를 클릭하면 autocomplete 셀렉트박스가 나오도록

 

 

html -> section 부분은 모달입NI다.

<!-- [D]팝업 : w:1080 / pop_container 최대 높이값 865 : 865이상 컨텐츠가 들어가면 자동 세로 스크롤 생김 (최소해상도:1280:1024 기준)  -->
<section id="popEstimateWrite" class="pop_wrap pop_wrap_wid1">
	<tbody id="prodList" />
</selection>

 

js -> "모달창에 autocomplete 붙이는 법" 1번과 2번을 잘 보세요.

$(document).ready(function () {
    // 견적서등록 빨간라인 중 거래명세서내역 그리기
    const t1 = "<td><span class='input_box2'><input type='text' placeholder='' class='input_txt3 align_l' title=";
    const t2 = "<td><span class='input_box2'><input type='text' placeholder='' class='input_txt3 align_cn' title=";
    const t3 = "<td><span class='input_box2'><input type='text' placeholder='' class='input_txt3 align_r' title=";
    const t4 = "></span></td>";
    const h1 = "<tbody id='prodList'>";
    let h2 = (id) => {
        return "<tr>"
            + t2 + "'월'       id='month_"            + id + "' name='month'            numberOnly" + t4
            + t2 + "'일'       id='day_"              + id + "' name='day'              numberOnly" + t4
            + t1 + "'내역'     id='prodNm_"           + id + "' name='prodNm'                     " + t4
            + t2 + "'규격'     id='standard_"         + id + "' name='standard'                   " + t4
            + t3 + "'수량'     id='shippingQuantity_" + id + "' name='shippingQuantity' numberOnly" + t4
            + t3 + "'회수수량' id='returnQuantity_"   + id + "' name='returnQuantity'   numberOnly" + t4
            + t3 + "'재고수량' id='bucketQuantity_"   + id + "' name='bucketQuantity'   numberOnly" + t4
            + t3 + "'단가'     id='unitPrice_"        + id + "' name='unitPrice'        numberOnly" + t4
            + t3 + "'공급가액' id='supply_"           + id + "' name='supply'           numberOnly" + t4
            + t3 + "'세액'     id='tax_"              + id + "' name='tax'              numberOnly" + t4
            + t3 + "'총액'     id='totalPrice_"       + id + "' name='totalPrice'       numberOnly" + t4
            + "</tr>";
    }
    const h3 = "</tbody>";
    let tmp;
    for (let i=1; i<=8; i++) {
        tmp = tmp + h2(i);
    }
    $("#prodList").replaceWith(h1 + tmp + h3);

    // input tag에 숫자(+천단위 콤마)만 받겠음
    $("input:text[numberOnly]").on("keyup", function() {
        $(this).val(priceToString($(this).val().replace(/[^0-9]/g,"")));
    });

    //---------------------------------------------------------------------------------------------
    // 품목 autocomplete
    //---------------------------------------------------------------------------------------------
    $('input[name=prodNm]').focus(function() {
        var e = $.Event("keydown", { keyCode: 40 }); // 아래쪽화살표 keyCode
        $(this).trigger(e);
    });
    $('input[name=prodNm]').autocomplete({
        source : function( request, response ) { // 자동완성 대상이 되고자 하는 데이터를 입력하는 부분
            $.ajax({
                async: false,
                type: "get",
                url: "/api/goods/salesSlip?perPage=999",
                contentType: "application/json; charset=utf-8",
                data : {
                    prodNmLike: request.term
                },
                dataType: "json",
                success: function (result) {
                    const r = result.data.contents;
                    //서버에서 json 데이터 response 후 목록에 추가
                    response(
                        $.map(r, function(item) { // json[i] 번째 에 있는게 item 임.
                            return {
                                label: item.prodNm,         // 목록에 표시되는 값
                                value: item.prodNm          // 선택 시 input창에 표시되는 값
                            }
                        })
                    );
                },
                error : function() {                       // 실패
                    alert("오류가 발생했습니다.");
                }
            });
        },    // source 는 자동 완성 대상
        focus : function(event, ui) {   // autocomplete를 한글과 사용할때 커서를 사용해서 아이템을 선택하면 나머지가 사라져 버리는 버그
            return false;               // return false; 또는 event.preventDefault(); 를 사용해서 이벤트를 무시하게 하는 것
        },
        select: function (event, ui) {  // 아이템 선택시 실행됩니다. ui.item 이 선택된 항목을 나타내는 객체입니다.
            // $($(this).attr('id')).val(ui.item.label + " / " + ui.item.value);
            console.log("SELECTED : (" + $(this).attr('id')) + ") " + ui.item.label + " / " + ui.item.value);
        },
        minLength: 0,                   // 자동완성 기능이 발생하는 최소 글자 수, 0이면 화살표키보드 아래로 했을때 selectbox 나옴
        delay: 300,                     // input Field에 글자를 쓰고 autocomplete 창이 뜰 때까지 걸리는 시간 (ms)
        autoFocus: true,                // 첫 번째 항목 자동 포커스 발생 여부 설정 (default: false)
        classes : {                     // 위젯 요소에 추가 할 클래스를 지정
            'ui-autocomplete' : 'highlight'
        },
        // disabled: true,              // 자동완성 기능 끄기
        position: {
            my: "right top",
            at: "right bottom",
            //---------------------------------------------------------------------------------------------
            // [02. 모달창에 autocomplete 붙이는 법]
            of: $(this).attr('id') // 클릭한 id의 엘리먼트 밑에 선택창이 나오도록 지시
            //---------------------------------------------------------------------------------------------
        },
        close : function(event){         // 자동완성창 닫아질때 호출
            // console.log(event);
        }
    // UI를 마음대로 변경하는 부분 (기본 tag가 li로 되어 있음)
    }).autocomplete( "instance" )._renderItem = function( ul, item ) {
        return $( "<li>" )
            .append( "<div>" + item.label + "</div>" )
            .appendTo( ul );
    };

    //---------------------------------------------------------------------------------------------
    // [01. 모달창에 autocomplete 붙이는 법]
    // bootstrap modal, 레이어 팝업 위에 검색창을 띄우고 싶은데, 자동 완성 부분이 이상한 곳에 붙어있다면
    // appendTo 옵션에 모달창 id를 부여하여 modal 레이어 위에 autocomplete 가 보이도록 함 
    //---------------------------------------------------------------------------------------------
    $('input[name=prodNm]').autocomplete("option", "appendTo", $("#popEstimateWrite"));

});

 

jpa -> goods.prodNm.like 부분으로 검색

@Override
public List<Goods.Response> findListByRequest(Goods.Request request) {
  QGoods goods = QGoods.goods;
  QAgency qAgency = QAgency.agency;
  JPAQuery<Goods.Response> query = jpaQueryFactory.select(Projections.fields(Goods.Response.class,
          goods.id,
          goods.prodNm,
          goods.stockPrice,
          goods.salePrice,
          goods.agentId,
          goods.prodRtnYnMethod,
          goods.useYn,
          goods.prodUnitNmMethod,
          goods.createdAt,
          ExpressionUtils.as(
                  JPAExpressions
                          .select(qAgency.agencyName)
                          .from(qAgency)
                          .where(qAgency.id.eq(goods.agentId))
                  , "agentNm")
  ));
  query.from(goods);
  if (null != request.getAgentId() && 0 != request.getAgentId()) {
    query.where(goods.agentId.eq(request.getAgentId())
    );
  }
  if (!StringUtils.isNullOrEmpty(request.getProdNmLike())) {
    query.where(goods.prodNm.like("%" + request.getProdNmLike() + "%")
    );
  }

  List<Goods.Response> contents = query
          .orderBy(goods.prodNm.asc())
          .fetch();/*fetch 사용*/

  /*total Count 쿼리를 직접 날린다.*/
  long total = query.fetchCount();

  return contents;

}

 

두 부분만 주의하면 됨

of: $(this).attr('id') // 클릭한 id의 엘리먼트 밑에 선택창이 나오도록 지시
$('input[name=prodNm]').autocomplete("option", "appendTo", $("#popEstimateWrite"));

소스코드

https://nomadcoders.co/nextjs-fundamentals/lobby

 

NextJS 시작하기 – 노마드 코더 Nomad Coders

The React Framework for Production

nomadcoders.co

01. aws.amazon.com/ko/free 가입
    - choickey76@naver.com
 
02. Region을 아시아-서울 로 설정
 
03. 프리티어로 인스턴스 생성 : t2.micro



    - 우분투로 설정

    - 키페어는 pem 으로 받고, putty-gen으로 암호없이 ppk생성
      (pem 파일의 소유자와 권한을 수정하여 윈도우커맨드에서 ec2접속해 보기)
    - 보안그룹 생성 : MySQL, SSH, HTTP, HTTPS
    - 볼륨 30G 설정
    - 용량확인 명령어   : https://velog.io/@hyeonseop/ec2-용량-full일-때-대처법
      df -gT 또는 lsblk : 프로젝트 중간에 용량을 증설하면 재기동 해줘야 함
 
04. 윈도우커맨드에서 ec2 접속하기

    - pem파일 User만 읽기권한 주기 (chmod 400 설정) - 이걸안하면 권한제어에 걸려서 로긴안됨
      [X] ubuntu@ec2.ap-northeast-2.compute.amazonaws.com: Permission denied (publickey).

    - 키페어 권한 변경

      icacls.exe DonzBoxKey.pem /reset
      icacls.exe DonzBoxKey.pem /grant:r %username%:(R)
      icacls.exe DonzBoxKey.pem /inheritance:r

    - 접속안내 : 인스턴스 -> 연결 -> 안내보기

      ssh -i ".......\EC2 KeyPair\DonzBoxKey.pem" ubuntu@ec2.ap-northeast-2.compute.amazonaws.com
 
05. putty 설정시 ppk 파일로 접속

    - d2coding으로 폰트변경

    - Ubuntu AMI       : ubuntu
      Amazon Linux2    : ec2-user
      Amazon Lunux AMI : ec2-user
      Debian AMI       : admin or root
      Fedora AMI       : ec2-user or fedora
 
06. 리눅스 버전 확인

    - 리눅스의 배포판 버전 확인

      1) $ grep . /etc/*-release
      2) $ cat /etc/*-release | uniq

    - 리눅스 커널 버전 확인

      1) uname
      2) uname -r
      3) cat /proc/version
 
07. git, zsh 설치

    - git설치 : apt-get update , apt-get install git -y , git version

    - zsh설치 : https://codingrabbit.tistory.com/28
 
08. fileziller 접속

    - sftp로 발급받은 key파일 지정하여 접속
 
09. MySQL 설치

    1) root 권한으로 실행

       $ sudo su

    2) mysql 설치

       $ apt-get update
       $ apt-get install mysql-server

    3) 외부접속허용

       # vi /etc/mysql/mysql.conf.d/mysqld.cnf
         bind-address=0.0.0.0 으로 수정

    4) 유저생성/권한설정

       $ mysql -u root -p
       # CREATE USER 'donz'@'%' IDENTIFIED BY '비밀번호';  -- %는 모든 곳에서 접속 허용
       # GRANT ALL PRIVILEGES ON *.* TO 'donz'@'%' WITH GRANT OPTION;
       # SHOW GRANTS FOR 'donz'@'%';
       # FLUSH PRIVILEGES;

    5) 방화벽설정 및 서비스 재시작

       $ ufw allow out 3306/tcp
       $ ufw allow in 3306/tcp
       $ service mysql restart

    6) DB생성

       # CREATE DATABASE {사용할 DB명};
       # SHOW DATABASES;

    7) 인스턴스 확인

       $ apt-get install net-tools
       $ netstat -tap | grep mysql
 
10. 외부에서 EC2에 설치한 MySQL에 접속
    ┌────────────────────────────┐
    │ 삽질금지 : 외부에서 MySQL 접속시 SSL이니 SSH니 설정필요 없음 │
    └────────────────────────────┘
    1) DBeaver 접속
       Public Key Retrieval is not allowed 에러 발생
       에러 해결 : https://deviscreen.tistory.com/85
                   Driver properties -> allowPublicKeyRetrieval=true

    2) MySQL Workbench 접속

       Public Key Retrieval is not allowed 에러 발생
       에러 해결 : https://sailer.tistory.com/entry/Mysql-Workbench-접속-에러-ssl-connection-error
                   SSL -> Use SSL : No
 
11. root 계정 활성화

    $ sudo passwd root

    $ sudo vi /etc/ssh/sshd_config
      #PermitRootLogin yes 부분의  주석(#)을 삭제하고 저장
    $ sudo mkdir /root/.ssh
    $ sudo cp /home/ec2-user/.ssh/authorized_keys /root/.ssh
    $ sudo systemctl restart sshd
 
 
 
 

 

 

글 남기는 시점 : 2022년 6월20일

 

EC2 Instance : Redhat free tier

version : Linux version 4.18.0-372.9.1.el8.x86_64 (mockbuild@x86-vm-09.build.eng.bos.redhat.com) (gcc version 8.5.0 20210514 (Red Hat 8.5.0-10) (GCC)) #1 SMP Fri Apr 15 22:12:19 EDT 2022

Oracle : oracle-database-ee-19c-1.0-1.x86_64.rpm

https://www.oracle.com/database/technologies/oracle-database-software-downloads.html

01. aws.amazon.com/ko/free 가입
 
02. Region을 아시아-서울 로 설정
 
03. 프리티어로 인스턴스 생성 : t2.micro
    - 레드햇 설정 (★★★ 조언 : 괜히 다른 OS로 삽질하지 말고 처음부터 레드햇으로 설치하세요 ★★★)
    - 볼륨 20G 설정
    - 용량확인 명령어   : https://velog.io/@hyeonseop/ec2-용량-full일-때-대처법
      df -gT 또는 lsblk : 프로젝트 중간에 용량을 증설하면 재기동 해줘야 함
 
04. putty 설정시 ppk 파일로 접속
    - d2coding으로 폰트변경
    - Ubuntu AMI       : ubuntu
      Amazon Linux2    : ec2-user
      Amazon Lunux AMI : ec2-user
      Debian AMI       : admin or root
      Fedora AMI       : ec2-user or fedora
 
05. 리눅스 버전 확인
    - 리눅스의 배포판 버전 확인
      1) $ grep . /etc/*-release
      2) $ cat /etc/*-release | uniq
    - 리눅스 커널 버전 확인
      1) uname
      2) uname -r
      3) cat /proc/version
 
06. root 계정 활성화
    $ sudo passwd root
    $ sudo vi /etc/ssh/sshd_config
      #PermitRootLogin yes 부분의  주석(#)을 삭제하고 저장
    $ sudo mkdir /root/.ssh
    $ sudo cp /home/ec2-user/.ssh/authorized_keys /root/.ssh
    $ sudo systemctl restart sshd
    ┌──────────────────────────────────┐
    │ 이후 root로 재접속하여 작업 진행
    └──────────────────────────────────┘
 
07. git, zsh 설치
    - git설치 : sudo yum update -y , sudo yum install git -y , git version
    - zsh설치 : https://codingrabbit.tistory.com/28
 
08. fileziller 접속
    - sftp로 발급받은 key파일 지정하여 접속
 
09. oracle 환결설정
    - 레드햇에 오라클 설치 참조 : https://pliss.tistory.com/105
    - EC2 보안그룹에 1521 포트 추가

    - (Free Tier 메모리 부족으로 필요시 설정함) swap memory설정
      $ cd /
      $ mkdir /swap
      $ dd if=/dev/zero of=/swap/swapfile bs=1024 count=2097152
      $ cd /swap
      $ mkswap swapfile
      $ swapon swapfile

    - 권한그룹설정 (oracle rpm 은 oinstall 이라는 그룹의 oracle 이라는 사용자로 설치되기 때문에 미리 계정 생성)
      $ cd /home
      $ groupadd oinstall
      $ groupadd dba
      $ tail /etc/group
      $ useradd -g oinstall -G dba oracle
      $ passwd oracle
      $ systemctl restart sshd

    - 커널 설정
      $ vi /etc/sysctl.conf
        fs.aio-max-nr = 1048576
        fs.file-max = 6815744
        #kernel.shmall = 2097152
        #kernel.shmmax = 536870912
        kernel.shmmni = 4096
        kernel.sem = 250 32000 100 128
        net.ipv4.ip_local_port_range = 9000 65500
        net.core.rmem_default = 262144
        net.core.rmem_max = 4194304
        net.core.wmem_default = 262144
        net.core.wmem_max = 1048576

    - 자원 제한 설정
      $ vi /etc/security/limits.conf
        oracle soft nproc 2047
        oracle hard nproc 16384
        oracle soft nofile 1024
        oracle hard nofile 65536
        oracle soft stack 10240

    - 전체적용 및 확인
      $ reboot
      $ /sbin/sysctl –p

    ★ oracle 로 사용자전환하여 하위 작업 진행 ★
     ┌───────────────┐
     │ $ su - oracle
     └───────────────┘
    - 오라클 환경 변수 설정
      $ vi /home/oracle/.bash_profile
        ORACLE_BASE=/opt/oracle
        ORACLE_SID=XE
        ORACLE_HOME=$ORACLE_BASE/product/19c/dbhome_1
        ORACLE_HOME_LISTNER=$ORACLE_HOME/bin/lsnrctl
        PATH=$ORACLE_HOME/bin:$PATH
        export PATH
        export ORACLE_BASE
        export ORACLE_SID
        export ORACLE_HOME
        export ORACLE_LISTNER
        export TMP=/tmp
        export TMPDIR=$TMP
      $ source /home/oracle/.bash_profile
 
10. oracle 설치 (Ubuntu)
    ┌─디펜던시 설치 (우분투일 경우)───────────────────────────

     │
     │ 1) 우분투 디스크 늘려주기 : 안늘려주면 2기가짜리 rpm -> deb 변환하다가 "No space left on device" 에러남
     │    $ lsblk -f
     │      NAME     FSTYPE   FSVER LABEL           UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
     │      loop0    squashfs 4.0                                                              0   100% /snap/amazon-ssm-agent/5656
     │      loop1    squashfs 4.0                                                              0   100% /snap/core18/2409
     │      loop2    squashfs 4.0                                                              0   100% /snap/core20/1518
     │      loop3    squashfs 4.0                                                              0   100% /snap/lxd/22923
     │      loop4    squashfs 4.0                                                              0   100% /snap/snapd/16010
     │      xvda
     │      ├─xvda1  ext4     1.0   cloudimg-rootfs 767f2b75-d030-4999-951c-d4ab6b37f31f    7.2G    53% /
     │      ├─xvda14
     │      └─xvda15 vfat     FAT32 UEFI            83EA-FFE2                              99.1M     5% /boot/efi
     │
     │    $ mount -o size=10M,rw,nodev,nosuid -t tmpfs tmpfs /tmp
     │    $ xfs_growfs -d /
     │      xfs_growfs: / is not a mounted XFS filesystem
     │    $ resize2fs /dev/xvda1                          : ec2에서 용량 늘려 설정 후 ex4 파일 시스템일 경우 resize2fs 명령어로 적용
     │      resize2fs 1.46.5 (30-Dec-2021)
     │      The filesystem is already 4165883 (4k) blocks long.  Nothing to do!
     │    $ df -h
     │      Filesystem      Size  Used Avail Use% Mounted on
     │      /dev/root        16G  8.1G  7.3G  53% /
     │      tmpfs           484M     0  484M   0% /dev/shm
     │      tmpfs           194M  844K  193M   1% /run
     │      tmpfs           5.0M     0  5.0M   0% /run/lock
     │      /dev/xvda15     105M  5.3M  100M   5% /boot/efi
     │      tmpfs            97M  4.0K   97M   1% /run/user/0
     │      tmpfs            10M     0   10M   0% /tmp
     │    $ umount /tmp
     │
     │ 2) 우분투 메모리 늘려주기
     │    $ dd if=/dev/zero of=/swapfile bs=128M count=32 : 스왑 파일의 읽기 및 쓰기 권한을 업데이트
     │    $ chmod 600 /swapfile                           : Linux 스왑 영역을 설정
     │    $ mkswap /swapfile                              : 스왑 공간에 스왑 파일을 추가하여 스왑 파일을 즉시 사용할 수 있도록
     │    $ swapon /swapfile                              : 프로시저가 성공적인지 확인
     │    $ swapon -s                                     : /etc/fstab 파일을 편집하여 부팅 시 스왑 파일을 시작
     │    $ sudo vi /etc/fstab                            : 재부팅 후에도 적용되도록 파일 끝에 다음 줄을 새로 추가
     │      /swapfile swap swap defaults 0 0
     │    $ swapon --show
     │    $ free -h
     │ - 스왑파일삭제
     │    $ swapoff -v /swapfile             : 스왑 비활성
     │    $ vi /etc/fstab                    : fstab파일 오픈
     │    $ /swapfile swap swap defaults 0 0 : 추가했던 라인 삭제
     │    $ rm /swapfile                     : 스왑 파일 삭제
     │
     │ 3) apt-get으로 yum, python, java 설치
     │    $ apt-get update && sudo apt-get upgrade        : apt(Advanced Packaging Tools) 은 리눅스에서 패키지 관리를 담당
     │    $ apt-get update                                : 설치 되어있는 패키지들의 새로운 버젼이 있는지 확인할 때 해당 명령어를 사용합니다
     │    $ apt-get upgrade                               : 위에 있는 apt-get update를 통해서 확인한 패키지들의 최신 버전에 따라서 패키지들의 버전을 업그레이드 해주는 명령어입니다
     │    $ apt install yum
     │    $ apt-get -y install yum
     │    $ apt update
     │    $ apt -y install yum
     │    $ apt-get update
     │    $ apt-get install yum
     │    $ apt install python-lzma
     │    $ apt install python-sqlitecachec
     │    $ apt install python-urlgrabber
     │    $ apt install python-pycurl
     │    $ apt install python-urlgrabber
     │    $ apt-get install openjdk-11-jdk
     │    $ javac -version 
     │    $ vi  ~/.bashrc
     │      export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))
     │      export PATH=$PATH:$JAVA_HOME/bin 
     │    $ source ~/.bashrc                              : 현재 실행중인 shell에 즉시 적용 (새로 실행한 shell에서는 필요없음)
     │    $ echo $JAVA_HOME
     │
     │ 4) Alien 버전업 설치
     │    Alien은 레드햇 패키지(.rpm) 를 데비안 패키지(.deb) 로 변환해 주는 프로그램
     │    RPM은 RedHat Package Manager 로 Linux Standaard Base의 표준 패키지포맷 중 하나이며,
     │    레드헷 계열(Redhat, CentOS, Fedora)계열의 리눅스에서 사용.
     │    반면 Debian, Ubuntu 같은 데비안 계열에서는 deb 포맷의 파일을 사용하고,
     │    apt-get라는 패키지관리도구를 이용하는데, 확장자가 .rpm 인 파일은 apt-get 으로 설치가 되지 않아 
     │    이때 Alien을 이용하면 rpm파일을 바로 설치하거나 deb파일로 변환하여 설치가 가능함
     │
     │    ★ 이전 alien 이 문제가 있어 재설치 ★
     │    $ uname -i        : 서버 버젼 확인 64 bit 
     │    $ apt-get install -y alien libaio1 unixodbc
     │    $ apt-get --fix-broken install
     │    $ apt-get remove alien
     │    $ curl -O http://archive.ubuntu.com/ubuntu/pool/main/a/alien/alien_8.90_all.deb
     │    $ dpkg -i alien_8.90_all.deb : dpkg(Debian Package) 패키지
     │
     │ 5) 오라클 rpm -> dev 변경
     │    $ alien --scripts -d  oracle-database-preinstall-21c-1.0-1.el7.x86_64.rpm : 파일변환 rpm -> deb
     │    $ alien     -i -c -v  oracle-database-preinstall-21c-1.0-1.el7.x86_64.rpm : 파일변환없이 바로설치
     │    $ apt-get     install dpkg-dev debhelper build-essential
     │    $ yum -y localinstall oracle-database-preinstall-21c-1.0-1.el7.x86_64.rpm
     │
     │    $ dpkg --install ora*.deb
     └─────────────────────────────────────────

 
10. oracle 설치
    -  EC2에서 사용가능한 ORACLE 버전 확인 : https://teratail.com/questions/318951

    -  다운로드 : https://www.oracle.com/database/technologies/oracle-database-software-downloads.html
                    -> oracle-database-ee-19c-1.0-1.x86_64.rpm
                    https://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64/index_src.html
                    -> oracle-database-preinstall-19c-1.0-3.el7.x86_64.rpm
     ┌───────────────┐
     │ $ su - root 
     └───────────────┘
    - 내컴퓨터로 받은 오라클 파일을 EC2로 옮긴 후 파일 소유자/그룹 변경
       $ chown oracle /home/oracle/install/oracle-database-*
       $ chown :oinstall /home/oracle/install/oracle-database-*
    -  디펜던시 설치
       $ yum update
       $ yum install -y http://mirror.centos.org/centos/7/os/x86_64/Packages/compat-libcap1-1.10-7.el7.x86_64.rpm
       $ yum -y install bc bind-utils binutils glibc-devel ksh libnsl libaio libaio-devel libstdc++-devel make net-tools nfs-utils smartmontools sysstat unzip xorg-x11-utils xorg-x11-xauth
    - 오라클 rpm 설치
       $ rpm -Uvh /home/oracle/install/oracle-database-preinstall-19c-1.0-3.el7.x86_64.rpm

              warning: /home/oracle/install/oracle-database-preinstall-19c-1.0-3.el7.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID ec551f03: NOKEY
              Verifying...                          ################################# [100%]
              Preparing...                          ################################# [100%]
              Updating / installing...
                 1:oracle-database-preinstall-19c-1.################################# [100%]

       $ rpm -Uvh /home/oracle/install/oracle-database-ee-19c-1.0-1.x86_64.rpm

              warning: /home/oracle/install/oracle-database-ee-19c-1.0-1.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID ec551f03: NOKEY
              Verifying...                          ################################# [100%]
              Preparing...                          ################################# [100%]
              Updating / installing...
                 1:oracle-database-ee-19c-1.0-1     ################################# [100%]
              [INFO] Executing post installation scripts...
              [INFO] Oracle home installed successfully and ready to be configured.
              To configure a sample Oracle Database you can execute the following service configuration script as root: /etc/init.d/oracledb_ORCLCDB-19c configure
 
11. oracle 설정
    - 환경변수 설정
      $ cd /opt/oracle/product/19c/dbhome_1/network/admin
      $ vi listener.ora
        SID_LIST_LISTENER =
            (SID_LIST =
                (SID_DESC =
                    (SID_NAME = PLSExtProc)
                    (ORACLE_HOME = /opt/oracle/product/19c/dbhome_1)
                    (PROGRAM = extproc)
                )
                (SID_DESC =
                    (GLOBAL_DBNAME = XE)
                    (ORACLE_HOME = /opt/oracle/product/19c/dbhome_1)
                    (SID_NAME = XE)
                    (SERVICE_NAME = XE)
                )
            )

        LISTENER =
            (DESCRIPTION_LIST =
                (DESCRIPTION =
                    (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC_FOR_XE))
                    (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
                )
            )

        DEFAULT_SERVICE_LISTENER = (XE)

      $ vi tnsnames.ora
        XE =
            (DESCRIPTION =
                (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
                (CONNECT_DATA =
                    (SERVER = DEDICATED)
                    (SERVICE_NAME = XE)
                )
            )

        EXTPROC_CONNECTION_DATA =
            (DESCRIPTION =
                (ADDRESS_LIST =
                    (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC_FOR_XE))
                )
                (CONNECT_DATA =
                    (SID = PLSExtProc)
                    (PRESENTATION = RO)
                )
            )
 
12. oracle 기동
    $ lsnrctl -> start -> status

    - 기동화면
    $ lsnrctl
             LSNRCTL for Linux: Version 19.0.0.0.0 - Production on 19-JUN-2022 15:44:05
             Copyright (c) 1991, 2019, Oracle.  All rights reserved.
             Welcome to LSNRCTL, type "help" for information.

    LSNRCTL> start

             Starting /opt/oracle/product/19c/dbhome_1/bin/tnslsnr: please wait...

             TNSLSNR for Linux: Version 19.0.0.0.0 - Production
             System parameter file is /opt/oracle/product/19c/dbhome_1/network/admin/listener.ora
             Log messages written to /opt/oracle/diag/tnslsnr/ip-172-31-7-255/listener/alert/log.xml
             Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC_FOR_XE)))
             Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521)))

             Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC_FOR_XE)))
             STATUS of the LISTENER
             ------------------------
             Alias                     LISTENER
             Version                   TNSLSNR for Linux: Version 19.0.0.0.0 - Production
             Start Date                19-JUN-2022 15:44:08
             Uptime                    0 days 0 hr. 0 min. 0 sec
             Trace Level               off
             Security                  ON: Local OS Authentication
             SNMP                      OFF
             Default Service           XE
             Listener Parameter File   /opt/oracle/product/19c/dbhome_1/network/admin/listener.ora
             Listener Log File         /opt/oracle/diag/tnslsnr/ip-172-31-7-255/listener/alert/log.xml
             Listening Endpoints Summary...
               (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC_FOR_XE)))
               (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521)))
             Services Summary...
             Service "PLSExtProc" has 1 instance(s).
               Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service...
             Service "XE" has 1 instance(s).
               Instance "XE", status UNKNOWN, has 1 handler(s) for this service...
             The command completed successfully

    LSNRCTL> status

             Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC_FOR_XE)))
             STATUS of the LISTENER
             ------------------------
             Alias                     LISTENER
             Version                   TNSLSNR for Linux: Version 19.0.0.0.0 - Production
             Start Date                19-JUN-2022 15:44:08
             Uptime                    0 days 0 hr. 0 min. 11 sec
             Trace Level               off
             Security                  ON: Local OS Authentication
             SNMP                      OFF
             Default Service           XE
             Listener Parameter File   /opt/oracle/product/19c/dbhome_1/network/admin/listener.ora
             Listener Log File         /opt/oracle/diag/tnslsnr/ip-172-31-7-255/listener/alert/log.xml
             Listening Endpoints Summary...
               (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC_FOR_XE)))
               (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521)))
             Services Summary...
             Service "PLSExtProc" has 1 instance(s).
               Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service...
             Service "XE" has 1 instance(s).
               Instance "XE", status UNKNOWN, has 1 handler(s) for this service...
             The command completed successfully
 
13. SQL PLUS 확인
    $ ........................ 알아보는 중
 
99. 추가작업
    - EC2(Linux) 사용자 별 .pem 파일 생성하기 및 ec2-user 비활성화
      https://junhyeong-jang.tistory.com/10

 

MICHAEL LEARNS TO ROCK - It’s Only Love (2007년)

(THE LIVE MUSICAL ADVENTURES)


It’s been the story of my live
   (내 삶의 이야기에요)
The things I love I have to sacrifice
   (내가 사랑하는 것들은 내가 희생해야 해요)
And now there’s nothing left of me
   (이젠 내게 남은 건 아무것도 없어)
Feeling invisible
   (보이지 않는 느낌)
In need of a miracle
   (기적이 필요해)
   
④ [후렴]

Another castle in the sky
   (하늘의 또 다른 성)
Another dream I have to push aside
   (내가 밀어내야 하는 또 다른 꿈)
And now I kneel before the truth
   (이젠 진실 앞에 무릎을 꿇고)
To face the unthinkable
   (생각지도 못한 일에 직면했어)
Feeling so breakable
   (깨지기 쉬운 기분)

 [후렴]

Trying to forget about you now
   (이젠 널 잊으려고 해)
Trying to move on but I don’t know how
   (넘어가려고 하는데 어떻게 해야 할지 모르겠어)
It’s only love that I feel
   (내가 느끼는 건 오직 사랑이야)

 [후렴]


④ [후렴]
I try to remember, it’s only love
   (기억하려고 노력하는데, 그건 오직 사랑이야)
We had to surrender, there’s no more us
   (우린 항복해야 했어 우린 이제 없어)
The world keeps on turning and I carry on
   (세상은 계속 돌아가고 난 계속해)
The dream of another you
   (또 다른 너의 꿈)
The song that I hold on to
   (내가 들고 있는 노래는)

 

<style>
    .video-container {
        position: relative;
        padding-bottom: 56.25%;
        padding-top: 30px;
        height: 0;
        overflow: hidden;
    }
     
    .video-container iframe,
    .video-container object,
    .video-container embed {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
    }
</style>
<div class="video-container">
  <iframe width="560" height="315" src="https://www.youtube.com/embed/HVkfKdIYf28?&amp;playlist=HVkfKdIYf28&amp;loop=1&amp;autoplay=1&amp;modestbranding=1" title="MLTR - Only Love" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
  </iframe>
</div>

 

Someday(1995)/ Michael Learns to Rock


In my search for freedom
  (자유와 마음의 평화를)
And peace of mind
  (찾아 다니면서)
I've left the memories behind
  (추억들은 뒤로 했어)
Wanna start a new life
  (새로운 삶을 시작하고 싶어)
But it seems to be rather absurd
  (그런데 지금도 늘 당신 생각 하고)
When I know the truth
  (있다는 사실 생각하니)
Is that I always think of you
  (왠지 말도 안되는 짓 같아)
② [Chorus:][후렴:]
Someday someway
  (언젠간 언젠간)
Together we will be baby
  (우리 하나가 될거야, 내 사랑)
I will take and you will take your time
  (나는 내 시간을, 당신은 당신 시간을 갖겠지)
We'll wait for our fate
  (우린 우리 운명을 기다리겠지)
Cos' nobody owns us baby
  (그 누구도 우리를 소유할 순 없으니까)
We can shake we can shake the rock
  (우리는 흔들 수 있을 거야, 바위조차도)


Try to throw the picture out of my mind
  (나 내 마음에서 그 그림을 지우려 해)
Try to leave the memories behind
  (옛 추억들을 잊으려 해)
Here by the ocean
  (여기 바닷가에서)
Wave's carry voices from you
  (파도들은 당신 목소리를 실어 날라)
Do you know the truth
  (당신 혹 이거 알아?)
I am thinking of you too
  (나 역시 당신 생각하고 있다는 거)



④ (repeat Chorus)(후렴 반복)
The love we had together
  (우리가 함께한 사랑은)
Just fades away in time
  (시간과 함께 사라져가)
And now you've got your own world
  (그리고 이제 당신은 당신 세계를 갖고 있고)
And I guess I've got mine
  (난 내 세계를 갖고 있고. 그런 것 같아)
But the passion that you planted
  (하지만 당신이 내 마음 한가운데)
In the middle of my heart
  (심어놓은 열정은)
Is a passion that will never stop
  (그 열정은 절대 멈추지 않을 거야)


<style>
    .video-container {
        position: relative;
        padding-bottom: 56.25%;
        padding-top: 30px;
        height: 0;
        overflow: hidden;
    }
     
    .video-container iframe,
    .video-container object,
    .video-container embed {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
    }
</style>
<div class="video-container">
  <iframe src="https://www.youtube.com/embed/__oCUzwL7i0?&amp;playlist=__oCUzwL7i0&amp;loop=1&amp;autoplay=1&amp;modestbranding=1" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" width="560" height="315" frameborder="0" allowfullscreen="" title="MLTR - Someday">
  </iframe>
</div>

go version go1.18 windows/amd64

구조 (출처: 노마드)

 
    main.go
    package main
    import (
        "fmt"
        dict "scraping/typeExample/main/detail"
    )

    func main() {
        // 이것은 Dictionary에 대한 Constructor가 아님!!!!!!
        dict := dict.Dictionary{"Donz": "I'm a boy"}
        dict["hello"] = "I'm find"
        fmt.Println("Setting :", dict)                 //-> Setting : map[Donz:I'm a boy hello:I'm find]

       // Search
       s, err := dict.Search("Donz")
       if err != nil {
           fmt.Println(" Search :", err)    //-> 
       } else {
           fmt.Println(" Search :", s)      //-> Search : I'm a boy
       }

       // Add
       addErr := dict.Add("Donz", "She's a beat")
       if addErr != nil {
           fmt.Println("    Add :", addErr)
           //-> Add : That word already exist
       }


       // Modify
       modifyErr := dict.Modify("Donz1", "He's Handsome")
       if modifyErr != nil {
           fmt.Println(" Modify :", modifyErr)
           //-> Modify : Can't modify non-existing word 
       } else {
           s, _ := dict.Search("Donz")
           fmt.Println(" Modify :", s)               //-> 
       }


       // Delete
       delErr := dict.Delete("Donz1")
       if delErr != nil {
           fmt.Println(" Delete :", delErr)
           //-> Delete : Can't delete non-existing word
       } else {
           _, err := dict.Search("Donz")
           if err != nil {
               fmt.Println(" Delete :", err)          //->
           }
       }
 }

 

    anything_banking_file.go
    package anything_dict_package
    import "errors"
    /*
       1) Dictionary는 map[string]string의 alias 일 뿐 struct가 아님    (예) type Momey int -> Money(1) -> int 1 과 같은 뜻
       2) struct 에만 method를 추가할 수 있는게 아님
       3) type 에도 method 를 추가할 수 있음                               (예) dictionary.Add() , dictionary.Delete()
    */
    type Dictionary map[string]string

    var (
        errNotFound   = errors.New("Can't find word ")
        errWordExists = errors.New("That word already exist")
        errCantModify = errors.New("Can't modify non-existing word")
        errCantDelete = errors.New("Can't delete non-existing word")
    )

    // Search method - dict.Search("word")
    func
 (d Dictionary) Search(word string) (stringerror) {
        defexist := d[word]
        if exist {
            return def, nil
        } else {
            return "", errNotFound
        }
    }



    // Add method - dict.Add("word", "def")
    func
 (d Dictionary) Add(word, def stringerror {
        _err := d.Search(word)
        switch err {
        case errNotFound:
            d[word] = def
        case nil:
            return errWordExists
        }
        return nil
    }

    // Modify method - dict.Modify("word", "def")
    func
 (d Dictionary) Modify(word, def stringerror {
        _err := d.Search(word)
        switch err {
        case errNotFound:
            return errCantModify
        case nil:
            d[word] = def
        }
        return nil
    }
    // Delete method - dict.Delete("word")
    func
 (d Dictionary) Delete(word stringerror {
        _err := d.Search(word)
        switch err {
        case errNotFound:
            return errCantDelete
        case nil:
            delete(d, word)
        }
        return nil
    }
 
mod.go
module scraping/typeExample/main

go 1.18

go version go1.18 windows/amd64

구조

 

main.go
package main

import (
    "fmt"
    banking "scraping/structExample/main/detail"
)

/* main의 의미 : 컴파일을 위해 필요한 것!
   명령어 go run main.go 뜻
   1. main package 찾음
   2. main function 찾고 실행 */
func main() {

    // fmt : formattiing  을 위한 패키지, Print의 "P"가 대문자인 이유는 function을 export 하겠다는 의미
    fmt.Println("GO 에서 Constructor 와 Method 사용")

    // [01] GO 에서 Constructor를 만드는 방법
    a := banking.NewAccount("Donz")
    fmt.Println(a) // <- 결과를 출력해 보면 요렇게 &{a 0} 주소표시가 붙어있음, a는 복사본이 아니라 object라는 뜻임
    // fmt.Println(a) 에서 콘솔에 "&{a 0}" 요렇게 표현해 주는 것은 String() 펑션 때문임, 출력형태 변경가능니 맨아래 참조

    // [02] GO 에서 Method 사용 방법
    a.Deposit(10)
    a.Balance()

    // [03] GO 에서 try-catch 처리
    e := a.Withdraw(11)
    if e != nil {
        fmt.Println(e.Error())
    }
}
anything_banking_file.go
package anything_banking_package

import (
    "errors"
    "fmt"
)

// 앞글자 a가 소문자라서 private: 파일내부에서만 사용가능
type account struct {
    owner   string
    balance int
}

/* 새로운 object를 리턴하고 싶은데, object를 만들긴 싫으니 복사본 자체를 return 함
   새로 만들어진 object를 보내는 거,  &:주소 / *:주소에 담긴값을 살펴봄 */
func NewAccount(owner string) *account {
    a := account{owner: owner, balance: 0}
    fmt.Println("a balance :", a.balance, &a.balance) // <- 0xc000004088
    return &a
}

/* GO의 Method 만드는 방법
   func와 func명 사이에 account의 b와 b의 type을 기입,
(b account) 부분을 receiver라고 하고 reciever는 b */
func (b *account) Deposit(amount int) {
    /* (*account) 뜻 : 누군가가 main.go의 a.Deposit을 호출한다면, Deposit method를 호출한 account를 사용하라는 거임 */
    b.balance += amount
    fmt.Println("b balance :", b.balance, &b.balance) // <- 0xc000004088
}

// main의 account를 여기로 가지고 와서 c로 복사본을 만듬
func (c account) Balance() int {
    fmt.Println("c balance :", c.balance, &c.balance) // <- 0xc0000040b8
    return c.balance
}

/* GO 는 try-catch가 없고 에러처리가 필요한 부분은 개발자가 이렇게 해줘야 함
   errors.New("Can't withdraw") 를 리턴하고, 받는 쪽에서 표현 */
func errWithdrwa() error {
    return errors.New("Can't withdraw")
}
func (d *account) Withdraw(amount int) error {
    if d.balance-amount < 0 {
        return errWithdrwa()
    } else {
        fmt.Println("d balance :", d.balance, &d.balance) // <- 0xc000004088
        d.balance -= amount
    }
    return nil
}
 
// GO 가 자동으로 호출해주는 method (fmt.Println 명령어 사용시 아래의 형태로 변형되어 표현됨)
func (a *account) String() string {
    return fmt.Sprint(a.owner, "'s account.\nHas :", a.balance)
}
mod.go
module scraping/structExample/main

go 1.18

!!! 이것만 알면 나도 GOPHER !!!

01. 상수 const name string = "a" 
    변수   var name string = "a"
    function 내에서는 축약 가능 name := "a"
 
02. 복수 형태의 return
    int와 string을 동시에 리턴함
    func test (a, b int) (int, string) {...}
 
03. 무제한 파라미터
    test("a", "b", "c", "d", "e");
    func test (a ...string) { ... }
 
04. naked return
    리턴값의 변수명을 function선언시에 지정하여 return 시에는 return 문장만 사용함
    
05. defer
    function 이 끝나고 난 직후 실행함, 파일을 닫는던지 등에 사용함
    
06. for idx, num := range numArr{ ... 
 
07. koreanAge := age+2
    if koreanAge < 18 { return true }
    위 두줄을 if-else에서 사용하는 베리어블 익스프레션으로 바꾸면
 -> if koreanAge := age+2; koreanAge < 18 { return true }
 
08. 포인터

& : 주소 * : 주소에 담긴 값을 살펴봄 주소에 *를 쓰고 주소에 담긴 값을 변경할 수 있음
a := 2      
b := &a     
            
Print(a, *b)
      2   2 
a := 2   
b := &a  
a  = 5   
Print(*b)
       5 
 a := 2  
 b := &a
*b  = 8
 Print(a)
       8 

  
09. array -> a := [5]string{"b","c","d"}
    slice -> a := []string{"b","c","d"}  append{a, "e"}
   
10. a := map[string]int{"b":1, "c":2}
    for key, val := range a { fmt.Print(val) }
    
11. type p struct {
       a string
       b int
       c [] string
    }
    d := a{a: "a", b:1, c:arr}

+ Recent posts