반응형
반응형
package com.lsj.blog;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.lsj.blog.repository.UserRepository;
import com.lsj.dto.ResponseDto;

@RestController
public class DummyController {

	@Autowired // DI
	private UserRepository userRepository;
	
	@PostMapping("/api/login")
	public ResponseDto<Integer> login(@RequestBody BlogUser user, HttpSession session){
		
		BlogUser principal = loginService(user); //principal (접근주체)
		if(principal != null) session.setAttribute("principal", principal);
		
		System.out.println("principal : " + session.getAttribute("principal"));
		
		return new ResponseDto<Integer>(HttpStatus.OK.value(), 1);
		
	}
	
	@Transactional(readOnly = true) // Select 할 때 트랜잭션 시작, 서비스 종료시 트랜잭션 종료 (데이터 일관성)
	public BlogUser loginService(BlogUser user) {
		return userRepository.findByUsernameAndPassword(user.getUsername(), user.getPassword());
	}
}
package com.lsj.blog.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import com.lsj.blog.BlogUser;


// extends JapRepository가 있는 경우 @Repository 생략가능
// JpaRepostiory는 다양한 기능을 가지고 있다. findAll (모든 레코드 select) 페이징해서 보내줄 수 있는 기능도 존재
public interface UserRepository extends JpaRepository<BlogUser, Integer>{ // BlogUser의 Repository이고 PK는 Integer이다.
	
	// JPA Naming 쿼리
	// SELECT * FROM bloguser WHERE username = ? AND password = ?;
	// SELECT * FROM ${리턴타입} WHERE username = ${첫번째 파라미터} AND password = ${두번째 파라미터};
	BlogUser findByUsernameAndPassword(String username, String password);
	
	// nativeQuery 방식 위와 동일하다
	@Query(value="SELECT * FROM bloguser WHERE username =1 ? AND password = 2?", nativeQuery = true)
	BlogUser login(String username, String password);
}
반응형
반응형

오라클의 경우 Read Commit 방식을 채택한다.

트랜잭션A가 시작되어 Update를 할 경우 Commit이 이루어질 때까지 UnDo의 영역을 읽기 때문에 Update하고 Commit의 사이에서 누군가 select할 시 1,000원이 출력된다.

 

트랜잭션A가 진행되면 누군가한테는 홍길동 누군가한테는 1,000원 누군가한테는 2,000원이 보일 수 있다.

이런식으로 보일 수 있기 때문에 정합성이 깨진다 → Phantom Read (데이터가 보였다 안 보였다)

 

이러한 점의 문제점은 트랜잭션 B와 같이 조회한 4개를 더해서 총 합을 구하는 시스템이라면 도중에 원래 기대값이 4,000원이지만 6,000원이 나오는 문제가 생긴다.

 

 

MySQL의 경우 Repeatable Read 방식을 채용한다.

UnDo 영역에 데이터를 읽고 자기 트랜잭션 번호보다 낮은 데이터를 읽기 때문에 중간에 Update를 해도 데이터의 일관성을 지킬 수 있다.

 

Insert, Select, Update, Delete의 경우 모두 @Transactional 이 필요하다

반응형
반응형
package com.lsj.blog;

import java.util.Random;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.lsj.blog.model.RoleType;
import com.lsj.blog.repository.UserRepository;
import com.lsj.dto.ResponseDto;

@RestController
public class DummyController {

	@Autowired // DI
	private UserRepository userRepository;
	
	@PostMapping("/api/user")
	@Transactional
	public ResponseDto<String> save(@RequestBody BlogUser user){

		BlogUser usre2 = new BlogUser();
		
		Random random = new Random();

		usre2.setUsername(String.valueOf(random.nextInt(10)));
		usre2.setPassword("12345"); 
		usre2.setEmail("abc@naver.com");
		userRepository.save(usre2); 
			
		new ResponseDto<String>(HttpStatus.OK.value(), "데이터 insert에 성공했습니다.");
		// HttpStatus.OK.value() → 200이라는 코드 반환 (정상 성공)
	}
}
package com.lsj.blog.handler;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

import com.lsj.dto.ResponseDto;

@ControllerAdvice // 어떤 Exception이 오든 이 페이지로 오게 된다.
@RestController
public class GlobalExceptionHandler {
	
	@ExceptionHandler(value=Exception.class) // 모든 부모 Exception
	public ResponseDto<String> handleException(Exception e) {
		return new ResponseDto<String>(HttpStatus.INTERNAL_SERVER_ERROR.value(),e.getMessage());
		// HttpStatus.INTERNAL_SERVER_ERROR.value() → 500 코드 반환 (서버 에러)
		//return "<h1>" + e.getMessage() + "</h1>";
	}
}
package com.lsj.dto;

import org.springframework.http.HttpStatus;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ResponseDto<T> {
	int status;
//	HttpStatus status;
	T data;
}

 

반응형
반응형

📝텍스트 파일로만 페이지 띄우기

tomcat path : C:\tomcat9
server.xml path : C:\tomcat9\conf\server.xml

<Host name="localhost"  appBase="webapps" unpackWARs="true" autoDeploy="true">
    <Context path="it" docBase="C:\tomcat9\webapps\ITWeb" privileged="true"/>
    ....


페이지에 띄울 텍스트파일 경로 : C:\tomcat9\webapps\ITWeb\nana.txt
nana.txt 내용 : 안녕하세요
페이지 호출 URL : http://localhost:8080/it/nana.txt

 

 

📝클래스 파일 직접 만들어서 페이지 띄우기

test.java 

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class test extends HttpServlet {
 public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
 {
  System.out.println("hello Servlet");
 }
}
1. cmd test.java 있는 경로로 이동
2. class 파일 만들기 → javac -cp C:\tomcat9\lib\servlet-api.jar test.java

3. 호출하기 위한 설정파일 수정 (web.xml) [WEB-INF안에 있는 파일은 직접 요청이 불가능하다.]
   WEB-INF 호출하기 위한 설정 파일 경로 : C:\tomcat9\webapps\ROOT\WEB-INF\web.xml
   실행시킬 class파일 : C:\tomcat9\webapps\ROOT\WEB-INF\classes\test.class

web.xml 내용

<servlet>
<servlet-name>testing</servlet-name>
<servlet-class>test</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>testing</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>


→
hello라는 url 요청이 오면 testing이라는 서블릿의 이름을 가진 애를 실행시키라는 의미
testing이라는 이름을 가지는 서블릿의 클래스파일은 test이다


이렇게 매핑정보를 xml으로 할수도 있지만(2.x) annotation(3.x)으로도 사용 가능하다.

annotation 방식을 이용하고 싶을 경우 metadata-complete를 false로 바꿔야한다.
경로 : C:\tomcat9\webapps\ROOT\WEB-INF\web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  version="4.0"
  metadata-complete="false">



반응형
반응형

 

package runnable_jar;

import java.text.SimpleDateFormat;
import java.util.Date;

public class ThreadGroupExample {

	public static void main(String[] args) {

		Date today = new Date();
		SimpleDateFormat yyyymmddForamt = new SimpleDateFormat("yyyyMMdd");
		
		String todayDate = yyyymmddForamt.format(today); 
		String date = "20221201";
		
		System.out.println("todayDate : " + todayDate); // 20221201
		
		int compare = todayDate.compareTo(date);

		// A.compareTo(B) 
		// A = B  → 0
		// A < B  → -1
		// A > B  → 1
		
		if     (compare > 0) System.out.println("date 날짜는 오늘 날짜 이전입니다."); 
		else if(compare < 0) System.out.println("date 날짜는 오늘 날짜 이후입니다.");
		else                 System.out.println("date 날짜는 오늘 날짜와 동일합니다.");
	}

}

// 출처 : https://soraji.github.io/java/2019/04/15/compareDATE/
package runnable_jar;

import java.text.SimpleDateFormat;
import java.util.Date;

public class ThreadGroupExample {

	public static void main(String[] args) {

		Date today = new Date();
		SimpleDateFormat yyyymmddForamt = new SimpleDateFormat("HHmmss");
		
		String todayTime = yyyymmddForamt.format(today); 
		String time = "224246";
		
		System.out.println("todayTime : " + todayTime); // 20221201
		
		int compare = todayTime.compareTo(time);

		// A.compareTo(B) 
		// A = B  → 0
		// A < B  → -1
		// A > B  → 1
		
		if     (compare > 0) System.out.println("time < 현재 시각"); 
		else if(compare < 0) System.out.println("time > 현재시각");
		else                 System.out.println("time = 현재시각");
	}

}
반응형
반응형

📝1. keysotre 파일 생성 (SSL인증서)

1. cmd 관리자 권한으로 실행
2. cd ${jdk/bin경로}
3. 하기 명령어 입력
keytool -genkey -alias tomcat -keyalg RSA -keystore tomcat.keystore
설명 : keytool -genkey -alias tomcat -keyalg RSA -keystore ${keystore 파일명}

4. 하기 내용 입력하기

키 저장소 비밀번호 입력:
새 비밀번호 다시 입력:
이름과 성을 입력하십시오.
[Unknown]: 
조직 단위 이름을 입력하십시오.
[Unknown]:
조직 이름을 입력하십시오.
[Unknown]: 
구/군/시 이름을 입력하십시오?
[Unknown]:
시/도 이름을 입력하십시오.
[Unknown]: seoul
이 조직의 두 자리 국가 코드를 입력하십시오.
[Unknown]: KR
N=maruara, OU=Unknown, O=Unknown, L=Unknown, ST=seoul, C=KR이(가) 맞습니까?
[아니오]: y
tomcat>에 대한 키 비밀번호를 입력하십시오.
(키 저장소 비밀번호와 동일한 경우 Enter 키를 누른다):

 

📝2. tomcat의 server.xml에서 https 설정하기

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystorePass="gkgkgk" keystoreFile="d:/openssl/tomcat.keystore"/>

port → https 통신 포트
keystorePass → 위에서 설정한 패스워드
keystoreFile → ssl 인증서 경로
반응형
반응형

CALL  

  1. 사용자 웹브라우저 URL 호출

DNS  

  1. DNS 방문
  2. DNS가 알려준 해당 아이피 주소로 이동 

3 Ways Handshake   

  1. 웹브라우저가 서버에 임의의 값을 건네준다
  2. 서버가 1을 더해 다시 웹브라우저에게 돌려준다
  3. 웹브라우저가 다시 1을 더해 웹브라우저에게 돌려준다 (3-ways handshake)

 

Request & Response 

  1. 서버에게 데이터 요청 (HTTP Request)
  2. 서버가 데이터를 준다 (HTTP Response)

DOM Tree

  1. W3C 명세에 따라 HTML과 CSS 해석 (Parsing)HTML 해석해 DOM Tree 생성
    1. CSS를 찾을 경우 DOM Tree 작업을 일시 중단하고 CSS Parsing 작업을 해 CSSOM Tree 생성
    2. 스크립트(JS)를 찾을 경우 Tree 생성 작업을 일시 중단하고 JS Engine 기동 해 AST(Abstract Syntax Tree) 생성
  2. Parsing이 끝나면 CSSOM Tree  + DOM Tree를 합쳐 Render Tree를 생성

Rendering

  1. 랜더링엔진이 Layout 작업 실시 (화면에 그릴 장소 체크)UI Backend가 Layout 작업이 실시된 곳에 UI를 그린다
  2. 레이어의 z-index를 기준으로 위치 재배치 (composition)
  3.  
  1. 웹 브라우저는 모든 데이터를 다 Parsing한 후에 이루어지는 것이 아니라 중간 중간에 그리고 화면에 표시한다

 

 

🔗 참고 및 출처

https://www.youtube.com/watch?v=FQHNg9gCWpg 

 

반응형
반응형

📝Man Month

프로젝트 제안서 작성시 투입 인원의 개념으로 작업시간과 투입 예정 시간을 의미한다.

  • 1 M/M 이면 1명이 한달간 하면 끝낼 수 있다.
  • 5 M/M 이면 1명이 5달 해야 끝나고 5명이 한달에 끝낼 수 있다

 

📝헬스체크

서버나 네트워크 등이 정상 가동되는지 상태를 확인하는 것 (ping 8.8.8.8 을 통해 네트워크 통신이 되고 있다)

📝백오피스(Back Office) BO

서비스를 제공하기 위하여 상품 등록 및 마케팅을 설정하고 결제와 매출, 수익 등을 관리하는 서비스를 제공 페이지로서 Admin이라고도 불린다

📝VoC

Voice of Customer 의 약자로 고객의 소리를 의미한다.
고객사의 컴플레인, 요청사항등이 포함된다.

 

📝whiteList(화이트리스트)

신뢰할 수 있는 대상들의 리스트로서 신뢰할 수 있는 대상만 허용하고 이외의 것들을 차단하게 된다

 

📝blackList(블랙리스트)

신뢰할 수 없는 대상을 제외한 모든 이메일을 허용한다.

 

📝로그 롤링

일정 단위로 로그파일을 재갱신하는 작업으로 2022-12-14(오늘날짜) 로그 쌓은 후 2022-12-15(내일)이 되었을 때

2022-12-14 로그는 2022-12-14 이름으로 저장되고 2022-12-15일 데이터를 따로 쌓기 시작합니다.

 


🔗 참고 자료 및 출처
 https://sb.pe.kr/7337

반응형
반응형

SELECT

               A.ID              AS ADMIN_ID             -- 아이디

             , A.REG_DATE    AS REG_DATE     -- 수정일자

             , A.COMPANY     AS COMPANY      -- COMPANY
             , A.WRITER       AS WRITER            -- 작성자
  FROM  COVID_VIEW A
WHERE  A.ID = '1'
       OR   A.ID = '2'
     AND   A.REG_DATE > 20220104
GROUP BY A.COMPANY
ORDER BY A.REG_DATE DESC

 

  1. SELECT 문 끝나는 줄에 줄맞추기
  2. 대문자로 전부 작성하기 → 테이블명이 소문자인경우 대문자 사용 못할 경우 소문자로 다 통일
  3. 필드에 AS (Alias) 사용시 구분하기 쉽게 정렬해준다.
  4. GROUP, ORDER 도 또한 SELECT 끝나는 줄에 맞춘다
반응형