myCar 변수가 Car 객체를 참조하게 되면 도트(.) 연산자를 사용해서 speed 필드에 접근 가능
도트(.)연산자는 객체 접근 연산자로 객체가 가지고 있는 필드나 메소드를 사용하고자 할 때 사용
밑에 코드는 Car 객체의 speed 필드값을 60으로 변경
myCar.speed = 60;
Car 클래스 필드 선언
//필드 ( 속성 )
//this 생성자의 오버로딩
String comany = "현대자동차";
String model = "그랜저";
String color = "검정";
int maxSpeed = 350;
int speed;
외부 클래스에서 Car 필드값 읽기와 변경
//객체 생성
Car myCar = new Car();
//필드값 읽기
System.out.println("제작회사:" + myCar.comany);
System.out.println("모델명:" + myCar.model);
System.out.println("색깔:" + myCar.color);
System.out.println("최고속도:" + myCar.maxSpeed);
System.out.println("현재속도:" + myCar.speed);
//필드값 변경
myCar.speed = 60;
System.out.println("수정된 속도:" + myCar.speed);
생성자
생성자는 new 연산자로 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화를 담당
객체 초기화란 필드를 초기화하거나 메소드를 호출해서 객체를 사용할 준비를 하는 것
생성자를 실행하지 않고는 클래스로부터 객체를 만들 수 없음
new연산자에 의해 생성자가 성공적으로 실행되면 힙 영역에 객체가 생성되고
객체의 번지가 리턴됨, 리턴된 객체의 번지는 클래스 변수에 저장
기본 생성자
모든 클래스는 생성자가 반드시 존재하며, 생성자를 하나 이상 가질 수 있음
클래스 내부에 생성자 선언을 생략했다면 컴파일러는 다음과 같이 중괄호 {} 블록 내용이
비어 있는 기본생성자를 바이트 코드에 자동 추가 ( 생략 가능 하다는 말 )
[public] 클래스() {}
그러나 클래스에 명시적으로 선언한 생서자가 1개라도 있으면 컴파일러는 기본 생성자를 추가하지 않음
명시적으로 생성자를 선언하는 이유는 객체를 다양한 값으로 초기화하기 위해서
생성자 선언
명시적으로 선언하려면 아래 이미지 형태로 작성
생성자는 메소드와 비슷한 모양을 가지고 있으나, 리턴 타입이 없고 클래스 이름과 동일
일반적으로 필드에 초기값을 저장하거나 메서드를 호출하여 객체 사용 전에 필요한 준비를 함
매개 변수 선언은 생략할 수도 있고 여러 개를 선언해도 좋음
매개 변수는 new 연산자로 생성자를 호출할 때 외부의 값을 생성자 블록 내부로 전달하는 역할을 함
Car myCar = new Car("그랜저", "검정", 300);
// Car 생성자를 호출할 때 3개의 매개값 제공
// 2개의 매개값은 String타입, 마지막 매개값은 int 타입
Car myCar = new Car(); <- 기본생성자를 호출할 수 없음
생성자를 호출해서 객체 생성할때는 그 밑에 기본생성자를 호출할 수 없음
public class Car {
//생성자
Car(String model, String color, int maxSpeed)
}
클래스에 생성자가 명시적으로 선언되어 있을 경우에는 반드시 선언된 생성자를
호출해서 객체를 생성
필드 초기화
클래스로부터 객체가 생성될 때 필드는 기본 초기값으로 자동 설정
다른 값으로 초기화 방법은 두가지가 있음
1. 필드를 선언할 때 초기값을 주는 방법
2. 생성자에서 초기값을 주는 방법
필드를 선언할 때 초기값을 주게 되면 동일한 클래스로부터 생성되는 객체들은 모두 같은 값을 갖게 됨
// 필드
String nation = "대한민국";
String name;
String ssn;
//생성자
Korean k1 = new Korean();
Korean k2 = new Korean();
nation 필드를 "대한민국"으로 초기값
k1, k2 객체를 생성하게 되면 둘 다 nation 필드에는 "대한민국"이 저장 되 있음
package sec02.exam01;
public class Korean {
// 필드
String nation = "대한민국";
String name;
String ssn;
//생성자
public Korean(String n, String s) {
name = n;
ssn = s;
}
}
객체 생성 시점에 외부에서 제공되는 다양한 값들로 초기화되어야 한다면
생성자의 매개값으로 이 값들을 받아 초기화하는 것이 맞음
생성자에서 필드 초기화
package sec02.exam01;
public class Korean {
// 필드
String nation = "대한민국";
String name;
String ssn;
//생성자
public Korean(String n, String s) {
name = n;
ssn = s;
}
}
객체 생성 후 필드값 출력
package sec02.exam01;
public class KoreanExample {
public static void main(String[] args) {
Korean k1 = new Korean("박자바", "011225-1234567");
System.out.println("k1.name :" + k1.name);
System.out.println("k1.ssn :" + k1.ssn);
Korean k2 = new Korean("김자바", "93525-0654321");
System.out.println("k2.name :" + k2.name);
System.out.println("k2.ssn :" + k2.ssn);
}
}
코드의 가독성을 높일라면 초기화시킬 필드 이름과 비슷하거나 동일한 이름을 사용하는 것이 좋음
일반적으로 필드와 동일한 이름을 갖는 매개 변수를 사용
그러나 이 경우 필드와 매개 변수 이름이 동일하기 때문에 생성자 내부에서 해당 필드에 접근 불가
왜냐하면 동일한 이름의 매개 변수가 사용 우선순위가 높기 때문에
해결 방법은 필드 앞에 'this.'를 붙이면 됨, this는 객체 자신의 참조
'this.필드'는 this라는 참조 변수로 필드를 사용하는 것과 동일
생성자 오버로딩
외부에서 제공되는 다양한 데이터들을 이용해서 객체를 초기화하려면 생성자도 다양화될 필요가 있음
생성자 오버로딩이란 매개 변수를 달리하는 생성자를 여러 개 선언하는 것을 의미
매개 변수의 타입, 개수, 순서가 다르게 선언되어야 함
Car 클래스 생성자 오버로딩 예시
Car(){...}
Car(String company){...}
Car(String company, String model){...}
Car(String company, String model, String color){...}
오버로딩 주의할 점은 매개 변수타입과 개수 선언된 순서가 똑같을 경우
매개변수 이름만 바꾸는 것은 생성자 오버로딩이 아님
Car(String company, String model){...}
Car(String model, String company){...} <- 오버로딩 아님
생성자가 오버로딩되어 있을 경우, new 연산자로 생성자를 호출할 때 제공되는 매개값의 타입과
수에 의해 호출될 생성자가 결정 됨
Car car1 = new Car();
Car car2 = new Car("그랜저");
Car car3 = new Car("그랜저", "흰색");
Car car4 = new Car("그랜저", "흰색", 300);
생성자의 오버로딩
생성자의 오버로딩
package sec02.exam01;
public class Car {
String company = "현대자동차";
String model;
String color;
int maxSpeed;
Car(){
} // 1.생성자
Car(String model ){
this.model = model;
} // 2.생성자
Car(String model, String color){
this.model = model;
this.color = color;
}//3. 생성자
Car(String model, String color, int maxSpeed){
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed;
}//4. 생성자
}
}
객체 생성 시 생성자 선택
package sec02.exam01;
public class CarThis {
public static void main(String[] args) {
CarExamole car = new CarExamole(); //1.생성자 선택
System.out.println("car1.company:" + car.company);
System.out.println();
CarExamole car2 = new CarExamole("자가용");//2.생성자 선택
System.out.println("car2.company:" + car2.company);
System.out.println("car2.model" + car2.mode);
System.out.println();
CarExamole car3 = new CarExamole("자가용", "빨강");//3.생성자 선택
System.out.println("car3.company:" + car3.company);
System.out.println("car3.model:" + car3.model);
System.out.println("car3.color:" + car3.color);
System.out.println();
CarExamole car4 = new CarExamole("택시", "검정", 200);//4.생성자 선택
System.out.println("car4.company:" + car4.company);
System.out.println("car4.model:" + car4.model);
System.out.println("car4.color:" + car4.color);
System.out.println("car4.maxSpeed:" + car4.maxSpeed);
}
}
다른 생성자 호출: this()
생성자 오버로딩이 많아질 경우 생성자 간의 중복된 코드가 발생할 수있음
매개 변수의 수만 달리하고 필드 초기화 내용이 비슷한 생성자에서 이러한 현상을 보임
이 경우에는 필드 초기화 내용은 한 생성자에만 집중적으로 작성하고
나머지 생성자는 초기화 내용을 가지고 있는 생성자를 호출하는 방법으로 개선이 가능
생성자에서 다른 생성자를 호출할 때에는 다음과 같이 this() 코드를 사용
this()는 자신의 다른 생성자를 호출하는 코드로 반드시 생성자의 첫 줄에서만 허용
this()의 매개값은 호출되는 생성자의 매개 변수에 맞게 제공해야 함
3개의 생성자 내용이 비슷하므로 앞에 2개의 생성자에서 this()를 사용해서
마지막 생성자를 호출하도록 수정하면 중복 코드를 최소화할 수 있음
밑에는 this() 활용 실습
다른 생성자를 호출해서 중복 코드 줄이기
package sec02.exam01;
public class CarThis2 {
//필드
//다른 생성자 호출:this()
//다른 생성자 호출해서 중복 코드 줄이기
String color;
int cc;
String model;
String company = "현대자동차";
int maxSpeed;
CarThis2(){ // 기본 생성자 생략 가능
}
CarThis2(String model){
this(model, "은색", 250);
}
CarThis2(String model, String color){
this(model, color, 250);
}
CarThis2(String model, String color, int maxSpeed){
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed; // 공통 실행 코드
}
}
객체 생성 시 생성자 선택
package sec02.exam01;
public class CarThis {
public static void main(String[] args) {
CarThis2 car = new CarThis2();
System.out.println("car1.company:" + car.company);
System.out.println();
CarThis2 car2 = new CarThis2("자가용");
System.out.println("car2.company:" + car2.company);
System.out.println("car2.model:" + car2.model);
System.out.println();
CarThis2 car3 = new CarThis2("자가용", "빨강");
System.out.println("car2.company:" + car3.company);
System.out.println("car2.model:" + car3.model);
System.out.println("car2.model:" + car3.color);
System.out.println();
CarThis2 car4 = new CarThis2("택시", "검정", 200);
System.out.println("car2.company:" + car3.company);
System.out.println("car2.model:" + car3.model);
System.out.println("car2.model:" + car3.color);
}
}
실습
Swap
package sec02.exam01;
public class Swap {
public static void main(String[] args) {
int a = 10;
int b = 20;
int result = a;
a = b;
b = result;
// swapData(a, b); call by value이어서 안됨
System.out.printf("a = %d, b = %d\n" , a,b);
}
public static void swapData (int x, int y) {
int result = x;
x = y;
y = result;
}
}
Bubble sort ( 버블 정렬 ) for문, if문 사용
package sec02.exam01;
public class Bubble {
public static void main(String[] args) {
// 정렬 bubble sort
// 정리하자면, 바깥쪽의 for 루프는 배열의 모든 인덱스를 순회하며 안쪽의
// for 루프를 실행하여 인접한 원소를 비교하고 필요한 경우 교환하는 과정을 반복
int a[] = {10, 3, 1, 4, 2};
for(int i=0; i<a.length-1; i++) {// 왼쪽 오른쪽 순서 인덱스 이동 -1은 뒤에 2는 빼고 안쪽 for문이 끝날때 마다 왼쪽에서 오른쪽으로 이동
for (int j=a.length-1; j>i; j--) {// 오른쪽 왼쪽 순서 이동
if(a[j] < a[j-1]) {// 오른쪽 왼쪽 값 비교 후 바꿔줌
int tmp = a[j];
a[j] = a[j-1];
a[j-1] = tmp;
}
System.out.printf("i:%d, j:%d\n", i, j);
}
}
for (int num : a) {
System.out.println(num + ", ");
}
}
}
문제풀이 3번 this() 활용 중복 코드 제거하기
package sec02.exam01;
public class Board {
// 3번 문제 this() 활용 중복 코드 제거
//this() 사용시 마지막 생성자 작성하고 작성하면 될듯
String title;
String content;
String writer;
String dete;
int hitcount;
Board(String title, String content){
this(title, content, "로그인한 회원아이디", "현재 컴퓨터 날짜", 0);
}
Board(String title, String content, String writer ){
this(title, content, writer, "현재 컴퓨터 날짜", 0);
}
Board(String title, String content, String writer, String dete ){
this(title, content, writer, "현재 컴퓨터 날짜", 0);
}
//공통 실행 코드
Board(String title, String content, String writer, String date, int hitcount){
this.title = title;
this.content = content;
this.writer = writer;
this.dete = dete;
this.hitcount = hitcount;
}
}
JSP 배열활용 웹페이지에서 배열에 숫자 입력 후 합계, 최고점수, 평균점수 받아오기 ( static 활용 )
for문의 괄호 ()에는 배열에서 꺼낸 항목을 저장할 변수 선언과 콜론(:) 그리고 배열을 나란히 작성
배열 및 컬렉션 항목의 개수만큼 반복하고, 자동적으로 for문을 빠져나감
package sec03.exam03;
public class ForEx1 {
public static void main(String[] args) {
// 향상된 for문
String[] arr2 = {"가", "나", "다"};
for(String ss : arr2) {// // 배열을 변수에 저장 ( 인덱스는 모름 )
System.out.println(ss);
}
int sum = 0;
int[] arr1 = {1,2,3,4,5};
for(int aa : arr1) {// 배열을 변수에 저장 ( 인덱스는 모름 )
sum += aa;
System.out.println(aa);
}
System.out.println("합계:" + sum);
}
}
열거 타입
열거타입은 한정된 값인 열거 상수 중에서 하나의 상수를 저장하는 타입
이클립스에서 NEW -> Enum으로 생성
package sec03.exam04;
public enum Week {
//열거 타입 Enum2
월요일, 화요일, 수요일, 목요일, 금요일, 토요일, 일요일
}
package sec03.exam04;
public enum Enumreult {
//열거 타입 Enum 1
SUCCESS, FAIL_ID, FAIL_PASSWORD
}
package sec03.exam04;
import java.util.Calendar;
public class EnumEx {
public static void main(String[] args) {
// 열거타입 1
Week today;
today = Week.수요일;
System.out.println(today);
int WEDNEDAY = 4;
System.out.println(WEDNEDAY);
Calendar calendar = Calendar.getInstance();
int week = calendar.get(Calendar.DAY_OF_WEEK);
System.out.println(week);
switch (week) {
case 1:
today = Week.일요일;
break;
case 2:
today = Week.월요일;
break;
case 3:
today = Week.화요일;
break;
case 4:
today = Week.수요일;
break;
case 5:
today = Week.목요일;
break;
case 6:
today = Week.금요일;
break;
case 7:
today = Week.토요일;
break;
}
System.out.println("오늘은: " + today);
if(today == Week.일요일) {
System.out.println("일요일에 쉽니다.");
}else {
System.out.println("자바 공부");
}
}
}
객체 지향 프로그래밍
객체지향 프로그래밍(OOP: Object - Oriented Programming)
객체란 물리적으로 존재하거나 추상적으로 생각할 수 있는 것 중에서 자신의 속성을 가지고
있으면서 식별 가능한 것을 말함
객체의 상호작용
객체들은 각각 독립적으로 존재하고, 다른 객체와 서로 상호작용(메소드)하면서 동작
이때 객체가 다른 객체의 기능을 이용하는 것이 메소드 호출
객체와 클래스
설계도 : 클래스, 클래스로부터 만들어진 객체를 해당 클래스의 인스턴스라고 함
클래스 선언 규칙
1. 하나 이상의 문자
2. 첫 글자에는 숫자가 올 수 없음
3. '$', '_'외의 특수문자는 사용 불가
4. 자바 키워드는 사용 불가
package sec01.exam01;
//설계도 ( 클래스 )
public class Student { // 설계도
String name = "홍길동"; // 멤버 필드
void printName() { // 메서드
System.out.println(name);
}
}
package sec01.exam01;
public class StudEx {
public static void main(String[] args) {
// 인스턴스
Student student = null; // 클래스 변수 선언
System.out.println(student);
student = new Student(); // 객체 생성
System.out.println(student.name); // name 속성(변수)
student.name = "이순신"; // name 속성 변경
System.out.println(student.name);
student.printName(); // 메서드 호출
}
}
실습
배열 문제 풀이
package sec03.exam02;
import java.util.Iterator;
public class ArrayEx001 {
public static void main(String[] args) {
//문제 풀이
// 4번 문제
// int max = 0;
// int [] array = {1,5,3,8,2};
//
// for (int i = 1; i < array.length; i++) {
// if(array[i] > max) {
// max = array[i];
// }
// }
// System.out.println("max:" + max);
//5번 문제
int[][] array = {
{95, 86},
{83, 92, 96},
{78, 83, 93, 87, 88}
};
int sum = 0;
double avg = 0.0;
int cnt = 0;
for(int i = 0; i < array.length; i++) {
for(int k=0; k <array[i].length; k++) {
sum += array[i][k];
cnt++; //0~10 만듬
}
}
avg = sum / (double) cnt;
System.out.println(sum);
System.out.println(avg);
}
}
다차원 배열 생성
package sec03.exam02;
import java.util.function.BiConsumer;
public class ArrayInArray01 {
public static void main(String[] args) {
// 다차원 배열
// int[][] score = {{95,80},
// {92, 96, 100},
// {65}};
int[][] score = new int[3][];
score[0] = new int[2];
score[1] = new int[3];
score[2] = new int[1];
score[0][0] = 95;
score[0][1] = 80;
score[1][0] = 92;
score[1][1] = 96;
score[1][2] = 100;
score[2][0] = 65;
int sum = 0;
for(int i = 0; i < score.length; i++) {
for (int j=0; j <score[i].length; j++) {
for(int k=0; k<score[j].length; k++) {
System.out.println(score[i][j]);
}
}
}
}
}
다차원 배열 가로, 세로 총점
package sec03.exam02;
public class ArrayInArray02 {
public static void main(String[] args) {
// 다차원 배열 가로 세로 총점
int[][] score = new int[3][];
score[0] = new int[4];
score[1] = new int[4];
score[2] = new int[4];
score[0][0] = 100;
score[0][1] = 20;
score[0][2] = 50;
score[0][3] = 80;
score[1][0] = 100;
score[1][1] = 100;
score[1][2] = 80;
score[1][3] = 60;
score[2][0] = 100;
score[2][1] = 95;
score[2][2] = 90;
score[2][3] = 100;
int korTot = 0;
int mathTot = 0;
int engTot = 0;
int useTot = 0;
for(int i = 0; i < score.length; i++) { // 행
int sum = 0; // 초기화 위치에 따라 배열 값 틀려짐
korTot += score[i][0];
mathTot += score[i][1];
engTot += score[i][2];
useTot += score[i][3];
for (int j=0; j <score[i].length; j++) { // 열
int sum2 = 0;
System.out.print(score[i][j]+", ");
sum += score[i][j];
}
System.out.print("총점: " + sum);
System.out.println();
}
System.out.println(korTot +"," + mathTot + ","+ engTot + "," + useTot);
}
}
int[] intArray = {10, 20, 30};
int num = intArray.length;
실습
짝수 구하기
package sec01.exam01;
import java.util.Iterator;
public class BreakContinu {
public static void main(String[] args) {
// 짝수 구하기
for(int i=1; i<=10; i++) {
if (i%2 != 0) {
continue;
}
System.out.println(i);
}
}
}
do-while
package sec01.exam01;
public class DoWhile {
public static void main(String[] args) {
int i = 0;
int j = 1;
while (j < 3) {
System.out.println(j);
j++;
}
do {
System.out.println(i);
i++;
}while (i > 3); // 조건에 안맞아도 1번은 실행
}
}
참조변수 / 참조변수 비교, 문자열 비교
package sec01.exam01;
public class TestEx {
public static void main(String[] args) {
//참조변수
// int[] scores = {10, 20, 30};
// scores[0] = 20;
// System.out.println(scores[0]);
// for( int i = 0; i < 3; i++) {
// if (scores[i] != 10)
// System.out.println(scores[i]);
//
// }
String name1 = "홍길동";
String name2 = "홍길동";
String name3 = new String("홍길동");
String name4 = new String("홍길동");
if (name3 == name4) {// 참조변수 비교
System.out.println("같다");
}else {
System.out.println("다르다");
}
if (name3.equals(name4)) {// 문자열 비교
System.out.println("같다");
}else {
System.out.println("다르다");
}
}
}
배열 타입별
package sec02.exam01;
public class ArrayEx {
public static void main(String[] args) {
// 배열
// int acores[] = {1,2,3,4};
// int[] acores = new int[3];
// for (int i=0; i < 3; i++) {
// System.out.println(acores[i]);
// 0
// 0
// 0
// }
// String[] acores = new String[3];
// for (int i=0; i < 3; i++) {
// System.out.println(acores[i]);
// null
// null
// null
// }
// double[] acores = new double[3];
// for (int i=0; i < 3; i++) {
// System.out.println(acores[i]);
// 0.0
// 0.0
// 0.0
// }
char[] acores = new char[3];
for (int i=0; i < 3; i++) {
System.out.println(acores[i]);
}
}
}
참조형 배열 메서드
package sec02.exam01;
public class ArrayEx03 {
//참조형 배열 메서드
public static void main(String[] args) {
int[] scores = {70, 80, 90, 60};
int sum = method(scores);
for (int i=0; i < scores.length; i++) {
System.out.println(scores[i]);
}
System.out.println("총점:" + sum);
}
public static int method(int[] nums) {
int sum = 0;
for (int i=0; i<nums.length; i++) {
nums[i] += 10;
sum += nums[i];
}
return sum;
}
}
package sec02.exam01;
import java.lang.reflect.Method;
import java.util.jar.Attributes.Name;
public class ArrayExTotall {
public static void main(String[] args) {
int sum = add(3, 5);
}
public static int add(int a, int b) {
int sum = a+b;
System.out.println("두 수의 합은" + sum + "입니다.");
return sum;
}
}
배열 1부터 100까지 합계
package sec02.exam01;
public class ArrayMethodEx {
public static void main(String[] args) {
// aaa(100); // 호출 // c = 100
// int num = bbb(); // int -> double로 바꿀시 double로 출력
// System.out.println("main()" + num);
sum(100);// ccc(100); -> ccc(i <= n)
int num = 100;
// int tot = sum(num);
sum(num);
System.out.println("1부터 "+num+"까지의 합계:");
}
// public static void aaa(int c) { // int = c 매개변수
// System.out.println("aaa()");
// }
// public static int bbb() {
// System.out.println("bbb()");
// return 100; // 14줄 int type만 return 가능
// }
public static void sum(int n) {
int sum = 0;
for (int i=1; i <= n; i++) {
sum += i;
}
System.out.println("1부터 "+n+"까지의 합계:" + sum);
}
}
maing( ) 메소드의 매개 변수 1, 2 번째 데이터 받기
package sec02.exam01;
public class ArreayEx04Main {
public static void main(String[] args) {
//main() 메소드의 매개 변수
if(args.length != 2) {
System.out.println("값의 수가 부족합니다.");
System.exit(0); // 프로그램 강제 종료
}
String strNum1 = args[0];//첫번째 데이터 받기
String strNum2 = args[1];//두번째 데이터 받기
int num1 = Integer.parseInt(strNum1);//문자열을 정수로 변환
int num2 = Integer.parseInt(strNum2);
int result = num1 + num2;
System.out.println(num1 + " + " + num2 +" = " + result);
}
}
JSP 자바스크립트 Login
<%@ 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>
<form action="res.jsp" onsubmit="return checkForWhiteSpace()">
<h1>로그인 하기</h1>
<a> 아이디 : </a><input type="text" name="kor" id="kor" oninput="validateInput()" />
<div></div>
<a> 패스워드 :</a> <input type="password" name="eng" id="eng" />
<input type="submit" value="확인" />
<script>
function checkForWhiteSpace() {
var kor = document.getElementById("kor").value; // "kor" id값
var eng = document.getElementById("eng").value; // "eng" id값
if (kor.trim() == "") {
alert("공백은 입력할 수 없습니다.");
return false;
}
if (eng.trim() == "") {
alert("공백은 입력할 수 없습니다.");
return false;
}
return true;
}
function validateInput() {
var input = document.getElementById("kor").value;
var pattern = /^[a-zA-Z0-9!@#$%^&*()]*$/; // 영문자, 숫자, 특수 기호만 허용하는 정규표현식
if (!pattern.test(input)) {
document.getElementById("kor").value = input;
alert("영문자, 숫자, 특수 기호만 입력해주세요.");
}
}
</script>
</form>
</body>
</html>