1.  디렉티브 태그  Directive Tag

디렉티브 태그는 JSP 페이지를 어떻게 처리할 것인지를 설정하는 태그

 

JSP 페이지가 서블릿 프로그램에서 서블릿 클래스로 변환할 때 JSP 페이지와 관련된 정보를 JSP 컨테이너에 지시하는 메시지. 따라서 디렉티브 태그는 JSP 페이지를 수정하여 다시 컴파일하는 경우에만 역할을 수행하기 때문에 개별 HTML 응답에 특별한 영향을 미치지 않음

 

태그 형식 설명
page <%@ page ... %> JSP 페이지에 대한 정보를 설정
include <%@ include ... %> JSP 페이지의 특정 영역에 다른 문서를 포함
taglib <%@ taglib ... %> JSP 페이지에서 사용할 태그 라이브러리를 설정

 

 

1)  page 디렉티브 태그 

 

🚀  JSP 페이지가 생성할 콘텐츠 유형의 문서, 사용할 자바 클래스, 오류 페이지 설정, 세션 사용 여부, 출력 버퍼의 존재 유무 등과 같이 JSP 컨테이너가 JSP 페이지를 실행하는데 필요한 정보를 설정 

🚀  일반적으로 JSP 페이지의 최상단에 선언하는 것을 권장

🚀  <@ 사이에는 공백을 주지 말것 

 

page 디렉티브 태그의 속성
속성 설명 기본값
language  현재 JSP 페이지에서 사용할 프로그래밍 언어를 설정 java
contentType  현재JSP 페이지의 콘텐츠유형을 설정 text/html
pageEncoding  현재 JSP 페이지의 문자 인코딩 유형을 설정   ISO-8859-1
import 현재 JSP 페이지에서 사용할 자바 클래스를 설정  
session  현재 JSP 페이지의 HTTP 세션 사용 여부를 설정 true
buffer 현재 JSP 페이지의 출력 버퍼를 설정 8KB
autoFlush 자동으로 출력 버퍼를 비우는 것을 제어하는데 사용 true
isThreadSafe  현재 JSP 페이지에서 멀티스레드의 동작을 제어하는 데 사 true
info  현재 JSP 페이 지에 대한 설명 을 설정  
errorPage  현재 JSP 페이 지가 실행되는 동안 오류가 발 생하면 특정 오류 페이지로 이동하는 데 사용   
isErrorPage 현재 JSP 페이지가 오류 페이지인지 여부를 설정  
isELIgnored  현재 JSP 페이지의 표현 언어 Expression
Language 사용 여부를 설정
false
isScripting 스크립트 태그 (선언문, 스크립틀릿, 표현문) 사용 여부를 설정  

 

  📍  하나의 page 디렉티브 태그에 하나 또는 여러 개의 속성을 설정 또는 여러 개의 속성마다 개별적으로 page 디렉티브 태그를 선언할 수 있음. import 속성을 제외한 속성은 JSP 페이지에 한 번씩만 설정할 수 있음

 

 

A. language 속성 

<%@ page language="java" %> 

 

  👾  현재 JSP 페이지에서 사용할 프로그래밍 언어를 설정하는 데 사용, 생략 가능 


B. contentType 속성 

<%@ page contentType="text/html :charset=utf-8" %> 

 

  👾  현재 JSP 페이지의 콘텐츠 유형을 설정하는 데 사용 

  👾  text/html, text/xml, text/plain 등이 있고 기본 값은 text/html.

  👾  문자열 세트 charset 를 설정하여 JSP 페이지의 전체 문자열을 변경할 수 있음 

application/msword 로 설정
<%@ page contentType="application/msword" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%--
    page 디렉티브 태그에 콘텐츠 유형을 마이크로 소프트 워드 문서(application/msword)로 설정하기.
    1) 콘텐츠 유형을 application/msword로 설정하도록 page 디렉티브 태그의 contentType 속성을 작성.
    --%>
    Today is: <%=new java.util.Date()%>
</body>
</html>

 

text/xml 로 설정
<%@ page contentType="text/xml;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h2>contentType 디렉티브 태그</h2>
    <h4>text/html : HTML 출력</h4>
    <h4>charset=utf-8 : 문자 인코딩</h4>
</body>
</html>


C. pageEncoding 속성 

<%@ pageEncoding="ISO-8859-1" %>
<%@ page contentType="text/html :charset=ISO-8859-1" %> 

 

  👾  현재 JSP 페이지의 문자 인코딩 유형을 설정하는 데 사용

  👾  문자 인코딩 유형의 기본값은 ISO-8859-1


D. import 속성 

<%@ page import="java.io.*, java.lang.*" %> 
<%@ page import="java.io.*" %> 
<%@ page import="java.lang.*" %> 

 

  👾  현재 JSP 페이지에서 사용할 자바 클래스를 설정하는 데 사용.

  👾  둘 이상의 자바 클래스를 포함하는 경우 쉼표(,)로 구분하여 연속해서 여러 개의 자바 클래스를 설정할 수 있음


E. session 속성 

<%@ page session="true" %> 

 

  👾  현재 JSP 페이지의 HTTP 세션 사용 여부를 설정하는 데 사용. 기본 값은 true. 

  👾  session 속성 값이 true이면 현재 JSP 페이지에서 내장 객체인 session 변수를 사용할 수 있음.


F. buffer 속성 

<%@ page buffer="none" %> 
<%@ page buffer="32KB" %>

 

  👾  현재 JSP 페이지의 출력 버퍼를 설정하는 데 사용

  👾  이 속성 값은 none과 '버퍼 크기'로 설정할 수 있음

     ⚡️ 속성 값을 none으로 설정하면 출력 버퍼를 채우지 않고 웹 브라우저로 직접 보냄

     ⚡️ '버퍼 크기'로 속성 값을 설정하면 출력 버퍼에 먼저 기록을 한 후 웹 브라우저로 전송

 

출력버퍼를 사용하는 이유 

 

  1) 작은 데이터를 여러 번 전송하는 것 보다 한번 큰 데이터를 전송함

        ▶️  큰 단위를 한번에 전송하는 것이 전송성능에 있어서 더 효율적

  2) 응답결과가 바로 전송되지 않기 때문에 JSP실행 도중 출력버퍼를 지우고 새로운 내용을 보여줄 수 있다. 

        ▶️ JSP가 응답 결과를 생성하는 도중 에러가 발생했을 시 출력버퍼를 비우고 에퍼레이지를 출력할 수 있도록 할 수 있다. 

  3) 버퍼가 다 차기 전까지는 헤더를 변경할 수 있다

       ▶️ 출력버퍼가 flush 되거나 꽉차서 자동으로 출력되기 이전까지는 얼마든지 헤더를 변경할 수 있다


 

G. autoFlush 속성 

<%@ page autoFlush="true" %>

 

  👾  자동으로 출력 버퍼를 비우는 것을 제어하는데 사용. 기본값은 true. 

  👾  출력 버퍼가 채워진 경우 자동으로 버퍼에 있는 데이터를 웹 브라우저로 보내고 버퍼를 비울지 또는 버퍼 오버플로의 예외를 나타낼지 등의 처리를 설정

  👾  false로 설정하면 출력 버퍼가 가득 채워질 때 버퍼 오버플로의 예외를 발생. 


H. isThreadSafe 속성 

<%@ page isThreadSafe="true" %> 

 

  👾  현재 JSP 페이지에서 멀티스레드의 동작을 제어하는 데 사용. 기본 값은 true. 

  👾  여러 요청이 동시에 수신되는 경우 JSP 페이지가 어떻게 동작해야 하는지를 JSP 컨테이너에 지시하여 응답할 수 있게 함. 

  👾 속성 값이 true이면 JSP 페이지에 대해 수신된 여러 요청이 동시에 처리되고 

                       false로 설정하면 요청이 순차적으로 처리


I. info 속성 

<%@ page info="Home Page JSP" %> 

 

  👾  현재 JSP 페이지에 대한 설명을 설정하는 데 사용. 주석과 같은 기능. 

 


J. errorPage 속성 

<%@ page errorPage="MyErrorPage.jsp" %> 

 

  👾  현재 JSP 페이지가 실행되는 동안 오류가 발생하면 특정 오류 페이지로 이동하는 데 사용.

  👾  웹 서버가 제공하는 기본 오류 페이지를 사용하지 않고 이동할 오류 페이지의 URL을 설정.


K. isErrorPage 속성 

<%@ page isErrorPage="true" %> 

 

  👾  현재 JSP 페이지가 오류 페이지인지 여부를 설정하는 데 사용

  👾  기본 값은 false이고 예외 처리를 위한 내장 객체인 exception 변수를 사용할 수 없음.

  👾 속성 값을 true로 설정하면 현재 JSP 페이지는 오류 페이지가 됨

  👾  만약 다른 JSP 페이지에서 오류가 발생하면, 호출되는 오류 페이지는 true가 설정된 JSP 페이지가 됨. 

 


L. isELIgnored 속성 

<%@ page isELIgnored="true" %>

 

  👾  재 JSP 페이지의 표현 언어 Expression Language 사용 여부를 설정

  👾  기본 값은 false이며 JSP 페이지에 표현 언어의 표현식 '${}'을 사용할 수 있음

  👾  true로 설정하면 JSP 페이지에 사용된 표현 언어의 표현식을 처리할 수 없기 때문에 정적 텍스트로 처리

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="true"%>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    request.setAttribute("RequestAttribute", "request 내장 객체");
%>
${requestScope.RequestAttribute} <%-- 표현문처럼 특정값을 추출 --%>
<script>
    const str = '문자열';
    alert(`${str} 입니다.`);
</script>

</body>
</html>

true일 때

 

false 일 때


M. isScriptingEnabled 속성 

<%@ page isScriptingEnabled="false" %> 

 

  👾  스크립트 태그 (선언문, 스크립틀릿, 표현문) 사용 여부를 설정하는데 사용

  👾  속성 값이 true로 설정하면 기본 스크립트 태그를 사용할 수 있고,

        false로 설정하면 스크립트 태그를 제한하기 때문에 스크립트 태그를 사용하는 경우 번역시 오류가 발생

 

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]

 


1.  자바 백엔드의 발전

 

1)  서블릿 : 자바로 html 표현하는 것 (자바와 html 결합) 처음엔 자바코드에서 html을 출력

     📍 단점: html 작업이 힘들다

출처 :&nbsp;https://medium.com/javarevisited/servlet-things-every-java-developer-must-know-servlet-container-filter-and-listener-374a460169bd

 

2)  JSP : PHP의 영향으로 html 코드에 자바가 들어감. 서블릿과 반대

     📍 단점: 규모가 큰 프로젝트에서는 구조화된 작업이 힘들다. → 유지보수 어려움

출처 :&nbsp;https://mauryaravi021.medium.com/servlet-and-jsp-3a830470689b

 

3)  JSP + 서블릿을 이용한 MVC 패턴 : controller와 model은 servlet으로, view는 jsp로 작업

     📍 단점 : 구조화된 프로그래밍은 가능한데, 규모가 더 커지니 코드가 복잡하고 성능 저하

 

💡 자바 서블릿 (Java Servlet)은 자바를 사용하여 웹페이지를 동적으로 생성하는 서버측 프로그램 혹은 그 사양을 말하며, 흔히 "서블릿"이라 불린다. 자바 서블릿은 웹 서버의 성능을 향상하기 위해 사용되는 자바 클래스의 일종이다. 서블릿은 JSP와 비슷한 점이 있지만, JSP가 HTML 문서 안에 Java 코드를 포함하고 있는 반면, 서블릿은 자바 코드 안에 HTML을 포함하고 있다는 차이점이 있다.

 

https://23log.tistory.com/178

 

[JSP] JSP, 서블렛, EL, JSTL에 대한 개념 정리

💬Spring 환경에서 개발을 해야하는데 ‘아.. 이거랑 이거 차이가 뭐였지..?’ 싶은 개념을 빠르게 적립하고 넘어가고 싶은 분들을 위해 작성하였습니다!인트로이전 싸피 교육 과정을 통해 Spring M

23log.tistory.com

 

 

4)  스프링 : servelet 코드 없이 순수 자바 코드만으로 작업 가능. 경량화

     📍 단점 : 버전이 올라가면서 성능 저하. 설정 잡기가 힘듦

 

5)  스프링 부트 : 적은 코드 줄 수로 서비스가 가능. MSA에 적합

     ➡️  최신 신규 프로젝트는 대부분 스프링 부트로 작업

 

  • 클라이언트 측 실행언어 : 브라우저에서 실행되는 언어. 자바스크립트
  • 서버 측 실행 언어 : 서버에서 실행되는 언어. JSP, PHP, ASP, 파이썬, node.js

2.  스크립트 태그  Script Tag

태그 형식 설명
선언문 declaration <!% ... %> 자바 변수나 메소드를 작성
스크립틀릿 scriptlet
<% ... %> 자바 로직 코드 작성
표현문 expression <%= ... %> 선언문의 변수, 메소드, 계산식을 호출하여 문자열로 출력

 

 

1) 선언문 태그 declaration 

<%! 자바 코드; %> 

 

🚀  변수나 메소드 등을 선언하는 태그 

🚀  선언문 태그에 선언된 변수와 메서드는 서블릿 프로그램으로 번역될 때 _jspService() 메소드 외부에 배치되므로 JSP 페이지 임의의 위치에서 선언할 수 있음

🚀  스크립틀릿 태그보다 나중에 선언해도 스크립틀릿 태그에서 사용할 수 있음

🚀  선언문 태그로 선언된 변수는 서블릿 프로그램으로 번역될 때 클래스 수준의 멤버 변수가 되므로 전역 변수로 사용

 

변수 선언
<body>
    <%--선언문 태그 사용 예 : 전역변수 선언--%>
    <%!
      int count = 0; // 전역변수 count를 0으로 초기화
    %>
    Page Count is
    <%
      out.println(++count); // 전역변수 1 증가. 새로 고침을 하면 숫자가 증가.
    %>
</body>


메소드 선언
<body>
    <%-- 선언문 태그에 전역 메서드 사용하기 --%>
    <%-- 전역 메서드 sum()을 선언하기 위해 선언문 태그를 작성 --%>
    <%!
      int sum(int a, int b) {
        return a + b;
      }
    %>
    <%-- 결과 값 출력을 위해 스크립틀릿 태그를 작성 --%>
    <%
      out.println("2 + 3 = " + sum(2, 3)); // 선언문 태그에 선언된 전역 메서드 sum() 호출.
    %>
</body>


2) 스크립틀릿 태그 scriptlet 

 

<% 자바 코드; %> 

 

🚀  자바 코드로 이루어진 로직 부분을 표현

🚀  스크립틀릿 태그는 가장 일반적으로 사용되며 변수 또는 메소드 호출, 유효식 등을 포함할 수 있음

🚀  모든 텍스트, HTML 태그, 또는 JSP 요소는 스크립틀릿 태그 외부에 있어야 함

🚀  스크립틀릿 태그에 작성된 자바 코드는 서블릿 프로그램으로 변환될 때 _jspService() 메소드 내부에 복사

      ➡️ 각 클라이언트의 요청에 대해_jspService() 메소드가 호출되므로 이 메소드의 내부 코드가 클라이언트의 요청마다 실행

      ➡️  _jspService() 메소드 내부에 복사되므로 지역변수가 되어 이 태그에 선언된 변수는 스크립틀릿 태그 내에서만 사용

 

지역 변수 선언
<body>
    <%
      int count = 0; // 지역 변수 선언
    %>
    Page Count is
    <%
      out.println(++count); // 지역 변수 1 증가.
    %>

</body>

 

  📍  전역 변수와 달리 지역변수에서는 1만 증가 ▶️ 새로고침해도 증가되지 않음

 


3) 표현문  expression

<body>
    <%-- 표현문 태그로 현재 날짜 출력하기 --%>
    <p> Today's date: <%=new java.util.Date()%></p>
</body>


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h2>Stripting Tag</h2>

    <%!
        // 선언문 태그를 사용하여 자바 변수와 메서드 정의.
        int count = 3;
        String makeItLower(String data) {
            return data.toLowerCase(); // 소문자로 변경하는 코드
        }
    %>
    <%
        // 스크립틀릿 태그로 자바 로직 코드 작성
        for (int i = 1; i <= count; i++) {
            out.println("Java Server Page " + i + ".<br>");
        }
    %>
    <%-- 표현문 태그로 선언문의 메서드를 호출하여 문자열 형태로 출력 --%>
    <%=makeItLower("Hello World")%>
</body>
</html>

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]


1. 셋  Set

👩🏻‍💻  셋은 중복을 허용하지 않는 리스트로 리스트와 유사한 구조이지만 인덱스로 조회할 수 없고, get() 메서드도 지원하지 않음

👩🏻‍💻  같은 값을 추가하더라도 해당 값은 하나만 저장
👩🏻‍💻  리스트와 마찬가지로 읽기 전용 셋과 읽기 쓰기 모두 가능한 셋, 총 두가지를 제공
       ➡️  각각 setOf(), mutableSetOf() 함수로 객체를 생성

    // 읽기 전용 셋
    val immutableSet = setOf(1, 1, 2, 2, 2, 3, 3)
    println(immutableSet) // [1, 2, 3]

 1) 빈 셋으로 초기화하고 값 입력하기

    var set = mutableSetOf<String>()
    set.add("JAN")
    set.add("FEB")
    set.add("MAR")
    set.add("JAN") // 셋은 중복을 허용하지 않기 때문에 동일한 값은 입력되지 않음

2) 셋 사용하기


  👾  인덱스로 조회하는 메서드가 없기 때문에 특정 위치의 값을 직접 사용할 수 없음

    println("Set 전체 출력 : ${set}") // Set 전체 출력 : [JAN, FEB, MAR]

3) 삭제하기


  👾  값이 중복되지 않기 때문에 값으로 직접 조회해서 삭제 할 수 있음

    set.remove("FEB")
    println("Set 전체 출력 : ${set}") // Set 전체 출력 : [JAN, MAR]

  👾  함수사용 결과는 요소 삭제나 추가가 정상적으로 이루어졌을 때 true,

         정상적으로 이루어지지 않았을 때 false로 boolean 형 결과로 나옴

    val mutableSet = mutableSetOf(1, 1, 2, 2, 2, 3, 3)
    println(mutableSet.add(100)) // true
    println(mutableSet.add(3)) // false

2.  맵  Map

👩🏻‍💻  맵은 키 Key와 값 Value의 쌍으로 입력되는 컬렉션
👩🏻‍💻  맵의 키는 리스트의 인덱스와 비슷한데 맵에는 키를 직접 입력하고 중복되지 않도록 해야 함

    ⚡️  제네릭으로 키와 값의 데이터 타입을 지정해서 맵을 생성
    ⚡️  맵의 요소는 Pair(A, B)를 사용하는 데 이는 A to B로도 표현할 수 있음

// 읽기 전용 맵
val immutableMap = mapOf("name" to "tom", "age" to 28, "age" to 20, "height" to 170)
println(immutableMap) // {name=tom, age=20, height=170} 중복이 있을 경우 마지막 키값이 저장됨

1) 맵 생성하기


  👾  키와 값의 데이터 타입을 모두 String으로 사용

 var map = mutableMapOf<String, String>()

2) 값 추가하기


  👾  값을 추가하기 위해 제공되는 put 메서드에 키와 값을 입력

    map.put("키1", "값1")
    map.put("키2", "값2")
    map.put("키3", "값3")
    println(map) // {키1=값1, 키2=값2, 키3=값3}


3) 맵 사용하기


  👾  get 메서드에 키를 직접 입력해서 값을 사용할 수 있음

println("map에 입력된 키1의 값은 ${map.get("키1")}입니다.") // map에 입력된 키1의 값은 값1입니다.

 4) 맵 수정하기


  👾  put() 메서드를 사용할 때 동일한 키를 가진 값이 있으면 키는 유지된 채로 값만 수정

map.put("키2", "수정한 값")
map["키2"] = "수정한 값"
println("map에 입력된 키2의 값은 ${map.get("키2")}입니다.") 
// map에 입력된 키2의 값은 수정한 값입니다.

5) 맵 삭제하기


  👾  remove() 메서드에 키를 입력해 값을 삭제할 수 있음

map.remove("키1")

// 없는 값을 불러오면 null 값이 출력됨
println("map에 입력된 키1의 값은 ${map.get("키1")}입니다.") 
// map에 입력된 키1의 값은 null입니다.

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]


1.  컬렉션

자바에서 리스트 List, 셋 Set, 맵 Map 등 여러 자료 구조를 사용하는데, 코틀린에서도 이러한 컬렉션을 모두 사용할 수 있을 뿐만 아니라 몇 가지 편리한 함수를 추가로 제공. 또한 코틀린은 컬렉션을 읽기 전용 immutable 컬렉션읽기-쓰기 mutable 컬렉션으로 크게 두 가지로 나눔


1) 리스트 List


  👻 리스트 List는 저장되는 데이터에 인덱스를 부여한 컬렉션이며 중복된 값을 입력할 수 있음
  👻 코틀린에서 동적으로 리스트를 사용하기 위해서는 리스트 자료형 앞에 뮤터블 Mutable 이라는 접두어 prefix가 붙음
        💫  접두어가 있는 리스트도 있지만 잘 사용하지 않기 때문에 항상 mutableList, mutableMap, mutableSet을 사용

 

 뮤터블과 이뮤터블


프로그래밍 언어에서 뮤터블은 변할 수 있는 데이터 타입을 가르키는 용어변수로는 var이 뮤터블
그리고 반대 개념인 이뮤터블 Immutable이 있는데 이것은 val과 같이 변할 수 없는 데이터 타입을 가르키는 용어.

  ⚡️ 코틀린은 컬렉션 데이터 타입을 설계할 때 모두 이뮤터블로 설계
  ⚡️ 기본 컬렉션인 리스트, 맵, 셋은 모두 한 번 입력된 값을 바꿀 수 없음
  ⚡️ 컬렉션의 원래 용도인 동적 배열로 사용하기 위해서는 뮤터블로 만들어진 데이터 타입을 사용해야 함

 

읽기 전용 리스트는 listOf() 함수를 사용
읽기 쓰기 모두 가능한 리스트는 mutableListOf() 함수를 사용
    // 이뮤터블
    val numList = listOf(1, 2, 3)
    println(numList[1]) // 2
    // numList[0] = 10    // error
   // 뮤터블
   val mutableList = mutableListOf("MON", "TUE", "WED") 
    // 3개의 값을 가진 크기가 3인 동적 배열 리스트가 생성

2) 리스트에 값 추가하기 : add


  👻  mutableList 변수에 add 메서드를 사용해서 값을 추가
  👻  값이 추가되면서 동적으로 리스트의 공간이 자동으로 증가

        mutableList.add("THU") 
        // 입력될 위치인 인덱스를 따로 지정해주지 않아도 입력되는 순서대로 인덱스가 지정.
        println(mutableList) 
        // [MON, TUE, WED, THU]

3) 리스트에 입력된 값 사용하기 : get


  👻  입력할 때와는 다르게 사용할 때는 인덱스를 지정해서 몇 번째 값을 꺼낼 것인지 명시

        var variable = mutableList.get(1) // 두 번째 값을 변수에 저장
        variable = mutableList[1]
        println(variable) // TUE

4) 리스트 값 수정하기 : set


  👻  특정 인덱스 값을 수정

        mutableList.set(1, "수정할 값") // 두 번째 값을 수정
        println(mutableList) // [MON, 수정할 값, WED, THU]
        mutableList[1] = "수정할 값" // 두 번째 값을 수정.

5) 리스트에 입력된 값 제거하기 : removeAt


  👻  리스트에 입력된 값의 인덱스를 지정해서 삭제

        println(mutableList.get(1)) // 수정할 값
        mutableList.removeAt(1) // 두 번째 값을 삭제
        // 두 번째 값을 삭제하면 세 번째 값부터 인덱스가 하나씩 감소하면서 빈자리의 인덱스로 이동
        println(mutableList.get(1)) // WED

6) 빈 리스트 사용하기


  👻  아무것도 없는 빈 리스트를 생성하면 앞으로 데이터 타입을 알 수 없기 때문에 값의 타입을 추론할 수 없음
  👻  빈 컬렉션의 경우 앞에서처럼 '데이터타입of'만으로는 생성되지 않고 데이터 타입을 직접적으로 알려주는 방법을 사용해야 함

var 변수명 = mutableListOf<컬렉션에 입력될 값의 타입>()
var stringList = mutableLisfOf<String>()
        // 생성
        val stringList = mutableListOf<String>() // 문자열로 된 빈 컬렉션을 생성

        stringList.add("월")
        stringList.add("화")
        println(stringList[1]) // 화

7) 컬렉션 개수 가져오기 : size


  👻  size 프로퍼티를 사용하면 컬렉션의 개수를 가져올 수 있음

        println("stringList에는 ${stringList.size}개의 값이 있습니다.")
        // stringList에는 2개의 값이 있습니다.

 


예제


    문자열을 저장할 수 있는 List 객체를 생성하고 여기에 "a", "b", "c", "d", "e"를 저장한 후 이것을 출력하는 프로그램을 생성
    출력 예:  [a, b, c, d, e]

    1. 뮤터블  2. 이뮤터블 두 케이스 다 작성

fun main() {

    val charList = listOf("a", "b", "c", "d", "e") 
    println(charList) // [a, b, c, d, e]

    val mutableList = mutableListOf<String>()
    // val mutableList: MutableList<String> = mutableListOf()
    mutableList.add("a")
    mutableList.add("b")
    mutableList.add("c")
    mutableList.add("d")
    mutableList.add("e")

    println(mutableList) // [a, b, c, d, e]
}

 

 

 

[ 내용 참고 : IT 학원 강의 ]


1.  Ajax ; Asynchronous JavaScript And XML

자바스크립트를 사용하여 브라우저가 비동기 방식으로 데이터를 요청하고, 서버가 응답한 데이터를 수신하여 웹페이지를 동적으로 갱신하는 프로그래밍 방식. (ex. 구글 지도)


  👾  Ajax는 브라우저에서 제공하는 Web API인 XMLHttpRequest 객체를 기반을 동작
  👾  XMLHttpRequest : HTTP 비동기 통신을 위한 메서드와 프로퍼티를 제공

  👾  이전의 웹페이지는 완전한 HTML을 서버로부터 전송받아 웹페이지 전체를 처음부터 다시 렌더링하는 방식으로 동작
          ➡️  화면이 전환되면 서버로부터 새로운 HTML을 전송받아 웹페이지 전체를 처음부터 다시 렌더링

 

전통적 방식의 단점 


    a. 이전 웹페이지와 차이가 없어서 변경할 필요가 없는 부분까지 포함된 완전한 HTML을 서버로부터

        매번 다시 전송받기 때문에 불필요한 데이터 통신이 발생
    b. 변경할 필요가 없는 부분까지 처음부터 다시 렌더링 한다. 이로 인해 화면 전환이 일어나면 화면이 순간적으로

         깜빡이는 현상이 발생한다.
    c. 클라이언트와 서버와의 통신이 동기 방식으로 동작하기 때문에 서버로부터 응답이 있을 때까지 다음 처리는 블로킹 된다.


Ajax의 장점


   a. 변경할 부분을 갱신하는 데 필요한 데이터만 서버로부터 전송받기 때문에 불필요한 데이터 통신 발생 x
   b. 변경할 필요가 없는 부분은 다시 렌더링하지 않는다. 따라서 화면이 순간적으로 깜빡이는 현상이 발생하지 않는다.
   c. 클라이언트와 서버와의 통신이 비동기 방식으로 동작하기 때문에 서버에게 요청을 보낸 이후 블로킹이 발생하지 않는다.

 

Ajax의 단점


    a. 즐겨찾기나 검색엔진에 불리
    b. 개발이 상대적으로 어려움

 

💡  '동기(synchronous)'란       
     -  직렬적으로 태스크를 수행  ▶️  요청을 보낸 후 응답을 받아야지만 다음 동작이 이루어지는 방식 (순차 진행)
💡  '비동기 (asynchronous)'란       
     -  병렬적으로 태스크를 수행  ▶️  요청을 보낸 후 응답의 수락 여부와는 상관없이 다음 태스크가 동작 (멀티 진행)
     
   * 출처 : https://velog.io/@khy226

 


2.  JSON ; JavaScript Object Notation

클라이언트와 서버간의 HTTP 통신을 위한 텍스트 데이터 포맷
자바스크립트에 종속되지 않은 언어 독립형 데이터 포맷으로, 대부분의 프로그래밍 언어에서 사용할 수 있음

  👾  JSON은 자바스크립트의 객체 리터럴과 유사하게 키와 값으로 구성된 순수한 테스트
  👾  JSON의 키는 반드시 큰 따옴표(작은 따옴표 사용 불가)로 묶여야 함
  👾  값은 문자열은 큰 따옴표(작은 따옴표 사용 불가)로 묶여야 함 나머지는 그대로 쓰여도 무관


 

1) JSON.stringify()


     ⚡️ 객체를 JSON 포맷의 문자열로 변환
     ⚡️ 클라이언트가 서버로 객체를 전송하려면 객체를 문자열화해야 하는 데 이를 직렬화 serializing 라고 함

// 기본 형식
JSON.stringify(value, replacer, space)
    1. value : 변환할 객체
    2. replacer : 함수. 값의 타입이 Number이면 필터링이되어 반환되지 않는다.

    3. space : 들여쓰기 몇 칸 할지 Int 형으로 기입
<head>
    <script>
    
        const obj = {
            name: 'Lee',
            age: 20,
            alive: true,
            hobby: ['traveling', 'tennis'],
        };
        console.log(typeof obj); // object

        // 객체를 JSON 포맷의 문자열로 변환.
        const prettyJson = JSON.stringify(obj, null, 2); 
        console.log(typeof prettyJson, prettyJson);
        /*
        string {
           "name": "Lee",
           "age": 20,
           "alive": true,
           "hobby": [
               "traveling",
               "tennis"
           ]
         }
        */
        
         function filter(key, value) {
            //undefined: 반환되지 않음
            return typeof value === 'number' ? undefined : value;
        }
        
        const strFilteredObject = JSON.stringify(obj, filter, 2);
        console.log(typeof strFilteredObject, strFilteredObject);
        /*
        string {
            "name": "Lee",
            "alive": true,
            "hobby": [
                "traveling",
                "tennis"
             ]
        */
}
    </script>
</head>

JSON.stringify() 메서드는 객체뿐만 아니라 배열도 JSON 포맷의 문자열로 변환
<script>
        const todos = [
            { id: 1, content: 'HTML', completed: false },
            { id: 2, content: 'CSS', completed: true },
            { id: 3, content: 'JavaScript', completed: false },
        ];
        // 배열을 JSON 포맷의 문자열로 변환
        const jsonArray = JSON.stringify(todos, null, 2);
        console.log(typeof jsonArray, jsonArray);
        /*
        string [
            {
                "id": 1,
                "content": "HTML",
                "completed": false
             },
            {
                "id": 2,
                "content": "CSS",
                "completed": true
             },
            {
                "id": 3,
                "content": "JavaScript",
                "completed": false
            }
         ]
         */
</script>

 


2)  JSON.parse()


    ⚡️  JSON 포맷의 문자열을 객체로 변환  ▶️  역직렬화 deserializing
    ⚡️  서버로부터 클라이언트에게 전송된 JSON 데이터는 문자열이고, 이 문자열을 객체로 변환

<script>

    const obj = {
        name: "Lee",
        age: 20,
        alive: true,
        hobby: ["traveling", "tennis"],
    };
    console.log(typeof obj); // obj

    // 객체를 JSON 포맷의 문자열로 변환.
    const json = JSON.stringify(obj);
    console.log(typeof json); // string

    // JSON 포맷의 문자열을 객체로 변환.
    const parsed = JSON.parse(json);
    console.log(typeof parsed, parsed); // object

</script>

 


3.  Ajax를 이용해 데이터 가져오기

 

<script>
    
    document.addEventListener('DOMContentLoaded', function () {
   
       // 1. XMLHttpRequest 객체 생성
       const xhr = new XMLHttpRequest();

       // 2. HTTP 요청 초기화
        xhr.open('GET', 'https://jsonplaceholder.typicode.com/todos/1');
        // HTTP 요청 방식(GET, POST), 클라이언트가 HTTP 요청을 보낼 서버의 URL 주소

       // 3. 이벤트 등록. XMLHttpRequest 객체의 readyState 프로퍼티 값이 변할 때마다 자동으로 호출
        xhr.onreadystatechange = () => {
            // readyState 프로퍼티의 값이 DONE : 요청한 데이터의 처리가 완료되어 응답할 준비가 완료됨.
            if(xhr.readyState !== XMLHttpRequest.DONE) return;

            if(xhr.status === 200) { // 서버(url)에 문서가 존재함
                console.log(JSON.parse(xhr.response));
                /*
                {
                    "userId": 1,
                    "id": 1,
                    "title": "delectus aut autem",
                    "completed": false
                }
                */
                
                const obj = JSON.parse(xhr.response);
                console.log(obj.title); // delectus aut autem
            } else {
                console.error('Error', xhr.status, xhr.statusText);
            }
        }
        xhr.send(); // 4. url에 요청을 보냄.
    });
</script>

 


💡 onreadystatechange
서버로 부터 응답이 오게 되어 XMLHttpRequest 객체의 값이 변하게 되면 이를 감지해 자동으로 호출되는 함수를 설정한다.
함수를 등록하게 되면 서버에 요청한 데이터가 존재하고, 서버로부터 응답이 도착하는 순간을 특정할 수 있게 된다.

💡  status
서버의 문서 상태를 표현한다(200 : 존재 / 404 : 미존재)

💡 xhr.send()

send() 메서드를 통해 서버로 객체를 전달한다. 이때 send() 메서드 매개변수를 쓰냐 안쓰냐에 따라 GET / POST 방식으로 다르게 보내게 된다.

💡  readyState 프로퍼티

XMLHttpRequest 객체의 현재 상태를 나타낸다. 이 프로퍼티의 값은 객체의 현재 상태에 따라 다음과 같은 주기로 순서대로 변화한다.

  1. UNSENT (숫자 0) : XMLHttpRequest 객체가 생성됨.
  2. OPENED (숫자 1) : open() 메소드가 성공적으로 실행됨.
  3. HEADERS_RECEIVED (숫자 2) : 모든 요청에 대한 응답이 도착함.
  4. LOADING (숫자 3) : 요청한 데이터를 처리 중임.
  5. DONE (숫자 4) : 요청한 데이터의 처리가 완료되어 응답할 준비가 완료됨.
 

출처: https://inpa.tistory.com/entry/JS-📚-AJAX-서버-요청-및-응답-XMLHttpRequest-방식 [Inpa Dev 👨‍💻:티스토리] 


출처: https://inpa.tistory.com/entry/JS-📚-AJAX-서버-요청-및-응답-XMLHttpRequest-방식
         [Inpa Dev 👨‍💻:티스토리]

응용 예제 - 현재 날씨 가져오기
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>

        document.addEventListener('DOMContentLoaded', function () {
            // url 인코딩된 키 사용
            const serviceKey = 'uAhO32pV0qa7BDOmkJLhw2ZyOB9i5bGj7cMN8cuuHmKIwyyf29lHLjym8hBXdIaXyvAI1IyLvQZopk5HW233qQ==';

            // 위치 값
            const nx = 89
            const ny = 90

            // 현재 시간 구함
            const today = new Date();

            const baseDate = `${today.getFullYear()}${('0' + (today.getMonth() + 1)).slice(-2)}${('0' + today.getDate()).slice(-2)}`;
            // 현재 분이 30분 이전이면 이전 시간(정시)을 설정.
            let baseTime = today.getMinutes() <= 30 ? `${today.getHours() -1}00` : `${today.getHours()}00`;
            baseTime = (baseTime.length === 3) ? `0${baseTime}` : baseTime; // 10시 전이면 0을 하나 붙임.

            const parameter = `?serviceKey=${serviceKey}&base_date=${baseDate}&base_time=${baseTime}&nx=${nx}&ny=${ny}&dataType=JSON`
            const url = 'http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getUltraSrtNcst' + parameter
            console.log(url+parameter);


            const xhr = new XMLHttpRequest();
            xhr.open('GET', url);
            xhr.onreadystatechange = () => {
                // readyState 프로퍼티의 값이 DONE : 요청한 데이터의 처리가 완료되어 응답할 준비가 완료됨.
                if(xhr.readyState !== XMLHttpRequest.DONE) return;

                if(xhr.status === 200) { // 서버(url)에 문서가 존재함
                    console.log(xhr.response);
                    jsonData = JSON.parse(xhr.response);
                    console.log(jsonData);

                    const weatherItems = jsonData.response.body.items.item;
                    let jsonStr = `[발표 날짜: ${weatherItems[0]["baseDate"]}]\n`;
                    jsonStr += `[발표 시간: ${weatherItems[0]["baseTime"]}]\n`;
                    for (let k in weatherItems) {
                        let weatherItem = weatherItems[k];
                        obsrValue = weatherItem['obsrValue']
                        // T1H: 기온, RN1: 1시간 강수량, REH: 습도 %
                        if (weatherItem['category'] === 'T1H') {
                            jsonStr += ` * 기온: ${obsrValue}[℃]\n`;
                        } else if (weatherItem['category'] === 'REH') {
                            jsonStr += ` * 습도: ${obsrValue} [%]\n`;
                        } else if (weatherItem['category'] === 'RN1') {
                            jsonStr += `* 1시간 강수량: ${obsrValue} [mm]\n`;
                        }
                    }

                    document.querySelector('div').innerText = jsonStr;


                } else {
                    console.error('Error', xhr.status, xhr.statusText);
                }
            }
            xhr.send();
        });

    </script>
</head>
<body>
<div>


</div>

 

 

 

 

 

 

[ 내용 참고 : IT 학원 강의 및 inpa_dev 티스토리 ]


1.  함수  function

🐰  함수는 fun으로 정의하고 반환값이 있는 함수는 내부에서 return으로 값을 반환
🐰  함수를 정의할 때 입력값을 기술한 것을 '파라미터'

    fun 함수이름 (파라미터 이름 : 타입) : 반환타입 {
        return 값
    }


  🥕  함수의 괄호 안에 입력되는 '파라미터 이름 : 타입'에 따라, 함수를 호출할 때 괄호 안에 값을 넣어서 전달하는데
        이 때 입력되는 값의 타입은 함수에 정의된 파라미터 타입과 동일하게 입력해야 함

 

1) 함수의 정의

 

 반환값과 입력값이 있는 함수의 정의


    ✏️  Int 타입의 x라는 입력 파라미터를 갖는 함수 square()를 정의

fun square(x: Int): Int {
    return x * x
}
// square() 함수가 호출되면 입력값을 제곱해서 호출한 측으로 반환하고 실행이 종류.

반환값이 없는 함수의 정의 

 

    ✏️  반환값 없이 입력값을 받아서 출력하는 함수 printSum() 함수를 정의. 함수가 호출되면 결과값을 출력하고 실행이 종료

fun printSum(x: Int, y: Int) {
    println("x + y = ${x + y}")
}

입력값 없이 반환값만 있는 함수의 정의
fun getPi(): Double {
    return 3.14
}


 2) 함수의 사용(호출)


🐰  함수의 사용은 이름 뒤에 괄호를 붙여서 명령어를 실행하는 형태

함수명(값)    

 

    🥕  괄호를 붙이지 않으면 함수의 코드가 실행되지 않고 마치 값처럼 인식

 

반환값과 입력값이 있는 함수의 호출


   ✏️  파라미터에 전달할 값을 입력하고 반환값은 대입 연산자(=)로 변수에 담은 후 사용

fun main() {
    var squareResult = square(30)
    println("30의 제곱은 ${squareResult}입니다.") // 30의 제곱은 900입니다.
    println("40의 제곱은 ${square(40)}입니다.") // 40의 제곱은 1600입니다.
}

반환값이 없는 함수의 호출


    ✏️  반환값이 없으면 대입 연산자(=)를 사용하지 않고 바로 호출해서 실행

fun main() {
    printSum(3, 5) // x + y = 8
}

입력값이 없는 함수의 호출


    ✏️  입력값이 없다면 괄호만으로 실행하고 결과값을 받을 수 있음

fun main() {

    val PI = getPi()
    println("지름이 10인 원의 둘레는 ${PI}입니다.") // 지름이 10인 원의 둘레는 3.14입니다.

}

 2.  함수 파라미터의 정의

🐰  함수에 입력되는 파라미터는 마치 변수를 정의하듯이 '이름 : 타입'의 형태로 정의
       ➡️  여러 개의 파라미터가 정의될 경우는 콤마로 구분
🐰  코틀린에서 함수 파라미터를 통해 입력되는 모든 값은 변하지 않는 immutable
🐰  코틀린에서의 함수 파라미터는 모두 읽기 전용 키워드 val이 생략된 형태

 fun 함수이름((val 생략) name1: String, name2: Int, name3: Double) {실행코드} 

 

 

1) 파라미터의 기본값 정의와 호출


    🥕  파라미터는 정의할 때 등호(=)를 사용해서 기본값을 설정할 수 있음

fun 함수이름 (name1: String, name2: Int = 157, name3: Double = 34.5) {실행코드}
fun newFun(name: String, age: Int = 29, weight: Double = 65.5) {
        // name = "tom"; // Val cannot be reassigned
        println("name의 값은 ${name}입니다.")
        println("age의 값은 ${age}입니다.")
        println("weight의 값은 ${weight}입니다.")
}

// 정의된 newFun() 함수를 호출할 때 기본값이 없는 첫 번째 파라미터에만 값을 입력하면
// 두 번째와 세 번째 파라미터에는 설정한 기본값이 자동으로 입력.
    
    newFun("Hello")
    /*
    name의 값은 Hello입니다.
    age의 값은 29입니다.
    weight의 값은 65.5입니다.
     */


2)  파라미터 이름으로 값을 입력하기


    🥕  함수에 정의된 파라미터가 많을 경우 입력하는 값의 의미가 명확하지 않을 때가 있음
    🥕  이럴 경우 순서와 상관 없이 정의된 파라미터 이름을 지정해서 직접 값을 입력할 수 있음

fun main() {

    newFun("Michael", weight=67.5)
    /*
     name의 값은 Michael입니다.
     age의 값은 29입니다.
     weight의 값은 67.5입니다.
     */

}

 


응용 예제

 

   📍 login() 메서드와 logout() 메서드를 선언
        login() 메서드를 호출할 때는 매개값으로 id와 passwd를 제공하고, logout() 메서드는 id만 매개값으로 제공

       1) login() 메서드는 매개값 id가 "admin", 매개값 password가 "1234"일 경우에만 true 로 리턴하고

           그외의 값일 경우에는 false를 리턴
       2) logout() 메서드는 "admin 아이디가 로그아웃 되었습니다"가 출력

fun main() {

    print("아이디를 입력해주세요. >> ")
    val id = readln()
    print("비밀번호를 입력해주세요. >> ")
    val password = readln()

    val result = login(id = id, password = password)
    if (result) {
        println("로그인 되었습니다.")
        logout(id)
    } else {
        println("id 또는 password가 올바르지 않습니다.")
    }

}

fun login(id:String, password: String): Boolean {
    return id == "admin" && password == "1234"
}

fun logout(id: String) {
    println("$id 아이디가 로그아웃 되었습니다.")
}

 


  📍  배열을 전달 받아 짝수만 출력하는 메서드 작업 

fun main() {
   
    val numbers = IntArray(10)
    for (i in numbers.indices) {
        numbers[i] = i + 1
    }
    print("main() : ")
    for (i in numbers.indices) {
        print(numbers[i])
        if (i < numbers.size - 1) {
            print(", ")
        }
    } // main() : 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

    println()
    printOdd(numbers) // printOdd() : 2, 4, 6, 8, 10
}

fun printOdd(numbers: IntArray) {
    print("printOdd() : ")
    for (i in numbers.indices) {
        if (numbers[i] % 2 == 0) {
            print(numbers[i])
            if ( i < numbers.size - 1) {
                print(", ")
            }
        }
    }

    val odds = numbers.filter {result -> result % 2 == 0}
    println(odds)
}

 


  📍 키보드로 부터 학생 수와 각 학생들의 점수를 입력받아서, 최고 점수 및 평균 점수를 구하는 프로그램

fun main() {

    var run = true // 반복문의 조건으로 사용 -> 값이 false가 된다면 반복문이 종료

    var scoreList: IntArray = IntArray(0)
    while (run) {
        println("-----------------------------------------------------")
        println("1.학생수 | 2.점수입력 | 3.점수리스트 | 4.분석 | 5.종료")
        println("-----------------------------------------------------")
        print("선택> ")
        val selectNo: Int = readln().trim().toInt()
        when (selectNo) {
           1 -> scoreList = inputStudentNum() // 학생수를 입력 받아서 배열 생성
           2 -> inputScores(scoreList) // 생성된 배열의 갯수 만큼 점수 입력
           3 -> printScores(scoreList) // 입력받은 배열의 값을 출력
           4 -> printAnalysis(scoreList) // 최고 점수, 평균 점수 출력
           5 -> run = setRun() // run 값 변경
        }
    }
    println("프로그램 종료")
}

fun inputStudentNum():IntArray {
    print("학생수> ")
    var studentNum = readln().toInt()
    return IntArray(studentNum)
}

fun inputScores(scores:IntArray) {
    for (i in scores.indices) {
        print("scores[$i] > ")
        scores[i] = readln().toInt()
    }
}

fun printScores(scores:IntArray) {
    for (i in scores.indices) {
        println("scores[$i] : " + scores[i])
    }
}

fun printAnalysis(scores: IntArray) {
    var max = scores[0]
    var sum = scores[0]
    var avg: Double

    for (i in 1 until scores.size) {
        if (scores[i] > max) {
            max = scores[i]
        }
        sum += scores[i]
    }

    avg = (sum / scores.size).toDouble()
    println("최고 점수: " + max)
    println("평균 점수: " + avg)

}

fun setRun(): Boolean {
    return false
}

 

 

 

[ 내용 참고 : IT 학원 강의 ]

+ Recent posts