본문 바로가기
국비학원/수업기록

국비 지원 개발자 과정_Day36

by 루팽 2023. 1. 16.

node.js

브라우저가 없어도 단독으로 테스트 가능

 

npm

노드 패키지를 관리해주는 툴 → 패키지들이 서로 의존되어 있어 하나의 문제가 발생하면 다른 것까지 가능하지 않을 수도

 

vscode 확장기능 설치(Auto Rename Tag/HTML CSS Support/Font Awesome Auto-complete & Preview/vscode-icons

 

package.json 설정참고

{
  "name": "html0116",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "test": "echo \\"Error: no test specified\\" && exit 1",
    "start": "nodemon app"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "colors": "^1.4.0",
    "express": "^4.18.2"
  },
  "devDependencies": {
    "nodemon": "^2.0.20"
  }
}

 

info.txt

npm init --yes

npm i express
:Restful API를 지원하는 프레임워크

npm i nodemon --save-dev
:--save-dev 옵션을 붙이면 로컬에서만 사용함

 

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>index페이지</title>
</head>
<body>
  <h3>index페이지</h3>
</body>
</html>

 

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script
      src=""
      crossorigin="anonymous"
    ></script>
    <title>TerrGYM</title>
  </head>
  <body>
    <h2>TerrGYM</h2>
    <ul>
      <li>스쿼트</li>
      <li>런지</li>
      <li>레풀다운</li>
      <li><i class="fa-solid fa-trash"></i></li>
      <li><i class="fas fa-plus"></li>
    </ul>
  </body>
</html>

 

let colors = require("colors");

console.log("hello".green); // outputs green text
console.log("i like cake and pies".underline.red); // outputs red underlined text
console.log("inverse the color".inverse); // inverses the color
console.log("OMG Rainbows!".rainbow); // rainbow
console.log("Run the trap".trap); // Drops the bass
console.log(colors.rainbow('OMG Rainbows!')); // rainbow
console.log(colors.green('OMG Rainbows!')); // rainbow
console.log(colors.red('OMG Rainbows!')); // rainbow

 

function add(a, b) {
  return a + b;
}

console.log(add(1, 2));
console.log(add(2, 3));
console.log(add(5, 7));
console.log(add(1, 5));

 

 

JAVA → JFrame사용, 브라우저에서 동작 안 함(native app)

웹 프로그래밍(html, css, js → 정적페이지 처리)

동적페이지 처리 → JAVA(HTTP 프로토콜을 지원하는 api가 없음) → Server에서 돌아가는 JAVA 필요함 → Applet(JFrame과 거의 같음) → 서버에서 돌아가는 애플릿 Server+Applet → Servlet 서블릿이 만들어짐(HTTP 프로토콜, Resful API 지원하게 됨) → 단점: out.print(”<html><head><body></body></head></html>”) 이렇게 줄줄이 써야 함 → JSP 등장(Java Server Page, 서버에서 돌아가는 자바) → 시니어, 주니어 개발자 갭차이가 많음 → Spring F/W발표(갭을 줄이기 위해 프레임워크 제시), 일본은 Struts1,2 쓰기도 → 우리나라는 전자정부프레임워크(200개), 자바공화국 시작(자바,스프링중요+오라클,리액트도 알면 좋음) → 프레임워크를 통해서 MVC패턴 주입받음 → 순수한 자바로 이루어진 MVC 미리 소개!

 

BookManager.java에 main메소드가 있음

사용자가 선택한 정보를 넘기는 방법 → 파라미터

String gubun = “bookMgr” or “boardMgr”

조회|수정|삭제|입력 → BookController로 연결

게시판 → BoardController로 연결

이와 같은 역할을 맡을 클래스 설계 → FrontController

package dev_java.bookMVC;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

// 개발 방법론에서 디자인 패턴 중 MVC패턴을 알아보자

// M: 모델 계층(XXXLogic + XXXDao.java) -> 서비스계층(비즈니스 로직, 업무 계층)
// XXXDao가 있고 없고는 MVC패턴에 영향이 없다
// 다만 오라클서버와 연계에 반복되는 코드를 줄여주고 오픈소스나 라이브러리
// (iBatis, MyBatis-반자동, Hibernate-완전자동, SQL문이 없음)를 조립하기위한
// 요구사항으로 만들어 사용하는 클래스이다.
// 클래스 쪼개기(생성자) -> POJO(pure) -> Spring(maven) -> Spring boot(Gradle)-완결편

// V: 뷰 계층

// C: 컨트롤 계층

// 프레임워크를 왜 원하는가? - 실력차이를 줄여야함
// 틀이 정해짐 -> 클래스, 메소드 선언 되어있음(단 파라미터 타입, 개수는 결정해야함)
// 개발자는 비즈니스 로직에만 집중할 수 있음
// 
public class BookManager extends JFrame implements ActionListener {
  JButton jbtn_sel = new JButton("조회"); // SELECT문
  JButton jbtn_ins = new JButton("입력"); // INSERT문
  JButton jbtn_upd = new JButton("수정"); // UPDATE문
  JButton jbtn_del = new JButton("삭제"); // DELETE문
  JButton jbtn_board = new JButton("게시판");
  JPanel jp_north = new JPanel();
  String gubun = "bookMgr"; // 도서 CRUD면 bookMgr, 게시판 CRUD면 boardMgr

  public BookManager() {
    // initDisplay(); -> 주로 속지(JPanel, JScrollPane)로 사용되는 페이지일때 생성자 안에서 메소드 부름
    // 요청에따른 페이지 갱신처리, 화면갱신, 화면 초기화
    // 그러나 스레드 구현시에는 이슈가 발생하니까 주의해야함
    // 문법에러 - 고치기 쉬움
    // 논리에러 - 트러블슈팅 어렵다(NullPointerException), 예외상황과 관계있음 -> 500번에러
  }

  public void initDisplay() {
    // 이벤트 소스와 이벤트 처리클래스 매핑하기
    jbtn_sel.addActionListener(this);
    jbtn_ins.addActionListener(this);
    jbtn_upd.addActionListener(this);
    jbtn_del.addActionListener(this);
    jbtn_board.addActionListener(this);
    // 화면에 추가
    jp_north.add(jbtn_sel);
    jp_north.add(jbtn_ins);
    jp_north.add(jbtn_upd);
    jp_north.add(jbtn_del);
    jp_north.add(jbtn_board);
    this.add("North", jp_north);

    this.setTitle("도서관리 시스템 Ver.1.0");
    this.setLocation(100, 100);
    this.setSize(500, 400);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setVisible(true);
  }

  public static void main(String[] args) {
    BookManager bManager = new BookManager();
    // 메인에 initDisplay() -> 메인스레드와 Runnable을 통해서 구현하는 스레드를 분리할 수 있는 경우에 사용
    // 메인스레드와 자기자신이run 구현체 클래스 역할을 병행하는 컨셉일 때
    // 이렇게 안하면 지연발생(화면이 안뜨거나 소켓 accept가 발생안함, 그냥 죽은코드)
    bManager.initDisplay();
    // 리팩토링 -결과의 변경 없이 코드의 구조를 재조정(가독성, 유지보수성을 목표로함)
  }

  // Override(재정의) 하는 이유
  // 장치마다(아이폰, 갤럭시, 아이패드) 결정되지 않았으니까
  @Override
  public void actionPerformed(ActionEvent e) { // 콜백함수
    // 입력|수정|삭제|조회버튼이 클릭되면 이벤트를 JVM이 감지하고
    // 감지되면 JVM이 actionPerformed 메소드를 알아서 호출해줌
    Object obj = e.getSource();
    BookController bookController = null;
    BoardController boardController = null;
    // 게시판 버튼을 눌렀을 때
    if (obj == jbtn_board) {
      System.out.println("게시판");
      gubun = "boardMgr";
      // 게시판 CRUD로 연결
      if ("boardMgr".equals(gubun)) {
        boardController = (BoardController) FrontController.getController(gubun);
        System.out.println("게시판관리 선택 => " + boardController);
        // 게시판 컨트롤러가 결정되면 다시 디폴트값으로 초기화
        gubun = "bookMgr";
      }
    }
    // 도서 CRUD로 연결
    else if ("bookMgr".equals(gubun)) {
      bookController = (BookController) FrontController.getController(gubun);
      System.out.println("도서관리 선택 => " + bookController);
      // if문은 무조건 조건을 따진다
      // else if문은 앞 조건을 수렴하면 뒤에 있는 코드는 실행기회를 갖지 않는다
      // 조회버튼을 눌렀을 때
      if (obj == jbtn_sel) {
        System.out.println("조회");
        bookController.getBookList(gubun, gubun);
      }
      // 입력버튼을 눌렀을 때
      else if (obj == jbtn_ins) {
        System.out.println("입력");
        bookController.bookInsert(null);
      }
      // 수정버튼을 눌렀을 때
      else if (obj == jbtn_upd) {
        System.out.println("수정");
        bookController.bookUpdate(null);
      }
      // 삭제(탈퇴)버튼을 눌렀을 때
      else if (obj == jbtn_del) {
        System.out.println("삭제");
        bookController.bookDelete(null);
      }
    }
  }
}

 

package dev_java.bookMVC;

public class FrontController {
  // 리턴타입을 Object로 한 이유 -> 사용자의 선택에따라 BookController 혹은 BoardController 연결해줘야하니까
  public static Object getController(String gubun) {
    // FrontController obj = null; // 상속관계로 처리했다면 이렇게 처리
    Object obj = null; // extends, implements 없이 할 경우
    if ("bookMgr".equals(gubun)) {
      obj = new BookController();
    } else if ("boardMgr".equals(gubun)) {
      obj = new BoardController();
    }
    return obj;
  }
}

 

package dev_java.bookMVC;

// 인터페이스는 추상메소드만 가질 수 있다
// 일반메소드, 생성자, 일반 전역변수 불가!
public interface Controller { // 인터페이스를 사용할 경우
  public abstract FrontController geController(String gubun);
}

 

package dev_java.bookMVC;

import java.util.List;
import java.util.Map;

// public class BookController  extends FrontController{ //상속받은 경우
// public class BookController implements Controller { // 인터페이스를 implements한 경우
public class BookController {
  // BookLogic bookLogic = new BookLogic();
  // 원래는 BookLogic 클래스를 객체주입해야하지만, 업무적인 depth가 얕아서
  // 로직클래스에서 선택, 결정에따른 추가적인 프로세스가 전혀 없는 상태임
  // 따라서 컨트롤러 클래스와 Dao 클래스 사이의 연결만 담당하니까 의미없음
  BookDao bookDao = new BookDao();

  // 조회
  public List<Map<String, Object>> getBookList(String cols, String keyword) {
    System.out.println("도서목록 조회");
    List<Map<String, Object>> bList = null;
    bList = bookDao.getBookList(cols, keyword);
    return bList;
  }

  // 입력
  public int bookInsert(BookVO bkVO) {
    System.out.println("도서정보 등록");
    int result = 0;
    result = bookDao.bookInsert(bkVO);
    return result;
  }

  // 수정
  public int bookUpdate(BookVO bkVO) {
    System.out.println("도서정보 수정");
    int result = 0;
    result = bookDao.bookUpdate(bkVO);
    return result;
  }

  // 쿼리문을 보고 리턴 타입과 파라미터 타입 및 개수를 결정하는데 참고
  // 삭제
  // DELETE FROM book WHERE bk_no = 5;
  // 리턴 타입 int - 1: 삭제성공 / 0: 삭제실패
  // 파라미터 타입 int - 도서번호
  public int bookDelete(BookVO bk_no) {
    System.out.println("도서정보 삭제");
    int result = 0;
    result = bookDao.bookDelete(bk_no);
    return result;
  }
}

/*
 * SQL 응용
 * JAVA와 오라클 연동(연계)하기
 * JDBC API(원시적) - MyBatis(반자동), 여기에 집중! - Hibernate(완전자동), 초보자에겐 독이다
 */

 

package dev_java.bookMVC;

import lombok.Data;

@Data
public class BookVO {
  private int bk_no;
  private String bk_title;
  private int bk_price;
  private String bk_date;
  private String bk_publish;
  private String bk_info;
  private String bk_author;
}

 

package dev_java.bookMVC;

import java.util.List;
import java.util.Map;

public class BookDao {
  /**
   * 도서 목록 조회
   * SELECT bk_no, bk_title FROM book
   * WHERE bk_title(?) = ?
   * WHERE bk_author(?) = ?
   * WHERE bk_info(?) = ?
   * 
   * @param cols    - 컬럼명 bk_title or bk_author or bk_info
   * @param keyword - 텍스트필드에 사용자가 입력한 값
   * @return - 검색결과는 n개의 로우 List<Map<>>
   *         조인이 필수적인 경우에는 반드시 List<Map<>> 형태가 유리하고
   *         그렇지 않은 경우라면 List<XXXVO> 형태와 별 차이가 없다
   *         단 조회결과로 얻은 정보를 자바코드에서 연산을 해야하는 경우라면
   *         제네릭 타입으로 Map보다는 XXXVO가 유리하다
   *         Map이면 리턴값이 무조건 Object이다 -> ClassCastingException주의
   *         int i = Integer.parseInt(pMap.get("bk_no").toString());
   *         int i = xxxVO.getBkno();
   */
  public List<Map<String, Object>> getBookList(String cols, String keyword) {
    System.out.println("getBookList호출");
    return null;
  }

  /**
   * 도서 정보 입력
   * 
   * @param bkVO - 입력요청으로 입력받은 값
   * @return - 1: 입력성공 / 0: 입력실패
   */
  public int bookInsert(BookVO bkVO) {
    int result = 0;
    System.out.println("bookInsert호출(사용자가 선택한 도서정보-주소번지) => " + bkVO);
    return result;
  }

  /**
   * 도서 정보 수정
   * 
   * @param bkVO - 수정요청으로 입력받은 값
   * @return - 1: 수정성공 / 0: 수정실패
   */
  public int bookUpdate(BookVO bkVO) {
    int result = 0;
    // 롬복 어노테이션 @Data를 사용했기에 getter / setter 메소드는 없지만 사용가능함
    // 단 VO타입이므로 전역변수에 담긴 값을 출력하려면 getter 메소드 호출함
    // 전역변수는 캡슐화로인해 직접 접근 불가하고 위변조로 인한 피해로부터 보호하기 위해
    // 접근제한자는 반드시 private로 할 것
    System.out.println("bookUpdate호출(사용자가 선택한 도서정보-주소번지) => " + bkVO);
    return result;
  }

  /**
   * 도서 정보 삭제
   * 
   * @param bk_no - 도서번호
   * @return - 1: 삭제성공 / 0: 삭제실패
   */
  public int bookDelete(BookVO bk_no) {
    int result = 0;
    System.out.println("bookDelete호출(사용자가 선택한 도서번호) => " + bk_no);
    return result;
  }
}

 

package dev_java.bookMVC;

public class BookLogic {
}

 

package dev_java.bookMVC;

// public class BoardController extends FrontController{ //상속받은 경우
  // public class BoardController implements Controller { // 인터페이스를 implements한 경우
      public class BoardController {
}

 

package dev_java.bookMVC;

import lombok.Data;

@Data
public class Book_BoardVO {
  private int b_no;
  private int mem_no;
  private String b_title;
  private String b_content;
  private int b_hit;
}

 

package dev_java.bookMVC;

public class BoardDao {
}

 

package dev_java.bookMVC;

public class BoardLogic {
}

댓글