최신 버전이 아닌 검증된 LTS버전을 받아준다. 설치 후 정상적으로 다운받아졌는지 확인한다.documents 폴더로 이동해준 후 boiler-plater폴더를 만들어 준다.boiler-plate 폴더로 이동해준 후 npm 패키지를 만들어 준다.기본 설정으로 계속 엔터를 쳐준 후 author에는 이름을 넣어준다.
오픈 폴더를 누르고 아까 만들어둔 폴더를 입력한다.아까 만들어둔 npm 패키지 파일을 확인하고 폴더 열기제이슨파일index.js 파일을 만들어 준다.(시작점을 만들어준다.)터미널창에서 윗 코드를 입력하여 인스톨 해준다. (express 라이브러리를 다운받아서 사용하는 것)
//express 모듈을 가지고 온다.
const express = require('express')
//새로운 펑션을 만들어서 app에 저장한다.
const app = express()
//백서버
const port = 3000
//Hello World!를 출력되게 한다.
app.get('/', (req, res) => res.send('Hello World!'))
//app을 실행 하는 것
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
index.js에 윗 예시를 넣어준다.
"start" : "node index.js",를 추가해준다.(시작점을 추가해준다)
콘솔창에서 실행 시켜준다. 웹브라우저 창에서서 해당되는 포트로 들어가면 결과물이 실행된다.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<!-- 상단의 네비게이션 바 부분 -->
<div class="nav">
<div class ="nav-item">메뉴1</div>
<div class ="nav-item">메뉴2</div>
<div class ="nav-item">메뉴3</div>
<div class ="nav-item">메뉴4</div>
</div>
<!-- 중간 테이블 -->
<div class = "main">
<div class ="title">
타이틀 부분
</div>
<div class="subtitle">
타이틀 아래의 내용을 기입 할 수 있습니다.
</div>
</div>
<div class = "leftside">
<div class="leftside-item">
왼쪽입니다.
</div>
<div class="leftside-item">
왼쪽2입니다.
</div>
<div class="leftside-item">
왼쪽3입니다.
</div>
</div>
<script src="script.js"></script>
</body>
</html>
CSS (스타일링) 구현하기
.box{
width : 100px;
height : 100px;
border : 1px solid black;
}
1. css는 HTML 엘레먼트의 스타일링을 하기 위해 사용
2. box는 class="box" 속성을 가진 엘레먼트를 스타일하고 싶다고 명시하는 것
3. width,height,border 같은 규칙을 써서 엘레먼트의 모양 및 위치를 바꿈
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<!-- 네비게이션 바 부분 css
height : 높이를 지정
border-bottom : 1px solid black : 선을 하나 그어준다.
display : flex; : 한 줄로 정렬한다.
align-items : center; : 글자를 중간으로 옮긴다.
-->
<style>
.nav {
height : 70px;
border-bottom : 1px solid black;
display : flex;
align-items : center;
}
</style>
</head>
<body>
<!-- 상단의 네비게이션 바 부분 -->
<div class="nav">
<div class ="nav-item">메뉴1</div>
<div class ="nav-item">메뉴2</div>
<div class ="nav-item">메뉴3</div>
<div class ="nav-item">메뉴4</div>
</div>
<!-- 중간 테이블 -->
<div class = "main">
<div class ="title">
타이틀 부분
</div>
<div class="subtitle">
타이틀 아래의 내용을 기입 할 수 있습니다.
</div>
</div>
<div class = "leftside">
<div class="leftside-item">
왼쪽입니다.
</div>
<div class="leftside-item">
왼쪽2입니다.
</div>
<div class="leftside-item">
왼쪽3입니다.
</div>
</div>
<script src="script.js"></script>
</body>
</html>
스타일링의 결과 값
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<!-- 네비게이션 바 부분 css -->
<style>
.nav {
height : 70px;
border-bottom : 1px solid black;
display : flex;
align-items : center;
}
.nav-right-items {
display : flex;
margin-left : auto;
}
.nav-item {
margin-left : 10px;
}
.company-name {
margin-left : 20px;
}
.title {
font-size : 60px;
font-weight : bold;
}
.subtitle {
font-size : 40px;
font-weight : 300;
}
</style>
</head>
<body>
<!-- 상단의 네비게이션 바 부분 -->
<div class="nav">
<div class="company-name">
GO치삼의 개발일지
</div>
<!-- 감싼 부분을 nav-right-item로 정의한다. -->
<div class="nav-right-items">
<div class ="nav-item">메뉴1</div>
<div class ="nav-item">메뉴2</div>
<div class ="nav-item">메뉴3</div>
<div class ="nav-item">메뉴4</div>
</div>
</div>
<!-- 중간 테이블 -->
<div class = "main">
<div class ="title">
타이틀 부분
</div>
<div class="subtitle">
타이틀 아래의 내용을 기입 할 수 있습니다.
</div>
</div>
<div class = "leftside">
<div class="leftside-item">
왼쪽입니다.
</div>
<div class="leftside-item">
왼쪽2입니다.
</div>
<div class="leftside-item">
왼쪽3입니다.
</div>
</div>
<script src="script.js"></script>
</body>
</html>
스타일링의 결과값
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<!-- 네비게이션 바 부분 css -->
<style>
.nav {
height : 70px;
border-bottom : 1px solid black;
display : flex;
align-items : center;
}
.nav-right-items {
display : flex;
margin-left : auto;
}
.nav-item {
margin-left : 10px;
}
.company-name {
margin-left : 20px;
}
.title {
text-align : center;
font-size : 60px;
font-weight : bold;
}
.subtitle {
text-align : center;
font-size : 40px;
font-weight : 300;
}
</style>
</head>
<body>
<!-- 상단의 네비게이션 바 부분 -->
<div class="nav">
<div class="company-name">
GO치삼의 개발일지
</div>
<!-- 감싼 부분을 nav-right-item로 정의한다. -->
<div class="nav-right-items">
<div class ="nav-item">메뉴1</div>
<div class ="nav-item">메뉴2</div>
<div class ="nav-item">메뉴3</div>
<div class ="nav-item">메뉴4</div>
</div>
</div>
<!-- 중간 테이블 -->
<div class = "main">
<div class ="title">
타이틀 부분
</div>
<div class="subtitle">
타이틀 아래의 내용을 기입 할 수 있습니다.
</div>
</div>
<div class = "leftside">
<div class="leftside-item">
왼쪽입니다.
</div>
<div class="leftside-item">
왼쪽2입니다.
</div>
<div class="leftside-item">
왼쪽3입니다.
</div>
</div>
<script src="script.js"></script>
</body>
</html>
글의 내용을 중앙으로 정렬한다.
정렬의 결과값
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<!-- 네비게이션 바 부분 css -->
<style>
.nav {
height : 70px;
border-bottom : 1px solid black;
display : flex;
align-items : center;
}
.nav-right-items {
display : flex;
margin-left : auto;
}
.nav-item {
margin-left : 10px;
}
.company-name {
margin-left : 20px;
}
.title {
text-align : center;
font-size : 3.5rem;
font-weight : bold;
}
.subtitle {
text-align : center;
font-size : 1.25rem;
font-weight : 300;
}
.main {
width : 800px;
margin : 0 auto;
margin-top : 60px;
}
</style>
</head>
<body>
<!-- 상단의 네비게이션 바 부분 -->
<div class="nav">
<div class="company-name">
GO치삼의 개발일지
</div>
<!-- 감싼 부분을 nav-right-item로 정의한다. -->
<div class="nav-right-items">
<div class ="nav-item">메뉴1</div>
<div class ="nav-item">메뉴2</div>
<div class ="nav-item">메뉴3</div>
<div class ="nav-item">메뉴4</div>
</div>
</div>
<!-- 중간 테이블 -->
<div class = "main">
<div class ="title">
타이틀 부분
</div>
<div class="subtitle">
타이틀 아래의 내용을 기입 할 수 있습니다.
</div>
</div>
<div class = "leftside">
<div class="leftside-item">
왼쪽입니다.
</div>
<div class="leftside-item">
왼쪽2입니다.
</div>
<div class="leftside-item">
왼쪽3입니다.
</div>
</div>
<script src="script.js"></script>
</body>
</html>
margin-top으로 윗 부붙에 여백을 지정해줍니다.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<!-- 네비게이션 바 부분 css -->
<style>
.nav {
height : 70px;
border-bottom : 1px solid black;
display : flex;
align-items : center;
}
.nav-right-items {
display : flex;
margin-left : auto;
}
.nav-item {
margin-left : 10px;
}
.company-name {
margin-left : 20px;
}
.title {
text-align : center;
font-size : 3.5rem;
font-weight : bold;
}
.subtitle {
text-align : center;
font-size : 1.25rem;
font-weight : 300;
}
.main {
width : 1000px;
margin : 0 auto;
margin-top : 60px;
}
.leftside-item {
width : 300px;
height : 350px;
border : 1px solid black;
margin : 20px;
border-radius : 4px;
}
.leftside {
display : flex;
}
.leftside-item-title {
font-size: 1.5rem;
background : rgba(0,0,0,.03);
text-align : center;
height : 53px;
line-height : 53px;
border-bottom: 1px solid black;
}
.leftside-item-price {
font-size: 1.5rem;
font-weight : bold;
padding : 20px;
text-align : center;
}
.leftside-item-detail {
font-size: 1.0rem;
font-weight : bold;
padding : 20px;
text-align : center;
}
.leftside-item-button {
padding: .5rem 1rem;
font-size: 1.25rem;
line-height : 1.5;
border-radius : .3rem;
color : #007bff;
background-color : transparent;
background-image : none;
border-color: #007bff;
margin-top : 20px;
margin-left : 85px;
}
.leftside-item-button-active {
background-color : #007bff;
color : white;
}
</style>
</head>
<body>
<!-- 상단의 네비게이션 바 부분 -->
<div class="nav">
<div class="company-name">
GO치삼의 개발일지
</div>
<!-- 감싼 부분을 nav-right-item로 정의한다. -->
<div class="nav-right-items">
<div class ="nav-item">메뉴1</div>
<div class ="nav-item">메뉴2</div>
<div class ="nav-item">메뉴3</div>
<div class ="nav-item">메뉴4</div>
</div>
</div>
<!-- 중간 테이블 -->
<div class = "main">
<div class ="title">
타이틀 부분
</div>
<div class="subtitle">
타이틀 아래의 내용을 기입 할 수 있습니다.타이틀 아래의 내용을 기입 할 수 있습니다.타이틀 아래의 내용을 기입 할 수 있습니다.타이틀 아래의 내용을 기입 할 수 있습니다.타이틀 아래의 내용을 기입 할 수 있습니다.타이틀 아래의 내용을 기입 할 수 있습니다.타이틀 아래의 내용을 기입 할 수 있습니다.타이틀 아래의 내용을 기입 할 수 있습니다.타이틀 아래의 내용을 기입 할 수 있습니다.타이틀 아래의 내용을 기입 할 수 있습니다.타이틀 아래의 내용을 기입 할 수 있습니다.타이틀 아래의 내용을 기입 할 수 있습니다.
</div>
<div class = "leftside">
<div class="leftside-item">
<div class = "leftside-item-title">
왼쪽의 윗칸
</div>
<div class = "leftside-item-price">
왼쪽의 중간칸(가격)
</div>
<div class = "leftside-item-detail">
왼쪽의 아랫칸
</div>
<button class = "leftside-item-button">
클릭하세요
</button>
</div>
<div class="leftside-item">
<div class = "leftside-item-title">
왼쪽1의 윗칸
</div>
<div class = "leftside-item-price">
왼쪽1의 중간칸
</div>
<div class = "leftside-item-detail">
왼쪽1의 아랫칸
</div>
<button class = "leftside-item-button leftside-item-button-active">
클릭하세요
</button>
</div>
<div class="leftside-item">
<div class = "leftside-item-title">
왼쪽2의 윗칸
</div>
<div class = "leftside-item-price">
왼쪽2의 중간칸
</div>
<div class = "leftside-item-detail">
왼쪽2의 아랫칸
</div>
<button class = "leftside-item-button leftside-item-button-active" >
클릭하세요
</button>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
style.css 안에서 태그를 해주면 html 태그 안에 <style>를 해주지 않아도 <link> 태그에서 css 파일을 불러와 반영해줄 수 있다.
<div class="box">박스</div>
<a href = "naver.com">네이버</a>
1. <div></div>는 태그라고 하고 항상 열림/닫힘 한 쌍이 있다.
2. class="box"은 속성이라고 함. 이 class 속성을 이용해서 나중에 css로 스타일링을 할 수 있음.
3. 합쳐서 "엘레먼트"라고 부름
<body>태그 관련텍스트 관련 태그들텍스트 관련 태그
미디어 관련 태그들
<!-- html 라는 것을 표현한다.-->
<html>
<!-- html 안에는 <head>,<body> 두 가지 태그가 있음 -->
<head>
<!-- 어떤 문서가 들어가는지 명시한다.-->
<title>타이틀을 적어주면 탭 창의 제목이 바뀝니다.</title>
<!--link 태그는 다른 곳에 저장되어있는 파일들을 불러와라라는 뜻이다.-->
<link href="style.css" rel="stylesheet" type="text/css"/>
<!-- mata 태그는 이 파일이 어떤 정보를 갖고 있는지를 나타내는 태그 이다. 스크랩할 때 간단하게 소개하는 멘트가 보여진다.-->
<meta name="description" content="HTML을 공부하는 문서">
<!--style태그는 css를 적어 줄 수 있다.-->
</head>
<body>
<!-- 미디어 관련 태그들 -->
<!-- 사진을 불러 올 때 쓰는 태그
src 는 소스의 줄임말이다. -->
<img src="이미지주소"/>
<!-- 비디오를 불러 올 때 쓰는 태그 -->
<video src="비디오주소" controls />
<!-- 링크 태그 -->
<a href="naver.com">네이버</a>
<!-- 새 창을 열어서 랑크 주소로 이동 -->
<a href="google.com" target="_blank">구글</a>
</body>
</html>
테이블 태그
<!-- html 라는 것을 표현한다.-->
<html>
<!-- html 안에는 <head>,<body> 두 가지 태그가 있음 -->
<head>
<!-- 어떤 문서가 들어가는지 명시한다.-->
<title>타이틀을 적어주면 탭 창의 제목이 바뀝니다.</title>
<!--link 태그는 다른 곳에 저장되어있는 파일들을 불러와라라는 뜻이다.-->
<link href="style.css" rel="stylesheet" type="text/css"/>
<!-- mata 태그는 이 파일이 어떤 정보를 갖고 있는지를 나타내는 태그 이다. 스크랩할 때 간단하게 소개하는 멘트가 보여진다.-->
<meta name="description" content="HTML을 공부하는 문서">
<!--style태그는 css를 적어 줄 수 있다.-->
</head>
<body>
<!-- 테이블 태그 -->
<table border="1">
<!-- 테이블의 칼럼 개수, 칼럼 이름 -->
<thead>
<!-- 칼럼 2개 생성 -->
<tr>
<th>이름</th>
<th>나이</th>
</tr>
</thead>
<!-- 표의 내용이 들어감 -->
<tbody>
<!-- 첫 줄 -->
<tr>
<td>고양이</td>
<td>6살</td>
</tr>
<!-- 두번째 줄 -->
<tr>
<td>물고기</td>
<td>1살</td>
</tr>
</tbody>
</table>
</body>
</html>
테이블 태그의 결과값
목록 태그들
<!-- html 라는 것을 표현한다.-->
<html>
<!-- html 안에는 <head>,<body> 두 가지 태그가 있음 -->
<head>
<!-- 어떤 문서가 들어가는지 명시한다.-->
<title>타이틀을 적어주면 탭 창의 제목이 바뀝니다.</title>
<!--link 태그는 다른 곳에 저장되어있는 파일들을 불러와라라는 뜻이다.-->
<link href="style.css" rel="stylesheet" type="text/css"/>
<!-- mata 태그는 이 파일이 어떤 정보를 갖고 있는지를 나타내는 태그 이다. 스크랩할 때 간단하게 소개하는 멘트가 보여진다.-->
<meta name="description" content="HTML을 공부하는 문서">
<!--style태그는 css를 적어 줄 수 있다.-->
</head>
<body>
<!-- 목록 태그들 -->
<!-- <ol>은 ordered list (순번을 붙여줌) -->
<ol>
<li>보비</li>
<li>쵸비</li>
<li>예쁘니</li>
</ol>
<!-- <ul> : unordered list / 앞에 점을 찍어주는 태그 -->
<ul>
<li>보비</li>
<li>쵸비</li>
<li>예쁘니</li>
</ul>
</body>
</html>
목록 태그의 결과 값
구역을 나누는 태그들
<!-- html 라는 것을 표현한다.-->
<html>
<!-- html 안에는 <head>,<body> 두 가지 태그가 있음 -->
<head>
<!-- 어떤 문서가 들어가는지 명시한다.-->
<title>타이틀을 적어주면 탭 창의 제목이 바뀝니다.</title>
<!--link 태그는 다른 곳에 저장되어있는 파일들을 불러와라라는 뜻이다.-->
<link href="style.css" rel="stylesheet" type="text/css"/>
<!-- mata 태그는 이 파일이 어떤 정보를 갖고 있는지를 나타내는 태그 이다. 스크랩할 때 간단하게 소개하는 멘트가 보여진다.-->
<meta name="description" content="HTML을 공부하는 문서">
<!--style태그는 css를 적어 줄 수 있다.-->
<style>
.top{
background: red;
height : 100px;
}
.mid{
background: blue;
height : 100px;
}
.bot{
background: green;
height : 100px;
}
</style>
</head>
<body>
<!-- 구역을 나누는 태그들 -->
<!-- <div> vs <span> -->
<div class ="top">상단</div>
<div class="mid">중단</div>
<div class="bot">하단</div>
</body>
</html>
구역을 나누는 태그의 결과값
<!-- html 라는 것을 표현한다.-->
<html>
<!-- html 안에는 <head>,<body> 두 가지 태그가 있음 -->
<head>
<!-- 어떤 문서가 들어가는지 명시한다.-->
<title>타이틀을 적어주면 탭 창의 제목이 바뀝니다.</title>
<!--link 태그는 다른 곳에 저장되어있는 파일들을 불러와라라는 뜻이다.-->
<link href="style.css" rel="stylesheet" type="text/css"/>
<!-- mata 태그는 이 파일이 어떤 정보를 갖고 있는지를 나타내는 태그 이다. 스크랩할 때 간단하게 소개하는 멘트가 보여진다.-->
<meta name="description" content="HTML을 공부하는 문서">
<!--style태그는 css를 적어 줄 수 있다.-->
<style>
.top{
background: green;
height : 100px;
}
.mid{
background: yellow;
height : 100px;
}
.bot{
background: red;
height : 100px;
}
.like{
background: green;
height : 100px;
}
.sub{
background: yellow;
height : 100px;
}
.comment{
background: red;
height : 100px;
}
</style>
</head>
<body>
<!-- 구역을 나누는 태그들 -->
<!-- <div> vs <span> -->
<!-- <div> -->
<div class ="top">상단</div>
<div class="mid">중단</div>
<div class="bot">하단</div>
<!-- <span> -->
<span class ="like">좋아요</div>
<span class="sub">구독</div>
<span class="comment">댓글</div>
<!-- <div>(block element)는 한 줄 전체 공간을 차지
<span>(inline element)은 자기 내용물 만큼의 공간만 차지 -->
</body>
</html>
<div> vs <span>의 결과값
인풋 태그
<!-- html 라는 것을 표현한다.-->
<html>
<!-- html 안에는 <head>,<body> 두 가지 태그가 있음 -->
<head>
<!-- 어떤 문서가 들어가는지 명시한다.-->
<title>타이틀을 적어주면 탭 창의 제목이 바뀝니다.</title>
<!--link 태그는 다른 곳에 저장되어있는 파일들을 불러와라라는 뜻이다.-->
<link href="style.css" rel="stylesheet" type="text/css"/>
<!-- mata 태그는 이 파일이 어떤 정보를 갖고 있는지를 나타내는 태그 이다. 스크랩할 때 간단하게 소개하는 멘트가 보여진다.-->
<meta name="description" content="HTML을 공부하는 문서">
</head>
<body>
<!-- 인풋 태그들 -->
텍스트 : <input type="text" />
체크박스 : <input type="checkbox" />
라디오 : <input type="radio" />
색깔 : <input type="color" />
여러문장 : <textarea></textarea>
드랍다운 : <select name="name">
<option value="보비">보비</option>
<option value="보비">쵸비</option>
</select>
<br>
로그인 :
<form>
<input type="email" placeholder="이메일" />
<input type="password" placeholder="비밀번호" />
<button type="submit">로그인</button>
</form>
</body>
</html>
같은 방식으로 신청 해준 후 , 파일질러로 닷홈 접속과 같이 들어간 후 같이 작업한 파일을 업로드 해준다.
컨트롤+F키로 email 주소를 찾아 준 뒤 수정 해주도록 한다.보여지는 결과값들jqBootstrapValidation.js를 열어주어 메일 기능 오류시 나오는 오류를 한글로 수정해준다.
if (settings.options.sniffHtml) {
var message = "";
// ---------------------------------------------------------
// PATTERN
// ---------------------------------------------------------
if ($this.attr("pattern") !== undefined) {
message = "예상치 못한 형식입니다.<!-- data-validation-pattern-message to override -->";
if ($this.data("validationPatternMessage")) {
message = $this.data("validationPatternMessage");
}
$this.data("validationPatternMessage", message);
$this.data("validationPatternRegex", $this.attr("pattern"));
}
// ---------------------------------------------------------
// MAX
// ---------------------------------------------------------
if ($this.attr("max") !== undefined || $this.attr("aria-valuemax") !== undefined) {
var max = ($this.attr("max") !== undefined ? $this.attr("max") : $this.attr("aria-valuemax"));
message = "값이 너무 높습니다. 최댓값 : '" + max + "'<!-- data-validation-max-message to override -->";
if ($this.data("validationMaxMessage")) {
message = $this.data("validationMaxMessage");
}
$this.data("validationMaxMessage", message);
$this.data("validationMaxMax", max);
}
// ---------------------------------------------------------
// MIN
// ---------------------------------------------------------
if ($this.attr("min") !== undefined || $this.attr("aria-valuemin") !== undefined) {
var min = ($this.attr("min") !== undefined ? $this.attr("min") : $this.attr("aria-valuemin"));
message = "값이 너무 낮습니다. 최솟값 :'" + min + "'<!-- data-validation-min-message to override -->";
if ($this.data("validationMinMessage")) {
message = $this.data("validationMinMessage");
}
$this.data("validationMinMessage", message);
$this.data("validationMinMin", min);
}
// ---------------------------------------------------------
// MAXLENGTH
// ---------------------------------------------------------
if ($this.attr("maxlength") !== undefined) {
message = "값이 너무 깁니다. 최댓값 : '" + $this.attr("maxlength") + "' characters<!-- data-validation-maxlength-message to override -->";
if ($this.data("validationMaxlengthMessage")) {
message = $this.data("validationMaxlengthMessage");
}
$this.data("validationMaxlengthMessage", message);
$this.data("validationMaxlengthMaxlength", $this.attr("maxlength"));
}
// ---------------------------------------------------------
// MINLENGTH
// ---------------------------------------------------------
if ($this.attr("minlength") !== undefined) {
message = "값이 너무 짧습니다. 최소값 : '" + $this.attr("minlength") + "' characters<!-- data-validation-minlength-message to override -->";
if ($this.data("validationMinlengthMessage")) {
message = $this.data("validationMinlengthMessage");
}
$this.data("validationMinlengthMessage", message);
$this.data("validationMinlengthMinlength", $this.attr("minlength"));
}
// ---------------------------------------------------------
// REQUIRED
// ---------------------------------------------------------
if ($this.attr("required") !== undefined || $this.attr("aria-required") !== undefined) {
message = settings.builtInValidators.required.message;
if ($this.data("validationRequiredMessage")) {
message = $this.data("validationRequiredMessage");
}
$this.data("validationRequiredMessage", message);
}
// ---------------------------------------------------------
// NUMBER
// ---------------------------------------------------------
if ($this.attr("type") !== undefined && $this.attr("type").toLowerCase() === "number") {
message = settings.builtInValidators.number.message;
if ($this.data("validationNumberMessage")) {
message = $this.data("validationNumberMessage");
}
$this.data("validationNumberMessage", message);
}
// ---------------------------------------------------------
// EMAIL
// ---------------------------------------------------------
if ($this.attr("type") !== undefined && $this.attr("type").toLowerCase() === "email") {
message = "이메일 형식이 잘못 입력 되었습니다. <!-- data-validator-validemail-message to override -->";
if ($this.data("validationValidemailMessage")) {
message = $this.data("validationValidemailMessage");
} else if ($this.data("validationEmailMessage")) {
message = $this.data("validationEmailMessage");
}
$this.data("validationValidemailMessage", message);
}
컨텍트미 파일 수정
$(function () {
$(
"#contactForm input,#contactForm textarea,#contactForm button"
).jqBootstrapValidation({
preventSubmit: true,
submitError: function ($form, event, errors) {
// additional error messages or events
},
submitSuccess: function ($form, event) {
event.preventDefault(); // prevent default submit behaviour
// get values from FORM
var name = $("input#name").val();
var email = $("input#email").val();
var phone = $("input#phone").val();
var message = $("textarea#message").val();
var firstName = name; // For Success/Failure Message
// Check for white space in name for Success/Fail message
if (firstName.indexOf(" ") >= 0) {
firstName = name.split(" ").slice(0, -1).join(" ");
}
$this = $("#sendMessageButton");
$this.prop("disabled", true); // Disable submit button until AJAX call is complete to prevent duplicate messages
$.ajax({
url: "/assets/mail/contact_me.php",
type: "POST",
data: {
name: name,
phone: phone,
email: email,
message: message,
},
cache: false,
success: function () {
// Success message
$("#success").html("<div class='alert alert-success'>");
$("#success > .alert-success")
.html(
"<button type='button' class='close' data-dismiss='alert' aria-hidden='true'>×"
)
.append("</button>");
$("#success > .alert-success").append(
"<strong>메일이 성공적으로 보내졌습니다. </strong>"
);
$("#success > .alert-success").append("</div>");
//clear all fields
$("#contactForm").trigger("reset");
},
error: function () {
// Fail message
$("#success").html("<div class='alert alert-danger'>");
$("#success > .alert-danger")
.html(
"<button type='button' class='close' data-dismiss='alert' aria-hidden='true'>×"
)
.append("</button>");
$("#success > .alert-danger").append(
$("<strong>").text(
"죄송합니다. " +
firstName +
"님, 현재 메일 서버가 응답하지 않습니다. 나중에 다시 시도해주세요. "
)
);
$("#success > .alert-danger").append("</div>");
//clear all fields
$("#contactForm").trigger("reset");
},
complete: function () {
setTimeout(function () {
$this.prop("disabled", false); // Re-enable submit button when AJAX call is complete
}, 1000);
},
});
},
filter: function () {
return $(this).is(":visible");
},
});
$('a[data-toggle="tab"]').click(function (e) {
e.preventDefault();
$(this).tab("show");
});
});
/*When clicking on Full hide fail/success boxes */
$("#name").focus(function () {
$("#success").html("");
});
contact_me.php 파일을 열어 준 후, 수정한다.
<?php
// Check for empty fields
if(empty($_POST['name']) || empty($_POST['email']) || empty($_POST['phone']) || empty($_POST['message']) || !filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
http_response_code(500);
exit();
}
$name = strip_tags(htmlspecialchars($_POST['name']));
$email = strip_tags(htmlspecialchars($_POST['email']));
$phone = strip_tags(htmlspecialchars($_POST['phone']));
$message = strip_tags(htmlspecialchars($_POST['message']));
// Create the email and send the message
$to = "helloqu@naver.com"; // Add your email address in between the "" replacing yourname@yourdomain.com - This is where the form will send a message to.
$subject = "메일이 도착하였습니다.: $name";
$body = "당신의 개인 홈페이지에서 메일이 도착하였습니다.\n\n"."이곳의 자세한 내용을 확인 하세요.:\n\nName: $name\n\nEmail: $email\n\nPhone: $phone\n\nMessage:\n$message";
$header = "From: http://helloqu.dothome.co.kr/\n"; // This is the email address the generated message will be from. We recommend using something like noreply@yourdomain.com.
$header .= "Reply-To: $email";
if(!mail($to, $subject, $body, $header))
http_response_code(500);
?>
package sp.aop;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice; // 이후라고하면 MethodAfterAdvice 구현받으면 된다.
//추가
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
//Advice : 모든 Class에 공통으로 사용할 기능( 소스코드 -> method 중심 )
//interface 대신(OOP 방식) 에 Advice Class 를 작성해서 구현(AOP 방식) -> Aspect
//실행 위치를 특정 Method 의 앞에서 실행 -> MethodBeforeAdvice 를 구현
public class BeforeLogAdvice implements MethodBeforeAdvice { //공통관심 모듈 클래스를 만든다.
private Log log = LogFactory.getLog(getClass()); //Log 객체를 얻어오는 문장
//1) Spring의 AOP(method 중심) -> 핵심 CLass의 Method
//2) 생성된 객체를 배열로 받아온다.
//3) target Class(핵심 Class의 객체를 얻어온다.)
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
//TODO auto-generated method stub
log.info(method.toString()+" Method : "+target+"에서 호출 전!");
}//before() END
}//BeforeLogAdvice CLASS END
package sp.aop;
//모든 핵심 class 에서 공통으로 사용할 목적으로의 Method 작성, 인터페이스는 메소드 옆에 {} 지정하면 안된다.
public interface TestService {
// 해당 메소드들은 public abstract void 와 같이 추상메소드로 작성된다.
public void save(String msg);// 입력
public void write(); //출력
}//TestService INTERFACE END
app.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<!-- 1. 핵심 Class 빈즈 등록 -->
<bean id="testServiceImpl" class="sp.aop.TestServiceImpl" />
<!-- 2. Advice Class 빈즈 등록 -->
<bean id="beforeLog" class="sp.aop.BeforeLogAdvice" />
<!-- 3.PointCut 생성 -> 어느 위치에서 AOP Method 를 지정해서 실행
value="접근 지정 반환명 package 명... Class 명 하위 package 명(..) 특정 Method명 0개 이상"
(*) 매개변수 한 개 표시, (*,*) 매개변수 2개 표시 -->
<bean id="writePointcut"
class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*write.*" />
</bean>
<!-- 4. Advice + PointCut(Advisor) 설정 -->
<bean id="testAdvisor"
class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="beforeLog" />
<property name="pointcut" ref="writePointcut" />
</bean>
</beans>
package sp.aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; // xml문서를 찾을 수 있게 하는 lib
public class ResultMain {
public static void main(String[] args) {
String path="sp/aop/app.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(path);
//TestService service= (TestService)context.getBean("testServiceImpl");
//원래는 위의 것이 일반적이지만, AOP 객체를 얻어오기 위해서는, 밑에처럼 AOP객체를 얻는다.
//AOP객체를 생성 -> Advisor 작동 -> Advice + pointcut 실행
TestService service = (TestService)context.getBean("testService");
service.save("AOP 적용 연습");
//before advice(before() 작동 실행) -> 실행상태에서 처리
service.write();
}//main()END
}//CLASS END
package com.ohj.controller;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; // 스프링은 모델이다.(모델 앤 뷰 객체)
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.ohj.domain.BoardVO;
import com.ohj.service.BoardService;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;
@Controller
@Log4j
@RequestMapping("/board/*")
@AllArgsConstructor
public class BoardController {
private BoardService service;
@GetMapping("/list")
public void list(Model model) {
log.info("list");
model.addAttribute("list", service.getList()); // 반환타입 List<BoardVO> --> list.jsp
}// list() END
// 이 리스트 메소드가 호출되려면 /board/list 로 되어야 한다.
// ModelAndView 에 값 실어주려면 setAttribute 인데 여기선 addAttribute 라는 메소드로 리스트란 명칭을 실어주는 것이다.
@GetMapping("/register")
public void register() {
}//register() END
@PostMapping("/register")
public String register(BoardVO board, RedirectAttributes rttr) {
log.info("register:" + board);
service.register(board);
rttr.addFlashAttribute("result", board.getBno()); // 딱 1회만 전송할 수 있도록 만들어주는 메서드(addFlashAttribute)
return "redirect:/board/list";
}//register() END
@GetMapping({"/get","/modify"}) //매개변수에서 url패턴명이 바로 model객체 내부로 들어가서 return 되는 것(모델 객체가 리턴)
public void get(@RequestParam("bno") Long bno, Model model) { // @RequestParam("bno") 이 부분은 board/get?bno=n 과 같이 데이터 전달을 알려준다.(자동주입)
//request.getParameter("bno")를 대신해주는 것이 @RequestParam("bno")
log.info("/get or modify");
model.addAttribute("board",service.get(bno)); //BoardVO 반환타입
}//get() END
@PostMapping("/modify")
public String modify(BoardVO board, RedirectAttributes rttr) {
log.info("modify : " + board);
if (service.modify(board)) {
rttr.addFlashAttribute("result", "success");
}
return "redirect:/board/list";
}// modify() END
//★삭제는 반드시 POST 방식으로 처리
@PostMapping("/remove")
public String remove(@RequestParam("bno") Long bno, RedirectAttributes rttr) {
log.info("remove...." + bno);
if(service.remove(bno)) {
rttr.addFlashAttribute("result","success");
}
return "redirect:/board/list";
}//remove() END
}//BoardController CLASS END