본문 바로가기

컴퓨터학원(복습)(수료)

자바(JAVA)기반 안드로이드 웹&앱 개발 73일차 (스프링 이어서 기본적인 CRUD, 페이징 오류처리, 댓글처리(REST,AJAX))

[검색 처리]

1. 검색 기능 : 검색조건, 키워드

1) 검색조건

(1) 일반 사용자 : <select> 태그

(2) 관리자용이나 검색기능이 강한 경우 : <checkbox> 태그

2. 검색의 유형

1) 제목, 내용, 작성자와 같은 단일 항목

2) 제목 + 내용, 제목 + 작성자와 같은 복합 항목

3) 검색 항목에 따라서 매번 다른 SQL이 처리될 필요가 있는 상황

4) MyBatis의 동적 쿼리기능을 이용해서 처리

http://www.mybatis.org/mybatis-3/ko/dynamic-sql.html

 

MyBatis – 마이바티스 3 | 동적 SQL

동적 SQL 마이바티스의 가장 강력한 기능 중 하나는 동적 SQL을 처리하는 방법이다. JDBC나 다른 유사한 프레임워크를 사용해본 경험이 있다면 동적으로 SQL 을 구성하는 것이 얼마나 힘든 작업인지 이해할 것이다. 간혹 공백이나 콤마를 붙이는 것을 잊어본 적도 있을 것이다. 동적 SQL 은 그만큼 어려운 것이다. 동적 SQL 을 사용하는 것은 결코 파티가 될 수 없을 것이다. 마이바티스는 강력한 동적 SQL 언어로 이 상황을 개선한다. 동적 SQL 엘리먼트들은 JSTL이나 XML기반의 텍스트 프로세서를 사용...

www.mybatis.org

[단일 항목 검색의 예]

1. 검색 조건 : 제목(title), 내용(content), 작성자(writer)

select * from tbl_board where bno > 0 and title like '%Test%' order by bno desc limit 10, 10;

SQL문 해석

tbl_board 테이블에 모든 속성(*)을 조회합니다.

조건1. bno가 0을 초과하고 title 속성에 Test(%Test%)가 들어가야 합니다.

조건2. bno 를 내림차순(desc)으로 10번째부터 10개까지(limit 10, 10) 출력합니다.

[다중 항목 검색]

1. 제목이나 내용 중에 "테스트"라는 문자열이 있는 게시물을 검색할 경우

select * from tbl_board where bno > 0 and ( title like '%테스트%' or content like '%테스트%')

order by bno desc limit 10, 10;

위의 SQL문에서 title에 테스트 혹은 content에 테스트가 들어가고

bno가 0을 초과하는 것으로 조건1이 바뀐것입니다.

OR을 먼저 선행조건으로 하기 위해서 양 옆에 '(' A or B ')'를 추가해야합니다.

(AND 가 선행되어 처리되기 때문입니다.)

[MyBatis의 동적태그들]

1. if

1) test 라는 속성과 함께 특정한 조건이 true가 되었을 때 포함된 SQL을 사용하고자 할 때 작성합니다.

2. choose (when, otherwise)

1) 여러 상황들 중 하나의 상황에서만 동작합니다.

3. trim ( where, set) (아직 잘 이해못했습니다.)

https://java119.tistory.com/103 (trim에 대한 설명)

1) 단독으로 사용되지 않고 <if> <choose>와 같은 태그들을 내포하여 SQL들을 연결해주고

앞 뒤에 필요한 구문들(AND, OR, WHERE 등)을 추가하거나 생략하는 역할을 합니다.

(1) prefix : 실행될 쿼리의 <trim>문 안에 쿼리 가장 앞에 붙여준다.

(2) prefixOverrides : 실행될 쿼리의 <trim> 문 안에 쿼리 가장 앞에 해당하는 문자들이 있으면

자동으로 지워준다.

(3) suffix : 실행 될 쿼리의 <trim> 문 안에 쿼리 가장 뒤에 붙여준다.

(4) suffixOverrides : 실행 될 쿼리의 <trim> 문 안에 쿼리 가장 뒤에 해당하는

문자들이 있으면 자동으로 지워준다.

2) 예시

예시

(1) <trim prefix = "AND (" prefixOverrides="OR" suffix=")">

ㄱ) prefix 속성이 'AND'로 되어있기 때문에 맨 앞에 'AND'가 붙습니다.

ㄴ) prefixOverrides 속성이 쿼리 중에 'OR' 텍스트를 찾고, 찾게 되면 'OR 텍스트를 제거합니다.

ㄷ) 그리고 suffix 속성이 <trim> 문 맨 마지막에 ')'를 닫아줍니다.

4. forEach

1) List, 배열, 맵 등을 이용해서 루프를 처리합니다.

[검색 조건처리를 위한 변경사항]

1. Criteria.java 클래스에서 검색항목(type)과 검색키워드(keyword)를 추가합니다.

1) type은 검색유형을 의미하고 keyword 는 검색어를 의미합니다.

getTypeArr() 메소드는 type 문자열(T,C,W 로 올겁니다)을 배열로 나누어 한 문자씩 자른 것을 의미합니다.

Criteria.java

2. BoardMapper.xml 을 변경합니다.

1) tbl_board 테이블에서 모든 칼럼(*) 을 bno > 0 이상인 것을 찾습니다.

2) 그런데, 실행될 쿼리의 <trim> 맨 앞에" AND"를 붙여주고

실행될 쿼리의 <trim> 문 안에 쿼리 가장 뒤에 ")"를 붙여줍니다. (prefix, suffix)

3) 실행될 쿼리의 <trim> 문 안에 쿼리 가장 앞에 "OR"이 있으면 자동으로 지워줍니다. (prefixOverrides)

4) foreach 문으로 Criteria 에 있던 type 들을 getTypeArr(collection="typeArr")로 가져옵니다.

(1) 그 안에서 prefix로 실행될 쿼리의 <trim> 문 안에 가장 앞에 "OR"을 붙여줍니다.

(2) <choose> <when> 으로 type 값에 따라 실행되는 쿼리문을 달리합니다. '검색어'

5) 1),2),3),4) 가 실행된 후 마지막으로 order by bno desc limit #{pageStart}, #{amount} 가

쿼리 뒤에 붙어서 limit 속성을 줍니다.

BoardMapper.xml

BoardMapperTests.java

※ 그런데 이러면 확장성이 너무 떨어집니다. 게시물의 검색과 게시물의 숫자 카운트에 공통으로 사용되는 부분이 언제든지 사용될 수 있으므로 <sql> 조각으로 분리하고, 필요한 곳에 <include>하는 방식으로의 모듈화가 필요합니다.

[<sql> 조각과 <include>]

1. BoardMapper.xml 에서 해당 부분을 sql 조각으로 분리합니다.

BoardMapper.xml

2. BoardMapper.xml의 getTotalCount sql 과 getListWithPaging 부분에 해당 쿼리 부분이 필요한 부분에 <include>합니다.

BoardMapper.xml

[화면에서 검색 조건 처리]

1. 화면 처리할 때의 주의사항

1) 페이지 번호가 파라미터로 유지되었던 것처럼 검색조건과 키워드 역시 화면 이동 시 같이 전송되어야 합니다.

2) 화면에서 검색 버튼을 클릭하면 새로 검색을 한다는 의미로 1 페이지로 이동하여야 합니다.

3) 한글의 경우 GET 방식으로 이동하는 경우 인코딩 처리가 필요합니다.

2. list.jsp를 수정합니다. (select(검색) 할 수 있는 기능 추가)

1) 그런데, 이렇게 넣으면 문제가 생깁니다.

예를들어, 3페이지를 보다가 검색을 하면 3페이지로 이동이 되어집니다.(1페이지로 가야합니다.)

또한, 검색 후 페이지를 이동하면 검색조건이 사라져 4페이지를 눌렀을 때, DB 기준 4페이지가 뜹니다.

검색 후 화면에서는 어떤 검색 조건과 키워드를 이용했는지 알 수 없습니다.(검색란이 비는 것입니다.)

list.jsp 검색기능 추가

3. 2번의 문제점을 해결하기 위해서 list.jsp의 검색버튼(javascript)를 수정합니다.

1) serachFrom(검색처리 요소의 form id) 버튼이 눌렸을 때 option 과 keyword가 비어있을 때(val())

경고창을 띄워주고 정상적으로 동작하였을 때 1페이지로 보여지도록 설정합니다.(pageNum val(1))

2) e.preventDefault() 는 html의 태그의 고유동작을 막아주는 것입니다. 예를 들어, a태그나 submit 태그를

누르게 되면 href를 통해 이동하거나, 창이 새로고침하여 실행됩니다. preventDeafult를 통해 이러한 동작을

막아주는 것입니다.

https://programming119.tistory.com/100 (e.preventDefault() 설명)

list.jsp

4. list.jsp에서 검색조건과 키워드를 보여주는 부분을 수정합니다.

1) keyword 가 추가되었습니다. 검색하고나서 keyword 파라미터가 유지될 수 있도록 합니다.

2) 문득 c:outvalue를 이용해서 {}를 출력하는 이유가 궁금해졌습니다.

[JSP]<c:out>을 사용하는 이유 (tistory.com)

XSS(Cross-stie Scripting)을 방지하기 위하여 사용한다고 합니다.

<c:out> 태그를 씌우면 사용자가 입력하는 창에서 자바스크립트 태그가 실행되지 않게 만들고

글자 그대로 출력하게 합니다. (예시 중 하나일뿐)

list.jsp

이제 검색하였을 때 keyword가 남고 1페이지로 이동됨을 확인할 수 있습니다.

[조회 페이지에서 검색 처리]

1. 게시글 리스트에서 특정 게시글 선택 시 게시글 상세보기로 이동하는데, 게시글 수정 버튼을 누르면 검색 유형(type)과 검색어(keyword)가 전달되어야 합니다. 즉, get.jsp(조회화면)에서도 현재 객체(cri)의 keyword 와 type을 받아야 합니다.

1) get.jsp form 부분 수정하기

get.jsp 추가

2. 이어서 modify.jsp(수정)에서도 수정과 삭제하였을 때도 마찬가지로 현재 객체(cri)의 keyword와 type을 받아야 합니다.

1) modify.jsp form 부분 수정하기

modify.jsp

2) modify가 동작하는 BoardController.java 의 modify()와 remove() 부분도 수정합니다.

현재 객체를 가져올 수 있는 메소드를 추가합니다.(rttr.addAttribute())

BoardController.java 주석 처리 되어 있는 빨간색 부분을 작성하시면 됩니다.

주석은 나중에 getListLink() 로 대체되어서 처리한 것이므로 현재는 주석이 안되어 있어야 하는 것이 맞습니다.

3) modify 화면에서 list(목록)를 눌렀을 때도 마찬가지로 keyword와 type을 알아야 하므로

modfiy.jsp의 자바스크립트를 수정합니다.

modify.jsp

[UriComponentsBuilder 를 이용하는 링크생성]

BoardController.java 를 보시면 지금까지 rttr.addAttribute로

4개의 파라미터 pageNum, amount, type, keyword를 받고 있었는데,

이것을 연결해서 URL의 형태로 만들어주는 기능을 만드는 것입니다.

1. Criteria.java 에 getListLink() 메소드를 추가합니다.

Criteria.java

2. getListLink() 를 BoardController.java 의 modify() 와 remove() 메소드에 적용합니다.

기본적인 CRUD 와 페이징 처리를 하는데 있어서, 오류들을 수정하였습니다. 이제 정상적으로 작동되는지 확인하시면 됩니다. 저는 잘됩니다!

[REST 방식과 Ajax를 이용하는 댓글처리]

[REST 방식으로의 전환]

1. 웹의 과거와 현재

1) 과거의 웹 서비스

(1) 고정된 브라우저의 주소창

(2) 특정한 확장자를 이용하는 모델 2 방식 (예, *.do)

(3) 특정한 파라미터에 의한 분기 구조

2) 현재의 웹 서비스

(1) URI + 식별 데이터

(2) GET/POST 외에 PUT/DELETE 등의 다양한 전송방식 사용

(3) 서버에서는 순수한 데이터만을 서비스하는 방식

[REST 방식]

1. REST는 'Representational State Transfer'의 약어로 하나의 URI 는

하나의 고유한 리소스(Resource)를 대표하도록 설계된다는 개념에 전송방식을 결합해서 원하는 작업을 지정

2. 스프링에서는 다양한 어노테이션과 기능을 통해서 REST 방식의 서비스를 간편하게 구축할 수 있음

3. 스프링 4에서부터는 @Controller 외에 @RestController 라는 어노테이션을 추가해서 해당 Controller의 모든 메서드의 리턴 타입을 기존과 다르게 처리한다는 것을 명시

4. @RestController는 메서드의 리턴 타입으로 사용자가 정의한 클래스 타입을 사용할 수 있고, 이를 JSON이나 XML로 자동으로 처리

예제를 진행하기 위해 새로운 프로젝트를 생성하겠습니다.

기존에 exam02 를 복사하여 exam 03을 설정하고 pom.xml에 XML과 JSON을 활용할 수 있는

jackson-databind 와 Jackson-dataformat-xml, Java 객체를 JSON으로 변환할 수 있는 gson 라이브러리를 추가하겠습니다.

[@RestController 의 반환 타입]

1. @RestController 를 사용하는 컨트롤러에서는 다음과 같은 반환 타입들을 사용합니다.

1) String 혹은 Integer 등의 타입들

2) 사용자 정의 타입

3) ResponseEntity<> 타입

4) 주로 ResponseEntity 타입을 이용하는 것이 일반적입니다.

2. 단순 문자열 반환을 확인하기 위해 org.zerock.controller 에 기존 SampleController 를 삭제하고

새로운 SampleController.java를 만든 후 다음과 같이 작성합니다.

1) 주소창에 localhost:8080/sample/getText 를 작성하여 동작을 확인합니다.

SampleController.java

[JSON 혹은 XML 로 변환될 데이터]

1. 이번에는 JSON 혹은 XML로 데이터를 변환하기 위해 SampleVO.java를 만들고 SampleController 에 다음과 같이 작성합니다.

1) 주소창에 한번은 localhost:8080/sample/getSample 을(XML)

한번은 localhost:8080/sample/getSample.json 을 (json)을 검색하여 결과를 확인합니다.

SampleVO.java

Samplecontroller.java

xml, json

[Collection(List, Map, Set) 타입의 객체 반환]

https://munsonghabnida.tistory.com/18 (컬렉션 설명)

1. Collection 타입의 객체반환을 확인하기 위해 SampleController java에 getMap()을 작성합니다.

SampleController.java

[ResponseEntity 타입]

https://devlog-wjdrbs96.tistory.com/182

 

[Spring Boot] ResponseEntity란 무엇인가?

먼저 REST API가 무엇인지는 아래 블로그를 먼저 잘 읽어보자. https://meetup.toast.com/posts/92 REST API 제대로 알고 사용하기 : TOAST Meetup REST API 제대로 알고 사용하기 meetup.toast.com 1. ResponseEn..

devlog-wjdrbs96.tistory.com

1. 단순히 데이터 뿐만 아니라 브라우저에서 HTTP 상태 코드 등 추가적인 데이터를 전달할 수도 있습니다.

2. SampleController.java 에 check() 메소드를 추가합니다.

1) height 값이 150보다 작으면 BAD를, 150이거나 크면 200(OK)를 주므로 주소창에

height 값을 달리하여 확인해봅니다.

[@RestController 에서 파라미터]

1. @PathVariable

1) 일반 컨트롤러에서도 사용이 가능하지만 REST 방식에서 자주 사용됩니다.

URL 경로의 일부를 파라미터로 사용할 때 이용

2) URI 경로 중간에 들어간 값을 얻기 위해 사용합니다.

(1) SampleController.java 에 getPath() 메소드를 추가하여 확인합니다.

URI 값을 받아 오는 것을 확인합니다.

2. @Requestbody

1) JSON 데이터를 원하는 타입의 객체로 변환해야 하는 경우에 주로 사용

2) 전송된 데이터가 JSON 이고, 이를 컨트롤러에서 사용자 정의 타입의 객체로 변환할 때 사용합니다.

3) Ticket 클래스를 생성하고, SampleController.java에 convert() 메소드를 정의하여 확인합니다.

(1) PostMapping 이므로 SampleControllerTests.java에 testConvert()를 정의하여 확인합니다.

SampleControllerTests.java json 형태로 변환된 것을 확인할 수 있습니다.

3. 일반 <form>방식으로 처리된 데이터