package.json 만 가지고 있으면 npm install 명령어만 입력하면 자동으로 package.json 파일 안의 패키지들이 자동으로 불러와져서 다운로드 받아진다, 나중에 프로젝트를 진행할때 package.json 파일만 올려놓으면 모두 npm install 명령어를 사용해서 다운로드 받으면 된다
파일 세팅
js 파일과 ejs 파일 초기 세팅 후 서버 구동
서버 구동 및 접속
- middle ware -
특정 기능을 처리하는 역할을 하는 것
( 여기에서는 router 라는 middle ware 를 사용하여 경로의 기능을 위임한다 )
router 에게 루트 경로의 기능을 위임
라우터를 여러개 생성하여 사용할 수 있다 ( 라우터 별로 root 경로를 설정하여 사용 )
아직 DB 를 연동하지 않았으므로 DB 를 대신해서 데이터를 저장 할 memberDAO.js 를 프로젝트 파일에 생성
더미 데이터 생성
module.exports 를 사용해서 생성한 더미 데이터 변수를 밖으로 내보낸다
memberDAO 파일에서 밖으로 내보내진 내용을 require 을 통해 경로를 지정해서 변수로 가져온다
서버 별칭 설정 및 사용
package.json 파일 안에 scripts 를 설정한다, 위와 같이 설정하면 npm run start 또는 npm start 만으로 설정한 서버를 실행시킬 수 있다.
( 구동해야하는 서버가 변경되면 script 의 값으로 들어가있는 npx supervisor app.js 에서 app.js 를 실행시킬 서버 파일로 변경해주면 된다 )
Flow
Flow ( 흐름 ) - 라우터에서 각 기능별 컨트롤러(다수의 컨트롤러)로 들어오는 주소에 따라 구분해서 연결해준다
라우터를 파일로 분리시키기 위해 파일 세팅
app02.js 와 test_router.js 파일 세팅
라우터를 보내고 서버에서 router 라는 변수로 해당 라우터의 기능을 받아온다
localhost:3030/ 경로로 접속되면 외부 파일인 test_router.js 의 router 로 이동되어 경로가 분할된다
여기까지 라우터를 분리 완료...
이제부터는 컨트롤러를 분리...
컨트롤러를 분리하기 위해 파일 세팅
controller 파일에서 응답을 보내는 함수를 외부로 전송, 컨트롤러에서는 해당 기능을 받아 응답 부분에 해당 변수를 대입하여 사용
여러개의 응답을 내보낼 경우는 키와 값을 가지는 Object 형태로 키와 값으로 함수가 매칭되게 보내줘서 app 에서는 해당 Object 의 키 값을 불러와서 사용한다
서버 실행
여기까지 컨트롤러 분리 완료...
이제부터 service 를 분리...
service 를 분리하기 위해 파일 세팅
test_service 에서 더미데이터가 저장된 memberDAO 의 내용을 가져와서 index 라는 함수에서 해당 값을 return 되게끔 설정 후 이 index 기능을 exports 로 외부로 전송 후 controller 에서 이 값을 require 로 받아와서 매개변수로 {member} 를 넣어준다
index.ejs 에서 해당 member 데이터를 사용하여 웹에 출력한다
실습 예제 1-1
실습 예제 1-1
예제 풀이 1-1
디렉토리와 파일 구조 동일하게 맞춘 뒤 기존에 사용하던 package.json 파일 가져와서 npm install 하여 패키지 모두 설치
실습 예제 1-2
실습 예제 1-2
예제 풀이 1-2
예제 풀이 1-2
예제 풀이 1-2
실습 예제 1-3
실습 예제 1-3
예제 풀이 1-3
예제 풀이 1-3
예제 풀이 1-3
실습 예제 1-4
실습 예제 1-4
예제 풀이 1-4
흐름을 잘 파악하기!!!!
무조건 url 주소로 접근이 들어오면 일단 app 이 실행되며 app 에서 접속 주소 구분에 따라서 각 접속 주소에 맞는 controller 로 보내준다 > 이때 controller 는 렌더링될 ejs 페이지를 응답하게 되는데 경우에 따라서 검증해야 할 값이 있으면 검증 후에 응답을 보낸다 > 응답 받은 페이지에서 클라이언트가 버튼을 클릭하여 다른 페이지가 호출되었을 경우 다시 app 에서 접속 주소 구분에 따라서 각 접속 주소에 맞는 controller 로 보내준다
서버를 생성하고 listen(포트번호) 를 설정하여 응답을 대기하고, teminal 창을 열어 현재 Node 를 실행중인 디렉토리에 접근해 node main 을 입력하여 생성한 프로젝트 명인 main.js를 구동시킨다
- 만약 서버를 구동할때 오류가 발생하는 경우 -
terminal 기본 창이 posershell 로 설정되어 있을텐데 command prompt 로 추가 / 변경하여 사용한다
구동된 서버 접속
서버가 구동되었으므로 127.0.0.1(localhost) 주소의 3000 포트로 접속하면 정상적으로 접속된다... 글자가 깨진 것은 연결 성공 되었습니다!!! 문구
- ip 로 서버를 구동하는 경우 -
ip 주소로 서버를 구동하려는 경우
한글이 깨지지 않게 설정
const http = require("http");
// require : 통신하기 위해 http 기능을 가져오겠다는 뜻
const app = http.createServer((req, res) => {
// http.createServer : 기능안의 서버를 만드는 기능을 호출 - 서버를 생성
// ( req : request(요청), res : response(응답) )
console.log("연결 성공!!!!");
res.writeHead(200, { "Content-Type": "text/html; charset=utf8" });
// 200 : 성공적으로 연결이 되었을 경우
// 사용자한테 전달될 값은 html 형식의 텍스트로 전송
// 인코딩 방식은 utf8 을 사용함
res.end("연결 성공 되었습니다!!!!");
// 연결 응답 전송
});
app.listen(3000, "192.168.42.86");
// 생성한 서버를 3000 번 포트로 응답을 대기하겠다는 뜻
res.writeHead() 추가
서버 접속 결과
supervisor npm 설치
현재는 코드를 수정할때마다 터미널에서 ^c 를 눌러서 서버를 종료시킨 뒤 다시 구동시켜야 하는데 이를 실시간으로 반영하게 해주는 supervisor 를 설치 > --save 옵션은 현재 위치 디렉토리에서만 적용하겠다는 뜻
npm 이란 ?
npm 은 자바스크립트 프로그래밍 언어를 위한 패키지 관리자, 패키지를 다운로드 하여 컴퓨터에 설치해준다
설치가 정상적으로 완료되면 해당 디렉토리 안에 node_modules, package-lock.json, package.json 이 추가됨
package.json : 의존성 관리 파일
supervisor main 명령어를 사용해서 서버를 구동
※ 만약 supervisor main 으로 서버가 정상적으로 구동되지 않는다면 npx supervisor main 를 사용하여 구동한다 ※
VScode 에서 코드를 변경한 뒤 접속한 웹에서 새로고침을 하면 정상적으로 변경 내용이 반영됨
접속 경로 별로 접속되는 경로 나누기
if 문을 사용하여 req(응답) 값을 확인 후 응답은 각각 설정
const http = require("http");
// require : 통신하기 위해 http 기능을 가져오겠다는 뜻
const app = http.createServer((req, res) => {
// http.createServer : 기능안의 서버를 만드는 기능을 호출 - 서버를 생성
// ( req : request(요청), res : response(응답) )
console.log("연결 성공!!!!");
res.writeHead(200, { "Content-Type": "text/html; charset=utf8" });
// 200 : 성공적으로 연결이 되었을 경우
// 사용자한테 전달될 값은 html 형식의 텍스트로 전송
// 인코딩 방식은 utf8 을 사용함
if (req.url === "/") {
// 유저가 접속한 값이 192.168.42.86:3000 이라면
res.end(`<h1>기본 페이지 연결</h1>
<a href="/test">test이동</a>`);
} else if (req.url === "/test") {
// 유저가 접속한 값이 192.168.42.86:3000/test 이라면
res.end("test 페이지 연결");
} else {
res.end("연결 성공 되었습니다!!!!");
}
// 연결 응답 전송
});
app.listen(3000, "192.168.42.86");
// 생성한 서버를 3000 번 포트로 응답을 대기하겠다는 뜻
코드 실행
직접 html 파일 형식으로 접속 경로 나누기
- 해당 형식으로 접속 경로를 나누진 않지만 연습으로 해봄
코드 실행
접속 경로별 응답 파일을 나눠주는 express 프레임워크 설치
npm install express --save
설치 후 package.json 파일에 설치한 express 가 추가된 모습.... 추후에 모듈을 지우고 다시 설치할땐 저 버전을 기억해둔 다음에 다시 설치해야 함
모듈을 삭제하고 버전을 명시하여 다시 설치하는 방법
npm uninstall [패키지명] : 모듈 패키지 삭제
npm install [패키지명]@[버전] : 최신버전의 패키지가 아닌 명시한 버전의 패키지를 설치
JavaFX 를 사용하여 미니 프로젝트를 진행하려하는데 Eclipse 가 아닌 IntelliJ 를 사용하여 프로젝트를 진행해보려 한다.
프로젝트는 데이터베이스를 연동하여 JavaFX 를 사용하여 서버(1), 사용자(2) 환경으로 구성한뒤 사용자가 숫자야구를 진행하여 순서대로 값을 입력하면 서버에서 값을 전달받아 처리하는 형식으로 만들어 보려고 한다.
프로젝트를 진행하기 앞서서 우선적으로 인텔리제이에 JavaFX 프로젝트를 생성해야 한다.
New Project 클릭
Generators 에서 JavaFX 를 선택해준뒤 프로젝트 이름과 경로를 설정하고 Next 클릭
Create 클릭
생성된 프로젝트에서 main 을 실행해주면 정상적으로 출력된다
- 단점 -
eclipse 보다 코드 실행속도가 느리다..... 그리고 Scene builder 를 연동하여 사용할때 우클릭으로 사용이 가능한 것 같긴 한데 관련된 자료가 너무 적어 설정 방법을 아직 모르겠으므로 우선은 SceneBuilder 를 설치하여 인텔리제이와 연동하지 않고 그냥 SceneBuilder 에서 fxml 파일을 불러와서 사용하는 방식으로 사용해야 할 것 같다.
정상적으로 fxml 파일이 끌어와진다 이후 저장하게 되면 인텔리제이의 fxml 파일에도 적용된다
아무래도 프로젝트를 진행하는데 있어서 윈도우에서 SceneBuilder 를 연동하거나 JavaFX 를 사용하는 방법에 대해서는 자료가 좀 있지만, 맥OS 관련해서는 자료가 거의 없다시피 하다... 문제가 발생할때 마다 하나하나씩 다 이클립스랑 비교해가며 부딫혀보는 수 밖에 없을 것 같다.....
: java.util 패키지에 들어있는 클래스 (java.util.Scanner)import로 불러와서 사용해야 한다.( import 단축키 - Ctrl + Shift + O )
package input;
import java.util.Scanner;
// java.lang은 기본 패키지로 자동으로 import되며
// java.lang을 제외한 패키지는 모두 import로 가져와야 사용 가능하다
public class Input {
public static void main(String[] args) {
// System.out : 표준 출력 객체
// System.in : 표준 입력 객체
Scanner sc;
// Scanner 클래스 : 데이터를 읽어오는 도구
// Scanner : 자료형(type), sc : 변수 이름
sc = new Scanner(System.in);
// sc라는 변수에 공간을 생성한다
System.out.print("이름 입력 : ");
String name = sc.next(); // next() : 입력 받는 키 값을 문자열로 가져온다
// 이 값을 name이라는 문자열 변수로 저장한다
System.out.println("입력 받은 이름은 " + name + " 입니다");
sc.close();
// - scanner는 사용 후 종료를 시켜주는 것이 바람직하다
}
}
저장할 변수 이름이 sc 일 필요는 없다.
또한, Scanner 를 선언하면서 동시에 초기화할 수 있다.
Scanner abc = new Scanner(System.in);
package input;
import java.util.Scanner;
// java.lang은 기본 패키지로 자동으로 import되며
// java.lang을 제외한 패키지는 모두 import로 가져와야 사용 가능하다
public class Input {
public static void main(String[] args) {
// 1. 키보드 값을 입력받기 위해서 Scanner를 생성
Scanner scan = new Scanner(System.in);
// 2. 키 값을 저장할 변수를 선언
String name;
int age;
double height;
// 3. 입력 진행
System.out.print("이름 : ");
name = scan.next(); // next() : 키 값을 문자열로 가져온다
System.out.print("나이 : ");
age = scan.nextInt(); // nextInt() : 키 값을 정수로 가져온다
System.out.print("신장 : ");
height = scan.nextDouble(); // nextDouble() : 키 값을 실수로 가져온다
// 4. 입력받은 내용을 원하는 대로 출력한다
System.out.printf("이름 : %s (%d세)\n", name, age);
System.out.println("신장 : " + height + "cm");
scan.close();
}
}
Scanner는 입력된 키 값을 '버퍼(buffer)' 라는 임시 공간을 활용해서 가져온다.
※ 버퍼는 enter와 space를 구분자로 인식한다 ※
package input;
import java.util.Scanner;
public class Input {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n1, n2;
System.out.print("두 정수 입력 : ");
// 콘솔 입력창에서 10 20 30 40 50 60 을 입력
// 버퍼는 enter와 space를 구분자로 인식하기 때문에
// 버퍼에 10 값이 스페이스바 때문에 n1으로 구분되어 들어가고
// 버퍼에 20 값이 스페이스바 때문에 n2로 구분되어 들어간다
n1 = sc.nextInt();
n2 = sc.nextInt();
System.out.printf("n1 = %d, n2 = %d\n", n1, n2);
int n3, n4;
System.out.print("다시 두 정수 입력 : ")
// 정수를 다시 입력받으려 했으나 위에서 입력한 값에서
// 10과 20은 n1과 n2로 할당되었고 뒤에 남은 30과 40값이
// 구분자에 의해 자동으로 n3와 n4로 할당된다
n3 = sc.nextInt();
n4 = sc.nextInt();
System.out.printf("n3 = %d, n4 = %d\n", n3, n4);
sc.nextLine(); // 버퍼의 모든 데이터를 가져온다
// - 엔터만 구분자로 인식
int n5, n6;
System.out.print("마지막 두 정수 입력 : ")
// 여기서 나머지 할당될 값 50, 60이 들어오지 않는 이유는
// enter만 구분자로 인식하는 nextLine()이 사용되었기 때문이다
// 버퍼에서 남은 입력이 50 60\n 이 남았기 때문에 \n을 인식하여
// "50 60" 이 통째로 한 입력값으로 인식되며, 이 값은 int자료형이
// 아니므로 n5와 n6에 들어갈 수 없으니 버려지게 되고 새로운 입력값을 받는다
// 70 80 입력하면 n5와 n6에 70, 80 값이 입력된다
n5 = sc.nextInt();
n6 = sc.nextInt();
System.out.printf("n5 = %d, n6 = %d\n", n5, n6);
sc.close();
}
}
int n = 10;
System.out.println("n + 6 = " + (n + 6));
System.out.println("n =" + n);
// 산술 계산을 한다고 변수의 값이 변화하는 것은 아님
System.out.println("n - 6 = " + (n - 6)); // 4
System.out.println("n * 2 = " + n * 2); // 20
System.out.println("n / 3 = " + n / 3); // 3
System.out.println("n % 3 = " + n % 3); // 1
System.out.println("n / 3.0 = " + n / 3.0);
// n / 3 은 자료형이 정수이기 때문에 3까지만 출력 된다
// n / 3.0 은 실수형으로 자동 형변환 되어 나머지까지 나오게 된다.
// 3.3333333333333335
// 소수점 끝자리가 5인 이유는 계산 시 오차가 발생했기 때문
2.대입 연산자: 공간(= 변수)에 값을 할당하는 연산자
- 좌변은 공간, 우변을 결과 값
- 대입 연산은 항상 우변부터 수행
- 대입 연산의 양변의 자료형은 일치시킨다
int n = 10 + 3;
// int n = 13;
// 우변부터 계산 후 변수에 대입
System.out.println("n = " + n);
int a, b, c = 30;
// 1. a, b, c 모두 30으로 초기화 된다??
// 2. c 만 30으로 초기화 된다??
// int a, int b, int c = 30 과 같음
// 즉, 답은 2번
// 변수를 한번에 초기화 하는 법
int d, e, f;
d = e = f = 30;
3.복합 대입 연산자: 산술 + 대입
- 연산한 결과를 변수에 다시 저장시 사용
int n = 10;
n += 6; // n = n + 6;
System.out.println("n = " + n); // 16
n -= 3;
System.out.println("n = " + n); // 13
n *= 2;
System.out.println("n = " + n); // 26
n /= 2;
System.out.println("n = " + n); // 13
n %= 5;
System.out.println("n = " + n); // 3
int a = 5, b = 3, c = 4;
a += b *= c -= 2;
// 복합대입연산자는 우선순위가 존재하지 않음
System.out.println("a = " + a); // 11
System.out.println("b = " + b); // 6
System.out.println("c = " + c); // 2
4.증감 연산자: 피연산자를 1증가 혹은 1감소
int n = 10;
++n; // 전치 : 연산자가 앞에 붙은 경우
System.out.println(n); // 11
--n;
System.out.println(n); // 10
n++; // 후치 : 연산자가 뒤에 붙은 경우
System.out.println(n); // 11
n--;
System.out.println(n); // 10
// 증감연산은 단독으로 사용 시 (전치/후치)는 차이가 없다.
// (전치/후치)가 상관있는 경우
int n1 = 10, n2, n3;
n2 = ++n1; // 전치 : 증감 후 다른 연산
System.out.println(n1 + ", " + n2); // 11, 11
n3 = n1++; // 후치 : 다른 연산 후 증감
System.out.println(n1 + ", " + n3); // 11, 10
// 연습
int a = 5, b = 4, c = 7, d;
d = ++a + b-- + c++;
System.out.println(a); // 6
System.out.println(b); // 3, 후치는 제일 마지막에 연산
System.out.println(c); // 8, 후치는 제일 마지막에 연산
System.out.println(d); // 17
5.비교 연산자: 데이터의 대소 관계를 비교
- 비교 결과는 boolean(true/false)로 얻어진다
int n = 10;
System.out.println("n > 10 결과 : " + (n > 10)); // false
System.out.println("n >= 10 결과 : " + (n >= 10)); // true
System.out.println("n < 20 결과 : " + (n < 20)); // true
System.out.println("n <= 20 결과 : " + (n <= 20)); // true
System.out.println("n == 9 결과 : " + (n == 9)); // false, 같으면 참, 다르면 거짓
System.out.println("n != 9 결과 : " + (n != 9)); // true, 같으면 거짓, 다르면 참
System.out.println();
// 결과는 boolean 타입에 저장할 수도 있다.
boolean result = n == 10; // boolean result = true
System.out.println("result = " + result); // result = true
6.논리 연산자: true / false 를 연산
- 비교 결과는 boolean( true / false )로 얻어진다
// 1. && : AND, 양쪽이 모두 참이면 결과가 참
// - 다른 말로 곱(*) 연산
// true : 1, false : 0 이라고 보면 됨
System.out.println("true AND true 결과 : " + (true && true)); // ture
System.out.println("true AND false 결과 : " + (true && false)); // false
System.out.println("false AND true 결과 : " + (false && true)); // false
System.out.println("false AND false 결과 : " + (false && false)); // false
System.out.println();
// 2. || : OR, 양쪽 모두 거짓이면 결과가 거짓
// - 다른 말로 합(+) 연산
// true : 1, false : 0 이라고 보면 됨
System.out.println("true OR true 결과 : " + (true || true)); // true
System.out.println("true OR false 결과 : " + (true || false)); // true
System.out.println("false OR true 결과 : " + (false || true)); // true
System.out.println("false OR false 결과 : " + (false || false)); // false
System.out.println();
// 3. ! : NOT, 참을 거짓으로 거짓을 참으로 변경
// - 다른 말로 반전 연산
// true : 1, false : 0 이라고 보면 됨
System.out.println("NOT true 결과 : " + !true); // false
System.out.println("NOT false 결과 : " + !false); // true
7..equals: 자바 문자열 비교
- 문자열이 동일한지 확인한다
String a = "안녕하세요";
String b = "안녕하세요";
System.out.println(a.equals(b)); // true 출력