09/04, chatterbox database

Ian·2020년 9월 4일
0

Today I Learned

목록 보기
17/40

09/04, chatterbox database

chatterbox database - 오전

export environment variable with terminal

export DATABASE_SPRINT_PASSWORD="my root account's password"

이런식으로 터미널에 내보내주었다. 내 비밀번호는 내 로컬 작업 환경 안에서만! 안전하게!

기타 삽질

USE DataBaseName;

SHOW TABLES 를 먼저 사용하기 전에, 일단은 어떤 DB를 사용할지 정해줘야 하기 때문에, 위와 같이 USE DataBaseName


Sprint Office Hour

PRIMARY KEY

PRIMARY KEY 를 만들 때는 auto increment 나 not null, unique 등의 속성이 들어간다.

그러나, MySQL 에서는 해당 문법이 존재하기 떄문에 문법을 통해 생성하면 잘 만들어진다. NOT NULL 등은 해당 문법을 통해 만든다면 자동으로 명시된다. (ALLOW NULL 등으로 명시하지 않는 이상은)

FOREIGN KEY

다른 항목(거의 PRIMARY KEY) 를 통해 참조하기 위한 필드. 1:1, 1:N, N:M 의 경우에도 전부 사용 가능하다. 기본적으로 참조하기 위한 것이기 때문에.

  • KEY 를 선언하고, 참조시키는 방식은 CREATE TABLE 안에서 해 줘도 되고, 그 밖에서 ALTER TABLE 을 통해 해 줘도 된다. 그래서 dbdiagram 을 통해 만들어진 문법도 딱히 문제는 없다.
  • 또 필드명에 backtick(```) 은 옵션이다. 꼭 사용해주지 않아도 된다.

Schema Design

Instagram - Schema

스프레드시트나 엑셀을 통해서 그림을 그리듯 편하게 짜고, 그걸 dbdiagram 을 통해 schema → code 로 만드는 과정이 편한 것 같다. 이 Schema 는 instagram 의 테이블 구조를 만들어본 spreadsheet 이다(간단하게)

JOIN

다이어그램을 보아도 사실상 우리가 주로 쓰는 건 ASIDE JOIN(LEFT, RIGHT) 혹은 INNER JOIN 이다. FULL OUTER JOIN 은 나중에 쓸 일이 생기면 알아두면 되는 정도. 심지어 ASIDE JOIN 중에서도 우리가 사용하는 방향에 따라 취향껏 사용하면 되는 것이기에 그렇게 어렵지 않고 겁먹을 필요도 없다.

OUTER JOININNER JOIN

INNER JOIN 은 중복되지 않는 항목들만 나오고, OUTER JOIN 은 중복되는 항목들도 같이 나온다. 정확히 말하면, INNER JOIN 은 "매칭이 되는" 항목들만 나오고, OUTER JOIN 은 "매칭되지 않는 항목들도" 같이 나온다.

환경변수 설정

echo $PATH

이런 식으로 하면 환경변수를 확인할 수 있다.

여담

sub-query(서브쿼리) 라는 것도 필요한 경우에 한 번 찾아보도록 하자. WHERE 와 ON 만으로도 안 되는 순간이 언젠간 올 수도 있으니깐. 물론 Schema Design 을 잘 해서 sub-query 를 사용하지 않도록 하는게 베스트이다.

GROUP BY, ORDER BY 정말 많이 쓴다. 특히 GROUP BY 는 통계적 사고를 갖기 위해서 정말정말정말 중요하다! ORDER BY 는 내가 만든 데이터를 정렬해서 필요한 것들만 보여주는 데 더욱 유용하게 사용할 수 있다.

힌트

진행이 안 되면 일단 하나 넣고 메시지 테스트가 통과하나 확인해보자!

spec/server-spec.js 는 queryString 과 queryArg 를 바꾸어주어야한다.

  • 테스트케이스는 이런식으로 수정하면 된다!
INSERT INTO messages(roomname, userId, text) values(?, ?, ?)
queryArgs = ["main", 1, "hi!"]

그리고, 파일구조 자체를 잘 이해해봅시다


chatterbox database - 오후

오늘 할 일은 express 로 구현한 서버와 MySQL 로 만든 DB 를 npm 의 mysql 모듈을 통해 연결하는 것이었다.

mysql

일단은 npm 의 MySQL 모듈에 대해 이해하느라 시간이 오래 걸렸다. 그리고 오랜 시간을 써서 해당 공식문서를 참조해 DB를 만들어주고, 연결해주고, 그리고 쿼리를 발송하는 과정을 순차적으로 이해한 결과 겨우겨우 스프린트를 시작할 수 있었다. 역시 모든 것의 첫걸음은 공식문서 독해인 듯 하다.

또한 callback 을 적극적으로 이용해야겠다는 생각도 들었다. 오늘 가장 삽질을 많이 한 부분이 callback 과 관련된 부분이었기 때문이다. 구체적으로 적어보자면, 이 부분이었다.


callback 을 활용합시다

오해의 시작

모듈을 어느정도 이해해서 사용해 보려고 코드를 작성했는데, 자꾸 코드 실행의 결과물이 넘어가지 않아 그를 해결하기 위한 삽질을 적는 단락이다.

상황을 적어보자면, 밑과 같은 상황이었다.


// server/models/index.js
module.exports = {
  messages: {
    get: function () {
      let queryStr = 'SELECT * FROM `messages`'
      db.query(queryStr, (err, results) => {
        if (err) {
          throw err;
        }
        return results;
      })
    }
};

먼저 이렇게 쿼리를 발송하는 과정을 만들었었고, module.exports 를 통해 내보낸 다음

var models = require('../models');

module.exports = {
  messages: {
    get: (req, res) => {
				res.send(models.messages.get());
      })
    }
};

이런 식으로 require 를 통해 부른 다음, 위와 같은 파일에서 활용하려고 했었다.

나는 models.messages.get() 를 호출하면서 results 가 return 되고, 그 results 는 res.send() 를 통해 날아오는 요청에 응답을 해 줄거라고 생각했다.

그런데 아무 값도 날아오지 않았다.

해결하기 위한 시도들

그래서 혹시 scope 때문인가 하는 생각에, 저 result 를 변수를 하나 만든 뒤 거기에 담아서 return 하자는 생각을 해 봤고 그렇게 위의 server/models/index.js 에 있는 코드를 수정하였다.

// server/models/index.js
module.exports = {
  messages: {
    get: () => {
			let queryResult = []
      let queryStr = 'SELECT * FROM `messages`'
      db.query(queryStr, (err, results) => {
        if (err) {
          throw err;
        }
        queryResult.push(results);
      })
    }
	return queryResult;
};

이렇게 하면 이번엔 queryResult 라는 변수에 results 라는 값이 할당되고 그 값이 넘어갈 줄 알았는데, 마찬가지로 아니었다. 아무 값도 넘어오지 않았다.

페어의 조언, callback 으로 처리하는 건 어떤가요?

같이 고민하던 페어가 "그러면 콜백을 사용해서 넘기는 건 어떻냐" 라고 내게 물어보았다. 생각해보니, 바로 넘겨주면 될 일이라 생각해서 callback 구조를 활용해 보았다.

// server/models/index.js
module.exports = {
  messages: {
    get: (callback) => {
      let queryStr = 'SELECT * FROM `messages`'
      db.query(queryStr, (err, results) => {
        if (err) {
          throw err;
        }
        callback(results);
      })
    }
};
var models = require('../models');

module.exports = {
  messages: {
    get: models.messages.get((arg) => { 
			res.send(arg);
		})
  }
};

그래서 arg => res.send(arg) 라는 함수를 저기 나와있는 callback 으로 넘겨주었다. 그리고 그 끝에 우리가 작성한 DB의 결과물이 넘어갔다.

[
    {
        "id": 1,
        "text": "hello world",
        "created_at": "2020-09-04T06:10:20.000Z",
        "userId": 1,
        "roomname": "main"
    }
]

이유는 일단 조금 더 찾아봐야 할 듯 하다. return 타입이 JSON 인 것도 이렇게 응답을 날려보고 나서야 알았다.


본격적인 구현

일단 감이 안와서 정규 세션이 끝난 뒤 추가로 계속 시도를 해 보는 중이다.

endpoint 처리를 /messages/users 로 따로 끊어주었다. 그런데 testcase 를 보고 어떻게 해야 할지 조금 감을 잡았다. 일단은 /classes 에서 요청을 받은 뒤 거기서 /classes/users, 그리고 /classes/messages 로 나눠주어야 한다.

결국 DB 스프린트를 결국 끝내지 못 했다. 쉽지 않다… 테스트케이스 실행은 안 되는데, 내가 postman 을 통해 보내는 쿼리는 또 잘 날아가서 DB에 박힌다. 뭐가 문제일까. 더 웃긴 건 response code 는 postman 으로 보내는 것이든 테스트케이스를 실행할 때 보내는 것이든 똑같다는 점. 그리고 user 테이블에 날아가서 박히는 경우는 잘 박히는데 messages 테이블에 날아가서 박히는 경우는 또 안 된다는 점. 머리가 아프다. 일단은 오늘은 여기까지 했으니 정리하고 잔다음 내일 마저 해야겠다.


기타등등

VSCODE 에서 작업중인 폴더를 창을 하나 더 만들어서 열기 위해서는 CMD + K, O 를 눌러주면 된다. 여러가지 파일을 한 번에 놓고 작업해야 하다보니 모니터 하나만으로 부족하여 sidecar 모니터까지 코딩창으로 사용하게 된다

profile
правда и красота, truth and beauty

0개의 댓글