어제 팀원들이랑 대화하다가 새벽 3시쯤 잠들어서 파워냅 30분했는데 코딩하는 꿈을 꿨습니다...😱  하루종일 코딩만 생각하니 이런 꿈도 꿉니다. 오늘은 주특기 2주차 시작일로 Spring 숙련주차입니다. 강의가 새로 지급되었고 개인과제와 팀과제가 새로 나왔습니다. 다들 월드컵 보러 갈 때 치킨으로 만족하고 강의 듣습니다.🍗🍗🍗

 

zep

JPA 심화

  • JPA는 자동으로 Id값을 찾아주지만 (@GeneratedValue 사용) Query는 Select를 사용해 최대값을 넣어서 찾아서 마지막 id값+1해서 넣어줘야 한다
  • JPA를 사용하면 query보다 간단함 
  • Spring Data JPA 사용

 

영속성 컨텍스트 Persistence context

  • 엔티티를 영구 저장 하는 환경
  • 어플리케이션이 데이터베이스에서 꺼내온 데이터 객체를 보관하는 역할
  • 영속성 컨텍스트는 엔티티 매니저를 통해 엔티티를 조회하거나 저장할때 엔티티를 보관하고 관리함

 

1. find(”memberB”)와 같은 로직이 있을 때 먼저 1차 캐시를 조회

2. 있으면 해당 데이터를 반환

3. 없으면 그 때 실제 DB로 “SELECT * FROM….” 의 쿼리를 보냄

4. 반환하기 전에 1차캐시에 저장하고 반환

 

 

=> MemberA, MemberB를 생성할 때 마다 DB를 다녀오는건 비효율적

 

해결책 =>“쓰기 지연 SQL 저장소” Transactional write-behind

 

1. memberA, memberB를 영속화

2. entityManager.commit() 메서드를 호출

3. 내부적으로 쓰기 지연 SQL 저장소에서 Flush가 발생 -> 임의로 시점 지정 가능

4. “INSERT A”, “INSERT B”와 같은 쓰기 전용 쿼리들이 DB로 전달

 

 

@Enumerated

  • 속성으로는 Ordinal, String이 있음
  • String인경우 해당 문자열 그대로 저장해서 비용은 많이 들지만, 나중에 Enum이 변경되어도 위험할일이 없기 때문에 일반적으로는 String을 사용합니다.
  • Enum은 데이터 순서대로 값을 매기기 때문에 변경되거나 삭제시 오류가 발생할 수 있음
    • 값이 변경되어도 위험할 일이 없기 때문에 대부분 String을 사용

 

 

 

아래와 같이 오류가 뜬다면 사용중인 포트를 터미널로 찾아서 kill 할 수 잇습니다.

Web server failed to start. Port 8080 was already in use.

Action:

Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.


Process finished with exit code 1

web server failed to start. Port 8080 was already in use

사용중인 포트 찾아서 kill 하는 법

1. 터미널에 들어가서 kill을 원하는 포트를 다음 코드를 입력해서 찾습니다.

ex) port 8080

lsof -i: 8080

숫자부분에 원하는 포트 번호를 입력하시면 됩니다.

 

아래와 같이 포트 정보가 출력됩니다.

 

2. 사용중인 포트 kill 하기

kill -9

또는 

kill PID숫자 를 입력하여 사용중인 포트를 kill 합니다.

위의 예시의 PID 숫자 55149를 아래와 같이 입력하였습니다

kill 55149

 

다시 코드를 실행하면 port가 잘 돌아가는 것을 확인할 수 있습니다.

 

 

벌써 12월이 되었습니다. 한달이 훌쩍 지나갔네요. 정식으로 부트캠프는 99일이라고 홍보가 되어있지만 사전 스터디 기간까지 합친다면 거진 2달의 기간이 지나갔습니다. 11월에는 자바가 무엇인지 객체지향 프로그램이 무엇인지 처음 배우는 시간이었습니다. 그동한 배우고 구현 해본 것들을 나열하자만 아래와 같습니다.

 

  • JWT를 이용해서 Flask python 회원가입, 로그인 기능 구현
  • 자바의 정석 유튜브 동영상 강의 ch 1 ~ 7
  • 프로그래머스 문제 풀이 30개
  • 혼자공부하는 자바 ch 1 ~ 7
  • 깃과 깃허브 사용해서 협업
  • 1주차 미니프로젝트 완성
  • 2주차 알고리즘 test
  • 3주차 Spring 주특기 1주차 강의
  • 객체지향 프로그래밍 과제
  • 게시판 구현 (CRUD 기능 구현: 등록, 조회, 수정, 삭제)
  • Postman 사용
  • JPA 기초
  • HTTP method (PUT, POST, DELETE 등)
  • API 명세서 작성
  • API 만들기

생각보다 한 게 많지만 없습니다.

개발자가 되기 위한 단계로 보면 이제 튜토리얼의 튜토리얼을 뗀 수준입니다. 

프로그래머의 삶

자바도 그렇고 이제 갓 배우기 시작해서 뭐든 다 새롭고 매일 엄청난 양의 새로운 정보를 습득하다 보니 혼란할 때도 많습니다. 어제 튜터님께 자바 공부를 하고 있다고 말씀드리니까 자바 백엔드 개발자 공부 로드맵을 이야기 해주셨습니다. 

 

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

 

자바 백엔드 공부 로드맵

자바 공부 로드맵

1. 자바의 정석

- 남궁성 자바의 정석 유튜브 보면서 다 따라치면서 연습하기

- 객체지향 부분은 스스로 예제 만들면서 익히기

 

2. 모던 자바인 액션

- 자바 8, 9, 10 버전을 예시와 함께 설명하는 책

 

3. 컴파일러 만들기

- 컴파일러 만들어보기

책입니다 --> 책정보 링크 클릭

 

4. 클린 코드, 이펙티브 자바

클린코드 책 구매 링크

이펙티브 자바 책 구매 링크

 

고급 개발자가 되기 위해서 읽자.

 

Gof의 디자인 패턴

(클린 코드 다음에 읽을 책)

 

schema 설계

DB 설계 중요

 

컴퓨터 공학 Network

1. MIT 유튜브 강의

2. 네트워크 공부하기

 

Spring 공부

1. 토비의 스프링 3.1 

- 좀 두꺼운 편이니까 아래 책을 먼저 읽는 것도 추천

 

2. 자바 웹프로그래밍 Next step

- 토비의 스프링보다 얇은 편

 

3. 김영한 강의도 추천

 

알고리즘 코딩 테스트 공부

하루에 1문제 풀기.

lv 순으로 풀기 보다는 bfs, dfs (최단시간) 문제 등 유형별로 풀어보기

 


12월의 목표는....

  • 자바에 대해 어느정도 익숙해지는 것
    • 자바의 정석 남궁성 유튜브 강의 완강
    • 혼자공부하는자바 완독
  • 아무것도 안보고 CRUD 혼자 구현해 보는 것
    • 이건 이번 주말에 할 겁니다
  • Spring 김영한 입문 강의 완강
    • 28개 강의
  • 알고리즘 공부
    • 2일에 한 문제씩 풀기

입니다.

 

2월 17일이 항해99 부트캠프가 끝나니까요. 그때는 얼마나 성장해 있을지 기대가 됩니다.

 

나는 2023년 1분기 이내 취직한다.

 

 

 

 

팀과제가 다 처음 배우는 것이라 Today I learned 입니다.

Spring TIL

JPA란

‘Java Persistence API’로 자바 ORM(Object Relational Mapping: 객체 관계 매핑)기술로 다음과 같은 기능을 함:

  • 쿼리 자동 생성
  • 어플리케이션 계층에서 spl 의존성을 낮춰 작업 효율성 상승
  • 패러다임 불일치 해결
  • 다양한 방언(h2 Database, mySQL, oracle 등) 지원

JPA 사용을 위해서는 Hibernate, EclipseLink 같은 ORM 프레임워크를 사용해아함.

스프링 부트에서는 Hibernate 사용

ORM(객체 관계 매핑)이란?

객체와 DB의 테이블이 매핑을 이루는 것으로 query를 직접 작성하지 않고 메서드 호출로 데이터 조회가 가능함 → 생산성 향상

스프링에서 JPA를 사용할 때 에상 가능하고 반복적인 코드들을 Spring Data JPA가 작성해줌 →JpaRepository 선언

책추천 (추천글/지은이의말 만 읽어도 도움됩니다)

 

restAPI의 put 과 patch 는 어떤 차이점이 있을까요? 어떤 경우에 사용하면 좋을까요?

Http Method 중 자원(엔티티)을 수정하는 용도 1)PUT

  • 전체 수정(자원 전체 교체) => 자원이 있다면 수정, 없다면 생성
  • 수정 시 모든 필드 필요
  • 자원 전체를 교체하는 것이기에, Client는 해당 자원 상태를 모두 알고 있다고 가정되어야 함 즉, Payload만으로 자원 전체 상태를 표시할 수 있어야 함
  • 멱등성 가짐

2)PATCH

  • 부분 수정(자원 부분 교체)
  • 수정 시 수정할 필드만 필요
  • 별도의 DTO 필요
  • 멱등성 가질 수 도, 안 가질 수도 있음

 멱등성(idemoitent)

  • 연산을 여러번 적용해도, 결과가 달라지지 않는 성질
  • 연산을 여러번 반복해도, 한번만 수행된것과 같은 성질
    • 동일한 요청을 한번 보내는 것과 여러번 연속 보내는 것이 같은 효과를 가지고, 서버 상태도 동일할 때, HTTP Method가 멱등성을 가졌다고 말함
  • ex) f(f(x)) = f(x)

HTTP란?

HyperText Transfer Protocol로 프로토콜, 즉 인터넷 통신 데이터 교환의 기준이 되는 약속이다. Stateless(무상태성)와 Connectionless(비연결성)이 특징으로 요청(request)을 주고 받을 때만 연결이 유지되고 응답(response)하고 나서 서버와 연결을 끊는다.

HTTP 메소드

클라이언트가 웹 서버에 사용자 요청의 목적 또는 종류를 알리는 수단으로 GET, POST, PUT, PATCH, DELETE 가 주로 쓰임

구성요소

  • Method (호출/요청 방식)
    • GET: 이름 그대로 어떤 리소스를 얻을 때 사용; 브라우저의 주소창에 URL을 입력하면 GET 메서드를 사용해서 서버에 요청을 보냄
    • POST: 웹 서버에 데이터를 게시할 때 사용 (ex. 회원가입, 게시글 작성, 댓글 작성)
  • Header (추가 데이터. 메타 데이터)
    • 브라우저가 어떤 페이지를 원하는지
    • 요청 받은 페이지를 찾았는지
    • 요청 받은 데이터를 성공적으로 찾았는지
    • 어떤 형식으로 데이터를 보낼지
    다양한 의사 표현을 위한 데이터를 모두 Header 필드에 넣고 주고 받음
  • 위에서 설명 된 메서드도 헤더에 포함되어 서버로 보냄
  • Payload (데이터. 실제 데이터)
    • 서버가 응답을 보낼 때에는 항상 Payload 보내기 가능
    • 클라이언트(브라우저)가 요청을 할 때에도 Payload를 보낼 수 있음
    • "GET method를 제외하곤 모두 Payload를 보낼 수 있다" 는게 HTTP에서의 약속

참고자료

 

HTTP | MDN

하이퍼텍스트 전송 프로토콜(HTTP)_은 HTML과 같은 하이퍼미디어 문서를 전송하기위한 _애플리케이션 레이어 프로토콜입니다. 웹 브라우저와 웹 서버간의 커뮤니케이션을위해 디자인되었지만, 다

developer.mozilla.org

 

(DB에서)트랜잭션(Transaction)

  • 나눌 수 없는 업무 단위
  • SQL DML에는 select(조회). insert(생성), update(수정), delete(삭제)가 있다.
  • 이 중 insert, update, delete는 Table 안에 data를 변경시킬 수 있는데(생성, 수정, 삭제) insert, update, delete SQL문을 모두 작성한 후 최종 반영(commit)할지, 취소(rollback)할지 결정해야 한다.
  • 문서파일에 글을 저장하지 않고 작성하다가 마지막에 닫기(X) 버튼 클릭하면(윈도우 기준) [저장] 또는 [저장안함]이 뜨는데, [저장]하면 사용자가 작성한 내용들이 저장되고, [저장안함]을 선택하면 사용자가 작성한 자료가 반영되지 않는다.
    • 여기서 [저장]은 commit, [저장안함]은 rollback이다.
  • SQL에서 Transaction이 필요한 이유는, DML 중 insert, update, delete가 사용자들에게 영향을 줄 수 있기 때문이다
  • Transaction은 이러한 문제를 해결하기 위해 누군가 특정 data에 작업(insert, update, delete)하려고 한다면, 작업하고 있는 data를 잠금(lock)한다.
  • 이 작업이 끝날 때까지 다른 사용자들은 해당 data를 insert, update, delete하지 못하고, 작업중인 사용자가 최종 반영할지(commit), 취소할지(rollback) 결정되면, 그때 감금이 해제된다.

 

트랜잭션 특징

원자성(Atomicity) :

  • 트랜잭션 안의 작업들이 분리되어 작업 불가
  • 트랜잭션의 가장 큰 특성 (이게 안되면 무결성이 훼손)

독립성(Isolation) :

  • 진행 중인 트랜잭션들은 정보전달, 서로 알아보기 등등 없다.
  • 트랜잭션은 하나씩만 열 수 있다. 여러 개를 같이 못함(독립성) (외부와 정보교환 수행 불가, Lock)

일관성(Consistency) :

  • 트랜잭션 실행 후 DB의 무결성은 반드시 유지 되어야 함

영속성(Durability) :

  • 작업 종료된 트랜잭션의 결과는 반드시 DB에 반영되어야 함

 

 

 

  • 스프링에서 의존성 주입이란 무엇인가?
  • 외부에서 두 객체 간의 관계를 결정해주는 디자인 패턴이다. 인터페이스를 사이에 두고 클래스 레벨에서 의존관계가 고정되지 않도록 한 후에 런타입 시에 관계를 동적으로 주입하여 유연성을 높이고 결합도를 낮출 수 있게 하는 것을 의미한다.
  • 예시-문제점) 아래의 코드는 두가지의 문제를 가지고 있다.
       **문제점 1. 두 클래스의 결합도가 높음** 
    
    → 만약 다른 타이어를 사용하고자 할 때 Car() 클래스의 직접 수정이 필요하다.→ 구현클래스를 직접 수정해야한다.
  • 문제점 2. 객체들 사이의 관계가 아닌 클래스같의 관계가 맺어져 있다.
  • public class Car() { private Tire kumhoTire; public Car() { this.kumhoTire = new kumhoTire(); } }
  • 예시-DI수행) 그럼 스프링에서의 DI를 수행해보자.
  1. 먼저 Tire 인터페이스를 생성하고 그것을 구현하는 kumhoTire 구현 클래스를 만든다.
  2. public interface Tire { } public class kumhoTire implements Tire { }
  3. 그리고 Car의 생성자를 만들고 인자값으로 Tire 객체를 받도록 만든다. 이렇게 함으로써 Car에서 kumhoTire 구체 클래스의 의존성을 제거한다.
  4. public class Car { private Tire tire; private Car(Tire tire) { this.tire = tire; } }
  5. 스프링은 애플리케이션 실행 시점에서 필요한 객체(bean)을 DI 컨테이너에서 생성한다. 그리고 의존성이 있는 두 객체를 연결하기 위해 아래와 같이 한 객체를 다른 객체로 주입시킨다.
  6. public class BeanFactory { // Bean의 생성 Tire kumhoTire = new KumhoTire(); // 의존성 주입 Car car = new Car(kumhoTire); }
  • 이러한 개념은 동시에 **제어의 역전(Inversion of Control, IOC)**라고 불린다. 왜냐하면, 어떠한 객체를 사용할지에 대한 책임을 프레임워크에 넘겼기 때문이다. 동시에 자신은 수동적으로 주입받는 객체를 사용하기 때문이다.

스프링에서 IOC (Inversion Of Control)란?

IOC는 제어의 역전, 즉 제어의 흐름을 바꾸는 것이다.

Java 프로그램에서는 각 객체들이 프로그램의 흐름을 결정하고 객체를 직접 생성하여 메소드 호출하는 방식의 작업을 했다.

사용자가 모든 작업을 제어하는 구조이다. ( A객체에서 B 객체에 있는 메소드를 사용하고 싶을 때 B 객체를 직접 A 객체 내에서 생성하고 메소드를 호출)

IOC가 적용된 경우에는 객체의 생성을 특별한 관리 위임 주체에게 맡긴다.

즉, 사용자가 객체를 직접 생성하지 않고 객체의 생성 및 소멸과 같은 생명주기에 관한 제어권을 다른 주체에게 넘긴다.

  • 클래스 내부의 객체 생성 -> 의존성 객체의 메소드 호출이 아니라, 스프링에게 제어를 위임하여 스프링이 만든 객체를 주입 -> 의존성 객체의 메소드 호출 구조이다.
  • 모든 의존성 객체를 스프링이 실행될 때 만들어 주고 필요한 곳에 주입한다.

Spring이 모든 의존성 객체를 Spring이 실행 될 때 다 만들어 주고 필요한 곳에 주입 시켜줌으로써 Bean들은 싱글톤 패턴의 특징을 갖습니다.

  • Bean : Spring IOC 컨테이너가 관리하는 객체

참조 및 내용출처 : 블로그

 

[Spring] 의존성 주입(Dependency Injection, DI)이란? 및 Spring이 의존성 주입을 지원하는 이유

1. 의존성 주입(Dependency Injection)의 개념과 필요성 [ 의존성 주입(Dependency Injection) 이란? ] Spring 프레임워크는 3가지 핵심 프로그래밍 모델을 지원하고 있는데, 그 중 하나가 의존성 주입(Dependency Inj

mangkyu.tistory.com

 

Layered Architecture 란 ?

복잡한 애플리케이션을 여러 개의 계층으로 나누어 설계하고 개발하는 것 !

각 계층을 전문적으로 다룬다는 목적이 있다. 레이어드 아키텍쳐는 구성요소들이 수평적인 레이어로 조직화되어 있는 다층 구조이며, 모든 구성요소가 연결되어 있지만 독립적이라 말할 수 있다.

  • Presentation Layer

클라이언트로 응답을 다시 보내는 역할을 담당하는 모든 클래스가 포함된다.

  • Business Layer

시스템을 구현해야하는 로직들을 해당 레이어에서 구현하게 된다. 접근성 , 보안 , 인증 , 유효성 검사 와 같은 로직들이 해당 계층에서 발생한다.

  • Persistence Layer

데이터베이스에서 데이터를 저장, 수정, 읽는 등 데이터베이스와 관련된 로직을 구현한다. DAO(Data Access Object)presentation, ORM(Object Relational Mappings) 등을 포함한다.

  • Database Layer

데이터 베이스가 저장되는 레이어

특징

레이어드 아키텍쳐는 하위 계층에만 의존한다. 위 그림 계층 구조에서 비즈니스 레이어는 프레젠테이션 레이어로부터 독립적이고 , 퍼시스턴스 레이어에는 의존적이다. 그래서 하위계층의 변경에 있어서는 상위계층은 신경쓰지 않아도 되는 장점이 있다. 이 특징으로 각 계층의 역할들이 명확해지며, 개발과 테스트가 용이해진다.

 

Entity와 DTO란?

Entity

실제 DB 테이블과 매핑되는 핵심 클래스로, DB 테이블에 존재하는 컬럼들을 필드로 가지는 객체

DTO (Data Transfer Object)

계층간 데이터 교환이 이루어 질 수 있도록 하는 객체

 

Entity와 DTO를 분리하는 이유 ⇒ 관심사 분리!!

  • 관심사의 분리 : Entity와 DTO를 분리해야 하는 가장 근본적인 이유는 관심사가 서로 다르기 때문! (*관심사의 분리(separation of concerns, SoC)는 소프트웨어 분야의 오래된 원칙 중 하나로써, 서로 다른 관심사들을 분리하여 변경 가능성을 최소화하고, 유연하며 확장가능한 클린 아키텍처를 구축하도록 도와줌)
  • Entity의 값이 변하면 Repository 클래스의 Entity Manager의 flush가 호출될 때 DB에 값이 반영되고, 이는 다른 로직들에도 영향 미친다. View와 통신 하면서 필연적으로 데이터의 변경이 많은 DTO클래스를 분리해주어야 한다
  • 도메인 설계가 아무리 잘 되있다 해도 Getter만을 이용해서 원하는 데이터를 표시하기 어려운 경우가 발생할 수 있는데, 이 경우에 Entity와 DTO가 분리되어 있지 않다면 Entity안에 Presentation을 위한 필드나 로직이 추가되게 되어 객체 설계를 망가뜨리게 된다. 때문에 이런 경우에는 분리한 DTO에 Presentation로직 정도를 추가해서 사용하고, Entity에는 추가하지 않아서 도메인 모델링을 깨뜨리지 않는다.

 

Singleton Pattern이란?

  • 싱글톤 패턴이란 인스턴스를 1개로 제한하며 어디서든 접근 할 수 있도록하는 객체 생성 디자인 패턴이다. 싱글톤 클래스는 본인을 호출하는 static 메소드를 가지고 있으며, 이 메소드를 호출하면 본인을 반환하도록 설계된다.
  • 객체 지향 프로그래밍에서는 모든 객체들은 라이프 사이클(객체가 생성되고 GC에 의해 삭제되기 까지)을 가지고 있다. 객체를 여러개 만들지 않고 1개만 만들고 공유하고 싶을 때 사용할 수 있는 패턴이 싱글톤 패턴이다. (ex. DB의 Transaction을 관리하는 클래스)

Singleton Pattern의 문제점

  1. 싱글톤 패턴을 구현하는 코드 자체가 많이 들어간다.
  2. 의존 관계 클라이언트가 추상화 클래스에 의존하는 게 아니라 구체 클래스에 의존하게 되면서 객체 지향 설계 5원징인 SOILD 중 DLP(의존관계 역전 원칙)를 위한하고 OCP(개방-폐쇄 원칙)을 위반할 가능성이 높다.
  3. 내부 속성을 변경하고 초기화하는게 어렵고 private 생성자로 자식 클래스를 만들기가 어렵다.

Spring에서의 Singleton Pattern

  • 스프링에서는 클래스 자체에 의해서 객체를 생성하지 않고 스프링 컨테이너에 의해 구현이 된다.
  • 스프링 컨테이너는 싱글톤 패턴의 문제를 해결하면서 싱글톤 패턴을 적용하지 않아도 객체의 인스턴스를 싱글톤으로 관리한다.
  • 스프링의 싱글톤 레지스트리 - 싱글톤 패턴의 단점을 보완하기 위해 나온것 - 스프링 컨테이너가 싱글톤 컨테이너 역할을 하고 싱글톤 객체를 생성하고 관리하는 기능
    • 스프링 컨테이너 기능 덕분에 싱글톤 패턴의 단점을 해결하면서 싱글톤으로 유지할 수 있다.
  • 결국 스프링 Bean이 싱글톤으로 관리되는 Bean이다

 

Factory Method Pattern

  • 객체 생성 처리를 서브 클래스로 분리하여 처리하도록 하는 캡슐화 패턴이다. 즉, 객체의 생성 코드를 별도의 클레스/메소드로 분리함으로써 객체 생성의 변화에 대비하여 유용하게 사용할 수 있다.
  • Factory Method Pattern의 장단점
    • 장점
      1. 비슷한 성격의 객체를 인터페이스를 통해 하나로 관리할 수 있다. (코드가 간결해진다.)
      2. 비슷한 유형의 객체가 생성되어도 implement를 통해 쉽게 추가할 수 있다.
    • 단점
      • 제품 클래스가 바뀔 때 마다 새로운 서브 클래스를 작성해야 한다.
    • 클래스가 많아지기 때문에 클래스 계층도 커질 수 있다.

Factory Method Pattern의 구조

  1. Product는 인터페이스를 선언한다. 인터페이스는 생성자와 자식 클래스들이 생성할 수 있는 모든 객체에 공통이다.
  2. Concrete Prodect들은 제품 인터페이스의 다양한 구현들이다.
  3. Creator 클래스는 새로운 제품 객체들을 반환하는 Factory Method를 선언한다. 이 때 Factory Method의 반환 유형이 Product 인터페이스와 일치해야한다.
  4. ConcreteCreator들은 기초 Factory Method를 오버라이드(재정의)하여 다른 유형의 Product를 반환하게 하도록 한다.
  • Factory Method는 항상 새로운 인스턴스를 생성해야 할 필요가 없다. 기존 객체들을 캐시, 객체 풀 또는 다른 소스로부터 반환할 수 있다.

 

Proxy Pattern

  • 어떤 객체에 대한 접근을 제어하기 위한 용도로, 실제 객체의 메소드를 호출하면 그 호출을 중간에 가로채는 패턴이다.
  • 즉, 제어 흐름을 조정하기 위해 중간에 대리자를 두는 패턴
  • 스프링에서는 AOP를 통해서 이런 공통적인 기능들을 별도로 분리해 필요한 곳에서 재사용이 가능 
    • AOP(Aspect Oriented Programming)이란?
    • 관점 지향 프로그래밍 - 공통 기능과 핵심 기능을 분리시켜 공통 기능을 계속 재활용하여 사용하는 방식 (main기능이 아닌 기능(Logging/Transcation)을 묶음으로 하여 Main 기능을 잘 구성할 수 있게 해주는 방식)

Proxy Pattern의 구조

  1. Client가 해당 함수를 직접 호출하는 것이 아닌 Proxy를 호출한다.
  2. Proxy Class에서 실제 Class를 호출한다.( Proxy Class는 실제로 호출할 Class를 이미 가지고 있다.
  3. 실제 Class에서 반환 받은 값을 Client에게 반환한다.
  • Proxy Pattern의 장단점
    • 장점
      • 사이즈가 큰 객체가 로딩되기 전에도 proxy를 통해 참조를 할 수 있다.(이미지, 동영상 등의 로딩에서 반응성 혹은 성능 향상 - 가상 프록시)
      • 실제 객체의 public, protected 메소드들을 숨기고 인터페이스를 통해 노출시킬 수 있다.( 안정성 - 보호 프록시 )
      • 로컬에 있지 않고 떨어져 있는 객체를 사용할 수 있다. (RMI, EJB 의 분산처리 등 - 원격 프록시)
      • 원래 객체의 접근에 대해서 사전처리를 할 수 있다. (객체의 레퍼런스 카운트 처리 - 스마트 프록시 )
      • 원본 객체의 참조만 필요할 때는 원본 객체를 사용하다가, 최대한 늦게 복사가 필요한 시점에 원본 객체를 복사하여 사용한다. (Concurrent package의 CopyInWriteArrayList - 변형된 가상 프록시)
    • 단점
      • 객체를 생성할 때 한단계를 거치게 되므로, 빈번한 객체 생성이 필요한 경우 성능이 저하될 수있다.
      • 프록시 안에서 실제 객체 생성을 위해서 thread가 생성되고 동기화가 구현되야하는 경우 서능이 저하되고 로직이 난해해질 수 있다.

디폴트 메서드와 static 메서드

디폴트 메서드와 static 메서드

  • 인터페이스에 디폴트 메서드, static 메서드 추가 가능 (JDK1.8부터)
  • 인터페이스에 새로운 메서드(추상 메서드)를 추가하기 어려움
    • 해결책 => 디폴트 메서드(default method) (인터페이스 원칙 위반: 예외)

 

디폴트 메서드가 기존의 메서드와 충돌할 때 해결책

  • 여러 인터페이스와 디폴트 메서드 간의 충돌
    • 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩 해야함
  • 디폴트 메서드와 조상 클래스의 메서드 간의 충돌
    • 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시됨

인터페이스 interface

  • 추상 메서드의 집합
  • 구현된 것이 전혀 없는 설계도. 껍데기 (모든 멤버가 public)
  • 기본 설계도
  • 다른 클래스를 작성하는데 도움이 될 목적으로 작성
  • 추상클래스와 인터페이스의 차이
    • 추상클래스는 일부가 구현된 미완성 설계도
    • 인터페이스는 아무것도 구현된 것도 없고 밑그림만 그려져있는 기본 설계도
interface 인터페이스이름 {
	public static final 타입 상수이름 = 값; //상수
    public abstract 메서드이름(매개변수목록); //추상메서드
}

//인터페이스의 모든 메소드는 public이고 final이고 abstract 여서 생략 가능

 

인터페이스의 상속

  • 인터페이스의 조상은 인터페이스만 가능(Object가 최고 조상이 아님)
  • 다중 상속이 가능 (추상메서드는 충돌해도 문제 없음)
interface Fightable extends Movable, Attackable {}
interface Movable {
	/** 지정된 위치(x,y)로 이동하는 기능의 메서드 */
    void move(int x, int y);
 }
 
 interface Attackable {
 	/** 지정된 대상(u)을 공격하는 기능의 메서드 */
    void attack(Unit u);
}

 

인터페이스의 구현

  • 인터페이스에 정의된 추상 메서드를 완성하는 것
class 클래스이름 implements 인터페이스이름 {
        // 인터페이스에 정의된 추상메서드를 모두 구현해야 한다
}
  • 구현한다는 의미의 키워드 'implements'를 사용함
class Fighter implements Fightable {
	public void move(int x, int y) { /*내용 생략 */}
    public void attack(Unit u)     { /*내용 생략 */} // 몸통 완성
}

//Fighter 클래스는 Fightable 인터페이스를 구현했다.
  • 추상클래스 완성과 동일; 키워드만 다름
  • 일부만 구현하는 경우, 클래스 앞에 abstract를 붙어야 함

 

  • 인터페이스란?
    • 추상 메서드의 집합
  • 인터페이스의 구현이란?
    • 인터페이스의 추상메서드 몸통{} 만들기(미완성 설계도 완성하기)
  • 추상 클래스와 인터페이스의 공통점은?
    • 추상 메서드를 가지고 있다 (미완성 설계도)
  • 추상 클래스와 인터페이스의 차이점은?
    • 인터페이스는 iv를 가질 수 없다

 

 

인터페이스를 이용한 다형성

  • 인터페이스도 구현클래스의 부모
  • 인터페이스 타입 매개변수는 인터페이스 구현한 클래스의 객체만 가능
  • 인터페이스를 메서드를 리턴타입으로 지정할 수 있다
abstract class Unit2 {
    int x, y;
    abstract void move(int x, int y);
    void stop() {
        System.out.println("멈춥니다.");
    }
}

interface Fightable { //인터페이스의 모든 메서드는 public abstract. 예외 없이
    void move (int x, int y); // public abstract가 생략됨
    void attack(Fightable f); // public abstract가 생략됨
}

class Fighter extends Unit2 implements Fightable{
    //오버라이딩 규칙: 조상(public) 보다 접근제어자가 좁으면 안된다.
    public void move (int x, int y) {
        System.out.println("["+x+","+y+"]로 이동");
    }
    public void attack(Fightable f){
        System.out.println(f+"를 공격");
    }

}

public class FighterTest {
    public static void main(String[] args) {
//      Fighter f = new Fighter();
        Unit2 u = new Fighter(); //Unit2에는 attack()이 없어서 호출불가
        Fightable f = new Fighter();
        u.move(100, 200);
//        u.attack(new Fighter());  //Unit2에는 attack()이 없어서 호출불가
        u.stop();

        f.move(100, 200);
        f.attack(new Fighter());
//        f.stop();                 //Fightable에는 stop()이 없어서 호출불가

    }
}

 

인터페이스의 장점

  • 두 대상(객체) 간의 '연결, 대화, 소통'을 돕는 '중간 역할'을 한다
  • GUI - Graphic User Interface
  • 선언(설계, 껍데기)와 구현(알맹이)을 분리시킬수 있게 함
    • 변경에 유리하고 유연한 코드가 됨
    • 인터페이스 덕분에 B가 변경되어도 A는 안바꿀 수 있게 됨 -> 느슨한 결합
    • 의존도가 낮아짐
  • 개발 시간 단축 가능
  • 변경에 유리한 유연한 설계 가능
  • 표준화가 가능
  • 서로 관계없는 클래스들을 관계를 맺어줄 수 있음
  • 다중상속 가능
class A{
    public void method(I i) { //인터페이스 I를 구현한 넘들만 들어와라
        i.method();
    }
}


// B클래스의 선언과 구현을 분
interface I {
    public  void method();
}

class B implements I{
    public void method(){
        System.out.println("B클래스의 메서드");
    }
}

class C implements I{
    public void method(){
        System.out.println("C클래스의 메서드");
    }
}

public class InterfaceTest {
    public static void main(String[] args) {
        A a = new A();
        a.method(new C()); // A가 B를 사용(의존)

    }
}

자바의정석 남궁성

 

추상클래스 (abstract class)

- 미완성 설계도, 미완성 메서드를 갖고 있는 클래스

- 추상메서드는 몸통{}이 없는 미완성 메서드

- 다른 클래스 작성에 도움을 주기 위한 것 -> 인스턴스 생성 불가

abstract class Player{
        abstract void play(int pos);  //추상메서드 (몸통{} 이 없는 미완성 메서드)
        abstract void stop();     // 추상메서드
}

- 상속을 통해 추상 메서드를 완성해야 인스턴스 생성가능

class AudioPlayer extends Player{
         void play(int pose) { /*내용 생략*/}  //추상메서드를 구현
         void stop() { /* 내용 생략*/ }             //추상메서드를 구현

 

추상 메서드(abstract method)

-미완성 메서드, 구현부 {}가 없는 메서드

abstract 리턴타입 메서드이름();

- 꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우 사용

 

 

abstract class Player {  //추상 클래스
    abstract void play(int pos);  //추상 메서드
    abstract void stop();  //추상 메서드 (선언부만 있고 구현부{}가 없는 메서드)

}

//추상 클래스는 상속을 통해 완성해야 객체 생성가능
class AudioPlayer extends  Player {
    @Override
    void play(int pos) {
        System.out.println(pos+"위치부터 play 합니다");
    }

    @Override
    void stop() {
        System.out.println("재생을 멈춥니다.");
    }
}


public class PlayerTest {

    public static void main(String[] args) {
//        Player p = new Player(); // 추상 클래스의 객체를 생성
//        AudioPlayer ap = new AudioPlayer();
        Player ap = new AudioPlayer(); //다형성
        ap.play(100);
        ap.stop();
    }
}

 

추상클래스의 작성

- 여러 클래스에 공통적으로 사용될 수 있는 추상클래스를 바로 작성하거나 기존 클래스의 공통 부분을 뽑아서 추상클래스를 만든다


public class Ex7_10 {
    public static void main(String[] args) {
//        Unit[] group = new Unit[]{new Marine(), new Tank(), new Dropship()};
        Unit[] group = new Unit[3];
        group[0] = new Marine();
        group[1] = new Tank();
        group[2] = new Dropship();
        for(int i = 0; i < group.length; ++i)
            group[i].move(100, 200);
    }

}

abstract class Unit {
    int x, y;
    abstract void move(int x, int y);
    void stop() {/*현재 위치에 정지*/}
}

class Marine extends Unit { //보병
    void move(int x, int y) {
        System.out.println("Marine[x="+x+",y="+y+"]");
    }
    void stimPack() {/*스팀팩을 사용한다. */}
}

class Tank extends Unit { //탱크
    @Override
    void move(int x, int y) {
        System.out.println("Tank[x="+x+",y="+y+"]");
    }
    void changeMod() { /*공격모드를 변환한다.*/}
}

class Dropship extends Unit { //탱크
    @Override
    void move(int x, int y) {
        System.out.println("Dropship[x="+x+",y="+y+"]");
    }
    void change() { /*공격모드를 변환한다.*/}
}

- 추상화된 코드는 구체화된 코드보다 유연; 변경에 유리함

 

 

자바의 정석 기초편

instanceof 연산자

  • 참조변수의 형변환 가능여부 확인에 사용 -> 가능하면 true return
  • 형변환 전에 반드시 instanceof로 확인해야함
  • 참조변수 형변환은 왜?
    • -> 참조변수를 변경함으로써 사용할 수 있는 멤버의 갯수를 조절하기 위해서
    • 타입 일치시키려고

 

매개변수의 다형성

  • 다형적 매개변수
  • 하나의 배열로 여러종류 객채다루기
  • 참조형 매개변수는 메서드 호출시, 자신과 같튼 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.

 

여러 종류의 객체를 배열로 다루기

  • 조상타입의 배열에 자손들의 객체를 담을 수 있다

 

Vector class에는 모든 종류의 객체 저장 가능

object[]

 

동영상 예시를 보면 도움이 된다.

 

 

 

혼공자 자동타입변환 형변환

자동타입변환 promotion

  • 프로그램 실행 도중에 자동적으로 타입 변환이 일어남

 

부모 타입 변수 = 자식 타입;

 

  • 자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있음
  • 바로 위의 부모가 아니더라도 상속 계층에서 상위 타입이면 자동 타입 변환이 일어날 수 있음
  • 부모 타입으로 자동타입 변환된 이후 부모 클래스에 선언된 필드와 메소드만 접근 가능
  • 변수는 자식 객체를 참조하지만 변수로 접근 가능한 멤버는 부모 클래스만 가능
  • 예외-> 메소드가 자식 클래스에서 재정의된 경우 자식 클래스의 메소드가 대신 호출됨

 

필드의 다형성

  • 다형성을 구현하기 위해서 부모타입으로 자동 타입 변환이 필요함
  • 필드의 타입을 부모 타입으로 선언하면 다양한 자식 객체들이 저장될 수 있기 때문에 필드 사용 결과가 달라질 수 잇음 -> 필드의 다형성
  • 객체들이 다른 객체로 교체 될 수 있어야 함
  • 자동 타입 변환을 이용해서 필드값을 교체함으로써 메소드를 수정하지 않아도 다양한 실행결과를 얻게 됨 -> 필드의 다형성

 

매개 변수의 다형성

  • 자동 타입 변환은 주로 메소드를 호출할 때 발생
  • 매소드 호출시 매개 변수의 타입과 동일한 매개값을 지정하는 것이 정석이지만 매개값을 다양화 하기 위해 매개 변수에 자식 객체를 저장할 수도 있음
  • 매개 변수 타입이 클래스일 경우, 해당 클래스의 객체뿐만 아니라 자식 객체까지도 매개값으로 사용 가능

 

강제 타입 변환 (casting)

  • 자식타입 변수 = (자식타입) 부모타입;
  • 자식타입이 부모 타입으로 자동 타입 변환 된 후 다시 자식 타입으로 변환할 때 사용
  • 자식에 선언된 필드와 메소드를 꼭 사용해야 할 때 강제 타입 변환을 해서 다시 자식 타입으로 변환 후 자식의 필드와 메소드 사용

 

객체 타입 확인 instanceof 연산자

  • 어떤 객체가 어떤 클래스의 인스턴스인지 확인하기 위해 사용

 

boolean result = 좌항(객체) instanceof 우향(타입)

 

  • 매개값의 타입을 조사할 때 주로 사용
  • 메소드 내에서 강제 타입 변환이 필요한 경우 매개값이 어떤 객체인지 instanceof 연산자로 확인하고 안전하게 강제 타입 변환
  • 타입 확인 안하고 강제 타입 변환 시도시 ClassCastException 발생할 수 있음

 

확인문제

  • 자식 객체는 부모 타입으로 자동 타입 변환 된다 (o)
  • 부모 객체는 항상 자식 타입으로 강제 타입 변환 된다 (x)
  • 자동 타입 변환을 이용해서 필드와 매개 변수의 다형성을 구현한다. (o)
  • 강제 타입 변환 전에 instanceof 연산자로 변환 가능한지 검사하는 것이 좋다 (o)

 

혼자공부하는자바 상속

  • 상속을 이용하면 부모 클래스의 수정으로 모든 자식 클래스들도 수정되는 효과를 가져오기 때문에 유지 보수 시간을 최소화 가능

 

클래스 상속

  • 프로그램에서는 자식이 부모를 선택
class 자식 클래스 extends 부모클래스 {

//필드

//생성자

//메소드

}

 

  • 단 하나의 부모 클래스만 상속 가능
  • 부모 클래스에서 private 접근 제한 필드와 메소드는 상속 대상 x
  • 다른 패키지라면 default 접근 제한 필드와 메소드는 상속 대상 x

 

부모 생성자 호출

  • 모든 객체는 클래스의 생성자를 호출해야만 생성
  • 부모 생성자는 자식 생ㅎ성자의 맨 첫출에서 호출됨
  • super()는 부모의 기본 생성자를 호출함 ->컴파일러가 자동 생성

 

메소드 재정의 (오버라이딩 overriding)

  • 부모의 메소드와 동일한 시그니처 (리턴타입, 메소드 이름, 매개 변수 목록)을 가저야 함
  • 접근 제한을 더 강하게 재정의할 수 없음
  • 새로운 예외를 throws할 수 없음
  • @Override 어노테이션을 붙여주면 컴파일러가 확인도 해줌 -> 안붙여도 상관 x but 추천

 

부모 메소드 호출

  • super.부모메소드()
  • 자식 클래스 내부에서 재정의된 부모 클래스의 메소드를 호출할 때 사용

 

final 클래스와 final 메소드

  • 상속할 수  없는 final 클래스
  • final 클래스는 부모 클래스가 될 수 없음
  • 재정의할 수 없는 final 메소드
  • final 메소드는 자식 클래스에서 재정의 할 수 없음

 

확인문제

  • 자바는 다중 상속을 허용한다. (x)
  • 부모의 메소드를 자식 클래스의 재정의(오버라이딩)할 수 있다. (o)
  • 부모의 private 접근 제한을 갖는 필드와 메소드는 상속의 대상이 아니다 (o)
  • protected 멤버는 같은 패키지의 모든 클래스와 다른 패키지의 자식클래스만 접근할 수 있다 (o)
  • 부모의 메소드는 숨김 효과가 나타난다 (o)
  • 재정의 시 접근 제한을 더 강하게 할 수 있다 (x)
  • @Override를 붙이면 컴파일러가 재정의를 확인한다 (o)
  • 부모 메소드를 호출하고 싶다면 super 키워드를 사용할 수 있다 (o)

 

final 클래스, final 필드, final 메소드에 관한 설명 o,x 

  • 모두 상속과 관련이 있다 (x) -> 필드는 상속과 관련이 없음
  • final 메소드를 가진 클래스는 부모 클래스가 될 수 없다 (x) -> 재정의 할 수 없다
  • final 메소드는 재정의 할 수 없다 (o)
  • final 클래스는 final 필드가 반드시 있어야 한다 (x)

 

 

+ Recent posts