월별 글 목록: 2022년 5월월

thymeleaf 타임리프 적용(스프링입문 html)

간단한 html파일에 타임리프를 적용해 보았다.
기존 코드는 그대로 두고 th:를 통해 덧대었다.

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="utf-8">
 <link href="../css/bootstrap.min.css"
 th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
</head>
<body>
<div class="container" style="max-width: 600px">
 <div class="py-5 text-center">
 <h2>상품 목록</h2>
 </div>
 <div class="row">
 <div class="col">
 <button class="btn btn-primary float-end"
onclick="location.href='addForm.html'"
 th:onclick="|location.href='@{/basic/items/add}'|"
type="button">상품 등록</button>
 </div>
 </div>
 <hr class="my-4">
 <div>
 <table class="table">
 <thead>
 <tr>
 <th>ID</th>
 <th>상품명</th>
 <th>가격</th>
 <th>수량</th>
 </tr>
 </thead>
 <tbody>
 <tr th:each="item : ${items}">
 <td><a href="item.html" th:href="@{/basic/items/{itemId}
(itemId=${item.id})}" th:text="${item.id}">회원id</a></td>
 <td><a href="item.html" th:href="@{|/basic/items/${item.id}|}"
th:text="${item.itemName}">상품명</a></td>
 <td th:text="${item.price}">10000</td>
 <td th:text="${item.quantity}">10</td>
 </tr>
 </tbody>
 </table>
 </div>
</div> <!-- /container -->
</body>
</html>

타임리프 사용 선언

<html xmlns:th="http://www.thymeleaf.org">


속성 변경 – th:href
th:href="@{/css/bootstrap.min.css}"
href="value1"th:href="value2" 의 값으로 변경
타임리프 뷰 템플릿을 거치면 원래 값을 th:xxx 값으로 변경. 만약 값이 없다면 새로 생성
HTML을 그대로 볼 때는 href 속성이 사용되고, 뷰 템플릿을 거치면 th:href 의 값이 href
대체되면서 동적으로 변경 가능
대부분의 HTML 속성을 th:xxx 로 변경 가능


타임리프 핵심
핵심은 th:xxx 가 붙은 부분은 서버사이드에서 렌더링 되고, 기존 것을 대체한다. th:xxx 이 없으면 기존 html의 xxx 속성이 그대로 사용
HTML을 파일로 직접 열었을 때, th:xxx 가 있어도 웹 브라우저는 th: 속성을 알지 못하므로 무시
따라서 HTML을 파일 보기를 유지하면서 템플릿 기능 가능


URL 링크 표현식 – @{…},
th:href="@{/css/bootstrap.min.css}"
@{…} : 타임리프는 URL 링크를 사용하는 경우 @{…} 를 사용. 이것을 URL 링크 표현식
URL 링크 표현식을 사용하면 서블릿 컨텍스트를 자동으로 포함


상품 등록 폼으로 이동
속성 변경 – th:onclick
onclick="location.href='addForm.html'"
th:onclick="|location.href='@{/basic/items/add}'|"
여기에는 다음에 설명하는 리터럴 대체 문법이 사용


리터럴 대체 – |…|
|…| :이렇게 사용
타임리프에서 문자와 표현식 등은 분리되어 있기 때문에 더해서 사용해야 함

<span th:text="'Welcome to our application, ' + ${user.name} + '!'">

다음과 같이 리터럴 대체 문법을 사용하면, 더하기 없이 편리하게 사용 가능

<span th:text="|Welcome to our application, ${user.name}!|">

결과를 다음과 같이 만들어야 하는데
location.href='/basic/items/add'
그냥 사용하면 문자와 표현식을 각각 따로 더해서 사용해야 하므로 다음과 같이 복잡해짐
th:onclick="'location.href=' + '\'' + @{/basic/items/add} + '\''"
리터럴 대체 문법을 사용하면 다음과 같이 편리하게 사용 가능
th:onclick="|location.href='@{/basic/items/add}'|"


반복 출력 – th:each

<tr th:each="item : ${items}">


반복은 th:each 를 사용. 이렇게 하면 모델에 포함된 items 컬렉션 데이터가 item 변수에 하나씩 포함되고, 반복문 안에서 item 변수를 사용 가능
컬렉션의 수 만큼 <tr>..</tr>이 하위 테그를 포함해서 생성


변수 표현식 – ${…}

<td th:text="${item.price}">10000</td>

모델에 포함된 값이나, 타임리프 변수로 선언한 값을 조회 가능
프로퍼티 접근법을 사용 ( item.getPrice() )


내용 변경 – th:text

<td th:text="${item.price}">10000</td>

내용의 값을 th:text 의 값으로 변경
여기서는 10000을 ${item.price} 의 값으로 변경


URL 링크 표현식2 – @{…},

th:href="@{/basic/items/{itemId}(itemId=${item.id})}"

URL 링크 표현식을 사용하면 경로를 템플릿처럼 편리하게 사용 가능
경로 변수( {itemId} ) 뿐만 아니라 쿼리 파라미터도 생성
예) th:href="@{/basic/items/{itemId}(itemId=${item.id}, query='test')}"
생성 링크: http://localhost:8080/basic/items/1?query=test


URL 링크 간단히
th:href="@{|/basic/items/${item.id}|}"
리터럴 대체 문법을 활용해서 간단히 사용 가능

참고
타임리프는 순수 HTML을 파일을 웹 브라우저에서 열어도 내용을 확인할 수 있고, 서버를 통해 뷰 템플릿을 거치면 동적으로 변경된 결과를 확인할 수 있다. JSP를 생각해보면, JSP 파일은 웹 브라우저에서 그냥 열면 JSP 소스코드와 HTML이 뒤죽박죽 되어서 정상적인 확인이 불가능하다. 오직 서버를 통해서 JSP를 열어야 한다.
이렇게 순수 HTML을 그대로 유지하면서 뷰 템플릿도 사용할 수 있는 타임리프의 특징을 네츄럴 템플릿(natural templates)이라 한다.

Kotlin 안드로이드 앱 프로그래밍 (7)

조건문과 반복문
조건문 if-else와 표현식

if-else 문

fun main() {
   var data = 10
   if (data > 0) {
      println("data > 0") */ data 0 보다 크면 */
   } else {
      println("data <= 0") */ data 0 보다 작거나 같을때 */
   }
}
> 실행결과
data > 0

if 문에 명시한 조건을 만족하면 if 부분을 실행, 그렇지 않으면 else 부분을 실행합니다. 또한 else if 문을 이용해서 아래와 같은 조건을 통해서 여러 개 나열할 수도 있습니다.

조건을 여러 개 나열한 예

fun main() {
   var data = 10
   if (data > 10) {
      println("data > 10") */ data 10 보다 클때 10 제외 */
   } else if (data > 0 && data <= 10") */ data 0 보다 크거나 10 보다 같거나 작을 때 */
      println("data > 0 && data <= 10")
   } else {
      println("data <= 0") */ data 0 또는 0 보다 작을 때 */
   }
}
> 실행 결과
data > 0 && data <= 10

위의 if-else문 else if 은 대부분의 프로그래밍 언어에서 제공하는 조건문과 차이가 없습니다. 그런데 코틀린에서는 if-else문은 표현식으로도 사용가능합니다. 표현식이란 결괏값을 반환하는 계산식을 말합니다. if-else문은 단순히 조건에 맞는 영역을 실행하는 용도로 사용해도 되지만, 결괏값을 반환하는 표현식으로도 사용가능합니다.

표현식으로 사용한 예

fun main() {
   var data = 10
   val result = if (data > 0) {
      println("data > 0")
      true
} else {
      println("data <= 0")
      false
   }
   println(result)
}
> 실행결과
data > 0
true

위의 소스를 보면 var result = if () {} else {} 형태로 작성하였습니다. 즉 if-else문의 조건에 맞는 코드를 실행하는 동작 외에 그 결괏값을 result 라는 변수에 대입하고 있는 if-else문 표현식 입니다.
if-else문을 표현식으로 사용하려면 else를 생략할 수 없습니다. if만 사용하거나 if-else를 if로 사용할 수 없다는 뜻입니다. 항상 else 구문이 있어야 하며 if-else 혹은 if-else if-else 형태로 사용하여야 합니다.
그리고 if-else 표현식이 반환하는 결괏값은 각 영역의 마지막 줄에 해당합니다. 즉 if-else 부분을 여러 줄로 작성했더라도 마지막 줄의 실행 결과만 반환합니다.

조건문 when
코틀린은 if-else문 말고도 when이라는 조건문을 작성할 수도 있습니다.

when 문 사용 예시

fun main() {
   var data = 10
   when (data) {
      10 -> println("data is 10")
      20 -> println("data is 20")
      else -> {
         println("data is not valid data")
      }
   }
}
> 실행 결과
data is 10

when 키워드 다음의 소괄호 () 안에 넣은 데이터가 조건이 되고 이 값에 따라 각 구문을 실행 합니다. 10 -> println() 코드는 when의 조건으로 지정한 데이터가 10 이면 -> 오른쪽에 있는 구문을 실행합니다.
when 문의 조건으로 정수가 아닌 다른 타입의 데이터를 지정할 수도 있습니다.

문자열 타입을 조건으로 사용

fun main() {
   var data = "hello"
   when (data) {
      "hello" -> println("data is hello")
      "world" -> println("data is world")
      else -> {
         println("data is not valid data")
      }
   }
}
> 실행 결과
data is hello

위 코드는 when 문에 지정한 데이터가 문자열이며 문자열 값에 따른 조건을 명시했습니다. 이처럼 when 문에서는 조건을 데이터 타입, 범위 등으로 다양하게 명시할 수 있습니다.

다양한 유형의 조건 제시

fun main() {
   var data: Any = 10
   when (data) {
      is String -> println("data is String") // data가 문자열 타입
      20, 30 -> println("data is 20 or 30") // data가 20 또는 30
      in 1..10 -> println("data is 1..10") // data가 1-10의 값
      else -> println("data is not valid")
   }
}
> 실행 결과
data is 1..10

위 소스에서 is는 타입을 확인하는 연산자이며 in은 범위 지정 연산자입니다. is String은 데이터가 String 타입이면 참이고, in 1..10은 데이터가 1부터 10까지 범위이면 참입니다.
또한 when 문을 이용하면서 데이터를 명시하지 않고 조건만 명시할 수도 있습니다.

조건만 명시한 예

fun main() {
   var data = 10
   when {
      data <= 0 -> println("data is <= 0")
      data > 100 -> println("data is > 100")
      else -> println("data is valid")
   }
}
> 실행 결과
data is valid

when은 if 문과 마찬가지로 표현식으로도 사용할 수 있습니다. when 문을 표현식으로 사용할 때는 else 문을 생략할 수 없습니다.

when 문을 표현식으로 사용

fun main() {
   var data = 10
   var result = when {
      data <= 0 -> "data is <= 0"
      data > 100 -> "data is > 100"
      else -> "data is valid"
   }
   println(result)
}
> 실행 결과
data is valid

RSA 암호알고리즘

  1. RSA와 소인수분해
  2. DES와 RSA의 암호화/복호화 비교
  3. RSA 암호화 알고리즘 실습

1. RSA와 소인수분해

RSA 암호체계의 안정성은 큰 숫자를 소인수분해 하는 것이 어렵다는 것에 기반을 두고 있다.

어떤 두 개의 소수 p=7, q=11을 잡고 pq를 계산하는 거는 어렵지 않다. 77 또한 숫자를
소인수분해 하는 것 또한 쉽다. 하지만 9735 이렇게 큰 수도 시간이 걸리지만 할 수 있지만

이렇게 큰 수는 1993년 8월부터 1600대의 컴퓨터를 사용하여 8개월이란 시간이 걸려서
소인수분해를 완료하였다. pq를 곱하는 것은 컴퓨터를 활용하면 1초도 안 걸리지만,
역으로 하게 되면 엄청난 시간이 소요된다.

이렇게 소인수분해의 어려움 n=pq로 소인수분해 될 때 p, q를 구하는 소요시간이 많이 필요하여 이를 암호로 사용하는 알고리즘이 바로 RSA 알고리즘이고, 소수가 무한하기에 RSA 앞에 숫자를 붙여준다.

위의 92자리 숫자를 이진법으로 고치면 129자리가 되고 이 문제를 RSA –129 문제라고 한다.

2. DES와 RSA의 암호화/복호화 비교

출처 : Naver Blog

3. RSA 암호화 알고리즘 실습

  1. genrsa 명령어를 사용하여 비밀키(private.pem)를 생성한다.
  2. rsa 명령어를 사용하여 공개키(public.pem)를 생성한다.
  3. 공개키 암호화를 위한 파일을 생성한다.
  4. 공개키를 사용하여 파일을 암호화한다.
  5. 개인키를 사용하여 파일을 복호화한다.
RSA 2048 비밀키 생성
RSA 2048 비밀키
공개키생성
공개키 암호화를 위한 파일 생성
공개키를 이용하여 파일 암호화 및 암호화 파일 확인
개인키를 이용하여 파일 복호화 및 복호화 파일 확인

중간고사를 준비하며 배웠던 내용에서 추가적으로 공부하며 글을 작성하였습니다.
다음 글의 주제는 WebPage 입니다. 홍보 포스터 업로드와 사진, 글 등 블로그 형식의
WebPage 제작 예정입니다.