Cloud 기반 웹 DevOps 프로젝트 개발자 과정

문이빈·2023년 7월 7일
0

전 시간 아이디 중복체크 부분 수정

member1.js

/**
 * member1의 자바스크립트
 */
// 전역변수
chk=false;

// id와 이름이 비어있지 않게 확인하는 메소드로 사용할거임
function validate1(){
		if(!c.value==1){
		alert("아이디 중복입니다.")
		return false;
	}
	else if (c.value ==0){
		chk = true;
	}
	if(!chk){
		alert("아이디 중복체크 하시오")
		return false;
	}
	// 아이디 중복 체크 하고 전송
	var formTag = document.querySelector("#regData");
	var inputTag = document.querySelectorAll("input");
	
	for(let i=0; i<inputTag.length; i++){
		if(inputTag[i].value.length==0){
			alert("아이디와 이름을 확인하여 입력하시오");
			return false;
		}
	}
	formTag.submit();
}
function idCheck(){
	var id = document.getElementById("id");
	if(id.value.trim().length==0){
		alert("id 입력하세요");
		id.focus();
		chk = false;
		return false
		}else{
			//팝업으로 아이디 체크를 불러주고 결과를 받기
		   window.open("DbIdchek.jsp?id="+id.value,
			           "popup", "width=500,height=200");
			      return;
		}
}

DbIdchek.jsp

<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.PreparedStatement"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn=
DriverManager.getConnection("jdbc:mysql://localhost:3306/boarddb","root","1234");
PreparedStatement pstmt = null;
ResultSet rs = null;
if(conn!=null){
	String uid = request.getParameter("id");
	String sql = "select count(id) as cnt from member where id = ?";
	pstmt = conn.prepareStatement(sql);
	pstmt.setString(1,uid);
	rs = pstmt.executeQuery();
	if(rs.next()){
		if(rs.getInt("cnt")!=0) request.setAttribute("cnt", 1);
		else request.setAttribute("cnt", 0);
	}
	}else{
		out.println("연결실패");
}
if(rs != null) rs.close();
if(pstmt != null) pstmt.close();
if(conn != null) conn.close();
%>
<input type="text" value="" id="pid" readonly="readonly"/>
<input type="button" value="중복체크" onclick="javascript:window.close();"/>
<script type="text/javascript">
//오프너의 id를 받아서 저장 팝업에 저장
document.getElementById("pid").value = opener.document.getElementById("id").value
function check(){
	 var c=<%=request.getAttribute("cnt")%>
	     if(c==1){
	    	 alert("중복된 아이디 입니다.")
	    	 // 
	     }else if(c==0){
	    	 alert("사용가능한 아이디 입니다.")
	     }
	     opener.document.getElementById("cnt").value=c;
	     window.close();
	     }
</script>

웹 프로그래밍

response 내장 객체

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Implicit Objects</title>
</head>
<body>
  <% response.sendRedirect("http://www.google.com"); %>
</body>
</html>

사이트 불러옴


로그인

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>reponse01</title>
</head>
<body>
  <form action="response01_process.jsp" method="post">
    <p>아 이 디 : <input type="text" name="id">
    <p>비밀번호 : <input type="text" name="passwd">
    <p><input type="submit" value="전송">
  </form>
</body>
</html>
  • response01_process.jsp
<body>
  <%
    request.setCharacterEncoding("utf-8");
    String userid = request.getParameter("id");
    String password = request.getParameter("passwd");
    
    if(userid.equals("관리자")&&password.equals("1234")){
    	response.sendRedirect("response01_success.jsp");
    }else{
    	response.sendRedirect("response01_failed.jsp");
    }
  %>
</body>

  • response01_success.jsp
<body>
  로그인을 성공했습니다!!
</body>

  • response01_failed.jsp
<body>
  <p>로그인을 실패했습니다.
  <p><a href="./response01.jsp">로그인 가기</a>
</body>


응답 HTTP 헤더 관련 메소드

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>response_Header</title>
</head>
<body>
  <%
    response.setHeader("Cache-control", "use_cache");
    response.addHeader("contentType", "text/html; charset=utf-8");
    response.setDateHeader("date", 1L);
  %>
  Cache-control : <%= response.getHeader("Cache-control") %><br>
  contentType : <%= response.getHeader("contentType") %><br>
  date : <%= response.getHeader("date") %><br>
</body>
</html>


새로고침

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>response02</title>
</head>
<body>
  <p>이 페이지는 2초마다 새로고침 됩니다.
    <%
      response.setIntHeader("Refresh", 2);
    %>
  
  <p> <%= (new java.util.Date()) %>
</body>
</html>

<% response.setIntHeader("Refresh", 2); %> 2초마다 새로고침


response 실습

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>response 실습</title>
</head>
<body>
  <%
    response.setCharacterEncoding("utf-8");
    response.setContentType("text/html; charset=utf-8");
  %>
    <p>문자 인코딩 " <%= response.getCharacterEncoding() %>"
    <p>콘텐츠 유형 " <%= response.setContentType() %>"
</body>
</html>


에러 페이지 보내기

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>response03</title>
</head>
<body>
  <%
    response.sendError(404, "요청 페이지를 찾을 수 없습니다.");
  %>
</body>
</html>


out 내장 객체의 기능과 사용법

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>out01</title>
</head>
<body>
  <%
    out.println("Hello"+"<br>");
    out.println("Java Server Pages 입니다.");
  %>
</body>
</html>


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>out01</title>
</head>
<body>
  <%
    out.println("오늘의 날짜 및 시각"+"<br>");
    out.println(java.util.Calendar.getInstance().getTime());
  %>
</body>
</html>


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>out02</title>
</head>
<body>
  <form action="out02_process.jsp" method="post">
    <p> 아 이 디 : <input type="text" name="id">
    <p> 비밀번호 : <input type="text" name="passwd">
    <p><input type="submit" value="전송">
  </form>
</body>
</html>

  • out02_process.jsp
<body>
  <%
    request.setCharacterEncoding("utf-8");
    String userid = request.getParameter("id");
    String password = request.getParameter("passwd");
  %>
  <p> 아 이 디 : <% out.println(userid); %>
  <p> 비밀번호 : <% out.println(password); %>
</body>


유효성 검사(validation)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>validate01</title>
  <script type="text/javascript">
    function checkForm(){
    	alert("이름은 "+document.frm.name.value+"입니다.");
    }
  </script>
</head>
<body>
  <form name="frm">
    <p> 이름 : <input type="text" name="name">
      <input type="submit" value="전송" onclick="checkForm()">
  </form>
</body>
</html>


java

TreeMap을 이용한 요소 삽•••

TreeMap을 이용한 요소 삽입•삭제•수정•검색•출력 예시

package ex12;

import java.util.Iterator;
import java.util.TreeMap;

public class Example07 {

	public static void main(String[] args) {
		TreeMap<Integer, String> cats = new TreeMap<Integer, String>();
		
		cats.put(7, "페르시안");
		cats.put(3, "러시안블루");
		System.out.println(cats);
		
		cats.put(5, "샴");
		System.out.println(cats);
		
		cats.replace(3, "래그돌");
		System.out.println(cats);
		
		cats.remove(5);
		System.out.println(cats);
		
		System.out.println(cats.size());
		System.out.println(cats.get(7));
		
		System.out.print("(key, Value) = ");
		Iterator<Integer> keys =cats.keySet().iterator();
		
		while(keys.hasNext()) {
			int key =keys.next();
			System.out.print("("+key+", "+cats.get(key)+")");
		}
	}
}


package ex12;

import java.util.Map.Entry;
import java.util.TreeMap;

public class Collection07 {

	public static void main(String[] args) {
		TreeMap<Integer, String> str = new TreeMap<Integer, String>();
		
		str.put(1, "A");
		str.put(2, "B");
		str.put(3, "C");
		
		System.out.println(str);
		
		System.out.print("Keys : ");
		for(Integer key : str.keySet()) {
			System.out.print(key);
			System.out.print(", ");
		}
		
		System.out.println();
		System.out.print("Values : ");
		for(String value : str.values()) {
			System.out.print(value);
			System.out.print(", ");
		}
		
		System.out.println();
		System.out.print("Keys=Values : ");
		for(Entry<Integer, String> entry : str.entrySet()) {
			System.out.print(entry);
			System.out.print(", ");
		}
	}
}


컬렉션

람다 함수(구경하고 가)

  • ComparableDemo
package sec01.lamda;

import java.util.Arrays;

public class ComparableDemo {

	public static void main(String[] args) {
		Rectangle[] rectangles = {new Rectangle(3,5),
				                  new Rectangle(2,10), 
				                  new Rectangle(5,5)
				                  };
		
		// Arrays sort는 Comparable을 통해서 비교한다.
		// Rectangle에는 Comparable을 구현하고 compareTo메소드를 구현해야 한다.
		Arrays.sort(rectangles);
		
		for(Rectangle r : rectangles)
			System.out.println(r);
		}
	}
  • Rectangle
package sec01.lamda;

class Rectangle implements Comparable<Rectangle> { // Rectangle 이라는 객체를 사용할
	                                               // Comparable을 구현해라
	// Rectangle은 Comparable의 구현체
	private int width, height;                     
	public Rectangle(int width, int height) {
		this.width = width;
		this.height = height;
	}
	public int findArea() {
		return width*height;
	}
	public String toString() {
		/* String.format("사각형[폭=%d, 높이=%d]", width, height)
		   format 형식을 주는 메소드이고 %d는 숫자형과 짝을 맞출때 사용
		     사각형[폭=width, 높이=height] 출력할 때 사용하는 방법
		 */
		return String.format("사각형[폭=%d, 높이=%d]", width, height);
	}
	public int compareTo(Rectangle o) {
		return findArea() - o.findArea();
	}
}


package sec01.lamda;

import java.util.Arrays;

public class Lambda1Dome {

	public static void main(String[] args) {
		String[] strings = {"로마에 가면 로마법을 따르라.", "시간은 금이다.", "펜은 칼보다 강하다."};     
        
		Arrays.sort(strings, (first, second) -> first.length() - second.length()); 
        
        // Arrays.sort(객체형 배열, 비교해서 결과를 내기위한 함수)
		/*(first, second) -> first.length() - second.length()
		  아래와 같이 바꿀 수 있다.
		  int campareA((first, second){
		     return first.length() - second.length()
		  }
		  first.length()보다 second.length()가 길이가 더 길어서 음수가 나옴
		  => 그래서 위에서 부터 길이가 짧은 글부터 출력된다. 
		*/
		
		for(String s : strings)
			System.out.println(s);
	}
}


package sec01.lamda;

interface Negative{
	int neg(int x);
}
interface Printable{
	void print();
}

public class Lambda2Demo {

	public static void main(String[] args) {
		// 인터페이스로 선언, 구현할 메소드가 단일이므로 가능
		Negative n;
		
		// neg구현
		n = (int x) -> {return - x; };
		
		// neg구현 이미 인터페이스에서 int형이라고 선언되어 있으므로 구현체도 자동 int형으로 컴파이러가 인지
		n = (x) -> {return - x; }; 
		
		// 어차피 타입을 알고 있는 x는 ()가 필요 없어서 생략
		n =  x -> {return - x; };
		
		// return 생략하고 {} 생략
		n = (int x) -> -x;
		n = (x) -> -x;
		n =  x -> -x;
        System.out.println(n.neg(5));
		
		Printable p;
		
		// 이름없는 구현체가 만들어짐 1
		p = () -> { System.out.println("안녕!");};
		
		// 이름없는 구현체가 만들어짐 2
		p = () -> System.out.println("안녕!");
		p.print();
		}
	}


package sec01.lamda;

interface Mathematical{
	double calculate(double d);
}
interface Pickable{
	char pick(String s, int i);
}
interface Computable{
	int compute(int x, int y);
}
class Utils{
	int add(int a, int b){
		return a + b;
	}
}
public class MethodRefDemo {

	public static void main(String[] args) {
		Mathematical m;
		Pickable p;
		Computable c;
		
		/* 정식이면 이렇게 작성했을 것이다.
		 class AAA implements Mathematical{
		 @Override
		 public double calculate(double d){
		   return Math.abs(d);
		   }
		 }
		 ------------------------------------------
		 익명 클래스
		 new Mathematical{
		      @Override
		      public double calculate(double d){
		           return Math.abs(d);
		   }
		 }
		*/
		//Mathematical m = (double d) -> {return Math.abs(d);};
		// m = (double d) -> {return Math.abs(d);}; 랑 같음
//		  m = d -> Math.abs(d);
		m = Math::abs; // 람다식의 축양형 정적 메소드 사용
		System.out.println(m.calculate(-50.3));
		
//		  p = (a,b) -> utils.add(a,b); 이렇게 생긴 애를 아래와 같이 변환함.
		p = String::charAt;  // 선언되어 있는 걸 모른다면 사용하기 어렵겠지만 람다식의 축양형 정적 메소드 사용
		System.out.println(p.pick("안녕, 인스턴스 메소드 참조!", 4));
		
		Utils utils = new Utils(); // 인스턴스 생성하고
//	      c = (a,b) -> utils.add(a,b); // 인스턴스의 메소드를 람다식으로 호출
		c = utils::add; //  람다식의 축약형인데 인스턴스 메소드 사용
		System.out.println(c.compute(20, 30));
	}
}


package sec01.lamda;

class Utils{
	int add(int a, int b) {
		return a + b ;
	}
}
interface Applyable{
	boolean apply(Box a, Box b);
}
class Box{
	int no;
	public Box(int no) {
		this.no = no;
	}
	boolean isSame(Box b) {
		return this.no == b.no;
	}
}
public class MethodRefDemo1 {

	public static void main(String[] args) {
		Applyable app;
		// app = (a,b) -> a.isSame(b);
		app = Box::isSame;
		System.out.println(app.apply(new Box(1), new Box(2)));
		System.out.println(app.apply(new Box(1), new Box(1)));
	}
}


package sec01.lamda;

interface NewObject<T>{
	T getObject(T o);
}
interface NewArray<T>{
	T[] getArray(int size);
}

public class ConstructorRefDemo {

	public static void main(String[] args) {
		NewObject<String> s;
		NewArray<Integer> i;
//		  s = x -> new String(x);
		s = String::new; // 축약형으로 구현함.
		
		String str = s.getObject("사과");
//		  i = x -> new Integer[x];
		i = Integer[]::new;
		Integer[] array = i.getArray(2);
		array[0] = 10;
		array[1] = 20;
		
		System.out.println("str==> " + str);
		System.out.println("str==> " + i);
	}
}


jQuery

글자 조작

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>GetTexthtml</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
    <script type="text/javascript">
      $(document).ready(function(){
    	  // text() 메소드와 html() 메소드의 리턴 값을 출력합니다.
    	  alert($('p').text());
    	  alert($('p').html());
      });
    </script> 
</head>
<body>
  <p>TestA</p>
  <p>TestB</p>
  <p>TestC</p>
</body>
</html>



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>GetTexthtml</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
    <script>
      $().ready(function(){
    	  $('.text-1').text("<h1>text()메소드</h1>");
    	  $('.text-2').html("<h1>html()메소드</h1>");
      });
    </script> 
</head>
<body>
  <p class="text-1">TestA</p>
  <p class="text-1">TestA</p>
  <p class="text-2">TestB</p>
  <p class="text-2">TestB</p>
</body>
</html>


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>스타일시트 변경</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
  <script type="text/javascript">
    $().ready(function(){
    //0부터 255까지 반복문을 돌리고	
      for (var i=0; i<256; i++){
    	  //div 하나 만들어주고 그것을 body에 추가하고 거기에 스타일을 주는데 rgb를 i값으로 준다
    	  $('<div></div>').css({
    		  height: 2,
    		  background: "rgb("+i+", "+i+","+i+")"
    	  }).appendTo('body');
      }
    });
  </script>
</head>
<body>

</body>
</html>


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>속성변경</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
    <script type="text/javascript">
      $(document).ready(function(){
          // img 태그에
          $('img').each(function(index, element){
        	  // src 속성을 조작합니다.
        	  $(this).attr('src', 'http://placehold.it/' + (index + 1) * 100 + 'x100');
          });
      });
    </script>
</head>
<body>
  <img />
  <img />
  <img />
</body>
</html>


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>속성 병경 연습2</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
    <script type="text/javascript">
      $(document).ready(function(){
          $('<h1></h1>')
            .text('안녕하세요')
            .attr('data-test','test')
            .css({
            	    backgroundColor: '#781D78',
            	    color: 'white'
            	  }).appendTo('body');
            });
    </script>
</head>
<body>

</body>
</html>


이벤트 메소드

jquery로 이벤트를 직접 연결할 때는 on()메소드를 사용한다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>이벤트 연결</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
    <script type="text/javascript">
      $().ready(function(){
    	  // h1 태그에 click 이벤트를 연결합니다.
    	  $('h1').on('click', function(event){
    		  // 이벤트를 발생시킨 문서 객체의 문자를 추출합니다.
    		  var text = $(this).text();
    		  // 출력합니다.
    		  alert(text);
    	  });
      });
    </script>
</head>
<body>
  <h1>Header_1</h1>
  <h1>Header_2</h1>
</body>
</html>

Header_1 or Header_2 클릭하면 alert 발생


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>이벤트 연결</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
    <script type="text/javascript">
      $().ready(function(){
    	  // h1 태그에 click 이벤트를 연결합니다.
    	  $('h1').on('click',function(event){
    		  $('<h1></h1>').text($(this).text()).appendTo('body');
    	  });
      });
    </script>
</head>
<body>
  <h1>Header</h1>
</body>
</html>


클릭 할 때마다 한개 씩 늘어난다.


이벤트 간접 연결

이벤트를 바디에 있는 h1에 위임

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>이벤트 간접 연결</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
    <script type="text/javascript">
      $().ready(function(){
    	  // body 태그에 h1 태그의 click 이벤트를 위임합니다.(body에 있는 h1을 클릭하면)
    	  $('body').on('click','h1',function(event){
    		  // h1 태그를 생성해서 body 태그에 추가해라
    		  $('<h1></h1>').text($(this).text()).appendTo('body');
    	  });
      });
    </script>
</head>
<body>
  <h1>Header</h1>
</body>
</html>


클릭 할 때마다 한개 씩 늘어난다.


이벤트 제거

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>이벤트 지우기</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
    <script type="text/javascript">
      $().ready(function(){
    	  const handler = function(event){
    		  // h1 태그를 생성해서 body에 추가
    		  $('<h1></h1>')
    		  .text($(this).text())
    		  .click(handler)
    		  .appendTo('body');
    		  // 현재 태그의 이벤트 제거
    		  $(this).off
    		  
    		  // h1 태그를 클릭하면 handler호출
    		  $().on('click', handler);
    	  }
      });
    </script>
</head>
<body>
  <h1>Header</h1>
</body>
</html>



클릭 할 때마다 한개 씩 늘어난다.
단. 한번 누른 것은 이벤트가 사라지고 새로 나타난 것을 눌러야 이벤트가 실행됨.


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jQuery Animate</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
    <style type="text/css">
      .box{
           /*크기*/
           width: 100px;
           height: 100px;
           /*색상*/
           background-color: blue;
           /*위치*/
           position: absolute;
           left: 10px;
           top: 10px;
           }
    </style>
  <script type="text/javascript">
    $().ready(function(){
    	// .box를 클릭하면~
    	$('.box').click(function(){
    		// 1초동안 오른쪽으로 1000픽셀로 이동시키기(그래서 왼쪽에 간격을 넓힘) 
    		$(this).animate({left:800},1000);
    	});
    });
  </script>
</head>
<body>
  <div class="box"></div>
</body>
</html>



클릭하면 오른쪽으로 800만큼 떨어진 거리를 1000밀리초 (1초) 동안 움직임

0개의 댓글