본문 바로가기

Coding/내일배움캠프

[내일배움캠프] Node.js 4기 TIL | Day 30 | 24.01.30.(화)

1-6. SQL 제약 조건 (2)

5) NOT NULL

NOT NULL : 특정 데이터가 존재하는 것을 제약조건으로 .. 
AUTO_INCREMENT : 값 안 넣으면 값을 1씩 증가해줌

CREATE TABLE Users (
     userId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
     name varchar(255)
);

--

DESC Users;

6) 고유(Unique) 제약 조건

- Unique 제약 조건은 특정 컬럼에서 중복된 값이 허용되지 않도록 설정하는 조건

Error: ER_DUP_ENTRY: Duplicate entry '이용우' for key 'Users.name'

name이라는 칼럼이 unique하기 때문 ..

7) 외래 키(Foreign Key) 제약 조건

- 외래 키 제약 조건은 테이블과 다른 테이블 간의 관계를 맺을 때 사용하는 제약 조건입니다.

연관 관계

- 1:1
- 1:N
- N:M

외래키 제약 조건 유구사항!

- 정원 테이블 / 이름 | 주소
- 정원 식물 / 식물 이름
- 이외 요구사항
- 정원 식물은 특정 정원에 소속되어 있음
- 하나의ㅏ 정원은 여러 개의 정원 식물을 가질 수 있음

1-7. SQL 제약 조건 (3)

8) 외래 키 (Foreign Key) 제약 조건 심화

- 외래 키의 경우 다른 테이블과 관계를 맺고 있는 참조 데이터가 삭제(DELETE) 또는 수정(UPDATE) 될 때 어떤 행위를 해야 하는지 설정할 수 있습니다.

연계 참조 무결성 제약 조건의 종류

- CASCADE | 가장 많이 사용한다
- NO ACTION
- SET NULL
- SET DEFAULT 

9) SELECT JOIN 연산자

- JOIN 연산자는 두 테이블 사이의 공통된 데이터를 기준으로 테이블을 연결하여 하나의 테이블처럼 조회할 수 있게 해주는 연산자입니다.

- JOIN 연산자는 SQL의 제약 조건은 아니다. SELECT 연산자의 활용법 중 하나

갈고리 모양 ~ 1:N 관계 ..

별칭(alias)은 여러 개의 테이블을 참조할 때, 특정 테이블을 간단하게 나타내기 위해 사용합니다.

별칭을 사용하지 않을 경우 모든 컬럼에 테이블명을 있는 그대로 작성해야 합니다.
만약 테이블의 이름이 길게 정의되어 있을 경우 나쁜 코드 냄새가 나는 코드로 구현될 것입니다.



1-8. SQL 제약 조건 (4)

-- CREATE TABLE Users (
--      userId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
--      name varchar(255)
-- );

-- DESC Users;

-- drop table Users;

-- CREATE TABLE Users (
--      userId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
--      name varchar(255) NOT NULL
-- );

-- DESC Users;

-- drop table Users;

-- CREATE TABLE Users (
--      userId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
--      name varchar(255) NOT NULL UNIQUE
-- );

-- DESC Users;

-- INSERT INTO Users (name) VALUES ('이용우');
-- INSERT INTO Users (name) VALUES ('이용우');

-- CREATE TABLE Garden(
--     gardenId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
--     name varchar(255) NOT NULL,
--     address varchar(255) NOT NULL
-- );

-- CREATE TABLE GardenPlants(
--     gardenPlantsId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
--     gardentid int(11) NOT NULL,
--     name varchar(255) NOT NULL,
--     FOREIGN KEY (gardenId) REFERENCES Garden (gardenId)
-- )

-- DROP TABLE Users;

-- CREATE TABLE Users
-- (
--     userId   int(11)      NOT NULL AUTO_INCREMENT PRIMARY KEY,
--     email    varchar(255) NOT NULL,
--     password varchar(255) NOT NULL
-- );

-- CREATE TABLE Posts
-- (
--     postId  int(11)      NOT NULL AUTO_INCREMENT PRIMARY KEY,
--     userId  int(11)      NOT NULL,
--     title   varchar(255) NOT NULL,
--     content varchar(255) NOT NULL,
--     FOREIGN KEY (userId) REFERENCES Users (userId)
-- );


-- INSERT INTO Users (userId, email, password)
-- VALUES (1, 'AAAA', '1234'),
--        (2, 'BBBB', '1234');

-- INSERT INTO Posts (userId, title, content)
-- VALUES (1, 'AAAA Title1', 'content'),
--        (1, 'AAAA Title2', 'content'),
--        (2, 'BBBB Title1', 'content'),
--        (2, 'BBBB Title2', 'content');

-- SELECT * FROM Users;

-- SELECT * FROM Posts;

-- SELECT p.postId, p.title, p.content, u.email
-- FROM Posts as p
-- JOIN Users as u
--  ON p.userId = u.userId;

-- CREATE TABLE Publisher(
--     publisherId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
--     publisherName varchar(255) NOT NULL,
--     publisherAddress varchar(255) NOT NULL
-- );

-- 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)
-- );

-- DESC Publisher;

-- DESC Books;

-- 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 Star(starId)
-- )


-- DESC Star;

-- DESC StarInfo;

-- CREATE TABLE Idol(
--     idolId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
--     name varchar(255) NOT NULL UNIQUE,
--     age int(11) 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(
--     productionMemberId int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
--     idolId int(11) NOT NULL,
--     productionId int(11) NOT NULL,
--     debutDate date NOT NULL,
--     FOREIGN KEY (idolId) REFERENCES Idol(idolId),
--     FOREIGN KEY (productionId) REFERENCES Production(productionId)
-- );

-- DESC Idol;

-- DESC Production;

-- DESC ProductionMember;

1-9. RAW Query 시작하기

1) Raw Query란?

- Raw Query는 데이터베이스에 SQL(Structed Query Language)을 이용하여 직접 쿼리(Query)를 요청하는 것을 뜻합니다.

- Raw Query의 결과값을 const [tableList]의 형태로 할당하는 이유가 있을까요?

Raw Query를 사용할 때, CREATE TABLE 명령어와 같이 데이터를 생성하는 명령어의 경우 반환하는 값이 존재하지 않았지만,
SHOW TABLES 또는 SELECT 문법의 조회 명령어는 반환값이 존재하게 됩니다.

mysql2의 경우 Raw Query를 이용하여 조회된 결과값은 배열의 첫 번째에 할당되게 되는데요.
그렇기 때문에, 배열 구조 분해 할당 문법을 이용해 배열의 첫 번째 값만 tableList 변수에 할당하게 됩니다.

- 컬럼명 변경할 때 .. 관련된 모든 코드 수정해야 한다..

- 사용자가 전달한 데이터를 데이터베이스에 직접 요청하게 됨 .. SQL 인젝션의 취약점을 가지게 될 수 있다 ..

- ORM을 통해 Node.js에서 SQL을 직접 작성하지 않고, JavaScript 만으로 데이터베이스를 조작할 수 있게 되어
코드의 유지보수성이 증가하게 되고, 최종적으로 더욱 객체지향적인 프로그래밍을 가능하게 만들 수 있게 된다.

1-10. ORM과 Prisma

1) Prisma

- Prisma는 ORM(Object Relational Mapping)으로써 Javascript 객체(Object)와 데이터베이스의 관계(Relation)을 연결(Mapping) 해주는 도구입니다.

2) Prisma vs mongoose

- mongoose의 경우 ODM(Object Document Mapping)으로 Javascript의 객체를 Document와 연결하지만, Prisma는 ORM(Object Relational Mapping)으로 JavaScript의 객체와 데이터베이스의 관계(Relation)를 연결해주는 차이점이 있습니다.

3) ORM의 장단점

Prisma와 같은 ORM을 사용하는 가장 큰 이유 2가지

1> 프로덕션에서 사용하는 데이터베이스가 언제 바뀔지 알 수 없습니다.
2> 데이터베이스에서 사용하는 DB 또는 Table 속성이 변경되었을 때 빠르게 수정이 가능합니다.

ORM도 만능은 아님

JOIN과 UNION 연산자를 동시에 사용하는 복잡한 쿼리를 작성할 경우, ORM으로 구현하기 위해 SQL보다는
ORM을 더 깊게 이해해야 하는 상황이 발생할 수 있고, 이로 인해 원인과 결과가 뒤집힌 상황이 발생할 수도 있습니다.



1-11. Prisma 시작하기

url 부분에서 env("DATABASE_URL") 방식으로, 데이터베이스의 주소가 노출되지 않게 작성하는 dotenv의 문법을 사용하고 있는데요.
env() 문법은 프로젝트의 root 폴더에 있는 .env 파일에 정의되어 있는 정보를 해당 schema.prisma 파일로 불러오는 것입니다.

여기서, dotenv는 어플리케이션의 환경 변수를 관리하는 모듈입니다. 실제 코드에서는 민감한 정보를 노출시키지 않도록 보호해주고,
개발 환경에 따라 다르게 설정해야 하는 값을 별도의 파일에서 관리할 수 있게 해줍니다.

데이터베이스 URL은 크게 4가지로 나눠집니다.

- Protocol
- Base URL

- Path
- Arguments