개발일지

[UniUnity 개발일지] 4. MySQL Table 및 모델 생성

Ji0_ 2023. 7. 6. 15:28

DB 설계할 때 생각지도 못한 부분이 있는데 바로 지도를 사용하려면 테이블에 저장되었는 모든 주소의 (위도, 경도) 값을 함께 저장해야 한다는 것

테스트용 데이터를 DB에 5개 정도 만드는데, 이 위도 경도 값을 다 가져와야 함

그리고 카카오 지도는 위도, 경도 순으로 데이터를 넣어줘야 하는데 사용하는 공공데이터는 경도, 위도 순으로 데이터를 제공해줌

...


우선 제휴 가게를 모아놓은 DB를 만들어야 했는데

역시나 위도, 경도 값을 어떻게 저장해야할지 감이 안와서 구글링을 했다.

보통 위도, 경도 값을 각각 DECIMAL로 저장하는 것 같았어 나도 DECIMAL로 설정했다.

create table Partner (
	storeID INT NOT NULL AUTO_INCREMENT primary key,
    storeName VARCHAR(50) NOT NULL, 
    store_location VARCHAR(100) NOT NULL,
    latitude DECIMAL(8,6) NOT NULL,
    longitude DECIMAL(9,6) NOT NULL,
    university_id INT NOT NULL,
    content VARCHAR(100),
    startDate DATE NOT NULL DEfAULT (current_date()),
	endDate DATE NOT NULL DEFAULT (current_date()),
	FOREIGN KEY (university_id) REFERENCES University(university_id) ON DELETE CASCADE
);

 

DECIMAL는 (전체자리수, 소수점 자리수)를 표기해야하고(전체자리수만 표시하면 정수값으로 저장) 카카오 지도에서 위/경도 값을 소수점 6자리까지만 받는 것 같아서 소수점 6자리로 설정. 이때 서울은 위도는 대부분 37.*****, 경도는 127.***로 표현되기 때문에 전체 자리수는 다르게 설정했다.

다른 팀원들이 만들어 놓은 테이블을 외래키로 사용하는 등의 상황이 발생해서 어려운 파트는 아니지만 시간이 생각보다 오래 걸림...

* 참고로 오류를 캡쳐하지는 못했는데 외래키 설정에 있어 내가 설정하려는 외래키가 참고하려는 테이블의 기본키가 아니여서 발생한 문제였다. 분명 데이터베이스 수업을 들었을 때는 그런 소리 못들었는데.... 어쨌든 번거롭지만 외래키는 univerisy_id로 설정을 하고 university_name을 받아와 university_id를 반환하게 하는 API를 따로 만들어주었다.

내가 지금 사용해야 할 테이블은 저것밖에 없고, 다른 테이블을 내가 만들자니 다른 팀원들이랑 상의를 해야할 것 같아서 우선 Partner 테이블만 생성함.

그리고 이 테이블을 사용하기 위해서는 DB와 연결하여 가져와야 함.

DB연결은 GCP를 사용해서 DB서버를 만들어주고 그걸 통해서 MySQL Workbench로 연결해서 사용해주었다.

아래처럼 mysql을 연결하기 위한 pool을 생성해서 사용해주었다.

수업에서 mysql2를 사용했는데, mysql2는 비동기 처리 방식을 이용하기 때문에 promise를 사용한다.

//db
require('dotenv').config();

const mysql = require('mysql2/promise');

// MySQL 연결 풀 생성

  const pool = mysql.createPool({
    host:process.env.DB_HOST,
        user:process.env.DB_USER,
        password:process.env.DB_PW,
        port:process.env.DB_PORT,
        database:process.env.DB_NAME,
        waitForConnections:true,
        insecureAuth:true,
        dateStrings : "date",
});

module.exports = pool;

사실 이 코드는 내가 안 만들었다... 팀원이 만들어준 코드 사용하기ㅋㅋ

그리고 참고로 dateStrings : "date"라는 설정을 추가해줬는데 이건 mysql의 Date변수 타입을 예쁘게 가져오기 위한 설정이다.

이걸 안해주면 DB에서 받아온 Date타입의 변수가 아래처럼 받아와진다.

따로 처리를 안해주면 안된다는게 번거롭지만 아래처럼 예쁘게 표시하기 위해서는 dateString설정이 필수!

 


우리는 MVC아키텍쳐를 사용하기 때문에 각각의 페이지 별로 모델을 생성해주었다.

"~Storage" 파일에는 연결한DB를 사용해서 값을 반환하는 코드를 생성해준다.

static getUniversity(university_url) {
       return new Promise(async (resolve,reject)=> {
           pool.query('SELECT university_name FROM University WHERE university_url =?',[university_url],(err,data)=>{
               if(err)reject(`${err}`);
               else {               
                   resolve(data[0]);
               }
           });
       });
 }

위 코드는 university_url을 인자로 받아 인자로 받은 university_url가 존재하는 튜플의 university_name을 출력하는 코드이다.

이런 식으로 PartnerStorage에는 내가 사용해야하는 API를 만들어주었다.

앞서 말했듯이 비동기 방식을 사용하기 때문에 함수에 Promise를 선언해준다. Promise의 경우는 return하는 것이 값 자체를 return하는 것이 아니라 '약속'을 return하는 것이다. 즉, 해결은 해주지 않고 약속을 한 채 우선 pending상태로 들어가며, 약속(Promise)이 잘 해결되면 resolve를 호출하여 fulfilled상태로 들어가며, 약속(Promise)을 실패하면 reject를 호출하여 rejected상태로 들어간다.

따라 위에 코드도 DB에 연결이 잘 되어 데이터를 받아오면 resolve를 호출하도록, 아니면 오류가 생겨 reject를 반환하도록 한 것이다.

* 비동기 처리 Promise에 관해서는 구글링을 해보념 더 자세한 설명을 한 다른 게시물 혹은 영상들이 많으니 궁금하면 참고해보는것이 좋다!

그 다음 Partner파일에서는 PartnerStorage에서 구현한 함수를 가져와서 try문으로 resolve 호출로 받은 값을 return해주는 코드를 만들어주었다.

async getUniversityName(university_url){
        try{
            const response = await PartnerStorage.getUniversityName(university_url);
            return response;
        }catch(err){
            return{success:false,msg:err};
        }
    }

그리고 그 코드를 라우터 사용을 위한 함수를 모아놓은 파일로 넘겨주었다.

getUniversityName:async(req,res)=>{
        const partner = new Partner();
        const response = await partner.getUniversityName(req.body.university_url);
        return res.json(response);
    },

이 함수를 사용하는 라우터는 POST로 구현을 해줄 것이기 때문에 body를 사용하여 req.body.university_url를 통해 인자를 넣어준다.

(GET의 경우 params를 사용하면 됨.)

그리고 이런 식으로 라우터 설정을 하면,

router.post("/getUniversityName", ctrl.result.getUniversityName);

http://localhst:3000/getUniversityName URL을 통해 request값으로 {university_url: "~~~~"}를 전달해주면 해당 university_url에 해당하는 university_name을 반환해준다.