목차로 돌아가기

프로젝트 생성

스프링 부트란?

- 스프링 프레임워크를 사용하는 프로젝트를 아주 간편하게 설정할 수 있는 스프링 프레임워크의 서브 프로젝트라고 할 수 있다.

- Spring Boot makes it easy to create stand-alone 
단독 실행 가능한 스프링 애플리케이션을 생성한다.

- 웹 컨테이너를 내장하고 있어 최소한의 설정으로 쉽게 웹 어플리케이션을 만들 수 있다.

스프링 부트를 왜 사용해야 하나? 장점?

- 스프링 프레임 워크를 사용하면 많은 xml 설정파일 등을 작성 하는 등 설정하는 방법이 어려운 편이기 때문에 보통 기본 설정 파일을 구성하는데 몇 날 몇 일이 걸렸다. 하지만 스프링 부트는 반복되는 개발환경 구축을 위한 코드작성등의 노력을 줄여주고 쉽고 빠르게 프로젝트를 설정할 수 있도록 도와준다.

- 프로젝트 환경 구축 시 비기능적인 기능도 기본적으로 제공한다.(내장형 서버, 시큐리티, 측정, 상태 점검 등)

 

스프링 부트 스타터(https://start.spring.io/) 란?

설정 화면 설명
지속적으로 버전 업을 진행하고 있다.

- GroupId : GrouId는 자신의 프로젝트를 식별해주는 고유 아이디 com.cjy.web'과 같이 인터넷 주소를 뒤집어 놓은 형태이다.

- ArtifactId : ArtifactId는 버전 정보를 생략한 이름(jar) 보통 프로젝트 id와 동일하게 작성한다.

 

설정 시 오류 만남 

더보기

흑.. 기존 maven을 쓰다가 gradle로  초기설정을 다시 하려고하니 역시나 쉽게 설정이 되지 않는다...

오류 해결방법

[Spring Boot] Plugin [id: 'org.springframework.boot', version: '2.5.6'] was not found 오류 해결하기


뭔가 gradle에서 다운로드 불가능한 상황이었고, 여러 해결 방법을 시도했지만 결국 JVM(jdk)를 재 설정 (Download JDK)를 통해 해결


라이브러리 살펴보기
라이브러리 살펴보기 
(우측 gradle)
설명
의존성을 살펴보면 boot 하위에 기본적으로 spring mvc, jpa, tomcat등이 의존 되어 있다. 그래서 boot를 사용하면 모두 사용가능하다.
*중요 : 로그 관련 라이브러리
spring boot 는 기본적으로 log-back을 쓴다. 요즘은 slf4j라는 것을 쓴다. slf4j는 로그를 사용하기 위한 모음이고 구현체가 log-back등이다. 
테스트 관련 라이브러리 
1. assert : assetTrue등..
2. mockito : mock 쓸 때..
3. juniit 등

핵심 라이브러리

  • 스프링 MVC
  • 스프링 ORM
  • JPA, 하이버네이트
  • 스프링 데이터 JPA ( 스프링 데이터 JPA는 스프링과 JPA를 각각 이해하고 쓰는 응용기술이다.)

기타 라이브러리 

  • H2 데이터베이스, 클라이언트
  • 커넥션 풀, 부트 기본은 HikariCP
  • WEB(thymeleaf)
  • 로깅 SLF4J & LogBack
  • 테스트

View 환경설정

thymeleaf(타임리프) 템플릿 엔진

- JSP를 대체하여 나온 view 라이브러리

- 장점 : Natural templates 마크업을 깨지 않고 그대로 사용, jsp는 안열리는데 thymeleaf는 바로 열린다.

더보기

Controller

@Controller
public class HelloController {

    /**
     * hello라는 요청이 오면 처리하는 메서드
     * @param model
     * @return resource->template->view(hello.html)
     */
    @GetMapping("hello")
    public String hello(Model model){
        model.addAttribute("data","hello!!");
        return "hello"; //retrun "hello.html"
    }
}

의문점 : return "hello"만 해주는데 templates의 hello.html을 찾아가나요?

-> 부트가 해준다. resources:templates/ + {ViewName} + .html을 찾아간다.

 hello.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Hello</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'안녕하세요. ' + ${data}" >안녕하세요. 손님</p>
</body>
</html>

결과

정적 컨텐츠 (static)

더보기

resources/static/index.html

<!DOCTYPE HTML>
<html>
<head>
    <title>Hello</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
Hello
<a href="/hello">hello</a>
</body>
</html>

꿀팁

- 화면단을 수정헀는데 그때마다 계속 서버를 restart하기 너무 부담이다.

해결

1. bulid.gradle에 dependencies에 spring-boot-devtools를 넣어준다.

더보기
implementation 'org.springframework.boot:spring-boot-devtools'

적용이 되면 restartMain이라는 문구를 볼 수 있다.

수정 후 Build에 Recompile hello.html을 해주면 수정된 부분만 바꿔어서 화면에 뿌려준다.


H2 데이터베이스 설치

개발이나 테스트 용도로 가볍고 편리한 DB, 웹 화면 제공 (h2database.com/html/main.html)

H2 설치 및 실행 (https://so-easy-coding.tistory.com/5)

JPA와 DB 설정, 동작확인

 

강좌명 기한 기한 완료여부
1강 웹과 네트워크의 기본에 대해 알아보자 3/25(금) OK
2강 간단한 프로토콜 HTTP    
3강 HTTP 정보는 HTTP 메시지에 있다    
4강 결과를 전달하는 HTTP 상태 코드    
5강 HTTP와 연계하는 웹 서버    
6강 HTTP 헤더    
7강 웹을 안전하게 하는 HTTPS    
8강 누가 엑세스하고 있는지를 확인하는 인증    
9강 HTTP에 기능을 추가한 프로토콜    
10강 웹 콘텐츠에서 사용하는 기술    
11강 웹 공격 기술    

'Back-end > NetWork (HTTP)' 카테고리의 다른 글

웹과 네트워크의 기본에 대해 알아보자  (0) 2022.01.19
실전! 스프링 부트와 JPA 활용1 - 웹 어플리케이션 개발 
실전! 스프링 부트와 JPA 활용2 - API 개발 및 성능 개선
  강좌명 기한 완료여부
강좌소개
1강 프로젝트 생성 ~1/17 O
2강 라이브러리 살펴보기 ~1/18 O
3강 View 환경 설정 ~1/18 O
4강 H2 데이터 베이스 설치 ~1/18 O
5강 JPA와 DB 설정, 동적확인 ~1/19  
도메인 분석 설계
6강 요구사항 분석 ~1/19  
7강 도메인 모델과 테이블 설계 ~1/19  
8강 엔티티 클래스 개발1    
9강 엔티티 클래스 개발2    
10강 엔티티 설계시 주의점    
애플리케이션 구현 준비
11강 구현 요구사항    
12강 애플리케이션 아키텍처    
회원 도메인 개발
13강 회원 리포지토리 개발    
14강 회원 서비스 개발    
15강 회원 기능 테스트    
주문 도메인 개발
16강 주문, 주문상품 엔티티개발    
17강 주문 리포지토리 개발    
18강 주문 서비스 개발    
19강 주문 기능 테스트    
20강 주문 검색 기능 개발    
웹 계층 개발
...      
       

 

'Spring > [인프런] Spring Boot & JPA' 카테고리의 다른 글

SpringBoot & JPA 프로젝트 생성  (0) 2022.01.18
강의 강좌명  기한 완료여부
기본 알고리즘 작성하기
4강 리스트 정렬하기 / 리스트 검색하기 / 요약 1  
자료구조
5강 리스트 / 배열과 리스트의 관계 2  
트리 / 맵 / 집합 /요약 2  
디자인 패턴
6강 예제 패턴 살펴보기 / 일반적으로 사용하는 패턴 / 요약 3  
자주 묻는 알고리즘
7강 라이브러리 기능 구현하기 / 제네릭 사용하기 4  
자바 기본
8강  원시타입 / 객체 이용하기 / 자바 배열 5  
Stirng 이용하기 / 제네릭 이해하기 / 오토박싱과 언박싱 6  
어노테이션 이용하기 / 명명 규칙 이해하기 / 예외 처리하기 7  
표준 자바 라이브러리 사용하기 / 자바 8 / 요약 8  
Junit으로 테스팅하기
9강  Junit 테스트 생명주기 / Junit 사용의 좋은 예 / 목으로 의존성 제거 하기 9  
행위 주도 개발 이용해 시스템 만들기 / 요약 9  
자바 가상머신(JVM) 이해하기
10강 가비지 컬렉터 / 메모리 튜닝 / JVM 자바 사이의 상호 작용 / 요약 10  
동시성
11강  스레드 사용하기 / 동시성 작업하기 / 엑터 / 요약 11  

자료구조

자료구조 생성 방법(new) 사용법
ArrayList(List)
List<String> list = new ArrayList<String>();
list.add("temp");
list.size();
list.get(i);
list.remove(i);
Stack
Stack<Integer> stack = new Stack<>();
stack.isEmpty
stack.peek(); //마지막 값
stack.pop(); //스택 마지막 값 빼기
stack.add(i); //값 넣기
queue
Queue<Integer> q = new LinkedList<>();
q.add(i); //추가
q.offer(i); //추가
q.poll(); //삭제
q.peek(); //queue의 첫번째 값
q.isEmpty 비어있는지 여부
Set
Set<String> setExample = new HashSet<String>();
Iterator<String> iterator = setExample.iterator();
while(iterator.hasNext()){
    String getin = iterator.next();
}
Map Map<K,V> map = new HashMap<K,V>(); 
Map<String, Integer> m = new HashMap<>();
//만약 값이 있을 때 value값 늘려주는 법
if(m.get(words[i]) == null)
   m.put(words[i], 1); //값이 없다면 1을 넣어준다
else
  //만약 값이 있다면 해당 value값을 가져와서 +1 해준다.
   m.put(words[i], m.get(words[i])+1 ) ;

map.put("asdf",123);
map.get(key) -> value 출력
map.keySet...
배열 int[] arr = new int[100];  
우선 순위 큐 //우선순위 낮은 숫자 순 = 오름차순
PriorityQueue<Integer> pq = new PriorityQueue<>();
//우선순위 높은 숫자 순 = 내림차순
PriorityQueue<Integer> pq = new PriorityQueue<Collection.reverseOrder());
pq.add(i);// 삽입
pq.poll() ;// 삭제
pq.isEmpty();//여부
pq.peek();// 맨 앞 값

pair

Pair 클래스 생성

//pair 클래스 생성
public Pair(){
	private int x; //은닉화 
	private int y;
    //생성자
    Pair(int x, int y){
    	this.x = x;
        this.y = y;
    }
}

queue 생성 및 추가, 추출

//queue 선언
Queue<Pair> q = LinkedList<>();

//queue 추가
q.add(new Pair(x,y));

//queue 추출
int first = q.peek().x;
int second = q.peek().y;

//queue 삽입
Pair temp = new Pair(10,20); //초기값 셋팅
temp.x = 20; //변경
q.add(temp); //queue에 삽입

 

형변환

관련 변환  
String String to int String str = "123";
int num = Integer.parseInt(str);
int to String int num = 123;
String str = Integer.toString(num);
Char char to int 방법1)
char c1 = '9'
int num = c1 - '0'; //아스키 코드이용

방법2)
char s1 = "4
int (s1);
int to char int num = 9;
char c = (char) num;

 

기타

    인덱스 접근
String   char tempChar = s[i]; [X]
char tempChar = s.charAt(i);

str.length(); //String의 길이
substring   String str = "g2g2g2";
String str2 = str.substring(3);
str2 = "g2g"

str2.substring(0,3); //0부터 세글자 이게 더 많이씀
equals   if(str.equals(str2)) //같으면 true, 틀리면 false
StringBuilder append 활용 StringBuilder sb = new StringBuilder();
sb.append("hello");
sb.append(" world");
//가변성개념인데 무변하면 힙메모리가 자꾸 차는데 이건 추가하는 개념이다.

 

'Algorithm > ***Algorithm Java' 카테고리의 다른 글

[백준] 1062_가르침  (0) 2022.03.01
[백준]7576_토마토(bfs/dfs)  (0) 2022.02.23
[백준] 15684_사다리 조작(DFS) java  (0) 2022.02.23
백준_17090_미로탈출하기  (0) 2022.02.16
[형 변환 정리] java, C++  (0) 2021.11.14

목차 돌아가기

Spring 커넥션풀
데이터베이스 연결을 미리 준비해 놓고 사용하는 방법
25-1 c3p0 모듈의 CombopolledDataSource
   
'c3p0'를 이용해서 dataSource에 db정보를 set 해준다.
25-2 스프링 설정파이를 이용한 DataSource 설정
   
스프링 설정파일을 통해서 dataSource를 저장한다.
new를 선언하는 방식(bean 등록x)
//1. dataSource 선언
private ComboPooledDataSource dataSource;
//2. new
dataSource = new ComboPooledDataSource();
//3. db정보 set
dataSource..setDirver(driver);
dataSource.setJdbcUrl(url);
dataSource.setUser(userId);...
//4. template 연동
template = new JdbcTemplate();
template.setDataSource(dataSource);
bean 등록(servlet-context.xml) -> 객체 @AutoWired(권장)
<!-- bean 등록 -->
<beans:bean id ="dataSource" class="com.hchange.v2.c3p0.ComPooledDataSource">
	<beans:property name="dirverClass" value="oracle..."/>
...
</beans>
@Autowired
public MenberDao(ComboPooledDataSource dataSource){
	this,template = new JdbcTemplate(dataSource);
}
Config 방법 -> @Autowired (권장)
@Configuration
public class DBconfig { 
	
    @Bean
    public ComPooledDataSource dataSource() throws PropertyVetoExcetion(){
    ComPooledDataSource dataSource = new ComPooledDataSource();
    
    dataSource.setDriver("oracle...");
    ...
    return dataSource;
}

'Spring > [인프런] Spring FrameWork' 카테고리의 다른 글

DI(Dependency injection)  (0) 2022.01.24
Spring AOP 개념  (0) 2022.01.21
Spring JDBC 연동 & JDBC Template  (0) 2022.01.08
리다이렉트, 인터셉트  (0) 2022.01.06
세션, 쿠키  (0) 2022.01.03

목차 돌아가기

Java 언어를 사용해서 DB와 통신하기 위한 방벙베 대해서 학습
23-1 기본 SQL
  • 테이블 생성
CREATE TABLE member (
    memId VARCHAR2(10) CONSTARINT mmdId_pk PRIMARY KEY,
    memPw VARCHAR2(10),
    memMail VARCHAR2(15),
    memPurcNum NUMBER(3) DEFAULT 0 CONSTARINT memPurcNum_ck CHECK (memPurcNum) < 3 )
)l
  • 테이블 계정(컬럼) 삽입
INSERT INTO member (memId, memPw, memMail)
values ('b', 'bb', 'bbb@gmail.com');
  • 테이블에서 'memId'가 'b'인 회원을 삭제한다.
DELETE FROM memeber WHERE memId = 'b';
  • 테이블의 모든 회원정보를 출력한다.
SELECT * FROM member;
  • 테이블을 삭제한다.
DROP TABLE member;
23-2 JDBC
JDBC 흐름 중요내용
SQL작성 및 전송 까지는 개발자가 직접해야한다. (매번 바뀌니깐)
하지만 자원해제는 개발자가 딱 한 번만만 해도 된다. 그래서 JdbcTemplate가 나오는 것이다.
JDBC INSERT
@Override
	public int memberInsert(Member member) {
		
		int result = 0;
		
		try {
			Class.forName(driver);
			conn = DriverManager.getConnection(url, userid, userpw);
			String sql = "INSERT INTO member (memId, memPw, memMail) values (?,?,?)";
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, member.getMemId());
			pstmt.setString(2, member.getMemPw());
			pstmt.setString(3, member.getMemMail());
			result = pstmt.executeUpdate();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(pstmt != null) pstmt.close();
				if(conn != null) conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		return result;
		
	}
JDBC SELECT
@Override
	public Member memberSelect(Member member) {
		
		Member mem = null;
		
		try {
			
			Class.forName(driver);
			conn = DriverManager.getConnection(url, userid, userpw);
			String sql = "SELECT * FROM member WHERE memId = ? AND memPw = ?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, member.getMemId());
			pstmt.setString(2, member.getMemPw());
			rs = pstmt.executeQuery();
			
			while (rs.next()) {
				String memId = rs.getString("memid");
				String memPw = rs.getString("mempw");
				String memMail = rs.getString("memMail");
				int memPurcNum = rs.getInt("memPurcNum");
				
				mem = new Member();
				mem.setMemId(memId);
				mem.setMemPw(memPw);
				mem.setMemMail(memMail);
				mem.setMemPurcNum(memPurcNum);
			}
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(rs != null) rs.close();
				if(pstmt != null) pstmt.close();
				if(conn != null) conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		return mem;
		
	}
JDBC UPDATE
@Override
	public int memberUpdate(Member member) {
		
		int result = 0;
		
		try {
			
			Class.forName(driver);
			conn = DriverManager.getConnection(url, userid, userpw);
			String sql = "UPDATE member SET memPw = ?, memMail = ? WHERE memId = ?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, member.getMemPw());
			pstmt.setString(2, member.getMemMail());
			pstmt.setString(3, member.getMemId());
			result = pstmt.executeUpdate();
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(pstmt != null) pstmt.close();
				if(conn != null) conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		return result;
		
	}
JDBC DELETE 
	@Override
	public int memberDelete(Member member) {
		
		int result = 0;
		
		try {
			
			Class.forName(driver);
			conn = DriverManager.getConnection(url, userid, userpw);
			String sql = "DELETE member WHERE memId = ? AND memPw = ?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, member.getMemId());
			pstmt.setString(2, member.getMemPw());
			result = pstmt.executeUpdate();
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(pstmt != null) pstmt.close();
				if(conn != null) conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		return result;
		
	}
소스들의 자원해제 부분이 너무 중복된 코드들이 많다라는 단점이 발생한다.
해결 : JDBC Template
사실상 JDBC는 쓸 일이 없고 JDBC Template를 사용한다.

JDBC Template

Java언어를 사용해서 DB 연동하는 방법 학습

24-1 JDBC의 단점을 보완한 JdbcTemplate
   
반복되고 동일한 작업을 막기 위해 'JdbcTemplte'를 사용
24-2 DataSource클래스
제공 클래스  
c3p0 : 커넥션 풀 할 때 이용
pom.xml 의존설정
maven에 없기 때문에 pom.xml에 추가해줘야 하는 내용
<!-- DB -->
    <dependency>
       <groupId>com.oracle</groupId>
        <artifactId>ojdbc6</artifactId>
        <version>12.1.0.2</version>
    </dependency>
    <!-- JDBC Template 사용 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>4.1.6.RELEASE</version>
    </dependency>
    <!-- c3p0 사용 -->
    <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.5</version>
    </dependency>
Template 사용
Template 사용 하므로 연결부터 해제까지 각각 안해줘도 된다. 
방법은 3가지 정도 있다.
방법(3가지)
1. PreparedStateMentSetter().. 
2. PreparedSattementCreator()..
3. RowMapper<Member>().. 
//데이터소스(데이터정보저장) 만들기
private DriverManegerDataSource datasource;

//처음에 초기 설정 한 번만 해준다.
public MemberDao(){
    datasource = new DriverManegerDataSource();
    datasource.setDriver(driver);
    datasource.setJdbcUrl(url);
    datasource.setUser(userId);
    datasource.setPassword(userpw);

    template = new JdbcTemplate();
    template.setDataSource(datasource);
}


//1. 주입 insert
@Override
public int memberInsert(Member member){
  ...
  int result = template.update(sql,member.getMemId(),member.getMempw(),member.getMail());
  ...
  return result;
}

//2. 주입 Select
@Override
public Member memberSelect(final Member member) {
		
	List<Member> members = null;
	//final로 해주면 다른 곳에서 사용 못함
	final String sql = "SELECT * FROM member WHERE memId = ? AND memPw = ?";

    members = template.query(sql, new Object[]{member.getMemId(), member.getMemPw()}, new RowMapper<Member>() {

        @Override
        public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
            Member mem = new Member();
            mem.setMemId(rs.getString("memId"));
            mem.setMemPw(rs.getString("memPw"));
            mem.setMemMail(rs.getString("memMail"));
            mem.setMemPurcNum(rs.getInt("memPurcNum"));
            return mem;
        }
            
    });

    if(members.isEmpty()) 
        return null;

    return members.get(0);
}

'Spring > [인프런] Spring FrameWork' 카테고리의 다른 글

Spring AOP 개념  (0) 2022.01.21
Spring 커넥션풀(c3p0)  (0) 2022.01.09
리다이렉트, 인터셉트  (0) 2022.01.06
세션, 쿠키  (0) 2022.01.03
Controller 객체 구현  (0) 2021.12.31

목차로 돌아가기

컨트롤러에서 뷰를 분기하는 방법과 컨트롤러 실행 전/후에 특정 작업을 가능하게 하는 방법에 대해서 학습합니다.

리다이렉트(redirect)
지금의 페이지에서 특정 페이지로 전환하는 기능
리다이렉트 구조 내용
순서
1) 회원정보 수정 요청
2) 회원인증 여부 결정(Y/N) : (로그인 되어있나?)
2-1) Y이면 회원정보 수정 페이지로 유도
2-2) N이면 return "redirect:/";
// Modify
	@RequestMapping(value = "/modifyForm")
	public String modifyForm(Model model, HttpServletRequest request) {
		
		HttpSession session = request.getSession();
		Member member = (Member) session.getAttribute("member");
		
		// 리다이렉트 코드
		if(null == member) {
			return "redirect:/";
		} else {
			model.addAttribute("member", service.memberSearch(member));
		}
		
		return "/member/modifyForm";
	}
인터셉터(interceptor)
리다이렉트를 하는 경우가 많은 경우 HandlerInterceptor를 사용
구조 설명
1) 클라이언트가 요청한다.
2) 원래면 핸들러,뷰(4,5,7,8)로 바로가야하지만 3, 6, 9를 거치는 인터페이스(HanderfInterceptor)를 발생 시킨다.

- preHandle() 컨트롤러 작업전에 작동(가장 많이 사용)
- postHandle() 컨트롤러 작업후에 작동
- afterHandle() 컨트롤러 뷰 이후에 작동

직접 구현은 어렵고 HanderfInterceptorAdaptor를 사용(spring에서 사용)
bean 객체 등록
mapping으로 적용되는 범위를 한정 지어준다. /member/modifyForm or /member/removeForm 이 작동하면 해당 경로의 인터셉터를 작동시켜라 라는 의미 
	<interceptors>
		<interceptor>
			<mapping path="/member/modifyForm"/>
			<mapping path="/member/removeForm"/>
			<beans:bean class="com.bs.lec21.member.MemberLoginInterceptor"/>
		</interceptor>
	</interceptors>

 

'Spring > [인프런] Spring FrameWork' 카테고리의 다른 글

Spring 커넥션풀(c3p0)  (0) 2022.01.09
Spring JDBC 연동 & JDBC Template  (0) 2022.01.08
세션, 쿠키  (0) 2022.01.03
Controller 객체 구현  (0) 2021.12.31
Service & Dao 객체 구현  (0) 2021.12.30

+ Recent posts