공부 기록/내배캠Java_5기

[내배캠][TIL] 14일 차 - 목요일, 팀 프로젝트 시작

노루동산 2024. 5. 2. 21:09
반응형

 

✔️ 알고리즘, SQL 문제 풀이
     ✔️ 알고리즘 코드카타
     ✔️ SQL 코드카타
     ✔️ 프로그래머스 Level 2

✔️ 개인 과제 개선
     ✔️ new 대신 OperatorFactory를 따로 만들어서 미리 만든 operator를 가져온다.
     ✔️ Util 클래스 만들기

✔️ Java 팀 프로젝트
      ✔️ 팀 회의
      ✔️ 뼈대 세우기
      ✔️ 수강생의 과목별 시험 회차 점수 수정

✔️ Java 심화반 수업

 

⏱️ 오늘의 일정 ⏱️

9:00 ~ 10:00 - 알고리즘 코드카타
10:00 ~ 10:30 - 팀 과제 발제
10:30 ~ 
11:30 - 팀 과제 내용 확인
11:30 ~ 13:00 - 개인 과제 개선

13:00 ~ 14:00 - 점심시간
14:00 ~ 15:00 - 팀 프로젝트 회의
15:00 ~ 16:00 - Java 심화반 수업

15:00 ~ 
18:00 - 팀 프로젝트 진행
18:00 ~ 19:00 - 저녁 시간
19:00 ~ 19:30 - 팀 프로젝트 회의
19:30 ~ 20:30 - TIL 작성

20:30 ~ 21:00 - 팀 프로젝트 회의

 

 

📜 Chapter 1. 알고리즘 문제 풀기

9:00 ~ 10:00 - 알고리즘 코드카타
✔️ 알고리즘, SQL 문제 풀이
     ✔️ 알고리즘 코드카타
     ✔️ SQL 코드카타
     ✔️ 프로그래머스 Level 2

 

쓸데없이 스크롤이 길어져서 코드카타 문제들은 그냥 깃헙 링크만 올리는 걸로 변경했다.

그리고 코테 푼 것도 아직 어렵다 느끼는 부분이 아닌데도 하나하나 포스팅을 하니 시간만 잡아먹는 느낌이라 하루 한 개 정도 제외하고는 생략하려고 한다.

✔️ 알고리즘 코드카타

짝수와 홀수

https://github.com/MetroDefro/CodingTest_AutoSave/tree/main/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/1/12937.%E2%80%85%EC%A7%9D%EC%88%98%EC%99%80%E2%80%85%ED%99%80%EC%88%98

 

CodingTest_AutoSave/프로그래머스/1/12937. 짝수와 홀수 at main · MetroDefro/CodingTest_AutoSave

모든 코딩 테스트 자동 저장. Contribute to MetroDefro/CodingTest_AutoSave development by creating an account on GitHub.

github.com

 

✔️ SQL 코드카타

여러 기준으로 정렬하기

https://github.com/MetroDefro/CodingTest_AutoSave/tree/main/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/1/59404.%E2%80%85%EC%97%AC%EB%9F%AC%E2%80%85%EA%B8%B0%EC%A4%80%EC%9C%BC%EB%A1%9C%E2%80%85%EC%A0%95%EB%A0%AC%ED%95%98%EA%B8%B0

 

CodingTest_AutoSave/프로그래머스/1/59404. 여러 기준으로 정렬하기 at main · MetroDefro/CodingTest_AutoSave

모든 코딩 테스트 자동 저장. Contribute to MetroDefro/CodingTest_AutoSave development by creating an account on GitHub.

github.com

 

✔️ 프로그래머스 Level 2

 

피보나치 수

https://mountain-noroo.tistory.com/142

 

[프로그래머스][Java] 피보나치 수 - level 2

문제 보기 https://school.programmers.co.kr/learn/courses/30/lessons/12945 프로그래머스코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합

mountain-noroo.tistory.com

 

짝 지어 제거하기

https://github.com/MetroDefro/CodingTest_AutoSave/tree/main/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/2/12973.%E2%80%85%EC%A7%9D%EC%A7%80%EC%96%B4%E2%80%85%EC%A0%9C%EA%B1%B0%ED%95%98%EA%B8%B0

 

CodingTest_AutoSave/프로그래머스/2/12973. 짝지어 제거하기 at main · MetroDefro/CodingTest_AutoSave

모든 코딩 테스트 자동 저장. Contribute to MetroDefro/CodingTest_AutoSave development by creating an account on GitHub.

github.com

 

 

📜 Chapter 2. 개인 과제 개선

11:30 ~ 13:00 - 개인 과제 개선
✔️ 개인 과제 개선
     ✔️ new 대신 OperatorFactory를 따로 만들어서 미리 만든 operator를 가져온다.
     ✔️ Util 클래스 만들기

 

✔️ new 대신 OperatorFactory를 따로 만들어서 미리 만든 operator를 가져온다.
// 오퍼레이터들을 생성하는 클래스
public class OperatorFactory <T extends Number> {
    private final AddOperator<T> addOperator; // 오퍼레이터들 변할 일 없으므로 final로 선언
    private final SubstractOperator<T> substractOperator;
    private final MultiplyOperator<T> multiplyOperator;
    private final DivideOperator<T> divideOperator;
    private final ModOperator<T> modOperator;

    // 생성자에서 오퍼레이터 생성
    public OperatorFactory() {
        addOperator = new AddOperator<>();
        substractOperator = new SubstractOperator<>();
        multiplyOperator = new MultiplyOperator<>();
        divideOperator = new DivideOperator<>();
        modOperator = new ModOperator<>();
    }

    public Operator<T> GetOperator(OperatorType type) {
        return switch (type) { // OperatorType에 따라 해당하는 Operator 리턴
            case ADD -> addOperator;
            case SUB -> substractOperator;
            case MUL -> multiplyOperator;
            case DIV -> divideOperator;
            case MOD -> modOperator;
        };
    }
}
public class ArithmeticCalculator<T extends Number> extends Calculator {

    private final OperatorFactory<T> operatorFactory;

    public ArithmeticCalculator() {
        this.operatorFactory = new OperatorFactory<>();
    }

    // 계산을 진행할 메서드
    public T calculate(T firstNumber, T secondNumber, char operator) {
        // operatorFactory 객체로부터 operator 타입에 맞는 operator를 받아 operate 호출하여 계산한다.
        return operatorFactory.GetOperator(OperatorType.fromOperator(operator)).operate(firstNumber, secondNumber);
    }

    // ...
}

 

✔️ Util 클래스 만들기
public class NumberConversionUtils {
    @SuppressWarnings("unchecked") // 경고 문구 나오지 않도록
    public static <T extends Number> T convertNumberToType(Number result, Class<T> type) {
        if(type == Integer.class) { // 타입이 Inteager인지 Double인지 검사하고
            return (T) Integer.valueOf(result.intValue()); // 타입 변환하여 리턴합니다.
        } else if(type == Double.class) {
            return (T) Double.valueOf(result.doubleValue());
        } else {
            throw new IllegalArgumentException("지원하지 않는 타입입니다. " + type); // 이상한 타입 들어올 경우 예외처리
        }
    }
}
public class AddOperator <T extends Number> extends Operator<T> {
    @Override
    public T operate(T firstNumber, T secondNumber) {
        // 들어온 타입이 무엇인지 검사해서 해당 타입으로 변환기에 전달합니다.
        return (T)NumberConversionUtils.convertNumberToType(firstNumber.doubleValue() + secondNumber.doubleValue(), firstNumber.getClass());
    }
}

이 부분은 답안 코드를 거의 그대로 적용하였다.

욕심이 좀 더 많긴 한데 일단 어제 눈에 보였던 부분은 이 정도라서 나머지는 피드백을 받은 다음에 개선해보겠다.

 

 

📜 Chapter 3. Java 팀 프로젝트

10:00 ~ 10:30 - 팀 과제 발제
10:30 ~ 
11:30 - 팀 과제 내용 확인
14:00 ~ 15:00 - 팀 프로젝트 회의
15:00 ~ 18:00 - 팀 프로젝트 진행

✔️ Java 팀 프로젝트
      ✔️ 팀 회의
      ✔️ 뼈대 세우기
      ✔️ 수강생의 과목별 시험 회차 점수 수정

 

드디어~ 팀 과제가 발제되었다. 문제를 보니 개인 과제와 난이도 차이가 많이 나지는 않으나 스코프를 제공하지 않는다는 점, 구현할 양이 많다는 차이가 있었다. 그러나 템플릿을 보니 워낙 잘 나와있기도 하고 이번 과제도 어려움은 없을 것 같다.

 

우리 팀은 오전에는 각자 팀 과제를 확인하고, 공부하는 시간을 갖고 오후 2시부터 팀 프로젝트를 시작했다.

일단 기본 구현이 딱 5개 있었기 때문에 하나하나 나눠가졌고 이것부터 마치기로 했다.

내가 맡은 기능은 아래와 같다.

  • 수강생의 과목별 시험 회차 점수 수정
  • 뼈대 세우기

일단 팀장이니까 템플릿을 참고하며 전체적인 뼈대를 만드는 작업을 한 것이다.

그리고 구현해야 하는 기능은 수강생의 고목별 시험 회차 점수 수정이었다.

Public class App {
    // 데이터 저장소
    private static List<Student> students;
    private static List<Subject> subjects;
    private static List<Score> scores;
    
    // 스캐너
    private static Scanner sc = new Scanner(System.in);
    
	// ...

    private static int getStudentId() {
        System.out.print("\n관리할 수강생의 번호를 입력하시오...");
        return Parser.parseId(sc.next());
    }

    private static String getSubjectName() throws InputMismatchException{
        System.out.print("\n과목 이름을 입력하시오...");
        // 과목 이름으로부터 List 조회해 Optional 객체 받음.
        return sc.next();
    }

    private static int getTurn() {
        System.out.print("\n회차를 입력하시오...");
        return Parser.parseTurn(sc.next());
    }

    private static int getScore() {
        System.out.print("\n점수를 입력하시오...");
        return Parser.parseScore(sc.next());
    }

    private static Student searchStudent(int studentId) throws InputMismatchException{
        Optional<Student> studentObj = students.stream()
                .filter(o -> o.getStudentId() == studentId)
                .findFirst();
        // 해당하는 데이터가 없을 경우 예외처리
        if(studentObj.isPresent()) {
            return studentObj.get();
        } else {
            throw new InputMismatchException("일치하는 학생이 없습니다.\n선택 화면 이동...");
        }
    }

    private static Subject searchSubject(String subjectName) throws InputMismatchException{
        Optional<Subject> subjectObj = subjects.stream()
                .filter(o -> o.getSubjectName().equals(subjectName))
                .findFirst();
        // 해당하는 데이터가 없을 경우 예외처리
        if(subjectObj.isPresent()) {
            return subjectObj.get();
        } else {
            throw new InputMismatchException("일치하는 과목이 없습니다.\n선택 화면 이동...");
        }
    }

    private static Score searchScore(int studentId, int subjectId, int turn) throws InputMismatchException {
        // scores 조회하여 수강생id, 과목id, 회차가 일치하는 객체 찾기
        Optional<Score> scoreObj = scores.stream().filter(o -> o.getStudentId() == studentId &&
                        o.getSubjectId() == subjectId && o.getScoreTurn() == turn)
                .findFirst();
        // 해당하는 데이터가 없을 겨우 예외처리
        if(scoreObj.isPresent()) {
            return scoreObj.get();
        } else {
            throw new InputMismatchException("일치하는 데이터가 없습니다.\n선택 화면 이동...");
        }
    }

    // 수강생의 과목별 회차 점수 수정
    private static void updateTurnScoreBySubject() {
        // 기능 구현 (수정할 특정 학생, 과목 및 회차, 점수 입력 받아 변환)
        Student studentIdInput = searchStudent(getStudentId());
        Subject subjectInput = searchSubject(getSubjectName());
        int turnInput = getTurn();
        int scoreInput = getScore();
        // 정보들을 바탕으로 점수 리스트를 조회해 점수를 받아온다.
        Score score = searchScore(studentIdInput.getStudentId(), subjectInput.getSubjectId(), turnInput);
        System.out.println("시험 점수를 수정합니다...");
        // 해당하는 점수 객체의 점수를 변경한다.
        score.patchScore(scoreInput, subjectInput.subjectType); // 시험 점수 업데이트
        System.out.println("\n점수 수정 성공!");
    }
}
// 입력 값의 예외 처리 및 파싱을 담당하는 클래스
public class Parser {

    // String을 int로 변환. 올바른Id(0 이상 정수)가 들어오지 않을 시 예외처리
    public static int parseId(String input) throws InputMismatchException { // int 파싱
        if(input.matches("^[0-9]+$")) { // 정규식 검사
            return Integer.parseInt(input);
        } else {
            throw new InputMismatchException("올바른 번호를 입력하시오...(0 이상 정수)"); // exception 만들어 던짐
        }
    }

    // String을 int로 변환. 올바른 회차(1~10 정수)가 들어오지 않을 시 예외처리
    public static int parseTurn(String input) throws InputMismatchException { // int 파싱
        if(input.matches("^[0-9]+$")) { // 정규식 검사
            int turn = Integer.parseInt(input);
            if (turn >= 1 && turn <= 10) {
                return turn;
            }
        }
        // if문에서 걸러져 나왔을 경우
        throw new InputMismatchException("올바른 번호를 입력하시오...(1 ~ 10 정수)"); // exception 만들어 던짐
    }

    // String을 int로 변환. 올바른 점수(0~100 정수)가 들어오지 않을 시 예외처리
    public static int parseScore(String input) throws InputMismatchException { // int 파싱
        if(input.matches("^[0-9]+$")) { // 정규식 검사
            int score = Integer.parseInt(input);
            if (score >= 0 && score <= 100) {
                return score;
            }
        }
        // if문에서 걸러져 나왔을 경우
        throw new InputMismatchException("올바른 번호를 입력하시오...(0 ~ 100 정수)"); // exception 만들어 던짐
    }
}
public class Score {
    // ...

    public void patchScore(int score, SubjectType subjectType) {
        this.score = score;
        reteGrade(score, subjectType); // 등급 매기기
    }

    private void reteGrade(int score, SubjectType subjectType) {
        if (subjectType == SubjectType.ESSENTIAL) { // 과목 타입 별로 등급을 다르게 매긴다.
            scoreGrade = evaluateGrade(score, 95, 90, 80, 70, 60); // 필수 과목
        } else if (subjectType == SubjectType.SELECT) { // 선택 과목
            scoreGrade = evaluateGrade(score, 90, 80, 70, 60, 50);
        }
    }

    private char evaluateGrade(int score, int... thresholds) {
        char[] grades = {'A', 'B', 'C', 'D', 'F'}; // 등급들
        char grade = 'N'; // 기본 등급 N부터 시작
        for (int i = 0; i < thresholds.length; i++) {
            if (score >= thresholds[i]) { // 점수가 임계값보다 높을 경우
                grade = grades[i]; // 등급을 매긴다.
                break; // 등급이 매겨졌으니 빠져나온다.
            }
        }
        return grade; // 등급 반환
    }
}

이거 기능 하나 딱 만들기에는 예외처리 부분이 너무나도 신경이 쓰여 파싱 하는 부분을 하나하나 다 만들고, 또 리스트에서 서치 하는 부분도 전부 만들어 놓았다... 서치하는 부분은 오버로딩해서 예를 들어 수강생 이름을 받았을 때와 수강생 아이디를 받았을 때와 같이 나누면 좋을 것도 같다.

 

 

📜 Chapter 4. Java 심화반 수업

15:00 ~ 16:00 - Java 심화반 수업
✔️ Java 심화반 수업

 

✔️ 네트워크 기초
  • 해저 광 케이블 / 인공위성을 통해 World Wide Web 구축
  • 인터넷 프로토콜 IP(Internet Protocol): 인터넷을 통한 데이터를 원활하게 주고받기 위한 통신규약.
  • IP 주소: 컴퓨터 주소로 패킷(Packet)이라는 단위로 전달한다.
  • 패킷: 헤더(출발지 IP, 도착지 IP, 기타 등등), 페이로드(전달 데이터), 트레일러(수신 여부)로 구성
  • IP 방식의 문제점: 비연결성(상대 IP 상태 고려 X), 비신뢰성(소실, 용량이 크면 도착하는 순서가 뒤바뀜)

 

✔️ TCP(Transmission Control Protocol)

신뢰성 있는 전달 방법: 3 Way HandShake

  1. 1. SYN 접속 요청 (SYN->)
  2. 2. ACK 요청 수락 (<-ACK, SYN)
  3. 3. ACK와 함께 데이터 전송 (ACK->)

잘 받았다는 응답을 반환해 줌, 순서가 뒤바뀌지 않음

 

✔️ UDP(User Datagram Protocol)
  • IP 방식과 거의 비슷 (3WH X)
  • 차이점으로 PORT가 존재하고(TCP에도 존재), 데이터 무결성 검사(체크섬)를 진행한다.
  • TCP는 신뢰성이 있으나 데이터 전송에 시간이 많이 소요되기 때문에 UDP를 많이 사용하는 추세(HTTP3에서 채택).
  • 실시간성이 보장되어야 하는 실시간 스트리밍 서비스, 온라인 게임, 인터넷 전화에서 주로 씀

 

✔️ PORT
  • 같은 IP 내에서 프로세스 구분을 하기 위해 사용.
  • 서버 부하 분산(로드 밸런싱)에서 자주 보임.
  • 전송하고자 하는 패킷이 어디에 필요한지 IP만으로는 모르기 때문에 애플리케이션을 구분하기 위해 사용되는 것.
  • 0~65535 할당 가능하나 0~1023까지는 국제 도메인 관리기구에 의해 관리되어 사용하지 않는 것이 좋음

*참고: HTTP: 80 HTTPS: 443

 

✔️ DNS(Domain Name System)
  • IP 대신 naver.com과 같은 도메인명으로 접속할 수 있는 것.
  • 도메인 명을 입력하면 DNS 서버는 IP 주소를 반환한다.
  • IP는 변동성이 있지만 바뀌어도 DNS 서버에 등록된 IP 주소만 바꾸면 됨.

 

✔️ URI(Uniform Resource Identifier)
  • 인터넷 자원을 나타내는 고유 식별자.
  • URI를 URL과 거의 같은 의미로 사용하고 대부분 URL만 사용함.
  • 프로토콜을 포함하고 자원의 위치를 의미한다.
  • URN(Resource Name): 프로토콜을 미포함하고 해당 자원의 이름을 의미한다.

 

✔️ URL
scheme:[//[user[:password]@host[:port]][/path][??query][#fragment]
  • - scheme: 주로 프로토콜을 사용. http, https ftp
  • - user[:password]: 보안에 취약해 요즘은 사용 안 함
  • - host[:port]: 호스트(도메인명 또는 IP주소)명, 포트는 보통 생략
  • - [/path]: 리소스의 경로, 계층 구조로 구성
  • - [?query]: key=value 형태. ?로 시작되고 &으로 구분. query parameter, query string 이라고도 함.
  • - [#fragment]: html 내부 북마크에 사용(페이지 내의 특정 위치)

 

✔️ URL을 입력했을 때 처리 과정
  1. URL 입력
  2. DNS 서버 조회하여 해당하는 IP 주소를 응답받음
  3. 웹 브라우저에서 HTTP 요청 메시지를 생성
  4. 요청 패킷(HTTP 메시지가 포함되어 있음)을 서버로 전송
  5. 서버에서 응답 HTTP 메세지 만들어 응답
  6. 응답패킷 도착 -> html이 응답으로 옴

 

✔️ HTTP(HyperText Transfer Protocol)

모든 형태의 데이터 전송 가능(클라이언트 to 서버뿐만 아니라 서버 to 서버 통신에서도 HTTP 사용)

HTTP메서드: POST, GET, PUT, PATCH, DELETE

CRUD

  • POST - Create 생성
  • GET - Read 조회
  • PUT - Update 수정 (요청 페이로드를 사용해 새로운 리소스를 생성하거나, 대상 리소스를 나타내는 데이터를 대체.)
  • PATCH - Update 수정 (리소스의 부분적인 수정을 할 때에 사용.)
  • DELETE - Delete 삭제

 

✔️ HTTP 특징

Stateless(무상태)

서버는 클라이언트의 상태를 보존하지 않음.

불특정 다수와 통신해야 하는데 계속 유지할 경우 많은 리소스가 필요하기 때문.

장점: Scale Out 수평 확장성이 높다(서버 증설이 쉽다).

단점: 클라이언트가 데이터를 추가적으로 전송해야 하고(데이터 양 증가), 항상 같은 서버가 유지되어야 한다.

한계점: 무상태로 설계할 수 없는 경우가 있다. 로그인은 쿠키, 세션, 토큰등을 활용해 진행.

 

Connectionless(비연결)

연결을 유지하지 않음.

수많은 사람이 서비스를 이용 중이어도 실제 서버에서 동시에 처리하는 요청은 적다.

장점: 서버 자원을 효율적으로 사용할 수 있음.

단점: 3WH을 새로 해야함, 웹 사이트의 리소스를 다시 다운해야 하지만 캐시, 브라우저 캐싱 사용.

HTTP 지속연결(Persistent Connections)로 문제를 해결 했다는데 이게 뭔지 잘 모르겠음.

 

✔️ HTTP Method의 속성

안전성: Get 메서드는 저장된 데이터를 변환하지 않으므로 안전. 나머지는 안전하지 않음.

멱등성: 몇 번을 호출하든 항상 결과는 같다. POST만 멱등성을 보장하지 않음.

캐시가능성: 재사용을 위해 캐시에 저장할 수 있음. GET, HEAD(주로 이 둘), POST, PATCH 메소드는 캐시 가능.

 

✔️ HTTP 상태코드
  • 1xx (정보 응답): 잘 안 보임
  • 2xx (성공 응답)
  • 3xx (리다이렉션)
  • 4xx (클라이언트 에러)
  • 5xx (서버 에러)

 

✔️ 공부할 것!!!!!!!!!!
  • [ ] TCP/IP 4 계층
  • [ ] OSI 7 계층
  • TCP/IP 패킷 어떻게 구성되어 있는지 알아보기
  • HTTP 요청, 응답 메시지의 구조에 대해 알아보자
  • Cookie, Session에 대해 알아봅시다
  • 캐시 → 심화 : 프락시 캐시
  • 리다이렉션 이란? 종류는 무엇이 있나?
  • Scale Out, Scale UP
  • Spring 부하분산 방법
  • DB 부하분산 방법
  • RESTful API란?
  • RESTful API 사용 이유
  • RESTful 한 API 설계 방법

 

🌙 오늘을 마치며 🌙 

큰일이다! 팀 프로젝트도 하고 심화반 수업도 듣고 개인 과제도 하니 따로 스프링을 공부할 시간이 없었다.

근데 뭐 어쩔 수 없지 애초에 지금 자바 주차인데...

반응형