반응형

https://www.acmicpc.net/problem/1699

 

1699번: 제곱수의 합

어떤 자연수 N은 그보다 작거나 같은 제곱수들의 합으로 나타낼 수 있다. 예를 들어 11=32+12+12(3개 항)이다. 이런 표현방법은 여러 가지가 될 수 있는데, 11의 경우 11=22+22+12+12+12(5개 항)도 가능하다

www.acmicpc.net

 


 

다이내믹 프로그래밍을 이용한 문제다.

1, 4, 9, 16.. 과 같은 제곱수를 활용하여 주어진 수 N을 최소한의 개수로 구성하는 것이 답이다.

 

최적의 값을 idx에 기억해두는 바텀업 방식으로 이중 for문을 사용했다.

해당 문제에서 최적의 값은 최소한의 연산 횟수다.

 


 

DP 테이블 초기화

먼저 dp 테이블을 idx는 숫자, value는 최소 연산 횟수로 사용된다.

각 제곱수 idx 는 1로 만들어 주고,

나머지는 min을 알아내야 하니 충분히 큰 값으로 채워놓는다.

 


 

첫 for문은 1부터 100_000까지 차례대로 최소 연산을 구하게 된다.

 

두번째 for문은 최소 연산을 구하기 위해 

j의 제곱이 i 기준 수 보다 크면 의미가 없으므로 continue 하고,

 

j의 제곱이 i 기준 수보다 작다면 몫과 나머지를 구해서 

나머지 값에 해당되는 idx에 해당되는 값 + 현재 몫으로 이전에 구해둔 값과 비교해서 최적의 값을 구할 수 있다.

 

바텀업 방식이니

나머지값에 해당되는 idx는 현재 i 위치보다 이전 값일 것이고, 

최적의 값이라는 것이 보장되고 사용하기 무리가 없다.

 

예전에 풀었던 1463번 1로 만들기 문제와 비슷하다.


코드

 

 

import java.io.*;
import java.math.BigInteger; // subtract , multiply, add, mod
import java.util.*;

public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    static StringTokenizer st;
    static StringBuilder sb = new StringBuilder();

    public static void main(String[] args) throws IOException {
        int number = Integer.parseInt(br.readLine());

        // dp 초기화
        int[] dp = new int[100001];
        Arrays.fill(dp, 1000_000);
        dp[0] = 0;
        for(int i = 1 ; i * i<dp.length; i++){
            int powNumber = i * i;
            dp[powNumber] = 1;
        }

        // 1부터 100_000 까지 min을 채워나가기
        for(int i = 1 ; i<dp.length; i++){
            for(int j = 325; j >= 1; j--){
                int jNumber = (int)Math.pow(j, 2);

                if(jNumber > i) // 기준숫자보다 제곱이 커지면 의미가 없으니 넘김
                    continue;

                int divide = i / jNumber;
                int rest = i % jNumber;

                dp[i] = Math.min(dp[i], dp[rest] + divide);
            }
        }
        System.out.println(dp[number]);
    }
}

 

 

반응형
반응형

https://www.acmicpc.net/problem/2206

 

2206번: 벽 부수고 이동하기

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로

www.acmicpc.net

 

 


 

처음 시도 때 시간 초과로 풀지 못한 문제다.

 

모든 벽을 큐에 넣고 해당 부분을 0으로 만들었다가 bfs가 종료되면 다시 1로 만드는 식으로

과정을 진행시켰는데 시간초과가 걸렸다.

 

 

생각을 해보면 BFS는 최단 경로를 찾을 수 있고,

Node class를 만들어서 BFS를 하면 해당 Node가 가장 먼저 도착한 Node일 테니 

벽을 뚫은적이 있는지, 없는지에 대한 상태를 저장시키면서 진행하면 될 것 같았다.

 

 

3차원 배열을 이용한 풀이가 있는데, 

3차원을 쓰지 않고, 방문처리 배열을 따로 사용하지 않고도

단순 2차원 graph로 로직 처리를 해주면 풀 수 있다.

 

 

  2
벽을 뚫은 적 x O O O X
벽을 뚫은 적 o O X X X

 

 

BFS 큐에 넣기 전 해당 위치의 값을 확인해서 사용가능성을 판단해주면 된다.

 

 

0

[ 방문하지 않은 상태 ]

 두 상태 다 사용 가능

해당 위치를 재방문 방지를 위해 2로 바꾼다.

 

 

1

[ 벽 ]

방문한 Node가 이미 벽을 뚫었다면 더 뚫을 수 없으므로 continue (더이상 뚫을 수 없음)

방문한 Node가 벽을 안뚫었다면 상태를 벽을 뚫은 상태로 바꾼다. 해당 위치는 다시 사용할 일이 없으므로 값을 3으로 바꾼다.

 

 

2

[ 벽을 뚫은 적 없는 Node를 위해 중간 방문 처리함 ]

방문한 Node가 벽을 뚫은 상태라면  continue (앞서 간 Node가 있음)

방문한 Node가 벽을 뚫지 않은 상태라면 해당 위치를 다신 사용하지 않도록 3으로 바꾼다.

 

 

3

[ 완전 방문된 상태 ]

해당 위치는 모든 노드가 사용할 수 없다.

(벽을 뚫지 않은 Node가 이미 지나간 상태)

 

 

 

 

벽을 뚫은 적이 없는 Node가 해당 위치를 완전 방문 처리하는 우선권이 있다고 생각하고, 최종 결정권을 준다.

방문한 Node의 상태를 확인하여 위치를 4가지 분기로 나눠서 해결해줄 수 있다.

 

 


 

import java.io.*;
import java.util.*;

public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    static StringTokenizer st;
    static StringBuilder sb = new StringBuilder();

    static int[][] graph;

    static Queue<Node> q = new LinkedList<>();
    static int low, col;
    static int[] xRange = {1, -1, 0, 0};
    static int[] yRange = {0, 0, 1, -1};

    public static void main(String[] args) throws IOException {
        StringTokenizer st = new StringTokenizer(br.readLine());

        low = Integer.parseInt(st.nextToken());
        col = Integer.parseInt(st.nextToken());

        graph = new int[low][col];

        for(int i = 0; i< graph.length; i++){
            String str = br.readLine();
            int idx = 0;
            for(int j =0; j< graph[i].length; j++){
                int ele = Integer.parseInt(str.charAt(idx) +"");
                graph[i][j] = ele;
                idx++;
            }
        }
        System.out.println(bfs());
    }

    //
    public static int bfs(){
        int dis = 1;
        q.add(new Node(0, 0, false, dis));
        graph[0][0] = 2;

        int[] xRange = {1, -1, 0, 0};
        int[] yRange = {0, 0, 1, -1};

        while(!q.isEmpty()){
            Node node = q.poll();
            dis = node.dis;
            if(node.x == graph.length - 1 && node.y == graph[0].length -1)
                return dis;

            for(int i = 0; i<4; i++){
                int x = xRange[i] + node.x;
                int y = yRange[i] + node.y;
                if(x>=0 && x<low && y>=0 && y<col){
                    int disn = node.dis + 1;

                    if(graph[x][y] == 3)
                        continue;

                    if(node.state){
                        if(graph[x][y] == 0) {
                            q.offer(new Node(x, y, node.state, disn));
                            graph[x][y] = 2;
                        }

                    }else{
                        if(graph[x][y] == 0 || graph[x][y] == 2){
                            q.offer(new Node(x, y, false, disn));
                            graph[x][y] = 3;
                        }

                        else if(graph[x][y] == 1){ // 벽을 뚫는다.
                            q.offer(new Node(x, y, true, disn));
                            graph[x][y] = 3;
                        }
                    }
                }
            }
        }
        return -1;
    }
}

class Node{
    int x;
    int y;
    boolean state;
    int dis;
    Node(int x, int y, boolean state, int dis){
        this.x = x;
        this.y = y;
        this.state = state;
        this.dis = dis;
    }
}
반응형
반응형

파일 시스템 오류 (-2147416359) 해결하기


 

해당 오류는 microsoft의 모든 앱이 작동되지 않습니다.

저는 sticky notes에 중요한 메모를 적어놨는데

microsoft의 모든 앱들이 켜지지가 않았습니다.



해결 방법을 알려드리겠습니다.


 

 

해결방법

 

 

 

windows + R을 눌러서 services.msc 라고 입력합니다.

 

 


 

 

 

서비스중 windows 라이선스 관리자 또는 windws license manager 를 찾습니다.

 

 


 

 

 

 

해당 서비스를 더블클릭하고 시작유형을 "자동"으로 수정합니다.

 

 

그후 재부팅하시면 microsoft 앱들이 정상 동작합니다. !!

반응형
반응형

빌드 도구 gradle 사용

 

공통사항

 

application.properties - DB연결

spring.datasource.url=jdbc:mysql://localhost:3307/스키마명?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul
spring.datasource.username=유저명
spring.datasource.password=유저비밀번호

 

build.gradle - mysql 종속성 추가

dependencies {
    implementation 'mysql:mysql-connector-java:8.0.29'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'

 


 

JPA 연동

 

build.gradle

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

 


 

myBatis 연동

 

build.gradle

implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.2'

 

application.properties - mapper 패키지 추가 // db snake_case와 java camelCase 매핑 

mybatis.type-aliases-package = com.example.project.mapper
mybatis.configuration.map-underscore-to-camel-case=true

 

반응형
반응형

[학습일지] Java & SpringBoot로 시작하는 웹 프로그래밍 : 자바 인강 8주차


 

8주차 학습 내용

REST API

HTTP PROTOCOL

SPRING BOOT

 

 


REST API

 

REST: 자원의 상태 전달

1. URI를 이용해서 자원을 식별해야함
2. 데이터를 전달할 수 있다 주로 json, html
3. http 프로토콜을 통해 데이터의 처리방식을 포함 - GET, POST, PUT, DELETE

4. 응답 데이터뿐만 아니라 추가적인 URI 정보를 제공할 수 있다.

 



URI - 자원을 나타내는 주소 값
URL - 자원의 위치를 식별하는 주소

 


 

설계규칙
계층관계는 / 를 사용한다.
하이픈은 가독성을 높이는데 이용한다.
소문자를 사용한다

복수형을 사용한다.
파일확장자를 명시하지 않는다.
세션을 명시하지 않는다.

 


HTTP PROTOCOL

 

컴퓨터에서 다루는 대부분의 데이터는 전송할 수 있다.

클라이언트가 서버에게 request , 서버의 response를 클라이언트가 받는 방식으로 작동한다.

 

HTTP METHOD
get - 자원 취득
post - 자원 생성, 수정
put - 자원 수정
delete - 자원 삭제

 


응답상태코드
1.. 처리중

2.. 성공

3.. 리다이렉트

4.. 클라이언트 에러

5.. 서버 에러

 


SPRING BOOT


 SPRING BOOT의 가장 큰 장점은 사전 구성이 거의 필요 없다.
기존에 사전 구성을 하기 위해 xml 설정이 과도하게 필요했는데 현재는 xml 요구사항이 전혀 없다.
또한 WAS를 내장하고 있기 때문에 별도의 설치가 필요 없다.

 

REST API를 활용하여 Get method를 이용하여 URI 정보를 받는 여러가지 방식


RequstMapping에 주소를 명시한다.
GetMapping에 세부 주소를 명시한다.

 

요청 정보 받기
PathVariable 은 주소에 { } 를 사용한다.
RequestParam 은 ?name=값 처럼 이용한다.
또한 DTO를 사용할 수도 있다.

 


 

REST API를 활용하여 Post method를 이용하여 정보를 받는 여러가지 방식

RequestBody 데이터를 HTTP body에 넣어서 전송
      DTO 를 body 에 전송할 땐 해당 어노테이션 사용

객체는 카멜케이스, json은 스네이크케이스이므로
칼럼에 JsonProperty
객체에 JosnNaming
body에 전달되어 오는 json을 객체에 매핑
객체를 json으로 변환시키고 return 시킬 수 있음

 



Put
PathVariable 수정할 자원을 명시

전달받기 위해 RequestBody를 활용할 수 있다.

 



Delete
PathVariable 삭제할 자원을 명시

역시 전달받기 위해 RequestBody를 활용할 수 있다.


json -> object 할때는 objectMapper사용하면 편리하다.

 


 

반응형
반응형

JPA 관계 설정

자바 관점에서 생각하지 말고, RDB 관점에서도 생각해야한다.

 

JPA에서는 연관 관계의 주인이라는 개념이 있다.

연관 관계의 주인이란 외래 키를 관리하는 주체이다.

 

 

관점의 불일치

(1)

RDB에서는 한 곳에서 외래키를 갖고 있는데 자바에서는 양방향 매핑시 양쪽 모두 서로의 Entity를 갖고 있음

RDB에서는 해당 필드(칼럼)이 없는데 자바에는 존재

관점이 다르기 때문에 발생하는 문제로 RDB 외래키를 관리해주는 Entity를 누구로 할지 결정해야한다.

 

(2)

자바는 단방향 매핑이면 참조타입이 없는 한쪽에서 다른쪽으로 접근하는 것이 불가능,

RDB는 외래키를 이용해서 조인하면 서로 접근이 가능

 

 

 

Q&A

무조건 외래 키가 있는 쪽이 연관 관계의 주인 ?

 - 대부분의 경우엔 그렇다. 하지만 외래키가 없는 Entity가 관계의 주인이 될 수 있다.

 

외래키가 없는 곳을 굳이 연관 관계의 주인으로 지정하는 이유?

 - 편하다. 외래 키가 없음에도 연관 관계 CRUD가 완벽 동작

 

원래 외래키가 있는 곳에서의 CRUD는?

 - 양방향 매핑이라면 전부 정상 동작한다. 외래 키가 없는 곳에서 CRUD를 하기 위함이다.

 

단점은 없는지?

 - 외래 키 설정을 위한 추가 update 쿼리가 동작한다. (성능 저하)

 

mappedBy로 외래 키가 있는 반대편을 지정하는 이유?

 - 코드 가독성 측면에서 수많은 Entity를 볼 때 양방향 매핑이 돼있음을 알림,

   JPA에게 반대편 Entity가 주인임을 알림(매핑 테이블 생성과 검색을 방지),

   외래 키가 있는 곳에서만 외래 키를 관리하여 복잡도를 줄이기 위함

 

 


 

✔ 단방향 관계

한쪽만 매핑 어노테이션을 설정한 것

@ManyToOne, OneToMany 알맞게 설정하고

@JoinColumn으로 외래키를 갖고 있는 쪽을 가르킨다.

 

 

(1) 다대일 

RDB와 JAVA 관점을 일치시키는 방식.

RDB 외래 키가 있는 곳을 연관 관계의 주인으로 설정

 

(2) 일대다 

RBD와 JAVA 관점이 불일치되는 방식.

외래 키가 없는 곳에만 매핑 어노테이션 설정

외래키가 있는 Entity에는 매핑 어노테이션을 설정하지 않는다. 단순히 long boardId

RDB 외래키가 없는 곳을 연관 관계의 주인으로 설정

 

다쪽에 있는 외래 키를 수정하기 위해 추가적인 update쿼리가 동작한다.

이 방식보다는 차라리 양방향 매핑을 사용하므로, 많이 사용하는 방식은 아니다.

 

 

 

* 양방향에서의 관계 주인 (CRUD의 가능 여부)

✔ 양방향 관계

양쪽이 매핑 어노테이션을 설정한 것

모든 테이블을 양방향 관계로 설정하면 복잡성이 증가하므로 필요할 때만 양방향 관계 지정

 

사실 단방향 만으로도 Entity 간의 관계 설정은 완료된 것이다.

(RDB는 한쪽만 외래키를 갖는 식으로 완벽히 동작해왔다.)

 

 

 

✔ 외래 키가 없는 Entity에서 반대쪽 Entity의 외래 키를 인식하게 하는 방법은 두 가지

(1) mappedBy 

외래 키는 반대쪽 Entity가 갖고 있음을 알려준다.

 

mappedBy가 없으면?

RDB에서 외래 키가 없는 테이블에 외래 키를 생성하게 된다. (조회 필드를 외래 키로 잘못 인식해버린다.)

JPA가 양방향인 것을 모르고 해당 필드가 외래키로 인식되어 매핑 테이블을 생성하고, 그곳에서 관계 정보를 찾으려고 한다.

JPA가 만든 양쪽 Entity id를 갖는 매핑 테이블에는 당연히 아무런 정보가 들어가 있지 않아 찾지 못한다.

 

 

 

(2) JoinColumn 

반대쪽 Entity를 가리키면 연관 관계의 주인을 외래 키가 없는 곳으로 설정

이 방식을 권장하지 않는 이유는 추가적인 쿼리를 소모하게 된다.

두 Entity의 데이터를 새로 추가시킨다고 했을 때 외래키가 없는 Entity로 save()하면

 

Entity1 insert ---> Entity2 insert ---> 외래키가 있는 Entity를 update

 

insert 만으로 끝날 동작을, 반대편 Entity 외래 키를 update 하며 추가적인 쿼리가 소모된다.

성능을 희생하고, 편의를 증가

두 Entity 모두 CRUD가 가능해진다.

 


 

양방향 매핑 두 가지 방법

 

(1) JoinColumn(외래 키가 있는 곳에 설정), mappedBy(외래키가 없는 곳에 설정)

       -> mappedBy가 있는 Entity는 외래키를 관리하지 않는다.

 

연관 관계의 주인을 외래키가 있는 곳으로 설정, 권장되는 방식

외래키가 존재하는 Entity에서 연관 Create, Select, Update, Delete가 가능

mappedBy 쪽에서도 cascade 설정하면 Insert 빼고는 다 전이된다.

 

@Entity
public class Troop {
    @OneToMany(mappedBy="troop")
    public Set<Soldier> getSoldiers() {
    ...
}

@Entity
public class Soldier {
    @ManyToOne
    @JoinColumn(name="troop_fk")
    public Troop getTroop() {
    ...
}         

 

 

 

 

(2) JoinColumn(외래 키가 없는 곳에 설정)

 

연관 관계의 주인을 외래키가 없는 곳으로 설정, 편의를 위해 성능을 희생시키는 방식

양쪽 모두 Create, Select, Update, Delete가 가능 (복잡도 증가)

 

@Entity
public class Troop {
    @OneToMany
    @JoinColumn(name="troop_fk") //we need to duplicate the physical information
    public Set<Soldier> getSoldiers() {
    ...
}

@Entity
public class Soldier {
    @ManyToOne
    @JoinColumn(name="troop_fk", insertable=false, updatable=false)
    public Troop getTroop() {
    ...
}

 

양방향 매핑 시에는 순환 참조, 순환 삭제 등 신경 써줘야 할 사항들이 생겨 복잡도가 증가한다.

그래서 mappedBy로 조회만 하고, 나머지는 연관 관계의 주인으로 처리하는 방식이 권장된다.

 

https://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#entity-mapping-association

 

Chapter 2. Mapping Entities

In Section 2.4.5.1, “Lazy options and fetching modes” we have seen how to affect the fetching strategy for associated objects using the @Fetch annotation. An alternative approach is a so called fetch profile. A fetch profile is a named configuration a

docs.jboss.org

 

 


Cascade

연관관계 Entity에 대한 영속성 전이 설정

dafault는 아무것도 설정되어있지 않다.

 

persist - 연관 Entity를 영속성 콘텍스트에 manage 되게 전이시킨다.

merge - 연관 Entity를 update 할 수 있게 한다.

detach - 연관 Entity를 영속성 콘텍스트에서 관리하지 않는다.

remove - 연관 Entity를 함께 제거한다.

 

 

 

orphanRemoval

연관 Entity만 삭제하고 싶을 때 사용한다.

 

set...(null)을 할 경우 외래키가 없는 것으로 update 된다.

이때 자동으로 연관 설정이 없는 Entity를 DB에서 제거하고자 할 때 사용한다. 

(cascade는 set..(null)로 동작하지 않는다.)

 

 


Entity를 영속성 컨텍스트에서 사용할 때 연관 Entity 설정 (fetch type)

 

LAZY

가장 먼저 lazy를 사용하기 위해선 Entity가 영속성 컨테이너에 관리되어지고 있어야 한다.

연관 관계 Entity가 필요할 때만 get()으로 연관 Entity를 select를 통해 나중에 가져온다.

 

EAGER

연관 관계 Entity를 영속성 컨테이너로 전부 즉시 가져온다.

 

LAZY가 보편적 권장 사항

 

 

 

 

✔ N+1 

1대 N 관계에서 1인 Entity를 findAll()했을 경우 Many Entity와 조인해서 한번에 가져올 것을 기대한다.

 

하지만, 실제 동작은 1인 Entity를 먼저 select 한 후, 1인 Entity의 id를 이용해서

매번 from N where Entity_id = id(1인 Entity의 id값)로 N 테이블에서 여러 번의 select로 id값을 확인한다.

 

[1회] select로 id 개수 확인 ---> [N회] id 개수만큼 select 동작

 

 

여러 번의 select보다 조인을 사용하고 싶을 때

1.  jpql - join fetch 이용

(join과의 차이: 연관 Entity도 한번에 가져온다)

2.  @EntityGraph에서 join 할 Entity 지정

(중복 데이터가 있을 수 있다. distinct사용)

 

 

 

 

✔ sql select의 실행 횟수 vs 조인된 데이터의 양 

두 가지를 고려하여 어떤 것이 더 효율적인가를 고려해야 한다.

 

sql select의 실행 횟수가 너무 많다면, DB를 반복적으로 접근해서 IO가 발생, 느려진다. -> 조인을 하는 선택을 한다.

가져온 데이터의 양이 너무 과하면 -> sql select를 필요한 것만 수행, 연관 Entity 정보만 가져오는 것을 선택한다.

 


참고

 

https://catsbi.oopy.io/f3204fd9-954c-44d7-ab18-2ca56000c5e5

 

다양한 연관관계 매핑

연관관계 매핑시 고려사항 3가지

catsbi.oopy.io

 

반응형
반응형

WAS

톰캣이다.

톰캣은 Java servlet을 관리한다.

 

톰캣외에도 WAS가 있지만 톰캣을 가장 많이 사용

 

 

역할

통신지원

멀티 스레드 관리

서블릿 생명주기 관리

세션 관리

 

동작방식

Request, Response 객체 생성 -> servlet에게 전달 /스프링/ spring dispatcher servlet 

 

 

 

용어 정리

 

✔ Socket

IP + Port

HTTP도 Socket을 사용함, Web Socket 통신이 아닐뿐임

 

✔ HTTP 통신

요청에 대한 응답을 주고 바로 통신을 해제

TCP 위에서 보편적으로 사용, UDP 위에서도 사용가능함 (Youtube QUIC)

 

✔ Web Socket 통신

HTTP와 달리 통신을 유지하며 실시간 통신 지원

처음 요청시 HTTP Get 으로 Upgrade:web socket 헤더를 추가하여 보냄

 

 

 

 Web Server

HTTP, HTTPS 통신을 위해 Server는 (IP + 80번, 443번)으로 socket 생성

정적인 데이터를 응답

 

✔ Web Container == Servlet Container

웹 컨테이너는  자바 서블릿과 상호작용한다.

동적인 처리를 위한 Servlet들이 모인 Container, JAVA에서는 동적 처리로 Servlet을 이용한다.

클라이언트의 URL에 맞는 Servlet을 매핑

(스프링에서는 Dispatcher Servlet 하나의 Servlet으로 URL에 맞는 Controller를 Handler Mapping)

 

  • 서블릿 객체의 생명주기 담당
  • 싱글톤 패턴으로 관리
  • 멀티 스레딩 지원

 

 

✔ Web Container Server == Web Application Server(WAS)

Web Container + Web Server

요청에 대한 동적인 데이터를 처리하여 응답

WAS에도 Web Server가 존재하지만 보안, 로드밸런싱, 정적데이터 처리를 위해 Web Server를 앞단에 하나 더 둠

 

 

 

 

 


JSP 라이프 사이클

 

  1.  클라이언트가 URI로 JSP 파일을 서버에 요청
  2.  톰캣이 서버에 해당 JSP 파일이 있다면 JSP파일 -> JAVA파일 -> JAVA파일 컴파일 -> 서버 메모리에 로드
  3.  init() 메서드 호출 -> service() 메서드 호출 -> HTTP response 로 응답

 

(jsp)자바파일의 변경이 없다면 -> 기존 메모리에 있는 instance service()로 바로 응답

(jsp)자바파일의 변경이 있다면 -> 기존 instance destroy() 메모리 해제 -> instance 새로 생성 -> init() -> service()

 

톰캣이 jsp 파일을 servlet instance로 만들어서 요청에대한 응답을 한다.

 


 

작성한 jsp 파일

 

 


 

톰캣이 생성한 jsp 파일.java

service() 메서드 일부

 

 

톰캣이 작성된 jsp 파일을 java class(servlet)으로 변환하고, service()메서드를 통해 요청을 처리한 후 응답한다.

 


Servlet

 

HTTP 의 request 를 처리하고 response를 돌려주는 동적인 처리를 위한 자바 기술

 

톰캣이 jsp를 class로 만들고 이 class는 요청을 처리하므로 사실 jsp는 servlet이다.

 - jsp보다 servlet이 먼저 등장했으며, servlet에서의 html 처리가 불편하여 jsp가 등장

 - jsp는 서버에서 데이터를 렌더링하여 html을 만들어서 전달하므로 Server Side Rendering(SSR)이라 한다.

 - 클라이언트에서 데이터를 받아 처리하는 것은 Client Side Rendering(CSR) - Vue, React

 

jsp를 이용하지 않고 직접 servlet에 HTML을 작성할 수도 있다.

 - 직접 작성한 servlet을 이용하게 되면 클라이언트의 요청을 jsp를 거치지 않고 servlet이 직접 받을 수 있다.

 

jsp파일은 view에 집중할 수 있게 되고,

작성한 servlet은 요청에 대한 로직을 처리하는 controller 역할만을 하게되어

jsp파일 내에서 혼합되어 처리되던 html코드와 자바 로직 코드 부분을 분리시켜 MVC 패턴을 적용시킬 수 있다.

 


 

Dispatcher Servlet

 

URL를 통해 서버에 요청이 오면 매핑된 servlet이 해당 요청을 받아준다.

이러한 요청에 맞는 servlet들을 일일이 작성해주어야 했는데 이 부분을 한곳에서 관리하고자 front controller라는 개념이 등장했다.

front controller는 한곳에서 URL과 controller를 매핑해주며, 요청에 위임할 controller에게 다시 요청한다.

spring framework은 dispatcher servlet으로 MVC패턴을 쉽게 구현할 수 있게 틀을 제공해준다.

 


 

클라이언트가 서버에게 HTTP 요청을 하면

 

요청을 받게되면 Servlet Container가 HttpServletReqeust, HttpServletResponse 객체 생성

Dispatcher Servlet으로 해당 URL에 맞는 Controller를 찾아서 비즈니스 로직 수행

이때 Controller에서 HttpServletReqeust의 값을 이용하여 로직 처리

View Resolver로 해당 view를 찾아 HttpServletReqeust, HttpServletResponse에 결과를 View에 렌더링한 후 HTTP header, body 응답

 

 

 

 

 


참고

 

https://www.theserverside.com/feature/Understanding-How-the-Application-Servers-Web-Container-Works

 

Understanding How the Application Server's Web Container Works

To understand how to do proper application server development, you need to understand how the two basic containers of an application server work, namely the Web container and the EJB container. This article will take a look at how a client application inte

www.theserverside.com

 

반응형

'프로그래밍 > Servlet \ JSP' 카테고리의 다른 글

서블릿/JSP  (0) 2022.07.19
반응형

 

https://www.amitph.com/spring-entity-to-dto/

 

Convert Entity To DTO In Spring REST API

A tutorial on How to Entity to DTO Conversion and DTO to Entity Conversion in a Spring REST API manually as well as by using Model Mapper.

www.amitph.com

 

변환하는 방법을 소개하는 좋은 글이 있어서 남긴다.

 

  • 생성자를 사용하는 방법
  • 메서드를 사용하는 방법
  • ModelMapper를 사용하는 방법
  • MapStruct를 사용하는 방법

 

메서드를 사용하는 방법이 직관적

만약 변경해야할 필드가 많다면 ModelMapper, MapStruct를 사용하는 것이 용이할 것 같다.

 


MapStruct 사용

 

 

compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'

implementation 'org.mapstruct:mapstruct:1.4.2.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'

 

gradle에서 mapstruct가 lombok과 이슈를 일으킨다.

lombok이 mapstruct보다 위에 있으면 해결된다.

 

 

 

 

@Mapper
public interface UserMapper {

    UserMapper mapper = Mappers.getMapper(UserMapper.class);

    // dto -> entity
    @Mapping(target = "userAge", source = "age")
    @Mapping(target = "name" , source = "name", defaultValue = "Park")
    UserEntity userDtoToEntity(UserDto userDto);


    @Mapping(target = "age", source = "userAge")
    UserDto userEntityToDto(UserEntity userEntity);

}

@Mapper 

구현체는 mapstruct가 만들어준다.

import할 때 Mybatis의 @Mapper와 구분

 

@Mapping

필드명 불일치를 해결할 수 있다.

defaultValue도 설정할 수 있다.

 

 

 

 

 

@Test
void UserDtoToEntity(){
    UserDto userDto = new UserDto(1, "cha", "email", 30);
    UserEntity userEntity = UserMapper.mapper.userDtoToEntity(userDto);

    System.out.println(userEntity);
}

 

 

 


참고

 

 

 

https://mapstruct.org/documentation/stable/reference/html/

 

MapStruct 1.5.2.Final Reference Guide

If set to true, MapStruct in which MapStruct logs its major decisions. Note, at the moment of writing in Maven, also showWarnings needs to be added due to a problem in the maven-compiler-plugin configuration.

mapstruct.org

 

 

http://modelmapper.org/getting-started/

 

ModelMapper - Getting Started

Getting Started This section will guide you through the setup and basic usage of ModelMapper. Setting Up If you’re a Maven user just add the modelmapper library as a dependency: org.modelmapper modelmapper 3.0.0 Otherwise you can download the latest Mode

modelmapper.org

 

 

https://blog.naver.com/PostView.nhn?isHttpsRedirect=true&blogId=kbh3983&logNo=220988245343 

 

[JAVA] ModelMapper Customizing

주의!! 일부 버전에서 Custom Mapping 이 됬다 안됬다하는 버그가 있음 아오....하루종일을 날렸네........

blog.naver.com

 


 

반응형
반응형

 

h2를 사용하다가 오류가 전혀 없어 보이는데 문법 오류가 났다.

 

h2에서는 mysql 문법을 지원하지 않아서 나는 오류다.

 


 

 

첫 연결시에 JDBC URL 마지막에 ;mode=mysql를 입력해주면 mysql 문법을 사용할 수 있다.

 

 


 

 

data.sql 을 spring boot 2.5부터 사용할 때 추가해줘야한다.

 

defer-datasource-initialization: true  # data.sql 사용할 때 spring boot 2.5부터 추가
반응형

' > 오류 모음' 카테고리의 다른 글

[DataBase] 오류  (0) 2022.06.29
[Spring boot] 오류 모음  (0) 2022.05.02
반응형

[학습일지] Java & SpringBoot로 시작하는 웹 프로그래밍 : 자바 인강 7주차


 

7주차 학습내용

 

객체지향

디자인 패턴

 


객체지향

 

현실에 존재하는 물체를 모델링하기 위한 방법론이다.

절차 지향적인 프로그래밍 방법을 객체지향적인 프로그래밍 방법으로 발전시켰다.

 

물체를 객체로 정의하기 위해 해당 객체가 가지고 있는 특성을 분석하여

속성(변수)과 기능(메서드)으로 분리하여 모델링한다.

객체는 실체화된 개념일 수 있고, 추상적인 개념일 수도 있다.

 

상태 유지(속성)

객체는 해당 상태를 저장할 수 있어야 하고 그 상태를 유지해야 한다.

기능 제공(메서드)

객체는 다른 객체와 협력하기 위해 기능을 제공해야 한다.

고유 식별자

객체는 고유한 값을 갖고, 다른 객체와 식별될 수 있어야 한다.

 


 

객체지향의 4대 특성

 

캡슐화

객체의 상태인 속성은 기능을 통해 변경되어야 한다.

무의미한 값을 저장하지 않도록 무결성을 유지할 수 있다.

상속

객체를 구조화할 수 있다. 유지보수가 향상된다.

추상화

객체 간의 특성을 추출하여 추상화시킬 수 있다.

다형성

하나의 인스턴스가 여러 형태로 변화할 수 있다.

코드의 재사용성이 향상된다.

 


 

객체지향 설계의 5원칙(SOLID)

 

객체 간의 의존성은 낮추고, 책임지고 있는 기능에 집중해야 한다.

결합도는 낮추고, 응집도는 높인다.

 

단일 책임 원칙

하나의 객체가 여러 기능을 부담하지 않고, 객체가 하나의 기능에 집중하도록 분리해야 한다.

 

개방 폐쇄 원칙

변경되어야 하는 부분은 폐쇄적이어야 하고, 확장에는 개방되어야 한다.

인터페이스를 사용하면 손쉬운 확장이 가능하고, 클라이언트 코드의 변경도 없다.

 

리스 코프 치환 원칙

부모의 인스턴스가 사용되던 자리에 자식의 인스턴스가 사용된다면

기존의 부모 인스턴스가 갖고 있던 규칙을 자식이 위반하면 안된다. (오버라이딩시 위배가능성)

 

인터페이스 분리 원칙

인터페이스의 기능들을 하나의 인터페이스에 통합하지말고

인터페이스를 분리해서 구현체가 필요한 메서드를 가진 인터페이스만을 구현받도록 분리해야 한다.

 

의존 역전 원칙

의존 객체를 구체적인 구현체가 아닌 상위 추상적인 개념을 의존하게끔 설계해야한다.

 

 


디자인 패턴

 

싱글톤

 

 

생성자를 private로 만들어서 생성할 수 없게 한다.

싱글톤 패턴은 자기 자신을 속성으로 갖고 있다. getInstance 메서드를 통해 자기 자신인 속성을 가져온다.

getInstance가 static이므로 getInstance에서 이용해야 하는 자기 자신인 속성도 static으로 선언된다.

 


 

어댑터

 

 

관련이 없는 두 인터페이스를 중간에서 어댑터가 바꿔치기하여 연결시켜주는 디자인 패턴이다.

기존 인터페이스가 A이고, A 인터페이스를 사용하는 위주로 클라이언트 코드가 작성되었다고 할 때

B 인터페이스 새로 사용해야 한다면 B 인터페이스를 A 인터페이스로 중간에서 교체하는 어댑터를 만들어 줄 수 있다.

 

어댑터는 A 인터페이스를 구현하고, B 인터페이스를 속성으로 받아

A 인터페이스들의 메서드를 호출하면, A메서드를 오버라이딩해서 B 인터페이스 메서드를 대신해서 호출시켜주면 된다.

 


 

프록시

 

 

스프링 프레임워크에서 AOP로 프록시 패턴을 사용한다.

프록시가 인터페이스인 GameInterface를 구현하고, 실제 구현체인 GameService를 속성으로 갖는다.

 

클라이언트 코드에서 직접 GameService를 사용하지 않고 Proxy를 통해 사용한다.

Proxy는 GameService의 메서드를 호출을 하는데, 이때 앞과 뒤로 추가적인 작업이 가능해진다.

 


 

데코레이터

 

상속관계를 통해 super키워드를 이용하여 부모의 메서드를 호출하여

실행 결과를 반환받는 디자인 패턴이다.

 

호출은 (자식 -> 부모) 순으로 호출되며

실행은 (부모 -> 자식)으로 나오게 된다.

 

 


 

옵저버

 

 

변화가 일어날 때 등록해둔 옵저버(인스턴스)들에게 모두 알려주는 것이다.

옵저버를 등록시키고, 특정 함수가 동작할 때 옵저버의 기능이 동작하도록 한다.

 


 

파사드

 

클라이언트 코드가 복잡한 (여러 클래스)들의 기능을 일련의 과정으로 사용할 때

(클라이언트 코드)와 (여러 클래스) 사이에 (파사드 객체)를 두어

파사드 객체가 각 클래스들이 복잡하게 호출되는 일련의 과정을 메서드로 제공한다.

 

클라이언트 코드는 파사드 객체가 제공하는 간단한 메서드를 사용하게 하는 방식이다.

 


 

전략

 

가장 보편적으로 사용되는 패턴으로 

클라이언트 코드단에서 인터페이스를 구현한 구현체 부분을 전략으로 선택하여

선택한 전략 구현체를 사용하는 방법이다.

 

생성자를 인수를 인터페이스로 지정하여 내부 동작들은 인터페이스의 메서드를 사용하여구현체인 인스턴스의 메서드로 동작시키는 것

 

 


 

반응형

+ Recent posts