생각기록
2022-11-22 Express, ejs 수업 본문
노드js로 웹서버 만들기
서버 구축, 웹프론트엔드랑 연결해서 데이터 주고받기가 목표
패키지 매니저
npm
Node Package Manager ( https://www.npmjs.com/ )
노드 패키지를 관리해주는 틀
*패키지 : 노드 모듈 - 패키지들 간 의존 관계가 존재
Express
웹 서버를 생성하는 것과 관련된 기능을 담당하는 프레임워크
웹 애플리케이션을 만들기 위한 각종 메소드와 미들웨어 등이 내장되어 있다.
http 모듈 이용시 코드의 가독성↓ 확장성 ↓ → 이를 해결하기 위해 만들어진 것이 Express 프레임워크
npm 환경설정
해당 파일 있는 폴더 cd로 들어가기
1. npm init
enter 연타! (default 값)
프로젝트를 시작할 때 사용하는 명령어 > package.json이 생성)
프로젝트에 대한 설명을 적을 수 있는 package.json에 입력한다.
2.npm init --yes
package.json이 생성될 때 기본 값으로 생성된다.
[자세히보면 내용이 추가 되는 것이 있음]
3. npm install express
프로젝트에서 사용할 패키지를 설치하는 명령어
설치된 패키지의 이름과 정보는 package.json에 dependencies(express 값 추가)에 입력된다.
-node_moudules 폴더와
pacakge-lock.json 파일이 추가 됨
package.json 파일
패키지들이 서로 의존되어 있어, 문제가 발생할 수 있는데 이를 관리하기 위해 필요한 것
프로젝트에 대한 정보와 사용 중인 패키지 이름 및 버전 정보 가 담겨 있는 파일
- “name” : 패키지 이름
- “version” : 패키지의 버전
- “main” : 자바스크립트 실행 파일 진입점 ( 문답식에서의 entry point )
- “description” : 패키지에 대한 설명
- “scripts” : npm run 을 이용해 정해놓는 스크립트 명령어
- “license” : 해당 패키지의 라이센스
4. .gitignore
내가있는곳에서 ~라는 폴더를 무시하겟다.
node_modules 폴더와
package-lock.json 파일을 무시 시키면,
=> express 모듈 설치로 인해서 추가된 애들이라서 git에 굳이 올릴 필요가 없음
=> .gitignore 파일 생성해서 /node_modules, package-lock.json 입력하여 2개 파일은 등록안되게 설정
- **/node_modules => 어떤 경로에서든 node_modules 폴더를 무시하겠다는 뜻
이런식으로 비활성화가 됨
Express 사용
express()
Express 모듈이 export 하는 최상위 함수로, express application을 만듦
담을 곳을 변수로 설정
app 객체
Express() 함수를 호출함으로써 만들어진 express application
app 객체의 method
- get 등.. 여러개 있음
- 클라이언트가 서버에 보낸 요청을 처리한다.
- HTTP 요청을 각 요청에 맞는 경로로 전송하는 메소드(라우팅)
기본 웹서버 정의 셋트
//웹서버 여는 코드
const express = require('express');
const app = express(); //필요한 메소드를 app객체 속에 넣음
//포트 정의 (1023이하 숫자 안됨!)
const port = 8080;
//브라우저에 들어가서 할 행동
//.get( 도메인 제외 주소, (req,res))
app.get('/',(req,res)=>{
res.send( ' hello Express !');
})
// 웹서버 여는법 listen(포트번호,함수)
// listen이 항상 밑으로 와야 위에 설정된 것들이 읽힘
app.listen(port,()=>{
console.log('서버 open : ', port);
})
브라우저에 들어가서 보여줄 행동 지정
- '/'은 일반 접속 즉 = localhost:8080 접속시 보여줄 행동
- .get은('라우터이름',(req,res)) 기본
app.get('/',(req,res) => {
res.send( ' hello Express !');
})
만약 html 파일 자체를 보여주고 싶다면?
1. localhost:8080/test > /test로 접속할 수 있는 라우터 만듦
2. .sendFile()에 들어올 경로는 무조건 절대경로
>__dirname은 현재 실행중인 폴더경로가 담긴 내장 변수 + '/views/index.html'이런식으로 사용 가능
= get 메소드로 test 라우터를 만들고 > sendFile로 파일경로 가져오는 것
app.get('/test', (req, res)=>{
res.sendFile(__dirname + 'views/index.html');
})
//localhost:8080/test > /test로 접속할 수 있는 라우터 만듦
//.sendFile()에 들어올 경로는 무조건 절대경로, __dirname은 현재 실행중인 폴더경로가 담긴 내장 변수 + '/views/index.html'이런식으로 사용 가능
//get 메소드로 test 라우터를 만들고 > sendFile로 파일경로 가져오는 것
서버안에 연결된 html같은 파일을 수정하면, img파일이 반영이 안된다.
미들웨어 등록
서버에서
클라이언트가 어떠한 폴더가 접근할수있게하려면, 서버측에서 권한을 만들어줘야한다.
= app.use 미들웨어 등록
미들웨어란?
- 요청이 들어옴에 따라 응답까지의 중간 과정을 함수로 분리한 것
- 서버와 클라이언트를 이어주는 중간 작업
- use() 를 이용해 등록할 수 있다.
- 실제존재하는 폴더에 가상경로 부여해서 쓸 수 있게함
미들웨어 - static
로컬 폴더를 서버가 인식할수 있도록 설정해줘야 한다.
이미지, css 파일 및 Javascript 파일과 같은 정적 파일 제공
Express 에 있는 static 메소드를 이용해 미들웨어로 로드
= static이라는 실제 존재하는 폴더에 publlic이라는 가상 경로로 접근할 수 있도록 함
// 서버 파일
app.use('/public', express.static('static'));
- app.use 미들웨어 등록 (가상경로, express.static( '실제 존재 폴더 이름' ));
가상경로는 마음대로, 두번째인자는 정해진대로 써야함// ejs 파일 //public 가상 폴더 경로 (미들웨어) <img src="/public/img/1.jpg">
- src='/public/img/1.jpg'
- 해당파일과 서버파일을 둘다 수정해야 사진같은 것들이 뜬다.
- tip. 가상 경로 = 폴더 이름 같은 이름으로 해야 편하다. > 예)app.use('/static', express.static('static')); src='/static/img/1.jpg'
- 하위 폴더들도 영향을 받기때문에 static폴더에 있으면, app.use 일일이 해줄 필요 없다
EJS란?
html 대신 ejs템플릿을 사용하면, 편리한 기능을 제공한다.
전체적으로 html과 똑같고, 차이점은 javaScript를 코드를 html 내부에 내장을 시킬 수 있다.
템플릿 엔진
문법과 설정에 따라 파일을 html 형식으로 변환시키는 모듈
ejs
Embedded Javascript 의 약자로, 자바스크립트가 내장되어 있는 html 파일
확장자는 .ejs
사용하기 위해서는, ejs를 깔아줘야 합니다.
ejs 템플릿 설정
1. npm install ejs
2. app.set('view engine', 'ejs');
이렇게 되면, views라는 폴더가 view가 모여있는 기본 디렉토리로 설정 됨!
ejs를 쓸거면, 그냥 외우도록 하자.
3. res.render('test');
test.ejs 파일 호출
view engine 이 설정되서
프로젝트 위치 /views/test.ejs를 찾는다.
기본 ejs 문법
문법
1. <% %> 하나의 태그, 이곳에 javaScript 코드를 쓸 수 있다 (이 안에서 쓸수있는 문법, 안되는 문법은 쓰면서 알 수 있다)
2. 한줄 내에 열리고 닫혀야한다.
3. { %> 중괄호를 첫 줄에서 열어줘야 이어진다는 의미로 인식한다
4. 변수 출력하고 싶을 때 : <%=변수%>
5. 예) data.length 변수 = <%=data[i]%> 는 서버 파일에서 data란 객체를 생성해서 .render()로 ejs 파일로 넘겼다.
6. <% = 문자열 인식 o, 태그 인식 x
7. <% - 태그 인식
8. <%-include(' view의 상대주소') %> 다른 view 파일을 불러올 때 사용
//ejs 파일
<title><%=title%></title> //서버파일에 res.render로 객체 데이터가 넘어 옴
<img src="/pubilc/img/1.jpg"> //미들웨어로 가상경로 폴더 public 사용
<% for(var i = 0; i<5; i++){ %>
<div>안녕<%=i+1%></div>
<% } %>
// = 은 문자열 인식 태그인식 x
// -는 태그로 인식합니다 > 글자가 파랑색
<div style="color: red;"><%="<span style='color:blue;'>안녕</span>"%>하세요</div>
<div style="color: red;"><%-"<span style='color:blue;'>안녕</span>"%>하세요</div>
//이런식으로 한 줄에 열리고 닫혀야 하고, <!-- <% if(true) { 중괄호가 다음에 이어지게 끊어친다
<!-- <% if(true) {%>
<% else if(true){ %>
<% } else { %>
<% } %> -->
//ejs 파일 연결 함수
//-include(파일이름 상대경로로) 함수 -는 태그 인식하라고 쓴것!
//navbar 같은 거 만들때, 여기저기 필요하기 때문에 제일 위에 위치시켜주면 된다.
// test.ejs 파일을 이 부분에 연결한다 라는 뜻
<%-include('test.ejs')%>
서버에서 보내준 데이터를 클라이언트가 데이터따라 바뀌어서 랜더하게 되는데
render() 매소드
res.render('ejs파일 이름', 두번째 인자)
- 해당 데이터를 'ejs파일'에 보낸다. = ejs 파일에 두번 째 인자를 넘긴다는 뜻
- 두번째 인자는 선택사항
- 객체 형태로 넘겨줘야 한다.
//서버 파일
app.get('/ejs', (req, res) => {
res.render('test', { //test.ejs파일에 넘긴다라는 뜻 data가 넘어간다!
title:"test 페이지 입니다!@",
data: ['a','b','c']
});
})
//7. ejs 템플릿 사용 : 서버에서 보내준 데이터를 클라이언트가 데이터따라 바뀌어서 랜더하게 되는데
// render 의 두번째 인자는 선택사항이며, 객체 형태로 넘겨줘야 한다.
// test.ejs 파일
<title><%=title%></title> //서버파일에 res.render로 객체 데이터가 넘어 옴
실습1. ejs에서 for문 사용해 사진 1,2,3이 /img 라우터에 나오게 하기
실습 http://localhost:8080/img로 접속했을 때
ejs의 for문을 이용해 사진 1,2,3이 나오게 하기
//서버 파일
app.get('/img', (req,res)=>{
res.render('img',{ //img.ejs파일에게 뒤의 정보를 보내겟다.
title:"이미지 for문"
})
})
//img.ejs
<head>
<title><%=title%></title>
</head>
<body>
<% for(var i = 1; i<=3; i++ ){ %>
<img src="/static/img/<%=i%>.jpg">
<% } %>
</body>

form 전송
form 태그
입력된 데이터를 한 번에 서버로 전송하기 위해 사용
즉, 클라이언트(컴퓨터)가 서버에게 정보를 전달할 때 사용
속성
action
정보를 전달할 주소(만들어둔 라우터를 action에 삽입)
= 서버측에도 저런 주소가 있어야 연결 된다.
예) getform 이란 라우터에 정보를 전달할 것이다.
서버에도 getform이란 라우터 생성
method
폼을 서버에 전송할 http의 메소드 지정 > get, post .. 등이 있다.
get과 post의 차이점은 get은 url에 정보전달 내용이 그대로 다 보임 > 보안성 떨어짐
name
폼을 식별하기 위한 이름
form name은 선택사항이고, input name은 필수사항
radio는 객관식이며 한 가지만 선택 가능 그 것을 묶는 묶음의 기준은 name임 / name 설정 없으면, 다중 선택
다중 선택을 사용하고 싶으면 checkbox 사용
value
우리 눈에는 input이 뭔지 구분하기 쉽지만, 서버는 그렇지 않다.input의 라디오든 체크박스든 value를 해줘야 서버가 어떤 값인지를 인식
target
action 속성값에 지정한 스크립트 파일을 현재 창이 아닌 다른 위치에서 열 수 있도록 함
_blank, _self
get과 post 사용법
먼저 post를 사용하려면 body-parser 설정을 해줘야 하는데
body-parser
클라이언트가 보내준 데이터를 쉽게 처리할 수 있도록 도와주는 라이브러리
Post로 정보를 전송할 때 요청의 body(req.body)로 받을 수 있게 도와 줌
express 4.x 부터 body-parser가 내장되어 있어 설치 필요 없음
body-parser 설정
//서버 파일
//9.form 전송, body-parser 쓰기위함 복붙, 외우기
app.use(express.urlencoded({extended:true})); //폼에도 타입이 있다. x-www-urlencoded 데이터 해석하겠다.
app.use(express.json()); // 데이터 형태를 json형태로 parsing해주겠다. = json: 딕셔너리 형태와 비슷하다.
app.use(express.urlencoded({ extended: true });
app.use(express.json());
기본적으로 form전송에는 타입이 있는데, 타입에 대한 설정을 해준다.
외우거나, 복붙해서 쓰자
method의 get과 post의 차이
get은 폼에 입력한 정보가 url에 추가되어 보인다.
기본 라우터 주소 +
http://localhost:8080/form/jsp?name=joon&address=suwoon < url에 그대로 정보가 노출 됨
?뒤에 있는 정보들을 쿼리라고 한다.
post
url에서 보이지 않는 것 때문에 보안상 좋다
http://localhost:8080/form/jsp
//form.ejs 파일
<h3>get 요청</h3>
<form action="/getform" method="get">
<input type="text" name="id">
<input type="password" name="pw">
//label과 for="아이디" 어딘가에 존재하는 아이디 , 기능: 라벨을 클릭하면 같이 클릭되게
//fieldset, legend는 묶여서 보임
<fieldset>
<legend>성별</legend>
<input type="radio" name="gender" value="남자" id="men"><label for="men">남자</label>
<input type="radio" name="gender" value="여자" id="women"><label for="women">여자</label>
</fieldset>
<fieldset>
<legend>취미</legend>
<input type="checkbox" name="interst" value="넷플릭스" id="net"><label for="net">넷플보기</label>
<input type="checkbox" name="interst" value="음악감상">음악감상
<input type="checkbox" name="interst" value="운동">운동
</fieldset>
<button type="submit">제출</button>
</form>
//readonly라고 하면, 입력이 안됨 클라이언트는 바꿀수없다.
//왜쓰냐? 그냥 기본값으로 value를 박고, 바꾸지 않길 바랄때
//네임은 셀렉트 태그, 값은 option에 넣는다
<h3>post 요청</h3>
<form action="/postform" method="post">
<input type="text" name="id" value="aaa" readonly>
<input type="password" name="pw" placeholder="비밀번호" required>
<select name="brithMonth">
<% for( var i = 1; i<=12; i++ ) { %>
<option value="<%=i%>"><%=i%>월</option>
<% } %>
</select>
//인풋과 다를바 없지만, 대용량으로 글을 쓸때 쓴다
//required를 쓰면, 반드시 값을 받는 필수값이 된다.
<textarea name="content" rows="30" cols="50" required></textarea>
<button type="submit">제출</button>
</form>
form 태그에 action은 정보를 전달할 주소 = 라우터
get 메소드 form 사용법
1. get 요청 form에서 제출 버튼을 눌러 정보를 전달하면, 받는 페이지가 /getform 이라는 주소에서 받겠다.
2. 서버에 getform 관련 라우터 생성과 어떤 행동을 할지 설정
app.get( ~ )
console.log(req(컴퓨터 > 서버 로 보낸 정보).query) => input으로 받은 정보 값을 딕셔너리 형태로 출력
getform으로 정보를 받으면, get 요청 성공이라고 페이지에 뜬다
1. localhost:8080/form 에서 get 속성인 form에 클라이언트가 정보를 전달하면
2. localhost:8080/getform 라우터로 정보를 전달 받고,
get의 특징인 url 속 ?뒤 = query에
정보 전달 값이 노출 된다. = 그래서 get은 url로 직접 치고 들어갈 수 있다.
post 메소드 form 사용법
1. post 요청 form에서 제출 버튼을 눌러 정보를 전달하면, 받는 페이지가 /postform 이라는 주소에서 받겠다.
2. 서버에 postform 관련 라우터 생성과 어떤 행동을 할지 설정
app.post( ~ )
get은 query를 통해 정보를 가져오지만,
post의 정보는 body에 담겨 온다.
req.body (컴퓨터의 정보 전달을 body에서 가져오겠다)
res.render (서버의 응답을 보여주겠다 'result'파일로 , {data : req:body}); 데이터란 객체에 클라이언트에게서 받은 정보를 넘겨 주겠다.
result.ejs 파일
1. localhost:8080/form에서 제출을 누르면
2. localhost:8080/portform 라우터로 정보가 전달 되며,
3. result.ejs파일이 보이며, 클라이언트가 보낸 정보를 받은 모습을 보여준다.
input 태그
- 사용자가 다양하게 폼 태그를 입력할 수 있게 하는 것
- 입력창 가장
- 기본적인 form 요소
속성
name : 이름 지정. backend에서 name으로 key가 설정된다.
readonly : 읽기 전용 (수정 불가)
required : 필수 입력 값
autofocus : 자동 focus
placeholder : 짧은 도움말
name = 키, 입력 값이 = 값
id : aaa
readonly는 기본값 설정 (변경하고싶지 않을 때)
required는 필수값 설정
input type 종류
type : 인풋 타입
select : 선택창
- 서버가 지정한 특정 값만을 선택할 수 있는 요소
- input이 주관식이면, select는 객관식
label : 폼 양식에 이름을 붙일 수 있다.
- for 속성에 연결할 요소의 id를 적어 label을 클릭해도 해당 요소로 가게 할 수 있다.
fieldset : form태그 요소들을 그룹핑
- <legend> 태그 : fildset 태그 안에 들어감, 목적에 맞게 이름을 지정 할 수 있다.
실습2,3 get, post로 정보 받기
실습 2. get으로 정보 받기

//test_2.ejs
<h1>test_2_form</h1>
<form action="/test_2_form" method="get">
이름 <input type="text">
<fieldset>
<legend>성별</legend>
<input type="radio" name="gender" value="남자" id="men"><label for="men">남자</label>
<input type="radio" name="gender" value="여자" id="women"><label for="women">여자</label>
</fieldset>
<fieldset>
<legend>생년월일</legend>
<select name="brithyear">
<% for( var i = 1900; i<=2022; i++ ) { %>
<option value="<%=i%>"><%=i%>년</option>
<% } %>
</select>
<select name="brithMonth">
<% for( var i = 1; i<=12; i++ ) { %>
<option value="<%=i%>"><%=i%>월</option>
<% } %>
</select>
<select name="brithdate">
<% for( var i = 1; i<=31; i++ ) { %>
<option value="<%=i%>"><%=i%>일</option>
<% } %>
</select>
</fieldset>
<fieldset>
<input type="checkbox" name="interest" value="여행" id="여행"><label for="여행">여행</label>
<input type="checkbox" name="interest" value="패션" id="패션"><label for="패션">패션</label>
<input type="checkbox" name="interest" value="음식" id="음식"><label for="음식">음식</label>
</fieldset>
<button type="submit">회원가입</button>
</form>
<h1>test_2_post</h1>
<form action="/test_2_post" method="post">
이름 <input type="text" required>
<fieldset>
<legend>성별</legend>
<input type="radio" name="gender" value="남자" id="men" required><label for="men">남자</label>
<input type="radio" name="gender" value="여자" id="women" required><label for="women">여자</label>
</fieldset>
<fieldset>
<legend>생년월일</legend>
<select name="brithyear">
<% for( var i = 1900; i<=2022; i++ ) { %>
<option value="<%=i%>"><%=i%>년</option>
<% } %>
</select>
<select name="brithMonth">
<% for( var i = 1; i<=12; i++ ) { %>
<option value="<%=i%>"><%=i%>월</option>
<% } %>
</select>
<select name="brithdate">
<% for( var i = 1; i<=31; i++ ) { %>
<option value="<%=i%>"><%=i%>일</option>
<% } %>
</select>
</fieldset>
<fieldset>
<input type="checkbox" name="interest" value="여행" id="여행"><label for="여행">여행</label>
<input type="checkbox" name="interest" value="패션" id="패션"><label for="패션">패션</label>
<input type="checkbox" name="interest" value="음식" id="음식"><label for="음식">음식</label>
</fieldset>
<fieldset>
<input type="color" name="color" value="컬러선택" id="컬러선택"><label for="컬러선택">컬러선택</label>
<input type="number" name="number" value="좋아하는 숫자" id="좋아하는 숫자"><label for="좋아하는 숫자">좋아하는 숫자</label>
</fieldset>
<button type="submit">회원가입</button>
</form>
//서버 파일
//기본 form > test_2_form 라우터
app.get('/test_2_form',(req,res)=>{
res.render('test_2');
})
//클라이언트에게 받을 정보 라우터 /test_2_getform
app.get('/test_2_getform',(req,res)=>{
console.log(req.query); //get이라 qurey로 받는다.
res.send('test_2_get요청 성공!')
})

실습3. post로 정보 받기

//test_2.ejs 파일
<h1>test_2_post</h1>
<form action="/test_2_post" method="post">
이름 <input type="text" required>
<fieldset>
<legend>성별</legend>
<input type="radio" name="gender" value="남자" id="men" required><label for="men">남자</label>
<input type="radio" name="gender" value="여자" id="women" required><label for="women">여자</label>
</fieldset>
<fieldset>
<legend>생년월일</legend>
<select name="brithyear">
<% for( var i = 1900; i<=2022; i++ ) { %>
<option value="<%=i%>"><%=i%>년</option>
<% } %>
</select>
<select name="brithMonth">
<% for( var i = 1; i<=12; i++ ) { %>
<option value="<%=i%>"><%=i%>월</option>
<% } %>
</select>
<select name="brithdate">
<% for( var i = 1; i<=31; i++ ) { %>
<option value="<%=i%>"><%=i%>일</option>
<% } %>
</select>
</fieldset>
<fieldset>
<input type="checkbox" name="interest" value="여행" id="여행"><label for="여행">여행</label>
<input type="checkbox" name="interest" value="패션" id="패션"><label for="패션">패션</label>
<input type="checkbox" name="interest" value="음식" id="음식"><label for="음식">음식</label>
</fieldset>
<fieldset>
<input type="color" name="color" value="컬러선택" id="컬러선택"><label for="컬러선택">컬러선택</label>
<input type="number" name="number" value="좋아하는 숫자" id="좋아하는 숫자"><label for="좋아하는 숫자">좋아하는 숫자</label>
</fieldset>
<button type="submit">회원가입</button>
</form>
//서버 파일
app.post('/test_2_post',(req,res)=>{
console.log(req.body); // post는 정보값은 body로 받는다
res.send('post성공');
})



form validation (유효성 검사)
form 요소들에 정보가 올바르게 입력되었는지 검사하는 것
ex. 비밀번호: 8자리 이상, 특수문자 및 대문자 1개 이상 포함
ex. 이메일: @ 기호 반드시 포함
required : 필수 값
minlength / maxlength : 최소/최대 문자수
min / max : 최소/최대 값
type : 입력받는 정보 타입
pattern : 정규식으로 검사
'SeSAC 풀스택 > Nodejs' 카테고리의 다른 글
2022_11_25_화면 출력 관련 / 참고 사이트 (0) | 2022.11.25 |
---|---|
2022-11-24 동적 form 전송 (0) | 2022.11.24 |
2022_11_19_프로미스 (0) | 2022.11.19 |
callback (0) | 2022.11.17 |
2022-11-17 node.js 모듈, 구조 분해 할당, callback (0) | 2022.11.17 |