240904 TIL - Node 숙련 1주차 1

LIHA·2024년 9월 4일
0

내일배움캠프

목록 보기
36/54
post-thumbnail

알고리즘

JS에는 진수변환 기능이 있었다!! 정섭 튜터님과의 발견

parseInt(스트링타입의 변환할 숫자, 변환 전 진수).toString(변환 후 진수) 를 써주면 된다고 한다...!! 3진수 만드는 코드부터 썼는데 대충격.
-> 내가 만든 코드는 3진수 변환까지는 일단 성공했는데, 3의 몇승부터 나눠주면 될 지를 몰라 i의 범위가 참 미묘해졌다.
예를 들어 99인 경우 3^4인 81로도 일단 나누어지기 때문에 10200(3)이 나온다. 그래서 length + 1을 하면 틀리기 때문에 length * 2를 했었다.

    // 3진수로 변환
    while (n >= 3) {
        for (let i = nStr.length * 2; i >= 0; i--) {
                quot += Math.floor(n / (3 ** i));
                n %= (3 ** i);
        }        
    }
    
    console.log(parseInt(nStr, 10).toString(3));
    console.log('3진수 quot: ', quot)

    // 0 자르기
    for (let i = 0; i < quot.length - 1; i++) {
        quot.substr(i);
        if (quot[i] !== '0') {
            break;
        }
    }

이런 코드를 썼었다. 여기서 불필요한 0을 자르는 for문이 돌아가지 않아 고민중이었다. (for문의 i 자릿수 설정때문에 1200이 아니라 01200, 0011122 이런식으로 나왔다.)

3일만에 완성된 정답코드!

// 3진법으로 변환 -> 자릿수 뒤집기 -> 10진법으로 변환 
// 3^0 + 3^1 + 3^2 + 3^3 + 3^4...

function digit3(n) {
    let nStr = n + '';
    let threeNum = '';
    let reverse = [];
    
    threeNum = parseInt(nStr, 10).toString(3);
    
    for (let i = 0; i <= threeNum.length - 1; i++) {
        reverse[i] = threeNum[threeNum.length - 1 - i]
    }
    reverse = reverse.join('')
    return reverse;
}

function digit10(n) {
    let nStr = n + '';
    let decimal = '';
    
    decimal = parseInt(nStr, 3).toString(10);
    return decimal;
}


function solution(n) {
    var answer = 0;
    answer = parseInt(digit10(digit3(n)));
    return answer;
}

SQL

DB의 테이블은 엑셀 표와 같다고 보면 OK

엑셀 파일 = DB,
엑셀 시트 = 테이블,
엑셀 행 = 데이터

이런 식으로 봐도 OK

정상이면 COMMIT, 비정상이면 ROLLBACK

  • 작업이 정상적으로 완료되었다면 COMMIT을, 실패했으면 ROLLBACK을 해야한다.

->DB에서의 COMMIT은 Git의 commit과는 다르다. 깃은 commit이면 임시저장, push가 진짜 반영인 느낌이라면 DB는 flush가 트랜잭션을 DB로 전송하는 것이고 commit이 진짜 반영이다.

START TRANSACTION
...
COMMIT;
START TRANSACTION
...
ROLLBACK;

테이블 조인: JOIN 테이블명 as (별명) ON (별명1).컬럼 = (별명2).컬럼

SELECT
    pm.productionId,
    pm.debutDate,
    p.productionName,
    p.address,
    pm.createdAt,
    pm.updatedAt,
    pm.deletedAt
FROM
    ProductionMember as pm
    JOIN Production as p ON pm.productionId = p.productionId;

이런 식으로, 보통 Id값이 겹칠 것이기에 Id를 토대로 테이블을 JOIN 시켜준다.

없으면 만들어줘: CREATE TABLE IF NOT EXISTS (이름)

CREATE TABLE IF NOT EXISTS courses (
    id bigint(5) NOT NULL AUTO_INCREMENT, 
    title varchar(255) NOT NULL,
    tutor varchar(255) NOT NULL,
    PRIMARY KEY (id)
);

이렇게 생긴 코드가 있는데,

쉼표 하나 빼먹으면 syntax error가 난다

이런 에러가 떴었는데, 다른게 아니고 SQL 쿼리문에 쉼표 하나 빼먹었더니 이렇게 되었다.

~~~~~~, 
~~~~~~, <- 여기
)

테이블끼리 관계가 생기면 컬럼을 추가해야 할 것이다

요구사항이 이렇게 생겼길래 책 테이블에 bookId와 bookName만 만들었는데, 그랬더니 아무리 생각해도 Publisher 테이블과 연결할 방법이 떠오르지 않았다. FOREIGN KEY로 Publisher와 뭔가 이어져야 할 것 같은데? 라고는 생각했는데 구현은 못했다.

CREATE TABLE Books (
    bookId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    bookName varchar(255) NOT NULL
    );

일단 여기까지 쓰고 FOREIGN KEY를 생각은 했는데, 거기에 bookId를 넣고는 헤매고 있었다. 아래는 정답코드.

CREATE TABLE Books (
    bookId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    publisherId int (11) NOT NULL,
    bookName varchar(255) NOT NULL,

    FOREIGN KEY (publisherId) REFERENCES Publisher (publisherId)
);

기초 요구사항 만으로는 할 수 없는 거였다. 뭘 더하고 뺄 수 있을지 생각해보자.

1:1 테이블을 만들고 싶으면 FOREIGN KEY에 UNIQUE를 걸자

정답코드와 거의 유사하게는 썼는데, 두 가지가 틀렸다. 하나는 FOREIGN KEY를 Star 쪽에 놨던 것이고, 하나는 StarInfo의 starId에 UNIQUE를 생각하지 못했다.


CREATE TABLE Star (
  starId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY 
);

CREATE TABLE StarInfo (
    starInfoId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    starId int(11) NOT NULL UNIQUE,
    name varchar(255) NOT NULL,
    magnitude varchar(255) NOT NULL,
    distance varchar(255) NOT NULL,

    FOREIGN KEY (starId) REFERENCES StarInfo (starId)

);

N:M 테이블은 어떻게 만들지? 어렵다 어려워!


CREATE TABLE Idol (
    idolId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    name varchar(255) UNIQUE,
    age int(11) NOT NULL,
    gender varchar(255) NOT NULL
);

CREATE TABLE Production (
    productionId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    productionName varchar(255) UNIQUE,
    address varchar(255) NOT NULL UNIQUE

);

CREATE TABLE ProductionMember (
    pmId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    debutDate int(11) NOT NULL,
    name varchar(255) UNIQUE,
    productionName varchar(255) UNIQUE,
    
    FOREIGN KEY (name) REFERENCES Idol (name)
    FOREIGN KEY (productionName) REFERENCES Production (productionName)
);

나는 이렇게 썼는데, 도무지 뭘 잡아와야 할지 모르겠다는 생각이 들었다. 아이돌이나 프로덕션은 서로를 여럿 가지거나 안 가질 수 있으니까 그 각각의 Name을 받아오는 건가? 라고 생각했다. 그래서 이름에 NOT NULL도 넣어두지 않았다. (없을 수 있다고 해서)

FOREIGN KEY는 당황하지 말고 침착하게 남의 PRIMARY KEY 머리채를 잡아오자

아래가 정답코드.


CREATE TABLE Idol (
    idolId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    name varchar(255) NOT NULL UNIQUE,
    age int(11) NOT NULL,
    gender enum('M', 'F') NOT NULL
);

CREATE TABLE Production (
    productionId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    productionName varchar(255) NOT NULL UNIQUE,
    address varchar(255) NOT NULL UNIQUE

);

CREATE TABLE ProductionMember (
    pmId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    debutDate int(11) NOT NULL,
    idolId int(11) NOT NULL,
    productionId int(11) NOT NULL,
    
    FOREIGN KEY (idolId) REFERENCES Idol (idolId),
    FOREIGN KEY (productionId) REFERENCES Production (productionId)
);

여기서 튜터님은 gender를 varchar대신 enum으로 넣어 놓으셨다. 남성 혹은 여성으로 반드시 지정되어 있기 때문에 이렇게 쓰셨다고.

  • 주의할 점 - N : M 릴레이션쉽은 중간테이블을 삭제하기 전에는 각각 프로그램들을 삭제할 수 없다.

Node

테이블 명에는 띄어쓰기를 넣을 수 없다! - 튜터님의 구원

강의 영상과 정말 똑같이 쳤는데도 나만 오류가 터지니 원인을 도무지 알 수가 없었다...

결론은 Insomnia에서 테이블 이름을 잘못 입력한 것 (띄어쓰기를 포함하면 안됨) 이었다!
정섭 튜터님이 정답을 알려 주셨지만 왜인지 그때는 에러가 계속 터지다 보니 저게 안 된다고 생각했었다. 하여 창민 튜터님께 소환되어 구원받았다.

  • 일단 저 쿼리문을 출력부터 해보자 -> const query~ 같은 이름으로 대충 선언하고, console.log로 받아서 출력이 되는지 보면 될 것.
  const queryPrint = `
        CREATE TABLE ${tableName}
        (
            id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
            name varchar(255) NOT NULL,
            createdAt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
        )`

        console.log(queryPrint);

위 쿼리문을 이용하여 출력해보니 일단 출력은 잘 되었다. tableName이라는 변수도 잘 받아왔다. 그러면 OK! 쿼리문에 문제가 있는 건 아니란 얘기. 얘는 app.post단에 붙어있는 애라 이후 Insomnia로 쏴보니까 잘 출력되어 app.post 로직에도 문제가 없단 얘기가 된다. 그래서 테이블 명의 띄어쓰기를 제거하니 무사히 해결.

profile
갑자기 왜 춤춰?

0개의 댓글