.


'깃 사용방법' 카테고리의 다른 글

branch -m master main 깃 브랜치 이름 변경  (3) 2022.08.19

회원가입은 어떤식으로 작동할것 같은가?

1. VIEW에 회원가입을위한 정보를 작성한다.

2. 버튼을 눌러 서버로 DB에 저장해달라고 '요청' 한다.

3. 작성한 정보는 Model 객체로 만들어지고 , DAO를 통해 DB에 저장이 된다.

 

 

로그인은 어떤식으로 작동할것 같은가?

1. VIEW에 로그인을 위한 정보를 작성한다 (아이디, 패스워드)

2. DAO를 통해 작성한 정보를 바탕으로 SELECT를 한다.

3. 실행결과가 있다면 분기하여 세션을 저장하여 다른페이지로 이동할때 그 세션을 계속 불러오도록 한다(?)

 

제가 이해하기 편하도록, 제가 이해한대로 써봤습니다..

반드시 이렇다. 라고 생각하지는 말아주세요 불확실한 정보입니다

 

 

ㅎㅇ

 

정리해야될거 선(先)정리

1. 로그인페이지 , 회원가입 페이지로 이동하게 해주는 페이지

2. 로그인 Form , 회원가입 Form (아이디 중복검사, 주소검색)

3. 로그인과 회원가입만을 위한 객체 LoginReqDto , JoinReqDto 생성, 이해하기

 

나중에 게시판이되어 게시글을 보여줄

list.jsp 를 생성합니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@ include file="../layout/header.jsp" %>

</body>
</html>

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>인덱스 페이지입니다.</h1>
</body>
</html> 

<%
	response.sendRedirect("board/list.jsp");    
%> 

header.jsp (부트스트랩, 제이쿼리 선언)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Cos 블로그</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</head>
<body>

<nav class="navbar navbar-expand-md bg-dark navbar-dark">
  <a class="navbar-brand" href="#">블로그</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="collapsibleNavbar">
    <ul class="navbar-nav">
      <li class="nav-item">
        <a class="nav-link" href="#">회원가입</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">로그인</a>
      </li>    
    </ul>
  </div>  
</nav>
<br> 

 

 

 

대충 이런모양이 나옵니다

list.jsp

 

로그인을 누르면 나올 화면인 

loginFrom.jsp

를 생성합니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@include file="../layout/header.jsp" %>

<!-- x-www-form-urlencoded -->
<div class="container">
	<form action="/blog/user?cmd=login" method="post">
		<div class="form-group">
			<input type="text" id="username" name="username" class="form-control"
				placeholder="Enter Username" required"/>
		</div>

		<div class="form-group">
			<input type="password" name="password" class="form-control"
				placeholder="Enter Password" required />
		</div>
		<button type="submit" class="btn btn-primary">로그인완료</button>
	</form>
</div>
</body>
</html>

LoginForm.jsp

 

 

 

회원가입 화면인

JoinForm.jsp 

를 생성합니다

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<%@include file="../layout/header.jsp"%>

<div class="container">
	<form action="/blog/user?cmd=join" method="post" onsubmit="return valid();">
		<div class="d-flex justify-content-end">
			<button type="button" class="btn btn-info" onClick="usernameCheck();">중복검사</button>
		</div>
		<div class="form-group">
			<input type="text" id="username" name="username" class="form-control"
				placeholder="Enter Username" required"/>
		</div>

		<div class="form-group">
			<input type="password" name="password" class="form-control"
				placeholder="Enter Password" required />
		</div>

		<div class="form-group">
			<input type="email" name="email" class="form-control"
				placeholder="Enter Email" required />
		</div>

		<div class="d-flex justify-content-end">
			<button type="button" class="btn btn-info" onClick="goPopup();">주소검색</button>
		</div>
		<div class="form-group">
			<input type="text"  name="address"  id="address" class="form-control" placeholder="Enter Address"  required/>
		</div>
		<button type="submit" class="btn btn-primary">회원가입완료</button>
	</form>
</div>


<script>
	var isChecking = false;

	function valid(){
		if(isChecking == false){
			alert("아이디 중복체크를 해주세요");
		}
		return isChecking;
	}
	function usernameCheck(){
		// DB에서 확인해서 username이 없다면 isChecking = true
		var username = $("#username").val();
		$.ajax({
			type: "POST",
			url: "/blog/user?cmd=usernameCheck",
			data: username,
			contentType: "text/plain; charset=utf-8",
			dataType: "text"  // 응답 받을 데이터의 타입을 적으면 자바스크립트 오브젝트로 파싱해줌.
		}).done(function(data){
			if(data === 'ok'){ // 유저네임 있다는 것
				isChecking = false;
				alert('유저네임이 중복되었습니다.')
			}else{
				isChecking = true;
				$("#username").attr("readonly", "readonly");
				alert("해당 유저네임을 사용할 수 있습니다.")
			}
		});
	}

	function goPopup() {
		// 주소검색을 수행할 팝업 페이지를 호출합니다.
		// 호출된 페이지(jusopopup.jsp)에서 실제 주소검색URL(https://www.juso.go.kr/addrlink/addrLinkUrl.do)를 호출하게 됩니다.
		
		var pop = window.open("/blog/user/jusoPopup.jsp", "pop",
				"width=570,height=420, scrollbars=yes, resizable=yes");
	}
	function jusoCallBack(roadFullAddr) {
		var addressEl = document.querySelector("#address");
		addressEl.value = roadFullAddr;
	}
</script>
</body>
</html>

 

ㅡㅡㅡㅡAjax 통신 정의ㅡㅡㅡㅡㅡ

Ajax (Async Javascript And XML)는 웹 페이지에서 새로운 데이터를 보여주려고 할 때 웹페이지 전체를 새로고침 하지 않고, 보여주고자 하는 데이터가 포함된 페이지의 일부 만을 로드 하기 위한 기법입니다.

Ajax는 비동기 처리 모델 (또는 non-blocking 이라고도 함)을 사용하여 데이터를 처리합니다.

 

동기 처리 모델에서 브라우저는 자바스크립트 코드를 만나면 스크립트를 처리하기 전까지 다른 작업을 일시 중지하고, 자바스크립트 코드의 처리가 끝난 후 기존 작업을 진행합니다.

반면에 Ajax를 사용하면 브라우저는 서버에 데이터를 요청한 뒤 페이지의 나머지를 로드하고 페이지와 사용자의 상호작용을 처리합니다.

 

Ajax 동작방식

function usernameCheck(){
		// DB에서 확인해서 username이 없다면 isChecking = true
		var username = $("#username").val();
		$.ajax({
			type: "POST",
			url: "/blog/user?cmd=usernameCheck",
			data: username,
			contentType: "text/plain; charset=utf-8",
			dataType: "text"  // 응답 받을 데이터의 타입을 적으면 자바스크립트 오브젝트로 파싱해줌.
		}).done(function(data){
			if(data === 'ok'){ // 유저네임 있다는 것
				isChecking = false;
				alert('유저네임이 중복되었습니다.')
			}else{
				isChecking = true;
				$("#username").attr("readonly", "readonly");
				alert("해당 유저네임을 사용할 수 있습니다.")
			}
		});
	}
//UserController.java  (Servlet)

else if(cmd.equals("usernameCheck")) { //유저네임 중복체크
			BufferedReader br = request.getReader(); //input 에 입력된 username을 읽음
			String username = br.readLine();
			System.out.println(username);
			//DB와 통신함 (service -> Dao)
			//Dao 에서 Select 해보고 int 결과값을 리턴해줌. 있으면 1 없으면 not 1
			int result = userService.유저네임중복체크(username); 
			
			PrintWriter out = response.getWriter();
			if(result == 1) {
				out.print("ok");
			}else {
				out.print("fail");
			}
			out.flush();
		}

 

  1. 요청(request) - 브라우저가 서버에 정보를 요청한다.
    바로 위에있는 JoinForm.jsp 에서 첫번째 Form의 중복검사 action이 usernameCheck() 함수를 가지고있는데,
    그 함수는 파일 하단에. 자바스크립트 함수로 정의되어 있습니다.

    이 함수가 JQuery를 이용한 Ajax 요청방법입니다. ( Web Front 에 입력된 데이터를 서버로 전송 )
    type : 요청방식 (get, post, delete, put)   //  url : 요청주소 ( Controller 에서 Servlet이 처리함 )

    data : 서버로 보낼 데이터. (위 함수에서는 var username = $("#username").val() 이 전송되는중)

    contentType : 응답받을 데이터의 형태, 보통은 데이터를 처리하기위해 JSON 이겠지만 
    Controller의 결과값을 보면 ok , fail 의 단순 문자열이기때문에 text

    응답에 성공을 한다면, done(function(data){  '대충 실행될 명령'   } ) 분기로 가서
    응답받은 데이터( data << Ajax 함수의 data 아님. Ajax의 결과값임 )로 해야할 일을 처리합니다.
    data를 result 로 바꾸는게 좀 보기 편할거같네요

  2. 서버의 동작 - 서버는 JSON, XML 등의 형식으로 데이터를 전달한다.
    최근에는 JSON을 가장 많이 사용하고 있습니다.

  3. 응답(response) - 브라우저에서 이벤트가 발생하여 콘텐츠를 처리한다.

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

 

 

JoinForm.jsp

 

 

명심할것!!!!!!! 컨트롤러 ↔ 서비스 ↔ DAO (DB)

User의 컨트롤을 담당 (로그인, 회원가입, 로그아웃)

UserController.java  (Servlet 파일)

package com.cos.blog.web;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.cos.blog.domain.user.User;
import com.cos.blog.domain.user.dto.JoinReqDto;
import com.cos.blog.domain.user.dto.LoginReqDto;
import com.cos.blog.service.UserService;
import com.cos.blog.util.Script;

//http://localhost:8000/blog/user
@WebServlet("/user")
public class UserController extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
    public UserController() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doProcess(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doProcess(request, response);
	}
	protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		UserService userService = new UserService();
		String cmd = request.getParameter("cmd");

		// http://localhost:8000/blog/user?cmd=loginForm
		if(cmd.equals("loginForm")) { //로그인 페이지
			// 서비스 호출
			RequestDispatcher dis = request.getRequestDispatcher("user/loginForm.jsp");
			dis.forward(request, response);
			//response.sendRedirect("user/loginForm.jsp");
		}else if(cmd.equals("login")) { //로그인 완료
			// 서비스 호출
			String username = request.getParameter("username");
			String password = request.getParameter("password");
			LoginReqDto dto = new LoginReqDto();
			dto.setUsername(username);
			dto.setPassword(password);
			
			User userEntity = userService.로그인(dto);
			if(userEntity != null) {
				HttpSession session = request.getSession();
				session.setAttribute("principal", userEntity); //인증주체
				//response.sendRedirect("index.jsp"); //로그인 성공
				RequestDispatcher dis = request.getRequestDispatcher("index.jsp");
				dis.forward(request, response);
			}else {
				Script.back(response, "로그인 실패");
			}
			
			
		}else if(cmd.equals("joinForm")) { //회원가입 페이지
			RequestDispatcher dis = request.getRequestDispatcher("user/joinForm.jsp");
			dis.forward(request, response);
			//response.sendRedirect("user/joinForm.jsp");
			
		}else if(cmd.equals("join")) { //회원가입 완료
			// 서비스 호출
			String username = request.getParameter("username");
			String password = request.getParameter("password");
			String email = request.getParameter("email");
			String address = request.getParameter("address");
			JoinReqDto dto = new JoinReqDto();
			dto.setUsername(username);
			dto.setPassword(password);
			dto.setEmail(email);
			dto.setAddress(address);
			System.out.println("회원가입 : "+dto);
			int result = userService.회원가입(dto); //DB와 통신함 (service -> Dao)
			if(result == 1) {
				RequestDispatcher dis = request.getRequestDispatcher("index.jsp");
				dis.forward(request, response);
			}else {
				Script.back(response, "회원가입 실패 -1");
			}
		}else if(cmd.equals("usernameCheck")) { //유저네임 중복체크
			BufferedReader br = request.getReader();
			String username = br.readLine();
			System.out.println(username);
			int result = userService.유저네임중복체크(username); //DB와 통신함 (service -> Dao)
			
			PrintWriter out = response.getWriter();
			if(result == 1) {
				out.print("ok");
			}else {
				out.print("fail");
			}
			out.flush();
		}else if(cmd.equals("logout")) { //로그아웃
			HttpSession session = request.getSession();
			session.invalidate(); //즉시 세션 만료
			RequestDispatcher dis = request.getRequestDispatcher("index.jsp");
			dis.forward(request, response);
		}
	}
}

UserService.java 작성

package com.cos.blog.service;

import com.cos.blog.domain.user.User;
import com.cos.blog.domain.user.UserDao;
import com.cos.blog.domain.user.dto.JoinReqDto;
import com.cos.blog.domain.user.dto.LoginReqDto;
import com.cos.blog.domain.user.dto.UpdateReqDto;

public class UserService {
	private UserDao userDao;
	
	public UserService() {
		userDao = new UserDao();
	}
	
	
	public int 회원가입(JoinReqDto dto) {
		
		int result = userDao.save(dto);
		return result;
	}

	public User 로그인(LoginReqDto dto) {
		return userDao.findByUsernameAndPassword(dto);
	}

	public int 회원수정(UpdateReqDto dto) {

		return -1;
	}

	public int 유저네임중복체크(String username) {
		int result = userDao.findByUsername(username);
		return result;
	}
}

 

DB.java 에 아래의 함수 생성

public static void close(Connection conn, PreparedStatement pstmt) {
		try {
			conn.close();
			pstmt.close();
		} catch (Exception e) {
			e.printStackTrace();
		}		
	}

 

UserDao.java 작성 (대부분 SQL문)

 

public int save(JoinReqDto dto) { // 회원가입
		String sql = "INSERT INTO user(username, password, email, address, userRole, createDate) VALUES(?,?,?,?, 'USER', now())";
		Connection conn = DB.getConnection();
		PreparedStatement pstmt = null;
		try {
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, dto.getUsername());
			pstmt.setString(2, dto.getPassword());
			pstmt.setString(3, dto.getEmail());
			pstmt.setString(4, dto.getAddress());
			int result = pstmt.executeUpdate();
			return result;
		} catch (Exception e) {
			e.printStackTrace();
		} finally { // 무조건 실행
			DB.close(conn, pstmt);
		}
		return -1;
	}
    
    public int findByUsername(String username) { //아이디 중복 체크
		String sql = "SELECT * FROM user WHERE username = ?";
		Connection conn = DB.getConnection();
		PreparedStatement pstmt = null;
		ResultSet rs  = null;
		try {
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, username); //dto가 아닌 그냥 username
			rs =  pstmt.executeQuery(); //조회 결과가 1건이라도 있으면 1 , 없으면 -1

			if(rs.next()) { //1건이라도 있다 = true 일때 실행
				return 1; // 있어
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally { // 무조건 실행
			DB.close(conn, pstmt, rs);
		}
		return -1; // 없어
	}
    
    public User findByUsernameAndPassword(LoginReqDto dto) { // 로그인
		String sql = "SELECT id, username, email, address FROM user WHERE username = ? and password =?";
		Connection conn = DB.getConnection();
		PreparedStatement pstmt = null;
		ResultSet rs  = null;
		try {
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, dto.getUsername()); //dto가 아닌 그냥 username
			pstmt.setString(2, dto.getPassword());
			rs =  pstmt.executeQuery(); 

			// Persistence API
			if(rs.next()) { //1건이라도 있다 = true 일때 실행
				User user = User.builder()
						.id(rs.getInt("id"))
						.username(rs.getString("username"))
						.email(rs.getString("email"))
						.address(rs.getString("address"))
						.build();
				
				return user;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally { // 무조건 실행
			DB.close(conn, pstmt, rs);
		}
		return null; // 없어
	}

 

한글 데이터 요청 , 응답시 한글 깨짐을 방지하기위한 

CharConfig.java 생성 (doFilter)

package com.cos.blog.config;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CharConfig implements Filter{

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
    	HttpServletResponse response = (HttpServletResponse) resp;

     	request.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");

//		String username = request.getParameter("username");
//		System.out.println("username : "+username);
//		
//		PrintWriter out = response.getWriter();
//		out.println("안녕");
//		out.flush();
		chain.doFilter(request, response);
	}
}

 

 

뒤로가기를 함수로 따로 구현하기 위한 

Script.java 작성

package com.cos.blog.util;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletResponse;

public class Script {
	public static void back(HttpServletResponse resp, String msg) throws IOException {
		PrintWriter out = resp.getWriter();
		resp.setContentType("text/html; charset=utf-8"); //utf-8로 응답하겠다
		out.println("<script>");
		out.println("alert('"+msg+"');");
		out.println("history.back();");
		out.println("</script>");
		out.flush();
	}

 

패키지정리는 알아보기쉽게.. (언젠간 한눈에 보일거같습니다)

 

Dto란?   Data Transfer Object 

데이터 교환만을 위한 객체로, DB에서 데이터를 얻어 Service나 Controller 등으터 보낼 때 사용하는 객체를 말한다.

User , Board 처럼 이미 모델이 만들어져있지만 각각 상황에 따라 일부 필드(변수)는 요구되지않는 요청이 생길 수 있다.

 

예를 들자면 로그인을 위한 데이터를 받고싶다고 하자. (아이디, 패스워드 만 있으면 됨)

그러나 User 모델은 로그인만을 하기위해 사용하기에는 쓸데없는 변수가 너무많다.

 

 

그럴때, 오로지 로그인만을 위한 DTO(Data Transfer Object : 데이터 전송 객체)를 만들어서 사용하는것이다.

 

미완성 게시물입니다. 이후 내용 추가

 

 

추가할 내용

유저네임 중복검사 , 로그인 구현

Ajax 통신 이해하기, (Reader, Writer)  이해하기,

(get,setAttribute) 이해하기,

RequestDispatcher 이해하기

 

집에서 새로 프로젝트 만들어서 내가 작성한내용 따라해서 리뷰하기.

개발환경 : STS4

서버 : Tomcat9.0

DB : MySQL

필요 준비물 : lombok.jar , mysql-connector-java-8.0.16.jar

 

 

앞으로의 시스템 흐름을 이해하기위해 가장 먼저 숙지 해야할 그림입니다. 

이번 시간에는 그림 아래부분에있는 DB를 생성하고 , 그것을 담을 Model객체를 만들어보겠습니다.

 

 

1. Dynamic Web Project - blog 생성 , Runtime Target = Tomcat9.0 으로 설정

더보기

저는 만드는 척만 하겠습니다.

1.a 21년 5월 23일 추가

옛날에는 새 프로젝트를 만들면 Dynamic Web Project 를 선택할 수 있었는데, STS의 버전이 업그레이드 되면서 해당 프로젝트의 생성을 권장하지 않아서 그런지 기본 선택목록에서 아예 제외된것 같습니다.

 

Web Project Plugin 설치방법

https://goodteacher.tistory.com/329

 

STS에서 Dynamic Web Project 개발

STS에서 Dynamic Web Project 개발 STS는 왜 이렇게 원래의 legacy 방밥을 통한 개발을 싫어할까? Boot를 밀고 싶은 맘이야 충분히 공감하지만 legacy도 좀 끼워주면 안되나 싶다. 사라져버린 Dynamic Web Program..

goodteacher.tistory.com

Help - install new software - ... 

 

 

2. MySQL Workbench 실행, 테이블생성 을 하기전에~~~~

유저 생성

더보기
create user 'bloguser'@'%' identified by '비밀번호';
GRANT ALL PRIVILEGES ON *.* TO 'bloguser'@'%';
create database blog;
use blog;

 

새로 만든 bloguser로 접속합시다

 

 

3. 테이블 생성

더보기
drop table user;
drop table board;
drop table reply;

CREATE TABLE user(
	id int primary key auto_increment,
    username varchar(100) not null unique,
    password varchar(100) not null,
    email varchar(100) not null,
    address varchar(100),
    userRole varchar(20),
    createDate timestamp
) ;

CREATE TABLE board(
	id int primary key auto_increment,
    userId int,
    title varchar(100) not null,
    content longtext,
    readCount int default 0,
    createDate timestamp,
    foreign key (userId) references user (id)
);

CREATE TABLE reply(
	id int primary key auto_increment,
    userId int,
    boardId int,
    content varchar(300) not null,
    createDate timestamp,
    foreign key (userId) references user (id) on delete set null,
    foreign key (boardId) references board (id) on delete cascade
);

 

 

 

4. Model 생성

더보기

com.cos.blog.domain 패키지 안에 board , reply , user 패키지생성.

각각의 패키지에 각각의 class 생성.

 

package com.cos.blog.domain.board;

import java.sql.Timestamp;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Board {
	private int id;
	private int userId;
	private String title;
	private String content;
	private int readCount;
	private Timestamp createDate;
}
package com.cos.blog.domain.reply;

import java.sql.Timestamp;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Reply {
	private int id;
	private int userId;
	private int boardId;
	private String content;
	private Timestamp createDate;
}
package com.cos.blog.domain.user;

import java.sql.Timestamp;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
	private int id;
	private String username;
	private String password;
	private String email;
	private String address;
	private String userRole; // admin, user
	private Timestamp createDate;
}

 

lombok.jar 설치 하셔야합니다

 

 

 5. Dao(DataAccessObject) 생성

더보기

Dao란 무엇인가??

DB에 접근하여 조회, 삽입, 수정, 삭제의 기능만을 담당하는 객체입니다.

그림에서 Model과 DB 사이에 위치하고있습니다.

 

기능은 나중에 구현하고 빈 클래스만 만들어주세요

 

 

 6. DB연결 

tomcat.apache.org/tomcat-9.0-doc/index.html

 

Apache Tomcat 9 (9.0.41) - Documentation Index

This is the top-level entry point of the documentation bundle for the Apache Tomcat Servlet/JSP container. Apache Tomcat version 9.0 implements the Servlet 4.0 and JavaServer Pages 2.3 specifications from the Java Community Process, and includes many addit

tomcat.apache.org

Tomcat Document에 가보시면 DB연결을 하기위한 세팅방법이 나와있습니다.

설명해드리겠습니다.

 

 

더보기

META-INF 와 WEB-INF 에 context.xml , web.xml 을 만들어주세요.

xml 파일의 파일명은 반드시 소문자로하셔야합니다. 대문자를 인식하지못합니다.

 

두 개의  파일은 원래 Tomcat의 설정 파일인데 add 해서 사용한다는 느낌? 같습니다

 

 

 

1. context.xml

Document 에서 가져왔습니다

 주석은 필요없고 driverClassName이랑 url에 서버시간만 붙여주시면 됩니다

 

 

수정안하고 해도 가능하긴할텐데 cj.jdbc가 더 최신버전인거같습니다 .

<context>
	<Resource name="jdbc/TestDB" auth="Container"
		type="javax.sql.DataSource" maxTotal="100" maxIdle="30"
		maxWaitMillis="10000" username="bloguser" password="비밀번호"
		driverClassName="com.mysql.cj.jdbc.Driver"
		url="jdbc:mysql://localhost:3306/blog?serverTimezone=Asia/Seoul" />
</context> ​

 

 

 

2. web.xml

저도 방금 봤는데 버전 차이가 조금 있네요

밑에걸로 복붙 해주세요

 

 

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="4.0"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
	http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd">

	<description>MySQL Test App</description>
	<resource-ref>
		<description>DB Connection</description>
		<res-ref-name>jdbc/TestDB</res-ref-name>
		<res-type>javax.sql.DataSource</res-type>
		<res-auth>Container</res-auth>
	</resource-ref>

</web-app>

 

 3. DB.java   +   DBTest.java 생성

 

 

3-1 DB.java

 

package com.cos.blog.config;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;



public class DB {
	public static Connection getConnection() {
		try {
			Context initContext = new InitialContext();
			Context envContext  = (Context)initContext.lookup("java:/comp/env");
			DataSource ds = (DataSource)envContext.lookup("jdbc/TestDB");
			Connection conn = ds.getConnection();
			return conn;
		} catch (Exception e) {
			System.out.println("DB연결실패");
			e.printStackTrace();
		}
		return null;
	}

 

 

jdbc/oracle 과 jdbc/TestDB 가 다릅니다

DB연결하는 기능을 함수화 했습니다.

 

 

3-2 DBTest.java

프로젝트에서 우클릭 - Build Path

 

 

 

Add Library - JUnit4 선택

 

 

 

package com.cos.blog.test;

import static org.junit.Assert.assertNotNull;

import java.sql.Connection;

import org.junit.Test;

import com.cos.blog.config.DB;


public class DBTest {
	
		@Test
	public void DBConnectionTest() {
		Connection conn2 = DB.getConnection();
		assertNotNull(conn2);
	}
}

방금 DB에서 만든 getConnection() 함수를 사용합니다

 

 

 

 @Test 어노테이션을 이용하여 테스트를 할 수 있습니다. 

근데 JUnit 은 제가 아직 사용을 잘 안해봐서 모르겠습니다 

 

 

 

 

테스트 결과

옛날에 만든거라 사용법을 아직 잘 몰라서 어떻게 성공시키는지 모르겠네요

DB연결은 잘 되긴합니다

 

 

 

ㅎㅇ!!

 

 

juso.go.kr 에 접속해서 우측  상단 '개발자 센터'로 이동합니다~

 

 

 

 

그리고 API신청하기 클릭

 

 

 

업체 아무거나 쓰셔도 됩니다

URL 저는 localhost:8080 썼습니다

어짜피 인증키는 즉시나오는거라 상관없는거같기도

 

 

그다음 본인인증 해주시고 인증키를 발급받습니다. (빨간색 글자로 되있음)

인증키만 복사하고 어디 메모장에 적어두세요. 다시 보려면 또 본인인증 해야합니다

guidePopupApiJSP.zip
1.72MB

juso.go.kr 홈페이지에서 제공하는 API 사용 가이드 샘플 jsp파일 입니다. 다운받아주세요.

 

새로운 Dynamic Web Project를 만드시고 다운받은 파일 안에있는 Sample.jsp , jusoPopup.jsp를 붙여넣기 해주세요

 

1. Sample.jsp 에서 jusoPopup을 불러오는 경로부분을 자신의 프로젝트 경로에 맞게 바꿔주셔야합니다

 

2. jusoPopup.jsp 에 발급받았던 인증키를 넣어줍니다.

 

 

 

 

Sample.jsp를 Run on Server 하여 체험해봅니다!!!!!!!! 

 

 

이것을 개인프로젝트에 적용하는 방법을 설명 해드리겠습니다

 

제 임시 프로젝트입니다. jusoPopup.jsp는 그대로 가져와서 사용해야합니다.

 

주소검색 버튼을 누르면, jusoPopup.jsp 이(가) 나오게 해야합니다.

 

주소검색 버튼의 속성값에 onClick="goPopup()" 을 추가해줍니다. 

 

주소입력란(?)(input)의 속성값에 임의의 id="address" 를 추가해줍니다.

어렵지 않습니다

 

 

 

Sample.jsp 의 script 내부에있는 함수 goPopup() , jusoCallBack을 복사해옵니다.

저는 jusoCallBack함수에서 하나의 필드만 사용했기 때문에 하나만 인자로 가져왔습니다

 

체험판에서 했던거랑 똑같이 jusoPopup.jsp 를 찾아주는 경로를 설정해주시면?

 

 

주소검색 버튼클릭 -> 주소 검색( jusoPopup.jsp ) -> input창에 주소검색결과 삽입됨

 

이렇게 실행 될것입니다~~

 

 

 

 

 

 

 

- 웹 서버 (Web Server)

클라이언트가 서버에 페이지 요청을 하면 요청을 받아 정적 컨텐츠(.html, .png, .css등)를 제공하는 서버

클라이언트에서 요청이 올 때 가장 앞에서 요청에 대한 처리를 한다.

클라이언트의 요청을 기다리고 요청에 대한 데이터를 만들어서 응답하는 역할 (정적 데이터)

CASE

정적 컨텐츠를 요청(request)했나?

1. 정적 컨텐츠구나! 내가 제공해줄게 => .html, .png 등 응답(response)

2. 정적 컨텐츠가 아니구나.. 웹서버에서 간단히 처리 못하겠군. WAS에게 처리를 부탁해야겠다! => 결국 WAS가 처리해준 컨텐츠를 받은 웹서버는 응답(response)을 해줌

대표 : Apache, nginx







- WAS (Web Application Server)

동적 컨텐츠를 제공하기 위해 만들어진 애플리케이션 서버 (DB조회, 로직처리가 요구되는 컨텐츠)

JSP,Servlet 구동 환경 제공

컨테이너, 웹컨테이너, 서블릿 컨테이너라고도 부름

* JSP, servlet을 실행시킬 수 있는 소프트웨어 = 컨테이너

동작 프로세스

1. 웹서버로부터 요청이 오면 컨테이너가 받아서 처리

2. 컨테이너는 web.xml을 참조하여 해당 서블릿에 대한 쓰레드 생성하고 httpServletRequest와 httpServletResponse 객체를 생성하여 전달한다.

3. 컨테이너는 서블릿을 호출한다.

4. 호출된 서블릿의 작업을 담당하게 된 쓰레드(2번에서 만든 쓰레드)는 doPost()또는 doGet()을 호출한다.

5. 호출된 doPost(), doGet() 메소드는 생성된 동적 페이지를 Response객체에 담아 컨테이너에 전달한다.

6. 컨테이너는 전달받은 Response객체를 HTTPResponse형태로 바꿔 웹서버에 전달하고 생성되었던 쓰레드를 종료하고 httpServletRequest, httpServletResponse 객체를 소멸시킨다.

대표 : Tomcat, Jeus, JBoss



WAS와 웹 서버 차이

- 동적 컨텐츠 처리를 수행 가능한가 아닌가.

WAS는 정적,동적 처리 둘다 가능하지만 정적처리를 WAS가 하게되면 부하가 많이 걸려서 좋지 않음


* 톰캣(WAS)에는 아파치(웹서버)의 기능(웹서비스데몬, Httpd)를 포함하고 있다.

- 일반적인 WAS, Web Server 구조가 아닌 걸로 알고 있음.


* WAS, Web Server를 따로 두고 쓰는 이유가 성능때문이라고 하는 건 잘못되었다.

톰캣5.5 이상부터는 httpd의 native모듈을 사용해서 정적파일을 처리하는 기능을 제공하는데 이것이 순수 아파치 Httpd만 사용하는 것과 비교해서 성능이 전혀 떨어지지 않기 때문이다.

그럼에도 톰캣앞에 아파치를 두는 이유는 하나의 서버에서 php애플리케이션과 java애플리케이션을 함께 사용하거나, httpd 서버를 간단한 로드밸런싱을 위해서 사용해야 할 때 필요하기 때문.



출처: https://jeong-pro.tistory.com/84 [기본기를 쌓는 정아마추어 코딩블로그]

이전 버전의 hello 프로젝트에는

일단 흐름을 계속 보면서 익힙시다 (가능하다면)


기능소개



로그인 

1. 서비스에서 req.getParameter로 input값을 저장할 String 변수 두 개를 만듬. (username , password)

2. UserDao의 login(Users uesrs) 함수의 매개변수를 만들어주기위해 Users 객체의 틀을 만든다.

3. UserDao 에서 DB연결 후 Users 객체 userEntity 에 DB에서 get해온값으로 build 한다. userEntity를 반환한다.

4. 다시 서비스로 돌아와, if(UserEntity != null) 이라면 



UsersService.java 일부

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public Users 로그인(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println("=========loginPorc Start=========");
        System.out.println(username);
        System.out.println(password);
        System.out.println("=========loginPorc End=========");
        // 2번 DB값이 있는지 select 해서 확인
        // login함수 의 매개변수를 만들어주기위한 빌드업 (Users 틀 만들기)
        Users user = Users.builder()
                .username(username)
                .password(password)
                .build();
 
        // login 함수 실행 (sql로 데이터베이스에 select)
        UsersDao usersDao = new UsersDao();
        //login 의 반환형이 Users
        Users userEntity = usersDao.login(user);       // UserDao
        
        if(userEntity != null) {
            // session에는 사용자 패스워드 절대넣지않기
            // 3번 세션 키 발급
 
            // session 두 줄 이 무슨 역할 하는건가요??
            HttpSession session = req.getSession();
            //setAttribute : name으로 지정한 이름에 value값을 할당합니다.
            session.setAttribute("sessionUser", userEntity); // name , Object(value)
            
            Script.href(resp, "index.jsp""로그인 성공123");
            //한글처리를 위해 resp객체를 건드린다.
            // mime타입
            // http header 에 context-type
            
//            resp.sendRedirect("index.jsp"); 데이터를 들고 이동하는게 아니고 그냥 페이지이동만하는 기능.(필요없음)
            return user;
        }else {
            Script.back(resp, "로그인실패 -1");
            resp.sendRedirect("auth/login.jsp");
        }
        return null;
    }
cs





UserDao.java 일부

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public Users login(Users users) throws SQLException {
        StringBuffer sb = new StringBuffer();
        sb.append("SELECT id, username, password, email FROM users WHERE username = ? AND password = ?");
        String sql = sb.toString();
        Connection conn = DBConnMySQL.getInstance();
        try {
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, users.getUsername());
            pstmt.setString(2, users.getPassword());
//            int result2 = pstmt.executeQuery(sql); // 변경된 row count를 리턴, 오류 시 -1를 리턴
//            System.out.println("result2 : " + result2);
            ResultSet rs = pstmt.executeQuery();
            if(rs.next()) { //출력할 행이 여러개면 while
                Users userEntity = Users.builder()
                        .id(rs.getInt("id"))  //Resultset rs 에서 가져오는중 = DB에서 가져오는중
                        .username(rs.getString("username"))
                        .password(rs.getString("password"))
                        .build();
                System.out.println("로그인 성공");
                return userEntity;
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("로그인 실패");
        return null;
    }
cs





ㅎㅇ 이번 실습은 정말 이해를 잘 해야하는, 하고싶은 부분이다


MVC가 웹 에서 가장 활용이 많이된다던  그 분의 말씀, 이제야 이해가 되는것 같다



먼저 MVC의 흐름? 을 그림으로 한눈에 보자



용어 설명

Model무엇을 할지 정의합니다. 비지니스 로직에서의 알고리즘, 데이터 등의 기능을 처합니다.
Controller어떻게 할지를 정의합니다. 요청을 받아서 화면과 Model과 View를 연결시켜주는 역할을 하지요.
View무엇을 화면으로 보여주는 역할을 하지요. 웹이라면 웹페이지, 모바일이라면 어플의 화면의 보여지는 부분입니다.



용어 설명2

Model: 어플리케이션의 데이터, 자료를 의미합니다.
View: 사용자에게 보여지는 부분, 즉 유저 인터페이스(User interface)를 의미합니다.

Controller: Model과 View사이를 이어주는 브릿지(Bridge)역할을 의미합니다.



용어 설명3

모델(Model)

프로그램에 사용되는 데이터를 의미하며 데이터베이스(DB), 상수, 문자열과 같은 변수들, 비전 프로그램이라면 카메라 정보와 같은 것들이 해당됩니다. 모델에는 뷰나 컨트롤러의 정보가 전혀 없습니다. 단지, 정보만 반환하거나 설정할 수 있습니다.

뷰(View)

다이얼로그에 존재하는 텍스트박스, 라벨, 버튼 등 사용자 인터페이스(User interface) 요소들을 의미합니다. 사용자가 제어하고 데이터를 확인할 수 있는 영역입니다. 뷰에서는 별도의 데이터를 보관하지 않습니다. 뷰에서 입력받고 출력해주는 모든 데이터는 모델을 사용해야합니다.

컨트롤러(Controller)

모델과 뷰를 관장하는 브릿지(Bridge)역할을 수행합니다. 사용자가 버튼을 클릭하면 이벤트는 뷰에서 발생하지만 내부 처리는 컨트롤러에서 관리하는 것입니다. 또한, 입력이 발생하면 이에 대한 통지를 담당합니다.


용어 설명4

M (model, domain)

M은 Model을 가리킨다.
Model이란 프로그램이 작업하는 세계관의 요소들을 개념적으로 정의한 것이라고 볼 수 있다.
예를 들어 음식점 무인 포스기를 개발한다고 가정해보자. 무인포스기가 정상적으로 목표하는 작업을 수행하기 위해서는 우선 메뉴가 있어야하고, 메뉴를 담을 수 있는 장바구니, 해당 메뉴의 수량, 결제수단, 할인정책 등등이 필요할 것이다.

이처럼 프로그램이 목표하는 작업을 원활하게 수행하기 위해 필요한 물리적 개체, 규칙, 작업등의 요소들을 구분되는 역할로써 정의해놓은게 Model이 된다. Model은 DTO와 DAO로 분류할 수 있다.
두 개념에 대해서는 나중에 다른 세션에서 정리할 예정이므로 간단히 언급만하고 넘어가겠다.

결과적으로 Model을 잘 설계하는 것은, 해당 도메인 세계를 얼마만큼 이해하고 있는지와도 밀접한 연관이 있다. 꼭 물리적인 요소뿐만아니라 추상적인 요소 또한 해당 작업을 수행하는데 특정 책임과 역할로서 구분될 수 있다면 최대한 구체적이고 작은 entitiy를 유지하면서 Model을 설계하는 것이 중요하다.

V (view)

V는 View를 가리키고 사용자가 보는 화면에 입출력 과정 및 결과를 보여주기 위한 역할을 한다. 입출력의 순서나 데이터 양식은 컨트롤러에 종속되어 결정되고, 도메인 모델의 상태를 변환하거나, 받아서 렌더링하는 역할을 한다.

view를 구현할 때 주의할 점은 도메인 로직의 어떤 것도 알고 있으면 안된다는 것이다. 절대적으로 객체를 전달받아 상태를 바로 출력하는 역할만을 담당해야 한다. 그렇기 때문에 view에서는 도메인 객체의 상태를 따로 저장하고 관리하는 클래스 변수 혹은 인스턴스 변수가 있을 필요가 없다.

C (controller)

C는 Controller를 가리킨다. controller는 model과 view를 연결 시켜주는 다리 역할을 함과 동시에 도메인 객체들의 조합을 통해 프로그램의 작동 순서나 방식을 제어한다. controller는 view와 model이 각각 어떤 역할과 책임이 있는 지 알고 있어야 한다.

웹 프로그래밍에서는 Controller에서 service layer를 분리하여 domain 로직이 수행되는 곳과 view의 요청을 매핑하는 곳을 독립적으로 관리할 수 있다.


웹사이트 개발시 MVC 패턴을 적용하는 일반적인 목적

- 애플리케이션에 데이터 구조와 Model(비지니스 로직)은 전형적으로 자주 변경되지 않지만, 데이터의 View(프레젠테이션 로직)은 사실 자주 변경되기 때문에 Model(비즈니스 로직)과 View(프레젠테이션 로직)을 분리함으로써 이러한 요구의 변경에 따라 애플리케이션에 유지보수가 쉬워진다. 

예를 들어 웹사이트가 보여주는 데이터 구조에는 변함이 없지만, 국내외의 사용자에게 다양한 언어로 데이터를 보여주어야 할 경우 또는 PC/스마트폰/스마트TV 등과 같은 해상도가 다른 장치에서 동일한 데이터를 보여주어야 할 경우 Model(비즈니스 로직)은 유지하고, View(프레젠테이션 로직)만 수정하면 된다. 즉 MVC 패턴을 사용하면 웹사이트의 유지보수가 쉽다.

Model(비지니스 로직)을 담당하는 웹 개발자와 View(프레젠테이션 로직)을 담당하는 웹 디자이너 분리된 작업이 가능하다.





추가 설명

JSP 에서 JAVA로 데이터를 전송하려면 그냥 form action="" 을 이용하면 되지만


JAVA의 데이터를 JSP로 넣으려면 Dispatcher 에 데이터를 담아서 보내야한다.

보내주는 사람(?)은 Request 객체 이다.




실습한 코드 


UsersController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.cos.hello.controller;
 
import java.io.IOException;
import java.sql.SQLException;
 
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
//javax 로 시작하는 패키지는 톰캣이 갖고있는 라이브러리이다.
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
 
import com.cos.hello.model.Users;
import com.cos.hello.service.UsersService;
 
public class UserController extends HttpServlet {
    // 12월 21알 월요일
    // req , res는 톰캣이 만들어줌. (클라이언트의 요청이 있을 때 마다)
    // req는 Reader 할 수 있는 ByteStream 요청
    // res는 Writer 할 수 있는 ByteStream 응답
    // http://localhost:8000/hello/user?gubun=login
 
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        String gubun = req.getParameter("gubun");
//        route(gubun, req, resp);
        System.out.println("doGet실행됨");
        doProcess(req, resp);
    }
 
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost실행됨");
        doProcess(req, resp);
    }
 
    protected void doProcess(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//      super.doGet(req, resp);
        System.out.println("UserController 실행됨");
 
        String gubun = req.getParameter("gubun");
        System.out.println(gubun);
        try {
            route(gubun, req, resp);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ServletException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
 
    private void route(String gubun, HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException, SQLException {
        UsersService usersService = new UsersService();
        
        if (gubun.equals("login")) {
            resp.sendRedirect("auth/login.jsp"); //loginProc 버튼
        } else if (gubun.equals("join")) {
            resp.sendRedirect("auth/join.jsp"); // joinProc 버튼
        } else if (gubun.equals("selectOne")) {
            usersService.유저정보보기(req, resp);
        } else if (gubun.equals("updateOne")) {
            usersService.유저정보수정페이지(req, resp);
        } else if (gubun.equals("joinProc")) { 
            usersService.회원가입(req, resp);
        } else if (gubun.equals("loginProc")) {
            usersService.로그인(req, resp);
            //SELECT id, username, email From users where username = ? and password = ?
            //DAO 함수명 : login() , return -> Users Object
            //정상 -> 세션을 담고 index.jsp , 비정상 -> login.jsp
        }
    }
}
 
cs

UsersService 객체를 만들어서 route에서 열심히 일하고있다.




UsersService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package com.cos.hello.service;
 
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
 
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
 
import com.cos.hello.dao.UsersDao;
import com.cos.hello.model.Users;
 
public class UsersService {
    public void 회원가입(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException {
        //input 에서 값을 받아옴
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String email = req.getParameter("email");
 
        System.out.println("=========joinProc Start=========");
        System.out.println(username);
        System.out.println(password);
        System.out.println(email);
        System.out.println("=========joinProc End=========");
        // 2번 DB에 연결해서 3가지 값을 INSERT하기
        // input 값을 토대로 Users 빌드
        Users user = Users.builder()
                .username(username)
                .password(password)
                .email(email)
                .build();
        
        // insert 함수 실행 (sql로 데이터베이스에 insert)  
        UsersDao usersDao = new UsersDao();
        int result = usersDao.insert(user); //pstmt
        
        if(result == 1) {
               resp.sendRedirect("auth/login.jsp");
            } else {
               resp.sendRedirect("auth/join.jsp");
            }
    }
    
    public Users 로그인(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println("=========loginPorc Start=========");
        System.out.println(username);
        System.out.println(password);
        System.out.println("=========loginPorc End=========");
        // 2번 DB값이 있는지 select 해서 확인 (생략)
        Users user = Users.builder()
                .username(username)
                .password(password)
                .build();
 
        // login 함수 실행 (sql로 데이터베이스에 select)
        UsersDao usersDao = new UsersDao();
        Users userEntity = usersDao.login(user);
        
        if(userEntity != null) {
            // session에는 사용자 패스워드 절대넣지않기
            // 3번 세션 키 발급
            HttpSession session = req.getSession();
            
            //setAttribute : name으로 지정한 이름에 value값을 할당합니다.
            session.setAttribute("sessionUser", userEntity); // name , value
            
            resp.sendRedirect("index.jsp");
            return user;
        }else {
            resp.sendRedirect("auth/login.jsp");
        }
        return null;
    }
    
    public void 유저정보보기(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException, ServletException {
        HttpSession session = req.getSession();
        
        Users users = (Users)session.getAttribute("sessionUser");
        UsersDao usersDao = new UsersDao();
        if(users != null) {
            Users userEntity = usersDao.selectById(users.getId());
            req.setAttribute("users", userEntity); // name , Object
            
            // xxx.jsp로 이동할겁니다 라는 객체
            RequestDispatcher dis = req.getRequestDispatcher("user/selectOne.jsp");
            
            // 덮어쓰기
            dis.forward(req, resp);
        }else {
            System.out.println("유저정보보기() 실패");
        }
    }
    
    public void 유저정보수정페이지(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException, ServletException {
        HttpSession session = req.getSession();
        Users users = (Users)session.getAttribute("sessionUser");
        UsersDao usersDao = new UsersDao();
        if(users != null) {
            Users userEntity = usersDao.selectById(users.getId());
            req.setAttribute("user", userEntity); // name , Object
            
            // xxx.jsp로 이동할겁니다 라는 객체
            RequestDispatcher dis = req.getRequestDispatcher("user/updateOne.jsp");
            
            // 덮어쓰기
            dis.forward(req, resp);
        }
    }
}
 
cs

Model (User 객체) , UserDao , MySQL 셋을 모두 활용하고 있다.

정확하게는 Model, UserDao 두가지. (UserDao 안에 MySQL Query가 있다.)



UserDao.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package com.cos.hello.dao;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import com.cos.hello.config.DBConnMySQL;
import com.cos.hello.model.Users;
 
public class UsersDao {
    //(String username,String password,String email)
    public int insert(Users users) throws SQLException {// 회원가입수행해줘
        // 1번 form의 input태그에 있는 3가지 값 username, passeword, email받기
            
        StringBuffer sb = new StringBuffer();
        sb.append("INSERT INTO users(username, password, email)");
        sb.append("VALUES(?,?,?)");
        String sql = sb.toString();
        Connection conn = DBConnMySQL.getInstance();
        try {
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, users.getUsername());
            pstmt.setString(2, users.getPassword());
            pstmt.setString(3, users.getEmail());
            int result2 = pstmt.executeUpdate(); // 변경된 row count를 리턴, 오류 시 -1를 리턴
            
//            pstmt.executeUpdate();
             
//            return pstmt.executeUpdate();
            if(result2 == 1) {
                System.out.println("result2 : " + result2);
                System.out.println("회원가입 성공");
                return 1;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 3번 INSERT가 정상적으로 되었다면 index.jsp
        
        return -1;
    }
    
    public Users login(Users users) throws SQLException {
        StringBuffer sb = new StringBuffer();
        sb.append("SELECT id, username, password, email FROM users WHERE username = ? AND password = ?");
        String sql = sb.toString();
        Connection conn = DBConnMySQL.getInstance();
        try {
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, users.getUsername());
            pstmt.setString(2, users.getPassword());
//            int result2 = pstmt.executeQuery(sql); // 변경된 row count를 리턴, 오류 시 -1를 리턴
//            System.out.println("result2 : " + result2);
            
            
            ResultSet rs = pstmt.executeQuery();
            if(rs.next()) {
                Users userEntity = Users.builder()
                        .id(rs.getInt("id"))
                        .username(rs.getString("username"))
                        .password(rs.getString("password"))
                        .build();
                
                return userEntity;
            }
            System.out.println("로그인 성공");
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("로그인 실패");
        return null;
    }
    
    public Users selectById(int id) throws SQLException {
        StringBuffer sb = new StringBuffer(); //간단한 문장은 String 으로 , 복잡한 문장은 Buffer로
        sb.append("SELECT id, username, password, email FROM users WHERE id = ?");
        String sql = sb.toString();
        
        Connection conn = DBConnMySQL.getInstance();
        try {
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, id);            
//            int result2 = pstmt.executeQuery(sql); // 변경된 row count를 리턴, 오류 시 -1를 리턴
//            System.out.println("result2 : " + result2);        
            ResultSet rs = pstmt.executeQuery();
            if(rs.next()) {
                Users userEntity = Users.builder()
                        .id(rs.getInt("id"))
                        .username(rs.getString("username"))
                        .password(rs.getString("password"))
                        .email(rs.getString("email"))
                        .build();
                System.out.println("SelectById 성공");
                return userEntity;
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("SelectById 실패");
        return null;
    }
}
 
cs



UsersService 에서 사용할 수 있도록 반환형이 Users 객체나 , success 인 정보를 함수로 반환한다.







hello 프로젝트 참고


https://github.com/tony6303/jspwork



ㅎㅇ 다이나믹 웹 프로젝트   프로젝트 이름 hello 를 만들어 놓으세요 ~


hello2 는 제가 삽질하느라 잘못 만든 프로젝트입니다 ~~~~





Servers 가 Tomcat 관련 파일이 들어있는곳인데 , web.xml에서 내용 일부를 복붙해서 hello 프로젝트에 새로 만들어 줄겁니다 ~


web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="4.0"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee                       http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd">
    <servlet>
        <servlet-name>userController</servlet-name>
        <servlet-class>com.cos.hello.controller.UserController</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>boardController</servlet-name>
        <servlet-class>com.cos.hello.controller.BoardController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>userController</servlet-name>
        <url-pattern>/user</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>boardController</servlet-name>
        <url-pattern>/board</url-pattern>
    </servlet-mapping>
</web-app>
cs




WEB-INF 폴더에 저장   ( new - xml file 로 직접 만들어서 코드만 복붙하세요 )






(미완성)



서블릿을 동작하게 만들려면 web.xml 에 필터를 만들어야함 , 서블릿 맵핑을 해야함


URL 패턴을 쓰지않고 URI 패턴을 사용하기위해서임


모든 요청을 한 곳 으로 모으고싶어서 쓰는것 ( 입구를 하나로)





ㅎㅇ 일단  톰캣을 설치하셈


https://tomcat.apache.org/download-90.cgi




9.0버전 , installer 로 다운받으시고






저는 셧다운포트 8005  연결포트 8000 으로 했습니다


연결포트 8080은 oracle의 포트와 충돌이 있을수도 있다고...


톰캣 설치 끝



STS 실행하세요


FIle > New > other > web > 다이나믹 웹 프로젝트 만드세요




타겟 런타임을 톰캣 9.0으로 설정해주세요

설치경로는 기본값으로 하셨다면 

C:\Program Files\Apache Software Foundation\Tomcat 9.0


여기 있을겁니다







이제 jsp 파일을 만들 수 있습니다



jsp 파일은 항상 WebContent 폴더에 작성해주세요


META-INF , WEB-INF 는  외부접근 불가 구역입니다. 주로 프로젝트의 설정파일을 저장하는곳입니다.


뜬금없지만 JSP관련 기초 설명을 하겠습니다


JSP는 쉽게 말하면 html 파일에서 자바코드를 작성할 수 있게 해주는 파일입니다.

톰캣은 하나의 자바 컴파일러 라고 할 수 있어요.



웹서버(아파치)

내 하드디스크의 특정 폴더를 http주소 방식으로 접근할 수 있게 열어둔 것


접근 방법

프로토콜://ip주소:포트번호/컨텍스트루트/자원명

ex) http://localhost:8000/test1/a.html


jsp

html파일안에 java코드를 넣을 수 있는 파일


톰켓

아파치가 처리할 수 없는 .jsp 파일 요청시 동작함. html파일은 그대로

두고 java코드만 컴파일하여 html코드와 그 결과를 .html파일로 만들

어서 응답해줌.


WebContent

프로젝트 폴더내에 유일하게 외부에서 접근할 수 있게 열어둔 영역


컨텍스트루트

웹서버내에 많은 프로젝트들을 구분하기 위해서 필요


URL

자원에 접근하는 법

URI

식별자로 접근하는 법





MySQL에 있는 데이터를 웹에 뿌려봅시다

아까 만든 다이나믹 웹 프로젝트에서 WEB-INF 폴더에, lib폴더에 >  jar파일 하나 추가하고 add 빌드패스 합니다


https://mvnrepository.com/artifact/mysql/mysql-connector-java



저는 8.0.16 버전 썼습니다







그리고 MySQL에 연결을 시켜줄 자바 파일을 하나 만듭니다

패키지명 com.cos.test1.config


얇은 지식으로 말씀드리자면 패키지명(유일해야함) = 도메인(유일함)

그러므로 도메인을 거꾸로 쓴거같은 양식이 유일하기때문에 그렇게 작성한다고 하네요



new > class > DBConn.java 생성




DBConn.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.cos.test1.config;
 
import java.sql.Connection;
import java.sql.DriverManager;
 
public class DBConn {
    public static Connection getConnection() {
        Connection conn = null;
        //localhost 뒤 = DB이름?
        String url = "jdbc:mysql://localhost:3306/ssar?serverTimezone=Asia/Seoul";
        String username = "ㅇㅎㅇㅀㅇㅀㅇㅀ";
        String password = "ㅇㅎㅇㅎㅎㄱㅎ";
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(url, username, password);
            
            System.out.println("DB 연결성공");
            return conn;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
 
cs


String url = "jdbc:mysql://localhost:3306/ssar?serverTimezone=Asia/Seoul";
String username = "ㅇㅀㄷㄱㅎㄷㅎr";
String password = "둃ㅇㅀㅇㅀ";


url = 포트번호뒤에 있는 ssar 은 제 계정에있는 데이터베이스 이름입니다. 각자 환경에 맞게 바꿔주세요

username = 사용자 계정 아이디 입니다.

password = 사용자 계정 비밀번호 입니다.




webcontent > new jsp file


select.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.PreparedStatement"%>
<%@page import="com.cos.test1.config.DBConn"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>찾아보기</title>
</head>
<body>
<%
    String sql = "SELECT * FROM users WHERE id=1";
    Connection conn = DBConn.getConnection();
    PreparedStatement pstmt = 
            conn.prepareStatement(sql);
    ResultSet rs = pstmt.executeQuery();
    
    rs.next();
    int id = rs.getInt("id");
    String username = rs.getString("username");
    String password = rs.getString("password");
    String email = rs.getString("email");
%>
<h3>id : <%=id %></h3>
<h3>username : <%=username %></h3>
<h3>password : <%=password %></h3>
<h3>email : <%=email %></h3>
</body>
</html>
cs

<% %> 로 감싸진 부분에서는 자바코드를 작성해도 되는 곳입니다.


아까 java resource에 만들었던 DBConn을 import 해서 사용하고있습니다.


executeQuery()의 반환값이 Resultset 이기 때문에 새로 변수를 만들어서 저장해줍니다.


rs,next() : 커서를 한 번 이동시켜줍니다 (안하면 안됨)


rs.get@@@ : 새로만든 변수에 get해서 데이터를 넣습니다 .    변수명은 웬만하면 필드명이랑 일치하게 작성합니다 


<%=id %> : 표현식 태그 라고하네요 결과값을 출력합니다.



실행하기전에~~~


크롬으로 바꿔주시고 (알아서 하셈)




프로젝트 폴더를 Run As > Run On Server 를 하신다면 welcome page (기본값 index.jsp , index.html) 을 실행할 것입니다.


그래서 저희는 그냥  select.jsp 를 Run On Server 할겁니다


TomCat 9.0  확인하고 Finish ㄱㄱ







잘 작동하고있네요 다행입니다




1편에서 한 내용


Oracle 사용자 계정만들기 , DB연결하기 , INSERT랑 DELETE 하기




INSERT , DELETE , UPDATE , SELECT (SELECT는 scott 계정에 맞게 작성하였음)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
 
import config.DBConnection;
import model.Dept;
 
public class MainApp {
 
    public static void main(String[] args) {
//        추가(9);
//        삭제(1);
        찾기(10);
    }
 
    // 함수로 모듈화
    public static void 추가(int id) {
//        String sql = "INSERT INTO test1(id) VALUES("+id+")"; //이렇게하면 인젝션 뚫림
        String sql = "INSERT INTO test1(id) VALUES(?)";
        Connection conn = DBConnection.getinstance();
        // Byte Stream (?)
 
        try {
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, id); // 첫번째 '?' 부분에 id를 넣겠다.
            int result = pstmt.executeUpdate(); // 변경된 row count를 리턴, 오류 시 -1를 리턴
            System.out.println("result : " + result);
            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
 
    // 함수로 모듈화
    public static void 삭제(int id) {
        String sql = "DELETE FROM test1 WHERE id = ?";
        Connection conn = DBConnection.getinstance();
        // Byte Stream (?)
 
        try {
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, id); // 첫번째 '?' 부분에 id를 넣겠다.
            int result = pstmt.executeUpdate(); // 변경된 row count를 리턴, 오류 시 -1를 리턴
            System.out.println("result : " + result);
//            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
 
    // 함수로 모듈화
    public static void 수정(int id) {
        String sql = "UPDATE test1 SET 4 WHERE id = ?";
        Connection conn = DBConnection.getinstance();
        // Byte Stream (?)
 
        try {
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, id); // 첫번째 '?' 부분에 id를 넣겠다.
            int result = pstmt.executeUpdate(); // 변경된 row count를 리턴, 오류 시 -1를 리턴
            System.out.println("result : " + result);
//            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
 
    // 함수로 모듈화 , 사용자 scott으로 변경해야함
    // return값 Dept
    public static Dept 찾기(int deptno) {
        String sql = "SELECT deptno, dname, loc FROM dept WHERE deptno=?";
        Connection conn = DBConnection.getinstance();
        // Byte Stream (?)
 
        try {
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, deptno); // 첫번째 '?' 부분에 id를 넣겠다.
            ResultSet rs = pstmt.executeQuery();
            if(rs.next()) {
                Dept dept = Dept.builder()
                        .deptno(rs.getInt("deptno"))
                        .dname(rs.getString("dname"))
                        .loc(rs.getString("loc"))
                        .build();
                System.out.println(dept);
                return dept;
//                int deptno2 = rs.getInt("deptno");
//                String dname = rs.getString("dname");
//                String loc = rs.getString("loc");
//                System.out.println(deptno2);
//                System.out.println(dname);
//                System.out.println(loc);
            }
 
//            int result = pstmt.executeUpdate(); // 변경된 row count를 리턴, 오류 시 -1를 리턴
//            System.out.println("result : " + result);
//            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
 
    
    
    // 함수로 모듈화 , 사용자 scott으로 변경해야함
    // return값 Dept
    public static List<Dept> 전체찾기() {
        String sql = "SELECT deptno, dname, loc FROM dept WHERE deptno=?";
        Connection conn = DBConnection.getinstance();
        // Byte Stream (?)
 
        try {
            PreparedStatement pstmt = conn.prepareStatement(sql);
//            pstmt.setInt(1, deptno); // 첫번째 '?' 부분에 id를 넣겠다.
            ResultSet rs = pstmt.executeQuery();
            if(rs.next()) {
                Dept dept = Dept.builder()
                        .deptno(rs.getInt("deptno"))
                        .dname(rs.getString("dname"))
                        .loc(rs.getString("loc"))
                        .build();
                System.out.println(dept);
                
//                return dept;
//                int deptno2 = rs.getInt("deptno");
//                String dname = rs.getString("dname");
//                String loc = rs.getString("loc");
//                System.out.println(deptno2);
//                System.out.println(dname);
//                System.out.println(loc);
            }
 
//            int result = pstmt.executeUpdate(); // 변경된 row count를 리턴, 오류 시 -1를 리턴
//            System.out.println("result : " + result);
//            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}
 
cs


모델 먼저 만드세요. [ 만드는이유 : 관리하기 편하기위해서 ? ]


참고로 올리는 scott 스키마 사진


▼Dept 클래스를 모델 패키지에 만든 모습

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package model;
 
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
 
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Dept {
    private int deptno;
    private String dname;
    private String loc;
}
 
cs


lombok.jar 다운로드


https://mvnrepository.com/artifact/org.projectlombok/lombok

알아서 빌드패스




이번에 해볼 일 : 전체찾기 (SELECT)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
 
import config.DBConnection;
import model.Dept;
 
public class MainApp {
 
    // 함수로 모듈화 , 사용자 scott으로 변경해야함
    // return값 List<Dept>
    public static List<Dept> 전체찾기() {
        String sql = "SELECT deptno, dname, loc FROM dept";
        Connection conn = DBConnection.getinstance();
        // Byte Stream (?)
 
        try {
            PreparedStatement pstmt = conn.prepareStatement(sql);
            ResultSet rs = pstmt.executeQuery();
            
            //List 하위에 vector , ArrayList가 있음, 선언은 반복문위에
            List<Dept> listDept = new ArrayList<Dept>();
            while(rs.next()) {
                Dept dept = Dept.builder()
                        .deptno(rs.getInt("deptno"))
                        .dname(rs.getString("dname"))
                        .loc(rs.getString("loc"))
                        .build();
                System.out.println(dept); //toString() 작동 ?
                
                //컬렉션에 담기
                listDept.add(dept);
            }
            return listDept;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    
    public static void main(String[] args) {
//        추가(9);
//        삭제(1);
//        찾기(10);
//        Dept dept = 찾기(10);
        List<Dept> listDept = 전체찾기();
    }
}
 
cs

메서드 전체찾기()만 보면 됩니다.

예제 준비물 : Oracle sqldeveloper , sts tool , ojdbc6.jar


1. sqldeveloper 에 존재하는 데이터베이스에 연동을 할것이기 때문에 사용자계정이 있어야한다.

만들어보자.


먼저 모든 권한을 갖고있는 system 계정에 로그인을 한 뒤 아래 명령어를 실행한다.


-- 앞으로 사용할 사용자이름 , 비밀번호

CREATE USER superuser IDENTIFIED BY 1234; -- 사용자를 만들면 데이터베이스가 같이 만들어짐

GRANT CREATE SESSION TO superuser;

GRANT CREATE TABLE TO superuser;

GRANT CREATE TABLESPACE TO superuser;

GRANT UNLIMITED TABLESPACE TO superuser;



2. Ojdbc6.jar를 다운받아서 buildpath를 한다.


https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc6/11.2.0.4 


여기서 다운받으면 아마 될 지도 ?


oracle developer 가있다면 이 경로에 가면 jar파일이 있을것이다. 나는 여기 있는걸 복붙해서 썼다.

C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib



Build Path 성공한 사진







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package config;
 
import java.sql.Connection;
import java.sql.DriverManager;
 
public class DBConnection {
    //커넥션을 리턴하는게 목적입니다
    //PC의 서버에 연결할것입니다
    public static Connection getinstance() {
        Connection conn = null;
        String url = "jdbc:oracle:thin:@localhost:1521:xe"; //고정
        String user = "superuser"; //사용자계정
        String password = "1234";
        
        //OracleDriver 클래스를 메모리에 로드, 알집파일 안에 있음
        //패키지 경로
        try {
            //문자열에 오류가 있을수도있으니 자체적으로 try문을 권장함
            //reflection 메모리에떠있는 타입을 찾아낸다 (getconnection 컨트롤 클릭 해보시오)
            Class.forName("oracle.jdbc.driver.OracleDriver");
            conn = DriverManager.getConnection(url, user, password);
            System.out.println("DB연결 성공이요");
            return conn;
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("연결 실패");
        return null;
    } // end of getinstance 
}
 
cs


문자열에서 오타가 발생하거나 인터넷이 끊겨있지 않은 이상 연결 성공 할것이다.




3. 자바로 데이터 INSERT 해보기


새 클래스를 만들고 메인함수를 만듭니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
 
import config.DBConnection;
 
public class MainApp {
 
    public static void main(String[] args) {
        String sql = "INSERT INTO test1(id) VALUES(1)";
        Connection conn = DBConnection.getinstance();
        // Byte Stream  (?)
        
        try {
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        
        
    }
 
}
 
cs


아 지금 보니 id필드를 갖고있는 test1 이라는 테이블이 있어야한다 알아서 만드십쇼



4. 함수로 모듈화

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
 
import config.DBConnection;
 
public class MainApp {
 
    public static void main(String[] args) {
        추가(9);
        삭제(1);
    }
    //함수로 모듈화
    public static void 추가(int id) {
//        String sql = "INSERT INTO test1(id) VALUES("+id+")"; //이렇게하면 인젝션 뚫림
        String sql = "INSERT INTO test1(id) VALUES(?)";
        Connection conn = DBConnection.getinstance();
        // Byte Stream  (?)
        
        try {
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, id); // 첫번째 '?' 부분에 id를 넣겠다.
            int result = pstmt.executeUpdate(); // 변경된 row count를 리턴, 오류 시 -1를 리턴
            System.out.println("result : " + result);
//            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    //함수로 모듈화
        public static void 삭제(int id) {
//            String sql = "INSERT INTO test1(id) VALUES("+id+")"; //이렇게하면 인젝션 뚫림
            String sql = "DELETE FROM test1 WHERE id = ?";
            Connection conn = DBConnection.getinstance();
            // Byte Stream  (?)
            
            try {
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setInt(1, id); // 첫번째 '?' 부분에 id를 넣겠다.
                int result = pstmt.executeUpdate(); // 변경된 row count를 리턴, 오류 시 -1를 리턴
                System.out.println("result : " + result);
//                pstmt.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
 
}
 
cs



ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

pstmt를 알고있다면 코드이해에 조금 도움이 될것입니다...

하지만 저는 아직 모르겠네요 알게되면 추가하겠습니다.


coolSMS 이용하기위한 준비물


javaSDK-2,2jar

https://github.com/coolsms/java-sdk/releases



JSON은 COOLSMS 실행에는 필요하지는 않습니당

json-simple-1.1.jar

http://www.java2s.com/Code/Jar/j/Downloadjsonsimple11jar.htm



coolSMS 회원가입후 대시보드(문자메시지 관리페이지) 에서 API KEY 발급받기





public class ExampleSend { public static void main(String[] args) { String api_key = "키입력"; String api_secret = "시크릿키입력"; Message coolsms = new Message(api_key, api_secret); // 4 params(to, from, type, text) are mandatory. must be filled HashMap<String, String> params = new HashMap<String, String>(); params.put("to", "발신번호"); params.put("from", "수신번호"); //무조건 자기번호 (인증) params.put("type", "SMS"); params.put("text", "보낼 메시지를 입력하시오"); params.put("app_version", "test app 1.2"); // application name and version try { //send() 는 메시지를 보내는 함수 JSONObject obj = (JSONObject) coolsms.send(params); System.out.println(obj.toString()); } catch (CoolsmsException e) { System.out.println(e.getMessage()); System.out.println(e.getCode()); } } 

}


class명을 ExampleSend 로 해서 메인함수 내의 코드만 복붙해 간다.

(이클립스 사용시) jar파일이 성공적으로 추가되었다면 Ctrl + Shift + O 를하면 자동으로 import가 될것이다.


JAR파일 추가하는법 (링크)


api_key , api_secert 에 발급받은 key를 대입한다.

발신번호와 수신번호에 각자 원하는 번호를 입력한다.


그러나 우리는 수신번호를 일부러 틀리게 적어서 error를 발생시킬것이다.



try문 안에있는 obj.toString()의 결과가 출력된다

{"group_id":"R2G9fqnb315X6VYf","error_list":{"1":"1062"},"success_count":0,"error_count":1}

key와 value값으로 이루어진 Json 형식의 데이터이다.



이 데이터를 String 클래스의 메서드로 뭔가뭔가 왤케왤케 하게 파싱을 해볼것이다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package sms;
 
import lombok.Data;
 
@Data
public class Response {
    String group_id;
    String error_list;
    String success_count;
    String error_count;
 
    static String startEndTrim(String str) {
        return str.substring(str.indexOf("{")+1,str.lastIndexOf("}"));
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String data = "{\"group_id\":\"R2GtX62GMhUpnaem\",\"error_list\":{\"1\":\"1062\"},\"success_count\":0,\"error_count\":1}\r\n"
                + "";
        System.out.println(data);
        System.out.println("----------------------------------");
        data = data.replaceAll("\"""");
        data = startEndTrim(data);
 
        Response res = new Response();
        System.out.println(data);
 
        String s1[] = data.split(",");
        for (int i = 0; i < 4; i++) {
            if(s1[i].contains("{")||s1[i].contains("}")) {
                s1[i] = s1[i].replace("{""");
                s1[i] = s1[i].replace("}""");
                System.out.println("s1[" + i + "] " + s1[i]);
            }else
                System.out.println("s1[" + i + "] " + s1[i]);            
        }
 
        for (int i = 0; i < s1.length; i++) {
            String s2[] = s1[i].split(":");
            for (int j = 0; j < s2.length; j++) {
                System.out.println("s2[" + i + "]" + "[" + j + "] " + s2[j]);
            }
        }
 
        System.out.println(res);
    }
 
}
 
cs




출력 결과

{"group_id":"R2GtX62GMhUpnaem","error_list":{"1":"1062"},"success_count":0,"error_count":1}


----------------------------------

group_id:R2GtX62GMhUpnaem,error_list:{1:1062},success_count:0,error_count:1

s1[0] group_id:R2GtX62GMhUpnaem

s1[1] error_list:1:1062

s1[2] success_count:0

s1[3] error_count:1


s2[0][0] group_id

s2[0][1] R2GtX62GMhUpnaem

s2[1][0] error_list

s2[1][1] 1

s2[1][2] 1062

s2[2][0] success_count

s2[2][1] 0

s2[3][0] error_count

s2[3][1] 1


대부분의 RAM의 절반은 OS가 사용한다.


나머지 반을 JVM이 관리를 해주게 되는데, 프로그램 내에 사용되지 않는 메모리(쓰레기)는 가비지 컬렉션 기능에의해 자동으로 회수된다.


static 은 사용하기전에도 메모리에 이미 존재하는 자료 ?

프로그램이 실행될 때 부터 종료될 때 까지 메모리에 남아있게 된다. 전역변수로 지정하고싶을 때 static 을 사용한다.


heap 은 잠깐 메모리에서 사용하고 사라지는 자료 ?

참조형 데이터 타입을 갖는 객체,배열 들은 Heap영역에 데이터가 저장된다. 이때 변수(객체변수, 참조변수)는 Stack영역의 공간에서 실제 데이터가 저장된 Heap영역의 참조값을 new 연산자를 통해 리턴받는다.

다시 말하면 실제 데이터를 갖고있는 Heap영역의 참조 값을 Stack영역의 객체가 갖고있다. (매핑 테이블 ? 이야기인듯)

이렇게 리턴 받은 참조 값을 갖고 있는 객체를 통해서만 해당 인스턴스를 핸들 할 수 있다.


출처 : http://blog.naver.com/heartflow89/220954420688



함수가 호출되면, 함수 내부를 stack이라고 하는데 함수 호출시점부터 함수가 종료될 때 까지 메모리가 유지된다.


.class파일을 실행하면 static부분을 메모리에 로드한다.

static공간에 있는 main()함수를 호출하고

이때 stack이 생성되는데 이 stack의 이름이 main이다.

main은 stack이 종료되면 프로그램도 종료된다.


ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

String str = "안녕하세요";


자바에서 String은 기본자료형이 아니라 클래스이다. (파스칼표기법)

크기를 정할수없는 타입(String 에 어떤크기의 변수가 들어갈지 모른다) = 레퍼런스 타입 (참조한다)

안녕하세요 가 저장이된것이 아니라 안녕하세요의 '주소'가 저장되어있다.


ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

int[] n = {1,2,3}

메모리에서 연속된 세 공간이 있는 자리를 찾아서 시작주소만 저장한다. (배열의 크기를 알고있기 때문에 끝주소가 자동으로 계산이 된다)


나는 백틱을 알기 전에는 자바스크립트 에서 문자열과 변수를 함께 다룰때 


print("Hello" + 어떤변수 + "world");


이렇게 큰따옴표와 + 연산을 이용하여 작성도 힘들고 보기도 불편한 작업을 하고 있었다.


하지만 백틱이라는 엄청난,,, 도구를 알게되었다. 자바스크립트에서만 사용할 수 (?) 있다는게 좀 아쉬운거같다


참고로 백틱은 키보드 1 왼쪽에있는 물결표시 버튼에 있습니다.   ( ` ) << 작은따옴표 아님




예제를 보면서 코드설명 하겠습니다


여기서 삭제 버튼을 누르면






문자열이 치환 되어버립니다




소스 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <title>Document</title>
    <style>
        #comment-list{
            border: 5px solid black;
            padding: 10px;
        }
        #comment-list span{
            display: inline-block;
            border: 2px solid red;
            padding: 10px;
        }
    </style>
</head>
<body>  
    <input type="text" id="input-comment"/>
    <button onclick="addComment()">댓글 작성</button>
    <hr/>
    <div id="comment-list">
        <div id="item-1">
            <span id="comment-1">댓글1</span>
            <span id="comment-delete-1" onclick="deleteComment(1)">삭제</span>
        </div>
        <div id="item-2">
            <span id="comment-2">댓글2</span>
            <span id="comment-delete-2" onclick="deleteComment(2)">삭제</span>
        </div>
    </div>
</body>
<script>
    //append, prepend, after, before
    no = 3;
    function addComment(){
        //get
        var comment = $("#input-comment").val();
 
        //set  
        //문자열과 변수를 같이 사용해야할 때 편리한 도구 >> ` <<(backtick, 키보드 1 왼쪽 버튼)
         /*
            1. 백틱이 필요한 라인을 그대로 복붙한다.
            <span id="comment-1">댓글1</span>
            <span id="comment-delete-1" onclick="deleteComment(1)">삭제</span>
            2. 변수로 바꾸어야 할 부분을 ${변수}로 직접 수정한다.
            <span id="comment-${no}">댓글1</span>
            <span id="comment-delete-${no}" onclick="deleteComment(${no})">삭제</span>
        */
 
        //한 줄에 쓰면 이렇게 됨
        // $("#comment-list").prepend(`<div id=item-${id}> <span id=comment-${id}>${comment}</span> 
        // <span id=comment-delete-${id} onclick="deleteComment(${id})">삭제</span> </div>`);
 
        //한 줄에 쓰는건 보기 안좋으니 변수에 문자열 추가 하는방식으로
        var commentitem = `<div id="item-${no}">`;
        commentitem = commentitem + `<span id="comment-${no}">${comment}</span>`;
        commentitem = commentitem + `<span id="comment-delete-${no}" onclick="deleteComment(${no})">삭제</span>`;
        
 
        $("#comment-list").prepend(commentitem);
        no = no + 1;
        
        // $("#input-comment").val();
    }
 
    function deleteComment(id){
        // $("#item-"+id).remove();
        $(`#comment-${id}`).text("삭제된 댓글 입니다");
    }
</script>
</html>
cs



1. 백틱이 필요한 라인을 그대로 복붙한다.
<span id="comment-1">댓글1</span>
<span id="comment-delete-1" onclick="deleteComment(1)">삭제</span>

2. 변수로 바꾸어야 할 부분을 ${변수}로 직접 수정한다.
<span id="comment-${no}">댓글1</span>
<span id="comment-delete-${no}" onclick="deleteComment(${no})">삭제</span>


addComment() 간략설명

no 라는 숫자변수를 함수 실행(댓글이 작성됨)마다 1씩 증가되기때문에 댓글을 번호로 모두 구별할수 있어서

삭제버튼을 누르면 해당 댓글만 삭제가 가능해집니다.


근데 핵심은 백틱을 사용해서 보기도좋고 작성하기도 편하다는것

'국비지원 Spring프레임워크 > JQuery' 카테고리의 다른 글

제이쿼리(Jquery) 개요  (0) 2020.11.09

jQuery를 사용하면 아주 간편하게 HTML 요소를 선택하고, 그렇게 선택된 요소에 손쉽게 특정 동작을 설정할 수 있다.

$(선택자).동작함수();

달러($) 기호는 jQuery를 의미하고, jQuery에 접근할 수 있게 해주는 식별자이다.
선택자를 이용하여 원하는 HTML 요소를 선택하고, 동작 함수를 정의하여 선택된 요소에 원하는 동작을 설정한다.

선택자에는 클래스, ID 도 들어갈 수 있다.



동작함수 정리 블로그

https://soft91.tistory.com/9



자주쓰는 함수

text() , html(), arrt(), val()



영화포스터 예제



소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <title>영화 포스터</title>
    <style>
        .container{
            margin: 0 auto;
            width: 80%;
            display: flex;
            text-align: center;
            justify-content: center;
        }
        .movie-item{
            padding: 10px;
            width: 300px;
            height: 500px;
            background-color: gray;
            border: 1px solid black;
            box-shadow: 0 0 3px 3px black;
        }
    </style>
</head>
<body>
    <h1>영화포스터</h1>
    <button onclick="getMovie()">영화 불러오기</button>
    <div class="container">
        <div class="movie-item">
            <div id="poster">
                <img id="movie-poster" src="#" width="290px" height="300px" alt="">
            </div>
            <div id="title">
                제목임시
            </div>
            <div id="rating">
                평점임시
            </div>
        </div>
    </div>
 
<script>
    function getMovie(){
        var movie = {
            poster: "https://t1.daumcdn.net/movie/99a4d42206a028764e86c5bff8cf0021db985223",
            title: "도굴",
            rating: 9.1
        }
 
        $("#movie-poster").attr("src",movie.poster);
        $("#title").text(movie.title);
        $("#rating").text(movie.rating);
        console.log("버튼테스트");
    }
</script>
</body>
</html>
cs

function 이 핵심 내용

'국비지원 Spring프레임워크 > JQuery' 카테고리의 다른 글

자바스크립트 백틱(backtick)  (0) 2020.11.10

relative




소스 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            .box1{
                position: static; /* 기본값 static , 물처럼 흐르듯이 표현*/
                left: 100px;
                width:300px;
                height:300px;
                background-color: yellow; 
                display: inline-block;
            }
            .box2{
                position: relative; /* top left는 static이 아닌 속성에 모두 적용가능 */
                top: 100px;
                left: 100px;
                width:300px;
                height:300px;
                background-color: red; 
                display: inline-block;
            }
            .box3{
                width:300px;
                height:300px;
                background-color: green; 
                display: inline-block;
            }
            .box4{
                width:300px;
                height:300px;
                background-color: blue; 
                display: inline-block;
            }
            .box5{
                width:300px;
                height:300px;
                background-color: bisque; 
                display: inline-block;
            }
        </style>
    </head>
    <body>
    <div class="box1"></div>
    <div class="box2"></div>
    <div class="box3"></div>
    <div class="box4"></div>
    <div class="box5"></div>
    </body>
</html>
 
 
 
cs



box2의 스타일 left, top은 box1과 body에 관계하여 적용되었다.



absolute



소스 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            body{
                position: relative;
            }
            .box1{
                
                width:300px;
                height:300px;
                background-color: yellow; 
                display: inline-block;
            }
            /* absolute 는 도화지가 한 장 더 생긴다. */
            .box2{
                position: absolute;
                left: 100px;
                top: 100px;
                width:300px;
                height:300px;
                background-color: red; 
                display: inline-block;
            }
            .box3{
                width:300px;
                height:300px;
                background-color: green; 
                display: inline-block;
            }
            .box4{
                width:300px;
                height:300px;
                background-color: blue; 
                display: inline-block;
            }
            .box5{
                width:300px;
                height:300px;
                background-color: bisque; 
                display: inline-block;
            }
        </style>
    </head>
    <body>
    <div class="box1"></div>
    <div class="box2"></div>
    <div class="box3"></div>
    <div class="box4"></div>
    <div class="box5"></div>
    </body>
</html>
 
 
 
cs


빨간색 box가 다른 box들 위에 나타난다. (새로운 도화지에 그린 느낌)



fixed


코드 그냥 안넣겠습니다 위의 코드에서 box2의 position 속성만 fixed 로 바꿔주면 되니까



스크롤해도 빨간색box가 fixed(고정)된 위치에 나타납니다.

'국비지원 Spring프레임워크 > HTML' 카테고리의 다른 글

input 태그  (0) 2020.11.04
레이아웃 FLEX  (0) 2020.11.03
div로 컨텐츠 위치 조정하기  (0) 2020.11.03
SVG 이미지  (0) 2020.11.03
Form 태그  (0) 2020.11.03



소스 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<html>
    <head>
        <style>
            .btn1{
                background-color: #FF5A5F;
                border: 0;
                color: white;
                cursor: pointer;
                font-size: 15px;
                font-weight: 700;
                border-radius: 6px;
                outline: 0;
                height: 45px;
                width: 70px;
                box-shadow: 0 2px 2px 0 black;
                opacity: 0.7;
            }
            .btn1:hover{
                opacity: 1;
            }
            .btn_google{
                background-color: white;
                width: 400px;
                height: 45px;
                font-size: 15px;
                font-weight: 700;
                border-radius: 6px;
                cursor: pointer;
            }
            .btn2{
                height: 20px;
                width: 260px;
            }
        </style>
    </head>
    <body>
        <h1>버튼</h1>
        <hr/>
        <button class="btn1">검색</button>
        <h1>구글 버튼</h1>
        <hr/>
        <button class="btn_google">
            <!-- 구글 로고 svg를 검색해서 복붙 했음 -->
        <svg viewBox="0 0 533.5 544.3" style="width: 18px; height: 18px; " xmlns="http://www.w3.org/2000/svg">
            <path d="M533.5 278.4c0-18.5-1.5-37.1-4.7-55.3H272.1v104.8h147c-6.1 33.8-25.7 63.7-54.4 82.7v68h87.7c51.5-47.4 81.1-117.4 81.1-200.2z" fill="#4285f4"/>
            <path d="M272.1 544.3c73.4 0 135.3-24.1 180.4-65.7l-87.7-68c-24.4 16.6-55.9 26-92.6 26-71 0-131.2-47.9-152.8-112.3H28.9v70.1c46.2 91.9 140.3 149.9 243.2 149.9z" fill="#34a853"/>
            <path d="M119.3 324.3c-11.4-33.8-11.4-70.4 0-104.2V150H28.9c-38.6 76.9-38.6 167.5 0 244.4l90.4-70.1z" fill="#fbbc04"/>
            <path d="M272.1 107.7c38.8-.6 76.3 14 104.4 40.8l77.7-77.7C405 24.6 339.7-.8 272.1 0 169.2 0 75.1 58 28.9 150l90.4 70.1c21.5-64.5 81.8-112.4 152.8-112.4z" fill="#ea4335"/>
        </svg>
        구글 계정으로 로그인
        </button>        
        <h1>인풋태그</h1>
        <hr/>
        <input class="btn2" type="text" placeholder="🔍 Search...">
        <!-- 이모지에서 돋보기를 이용 했음 -->
    </body>
</html>
cs



'국비지원 Spring프레임워크 > HTML' 카테고리의 다른 글

position: relative, absolute, fixed  (0) 2020.11.04
레이아웃 FLEX  (0) 2020.11.03
div로 컨텐츠 위치 조정하기  (0) 2020.11.03
SVG 이미지  (0) 2020.11.03
Form 태그  (0) 2020.11.03

FLEX02


각종 애플리케이션에서 레이아웃은 디자인에서 가장 중요한 요소입니다.


그러나 인류는 레이아웃을 코드로 명확히 표현하기 어려움이 있었는데 FLEX가 등장함으로써 많은 문제가 해결 되었다고 합니다. ( 생활코딩 FLEX 강의 : https://opentutorials.org/course/2418/13526 )



소스 코드 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<html>
    <head>
        <style>
            /* */
            .flex-container{
                display: flex; /* 콘텐츠들이 블럭에서 인라인으로 바뀌었다 */
                justify-content: space-evenly; /* 기본 진행방향은 가로, 속성값 : flex-start, flex-end, center */
                /* space-around : 가운데 콘텐츠를 기준으로 여백 ,space-between : 모서리 여백 없음 ,space-evenly : 여백이 모두같음*/
            }
            .item{
display: flex;
                border: 5px solid black;
                height: 100px;
                width: 200px;
                justify-content: center; /* 주 축 정렬( 기본 :row ) */
                align-items: center; /* 수직 축 정렬( col ) */
            }
        </style>
    </head>
    <body>
        <div class="flex-container">
            <div class="item">첫번째 박스</div>
            <div class="item">두번째 박스</div>
            <div class="item">세번째 박스</div>
        </div>
    </body>
</html>

cs







ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

FLEX 05


소스코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<html>
<head>
    <meta charset="utf-8">
    <style>        
        header{
            background-color: yellow;
            height: 80px;
        }
        /* 콘텐츠 스타일 시작 */
        .content{
            display: flex;
            flex-direction: row; /* 기본값 */
            justify-content: space-between;
            height: 500px;
        }
            .content nav{
                background-color: rgb(167, 170, 5);            
                width: 350px;
            }
            .content aside{
                background-color: red;
                width: 350px;
            }
            /* 메인 스타일 시작 */
            .content main{
                flex-direction: column;
                background-color: green;
                width: 800px;
            }
                .mini-head{
                    background-color: green;
                }
                .mini-main{
                    background-color: white;
                }
                .mini-footer{
                    background-color: red;
                }
                /* 메인 스타일 끝 */
        /* 콘텐츠 스타일 끝 */
        footer{
            background-color: pink;
            height: 80px;
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            header
        </header>
        <section class="content">
            <nav>
                nav
            </nav>
            <main>
                <div class="mini-head">mini-head</div>
                <div class="mini-main">mini-main</div>
                <div class="mini-footer">mini-footer</div>
            </main>
            <aside>
                aside
            </aside>
        </section>
        <footer>
            footer
        </footer>
    </div>
</body>
</html>
cs


ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

FLEX 06


소스 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<html>
    <head>
        <style>
            body{
                display: flex;
                justify-content: center;
            }
            .container{
                width: auto;
                background-color: gray;
            }
            .header{
                background-color: orange;
                text-align: center;
                margin: 10px;
            }
            .contents{
                background-color: lightgreen;
                text-align: center;
                margin: 10px;
            }
            .button{
                display: flex;
                background-color: lightblue;
                justify-content: center;
                margin: 10px;
            }
            .image-view{
                display: flex;
                width: 1000px;
                background-color: plum;
                flex-direction: column;
            }
            .text{
                text-align: center;
            }
            .image-container{
                display: flex;
                justify-content: space-around;
            }
            div.image1{
                background-image: url("images/london.jpg");
                background-size: cover;
                width: 250px;
                height: 250px;
                margin: 10px 0px;
                
            }
            div.image2{
                background-image: url("images/napa.jpg");
                background-size: cover;
                width: 250px;
                height: 250px;
                margin: 10px 0px;
                
            }
            div.image3{
                background-image: url("images/new-york.jpg");
                background-size: cover;
                width: 250px;
                height: 250px;
                margin: 10px 0px;
            }
            .image-container img{
                width: 250px;
                height: 250px;
                object-fit: fill;
                margin: 10px 0px;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="header">제목</div>
                <div class="contents">콘텐츠</div>
                    <article class="image-view">                                               
                        <div class="text">class image-view width 1000px (pink)</div
                        <div class="text">background-image , background-size : cover</div>
                        <div class="image-container">
                            <div class="image1"></div>
                            <div class="image2"></div>
                            <div class="image3"></div>
                        </div>
                    </article>
                <div class="button"><button>버튼</button></div>
 
                <hr>
                
            <div class="header">제목2</div>
                <div class="contents">콘텐츠2</div>
                    <article class="image-view">
                        <div class="text">class image-view width 1000px (pink)</div
                        <div class="text">selector img , object-fit : fill</div>
                        <div class="image-container">
                            <div class="image4"><img src="images/san-francisco.jpg" alt=""></div>
                            <div class="image5"><img src="images/san-francisco-2.jpg" alt=""></div>
                            <div class="image6"><img src="images/sonoma.jpg" alt=""></div>
                        </div>
                    </article>
                <div class="button"><button>버튼</button></div>
        </div<!--container 끝-->
        
    </body>
</html>
cs



마지막시간에 학생들 방치해서 좀 당황했음

'국비지원 Spring프레임워크 > HTML' 카테고리의 다른 글

position: relative, absolute, fixed  (0) 2020.11.04
input 태그  (0) 2020.11.04
div로 컨텐츠 위치 조정하기  (0) 2020.11.03
SVG 이미지  (0) 2020.11.03
Form 태그  (0) 2020.11.03




실습 결과화면 입니다.  바로 소스 코드를 보며 이해 해보겠습니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<html>
    <head>
        <style>
            /* 인라인블럭 */
            .box{
                display: inline-block;
                border: 1px solid black;
                height: 100px;
                width: 200px;                                
            }
            /* 그냥 div 의 display는 block (부모의 영역 끝까지) */
            /* text-align 은 inline 속성을 가져야만 적용된다 */
            .container{
                display: inline-block;
                text-align: center;
                border: 3px green solid;
                width: 800px;
            }
            .outer{
                margin: 0px auto; /* 세로 가로 */
                text-align: center;
                border: 1px red solid;
                width: 80%;
            }
        </style>
    </head>
    <body>
        <div class="outer">
            <div class="container"> <!-- box클래스의 div들이 글자(?)로 인식되어서 가운데 정렬이 가능하게 된다.-->
                <div class="box">첫번째 박스</div>
                <div class="box">두번째 박스</div>
                <div class="box">세번째 박스</div>
            </div>
        </div>
    </body>
</html>
cs

outer 클래스가 가장 큰 영역을 차지하고있고 (빨간색)


그 안에 container (초록색)


또 그 안에 box (검은색) 이 있습니다.


div안에 자신이 원하는 컨텐츠를 넣어서 스타일을 입혀서 위치를 지정하는게 실무에서도 많이 쓰이는 기본기라고 합니다.

'국비지원 Spring프레임워크 > HTML' 카테고리의 다른 글

input 태그  (0) 2020.11.04
레이아웃 FLEX  (0) 2020.11.03
SVG 이미지  (0) 2020.11.03
Form 태그  (0) 2020.11.03
테이블 만들기 실습  (0) 2020.11.03

이미지 파일을 비트맵 형식으로 변환시킨 확장자인 SVG에 대해서 알게되었다.





이 JPG 파일을 SVG생성기로 변환시켜보았다. (convertio.co)



SVG의 장점은 글자(비트맵) 이기 때문에 jpg파일과는 다르게 확대하거나 축소하여도 깨지지가 않는다.

주로 로고(메인로고, 이모티콘) 등 작은 사진을 표현할 때 사용한다.



SVG 소스 코드 (HTML 편집기에 복사하면 SVG이미지가 출력된다)

<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
 width="500.000000pt" height="500.000000pt" viewBox="0 0 500.000000 500.000000"
 preserveAspectRatio="xMidYMid meet">

<g transform="translate(0.000000,500.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M2270 4590 c-337 -47 -596 -166 -801 -370 -217 -214 -323 -482 -323
-815 1 -251 61 -490 178 -698 38 -69 142 -213 168 -235 12 -9 15 -24 11 -52
-4 -25 0 -48 9 -62 11 -19 12 -51 6 -178 -15 -288 29 -798 108 -1251 6 -36 5
-36 -32 -44 -87 -16 -182 -89 -210 -160 -25 -68 -3 -127 65 -169 49 -31 210
-83 301 -97 103 -16 375 -6 460 16 101 27 186 71 221 115 l31 39 32 -33 c78
-82 256 -136 477 -143 289 -10 476 48 518 160 36 95 -36 210 -151 245 -46 13
-58 21 -58 37 0 11 14 85 30 165 51 242 78 391 95 516 16 125 37 519 34 639
-1 39 4 84 10 100 7 17 11 46 9 65 -4 31 2 40 64 103 161 163 268 394 303 657
17 125 19 333 4 433 -58 387 -278 683 -645 865 -218 109 -403 152 -669 157
-99 2 -209 0 -245 -5z m333 -27 c-7 -2 -21 -2 -30 0 -10 3 -4 5 12 5 17 0 24
-2 18 -5z m622 -181 c-3 -3 -11 0 -18 7 -9 10 -8 11 6 5 10 -3 15 -9 12 -12z
m245 -172 c31 -30 36 -37 11 -15 -25 23 -72 60 -103 84 -32 24 -58 45 -58 48
0 10 96 -65 150 -117z m-1875 80 c-10 -11 -22 -20 -28 -20 -5 0 1 9 14 20 31
25 37 25 14 0z m-45 -33 c0 -1 -33 -34 -72 -72 l-73 -70 70 73 c64 67 75 77
75 69z m2084 -239 c11 -18 17 -31 14 -28 -12 11 -108 141 -108 147 0 9 74 -84
94 -119z m-2234 78 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21
13z m890 -61 c95 -48 154 -131 181 -251 16 -71 2 -197 -31 -271 -24 -56 -46
-74 -28 -23 19 55 -13 120 -58 120 -27 0 -74 -53 -74 -84 0 -46 22 -88 53
-101 l31 -13 -36 -15 c-50 -21 -137 -31 -202 -23 -67 9 -135 52 -175 110 -124
180 -45 491 143 560 52 20 150 15 196 -9z m608 -6 c125 -61 200 -229 180 -406
-20 -178 -157 -281 -335 -253 -36 6 -82 19 -102 30 -34 18 -35 19 -10 20 33 0
55 25 64 70 8 44 -7 84 -39 105 -64 42 -115 -40 -81 -130 5 -16 3 -15 -14 5
-32 39 -52 107 -58 200 -12 175 52 302 182 361 57 26 156 25 213 -2z m123 -56
c13 -16 12 -17 -3 -4 -17 13 -22 21 -14 21 2 0 10 -8 17 -17z m-1061 3 c0 -2
-8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m1715 -26 c9 -16 13
-30 11 -30 -3 0 -12 14 -21 30 -9 17 -13 30 -11 30 3 0 12 -13 21 -30z m-2375
-10 c-6 -11 -13 -20 -16 -20 -2 0 0 9 6 20 6 11 13 20 16 20 2 0 0 -9 -6 -20z
m2429 -105 c0 -5 -6 1 -14 15 -8 14 -14 30 -14 35 0 6 6 -1 14 -15 8 -14 14
-29 14 -35z m-1238 18 c-8 -15 -10 -15 -11 -2 0 17 10 32 18 25 2 -3 -1 -13
-7 -23z m1268 -103 c0 -10 -3 -8 -9 5 -12 27 -12 43 0 25 5 -8 9 -22 9 -30z
m-642 -97 c-2 -16 -4 -3 -4 27 0 30 2 43 4 28 2 -16 2 -40 0 -55z m670 -25
c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m10 -60 c-3 -7 -5 -2 -5
12 0 14 2 19 5 13 2 -7 2 -19 0 -25z m-1894 -41 c34 -74 79 -122 145 -153 52
-25 63 -26 159 -22 92 4 103 3 97 -11 -12 -30 -16 -90 -10 -126 10 -49 77
-121 127 -137 l39 -11 0 -364 0 -363 -26 0 c-111 0 -456 185 -668 358 l-69 57
39 7 c21 3 91 14 154 23 152 22 160 24 160 36 0 7 -12 9 -32 6 -18 -3 -105
-16 -192 -28 l-160 -23 -77 82 c-43 45 -80 82 -83 82 -17 0 1 -25 64 -93 l71
-75 -76 -13 c-41 -6 -75 -16 -75 -20 0 -12 10 -11 101 2 l76 12 74 -62 c158
-133 407 -282 571 -343 78 -28 89 -30 193 -25 92 3 128 10 222 41 142 47 347
150 500 251 124 83 300 245 288 265 -5 8 -11 8 -21 -1 -12 -9 -14 -5 -14 25 0
21 -5 46 -11 58 -14 25 -10 28 40 35 59 8 50 23 -13 23 -39 0 -68 7 -102 25
-76 40 -155 32 -239 -25 -26 -17 -46 -20 -142 -20 -111 0 -143 -5 -143 -21 0
-4 52 -5 115 -2 114 6 134 1 101 -26 -7 -6 -26 -38 -40 -72 l-28 -60 -86 7
c-106 8 -102 -7 6 -21 l77 -10 5 -65 c3 -45 14 -83 33 -119 15 -29 24 -57 21
-62 -7 -12 -158 -88 -245 -124 -98 -41 -217 -74 -287 -82 l-62 -6 2 363 3 363
42 12 c22 7 55 22 71 34 63 45 93 162 58 232 -14 29 -14 30 2 24 39 -15 140
-26 187 -20 99 13 196 89 231 181 17 44 17 44 58 38 224 -29 398 -139 471
-298 118 -257 33 -586 -212 -816 -103 -98 -180 -145 -291 -179 -201 -60 -347
-81 -577 -81 -258 0 -469 34 -674 109 -110 40 -154 67 -228 139 -171 168 -273
399 -273 623 0 215 185 429 433 500 91 26 93 26 120 -34z m611 -19 l22 -53
-48 0 c-26 0 -48 1 -48 3 0 1 9 20 20 42 11 22 20 47 20 56 0 25 10 11 34 -48z
m826 42 c8 -5 11 -10 5 -10 -5 0 -17 5 -25 10 -8 5 -10 10 -5 10 6 0 17 -5 25
-10z m467 -107 c-2 -16 -4 -3 -4 27 0 30 2 43 4 28 2 -16 2 -40 0 -55z m-1419
34 c2 -12 -3 -17 -17 -17 -12 0 -21 6 -21 13 0 31 32 34 38 4z m250 -10 c2
-12 -3 -17 -17 -17 -12 0 -21 6 -21 13 0 31 32 34 38 4z m853 -4 c13 -16 12
-17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m-2001 -38 c-24 -25 -46 -45
-49 -45 -3 0 15 20 39 45 24 25 46 45 49 45 3 0 -15 -20 -39 -45z m-313 -17
c-2 -13 -4 -5 -4 17 -1 22 1 32 4 23 2 -10 2 -28 0 -40z m2424 -60 c15 -28 5
-21 -21 15 -15 20 -17 27 -6 18 9 -8 22 -23 27 -33z m-2424 0 c-3 -7 -5 -2 -5
12 0 14 2 19 5 13 2 -7 2 -19 0 -25z m1299 -4 c37 -55 -25 -117 -80 -80 -30
19 -35 65 -10 90 25 25 71 20 90 -10z m1331 -126 c-2 -18 -4 -4 -4 32 0 36 2
50 4 33 2 -18 2 -48 0 -65z m-130 -65 c-3 -10 -5 -4 -5 12 0 17 2 24 5 18 2
-7 2 -21 0 -30z m-2480 5 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z
m2600 -25 c-3 -10 -5 -4 -5 12 0 17 2 24 5 18 2 -7 2 -21 0 -30z m-2470 -5
c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m-120 -20 c-3 -8 -6 -5
-6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m2480 -25 c-3 -10 -5 -2 -5 17 0 19 2
27 5 18 2 -10 2 -26 0 -35z m100 -5 c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2
-19 0 -25z m-2470 -30 c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2 -19 0 -25z
m2460 -20 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m-432 7 c-23
-8 -125 -11 -113 -4 7 5 38 8 68 8 30 0 51 -2 45 -4z m53 -21 c34 -24 52 -68
52 -128 0 -52 -2 -56 -47 -99 -27 -25 -60 -55 -75 -67 l-28 -21 2 48 c1 36 2
40 5 16 2 -18 8 -33 12 -33 4 0 33 23 64 51 57 50 57 51 57 107 0 62 -21 106
-62 128 -13 8 -18 13 -13 14 6 0 21 -7 33 -16z m-222 -23 c-80 -64 -119 -143
-118 -241 0 -66 32 -160 54 -160 5 0 41 20 79 45 l69 45 0 75 c0 75 11 115 31
115 6 0 3 -7 -5 -16 -12 -11 -16 -36 -16 -97 l0 -82 -81 -54 c-90 -60 -84 -61
-121 19 -33 71 -29 163 11 244 29 60 99 136 124 136 5 0 -7 -13 -27 -29z m591
-3 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m-2440 -40 c-3 -8 -6
-5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m2430 0 c-3 -8 -6 -5 -6 6 -1 11 2
17 5 13 3 -3 4 -12 1 -19z m-70 -20 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4
-12 1 -19z m34 -85 c-12 -20 -14 -14 -5 12 4 9 9 14 11 11 3 -2 0 -13 -6 -23z
m-404 -25 c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2 -19 0 -25z m-2007 -13 c0
-5 -5 -3 -10 5 -5 8 -10 20 -10 25 0 6 5 3 10 -5 5 -8 10 -19 10 -25z m35 -65
c9 -16 13 -30 11 -30 -3 0 -12 14 -21 30 -9 17 -13 30 -11 30 3 0 12 -13 21
-30z m2320 -20 c-14 -27 -28 -50 -30 -50 -3 0 6 23 20 50 14 28 28 50 30 50 3
0 -6 -22 -20 -50z m-61 -52 c-9 -18 -25 -45 -35 -60 -24 -33 -24 -45 -2 -27
10 8 3 -5 -15 -28 -31 -40 -153 -153 -165 -153 -9 0 127 134 137 135 5 0 11 6
14 14 3 9 0 11 -8 6 -7 -5 0 12 17 36 17 24 38 59 47 77 9 17 19 32 22 32 2 0
-3 -15 -12 -32z m-2209 -14 c9 -15 12 -23 6 -20 -11 7 -35 46 -28 46 3 0 12
-12 22 -26z m56 -41 c12 -21 22 -46 21 -56 0 -9 3 -15 7 -12 5 2 14 -2 21 -10
7 -8 10 -15 7 -15 -3 0 18 -23 46 -51 46 -45 47 -48 12 -21 -22 17 -54 45 -71
64 -42 45 -93 116 -71 99 19 -15 22 -9 7 20 -19 34 -3 20 21 -18z m2159 13 c0
-2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m-2053 -358 c-3
-7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2 -19 0 -25z m53 -4 c0 -2 -9 0 -20 6 -11
6 -20 13 -20 16 0 2 9 0 20 -6 11 -6 20 -13 20 -16z m1797 -156 c-2 -29 -3 -6
-3 52 0 58 1 81 3 53 2 -29 2 -77 0 -105z m-17 137 c0 -2 -10 -9 -22 -15 -22
-11 -22 -10 -4 4 21 17 26 19 26 11z m-67 -52 c-7 -2 -21 -2 -30 0 -10 3 -4 5
12 5 17 0 24 -2 18 -5z m-86 -9 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17
-2 13 -5z m-702 -35 c72 -20 145 -90 114 -110 -17 -10 -336 -11 -363 0 -16 6
-13 12 25 52 62 64 135 82 224 58z m-620 -29 c3 -6 -1 -7 -9 -4 -18 7 -21 14
-7 14 6 0 13 -4 16 -10z m249 -35 c48 -8 91 -17 94 -20 4 -3 -7 -16 -22 -29
-25 -19 -27 -25 -17 -43 6 -12 11 -36 11 -54 l0 -32 -63 62 c-35 34 -85 77
-111 96 -66 47 -67 49 -21 40 22 -4 80 -13 129 -20z m-617 -122 c-2 -27 -3 -5
-3 47 0 52 1 74 3 48 2 -27 2 -69 0 -95z m1342 114 c-68 -54 -109 -92 -138
-131 -19 -25 -38 -46 -41 -46 -8 0 3 76 14 102 5 12 0 22 -18 33 -14 10 -26
21 -26 25 0 7 128 26 195 28 25 1 28 -1 14 -11z m21 -21 c0 -2 -8 -10 -17 -17
-16 -13 -17 -12 -4 4 13 16 21 21 21 13z m-210 -47 c0 -13 -68 -19 -230 -19
-162 0 -230 6 -230 19 0 3 104 6 230 6 127 0 230 -3 230 -6z m-595 -19 c10
-11 16 -20 13 -20 -3 0 -13 9 -23 20 -10 11 -16 20 -13 20 3 0 13 -9 23 -20z
m745 17 c0 -2 -15 -16 -32 -33 l-33 -29 29 33 c28 30 36 37 36 29z m-164 -86
c-11 -81 -85 -161 -163 -177 -30 -6 -31 -5 -35 35 -3 35 0 44 19 57 13 8 23
24 23 36 0 28 -28 58 -53 58 -50 0 -76 -68 -37 -92 15 -10 20 -24 20 -55 0
-47 -6 -50 -61 -31 -76 25 -131 92 -144 174 l-7 41 222 -1 222 0 -6 -45z
m-501 -1 c10 -11 16 -20 13 -20 -3 0 -13 9 -23 20 -10 11 -16 20 -13 20 3 0
13 -9 23 -20z m585 -4 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21
21 13z m627 -129 c-2 -23 -3 -1 -3 48 0 50 1 68 3 42 2 -26 2 -67 0 -90z
m-1146 56 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m449 -23
c-6 -11 -13 -20 -16 -20 -2 0 0 9 6 20 6 11 13 20 16 20 2 0 0 -9 -6 -20z
m-1143 -52 c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2 -19 0 -25z m104 15 c13
-16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m673 -55 c22 -39 11
-29 -29 27 -17 23 -21 33 -9 23 10 -9 28 -32 38 -50z m896 -13 c-41 -41 -77
-75 -79 -75 -3 0 28 34 69 75 41 41 77 75 79 75 3 0 -28 -34 -69 -75z m120 72
c0 -2 -10 -12 -22 -23 l-23 -19 19 23 c18 21 26 27 26 19z m-739 -63 c-10 -21
-27 -67 -36 -101 l-18 -63 -59 0 c-47 0 -60 3 -64 18 -3 9 -18 45 -35 80 -35
75 -36 87 -8 72 36 -20 133 -13 186 12 26 13 49 23 50 23 2 -1 -6 -19 -16 -41z
m47 21 c-6 -14 -13 -23 -15 -21 -5 5 15 46 22 46 3 0 -1 -11 -7 -25z m-997
-12 c13 -16 12 -17 -3 -4 -17 13 -22 21 -14 21 2 0 10 -8 17 -17z m26 -35 c-3
-8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m113 -15 c0 -7 -39 17 -46
28 -3 6 5 3 20 -6 14 -10 26 -19 26 -22z m1587 -10 c-3 -10 -5 -4 -5 12 0 17
2 24 5 18 2 -7 2 -21 0 -30z m-1631 2 c14 -9 25 -34 33 -72 33 -171 164 -326
344 -407 121 -55 187 -69 327 -68 299 1 542 103 649 271 35 54 47 88 61 170 7
40 18 63 42 88 17 18 36 33 41 33 6 0 7 -30 3 -75 -26 -284 -204 -474 -516
-550 -91 -22 -317 -31 -418 -16 -202 30 -382 127 -484 262 -71 94 -107 188
-123 322 -7 62 1 71 41 42z m-189 -62 c-3 -10 -5 -2 -5 17 0 19 2 27 5 18 2
-10 2 -26 0 -35z m120 -5 c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2 -19 0 -25z
m155 13 c35 -21 220 -49 456 -71 272 -25 636 -9 800 34 l52 14 0 -29 c0 -49
-50 -157 -96 -208 -182 -203 -633 -277 -910 -150 -61 28 -159 97 -200 141 -63
66 -120 174 -138 261 -8 32 -6 32 36 8z m1535 -33 c-3 -7 -5 -2 -5 12 0 14 2
19 5 13 2 -7 2 -19 0 -25z m-973 -3 c4 -10 -1 -15 -15 -15 -17 0 -18 2 -7 15
16 18 15 18 22 0z m603 9 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13
-5z m-720 -10 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m310 -16
c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m340 16 c-3 -3 -12 -4
-19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m350 -26 c-3 -7 -5 -2 -5 12 0 14 2
19 5 13 2 -7 2 -19 0 -25z m-434 15 c-7 -2 -19 -2 -25 0 -7 3 -2 5 12 5 14 0
19 -2 13 -5z m514 -65 c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2 -19 0 -25z
m-10 -60 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m-1770 -20 c-3
-8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m1760 -40 c-3 -7 -5 -2 -5
12 0 14 2 19 5 13 2 -7 2 -19 0 -25z m-1546 -75 c13 -16 12 -17 -3 -4 -10 7
-18 15 -18 17 0 8 8 3 21 -13z m1379 -17 c0 -2 -8 -10 -17 -17 -16 -13 -17
-12 -4 4 13 16 21 21 21 13z m-1349 -23 c13 -16 12 -17 -3 -4 -17 13 -22 21
-14 21 2 0 10 -8 17 -17z m1309 -26 c0 -2 -15 -16 -32 -33 l-33 -29 29 33 c28
30 36 37 36 29z m177 -19 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z
m-30 -140 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m-20 -90 c-3
-8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m-827 2 c0 -5 -4 -10 -10
-10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10 -10z m98 5 c-10 -10 -89
-15 -83 -5 3 5 25 10 47 10 23 0 39 -2 36 -5z m712 -125 c0 -11 -4 -20 -9 -20
-5 0 -7 9 -4 20 3 11 7 20 9 20 2 0 4 -9 4 -20z m-1588 -30 c71 -41 159 -53
393 -53 166 0 240 4 300 16 44 10 83 17 88 17 4 0 7 -39 7 -88 0 -91 -8 -115
-55 -154 -122 -104 -501 -135 -785 -66 -184 45 -246 107 -200 203 26 54 86
103 154 127 64 22 58 22 98 -2z m1715 -36 c56 -32 93 -95 93 -157 0 -119 -149
-179 -450 -180 -277 -1 -500 72 -540 178 -6 15 -10 60 -10 102 l0 76 33 -8
c17 -4 50 -11 72 -16 22 -5 121 -12 220 -15 203 -7 357 5 432 35 56 22 91 19
150 -15z m-404 9 c-7 -2 -19 -2 -25 0 -7 3 -2 5 12 5 14 0 19 -2 13 -5z"/>
<path d="M1525 3371 c3 -5 22 -15 43 -22 51 -16 298 -119 405 -168 49 -23 93
-41 98 -41 48 0 -109 77 -378 186 -127 51 -181 66 -168 45z"/>
<path d="M3390 3320 c-30 -10 -162 -51 -292 -91 -138 -42 -238 -77 -238 -84 0
-8 69 9 193 47 105 33 243 76 305 95 61 19 112 39 112 44 0 13 -16 10 -80 -11z"/>
<path d="M1420 3060 c0 -5 6 -10 13 -10 22 0 319 -30 462 -46 77 -8 148 -16
157 -17 9 -1 18 3 20 8 4 12 -99 26 -392 54 -246 24 -260 25 -260 11z"/>
<path d="M1440 2591 c0 -5 7 -15 17 -22 15 -13 15 -12 4 9 -12 23 -21 28 -21
13z"/>
<path d="M3580 1300 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
</g>
</svg>


'국비지원 Spring프레임워크 > HTML' 카테고리의 다른 글

input 태그  (0) 2020.11.04
레이아웃 FLEX  (0) 2020.11.03
div로 컨텐츠 위치 조정하기  (0) 2020.11.03
Form 태그  (0) 2020.11.03
테이블 만들기 실습  (0) 2020.11.03

Form 태그란? 사용자가 입력한 데이터를 한번에 전송하게 해주는 태그.

그런데 점점 사용을 안하는 추세라고 한다.


input type 실습을 해봤다.


데이터 전송 태그










소스 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html>
    <body>
        <h1>데이터 전송 태그</h1>
        <hr>
        <form action="https://www.naver.com">
            <input type="text" name="username" placeholder="유저네임을입력" required/><br/>
            <input type="password" name="password" placeholder="password를입력" required/><br/>
            <input type="email" name="email" placeholder="이메일을입력" required/><br/>
            <input type="date" name="date" id=""><br/>
            <input type="checkbox" name="checkbox"><br/>
            <input type="text" name="address" placeholder="주소를입력하세요" readonly><br/>
            <button>회원가입</button>
        </form>
    </body>
</html>
cs


'국비지원 Spring프레임워크 > HTML' 카테고리의 다른 글

input 태그  (0) 2020.11.04
레이아웃 FLEX  (0) 2020.11.03
div로 컨텐츠 위치 조정하기  (0) 2020.11.03
SVG 이미지  (0) 2020.11.03
테이블 만들기 실습  (0) 2020.11.03

만들어야 할 테이블




소스 코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<table border="1">
                <tr>
                    <td><b>방 이름</b></td>
                    <td><b>대상</b></td>
                    <td><b>크기</b></td>
                    <td><b>가격</b></td>
                </tr>
                <tr>
                    <td><b>유채방</b></td>
                    <td>여성 도미토리</td>
                    <td rowspan="3">4인실</td>
                    <td rowspan="4">1인 20,000원</td>
                </tr>
                <tr>
                    <td rowspan="2"><b>동백방</b></td>
                    <td>동성 도미토리</td>
                </tr>
                <tr>
                    <td>가족 1팀</td>
                </tr>
                <tr>
                    <td><b>천혜향방</b></td>
                    <td>-</td>
                    <td>2인실</td>
                </tr>
                <tr>
                    <td colspan="4"><b>바깥채 전체를 렌트합니다</b></td>
                </tr>
            
            </table>
cs



'국비지원 Spring프레임워크 > HTML' 카테고리의 다른 글

input 태그  (0) 2020.11.04
레이아웃 FLEX  (0) 2020.11.03
div로 컨텐츠 위치 조정하기  (0) 2020.11.03
SVG 이미지  (0) 2020.11.03
Form 태그  (0) 2020.11.03

+ Recent posts