의존성 주입(Dependency Injection)은 객체 간의 의존성을 외부에서 주입받아 결합도를 낮추고 코드의 유연성과 테스트 가능성을 높이는 소프트웨어 설계 패턴이다, 스프링에서 사용하는 의존성 주입 방식에는 필드 주입, 생성자 주입, Setter 주입 세 가지를 정리해보려 한다.

 

 

 


 

필드주입(Field Injection)

클래스의 필드에 @Autowired를 직접 사용하여 의존성을 주입한다.

 

장점

  1. 간결한 코드로 구현가능.
  2. 생성자나 Setter 없이 의존성을 선언 가능

단점

  1. private 필드 접근의 제한으로 *테스트가 어렵다.
  2. 객체초기화 시점에 의존성을 강제하지 않아 null point exception 발생하여 예외가 발생할 있다.
  3. 클래스의 의존성을 명시적으로 표현하지 않아 코드 가독성이 떨어진다.

*필드주입의 테스트가 어려운 이유

클래스의 생성자나 메서드 시그니처에 의존성이 드러나지 않으므로 어떤 의존성이 필요한지 파악하기 힘들고 의존성을 명시적으로 주입할 수 없다.

예시)

@SpringBootTest
class MyServiceTest {
    @Autowired
    private MyService myService;  // 필드 주입
}

 

MyService에 어떤 의존성이 주입되는지 명확히 확인하기 어렵습니다. 생성자나 세터 주입 방식으로 했다면, @Autowired와 함께 실제 어떤 값이 주입될지 더 명확하게 제어할 수 있습니다.

 

 

 

생성자 주입(Constructior Injection)

의존성을 생성자를 통해 주입받는다. 스프링에서는 생성자가 하나만 있을 경우 @Autowired를 생략가능

 

장점

  1. 필드를 final로 선언할 수 있어 불변성을 보장
  2. 클래스의 의존성이 명확히 드러난다
  3. 테스트에서 의존성을 쉽게 Mock로 교체 가능
    *실제 객체를 만들기엔 비용과 시간이 많이 들거나 의존성이 길게 걸쳐져 있어 제대로 구현하기 어려울 경우, 가짜 객체를 만들어 사용하는데 이것을 Mock이라 한다.
  4. 런타임에서 *순환참조를 감지해 오류를 방지

단점

  1. 의존성이 많아질 경우 생성자 매개변수가 많아질 수 있다.

*순환참조

두 개 이상의 빈(Bean)이 서로를 참조하는 상황으로 인해 스프링이 빈을 초기화하기 못하는 문제를 말한다.

순환참조 예시 

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class AService {

    private final BService bService;

    @Autowired
    public AService(BService bService) {
        this.bService = bService;
    }

    public void print() {
        System.out.println("AService");
    }
}

@Service
public class BService {

    private final AService aService;

    @Autowired
    public BService(AService aService) {
        this.aService = aService;
    }

    public void print() {
        System.out.println("BService");
    }
}

설명

  1. AService 클래스는 BService를 의존하고 있습니다.
  2. BService 클래스는 AService를 의존하고 있습니다.

이렇게 되면 Spring은 AService와 BService를 생성하려고 할 때, 각각의 객체를 생성하는 과정에서 서로가 서로를 참조하므로 무한 루프에 빠지게 됩니다.

 

순환참조의 해결방안

  1. @Lazy 어노테이션 사용하면 빈 초기화를 지연시켜 순환참조 문제를 해결할 수 있다.
  2. 순환 참조의 한쪽을 Setter  주입(Setter Inject)  방식으로 변경하여 해결
  3. 순환 참조 자체를 제거하는 설계변경 가장 바람직하다.

*스프링 부트 2.6이상에서는 순환참조금지가 기본설정으로 순환참조를 허용하려면 설정을 변경해야 한다.

 

Setter 주입(Setter Injection)

Setter 메서드에 @Autowired를 사용하여 의존성을 주입한다.

 

장점

  1. 의존성을 선택적으로 설정가능
  2. 유연한 초기화가 필요한 경우 유용

단점

  1. 필수 의존성이 누락될 가능성이 있어 객체의 *불완전 상태가 발생할 수 있다.
  2. Setter가 외부에서 호출되어 의존성이 변경될 위험이 있다.

 

*Setter 주입의 불완전상태 발생이유

  1. 객체 생성 이후 스프링 컨테이너가 setter 메서드를 호출할 때 의존성이 주입된다. 주입이 완료되기 전 객체가 사용되면 의존성이 없는 상태로 동작할 수 있다.
  2. 주입순서를 명시적으로 제어하기 어렵고 이로 인해 객체가 완전한 상태로 초기화되지 않을 가능성이 있다.
  3. 주입 대상 필드가 초기화 전에 호출되면 null point exception이 발생할 수 있다.

 

 

 

 

 

 

[결과]

필드주입은 간단한 구현에 사용하지만 테스트가 private접근제한이나 객체 초기화 시점의 의존성 강제하지 않아 테스트가 어려울 수 있다.

생성자 주입은 final로 선언이 가능해 불변성이 보장되고 클래스의 의존성이 명확히 드러난다. 하지만 의존성이 많아지면 생성자 매개변수가 많아질 수 있다.

Setter 주입은 유연한 초기화, 의존성을  선택적으로 설정 가능하나 필수 의존성이 누락될 가능성이 있어 객체의 불완전한 상태가 발생할 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

request, respones객체는 JSP 페이지에서 가장 많이 사용되는 기본 객체로서 웹브라우저의 요청과 관련이 있다. 

이미지 출처: https://nitropack.io/blog/post/time-to-first-byte-ttfb

 


 

request 객체

  • 클라이언트로부터 서버로 전송된 HTTP 요청에 대한 정보를 제공한다.

 

1. HTTP 메서드

  • GET: 서버에서 데이터를 요청한다 주로 데이터를 조회하기 위해 사용
  • POST: 서버에 데이터를 전송합니다. 주로 폼 데이터를 제출하거나 서버에서 리소스를 생성하는 데 사용
  • HEAD: GET 요청과 동일하지만, 응답 본문을 포함하지 않습니다. 주로 헤더 정보를 확인하기 위해 사용됩니다.

2. URL

  • 요청대상 리소스의 경로를 나타낸다.
더보기

리소스는 웹에서 접근 가능한 데이터나 서비스로, URL을 통해 식별된다.

EX)웹 페이지, 이미지, API 엔드포인트 등

3. Headers

  • Host: 요청이 전송된 서버의 도메인 이름을 나타낸다.
  • User-Agent: 요청을 보낸 클라이언트(브라우저 또는 애플리케이션)의 정보.
  • Accept: 클라이언트가 처리할 수 있는 미디어 타입을 명시함

 

4. Body

  • POST, PUT 요청 등에서 클라이언트가 서버로 전송하는 데이터, 폼 제출 시 폼 데이터가 본문에 포함된다. GET 요청의 경우 일반적으로 본문이 비어있다. POST 방식에는 폼데이터, 파일, JSON, XML, 텍스트, 바이너리 파일 등 다양항 형식의 데이터가 들어갈 수 있다 POST 방식은 특히 데이터 생성, 파일 업로드, 로그인 전송등에 주로 사용

 

5. Cookies

  • 클라이언트가 서버로 전송하는 작은 데이터 조각으로, 사용자의 세션정보를 유지하거나, 사용자의 기본 설정을 저장하는 데 사용

 

Request URL: https://www.gstatic.com/cv/js/sender/v1/cast_sender.js
Request Method: GET
Status Code: 200 OK
Referrer Policy: strict-origin-when-cross-origin

accept-ranges: bytes

alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000

cache-control: private, max-age=3000
content-encoding: gzip
content-length: 2007
content-security-policy-report-only: require-trusted-types-for 'script'; report-uri https://csp.withgoogle.com/csp/cloudview
content-type: text/javascript
cross-origin-opener-policy: same-origin; report-to="cloudview"
cross-origin-resource-policy: cross-origin
date: Sun, 20 Oct 2024 14:46:35 GMT
expires: Sun, 20 Oct 2024 14:46:35 GMT
last-modified: Tue, 16 Feb 2021 23:57:06 GMT
report-to: {"group":"cloudview","max_age":2592000,"endpoints":[{"url":"https://csp.withgoogle.com/csp/report-to/cloudview"}]}
server: sffe

x-content-type-options: nosniff
x-xss-protection: 0
  • authority: 호스트이름을 나타낸다.
  • accept: 클라이언트가 선호하는 응답형식을 서버에 알려준다.
       ex) text/html, application/json, application/xml;q=0.9, */*;q=0.8
  • scheme: 사용된 URL의 프로토콜을 나타낸다 주로 http, https가 사용됨vary: Accept-Encoding
  • method: GET 데이터 조회할때 사용, POST 데이터를 생성하거나 제출할 때 사용, PUT 서버의 리소스를 수정하기 위한 요청, DELETE 서버의 리소스를 삭제하기 위한 요청, PATCH 서버의 리소스를 부분적으로 수정하기 위한 요청, HEAD 헤더 정보만 가져오기 위한 요소

reponse 객체

  • 객체는 클라이언트로 전송하는 HTTP 응답에 대한 정보를 제공하는 기본객체

 

1. HTTP 상태코드

  • 요청에 대한 처리 결과를 나타내는 숫자.
  • 200: 요청이 성공적으로 처리
  • 404: 요청한 리소스를 찾을 수 없습니다.
  • 500: 서버에서 요류가 발생했습니다.
    상태코드에 대하여 좀더 확인하고 싶으면 https://prodonghwa.tistory.com/13 참고해 주세요

2. Header

  • 응답에 대한 메타데이터를 포함하는 키-값 쌍의 모음

3. addCookie 

  • 클라이언트에 쿠키를 추가하고 설정할 수 있다.

4. Redirect

  • 클라이언트를 다른 URL로 리다이렉트 시킬 수 있다.

5. 응답 본문작성:

  • HTTP 응답의 본문을 작성할 수 있다. HTML, TEXT, JSON 등 데이터를 클라이언트로 보낼 수 있다

 

authority: jnn-pa.googleapis.com
method: POST
path: /$rpc/google.internal.waa.v1.Waa/Create
scheme: https
accept:*/*
accept-encoding: gzip, deflate, br, zstd
accept-language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7

content-length: 24
content-type: application/json+protobuf
origin: https://www.youtube.com
priority: u=1, i
referer: https://www.youtube.com/
sec-ch-ua: "Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) 

Chrome/129.0.0.0 Safari/537.36
  • accept-ch:  서버가 요청헤더로 받기 원하는 정보를 브라우저에 알리는 헤더
  • DPR: 픽셀밀도, Width: 브라우저의 레이아웃 너비, Viewport-Width: 브라우저의 뷰포트 너비
  • Save-Data: 데이터 절약모드 활성화 여부
  • server: 서버 소프트웨어의 이름 및 버전정보를 클라이언트에게 제공하나 보안을 고려하여 server 헤더를 제거하거나 커스터마이징가능하다.
  • vary: 동일한 URL에 요청을 하더라도 요청한 사용자의 특징에 따라 서로 다른 응답을 쥐기 위하여 존재함

 

 

[결과]

request 객체는 클라이언트의 HTTP 요청에 대한 정보를 읽고 처리하는 데 사용되는 기본객체

response 웹 애플리케이션에서 클라이언트로 전송하는 HTTP응답에 대한 정보를 다루는 기본 객체. 응답의 상태, 헤더, 본문 등을 조작하여 클라이언트에게 적절한 응답을 보낼 수 있도록 한다.

 

[느낀 점]

한번 검색을 하여 네트워크 소스보기를 하면 여러 개의 항목과 그에 따른 request와 respone가 존재한다 이것을 보았을 때 실제로 검색에 필요한 부분이라면 왜 이렇게 되는지 확인하고 싶다

각 나라별로 밤낮이 다르듯이 시간또한 다르다 그 기준을 알아보고 대한민국의 기준시간의 표현방식을 확인하려한다.

 

 

이미지 출처:https://smallbusiness.patriotsoftware.com/different-time-zones/

 

 


 

 

TimeZone

Time Zone(타임존)은 동일한 로컬 시간을 따르는 것을 의미한다. 주로 해당 국가에 의해 법적으로 지정되며, 국가별로 각자의 고유한 타임존을 가짐

 

GMT

Greenwich Mean Time(그리니치 평균시)는  런던을 기점으로 하고 웰링턴에 종점으로 설정되는 협정 세계시의  기준시간

 

UTC

Coordinate Universial Time(세계 협정시)는 GTC의 시간 기반으로 세슘 원자의 진동수를 사용해 시간을 계산하여 30만년에 1초 수준으로 오차를 줄였고 기술적인 표기에서는 UTC를 사용한다.

 

KST

Korean Standard Time 한국표준시 대한민국 북한의 표준시로 일본 표준시와 같은 동경 135도를 기준으로 하여 UTC보다 9시간 빠른 표준시 (UTC+09:00)

 

summertime

하절기에 국가의 표준시를 원래 시간보다 (일반적으로) 한 시간 앞당겨 사용하는 것을 말한다

좀더 구체적인 시기는 3월의 둘째 일요일부터 11월의 첫째 일요일까지의 기간동안 0시에 일광 절약 시간제를 실시하며 1시로 시간을 조정해야 한다 UTC-4

 

[결과]

GMT의 평균 태양시라는 것을 사용하여 하루를 정의 UTC는 GMT시간기반에 세슘원자의 진동수를 사용해 시간을 계산

 

 

 

 

 

 

https://brunch.co.kr/@wonish/374

 

세계 각국 타임존 : UTC, PST, EST, KST

영어 이메일 필사를 하다가 UTC, PST, EST 같은 각국 시간대 표현이 나와서 궁금해서 찾아봤다. 예전부터 어렴풋이는 알았지만 정확하게는 알지 못했던 세계 각국의 시간대다. 해외 법인과 일을 하

brunch.co.kr

https://blog.naver.com/whdgml1996/222494354417?trackingCode=rss

 

[개발 관련 주변지식 01] 날짜와 시간 (Timezone, GMT, UTC, KST, ISO 8601)

1. timezone timezone이란 단어를 위키피디아에서 검색하면 아래와 같은 설명을 볼 수 있습니다. A time z...

blog.naver.com

 

인터넷을 하다보면 어쩌다 한번씩 만나는 HTTP 상태코드는 Internet Assigned Numbers Authority (IANA) 가 현재 공식적으로 HTTP 응답 상태 코드 레지스트리로 관리하고있고 이 관리코드는 HTTP/1.0에 클라이언트와 서버간의 통신을 보다 정교하게 만들기 위해 다양한 상태코드와 헤더가 추가되었다 HTTP 상태코드를 확인해보자.

 


 

 

 

1xx (정보): 요청을 받았으며 프로세스를 계속한다.

 

 

임시 응답으로 현재 클라이언트의 요청은 처리되었고 계속 진행하라는 의미 HTTP 1.1버전부터 추가

  • 100(Continue): 요청자는 요청을 계속해야 한다. 서버는 이 코드를 제공하여 요청의 첫 번째 부분을 받았으며 나머지를 기다리고 있음을 나타낸다.
  • 101(Switching Protocol): 요청자가 서버에 프로토콜 전환을 요청했으며 서버는 이를 승인하는 중이다
  • 102(Processing, RFC 2518): 서버가 처리하는 데 오랜 시간이 예상되어 클라이언트에서 타임 아웃이 발생하지 않도록 이 응답 코드  전송
    **RFC 2518이란 WebDAV 프로토콜을 정의하는 문서로 WebDAV는 HTTP 프로토콜을 확장하여 웹 서버에서의 파일 관리를 가능하게 하는 표준 RFC 2518은 이후 RFC 4918로 대체됨

 

2xx (성공): 요청을 성공적으로 받았으며 인식했고 수용하였다.

 

클라이언트의 요청이 서버에서 성공적으로 처리되었다는 의미

  • 200(OK): 서버가 요청을 제대로 처리했다는 뜻이다. 이는 주로 서버가 요청한 페이지를 제공했다는 의미로 쓰인다.
  • 201(Created): 성공적으로 요청되었으며 서버가 새 리소스를 작성했다.
  • 202(Accepted): 서버가 요청을 접수했지만 아직 처리하지 않았다.
  • 203(Non-Authoritative Information): 서버가 요청을 성공적으로 처리했지만 다른 소스에서 수신된 정보를 제공
    **신뢰할 수 없는 정보의 예로 콘텐츠 필터링: 어떤 민감한 단어들을 필터링, 이미지 압축 프록시 서버: 고해상도 이미지를 요청하였을 때  데이터 절약을 위해 이미지 파일을 저해상도로 변환
    *** 콘텐츠타입 예시: json, xml, text, csv
  • 204(No Content): 서버가 요청을 성공적으로 처리했지만 콘텐츠를 제공하지 않는다.
  • 205(Reset Content): 서버가 요청을 성공적으로 처리했지만 콘텐츠를 표시하지 않는다. 204 응답과 달리 이 응답은 요청자가 문서 보기를 재설정할 것을 요구한다(예: 새 입력을 위한 양식 비우기).
  • 206(Partial Content): 서버가 GET 요청의 일부만 성공적으로 처리했다
프록시서버

프록시 서버는 클라이언트의 실제 목적시 서버 사이에서 중계역할을 하는 서버로 여러가지 중요한 기능을 수행
1. IP 주소의 보호: 클라이언트가 웹사이트나 서비스를 요청할 때 클라이언트의 실제 IP 주소를 숨기고 프록시 서버의 IP주소를 대신하여 사용자의 익명성이 보호된다.

2. 트래픽 제어 및 성능 향상: 프록시 서버는 캐싱 기능을 활용해 자주 요청되는 데이터를 저장하고, 클라이언트가 동일한 요청을 할 경우 원 서버에 접속하지 않고 캐시에서 빠르게 데이터를 제공할수 있다.

3. 접근제어 및 보안강화: 프록시 서버는 특정 웹사이트, 특정 콘텐츠, 악성 웹사이트나 불법적인 접근을 차단하는필터 역할을 수행할 수 있다.

4. 로깅 및 모니터링: 프록시 서버는 클라이언트의 요청 기록을 저장할 수 있어, 사용자의 웹 활동을 추적하거나
분석이가능하다.
게이트웨이서버

1. 추상서버: 클라이언트가 실제 서버의 위치나 복잡한 구조를 인식하지 않고, 단순한 인터페이스를 통해 서비스를
제공받도록 돕는 개념

1) 서버의 복잡성 숨김: 추상 서버는 다양한 백엔드 시스템(예: 데이터베이스, 마이크로서비스, 외부 API 등)을 통합하고, 클라이언트에게는 하나의 통합된 서비스처럼 보이게한다.

2) 서비스 통합:  클라이언트가 한 번의 요청을 보내면, 게이트웨이 서버는 여러 백엔드 서비스에 요청을 전달한 후, 그 결과를 합쳐 클라이언트에게 응답하여 하나의 단일 서비스로 제공할 수 있다.

3) 로드 밸런싱 및 장애 처리: 추상 서버로서의 게이트웨이 서버는 서버 부하를 분산시키고, 서버 장애 발생 시에도 요청을 다른 서버로 전환하는 역할이 가능하다.

4) 보안 및 접근제어: 추상 서버는 보안 측면에서도 중요한 역할을 한다. 게이트웨이 서버는 클라이언트가 모든 백엔드 서버에 직접 접근하지 못하도록 하여 보안을 강화할 수 있다. 클라이언트는 게이트웨이를 통해서만 백엔드 서버에 접근할 수 있으며, 게이트웨이가 클라이언트의 요청을 필터링하거나 권한을 검증하는 역할을 수행한다.

2. 보안로직 통일: 게이트웨이 서버는 다양한 백엔드 시스템에 대한 보안 정책을 통일할 수 있는 중심점으로
작동한다.

1) 중앙화된 인증 및 인가: 게이트웨이 서버는 단일 진입점으로 작용하여, 모든 클라이언트 요청에 대해 중앙에서 인증 및 권한 검증을 수행, 클라이언트는 백엔드 서버에 접근하지 않고 게이트웨이서버를 통과하여야하므로 
일관된 보안로직이 적용

2) 보안 정책의 통일: 게이트웨이 서버는 방화벽 규칙, 데이터 암호화, 접근 제어와 같은 보안 규칙을 중앙화하여 
관리한다,백엔드 서버들마다 서로 다른 보안 설정을 관리할 필요 없이, 게이트웨이 서버에서 한 번에 관리

3) 암호화 관리: 게이트웨이 서버는 모든 외부 통신을 SSL/TLS와 같은 암호화 프로토콜로 보호하고, 이를 일관되게 적용가능하다. 각 백엔드 서버가 개별적으로 암호화 통신을 설정하는 대신, 게이트웨이에서 중앙 집중적으로 암호화 처리

3. 권한 문제 해결 및 통일된 권한 관리: 권한 관리를 단순화하고, 중앙 집중화된 방식으로 통합할 수 있다. 이로
인해 개별 서비스나 시스템에서 따로 권한 설정을 관리할 필요가 없으며, 모든 권한 관련 로직을 게이트웨이 서버에서 처리할 수 있게된다.

1) 권한 검증의 중앙화: 각 백엔드 시스템에서 권한 검증을 따로 처리하는 대신, 게이트웨이 서버에서 중앙화된 
권한 관리가 가능하다. 사용자가 특정 자원이나 서비스에 접근할 때, 게이트웨이 서버가 사용자의 권한을 검증하고, 허가된 요청만 백엔드 서버로 전달

2) 세분화된 접근 제어: 게이트웨이 서버는 다양한 권한 레벨에 따라 세분화된 접근 제어를 적용할 수 있다. 예를
들어, 사용자의 역할(Role)에 따라 특정 API는 읽기 권한만 부여하고, 다른 API는 쓰기 권한을 부여하는 식으로
권한을 구분할 수 있다.

3) 역할 기반 접근 제어(Role-Based Access Control, RBAC): 게이트웨이 서버에서 사용자 역할(Role)에 따라
접근 권한을 중앙에서 관리할 수 있다. 이로 인해 사용자가 가지고 있는 권한에 따라 각기 다른 자원이나 서비스에 접근할 수 있도록 보장할 수 있다.

4. 네트워크 허용 규칙 간편화

1) 단일 진입점 제공: 게이트웨이 서버는 네트워크의 단일 진입점 역할을 한다. 즉, 모든 외부 트래픽은 게이트웨이를 통해 들어오고 나가므로, 네트워크 규칙을 관리하는 위치가 단일화가되어 이를 통해 복잡한 네트워크 규칙 설정을 단순화할 수 있다.

2) IP 필터링 및 방화벽 규칙 관리: 게이트웨이 서버는 네트워크에 대한 IP 필터링이나 방화벽 규칙을 중앙에서 관리할 수 있다. 이를 통해 외부 네트워크에서 특정 IP 주소나 포트에 대한 접근을 쉽게 차단하거나 허용할 수 있다.

3) VPC 게이트웨이 통합: 클라우드 환경에서는 가상 사설 클라우드(VPC)를 사용하여 네트워크를 분리하고, 게이트웨이를 통해 내부 및 외부 네트워크 연결을 간소화할 수 있다. 게이트웨이는 VPC 내 네트워크 허용 규칙을 일관되게 적용하고, 외부와의 트래픽을 제어하는 중요한 역할을 한다.
3xx (리다이렉션): 요청 완료를 위해 추가 작업 조치가 필요하다.

완전한 처리를 위해서 추가 동작이 필요한 경우 주로 서버의 주소 또는 요청한 URI의 웹 문서가 이동되었으니 그 주소로 다시 시도하라는 의미

  • 300(Multiple Choice): 서버가 요청에 따라 여러 조치를 선택할 수 있다. 서버가 사용자 에이전트에 따라 수행할 
    작업을 선택하거나, 요청자가 선택할 수 있는 작업 목록을 제공한다.
  • 301(Moved Permanently): 요청한 페이지가 새 위치로 영구적으로 이동했다. GET 또는 HEAD 요청에 대한 
    응답으로 이 응답을 표시하면 요청자가 자동으로 새 위치로 전달된다.
  • 302(Found): 현재 서버가 다른 위치의 페이지로 요청에 응답하고 있지만 요청자는 향후 요청 시 원래 위치를 계속 
    사용해야 한다.
  • 303(See Other): 요청자가 다른 위치에 별도의 GET 요청을 하여 응답을 검색할 경우 서버는 이 코드를 표시한다. HEAD 요청 이외의 모든 요청을 다른 위치로 자동으로 전달한다.
  • 304(Not Modified): 마지막 요청 이후 요청한 페이지는 수정되지 않았다. 서버가 이 응답을 표시하면 페이지의 
    콘텐츠를 표시하지 않는다. 요청자가 마지막으로 페이지를 요청한 후 페이지가 변경되지 않으면 이 응답(If-Modified-Since HTTP 헤더라고 함)을 표시하도록 서버를 구성해야 한다.
  • 305(Use Proxy): 요청자는 프록시를 사용하여 요청한 페이지만 액세스할 수 있다. 서버가 이 응답을 표시하면
    요청자가 사용할 프록시를 가리키는 것이기도 하다.
    *프록시 사용의 예로는 어떤 회사에서는 직원들이 사내 네트워크에서 외부 웹사이트에 접근할 때 특정 프록시 서버를 거치도록 설정하였고 이 프록시서버는 트래픽을 모니터링하고, 보안검사를 수행한 훙 외부서버에 전송
  • 307(Temporary Redirect): 현재 서버가 다른 위치의 페이지로 요청에 응답하고 있지만 요청자는 향후 요청 시
    원래 위치를 계속 사용해야 한다.
    *임시 리디렉션의 예로는 서버의 유지보수를 하기위여 서비스나 기능에 접근하면 임시페이지로 이동시키거나, 파일 다운로드 서버가 트래픽 부하로 인해 일시적으로 변경

 

4xx (클라이언트 오류): 요청의 문법이 잘못되었거나 요청을 처리할 수 없다.

 

없는 페이지를 요청하는 등 클라이언트의 요청 메시지 내용이 잘못된 경우를 의미

  • 400(Bad Request): 서버가 요청의 구문을 인식하지 못했다.
  • 401(Unauthorized): 이 요청은 인증이 필요하다. 서버는 로그인이 필요한 페이지에 대해 이 요청을 제공할 수 있다. 상태 코드 이름이 권한 없음(Unauthorized)으로 되어 있지만 실제 뜻은 인증 안됨(Unauthenticated)에 더 가깝다.
    **권한없음의 예로는 로그인이 필요한 웹사이트에 접근하려고 하였을 때, API  호출시 유효하지 않은 인증토큰
    (만료되거나 올바르지 않을 경우)을 사용할때,인증을 하지 않았을 때 권한없음의 페이지로 이동
  • 402(Payment Required): 이 요청은 결제가 필요합니다.
  • 403(Forbidden, 금지됨): 서버가 요청을 거부하고 있다. 예를 들자면, 사용자가 리소스에 대한 필요 권한을 갖고
    있지 않다. (401은 인증 실패, 403은 인가 실패라고 볼 수 있음)
    **금지됨의 예로는 관리자만 접근이 가능한 페이지에 일반사용자나 관리자로그인을 하지 않은 사용자가 접속을 시도할 때, 특정 디렉토리나 파일에대한 직접접근을 차단하는경우, 특정 IP주소를 차단,서버의 읽기 권한이 없는 파일에 엑세스 하였을때 해당 코드가 발생한다.
  • 404(Not Found, 찾을 수 없음): 서버가 요청한 페이지(Resource)를 찾을 수 없다. 예를 들어 서버에 존재하지 않는 
    페이지에 대한 요청이 있을 경우 서버는 이 코드를 제공한다.
  • 405(Method Not Allowed): 요청에 지정된 방법을 사용할 수 없다. 예를 들어 POST 방식으로 요청을 받는 
    서버에 GET 요청을 보내는 경우, 또는 읽기 전용 리소스에 PUT 요청을 보내는 경우에 이 코드를 제공한다.
  • 406(Not Acceptable): 요청한 페이지가 요청한 콘텐츠 특성으로 응답할 수 없다.
  • 407(Proxy Authentication Required): 이 상태 코드는 401(권한 없음)과 비슷하지만 요청자가 프록시를 사용하여 
    인증해야 한다. 서버가 이 응답을 표시하면 요청자가 사용할 프록시를 가리키는 것이기도 하다.
  • 408(Request Timeout): 서버의 요청 대기가 시간을 초과하였다.
  • 409(Conflict): 서버가 요청을 수행하는 중에 충돌이 발생했다. 서버는 응답할 때 충돌에 대한 정보를 포함해야 
    한다. 서버는 PUT 요청과 충돌하는 PUT 요청에 대한 응답으로 이 코드를 요청 간 차이점 목록과 함께 표시해야 한다.
  • 410(Gone): 서버는 요청한 리소스가 영구적으로 삭제되었을 때 이 응답을 표시한다. 404(찾을 수 없음) 코드와 비슷하며 이전에 있었지만 더 이상 존재하지 않는 리소스에 대해 404 대신 사용하기도 한다. 리소스가 영구적으로 이동된 경우 301을 사용하여 리소스의 새 위치를 지정해야 한다.
  • 411(Length Required): 서버는 유효한 콘텐츠 길이 헤더 입력란 없이는 요청을 수락하지 않는다.
  • 412(Precondition Failed): 서버가 요청자가 요청 시 부과한 사전조건을 만족하지 않는다.
  • 413(Payload Too Large): 요청의 본문이 너무 길어 서버가 처리할 수 없다.
  • 414(URI Too Long): 요청 URI(일반적으로 URL)가 너무 길어 서버가 처리할 수 없다.
  • 415(Unsupported Media Type): 요청이 요청한 페이지에서 지원하지 않는 형식으로 되어 있다.
  • 416(Requested Range Not Satisfiable): 요청이 페이지에서 처리할 수 없는 범위에 해당되는 경우 서버는 이 상태 
    코드를 표시한다.
  • 417(Expectation Failed): 서버는 Expect 요청 헤더 입력란의 요구사항을 만족할 수 없다.

 

5xx (서버 오류): 서버가 명백히 유효한 요청에 대해 충족을 실패했다.

 

- 서버 사정으로 메시지 처리에 문제가 발생한 경우입니다. 서버의 부하, DB 처리 과정 오류, 서버에서

예외(Exceptio)가 발생하는  경우를 의미

  • 500(Internal Server Error): 서버에 오류가 발생하여 요청을 수행할 수 없다.
  • 501(Not Implemented): 서버에 요청을 수행할 수 있는 기능이 없다. 예를 들어 서버가 요청 메소드를 인식하지 못할 때 이 코드를 표시한다.
  • 502 (Bad Gateway, 불량 게이트웨이): 서버가 게이트웨이나 프록시 역할을 하고 있거나 또는 업스트림 서버에서
     잘못된 응답을 받았다.
    **bad gateway의 예로는 게이트웨이 또는 프록시 서버로 부터 잘못된 응답을 받았을 때, 목적시 서버가 응답을 
    하지 않거나 잘못된 응답을 반환할때 서버간의 통신오류를 나타낸다
  • 503(Service Unavailable): 서버가 오버로드되었거나 유지관리를 위해 다운되었기 때문에 현재 서버를 사용할 수 
    없다. 이는 대개 일시적인 상태이다.
  • 504(Gateway Timeout): 서버가 게이트웨이나 프록시 역할을 하고 있거나 또는 업스트림 서버에서 제때 요청을 
    받지 못했다.
  • 505(HTTP Version Not Supported): 서버가 요청에 사용된 HTTP 프로토콜 버전을 지원하지 않는다.



    [결과]

    1xx는 현재 클라이언트의 요청까지는 처리되었고 작업을 계속 진행함 코드, 2xx는 요청을 성공적으로 받고 인식및 수용한 상태, 3xx는 요청완료를 하였고 추가작업 조치가 필요다는 상태, 4xx는 없는페이지를 요청하는 등 요청이 잘못되었다는 상태, 5xx는 서버의 사정으로 요청 처리에 문제가 발생한 경우로 크게 분류하며 많은 상태코드가 존재한다.


    [느낀점]

    HTTP 상태코드를 공부하기 전에는 404, 502정도만 보았고 생각없이 웹사이를 이용하였지만 상태코드에 대하여 알아보자 많은 코드들이 있었고, 그에 따른 코드가 어떻게 하면 실제로 나오게 되는가에 대하여 알아내는 것이 쉽지않았다. 해당 코드와 설명은 있지만 예시를 들기위하여 확인하는 과정이 아직 준비되지 않아 아직 많은 내용을 추가하지 못하여 추후 내용 업데이트 하려고 한다.

 

https://hongong.hanbit.co.kr/http-%EC%83%81%ED%83%9C-%EC%BD%94%EB%93%9C-%ED%91%9C-1xx-5xx-%EC%A0%84%EC%B2%B4-%EC%9A%94%EC%95%BD-%EC%A0%95%EB%A6%AC/

 

[웹 프로그래밍] HTTP 상태 코드 표(100 ~ 500) 전체 요약 정리

서버에서의 처리 결과는 응답 메시지의 상태 라인에 있는 상태 코드(status code)를 보고 파악할 수 있습니다. 상태 코드는 세 자리 숫자로 되어 있는데 첫 번째 숫자는 HTTP 응답의 종류를 구분하는

hongong.hanbit.co.kr

hongong.hanbit.co.kr
https://ko.wikipedia.org/wiki/HTTP_%EC%83%81%ED%83%9C_%EC%BD%94%EB%93%9C

 

HTTP 상태 코드 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 아래는 HTTP(하이퍼텍스트 전송 프로토콜) 응답 상태 코드의 목록이다. IANA가 현재 공식 HTTP 상태 코드 레지스트리를 관리하고 있다. 모든 HTTP 응답 코드는 5개의

ko.wikipedia.org

 

이미지 출처:https://velog.io/@ghkdwp018/JAR-vs.-WAR

 

 

java jvm환경에서 애플리케이션을 개발할 때 애플리케이션을 쉽게 배포하고 동작시킬 수 있도록 관련파일(리소스, 속성파일 등)들을 패키징 해주는 jar, war에 대하여 알아보자

 


 

JAR(Java Archive)

여러 개의 Java 클래스 파일, 메타데이터, 리소스 파일 등을 하나의 파일로 묶은 아카이브 파일로

Java 클래스와 관련 리소스를 패키징하여 재사용 가능한 라이브러리나 실행 가능한 애플리케이션을 생성한다.

사용처는 Java 라이브러리, standalone(독립실행) Java 애플리케이션, 의존성 패키지

JAR파일은 플랫폼에 귀속되는 점만 제외하면 WIN ZIP파일과 동일한 구조이다.

** standalone 방식은 스프링 부트만 실행하면 자동으로 서블릿 컨테이너까지 설정하고, 실행해 준다는 의미

 

 

Java 애플리케이션 실행방식에 대한 장단점

 

1. Standalone 애플리케이션

 

장점

  • 독립적으로 실행가능하고 사용자에게 쉽게 배포할 수 있다.
  • GUI(Graphical User Interface)또는 CLI(Command-Line Interface) 기반으로 직관적으로 사용가능하다.

단점

  • 시스템에 따라 환경설정이 필요할 수 있다.
  • 여러 사요 자가 동시에 접근하기 어렵다.

 

2. 웹 애플리케이션

 

장점

  • 여러 사용자가 동시에 접근이 가능하다.
  • 클라이언트 - 서버 아키텍처로 중앙 집중식 관리 가 용이하다.

단점

  • 서버 및 클라이언트 간 네트워크 의존성
  • 서버 유지보수 및 보안 문제가 있을 수 있음.

 

3. 모듈형 애플리케이션

 

장점

  • 모듈화로 인해 유지보수와 확장이 용이함.
  • 필요한 모듈만 로드하여 성능 최적화 가능.

단점

  • 복잡한 아키텍처로 인해 학습 곡선이 가파를 수 있음.
  • 종속성 관리가 어려울 수 있음

 

4. 컨테이너화된 방식

 

장점

  • 일관된 실행환경 제공, 배포가 간편함.
  • 종속성 문제를 줄이고, 확장성이 뛰어남.

단점

  • 컨테이너 관리 및 오케스트레이션의 복잡성,
  • 초기설정이 복잡할 수 있음.

 

WAR(Web Application Arcshive)

웹 애플리케이션을 패키징 하기 위한 파일포맷으로 Java 클래스, JSP, 서블릿, XML, 라이브러리, 정적웹리소스(HTML, CSS, JavaScript)등 웹 애플리케이션 구성요소 포함하며 하나의 단위로 패키징하고 배포하기 위한 목적으로 사용

사용처는 Java 기반의 웹 애플리케이션 서버나 서블릿 컨테이너(Tomcat, JBoss, WebLogic 등)에서 실행되는 웹애플리케이션에 사용

 

**서블릿(Servlet)
Servlet은 자바 기반의 웹 애플리케이션을 개발하기 위한 서버 측 프로그램 또는 기술이다.
서블릿은 HTTP 요청(Request)을 받아 이를 처리한 뒤 HTTP 응답(Response)을 생성하여 클라이언트에게 전달하는, 다시 말하면 클라이언트의 요청을 처리하여 동적인 웹 페이지를 생성하는 역할

**서블릿 컨테이너(Servlet Container)
서블릿은 혼자서 동작할 수 없기 때문에 서블릿을 실행하고 관리해 주는 서블릿 컨테이너 내에서 동작한다.
서블릿 컨테이너는 서블릿 객체를 생성, 초기화, 호출, 종료하는 생명주기를 관리할 뿐만 아니라, 클라이언트의 요청을 받고 응답할 수 있도록 웹 서버와의 소켓 통신을 지원한다.

 

웹사이트 배포순서

 

1. 웹사이트의 파일과 리소스를 준비한다.

    HTML, CSS, JavaScript 등으로 이루어짐

 

2. 웹 호스팅 서비스 또는 웹서버를 준비한다.

   GitHub Pages AWS 등이 웹호스팅 Apache, Microsoft IIS 등 웹서버

 

3. 웹사이트 업로드 웹 호스팅 사이트나 웹서버에 파일을 업로드한다.

 

4. 도메인 등록

    도메인을 구매하고 DNS 설정을 통하여 웹호스팅 또는 웹서버의 IP를 등록한다.

 

5. 배포 전 검증

     웹사이트가 실제 배포환경에서 제대로 동작할지 사전에 확인하는 과정으로 다양한 테스트와 점검이 이루 진다.

 

 - 코드리뷰: 개발된 코드가 모범사례에 따라 작성되었는지, 효율적인지, 유지보수가 용이한지, 보안문제, 성능저하요소 불필요한 코드 등이 있는지 검토

- CI/CD 파이프라인에서 자동화된 테스트

단위테스트: 각 함수나 메서드가 의도한 대로 동작하는지 개별적으로 테스트

통합테스트: 여러 모듈이 통합되어 정상적으로 상호작용하는지 확인

UI 테스트: 사용자의 실제 워크플로우에 따라 전체 시스템이 제대로 동작하는지 시나리오 기반으로 확인

End-to-End(E2E) 테스트: 사용자의 실제 워크플로우에 따라 전체 시스템이 제대로 동작하는지 시나리오 기반 확인

- 스테이징 환경에서 검증

스테이징 환경은 실제 배포 환경과 유사한 환경에서 웹사이트를 실행하여, 배포 후 발생할 수 있는 문제를 사전에 파악

배포할 코드가 실제 서버에서 제대로 동작하는지 확인할 수 있는 환경 데이터베이스, 외부 API, 서버 성능 등도 검증

 - 성능테스트

부하 테스트: 사용자가 급증할 때 웹사이트가 얼마나 잘 대응할 수 있는지 확인

응답시간테스트: 페이지 로드 시간, API 응답시간 등을 테스트하여 성능이 기준을 충족하는지 확인

 - 보안 검증

취약점스캐닝: OWASP Top 10 같은 일반적인 보안 취약점(SQL 인젝션, xss 등)에 대한 자동화된 도구를 활용한 스캔

인증 및 권한 테스트: 사용자 권한 및 접근 제어가 올바르게 설정되어 있는지 확인

HTTPS 검증: 사이트가 HTTPS를 통해 안전하게 제공되고 있는지 확인

 - 환경설정 검증

배포할 환경(서버, 데이터베이스, 클라우드 서비스 등)이 올바르게 설정되어 있는지 확인

서버 자원(메모리, CPU) 및 설정 파일들이 제대로 구성되었는지 검증

 

[결과]

JAR은 JAVA애플리케이션이 동작할 수 있도록 자바프로젝트를 압축한 파일

WAR은 웹어플이 케이션 압축파일 포맷으로 웹 관련 자원만 포함하고 있으며 이를 사용하면 웹 애플리케이션을 쉽게 배포가능 WAR파일을 실행하려면 Tomca, Weblog, Websphere 등의 웹서버나 웹컨테이너가 필요하다

 

[느낀 점]

war, jar 업무 하면서 어디선가 보았던 파일들이었는데 이번 공부를 하면서 무슨 파일인지 알아보았다 

JAR이나 WAR파일로 압축한다는 개념이라면 압축을 풀 수도 있을지 찾아봐야겠다.

 

 

 

 

 

 

https://sharonprogress.tistory.com/225

 

Jar 파일과 War 파일이란? 차이점도!

웹 프로그래밍을 공부하면서 질리게 듣게 되는 파일 형식이다. JAR 파일과 WAR 파일은 둘 다 Java 기반의 애플리케이션을 패키징하기 위한 파일 포맷이다. 1. Jar(Java ARchive)파일 정의: JAR 파일은 여러

sharonprogress.tistory.com

https://ifuwanna.tistory.com/224

 

[Java] JAR WAR 차이점 및 특징 ( + EAR )

JAR (Java Archive) WAR (Web Application Archive) 모두 JAVA의 jar 툴을 이용하여 생성된 압축(아카이브) 파일이며 어플리케이션을 쉽게 배포하고 동작시킬 수 있도록 있도록 관련 파일(리소스, 속성파일 등)들

ifuwanna.tistory.com

 

https://wildeveloperetrain.tistory.com/372

 

서블릿과 서블릿 컨테이너 이해하기(Servlet, ServletContainer)

서블릿과 서블릿 컨테이너 이해하기(Servlet, ServletContainer)서블릿(Servlet)과 서블릿 컨테이너(ServletContainer)는 자바 기반 웹 애플리케이션을 개발하는데 기본이 되고 또 자주 만나게 되는 개념입니

wildeveloperetrain.tistory.com

 

 

 

 

java는 다양한 버전이 존재한다 그중 많이 쓰이는 버전은 java 8, 11, 17이 세 가지 버전이 많이 쓰이는 이유는 LTS(Long Term Support) 버전으로 LTS버전이란 장기간 보안업데이트와 버그 수정을 지원해 주는 버전이다.

 

JET BRAINS에 웹페이지에서 2021년도 2022년도 사용 통계를 확인

 


 

1. java8

  • 오라클이 자바 인수 후 출시한 첫 번째 LTS 버전
  • 32bit를 지원하는 마지막 공식 Java 버전
  • Oracle JDK(Oracle사에서 지원하는 버전으로 유료) , Open JDK(오픈소스 기반의 무료)로 나뉨
  • 새로운 날짜와 시간 API(LocalDateTime 등)
  • 람다식(Lambda), Stream API
  • PermGen 영역 삭제
  • Static Link JNI Library

 

람다식(Lambda)

함수를 간단한 식으로 표현하는 방법이다. 메서드 이름과 반환값이 생략되서 익명함수(anonymous function)이라고도 불림

int max(int a, int b) {
    return a > b ? a : b;
}

//람다식으로 변환
(a, b) -> a > b ? a : b;

 

Stream API

컬렉션의 저장 요소를 하나씩 순회하면서 처리할 수 있는 코드패턴으로 람다식을 지원하고 내부 반복자를 사용하기 때문에 병렬 처리가 쉽다는 특징이 있음

List<String> lowercase = Arrays.asList("a", "b", "c", "d", "e");
lowercase.stream()
        .map(String::toUpperCase)
        .forEach(System.out::println);

 

interface default method

java 8 이전의 인터페이스는 메서드 정의만 할 수 있고 구현 할 수  없었지만 8 버전부터는 default method라는 개념이 생기면서 구현 내용도 인터페이스에 포함시킬 수 있게

public interface TestInterface {
    void doSomething();
    default void doSomethingDefault() {
        System.out.println("doing something default");
    }
}

//implements the interface
public class TestClass implements TestInterface {
    @Override
    public void doSomething() {
        System.out.println("doing something");
    }
}

TestClass testClass = new TestClass();
testClass.doSomething();          // Output: "doing something"
testClass.doSomethingDefault();   // Output: "doing something default"

 

optional class

optional<T>는 nul이 올 수 있는 값을 감싸는 Wrapper 클래스로 참조하더라도 NPE(Null Pointer Exception)가 발생ㅈ하지 않도록 도와주는 역할을 한다 따라서 예상치 못한 NPE(Null Pointer Exception)이 발생될 상황에서도 예시와 같이 제공되는 메서드를 통해 간단히 예외 처리 가능

//create an optional that contains a value
Optional<String> optional = Optional.of("Hello, world!");
//check if a value is present
if (optional.isPresent()) {
	String value = optional.get();
	System.out.println(value);    // Output: "Hello, world!"
}
		
//create an empty optional
Optional<String> emptyOptional = Optional.empty();
//get a default value if the optional is empty
String value = emptyOptional.orElse("default value");
System.out.println(value);    // Output: "default value"
		
//throw exception
emptyOptional.orElseThrow(() -> new RuntimeException("throw Exception"));

 

2. java 11

  • Oracle JDK와 Open JDK 통합되고 Oracle JDK가 구독형 유료 모델로 전환
  • 람다 지역 변수 사용 방법 변경
  • Third Party JDK로의 이전 필요
  • HTTP 클라이언트 표준화 기능
  • 앱실론 가비지 컬렉터 (Epsilon GC)

 

람다 지역변수 사용 방법 변경

var 키워드는 java 10에서 추가 var 키워드를 사용하는 경우 데이터 유형을 지정하지 않고 변수를 선언하고 정의할 수 있으며 컴파일러는 할당된 데이터 유형에 따라 데[이터 유형을 결정하게 

(var s1, var s2) -> s1 + s2

 

HTTP Client

11 버전에서 도입된 Java HttpClient API는 최신 HTTP 표준의 클라이언트를 구현하고 동기 및 비동기 프로그래밍 모델인 HTTP/1.1 및 HTTP/2를 지원한다

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://test-api.com/posts"))
        .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

 

3. java 17

  • 봉인 클래스(Seald Class) 정식 추가
  • 패턴 매칭 프리뷰 단계
  • Incubator (Foreign Function & Memory API)
  • 애플 M1 및 이후 프로세서 탑재 제품군에 대한 정식 지원
  • 의사난수 생성기를 통해 예측하기 어려운 난수를 생성하는 API 추가
  • 컨텐츠 기반의 역직렬화 필터링
  • Record Data Class 추가
  • Spring Boot 3.0부터는 자바 17 이상을 지원 

 

Seald Class

17 버전에서 추가된 Seald Class, Interface는 상속하거나(extends), 구현(implements)할 클래스를 지정해 두고, 해당 클래스들만 상속 또는 구현을 허용하는 키워드
개발자는 seald 키워드를 통해 어떤 클래스가 해당 클래스를 상속 또는 구현하는지를 쉽게 알 수 있고, 또 제한할 수 있다.

public sealed class Shape permits Circle, Square {
    // common fields and methods
}

public final class Circle extends Shape {
    // circle-specific fields and methods
}

public final class Square extends Shape {
    // square-specific fields and methods
}

 

Record Data Class

Record 클래스는 불변 데이터를 객체 간에 전달하는 작업을 간단하게 만들어주며 record를 사용함으로 불필요한 코드를 제거할 수 있고 적은 코드로 명확한 의도(data carrier)를 표현할 수 있다.

//Lombok 사용 예시
@EqualsAndHashCode
@ToString
@AllArgsConstructor
@Getter
public class Person {
    private final String name;
    private final String address;
}

//record class 예시
public record Person (String name, String address) { }

 

텍스트 블록(Text Blocks)

멀티라인의 문자열을 이스케이프 시퀸스 없이 사용하여 소스코드 작성을 편리하게 하고 코드의 가독성을 높이는데 주된 목적을 지님

String html1 = "<html>\n" +
        "           <body>\n" +
        "               <p>Hello, world</p>\n" +
        "           </body>\n" +
        "       </html>\n";

// Text Blocks
String html2 = """
        <html>
            <body>
                <p>Hello, world</p>
            </body>
        </html>
        """;

 

 

[결과]

자바의 버전별 사용량을 보았을 때 LTS 버전을 주로 사용하고 Spring Boot 3.0부터는 java17 이상을 지원하여 많은 사용자가 java17로 이전

 

[느낀 점]

자바는 하위호환성이 매우 높아서 상위버전에서 하위버전의 기능을 컴파일이 가능하다 java8에서 공부를 하고 상위 버전에 추가된 기능을 공부하는 것이 좋을 것 같다

 

 

 

 

 

참조 사이트

https://wildeveloperetrain.tistory.com/287

 

Java 8, 11, 17 버전별 추가된 기능 (+ 무슨 버전을 써야할까?)

java 8, 11, 17 버전이 많이 사용되는 이유와 버전별 추가된 기능 최근 몇 년 동안 java에서 가장 많이 사용되는 버전은 'java 8'으로 저 역시 실무에서는 java 8만 계속 사용하고 있는데요. 자바는 2021년

wildeveloperetrain.tistory.com

https://code-lab1.tistory.com/253

 

[JAVA] JRE 와 JDK의 차이? Java 8, 11, 17 에 대하여

JRE, JDK란? 처음 Java를 설치하려고 보니 JRE, JDK 등이 존재하는 것을 확인할 수 있다. 둘의 차이는 무엇일까? 참고) [JAVA] 자바(JAVA)란? 자바의 특징 자바(JAVA)란? 자바는 C언어에 객체 지향적 기능을

code-lab1.tistory.com

 

멀티 스레드 환경에서 동시성 문제는 여러 스레드가 동시에 실행되면서 공유자원에 접근하거나 수정할 때 발생하는 문제 동시성 문제는 주로 데이터 불일치, 레이스 컨디션, 데드락 등의 형태로 나타난다.

 

이미지 출처:https://www.javatpoint.com/deadlock-in-java

 

 

 

 

동시성 문제의 유형

  1. 데이터 불일치: 여러 스레드가 동시에 데이터를 읽고 수정하면서 데이터의 일관성이 깨지는 현상.

  2. 레이스 컨디션: 여러 스레드가 경쟁적으로 자원에 접근하면서 발생하는 문제로, 예기치 않은 실행결과가 나올 수 있다.

  3. 데드락: 두 개 이상의 스레드가 서로가 가지고 있는 자원을 기다리면서 무한 대기상태에 빠지는 문제}

Thread-safe 
여러 스레드가 동시에 접근하거나 수정할 수 있는 코드나 객체가
데이터의 일관성과 안정성을 유지하도록 안전하게 설계된 것을 의미한다.

동시성 문제 해결 방법

1. 동기화( Synchronization)

공유자원에 대한 접근을 제어하여 데이터의 일관성을 유지하는 방법으로 Lock을 걸게 되면 스레드의 공유자원에 대한 독점을 허용하기 때문에 다른 스레드가 자원에 접근하지 못하고 대기하게 된다. 이는 여러 스레드가 공유자원에 동시에 접근하지 못하므로 동시성 문제를 막을 수 있지만, 하나의 스레드만 자원을 사용하므로 병렬성은 낮아지게 된다.

public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}

 

2. Lock 사용

    synchronized키워드를 사용하는 암시적 Lock과는 달리  Lock 객체를 사용하여 더 정교한 제어가 가능

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Counter {
    private int count = 0;
    private final Lock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

    public int getCount() {
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }
}

 

3. Atomic 변수 사용

    java.util.concurrent.atomic 패키지의 Atomic 클래스들을 사용하여 스레드 안전하게 값을 수정할 수 있다

Atomic 클래스들은 Compare and Swap(CAS) 기반으로 되어 있어 스레드에 안전하다. Compare and Swap(CAS)란 변수의 값을 변경하기 전에 기존의 값이 내가 예상한 값인지 확인하여 같은 경우에만 값을 할당하는 알고리즘 기법이다. (값을 할당하기 전 한 번 더 검사함) 

import java.util.concurrent.atomic.AtomicInteger;

public class Counter {
    private AtomicInteger count = new AtomicInteger(0);

    public void increment() {
        count.incrementAndGet();
    }

    public int getCount() {
        return count.get();
    }
}

 

4. Concurrent Collections 사용

    java.util.concurrent 패키지는 동시성 문제를 해결하기 위한 다양한 클래스와 인터페이스를 제공한다. ConcurrentHashMap, CopyOnWriteArrayList 등의 클래스들이 있

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentMapExample {
    private ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

    public void put(String key, Integer value) {
        map.put(key, value);
    }

    public Integer get(String key) {
        return map.get(key);
    }
}

 

5. 데드락 방지

    잠금 순서를 정해 데드락을 예방하거나, 타임아웃을 설정하여 데드락에 빠지지 않도록 할 수 있다.

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.TimeUnit;

public class DeadlockExample {
    private final Lock lock1 = new ReentrantLock();
    private final Lock lock2 = new ReentrantLock();

    public void method1() {
        try {
            if(lock1.tryLock(10, TimeUnit.SECONDS)) {
                try {
                    if(lock2.tryLock(10, TimeUnit.SECONDS)) {
                        try {
                            // Critical section
                        } finally {
                            lock2.unlock();
                        }
                    }
                } finally {
                    lock1.unlock();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void method2() {
        try {
            if(lock2.tryLock(10, TimeUnit.SECONDS)) {
                try {
                    if(lock1.tryLock(10, TimeUnit.SECONDS)) {
                        try {
                            // Critical section
                        } finally {
                            lock1.unlock();
                        }
                    }
                } finally {
                    lock2.unlock();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

[결과]

동시성 문제는 주로 데이터 불일치, 레이스 컨디션, 데드락 등의 형태로 나타나고 멀티스레드 환경에서 동시성 문제를 해결하기 위해서는 주로 동기화, Lock 객체, Atomic 변수, Concurrent Collections 등을 사용한다.

 

[느낀 점]

불변객체를 사용하여 동시성 문제를 해결할 수도 있지만 객체를 생성하는 비용이 굉장히 크기 때문에 성능상 문제가 발생할 수 있므로 내용을 제외하였다.

 

 

 

참조 사이트

https://everydayyy.tistory.com/154

 

[Java] 멀티스레드 환경에서의 동시성 문제와 대책

스레드란? 프로세스는 실행중인 프로그램이란 뜻이다. 프로그램이 실제로 실행되어, 메모리나 CPU와 같은 자원을 할당 받으면 이를 프로세스라고 부른다. 스레드는 프로세스 내에서 실제로 작업

everydayyy.tistory.com

 

https://yeoonjae.tistory.com/entry/Java-%EB%A9%80%ED%8B%B0%EC%93%B0%EB%A0%88%EB%93%9C-%EB%8F%99%EA%B8%B0%ED%99%94-synchronized

 

[Java] 멀티쓰레드 동기화 - synchronized

쓰레드의 동기화 씽글쓰레드의 경우에는 하나의 프로세스 내에서 하나의 쓰레드만 작업하기 때문에 프로세스의 자원에 대한 문제가 딱히 없다. 하지만 멀티쓰레드의 경우 여러개의 쓰레드가

yeoonjae.tistory.com

 

이미지 출처:https://medium.com/@wassimdhokkar/difference-between-process-and-thread-90f6c5a5919b

 

프로세스(process)

운영체제로부터 자원을 할당받은 작업의 단위이다. 기본적으로 프로세스당 최소1개의 스레드(메인스레드)를 가지고 있다.

 

주요 특징

  • 독립된 메모리 공간: 각 프로세스는 고유한 주소 공간을 가지고 있어 다른 프로세스와 메모리 공간을 공유하지 않음
  • 자원 소유: 프로세스는 CPU시간, 메모리, 파일핸들 등과 같은 자원을 소유한다
  • 고립성: 한 프로세스의 실패는 다른 프로세스에 영향을 미치지 않는다.
  • 운영체제의 관리: 운영체제는 프로세스의 생성, 실행, 대기, 종료 등을 관리한다.

 

스레드(Thread)

스레드는 프로세스 내에서 실행되는 더 작은 실행 단위.한 프로세스는 여러 스레드를 가질 수 있으며, 이 스레드들은

프로세스의 자원을 공유한다.

 

주요 특징

  • 공유 메모리 공간: 동일한 프로세스 내의 스레드들은 메모리 공간을 공유한다. 이를 통하여 스레드 간의 데이터 공유가빠르고 효율적
  • 독립된 실행 흐름: 각 스레드는 독립적으로 실행흐름을 가지고 있다. 한 스레드가 차단되거나 대기 상태에 있어도 다른스레드는 계속 실행될 수 있다.
  • 경량성: 스레드는 프로세스 보다 생성과 종료에 필요한 자원이 적다.
  • 동기화 문제: 여러 스레드가 동일한 자원에 접근할 수 있으므로 동기화 문제가 발생할 수 있다. 이를 해결하기 위하여뮤텍스, 세마포어 같은 동기화 기법이 사용된다.

 

특징

특징 프로세스 스레드
메모리 공간 독립석인 주소 공간 같은 프로세스 내에서 메모리 공간을 공유
실행단위 독립적인 실행단위 프로세스 내의 독립적인 실행단위
자원 소유 CPU시간, 메모리 등 고유 자원 소유 프로세스의 자원을 공유
생성 및 종료 비용 상대적으로 큼 상대적으로 작음
상호통신 ICP(Inter-Process Communication)필요 메모리 공유를 통해 빠르게 통신가능
독립성 한 프로세스의 실패가 다른 프로세스에 영향없음 한 스레드의 실패가 프로세스의 다른 스레드에 영향

 

멀티프로세스(Multiprocessing)

멀티프로세싱은 여러개의 프로세스를 사용하여 동시에 여러 작업을 수행하는 방식.

 

특징

  • 독립된 메모리 공간: 각 프로세스는 독립된 메모리 공간을 가지며, 다른 프로세스와 메모리 공유하지 않음
  • 높은 안정성: 한 프로세스의 오류가 다른 프로세스에 영향을 미치지 않는다.

장점

  • 안정성: 프로세스 간의 독립성으로 인해 한 프로세스의 오류가 전체 시스템에 영향을 미치지 않는다.
  • 간단한 디버깅: 프로세스가 독립적이므로 디버깅이 비교적 간단하다.

단점

  • 높은 오버헤드: 프로세스 간의 전환이 느리고 더 많은 메모리와 시스템 자원을 소비한다.
  • 복잡한 통신: 프로세스 간 통신이 복잡하고 이를 위해 IPC메커니즘이 필요하다

 

멀티스레드(Multithreading)

멀티스레딩은 하나의 프로세스 내에서 여러 스레드를 사용하여 동시에 여러 작업을 수행하는 방식

 

특징 

  • 공유 메모리: 같은 프로세스 내에서 실행되는 여러 스레드는 메모리와 자원을 공유
  • 효율적인 자원사용: 메모리 및 시스템 자원을 효율적으로 사용한다.

장점

  • 높은 성능: 스레드 간의 통신이 빠르고 효율적이다.
  • 낮은 오버헤드: 스레드 간 전환이 빠르고 자원소모가 적다.
  • 자원 공유: 데이터 공유가 쉽고 효율적이다.

단점

  • 동기화 문제: 자원 공유로 인한 동기화 문제가 발생할 수 있으며, 이를 해결하기 위하여 추가적인 동기화 기법이 필요
  • 안정성: 하나의 스레드 오규가 전체 프로세스에 영향을 미칠 수 있다.

 

 

[결과]

프로세스는 운영체제로부터 자원을 할당받은 작업의 단위이다. 각 프로세스는 고유한 메모리 공간과 자원을 가지고 있다.

스레드는 프로세스 내에서 실행되는 더 작은 단위이다 같은 프로세스 내의 다른 스레드와 메모리 공간을 공유한다.

 

 

[느낀 점]

프로그램은 명령어들의 집합이고 프로세스는 실행 중인 프로그램이다. 프로그램이 메모리에 올라가고 CPU 자원을 할당받은 상태

 

참조사이트

https://velog.io/@hyojhand/OS-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-vs-%EC%8A%A4%EB%A0%88%EB%93%9C

 

[OS] 프로세스 vs 스레드 (Process vs Thread)

프로세스는 각각 독립된 메모리영역 (Code, Data, Stack, Heap 의 구조)을 할당 받는다. 기본적으로 프로세스당 최소 1개의 스레드( 메인 스레드)를 가지고 있다.

velog.io

https://charlezz.medium.com/process%EC%99%80-thread-%EC%9D%B4%EC%95%BC%EA%B8%B0-5b96d0d43e37

 

Process와 Thread 이야기

프로세스(Process)

charlezz.medium.com

 

이미지 출처:https://www.javatpoint.com/exception-handling-in-java

 

 

예외처리

자바의 예외를 try-catch 블록으로 잡았다고 끝이 아니다. 예외가 발생하였으면 코드를 수정하여 문제점을 고쳐야 하는 것이 맞지만 예상할 수 없는 예외의 경우 회피를 하거나 복구 동작을 하는 등 예외를 핸들링하여 처리하는 로직이 필요하다. 예외를 처리하는 방법 예외 복구, 예외 처리 회피, 예외 전환 방법을 알아보자.

 

 

1. 예외복구

  • 예외 상황을 파악하고 문제를 해결해서 정상상태로 돌려놓는 방법
  • Exception이 발생하여도 어플리케이션은 정상적으로 동작
  • 반복문을 이용하여 예외가 발생하더라도 일정 수만큼 재시도를 하여 예외 복구를 시도
  • 만일 최대 재시도 횟수를 넘기게 되는 경우 예외를 발생시키거나 혹은 다른 플랜으로 문제 해결을 시도
  • 네트워크에 연결하거나 하는 등의 로직에서 유용하다.
public class ExceptionRecoveryExample {
    public static void main(String[] args) {
        try {
            int result = divide(10, 0);
            System.out.println("Result: " + result);
        } catch (ArithmeticException e) {
            System.out.println("Error: Division by zero. Trying with a default value.");
            int result = divide(10, 1); // Default recovery logic
            System.out.println("Recovered Result: " + result);
        }
    }

    public static int divide(int a, int b) {
        return a / b;
    }
}

 

2. 예외처리 회피

  • 예외처리를 직접 담당하지 않고 호출한 쪽으로 던져 회피하는 방법(throws)
  • 다만 그렇게 추천되어지는 방법은 아니다.
  • 호출한 쪽에서 예외를 처리하는 것이 바람직할 때 사용한다.
  • 해당 로직에서 예외가 발생했을 때 처리하지 않고 회피하는 것이 최선의 방법일 때만 사용한다.
public class ExceptionPropagationExample {
    public static void main(String[] args) {
        try {
            int result = divide(10, 0);
            System.out.println("Result: " + result);
        } catch (ArithmeticException e) {
            System.out.println("Error: " + e.getMessage());
        }
    }

    public static int divide(int a, int b) throws ArithmeticException {
        if (b == 0) {
            throw new ArithmeticException("Division by zero");
        }
        return a / b;
    }
}

 

3. 예외전환

  • 위의 예외 처리 회피와 비슷하게 메서드 밖으로 예외를 던지지만, 그냥 무작정 던지지 않고 적절한 예외로 필터링해서 넘기는 방법이다.
  • 조금 더 명확안 의미로 전달되기 위해 적합한 의미를 가진 예외로 변경해서 throws 하는 것이라 보면 된다.
  • 이외에도 예외처리를 상위클래스로 단순하게 처리하기 위한 포장(wrap)하는 방법도 일컫는다.
public class ExceptionTranslationExample {
    public static void main(String[] args) {
        try {
            int result = divide(10, 0);
            System.out.println("Result: " + result);
        } catch (CustomException e) {
            System.out.println("Custom Error: " + e.getMessage());
        }
    }

    public static int divide(int a, int b) throws CustomException {
        try {
            return a / b;
        } catch (ArithmeticException e) {
            throw new CustomException("Custom Error: Division by zero occurred", e);
        }
    }
}

class CustomException extends Exception {
    public CustomException(String message, Throwable cause) {
        super(message, cause);
    }
}

 

 

 

 

[결과]

예외복구 방식은 예외 상황을 파악하고 문제를 해결해서 정상상태로 돌려놓는 방법으로 네트워크를 연결하는 방식에서 유용하다.

예외처리 회피방식은 예외처리를 직접담당하지 않고 호출한 쪽으로 던지는 방식으로 해당 로직에서 예외가 발생하였을 때 처리하지 않고 회피하는 것이 최선일 때 사용한다.

예외전환 방식은 예외처리 방식과 비슷하나 메서드 밖으로 예외를 던지지만 적절한 예외로 필터링하여 넘기는 방식이다.

 

[느낀 점]

예외처리방식의 3가지 방식에 대해 알아보았다 프로그램 실행 시 발생할 수 있는 예기치 못한 예외의 발생에 대비한 코드를 작성하는 것으로 프로그래밍의 코드작성에 중요하고 많이 쓰일 것으로 보인다

 

 

 

 

 

 

https://inpa.tistory.com/entry/JAVA-%E2%98%95-Exception-Handling-%EC%98%88%EC%99%B8%EB%A5%BC-%EC%B2%98%EB%A6%AC%ED%95%98%EB%8A%94-3%EA%B0%80%EC%A7%80-%EA%B8%B0%EB%B2%95

 

☕ Exception Handling - 자바 예외를 처리하는 3가지 기법

Exception Handling 3가지 기법 자바의 예외를 try - catch 블럭으로 잡았다고 해서 끝이 아니다. 예외가 발생하였으면 코드를 수정하여 문제점을 고쳐야 되는 것은 맞지만, 예상할 수 없는 예외인 경우

inpa.tistory.com

 

이미지 출처:https://www.itrelease.com/2011/05/difference-between-static-final-and-abstract-class-in-java/

 

추상화란?

java에서의 추상화는 클래스들의 중요하고 공통된 성질들을 추출하여 부모 클래스를 선정하는 개념이다.

java 클래스를 작성하기 위한 설계도를 소스코드 형태로 제시하는 역할을 한다.

 

 

추상 클래스(Abstract Class)

class 앞에 abstract 키워드를 사용하여 정의하며, 하나 이상의 추상 메서드를  가지는 클래스를 말한다. 추상 메서드를 선언하여 상속을 통해서 하위 클래스에서 (반드시) 구현하도록 강제하는 클래스 

  • 추상 클래스는 인스턴스, 즉 객체를 만들 수 없는 클래스(new 키워드로 객체 생성불가)
  • 추상 클래스는 상속키워드 extends를 사용한다.(일반 클래스 상속과 동일)
  • 추상 메서드는(추상 클래스를 상속 받는) 하위 클래스에서 메소드의 구현을 강제해야한다(Override)
  • 추상 메서드를 포함하는 클래스는 반드시 추상 클래스여야 한다.
  • 다중 상속이 불가능하다. 

 

인터페이스(Interface)

interface 키워드를 사용하여 정의하며, 오직 추상 메서드와 상수(static final)만을 가지고 있는 것을 인터페이스라고 한다. 추상클래스와 마찬가지로 인터페이스 또한 인터페이스 선언되어있는 추상 메서드를 implements 하는 클래스에서(반드시)구현하도록 강제한다.

  • 인터페이스의 모든 맴버 변수는 public static final이어야 하며, 이를 생략가능하다.
  • 인터페이스의 모든 메서드는 public abstract이어야 하며, 이를 생략가능하다.
  • java8 부터는 static, default method를 사용할 수 있다.
  • 인터페이스는 상속 키워드로 implements를 사용한다.
  • 다중상속이 가능하다.
구분 추상 클래스 인터페이스
공통점 객체 생성 객체를 생성(인스턴스)할 수 없다.
추상 메서드 추상 메서드를 포함한다.
기능적 목적 상속받는 클래스에서는 추상 메서드를 반드시 재정의하여 구현해야 한다.
차이점 개념적 목적 상속받아서 기능을 확장시키는 목적 구현 객체의 동일한 실행 기능 보장하기 위한 목적
클래스 클래스. 클래스가 아니다
일반 메서드 일반 메서드 정의가 가능 일반 메서드 정의 불가등(java8 이후 staic, default 메서드 정의가능)
맴버 변수 클래스와 동일하게 변수 선언 및 사용
가능
상수만 사용 가능
*상수(변하지않고 고정된  값)
상속 키워드 extends implements
다중 상속 불가능 가능

 

인터페이스와 코드응집도

  1. 높은 응집도를 유지: 인터페이스는 클래스가 특정 기능에 집중하도록 도와줍니다. 클래스는 인터페이스에서 정의한 메서드들만 구현하면 되므로, 각 클래스는 특정 역할에 집중할 수 있습니다. 이는 클래스 내부의 메서드들이 긴밀하게 관련되어있음을 보장하여 높은 응집도를 유지하게 합니다.
  2. 단일 책임의 원칙: 인터페이스는 단일 책임원칙(Single Responsibility Principle)을 준수하도록 유도합니다. 하나의 인터페이스는 한 가지 역할만 정의하도록 설계되어야 하며, 이를 구현하는 클래스 역시 한 가지 역할에 집중할 수 있습니다.
  3. 유지보수성의 향상: 인터페이스를 사용하여 클래스 간 결합도를 낮추면, 코드 변경 시 영향을 받는 범위가 줄어듭니다. 이는 각 모듈이 독립적으로 동작하게 하여 높은 응집도를 유지하는 데 기여합니다.
  4. 테스트의 용이성: 인터페이스를 통하여 의존성을 주입하면, 테스티 시 Mock 객체 등을 활용하여 각 모듈을 독립적으로 테스트할 수 있습니다. 이는 코드의 응집도를 높이고, 각 모듈의 역할을 명확하게 구분하는 데 도움을 줍니다.

 

인터페이스 예제

// AnimalActions.java
public interface AnimalActions {
    void eat();
    void sleep();
    void makeSound();
}

 

추상클래스 예제

// Animal.java
public abstract class Animal {
    protected String name;
    protected int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void describe() {
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
    }

    // 추상 메서드: 서브클래스에서 구현해야 함
    public abstract void move();
}

 

추상클래스와 인터페이스를 구현하는 예제

// Dog.java
public class Dog extends Animal implements AnimalActions {
    public Dog(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println(name + " is eating dog food.");
    }

    @Override
    public void sleep() {
        System.out.println(name + " is sleeping in a dog bed.");
    }

    @Override
    public void makeSound() {
        System.out.println(name + " says: Woof!");
    }

    @Override
    public void move() {
        System.out.println(name + " is running.");
    }
}

// Cat.java
public class Cat extends Animal implements AnimalActions {
    public Cat(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println(name + " is eating cat food.");
    }

    @Override
    public void sleep() {
        System.out.println(name + " is sleeping in a cozy spot.");
    }

    @Override
    public void makeSound() {
        System.out.println(name + " says: Meow!");
    }

    @Override
    public void move() {
        System.out.println(name + " is jumping.");
    }
}

 

메인클래스 예제

// Main.java
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("Buddy", 3);
        Cat cat = new Cat("Whiskers", 2);

        System.out.println("Dog:");
        dog.describe();
        dog.eat();
        dog.sleep();
        dog.makeSound();
        dog.move();

        System.out.println("\nCat:");
        cat.describe();
        cat.eat();
        cat.sleep();
        cat.makeSound();
        cat.move();
    }
}

 

 

[결과]

추상클래스, 인터페이스 둘다 추상 메서드라는 공통점을 가지고 있으며 독립적으로 객체를 생성할 수 없다는 공통점을 지니고있고 여러곳에 사용될 공통된 기능에 대한 강제구현을 하기위한 기능이 있다. 

인터페이스는 높은 응집도를 유지, 단일책임의 원칙, 유지보수성의 향상, 테스트의 용이성을 가지고 있다.

 

[느낀점]

추상 클래스와 인터페이스 비슷한 모습을 가진 부분에 대하여 공부하였다 시간 날때마다 한번씩 더 봐야할 것 같다.

 

 

 

 

 

 

https://hahahoho5915.tistory.com/70#%EB%-B%A-%EC%A-%--%--%EC%--%--%EC%--%-D%-F

 

 

 

+ Recent posts