아쿠의 개발 일지

한화 시스템 부트 캠프 8주차 회고 본문

ETC/한화시스템

한화 시스템 부트 캠프 8주차 회고

디아쿠 2024. 6. 22. 13:11

집에서 회고록 쓰고 있지만 집 가고 싶다

 

 

벌써 8주차 회고록이라니 믿기지가 않는다. 그래도 믿어야지 어쩌겠나...

일단 배움에 많은 변화가 생겼다. java가 끝나고 Spring 수업에 들어왔다는...!? 점이 가장 크게 변한 것 같다.

8주차에서 2일은 알고리즘에 대해 배웠고, 나머지 3일은 Spring 이론과 약간의 실습?에 대해서 배웠다.

 

알고리즘은 저번 자료구조와는 다르게 발표 준비를 정말 열심히 했고, 나 혼자 뭐라도 구현을 하기 위해서 애쓴 것 같다.

딱 이런 느낌? 우리 팀은 정말 잘하드라...

 

우리팀은 Dijkstra 알고리즘에 대해서 맡게 되었고, 뭐... 역시나 어렵더라.

착각?인 것 같지만 이해하기는 레드블랙트리보다 수월했던 것 같다. (아마도)

 

Dijkstra 이란?

다익스트라 알고리즘은 다이나믹 프로그래밍을 활용한 대표적인 최단 경로 탐색 알고리즘이다. 주로 가중치가 있는 그래프에서 사용되며 , 음의 가중치가 없는 경우에 적용된다. 이 알고리즘은 BFS와 유사하지만 , 각 간선의 가중치를 고려하여 최단 경로를 계산하는 방식으로 동작한다.

 

장점으로는 실시간 최단 경로를 갱신할 수 있다는 것과 단일 출발점이라는 점이 있다.

단점으로는 음중 가중치 간선 처리가 불가능하다는 점이다.

 

글로 설명하면 나도 당연히 이게 뭐지? 싶었다... 

 

우리팀 발표 자료다.

 

1을 시작 기준으로 2번 정점과 3번 정점의 길이는 저렇게 되어있다. 최소 값을 선택하여 업데이트 해주는 것이 다익스트라 알고리즘이라고 생각하면 된다.

1에서 2까지의 가중치는 3

1에서 3까지의 가중치는 2

이렇게 보여진다. 아까 말했듯 음수 가중치가 올 수 없다는 게 다익스트라 알고리즘이었다.

그 이유는 A가 만약 -4라면 1에서 3까지 가는 길이가 3 -4 가 되기에 -1으로 업데이트가 된다.

최단 경로를 결정한 후, 이미 방문한 노드가 최단 경로가 아닌 것이 되기 때문에 음수 가중치가 올 수 없다는 것이다.

 

만약 !!

1에서 2까지 가는 가중치가  1이고, 

1에서 3까지 가는 가중치가  4고,

2에서 3까지 가는 가중치가 1이라고 가정 해 보자.

 

1에서 3을 가는 가중치가 4고,

1에서 2를 거치고(가중치:1) + 2에서 3을 (가중치:1) 가는 가중치를 거치면 최종적으로 1->2->3 으로 가니 1->3이 된다.

1+1 은 2가 되는 것이고, 2를 거쳐서 3으로 가는 경로가 더 가까우니 최소 가중치를 선택하는 다익스트라 알고리즘은 2의 가중치를 선택하게 되는 것이다... . . . (이해가 됐길 바랍니다.)

 

 

 

우리팀 ppt 너무너무 잘 만들었다!ㅎㅎ

 

package dijkstra;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.PriorityQueue;

public class DijkstraPri {
    ArrayList<ArrayList<Node>> graph = new ArrayList<>();
    Integer[] prev;   // 이전 경로를 찾아가기 위한 배열
    int[] dist;   // 현재 노드까지 최단 거리(가중치) 저장

    public DijkstraPri(int v, int[][] list) {
        //리스트 초기화
        // 노드 별 가중치 계산을 위한 dist 배열
        this.dist = new int[v];

        this.prev = new Integer[v];

        // 인접 리스트 생성
        for (int i = 0; i < v; i++) {
            this.graph.add(new ArrayList<>());
        }

        //인접 리스트에 그래프 값 저장
        for (int[] ints : list) {
            graph.get(ints[0]).add(new Node(ints[1], ints[2]));
            graph.get(ints[1]).add(new Node(ints[0], ints[2]));
        }
    }

    public void findPath(int start) {
        //  초기화 시켜주기
        Arrays.fill(dist, Integer.MAX_VALUE);
        //시작점은 0으로 초기화
        dist[start] = 0;

        //우선순위큐로 구현
        PriorityQueue<Node> pq = new PriorityQueue<>((o1, o2) -> o1.weight - o2.weight);

        pq.add(new Node(start, 0));

        while (!pq.isEmpty()) {
            // 큐에서 빼서 현재 노드로 저장
            Node curNode = pq.poll();
            
            // 다시 방문하더라도 dist 배열에 있는 해당 노드의 값과 비교해서 큰 값이라면 반복문을 통과하도록
            // 하여 큐를 비워준다  
            if (dist[curNode.to] < curNode.weight) continue;


            //인접 노드 확인해서 값을 큐에 넣기
            for (int i = 0; i < graph.get(curNode.to).size(); i++) {
                Node adjNode = graph.get(curNode.to).get(i);
                if (dist[adjNode.to] > curNode.weight + adjNode.weight) {
                    dist[adjNode.to] = curNode.weight + adjNode.weight;
                    pq.offer(new Node(adjNode.to, dist[adjNode.to]));
                    prev[adjNode.to] = curNode.to;
                }
            }
        }
    }

    public void printPath() {
        System.out.println("Cost: " + Arrays.toString(Arrays.stream(dist).mapToObj(cost -> cost == Integer.MAX_VALUE ? "INF" : "" + cost).toArray()));
        System.out.println();

        System.out.println("Path: " + Arrays.toString(prev));
        System.out.println();

        // 출발점에서 어떤 경로로 각 노드까지 이동하는지
        // 각 노드에서 prev 따라가서 최종적으로 출발지 만나면 종료
        for (int j = 0; j < prev.length; j++) {
            System.out.print(j + ": ");
            Integer check = prev[j];
            String str = "" + j;

//            방문할 수 있는 노드가 없을 때, No Path 출력
            if (check == null) {
                System.out.println("No Path");
                continue;
            }

//            check가 있으면 계속해서 출력
            while (check != null) {
                str = check + " " + str;
                check = prev[check];
            }

            System.out.println(str);
        }
    }
}

 

팀이 구현한 코드 남깁니다 ,, 이렇게 발표를 마치고 나서 

2등 !

을 하게 되었고, 강사님께서 1등과 2등에게 너무 너무 행복한 상품을 쥐어주셨다. 

1등은 인당 한 명씩 치킨을 주셨고, 2등은 먹고싶은 카페 메뉴를 고르라고 하셨다..! 솔직히 누가 토이 프로젝트도 아니고 ,,, 수업 시간에 잘 들었는지 발표하는? 시간에 이렇게 상품을 주십니까 ,,, ㅠㅠ 하는 말과는 다르게

 

당일에 바로 써서 드렸다. 다른 팀은 좀 걸렸다고 하시는데, 뭐... 빠르면 좋지 않나!?

 

바로 드렸다! 저 옆에 체크 표시는 아마도 강사님이 보냈다고 표시 하신 것 같았다.!

투썸플레이스 스무디 추천합니다. 모자이크 기능이 있다는 것을 위에 스티커 붙이고 알았습니다.

 

강사님이 아. 라고 보내셨길래 뭐지? 잘못 보내신건가? 하고 일 초만에 네? 라고 답장을 드렸는데,,,

알고보니 사진은 오던 중이었던 것이다. 강사님께 받은 투썸은 오늘 ! 스프링 공부를 하러 갈 때 마실 것이다.

이 건 [일상] 블로그에 올리겠습니다. 감사합니다 강사님,,,,,,, 앞으로도 열심히? 출석? 할게요! q(≧▽≦q)

 

이제 열심히 하겠다는 각오와는 다르게 Spring에 발을 붙이자마자 무너져버렸다.

 

Spring이란?

자바 플랫폼을 위한 오픈 소스 애플리케이션 프레임워크로써 간단히 스프링이라고도 한다.

동적인 웹 사이트를 개발하기 위한 여러 가지 서비스를 제공해준다.

 

Spring의 핵심 기능 중 하나인 " 의존 주입 " 에 대해서 배웠는데

노드 클래스, 연결 리스트를 만든다? -> 클래스가 있고, 객체를 가져와서 사용한다 = 이게 의존성이다...

뭔 말인가 싶은 분들이 계시겠지만 저 이해하기도 벅찼습니다.

메인 코드를 실행시키기 위해서 클래스들을 갖고 있어야 하기 때문에,, 메인이 저 클래스들을 의존한다고? 표현 하는 것 같다.

 

MVC 패턴에 대해서도 배우게 됐는데, 웹 서버를 만들 때 객체지향적으로 만들자. 라는 뜻이라고 기억이 난다.

우리는 백엔드가 되기 위해서 배우고 있는 중이라 M과 C에 대해서 중점적으로 학습했다.

M : model

V : view

C : Controller

 

Controller가 하는 일이 너무 많아서 분리하기 위해 레이어드 아키텍처를 만들었다.는 것인데 컨트롤러, 서비스, 레포지토리 이렇게 나눠서 처리한다.

급하게 화면 캡쳐한 거라 좀 웃기긴 하지만 뜻만 보이면 되잖아요.

 

Model은?

이렇게 서버로 보내주면, 서버에서 받고 터미널에 출력한다. web브라우저 주소에 치면 무조건 GET 방식이라고 생각하기로 했다.

HTTP가 요청하면 Controller에서 확인하고, 그 값이 맞으면 전달 받고 ? 이렇게 진행 되는 것 같다.

매개변수에 DTO를 전달받게 해두면 Spring이 알아서 변수 이름이랑 비교해서 값을 넣어주게 된다.

@RequestMapping(method = RequestMethod.요청타입, value = "/요청주소")
public 반환타입 메소드이름(RequestBody DTO클래스이름 DTO변수이름) {
	클래스이름 변수;
    	변수 = 서비스_메소드 실행;
    
    return 변수;
   
   }

컨트롤러에서 이렇게 실행해서 서비스 메소드로 들어가고, 서비스 메소드에서도 구현한 틀에 맞게 또 메소드가 실행되고,,, 타고 타고 가는 방식이다. 요즘 CRUD에 대해서 반복 학습하고 있으니, 꼭 이 부분에 대해서는 올리도록 하겠다.

 

순서는 다음과 같다.

1. 클라이언트가 보내준 데이터를 컨트롤러의 메소드에 전달하면서 메소드가 실행
2. 컨트롤러가 서비스 메소드를 실행
3. 서비스 메소드에서는 클라이언트가 보낸 데이터를 처리
4. 서비스의 메소드는 처리한 결과를 응답 DTO에 담아서 컨트롤러한테 반환
5. 컨트롤러는 서비스 메소드가 반환한 처리된 데이터를 ResponseEntity에 담아서 클라이언트에게 전달

 

이번 주도 알차게 살았다. 너무 많이 적었다. 읽다가 넘기셔도 인정 하겠습니다. 감사합니다.

 


블로그를 너무 내 느낌대로 적는 것 같아서 keep, problem, try에 대해서는 꼭 넣기로 했다.

 

Keep

 

Spring에 대해서 배우고 있는데, Java 때 어렵게 구현했던 것들이 한 줄의 코드 내로 정의 된다니까 너무 신기했다.

이러한 느낌을 주시려고 강사님께서 돌리신 것 같긴 한데, 배울 수록 아... 배움엔 끝이 없구나 싶다. 오늘도 회고록을 쓰고

카페로 복습하러 갈 것이다. 휴식도 중요하지만 지금 내게 더 중요한 것은 복습인 것 같다. 

꾸준히 학습하는 습관을 이어나갈 것!

복습하는 습관 & 꾸준함 & chat gpt 말고 강사님께 여쭤보는 거,,, 그대로 가지고 가기 ㅎㅎ.

 

Problem

 

집에서 교육장까지 가는 시간이 2시간 조금 안 되게 걸린다.

예전엔 강의를 어떻게든 들으면서 갔는데 요즘은 꾸벅 꾸벅 졸면서 간다.

이를 개선해보도록 하자,,, 

++ 프로젝트 기간이 아니면 너무 집을 빠르게 간다.

집 가서 어차피 씻고 바로 잘 건데 복습을 차라리 교육장에서 하는 것은?! 

> 조금 더 생각 해 보도록 하자.

 

Try

 

오늘은 복습을 하고 내일은 자격증 공부를 할 것이다. 그리고 진도를 따라가기 위해서 어떻게든 토요일은 새벽까지 공부를 해 보도록 하자. 요즘 많이 자고 싶어도 일어나면 아침 8시?더라... 

 

이거 쓰고 바로 씻으면 일류다.

 

하지만 난 일류가 아니니까 이따 씻도록 하겠다.

728x90