파일 업로드, 다운로드는 post 방식을 사용하기 때문에 body-parser 사용 router 위임
router.js 에서 app 을 위임받아 사용 후 바로 router 를 export
router 에서 /file 경로로 들어오는 부분은 fileRouter 를 변수로 생성하여 위임 후 file_router.js 에서는 /file 경로로 들어올때 내용을 처리하고 router 를 다시 export 로 반환
file_router 에서는 세부 경로를 다시 file_controller 로 위임
file_controller 에서 Object 를 하나 변수로 선언하여 키와 값으로 경로들을 묶어서 export 하고 file_router.js 에서는 사용 하고자 하는 키로 값을 가져와 사용한다
controller 작성, file_index.ejs 작성 후 작동 결과
form 태그 내에서 파일을 전송하는 경우
enctype="multipart/form-data"
위 코드를 적용해줘야 함
file_router 에 파일 선택 후 업로드할때 출력될 페이지 경로 설정 ( 파일 전송이기 때문에 post 방식 )
단순히 화면을 출력하는 부분은 view 라는 Object 에 모아서 사용, process 라는 Object 에는 연산을 하는 부분을 넣어서 사용, file_router 에서도 코드 수정
controller 에서 기존처럼 사용하지 않는 이유는 결국 controller 에 세부 경로가 많아질 수록 코드가 쌓이게 되는데 코드에서 문제가 생길 시 단순 출력 부분과 연산 부분 중 어느 부분이 문제가 생긴지 파악하고 쉽게 고칠 수 있기 때문... 또한 Object 로 묶어서 사용하는 이유는 exports 의 코드가 너무 길어지기 때문이므로 Object 를 exports 하여 router 에서 Object.key 형식으로 함수를 사용한다
router 에 multer 설정 및 파일 업로드 부분에 multer 의 기능을 추가.... controller 에서 console 로 출력 코드 적고 파일 전송해봄
저장되는 파일의 이름을 원본 파일과 동일하게 저장하기 위해 코드를 수정
코드 실행
특정 파일 형식만 사용하고 싶은 경우
filter 를 따로 구성하여 multer 에 추가한다
사용할 수 없는 확장자를 올리는 경우 filter 에서 확장자가 일치하지 않는 경우 req.fileValidation 에 문구를 설정하고 req.fileValidation 은 controller 에서도 사용할 수 있기 때문에 컨트롤러에서 확인하여 분류한다
코드 동작 영상
다운로드 구현
router 와 controller 에 이미지가 저장된 디렉토리의 내용을 읽어오는 코드를 작성
읽어온 이미지를 /file/list 경로로 보내줘서 출력 후 a 태그를 걸어 다운로드 링크를 생성
라우터에 다운로드 경로 추가, 컨트롤러에 다운로드 기능 추가
res.download(경로) : 해당 경로를 다운로드
다운로드 기능 구현 완료
이미지 업로드 시 미리보기 기능 구현
이미지 미리보기 구현은 파일 올리는 부분의 ejs 에서만 처리해주면 된다
onchange="readURL(this)" : 만약 파일이 선택되면 태그에 변경이 일어나기 때문에 readURL() 함수를 실행시킨다, 이때 매개변수로 자기 자신 태그가 가지고 있는 파일 정보를 전송한다.
readURL 함수에서는 이 파일의 정보를 input 변수로 넘겨 받아서 해당 변수의 files 라는 키 안에 들어있는 파일의 저장 경로를 file 함수로 담아준다
> 만약 파일 경로가 비어있지 않다면 ( 파일이 정상적으로 올라왔다면 ) 이 파일의 정보를 FileReader 를 사용하여 읽어서 변수 e 로 만든다.
> 이후에 이 변수의 target 이라는 키 안에 result 키에 담겨있는 이미지에 대한 경로를 가져와서 html 코드의 img 경로를 변경해준다
나중에 쇼핑몰같은 홈페이지의 경우 썸네일을 모두 원본으로 사용해버리면 용량이 너무 커지기 때문에 썸네일용으로 따로 파일을 처리해서 사용해야 한다 ( 구선생님께 노드 썸네일 생성 으로 검색하면 나옴 )
파일 삭제 구현
ejs 작성, router 작성
controller 에 삭제 기능 구현
파일 수정
원본 파일을 삭제 후 저장
수정기능 경로로 가는 ejs 파일 작성, router 에 경로와 파일이름 같이 전송
controller 에 views 에 modify_form 경로로 가는 부분 작성
modify_form.ejs 작성
modify_form.ejs 에 hidden 으로 코드 추가
수정 부분 router 에 추가 ( 파일을 전송하기 때문에 post 방식 )
파일을 수정하면 원본으로 있던 파일을 삭제하는 코드를 controller 에 작성, 그리고 수정을 누르는 순간 router 에서 수정될 이미지는 upload 명령어를 사용해서 저장하기 때문에 따로 새로 수정될 이미지를 저장하는 코드는 작성하지 않음
자바스크립트 파일과 css 파일을 하나의 파일로 분리하여 관리
중복된 스크립트 코드를 image_read.js 라는 파일에 옮겨놓음
스크립트가 들어있는 경로를 /static 으로 설정 후 file_index.ejs 파일과 modify_form.ejs 파일에 설정
암호화된 값을 비교할땐 compareSync(로그인 입력 비밀번호, DB에 저장된 비밀번호) 로 비교하여 결과 값이 true, false 로 나오는 것을 확인하여 사용한다.
fetch
fetch 를 사용하기 위해서 body-parser 모듈의 기능이 필요함
app02.js 파일 생성 후 코드 작성
보여질 폴더, 파일 추가
non_fetch.ejs 파일 작성
조회수 기능을 만들기 위해 count 함수 추가 후 전달
non_fetch.ejs 파일에 조회수 출력
fetch 를 사용하지 않고 자기 자신의 페이지로 가는 링크를 이동하면 웹페이지가 처음부터 끝까지 새로 갱신된다
( 즉, 웹을 처음부터 끝까지 다시 로딩한다 )
fetch 를 사용할 경로인 localhost:3000/fetch01 생성
fetch01.ejs 파일 생성하여 fetch 를 사용해서 자기 자신 경로를 다시 서버로 요청
fetch : 서버로 요청을 하는 것은 a 태그, location.href 와 동일하나 fetch 는 서버로 연동은 되지만 페이지를 요청하는 것이 아닌 데이터만 주고 받는다
.then 을 통해 동기처리, async - await 을 통해 동기 처리
fetch 를 사용해서 받아온 데이터는 비동기적으로 작동하기 때문에 동기적으로 작동하게끔 처리해줘야 하며, 전달 받은 데이터는 json 형식으로 변환해야 확인 할 수 있기 때문에 json() 을 사용하여 json 형식으로 변환시켜서 사용하며 이 과정도 비동기적으로 작동하기 때문에 동기적으로 작동하게끔 처리해줘야 한다
get : 데이터를 얻어올 때 사용 ( 파라미터를 get 방식으로 서버와 주고 받음 )
post : 데이터를 추가할 때 사용 ( 파라미터를 post 방식으로 서버와 주고 받음 )
create table members(
id varchar2(20) primary key,
pwd varchar2(100),
name varchar2(20),
addr varchar2(100)
);
insert into members values('aaa','aaa','홍길동','산골짜기');
insert into members values('bbb','bbb','김개똥','개똥별');
insert into members values('ccc','ccc','고길똥','마포구');
commit;
이제는 router 경로를 최초 root 경로만 app.js 에서 설정한 뒤 세부 주소는 router.js 에서 나눠준다
router.js 에서는 app.js 에서 전달받은 app 을 사용한 뒤 return 으로 라우터를 반환하고 바로 module.exports 를 시켜버린다, index.ejs 작성
회원정보 클릭시 이동되는 /member/list 경로를 member_router.js 에 작성, router.js 에서는 경로가 /member 로 오면 member_router.js 가 경로를 관리하게끔 설정 - app.use("/member", [require 를 통해 받아온 member_router 의 이름] )
login.ejs 작성 ( 로그인 정보를 세션으로 담아 보낼 것이기 때문에 post 형식으로 전달 )
router 에 login_check 경로 생성 ( post 방식으로 전달했기 때문에 router.post 를 사용 )
라우터에 post 방식으로 받아오기 때문에 router.post 를 사용한다
controller 에서 세션에 대한 정보를 받아서 콘솔에 출력하는 코드 작성
세션 값 확인
로그인 검증 코드를 controller 에 작성 ( DB 는 더미 데이터 변수 사용 )
success 경로로 가는 기능을 router 와 controller 에 작성
success.ejs 파일 생성 및 작성
로그인 정보가 있을때만 success 페이지로 보내는 코드를 작성, 로그인 실패 시 로그인 실패 문구 출력 코드도 작성
success 함수 부분에 if 문 안에 req.session.username 은 오타 => req.session.userName 으로 변경해야 함
스크립트를 처리하는 함수를 따로 선언
함수로 간단하게 출력 문구 코드 대체
로그인 부분에 username 키를 전달
로그인 페이지에 접근했을때 username 이라는 세션이 존재한다면 로그인 문구 출력, 세션이 존재하지 않는다면 로그인 창을 출력
router 와 controller 에 세션을 모두 만료시키는 기능을 추가
코드 실행
( 시크릿 모드로 실행시키면 개발자 모드를 켜놓지 않고 /localhost:3000/session/success 로 직접 진입 시 alert 창이 출력되지 않고 바로 /localhost:3000/session/login 으로 리다이렉트 되는 현상이 발생.... 시크릿 모드 해제 또는 시크릿모드에서 개발자 모드 활성화 및 다른 브라우저로 작동시키면 정상 작동 확인 )
파일로 세션을 저장해서 관리하는 방법
( 개발할때 테스트가 필요한 경우 코드를 수정하면 세션이 초기화되기 때문에 파일로 저장해놓고 사용 )
기본 코드 작성 ( app.js, cookie_router.js, cookie_controller.js, cookie01.ejs )
서버 실행 확인
쿠키와 세션을 사용하는 이유 : HTTP 통신은 비연결성 통신( 연결 시도 후 연결이 되면 끊기는 형식 - 예를 들어 클라이언트가 request 를 서버로 전송한 뒤 연결을 끊음, 그럼 서버는 클라이언트에게 response 를 보낸 후 연결을 끊음.... 그렇기 때문에 로그인 정보와 같은 것을 쿠키와 세션에 보관해서 인증한다 )
쿠키 : 클라이언트가 관리 ( 보안에 좋지 않기 때문에 쿠키는 로그인에는 잘 사용하지 않는다 )
세션 : 서버가 관리
app01.js 파일에 cookie-parser 모듈을 불러온다
app 에서 동작하는 cookieParser 라는 값을 app 에서 사용할 수 있게끔 middle ware 로 위임
cookie_ctrl.js 에서 response 에 cookie 를 추가 이때 res.cookie("쿠키 키","쿠키 값"); 으로 표현한다
다시 웹에 접속해 개발자 모드(F12)에서 Application 탭에 들어가서 쿠키 탭을 확인하면 쿠키가 정상적으로 받아지는 것을 확인할 수 있다
쿠키 설정 값을 변수화하여 쿠키의 속성 값을 적용한다
쿠키가 5초뒤에 삭제됨
전달 받은 쿠키의 값이 제대로 출력되는지 cookie01.ejs 파일에 전달하여 출력해보기
쿠키 관리를 위해 팝업을 띄우기
쿠키를 생성하여 5초동안 팝업이 뜨지 않게 하기
localhost:3000/cookie02 로 접속하면 창 띄우기
쿠키 정보가 담긴 userCookie 변수를 cookie02.ejs 를 실행할때 전송하기
cookie02.ejs 에서는 쿠키가 존재하지 않는다면 팝업창을 띄우기.... popup02 를 띄우게 라우터와 컨트롤러에 다시 설정하러 가야함
popup02 경로를 설정
popup02.ejs 파일에서 하루동안 열지 않음!!! 텍스트나 체크박스를 클릭하면 makeCookie 함수가 실행되며 이 함수에는 /cookie/makeCookie 경로로 이동시키는 기능과 창을 닫는 기능을 스크립트로 생성해놓는다
makeCookie 가 실행되면 쿠키를 적용해주고 창을 닫는다
코드 실행 시 쿠키를 가지고 있는 5초 동안은 새로고침을 해도 팝업창이 출력되지 않는 모습
쿠키를 암호화 하기, 쿠키를 config.js 파일로 분리하기
기존에 있던 cookieConfig 를 config.js 파일을 따로 생성하여 분리하면서 signed : true 옵션을 사용하여 암호화 시킨다
signed : true => 쿠키 암호화 ( 암호화 키 값은 cookieParser 를 미들웨어로 등록할때 괄호 안에 키 값을 입력해준다 )
이후에 cookieConfig 를 require 하여 불러온 뒤 사용한다, 또한 쿠키를 가져올땐 req.signedCookies.쿠키이름 을 사용하여 쿠키를 가져온다... 기존에는 req.cookies.쿠키이름 이었지만 signedCookies 로 암호화된 쿠키를 가져옴을 명시한다
장바구니 만들기
더미로 장바구니 DB 생성
라우터에 경로 추가
컨트롤러에 cart 경로와 서비스 추가
cookie_service 에 더미 DB 반환 코드 추가 및 export
전달 받은 더미 데이터 forEach 문으로 나열하기
상품 목록에 상품 아이디로 링크를 걸기 링크 클릭하면 /cookie/save 로 넘어가야 하기 때문에 경로를 라우터와 컨트롤러에 추가
/save/:goods 에서 경로 뒤에 :goods 는 콜론 뒤에 /save/ 경로 뒤에 오는 내용을 goods 라는 변수로 저장한다는 뜻
goods 라는 변수로 넘겨받은 /save/ 뒤의 경로 정보를 params 를 사용하여 변수로 저장한 뒤 alert 창을 출력하고 다시 /cookie/cart 경로로 돌려보낸다
코드 실행
쿠키 정보가 있는지 없는지 확인 후 변수에 쿠키에 저장될 변수를 생성 및 데이터 추가
cookie_service 에서 전달받은 cart_list 에 쿠기를 저장한 뒤 cart_list 를 다시 반환
저장 목록 확인을 눌렀을때 이동되는 view_list 경로를 라우터에 설정controller 에도 설정하여 만약 cart_list 라는 쿠키를 사용자가 가지고 있지 않다면 alert 창을 띄운 후 다시 /cookie/cart 로 보내고 사용자가 cart_list 쿠키를 가지고 있다면 views_list.ejs 에 cart_list 쿠키를 값으로, list 를 키로 설정하여 전달
view_list.ejs 파일 생성하여 해당 내용을 출력하게 설정
코드 실행 영상 ( 쿠키는 현재 5초 뒤 삭제되게끔 설정되어 있으므로 5초가 경과되면 자동으로 저장 목록이 삭제된다 )