Ⅰ. 오전 수업
A. 1교시
1. 지난 시간 복습
2. 로그인 구현
B. 2교시
1. 로그인 구현(cont.)
C. 3교시
1. 탈퇴 로직 보완
Ⅱ. 오후 수업
4-6교시 시험
Ⅲ. CAREER UP
DB 특강
Ⅳ. 하루 돌아보기
console.log(req.body);let {id,pw,nick} = req.body;: 객체 비구조화(구조분해) 할당(destructuring assignment)DB 연결할 때 위에서 소개한 프로세스만 있는 건 아님! 더 간단한 방법도 있고 더 권장되는 방법도 따로 있음(쿼리만 관리하는 파일을 만들어 쿼리문을 따로 관리하는 방식)
TIP
모듈은 모두 exports 해주기
항상 '값'(e.g., conn, router, …)을 리턴하기:module.exports = conn
[id, pw, nick]
비구조화 할당(Destructuring Assignment) = 구조 분해 할당
배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 할당하는 JavaScript 표현식(expression)입니다. 이 기능을 통해 필요한 값을 구조에서 쉽게 추출하고 변수에 할당할 수 있으며, 코드의 가독성을 높이고 라인 수를 줄여 유지보수를 용이하게 하는 데 사용됩니다.
간단하게 정리하면 배열 [], 혹은 객체 {} 안의 값을 편하게 꺼내 쓸 수 있는 문법입니다.
- 주요 특징
- 배열 비구조화: 배열의 요소들을 순서대로 변수에 할당합니다.
const [a, b] = [1, 2];// a는 1, b는 2가 됩니다- 객체 비구조화: 객체의 프로퍼티 이름과 동일한 변수에 해당 값을 할당합니다.
const { x, y } = { x: 1, y: 2 };// x는 1, y는 2가 됩니다- 코드 간결성: 여러 값을 한 번에 할당할 수 있어 코드를 간결하게 만듭니다.
- 가독성 향상: 변수 이름을 명확하게 사용하여 코드의 의도를 더 쉽게 파악할 수 있게 합니다.
- 예시
var [a1, a2, ...rest_a] = [1, 2, 3, 4, 5, 6, 7, 8, 9]; console.log(a1); // 1 console.log(a2); // 2 console.log(rest_a); // [3, 4, 5, 6, 7, 8, 9]
- 전개 연산자( ... )를 사용하여 좌항에서 명시적으로 할당되지 않은 나머지 배열 값들을 사용할 수 있고 var, let, const를 사용해 변수들의 유효 범위를 명시적으로 선언할 수 있습니다.




대부분의 코드는 마지막 지점이 핵심 포인트: 우리는 dbRouter.js가 핵심!
let sql = "select * from member where id=? and pw=?";








// 회원 정보 수정 페이지 처리 로직
router.get("/update",(req,res)=>{
res.sendFile(filePath+"/update.html");
});
// 회원 정보 삭제 페이지 처리 로직
router.get("/delete",(req,res)=>{
res.sendFile(filePath+"/delete.html");
});
form 태그 action 경로 설정하기
action="http://localhost:3000/db/update"action="http://localhost:3000/db/delete"dbRouter 연결하기
// 회원 수정 로직
// * 팁 : DB에 값을 넘겨줄 때 넘겨주는 값의 순서를 반드시 체크하자(쿼리문 물음표 순서대로 넣기)
// * 팁 2: 값이 변화면 rows는 "영향"을 받는다 → 영향 받으면 메인으로, 아니면 업데이트로 이동
router.post("/update",(req,res)=>{
let {id,pw,nick} = req.body;
let sql = "update member set nick=? where id=? and pw=?;";
conn.query(sql,[nick,id,pw],(err,rows)=>{
console.log(rows);
if(rows.affectedRows>0){
res.redirect('/');
}else{
res.redirect("/update");
};
});
});
// 회원 탈퇴 로직
// 탈퇴가 되면 메인으로, 안 되면 탈퇴 페이지로 이동
router.post("/delete",(req,res)=>{
let {id,pw} = req.body;
let sql = "delete from member where id=? and pw=?;";
conn.query(sql,[id,pw],(err,rows)=>{
console.log(rows);
if(rows.affectedRows>0){
res.redirect('/');
}else{
res.redirect("/delete");
};
});
});





e.preventDefault();
!choice는 false니까 → submit 진행되고 dbRouter 동작해 db에서 삭제 진행한 뒤 메인 페이지로 이동함e.preventDefault();) → delete 페이지에 그대로 머물러 있음인라인 방식으로 써도 OK


npm i

alert를 구현해보고 싶어서
router.post("/update",(req,res)=>{ let {id,pw,nick} = req.body; let sql = "update member set nick=? where id=? and pw=?;"; conn.query(sql,[nick,id,pw],(err,rows)=>{ console.log(rows); if(rows.affectedRows>0){ res.send("<script>alert('수정이 완료되었습니다!')</script>"); res.redirect('/'); }else{ res.redirect("/update"); }; }); });이렇게 했더니 alert만 뜨고 경로 이동이 안 되서 찾아봤음:
- res.send()와 res.redirect()를 한 요청에서 동시에 호출하면 첫 번째 응답만 전송되고, 두 번째는 무시
- 한 번의 요청에 대해 클라이언트로 응답을 “한 번만” 보낼 수 있기 때문
- Express 공식문서에는 응답 객체가 end/send/redirect 중 하나로만 한 번 종료되어야 함이 명시되어 있음
- alert를 보내면서 리다이렉트 하려면, 한 가지 방법만 선택해야 함
- 서버에서 직접 alert와 리다이렉트를 동시에 처리하려면 클라이언트 측 자바스크립트를 사용하는 것이 일반적
res.send("<script>alert('수정이 완료되었습니다!'); location.href='/'</script>");- 요약
- 한 번에 res.send 혹은 res.redirect 둘 중 하나만 사용할 수 있음
- 경고창 + 리다이렉트가 모두 필요하다면
<script>방식으로 처리


오늘 수업에서는 CREATE, ALTER, DROP만 다룸

TIP: 위 3개의 대표적인 자료형만 알아도 무난하게 사용 가능!



CREATE TABLE 테이블명 ( 컬럼명 + 자료형 + DEFAULT로 지정할 값 + 제약조건);-- oracle
CREATE TABLE QUIZ_TABLE(
Q_ID NUMBER(3,0) NOT NULL
, Q_CONTENT VARCHAR2(200) NOT NULL
, Q_ANSWER VARCHAR(100)
, REG_DATE DATE DEFAULT SYSDATE
, Q_BINGO VARCHAR(100) DEFAULT ‘O’
);
--MySQL
CREATE TABLE QUIZ_TABLE (
Q_ID INT NOT NULL
, Q_CONTENT VARCHAR(200) NOT NULL
, Q_ANSWER VARCHAR(100)
, REG_DATE DATETIME DEFAULT CURRENT_TIMESTAMP
, Q_BINGO VARCHAR(100) DEFAULT 'O'
);




DROP TABLE 테이블명 [ CASCADE CONSTRAINTS ]
ALTER TABLE 테이블명 MODIFY COLUMN 컬럼명 + 자료형 + NOT NULL ;CREATE TABLE 테이블명 ( 컬럼명 + 자료형 + NOT NULL );-- Oracle
ALTER TABLE QUIZ_TABLE MODIFY COLUMN Q_ANSWER VARCHAR(100) NOT NULL ;
CREATE TABLE QUIZ_TABLE(
Q_ID NUMBER(3, 0) PRIMARY KEY ,
Q_CONTENT VARCHAR2(200) UNIQUE ,
Q_ANSWER VARCHAR(100) NOT NULL,
REG_DATE DATE DEFAULT SYSDATE ,
Q_BINGO VARCHAR(100) DEFAULT ‘O’
) ;
ALTER TABLE 테이블명 ADD CONSTRAINT 제약조건명 UNIQUE ( 컬럼 ) ;CREATE TABLE 테이블명 ( 컬럼명 + 자료형 + UNIQUE )-- Oracle
ALTER TABLE QUIZ_TABLE ADD CONSTRAINT UK_QUIZ_TABLE UNIQUE(Q_CONTENT) ;
CREATE TABLE QUIZ_TABLE(
Q_ID NUMBER(3, 0) PRIMARY KEY ,
Q_CONTENT VARCHAR2(200) UNIQUE ,
Q_ANSWER VARCHAR(100) NOT NULL,
REG_DATE DATE DEFAULT SYSDATE ,
Q_BINGO VARCHAR(100) DEFAULT ‘O’
) ;
ALTER TABLE 테이블명 ADD CONSTRAINT 제약조건명 CHECK ( 조건 OR 범위 ) ;CONSTRAINT 제약조건이름 CHECK ( 조건 OR 범위 );-- Oracle
ALTER TABLE QUIZ_TABLE ADD CONSTRAINT Q_BINGO_CK CHECK (Q_BINGO IN (‘O’, ‘X’) ) ;
CREATE TABLE QUIZ_TABLE(
Q_ID NUMBER(3, 0) PRIMARY KEY ,
Q_CONTENT VARCHAR2(200) UNIQUE ,
Q_ANSWER VARCHAR(100) NOT NULL,
REG_DATE DATE DEFAULT SYSDATE ,
Q_BINGO VARCHAR(100) DEFAULT ‘O’
CONSTRAINT Q_BINGO_CK CHECK (Q_BINGO IN(‘O’, ‘X’) )
) ;
새로운 휴대폰을 맞추려고 방문한 휴대폰 매장에서는 내 정보를 어떻게 찾을까? → 핸드폰 번호
라일락 회사의 ‘이지은’ 사원의 연봉 정보를 찾으려면 어떤 정보를 기준으로 찾을까? → 사번
한국대학교의 ‘김민수’ 학생을 찾기 위해서는 DB의 어떤 컬럼을 기준으로 찾을까? → 학번
ALTER TABLE 테이블명 ADD CONSTRAINT 제약조건명 PRIMARY KEY ( 컬럼 ) ;CREATE TABLE 테이블명 ( 컬럼명 + 자료형 + PRIMARY KEY );-- Oracle
ALTER TABLE QUIZ_TABLE ADD CONSTRAINT PK_QUIZ_TABLE PRIMARY KEY(Q_ID);
-- 이제 QUIZ_TABLE의 Q_ID에는
중복 값과 NULL 값 입력 불가!
CREATE TABLE QUIZ_TABLE(
Q_ID NUMBER(3, 0) PRIMARY KEY ,
Q_CONTENT VARCHAR2(200) UNIQUE ,
Q_ANSWER VARCHAR(100) NOT NULL,
REG_DATE DATE DEFAULT SYSDATE ,
Q_BINGO VARCHAR(100) DEFAULT ‘O’
) ;
FOREIGN KEY (FK)
다른 테이블에 있는 기본 키(PRIMARY KEY)를 참조하는 컬럼을 외래 키(FK, FOREIGN KEY)로 지정
데이터 무결성을 지원

참조하는 테이블의 기본 키 값과 반드시 동일한 값으로 구성되어야 함


문법
-- 1
ALTER TABLE 테이블명 ADD CONSTRAINT 제약조건명
FOREIGN KEY ( 참조받을 컬럼 ) REFERENCES 참조할 테이블(참조할 컬럼) ;
-- 2
CREATE TABLE 테이블명 ( 생성할 컬럼 정보 , CONSTRAINT 제약조건명
FOREIGN KEY (참조받을 컬럼) REFERENCES 참조할 테이블(참조할 컬럼) ) ;
예시
-- Oracle
ALTER TABLE QUIZ_TABLE2 ADD CONSTRAINT TABLE1_TABLE_2_FK
FOREIGN KEY(Q_ID) REFERENCES QUIZ_TABLE (Q_ID) ;
CREATE TABLE QUIZ_TABLE2 (
Q_ID NUMBER(3,0) ,
Q_REAL VARCHAR2(200) ,
CONSTRAINT TABLE1_TABLE2_FK FOREIGN KEY (Q_ID)
REFERENCES QUIZ_TABLE (Q_ID)
) ;
INSERT INTO 테이블명 ( COLUMN_LIST ) VALUES ( COLUMN_LIST에 입력할 값 리스트);
INSERT INTO 수강생정보 (학생ID, 학생이름, 소속반) VALUES ('S0088', '김민수', 'H')






UPDATE 테이블명 SET 바꿀컬럼 = 바꿀값 WHERE 바꾸고싶은행조건;

DELETE FROM 테이블명 WHERE 삭제하고 싶은 행조건 ;
주의: 각 문제를 잘 풀었다면, COMMIT; 명령어 실행
그래야 테이블에 수정된 내용이 제대로 반영됨
만약 내용 수정에 실수하였다면 ROLLBACK; 명령어 실행
사용하면 최근에 사용한 COMMIT 명령어 이전으로 복구 가능
자바에서 넘어온 데이터
(입력되지 않은 성별 컬럼의 경우 NULL 값이 들어가도록 해주세요.)
직원ID : 'A1000'
패스워드 : 'hello1000'
이름 : '신캐릭'
나이 : 29
입사일시 : 현재시점을 넣을 수 있게 SYSDATE 로 값 대입
주민등록번호 : '950120-1566221'
연봉 : 3500
부서id : 'D006'
【수정할 데이터】
성별 : '남'
부서ID : 'D005'
패스워드 : 'hello1000!!!'
위에서 입력한 'A1000' 직원이 오늘 퇴사를 하였습니다. 해당 직원정보를 직원 테이블에서 삭제(DELETE) 해주세요.
퇴사한 A1000 대신에 새로운 직원이 입사를 하였습니다. 이번에는 직원정보와 함께 연락처 정보와 주소 정보가 함께 들어왔습니다. 반드시 아래의 순서로 데이터를 INSERT 해주세요.
(1)직원 테이블 -> (2)직원연락처 테이블 -> (3)직원주소 테이블
직원ID : 'A2000'
패스워드 : 'hello222'
이름 : '이홍시'
나이 : 40
입사일시 : 현재시점을 넣을 수 있게 SYSDATE 로 값을 넣어주세요.
주민등록번호 : '830220-1566221'
연봉 : 5600
부서id : 'D006'
핸드폰번호 : '010-5959-1111'
집주소 : '운천로 123'
TIP: 결과적으로 3개의 테이블에 한 행씩 입력되어야 합니다.
3개의 테이블에 데이터가 모두 입력되면 COMMIT; 를 해주세요.
힌트: 핸드폰번호는 구분코드를 '휴대폰' 으로 입력
집주소는 구분코드를 '집' 으로 입력
2023년을 맞이해 성적표 테이블의 모든 데이터를 초기화하려고 합니다.
성적표 테이블의 모든 데이터를 삭제해주세요.
직원ID가 'A2000' 인 직원의 집전화 번호는 '062-123-1111' 입니다.
이 데이터를 직원연락처 테이블에 입력해주세요.
직원 'A2000' 이 가지고 있는 휴대폰 연락처는 '010-5959-1111' 입니다.
그런데 이번에 휴대폰을 바꿔서 번호가 '010-3333-5959' 로 변경이 되었습니다.
변경된 핸드폰 번호가 반영되도록 휴대폰 연락처를 수정해주세요.
직원 테이블에서 직원ID 가 'A0011' 인 대상을 삭제해주세요
수강생 S0001 이 최근 시험에서 국어 , 수학 , 영어 점수를 각각 90 , 85 , 70 점
맞았습니다.
이 정보를 성적표 테이블에 INSERT 해주세요.
예) 학생ID는 문자형 , 과목은 문자형 , 성적은 숫자형 컬럼입니다.
S0001 국어 90
S0001 수학 85
S0001 영어 70