분류 전체보기 (358)

 

둥근 토글 버튼

본 포스팅에서는 html, css, javascript를 이용하여 둥근 toggle버튼을 만들고, 버튼의 상태가 변경될 때마다 상태를 출력하는 기능까지 만들어 봅니다. 본 보스팅에 사용되는 기본코드는 w3schools에서 가지고 온 것입니다. w3schools에서는 단순히 css를 이용해서 토글버튼처럼 보이는 것을 만드는 것 까지만 보여주었는데, 저는 그렇게 토글이 될 때마다 자바스크립트를 이용해서 어떤 기능이 실행되는 부분까지 확장해서 포스팅합니다.

 

우선 toggle.html 파일에 input tag를 이용해서 아래와 같이 작성해줍니다.

<!DOCTYPE html>
<html>

<head>
</head>

<body>
    <label class="switch">
        <input type="checkbox" />
        <span class="slider round"></span>
    </label>
</body>

</html>

 

그리고 toggle.css 파일을 하나 만들어서 그 안에 아래와 같이 작성을 해줍니다.

/* 슬라이더 외부를 감싸는 라벨에 대한 스타일 */
.switch {
  position: relative;
  display: inline-block;
  width: 60px;
  height: 34px;
}

/* HTML 기본 체크박스 숨기기 */
.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

/* 슬라이더 - 실제로 토글될 부분 */
.slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #ccc;
  -webkit-transition: .4s;
  transition: .4s;
}

.slider:before {
  position: absolute;
  content: "";
  height: 26px;
  width: 26px;
  left: 4px;
  bottom: 4px;
  background-color: white;
  -webkit-transition: .4s;
  transition: .4s;
}

input:checked + .slider {
  background-color: #2196F3;
}

input:focus + .slider {
  box-shadow: 0 0 1px #2196F3;
}

input:checked + .slider:before {
  -webkit-transform: translateX(26px);
  -ms-transform: translateX(26px);
  transform: translateX(26px);
}

/* 슬라이더를 동그랗게 보여주기 위한 부분 */
.slider.round {
  border-radius: 34px;
}

.slider.round:before {
  border-radius: 50%;
}

 

이제 HTML 파일의 <head></head> 부분에 위 css 파일을 링크시켜줍니다.

<head>
	<link rel="stylesheet" type="text/css" href="toggle.css" />
</head>

 

이제 toggle.html 파일을 더블클릭해서 브라우저에서 열어보면 아래 영상처럼 움직이는 것을 확인할 수 있습니다.

 

둥근 토글 버튼 움직이는 영상

 

자, 이제 여기에 자바스크립트를 이용하여 기능을 추가해보도록 할건데요,

이 토글버튼은 input 태그의 checkbox를 이용한 것이므로 토글이 될 때마다 checked 속성이 변경되도록 되어있습니다.

이 기본적인 내용을 기억하고 자바스크립트에서 토글버튼의 checked 속성을 기반으로 특정 문자열을 출력하도록 해보겠습니다.

자바스크립트 파일은 따로 만들지 않고 그냥 html 파일에 추가하도록 할게요.

우선, input 태그에 onclick 속성을 이용하여 toggle이라는 함수를 호출하도록 하고, toggle 함수를 구현하겠습니다.

아래처럼 input  태그의 onclick 속성을 넣어주세요. 

<label class="switch">
    <input type="checkbox" onclick="toggle(this)">
    <span class="slider round"></span>
</label>

이렇게 해주면 토글버튼(체크박스)가 클릭될 때마다 toggle이라는 함수를 호출하면서 자기자신을 파라미터로 넘겨주게 됩니다.

 

자, 이제 body 아래쪽에 자바스크립트를 이용하여 스크립트를 작성해보겠습니다.

<script>
    function toggle(element) {
        console.log(element.checked);
    }
</script>

위 코드는 <head></head> 에 위치해도 되고 <body></body> 사이에 위치해도 됩니다.

당연히 별도 파일로 분리하여 작성해도 됩니다.

분리하여 작성하는 것과 관련해서는 제가 작성한 다른 포스트에서 확인 가능합니다. -> https://keichee.tistory.com/356

저는 <body></body> 사이에 넣어놓았습니다.

<body>
    <label class="switch">
        <input type="checkbox" onclick="toggle(this)">
        <span class="slider round"></span>
    </label>

    <script>
        function toggle(element) {
            console.log(element.checked);
        }
    </script>
</body>

 

자, 여기까지 html 파일 전체 코드가 어떻게 되는지 다시 한번 보여드릴게요.

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" type="text/css" href="toggle.css" />
</head>

<body>
    <label class="switch">
        <input type="checkbox" onclick="toggle(this)">
        <span class="slider round"></span>
    </label>

    <script>
        function toggle(element) {
            console.log(element.checked);
        }
    </script>
</body>

</html>

 

여기까지 완성하여 실행하면 체크박스(토글버튼)을 클릭할 때마다 toggle함수가 실행되면서 현재 체크박스의 상태가 어떻게 바뀌었는지를 출력하게 됩니다.

확인을 위해서 브라우저에서 toggle.html 파일을 새로고침하여 다시 열어주시고,

화면에서 우클릭 > 검사 (inspect)를 선택하여 개발자도구(developer tools)를 열어서 console탭을 열어주세요.

그리고 버튼을 누를때마다 어떤 값이 출력이 되는지 확인해보도록 하겠습니다.

 

토글 버튼 동작 영상

 

자, 이렇게 자바스크립트를 이용해서 토글버튼의 상태값을 출력해보았습니다.

어떤가요? 별로 어렵지 않죠? css 스타일을 해석하기 힘드실 순 있겠으나, 여기서 그런 부분을 자세하게 다루진 않겠습니다.

좀 더 나아가서 토글버튼의 상태값에 따라 ajax 요청을 서버에 날려 실제 DB를 업데이트하거나, 

또는 html의 특정 element를 hide하거나 show하는 등의 기능을 만들어 보세요.

 

그럼 오늘도 즐거운 코딩하시길 바래요 ^-^

 

- 깐깐한 개발자 -

웹사이트를 만들다보면 HTML파일 크기가 커지기 마련입니다.

웹사이트가 dynamic한 동적 사이트라면 더더욱 그럴 가능성이 커집니다.

이런 저런 기능을 자바스크립트로 구현을 하다보면 주체할 수 없이 커지는 html 파일을 볼 수도 있는데요

이럴 때는 자바스크립트 부분을 별도의 .js 파일로 분리한 뒤 html 파일에 링크를 걸어서

마치 html 파일에 자바스크립트를 직접 작성한 것처럼 사용할 수 있습니다.

 

방법도 매우 간단합니다.

아래 html 예제를 먼저 보도록 하겠습니다.

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" type="text/css" href="toggle.css" />
</head>

<body>
    <label class="switch">
        <input type="checkbox" onclick="toggle(this)">
        <span class="slider round"></span>
    </label>

    <script>
        function toggle(element) {
            console.log(element.checked);
        }
    </script>
</body>

</html>

위 코드는 토글버튼 만들기 시간에 사용했던 코드입니다.

위 코드에서 <script> 태그로 감싼 부분을 .js 파일로 분리해내고 해당 파일을 html파일에 링크(import, include라고 얘기하기도 함)를 걸어서 기능이 정상적으로 돌아가도록 해보겠습니다.

우선 html 문서의 <script> 태그 내에 있던 내용을 복사하여 toggle.js 파일을 만들어 넣어줍니다.

function toggle(element) {
    console.log(element.checked);
}

이제 <head>태그 내에 아래와 같이 toggle.js 파일을 연결시켜주고, <body>안에 있던 script는 제거합니다.

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" type="text/css" href="toggle.css" />
    <script src="toggle.js"></script>
</head>

<body>
    <label class="switch">
        <input type="checkbox" onclick="toggle(this)">
        <span class="slider round"></span>
    </label>
</body>

</html>

<script> 태그가 사라지니 화면에 그림을 그려주는 요소들만 <body>에 남아있게 되었습니다.

위 코드 자체가 워낙 작은 코드라 깔끔해졌다는 느낌을 받지 못할 수 있으나, 

위 처럼 짧은 html 문서는 테스트용밖에 없을 것입니다. 

개발자가 되고싶다면 항상 .js 파일을 분리하여 링크걸어 사용하길 추천합니다.

 

뭔가 길게 설명드렸지만, html파일에 자바스크립트 파일을 연결/링크/import/include 시키는 방법은 <head>태그 내에 아래와 같이 한 줄만 추가해주시면 됩니다.

<script src="toggle.js"></script>

여기서 .js 파일의 위치는 html 파일의 위치에서 상대경로로 지정해주시면 됩니다.

또는 웹상에 있는 파일일 경우 URL 주소가 들어올 수도 있으니 참고하시기 바랍니다.

 

💻 Programming

[Node.js] npm 업데이트 하기

최근에 React.js 개발을 공부하기위해 node.js부터 업데이트 하기로 했어요.

우선 커맨드창에서 아래와 같이 입력해보니

$ npm --help

명령어 사용법이 틀렸다고 하면서 사용법을 출력해주더니

마지막에는 친절하게도 npm 현재 버전이 낮으니 최신버전으로 업데이트하라는 안내 문구가 나오네요.

안쓴지 오래되서 버전이 5.6.0 이네요 ㅠㅠ

 

실행명령어를 가르쳐줬으니 실행해볼게요~

$ npm i -g npm

근데 잘 실행하다가 아래처럼 에러가 나네요. 아흑 ㅜㅜ

npm 업데이트 오류

에러메시지를 보니 디렉토리에 권한이 없었네요. 

아래 명령어로 다시 시도해볼게요.

$ sudo npm i -g npm

npm 업데이트 완료

슉~슉~ 뭐가 나오더니 11초만에 업데이트가 끝났어요.

 

#npm버전확인명령어 로 업데이트가 잘 되었는지 확인해볼게요.

$ npm -v
6.9.2

 6.9.2로 업데이트가 된 것을 확인할 수 있네요.

 

업데이트 성공~

JSP와 Javascript의 차이가 뭘까요? 라는 질문을 받은 적이 있습니다.

초보자 분들이 충분히 할만한 질문이죠. JSP도 자바스크립트도 제대로 사용해보기 전에는 두 가지가 뭐가 다른지 잘 모를 수 있습니다.

 

초보자 분들이 이해할 정도로 간략하고 쉽게 요점만 설명드리겠습니다.

 

Javascript웹브라우저(사용자의 컴퓨터)에서 실행이되는 스크립트 언어입니다.

자바스크립트 파일은 .js 확장자를 가지며, 자바스크립트 문법에 따라 작성을 해야합니다.

프로그래밍 언어 중 하나라고 생각하시면 됩니다.

반면, JSP는 Java Server Page의 약자로 .jsp 확장자를 가지며, 언어의 종류를 나타내는 것은 아닙니다.

.jsp 파일에는 html태그와 javascript 함수도 사용이 가능하며, 추가로 아래와 같이 <% java code %> 형태로 자바문법을 사용할 수 있습니다.

 

<html>

<head><title>Hello World</title></head>

<body> Hello World!<br/>

<% out.println("Your IP address is " + request.getRemoteAddr()); %>  <!-- 여기가 JSP 문법 -->

</body>

</html>

 

JSP에 작성된 내용은 서버에서 실행되고, 그 결과가 웹브라우저(사용자 컴퓨터)로 전송됩니다.

 

이제 JSP와 자바스크립트의 차이점이 뭔지 아시겠죠?

 

가시기 전에 공감 꾸~~~~욱 눌러주고 가세요 ^-^

💻 Programming/Java

[Java] 자바 8진수를 10진수로 변환하기

자바에서 8진수 숫자를 사용자(키보드)로부터 입력받아서 10진수로 변환하여 출력하는 예제입니다.


import java.util.Scanner;

public class OctalToDex
{
  public static void main(String[] args)
  {
    Scanner sc = new Scanner(System.in);
    String b=sc.nextLine();
    int a=Integer.valueOf(b, 8);
    sc.close();
    System.out.println(a);
   }
} 


Java에서는 Integer클래스가 존재하여 2진수, 8진수, 16진수의 숫자를 10진수로 쉽게 변환이 가능하며, 그 반대로 10진수를 2진수,8진수,16진수로 변환하는 것을 쉽게할 수 있습니다.

메서드는 아래와 같습니다.
 10진수 -> 2진수 변환 : Integer.toBinaryString(int);
 10진수 -> 8진수 변환 : Integer.toOctalString(int);
10진수 -> 16진수 변환 : Integer.toHexString(int);
 10진수 -> 2진수 변환 : Integer.toBinaryString(int); 
 10진수 -> 8진수 변환 : Integer.toOctalString(int);
 10진수 -> 16진수 변환 : Integer.toHexString(int);​


위 메서드는 10진수 숫자(int)를 2진수/8진수/16진수 스트링으로 반환합니다.

 2진수 -> 10진수 변환 : Integer.valueOf(string, 2);
 8진수 -> 10진수 변환 : Integer.valueOf(string, 8);
16진수 -> 10진수 변환 : Integer.valueOf(string, 10);
2진수 -> 10진수 변환 : Integer.valueOf(string, 2);
8진수 -> 10진수 변환 : Integer.valueOf(string, 8);
16진수 -> 10진수 변환 : Integer.valueOf(string, 10);​


위 메서드는 2진수/8진수/16진수를 나타내는 숫자스트링을 10진수 int로 반환해줍니다.

자바 웹앱을 개발할 때 가장 많이 사용하는 툴이 이클립스와 스프링부트입니다.

이번 시간에는 이클립스에서 스프링 프레임웍을 사용할 수 있도록 스프링을 설치해보도록 하겠습니다.

우선, 이클립스가 설치되어있다고 가정합니다.

최신 이클립스는 우측 링크에서 받으실 수 있습니다. -> https://www.eclipse.org/downloads/

 

이클립스 상단 메뉴에서 Help > Eclipse Marketplace... 을 선택합니다.

그리고 검색창에서 "sts"를 검색합니다.

위 화면처럼 나오면 "Spring Tools 4 - for Spring Boot (aka Spring Tool Suite 4)"를 install 버튼을 눌러 설치합니다.

Spring Tools 4 플러그인을 설치할 때 어떤 것들을 설치할 수 있는지 목록을 조회해 오고 있습니다.

상세 목록을 위 사진처럼 보여주는데, 기본적으로 모두 체크가 되어있습니다.

그냥 "confirm" 눌러주세요.

소프트웨어 라이센스에 동의하는지 묻는 질문에는 "I accept the terms...."를 선택하고 "Finish"버튼을 눌러주시면 됩니다.

 

STS 4 설치 진행 상태

우측 하단의 "Progress" 버튼을 클릭하면 Progress 창으로 focus가 맞춰지면서 설치 상태를 보여줍니다.

인터넷 환경에 따라 시간이 좀 걸릴 수도 있습니다.

 

 

세로로 나열된 5개의 네스프레소 배열

이번에는 자바로 1차원 배열을 만들어 보도록 하겠습니다.
자바로 배열을 만드는 방법은 여러 가지가 있습니다.
우선 용어부터 정리하고 가겠습니다.
제가 만든다라고 얘기한 것은 일반적으로 얘기하려고 한 것인데 이는 두 가지 의미를 포함하고 있습니다.
바로 "선언"과 "초기화"입니다.
여기서 "선언"이라는 것은 변수의 이름을 지어주는 것을 얘기하며,
"초기화"라는 것은 그 변수에 값을 할당하는 것을 의미합니다.
이 용어들을 머릿속에 넣고 출발하도록 하겠습니다.

배열을 선언하는 방법

자바에서 배열을 선언하는 방법은 아래와 같이 3가지가 있습니다.

public static void main(String[] args) {

        // 배열을 선언하는 방법
        int[] intArr1;
        int []intArr2;
        int intArr3[];
}

위에서는 int 타입의 배열을 3가지 방법으로 선언해 보았습니다.
int타입 대신 long, double, Integer, Long, Double, String 등 다른 타입을 사용할 수도 있습니다.
이렇게 선언을 해 놓아도 공간(메모리)을 차지하지는 않습니다.
배열은 초기화를 하면서 사이즈를 정해줘야 공간(메모리)을 차지하게 됩니다.
그럼 배열 초기화는 어떻게 할까요?

배열을 초기화하는 방법

배열을 초기화할 때는 아래와 같이 합니다.

public static void main(String[] args) {

        // 배열을 선언하는 방법
        int[] intArr1;

        // 배열을 초기화하는 방법
        intArr1 = new int[3];
}

위 예제에서는 intArr1이라는 이름을 가진 배열을 사이즈가 3인 배열로 초기화를 하였습니다.
이렇게 초기화를 하면 int 타입의 경우 기본값 0으로 세팅이 됩니다.

배열의 선언과 초기화를 동시에 하는 방법

자바에서는 아래와 같이 배열의 선언과 초기화를 동시에 할 수도 있습니다.

public static void main(String[] args) {

        int[] intArr1 = new int[10];    // size 10, index range from 0 to 9
        int []intArr2 = new int[20];    // size 20, index range from 0 to 19
        int intArr3[] = new int[20];    // size 20, index range from 0 to 19
}

위에서 설명드린 선언문과 초기화문을 한 줄에 붙여 쓰면 동시에 선언과 초기화가 가능합니다.

자, 그런데 이렇게 하면 int 타입의 배열에는 모두 0으로 값이 세팅이 됩니다.

전, 제가 원하는 값으로 세팅을 하고 싶은데 그렇게도 할 수 있나요?

물론이죠~ 그렇게도 할 수 있습니다.
아래와 같이 하시면 됩니다.

public static void main(String[] args) {

        int[] intArr4 = {1, 2, 3, 4};   // size 4, index range from 0 to 3
        int[] intArr5 = {0, 0, 0, 0, 0, 0, 0};  // size 7, index range from 0 to 6
}

intArr4에는 [1, 2, 3, 4]가 저장됩니다.
intArr5에는 new int[7] 로 초기화한 것과 같이 0으로 값이 들어갑니다.

배열 출력하기

그럼 이렇게 배열에 들어간 값을 출력해보고 싶을 땐 어떻게 할까요?
자바에서 콘솔창에 출력을 할 때에는 System.out.println() 메서드를 사용하는 것은 다들 알고 계시죠?
Hello World를 해보셨다면 다들 알고 계실겁니다.
그럼 이 메서드를 이용해서 변수이름을 넣어주면 될까요?
아닙니다. 배열이 담긴 변수명만 넣어주면 쓰레기값이 출력이 됩니다.
이런 경우에는 Arrays.toString() 메서드를 이용하면 됩니다.

public static void main(String[] args) {

        int[] intArr1 = new int[10];    // size 10, index range from 0 to 9
        int []intArr2 = new int[20];    // size 20, index range from 0 to 19
        int intArr3[] = new int[20];    // size 20, index range from 0 to 19
        int[] intArr4 = {1, 2, 3, 4};   // size 4, index range from 0 to 3
        int[] intArr5 = {0, 0, 0, 0, 0, 0, 0};  // size 7, index range from 0 to 6

        System.out.println(Arrays.toString(intArr1));
        System.out.println(Arrays.toString(intArr2));
        System.out.println(Arrays.toString(intArr3));
        System.out.println(Arrays.toString(intArr4));
        System.out.println(Arrays.toString(intArr5));
}

출력 결과

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 2, 3, 4]
[0, 0, 0, 0, 0, 0, 0]

이상으로 배열의 선언과 초기화에 대한 포스팅을 마치겠습니다.
궁금한 점이 있으시면 댓글 달아주시면 답변드리겠습니다.

2차원 배열에 대한 내용은 [Java] 자바 2차원 배열 생성(선언 및 초기화)에서 더 다루고 있으니 참고하시구요~

도움이 되셨다면 공감 꾸~~~~욱 눌러주고 가세요 ^-^

감사합니다.

지난 시간에는 프로그래밍이란 무엇인지에 대해 간략하게 설명을 해보았습니다.

너무 지루한 이론적인 이야기 보다는 개발자로 개발을 하면서 느낌점을 바탕으로 정의를 내렸었는데

이해하는데 도움이 되었으리라 생각합니다. 

 

이번 시간에는 무작정 따라하기 시간을 가져보겠습니다.

우선 여러분들 컴퓨터에 아래와 같은 것들을 준비해야 합니다.

 

1. JDK (Java Development Kit)

2. 이클립스 IDE (Integrated Development Environment)

 

설치하기 전에 이친구들이 뭔지부터 알고 설치를 해야겠죠? 해킹프로그램이면 큰 일 날 테니까요.

우선, JDK라는 친구는 "자바 개발 툴" 줄여서 "자개툴"이라는 녀석이죠. 자바 언어 사전이라고 생각하시면 됩니다.

이 녀석이 있어야 여러분들이 작성한 자바소스코드를 컴퓨터가 이해하는 언어로 변경이 가능하고,

자바 프로그램을 실행시킬 수가 있습니다. 태생부터 현재까지 무료입니다. (Java 8의 특정 버전 부터는 유료라이센스로 전환되었습니다)

 

다음으로 이클립스라는 친구는 여러분들이 개발을 좀 더 쉽게 할 수 있도록 하기위해

오픈소스로 공개된 무료로 사용가능"통합 개발 환경"을 제공하는 도구입니다.

개발자가 소설작가라면 이클립스 IDE는 워드프로세서와 같은 것입니다.

 

 

자, 그럼 설치를 하러 가볼까요??

 

1. JDK 8 (Java SE Development Kit 8) 설치 -> 다운로드 링크

-> 혹시 다운로드 링크 들어갔는데 cookie 관련 아래와 같은 창이 뜬다면 그냥 I agree 하지마시고 아래처럼 따라해주세요.

1. 주황색 버튼 클릭
2. Required Cookies 만 선택되도록 한뒤 Submit Preferences  선택
3. Close 버튼 선택
4. Accept License Agreement 선택 후 본인 운영체제에 맞는 버전을 다운로드

2. 이클립스(개발툴, IDE) 설치 -> 다운로드 링크

 

1. Download 선택

 

3. 이제 다운로드 받은 JDK 설치 파일을 "더블클릭"해서 설치해주세요.

-> 설치 시 세팅(설치 경로 변경 등)은 하지말고 기본값 그대로 Next, Next 하시면 됩니다.

 

설치가 완료되면 윈도우에서는 cmd창, Mac에서는 터미널창에서 아래와 같이 자바의 버전을 확인하는 명령어를 입력해보세요.

java -version

결과는 아래처럼 나와야 합니다. 물론 버전을 나타내는 숫자는 다를 수 있습니다.

자바 버전 확인

여기서 확인할 것은 세 번 째 줄에 HotSpot이라고 뜨는지가 중요합니다.

(자바는 실행환경만 제공하는 JRE와 개발환경까지 제공하는 JDK가 있습니다.

저희는 JDK를 설치한 것이고 JDK의 버전에는 저렇게 HotSpot Server VM이라는 게 출력됩니다.)

 

여기까지 잘 따라오셨다면 이제 이클립스를 설치해주세요.

이클립스 설치 화면

우리는 이클립스 인스톨러에서 위에서 두 번째 꺼를 선택해서 설치할겁니다. 

설치 위치는 기본적으로 세팅이 되어있습니다. 그냥 INSTALL 버튼을 꾹 눌러주시면 됩니다.

만약 Java 경로가 나오지 않는다면 Java 설치가 제대로 안되었다는 의미이므로 확인을 해보셔야 합니다.

 

설치가 진행되고 있습니다. 

이런 저런 파일들을 인터넷에서 다운로드 받아가면서 설치를 합니다.

 

중간에 이런 라이센스 동의 팝업창이 뜨면 "Remember accepted licenses"에 체크해주고 "Accept"버튼을 눌러줍니다.

여기도 마찬가지입니다. "Remember choice"에 체크해주시고, "Accept" 고고싱~

이 화면은 윈도우 운영체제에서는 안나올 수 있으니, "이런 화면은 왜 안나오지?"하실 필요가 없습니다.

윈도우에서는 그냥 next, next 하시면 될겁니다.

여기서도 체크해주고 "Accept selected" 고고싱~

설치가 완료되면 Launch 버튼이 활성화됩니다.

이클립스 설치 완료 화면

이제 Launch 버튼을 눌러 실행을 시켜보도록 하겠습니다.

workspace 경로 설정창

실행하면 위와 같은 창이 뜨는데 무시하고 그냥 "Launch" 버튼을 클릭합니다. (경로는 다를 수 있습니다.)

welcome 창

welcome 창이 떠있습니다. 이런저런 메뉴가 보이고 바로 프로젝트를 만들어 볼 수 있는 메뉴도 보입니다.

이제 간단한 프로젝트를 하나 만들어 보겠습니다.

바로 "안녕 프로젝트"입니다.

welcome 창의 우측에서 "Tutorials"를 선택합니다.

"Create a Hello World application"을 선택합니다.

뭔가 바둑판처럼 생긴 복잡해보이는 화면이 나왔는데 신경끄고 오른쪽에 보이는 "웰컴창"만 보시면 됩니다.

따라하기처럼 되어있는데 버튼만 누르면 알아서 이것저것 해줍니다.

여기서 중요한 것은 순서입니다.

Hello World 애플리케이션을 만들기 위한 작업 순서를 한번 연습하고

다음에 다른 애플리케이션을 만들 때 동일한 순서로 작업을 진행하면 됩니다.

 

가운데 파란색으로 "Click to Begin"을 클릭해봅시다.

바로 아래쪽에 있는 "Open the Java perspective" 메뉴가 열리면서 이런저런 설명이 또 나옵니다.

설명은 어렵지 않으니 한번 읽어보고, "Click to perform"을 클릭합니다.

Java Perspective가 선택됨

뭔가 실행하는 듯 하더니 이클립스 창 우상단에 선택된 아이콘이 변경되었습니다.

원래 커피콩 모양이 있는 아이콘이 선택되어있었는데, 이제 J라는 글자가 있는 아이콘이 선택되어져 있네요.

그리고 웰컴창에서는 다음 단계인 "Create a Java project" 메뉴가 열렸습니다.

설명을 한번 읽어보고 또 "Click to perform" 을 클릭합니다.

자바 프로젝트 생성창

자바 프로젝트 생성창이 떴는데 여기서 "Project name"만 입력해주고 "Finish"버튼을 클릭합니다.

좌측의 "Project Explorer" 뷰에 입력만 프로젝트명이 보이는지 확인합니다.

생성된 HelloWorld 프로젝트

이제 다음 단계인 "Create your HelloWorld class" 를 진행합니다.

설명에 있는대로 따라하거나 "Click to perform"을 클릭합니다.

HelloWorld 클래스 생성창

클래스 생성창이 뜨는데 여기서는 "Name""HelloWorld" 입력 후 아래쪽에 "public static void main(String[] args)" 옆의 체크박스를 체크하고 "Finish" 합니다.

생성된 HelloWorld 클래스

HelloWorld 클래스가 생성되어 좌측의 Package Explorer 에도 파일이 생성된 것을 확인할 수 있고,

가운데 텅텅 비어있던 창에도 뭔가가 나타났습니다. 

이것이 바로 자바 문법에 기초한 소스코드입니다.

자, 이제 처음으로 소스코드를 작성해볼 차례입니다.

웰컴창의 설명대로 아래처럼 출력문을 하나 작성해 주세요.

Hello world! 출력문 작성

위 처럼 한줄을 추가하고 저장합니다.

이제 마지막으로 우리가 작성한 코드를 실행해보겠습니다.

웰컴창 마지막 단계의 설명을 따라서 실행해봅니다.

HelloWorld 실행하기
HelloWorld 실행 결과

HelloWorld에 작성한 출력문에 따라 그대로 출력되는 것을 확인할 수 있습니다.

여기까지가 HelloWorld 튜토리얼의 끝입니다.

 

우리는 하나만 더 해보죠.

System.out.println("Hello world!");

여기서 "Hello world!""안녕 프로젝트 성공" 으로 바꿔서 출력할겁니다.

아래처럼 변경해주시면 됩니다.

System.out.println("안녕 프로젝트 성공");

이제 다시 실행해보세요. 

아래처럼 결과가 잘 나오면 됩니다. 

 

여기까지 잘 따라 오셨습니다.

여러분은 이제 개발자가 되었습니다. 

 

이번 시간에는 JDK 설치와 이클립스 IDE 설치 그리고 헬로월드 애플리케이션 만들기 까지

무작정 따라해보는 시간을 가졌습니다.

이제 개발을 위한 기본적인 준비는 모두 끝났습니다.

 

다음 시간부터는 자바언어를 이용하여 간단한 애플리케이션을 직접 만들어보는 시간을 가지도록 하겠습니다.

 

 

프로그래밍 소스 코드 일부

서문

나는 이 글을 쓰는 지금 7년차 자바 백엔드 개발자이다.

나는 자바를 제대로 공부하지도 않고 개발자가 되었고, 개발자가 된지 5년이 지나서야 책을 읽어봤다.

수많은 책들이 있었고 그 중 제일 유명한 남궁성님의 책과 윤성우님의  책을 사서 훑어보았다.

책은 너무 두꺼웠고 다시금 까먹고 있던 기초지식을 확인하는 기회가 되었다.

그러다가 한 학생을 가르치게 되었는데 비전공자라 책의 내용을 이해하는데 힘들어했다.

언젠간 나도 책을 내봐야지라는 생각을 가지고 있던터라 이참에 책의 기초가 될만한 강의를 여기서 해볼까 한다.

일반인들, 개발자가 되려는 비전공자들, 그리고 어린 학생들이 읽어도 쉽게 이해할 수 있는 내용으로 강의를 하려 한다.

내 아이가 나중에 커서도 자바가 많이 사용된다면 읽어보도록 추천할 수 있을 정도의 퀄리티를 갖는 내용으로 말이다.

그래서 어떻게 쉽게 전달할 수 있을지 많은 고민을 해야할 것이기에 강의가 빨리 진행되기는 어려울 수 있으나 조금씩 꾸준히 해보려고 한다.

 

 

오늘은 그 1일차로 프로그래밍이란 무엇인지에 대해 얘기를 해보겠습니다.

 

자바란?

세상에는 많은 언어들이 있습니다. 한국어, 중국어, 영어, 일본어, 스페인어, 불어, 독어 등등 말이죠.

한국사람들은 한국어를 사용하고, 일본사람들은 일어를 사용합니다.

어떤 사람들은 3개국어 4개국어를 하기도 합니다.

일본어는 한국어와 문법이 유사해서 쉽고, 영어는 문법이 달라 배우기 어렵다고들 합니다.

언어마다 특정 표현을 할 때 좀더 공감이 가는 문장이 있습니다.

한국어로 직역 또는 의역해도 영어의 특정 문장의 느낌을 그대로 전달하기는 힘들 때가 있는 것처럼 말이죠.

 

프로그래밍 언어에도 그러한 내용이 딱 들어맞습니다.

자바는 수많은 프로그래밍 언어(세계 각국의 언어)들 중 하나입니다. 

자바 개발자(한국인)들은 자바(한국어)로 개발을 합니다.

모국어는 한국어이지만 3개국어, 4개국어를 할 줄 아는 사람들이 있듯이,

자바 개발자들도 자바만 하는것이 아니라 파이썬, 자바스크립트, C# 등의 언어를 제2외국어처럼 하기도 합니다.

자바와 문법이 유사한 언어는 자바개발자들에게는 learning curve가 낮지만, 너무 다른 언어는 적응하기가 힘들죠.

마치 한국어와 일본어, 한국어와 영어의 차이처럼 말이죠.

자바로는 구현하기 쉬운 기능이 다른 언어에서는 구현하기 힘들 수도 있습니다.

 

사람들은 언어를 이용하여 다른 사람들과 소통을 합니다.

어휘력이 좋은 사람이 있고 안좋은 사람도 있죠.

대화의 논리가 확실히 잡혀있는 사람도 있고 논리는 없고 앞뒤없는 대화를 하기도 합니다.

개발자들은 소스코드를 이용하여 소통을 합니다.

자바 언어에서 제공하는 문법을 많이 알고있는 개발자도 있고 기초적인 것만 알고있는 개발자도 있죠.

동일한 문제를 풀때에도 알고리즘이 간결하고 명확한 개발자도 있고, 그렇지 않은 개발자도 있습니다.

즉, 자바라는 언어는 개발자들이 프로그래밍을 할 때 사용하는 제2외국어와 같은 존재입니다.

 

소스코드와 소설

제 와이프는 제가 IDE(개발툴)화면에 코딩을 하는 모습을 보고, "이게 뭐야? 도대체 뭐라고 쓰는건지 하나도 모르겠네. 이런게 이해가 되?" 라고 질문을 합니다. 당연히 그런 반응이 나올 수 밖에 없습니다. 와이프 입장에서는 제가 오지의 인디언이 사용하는 언어로 글을 쓰고있는 것처럼 느껴질 테니까요. 

개발자들은 자신이 사용하는 프로그래밍 언어(제2외국어)를 이용하여 자신들만의 글을 써내려 갑니다. 같은 내용에 대해서 개발을 한다해도 개발자들 성향에 따라 1. 효율성은 조금 떨어지지만 가독성이 좋은 코드를 작성할 수도 있고, 2. 효율성은 극대화했지만 다른 개발자가 이해하기 힘든 코드를 작성할 수도 있습니다. 물론 저는 전자를 지향하고 후배들에게도 전자를 지향하도록 조언합니다.

 

시인, 소설작가, 수필가 등 글을 쓰는 분들이 단어 하나하나에 고심을 하듯 저도 코딩을 할 때 고민을 많이 합니다. 동일한 기능을 하더라도 좀 더 간결하고 명확하게 효율적인 코딩을 하려고 말이죠. 좋은 글을 작성하기위해 첨삭을 받는 것처럼, 개발자들도 코드리뷰 시간을 통해 고급개발자들의 조언을 듣습니다. 그래서 저는 프로그래밍을 이렇게 정의합니다. "프로그래밍이란 개발자들이 써내려가는 글이다"라고 말이죠. 내가 작성한 코드가 짧지만 이해하기 어려운 시가 될 수도 있고, 좀 길어도 술술 읽어내려갈 수 있는 판타지 소설이 될 수도 있습니다. 어떤 글을 작성하느냐는 순전히 개발자들의 몫이죠. 

 

 

Wrap Up

프로그래밍 언어란 개발을 위한 언어로 일어, 중국어, 영어와 같은 제2외국어의 하나다.

프로그래밍 언어에는 여러 언어들이 존재하는데 그 중 하나가 자바(java)다.

 

고급내용 보충

자바는 다른 언어들과는 다르게 JVM(Java Virtual Machine)이라는 가상머신 위에서 실행이 됩니다. 이 때문에 플랫폼(OS, 운영체제)에 의존적이지 않죠. Linux계열에서도 실행이 가능하고, Windows에서도 실행이 가능합니다. 심지어 안드로이드 애플리케이션도 자바로 개발합니다(요즘은 Kotlin이라는 언어도 많이 사용하시더군요). 또한, JVM이 직접 메모리 관리를 해주기 때문에 별도로 개발자가 메모리 관리를 하지 않아도 됩니다. C언어는 개발자가 직접 메모리에 접근을 하여 사용할 수 있기 때문에 관리도 직접 해야하죠.

자바는 웹개발에 많이 사용됩니다. Python(파이썬)은 빅데이터 영역에서 많이 사용되고, C, C++은 임베디드 영역에서 많이 사용되며, C#은 게임개발에서 많이 사용됩니다.

 

 

💻 Programming/Java

[Java] 로또 번호 자동 생성기 만들기

2019년 6월 15일 로또 1등 당첨번호

이번에는 자바로 로또 번호 자동 생성기를 만들어보도록 하겠습니다.

자바로 프로그래밍을 하기전에 우선 로또의 규칙부터 알아야 겠죠.

로또에는 1부터 45까지의 숫자가 존재하고

보너스 번호를 포함하여 총 7개의 숫자를 랜덤하게 뽑습니다.

각 숫자는 중복되어 선택할 수 없습니다.

여기서 키 포인트 단어는 바로 랜덤과 중복 입니다.

자바에서 중복을 제거하는 가장 좋은 방법은 Set을 이용하는 방법입니다.

 

자, 그럼 랜덤하게 숫자를 구하는 것부터 해보도록 하겠습니다.

자바에서 랜덤한 숫자를 얻을 때는 Math.random() 메서드를 이용합니다.

그런데 이 메서드는 0부터 1사이의 double 형태의 소수를 리턴해줍니다.

오잉?? 그럼 어떻게 1부터 45까지의 숫자를 얻는다는 걸까요??

이제부터 트릭을 알려드리겠습니다.

 

Math.random()은 0보다 크거나 같고 1보다 작은 숫자를 반환해줍니다.

내가 얻고자하는 max숫자를 곱해주면

0부터 max값 사이의 double 형태의 숫자를 얻을 수 있습니다.

그럼 이 숫자를 다시 int형태로 casting을 해버리면?

0<= 원하는 숫자 < max 사이의 int 값을 얻을 수 있습니다.

 

예제를 한번 보여드리도록 하겠습니다.

public static void main(String[] args) {
  getRandomNumber();
}
	
private static void getRandomNumber() {
  final int max = 46;
  for(int i = 0; i < 10; i++) {
    int randomNumber = (int)(Math.random() * max);
    System.out.println(randomNumber);
  }
}

위 코드를 실행시키면 아래와 같은 결과를 얻을 수 있습니다.

0
12
34
27
5
21
10
24
43

위 결과에는 중복된 숫자가 나오지 않았지만

몇 번 실행하다보면 동일한 숫자가 연속으로 나오는 경우도 있습니다.

따라서 중복을 제거해주는 과정이 필요하게 됩니다.

이때 필요한 것이 바로 Set입니다.

Set은 자바에서 중복을 제거하고자 할 때 아주 유용하게 쓰이는 자료구조입니다.

Set의 구현체는 여러가지가 있는데 일반적으로 많이 쓰이는 것은 HashSet입니다.

아래 예제 코드를 한번 보겠습니다.

public static void main(String[] args) {
  removeDuplicate();
}
	
private static void removeDuplicate() {
  Set<Integer> noDuplicated = new HashSet<>();
  noDuplicated.add(30);
  noDuplicated.add(30);
  noDuplicated.add(31);
  System.out.println(noDuplicated);
}

위 코드를 실행하면 아래와 같이 출력됩니다.

[30, 31]

보시는 바와 같이 30을 두 번 add 했는데 1개만 저장이 되었습니다.

이것을 이용해서 이미 뽑은 숫자는 저장하지 않고 새로운 번호를 뽑도록 할 수 있습니다.

 

아래는 완성된 로또 번호 생성기의 샘플입니다.

private static void lotto() {
  final int min = 1;
  final int max = 45;
		
  Set<Integer> selected = new HashSet<>();
  while(true) {
    int randomNumber = (int)(Math.random() * (max - min +1) + min);
    if(selected.add(randomNumber)) {
      if(selected.size() == 6) {
        break;
      }
    }
  }
  System.out.println(selected.stream().sorted().collect(Collectors.toList()));
}

위 메서드를 main 함수에서 실행시키면

1~45까지의 숫자들 중에서 중복되지 않은 6개의 숫자를 출력해줍니다.

랜덤 번호 생성하는 부분이 조금 수정된 것을 눈치채셨나요?

저 위에서 보여드린 로직으로는 0이 나올 수 있기 때문에 수정을 한 것입니다.

자바로 랜덤 숫자 구하는 방법에 대한 자세한 내용은 랜덤 숫자 구하기 에서 확인하실 수 있습니다.

 

위 메서드를 10번 실행한 결과는 아래와 같습니다.

[5, 17, 18, 25, 29, 33]
[9, 13, 16, 26, 30, 34]
[21, 24, 27, 30, 31, 42]
[9, 15, 17, 34, 36, 42]
[2, 3, 15, 35, 38, 41]
[8, 16, 30, 31, 36, 39]
[1, 5, 11, 40, 43, 44]
[1, 3, 4, 18, 21, 39]
[4, 7, 19, 28, 38, 40]
[7, 9, 14, 18, 30, 41]

이상으로 자바로 심플한 로또 번호 자동 생성기 만들기 포스팅을 마치도록 하겠습니다.

궁금한 점이 있으시면 댓글 달아주시고,

포스팅 내용이 도움이 되셨다면 공감 꾹 부탁해요 ^-^

 

💻 Programming

스프링부트 스케쥴러 사용하기

스프링부트 스케쥴러

이번 포스팅에서는 스프링부트 프로젝트에서 스케쥴링 작업을 등록하여 사용하는 방법에 대해서 설명합니다.

스프링 부트에서 스케쥴러를 사용하려면 우선 아래처럼

@EnableScheduling 어노테이션을 @Configuration이 붙은 클래스에 등록해줘야 합니다.

 

스케쥴링 활성화를 위한 @EnableScheduling 사용

 

위 처럼 어노테이션을 붙여주면

스프링이 관리하는 빈 중에서 아래와 같이

@Scheduled 어노테이션이 붙어있는 것들을

찾아서 활성화 시켜주는 역할을 하게됩니다.

 

위 처럼 @Scheduled 어노테이션을 붙여주고 실행주기를 특정지어주면

해당 애플리케이션이 실행되면 자동으로 실행이 됩니다.

 

실행주기를 설정하는 방법은 기본적으로 세 가지가 있습니다.

 

fixedRate : 매 특정 밀리초마다 동작

fixedDelay : 해당 기능이 종료된 후 특정 밀리초 이후에 다시 동작

cron : 크론표현식에 정해진 내용대로 동작

 

여러 개의 스케쥴 잡을 등록할 때에는 주의할 점이 있습니다.

위 처럼 두 개의 스케쥴 잡이 등록되어있을 경우 한 번에 하나의 잡만 동작한다는 점입니다.

즉, @Scheduled가 붙은 기능들이 실행되는 시간이 중복될 경우 한 번에 하나의 작업만 실행됩니다.

 

만약 두 개 이상의 기능이 한꺼번에 실행되어도 성능에 문제가 없을 경우에는

아래처럼 @Async처리를 할 수 있습니다.

 

@Async 처리한 스케쥴 tasks

 

물론, @Async 가 적용되려면 @Configuration에 @EnableAsync도 추가해줘야 합니다.

 

여기까지 설정이 되었다면 위 두 scheduled task들은 동시에 실행됩니다.

 

추가로 @Async를 붙이지 않은 task를 하나 더 추가하면 어떻게 동작할까요?

task를 하나 더 추가해서 꼭!! 테스트해보세요.

 

이상으로 스프링부트에서 스케쥴링 잡을 등록하여 활용하는 방법에 대해 간단히 포스팅 해보았습니다.

유용했다면 좋아요 꾹!꾹!꾹! 눌러주세요 ^-^

💻 Programming

안드로이드 폰에 웹사이트 바로가기 만들기

인터넷 서핑을하다가 앱버전이 별도로 없는 사이트를 홈화면에 등록하여 

앱을 실행하듯 사용할 수 있도록 바로가기를 만들어보도록 하겠습니다.

갤럭시 S8 & 크롬(Chrome)브라우저 기준으로 스샷을 첨부하였습니다.

참고로 기종(정확히는 안드로이드OS 버전) 및 

사용하시는 브라우저의 종류에 따라 스샷의 내용이 상이할 수 있습니다.



1. 우선 크롬브라우저를 이용하여  바로가기를 만들고 싶은 웹사이트로 이동을 합니다.

2. 크롬 브라우저 우상단의 메뉴버튼(세로로 나열된 동그라미 세개)을 터치하여 메뉴를 확인합니다.


3. 홈 화면에 추가를 선택합니다.




4. 바로가기 이름을 입력하고 추가를 터치합니다.




5. 다시 한번 추가를 터치합니다.




6. 아래처럼 홈 화면에 아이콘이 생긴 것을 확인하시면 됩니다.


7. 이제 생성된 바로가기를 터치하여 실행해보세요~


이상으로 안드로이드 폰의 홈 화면에 웹사이트 바로가기 만들기 포스팅을 마칩니다.




스트링 거꾸로 뒤집기

 

자바에서 스트링을 거꾸로 뒤집는 간단한 방법을 소개해드립니다.

 

자바에는 각종 array로부터 String을 쉽게 만들 수 있도록 해주는 StringBuilder가 있습니다.

 

생성자에 String을 그대로 넣어서 새로운 스트링을 만들 수도 있을 뿐만 아니라 기본적으로 구현되어있는 reverse 메서드가 있습니다.

 

이 메서드를 이용하면 아래와 같이 단 한 줄로 스트링을 거꾸로 배열할 수 있습니다.

String a = "abcdefg";

String b = new StringBuilder(a).reverse().toString();

System.out.println(a);
System.out.println(b);

출력 결과 

abcdefg

gfedcba

 

아주 간단합니다.

 

💻 Programming/JSP

[JSP] Security ( 보안 )

JSP와 servlets 은 Web 개발자들을 위해서 보안(인증)을 처리할 수 있는 다양한 방법을 제공합니다.  

오늘은 그 중 두가지에 대해서만 알아보도록 하겠습니다. 

 

역할 기반 인증

servlet 에서 제공하는 역할 기반 인증은 사용자 레벨에서 리소스를 제한하는 것이 아니라 사용자에게 역할을 부여하고 특정 역할을 가진 모든 사용자에 대해서 리소스를 제한하는 방법입니다.  

톰캣 홈 디렉토리의 conf디렉토리에 tomcat-users.xml 파일을 만들고 아래코드를 넣어주세요.

<?xml version='1.0' encoding='utf-8'?> 
<tomcat-users> 
	<role rolename="tomcat"/> 
	<role rolename="role1"/> 
	<role rolename="manager"/> 
	<role rolename="admin"/> 
	<user username="tomcat" password="tomcat" roles="tomcat"/> 
	<user username="role1" password="tomcat" roles="role1"/> 
	<user username="both" password="tomcat" roles="tomcat,role1"/> 
	<user username="admin" password="secret" roles="admin,manager"/> 
</tomcat-users>

위 코드가 뭘 하고있는지는 대충 봐도 아시겠죠? 역할을 생성하고 사용자를 만들때 역할을 부여하고 있습니다.

 

이제  web.xml파일에 <security-constraint> 태그를 추가하고 아래처럼 넣어보세요. 물론 url-pattern은 여러분이 가지고 있는 웹애플리케이션에 실제로 존재하는 url이어야게죠? 그래야 테스트가 가능합니다~ 

 

<web-app> 
    ... 
    <security-constraint> 
    	<web-resource-collection> 
        	<web-resource-name> SecuredBookSite </web-resource-name> 
            <url-pattern>/secured/*</url-pattern> 
            <http-method>GET</http-method> 
            <http-method>POST</http-method> 
        </web-resource-collection> 
        <auth-constraint> 
        	<description> Let only managers use this app </description> 
            <role-name>manager</role-name> 
        </auth-constraint> 
    </security-constraint> 
    <security-role> 
    	<role-name>manager</role-name> 
    </security-role> 
    <login-config> 
    	<auth-method>BASIC</auth-method> 
    </login-config> 
    ... 
</web-app>

위 소스코드가 의미하는 것이 무언인가 하면 다음과 같습니다. 

  • HTTP GET 이나 POST 방식의 요청에 대해서 /secured/* URL에 대한 요청이 들어오면 보안설정의 제약을 받게됩니다.

  • 매니저 역할을 가지고 있는 사용자에 대해서만 /secured/* 리소스에 접근이 가능합니다.

  • 마지막으로 login-config 태그가 기본형태의 인증을 위해서 사용되었습니다. 

이제 /security내부의 페이지로 접근을 하려면 사용자명과 비밀번호를 입력하라는 창이 뜨게됩니다. 접속할 수 있는 역할을 가지고 있지 않거나 인증에 실패하면 접속이 불가능하나 페이지가 되는 것이죠. 

 

Form을 이용한 인증

FORM 인증을 사용하려면 사용자에게 로그인 폼을 제공해주어야 합니다.  

<html>

<body bgcolor="#ffffff">
    <form method="POST" action="j_security_check">
        <table border="0">
            <tr>
                <td>Login</td>
                <td><input type="text" name="j_username"></td>
            </tr>
            <tr>
                <td>Password</td>
                <td><input type="password" name="j_password"></td>
            </tr>
        </table> <input type="submit" value="Login!"> </center>
    </form>
</body>

</html>

위 코드를 login.jsp에 넣어주세요. <form> 태그 안에있는 action의 값은  j_security_check 여야 합니다. POST 방식이 사용되어야 한다는 것은 알고 계시겠죠? 자 이제 web.xml의 <login-config> 태그를 FORM을 이용하도록 수정해야합니다.

<web-app> 
    ... 
    <security-constraint>
        <web-resource-collection>
            <web-resource-name> SecuredBookSite </web-resource-name>
            <url-pattern>/secured/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <description> Let only managers use this app </description>
            <role-name>manager</role-name>
        </auth-constraint>
    </security-constraint>
    <security-role>
        <role-name>manager</role-name>
    </security-role>
    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
            <form-error-page>/error.jsp</form-error-page>
        </form-login-config>
    </login-config> 
    ...
</web-app>

이제  /secured/* 주소로 접속을 시도해 보세요. 사용자 ID와 패스워드를 입력하라고 할겁니다. 컨테이너가  "j_security_check" 액션을 만나면요청을 인증하기위한 내부 메카니즘을 실행합니다.

로그인이 성공하고 리소스를 조회할 수 있는 역할을 가지고 있다면 컨테이너는 사용자를 확인하기위해서 session-id 를 비교합니다. 컨테이너는 세션아이디를 가지고있는 쿠키와 함께 세션을 유지하게됩니다. 서버가 이 쿠키를 클라이언트로 되돌려보내고 이후 요청때마다 이 쿠키를 서버로 전송하게되면 컨테이너는 요청하는 클라이언트를 식별할 수 있습니다.

로그인이 실패하면 서버는 에러페이지를 전송하게 됩니다.  

 

j_security_check 가 톰캣 컨테이너에서 어떻게 동작하는지에 대해서 더 자세한 정보를 보시려면 Standard Realm Implementations 이곳에 가보세요. 

 

Servlet/JSP의 코드로 보안적용하기

HttpServletRequest 객체가 보안관련해서 제공하는 메소드들은 다음과 같습니다.

 

SN Method and Description
1 String getAuthType()
The getAuthType() method returns a String object that represents the name of the authentication scheme used to protect the Servlet.
2 boolean isUserInRole(java.lang.String role)
The isUserInRole() method returns a boolean value: true if the user is in the given role or false if they are not.
3 String getProtocol()
The getProtocol() method returns a String object representing the protocol that was used to send the request. This value can be checked to determine if a secure protocol was used.
4 boolean isSecure()
The isSecure() method returns a boolean value representing if the request was made using HTTPS. A value of true means it was and the connection is secure. A value of false means the request was not.
5 Principle getUserPrinciple()
The getUserPrinciple() method returns a java.security.Principle object that contains the name of the current authenticated user.

 

예를들어 매니저 권한을 갖고있는 사용자들을 위한 링크를 제공하는 JavaServer Page 를 만들려면 아래 코드를 삽입해주시면 되는거죠 

<% if (request.isUserInRole("manager")) { %> 
    <a href="managers/mgrreport.jsp">Manager Report</a> 
    <a href="managers/personnel.jsp">Personnel Records</a> 
<% } %>

그러면 사용자 역할을 검사한 뒤 매니저역할을 가지고 있는 사용자에게만 링크를 보여주게 됩니다. 만약 로그인 폼에서 입력한 사용자명이 필요한 경우에는 getRemoteUser 메소드를 호출하면 됩니다.

 

 

 

Reference : http://www.tutorialspoint.com/jsp/jsp_security.htm 

 

 

 

 

 

 

💻 Programming/JSP

[JSP] Database CRUD (데이터베이스 연동)

오늘은 JSP를 이용하여 데이타베이스에 접속하고  SELECT, INSERT, DELETE, 그리고 UPDATE 하는 방법에 대해서 알아보도록 하겠습니다.

우선 데이타베이스를 설치가되어있고 emp계정이 만들어져 있으며 Employees테이블이 id, first, last, age 컬럼으로 이루어져 있다고 가정을 했습니다. 

 

SELECT Operation:

JTSL을 이용하여 JSP 페이지를 작성합니다.

<%@ page import="java.io.*,java.util.*,java.sql.*"%> <%@ page import="javax.servlet.http.*,javax.servlet.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%> <html>

<head>
    <title>SELECT Operation</title>
</head>

<body>
    <sql:setDataSource var="snapshot" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/TEST" user="emp"
        password="emp" />
    <sql:query dataSource="${snapshot}" var="result"> SELECT * from Employees; </sql:query>
    <table border="1" width="100%">
        <tr>
            <th>Emp ID</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Age</th>
        </tr>
        <c:forEach var="row" items="${result.rows}">
            <tr>
                <td>
                    <c:out value="${row.id}" />
                </td>
                <td>
                    <c:out value="${row.first}" />
                </td>
                <td>
                    <c:out value="${row.last}" />
                </td>
                <td>
                    <c:out value="${row.age}" />
                </td>
            </tr>
        </c:forEach>
    </table>
</body>

</html>

위 JSP페이지에 접속하면 아래와 같은 결과가 나오겠죠? 

Emp ID

First Name

Last Name

Age

100

Zara

Ali

18

101

Mahnaz

Fatma

25

102

Zaid

Khan

30

103

Sumit

Mittal

28

 

INSERT Operation:

역시나 JSTL을 이용한 JSP 페이지입니다. 

<%@ page import="java.io.*,java.util.*,java.sql.*"%> <%@ page import="javax.servlet.http.*,javax.servlet.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%> <html>

<head>
    <title>JINSERT Operation</title>
</head>

<body>
    <sql:setDataSource var="snapshot" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/TEST" user="emp"
        password="emp" />
    <sql:update dataSource="${snapshot}" var="result"> INSERT INTO Employees VALUES (104, 2, 'Nuha', 'Ali');
    </sql:update>
    <sql:query dataSource="${snapshot}" var="result"> SELECT * from Employees; </sql:query>
    <table border="1" width="100%">
        <tr>
            <th>Emp ID</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Age</th>
        </tr>
        <c:forEach var="row" items="${result.rows}">
            <tr>
                <td>
                    <c:out value="${row.id}" />
                </td>
                <td>
                    <c:out value="${row.first}" />
                </td>
                <td>
                    <c:out value="${row.last}" />
                </td>
                <td>
                    <c:out value="${row.age}" />
                </td>
            </tr>
        </c:forEach>
    </table>
</body>

</html>

결과는 아래처럼 한줄이 추가가 되어 나오겠죠.

Emp ID

First Name

Last Name

Age

100

Zara

Ali

18

101

Mahnaz

Fatma

25

102

Zaid

Khan

30

103

Sumit

Mittal

28

104

Nuha

Ali

2

 

DELETE Operation:

<%@ page import="java.io.*,java.util.*,java.sql.*"%> <%@ page import="javax.servlet.http.*,javax.servlet.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%> <html>

<head>
    <title>DELETE Operation</title>
</head>

<body>
    <sql:setDataSource var="snapshot" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/TEST" user="emp"
        password="emp" />
    <c:set var="empId" value="103" />
    <sql:update dataSource="${snapshot}" var="count"> DELETE FROM Employees WHERE Id = ?
        <sql:param value="${empId}" />
    </sql:update>
    <sql:query dataSource="${snapshot}" var="result"> SELECT * from Employees; </sql:query>
    <table border="1" width="100%">
        <tr>
            <th>Emp ID</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Age</th>
        </tr>
        <c:forEach var="row" items="${result.rows}">
            <tr>
                <td>
                    <c:out value="${row.id}" />
                </td>
                <td>
                    <c:out value="${row.first}" />
                </td>
                <td>
                    <c:out value="${row.last}" />
                </td>
                <td>
                    <c:out value="${row.age}" />
                </td>
            </tr>
        </c:forEach>
    </table>
</body>

</html>

결과는 아래와 같습니다. 

Emp ID

First Name

Last Name

Age

100

Zara

Ali

18

101

Mahnaz

Fatma

25

102

Zaid

Khan

30

104

Nuha

Ali

2

 

UPDATE Operation:

<%@ page import="java.io.*,java.util.*,java.sql.*"%> <%@ page import="javax.servlet.http.*,javax.servlet.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%> <html>

<head>
    <title>DELETE Operation</title>
</head>

<body>
    <sql:setDataSource var="snapshot" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/TEST" user="emp"
        password="emp" />
    <c:set var="empId" value="102" />
    <sql:update dataSource="${snapshot}" var="count"> UPDATE Employees SET last = 'Ali'
        <sql:param value="${empId}" />
    </sql:update>
    <sql:query dataSource="${snapshot}" var="result"> SELECT * from Employees; </sql:query>
    <table border="1" width="100%">
        <tr>
            <th>Emp ID</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Age</th>
        </tr>
        <c:forEach var="row" items="${result.rows}">
            <tr>
                <td>
                    <c:out value="${row.id}" />
                </td>
                <td>
                    <c:out value="${row.first}" />
                </td>
                <td>
                    <c:out value="${row.last}" />
                </td>
                <td>
                    <c:out value="${row.age}" />
                </td>
            </tr>
        </c:forEach>
    </table>
</body>

</html>

결과는 아래처럼 나오겠죠?

 

Emp ID

First Name

Last Name

Age

100

Zara

Ali

18

101

Mahnaz

Fatma

25

102

Zaid

Ali

30

104

Nuha

Ali

2

 

 

 

💻 Programming/JSP

[JSP] JSTL ( JSP Standard Tag Library )

JSTL 는 유용한 JSP 태그들을 모아놓은 라이브러리입니다. 커스텀 태그를 JSTL tags와 통합할 수 있는 프레임워크도 제공하므로 알아두시면 좋을거에요. 

JSTL태그는 기능별로 분류가 됩니다.  

  • Core Tags

  • Formatting tags

  • SQL tags

  • XML tags

  • JSTL Functions


JSTL 설치하기

Apache Tomcat container 를 사용중이면 아래 두가지 스텝으로 설치가 완료됩니다.

  • Apache Standard Taglib 이곳에서 라이브러리를 다운로드하고 압축을 풀어주세요.

  • 압축이 풀린 디렉토리내의 lib디렉토리의 JAR 파일들을 여러분이 사용하려는 애플리케이션의 webapps\ROOT\WEB-INF\lib 디렉토리안에 넣어주세요. ( 이거는 이클립스에서 직접 하실 수 있는건 아시죠? )  

태그라이브러리를 사용하려면 <taglib> 디렉티브를 JSP 페이지 제일 위쪽에 선언해주셔야 합니다.  


Core Tags:

JSTL 태그 중에서 가장 많이 사용되는 태그입니다.  

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

 

TagDescription
<c:out >Like <%= ... >, but for expressions.
<c:set >Sets the result of an expression evaluation in a 'scope'
<c:remove >Removes a scoped variable (from a particular scope, if specified).
<c:catch>Catches any Throwable that occurs in its body and optionally exposes it.
<c:if>Simple conditional tag which evalutes its body if the supplied condition is true.
<c:choose>Simple conditional tag that establishes a context for mutually exclusive conditional operations, marked by <when> and <otherwise>
<c:when>Subtag of <choose> that includes its body if its condition evalutes to 'true'.
<c:otherwise >Subtag of <choose> that follows <when> tags and runs only if all of the prior conditions evaluated to 'false'.
<c:import>Retrieves an absolute or relative URL and exposes its contents to either the page, a String in 'var', or a Reader in 'varReader'.
<c:forEach >The basic iteration tag, accepting many different collection types and supporting subsetting and other functionality .
<c:forTokens>Iterates over tokens, separated by the supplied delimeters.
<c:param>Adds a parameter to a containing 'import' tag's URL.
<c:redirect >Redirects to a new URL.
<c:url>Creates a URL with optional query parameters


Formatting tags:

포매팅 관련 태그들입니다.다국적 Web 사이트를 만들때 유용하다고 하네요.

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

 

TagDescription
<fmt:formatNumber>To render numerical value with specific precision or format.
<fmt:parseNumber>Parses the string representation of a number, currency, or percentage.
<fmt:formatDate>Formats a date and/or time using the supplied styles and pattern
<fmt:parseDate>Parses the string representation of a date and/or time
<fmt:bundle>Loads a resource bundle to be used by its tag body.
<fmt:setLocale>Stores the given locale in the locale configuration variable.
<fmt:setBundle>Loads a resource bundle and stores it in the named scoped variable or the bundle configuration variable.
<fmt:timeZone>Specifies the time zone for any time formatting or parsing actions nested in its body.
<fmt:setTimeZone>Stores the given time zone in the time zone configuration variable
<fmt:message>To display an internationalized message.
<fmt:requestEncoding>Sets the request character encoding


SQL tags:

JSTL SQL 태그는 관계형 데이타베이스 시스템을 핸들링할 수 있습니다. ( Oracle, MySQL, Microsoft SQL Server )

<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>

 

TagDescription
<sql:setDataSource>Creates a simple DataSource suitable only for prototyping
<sql:query>Executes the SQL query defined in its body or through the sql attribute.
<sql:update>Executes the SQL update defined in its body or through the sql attribute.
<sql:param>Sets a parameter in an SQL statement to the specified value.
<sql:dateParam>Sets a parameter in an SQL statement to the specified java.util.Date value.
<sql:transaction >Provides nested database action elements with a shared Connection, set up to execute all statements as one transaction.


XML tags:

JSTL XML 태그는 JSP에서 XML 문서를 생성 및 조작할 수 있도록 해줍니다. 하지만 XML을 파싱하거나 데이타를 변환하거나 XPath 표현식을 사용하려면 추가적인 커스텀 태그가 필요합니다.  

<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>

아래의 두 jar파일도 <Tomcat Installation Directory>\lib 에 추가해주셔야 합니다. 

 

TagDescription
<x:out>Like <%= ... >, but for XPath expressions.
<x:parse>Use to parse XML data specified either via an attribute or in the tag body.
<x:set >Sets a variable to the value of an XPath expression.
<x:if >Evaluates a test XPath expression and if it is true, it processes its body. If the test condition is false, the body is ignored.
<x:forEach>To loop over nodes in an XML document.
<x:choose>Simple conditional tag that establishes a context for mutually exclusive conditional operations, marked by <when> and <otherwise>
<x:when >Subtag of <choose> that includes its body if its expression evalutes to 'true'
<x:otherwise >Subtag of <choose> that follows <when> tags and runs only if all of the prior conditions evaluated to 'false'
<x:transform >Applies an XSL transformation on a XML document
<x:param >Use along with the transform tag to set a parameter in the XSLT stylesheet


JSTL Functions:

JSTL 은 표준 함수들을 제공하고 있습니다. 대부분 스트링관련 함수들이죠.

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

 

FunctionDescription
fn:contains()Tests if an input string contains the specified substring.
fn:containsIgnoreCase()Tests if an input string contains the specified substring in a case insensitive way.
fn:endsWith()Tests if an input string ends with the specified suffix.
fn:escapeXml()Escapes characters that could be interpreted as XML markup.
fn:indexOf()Returns the index withing a string of the first occurrence of a specified substring.
fn:join()Joins all elements of an array into a string.
fn:length()Returns the number of items in a collection, or the number of characters in a string.
fn:replace()Returns a string resulting from replacing in an input string all occurrences with a given string.
fn:split()Splits a string into an array of substrings.
fn:startsWith()Tests if an input string starts with the specified prefix.
fn:substring()Returns a subset of a string.
fn:substringAfter()Returns a subset of a string following a specific substring.
fn:substringBefore()Returns a subset of a string before a specific substring.
fn:toLowerCase()Converts all of the characters of a string to lower case.
fn:toUpperCase()Converts all of the characters of a string to upper case.
fn:trim()Removes white spaces from both ends of a string.

 

 

 

Reference : http://www.tutorialspoint.com/jsp/jsp_standard_tag_library.htm 

 

💻 Programming/JSP

[JSP] Page Redirection ( 페이지 리디렉션 )

페이지 리디렉션을 하는 가장 간단한 방법은 response 객체의 sendRedirect() 메소드를 이용하는 것이랍니다. 

public void response.sendRedirect(String location) throws IOException

이 메소드는 상태코드와 새로운 페이지 주소를 함께 response객체에 담아서 브라우저로 전송합니다.  setStatus() 와 setHeader() 를 이용하여 세팅을 해주면 됩니다. 아래처럼 말이죠. 

.... String site = "http://www.newpage.com" ; response.setStatus(response.SC_MOVED_TEMPORARILY); response.setHeader("Location", site); ....

예제

JSP 로 어떻게 페이지 리디렉션을 하는지 예제를 통해 알아볼까요? 

<%@ page import="java.io.*,java.util.*" %> <html> <head> <title>Page Redirection</title> </head> <body> <center> <h1>Page Redirection</h1> </center> <% // New location to be redirected String site = new String("http://www.naver.com"); response.setStatus(response.SC_MOVED_TEMPORARILY); response.setHeader("Location", site); %> </body> </html>

위 코드를 PageRedirect.jsp 에 넣고 http://localhost:8080/PageRedirect.jsp 를 웹브라우저에서 요청해보세요.   

 

http://www.naver.com 사이트로 리디렉션이 되나요?? ^____^ 

 

 

 

Reference : http://www.tutorialspoint.com/jsp/jsp_page_redirect.htm 

 

 

💻 Programming/JSP

[JSP] File Upload ( 파일 업로드 )

파일 업로드 폼 만들기

 

다음에 볼 HTML 코드가 바로 파일 업로드 폼입니다. 여기서 중요한 점을 몇가지 짚고 넘어가겠습니다.

  • <form>의 method 속성은 POST 입니다. 

  • <form>의 enctype 속성은 multipart/form-data 입니다. 

  • <form>의 action 속성은 백엔드 쪽에서 파일 업로드를 핸들링할 JSP 파일입니다. 아래 예제는 UploadFile.jsp를 사용했습니다.

  • 한개의 파일만 업로드 할 때는  <input .../> 태그를 type="file" 속성고 함께 사용합니다. 멀티플 파일업로딩을 구현하려면 하나 이상의 input태그를 각기 다른 name으로 설정해줘야 합니다.  

<html> <head> <title>File Uploading Form</title> </head> <body> <h3>File Upload:</h3> Select a file to upload: <br /> <form action="UploadServlet" method="post" enctype="multipart/form-data"> <input type="file" name="file" size="50" /> <br /> <input type="submit" value="Upload File" /> </form> </body> </html>

위 소스를 UploadFile.htm에 넣어주세요. 위 페이지를 출력해보면 아래처럼 나올거에요. 파일을 업로드 해보세요 ^___^ 참고로 위 코드는 그냥 dummy코드라서 실제로 파일을 어딘가로 업로드 하지는 않습니다. 

 
 

백엔드 JSP 스크립트 만들기

 

우선 파일들이 업로드되었을 때 어디에 저장될지 경로를 지정해볼게요. 경로를 지정하는 방법은 소스에 하드코딩하는 방법도 있고 web.xml파일에 context-param 태그내에 지정해주는 방법도 있습니다.

<web-app> .... <context-param> <description>Location to store uploaded file</description> <param-name>file-upload</param-name> <param-value> c:\apache-tomcat-5.5.29\webapps\data\ </param-value> </context-param> .... </web-app>

아래는 한번에 여러개의 파일을 업로드 할 수 있는 UploadFile.jsp의 소스코드에요. 소스부터 보기전에 점검해야할 것들이 있습니다. 

  • 아래 예제는 FileUpload 클래스를 사용하기 때문에 최신버전의 commons-fileupload.x.x.jar 파일을 클래스패스에 넣어주셔야 합니다. 여기서 http://commons.apache.org/fileupload/ 다운로드 받으실 수 있어요. 

  • 또한 Commons IO 라이브러리도 필요합니다.  commons-io-x.x.jar 파일 역시 클래스 패스에 설정을 해주셔야 되요. 다운로드는 http://commons.apache.org/io/.

  • 아래 예제를 테스트할 때에는 maxFileSize 에 설정된 파일크기보다 작은 파일들만 업로드가 가능하답니다.

  • c:\temp 와 c:\apache-tomcat-5.5.29\webapps\data 디렉토리가 있는지 확인하시고 없으면 생성해주세요. 
     

<%@ page import="java.io.*,java.util.*, javax.servlet.*" %> <%@ page import="javax.servlet.http.*" %> <%@ page import="org.apache.commons.fileupload.*" %> <%@ page import="org.apache.commons.fileupload.disk.*" %> <%@ page import="org.apache.commons.fileupload.servlet.*" %> <%@ page import="org.apache.commons.io.output.*" %> <% File file ; int maxFileSize = 5000 * 1024; int maxMemSize = 5000 * 1024; ServletContext context = pageContext.getServletContext(); String filePath = context.getInitParameter("file-upload"); // Verify the content type String contentType = request.getContentType(); if ((contentType.indexOf("multipart/form-data") >= 0)) { DiskFileItemFactory factory = new DiskFileItemFactory(); // maximum size that will be stored in memory factory.setSizeThreshold(maxMemSize); // Location to save data that is larger than maxMemSize. factory.setRepository(new File("c:\\temp")); // Create a new file upload handler ServletFileUpload upload = new ServletFileUpload(factory); // maximum file size to be uploaded. upload.setSizeMax( maxFileSize ); try{ // Parse the request to get file items. List fileItems = upload.parseRequest(request); // Process the uploaded file items Iterator i = fileItems.iterator(); out.println("<html>"); out.println("<head>"); out.println("<title>JSP File upload</title>"); out.println("</head>"); out.println("<body>"); while ( i.hasNext () ) { FileItem fi = (FileItem)i.next(); if ( !fi.isFormField () ) { // Get the uploaded file parameters String fieldName = fi.getFieldName(); String fileName = fi.getName(); boolean isInMemory = fi.isInMemory(); long sizeInBytes = fi.getSize(); // Write the file if( fileName.lastIndexOf("\\") >= 0 ){ file = new File( filePath + fileName.substring( fileName.lastIndexOf("\\"))) ; }else{ file = new File( filePath + fileName.substring(fileName.lastIndexOf("\\")+1)) ; } fi.write( file ) ; out.println("Uploaded Filename: " + filePath + fileName + "<br>"); } } out.println("</body>"); out.println("</html>"); }catch(Exception ex) { System.out.println(ex); } }else{ out.println("<html>"); out.println("<head>"); out.println("<title>Servlet upload</title>"); out.println("</head>"); out.println("<body>"); out.println("<p>No file uploaded</p>"); out.println("</body>"); out.println("</html>"); } %>

이제 http://localhost:8080/UploadFile.htm 에 접속해서 테스트 해볼까요? 

 

제대로 작동한다면  c:\apache-tomcat-5.5.29\webapps\data\ 디렉토리에 파일이 업로드 되어있을 거에요~ 

 

 

 

Reference : http://www.tutorialspoint.com/jsp/jsp_file_uploading.htm 

 

 

💻 Programming/JSP

[JSP] Session ( 세션 )

이번에는 JSP로 세션을 다루는 법에 대해서 배워보도록 하겠습니다. HTTP는 "stateless" 프로토콜입니다.  무슨 말이냐하면 말이죠, 클아이언트(웹브라우저)가 웹페이지를 불러올때마다 클라이언트는 웹서버로 별도의 커넥션을 맺습니다. 그리고 이전 클라이언트의 접속에 대한 어떠한 정보도 자동으로 기록하지는 않습니다. 

어쨌든 세션이라는 것은 바로 웹브라우저가 웹서버와 연결이 될때 생기는 것인데, 이 세션을 유지하는 방법에는 여러가지가 있답니다.  

1. Cookies

쿠키에 세션ID를 저장하는 식으로 세션을 관리할 수는 있겠지만 브라우저에서 쿠키사용 제한 설정이 있을 수 있기때문에 세션을 쿠키를 이용해서 관리한다는 것은 좋은방법이 아닙니다.

 

 

2. Hidden Form Fields

 

웹서버는 hidden HTML form field에 unique session ID를 넣어서 아래처럼 전송할 수 있습니다.

<input type="hidden" name="sessionid" value="12345">

form이 전송될 때 세션ID와 값을 넘겨주는거죠. 브라우저에서 이 정보를 웹서버에 보내면 이 정보를 가지고 웹서버에서는 다른 브라우저에서 접속한 것인지를 판단할 수 있게 됩니다. 하지만 이 역시 좋은 방법은 아니죠. <a> 태그를 이용해서 링크를 타고 들어오는 경우에는 저 form데이타를 전송하지 않거든요.

3. URL Rewriting

URL 끝에 세션에 대한 정보를 추가할 수도 있습니다. 그리고 서버는 그 정보를 가지고 세션을 비교할 수 있겠죠.

예를들면, http://tutorialspoint.com/file.htm;sessionid=12345 이렇게 요청을 보내면 서버에서 sessionid=12345부분에 대한 정보를 가지고 웹서버의 세션정보와 비교를 하는거죠.

URL rewriting 은 세션을 관리하기위한 방법들 중에서는 그나마 좋은 방법이긴 합니다. 브라우저가 쿠키사용을 안할때도 사용가능한 방법이니까요. 하지만 역시 결점이 있습니다. 세션ID를 동적으로 매번 생성해줘야 하기 때문입니다. 정적인 HTML페이지라도 말이죠.  


The session Object:

위 세가지 방법 이외에도 JSP는 HttpSession 인터페이스를 사용할 수 있습니다. 기본적으로 JSPs는 세션을 추적하게 되어있으며 새로운 HttpSession 객체가 새로운 클라이언트들이 접속할 때마다 자동으로 생성됩니다. 세션 추적 기능을 끄려면 page directive의 세션 속성을 false로 세팅해줘야 합니다. 아래 처럼 말이죠.

<%@ page session="false" %>

JSP engine은 JSP개발자들에게 HttpSession 객체를 통해서 session에 접근할 수 있도록 해줍니다. session 객체가 기본적으로 제공이 되기 때문에 개발자들은 궂이 세션객체를 생성하거나 getSession() 메소드를 이용해서 얻어올 필요가 없습니다.

웹애플리케이션을 작성하고 있다면 그냥 세션을 파라미터로 받아서 쓰면 되는 겁니다. 

 

다음은 세션 객체가 가지고 메소드 목록입니다. 어떤 메소드들이 있는지 한번 살펴볼까요~

 

S.N.Method & Description
1public Object getAttribute(String name)
This method returns the object bound with the specified name in this session, or null if no object is bound under the name.
2public Enumeration getAttributeNames()
This method returns an Enumeration of String objects containing the names of all the objects bound to this session.
3public long getCreationTime()
This method returns the time when this session was created, measured in milliseconds since midnight January 1, 1970 GMT.
4public String getId()
This method returns a string containing the unique identifier assigned to this session.
5public long getLastAccessedTime()
This method returns the last time the client sent a request associated with this session, as the number of milliseconds since midnight January 1, 1970 GMT.
6public int getMaxInactiveInterval()
This method returns the maximum time interval, in seconds, that the servlet container will keep this session open between client accesses.
7public void invalidate()
This method invalidates this session and unbinds any objects bound to it.
8public boolean isNew(
This method returns true if the client does not yet know about the session or if the client chooses not to join the session.
9public void removeAttribute(String name)
This method removes the object bound with the specified name from this session.
10public void setAttribute(String name, Object value) 
This method binds an object to this session, using the name specified.
11public void setMaxInactiveInterval(int interval)
This method specifies the time, in seconds, between client requests before the servlet container will invalidate this session.


Session Tracking Example:

다음 예제는 HttpSession 객체를 이용하여 세션의 생성시간과 마지막 접근시간 정보를 가져오는 방법에 대해서 설명해주고 있습니다.  

<%@ page import="java.io.*,java.util.*" %> <% // Get session creation time. Date createTime = new Date(session.getCreationTime()); // Get last access time of this web page. Date lastAccessTime = new Date(session.getLastAccessedTime()); String title = "Welcome Back to my website"; Integer visitCount = new Integer(0); String visitCountKey = new String("visitCount"); String userIDKey = new String("userID"); String userID = new String("ABCD"); // 처음 접속한 방문자라면 세션을 생성합니다. if (session.isNew()){ title = "Welcome to my website"; session.setAttribute(userIDKey, userID); session.setAttribute(visitCountKey, visitCount); } visitCount = (Integer)session.getAttribute(visitCountKey); visitCount = visitCount + 1; userID = (String)session.getAttribute(userIDKey); session.setAttribute(visitCountKey, visitCount); %> <html> <head> <title>Session Tracking</title> </head> <body> <center> <h1>Session Tracking</h1> </center> <table border="1" align="center"> <tr bgcolor="#949494"> <th>Session info</th> <th>Value</th> </tr> <tr> <td>id</td> <td><% out.print( session.getId()); %></td> </tr> <tr> <td>Creation Time</td> <td><% out.print(createTime); %></td> </tr> <tr> <td>Time of Last Access</td> <td><% out.print(lastAccessTime); %></td> </tr> <tr> <td>User ID</td> <td><% out.print(userID); %></td> </tr> <tr> <td>Number of visits</td> <td><% out.print(visitCount); %></td> </tr> </table> </body> </html>

 main.jsp​에 위 코드를 넣고 http://localhost:8080/main.jsp 를 호출해보세요. 서버 실행시키는 것 잊어먹지 마시구요~ ^___^ 

Welcome to my website

Session Infomation

Session infovalue
id0AE3EC93FF44E3C525B4351B77ABB2D5
Creation TimeTue Jun 08 17:26:40 GMT+04:00 2010
Time of Last AccessTue Jun 08 17:26:40 GMT+04:00 2010
User IDABCD
Number of visits0

 

 

위와같은 페이지가 나오나요??

 

다시한번 호출 해 볼까요??

 

Welcome Back to my website

Session Infomation

info typevalue
id0AE3EC93FF44E3C525B4351B77ABB2D5
Creation TimeTue Jun 08 17:26:40 GMT+04:00 2010
Time of Last AccessTue Jun 08 17:26:40 GMT+04:00 2010
User IDABCD
Number of visits1


위와 같은 결과가 나오나요? Welcome 메시지가 Welcome Back 메시지로 바뀌었네요. ^__^ 

 

 

이제 세션 데이타를 삭제하는 방법을 알아볼까요??​​

 

Deleting Session Data:

사용자의 세션 데이타로 해야되는 작업을 모두 완료하였다면 아래와 같은 작업을 마지막으로 해줄 수 있습니다.

  • 특정 속성 삭제 : removeAttribute(String name) 메소드를 이용해서 세션의 특정 속성값만 삭제할 수 있습니다. 

  • 세션 삭제 : invalidate() 메소드를 호출하여 세션 전체를 무효화 시킬 수 있습니다. 세션을 끊는다고 표현하죠. 

  • 세션 타임아웃 설정 : setMaxInactiveInterval(int interval) 메소드를 이용하여 세션별로 타임아웃을 설정할 수 있습니다.

  • 사용자 로그아웃 : servlets 2.4를 지원하는 서버라면 logout 을 호출하여 사용자를 로그아웃시키고 모든 세션을 무효화 시킬 수 있습니다.  

  • web.xml 설정 : Tomcat을 사용중이라면 web.xml 파일에서 아래처럼 타임아웃 시간을 설정할 수도 있습니다.

<session-config> <session-timeout>15</session-timeout> </session-config>

여기서 타임아웃 시간의 단위는 분 단위이며 톰캣의 기본 타임아웃인 30 분을 오버라이드하여 적용됩니다.

서블릿의 getMaxInactiveInterval( )메소드는 초단위로 타임아웃 시간을 가져옵니다. 따라서 web.xml 파일에 15 분으로 설정되어있다면  getMaxInactiveInterval( ) 메소드는 900 ( 15분 * 60초 )를 반환하게 됩니다 .

 

 

 

 

Reference : http://www.tutorialspoint.com/jsp/jsp_session_tracking.htm 

 

💻 Programming/JSP

[JSP] Cookies ( 쿠키 세팅, 읽기, 삭제하기)

Cookies 는 그냥 일반 text files 이죠. 아마 JSP를 공부하시는 분들이라면 이정도는 알고 계시겠죠? 

JSP로 HTTP cookies 를 다루는 법에 대해서 한번 알아볼텐데 그 전에 하나만 짚고 넘어갈까요?

사용자가 특정 사이트에 재접속 했다는 것을 웹사이트에서 어떻게 알까요?

3초만에 답이 안나온다면 아래를 읽어봅시다.

 

재접속하는 사용자를 판단하는 과정은 세 단계로 나뉩니다.

  • 서버쪽에서 쿠키를 브라우저로 보냅니다.  

  • Browser는 서버에서 보낸 쿠키를 로컬에 저장을 하겠죠.

  • 이제 사용자가 이 브라우저를 이용해서 특정사이트에 접속할 때 저장되어있는 쿠키의 정보가 서버쪽으로 전달되고 서버쪽에서는 이 정보를 이용해서 사용자를 판별할 수 있는 것이죠.  

쿠키는 다른 정보로도 사용될 수 있으니 쿠키를 다루는 법을 한번 알아보도록 하겠습니다. 여기서는 쿠키 세팅, 리셋, 읽기, 삭제하기에 대해서 알아보도록 하겠습니다.  


Cookie 해부하기

 쿠키는 보통 HTTP header 안에 세팅되어있습니다. ( JavaScript 는 직접 브라우저에 쿠키를 설정할 수 있다네요 ). 쿠키를 세팅하는 JSP 는 아래와 같은 헤더를 보낼거에요. 

HTTP/1.1 200 OK Date: Fri, 04 Feb 2000 21:03:38 GMT Server: Apache/1.3.9 (UNIX) PHP/4.0b3 Set-Cookie: name=xyz; expires=Friday, 04-Feb-07 22:03:38 GMT; path=/; domain=tutorialspoint.com Connection: close Content-Type: text/html

이미 request 객체시간에 한번 본적이 있던 내용이죠? 그런데 추가된게 하나 있네요. Set-Cookie header 입니다. 보아하니 이름, 만료일시, 경로, 그리고 도메인정보를 가지고 있네요.  

브라우저에서 쿠키를 저장하도록 설정이 되어있으면 브라우저는 이런 정보들을 만료일 전까지 저장하게 됩니다.만약 사용자가 쿠키에 설정된 경로로 접속을 하게되면 브라우저는 서버로 그 쿠키를 재전송합니다. 그 브라우저의 헤더는 다음과 같은 정보를 갖고 있을 겁니다. 

GET / HTTP/1.0 Connection: Keep-Alive User-Agent: Mozilla/4.6 (X11; I; Linux 2.2.6-15apmac ppc) Host: zink.demon.co.uk:1126 Accept: image/gif, */* Accept-Encoding: gzip Accept-Language: en Accept-Charset: iso-8859-1,*,utf-8 Cookie: name=xyz

이제 JSP script 는 request method중 하나인 request.getCookies() 를 통해서 쿠키에 접근할 수 있습니다. 

 

Servlet Cookies 메소드

아래 메소드들은 JSP에서 쿠키를 다룰때 사용될 수 있는 메소드목록 및 기능입니다.

 

S.N.Method & Description
1public void setDomain(String pattern)
This method sets the domain to which cookie applies, for example tutorialspoint.com.
2public String getDomain()
This method gets the domain to which cookie applies, for example tutorialspoint.com.
3public void setMaxAge(int expiry)
This method sets how much time (in seconds) should elapse before the cookie expires. If you don't set this, the cookie will last only for the current session.
4public int getMaxAge()
This method returns the maximum age of the cookie, specified in seconds, By default, -1 indicating the cookie will persist until browser shutdown.
5public String getName()
This method returns the name of the cookie. The name cannot be changed after creation.
6public void setValue(String newValue)
This method sets the value associated with the cookie.
7public String getValue()
This method gets the value associated with the cookie.
8public void setPath(String uri)
This method sets the path to which this cookie applies. If you don't specify a path, the cookie is returned for all URLs in the same directory as the current page as well as all subdirectories.
9public String getPath()
This method gets the path to which this cookie applies.
10public void setSecure(boolean flag)
This method sets the boolean value indicating whether the cookie should only be sent over encrypted (i.e. SSL) connections.
11public void setComment(String purpose)
This method specifies a comment that describes a cookie's purpose. The comment is useful if the browser presents the cookie to the user.
12public String getComment()
This method returns the comment describing the purpose of this cookie, or null if the cookie has no comment.


 JSP로 쿠키 설정하기

JSP로 쿠키를 설정하려면 아래와 같은 단계를 거칩니다.

 

(1) Cookie 객체 생성 : You call the Cookie constructor with a cookie name and a cookie value, both of which are strings.

Cookie cookie = new Cookie("key","value");

자바에서 쿠키 생성하는거랑 똑같습니다. 그런데 여기서 name과 value ( "key"가 name인거고 "value"가 value가 되겠죠)에는 절대로 스페이스(빈칸)이나 아래에 나열된 특수문자가 사용될 수 없습니다.  

[ ] ( ) = , " / ? @ : ;

(2) Max age 설정 : 초 단위로 max age를 설정합니다. 이 쿠키가 살아있을 수 있는 시간을 설정하는거죠. 아래는 24 시간동안 존재할 수 있는 쿠키를 설정하는 예제입니다.

cookie.setMaxAge(60*60*24);

(3) Cookie를 HTTP response header에 추가하기 : response.addCookie 메소드를 이용하면 추가하 수 있습니다.  

response.addCookie(cookie);

예제

<% // Create cookies for first and last names. Cookie firstName = new Cookie("first_name", request.getParameter("first_name")); Cookie lastName = new Cookie("last_name", request.getParameter("last_name")); // Set expiry date after 24 Hrs for both the cookies. firstName.setMaxAge(60*60*24); lastName.setMaxAge(60*60*24); // Add both the cookies in the response header. response.addCookie( firstName ); response.addCookie( lastName ); %> <html> <head> <title>Setting Cookies</title> </head> <body> <center> <h1>Setting Cookies</h1> </center> <ul> <li><p><b>First Name:</b> <%= request.getParameter("first_name")%> </p></li> <li><p><b>Last Name:</b> <%= request.getParameter("last_name")%> </p></li> </ul> </body> </html>

 main.jsp 파일에 위 코드를 넣어주세요. 그리고 다음 코드는 hello.jsp파일에 넣어주세요. 

<html> <body> <form action="main.jsp" method="GET"> First Name: <input type="text" name="first_name"> <br /> Last Name: <input type="text" name="last_name" /> <input type="submit" value="Submit" /> </form> </body> </html>

두 jsp파일을 <Tomcat-installation-directory>/webapps/ROOT 디렉토리에 넣어주세요.

이제 http://localhost:8080/hello.jsp 에 접속을 해보세요.

 

 

 

이런게 나오나요? 이제 이름을 넣고 submit버튼을 눌러보세요. 

그럼 예전에 봤던 것처럼 퍼스트 네임과 래스트 네임이 출력이 될겁니다. 그런데 여기서 이녀석이 몰래하는 작업이 또 있습니다. 눈에는 보이지 않았지만 first_name과 last_name이라는 쿠키를 생성한것입니다. 그리고 submit버튼이 또 눌리게 될 경우 방금 만들어진 쿠키들이 서버쪽으로 전송되게 되겠죠. 

자, 그럼 이제 서버쪽으로 전송되는 쿠키정보를 JSP에서 읽어오는 것을 한번 해보겠습니다. 


JSP를 이용하여 쿠키정보 읽어오기

쿠키를 읽으려면 HttpServletRequest 의 getCookies( ) 메소드를 호출하기만 하면 됩니다. 이 메소드는 Cookie[]를 반환합니다. 한번에 여러개의 쿠키가 전송될 수 있다는 것이죠. 그럼 루프를 돌면서 전송된 쿠키의 정보를 출력하는 예제를 한번 보도록 하겠습니다.  


예제

<html> <head> <title>Reading Cookies</title> </head> <body> <center> <h1>Reading Cookies</h1> </center> <% Cookie cookie = null; Cookie[] cookies = null; // Get an array of Cookies associated with this domain cookies = request.getCookies(); if( cookies != null ){ out.println("<h2> Found Cookies Name and Value</h2>"); for (int i = 0; i < cookies.length; i++){ cookie = cookies[i]; out.print("Name : " + cookie.getName( ) + ", "); out.print("Value: " + cookie.getValue( )+" <br/>"); } }else{ out.println("<h2>No cookies founds</h2>"); } %> </body> </html>

위 코드를 main.jsp 파일에 넣고 접속해보세요. 쿠키에 설정한 값들이 나오겠죠? 아래처럼 말이죠.


Found Cookies Name and Value

Name : first_name, Value: 홍길동은
Name : last_name, Value: 플레이보이


JSP를 이용한 쿠키 삭제

이번에는 쿠키를 삭제해보도록 하겠습니다. 뭐 쿠키삭제는 브라우저에서도 할 수 있는 기능이긴 하지만 그래도 한번 읽어나 보세요. 웹개발자라면 쿠키 다루는 법은 잘 알고 있어야 할 테니까요. 

  • 쿠키를 읽어와서 쿠키객체에 저장합니다.

  • 쿠키의 나이를 0으로 만들어버리세요. setMaxAge() 메소드를 사용하면 되는건 아시죠?

  • 이 쿠키를 다시 response에 넣어 되돌려보내세요.


예제

아래 예제는 "first_name" 쿠키를 삭제하는 main.jsp 소스입니다. 삭제된 후에 이 쿠키를 다시 읽어오려고하면 null이 나올겁니다.

<html> <head> <title>Reading Cookies</title> </head> <body> <center> <h1>Reading Cookies</h1> </center> <% Cookie cookie = null; Cookie[] cookies = null; // Get an array of Cookies associated with this domain cookies = request.getCookies(); if( cookies != null ){ out.println("<h2> Found Cookies Name and Value</h2>"); for (int i = 0; i < cookies.length; i++){ cookie = cookies[i]; if((cookie.getName( )).compareTo("first_name") == 0 ){ cookie.setMaxAge(0); response.addCookie(cookie); out.print("Deleted cookie: " + cookie.getName( ) + "<br/>"); } out.print("Name : " + cookie.getName( ) + ", "); out.print("Value: " + cookie.getValue( )+" <br/>"); } }else{ out.println( "<h2>No cookies founds</h2>"); } %> </body> </html>

이제 main.jsp를 요청해보세요. http://localhost:8080/main.jsp 주소로 요청하면 되겠죠? 그럼 아래처럼 결과가 나올 거에요.


Cookies Name and Value

Deleted cookie : first_name
Name : first_name, Value: John
Name : last_name, Value: Player

 

 http://localhost:8080/main.jsp 를 다시한번 요청하면 아래와 같은 결과를 보게 될 거에요.

 

Found Cookies Name and Value

Name : last_name, Value: Player

 

first_name 쿠키는 삭제되어서 안나오네요.

 

어때요? 쉽죠잉?  

 




 

 

Reference : http://www.tutorialspoint.com/jsp/jsp_cookies_handling.htm