반응형
반응형

📝Single Block I/O

DB에서 데이터들은 일반적으로 HDD에 저장되는데 레코드를 한번의 I/O Call에 한줄(하나의 데이터 블록)씩 읽어오는 걸 의미한다.
인덱스를 이용한 실행계획일 때 Single Block I/O 방식으로 이용하게 된다.
그 이유는 인덱스는 블록간 논리적 순서는 물리적으로 데이터파일에 저장된 순서가 달라 그 블록들이 논리적 순서로는 한참 뒤쪽에 위치할 수 있습니다. 
소량데이터를 읽을때 주로 사용하는 방식입니다.

📝Multi Block I/O

DB에서 데이터들은 일반적으로 HDD에 저장되는데 I/O Call 시점에 인접한 블록들을 같이 읽어 메모리에 적재하는 것을 의미합니다.
테이블 전체를 스캔할때 이 방식을 사용하며 테이블이 클수록 Multiblock I/O 단위도 크면 좋고 많은 데이터 블록을 읽을때 주로 사용합니다.
하지만 OS가 일반적으로 허용하는 I/O 단위가 1MB이면 1MB만큼만 읽습니다.

db file sequential read : Single Block I/O방식으로 I/O요청할때 발생
db file scattered read : Multiblock I/O 방식으로 I/O요청할때 발생

대량의 데이터를 Multiblock I/O방식으로 읽을 때 Single Block I/O보다 성능상 유리한 것은 I/O Call 발생횟수를 줄여주기 때문입니다.

📝바인드 변수 

고정적인 쿼리문이 있을 뿐더러 동적으로 쿼리문이 들어가는 경우도 존재합니다.
이렇게 ?와 같이 동적으로 변하는 부분의 변수는 바인드 변수라고 합니다.
예) select * from tab where id = ? 

 

해당 변수의 목적은 Hard Parse 를 줄이기에 있습니다.
바인드 변수를 사용할 경우 변수의 값이 달라져도 같은 문장으로 인식하기 때문에 불필요한 Hard Parse를 줄일 수 있습니다.

 

SQL 문의 경우 Hard parsing 이 많아지면 자원소모가 많아지며 실행이 느려지게 됩니다.

자바로 설명하겠습니다.

Connection con = null; 
String query = "select * from shop where id = " + id; 

Statement stmt = con.createStatement(stmt); 
ResultSet rs = stmt.executeQuery(); 

이런식으로 코딩하게 될 경우 아래와 같이 쿼리문이 들어가게 됩니다.

select * from shop where id = 1; 
select * from shop where id = 2; 
select * from shop where id = 3; 

다른 문장으로 처리가 되기 때문에 Hard Parse를 하게 되어 느려지게 됩니다.

하지만 아래와 같이 바인드변수를 이용할 경우 모두 같은 실행 계획을 세우게 되고 Soft Parse가 되기 때문에 실행계획을 안 세워서 빠르게 결과를 받을 수 있습니다.
select * from shop where id = ? 

아래와 같은 방식으로 처리할 경우 바인드 변수 처리가 되지 않습니다.
String query = "select * from shop where id = " + id; 
PreparedStatement pstmt = con.prepareStatement(query); 

아래와 같은 형식으로 처리해야 바인드변수 처리가 됩니다. 고로 바인드 변수는 무조건 이용하되 라이브러리가 지원해주는 형식으로 사용하는 방법을 찾아서 써야합니다.
String query = "select * from shop where id = ?" 
PreparedStatement pstmt = con.prepareStatement(query); 
pstmt.setInt(1, id); 

Parse해 실행계획을 처리할 경우 CPU 점유율 차이가 20%나 차이가 난다고 합니다.
또한 바인드 변수 사용할 때 해당 바인드 변수를 이용하는 조건절따위에 인덱스가 걸려있어도 형변환으로 인해 인덱스를 안 탈 수도 있기 때문에 주의해야한다.

 

 

📝SQL 실행 순서

SQL을 입력 받을시 제일 먼저 실행하려고 문법 오류를 검사한다.
그 후 SQL 이전 실행한 적 있는지 메모리(SHARED POOL)를 검사한다 있다면 기존에 실행한 방식으로 실행한다 이것을 SOFT PARSING이라고 한다.
하지만 그와 같은 기록이 없다면 SQL을 어떤 방식으로 처리할 것인지 실행 계획을 세운다. 이것을 HARD PARSING이라고 한다. 그 이후에 SHARED POOL에 실행 게획을 저장한다.

 

📝SQL 동작방식 

 

 

Soft Parse : Parsing  syntax  semantic → Execution  

Hard Parse : Parsing syntax semantic → Query Transformer Estimator → Plan Generator → Execution  

 

Query Transformer

PARSING 과정을 거친 SQL은 PARSING 트리 형태로 변형되어 Query Transformer는 넘겨 받은 SQL을 보고 같은 결과를 도출하되 좀 더 나은 실행 계획을 갖는 SQL로 변형이 가능한지 판단해 변환 작업을 수행
예를 들면 복잡한 서브쿼리나 뷰를 사용한 SQL을 일반적인 조인 형태의 SQL로 변환해 실행 계획을 도출하기 좋은 상태로 만든다.

Estimator

Query Transformer를 통해 변환 작업을 마치고난 SQL은 Estimator로 넘겨지게 되는데 이때 수행하는데 드는 총 비용을 계산한다.

Plan Generator

Estimator를 통해 계산된 값들을 토대로 후보군 실행계획 도출 Row Source Generator를 통해 출력이 가능한 코드 형태로 바꾼다.

 

 

📝실행시간 (Execution time) vs 패치시간 (Fetch time)

실행 시간은 SQL문을 Parse해 실행 계획을 세워 실행하는데까지 걸리는 시간이다.

패치 시간은 실행해서 나온 결과를 전송하는 데 걸리는 시간을 측정한다 (Binary로 전달하기 때문에 네트워크 연결에 의존한다)

 

 

🔗 참고 및 출처

https://blogingming.tistory.com/entry/%EC%8B%A4%ED%96%89%EC%8B%9C%EA%B0%84-Execution-time-vs-%ED%8C%A8%EC%B9%98%EC%8B%9C%EA%B0%84-Fetch-time
 https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=gh2501&logNo=115281737

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=gh2501&logNo=115281737
https://sksstar.tistory.com/89
http://wiki.gurubee.net/display/STUDY/03.+Single+Block+vs+Multiblock+IO 
https://argolee.tistory.com/60

반응형
반응형

📝Server Side Template Engine

페이지 렌더링 전에 필요한 데이터를 모두 받아서 정의된 Template에 넣어 Html을 그려 클라이언트에 전달해준다 → 서버에서 처리함

 

📝Client Side Template Engine

페이지가 모두 렌더링 된 상태에서 필요한 부분만 다시 정의하기 위해서 프론트단에서 HTTP 통신해 데이터를 다시 받아와 그려주는 역할을 한다 → 클라이언트에서 요청 후 다시 그려준다

 

📝Template Engine (템플릿엔진)

HTML만 가지고서 데이터를 받아와 화면에 보여주고 하는 그런 행위는 불가능하다
정해진 템플릿 양식이 있으면 데이터를 받아와 화면에 보여줄 HTML을 재구성해서 보여주는 소프트웨어를 의미한다.

📝템플릿 엔진(Template Engine)의 필요성

  • 많은 코드를 줄일 수 있다
  • 대부분의 Template Engine은 기존의 HTML에 비해서 간단한 문법을 사용한다.
  • 재사용성이 높다
  • 웹페이지 혹은 웹앱을 만들 때 똑같은 디자인의 페이지에 보이는 데이터만 바뀌는 경우가 굉장히 많다.
  • 유지보수에 용이하다
  • 하나의 Template을 만들어 여러 페이지를 렌더링하는 작업에는 또 다른 이점이 있다.

📝템플릿엔진 종류

레이아웃 템플릿 엔진

페이지 마다 include를 두는게 아닌 최상위 레이아웃이 있어서 해당 레이아웃에 Include해서 사용하게 도와준다
페이지 별 Include가 있을 시 헤더 또는 푸터 등의 경로 변경이 있거나 전체적인 레이아웃 구조가 변경될 때 모든 페이지를 다 수정해야하는 불상사를 최상위 레이아웃만 수정해서 간단하게 처리 가능 (모듈화)
예) Apache Tiles

 

텍스트 템플릿 엔진

템플릿 양식에 적절한 데이터를 넣어 결과를 문서에 출력합니다. 
예) JSP, Thymeleaf

 

 

🔗 참고 및 출처

https://gmlwjd9405.github.io/2018/12/21/template-engine.html%EF%BB%BF

반응형
반응형

 

 

"김영한 스프링 입문 - 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술" 내용을 기반으로 작성한 내용입니다.

 

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 강의 | 김영한 - 인프런

김영한 | 웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습

www.inflearn.com

 

 

 

📝초창기 WEB

초창기 WEB이란 정적 데이터만 전달했습니다 그렇기 때문에 동적인 처리가 불가능합니다.

 

📝CGI

그래서 나온 동적 데이터를 처리하는 CGI라는 프로토콜(인터페이스)가 만들어졌습니다.

HTTP에 대한 요청이 있으면 그 요청에 맞게 서버에서 화면을 만들어서 주는 형식이죠

 

하지만 CGI에는 문제가 있습니다.

  1. Request가 있을 때마다 프로세스를 만들기 때문에 메모리 사용량이 많아 과부하현상이 벌어지곤 했습니다.
  2. 같은 결과값이라도 요청 프로세스가 다른 경우 같은 걸 여러개를 만드는 문제가 있었습니다.

 

이러한 이슈를 보완하기 위해서 만들어진 방법이 있습니다.

  1. 프로세스가 아닌 스레드로 처리를 변경했습니다.
  2. 동일한 요청이 있는 경우 실글톤 패턴을 사용합니다.

 

📝Servlet

이러한 점을 보완해서 등장한 것이 Servlet 입니다.

public class WelcomeServlet extends HttpServlet {
	protected void doPost(HttpServletRequest req, 
    					HttpServletResponse res) throws ServletException, IOException{
   		
        // Request의 파라미터를 받는다.(form field를 읽는다)
        String userid = req.getParameter("userid");
        String password = req.getParameter("password");
        
        // Business Logic 처리.
        String result = doSomething(userid, password);
        
        // 결과값을 담은 View 생성.
        String htmlResponse = "<html>";
        htmlResponse += "<h2>Your userid is: " + username + "<br/>";      
        htmlResponse += "Your password is: " + password + "</h2>";    
        htmlResponse += "</html>";	
        
        // 클라이언트에게 결과값 전송.
        PrintWriter writer = res.getWriter();
        writer.println(htmlResponse); 
   }
}

이렇게 서버에 코딩을 하고 HTML 태그도 붙이면 동적인 페이지를 만들 수 있지만 HTML이 엄청 많아질 수록 처리가 너무 힘듭니다. 또한 서버에 부담이 많이 됩니다.

 

 

📝JSP

이러한 유지보수 및 개발 속도를 개선 시키기 위해서 JSP라는게 나오게 됩니다

<% %> 라는 스크립트 영역이 있고 스크립트 안에 있는 건 서버에서 실행하는 형식입니다.

컴파일시 JSP를 Servlet으로 변환시켜줍니다

하기 코드는 위에 Servlet 코드를 JSP로 변환시킨 것입니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Welcome</title>
</head>
<body>
    <%
        // Request의 파라미터를 받는다.(form field를 읽는다)
        String userid = request.getParameter("userid");
        String password = request.getParameter("password");

        // Business Logic 처리.
        String result = doSomething(userid, password);
    %>

<h2>Your userid is: <%= userid %><br/>
Your password is: <%= password %></h2>
</body>
</html>

이러면 익숙한 구조에 빠르게 개발할 수 있는 구조이지요

 

초창기 서블릿, JSP는 성능이 너무 안 좋았습니다. 속도 수준이 PHP >= ASP >>>> JSP 수준이였고 JDBC의 성능도 최악 JVM 성능도 최악이었습니다 그러다 보니 High Cost인 DB 연결을 DBCP (Connection Pool)을 도입 및 고도화로 인해 PHP = JSP > ASP 까지 끌어 올렸습니다

 

 

📝J2EE & Java EE

J2EE 및 JavaEE의 경우 어플리케이션을 만들기 위해 필요한 스펙의 집합으로 다양한 구성요소가 있습니다 → Servlet, JSP, EJB, JNDI, JMS, JDBC 등

하지만 EJB(Enterprise Java Beans)라는 기술이 핵심인데 사용하다보니 너무 불편했고 그로 인해 사람들을 무료면서 불편사항들을 모두 해결할 수 있는 Spring을 사용하게 됩니다.

 

 

📝Spring (MVC 패턴)

JSP의 가장 안 좋은 점은 비즈니스 코드 + 화면 코드 + 모델(POJO)가 한군데 모여있다는 점으로 유지보수가 매우 힘들다는 점이 있습니다. 그 외에 데이터베이스 연동 세션 관리등 많은 문제점을 개선한 Spring FrameWork가 나오게 됩니다.

Spring MVC의 경우 Model View Controller로 분리 시켜서 프로젝트의 유지보수 및 개발 생산성을 높여주는 역할을 합니다. 또한 의존성 주입(DI), IoC를 이용해 더 효율적인 비즈니스 로직을 이용할 수 있게합니다.

 

 

MVC 변화 1

// @WebServlet은 URL 접근경로와 이름을 설정해서 URL로 접근할 수 있게 해주는 역할입니다.
@WebServlet(name = "mvcMemberSaveServlet", urlPatterns = "/servlet-mvc/members/save") 
public class MvcMemberSaveServlet extends HttpServlet {

    private MemberRepository memberRepository = MemberRepository.getInstance();

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String username = request.getParameter("username");
        int age = Integer.parseInt(request.getParameter("age"));
        Member member = new Member(username, age);
        System.out.println("member = " + member);

        memberRepository.save(member);
        //Model에 데이터를 보관한다.
        request.setAttribute("member", member);

        String viewPath = "/WEB-INF/views/save-result.jsp";
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request, response);

    }
}

Data Model과 로직을 컨트롤러에 두고 View를 JSP로 분리시켜 명확하게 역할이 구분 되지만 중복이 많고 필요하지 않는 코드들도 많이 보입니다.

 

⚠️단점

 

  • forward로 model 정보를 view에 전달하는 코드가 각 controller마다 존재하는 중복 코드
  • jsp가 아닌 thymeleaf같은 다른 템플릿 엔진으로 변경시 코드 전체 수정 필요
  • request, response객체가 필요 없는 곳에서도 반드시 사용해야하며 테스트 코드 작성도 어려움
  • 공통코드가 있을 때 forward처럼 각 controller마다 다 입력해야 함

 

 

MVC 변화 2

MVC 변화 1의 문제점을 해결하기 위해서는 FrontController 패턴을 도입해 공통코드를 앞에서 다 처리하게끔 한다.

 

/** ──── Front Controller ──── **/
@WebServlet(name = "frontControllerServletV1", urlPatterns = "/front-controller/v1/*")
public class FrontControllerServletV1 extends HttpServlet {
    private Map<String, ControllerV1> controllerMap = new HashMap<>();
    
    // controller mapping 관리
    public FrontControllerServletV1() {
        controllerMap.put("/front-controller/v1/members/new-form", new MemberFormControllerV1());
        controllerMap.put("/front-controller/v1/members/save", new MemberSaveControllerV1());
        controllerMap.put("/front-controller/v1/members", new MemberListControllerV1());
    }
    
    
    // front controller service (공통 처리)
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("FrontControllerServletV1.service");
        String requestURI = request.getRequestURI();
        ControllerV1 controller = controllerMap.get(requestURI);
        
        if (controller == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
    	}
        
    	controller.process(request, response);
    }
}



/** ──── Controller Interface ──── **/
public interface ControllerV1 {
	void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}


/** ──── Controller ──── **/
public class MemberListControllerV1 implements ControllerV1 {
    private MemberRepository memberRepository = MemberRepository.getInstance();

    @Override
    public void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Member> members = memberRepository.findAll();
        request.setAttribute("members", members);
        String viewPath = "/WEB-INF/views/members.jsp";
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request, response);
    }
}

FrontController에서 Controller랑 매핑시킬 Map을 만듭니다. 그리고 공통 처리에 필요한 건 service에 작성합니다.

service에서 공통적으로 처리하기 위해 Controller Interface를 상속받아 구체적인 Controller에 구현합니다.

 

요약하면 사용자가 FrontController에 있는 URL Pattern에 해당하는 URL을 요청하면 service 함수가 작동하고 service에 있는 공통 처리 이후에 controllerMap에서 해당 URL에 해당하는 값을 찾아 해당 상세 controller를 실행(process 함수)시킵니다.

 

⚠️단점

  • view로 이동시키는 forward 공통코드 분리 필요

 

MVC 변화 3

/** ──── Front Controller ──── **/
@WebServlet(name = "frontControllerServletV2", urlPatterns = "/front-controller/v2/*")
public class FrontControllerServletV2 extends HttpServlet {
    private Map<String, ControllerV2> controllerMap = new HashMap<>();

    public FrontControllerServletV2() {
        controllerMap.put("/front-controller/v2/members/new-form", new MemberFormControllerV2());
        controllerMap.put("/front-controller/v2/members/save", new MemberSaveControllerV2());
        controllerMap.put("/front-controller/v2/members", new MemberListControllerV2());
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String requestURI = request.getRequestURI();
        ControllerV2 controller = controllerMap.get(requestURI);

        if (controller == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        MyView view = controller.process(request, response);
        view.render(request, response);
    }
}


/** ──── MyView ──── **/
public class MyView {
    private String viewPath;
    
    public MyView(String viewPath) {
        this.viewPath = viewPath;
    }
    
    public void render(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    	RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request, response);
    }
}

/** ──── Controller Interface ──── **/
public interface ControllerV2 {
	MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}

/** ──── Controller ──── **/
public class MemberListControllerV2 implements ControllerV2 {
    private MemberRepository memberRepository = MemberRepository.getInstance();
    
    @Override
    public MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Member> members = memberRepository.findAll();
        request.setAttribute("members", members);
        return new MyView("/WEB-INF/views/members.jsp");
    }
}

dispatcher.forward로 해당 view로 화면 전환시키는 과정이 중복되게 되는데 이걸 분리시켜 공통작업인 FrontController에게 위임합니다. (render 함수) 상세 Controller에서 처리한 view정보를 MyView라는 객체에 담아서 반환해줍니다.

 

 

⚠️단점

  • Request, Response 객체 필요 없을 때도 사용해야 함 → 서블릿 종속 제거
  • 뷰의 공통 Path 중복 제거 → WEB-INF/views

 

MVC 변화 4

/** ──── Front Controller ──── **/
@WebServlet(name = "frontControllerServletV3", urlPatterns = "/front-controller/v3/*")
public class FrontControllerServletV3 extends HttpServlet {

    private Map<String, ControllerV3> controllerMap = new HashMap<>();
    
    public FrontControllerServletV3() {
        controllerMap.put("/front-controller/v3/members/new-form", new MemberFormControllerV3());
        controllerMap.put("/front-controller/v3/members/save", new MemberSaveControllerV3());
        controllerMap.put("/front-controller/v3/members", new MemberListControllerV3());
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String requestURI = request.getRequestURI();
        ControllerV3 controller = controllerMap.get(requestURI);
        
        if (controller == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        Map<String, String> paramMap = createParamMap(request);
        ModelView mv = controller.process(paramMap);
        String viewName = mv.getViewName();
        MyView view = viewResolver(viewName);
        view.render(mv.getModel(), request, response);
    }

    private Map<String, String> createParamMap(HttpServletRequest request) {
        Map<String, String> paramMap = new HashMap<>();
        request.getParameterNames()
               .asIterator()
               .forEachRemaining(paramName -> paramMap.put(paramName, request.getParameter(paramName)));

        return paramMap;
    }

    private MyView viewResolver(String viewName) {
        return new MyView("/WEB-INF/views/" + viewName + ".jsp");
    }
}


/** ──── ModelView ──── **/
public class ModelView {
    private String viewName;
    private Map<String, Object> model = new HashMap<>();
    
    public ModelView(String viewName) {
        this.viewName = viewName;
    }
    
    public String getViewName() {
        return viewName;
    }
    
    public void setViewName(String viewName) {
        this.viewName = viewName;
    }
    
    public Map<String, Object> getModel() {
        return model;
    }
    
    public void setModel(Map<String, Object> model) {
        this.model = model;
    }
}

/** ──── MyView ──── **/
public class MyView {
    private String viewPath;
    
    public MyView(String viewPath) {
        this.viewPath = viewPath;
    }
    public void render(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

	RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request, response);
    }
    
    public void render(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        modelToRequestAttribute(model, request);
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request, response);
    }

    private void modelToRequestAttribute(Map<String, Object> model, HttpServletRequest request) {
        model.forEach((key, value) -> request.setAttribute(key, value));
    }
}


/** ──── Controller Interface ──── **/
public interface ControllerV3 {
    ModelView process(Map<String, String> paramMap);
}


/** ──── Controller ──── **/
public class MemberSaveControllerV3 implements ControllerV3 {
    private MemberRepository memberRepository = MemberRepository.getInstance();
    
    @Override
    public ModelView process(Map<String, String> paramMap) {
        String username = paramMap.get("username");
        int age = Integer.parseInt(paramMap.get("age"));
        Member member = new Member(username, age);
        memberRepository.save(member);
        
        ModelView mv = new ModelView("save-result");
        mv.getModel().put("member", member);
        
        return mv;
    }
}

서블릿종속을 제거하기 위해 데이터를 담는 곳을 Request, Response가 아닌 별도의 Model에 담는다. (ModelView = View에 해당하는 모델정보와 View정보가 들어간다) 또한 별도 Model을 분리시킨 ModelView를 가지고 Render하기 위해서 ModelView를 매개변수로 받는 MyView에서 Render함수를 추가 작성합니다.

공통 Path 중복코드를 제거하기 위해 FrontController의 viewResolver를 통해 뷰 공통 Path를 제거시킵니다.

 

 

 

🔗 출처 및 참고

https://charliecharlie.tistory.com/248

https://jhyonhyon.tistory.com/27

 

 

 

 

반응형
반응형

📝EJB

기업환경의 시스템을 구현하기 위한 서버측 컴포넌트 모델이다. 
즉, EJB는 애플리케이션의 업무 로직을 가지고 있는 서버 애플리케이션이다. 
EJB 사양은 Java EE의 자바 API 중 하나로 주로 웹 시스템에서 JSP는 화면 로직을 처리하고, EJB는 업무 로직을 처리하는 역할을 한다

스프링과 같이 백엔드 프레임워크라고 생각하면 쉽다

📝JBoss

Jboss란 Red Hat의 자회사인 Jboss가 개발한 Jboss Application Server이다 EJB를 포함해 트랜잭션 처리, 보안 분산 컴퓨팅등의 기능을 제공해주는 서버측 컴포넌트 모델

📝Jboss와 Tomcat의 차이점

Jboss와 Tomcat은 모두 Java Servlet Application 서버지만 Jboss는 훨씬 더 기능이 많다. 이 둘의 가장 큰 차이점은 Jboss가 EJB 및 엔터프라이즈 Java 응용 프로그램에서 작업하는 개발자에게 유용한 기타 기술을 포함하여 완전한 Java Enterprise Edition(JEE) 스택을 제공한다는 것이다

Tomcat은 훨신 더 제한적이다

Jboss가 Servlet Container와 Web server를 포함하는 JEE 스택인 반면 Tomcat은 대부분 Servlet Container와 Web Server이다

📝J2EE

J2EE (Java 2 Platform, Enterprise Edition)는 서버용 Java 플랫폼인 Java EE의 이전 이름
자바 기술로 기업환경의 어플리케이션을 만드는데 필요한 스펙들을 모아둔 스펙 집합 → 프레임워크
JSP, EJB, JDBC, RMI, JNDI 등 제공

📝자카르타 EE

이전에는 J2EE라 불리었으나 버전 5.0 이후로 Java EE로 개칭되었으며 2017년 프로젝트가 이클립스 재단으로 이관됨에 따라 자카르타EE로 변경되었다.


반응형
반응형

📝러닝 커브(Learning Curve)

학습 곡선을 의미하며 특정 기술 또는 지식을 업무에 적용 시키는데 까지 드는 비용(시간)을 의미하기도 합니다.

 

📝Entity

엔터티(Entity)는 업무에 필요하고 유용한 정보를 저장하고 관리하기 위한 "어떤 것(Thing)"
간단하게는 데이터베이스 테이블

 

📝웹 어플리케이션 아키텍쳐 

웹 서비스를 할 때 어떤식으로 데이터가 흐르는지 방화벽 등에 대한 구조를 도식화 한 것

 

📝Stateless (무상태)

HTTP는 비연결성과 상태 없음이란 특징지닌다

어떠한 상태(state)를 계속 지니고 있지 않고 요청(request)를 보내고 응답(response)를 받으면 그것으로 끝이라는 특징이다.

 

 

📝UDF (사용자 정의함수)

사용자 정의 함수는 미리 제공되는 것이 아니라 사용자가 직접 정의하여 사용하는 함수를 의미

 

 

🔗 참고 및 출처

https://kim-dragon.tistory.com/235

 

 

 

반응형
반응형

📝도메인형 패키지 (DDD)

com
  └ lsj
      └  shopping_mall
 	  	  └ dashboard
		  |	  └  controller
		  |	  └  service
		  |	  └  dao
		  |	  └  dto
		  |	      └ request
		  |	      └ response
		  |	  └  util
		  |	  └  exception
		  |	  
		  |
		  └ global
		        └ config
		        └ user
		        └ exception
		        └ jwt
		        └ util (공통 API)

dao 구조

 

com
  └ lsj
      └  shopping_mall
 	  	  └ dashboard
		  |	  └  controller
		  |	  └  service
		  |	  └  repository
		  |	  └  entity
		  |	  └  dto
		  |	      └ request
		  |	      └ response
		  |	  └  util
		  |	  └  exception
		  |	  
		  |
		  └ global
		        └ config
		        └ user
		        └ exception
		        └ jwt
		        └ util (공통 API)

repository + jpa 구조

 

DDD(Domain-Driven Design)는 소프트웨어 개발 방법론으로 비즈니스 도메인에 초점을 맞추어 시스템을 설계하는 접근 방식

 

💗장점

높은 응집력과 낮은 결합도로 변경과 확장에 용이한 설계

 

⚠️단점

프로젝트에 대한 이해도가 낮을 경우 전체적인 구조를 파악하기 어려움 → 이게 더 이해가 쉽던데.. 잘 모르겠음

 

📝계층형 패키지

├── java
│   └── com
│       └── 11bun
│           └── shopping
│               ├── config
│               ├── controller
│               ├── dao
│               ├── exception
│               └── service
└── resources
    └── application.properties

각 계층을 대표하는 디렉터리를 기준으로 코드들이 구성이 되는데 아래 디렉토리 구조를 보면 더 이해가 쉽다 →  controller, service, dao 한 곳에 다 모여있는 구조

 

💗장점

프로젝트에 이해가 상대적으로 낮아도 전체적인 구조를 빠르게 파악 가능 → 개인적으로 DDD보다 파악이 어려워 보임

 

⚠️단점

계층형 같은 경우 Controller, Service 등에 너무 많은 클래스들이 밀집되어 파악하기 힘들다 

 

📝DAO(Data Access Object), Repository

DB의 데이터를 접근하기 위한 객체로 일반적으로 단일 쿼리문에 대한 내용만 담고 있습니다.

 

📝DTO (Data Transfer Object), VO(Value Object)

계층 간 데이터 교환을 하기 위해 사용하는 객체
로직을 가지지 않는 순수한 데이터 객체(getter & setter만 가진 클래스)이다

📝R&R (알앤알)

역할과 책임인 Role & Responsibility 약자로 담당자끼리 수행할 업무를 나누는 것을 의미한다.
예) 알앤알은 정하고 진행하는거야?

📝벤더 (vendor)

제품 판매인 또는 판매업체로 판매한 제품에 대해 책임을 지는 곳을 가리킨다 → 물품을 공급한 곳
벤더는 제품을 제조한 곳일 수도 있고. 다른 회사 제품을 판매만 하는 곳일 수도 있다
예) 그 솔루션은 벤더사에서 지원을 중단했다

 

 

🔗 참고 및 출처

https://cheese10yun.github.io/spring-guide-directory/#:~:text=%EA%B3%84%EC%B8%B5%ED%98%95,-1&text=%EA%B3%84%EC%B8%B5%ED%98%95%20%EA%B5%AC%EC%A1%B0%EB%8A%94%20%EA%B0%81,%EB%A7%8E%EC%9D%B4%20%EB%AA%A8%EC%9D%B4%EA%B2%8C%20%EB%90%98%EB%8A%94%20%EC%A0%90%EC%9E%85%EB%8B%88%EB%8B%A4.

반응형
반응형

 

📝CMS (Content Management System)

직관적으로 관리할 수 있는 대시보드가 마련되어 코딩에 대한 지식이 전혀 없는 사람이라도 웹 상에서 콘텐츠를 생성, 수정, 삭제할 수 있다는 장점으로 "워드프레스"가 대표적이다.

 

 

📝간트 차트

프로젝트 일정관리를 위한 바(bar)형태의 도구

 

 

 

📝애자일 방법론

애자일 방법론 이란 "Agile = 기민한, 날렵한" 이란 뜻으로 좋은 것을 빠르게 취하고, 낭비 없게 만드는 다양한 방법론

계획 → 설계(디자인) → 개발(발전) → 테스트 → 검토(피드백) 순으로 반복적으로 진행 계획을 세운 후 다음 단계까지 기다려서 절차대로 진행하는 폭포수 모델과 달리 먼저 진행 후 분석, 시험, 피드백을 통하여 개선하여 나가는 진행 모델

 

💗장점

  1. 프로젝트 계획에 걸리는 시간을 최소화
  2. 점진적으로 테스트할 수 있어서 버그를 쉽고 빠르게 발견
  3. 계획 혹은 기능에 대한 수정과 변경에 유연
  4. 고객 요구사항에 대한 즉각적인 피드백에 유연하며 프로토타입 모델을 빠르게 출시
  5. 빠듯한 기한의 프로젝트를 빠르게 출시

 

⚠️단점

  1. 확정되지 않은 계획 및 요구사항으로 인한 반복적인 유지보수 작업이 많다
  2. 고객의 요구사항 및 계획이 크게 변경되면 모델이 무너질 수 있다
  3. 개인이 아닌 팀이 중심이 되다 보니 공통으로 해야 할 작업이 많을 수 있다 → 회의, 로그 등
  4. 반복적인 업무로 속도는 빠를 수 있으나 미흡한 기능들에 대한 대처가 필요하다
  5. 확정되지 않은 계획으로 개발 진행 시 이해하지 못하고 진행하는 부분이 많을 수 있다

 

📝가상쓰레드

하나의 물리적인 스레드를 이용하여 여러 개의 가상 스레드를 생성한다

자바 16에서 실험적으로 시작되었고 19버전에서 크게 변화가 되었다.
하나의 물리적 스레드를 여러 개의 스레드로 나눠서 자원을 최대한 활용한다.

// 예시
package com.infoworld;
import java.util.Random;

public class App { 
    public static void main( String[] args ) {  
        boolean vThreads = args.length > 0;
        System.out.println( "Using vThreads: " + vThreads);  
        long start = System.currentTimeMillis();
        Random random = new Random();  
        Runnable runnable = () -> { 
            double i = random.nextDouble(1000) % random.nextDouble(1000); 
        };   
        
        for (int i = 0; i < 50000; i++) { 
            if (vThreads){
                Thread.startVirtualThread(runnable);
            } else {    
                Thread t=new Thread(runnable);
                t.start();   
            }  
        } 
        
        long finish=System.currentTimeMillis();
        long timeElapsed=finish - start;
        System.out.println("Runtime: " + timeElapsed); 
    }
}
 
 

🔗 참고 및 출처

https://gentlysallim.com/cms%EB%9E%80-%EB%AD%90%EA%B3%A0-%EC%9B%B9%EC%82%AC%EC%9D%B4%ED%8A%B8-%EB%B9%8C%EB%8D%94%EB%9E%80-%EB%AD%90%EC%9E%84/http://www.hippochart.com/gallery/galcategory.aspx?cate=charttype&type=Gantt&idx=135%EF%BB%BF

https://www.ciokorea.com/t/21999/%EA%B0%9C%EB%B0%9C%EC%9E%90/263380#:~:text=%EA%B0%80%EC%83%81%20%EC%93%B0%EB%A0%88%EB%93%9C%EB%8A%94%20%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%20%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4,%EC%A4%91%EC%9E%AC%ED%95%98%EB%8A%94%20%EC%97%AD%ED%95%A0%EC%9D%84%20%ED%95%9C%EB%8B%A4.

 

 

 

 

 

 

 

반응형
반응형

📝세션 변조를 이용한 불법 로그인

로그인시 WAS에 세션을 만들고 해당 세션에 대한 정보(로그인 정보, 장바구니 등)는 서버에 저장되지만 해당 유저가 어떤 유저인지에 대한 키가 있어야합니다. 그래서 계속적인 체크를 위해서 해당 키를 쿠키에 저장해서 사용자에게 보냅니다

그리고 데이터 및 서비스를 요청할때마다 세션의 쿠키의 ID를 같이 보냅니다

이러한 과정에서 해당 Session ID 값인 쿠키를 탈취하게 되어서 내쪽에 입력하게 되면 해당 아이디로 로그인이 되거나 해당 사용자가 이용한 것들(장바구니 등...)을 사용할 수 있게 됩니다

 

이러한 것들을 훔치기 위해서 XSS같은 공격을 사용해 Javascript를 실행하게 쿠키를 읽게하는 스크립트를 이용해 훔쳐갈 수 있습니다

 

방지 방법으로 다양하게 있습니다

  1. 웹 방화벽 사용 (제품이라 돈 필요)
  2. 보안 장비에 쿠키 값 변조 감지 제품 있음 (제품이라 돈 필요)
  3. 쿠키 변조 탐지 및 단순 쿠키 체크가 아닌 다양한 2차 인증 과정 구현

뭐 위에 3가지도 누군가 개발을 한 거이기 때문에 결국엔 개발이 필요합니다

관리자페이지에서 F12로 들어가서 보면 JSESSIONID라는 키로 확인이 가능합니다

반응형
반응형

http://web.cs.ucla.edu/classes/winter13/cs111/scribe/10b/

📝하드디스크 (HDD)

컴퓨터의 보조 기억 장치이다.

하드디스크는 실린더의 집합으로 되어있다.

 

📝구성

  • Platter (플래터)
    • 데이터가 기록되어있는 원판
  • Spindle (스핀들)
    • 플래터를 회전 시킵니다.
  • Actuator Arm (액츄에이터 암)
    • 디스크를 가로 질러 헤드를 움직이고, 원하는 트렉으로 헤드가 찾아가게 하는 장치
  • Head (헤드)
    • 실질적으로 데이터를 읽는 부분
  • Sector (섹터)
    • 데이터 저장할 수 있는 구역을 나눠 놓은 것
  • Track (트랙)
    • 섹터의 집합
  • Cylinder (실린더)
    • 트랙의 집합
  • Boom (붐)
    • 실린더를 선택한다

 

📝동작원리

Boom이 Cylinder를 선택하고 원하는 Sector에 Head를 가져다 놓아서 읽을 수 있도록 Spindle이 회전시킵니다.

그렇기 때문에 물리적으로 찾아가는 시간이 있어서 느립니다

 

https://www.utmel.com/blog/categories/memory%20chip/solid-state-drive-ssd-classification-and-architecture

 

📝SSD (Solid State Drive)

SSD는 모든 구조가 메모리로 되어있는 보조기억장치이다.

 

📝동작원리

전압을 주어서 전자를 메모리 셀에다가 채우고 비우고를 하는 과정으로 데이터를 쓰기, 삭제, 읽기한다 → 메모리와 비슷하게 동작

 

📝Jinja

Jinja는 Python 프로그래밍 언어용 웹 템플릿 엔진입니다 → 템플릿태그 JSTL과 유사

 

📝SQLAlchemy

Python의 ORM

 

📝WebSocket

실시간 양방향 통신을 제공하는 프로토콜입니다

WebSocket을 사용하면 서버와 클라이언트 간에 지속적인 연결을 유지하며 데이터를 실시간으로 주고받을 수 있습니다

이는 푸시 알림, 채팅, 주식 시세 업데이트 등과 같은 상황에서 특히 효과적입니다

WebSocket은 이벤트 리스너를 사용하여 간단히 이벤트를 수신하고 데이터를 전송할 수 있습니다

가상화폐 거래소와 같이 데이터 양이 많은 경우에도 효율적으로 동작하며 업비트나 바이낸스 소켓 API와 같은 서비스에서는 대용량의 실시간 데이터를 처리할 수 있습니다

 

📝Socket.io

WebSocket을 기반으로 한 실시간 웹 소켓 라이브러리입니다 → Javascript 라이브러리

더 쉽게 사용하고 여러 기능을 추가로 제공하는 데 중점을 둔 것이 특징입니다

프론트에서 이벤트 핸들링한다고 생각하시면 됩니다 물론 백엔드 소켓 서버가 존재해야합니다

 


🔗 참고 및 출처
https://velog.io/@davidko/Web-Socket-%EC%9D%B4%EB%9E%80

 

Web Socket 이란?

web socket이란

velog.io

https://inpages.tistory.com/72

 

프로그래밍 언어에서 Syntax와 Semantics의 차이는 무엇인가?

요약Syntax는 문장이 언어으 문법(grammar)에 따라 유효하진 혹은 타당한지 아닌지 확인하는 것과 관련있다.Semantics는 문장이 타당한 의미를 지니는지 아닌지를 판별하는 것과 관련있다. 조금 더 자

inpages.tistory.com

https://duzi077.tistory.com/19

 

[하드웨어] SSD 동작방식 요약

# SSD 동작 방식 전압을 주어서 전자를 메모리 셀에다가 채우고 비우고를 하는 과정으로 데이터를 쓰기, 삭제, 읽기를 한다. 절연체인 산화막에 같혀있어서 전자가 빠져나가지 않고 그 안에 유지

duzi077.tistory.com

 

반응형