REST의 개념

 

  REST란

 

    REST의 정의

 

      Representational State Tramsfer"의 약자.

        자원을 이름(자원의표현)으로 구분하여 해당 자원의 상태(정보)를 주고받는 모든 것을 의미한다.

 

        즉, 자원(resource)의 표현(representation)에 의한 상태 전달.

 

           자원(resource)의 표현(representation)

              자원 : 해당 소프트웨어가 관리하는 모든 것

               ->Ex) 문서, 그림, 데이터, 해당 소프트웨어 자체 등

              자원의 표현 : 그 자원을 표현하기 위한 이름

               ->Ex) DB의 학생 정보가 자원일때, 'students'를 자원의 표현으로 정한다.

 

           상태(정보)전달

              데이터가 요청되어지는 시점에서 자원의 상태(정보)를 전달한다.

              JSON 혹은 XML을 통해 데이터를 주고받는 것이 일반적이다.

 

        월드와이드웹(www)과 같은 분산 하이퍼미디어 시스템을 위한 소프트웨어 개발 아키텍쳐의 한 형식.

           REST는 기본적으로 웹의 기존 기술과 HTTP 프로토콜을 그대로 활용하기 때문에 웹의 장점을 최대한

           활용할 수 있는 아키텍처 스타일이다.

           REST는 네트워크 상에서 Client와 Server 사이의 통신 방식 중 하나이다.

 

     REST의 구체적인 개념

 

       HTTP URI(Uniform Resouce Identifier)를 통해 자원(Resource)을 명시하고,

       HTTP Method(POST, GET, PUT, DELETE)를 통해 해당 자원에 대한 CRUD Operation을 적용하는것을 의미한다.

         즉, REST는 자원 기반의 구조(ROA, Resource Oriented Architecture) 설계의 중심에 Resource가 있고

         HTTP Method를 통해 Resource를 처리하도록 설계된 아키텍쳐를 의미한다.

         웹 사이트의 이미지, 텍스트, DB내용 등의 모든 자원에 고유한 ID인 HTTP URI를 부여한다.

 

         CRUD Operation

            Create : 생성(POST)

            Read : 조회(GET)

            Update : 수정(PUT)

            Delete : 삭제(DELETE)

            HEAD : header 정보 조회(HEAD)

 

  REST의 장단점

 

    장점

      HTTP 프로토콜의 인프라를 그대로 사용하므로 REST API 사용을 위한 별도의 인프라를 구출 할 필요가 없다.

      HTTP 프로토콜의 표준을 최대한 활용하여 여러 추가적인 장점을 함께 가져갈 수 있게 해준다.

      HTTP 표준 프로토콜에 따르는 모든 플랫폼에서 사용이 가능하다.

      Hypermedia API의 기본을 충실히 지키면서 범용성을 보장한다.

      REST API 메시지가 의도하는 바를 명확하게 나타내므로 의도하는 바를 쉽게 파악할 수 있다.

      여러가지 서비스 디자인에서 생길 수 있는 문제를 최소화한다.

      서버와 클라이언트의 역할을 명확하게 분리한다.

 

    단점

      표준이 존재하지 않는다.

      사용할 수 있는 메소드가 4가지 밖에 없다.

        HTTP Method 형태가 제한적이다.

      브라우저를 통해 테스트 할 일이 많은 서비스라면 쉽게 고칠 수 있는 URL보다 Header 값이 왠지 더 어렵게

      느껴진다.

      구형 브라우저가 아직 제대로 지원해주지 못하는 부분이 존재한다.

        PUT, DELETE를 사용하지 못하는 점

        pushState를 지원하지 않는 점

 

  REST가 필요한 이유

    애플리케이션 분리 및 통합

    다양한 클라이언트의 등장

    최근의 서버 프로그램은 다양한 브라우저와 안드로이드폰, 아이폰과 같은 모바일 디바이스에서도 통신을 할 수

    있어야 한다,

    이러한 멀티 플랫폼에 대한 지원을 위해 서비스 자원에 대한 아키텍처를 세우고 이용하는 방법을 모색한 결과,

    REST에 관심을 가지게 되었다.

 

  REST 구성요소

    1. 자원(Resource) : URI

        모든 자원에 고유한 ID가 존재하고, 이 자원은 Server에 존재한다.

        자원을 구별하는 ID는 '/groups/:group_id'와 같은 HTTP URI다.

        Client는 URI를 이용해서 자원을 지정하고 해당 자원의 상태(정보)에 대한 조작을 Server에 요청한다.

 

    2. 행위(Verb) : HTTP Method

        HTTP 프로토콜의 Method를 사용한다.

        HTTP 프로토콜은 GET, POST, PUT, DELETE와 같은 메소드를 제공한다.

 

    3. 표현(Representation of Resource)

        Client가 자원의 상태(정보)에 대한 조작을 요청하면 Server는 이에 적절한 응답(Representation)을 보낸다.

        REST에서 하나의 자원은 JSON, XML, TEXT, RSS 등 여러 형태의 Representation으로 나타내어 질 수 있다.

        JSON 혹은 XML을 통해 데이터를 주고 받는 것이 일반적이다.

 

  REST 특징

    1. Server-Client(서버-클라이언트 구조)

       자원이 있는 쪽이 Server, 자원을 요청하는 쪽이 Client가 된다.

          REST Server : API를 제공하고 비즈니스 로직 처리 및 저장을 책임진다.

          Client : 사용자 인증이나 context(세션, 로그인 정보)등을 직접 관리하고 책임진다.

       서로 간 의존성이 줄어든다.

 

    2. Stateless(무상태)

        HTTP프로토콜은 Stateless Protocol이므로 REST 역시 무상태성을 갖는다.

        Client의 context를 Server에 저장하지 않는다.

           즉, 세션과 쿠키와 같은 context정보를 신경쓰지 않아도 되므로 구현이 단순해진다.

        Server는 각각의 요청을 완전히 별개의 것으로 인식하고 처리한다.

           각 API 서버는 Client의 요청만을 단순 처리한다.

           즉, 이전 요청이 다음 요청의 처리에 연관되어서는 안된다.

           물론 이전 요청이 DB를 수정하여 DB에 의해 바뀌는 것은 허용한다.

           Server의 처리방식에 일관성을 부여하고 부담이 줄어들며, 서비스의 자유도가 높아진다.

 

    3. Cacheable(캐시 처리 기능)

        웹 표준 HTTP프로토콜을 그대로 사용하므로 웹에서 사용하는 기존의 인프라를 그대로 활용 할 수 있다.

          즉, HTTP가 가진 가장 강력한 특징 중 하나인 캐싱 기능을 적용할 수 있다.

          HTTP 프로토콜 표준에서 사용하는 Last-Modified 태그나 E-Tag를 이용하면 캐싱 구현이 가능하다.

        대량의 요청을 효율적으로 처리하기 위해 캐시가 요구된다.

        캐시 사용을 통해 응답시간이 빨라지고 REST Server 트랜잭션이 발생하지 않기 때문에 전체 응답시간, 성능,

        서버의 자원 이용률을 향상시킬 수 있다.

 

    4. Layered System(계층화)

        Client는 REST API Server 만 호출한다.

        REST Server는 다중 계층으로 구성될 수 있다.

          API Server는 순수 비즈니스 로직을 수행하고 그 앞단에 보안, 로드밸런싱, 암호화, 사용자인증등을 추가하여

          구조상의 유연성을 줄 수 있다.

          또한, 로드밸런싱, 공유 캐시 등을 통해 확장성과 보안성을 향상시킬 수 있다.

        PROXY, 게이트웨이 같은 네트워크 기반의 중간 매체를 사용할 수 있다.

 

    5. Code-On-Demand(optional)

        Server로부터 스크립트를 받아서 Client에서 실행한다.

        반드시 충족할 필요는 없다.

 

    6. Uniform Interface(인터페이스 일관성)

        URI로 지정한 Resource에 대한 조작을 통일되고 한정적인 인터페이스로 수행한다.

        HTTP표준 프로토콜에 따른느 모든 플랫폼에서 사용이 가능하다.

          특정 언어나 기술에 종속되지 않는다.

'JAVA' 카테고리의 다른 글

객체지향프로그래밍(Object Oriented Programming, OOP)  (0) 2021.01.25
REST API의 개념  (0) 2020.05.19
배열(Array)  (1) 2020.05.08
this, this(), super, super()  (1) 2020.05.08
접근제어자  (0) 2020.05.08

제어문이란 프로그램의 흐름을 제어할 수 있도록 도와주는 문장이다.

조건을 만족하는지의 여부에 따라 코드를 제어할 수 있는 조건문과 변수에 일치하는 경의 값에 따라 코드를 제어할

수 있는 선택문 그리고 특정 코드를 여러번 반복해서 실행할 수 있도록 하는 반복문이 있다.

 

조건문

  조건식의 값이 true인지 false인지에 따라 자바스크립트 코드를 제어한다.

  조건문의 종류에는 if문 else문 그리고 else if문이 있다.

 

if문

  if문은 조건식을 만족할 경우에만 코드를 실행한다.

  boolean과 마찬가지로 어떤 데이터를 입력해도 true 또는 false를 반환한다.

  기본형은 자바와 같다. 

기본형
if(조건식)	{
    자바스크립트 코드;
}
var num=10;
if(num<500){ //true를 반환한다.
	document.write("hello");
}

  위 예제에서 num<500 의 비교결과는 10<500이므로 true를 반환한다.

  조건문 내에 적어 놓은 hello는 현재 조건이 만족하기 때문에 출력된다.

if(0){ //false를 반환한다.
    document.write("hello");
}

  위 예제의 조건식에 있는 0은 boolean()메소드에 0을 입력했을 때와 결과가 같다.

  그 결과 false를 반환하여 조건문 내의 코드를 실행하지 않는다.

 

  다음 에제는 방문자로부터 입력받은 걸음 수를 조건문으로 만들고, 걸음 수가 10,000보 이상일 경우에만 결과를

  출력한다.

<script>
    var walkAmount = prompt("당신의 하루 걷는 양은 몇 보인가요?", "0");
    
    if(walkAmount >= 10000){
        document.write("매우 좋은 습관을 지니고 계시는군요!!","<br>");
    }
    document.write("==========The End==========");
</script>

  10,000보 이상일 경우에는 조건식에 true를 반환하여 { }안의 코드를 실행하지만 10,000보 미만일 경우에는

  ========The End=========를 출력한다.

 

조건식에 논리형 데이터가 아닌 다른 형이 오는 경우

  조건식에 논리형데이터(ture,false)가 아닌 다른 형의 데이터가 입력되어도 true 또는 false로 인식된다.

  

  다음 예제에서 방문자가 질의응답 창에 이름을 입력하지 않으면 기본 응답값인 빈문자("")가 변수에 저장되어

  조건식에 false값이 반환되고 그 결과 문장이 출력되지 않는다.

<script>
    var userName = prompt("방문자의 이름은?","");
    
    if(userName){  //userName에 이름이 저장되면 중괄호 내의 코드가 실행.
        document.write(userName+"님 반갑습니다! 방문을 환영합니다.");
    }
</script>

 

else문

  조건식을 만족할 경우와 만족하지 않을 경우에 따라 실행되는 코드가 달라진다.

  즉, 두가지 결과가 나올 수 있다.

 

  다음은 조건식의 만족 여부에 따라 실행되는 코드가 달라지는 else문의 기본형이다.

if(조건식){
    자바스크립트코드1;
}else{
    자바스크립트코드2;
}

 

<script>
    var num = prompt("당신이 좋아하는 숫자는?","0");
    
    if(num % 2 == 0){ //짝수일 경우에 실행
        document.write("당신이 좋아하는 숫자는 짝수입니다.");
    }else{
        document.write("당신이 좋아하는 숫자는 홀수입니다.");
    }
</script>

 

  다음은 confirm객체를 사용하여 웹페이지에 회원 탈퇴 여부를 묻는 확인/취소 창이 나타나게 하고,

  else 조건문으로 사용자가 확인 버튼을 눌렀을 때와 취소 버튼을 눌렀을 때 결과 화면이 다르게 나타나도록 할 것이다.

 

  확인/취소 창은 confirm() 메소드를 사용한다.

  확인 버튼은 true, 취소 버튼은 false를 반환한다.

기본형

confirm("message");

 

  다음은 confirm() 메소드를 사용해 회원 탈퇴 여부를 묻는 창을 만드는 예제이다.

<script>
    var result = confirm("정말로 회원을 탈퇴하시겠습니까?");
    
    if(result){
        document.write("탈퇴처리 되었습니다.");
    }else{
        document.write("탈퇴 취소 되었습니다.");
    }    
</script>

else if문

  else if문은 두가지 이상의 조건식과 정해놓은 조건을 만족하지 않았을 때 실행되는 코드로 이루어져 있다.

  

  다음은 else if문의 기본형이다.

if(조건식1){
    코드1;
}else if(조건식2){
    코드2;
}else if(조건식3){
    코드3;
}else if(조건식4){
    코드4;
}else if(조건식5){
    코드5;
}else{
    코드 6;
}

  가장 위에 있는 조건식 1부터 5까지 차례로 조건 검사를 하면서 만족하는 값이 나오면 그에 해당하는 코드를 실행하고

  조건문을 종료한다.

  조건식 중 만족하는 값이 하나도 없으면 else문의 중괄호 { }에 있는 코드를 실행한다.

 

  다음 예제는 질의응답 창을 이용하여 "현재는 몇월입니까"를 묻고 else if문을 사용해 현재 월에 해당하는 계절과

  관련된 문구가 출력되도록 했다.

<script>
    var mon = prompt("현재는 몇월입니까?","0");
    
    if(mon >= 9 && mon <= 11){	//9-11
        document.write("독서의 계절 가을이네요!!");
    }else if(mon >= 6 && mon <= 8{	//6-8
        document.write("여행가기 좋은 여름이네요!!");
    }else if(mon >= 3 && mon <= 5{	//3-5
        document.write("햇살 가득한 봄이네요!!");
    }else{
        document.write("스키의 계절 겨울이네요!!");
    }
</script>

중첩 if문

  조건문 안에 조건문이 있는 것을 중첩 if문이라 한다.

기본형

if(조건식1){
  if(조건식2){
    자바스크립트코드;
  }
}

  중첩 if문은 바깥쪽에 있는 조건문인 조건식 1을 만족해야만 안쪽에 있는 조건문인 조건식 2를 검사한다.

  만일 안쪽 if문의 조건식 2를 만족하지 않으면 바깥쪽 조건문인 조건식1의 중괄호 안에 있는 코드만 실행하고

  종료한다.

  

  다음은 중첩 if문을 사용해 아이디와 비밀번호가 일치했을 때 환영문구가 출력되도록 작성한 예제이다.

<script>
  var id="easy1004"; //아이디
  var pw="112233";   //비밀번호

  var user_id=prompt("아이디는?", "0"); //아이디입력
  var user_pw=prompt("비밀번호는?", "0"); //비밀번호 입력

  if(id == user_id){  //아이디가 일치하면 실행한다.
    if(pw == user_pw){
      document.write(user_id+"님 반갑습니다."); //비밀번호가 일치하면 실행한다.
    }else{
      alert("비밀번호가 일치하지 않습니다."); //비밀번호가 일치하지 않으면 실행한다.
      loaction.reload();  //브라우저 새로고침
    }
  }else{
    alert("아이디가 일치하지 않습니다");  //아이디가 일치하지 않으면 실행한다.
    location.reload();
  }
</script>

반복문

  while문

    while문은 조건식을 만족할 때까지 코드를 여러 회 반복하여 실행할 수 있다.

    다음은 while문의 기본형이다.

var 변수=초기값;

while(조건식){
    자바스크립트코드;
    증감식;
}

    while문의 실행 순서는 조건식을 검사하고 만족하면 중괄호 안에 있는 코드를 실행한다.

    그리고 다시 조건식을 검사한다.

 

    다음은 while문을 사용해 "안녕하세요1 ~ 안녕하세요10"까지 1씩 증가하면서 10회 출력하도록 작성한 예제이다.

<script>
      var i = 1;
      while(i<=10){
        document.write("안녕하세요"+i, "<br>");
        i++;
      }
      document.write("======The End======");
</script>

    다음은 while문을 사용하여 1부터 30까지의 숫자 중 2의 배수이면서 6의 배수인 숫자만 출력하는 예제이다.

<script>
      var i = 1;
      while(i<=30){
        if(i % 2 == 0 && i % 6 == 0){

        document.write(i, "<br>");
        }
        i++;
      }
</script>

    다음은 20부터 10까지의 숫자 중 짝수일 경우에는 파란색으로 출력되고, 홀수일 경우에는 빨간색으로 출력되도록

    작성한 예제이다.

<script>
      var i = 20;
      while(i>=10){
        if(i % 2 == 0){
        document.write("<p class='blue'>"+i+"</p>");
        }else{
        document.write("<p class='red'>"+i+"</p>");
        }
        i++;
      }
</script>

  do while문

    do while문은 반드시 한번은 코드를 실행하고 조건식을 검사한다.

    다음은 do while문의 기본형이다. 중괄호에 있는 코드를 먼저 실행하고 조건식을 검사한다.

var 변수 = 초기값;

do{
    자바스크립트코드;
    증감식;
}while(조건식)

    다음은 do while문의 예제이다.

<script>
      var i = 10;

      do{
        document.write("hello!");
      }while(i<3)
</script>

   

    do에 있는 hello를 먼저 출력하고 조건식을 검사한다. 조건식은 false이기 때문에 do while문이 종료된다.

 

for 문

  for문은 조건식을 만족할 때까지 특정 코드를 반복하여 실행한다. while문과 사용방법은 같지만 while문보다 

  사용하기 편해 사용 빈도가 높은 편이다.

  다음은 for문의 기본형이다.

for(초기값; 조건식; 증감식){
    자바스크립트코드;
}

  다음은 for문으로 '반복1~반복 10'까지 i를 1씩 증가하며 출력한 예제이다.

<script>
      for(var i = 1; i <= 10; i++){
        document.write("반복"+i, "<br>");
      }
</script>

  다음은 1부터 100까지 5의 배수일 경우에는 빨간색글자, 7의 배수일 경우에는 초록색 글자 그리고 5의 배수이며

  7의 배수일 경우에는 아쿠아색 글자로 출력하는 예제이다.

<script>
      for(var i = 1; i <= 100; i++){
        if(i % 5 == 0 && i % 7 != 0){
          document.write("<p class='red'>"+i+"</P>");
        }else if(i % 7 == 0 && i % 5 != 0){
          document.write("<p class='green'>"+i+"</p>");
        }else if(i % 7 == 0 && i % 5 == 0){
          document.write("<p class='aqua'>"+i+"</P>");
        }
      }
</script>

break 문

  반복문에서 break문을 실행하면 조건식과 상관없이 강제로 반복문을 종료한다.

  즉, break문은 반복문을 강제로 종료할 때 사용한다.

 

  다음은 break문의 기본형이다.

  break문이 코드보다 앞에있으므로 코드는 실행되지 않고 반복문이 바로 종료된다.

for(초기값; 조건식; 증감식){
    break; <!--반복문을 강제로 종료한다.-->
    자바스크립트코드;
}

var 변수 = 초기값;
while(조건식){
    break;
    자바스크립트코드;
    증감식;
}

  다음은 1부터 10까지 반복하도록 작성한 예제이다. 그리고 break문을 사용하여 i의 값이 6일경우 강제로 종료한다.

    <script>
      for(var i = 1; i <= 10; i++){
        if(i == 6) break;
        document.write(i, "<br>");
      }
      document.write("=====The End=====");
    </script>

continue문

  continue문은 반복문에서만 사용할 수 있다. while문에 사용할 경우 continue문 다음에 오는 코드는 무시하고

  바로 조건식으로 이동해 조건 검사를 한다. 즉, while문 안에 있는 continue문은 "다음에 오는 코드는 무시하고

  조건식에서 조건 검사를 실행"하라고 하는 것이다.

 

  for 문에서 continue문을 실행할 경우에는 continue문 다음에 오는 코드는 무시하고 바로 증감식으로 이동하여

  증감연산을 실행한다. 즉, for 문 안에 있는 continue문은 "다음에 오는 코드는 무시하고 증감식을 바로 실행"

  하라는 것이다.

 

  continue문의 기본형은 다음과 같다.

for(초기값; 조건식; 증감식){
    continue;
    자바스크립트 코드;
}

var 변수 = 초기값;
while(조건식){
    증감식;
    continue;
    자바스크립트 코드;
}

  다음은 for문을 이용해 1부터 10까지 i가 2의 배수일 경우에만 continue 문을 실행하여 홀수만 출력하는 예제이다.

<script>
      for(var i = 1; i <= 10; i++){
        if(i % 2 ==0)continue;
        document.write(i, "<br>");
      }
      document.write("====The End====");
</script>

중첩 for문

  for문 안에 for문을 사용한 것을 중첩 for문이라고 한다. 중첩 for문은 예를 들어 자바스크립트를 이용해 3행 5열의

  표를 만든다고 할 때 1행씩 행이 만들어질 때 마다 5개의 열을 만들어야 할 경우에 사용한다.

  중첩 for문의 기본형은 다음과 같다.

for(초기값; 조건식; 증감식){
    for(초기값; 조건식; 증감식){
        자바스크립트 코드;
    }
}

  다음은 중첩 for문을 사용하여 1행 1열부터 3행 2열까지 출력하는 예제이다.

<script>
      for(var i = 1; i<=3; i++){
        for(var k=1; k<=2; k++){
          document.write(i+"행"+k+"열", "<br>");
        }
        document.write("<br>");
      }
</script>

 

(참고 : do it 자바스크립트+제이쿼리 입문)

'Java Script' 카테고리의 다른 글

객체(내장객체)  (1) 2020.05.19
연산자  (0) 2020.05.17
변수  (0) 2020.05.16
자바 스크립트 기초문법  (1) 2020.05.16
자바스크립트 간단한 실행문 예제  (1) 2020.05.16

연산자란?

  자바스크립트에서 사용하는 연산자에는 산술, 문자 결합, 대입(복합 대입), 증감, 비교, 논리, 삼항 조건 연산자가 있다.

 

산술 연산자

  산술 연산자에는 더하기(+), 빼기(-), 곱하기 (*), 나누기(/), 나머지(%)가 있다.

  산술 연산자로 연산을 하기 위해서는 연산 대상 데이터가 반드시 2개 이상 있어야 한다.

  

  다음 예제는 산술 연산자를 사용하는 예제이다.

<script>
    var num1=15;
    var num2=2;
    var result;
    result = num1 + num2;
    document.write(result, "<br>");	//17
    result = num1 - num2;
    document.write(result, "<br>");	//13
    result = num1 * num2;
    document.write(result, "<br>");	//30
    result = num1 / num2;
    document.write(result, "<br>");	//7.5
    result = num1 % num2;
    document.write(result, "<br>");	//1
</script>

문자 결합 연산자

  문자 결합 연산자는 피연산자(연산 대상 데이터)가 문자형 데이터이다.

  여러개의 문자를 하나의 문자형 데이터로 결합할 때 사용한다.

 

  다음과 같이 더하기에 피연산자로 문자형 데이터가 한 개라도 포함되어 있으면 다른 피연산자의 데이터는 자동으로

  문자형 데이터로 형 변환되고 문자 결합이 이루어져 하나의 문자형 데이터를 반환한다.

문자형 데이터 + 문자형 데이터 = 하나의 문자형 데이터
ex)"do it" + "javascript" = "do it javascript";

문자형 데이터 + 숫자형 데이터 = 하나의 문자형 데이터
ex) "100" + 200 = "100200";

  다음은 t1, t2, t3, t4라는 변수에 문자와 숫자 데이터를 각각 넣고 하나의 문자 데이터로 결합하는 예제이다.

<script>
    var t1="학교종이";
    var t2="땡땡땡";
    var t3=8282;
    var t4="어서 모이자";
    var result;
    
    result=t1+t2+t3+t4;
    document.write(result);	//학교종이 땡땡땡 8282 어서 모이자
</script>

대입 연산자

  대입 연산자(=)는 연산된 데이터를 변수에 저장할 때 사용한다.

  복합 대입 연산자(+=, -=, *=, /=, %=)는 산술 연산자와 대입연산자가 복합적으로 적용된것을 말한다.

  다음은 대입연산자 예제이다.

<script>
    var num1=10;
    var num2=3;
    
    num1+=num2;	//num1 = num1(10)+num2(3);
    document.write(num1, "<br>");	//13
    
    num1-=num2;	//num1 = num1(10)-num2(3);
    document.write(num1, "<br>");	//10
    
    num1*=num2;	//num1 = num1(10)*num2(3);
    document.write(num1, "<br>");	//30
    
    num1%=num2;	//num1 = num1(10)%num2(3);
    document.write(num1, "<br>");	//0
</script>

  다음은 여러개의 문자형 데이터로 저장된 HTML 태그를 복합 대입 연산자를 이용하여 하나의 문자로 결합한 다음

  document.write(str);을 이용하여 화면에 출력하는 예제이다.

<script>
    var srt="<table border='1'>";
    str +="<tr>";
    str +="<td>1</td><td>2</td><td>3</td>";
    str +="</tr>";
    str +="</table>";
    
    <!--여러개의 문자형 데이터가 하나의 문자로 결합되어 str에 저장.
         즉, 한개의 문자형 데이터로 결합.-->
    
    document.write(str);
    
    <!--str을 출력하면 문자가 아닌 태그로 인식되어 표가 출력.-->
</script>

  결과화면

  문자형 데이터로 저장된 태그를 복합 대입 연산자를 사용해서 하나의 데이터로 결합 하였기 때문에

  표가 만들어 진다.

 

증감연산자

  증감 연산자에는 숫자형 데이터를 1씩 증가시키는 증가 연산자(++)와 반대로 1씩 감소시키는 감소연산자(--)가 있다.

  증감 연산자는 앞에서 배운 연산자와는 달리 피연산자가 한 개만 필요한 단항 연산자이다.

  증감 연산자는 어느위치에 오는가에 따라 결과값이 달라진다.

변수의 값을 1만큼 감소시킨다.
변수--; 또는 --변수;

변수의 값을 1만큼 증가시킨다.
변수++; 또는 ++변수;
var A=++B;
<!-- 먼저 B의 값을 1만큼 증가시키고 증가된 B의 값을 A에 대입한다.-->

var A=B++;
<!-- B의 값을 A에 먼저 대입한 뒤 B의 값을 1만큼 증가시킨다-->

  다음은 증감연산자를 사용해 증감 처리 하고 문서에 출력하는 예제이다.

<script>
    var num1=10;
    var num2=20;
    var result;
    
    num1--;			//9
    document.write(num1, "<br>");
    
    num1++;			//10
    document.write(num1, "<br>");
    
    result = num2++;		//result: 20, num2:21
    document.write(result, "<br>");
    
    result = ++num2;		//result:22, num2:22
    document.write(result, "<br>");
</script>

비교연산자

  두 데이터를 '크다, 작다, 같다'와 같이 비교할 때 사용하는 연산자이다.

  연산된 결과값은 true, false로 논리형 데이터를 반환한다.

  

  다음은 비교연산자의 종류이다.

  비교 연산자 ==와 !+는 피연산자의 자료형(type)이 비교 연산자의 실행 결과에 영향을 미치지 않는다.

  다음 예제의 경우 변수 k에는 숫자형 데이터 10이 저장되었고, 변수 m에는 문자형 데이터 "10"이

  저장되었다.

  그리고 두 변수 모두 숫자형 데이터 10과 같은지 비교하였고 결과는 둘 다 true를 반환한다.

var k=10, m="10";
k==10	//true
m==10	//true

  비교연산자 중 ===와 !==는 피연산자 자료형에 따라 결과값이 달라진다.

  다음 예제의 경우 변수 k에는 숫자형 데이터 10이 저장되었고, k===10은 숫자형 데이터로 둘다 일치하기 때문에 

  true를 반환한다.

  하지만 m에는 문자형 데이터 "10"이 저장되었다. 문자형데이터 "10"과 숫자형데이터 10은 자료형이 다르므로

  m===10은 false를 반환한다.

var k=10, m="10";
k===10	//true
m===10	//false
<script>
    var a=10;
    var b=20;
    var c=10;
    var f="20";
    var result;
    
    result=a>b;		//false
    document.write(result, "<br>");	<!-- a(10)>b(20)은 false가 반환된다.-->
    result=a<b;		//true
    document.write(result, "<br>");
    result=a<=b;	//true
    document.write(result, "<br>");
    result=b==f;	//true
    document.write(result, "<br>");	<!-- b(20)==f("20"은 자료형과 상관없이 숫자만 비교하여 true가 반환된다.-->
    result=a!=b;	//true
    document.write(result, "<br>");	<!-- a(10)!=b(20)은 데이터가 다르므로 true가 반환된다-->
    result=b===f;	//false
    document.write(result, "<br>");	<!-- b(20==f("20")은 숫자는 같지만 자료형이 다르므로 false가 반환된다.-->
</script>

 

논리연산자

  논리 연산자에는 ||(or), &&(and), !(not)이 있다.

  논리 연산자는 피연산자가 논리형 데이터인 true 또는 false로 결과값을 반환한다.

 

연산자 우선순위

  1. ()

  2. 단항 연산자(--, ++, !)

  3. 산술 연산자(*, /, %, +, -)

  4. 비교 연산자(>, >=, <, <=, ==, ===, !==, !=)

  5. 논리 연산자(&&, ||)

  6. 대입(복합대입)연산자(=, +=, -=, &=, /=, %=)

 

  다음은 비교연산자와 논리연산자를 적용한 예제이다.

  코드 한줄에 비교연산자와 논리연산자가 함께 포함되어 있다면 연산자 우선순위에 따라 비교연산이 먼저 실행되고,

  그 다음 논리연산자가 실행된다.

<script>
    var a=10;
    var b=20;
    var m=30;
    var n=40;
    
    var result;
    result = a>b || b>=m || m>n;		//false||false||false
    document.write(result, "<br>");		//false
    
    result = a>b || b>=m || m<=n;		//false||false||true
    document.write(result, "<br>");		//true
    
    
    result = a<=b && b>=m && m<=n;		//true&&false&&true
    document.write(result, "<br>");		//false
    
    
    result = a<=b || b<=m && m<=n;		//true&&true&&true
    document.write(result, "<br>");		//true
    
    
    result = !(a>b);				//!false를 계산
    document.write(result, "<br>");		//true
</script>

  연산자는 피연산자 중 true가 한개라도 포함되어 있으면 true를 반환한다.

  &&연산자는 피연산자 중 false가 한개라도 포함되어 있으면 false를 반환한다.

  !연산자는 피연산자가 false면 true를 반환한다.

 

삼항 조건 연산자

  삼항 조건 연산자는 조건식(true또는 false의 결과값을 반환)의 결과에 따라 실행 결과가 달라지는 삼항연산자로,

  연산을 위해 피연산자가 3개 필요하다.

 

  삼항 조건 연산자는 연산한 결과 조건식의 만족 여부에 따라 실행하는 코드를 다르게 실행하고자 할 때

  사용한다. 예를 들어 방문자로부터 입력받은 나이값이 20세 이상이면 '성인'이라 출력하고,

  미만이면 '미성년자'라고 출력하도록 할 때 사용할 수 있다.

조건식 ? 자바스크립트 코드 1 : 자바스크립트 코드 2;
<script>
    var a=10;
    var b=3;
    
    var result=a>b ? "javascript" : "hello";
    <!-- a(10)>b(3)은 true 이므로 "javascript"가 result에 저장된다.-->
    document.write(result);	//javascript
</script>

 

예제

  적정 체중을 구하는 테스트기.

    적정 체중 계산법 : 적정체중 = (본인신장 - 100) x 0.9

  

  결과 폼

신장: 180(cm)
체중: 74(kg)
적정 체중: (180-100) x 0.9 = 72(kg)
결과: 적정 체중은 72kg이며, 현재 적정 체중에서 2kg 초과한 것을 알 수 있습니다.

  신장과 체중은 추후 바뀔 수도 있으므로 변수에 저장한다. 신장이 바뀌면 적정 체중도 바뀔것이므로,

      적정체중도 변수에 저장한다.

<script>
    var userHeight=180;	//신장
    var userweight=74;	//체중
    
    //평균체중 = (신장 - 100) x 0.9
    var nomal_w=(userHeight - 100) * 0.9; //결과값을 nomal_w에 저장
    document.write(nomal_w);
</script>

  코드 작성하기

    코드내에서 변수에 직접 대입하는 것이 아닌 사용자가 직접 입력해서 사용할 수 있도록 코드를 작성.

    사용자가 입력 할 수 있는 창을 만들때는 prompt() 메소드를 사용한다.

    prompt() 메소드의 기본형은 prompt("질문","기본응답"); 이며, 사용자로부터 입력된 값은 문자형 데이터로 반환한다.

<script>
    var name=prompt("당신의 이름은?","");		//이름입력
    var height=prompt("당신의 신장은?","");		//신장입력
    var weight=prompt("당신의 몸무게는?","");		//체중입력
    
    var nomal_w=(height - 100)*0.9;		//평균체중
    var result=weight>=nomal_w - 5 && weight <= nomal_w + 5;	//오차범위 +-5
    result = result ? "적정 체중입니다." : "적정 체중이 아닙니다";
    document.write(name+"님은"+result);
</script>

(참고 : do it 자바스크립트+제이쿼리 입문)

'Java Script' 카테고리의 다른 글

객체(내장객체)  (1) 2020.05.19
제어문  (0) 2020.05.19
변수  (0) 2020.05.16
자바 스크립트 기초문법  (1) 2020.05.16
자바스크립트 간단한 실행문 예제  (1) 2020.05.16

자바스크립트에서의 변수 선언

  변수를 선언할 때는 var 키워드를 변수명 앞에 붙인다.

  변수명에는 한글을 사용할 수 없으며, 영문과 숫자 그리고 일부 특수문자(_  $)만 포함 될 수 있다.

  단어와 단어의 조합으로 짓는 변수명은 두번째 단어의 첫 글자를 대문자로 표기하는데

  이것을 낙타(Camel)표기법이라고 한다. (ex.mathNum)

기본형
    var 변수명;
    var 변수명=값;

  변수를 선언하면 변수명으로 데이터를 저장할 수 있는 공간이 생긴다.

  다음 예제처럼 대입하면 변수에 100이 저장된다.

var box;
box=100;

변수에 저장할 수 있는 자료형

  변수에 저장할 수 있는 자료형(Data Type)으로는 문자형(String), 숫자형(Number), 논리형(Boolean) 그리고

  빈 데이터(Undefined)가 있다.

  

  문자형

    문자형(String)데이터는 문자나 숫자를 "" 또는 ''로 감싸고 있다.

    또한 HTML 태그를 포함하여 출력하면 태그로 인식한다.

var 변수="사용할 문자나 숫자";

var s="javascripot";
var num=100;
var tag="<h1>String</h1>";

  숫자형

    숫자형(number)데이터는 단어 의미 그대로 숫자를 의미한다.

    만약 "100"과 같이 ""가 숫자를 감싸고 있다면 숫자형이 아닌 문자형이다.

    이 경우에는 Number("100")을 이용하면 문자형 데이터를 숫자형 데이터로 바꿀 수 있다.

var 변수=숫자; 또는 Number("문자형 숫자");

var s=100;
var t=Number("500"); //"500"-> 500

  논리형

    논리형(boolean)데이터는 true(참) 또는 false(거짓)가 있다.

    기본형은 다음과 같다.

var 변수=true or false; 또는 Boolean(데이터);

var s=true;
var t=10)=100;		//false
var k=Boolean("hello");	//true

    Boolean() 메소드에 데이터를 입력하면 논리형 데이터인 true 또는 false를 반환한다.

    Boolean() 메소드는 숫자 0과 null, undefined, 빈 문자(" ")를 제외한 모든 데이터에 대해 true를 반환한다.

 

    다음 예제와 같이 Boolean()메소드에 숫자 0을 입력하면 false라는 값을 반환한다. 그리고 Boolean()메소드에

    "홍길동"을 입력하면 true를 반환한다.

var m=Boolean(0)	//false
var k=Boolean("홍길동")	//true

    다음 예제는 논리형 값, 비교 연산자, Boolean 메소드를 사용해 변수에 논리형 데이터를 저장한 후 문서에 

    출력하는 예제이다.

<script>
    var a=true;
    var b=false;
    var c=10>5;			//true
    var d=Boolean(null);	//false
    
    document.write(a, "<br>");
    document.write(b, "<br>");
    document.write(c, "<br>");
    document.write(d, "<br>");
</script>

    결과값은 다음과 같다.

true
false
true
false

  null & undefined 데이터

    undefined는 다음과 같이 변수 s에 값이 등록되기 전의 기본값이고, null은 변수에 저장된 값이 null인 경우를 

    가리킨다. null은 변수에 저장된 데이터를 비우고자 할 때 사용한다.

var s;	//undefined
var t=hello;
t=null;

  typeof

    typeof는 지정한 데이터 또는 변수에 저장된 자료형을 알고 싶을 때 사용한다.

typeof 변수 또는 데이터;

    다음은 typeof를 이용하여 변수에 저장된 자료형을 알아내는 예제이다.

<script>
    var num=100;
    var str="자바스크립트";
    
    document.write(typeof num, "<br>");	//number
    document.write(typeof str);		//string
</script>

    결과값은 다음과 같다.

number
string

변수 선언 시 주의사항

  1. 변수명 첫 글자로는 &, _(언더바), 영문자만 올 수 있다.

var 1num=10;	(X)
var $num=10;	(O)

  2. 변수명 첫 글자 다음은 영문자, 숫자, &, _ 만 포함할 수 있다.

var 100num=10;	(X)
var num100=10;	(O)

  3. 변수명으로는 예약어(document, location, window 등)를 사용할 수 없다.

      예약어란 이미 자바스크립트에서 사용중인 단어를 말한다.

var document=10;	(X)
var num=10;		(O)

  4. 변수명을 지을때는 되도록 의미를 부여해 작성하는 것이 좋다.

var num="hello";	(X)
var num=10;		(O)

  5. 변수명을 사용할 때는 대,소문자를 구분해야 한다.

var num=10;	document.write(Num)	(X)
var num=10;	document.write(num)	(O)

 

(참고 : do it 자바스크립트+제이쿼리 입문)

'Java Script' 카테고리의 다른 글

객체(내장객체)  (1) 2020.05.19
제어문  (0) 2020.05.19
연산자  (0) 2020.05.17
자바 스크립트 기초문법  (1) 2020.05.16
자바스크립트 간단한 실행문 예제  (1) 2020.05.16

여기서는 자바와 다른 부분만 체크해서 작성할 것이다.

 

자바스크립트 선언문

  선언문은 자바스크립트 코드를 작성할 영역을 선언하는 것이다.

  <script>라는 태그로 선언문이 시작된 곳 부터 </script>라는 종료 태그를 작성한 곳까지를 스크립트 영역이라고 한다.

<script>
    <!-- 자바스크립트 코드 영역 -->
</script>

  선언문은 <head> 태그 영역 또는 <body> 태그 영역에 선언하면 된다.

  우리나라에서 대부분은 <head>태그 영역에 선언하고 있다고 한다.

  

  다음은 선언문 작성 예제.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script>
        document.write("환영합니다");
    </script>
</head>
<body>
</body>
</html>

  doucument는 문서 객체이며 문서 출력 메소드인 write()를 이용하여 데이터를 문서에 출력할 때 사용한다.

 

자바스크립트 주석처리

  스크립트 선언문 안에서 주석처리를 하고 싶을 때, 한줄 주석일 경우에는 '//'로 작성하고,

  여러줄 주석일 경우에는 '/*  */'로 작성하면 된다.

  HTML  소스의 설명글은 <!-- -->로 작성한다.

 

내부스크립트 외부로 분리하기

  위 예제에서 HTML 내부에 작성된 스크립트는 마지막에는 외부로 분리하는 작업을 해야한다.

  그렇게 하면 소스 찾기도 쉽고 누군가가 소스를 손상시킬 염려도 없다.

  즉, 분리의 주된 목적은 프로젝트 관리를 원활하게 하기 위함이다.

 

  다음은 외부 자바스크립트 연동 코드로 파일을 연결하는 기본형이다.

<script src="JS 파일 경로"></script>

  내부 스크립트를 외부로 분리하려면 따로 파일을 만들어서 저장해야 한다.

  즉, HTML 파일과 JS 파일을 분리하여 HTML 내에서 JS 파일을 연동하면 된다.

 

내부 스크립트 분리하기

 

  먼저 js 파일을 만든다.

document.write("환영합니다");

  html파일을 열어 위에 작성한 js파일을 연동한다.

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8">
    <title>외부 자바스크립트 연동</title>
    <script src="js/example.js"></script>
  </head>
  <body>
    
  </body>
</html>

  'src="파일 경로" '로 해당 경로의 내부 스크립트를 분리가 되었다.

  이렇게 분리하면 소스를 분석할 때 찾기 쉬울 뿐 아니라 다른 개발자가 잘못하여 소스를 손상시킬 일도 없다.

 

코드 입력 시 주의사항

 1. 자바스크립트는 대,소문자를 구분하여 작성한다.

날짜 객체 생성 : New date(); (X)
날짜 객체 생성 : new Date(); (O)

  2. 코드 한 줄을 작성한 후에는 세미콜론(;)을 쓰는 것이 좋다. 세미콜론을 쓰지 않으면 다음 예제처럼 한 줄에

     2개의 코드를 작성할 경우 오류가 발생한다.

document.write("hi") document.write("bye")   (X)
document.write("hi"); document.write("bye"); (O)

  3. 위 예제처럼 작성해도 오류가 발생하거나 하진 않지만 가독성을 위해 한 줄에 한 문장만 작성하는 것이 좋다.

 

  4. 문자형 데이터를 작성할 때는 큰 따옴표("")와 작은따옴표('')의 겹침 오류를 주의해야 한다.

큰 따옴표 겹침 오류
document.write("책에 "자바스크립트는 대소문자를 구분해야 합니다"라고 나와있다.");

잘된 예
document.write('책에 "자바스크립트는 대소문자를 구분해야합니다"라고 나와있다.');
document.write("책에\"자바스크립트는 대소문자를 구분해야합니다\"라고 나와있다.");

  5. 코드를 작성할 때 중괄호{} 또는 소괄호()의 짝이 맞아야 한다.

document.write("welcome!";  (X)
document.write("welcome!"); (O)

 

(참고 : do it 자바스크립트+제이쿼리 입문)

'Java Script' 카테고리의 다른 글

객체(내장객체)  (1) 2020.05.19
제어문  (0) 2020.05.19
연산자  (0) 2020.05.17
변수  (0) 2020.05.16
자바스크립트 간단한 실행문 예제  (1) 2020.05.16
<!DOCYTPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>맛보기 예제<title>
</head>
<body>
	<script>
    	var age = prompt("당신의 나이는?", "0");
        if(age >= 20){
        	document.write("당신은 성인입니다");
        }else{
        	document.write("당신은 미성년자입니다.");
        }
    </script>
</body>
</html>

 

prompt로 age값을 설정하고 if문으로 조건에 맞는 write를 출력한다.

document.write는 자바에서 System.out.print와 같은 것이다.

 

(참고 : do it 자바스크립트+제이쿼리 입문)

'Java Script' 카테고리의 다른 글

객체(내장객체)  (1) 2020.05.19
제어문  (0) 2020.05.19
연산자  (0) 2020.05.17
변수  (0) 2020.05.16
자바 스크립트 기초문법  (1) 2020.05.16

DI(Dependency Injection  의존성주입)

  표준을 정의할 수 있고, 정의된 표준을 바탕으로 같은 설계를 하게 해준다.

  보통 엔터프라이즈 어플리케이션을 개발할 때는 하나의 처리를 수행하기 위해 여러개의 컴포넌트를 조합해서

  구현하는 경우가 일반적이다.

  이때 사용되는 컴포넌트에는 '공통으로 사용되는 기능을 따로 분리한 컴포넌트', '데이터베이스에 접근하기 위한

  컴포넌트', '외부 시스템이나 서비스에 접속하기 위한 컴포넌트' 등과 같이 다양한 컴포넌트가 있다.

  

  이처럼 하나의 처리를 구현하기 위해 여러개의 컴포넌트를 통합할 때 의존성 주입이라는 접근 방식이 큰 힘을

  발휘한다. 예를들어, 사용자를 등록하는 클래스를 구현한다고 가정하면, 사용자 등록을 위해 필요한 처리 흐름은

  다음과 같다.

    1. 등록하려는 사용자 계정이 이미 등록되어 있는지 확인한다.

    2. 등록하려는 사용자의 패스워드를 해시(Hash)한다.

    3. 사용자 정보를 저장한다.

  

  이 같은 처리를 구현하는데 필요한 인터페이스는 다음과 같다.

  

  사용자 등록을 처리하는 인터페이스

public interface UserService {
	//사용자 정보를 등록한다.
    void register(User user, String rawPassword);
}

 

  패스워드를 해시화하는 인터페이스

public interface PasswordEncoder {
	//패스워드를 해시화한다.
    String encode(CharSequence rawPassword);
}

 

  사용자 정보를 관리하는 인터페이스

public interface UserRepository {
	//사용자 정보를 저장한다.
    User save(User user);
    //사용자 계정명이 일치하는 사용자 수를 카운트한다.
    int countByUsername(String username);
}

 

  사용자 등록을 처리하는 구현 클래스

public class UserServiceImpl implements UserService {
	private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;
    
    public UserServiceImpl(javax.sql.DataSource dataSource) {
    	//데이터베이스 방식으로 사용자 정보를 관리하는 구현 클래스
        this.userRepository = new JdbcUserRepository(dataSource);
        
        //Bcrypt 알고리즘으로 해시화하는 구현 클래스
        this.passwordEncoder = new BCryptPasswordEncoder();
    }
    
    public void register(User user, String rawPassword) {
    	if(this.userRepository.countByUsername(user.getUsername()) > 0) {
        	//같은 사용자 계정의 사용자가 있다면 예외를 발생시킨다.
            throw new UserAlreadyRegisteredException();
        }
    
    //입력된 원본 패스워드를 해시화 한 후, 사용자 정보로 설정한다.
    user.setPassword(this.passwordEncoder.encode(rawPassword));
    this.userRepository.save(user);
    }
}

 

  위 예제에서는 생성자에서 userRepository와 passwordEncoder를 초기호 ㅏ하기 위해 UserRepository 와

  PasswordEncoder의 구현 클래스를 직접 생성해서 할당한다.

  그래서 UserServiceImpl클래스를 개발하는 단계에서는 의존하는 컴포넌트 클래스가 이미 완성되어 있어야 한다.

  

  이처럼 필요한 컴포넌트를 생성자에서 직접 생성하는 방식은 일단 클래스가 생성되고 나면 이미 생성된

  UserRepository나 PasswordEncoder의 구현 클래스를 교체하는것이 사실상 어려울 수 있다.

  이러한 클래스 간의 관계를 두고 '클래스 간의 결합도가 높다'라고 말한다.

 

  엔터프라이즈 애플리케이션을 개발할 때는 다양한 컴포넌트를 조합하는 것이 일반적이라고 했는데,

  많은 컴포넌트에 의존해야 하는 클래스를 이 같은 방식으로 개발하는것은 상당히 비효율적이다.

  예를들어 의존하는 클래스가 아직 개발중이거나, 미들웨어 벤더가 제공해줘야 하는 클래스가 있는데

  그 벤더의 제품이 완성되지 않았을 수도 있다.

  결국 모든 컴포넌트가 제대로 모양새를 갖추려면 개발의 막바지에 이르러서야 오류없이 조립할 수 있다.

  해결 대안으로는 필요한 컴포넌트가 완성 될 때 까지 임시로 dummy 클래스를 만들어서 대체하는 방법이 있다.

  다만, 언젠가는 제대로 구현해서 교체해야 할 코드이기 때문에 개발규모가 커지면 커질수록 재 작업의 양이 늘어난다.

 

  UserServiceImpl 클래스의 결합도를 낮추려면 우선 생성자 안에서 UserRepository와 passwordEncoder의

  구현 클래스를 직접 생성하는 대신, 생성자의 인수로 받아서 할당하는 방법을 생각해볼 수 있다.

 

  생성자를 활용한 의존 컴포넌트 초기화

public UserServiceImpl(UserRepository userRepository,
						PassworkdEncoder passwordEncoder) {
		
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
}

 

  이렇게 하면 UserServiceImpl의 소스코드 안에서 UserRepository와 passwordEncoder의 구현 클래스 정보가 제거되어

  UserServiceImpl의 외부에서 UserRepository와 passwordEncoder의 구현체를 쉽게 변경할 수 있게 된다.

 

  애플리케이션에서 UserService를 사용

UserRepository userRepository = new JdbcUserRepository(dataSource);
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
UserService userService = new UserServiceImpl(userRepository, passwordEncoder);
//생략

  먄약 JdbcUserRepository와 BCryptPasswordEncoder가 아직 완성되지 않았다면 앞서 생성자 안에서 구현 클래스를

  직접 생성하던 방식과 달리 UserServiceImpl을 변경하지 않고 JdbUserRepository와 BCryptEncoder의 더미클래스를

  임시로 만들어서 대체하면 개발을 중단없이 계속 할 수 있다.

 

  미완성된 클래스를 더미로 대체

UserRepository userRepository = new DummyUserRepository();
passwordEncoder passwordEncoder = new DummyPasswordEncoder();
UserService userService = new UserServiceImpl (userRepository, passwordEncoder);
//생략

  하지만 이 경우에도 UserServiceImpl이 의존하는 각 컴포넌트는 개발자가 직접 생성해서 주입해야 하기 때문에

  변경이 발생하는 경우의 재작업은 불가피하다.

  

  어떤 클래스가 필요로 하는 컴포넌트를 외부에서 생성한 후, 내부에서 사용 가능하게 만들어 주는 것을

  '의존성 주입(DI)한다', 또는 '인젝션(Injection)'한다' 라고 말한다.

  그리고 이러한 의존성 주입을 자동으로 처리하는 기반을 'DI 컨테이너'라고 한다.

 

DI 컨테이너

  스프링 프레임워크가 제공하는 기능 중 가장 중요한 것이 DI컨테이너 기능이다.

  스프링 프레임워크의 DI컨테이너에 UserService, UserRepository, PasswordEncoder의 인터페이스와

  구현 클래스를 알려주고 의존관계를 정의해주면 UserServiceImpl이 생성될 때 UserRepository와

  PasswordEncoder의 구현 클래스가 자동으로 생성되어 주입된다.

  UserService를 사용하고 싶은 애플리케이션은 DI 컨테이너에서 UserService를 꺼내오기만 하면 되고,

  이 때 UserRepository와 PasswordEncoder는 UserService에 이미 조합 된 상태이다.

 

  DI 컨테이너에서 UserService 꺼내기

ApplicationContext context = ...; //스프링 DI컨테이너
UserService userService = context.getean(UserService.class);
//생략

 

  이렇게 DI 컨테이너를 통해 각 컴포넌트의 인스턴스를 생성하고 통합 관리하면서 얻을 수 있는 장점은

  컴포넌트간의 의존성 해결 뿐만이 아니다.

  어떤 컴포넌트는 반드시 단 하나의 인스턴스만 만들어서 재사용 되도록 싱글턴(singleton)객체로 만들어야 하고

  어떤 컴포넌트는 매번 필요할 때마다 새로운 인스턴스를 사용하도록 프로토타입(prototype)객체로 만들어야 한다.

  이러한 인스턴스의 스코프(scope)관리를 DI컨테이너가 대신한다.

  각 인스턴스가 필요로 하는 공통 처리 코드를 외부에서 자동으로 끼워넣는 AOP기능도 DI컨테이너가 대신 해준다.

 

DI 개요

  의존성 주입이라고도 하며 IoC라고 하는 소프트웨어 디자인 패턴 중 하나다.

 

  DI 컨테이너에서 인스턴스를 관리하는 방식에는 다음과 같은 장점이 있다.

    1. 인스턴스의 스코프를 제어할 수 있다.

    2. 인스턴스의 생명 주기를 제어할 수 있다.

    3. AOP 방식으로 공통 기능을 집어넣을 수 있다.

    4. 의존하는 컴포넌트 간의 결합도를 낮춰서 단위 테스트 하기 쉽게 만든다.

  스프링의 공식 문서에서는 DI가 아닌 IoC컨테이너라고 기재하고 있다.

 

ApplicationContext와 빈 정의

  스프링 프레임워크에서는 ApplicationContext가 DI 컨테이너의 역할을 한다.

  

  DI컨테이너에서 인스턴스 꺼내기

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
//설정클래스(Configuration class)를 인수로 전달하고 DI컨테이너를 생성한다.
//설정클래스는 여러개 정의 할 수도 있다.

UserService userService = context.getBean(UserService.class);
//DI컨테이너에서 UserService 인스턴스를 가져온다.

  여기서 AppConfig 클래스는 DI컨테이너에서 설정파일 역할을 하며, 자바로 작성돼 있어서

  자바 컨피규레이션클래스(Java Configuration Class)라고도 한다.

  그리고 이렇게 자바 컨피규레이션 클래스로 설정하는 방식을 자바 기반 설정방식이라고 하며, 다음과 같은 형태로

  작성한다.

 

  자바기반 설정 방식의 예

@Configuration
public class AppConfig {
	@Bean
	UserRepository userRepository() {
		return new UserRepositoryImpl();
	}
	
	@Bean
	PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
	
	@Bean
	UserService userService() {
		return new UserServiceImpl(userRepository(), passwordEncoder());
	}
}

 

  그리고 이 설정을 사용하는 애플리케이션과 ApplicationContext의 관계는 다음과 같다.

  @Configuration 과 @Bean 어노테이션을 사용해서 DI컨테이너에 컴포넌트를 등록하면 애플리케이션은

  DI 컨테이너에서 있는 빈(Bean)을 ApplicationContext 인스턴를 통해 가져올 수 있다.

  스프링 프레임워크에서는 DI 컨테이너에 등록하는 컴포넌트를 빈이라고 하고, 이 빈에 대한 설정(Configuration)

  정보를 '빈 정의(Bean Definition)'라고 한다.

  또한 DI컨테이너에서 빈을 찾아오는 행위를 룩업(lookup)이라고 한다.

 

  DI 컨테이너에서 빈 가져오기

UserService userService = context.getBean(UserService.class);
//가져오려는 빈의 타입(Type)을 지정하는 방법이다.
//지정한 타입에 해당하는 빈이 DI 컨테이너에 오직 하나만 있을 때 사용한다.
//스프링프레임워크 3.0 부터 사용할 수 있다.

UserService userService = context.getBean("userService", UserService.class);
//가져오려는 빈의 이름과 타입을 지정하는 방법.
//지정한 타입에 해당하는 빈이 DI컨테이너에 여러개 있을 때 이름으로 구분하기 위해 사용.
//2.5.6버전까지는 반환값이 Object 타입이라서 원하는 빈의 타입으로 형변환 해야 했지만
//3.0.0버전 이후부터는 형변환 하지 않아도 된다.

UserService userService = (UserService) context.getBean("userService");
//가져오려는 빈의 이름을 지정하는 방법이다.
//반환값이 Object타입이라서 원하는 빈의 타입으로 형변환 해야 한다.
//1.0.0버전부터 사용할 수 있다.

 

  빈 설정 방법

  자바 기반 설정 방식이나 XML 기반 설정 방식만 사용해서 빈을 정의할 수도 있지만 대부분의 경우 자바 기반

  설정 방식과 어노테이션 기반 설정 방식을 조합하거나 XML 기반 설정 방식과 어노테이션 기반 설정 방식의

  조합을 많이 사용한다.

 

  ApplicationContext를 생성하는 다양한 방법

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
//자바 기반의 설정방식으로 AnnotationConfigApplicationContext의 생성자에
//@Configuration 어노테이션이 붙은 클래스를 인수로 전달한다.

ApplicationContext context = new AnnotationConfigApplicationContext("com.example.app");
//어노테이션 개반 설정방식으로 AnnotationConfigApplicationContext의 생성자에
//패키지명을 인수로 전달한다.
//지정된 패키지 이하의 경로에서 컴포넌트를 스캔한다

ApplicationContext contet = 
            new ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml");
//XML 기반의 설정방식으로 ClassPathXmlApplicationContext의 생성자에 XML파일을 인수로 전달한다.
//경로에 접두어(Prefix)가 생략된 경우에는 클래스패스 안에서 상대경로로 설정파일을 탐색한다.

ApplicationContext context =
            new FileSystemXmlApplicationContext("./spring/applicationContext.xml");
//XML기반의 설정방식으로 FileSystemXmlApplicationContext의 생성자에 XML 파일을 인수로 전달한다.
//경로에 접두어가 생략된 경우에는 JVM의 작업 디렉토리 안에서 상대경로로 설정파일을 탐색한다.

  ApplicationContext는 단독 애플리케이션에서 스프링 프레임워크를 사용하거나 JUnit으로 만든 테스트 케이스 안에서

  스프링 프레임워크를 구동할 때 사용된다.

  웹 애플리케이션에서는 스프링 MVC를 활용하게 되는데, 이때는 웹 환경에 맞게 확장한 WebApplicationContext를

  사용한다.

 

빈 설정

 

배열

  배열은 여러 데이터를 순차적으로 관리하는 일종의 자료구조로, 프로그램 개발에 꼭 필요한

  기본 구성 요소이다.

  배열을 사용하면 인덱스 위치를 써서 배열에 있는 임의 원소를 사용할 수 있기 때문에 올바른 임의 접근이 가능하다.

  배열의 모든 원소는 그냥 변수이다.

  즉, 여덟개의 원시 변수 유형이나 레퍼런스 변수이다. 그런 유형의 변수에 집어넣을 수 있는 것은 모두 그 유형의

  배열 원소로 대입할 수 있다.

  따라서 int형 배열(int[])의 각 원소에는 int가 들어간다.

  그렇다고 Dog 배열(Dog[])의 각 원소에도 Dog가 들어가는것은 아니다.

  레퍼런스 변수에는 객체 자체가 아닌 레퍼런스가 들어간다.

  

  배열은 원시변수의 배열이든 객체 레퍼런스에 대한 배열이든 상관없이 항상 객체이다.

  물론, 원시값을 저장하도록 선언된 배열 객체를 만들 수 있다. 즉, 배열 객체의 원소가 원시 값이더라도

  배열 자체는 절대 원시 값이 아니다.

  배열에 어떤 것이 들어가든 배열자체는 언제나 객체라는점을 꼭 기억해야 한다.

 

배열의 개념

  보통 배열은 인덱스(순차번호)와 데이터로 구성된 일종의 자료구조를 말한다.

 

사용분야

  집합형의 데이터를 관리할 필요가 있을 때 사용.

 

int[] num = new int[4];
int num[] = new int[4];	//위 코드와 이 코드는 크기가 4인 배열을 선언하는 것이다.
int[] num = {10, 20, 40, 99} //배열 선언과 함께 초기값을 할당.
int[][] num = {{10, 20}, {30, 40}, {50, 60}};	//2차원 배열 선언과 함께 초기값 할당

int[][] table = new int[5][10];	//5행 10열의 배열.

배열의 특징

  1. 같은 자료형으로만 구성한다.

  2. 배열 안 데이터는 0부터 시작하는 인덱스를 참조한다.

  3. 배열을 선언할 때 크기를 지정해야 하며, 나중에 그 크기를 변경할 수 없다.

  4. 특정한 값으로 초기화하지 않은 배열 안 데이터를 참조하며 Null Pointer Exception이 발생한다.

  5. 배열의 인덱스는 1이 아닌 0부터 시작한다.

 

다차원배열

  일차원적인 배열 만으로는 한계가 있다.

  예로 학교를 생각해보면 각 반마다 학생이 여러명이 있고, 반 자체도 여러 반이 있는데

  이걸 일차원적인 배열로 표현을 하려면 각 반마다 일일히 배열을 선언해줘야 하는 상황이 발생한다.

  그래서 이것을 다차원배열로 설정해준다.

  위 예제 코드 중 제일 마지막 줄을 보면 [5][10]으로 되어있는데 5행 10열의 값이 나온다는 의미이다.

 

  이 2차 배열의 초기화는 다음과 같이 할 수 있다.

int[][] table = { {1,2,3,4,5,6,7,8,9,10},
                  {2,3,4,5,6,7,8,9,10,1},
                  {3,4,5,6,7,8,9,10,1,2},
                  {4,5,6,7,8,9,10,1,2,3},
                  {5,6,7,8,9,10,1,2,3,4} };

  이 배열에서 table.length를 호출하면 5가 나올 것이고 table[0].length를 호출하면 10이 반환된다.

  

  하나의 배열은 2,3 혹은 그 이상의 차원을 가질 수 있는데 2차원 이상을 갖는 배열을 다차원 배열이라고 한다.

  3차원 배열은 육면체로 그릴 수 있는데 그 이상의 배열은 그림으로 나타내기 어렵다.

  2차원 배열은 매우 일반적이지만 프로그램에서 다차원배열은 조심해서 사용해야 한다.

  여러 레벨에서 방대한 정보를 다루게되면 관리가 어려워지기 때문이다.

 

배열의 선언

  java에서 배열은 객체이다. 배열을 생성하기 위해서는 배열을 반드시 선언해야 한다.

  배열의 크기는 length를 사용하여 확인할 수 있다.

 

배열의 특징

  자바는 객체지향 언어이고 객체 타입의 참조변수를 지원하기 때문에 배열에서도 원시 자료형 외의 객체타입을

  사용할 수 있다.

 

예제

class Dog {
	String name;
	public static void main(String[] args) {
		//Dog 객체를 만들고 접근한다.
		Dog dog1 = new Dog();
		dog1.bark();
		dog1.name = "Bart";
		
		//이번에는 Dog 배열을 만든다.
		Dog[] myDogs = new Dog[3];
		//그리고 개를 몇마리 넣는다.
		myDogs[0] = new Dog();
		myDogs[1] = new Dog();
		myDogs[2] = dog1;
		
		//배열 레퍼러느를 써서 Dog 객체에 접근한다.
		myDogs[0].name = "Fred";
		myDogs[1].name = "Marge";
		
		//myDogs[2]의 이름은???
		System.out.print("마지막 개의 이름 : ");
		System.out.println(myDogs[2].name);
		
		//이제 순환문을 써서 배열에 들어있는 모든 개가 짖도록 한다.
		int x = 0;
		while(x < myDogs.length) {
			myDogs[x].bark();
			x = x + 1;
		}
	}
	
	public void bark() {
		System.out.println(name + "이(가) 왈! 하고 짖습니다.");
	}
	
	public void eat() {}
	public void chaseCat() {}
}

  출력결과

    null이(가) 왈! 하고 짖습니다.

    마지막 개의 이름 : Bart

    Fred이(가) 왈! 하고 짖습니다.

    Marge이(가) 왈! 하고 짖습니다.

    Bart이(가) 왈! 하고 짖습니다.

 

정리

  변수에는 원시변수와 레퍼런스. 이렇게 두 종류가 있다.

  변수를 선언할 때는 반드시 이름과 유형이 있어야 한다.

  원시 변수의 값은 그 값을 표시하는 비트로 구성된다.(5, 'a', true, 3.1416 등)

  레퍼런스 변수의 값은 힙에 들어있는 객체를 건드릴 수 있는 방법을 나타내는 비트이다.

  레퍼런스 변수는 리모컨과 같다. 레퍼런스 변수에 대해 점 연산자(.)를 사용하는 것은 리모컨의 버튼을 눌러서

     메소드나 인스턴스 변수에 접근하는 것과 비슷하다.

  레퍼런스 변수가 아무 객체도 참조하지 않으면 그 값은 null이 된다.

  배열은 항상 객체이다. 배열에 원시변수를 저장하도록 선언해도 마찬가지이다.

     원시배열같은것은 없다. 원시변수가 들어있는 배열이 있을 뿐이다.

 

'JAVA' 카테고리의 다른 글

REST API의 개념  (0) 2020.05.19
REST  (0) 2020.05.19
this, this(), super, super()  (1) 2020.05.08
접근제어자  (0) 2020.05.08
제어문, 반복문 예제  (1) 2020.04.30

+ Recent posts