# TIL: 2025-04-29 하나가 끝나면 또 하나가 나타나고..✨

heeezni·2025년 4월 30일
post-thumbnail

1. 배열 선언법

배운 내용

Javascript에서 배열을 선언하는 방법 2가지

1) 배열 리터럴을 이용한 생성
배열 선언과 동시에 데이터 초기화 - 반복문 못 돌림 (,찍어야하니까)

        let arr=[1,2,3];

2) new 연산자로 선언
명시적 객체 생성 후 사용하는 법 - 반복문 가능

        let arr = new Array();
        arr[0]=1;
        arr[1]=2;
        arr[2]=3;

2. 배열+랜덤

예제 1-1. 가위바위보

가위바위보 실행 버튼을 누르면 랜덤으로 가위,바위,보 이미지 화면에 출력

    <script src="../../js_lib/common.js"></script>
        let imgArray=new Array(3); //메모리에 빈 상자 3개를 만들되
                                   // 상자들간 서로 딱 붙어있게 [0][1][2]
        imgArray[0]="가위.png"
        imgArray[1]="바위.png"
        imgArray[2]="보.png"
    
        function gawi(){
            let img=document.querySelector("img");
            img.src="../../images/"+imgArray[getRandom(imgArray.length-1)];
            // getRandom[2] 는 하드코딩 
            // imgArray.length로 유연하게 변수 주기

        }

        addEventListener("load", function(){
            document.querySelector("button").addEventListener("click", function(){
                gawi(); //버튼 누를 때 호출
            });
        });
<body>
    <button>가위바위보 실행</button>
    <p>
    <img>
</body>

핵심포인트

  • 배열의 용도 : 규칙이 없는 데이터를 규칙화 시킬 수 있음
    랜덤 뿐만 아니라, 반복문과도 자주 쓰임

  • 현재 이 프로그램의 경우 파일명에 규칙이 하나도 없음
    → 파일명을 규칙있는 배열로 전환

  • ★중요★ imgArray[getRandom(imgArray.length-1)]로 호출한 이유
    배열 인덱스는 0부터 시작하므로 length - 1까지가 유효 범위
    imgArray 배열에서 무작위로 하나의 이미지를 선택한다는 뜻

예제 1-2. 점심 뭐 먹을래?

<head>
    <title>점심 뭐 먹을래?</title>
    <script src="../../js_lib/common.js"></script>
    <script>
        let array=new Array(10);
        array[0]="김밥";
        array[1]="닭갈비";
        array[2]="떡볶이";
        array[3]="짬뽕";
        array[4]="육회비빔밥";
        array[5]="타코";
        array[6]="포케";
        array[7]="핫도그";
        array[8]="햄버거";
        array[9]="김치볶음밥";

        function menu(){
            let div=document.querySelector("div");
            div.innerText=array[getRandom(array.length-1)];
        }

        addEventListener("load",function(){
            document.querySelector("button").addEventListener("click", function(){
                menu();
            });
        });
    </script>
</head>
<body>
    <button>점심메뉴는?</button>
    <div>뭐가 나올까</div>
</body>
</html>

예제 2-1. 갤러리 만들기 (고급ver.)

#footer에 있는 사진에 마우스올리면 해당 사진이 #content에 표시되게 구현

<head>
    <title>슈렉사진으로 갤러리 만들기</title>
    <style>
        #wrapper{
            width: 500px;
            height: 400px;
            margin: auto;
        }
        #mask{
            width: 500px;
            height: 340px;
            background-color: beige;
            position: relative;  /* relative = static + left + top */
            border: 3px solid black;
            overflow: hidden;
            /* 넘치는 컨텐츠는 가리자 */
        }
        #footer{
            width: 100%;
            background-color: beige;
            border-left: 3px solid black;
            border-right: 3px solid black;
            border-bottom: 3px solid black;
            float: left;
            text-align: center;
        }
        #footer img{
            width: 60px;  
            height: auto; /* 자동으로 비율 맞춤 */
            margin-left: 10px;

            vertical-align: middle; /* 세로 가운데 정렬 */
        }
    
    </style>
    <script>
        let imgArray=[
            "img0.jpg",
            "img1.jpg",
            "img2.jpg",
            "img3.jpg",
            "img4.jpg",
            "img5.jpg",
            "img6.jpg"
        ];
        let box; //모든 영역에서 접근하기 위함
        let n=0; //사용자가 현재 보고있는 사진의 index를 표현한 전역변수
        let a=0.1;

        function createImg(){ //슈렉 이미지 7개 생성하고, 7개 이미지를 담게될 바깥쪽 부모인 box생성하여
                            //mask의 자식 요소로 부착하자

                box=document.createElement("div");
                box.style.width=500*imgArray.length+"px"; //박스의 너비는 사진 개수에 따라 유동적이기 때문
                box.style.height=340+"px";
                box.style.position="absolute";
                box.style.left=0+"px"; //자바스크립트에서 제어하기 전에 초기화
                                        //css와 호환이 안되는 경우가 많음

                for(let i=0; i<imgArray.length; i++){
                    //box안에 이미지 배열 수만큼의 슈렉을 생성하여 자식으로 부착하자
                    let img=document.createElement("img");
                    img.src="../../images/shurek/"+imgArray[i];
                    img.style.position="absolute"; //부모인 box를 기준으로 배치
                    img.style.left=(i*500)+"px";

                    box.appendChild(img);//슈렉 이미지 추가
                }

                let mask=document.getElementById("mask");
                mask.appendChild(box)
        }
        
        function move(){ //사용자가 선택한 번 째의 슈렉이미지 box값을 위치시키기
            //0번째 0px, 1번째 -500px, 2번째 -1000px
            //n*-500
            // box.style.left=n*-500+"px"; 끊겨서 움직이는 모습
            // console.log(box.style.left);
            box.style.left=parseFloat(box.style.left)+a*(-n*500-parseFloat(box.style.left))+"px"
        }

        function createControl(){ //일반인들은 콘솔 제어가 불가능하므로 UI로 이미지 제어 가능하게
            let footer=document.getElementById("footer");
            for (let i=0; i<imgArray.length; i++){
                let img = document.createElement("img");
                img.src="../../images/shurek/"+imgArray[i];
  
                img.addEventListener("mouseover", function(){
                    n=i;
                });
                footer.appendChild(img);
            }
        }

        function gameLoop(){
            // console.log("gameLoop call");
            move();
        }

        addEventListener("load",function(){
            createImg(); //슈렉의 이미지들 생성
            createControl(); //이미지 컨트롤러 생성
            setInterval("gameLoop()",10); //움직이는 건 무조건 setInterval호출
        });
    </script>
</head>
<body>
    <div id="wrapper">
        <!-- 겉에 있는 작은 액자(mask)가 부모 
        안에 있는 긴 액자는 자식 -->
        <div id="mask"></div>
        <div id="footer"></div>
    </div>
</body>

핵심포인트

  • 사용자가 선택한 이미지가 마치 중앙에 오도록 box의 위치(left)를 조정하기

    > 각 이미지의 너비는 500px이니까,
    img1은 left=500px, img2는 left=1000px 위치에 있어요.
    이 이미지들을 감싸는 박스(box)를 왼쪽으로 옮기면
    → 보이는 이미지를 바꿀 수 있어요 (즉, 슬라이드).
    function move(){
    	box.style.left = parseFloat(box.style.left) + a * (-n * 500 - parseFloat(box.style.left)) + "px";
    }
  • gameLoop()를 주기적으로 호출하는 이유:
    감속도 운동 (easing animation) 을 구현하기 위해서

  • mouseover 이벤트로 n값을 변경
    → 메인 이미지 슬라이딩 트리거

예제 2-2. 단어게임


순서대로 단어가 나오고 input창에 맞는 단어를 쓰면 feedback이 O, 틀린 단어를 쓰면 X로 나오게.
맞추면 점수도 +10, 틀리면 -10으로 구현
준비된 단어가 끝나면 "-Game Over-"표시

<head>
    <title>단어게임</title>
    <style>
        #wrapper{
            width: 400px;
            height: 580px;
            margin: auto;

            padding: 10px;
            border: 5px solid black;          /* 연한 회색 테두리 */
            border-radius: 30px;              /* 둥글게 */
            background-color: white;        /* 거의 흰색 배경 */
        }

        #content{
            width: 100%;
            height: 300px;
            background-color: white;
            border: 3px solid black;
            border-radius: 10px;
            margin-bottom: 3px;
            background-color: rgb(238, 221, 226);
            text-align: center;
            font-size: 100px;
            font-weight: bold;
            line-height: 300px;

        }
        #input_area{
            width: 100%;
            height: 80px;
            border: 3px solid black;
            background-color: rgb(238, 221, 226);
            border-radius: 10px;
            margin-bottom: 3px;
        }
        #input_area input{
            width: 99%;
            height: 98%;
            border-radius: 10px;
            border: 0px;
            text-align: center;
            font-size: 70px;
        }
        #feedback{
            width: 100%;
            height: 100px;
            border: 3px solid black;
            background-color: rgb(233, 157, 183);
            border-radius: 10px;
            margin-bottom: 3px;
            text-align: center;
            font-size: 90px;
            font-weight: bold;
            line-height: 100px;
            text-align: center;
            font-size: 75px;
            font-weight: bold;
        }
        #score{
            width: 100%;
            height: 70px;
            border: 3px solid black;
            background-color: palevioletred;
            border-radius: 10px;
            text-align: center;
            font-size: 50px;
            font-weight: bold;
            color: white;
            line-height: 70px;
        }
    </style>
    <script>
        let wordArray=["개미","안경","나무","구름","미끄럼틀","자동차","컴퓨터","책","강아지","비행기"];
        let content;
        let input;
        let feedback;
        let score;
        let n=0; //n의 값에 따라 어떤 단어가 나오게 될 지 결정
        let num=0; //점수를 누적시킬 전역변수

        function printScore(){//점수 계산 및 출력
            score.innerText=num;
        } 
        
        function printWord(){ //게임에 사용할 단어를 출력하는 함수
            
            if(n<wordArray.length){
                content.innerText=wordArray[n];
            } else {
                content.innerText="- Game Over -";
                content.style.fontSize = "40px";
            }
        }

        function next(){ //이 함수를 호출하면 다음 단어가 나옴 (일치할 때만 이 함수 호출하기)
            n++;
            printWord();
        }

        function init(){ //초기화 함수
            content=document.getElementById("content");
            input=document.querySelector("#input_area input");
            feedback=document.getElementById("feedback");
            score=document.getElementById("score");

            //텍스트 박스에 키보드 이벤트 연결
            input.addEventListener("keyup",function(e){
                
                if(e.keyCode==13){ //엔터=아스키코드 13
                    // console.log("엔터쳤어?");
                    
                    if(content.innerText==input.value){//일치할 때만 이 코드가 수행 
                                                    // (input 안의 값은 value로 표현)
                        next();
                        feedback.innerText="O";
                        feedback.style.color="blue";
                        num+=10; //점수 10누적
                        printScore(); //점수 출력
                    }else{
                        feedback.innerText="X"
                        feedback.style.color="red";
                        num-=10; //점수 10누적
                        printScore(); //점수 출력
                    }
                    input.value=""; //단어가 맞던, 틀리던 다시 입력할 기회를 주자 (초기화)
                }
            });
            printWord(); //게임에 사용할 단어 출력
            printScore(); //초기 점수로 출력
        }

        addEventListener("load", function(){
            init();
            
        });
    </script>
</head>
<body>
    <div id="wrapper">
        <div id="content"></div>
        <div id="input_area"><input type="text"></div>
        <div id="feedback"></div>
        <div id="score"></div>
    </div>
</body>

3. Oracle

배운 내용

  • SQL*Plus는 DBMS가 아님
    오라클 DB에 접속하기 위한 접속 클라이언트

  • SPOOL은 SQL*Plus에서 출력 결과를 파일로 저장하는 명령어

SPOOL 'fileName.txt';

SPOOL OFF;
EXIT;
  • 오라클은 데이터베이스라는 용어보다는 tablespace 라는 용어로 여러 데이터 베이스 파일 묶는 논리적 개념 사용

JAVASPACE라는 테이블에 JS라는 유저 생성 후 DCL로 권한부여함

> GRANT CREATE SESSION TO JS;
> GRANT CREATE TABLE TO JS;

--현재 프로그램을 유지한 채로 접속 유저 변경
> CONNECT JS/****

--유저 확인
> SHOW USER;
USER is "JS"

--레코드 1건 삽입
> INSERT INTO 테이블명 (컬럼1, 컬럼2, 컬럼3, ...)
VALUES (1,2,3, ...);

EDIT 명령어 사용법

EDIT 명령어를 입력하면 SQL*Plus는 편집기를 열어줌
편집을 완료하고 파일을 저장하면, 저장된 SQL 문이 SQL*Plus 세션에 반영되고,
SQL*Plus로 돌아가면 쿼리가 자동으로 실행되지 않기 때문에, 쿼리를 실행하려면 /명령어로 실행하기


4. Oracle 테이블 제약조건

배운 내용

  • 제약조건(constraints): 테이블 생성 시 각 컬럼에 들어갈 데이터를 까다롭게 따져서 각종 제약 및 규칙 설정
  • NOT NULL NULL 값 ❌ (필수 입력)
  • UNIQUE 중복 ❌ (NULL은 허용됨)
  • CHECK 특정 조건 만족해야 함
  • DEFAULT 기본값 지정

-- 이건 아직 안 배움

  • PRIMARY KEY 각 행을 고유하게 식별함. 중복 ❌, NULL ❌
  • FOREIGN KEY 다른 테이블의 값과 연결 (참조 무결성)
> CREATE TABLE member (
    id       VARCHAR2(20) UNIQUE,
    name     VARCHAR2(20) NOT NULL,
    gender   VARCHAR2(8),
    regdate  DATE DEFAULT SYSDATE,
    CONSTRAINT chk_gender CHECK (gender = '남' OR gender = '여')
);
> insert into member(id, name, gender) values ('batman', '배트맨', '여');

이 데이터를 2번 넣으면?

ERROR at line 1:
ORA-00001: unique constraint (JS.SYS_C007001) violated
→ 에러남 (unique 중복방지 제약조건 때문에)

핵심 포인트

  • VARCHAR2(n) 가변 길이 문자열을 저장하는 Oracle 전용 타입 (유연하고 실용적)
    vs CHAR(n) 고정 길이 → 남는 자리 공백으로 채움
    (n은? 최대 n바이트 또는 n문자까지 입력할 수 있다는 뜻)

  • DEFAULT SYSDATE: 아무 값도 지정하지 않으면 자동으로 현재 날짜/시간이 기본값으로 입력

  • TO_DATE('문자열', '날짜 형식')로 직접 날짜 입력도 가능
    ex) TO_DATE('2025-04-29', 'YYYY-MM-DD')

  • chk_gender: gender 컬럼에 적용되는 제약 조건의 이름 (관리할 때 유용)

ALTER TABLE member DROP CONSTRAINT chk_gender;
  • CONSTRAINT 이름을 붙여 쓰는 이유:
    나중에 이렇게 제약 조건을 수정하거나 삭제할 때 유용함

느낀 점

슈렉 갤러리 만들기가 정말 어려웠다... 이제 끝났나? 싶으면 또 다른 함수 만들어서 이벤트 추가하고.. 이제 끝났나? 싶으면 또 다른 함수 만들어서 기능 추가하고 ㅠㅠ
그래도 반복연습만이 살길! 연휴에 놀지만 말고 열심히 연습해야지!


profile
아이들의 가능성을 믿었던 마음 그대로, 이제는 나의 가능성을 믿고 나아가는 중입니다.🌱

0개의 댓글