웹에서의 상태 유지기술

- HTTP프로토콜은 상태 유지가 안되는 프로토콜이다.

- 상태 유지를 위해서 쿠키와 세션의 기술이 등장한다.

 

쿠키(Cookie)와 세션(Session)

 

쿠키

-사용자 컴퓨터에 저장

-저장된 정보를 다른 사람 또는 시스템이 볼 수 있는 단점

-유효시간이 지나면 사라진다.

-이름과 값 쌍으로 정보를 저장한다.

-이름-값 쌍 외에도 도메인(Domain), 경로(Path), 유효기간(Max-Age, Expires), 보안(Secure), HttpOnly 속성을 저장할 수 있다.

-브라우저별로 제한 값을 다르게 가져가고 있다.

 

 

Spring MVC에서의 Cookie 사용

 

-@CookieValue 애노테이션 사용
- 컨트롤러 메소드의 파라미터에서 CookieValue애노테이션을 사용함으로써 원하는 쿠키정보를 파라미터 변수에 담아 사용

-컨트롤러메소드(@CookieValue(value="쿠키이름", required=false, defaultValue="기본값") String 변수명)

 

 

세션

- 클라이언트(사용자,컴퓨터) 별로 서버에 저장

-서버가 종료되거나 유효시간이 지나면 사라짐

 

/*세션 생성 및 얻기
request의 getSession()메소드는 서버에 생성된 세션이 있다면 세션을 반환하고, 없다면 새롭게 세션을 생성하여 반환합니다.
새롭게 생성된 세션인지는 HttpSession이 가지고 있는 isNew()메소드를 통해 알 수 있습니다.*/
HttpSession session = request.getSession();
HttpSession session = request.getSession(true);
//request의 getSession()메소드에 파라미터로 false를 전달하면, 이미 생성된 세션이 있다면 반환하고 없으면 null을 반환합니다.
HttpSession session = request.getSession(false);

/*세션에 값 저장
name과 value의 쌍으로 객체 Object를 저장하는 메소드입니다.
세션이 유지되는 동안 저장할 자료를 저장합니다.*/
setAttribute(String name, Object value);
session.setAttribute(이름, 값);

//세션값 조회
//반환 값은 오브젝트 유형으므로 저장된 객체로 자료 유형 변환이 필요함
String value = (String) session.getAttribute("id");

//세션 값 삭제
removeAttribute(String name); // name값에 해당하는 세션 정보를 삭제
nvalidate(); //모든 세션 정보를 삭제

':: IT > 백엔드' 카테고리의 다른 글

백엔드 정의, HTTP, 브라우저, WAS, Servlet,JSP  (0) 2020.03.30
SQL & JDBC 프로그래밍  (0) 2020.03.30
[Spring]  (0) 2020.03.29
scope(스코프)  (0) 2020.03.28

백 엔드(Back-End)

- 정보를 처리하고 저장하며, 요청에 따라 정보를 내려주는 역할

- 가령 쇼핑몰이라면, 상품 정보를 가지고 있고, 주문을 받아서 저장하고, 사용자가 관심있어 하는 상품을 골라주는 역할이 back-End의 역할

 

백 엔드 개발자가 알아야 할 것들

  • 프로그래밍 언어(JAVA,  Python, PHP, Javascript 등)
  • 웹의 동작 원리
  • 알고리즘(algorithm), 자료구조 등 프로그래밍 기반 지식
  • 운영체제, 네트워크 등에 대한 이해
  • 프레임워크에 대한 이해(예: Spring)
  • DBMS에 대한 이해와 사용방법(예: MySQL, Oracle 등)

 

HTTP

browser의 동작

해석기(Parser)

 

WAS(Web Application Server) 톰캣

- 일종의 미들웨어로 웹 클라이언트(보통 웹 브라우저)의 요청 중 웹 애플리케이션이 동작하도록 지원하는 목적

- word 파일을 열어서 내용을 확인하기 위해서는 ms office의 word 프로그램이나 viewer가 필요합니다.

  웹 어플리케이션을 실행하기 위해서도 필요한 것

 

JAVA언어를 작성된 프로그램을 실행하기 위해선 JRE(Java SE Runtime Environment)가 필요합니다.

JAVA언어를 사용하는 개발자가 아니라 JAVA언어로 만들어진 프로그램을 실행하는 사용자라면 JRE만 컴퓨터에 설치하면 됩니다.

보통 사용자 입장에서 JAVA를 설치한다는 것은 JRE를 설치하는 것을 말합니다.

JAVA언어를 사용하는 개발자는 JAVA언어로 작성된 소스(Source)를 컴파일하고 관리할 필요가 있습니다.

이때 사용되는 도구를 JDK(Java SE Development Kit)라고 말합니다.

JDK안에는 JRE도 포함되어 있습니다.

컴파일한 결과를 실행하기 위해서는 JRE가 필요하기 때문입니다.

 

자바 웹 어플리케이션(Java Web Application)

WAS에 설치(deploy)되어 동작하는 어플리케이션

-  HTML, CSS, 이미지, 자바로 작성된 클래스(Servlet도 포함됨, package, 인터페이스 등), 각종 설정 파일 등이 포함

 

자바 웹 어플리케이션의 폴더 구조

 

Servlet 

- 자바 웹 어플리케이션의 구성요소 중 동적인 처리를 하는 프로그램의 역할

- WAS에 동작하는 JAVA 클래스

- HttpServlet 클래스를 상속 

- 웹 페이지를 구성하는 화면(HTML)은 JSP로 표현하고, 복잡한 프로그래밍은 서블릿으로 구현

 

버전에 따른 Servlet 작성 방법

1. Servlet 3.0 spec 이상에서 사용하는 방법

  • web.xml X
  • 자바 어노테이션(annotation)을 사용
  • first web에서 사용

2. Servlet 3.0 spec미만에서 사용하는 방법

  • servlet을 등록할 때 web.xml 파일에 등록

 

라이프 사이클(Life Cycle)

-어떤 객체의 생성부터 소멸까지의 과정

 

Servlet 생명주기

  • WAS는 서블릿 요청-> 해당 서블릿이 메모리에 있는지 확인
  •  if (메모리에 x) {
     - 해당 서블릿 클래스를 메모리에 올림
     - init() 메소드 실행
    }
     - service()메소드 실행
  • was가 종료 or 웹 어플리케이션이 새롭게 갱신될 경우,  destroy() 메소드가 실행 

service(request, response) 메소드

HttpServlet의 service메소드는 템플릿 메소드 패턴으로 구현

  • 클라이언트의 요청이 GET일 경우 -> doGet(request, response)
  • 클라이언트의 요청이 Post일 경우 -> doPost(request, response)

요청과 응답

WAS는 웹 브라우저로부터 Servlet요청을 받으면,

  • 요청할 때 가지고 있는 정보를 HttpServletRequest객체를 생성하여 저장
  • 웹 브라우저에게 응답을 보낼 때 사용하기 위하여 HttpServletResponse객체를 생성
  • 생성된 HttpServletRequest, HttpServletResponse 객체를 서블릿에게 전달

 

HttpServletRequest

  • http프로토콜의 request정보를 서블릿에게 전달하기 위한 목적으로 사용합니다.
  • 헤더정보, 파라미터, 쿠키, URI, URL 등의 정보를 읽어 들이는 메소드를 가지고 있습니다.
  • Body의 Stream을 읽어 들이는 메소드를 가지고 있습니다.

 

HttpServletResponse

  • WAS는 어떤 클라이언트가 요청을 보냈는지 알고 있고, 해당 클라이언트에게 응답을 보내기 위한 HttpServleResponse객체를 생성하여 서블릿에게 전달
  • 서블릿은 해당 객체를 이용하여 content type, 응답코드, 응답 메시지등을 전송

 

JSP의 생명주기

  1. 브라우저가 웹서버에 JSP에 대한 요청 정보를 전달한다.
  2. 브라우저가 요청한 JSP가 최초로 요청했을 경우만 JSP로 작성된 코드가 서블릿으로 코드로 변환한다. (java 파일 생성)
  3. 서블릿 코드를 컴파일해서 실행가능한 bytecode로 변환한다. (class 파일 생성)
  4. 서블릿 클래스를 로딩하고 인스턴스를 생성한다.
  5. 서블릿이 실행되어 요청을 처리하고 응답 정보를 생성한다.
  • 스크립트릿 : <% %>
  • 가장 일반적으로 많이 쓰이는 스크립트 요소
  • 주로 프로그래밍의 로직을 기술할 때 사용
  • 스크립트릿에서 선언된 변수는 지역변수
  • 스크립트릿의 문법
  • <% 문장%>
  • 표현식 : <%=%>
  • JSP 페이지에서 웹 브라우저에 출력할 부분을 표현 (즉, 화면에 출력하기 위한 것)
  • 스크립트릿내에서 출력할 부분은 내장객체인 out 객체의 print() 또는 println() 메소드를 사용해서 출력
  • 표현식의 문법
  • <%=문장%>

JSP 내장 객체

  • JSP를 실행하면 서블릿 소스가 생성되고 실행
  • JSP에 입력한 대부분의 코드는 생성되는 서블릿 소스의 _jspService() 메소드 안에 삽입되는 코드로 생성
  • _jspService()에 삽입된 코드의 윗부분에 미리 선언된 객체들이 있는데, 해당 객체들은 jsp에서도 사용 가능
  •  

':: IT > 백엔드' 카테고리의 다른 글

상태정보(쿠키와 세션)  (0) 2020.04.02
SQL & JDBC 프로그래밍  (0) 2020.03.30
[Spring]  (0) 2020.03.29
scope(스코프)  (0) 2020.03.28

1. MySQL

- 데이터를 쉽고 편리하게 다룰 수 있도록 하기 위해서 등장한 것

(데이터베이스 메니지먼트 시스템(DBMS) Oracle, SQL Server, MySQL, DB2

ex) 데이터베이스: 책장 / 데이터메니먼트시스템 : 책장관리자

 

2. SQL

- 데이터를 보다 쉽게 검색하고 추가, 삭제, 수정 같은 조작을 할 수 있도록 고안된 컴퓨터 언어

- 관계형 데이터베이스에서 데이터를 조작하고 쿼리하는 표준

 

- DML (Data Manipulation Language): 데이터를 조작하기 위해 사용
INSERT, UPDATE, DELETE, SELECT 등

 

SELECT

SELECT * FROM 테이블명;

select 필드명 from 테이블명;

 

employee 테이블에서 직원의 사번(empno), 이름(name), 직업(job)을 출력하시오.

select empno as 사번, name as 이름, job as 직업 from employee;

employee 테이블에서 사번과 부서번호를 하나의 칼럼으로 출력하시오

SELECT concat( empno, '-', deptno) AS '사번-부서번호' FROM employee;

사원 테이블의 모든 부서번호 출력하시오. (사원 수 만큼 출력된다.)

select deptno from employee;

사원 테이블의 부서번호를 중복되지 않게 출력하시오.

select distinct deptno from employee;

employee 테이블에서 직원의 사번(empno), 이름(name), 직업(job)을 출력하시오.

단, 이름을 기준으로 오름차순 정렬합니다.

select empno, name, job from employee order by name;

select empno as 사번, name as 이름, job as 직업 from employee order by 이름;

select empno, name, job from employee order by name desc;

employee 테이블에서 고용일(hiredate)이 1981년 이전의 사원이름과 고용일을 출력하시오.

select name, hiredate from employee where hiredate < '1981-01-01';

select name, deptno from employee where deptno = 30;

select name, deptno from employee where deptno in (10, 30);(또는)

select name, job from employee where name like '%A%';(% 는 0에서부터 여러 개의 문자열을 나타냄)

 

INSERT

INSERT INTO 테이블명(필드1, 필드2, 필드3, 필드4, … ) VALUES ( 필드1의 값, 필드2의 값, 필드3의 값, 필드4의 값, … )

UPDATE

UPDATE 테이블명 SET 필드1=필드1의값, 필드2=필드2의값, 필드3=필드3의값, … WHERE 조건식

DELETE

DELETE FROM 테이블명 WHERE 조건식

 

- DDL (Data Definition Language): 데이터베이스의 스키마(데이터 집합)를 정의하거나 조작하기 위해 사용
CREATE, DROP, ALTER 등

 

CREATE

create table 테이블명( 필드명1 타입 [NULL | NOT NULL][DEFAULT ][AUTO_INCREMENT],

필드명2 타입 [NULL | NOT NULL][DEFAULT ][AUTO_INCREMENT],

필드명3 타입 [NULL | NOT NULL][DEFAULT ][AUTO_INCREMENT], ...........

PRIMARY KEY(필드명) );

 

테이블 수정

alter table 테이블명 add 필드명 타입 [NULL | NOT NULL][DEFAULT ][AUTO_INCREMENT];

alter table 테이블명 change 필드명 새필드명 타입 [NULL | NOT NULL][DEFAULT ][AUTO_INCREMENT];

alter table 테이블명 rename 변경이름;

 

테이블 삭제

alter table 테이블명 drop 필드명;

 

- DCL (Data Control Language) : 데이터를 제어하는 언어, 권한을 관리하고, 테이터의 보안, 무결성 등을 정의
GRANT, REVOKE 등

 

create database DB이름;

 

데이터베이스 사용자 생성과 권한 주기

- db이름 뒤의 * 는 모든 권한을 의미

- @’%’는 어떤 클라이언트에서든 접근 가능하다는 의미이고, @’localhost’는 해당 컴퓨터에서만 접근 가능하다는 의미

- flush privileges는 DBMS에게 적용을 하라는 의미

grant all privileges on db이름.* to 계정이름@'%' identified by '암호’;

grant all privileges on db이름.* to 계정이름@'localhost' identified by '암호’;

flush privileges;

 

데이터베이스 접속

mysql –h호스트명 –uDB계정명 –p 데이터베이스이름

(mysql –h127.0.0.1 –uconnectuser –p connectdb [enter])

 

연결끊기

QUIT

exit

 

입력 도중 취소

\c

 

show databases;

use mydb;

show tables;

desc 테이블명;

 

Maven?

프로젝트를 빌드하는 방법에 대하여 가이드하는 것도 쉬운 일이 아님 so

Maven에 설정한 대로 모든 개발자가 일관된 방식으로 빌드를 수행

다양한 플러그인을 제공해줘서, 굉장히 많은 일들을 자동화

설정 파일에 몇 줄 적어줌으로써 직접 다운로드 받거나 하는 것을 하지 않아도 라이브러리를 사용

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>kr.or.connect</groupId>
    <artifactId>examples</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>mysample</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>
  • project : pom.xml 파일의 최상위 루트 엘리먼트(Root Element)입니다.
  • modelVersion : POM model의 버전입니다. 
  • groupId : 프로젝트를 생성하는 조직의 고유 아이디를 결정합니다. 일반적으로 도메인 이름을 거꾸로 적습니다.
  • artifactId : 해당 프로젝트에 의하여 생성되는 artifact의 고유 아이디를 결정합니다. Maven을 이용하여  pom.xml을 빌드할 경우 다음과 같은 규칙으로 artifact가 생성됩니다. artifactid-version.packaging. 위 예의 경우 빌드할 경우 examples-1.0-SNAPSHOT.jar 파일이 생성됩니다.
  • packaging : 해당 프로젝트를 어떤 형태로 packaging 할 것인지 결정합니다. jar, war, ear 등이 해당됩니다.
  • version : 프로젝트의 현재 버전. 추후 살펴보겠지만 프로젝트가 개발 중일 때는 SNAPSHOT을 접미사로 사용합니다. Maven의 버전 관리 기능은 라이브러리 관리를 편하게 합니다.
  • name : 프로젝트의 이름입니다.
  • url : 프로젝트 사이트가 있다면 사이트 URL을 등록하는 것이 가능합니다.

 

JDBC

자바 프로그램 내에서 SQL문을 실행하기 위한 자바 API(응용 프로그램에서 사용할 수 있도록, 운영 체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만든 인터페이스를 뜻)

 

import java.sql.*;

Class.forName( "com.mysql.jdbc.Driver" ); //드라이버 로드

String dburl = "jdbc:mysql://localhost/dbName";

Connection con = DriverManager.getConnection ( dburl, ID, PWD ); // /커넥션 연결

Statement stmt = con.createStatement();

 

ResultSet rs = stmt.executeQuery("select no from user" );

 

stmt.execute(“query”); //any SQL

stmt.executeQuery(“query”); //SELECT

stmt.executeUpdate(“query”); //INSERT, UPDATE, DELETE

 

닫기

rs.close();

stmt.close();

con.close();

':: IT > 백엔드' 카테고리의 다른 글

상태정보(쿠키와 세션)  (0) 2020.04.02
백엔드 정의, HTTP, 브라우저, WAS, Servlet,JSP  (0) 2020.03.30
[Spring]  (0) 2020.03.29
scope(스코프)  (0) 2020.03.28

Spring Framework

- 프레임워크 : 반제품

 

컨테이너[Container]

- 인스턴트의 생명주기를 관리하며 , 생성된 인스턴스에게 추가적인 기능을 제공

 

IoC(제어의 역전)

-  서블릿 클래스는 개발자가 만들지만, 그 서블릿의 메소드를 알맞게 호출하는 것은 WAS

이렇게 개발자가 만든 어떤 클래스나 메소드를 다른 프로그램이 대신 실행해주는 것을 제어의 역전

 

DI

- 클래스 사이의 의존 관계를 빈(Bean) 설정 정보를 바탕으로 컨테이너가 자동으로 연결해주는 것

 

Bean class란?

예전에는 Visual 한 컴포넌트를 Bean이라고 불렀지만, 근래 들어서는 일반적인 Java클래스를 Bean클래스라고 보통 말합니다.

Bean클래스의 3가지 특징은 다음과 같습니다.

  • 기본생성자를 가지고 있습니다.
  • 필드는 private하게 선언합니다.
  • getter, setter 메소드를 가집니다.
  • getName() setName() 메소드를 name 프로퍼티(property)라고 합니다. (용어 중요)

Spring JDBC

-JDBC의 모든 저수준 세부사항을 스프링 프레임워크가 처리

-개발자는 필요한 부분만 개발

 

Spring JDBC 패키지

org.springframework.jdbc.core

  • JdbcTemplate 및 관련 Helper 객체 제공

org.springframework.jdbc.datasource

  • DataSource를 쉽게 접근하기 위한 유틸 클래스, 트랜젝션매니져 및 다양한 DataSource 구현을 제공

org.springframework.jdbc.object

  • RDBMS 조회, 갱신, 저장등을 안전하고 재사용 가능한 객제 제공

org.springframework.jdbc.support

  • jdbc.core 및 jdbc.object를 사용하는 JDBC 프레임워크를 지원

DTO란?

  • DTO란 Data Transfer Object의 약자입니다.
  • 계층간 데이터 교환을 위한 자바빈즈입니다.
  • 여기서의 계층이란 컨트롤러 뷰, 비지니스 계층, 퍼시스턴스 계층을 의미합니다.
  • 일반적으로 DTO는 로직을 가지고 있지 않고, 순수한 데이터 객체입니다.
  • 필드와 getter, setter를 가진다. 추가적으로 toString(), equals(), hashCode()등의 Object 메소드를 오버라이딩 할 수 있습니다.

DAO란?

  • DAO란 Data Access Object의 약자로 데이터를 조회하거나 조작하는 기능을 전담하도록 만든 객체입니다.
  • 보통 데이터베이스를 조작하는 기능을 전담하는 목적으로 만들어집니다.

ConnectionPool 이란?

  • DB연결은 비용이 많이 듭니다.
  • 커넥션 풀은 미리 커넥션을 여러 개 맺어 둡니다.
  • 커넥션이 필요하면 커넥션 풀에게 빌려서 사

DataSource란?

  • DataSource는 커넥션 풀을 관리하는 목적으로 사용되는 객체입니다.
  • DataSource를 이용해 커넥션을 얻어오고 반납하는 등의 작업을 수행합니다.

':: IT > 백엔드' 카테고리의 다른 글

상태정보(쿠키와 세션)  (0) 2020.04.02
백엔드 정의, HTTP, 브라우저, WAS, Servlet,JSP  (0) 2020.03.30
SQL & JDBC 프로그래밍  (0) 2020.03.30
scope(스코프)  (0) 2020.03.28

 

Scope(스코프/변수 범위)란?

-Application : 웹 어플리케이션이 시작되고 종료될 때까지 변수가 유지되는 경우 사용

-Session : 웹 브라우저 별로 변수가 관리되는 경우 사용

-Request : http요청을 WAS가 받아서 웹 브라우저에게 응답할 때까지 변수가 유지되는 경우 사용

-Page : 페이지 내에서 지역변수처럼 사용

 

1. page :페이지 내에서 지역변수처럼 사용한다.

특정 서블릿이나 JSP가 실행되는 동안에만 정보를 유지하고 싶은 경우에 사용

 

  • PageContext 추상 클래스를 사용한다.
  • JSP 페이지에서 pageContext라는 내장 객체로 사용 가능 하다.
  • forward가 될 경우 해당 Page scope에 지정된 변수는 사용할 수 없다.
  • 사용방법은 Application scope나 Session scope, request scope와 같다.
  • 마치 지역변수처럼 사용된다는 것이 다른 Scope들과 다릅니다.
  • jsp에서 pageScope에 값을 저장한 후 해당 값을 EL표기법 등에서 사용할 때 사용됩니다.
  • 지역 변수처럼 해당 jsp나 서블릿이 실행되는 동안에만 정보를 유지하고자 할 때 사용됩니다.

 

- PageComtext  

PageComtext.setAttribute

PageComtext.getAttribute

 

2. requset

  • http 요청을 WAS가 받아서 웹 브라우저에게 응답할 때까지 변수값을 유지하고자 할 경우 사용한다.
  • HttpServletRequest 객체를 사용한다.
  • JSP에서는 request 내장 변수를 사용한다.
  • 서블릿에서는 HttpServletRequest 객체를 사용한다.
  • 값을 저장할 때는 request 객체의 setAttribute()메소드를 사용한다.
  • 값을 읽어 들일 때는 request 객체의 getAttribute()메소드를 사용한다.
  • forward 시 값을 유지하고자 사용한다.
  • 앞에서 forward에 대하여 배울 때 forward 하기 전에 request 객체의 setAttribute() 메소드로 값을 설정한 후, 서블릿이나 jsp에게 결과를 전달하여 값을 출력하도록 하였는데 이렇게 포워드 되는 동안 값이 유지되는 것이 Request scope를 이용했다고 합니다.

 

 

3.Session :

  • 웹 브라우저별로 변수를 관리하고자 할 경우 사용한다.
  • 웹 브라우저간의 탭 간에는 세션정보가 공유되기 때문에, 각각의 탭에서는 같은 세션정보를 사용할 수 있다.
  • HttpSession 인터페이스를 구현한 객체를 사용한다.
  • JSP에서는 session 내장 변수를 사용한다.
  • 서블릿에서는 HttpServletRequest의 getSession()메소드를 이용하여 session 객체를 얻는다.
  • 값을 저장할 때는 session 객체의 setAttribute()메소드를 사용한다.
  • 값을 읽어 들일 때는 session 객체의 getAttribute()메소드를 사용한다.
  • 장바구니처럼 사용자별로 유지가 되어야 할 정보가 있을 때 사용한다.

 

4. Application

  • 웹 어플리케이션이 시작되고 종료될 때까지 변수를 사용할 수 있다.
  • ServletContext 인터페이스를 구현한 객체를 사용한다.
  • jsp에서는 application 내장 객체를 이용한다.
  • 서블릿의 경우는 getServletContext()메소드를 이용하여 application객체를 이용한다.
  • 웹 어플리케이션 하나당 하나의 application객체가 사용된다.
  • 값을 저장할 때는 application객체의 setAttribute()메소드를 사용한다.
  • 값을 읽어 들일 때는 application객체의 getAttribute()메소드를 사용한다.
  • 모든 클라이언트가 공통으로 사용해야 할 값들이 있을 때 사용한다.

':: IT > 백엔드' 카테고리의 다른 글

상태정보(쿠키와 세션)  (0) 2020.04.02
백엔드 정의, HTTP, 브라우저, WAS, Servlet,JSP  (0) 2020.03.30
SQL & JDBC 프로그래밍  (0) 2020.03.30
[Spring]  (0) 2020.03.29

+ Recent posts