반응형
SMALL

Node.js란?

Node.js는 Chrome V8 엔진으로 구동되는 JavaScript 런타임 환경이다.
즉, JavaScript를 브라우저가 아닌 서버에서도 실행할 수 있도록 만든 플랫폼이다.

🚀 쉽게 말해?
원래 JavaScript는 웹 브라우저에서만 실행되던 언어인데,
Node.js 덕분에 서버에서도 실행할 수 있게 됐다!

 

Node.js는 비동기 방식을 기본적으로 사용한다.
즉, 한 가지 작업이 끝날 때까지 기다리지 않고, 다음 작업을 실행한다.

 

Node.js는 기본적으로 단일 스레드(Single-threaded)로 작동하지만,
비동기 작업을 활용해 여러 작업을 동시에 처리할 수 있다.
I/O 작업(파일 읽기, 네트워크 요청 등)은 블로킹 없이 처리된다.

 

Windows, macOS, Linux 등 다양한 운영체제에서 실행 가능

오픈소스로 누구나 자유롭게 사용 가능

 

Node.js는 package.json 파일에 프로젝트의 모든 정보를 기록한다. 각 항목의 의미는 다음과 같다.

name: 프로젝트 이름
version: 프로젝트 버전 정보
description: 프로젝트 설명
main: 노드 어플리케이션일 경우 진입점 경로. 프론트엔드 프로젝트일 경우 사용하지 않는다.
scripts: 프로젝트 명령어를 등록할 수 있다.초기화시 test 명령어가 샘플로 등록되어 있다
author: 프로그램 작성자
license: 라이센스



🚀 1. 자바스크립트의 발전 속도 vs. 브라우저의 지원 속도

자바스크립트는 계속 새로운 기능이 추가되지만, 브라우저가 그 기능을 바로 지원하지 못하는 경우가 많다.
👉 최신 기능을 쓰려면 "징검다리 역할"을 하는 도구가 필요하다.
대표적으로 "Babel(바벨)"이 있는데, 이건 최신 자바스크립트 코드를 옛날 브라우저에서도 실행되도록 변환해 준다.

 


🔧 2. 개발을 더 편하게 해주는 도구들

프론트엔드 개발을 할 때는 여러 가지 도구들이 필요하다.
예를 들어:
✔ Webpack(웹팩): 여러 개의 자바스크립트, CSS, 이미지 같은 파일을 하나의 번들(Bundle)로 묶어주는 도구다.

👉 웹 개발을 하다 보면, 파일이 너무 많아지고 관리하기 힘들어지기 때문!
👉 여러 개의 파일을 하나로 합쳐서 성능을 최적화하면, 웹사이트 로딩 속도가 빨라진다!

🔹 웹팩이 하는 일
- 자바스크립트 파일 묶기 (import 또는 require로 불러온 파일들을 하나로 합침)
- CSS, 이미지 파일도 포함 가능 (예: SCSS, SASS, LESS 변환)
- 코드 압축 & 최적화 (파일 크기를 줄여서 로딩 속도를 빠르게!)
- 실시간 변경 적용 (Hot Reloading) (파일을 수정하면 자동으로 반영됨)

 

 

✔ NPM: 패키지 관리자로, 필요한 라이브러리를 쉽게 설치하고 관리할 수 있도록 도와줌
👉 개발할 때 남들이 만든 유용한 기능을 가져다 쓰면 더 빠르고 효율적으로 작업 가능!
👉 하지만, 일일이 파일을 다운로드하면 업데이트 관리가 어렵고 버전 충돌 위험이 있음.
👉 NPM을 사용하면, 명령어 하나로 패키지 설치 및 업데이트 가능!

 


이런 도구들은 Node.js 기반에서 동작하므로, Node.js가 설치되어 있어야 개발 환경을 만들 수 있다.

 


🎨 3. 고급 언어를 사용하려면 변환 과정이 필요하다

기본적인 HTML, CSS, JavaScript 외에도, 개발자들이 더 편하게 사용할 수 있는 언어들이 있다.

 

✔ TypeScript(타입스크립트): 자바스크립트를 더 체계적으로 작성할 수 있도록 도와줌

👉  마이크로소프트(Microsoft)에서 개발한 자바스크립트(JavaScript)의 상위 집합(Superset) 언어로, 자바스크립트의 기능을 확장하면서 정적 타입 검사(Static Type Checking) 및 객체 지향 프로그래밍(OOP) 기능을 추가한 언어이다.
👉  즉, TypeScript = JavaScript + 타입 시스템 + ES6 이상의 기능들


✔ SASS(사스): CSS를 더 강력하고 효율적으로 작성할 수 있도록 도와주는 CSS 전처리기(Preprocessor)

👉   CSS의 단점을 보완하여 변수, 중첩, 믹스인, 상속 등 프로그래밍적인 기능을 추가할 수 있다.
👉   SASS 파일(.scss 또는 .sass)을 작성한 후, 일반 CSS 파일로 변환해야 한다.

 

더보기

✅ SASS는 CSS를 더 강력하고 효율적으로 사용할 수 있도록 도와주는 도구다.
✅ 변수, 중첩, 믹스인, 상속 등 코드 재사용 기능을 제공하여 유지보수가 쉬워진다.
✅ SASS 파일을 작성한 후, CSS로 변환해야 웹에서 사용할 수 있다.
✅ 웹 개발에서 CSS보다 SASS를 많이 사용하며, 웹팩(Webpack)과 함께 자동 변환하는 것이 일반적

 

✏ SASS 기본 문법


SASS는 두 가지 문법을 제공한다.
1️⃣ .scss (가장 많이 사용됨, 일반 CSS와 비슷한 문법)
2️⃣ .sass (중괄호 {}와 세미콜론 ; 없이 들여쓰기로 구분)

🔹 1. 변수 사용 ($)

// SASS (SCSS 문법)
$main-color: #3498db; // 변수 선언

body {
  background-color: $main-color; // 변수 사용
}

//⬇ CSS 변환 후 ⬇
body {
  background-color: #3498db;
}

✔ 색상, 폰트 크기, 여백 등을 변수로 관리하면 유지보수가 쉬워진다!

 

🔹 2. 중첩(Nesting)

// SASS
.navbar {
  background: #333;
  color: white;
  
  a {
    text-decoration: none;
    color: inherit;

    &:hover {
      color: yellow;
    }
  }
}


//⬇ CSS 변환 후 ⬇
.navbar {
  background: #333;
  color: white;
}

.navbar a {
  text-decoration: none;
  color: inherit;
}

.navbar a:hover {
  color: yellow;
}

✔ 중첩을 사용하면 CSS 계층 구조를 더 직관적으로 표현할 수 있다.

 

 

🔹 3. 믹스인(Mixin) – 코드 재사용

// SASS
@mixin button-style {
  padding: 10px 20px;
  border-radius: 5px;
  background-color: blue;
  color: white;
}

// 믹스인 사용
.button {
  @include button-style;
}


//⬇ CSS 변환 후 ⬇
.button {
  padding: 10px 20px;
  border-radius: 5px;
  background-color: blue;
  color: white;
}

✔ 반복되는 스타일을 함수처럼 만들어서 재사용할 수 있다!

 

🔹 4. 상속(Extend) – 스타일 공유

// SASS
%box-style {
  border: 1px solid #ddd;
  padding: 10px;
  border-radius: 5px;
}

.card {
  @extend %box-style;
  background: white;
}

.alert {
  @extend %box-style;
  background: red;
  color: white;
}


//⬇ CSS 변환 후 ⬇
.card, .alert {
  border: 1px solid #ddd;
  padding: 10px;
  border-radius: 5px;
}

.card {
  background: white;
}

.alert {
  background: red;
  color: white;
}

✔ 공통 스타일을 상속받아 중복을 줄이고 코드 유지보수를 쉽게 할 수 있다.

 

 


하지만!
👉 브라우저는 TypeScript와 SASS를 직접 이해하지 못한다.
👉 그래서 "트랜스파일러"라는 변환 도구를 사용해서 자바스크립트와 CSS로 변환해야 한다.

 

 

대표적인 트랜스파일러 = Babel(바벨)

 

🎯 Babel(바벨)이란?

최신 자바스크립트 코드를 구형 브라우저에서도 실행할 수 있도록 변환해주는 도구(트랜스파일러)다.

 

자바스크립트는 계속 새로운 기능이 추가되지만, 모든 브라우저가 최신 기능을 바로 지원하는 것은 아니다.
✔ 크롬, 파이어폭스 같은 최신 브라우저는 대부분 지원하지만,
✔ 인터넷 익스플로러(IE)나 오래된 브라우저에서는 실행되지 않는 경우가 많다.

👉 Babel을 사용하면 최신 문법을 옛날 브라우저에서도 실행 가능하도록 변환할 수 있다!

👉  React, Vue 같은 최신 프레임워크를 사용할 때 (JSX 같은 문법을 변환하는 데에도 사용됨)

 

Babel이 변환하는 대표적인 문법
1. 화살표 함수 (=>) 변환

// 최신 문법 (ES6+)
const add = (a, b) => a + b;

// ES5 (옛날 브라우저도 실행 가능)
var add = function (a, b) {
    return a + b;
};

 

2. const, let 같은 최신 변수 선언 변환

// 최신 문법 (ES6+)
const name = "Alice";
let age = 25;

// ES5
var name = "Alice";
var age = 25;

 

3. 클래스 문법 변환

// 최신 문법 (ES6+)
class Person {
    constructor(name) {
        this.name = name;
    }
}

// ES5
function Person(name) {
    this.name = name;
}

 

Babel은 단독으로 사용하기도 하지만, 보통 Webpack과 함께 사용하여 자동 변환한다.

 


💡 결론
최신 웹 개발 환경을 만들려면, 단순히 HTML + CSS + JavaScript만 쓰는 게 아니라,
✔ Babel, Webpack 같은 도구를 사용해야 하고
✔ TypeScript, SASS 같은 고급 언어를 변환할 필요도 있으며
✔ 이 모든 걸 관리하려면 Node.js 환경이 필요하다!

즉, Node.js는 최신 프론트엔드 개발의 기반이 되는 필수 도구라고 볼 수 있다!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형
LIST

'[ javascript ]' 카테고리의 다른 글

스프레드 연산자 (...)란?  (0) 2025.02.27
대표적인 es6 문법 정리  (0) 2024.12.30
부동소수점 이슈  (0) 2024.03.29
Node.js & npm 업데이트 하기  (1) 2024.03.22
리액트란?  (0) 2024.03.19
반응형
SMALL

Tomcat만 주구장창 쓰다보니 Jeus는 잘 모름...

Jeus 를 쓰는 고객사를 방문해서 보다보니 구조가 달라 지원에 어려움을 느꼈다.

정확히 한번 정리할 필요성을 느껴 정리해보는 글...


 

Tomcat과 Jeus는 둘 다 웹 애플리케이션 서버(WAS, Web Application Server)이지만, 기능과 역할에서 차이가 있다.
Tomcat은 경량 WAS이고, Jeus는 엔터프라이즈급 WAS이다.

 

📌 1. 기본 개요

  Tomcat Jeus
제작사 Apache Software Foundation TmaxSoft
라이선스 오픈소스 (무료) 상용 소프트웨어 (유료)
주요 용도 가벼운 웹 애플리케이션 실행 (JSP, Servlet) 기업용 WAS, 대규모 시스템 운영
J2EE 지원 여부 부분 지원 (Servlet, JSP만 가능) 완전한 J2EE 지원 (EJB, JMS, JTA 등 포함)

 

 

📌 2. 기술적인 차이

  Tomcat Jeus
설치 경로 /opt/tomcat/ 또는 /home/tomcat/ /home/jeus/
웹 애플리케이션 배포 경로 /webapps/ /domains/{도메인}/applications/
배포 방식 WAR 파일 배포 또는 폴더 배치 WAR 또는 EAR 배포
서버 실행 ./startup.sh ./startServer.sh {도메인} {서버명}
서버 종료 ./shutdown.sh ./stopServer.sh {도메인} {서버명}
관리 콘솔 제공 X (별도 툴 필요) O (jeusadmin CLI, 웹 콘솔 지원)
클러스터링 지원 부분 지원 (추가 설정 필요) O (기본 기능 포함)
멀티 도메인 지원 X (Tomcat 인스턴스를 따로 띄워야 함) O (도메인 기반 다중 서버 운영 가능)
트랜잭션 처리 X (Servlet/JSP 수준) O (JTA, EJB 지원)

 

📌 3. 실행 구조 차이

✔ Tomcat 실행 구조

/home/tomcat/
 ├── bin/           # 실행 파일 (startup.sh, shutdown.sh)
 ├── conf/          # 설정 파일 (server.xml 등)
 ├── logs/          # 로그 파일
 ├── webapps/       # 배포된 웹 애플리케이션 (WAR, JSP, HTML 파일 위치)
 ├── work/          # 실행 중인 애플리케이션 캐시
 ├── temp/          # 임시 파일

 

📌 웹 애플리케이션 배포 방식

  • /webapps/ROOT/에 index.html, index.jsp 등을 배치하면 자동 실행됨
  • 브라우저에서 http://localhost:8080/로 접속 가능

Jeus  실행 구조

/home/jeus/
 ├── bin/            # 실행 파일 (startServer.sh, stopServer.sh 등)
 ├── config/         # 설정 파일
 ├── domains/        # 도메인별 설정 및 애플리케이션 배포
 │   ├── mydomain/
 │   │   ├── applications/  # 웹 애플리케이션 배포 폴더 (WAR, JSP, HTML 파일 위치)
 │   │   ├── servers/       # 실행 중인 서버 관리
 │   │   ├── config/        # 도메인별 설정 파일
 ├── lib/            # 라이브러리
 ├── logs/           # 로그 파일
 ├── deploy/         # 자동 배포 폴더 (WAR, EAR 파일 배치 가능)

 

📌 웹 애플리케이션 배포 방식

  • /domains/{도메인}/applications/ROOT/에 index.html, index.jsp 등을 배치
  • 브라우저에서 http://localhost:8080/로 접속 가능

📌 4. 주요 차이점 정리

  Tomcat  Jeus
속도 가볍고 빠름 상대적으로 무거움
운영 환경 소규모 프로젝트, 개발용 엔터프라이즈 환경, 대기업, 금융권
설치 및 관리 쉽고 간단함 복잡한 설정 필요
보안 기본적인 보안만 제공 기업용 보안 기능 포함
부하 분산 직접 구현 필요 기본적으로 로드 밸런싱 지원
J2EE 표준 지원 Servlet, JSP만 지원 EJB, JMS, JTA 등 전체 지원
가격 무료 유료 (라이선스 비용 필요)

 


📌 5. 언제 Tomcat을 쓰고, 언제 Jeus를 써야 할까?

✔ Tomcat이 적합한 경우
✅ 빠르게 웹 서비스를 개발하고 배포해야 할 때
✅ JSP, Servlet 정도만 사용하고, 트랜잭션, EJB 등의 기능이 필요 없을 때
✅ 비용 절감이 중요한 프로젝트 (오픈소스, 무료 사용 가능)
✅ 단일 서버에서 운영하는 소규모 웹 서비스

 

✔ Jeus가 적합한 경우
✅ 엔터프라이즈 환경에서 안정적으로 운영해야 할 때
✅ 대규모 트랜잭션 처리, 복잡한 비즈니스 로직이 필요한 경우
✅ 보안 및 고가용성이 중요한 금융, 공공기관, 대기업 환경
✅ 여러 대의 서버를 클러스터링해서 운영해야 할 때

 


✅ Tomcat에서 HTML/JS 파일 실행 방식

Tomcat에서는 webapps/ROOT/ 폴더에 HTML/JS 파일을 넣고, startup.sh를 실행하면 브라우저에서 확인할 수 있다.

cd /home/tomcat/bin ./startup.sh

 

📌 파일 저장 위치

/home/tomcat/webapps/ROOT/index.html /home/tomcat/webapps/ROOT/js/script.js

 

📌 브라우저에서 실행 확인

http://localhost:8080/index.html

 

 

✅ Jeus에서 HTML/JS 파일 실행 방식

Jeus에서는 Tomcat과 폴더 구조와 실행 방식이 다르다.
Jeus는 보통 WAR 파일을 배포하는 방식을 사용하지만, 정적 파일을 직접 배포할 수도 있다.

 

2️⃣ HTML/JS 파일 저장 위치

📌 Jeus에서 정적 파일을 직접 넣으려면 다음 경로를 사용해야 한다.
(Tomcat의 webapps/ROOT 역할)

/home/jeus/domains/mydomain/applications/ROOT/

 

📌 예제 파일 위치

/home/jeus/domains/mydomain/applications/ROOT/index.html
/home/jeus/domains/mydomain/applications/ROOT/js/script.js

 

📌 브라우저에서 실행 확인

http://localhost:8080/index.html

 

 

✅ Jeus 서버 실행 방법

Jeus는 Tomcat의 startup.sh처럼 startServer.sh를 사용한다.

1️⃣ Jeus 실행

cd /home/jeus/bin
./startServer.sh mydomain server1

 

🔹 mydomain → 실행할 도메인 이름
🔹 server1 → 실행할 서버 인스턴스

 

2️⃣ Jeus 중지

cd /home/jeus/bin 
./stopServer.sh mydomain server1
 

✅ 최종 정리

  Tomcat Jeus
정적 파일 위치 /webapps/ROOT/ /domains/mydomain/applications/ROOT/
서버 실행 ./startup.sh ./startServer.sh mydomain server1
서버 중지 ./shutdown.sh ./stopServer.sh mydomain server1
브라우저에서 확인 http://localhost:8080/index.html http://localhost:8080/index.html

 

반응형
LIST
반응형
SMALL

스프레드 연산자(...)는 배열, 객체, 문자열 등의 요소를 개별적으로 펼쳐서 사용할 수 있도록 해주는 JavaScript 연산자.

 

FullCalendar 사용할 때 아래처럼 eventSources에 일정을 배열로 넣어야하는데,

eventSources: [
    {
        id: "대한민국 공휴일",
        googleCalendarId: "ko.south_korea#holiday@group.v.calendar.google.com",
        color: "#FF0000",
        editable: false
    },
    {
        id: "일정2",
        color: "#FF0000",
        editable: false
    },
    ...
]

 

특정 eventList를 Map형태로 뽑아 전체를 넣기 위해 아래같이 사용함.

eventSources: [
    eventList.map(event => ({
        id: event.id,
        groupId: event.id,
        events: [],
        backgroundColor: event.bgColor,
    })), // ❌ 이렇게 하면 안됨
    {
        id: "대한민국 공휴일",
        googleCalendarId: "ko.south_korea#holiday@group.v.calendar.google.com",
        color: "#FF0000",
        editable: false
    }
]

문제는 eventList.map(...)이 이미 배열을 반환하기 때문에 이중배열([ [...mappedEvents], {...} ]) 형태가 되어 추가되지 않음.

 

이럴 때 사용하는게 스프레드 연산자!

   //이렇게 사용해야 한다.  
   eventSources: [
        ...eventList.map(event => ({ // 기본 이벤트 항목 추가
            id: event.id,
            groupId: event.id,
            events: [],
            backgroundColor: event.bgColor,
        })),
        {
            id: "대한민국 공휴일", // 대한민국 공휴일 추가
            googleCalendarId: "ko.south_korea#holiday@group.v.calendar.google.com",
            color: "#FF0000",
            editable: false
        }
    ],

 

 


📌 1. 배열에서의 스프레드 연산자 활용

배열을 복사하거나, 합칠 때 사용됩니다.

✅ 예제 1: 배열 복사 (얕은 복사)

const arr1 = [1, 2, 3];
const arr2 = [...arr1]; // arr1을 복사

console.log(arr2); // [1, 2, 3]


arr2 = [...arr1]를 사용하면 arr1의 개별 요소가 펼쳐져서 새로운 배열이 생성됩니다.

 

✅ 예제 2: 배열 합치기

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

const merged = [...arr1, ...arr2]; // 두 배열을 합침

console.log(merged); // [1, 2, 3, 4, 5, 6]


arr1과 arr2의 요소들이 개별적으로 풀려서 하나의 배열로 합쳐짐.

 

✅  예제 3: 배열의 중첩 구조 해결

const arr1 = [1, 2, 3];
const arr2 = [arr1, 4, 5];

console.log(arr2);
// [[1, 2, 3], 4, 5] <-- 배열이 중첩됨

const arr3 = [...arr1, 4, 5]; // 스프레드 연산자로 펼침

console.log(arr3);
// [1, 2, 3, 4, 5] <-- 중첩되지 않고 개별 요소가 추가됨

스프레드 연산자를 사용하면 배열의 중첩 없이 개별 요소로 추가할 수 있음.

 

📌 2. 객체에서의 스프레드 연산자 활용

객체를 복사하거나, 속성을 병합할 때 유용합니다.

 

✅ 예제 4: 객체 복사

 
const obj1 = { name: "Alice", age: 25 };
const obj2 = { ...obj1 }; // obj1을 복사

console.log(obj2); // { name: "Alice", age: 25 }

기존 객체를 새로운 객체로 복사하는 방법.

 

✅ 예제 5: 객체 속성 병합

 
const obj1 = { name: "Alice", age: 25 };
const obj2 = { job: "Developer", city: "Seoul" };

const mergedObj = { ...obj1, ...obj2 };

console.log(mergedObj);
// { name: "Alice", age: 25, job: "Developer", city: "Seoul" }

 

 

반응형
LIST

'[ javascript ]' 카테고리의 다른 글

Node.js 뜯어보기  (0) 2025.03.20
대표적인 es6 문법 정리  (0) 2024.12.30
부동소수점 이슈  (0) 2024.03.29
Node.js & npm 업데이트 하기  (1) 2024.03.22
리액트란?  (0) 2024.03.19
반응형
SMALL

부트스트랩으로 만들어진 템플릿에서 modal을 띄우기 위해 아래처럼 style.display = "block"을  사용했다.

document.getElementById('event-modal').style.display = "block";

 

근데 안나오는거...;; 왜지...

 

 

 

확인해보니 부트스트랩의 modal은 기존 HTML/CSS 모달과는 다르게 Javascript로 동작하기 때문에 사용 방법이 다르다.

HTML의 display: block; 속성만으로는 제대로 표시되지 않는 이유도 부트스트랩 modal이 내부적으로 추가적인 조작을 하기 때문.

var eventModal = new bootstrap.Modal(document.getElementById("event-modal"));
eventModal.show();

이렇게 사용해야함!

 

✅ 부트스트랩 모달의 주요 차이점

부트스트랩 modal 부분을 보면 아래와 같이 class 가 설정되어있다.

<div class="modal fade" id="event-modal" tabindex="-1">
    <div class="modal-dialog modal-dialog-centered">
        <div class="modal-content">
        ...

 

1) 애니메이션 효과 (fade 클래스) 

부트스트랩 모달은 기본적으로 fade 클래스를 사용하여 부드러운 애니메이션 효과가 적용됨. 

 

2) 배경 비활성화 (.modal-backdrop)

모달이 열릴 때 자동으로 <div class="modal-backdrop"> 요소가 생성됨.

이를 통해 배경 클릭 시 닫히는 기능을 제공함.

배경 비활성화 (.modal-backdrop) - 뒤에 흐려짐

 

3) 키보드 ESC 키 닫기 기능

esc 키를 누르면 모달이 닫히도록 기본 설정되어 있음.

keyboard: false 옵션을 사용하면 ESC 키로 닫히는 기능을 비활성화할 수 있음.

 

4) ARIA 접근성 지원
role="dialog"와 aria-labelledby="modal-title" 등의 속성이 자동으로 추가되어 접근성이 향상됨.

 

5) JavaScript API 제공
.show(), .hide(), .toggle() 등의 메서드를 제공하여 동적으로 모달을 조작할 수 있음.

 

<button class="btn btn-primary w-100" id="btn-new-event">Create New Event</button>

 

근데 사실 JavaScript 방식 (onclick 사용) 을 안해도 된다.

 

부트스트랩에서는 data-bs-toggle="modal"과 data-bs-target="#모달ID"를 버튼에 추가하면 자동으로 모달을 띄울 수 있음!

<button class="btn btn-primary w-100" id="btn-new-event" data-bs-toggle="modal" data-bs-target="#event-modal">Create New Event</button>

 

비슷하게 모달 안에 있는 닫힘버튼도 data-bs-dismiss="modal" 설정해서 사용 가능.

 aria-hidden="true"  는 접근성 API 차단 (가상 커서로 탐색 x)

<button type="button" class="btn-close" data-bs-dismiss="modal"aria-hidden="true"></button>

 

 

 

✅ 부트스트랩 모달에 항목 저장해서 리스트에 추가하기

열고 닫는건 했으니 저장처리 해주고 모달을 닫아주면 된다.

저장버튼이 기존에 <button type="submit"> 이었는데 submit은 폼을 제출하면서 페이지를 새로고침하니까 type:"button"으로 변경해줌.

 

 

 

 

반응형
LIST
반응형
SMALL

+ Recent posts

반응형
LIST